vuejs / core

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

Dynamic render error can't be captured #9007

Open sportdeath opened 1 year ago

sportdeath commented 1 year ago

Vue version

3.3.4

Link to minimal reproduction

https://play.vuejs.org/#eNqNVNtO20AQ/ZWp1QpHJDYtfXITRIuQ2qo3FfpQyQ8YexIv2LvW7mwCivzvnd11LiBATR7iufjMmTMzWUcfuy5ZWoyyaGpKLToCg2S7k1yKtlOaYA0a52Oox1CqtrOEVXgSDY5ByXOtlT4rOrIaK+hhrlULB4x4kMtclkoa4vQKYeZw4qvptSVSEk7LRpS3szwqlZV0eJhHXBLgzFlCLmCl9K3JYL3mt9kFfZ/LaRpe5kw2Xk0m8IcrtC1ynGphoBESYa40FBKsLAu7qAnQMeT8YlfTf+Vk8h9A8DxKzJynacEgjHQ1cliP9IhxdgJr11fRoKb4ykc3kMqSERVm8HqNCakL0tx4POodFLBaDCFhXjQGc9l7+CBnfd+hHoY1204ljkebYqTvw8MWpY4H23lkhTrbzDB2w0mWRWNxNN7kVAUVGXjAeBhABkfQ7zK8HLs2R5t67vNUr0K+0OqG2H7DwcdD9z8+rWcwKuu9atvuDiqxPBjvSAgpUX++/P4tg/16D9CCqNM0KBlWgbDtmoLQ7yJbd1RoLGA5aVmlxm9rhX7sm1jInAtsKj4cb7Hd4IJlPvmrLCvgtj+ojlU2TYfYkLk3zDRgpXtgrs6WEZuG7ptAbstt6HklKqozeHt09OZD8NQoWHl2vdPYep8/oQARjaNw35O26JIboyT/A3iofAiYPOLzC1B5xAft7DyqiTqTpWlZSX6NRRFLnUikVHZtylmnx8lx8j6thCFnJmjaybVWK4Oa893ZBemZABne57lYPCo/LKb+2ZHgfX9Ao2gatfrqfaQtDuvI79RY3j7hvzF3gfYvjcxgyU1sYyzfAimEzy9+sJ57QZ63bYaWnwn+RqMa6ziGtE9WVkx7L8+z/eLV5PW7NOd3hHwHQ1OOqFfD53uJz15ofUeXFd6q2P8DPnboTw==

Steps to reproduce

  1. Uncomment the marked line in the textarea to try to render <a @click=""".
  2. Click the button in the rendered code.
  3. Add random text to the textarea.
  4. Click the button again.

What is expected?

The error should be caught by either errorCaptured or onErrorCaptured causing an alert to occur. The error should not propagate and show up in the console.

What is actually happening?

An error is produced. In Firefox:

Uncaught (in promise): String contains an invalid character

In Chrome:

Uncaught (in promise): Failed to execute 'setAttribute' on 'Element': '"' is not a valid attribute name.

In Safari:

Uncaught (in promise): The string contains invalid characters.

Additionally, once the count button is clicked, copies of it appear in the DOM. Once more text is added to the textarea and the button is pressed the count resets and copies of the button appear outside the fieldset.

Screenshot 2023-08-19 at 9 07 32 PM

System Info

No response

Any additional comments?

I'm trying to build a Vue playground (much like the Vue SFC Playground) to include with documentation of an Vue plugin I am writing. Users should be able to modify code in an editor and see it rendered live in another pane. The playground must be robust so that the renderer doesn't break when the user enters an incomplete input or an input with typos.

I have a mock-up that mostly works but there are certain inputs that break everything, as shown in the minimal example. I believe the error should be caught by either errorCaptured or onErrorCaptured which should isolate the error and prevent it from propagating to the rest of the application.

EruditionTu commented 1 year ago

You need to use

<component/>

to achieve dynamic rendering. If you write like this, Vue will only treat it as a responsive string, and does not perform runtime parsing when the app is running.

sportdeath commented 1 year ago

If I replace <hyperscript /> with <component :is="hyperscript" /> the error persists.

Runtime parsing is clearly being performed already because as you change the text in the textarea, it modifies the rendered code because I'm using h to create a vnode directly. You can add more reactive buttons, etc. The lines I've included that cause errors are special cases.

Interestingly, I changed to prod (vue.esm-browser.jsvue.esm-browser.prod.js) and the syntax error is caught in the try/catch, printing out SyntaxError: 17 in the "Your code rendered" section but not propagating the error as desired. Why does prod work but not dev?