Fork me on GitHub
#cljs-dev
<
2016-01-28
>
mfikes20:01:48

If you evaluate #js {"a" 1} in a ClojureScript REPL, the JavaScript expression {"a": (1)} is emitted. This works fine in Nashorn, and V8, but not in JavaScriptCore and SpiderMonkey. In the latter two, if you wrap in parens, e.g. ({"a": (1)}), you end up with evaluatable JavaScript expressions, which work in the sense that ({"a": (1)}).a evaluates to 1. My question: Is ClojureScript emitting invalid JavaScript in this corner case? Or, is it JavaScriptCore and SpiderMonkey that are wrong? (I did some minimal Googling, but figured I’d toss this one here to people more experienced with JavaScript and what the compiler emits.)

mfikes20:01:35

Actually, wrt the above, I wouldn’t say it is fine in V8. It is fine in Node.js, but not Chrome. (Try (js* "{\"a\": (1)}”) vs. (js* "({\"a\": (1)})”) in your favorite ClojureScript REPL.)

dnolen21:01:27

hrm very edge-casey, can’t say I know myself what is and isn’t supposed to work here

mfikes21:01:46

I should point out that it is indeed a corner case even for ClojureScript. If, for example you do (def x #js {"a" 1}) (or any expression where the literal is not “bare”), the emitted JavaScript is consumable everywhere.

mfikes21:01:54

I found one interesting statement regarding this:

> You should not use an object literal at the beginning of a statement. This will lead to an error or not behave as you expect, because the { will be interpreted as the beginning of a block.
– Mozilla’s [Grammar and types]()

dnolen21:01:50

so perhaps as simple solution possible based on that information

mfikes23:01:37

Yeah, something like this does the trick https://github.com/mfikes/clojurescript/commit/66b105b941438ff1849e0828b2df25246ac52327 Or, even simpler would be to just unconditionally emit ({ and }), which also passes tests.