Skip to content

Commit

Permalink
* add js-global? helper to analyzer
Browse files Browse the repository at this point in the history
* in host call check for this case
  - if js global change the type resolution via externs
* add some comment eval exprs for context
  • Loading branch information
swannodette committed Jan 28, 2025
1 parent 9609c26 commit 19677db
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 9 deletions.
19 changes: 14 additions & 5 deletions src/main/clojure/cljs/analyzer.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -3542,6 +3542,12 @@
(list* '. dot-form) " with classification "
(classify-dot-form dot-form))))))

(defn js-global?
"Return true if the expr is a JS global"
[expr]
(and (= 'js (:ns expr))
(some? (get-in (get-externs) [(-> (:name expr) name symbol)]))))

(defn analyze-dot [env target field member+ form]
(let [v [target field member+]
{:keys [dot-action target method field args]} (build-dot-form v)
Expand All @@ -3550,11 +3556,14 @@
form-meta (meta form)
target-tag (:tag targetexpr)
prop (or field method)
tag (or (:tag form-meta)
(and (js-tag? target-tag)
(vary-meta (normalize-js-tag target-tag)
update-in [:prefix] (fnil conj '[Object]) prop))
nil)]
tag (if (js-global? targetexpr)
;; we have a known global, don't treat as instance of some type
(with-meta 'js {:prefix [(-> targetexpr :name name symbol) prop]})
(or (:tag form-meta)
(and (js-tag? target-tag)
(vary-meta (normalize-js-tag target-tag)
update-in [:prefix] (fnil conj '[Object]) prop))
nil))]
(when (and (not= 'constructor prop)
(not (string/starts-with? (str prop) "cljs$"))
(not (-> prop meta :protocol-prop)))
Expand Down
2 changes: 1 addition & 1 deletion src/main/clojure/cljs/compiler.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@

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

(defmethod emit* :if
[{:keys [test then else env unchecked]}]
Expand Down
1 change: 1 addition & 0 deletions src/main/clojure/cljs/externs.clj
Original file line number Diff line number Diff line change
Expand Up @@ -432,5 +432,6 @@
(get 'React)
(find 'Component) first meta)

(info (externs-map) '[Number])
(-> (info (externs-map) '[Number isNaN]) :ret-tag) ;; => boolean
)
25 changes: 22 additions & 3 deletions src/test/clojure/cljs/externs_parsing_tests.clj
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,35 @@
(find 'HTMLDocument) first meta)]
(is (= 'Document (:super info)))))

;; TODO:
;; analyze (.isNaN js/NaN 1)
;; node :tag should be js/Boolean
(deftest test-number-infer-test
(let [cenv (env/default-compiler-env)
aenv (ana/empty-env)]
(is (= (env/with-compiler-env cenv
(:tag (ana/analyze aenv '(.isNaN js/Number 1))))
'js/Boolean))))

;; TODO: js/subtle.crypto

(comment

(externs/info
(::ana/externs @(env/default-compiler-env))
'[Number])

(externs/info
(::ana/externs @(env/default-compiler-env))
'[Number isNaN])

;; js/Boolean
(env/with-compiler-env (env/default-compiler-env)
(ana/js-tag '[Number isNaN] :ret-tag))

;; js
(let [cenv (env/default-compiler-env)
aenv (ana/empty-env)]
(->> (env/with-compiler-env cenv
(:tag (ana/analyze aenv '(.isNaN js/Number 1))))))

(externs/parse-externs
(externs/resource->source-file (io/resource "goog/object/object.js")))

Expand Down

0 comments on commit 19677db

Please sign in to comment.