Fork me on GitHub
#clojurescript
<
2021-08-25
>
seancorfield04:08:12

A user of tools.cli on ClojureScript just tripped over this difference from Clojure -- is this a known issue? Is it considered a bug?

ClojureScript 1.10.758
cljs.user=> (hash-map :a)
{}
cljs.user=> (apply hash-map [:a])
{:a nil}
Both of those raise exceptions in Clojure -- and they don't even seem consistent with each other in ClojureScript.

thinking-face 3
seancorfield04:08:03

(they had a named argument without a value -- which is an error in Clojure but slightly behaved in ClojureScript as if the named argument had the value nil)

Simon10:08:15

Does someone know where i can find this pulsating hint component: I have often seen it in getting started guides and i suspect it is a OTS component.

p-himik11:08:11

It's relatively easy to implement with just CSS, no need for some components at all. For example: https://findbootstrapsnippets.com/bootstrap-templates/ripple-dot-animation.html

šŸ™ 3
Simon11:08:25

Thank You. I agree it is not a big challenge, but importing something would be easier

Simon11:08:20

for reference. I might look into using this: https://ant.design/components/badge/# with :status "processing"

p-himik11:08:46

As long as you're aware of the potential consequences of using just a single component from a huge UI library. :)

Simon11:08:06

with advanced compilation, that shouldn't be a problem AFAIK?

p-himik11:08:05

That can very well be a problem. It all depends on how much that component uses and how you import it. Advanced compilation is not a wizard - DCE is rather limited in its abilities.

p-himik11:08:32

Personally, I wouldn't even try using some library for just that tiny dot. I'd copy the CSS and be done with it. Apart from giving me a guarantee that it will remain tiny, forever, it also gives me an ability to customize it in absolutely any way. But if you really want to use some component, make sure to analyze the resulting bundle size (at least shadow-cljs is able to provide you with the details) and see how bad it is.

Simon11:08:16

Actually I agree that it is quite ridiculous to use a component in this case. But another very relevant topic is bundle size: ā€¢ when I run a prod build on shadow-cljs it doesn't show this message. but shows it in dev builds. So i think it works. ā€¢ But what tool in shadowcljs are you referring to? the 13.4 build report? (see image)

p-himik11:08:11

Yes, the build report.

p-himik11:08:54

> when I run a prod build on shadow-cljs it doesn't show this message. but shows it in dev builds What message?

p-himik11:08:13

Ah, gotcha.

p-himik11:08:29

My bet is that the warning is simply disabled in the production build.

Simon12:08:03

Hmm okay, i will check that out.

Simon12:08:41

warning or no warning the build report and bundle size will decide

šŸ‘ 3
Simon12:08:59

Thanks again

Pepijn de Vos12:08:37

Hm so I have an ancient clj library that predates cljs and I'm thinking of implementing the same functionality in cljs. What would be a good way to publish that as a library? It needs JS dependencies. The app I want to use it with is using shadow-cljs but uh I basically have no idea how cljs+js+clojars works.

Pepijn de Vos08:08:54

huh I was trying to see a full example but https://github.com/henryw374/cljs.java-time/blob/master/deps.edn doesn't contain any npm

henryw37408:08:38

well... no. there's quite a bit of detail that's not documented anywhere else. also there's choices wrt npm-deps, cljsjs etc that is discussed

dnolen12:08:38

@pepijndevos publishing CLJS is the same as CLJ more or less

dnolen12:08:21

deps.cljs in the JAR can declare :npm-deps which is used to determine deps from NPM

āœ… 3
Ryan13:08:56

