The :hoplon: ClojureScript Web Framework - http://hoplon.io/
dave 2020-04-10T12:15:26.057Z

has anyone experienced hoplon's prerendering turning < in inline scripts into <? i'm running into trouble with my app's content security policy because the prerender step is changing the content of an inline script that contains < so that it contains < instead

dave 2020-04-10T12:32:32.058100Z

which seems like a bug. the content of script tags should not be html-escaped

micha 2020-04-10T12:34:40.058900Z

the prerenderer specifically skips scripts

micha 2020-04-10T12:34:46.059200Z

in both the head and the body

dave 2020-04-10T12:34:51.059400Z

in this case, the scripts have :prerender-keep

micha 2020-04-10T12:35:46.060200Z

yeah but that code doesn't look like it knows about :prerender-keep

micha 2020-04-10T12:36:12.060600Z

it's suspicious that it broke all of a sudden

micha 2020-04-10T12:36:20.061100Z

in the middle of changing all the tooling

dave 2020-04-10T12:36:45.061600Z

i think it's been broken the whole time, we just didn't notice in this particular project because the existing scripts we had with :prerender-keep happened not to contain &, <, or >

dave 2020-04-10T12:36:56.061900Z

the new one we're adding wants to do a less-than comparison

micha 2020-04-10T12:37:11.062200Z

can you make a minimal repro case?

dave 2020-04-10T12:37:38.062600Z

to be clear, i've put the debooted branch aside

dave 2020-04-10T12:37:45.063Z

this is all using the existing boot pipeline for geir

micha 2020-04-10T12:37:47.063100Z

like a helloworld that exhibits the problem

dave 2020-04-10T12:38:10.063300Z

i'll see if i can take a stab at that when i have time

dave 2020-04-10T12:38:28.064Z

for now, i think i might need to add a postprocessing step that re-encodes &lt; as &lt;

micha 2020-04-10T12:38:30.064100Z

i don't see how it can possibly be including those scripts

dave 2020-04-10T12:38:36.064300Z

i guess inside of script tags only

micha 2020-04-10T12:38:59.064800Z

there are better ways, you can use the baackslash hex encoding if you need to

micha 2020-04-10T12:39:04.065Z

in the js

dave 2020-04-10T12:39:13.065400Z

ah! i was wondering if there were another way to encode it in the JS

micha 2020-04-10T12:39:26.065800Z

like \x12 or whatever

micha 2020-04-10T12:39:43.066100Z

but link me to the script tag in the cljs code

micha 2020-04-10T12:39:53.066300Z

the problematic one

micha 2020-04-10T12:40:08.066600Z

and also have you tried with prerendering off?

dave 2020-04-10T12:40:24.066800Z

sending it to you on adzerk slack

dave 2020-04-10T12:40:50.067200Z

i've actually been wondering if we really need prerendering

dave 2020-04-10T12:41:20.067900Z

since we're getting caching via cloudfront, i'm not sure if prerendering is helping much beyond that

micha 2020-04-10T12:41:40.068200Z

prerendering helps with the flash of unstyled content

micha 2020-04-10T12:41:53.068500Z

have you built it with prerendering off though?

micha 2020-04-10T12:42:06.068900Z

to eliminate other issues unrelated to prerendering that may be causing it

dave 2020-04-10T12:43:08.069200Z

yeah, without prerendering the problem goes away

dave 2020-04-10T12:43:20.069700Z

my first thought was that it might be an advanced optimizations issue, but that wasn't it

dave 2020-04-10T12:49:03.070700Z

hmm, it looks like \x3C is the escape sequence for &lt;, but it doesn't seem to work outside of javascript string literals

dave 2020-04-10T12:49:19.071200Z

i've only experimented in the JS console, though. not sure if it behaves differently in an inline script tag

dave 2020-04-10T12:49:48.071600Z

in the JS console you can do escape("&lt;"), which returns "%3C"

dave 2020-04-10T12:50:06.072Z

then you can do "\x3C", and that returns "&lt;"

micha 2020-04-10T12:50:18.072300Z

you should be able to put that in the js source, no?

dave 2020-04-10T12:50:24.072500Z

i'll give it a try

micha 2020-04-10T12:51:00.072900Z

you need to escape the backslash because clojure strings interpret it

micha 2020-04-10T12:51:20.073400Z

like (script "foo \\3C ...")

dave 2020-04-10T12:51:44.073600Z

makes sense

dave 2020-04-10T12:57:50.073800Z

that doesn't appear to work

micha 2020-04-10T12:58:29.074700Z

what does it look like when you do "show source" (not the elements pane of the devtools)

dave 2020-04-10T12:58:35.074900Z

i changed the offending part of the code to for(w=0,x=v.length;w\\x3Cx;++w) whereas the \\x3C used to be &lt;

dave 2020-04-10T12:58:54.075500Z

i haven't tried prerendering yet, so show source doesn't include the script tag

