@borkdude or anyone — I am working on a portal viewer that’s cljs evaluated via sci.
this require fails with “could not find namespace: goog.object”
https://github.com/mentat-collective/Leva.cljs/blob/main/src/leva/schema.cljs#L6
is there a replacement I can use, for goog.object/set with a string key (not known at compile time) and value?
I would use assoc if I were in cljs, but I’m mutating a JS object here
yes, (aset obj "foo" "bar")
okay nice, whenever I do that someone pops up and says “only use aset with arrays!!”
yeah, I know ;P
borkdude approved, done! and yes this is clearly the right way, thanks!
cljs.user=> (doto #js {} (js/Reflect.set "foo" "bar"))
#js {:foo "bar"}but this is way more expensive in SCI, so I'd just use aset
@borkdude any preferred substitute for this-as in sci?
depends on the exact example
this is from portal, when I try to require a cljs file that uses this-as inside of it cc @djblue
https://github.com/mentat-collective/JSXGraph.cljs/blob/main/src/jsxgraph/core.cljs#L50-L52
@borkdude oh whoops I assumed your link was a docstring for this-as, instead it’s a workaround -
yes, this-as is only possible in a compiled language, in an interpreter I haven't found a way
there must be some other way to get the “context” for the event, I’ll read up
so it’s calling the handler with https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
I think I can get around this
thisAs = new Function('return this'); var obj = { fn: thisAs }; obj.fn()
=> {fn: ƒ}
nice :)
user=> (def thisAs (new js/Function "return this"))
#'user/thisAs
user=> (def obj #js {:fn thisAs})
#'user/obj
user=> (.fn obj)
#js {:fn #object[anonymous]}(this is SCI)
I guess I could use that in SCI and track where the this-as local is used and insert a call to this special thisAs function instead
another alternative would be to wrap every function body in SCI with this-as in the host, but not sure if there would be a performance impact
Although, I guess this-as is a macros
(defmacro this-as
"Defines a scope where JavaScript's implit this is bound to the name provided."
[name & body]
`(let [~name (~'js* "this")]
~@body))in CLJS it's a macro, but in SCI I could treat it as a special thing
I updated the issue here, I think the js/Function thing is interesting, I'll try it when I have some time after the bb conf. Or perhaps @mkvlr feels like hacking on this with me tomorrow ;) https://github.com/babashka/sci/issues/564
I’ve got it worked out for now, turns out I could close over the object that was eventually passed to my callback as this, since I had just created it when I registered the callback
yeah, that's how I usually work around it too
I tried a couple of things, but I'm still getting the global object in SCI for "this":
cljs.user=> (def obj (sci/eval-form (sci/init {:bindings {'thisAs (js/Function. "return this") }}) (do (def obj (clj->js {:f (fn [] (thisAs))})) (.f obj))))
#'cljs.user/obj
cljs.user=> (identical? obj js/globalThis)
trueah wait:
cljs.user=> (sci/eval-form (sci/init {:bindings {'thisAs (js/Function. "return this") }}) (do (def obj (clj->js {:fn thisAs})) (.fn obj)))
#js {:fn #object[anonymous]}so it doesn't work when you add the thisAs in a wrapped function
I wish I could make this work:
(sci/eval-form (sci/init {:bindings {'thisAs (js/Function. "return this") }}) (do (def obj (clj->js {:fn (fn [] (thisAs))})) (.fn obj)))
since then I could probably also make this-as work, but it seems thisAs needs to be directly on the object@sritchie09 unchecked-set/get may be more "idiomatic" than aget/set, even though the docs say it's internal ;)
oh not exposed in SCI it seems
but could do that (issue/PR welcome)
ah well, aget/set works