This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-20
Channels
- # announcements (1)
- # architecture (14)
- # asami (21)
- # babashka (1)
- # beginners (44)
- # biff (6)
- # calva (24)
- # clojure (16)
- # clojure-europe (12)
- # clojurescript (32)
- # cursive (23)
- # datascript (5)
- # honeysql (8)
- # hyperfiddle (1)
- # malli (1)
- # nextjournal (34)
- # nrepl (4)
- # off-topic (64)
- # re-frame (12)
- # reagent (1)
- # releases (2)
- # reveal (41)
- # shadow-cljs (137)
- # spacemacs (4)
- # xtdb (5)
Hi there, I'm using server-side hiccup and would like to embed some inline JS into a <script />
tag to set a variable on the window
object. Something that gets rendered as
<script>window.hello = '{:simple 1}'</script>
and then use cljs.reader/read-string
to convert back into EDN. I'm having trouble figuring out how to achieve the above. Does anyone have any pointers?
[:script (str "window.hello = '" {:simple 1} "'"]
;; <script>'{:simple 1}'</script>
[:script (str "window.hello = \"" {:simple 1} "\"")]
;; <script>window.hello = "{:simple 1}"</script>
Don't use window
. Instead, assign an ID to that tag and set a custom script type. E.g. I use transit for such things and I set the type to application/transit+json
, although it's not really important because the browser just ignores it.
Thanks for the suggestion! I'll give that a try
For my own understanding, is there a benefit to extracting the content from the tag vs. setting it on window
? I guess it's nice to not pollute the global window
, but I was also planning to delete window.hello
once I've accessed the data.
Also for future reference - what is the way to get window.hello = "{:simple 1}"
like I was trying to do above? Seems to be getting html escaped
It's not just polluting - it's also potential clashes. A custom script tag will be available from anywhere, without any need to delete it. Regarding escaping - no clue, to be honest. There's probably a flag for there somewhere or something else that allows it.
if you're using reagent to do SSR you ought to use :dangerously-set-inner-html
to avoid escaping
I am having some trouble with advanced compilation. I have compile options of {:pseudo-names true :pretty-print true}
and the error I am receiving is this:
main.js:12203 Uncaught TypeError: Cannot read properties of undefined (reading '$addModule$')
With output:
return $context$jscomp$1$$.$audioWorklet$.$addModule$($url$jscomp$58$$).then(function() { // remainder truncated
The ClojureScript source this is derived from
(defn init-transport
[ch context media-stream]
(let [url (processor-url)
*module (-> context .-audioWorklet (.addModule url))]
(-> *module
(.then #(put! ch [true (create-transport context media-stream)]))
(.catch #(put! ch [false %])))))
The context
here is a native AudioContext
type created via (js/AudioContext.)
- Am I doing something incorrectly? Should this be an issue with advanced compilation and a native API?^js
in front of context
in the function arg vector should fix it.
I think what's going on is that GCC has an extern for -audioWorklet
but doesn't have an extern for addModule
and CLJS doesn't know that the result of (.-audioWorklet context)
is a JS value.
I tried the following:
(defn init-transport
[ch ^js context media-stream]
(let [url (processor-url)
*module (-> context .-audioWorklet (.addModule url))]
(-> *module
(.then #(put! ch [true (create-transport context media-stream)]))
(.catch #(put! ch [false %])))))
It seems covered there, is this just an issue of clojurescript using an older version of gcc?
It could be, although I was fully expecting ^js
to work there. Hmm.
Does anything change if you extract (.-audioWorklet context)
as a separate binding and mark its name with ^js
instead?
I’ve gone nuclear with this:
(defn init-transport
[ch ^js context media-stream]
(.log js/console "init transport")
(let [url (processor-url)
^js worklet (.-audioWorklet context)
*module (.addModule worklet url)]
(-> *module
(.then #(put! ch [true (create-transport context media-stream)]))
(.catch #(put! ch [false %])))))
function $blah$impl$init_transport$$($ch$jscomp$63$$, $context$jscomp$1$$, $media_stream$jscomp$1$$) {
console.log("init transport");
var $url$jscomp$58$$ = URL.createObjectURL(new Blob(["class WorkletProcessor extends AudioWorkletProcessor {\n process (inputs, outputs, params) {\n const input \x3d inputs[0];\n \n let frames \x3d [];\n for (let ch \x3d 0; ch \x3c input.length; ch++) {\n const samples \x3d input[ch];\n frames[ch] \x3d samples;\n }\n \n this.port.postMessage(frames);\n \n return true;\n }\n }\n\n registerProcessor('worklet', WorkletProcessor);"],
{type:"application/javascript"}));
return $context$jscomp$1$$.$audioWorklet$.$addModule$($url$jscomp$58$$).then(function() {
var $JSCompiler_temp_const$jscomp$151$$ = $cljs$core$PersistentVector$EMPTY_NODE$$, $node$jscomp$inline_1099$$ = new AudioWorkletNode($context$jscomp$1$$, "worklet"), $source$jscomp$inline_1100$$ = $context$jscomp$1$$.createMediaStreamSource($media_stream$jscomp$1$$);
return $cljs$core$async$put_BANG_$cljs$0core$0IFn$0_invoke$0arity$02$$($ch$jscomp$63$$, new $cljs$core$PersistentVector$$(null, 2, 5, $JSCompiler_temp_const$jscomp$151$$, [!0, new $cljs$core$PersistentArrayMap$$(null, 4, [$cljs$core$cst$0kw$0node$$, $node$jscomp$inline_1099$$, $cljs$core$cst$0kw$0source$$, $source$jscomp$inline_1100$$, $cljs$core$cst$0kw$0context$$, $context$jscomp$1$$, $cljs$core$cst$0kw$0media_DASH_stream$$, $media_stream$jscomp$1$$], null)], null));
}).catch(function($p1__3208_SHARP_$$) {
return $cljs$core$async$put_BANG_$cljs$0core$0IFn$0_invoke$0arity$02$$($ch$jscomp$63$$, new $cljs$core$PersistentVector$$(null, 2, 5, $cljs$core$PersistentVector$EMPTY_NODE$$, [!1, $p1__3208_SHARP_$$], null));
});
}
The error is occurring at the return
there. I added the logging as well just to be sure
Also, the compiled output looks suspiciously different from the CLJS code above... With createObjectURL
and stuff.
Note that there's also async
in there - just in case, using go
blocks will also invalidate ^js
. It's a known problem, not sure whether it's fixed in 1.11.4.
In that location - probably, because it shouldn't be. But in general, there are still places where ^js
is needed.
Hi there, I'm using transit to serialize my application state (for SSR), send the state down with html, then deserialize on the client. The transit encoding seems to be failing right now, but the error I'm getting is not that helpful.
Error: Cannot write Interpreter
Since the app state is pretty large, I'd like to hone in on which piece is failing. Do you have any tips to get better debugging info from this?