Fork me on GitHub
#cljs-dev
<
2022-02-03
>
dnolen00:02:49

It's unusual to need to have worry about this unless you’re writing a wrapper of some kind

dnolen00:02:51

js is a kind of taint - signaling nothing can be known so all users of the thing via interop should also be tainted

dnolen00:02:13

If you're requiring a npm lib it’s already tainted

dnolen00:02:21

This is why you don't need to bother

neumann02:02:40

Thanks for the reply! To add detail, in my case, I'm writing wrapper functions around the WebRTC API in the browser, and I need to support advanced compilation. It's interop on built-in types. I had ^js/RTCRtpTransceiver, but it still created a warning and did not generate the extern. I had to use ^RTCRtpTransceiver instead. Why the difference? Is there something different about browser API types?

(defn set-codec-preferences
  [^RTCRtpTransceiver transceiver
   codecs]
  (.setCodecPreferences transceiver codecs))

thheller06:02:39

the closure compiler already has externs for webrtc by default. you sure you need them? https://github.com/google/closure-compiler/blob/master/externs/browser/w3c_rtc.js

neumann17:02:24

Apparently I also need to update my ClojureScript version. I'm on 1.10.773. The extern for setCodecPreferences was added in the Closure Compiler more recently. Nonetheless, I'm still trying to figure out why having js/ would prevent the automatic extern inference and removing it allows automatic extern inference to work fine.

neumann17:02:51

I'll get all my versions up-to-date and experiment more.

quoll13:02:51