Hey all, trying to use the materialdesignicon (mdi) library for icons.. it's basically a ton of exported vars with svg attached like mdiAccountCircle, is there a way to import without naming each individual icon? I've tried [:require "@mdi/js" :as "mdi" then calling mdi/mdiAccountCircle but no luck so far.

Ryan13:08:47

Hmm I think I sorted it by not including the name I :as'd to. [:> Icon {:path "mdiAccountCircle"}] worked just fine with my :as mdi

p-himik13:08:05

Note that importing all the icons will increase your bundle size, even the release one.

Ryan14:08:30

Hmm a good point, I guess the bundle size restriction would be worth the super gangly import (we use like 30-40 icons on various bits of global nav

Ryan14:08:04

Ok, a bit of refactoring later and I did need to add the :as, e.g. mdi/mdiAccountCircle ... I'm trying to abstract it to just require the mdiAccountCircle as a string, I tried to call it using (symbol "mdi" "mdiAccountCircle") but I don't think its resolving.. what do I need to call on a symbol to resolve it from an import?

Ryan14:08:16

I should really try calling the first function that comes to mind before I post šŸ˜‰

p-himik14:08:26

mdi will be a JS object - you will be able to access mdiAccountCircle via regular JS interop.

Ryan15:08:52

I'm struggling with this a bit.. the only thing I can get to work is [:> Icon {:path mdi/mdiAccountCircle}], cannot figure out how to replcea the mdiAccountCircle piece with an arbitrary string

Ryan15:08:09

The library file just exports paths like export mdiAccountCircle={blah}

p-himik15:08:44

What does your import look like?

Ryan15:08:07

["@mdi/js" :as mdi]

p-himik15:08:23

You should be able to replace mdi/mdiAccountCircle with (goog.object/get mdi "mdiAccountCircle").

Ryan15:08:22

ooh heck yes that works

Ryan15:08:02

thanks @p-himik .. I was trying all sorts of dots and dashes .. I felt like I was trying to fake morse code

šŸ‘ 3
Ryan15:08:14

I need to wrap my head around interop better!

ersin13:08:34

Hi all, this might be an easy question but I couldnā€™t find an answer. Is there a way to convert integers to doubles (with decimal) in ClojureScript? Simply Iā€™d do (double 1.0) => 1.0 in clojure to get the value but in cljs I get (double 1.0) => 1 which is causing me issues when I try to validate input in backend.

donavan13:08:25

There are no integers in jsā€¦ theyā€™re all doubles

ersin13:08:51

Thanks for the quick reply but Iā€™m still a bit confused. Letā€™s say I want to call my endpoint with {:value (- 5.00 1.00)} and on server side I validate schema by saying value should be double. value I sent gets converted (after the - calculation) to 4 instead of 4.00 which will cause exception. How would you go for it or am I missing something?

donavan13:08:03

Not sure exactlyā€¦ what is in the request to the server? E.g. what is in the request in Chromeā€™s network tab

ersin13:08:20

["^ ","~:endHeight",12,"~:endX",152.9246,"~:type","Text","~:startHeight",12,"~:startPage",2,"~:endY",332.625,"~:startX",54,"~:startY",332.625,"~:endPage",2,"~:text","Some example text here"]
This is a transit request body taken from the Chrome Network tab which Iā€™m trying to send startX value as double, but I cannot send it as 54.0 which our backend expects it to be a double and gives exception. This is the request body we passed to cljs-ajax:
{:type        "Text"
 :text        text
 :startX      (double (:x start-position))
 :startY      (double (:y start-position))
 :startHeight (double (:height start-position))
 :endX        (double (:x end-position))
 :endY        (double (:y end-position))
 :endHeight   (double (:height end-position))
 :startPage   start-page-number
 :endPage     end-page-number}

donavan13:08:36

I would probably coerce before validating. AFAIK there is no way to ensure itā€™s represented as a double in js

donavan13:08:04

ā€¦i.e. always with a decimal at the end

p-himik13:08:49

As an alternative, change the backend so the relevant functionality accepts not only doubles but also longs.

dpsutton14:08:32

> valueĀ I sent gets converted (after the - calculation) to 4 instead of 4.00 This statement is false. 4.00 does not get converted to 4. They are exactly identical. There is no 4 integral value in javascript

šŸ‘ 3
ersin14:08:59

Taken from core.cljs

(defn ^number short [x] x)
(defn ^number float [x] x)
(defn ^number double [x] x)
Seems like clojurescript doesnā€™t do anything with double function which confused me in the first place. Iā€™m guessing it is related to number handling in js world as you all said. Thanks for answers and your time.

ersin14:08:47

@p-himik we already diverted to that path I wanted to see if there is any other way šŸ˜„

šŸ‘ 3
Davey Wood21:08:32

If there was anything to be done in the client, it would be done in your serialization code. Not by doing any sort of conversion on the value.

dnolen13:08:22

@esezgin2000 there are no integers in JavaScript. What you are seeing is simply how JavaScript prints values. You probably want to format then.

šŸ™ 3
dnolen13:08:00

(1.0).toString() => "1" you can try this yourself in any JS console/REPL

ersin13:08:20

["^ ","~:endHeight",12,"~:endX",152.9246,"~:type","Text","~:startHeight",12,"~:startPage",2,"~:endY",332.625,"~:startX",54,"~:startY",332.625,"~:endPage",2,"~:text","Some example text here"]
This is a transit request body taken from the Chrome Network tab which Iā€™m trying to send startX value as double, but I cannot send it as 54.0 which our backend expects it to be a double and gives exception. This is the request body we passed to cljs-ajax:
{:type        "Text"
 :text        text
 :startX      (double (:x start-position))
 :startY      (double (:y start-position))
 :startHeight (double (:height start-position))
 :endX        (double (:x end-position))
 :endY        (double (:y end-position))
 :endHeight   (double (:height end-position))
 :startPage   start-page-number
 :endPage     end-page-number}

ersin14:08:59

Taken from core.cljs

(defn ^number short [x] x)
(defn ^number float [x] x)
(defn ^number double [x] x)
Seems like clojurescript doesnā€™t do anything with double function which confused me in the first place. Iā€™m guessing it is related to number handling in js world as you all said. Thanks for answers and your time.

dnolen14:08:11

@esezgin2000 there are some placeholder fns just for compatibility

šŸ‘ 3
dnolen14:08:19

but let's rewind - your problem isn't a JavaScript problem

dnolen14:08:23

it's a Transit problem

dnolen14:08:18

back when I worked on transit-js at Cognitect - it was decided for transport, integers were probably the more common case for typical client to backend - that's debatable - but that's what we went with

dnolen14:08:52

however transit-js is an extensible format

dnolen14:08:21

just define your own tagged type - wrap your JS numbers in it, and then you will get what you want on the other side provided you have corresponding read handler

ersin14:08:41

Thanks for the detailed answer, after reading your messages I read the source code for the transit conversion where I believe this is implemented. It gave me a good insight for how it works.

Pepijn de Vos14:08:53

Welp somehow the very first thing I try in cljs.core.async blows up spectactularly

(defn pouch-swap! [db key f & args]
  (go-loop [r (<p! (.get db key))]
      (try
        (<p! (.put db (apply f r args)))
        (catch js/Error err
          (recur (<p! (.get db key)))))))
What?
IllegalArgumentException: No implementation of method: :emit-instruction of protocol: #'cljs.core.async.impl.ioc-macros/IEmittableInstruction found for class: cljs.core.async.impl.ioc_macros.Jmp

dnolen14:08:04

@pepijndevos you cannot recur across try

souenzzo14:08:58

worth a ticket for a better error message?

šŸ‘€ 3
Pepijn de Vos14:08:10

Hm so how do I work around that?

souenzzo14:08:17

one possible solution

(defn pouch-swap! [db key f & args]
  (go-loop []
    (let [r (<p! (.get db key))
          [result ex] (try
                        [(<p! (.put db (apply f r args)))]
                        (catch js/Error ex
                          [nil ex]))]
      (if ex
        (recur)
        result))))

āœ… 3
dnolen14:08:36

there is no way to work around it, you cannot do it

dnolen14:08:58

but probably whatever you're trying to do can be done, just re-arrange the code

p-himik14:08:31

Lift the recur from try, make it conditional upon one of the two values returned from try (the regular result and the error result).

āœ… 3
souenzzo14:08:58

worth a ticket for a better error message?

šŸ‘€ 3
Pepijn de Vos14:08:33

I can never figure out where the type hint goes when the compiler complains.

(.-status (.-cause res))
I've tried spamming ^js everywhere but it keeps saying `Cannot infer target type in expression (. inst_37262 -cause)`

Pepijn de Vos14:08:39

It also plain doesn't work. If I make rest a global variable in the firefox console temp1.cause.status gives 409 but apparently that code does not...

p-himik14:08:29

Have you tried (.-cause ^js res)?

Pepijn de Vos14:08:37

I've tried ^js (.-status ^js (.-cause ^js res)) and still nothing

p-himik14:08:43

Are you 100% certain that it's that form in particular that generates the warning?

p-himik14:08:27

inst_37262 looks very different from res. :)

p-himik14:08:41

You seem to have some macro somewhere that uses inst#.

Pepijn de Vos14:08:01

99% but everything is so fucked up right now I have no idea what's going on. It's the only -cause in the whole code, but it's in a go block so maybe that's doing funky stuff.

p-himik14:08:27

Ah, yes. that's the case. go blocks remove metadata.

p-himik14:08:42

Or rather, CLJS type hints.

p-himik15:08:22

Instead, extract that getting operation in a function with a proper hint and call that function in the go block.

p-himik15:08:06

A go block is a macro that heavily transforms the code within it. It just isn't written in a way that would preserve that metadata (not sure if it's possible to write it in such a way at all).

