core: Compiler: Incorrect parsing when string contains }} (two closing braces)

Version

3.0.5

Reproduction link

Vue 3 Template Explorer (credit: @ota-meshi)

Steps to reproduce

Use two consecutive closing braces in a string, inside a template.

What is expected?

Correct parsing.

What is actually happening?

Vue template compilation error: Error parsing JavaScript expression: Unterminated string constant (1:5)


This will happen frequently when using something like ICU message formatting, as seen in the example at the URL above.

(initially reported @ https://github.com/vuejs/vue-eslint-parser/issues/94)

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 6
  • Comments: 27 (17 by maintainers)

Most upvoted comments

So how would u deal with this scenario?

<p>{{ someFn({ a: {b: 1}})  }}</p>

Not sure why this issue is already closed?

That’s rather bad and closing doesn’t feel like the right thing to do to me.

AFAIK:

  • expressions in template can only be JS, no other language allowed.
  • compiler-sfc already embeds a JS parser, namely Babel.

So when encountering a {{ interpolation marker, why not parse a JS expression starting on next char, then check if the expression is properly closed with }} and throw an error if the JS is invalid or the interpolation is not properly closed.

Sure, it’s more work then doing a find for the next “}}” in string, but it’s the right thing to do.

} can appear in many places inside a JS expression: inside comments /* }} */, strings "}}", interpolated strings `object is {${ obj }}`, object literals { a: { b: 4 }}, lambda or method member bodies function () { return () => { return { g() { }}}

If you don’t want to parse, another common strategy when embedding DSL like that is to provide an escaping. Tell people that if they need to write }} inside an interpolation they need to escape it somehow (and don’t forget to provide an escape for the escape itself). As others have mentioned in this thread, it impacts every tooling that needs to unescape the interpolated expression before processing it, so it isn’t the best solution.

Just saying “find a way to write your code without }}” is the worst solution from a user perspective.

I started writing spec (https://github.com/vuejs/docs-next/pull/729), it follows HTML spec like format.

Yes, we can unescape in AST but it will break eslint, typescript, babel vetur (pretty much everything). Parsing of interpolation braces is designed same as <script> parsing of HTML (e.g. https://jsfiddle.net/znck/L375htkg/).

I think we can close this once the docs has been updated since that seems to be the consensus for the action item here (so we can link from the formatjs side as well).

@posva Why are you closing this issue? This is a clear and obvious bug.

As @longlho stated, placing a backslash between the braces is not escaping anything, it’s just avoiding the issue by preventing two braces from being positioned next to each other.

Please reopen.