dave 2020-04-10T12:59:21.075900Z

i suspect the result would be the same

micha 2020-04-10T13:01:00.076Z

micha 2020-04-10T13:01:41.076500Z

what does the script tag look like in the elements pane

micha 2020-04-10T13:02:31.077Z

the easiest thing to do really is to make your own html file and then mount the app in a div inside there

micha 2020-04-10T13:03:21.077500Z

then you don't need prerendering because you can pull out the things you want to have prerendered into the html file

dave 2020-04-10T14:39:13.078Z

dave 2020-04-10T14:39:43.078600Z

looks like what i expected: w\x3Cx intsead of w&lt;x

dave 2020-04-10T14:42:21.079100Z

making our own html file is a good suggestion. i've been thinking about that in the back of my mind

dave 2020-04-10T14:42:41.079500Z

i would just need to do some post-processing to insert the right cache keys for cache busting

dave 2020-04-10T14:44:46.080200Z

could another solution be to put the inline JS into a file instead? or would that potentially screw up the load order?

dave 2020-04-10T15:14:54.080600Z

putting the JS into a file got me un-stuck


just catching up,was the problem literla JS inside a script tag in a cljs file?

dave 2020-04-10T15:15:23.081300Z


dave 2020-04-10T15:15:26.081500Z

with :prerender-keep

dave 2020-04-10T15:15:45.081800Z

although i guess i'm not 100% sure if :prerender-keep was related


i think i've run into that before,with google analytics or something


i wonder about using js* to inline JS strategically


that would roll it into the cljs source


i guess sometimes you need JS to run before the cljs kicks in tho

dave 2020-04-10T15:18:26.083600Z

does it need to be inline for that to be the case?

dave 2020-04-10T15:20:16.085300Z

like is the load order for this:

&lt;script src="index.cachekeygoeshere.html.js"&gt;&lt;/script&gt;
any different than the load order for this?
&lt;script src="alert_lol.js"&gt;&lt;/script&gt;
&lt;script src="index.cachekeygoeshere.html.js"&gt;&lt;/script&gt;


should be no different


i was suggesting using js* to put alert("lol") in index.cachekeygoeshere.html.js

dave 2020-04-10T15:22:43.086300Z

ah, i see

dave 2020-04-10T15:22:49.086600Z

we're actually doing that for google analytics in geir

dave 2020-04-10T15:23:09.087100Z

it's just that it only works because the inline JS doesn't include &, <, or > which hoplon's prerenderer would escape


seems to me like the prerender shouldn't escape script tag innards


from a pure xml sense it make sense, and is a good default. maybe a bug in prerender?

dave 2020-04-10T15:26:43.090200Z

i'm thinking it's a bug, too

dave 2020-04-10T15:27:03.090600Z

like if the type of the DOM node is "script," then the escaping shouldn't happen


absolut nyet


anothre option is golf that code to not use any escaped chars like goog did


partially as entertainment 😆

dave 2020-04-10T15:28:29.092500Z

haha, nothing like a rousing game of code golf 😄

dave 2020-04-10T15:28:47.092900Z

i'm sure there is some too-clever way to get "less-than" semantics without using &lt;


function lt(x, y) { var z = (y - x); return z != "0" && z.toString()[0] !== "-"; }



dave 2020-04-10T15:34:17.093500Z


dave 2020-04-10T15:36:20.094200Z

function lt(x, y) { return (x - y).toString()[0] == "-"; }
would this work?


that would be <= because if x == y, [0] !== "-"


close but no banana

dave 2020-04-10T15:37:34.095400Z

hmm, i tried that in my browser and lt(2, 2) is false like i expected


oh i see, yes, it should work


my thing was lte, yours is lt


x is < y iff (y - x) < 0, e.g. its string rep. has a leading dash


i bet google did that intentionally man


i wonder if a tool of theirs does this kind of rewriting even

dave 2020-04-10T15:40:25.097800Z

golfed a bit further 😄


aha that =&gt; tho


gotta keep it es3

dave 2020-04-10T15:40:56.098700Z

i keep forgetting that JS has had that for like 5-10 years lol


ha yeah


a few years ago at my new job i spent a few weeks relearning JS starting from 2012 or something


it has all the things now pretty much


in addition to all the crazy things it always had


you know, i guess you can't make a real short-circuting &amp;&amp; as a function, because the real one delays evaluation


the best you could do is wrap every argument in a function at the call site

dave 2020-04-10T15:43:15.101500Z

for the purposes of <= and >=, you could just implement < and > and then call it with !


lol this is unfolding into a great big tech company interview question

dave 2020-04-10T15:43:31.102Z


dave 2020-04-10T15:43:54.102700Z

"please sort this linked list in JS, and you can't use &, <, or >"


oh sweet, yes good point


you could even say it's not a contrived question, it actually came up in the course of work haha

dave 2020-04-10T15:45:03.103700Z