vuejs / core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
https://vuejs.org/
MIT License
47.51k stars 8.31k forks source link

`</script>` in script block breaks SFC parsing #7391

Open danielroe opened 1 year ago

danielroe commented 1 year ago

Vue version

3.2.45

Link to minimal reproduction

https://sfc.vuejs.org/#eNp9jstqw0AMRX9l0DqegT427sSkP9HVbFxbpG4zDyTZpQT/e+WahjwgG4HOlXR0hNdS7DQi1OAFYzm0go3vh6nxbq0nGpLnjoYi5tCm/TaAcADDKGPRrMuJxcSft5bM1gTwbh1uArzo5n9nYANDLJmkim2xn5yTqo8hGd1ZA71amz+yMP1t6QN8iBSunRtT+drbLke308zRmGSIWPU57h7tg3161r9ZzrlFjtU75W9GUmOAzdlxp3BCqghTj4R0V3Y1eyG8ym6ki3MOaYb5FyirgIQ=

Steps to reproduce

Include </script> within a string in the script block

What is expected?

The template should still compile.

What is actually happening?

The <script> block is not correctly parsed.

System Info

No response

Any additional comments?

Upstream issue: https://github.com/nuxt/nuxt.js/issues/15624 Fuller reproduction: https://stackblitz.com/edit/github-mgrldc

sxzz commented 1 year ago

I guess we have to avoid </script> string in <script> block since the compiler cannot perceive if it's a JavaScript string or the end tag when parsing SFC.

There's a workaround, splitting the string.

<script lang="ts" setup>
const myVar = "</" + "script>";
</script> 
jakub791 commented 1 year ago

Shouldn't it easy to differentiate the two?

haoqunjiang commented 1 year ago

A note from #7944: the syntax highlighting in VS Code doesn't correctly handle this situation, while in the SFC playground, we can clearly see the first closing tag.

equt commented 1 year ago

The easiest and safest way to avoid [..] is to always escape an ASCII case-insensitive match for <!-- as \x3C!--, <script as \x3Cscript, and </script as \x3C/script when these sequences appear in literals in scripts [..]

So according to the WHATWG HTML Standard, as long as the Vue SFC template aims to be a superset(?) of HTML, this behavior is the feature, rather than a bug :(

linzhe141 commented 2 months ago

Is it possible to throw a more intuitive error message like a browser does?

image

Simon-He95 commented 1 month ago

I think maybe use regular expression to convert the / in the string into \/ before parser

https://play.vuejs.org/#eNp9UctSwjAU/ZVO1rSZEdxgYVCHhS7UUcdVNrW9lkDzmOQGcDr9d9NUakFll5xzb84jNbnWOtk6IFOSIghdZQjztODbeV2Lz7fMNE1K22tKe5rJ1OaGa4yqTJYzRtAyEllApz2XK2kxCrvRLGIkZYx243NGrvzu4RaREeFCK4OxyHSytkp6FzWTkd/qCP/uNApIi3mb7Z2RFaK2U0qd1JsyyZWgC89R4yRyAXGhxGKcXCSTS+/c4hBPwIr43aidBeMVGRkNHqce3IKJDcgCDJizYiezR4In3C/RVrNhsvEFoPV9ffDyJL6X0bwC86iR+z6PasiqSu3uA4bGQZ8gX0G++QNf232X5MlAcDZIjZkpATt6+fIAe3/uSaEKV31X/g/5DFZVrvXYjd04WXjbg7ng9i78Jpflq13uEaQ9hGqNhjbCfPiF2zPRf+yOk0nfYvMFORXuOg==