Skip to content

Commit 16ec711

Browse files
committed
* add lift-tag-to-js helper
- CLJS uses boolean - but externs inference returns js/Boolean * in resolve-var add the ctor to the tag to track later, this also lets the extra information flow * in analyze-dot check to see if the target is a constructor - if it is use that tag instead, Function is not desirable * safe-test? needs to check js/Boolean now * unit tests
1 parent ed1aec6 commit 16ec711

File tree

3 files changed

+27
-7
lines changed

3 files changed

+27
-7
lines changed

src/main/clojure/cljs/analyzer.cljc

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,9 @@
11101110
(or (has-extern?* pre externs)
11111111
(-> (last pre) str (string/starts-with? "cljs$")))))
11121112

1113+
(defn lift-tag-to-js [tag]
1114+
(symbol "js" (str (alias->type tag tag))))
1115+
11131116
(defn js-tag
11141117
([pre]
11151118
(js-tag pre :tag))
@@ -1119,7 +1122,7 @@
11191122
(js-tag pre tag-type externs externs))
11201123
([pre tag-type externs top]
11211124
(when-let [tag (get-in (resolve-extern pre externs) [:info tag-type])]
1122-
(symbol "js" (str (alias->type tag tag))))))
1125+
(lift-tag-to-js tag))))
11231126

11241127
(defn dotted-symbol? [sym]
11251128
(let [s (str sym)]
@@ -1310,8 +1313,9 @@
13101313
(assoc shadowed-by-local :op :local))
13111314

13121315
:else
1313-
(let [pre (->> (string/split (name sym) #"\.") (map symbol) vec)]
1314-
(when (and (not (has-extern? pre))
1316+
(let [pre (->> (string/split (name sym) #"\.") (map symbol) vec)
1317+
res (resolve-extern (->> (string/split (name sym) #"\.") (map symbol) vec))]
1318+
(when (and (not res)
13151319
;; ignore exists? usage
13161320
(not (-> sym meta ::no-resolve)))
13171321
(swap! env/*compiler* update-in
@@ -1320,10 +1324,12 @@
13201324
{:name sym
13211325
:op :js-var
13221326
:ns 'js
1323-
:tag (with-meta (or (js-tag pre) (:tag (meta sym)) 'js) {:prefix pre})}
1327+
:tag (with-meta (or (js-tag pre) (:tag (meta sym)) 'js)
1328+
{:prefix pre
1329+
:ctor (-> res :info :ctor)})}
13241330
(when-let [ret-tag (js-tag pre :ret-tag)]
13251331
{:js-fn-var true
1326-
:ret-tag ret-tag})))))
1332+
:ret-tag ret-tag})))))
13271333
(let [s (str sym)
13281334
lb (handle-symbol-local sym (get locals sym))
13291335
current-ns (-> env :ns :name)]
@@ -3585,7 +3591,8 @@
35853591
enve (assoc env :context :expr)
35863592
targetexpr (analyze enve target)
35873593
form-meta (meta form)
3588-
target-tag (:tag targetexpr)
3594+
target-tag (as-> (:tag targetexpr) $
3595+
(or (some-> $ meta :ctor lift-tag-to-js) $))
35893596
prop (or field method)
35903597
tag (or (:tag form-meta)
35913598
(and (js-tag? target-tag)

src/main/clojure/cljs/compiler.cljc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@
641641

642642
(defn safe-test? [env e]
643643
(let [tag (ana/infer-tag env e)]
644-
(or (#{'boolean 'seq} tag) (truthy-constant? e))))
644+
(or ('#{boolean seq js/Boolean} tag) (truthy-constant? e))))
645645

646646
(defmethod emit* :if
647647
[{:keys [test then else env unchecked]}]

src/test/clojure/cljs/externs_infer_tests.clj

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
(ana/resolve-extern '[console] externs)
8888
(ana/resolve-extern '[console log] externs)
8989
(ana/resolve-extern '[undefined] externs)
90+
(ana/resolve-extern '[Number] externs)
9091
(ana/resolve-extern '[Number isNaN] externs)
9192
(ana/resolve-extern '[document] externs)
9293

@@ -146,6 +147,18 @@
146147
(map (comp :externs second)
147148
(get @test-cenv ::ana/namespaces))))))))))))
148149

150+
(deftest test-externs-type-infer
151+
(is (= 'js/Boolean
152+
(-> (binding [ana/*cljs-ns* ana/*cljs-ns*]
153+
(env/with-compiler-env (env/default-compiler-env)
154+
(analyze (ana/empty-env) '(.isNaN js/Number 1))))
155+
:tag)))
156+
(is (= 'js/Boolean
157+
(-> (binding [ana/*cljs-ns* ana/*cljs-ns*]
158+
(env/with-compiler-env (env/default-compiler-env)
159+
(analyze (ana/empty-env) '(js/Number.isNaN 1))))
160+
:tag))))
161+
149162
(deftest test-externs-infer
150163
(is (= 'js/Foo
151164
(-> (binding [ana/*cljs-ns* ana/*cljs-ns*]

0 commit comments

Comments
 (0)