cljs-dev

borkdude 2025-08-28T12:31:14.544699Z

@dnolen about referring global things https://clojurians.slack.com/archives/C03S1L9DN/p1756384244216269?thread_ts=1756298300.319249&cid=C03S1L9DN - maybe continue here?

borkdude 2025-08-28T12:31:24.372809Z

would love to know more

dnolen 2025-08-28T12:31:54.179799Z

:refer-global :only

borkdude 2025-08-28T12:34:25.082719Z

@dnolen I see there is also a variant without :only?

(ns foo.core
                           (:refer-global [Date] :rename {Date MyDate})

thheller 2025-08-28T12:35:24.177559Z

thats commented out, so probably not 😛

dnolen 2025-08-28T12:35:44.494059Z

yeah, no

dnolen 2025-08-28T12:35:48.989559Z

no variants

borkdude 2025-08-28T12:36:55.948519Z

oh ok. values going into :rename don't have to be :only 'd first? with :require + :refer that is the case AFAIK?

dnolen 2025-08-28T12:38:06.017799Z

I'm inclined not to support that - at least initially

borkdude 2025-08-28T12:38:47.204969Z

FWIW:

user=> (require '[clojure.set :rename {union xunion}])
nil
user=> (xunion #{1 2 3} #{4 5 6})
Syntax error compiling at (REPL:1:1).
Unable to resolve symbol: xunion in this context
My expectation is that this would work the same in CLJS for :require-global

thheller 2025-08-28T12:39:05.583109Z

why not? seems redundant to name things twice

borkdude 2025-08-28T12:39:16.988369Z

but this test seems to suggest otherwise:

(deftest test-parse-global-refer
  (let [parsed (ana/parse-global-refer-spec {}
                '((:refer-global :only [Date] :rename {Symbol JSSymbol})))]
    (is (= parsed
           '{:use {Date js}
             :rename {JSSymbol js/Symbol}}))))

dnolen 2025-08-28T12:40:32.846089Z

oh hrm sorry, I switched gears to the lite mode stuff - I think you all are right, only and rename gets combined - so it works

borkdude 2025-08-28T12:40:37.234639Z

why not? it seems CLJS already works that way:

$ plk
ClojureScript 1.11.132
cljs.user=> (require '[clojure.set :rename {union xunion}])
Unexpected error (ExceptionInfo) compiling at (<cljs repl>:1:1).
Renamed symbol union not referred at line 1

dnolen 2025-08-28T12:40:53.865979Z

and this agrees w/ what was done before

dnolen 2025-08-28T12:41:27.348429Z

but the important thing to note here ... is that what's driving this is Clojure refer

dnolen 2025-08-28T12:41:30.709689Z

not require

dnolen 2025-08-28T12:41:38.937819Z

because nothing is being required here

borkdude 2025-08-28T12:41:55.085939Z

only is the counterpart to refer here?

dnolen 2025-08-28T12:41:56.747449Z

so require expectations do not need to be fulfilled

dnolen 2025-08-28T12:43:32.483039Z

yeah so I'm correct in that you probably need :only

dnolen 2025-08-28T12:43:35.010589Z

see https://clojuredocs.org/clojure.core/refer

borkdude 2025-08-28T12:44:55.674469Z

I'm not sure if we're on the same page. Do you think that the renamed value should also occur in :only ? yes or no

dnolen 2025-08-28T12:45:29.217569Z

you do see how :refer works and what it means in Clojure?

dnolen 2025-08-28T12:45:43.614449Z

I'm starting from there, I'm not concerned about convenience or anything else really

borkdude 2025-08-28T12:46:32.370979Z

aaah I see now:

user=> (refer 'clojure.set :rename '{join x}
)
nil
user=> (x #{1 2 3})
Execution error (ArityException) at user/eval8 (REPL:1).
Wrong number of args (1) passed to: clojure.set/join

dnolen 2025-08-28T12:46:42.836239Z

I ran aground of this problem once I started working on the macro for the REPL

dnolen 2025-08-28T12:46:58.712269Z

you just referred the whole clojure.set namespace

dnolen 2025-08-28T12:47:13.068969Z

see the clojure.docs for the conflict warnings example

borkdude 2025-08-28T12:48:20.121329Z

right, so it should be:

user=> (refer 'clojure.set :only '[join] :rename '{join x})
nil
user=> (x #{1 2 3} #{4 5 6})
and this is how require-globals should also work - right?

borkdude 2025-08-28T12:48:41.399489Z

sorry, `:refer-globals` :refer-global

dnolen 2025-08-28T12:49:21.260099Z

yes

borkdude 2025-08-28T12:49:54.924449Z

then we are on the same page since my original message, thank you for clearing this up. the test-parse-global-refer seemed to indicate otherwise

dnolen 2025-08-28T12:50:55.715019Z

oh yeah sorry, that needs to be fixed up

dnolen 2025-08-28T12:53:34.521039Z

I'm not totally against sugar because of course refer-global w/o :only doesn't mean anything - we cannot know what's in the global ns

dnolen 2025-08-28T12:54:02.869599Z

but can be done trivially after people play around w/ it

thheller 2025-08-28T12:54:56.983299Z

(:refer-global :rename {Date Foo}) we also know that Date is something global, so the extra :only [Date] is just redundant. that can be inferred

dnolen 2025-08-28T12:55:13.388049Z

that could be a nice thing

dnolen 2025-08-28T12:55:21.095279Z

if we can auto known things

dnolen 2025-08-28T12:55:40.858519Z

(but that's why I kind of like these decisions later since the design space opens up fast)

thheller 2025-08-28T12:56:00.786629Z

but we know it just by the fact that its mentioned in this form. it can't rename something from another form or so

borkdude 2025-08-28T12:56:02.202979Z

The point that it can be inferred seemed not to be an argument for :require + :refer in JVM Clojure and CLJS so far. I'm not totally against it, but I think it's nice to keep to the defacto standard which is JVM Clojure as well

thheller 2025-08-28T12:56:52.598359Z

(CLJ doesn't have refer-global so no "standard" to adhere to)

thheller 2025-08-28T13:00:55.023039Z

I find the implication of :only a bit confusing, since that kinda seems to imply there is a way to :refer :all for all globals, which we can't know

borkdude 2025-08-28T13:01:23.575919Z

(:refer js/globalThis :only [Date] :rename {Date x})

borkdude 2025-08-28T13:01:58.573859Z

I had the same feeling about :only but I dropped that objection since :refer is a standard

borkdude 2025-08-28T13:03:59.246149Z

but if you argue that there is no standard to adhere to since this is a completely new feature, I'd buy that too

thheller 2025-08-28T13:05:46.376979Z

:only as used in current places means actual "only", as in that thing but nothing else. not using :only meaning everything. but in :refer-global not using it doesn't mean all globals, since we can't know that

👍 1
thheller 2025-08-28T13:06:05.460589Z

dunno its bikeshedding. doesn't really matter what it is as long as its consistent

thheller 2025-08-28T13:06:28.198719Z

:only+`:rename` seems redundant but also doesn't really matter

borkdude 2025-08-29T10:59:09.225639Z

One additional question. Will :refer-global also support the property syntax, like:

(:refer-global :only [Library$Module])
like is supported in :require with e.g. $default ? I think this is a must have when using CLJS with script tags that pull in other libraries that define a nested library structure. Even more compelling with :lite-mode . I don't think the :refer-global syntax lends itself well for this at the moment. In :require you can give such a property-accessed object an alias, e.g. (:require ["foobar$default" :as foobar]) but this doesn't work with :refer-global

borkdude 2025-08-29T11:16:12.811089Z

(I removed my "ship it" message since this seems kind of important!)

dnolen 2025-08-29T12:19:57.537729Z

there's a separate thing I haven't worked on yet :require-global which supports require syntax.

dnolen 2025-08-29T12:20:31.109229Z

The idea here is to distinguish between browser builtins and other scripts you added to the page. :require-global is for the later.

borkdude 2025-08-29T12:28:19.714959Z

why distuingish? and how would one refer window.Intl.NumberFormat for example? (this is just an example, there might better ones)

dnolen 2025-08-29T14:43:24.138519Z

Intl/NumberFormat - any real properties in the browser can be inferred properly

dnolen 2025-08-29T14:43:39.219529Z

you never need to write window that's just global stuff

dnolen 2025-08-29T14:44:45.001389Z

haven't seen any compelling argument for complecting into one thing here.

dnolen 2025-08-29T14:46:17.142869Z

another thing here is validation logic

dnolen 2025-08-29T14:46:43.784629Z

for browser globals we can check lots of things that aren't going to work

dnolen 2025-08-29T14:47:04.532129Z

for libs, maybe a couple of runtime asserts in dev

borkdude 2025-08-29T14:50:52.589789Z

I mean when you want to have NumberFormat itself referred, not with the Intl prefix. So you can write (NumberFormat/supportedLocalesOf ...) . Maybe this isn't the strongest example, but maybe down the road there will be browser APIs where this makes more sense. Complected: I'm agnostic to the difference between a host global or something defined by a polyfill or just a normal library. To me it doesn't matter. This also isn't browser specific, could also be node, Bun, etc.

dnolen 2025-08-29T14:59:33.849449Z

browser apis are not that nested - it's inconvenient, really not concerned about that.

dnolen 2025-08-29T15:00:00.496529Z

polluting the global ns is not a thing JS runtimes do that much for the obvious reasons

dnolen 2025-08-29T15:00:10.137109Z

unlike the browser

p-himik 2025-08-28T19:47:40.801229Z

Looks like a bug in CLJS. As I mentioned in my response to that thread, no clue how Transit would be related, but cljs.analyzer/cache-file can return either File or URL while cljs.analyzer/write-analysis-cache expects it to always be File. https://clojurians.slack.com/archives/C03S1L9DN/p1756400705732949