Inconsistency between `${foo}` and "#{foo}"

12 views
Skip to first unread message

pcxunl...@gmail.com

unread,
Sep 13, 2014, 6:20:32 PM9/13/14
to strati...@googlegroups.com
The title pretty much sums it all. I was confused since I was using `#{foo}` and it wasn't working, even though that's the syntax that is used for string interpolation. There's probably some historical reason for this, but could the two be made consistent? I don't care much whether it's #{} or ${} or whatever, just so long as they're both the same.

Alexander Fritze

unread,
Sep 14, 2014, 1:00:05 PM9/14/14
to strati...@googlegroups.com
I agree, I'd find it easier if we used ${} in both quasis and strings.
(#{} is bad because '#' is a common character in urls).
But we had a discussion about this a while ago, and Tim thought that
there'd be advantages to having separate symbols. I'll check how he
feels about it now.
> --
> You received this message because you are subscribed to the Google Groups
> "StratifiedJS" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to stratifiedjs...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Tim Cuthbertson

unread,
Sep 14, 2014, 9:20:39 PM9/14/14
to strati...@googlegroups.com
So my reasoning is admittedly a bit of a long (and perhaps paranoid) bow, but here it is:

In many cases, the difference between them is both important and very subtle. If you're using quasis for their ability to escape embedded content, then any accidental use of "#{...}" instead of `${...}` could lead to security bugs which are not immediately obvious (they often produce different output only on malicious input, which you might not always be testing for).

Given that, I like that the difference is hard to mistake, and that it is reinforced at each embedded variable - because in most cases, you care _a lot_ which one you're using. Consider:

var content = "
   <h1>Hello there</h1>
   <p>
     line1
     line2
     #{greeting}
     line3
     line4
  </p>
";

This is safe when `greeting` is a predefined or localized string.

But if you change just that line to:

    #{greeting}, #{username}

Then this should trigger a mental warning, because "#{...}" is not safe for embedding arbitrary data.

If we used #{ ... } for both unsafe string interpolation and safe quasi interpolation, you might assume that this big-html-looking-thing is enclosed in ``, without checking it too hard. And then you have introduced an XSS vulnerability[0].

Perhaps this is too much effort to counter an unlikely scenario, and it's not really the language's job to make you jump through hoops to prove you know what you're doing. But it's also very important to understand the distinction between these two types of quotes, and they are often many lines long - so I personally like the reinforcement that the distinct interpolation characters provide.

If it's too confusing though, I'll only be slightly sad to just make them the same ;). But note that here are other differences too - e.g `$foo` works inside a quasi (for convenience of stringing templates together), while you always need the braces inside a string interpolation (because we don't want to make you always escape `#` or `$` in every single string). So just making the trigger character the same would not actually make the two consistent, we'd need to resolve that difference too.

What text editor do you use? The problem becomes much easier to spot if you use the vim syntax highlighting (it's under `vim/` in the SJS repo), because it will only highlight interpolation that matches the surrounding quotes. I'm not sure if the emacs mode does the same, though (I haven't used it).

[0] In the case of surface, this is already mitigated because that we _always_ escape strings. But there are plenty of potential uses of quasis where you would accept either a quasi or a flat string.

Cheers,
 - Tim.


On Monday, September 15, 2014 3:00:05 AM UTC+10, Alexander Fritze wrote:
I agree, I'd find it easier if we used ${} in both quasis and strings.
(#{} is bad because '#' is a common character in urls).
But we had a discussion about this a while ago, and Tim thought that
there'd be advantages to having separate symbols. I'll check how he
feels about it now.


pcxunl...@gmail.com

unread,
Sep 14, 2014, 11:36:34 PM9/14/14
to strati...@googlegroups.com
Your reasoning isn't bad, I just don't think the potential benefits of having two syntaxes outweighs the potential problems.

Normal JS has a hard time dealing with escaping because it only has strings, but SJS has strings *and* quasis. So the natural thing for libraries (including surface) is to use quasis for templates and strings for escaped content. And if that's the idiomatic thing that every library does, then the distinction between #{} and ${} no longer has any benefit.

Of course there may be exceptions, but I doubt that's enough to justify the common confusion of having two syntaxes. This will become even more pronounced once regular JavaScript gets quasis and libraries start to be built around them.

To answer your question, I use LightTable, and it does indeed syntax-highlight `${}` properly. But it doesn't syntax highlight "#{}", so when `#{}` wasn't syntax highlighted, it didn't seem wrong, since I was used to "#{}" not syntax highlighting.
Reply all
Reply to author
Forward
0 new messages