Is it a bug?
(when ^boolean (aget js/window "location")
(js/console.log 1))
emits checked if
if(cljs.core.truth_((window["location"]))){
console.log((1));
} else {
}
Man, on the surface, that does seem like a reasonable hint. It seems easy to support
diff --git a/src/main/clojure/cljs/analyzer.cljc b/src/main/clojure/cljs/analyzer.cljc
index e021b5e9..efe5f714 100644
--- a/src/main/clojure/cljs/analyzer.cljc
+++ b/src/main/clojure/cljs/analyzer.cljc
@@ -1647,7 +1647,9 @@
(throw (compile-syntax-error env "Too few arguments to if" 'if)))
(when (> (count form) 4)
(throw (compile-syntax-error env "Too many arguments to if" 'if)))
- (let [test-expr (disallowing-recur (analyze (assoc env :context :expr) test))
+ (let [test-tag (:tag (meta test))
+ test-expr (cond-> (disallowing-recur (analyze (assoc env :context :expr) test))
+ test-tag (assoc :tag test-tag))
then-expr (allowing-redef (analyze (set-test-induced-tags env test) then))
else-expr (allowing-redef (analyze env else))]
{:env env :op :if :form form
For some reason this hint works https://github.com/clojure/clojurescript/blob/b38ded99dc0967a48824d55ea644bee86b4eae5b/src/main/cljs/cljs/core.cljs#L2061
I suspect the problem here is that if the test is a macro, it will get expanded, and, in the process, the tag is discarded. If you think about it, this probably couldn't be generally fixed with a revision to the macroexpansion logic because a macro could expand to some code that can't hold meta.
So maybe it could indeed be deemed a corner case bug in the situation where hints on macro expressions evaporate. (And the change above really only fixes it for the if
test case.)
Which sort of object in JS couldn’t hold meta? Just curious since it seems like everything in JS can be extended
For the primitive types which couldn't hold meta without extending them to IMeta
, it's probably a moot point anyway because the compiler can infer their types.
But even for types that can hold meta, preserving meta through macroexpansion would differ from Clojure, which doesn't do that:
user=> (defmacro foo [] [])
#'user/foo
user=> (meta ^:bar (foo))
nil