Skip to content

Commit 19677db

Browse files
committed
* add js-global? helper to analyzer
* in host call check for this case - if js global change the type resolution via externs * add some comment eval exprs for context
1 parent 9609c26 commit 19677db

File tree

4 files changed

+38
-9
lines changed

4 files changed

+38
-9
lines changed

src/main/clojure/cljs/analyzer.cljc

+14-5
Original file line numberDiff line numberDiff line change
@@ -3542,6 +3542,12 @@
35423542
(list* '. dot-form) " with classification "
35433543
(classify-dot-form dot-form))))))
35443544

3545+
(defn js-global?
3546+
"Return true if the expr is a JS global"
3547+
[expr]
3548+
(and (= 'js (:ns expr))
3549+
(some? (get-in (get-externs) [(-> (:name expr) name symbol)]))))
3550+
35453551
(defn analyze-dot [env target field member+ form]
35463552
(let [v [target field member+]
35473553
{:keys [dot-action target method field args]} (build-dot-form v)
@@ -3550,11 +3556,14 @@
35503556
form-meta (meta form)
35513557
target-tag (:tag targetexpr)
35523558
prop (or field method)
3553-
tag (or (:tag form-meta)
3554-
(and (js-tag? target-tag)
3555-
(vary-meta (normalize-js-tag target-tag)
3556-
update-in [:prefix] (fnil conj '[Object]) prop))
3557-
nil)]
3559+
tag (if (js-global? targetexpr)
3560+
;; we have a known global, don't treat as instance of some type
3561+
(with-meta 'js {:prefix [(-> targetexpr :name name symbol) prop]})
3562+
(or (:tag form-meta)
3563+
(and (js-tag? target-tag)
3564+
(vary-meta (normalize-js-tag target-tag)
3565+
update-in [:prefix] (fnil conj '[Object]) prop))
3566+
nil))]
35583567
(when (and (not= 'constructor prop)
35593568
(not (string/starts-with? (str prop) "cljs$"))
35603569
(not (-> prop meta :protocol-prop)))

src/main/clojure/cljs/compiler.cljc

+1-1
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/main/clojure/cljs/externs.clj

+1
Original file line numberDiff line numberDiff line change
@@ -432,5 +432,6 @@
432432
(get 'React)
433433
(find 'Component) first meta)
434434

435+
(info (externs-map) '[Number])
435436
(-> (info (externs-map) '[Number isNaN]) :ret-tag) ;; => boolean
436437
)

src/test/clojure/cljs/externs_parsing_tests.clj

+22-3
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,35 @@
4848
(find 'HTMLDocument) first meta)]
4949
(is (= 'Document (:super info)))))
5050

51-
;; TODO:
52-
;; analyze (.isNaN js/NaN 1)
53-
;; node :tag should be js/Boolean
51+
(deftest test-number-infer-test
52+
(let [cenv (env/default-compiler-env)
53+
aenv (ana/empty-env)]
54+
(is (= (env/with-compiler-env cenv
55+
(:tag (ana/analyze aenv '(.isNaN js/Number 1))))
56+
'js/Boolean))))
57+
58+
;; TODO: js/subtle.crypto
5459

5560
(comment
5661

62+
(externs/info
63+
(::ana/externs @(env/default-compiler-env))
64+
'[Number])
65+
66+
(externs/info
67+
(::ana/externs @(env/default-compiler-env))
68+
'[Number isNaN])
69+
5770
;; js/Boolean
5871
(env/with-compiler-env (env/default-compiler-env)
5972
(ana/js-tag '[Number isNaN] :ret-tag))
6073

74+
;; js
75+
(let [cenv (env/default-compiler-env)
76+
aenv (ana/empty-env)]
77+
(->> (env/with-compiler-env cenv
78+
(:tag (ana/analyze aenv '(.isNaN js/Number 1))))))
79+
6180
(externs/parse-externs
6281
(externs/resource->source-file (io/resource "goog/object/object.js")))
6382

0 commit comments

Comments
 (0)