This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-15
Channels
- # announcements (8)
- # architecture (9)
- # autochrome-github (1)
- # babashka (48)
- # beginners (55)
- # calva (36)
- # cider (16)
- # clj-commons (1)
- # clj-kondo (38)
- # cljs-dev (44)
- # cljsrn (1)
- # clojure (164)
- # clojure-europe (35)
- # clojure-nl (2)
- # clojure-norway (10)
- # clojure-uk (23)
- # clojurescript (50)
- # conjure (24)
- # core-async (1)
- # cryogen (2)
- # cursive (38)
- # datalevin (11)
- # datascript (2)
- # datomic (13)
- # duct (1)
- # emacs (16)
- # events (12)
- # exercism (3)
- # figwheel-main (7)
- # fulcro (26)
- # honeysql (5)
- # integrant (1)
- # jobs (3)
- # kaocha (6)
- # lsp (72)
- # malli (22)
- # nextjournal (35)
- # nrepl (1)
- # off-topic (34)
- # pathom (5)
- # polylith (8)
- # portal (40)
- # re-frame (14)
- # reagent (42)
- # reitit (1)
- # releases (1)
- # remote-jobs (1)
- # reveal (9)
- # sci (2)
- # shadow-cljs (13)
- # sql (3)
- # tools-deps (33)
- # vim (25)
I posted here previously about an issue with extern inference. I did more digging, and I have some follow-up information for anyone interested. The following code does not produce an extern for MediaDevices
. Note the lack of js/
:
(defn on-device-change!
[callback]
(let [^MediaDevices media-devices (.-mediaDevices js/navigator)]
(set! (.-ondevicechange media-devices) callback)))
If I add the js/
to be ^js/MediaDevices
, ClojureScript does infer and generate the extern, but I also get a warning:
Cannot resolve property ondevicechange for inferred type js/MediaDevices in expression (. media-devices -ondevicechange)
Although the ondevicechange
attribute is part of the W3C spec and supported by browsers, it is not listed in the pre-defined set of externs in Closure Compiler: https://github.com/google/closure-compiler/blob/master/externs/browser/w3c_rtc.js#L1527
This ClojureScript warning only appears to happen in this situation: the Closure Compiler includes externs for the class, but is missing the specific property/method that needs to be inferred.without the js/
in the hint you are basically telling the compiler this class is safe to get renamed, since it assumes it is a CLJS/Closure class
pretty sure the closure externs are missing that property since you are normally expected to use addEventListener
to add events?
addEventListener
is also part of the spec and is often recommended over the attribute, but there are still advantages of using the attribute.
But I'm guessing that's why Google didn't include the attribute in their definitions.
When I posted about this the first time, I was running into a situation where I had an older version of ClojureScript that pulled in an older set of externs. I was calling a method that had been added to browsers more recently. It's the same kind of problem: incomplete externs in the Closure Compiler generate a warning on inference.
Is this something I should open an issue for? Sorry for my ignorance. I'm not totally sure what to do with this information aside from posting here.
@dnolen The main problem is that the warning is confusing and steers one in the wrong direction. The compiler is generating the same warning as if the type hint doesn't exist at all. Even though adding the type hint does the right thing (infers the extern), it still feels broken (identical error to no type hint). Worse yet, by dropping the js/
, the warning will go away (feels fixed), but no extern is generated (actually broken).
type hints aren't really a thing in ClojureScript - they exist most for internals reason
I, personally, got thrown off by String
example in the https://gist.github.com/swannodette/4fc9ccc13f62c66456daf19c47692799. But, like you say, the docs always use js/
.
It would be extremely helpful if the warning that was generated by having no hint whatsoever was different than having a hint for an attibute/method that wasn't found in the set of externs the compiler knows about.
that is what this warning Cannot resolve property ondevicechange for inferred type js/MediaDevices in expression (. media-devices -ondevicechange)
does
It is in this situation. Here, I'll paste for reference. Without:
[Figwheel:WARNING] Compile Warning /home/enigma/Devel/Hypersignal/platform/ui/src/cljs/app/api/web/media.cljs line:52 column:11
Cannot resolve property ondevicechange for inferred type js/MediaDevices in expression (. media-devices -ondevicechange)
47 (= (.-name err) "NotAllowedError"))
48
49 (defn on-device-change!
50 [callback]
51 (let [media-devices (.-mediaDevices js/navigator)]
52 (set! (.-ondevicechange media-devices) callback)))
^---
With:
[Figwheel:WARNING] Compile Warning /home/enigma/Devel/Hypersignal/platform/ui/src/cljs/app/api/web/media.cljs line:52 column:11
Cannot resolve property ondevicechange for inferred type js/MediaDevices in expression (. media-devices -ondevicechange)
47 (= (.-name err) "NotAllowedError"))
48
49 (defn on-device-change!
50 [callback]
51 (let [^js/MediaDevices media-devices (.-mediaDevices js/navigator)]
52 (set! (.-ondevicechange media-devices) callback)))
^---
OK. So it was able to infer the js/MediaDevices
type without the annotation. I felt like I was adding information, but I wasn't because the compiler already knew that.
Oh, I didn't read that as obtuse at all! I appreciate it! I just wanted to confirm my understanding. 😄
might was well infer the types through Google Closure externs since it's already there
Yeah, the externs inference you added is super helpful! I really like that it can track the type. Awesome stuff! I got hooked on aget
and later on oget
years ago, and this last year I decided to switch to externs inference.
I'm not totally sure why I got confused. I'm going to think about it and re-look at the docs and see if there might be an example or clarification that would have helped me. It looks like there is a "Cannot resolve property" example. If something strikes me, I'll report back. I really appreciate you clarifying! I know you have a ton on your plate.
Is there any way to avoid that warning? The ondevicechange
attribute is a valid attribute, and by using it, I'm stuck with a "Cannot resolve property" warning on every compile. If I set the hint as ^js/FooBar
, I don't get any warning and the ondevicechange
attribute isn't mangled by the Closure Compiler, but that feels very much like a hack. Using ^js/Object
still gives me a warning.