Pepijn de Vos15:08:03

Ok yea that did the trick

souenzzo15:08:57

go also do not play nice with #js {} literals

p-himik15:08:52

How come, what happens?

p-himik15:08:06

Superficially, seems to work just fine:

cljs.user=> (a/go (js/console.log (a/<! (a/go #js {:a 1}))))
#object[cljs.core.async.impl.channels.ManyToManyChannel]
cljs.user=> { a: 1 }

souenzzo15:08:41

I can't remember now, but it's something with var access....

(def a 1)
(defn ...
  (let [a 2]
     (go #js {:a a})))
Maybe you need a <! in some place too.

dnolen15:08:27

cljs.core.async go block definitely has many old issues - it was never brought in line with Clojure impl

dnolen15:08:00

the js literal thing is the killer one - that's definitely next on my list when I have time for core.async stuff

ā¤ļø 3
dnolen15:08:39

unfortunately unlike the years old and/or bug which was finally fixed, this requires actually tweaking core.async

Pepijn de Vos15:08:50

Eh... how broken is this go block?

(defn pouch-swap! [db key f]
  (go-loop []
    (let [old (js->clj (<p! (.get db key)))
          new (f old)
          res (try
                (<p! (.put db (clj->js new)))
                (catch js/Object err err))]
      (if (instance? js/Error res)
        (if (= 409 (errorcode res))
          (recur)
          (throw res))
        [old new]))))
Gives
Uncaught Error: Invalid arity: 7
    call core.cljs:6851
    switch__29505__auto__ hipflask.cljs:11
    ret_value__29507__auto__ hipflask.cljs:11
[...]
Where the core.cljs line points to
(deftype PersistentArrayMap [meta cnt arr ^:mutable __hash]
What the hell?

borkdude15:08:50

In CLJS projects do you folks typically run tests with both optimizations none and advanced or only the latter?

thheller16:08:54

advanced in CI, none while working on the tests

dnolen16:08:26

@pepijndevos you probably want (catch :default ...)

p-himik16:08:53

Apart from :default, don't use the word new - that's the thing that messes the above code.

dnolen16:08:17

@pepijndevos you're also throwing from async code which is meaningless

dnolen16:08:23

noone will ever catch it

Pepijn de Vos16:08:07

ahh new messed it up apparently ok wft haha

Pepijn de Vos16:08:42

Uh so what do you do with the error? Just log it and pretend all is good?

dnolen16:08:31

at high level the problem is same as callback and Promises

dnolen16:08:38

you cannot throw, because no one is going to catch it

dnolen16:08:02

with callbacks you must feed the error into the callback, following some convention

dnolen16:08:18

with Promises you must provide a rejection handler and be extremely careful

dnolen16:08:43

with core.async you should probably return the error as the value of channel - (in the above case exit the loop and return the error value for somebody do something about it - if something can be done)

Joshua Suskalo16:08:22

Is there a good way to have an optional dependency in cljs? Like in clojure I can do the following:

(try (require '[some.ns :as a])
     (do stuff)
     (catch Exception _))
And with that it'll do the stuff iff the library some.ns is available, and will do nothing if it isn't. Is there something I can do in cljs that's equivalent?

p-himik16:08:08

One option is to have a mock namespace and swap the classpath as needed.

dnolen16:08:07

@suskeyhose it is not possible

p-himik16:08:21

Why do these produce different result?

cljs.user=> (macroexpand '(js/Number.))
(new js/Number)
cljs.user=> (macroexpand '(do (js/Number.)))
(do (js/Number.))

dnolen16:08:22

not at runtime

Joshua Suskalo16:08:38

Ah, that's frustrating. I guess this has to be a clj-only feature in my library for now.

dnolen16:08:55

@p-himik macroexpand is not recursive

Joshua Suskalo16:08:39

I thought macroexpand was recursive, but only expanded macros that are at the call position of the top-most list.

šŸ‘€ 1
p-himik16:08:43

Ah, shoot - got confused by the fact that we have macroexpand-1.

Joshua Suskalo16:08:37

It's these sorts of things that make me wish that the clojure cli and deps.edn had a way of resolving dependencies with aliases applied from the dependency map, that way we could more or less have feature flags like in rust.

Joshua Suskalo16:08:11

Especially if it were paired with an "optional require" syntax, where it'd require a namespace if it is available, but wouldn't error if it isn't.

p-himik16:08:26

@dnolen Any chance we'll see clojure.walk/macroexpand-all in CLJS? Got a bit confused by its absence.

p-himik16:08:37

@pepijndevos @dnolen And seems like that issue with new is indeed a bug with go:

(let [new 1] (js/Number.))
after compilation => 
var new_35 = (1);
(new Number());
whereas
(a/go (let [new 1] (js/Number.)))
after compilation (abridged) =>
[...]
var inst_36 = (1).call(null,Number);
[...]
So in a regular let the new gets replaced with new_35 . But in a let within a go, it's not replaced, making it possible to shadow it.

dnolen16:08:54

right there's lot of stuff like this because cljs.core.async doesn't use any analyzer lib

šŸ‘ 3
dnolen16:08:29

that would be next thing to fix after JS literals - but more work

p-himik16:08:00

And right now, sometimes there are šŸ‰ :)

dnolen16:08:27

it would be a good OSS 1-2 month project for somebody to apply to Clojurists Together

dnolen16:08:35

I'm sure many people would be grateful including myself šŸ™‚

dnolen16:08:16

it would mostly be mechanical - since it has been done once already with tools.analyzer for Clojure

dnolen16:08:32

that could be adapted - but of course it will be slow going to get all the tests to pass etc.

dpsutton16:08:20

is there a good document that shows how to hack on the compiler? Just quality of life things like some function that takes a string of clojurescript and returns (or even prints) the compiled js code? I remember seemingly simple things like this were surprisingly difficult to find for me last time.

dnolen16:08:33

no document - but there are lot of tests that show exactly how to do stuff like that

šŸ‘ 3
dnolen16:08:25

tests for externs inference, and/or optimization, etc. all need to compile some form as data and check the output for something

dnolen16:08:12

probably not that well known but even the build function takes forms and can generate a string

Tiago Dall'Oca16:08:43

Hello there! I'd like to ask for guidance to set up a repository for a new library I'm developing. Requirements: - It's meant to target CLJS, hence why I'm posting here - If possible, I would prefer to use deps.edn instead of lein or shadow-cljs - The setup should include tests and examples (ClojureDocs or similar are a plus) How should I set up the repository? How to build and package? Can I host in clojars and are there better alternatives? Any guides or tutorials are welcome! I'm most comfortable with Clojure, having limited Clojurescript experience.

lilactown16:08:57

in terms of building and packaging and publishing to clojars, all you need to do is publish a JAR with your clojurescript source code in it

lilactown16:08:14

I haven't done this with plain deps.edn but I'm sure it's doable

lilactown16:08:42

for running tests, kaocha makes it pretty easy to do that from the CLI and in a CI environment

dpsutton16:08:03

i think i remember the most trouble was figuring out how to get the correct initialized environment.

dnolen16:08:54

@dpsutton right the tests how to do all that too - it is annoying for sure and become more so over time mostly due to externs inference

dnolen16:08:17

ClojureScript has some files to generate the AST reference

dpsutton16:08:34

oh nice. that's quite helpful. I think it would be kinda fun to try this. Might apply for the clojurists together bit

dnolen16:08:09

it does take some time to get familiar with - but honestly I do not think it is particularly challenging

dnolen16:08:29

again you have many tests to look at - the new passes stuff would also be useful when hacking

dnolen16:08:41

in the case of core.async I'm pretty sure you're just messing around w/ the AST - you don't need to concern yourself with much else

dnolen16:08:53

(can ignore the details of analysis and ignore emission)

dnolen16:08:54

I believe I fixed the last issue with tools.analyzer rep conformance when I did the and/or stuff

dnolen16:08:01

permitting generic walking

danbunea18:08:26

Hi, I would like to use a material web component in my reagent app, specifically the mwc-button (https://github.com/material-components/material-web/tree/master/packages/button). Any idea?

danbunea18:08:56

that was fast. Thank you šŸ™‚

danbunea18:08:40

unfortunately this is the web component (mwc-button) that I need, not the react component for material UI

borkdude19:08:02

Re, yesterday's convo on ESM style imports + the new dollar sign in CLJS. I just tried this with the nodejs chalk library to stay close to their README example, and with #nbb it just worked :)

(ns script
  (:require ["chalk$default" :as chalk]
            ["console$log" :as log]))

;; Combine styled and normal strings
(log (chalk/blue "hello") (str " world" (chalk/red "!")))

šŸ™Œ 9
3
thheller05:08:23

please note that :as is meant to be an alias, if you are calling it directly you likely should be using :refer (eg. (:require ["console" :refer (log)]))

thheller05:08:15

also note that there is no such thing as ESM style imports. "$" works for any JS and is not related to ESM in any way. literally all it does is append the suffix to the thing you imported

borkdude05:08:53

Good points. The dollar is probably just more ubiquitous because of the ā€˜defaultā€™ thing with ESM

thheller05:08:17

yeah its syntax sugar since ["chalk" :as chalk] and (chalk/default.blue "hello") kinda sucks, as does ["chalk" :rename {default chalk}] (.. chalk (blue "hello"))

thheller05:08:59

even ["chalk" :default chalk] and (.. chalk (blue "hello")) kinda sucks so the "$" setting up any :as alias is nicer.

johanatan19:08:05

does anyone know if there is a tool like the following for clojurescript: https://github.com/gfredericks/clj-usage-graph ??

borkdude19:08:07

clj-kondo can provide you this information

johanatan19:08:01

@U04V15CAJ thanks, i'll look into that

Pepijn de Vos19:08:42

Does cljs have like a drop trait? Basically I made a deftype constructor that registers an event handler that calls methods on the deftype, the problem is this event handler leaks the deftype. So somehow I need to cancel the event handler when the deftype is freed.

p-himik19:08:48

Not sure I understand. What do you mean by "when the deftype is freed"? Shouldn't it be the reverse - you detach the event handler, and it no longer holds a reference to an instance of the deftype?

p-himik19:08:42

Exactly, so you hold on to the reference to p in that .on "change". Remove the handler - and the reference should be freed as well.

Pepijn de Vos19:08:51

Yea so then you manually have to cancel the handler when you're done with the PAtom.

Pepijn de Vos19:08:33

I was hoping there is a way to have like a "weak" reference to the PAtom, and then cancel the event handler when the PAtom goes out of scope.

lilactown20:08:25

WeakMap/WeakRef and finalizers have only been in the spec for a couple years. previous to that you had no real way to do this in a JS context

Pepijn de Vos20:08:43

(defn patom [db key]
  (let [p (PAtom. db key nil nil)
        wp (js/WeakRef. p)
        ch (.changes db #js{:since "now"
                      :live true
                      :include_docs true
                      :doc_ids #js[key]})]
        (.on ch "change" (fn [change]
                        (if-let [myp (.deref wp)]
                          (-notify-watches myp nil (js->clj (.-doc change)))
                          (.cancel ch))))
    p))
Still doesn't work.

lilactown20:08:37

what do you mean it doesn't work?

Pepijn de Vos20:08:16

(defn watch-changes [db key wp]
  (let [ch (.changes db #js{:since "now"
                            :live true
                            :include_docs true
                            :doc_ids #js[key]})]
    (.on ch "change" (fn [change]
                       (if-let [myp (.deref wp)]
                         (-notify-watches myp nil (js->clj (.-doc change)))
                         (.cancel ch))))))

(defn patom [db key]
  (let [p (PAtom. db key nil nil nil)]
    (set! (.-changes p) (watch-changes db key (js/WeakRef. p)))
    p))
If I do this... well, without the set! it doesn't trigger at all, and with the set! the callback and PAtom never gets freed.

Pepijn de Vos20:08:03

So it seems there is REEEEAALLY sneaky stuff going on with closures holding on to stuff or not.

lilactown20:08:02

that looks right. I don't know how you would reason that p never gets freed because of set!

Pepijn de Vos20:08:14

I figured if I broke out the watch-changes function it would not hold on to the patom closure, which... maybe worked?

lilactown20:08:35

you don't get any guarantees about when or even if p gets freed, only that it eventually might, and if it does it will cancel the change listener

Pepijn de Vos20:08:53

Well so without the set, it never works in the first place.

Pepijn de Vos20:08:13

ah no... works... but now big question is... will it ever get cancelled.

lilactown20:08:04

if you want guarantees, you should have a manual way of disposing of it

lilactown20:08:26

otherwise you're relying on the GC, which may decide to reclaim it immediately or never

Pepijn de Vos20:08:14

Yea I mean, I don't care when it does it... I just want to verify it'll do so before my ram explodes.

Pepijn de Vos20:08:38

Is there a way to see what is referencing an object?

thheller10:08:51

don't think so. at least in chrome. maybe the firefox or safari devtools have something.

Pepijn de Vos10:08:44

Yesterday late at night I was experimenting a bit with just making several thousand listeners and seeing what happened. I got mixed results of CPU spikes followed by what seemed to be reclamation, or just hanging the browser entirely. I'll have to try that some more.

Pepijn de Vos10:08:16

In Firefox I could not really find a memory profiler. It can just take snapshots, or profile CPU.