OK, I had to share this… I’m looking at parse-long and parse-double. The first one was simple enough: (and (re-matches #"[+-]?\d+" s) (js/parseInt s)) So then I looked at the second one, and thought that I’d just use a regex like last time. A little more complicated, because the decimal point and fractional parts are optional, there’s scientific notation, etc. But it turns out that https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html#valueOf-java.lang.String-

quoll13:02:27

Quoting…

quoll13:02:30

To avoid calling this method on an invalid string and having a `NumberFormatException` be thrown, the regular expression below can be used to screen the input string:

final String Digits     = "(\\p{Digit}+)";
  final String HexDigits  = "(\\p{XDigit}+)";
  // an exponent is 'e' or 'E' followed by an optionally
  // signed decimal integer.
  final String Exp        = "[eE][+-]?"+Digits;
  final String fpRegex    =
      ("[\\x00-\\x20]*"+  // Optional leading "whitespace"
       "[+-]?(" + // Optional sign character
       "NaN|" +           // "NaN" string
       "Infinity|" +      // "Infinity" string

       // A decimal floating-point string representing a finite positive
       // number without a leading sign has at most five basic pieces:
       // Digits . Digits ExponentPart FloatTypeSuffix
       //
       // Since this method allows integer-only strings as input
       // in addition to strings of floating-point literals, the
       // two sub-patterns below are simplifications of the grammar
       // productions from section 3.10.2 of
       // The Java Language Specification.

       // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
       "((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+

       // . Digits ExponentPart_opt FloatTypeSuffix_opt
       "(\\.("+Digits+")("+Exp+")?)|"+

       // Hexadecimal strings
       "((" +
        // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
        "(0[xX]" + HexDigits + "(\\.)?)|" +

        // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
        "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +

        ")[pP][+-]?" + Digits + "))" +
       "[fFdD]?))" +
       "[\\x00-\\x20]*");// Optional trailing "whitespace"

  if (Pattern.matches(fpRegex, myString))
      Double.valueOf(myString); // Will not throw NumberFormatException
  else {
      // Perform suitable alternative action
  }

quoll14:02:15

Note: a lot of these lines are comments, and hex is not allowed

quoll23:02:11

If you really want to know, I went with: #"[\x00-\x20]*[+-]?(Infinity|((\d+\.?\d*|\.\d+)([eE][+-]?\d+)?)[dDfF]?)[\x00-\x20]*"

😱 1
quoll23:02:46

I check for NaN first, because it has to be dealt with separately (it will explicitly return ##NaN while many other numbers parsed in JS will also return NaN and instead we need to return nil)

quoll23:02:50

What’s up @U4YGF4NGM? That’s eminently readable!

lilactown23:02:30

as far as regex goes i'm sure it is

quoll00:02:48

With a little practice, regex becomes very easy to write… … … and really hard to read

quoll14:02:23

Anyway, it made me laugh

dpsutton15:02:16

I saw that Alex is asking for people to try the beta on projects. Is it possible to run canary or coal-mine (forgot exactly which) but holding the cljs version constant and instead using the new beta? And if so, would that be helpful?

dnolen15:02:03

yes probably - been meaning to look at canary (to move it to GH CI) but simply haven't had time

Alex Miller (Clojure team)15:02:30

did you ever bump the data.json version cljs uses?

dnolen15:02:26

hrm don't think so

Alex Miller (Clojure team)15:02:18

well, we made it a lot faster :)

dnolen15:02:14

@alexmiller should I bump transit too?

dnolen15:02:38

but I guess transit doesn't depend on data.json

Alex Miller (Clojure team)15:02:55

no, it doesn't, but probably would be good to bump transit if it's lagging

Alex Miller (Clojure team)15:02:31

we are near to releasing a new transit-java and transit-clj, although I don't think the fix that will be in there has any impact on cljs's use

dnolen15:02:18

what was the issue - transit-js definitely ported over bits of the Java in terms of the big picture

fogus (Clojure Team)15:02:21

transit-java determined key stringability based on the value of the key rather than the xform of the key.

Alex Miller (Clojure team)15:02:45

from testing, I think this was not an issue in transit-cljs

dnolen15:02:04

ah got it - k

fogus (Clojure Team)15:02:23

I looked briefly at the CLJS impl and it seemed that the specific symbol + meta problem wouldn't cause an error because (my memory is foggy here) on strings are stringable (?)

fogus (Clojure Team)15:02:19

It was a while ago so I may be wrong

dnolen15:02:48

@fogus well I think did the original metadata support many many years ago on transit-clj and transit-cljs - probably I just missed this issue on the the clj side

dnolen17:02:31

so the problem with lifting all js/require is a one composition

dnolen17:02:04

each type of thing might need to be handled differently, i.e. images in React Native vs. CSS for web stuff

dnolen17:02:41

does this make sense?

dnolen17:02:44

so composing this at build time is busted

dnolen17:02:00

because you have to know all the features which were used - so again doesn't compose

dnolen17:02:05

doesn't solve the transitive problem

dnolen17:02:30

however we could use ns metadata to hint the compiler

borkdude17:02:08

this isn't about ES6/ESM is it?

dnolen17:02:26

@borkdude hrm I don't see how it could be related

dnolen17:02:36

it's more about require("foo.css")

dnolen17:02:45

require("bar.png")

mikerod17:02:23

Yeah, I think I am following what you are describing.

dnolen17:02:30

^{:cljs-pass/lift-require} (ns my.cool.component ...) ...

👀 1
mikerod17:02:35

I believe it’s fairly popular to need to bring in these non-js assets with npm deps though. So I’d imagine this should be a fairly common problem space.

dnolen17:02:15

so then if you js/require after your ns declaration they would get lifted - but in this namespace only

dnolen17:02:26

and only the compiler pass that matches would match

dnolen17:02:33

thus preventing all conflicts

dnolen17:02:47

and removing the need for manual composition in the build

dnolen17:02:02

thus giving something that works for transitive deps

mikerod17:02:34

That approach makes sense to me certainly for this. Sounds promising! Basically it gives a way to add to the generated js.

dnolen17:02:37

@mikerod what patterns are you all actually using

dnolen17:02:52

.json .css images, SVG - others?

mikerod17:02:01

So far I believe I’ve only encountered css, svg, and png

dnolen17:02:47

so I think to avoid a compiler pass carnival this can be restricted to the assets use case

dnolen17:02:32

{:js-require/assets #{:css :svg}} or {:js-require/assets :all}

mikerod17:02:55

Yeah, it may be better to constrain. So this is still metadata you’d put on the ns form, which would allow you to have these js/require’s after the ns form for the specified asset types?

mikerod17:02:15

What if you only said #{:css}, but then tried a require("my.svg")

dnolen17:02:24

it would ignore it

dnolen17:02:34

under the assumption something else would manage it

dnolen17:02:50

for example in Krell we have to do it differently

mikerod17:02:54

Ah I see. Ok, that makes more sense to me then.

dnolen17:02:06

because the target directory has the JS we have to change all the img paths to point to the right locations

dnolen17:02:12

so lifting is not sufficient

dnolen17:02:39

though I guess - they will need to be rewritten here too?

dnolen17:02:09

but anyways

dnolen17:02:15

I guess the idea is to not close all the doors

dnolen17:02:21

and at least let you say what you want to match

mikerod17:02:48

I see. Yeah, the path changing seems a bit heavier.

lilactown17:02:49

ought it be a string instead of a kw to allow file patterns that aren't valid kws? e.g. #{".foo.bar"}

👀 1
mikerod17:02:05

I think generally, I agree with the idea of not closing doors and needing to be more specific in the metadata.

dnolen17:02:00

@mikerod unfortunately you definitely have to change the path

dnolen17:02:13

because the compiled stuffs gets served out of :output-dir

mikerod17:02:21

I’m still trying to comprehend this one.

dnolen17:02:17

src/resources/my.svg

dnolen17:02:41

then in your CLJS (js/require "../resources/my.svg")

dnolen17:02:55

but when that CLJS is compiled to JS and emitted to :output-dir

dnolen17:02:58

it cannot be right

dnolen17:02:17

we could copy everything over, or we could just rewrite

thheller17:02:25

please don't adopt this insanity of using require for assets in CLJS 😞

❤️ 2
dnolen17:02:35

since there are large assets - not sure about copying them

dnolen18:02:29

@thheller I don't have much love for it either - but this one of the most often asked questions - and everyone has to workaround it

dnolen18:02:52

and you cannot wrap a lib and consume downstream in a reproducible way

mikerod18:02:37

Yeah, I also wasn’t a fan of requiting assets from the JS-ecosystem. It just seems like libs are nearly forcing you into it.

mikerod18:02:52

Or have to just manually copy things around.

mikerod18:02:57

re: path problems: I’d think the require from CLJS (in an npm case) would be something more like (js/require "npm-lib-dep/css/styles.css") where it’d come from something like the installed node_modules, but now that I say this, I’m really only familiar with doing these things in the es6 style import, so maybe I’m completely off.

dnolen18:02:57

@mikerod right, I guess we could check that it is or isn't relative

👍 1
borkdude18:02:33

@thheller just wondering, does the above import 'foo.css' stuff already work with shadow's target :esm ?

thheller19:02:32

does it work in your browser? 😛

thheller19:02:32

no, since its not standard ESM functionality. if you post process with webpack it'll work yes

dnolen20:02:49

@borkdude the asset thing is just tooling stuff, but obnoxiously popular tooling stuff

👍 2
dnolen20:02:46

which has nothing to do w/ the JS specification

dnolen20:02:34

in fairness I believe the pattern appeared before ESM was popular - it works w/ require(...)