Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add line number and a snippet of the source template to template render error reports #10966

Open
davidkhess opened this issue Dec 30, 2019 · 6 comments

Comments

@davidkhess
Copy link

davidkhess commented Dec 30, 2019

What problem does this feature solve?

It helps developers pinpoint template errors in larger templates.

At the moment, render errors look like this (from version 2.5.18):

vue.js:616 [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined"

found in

---> <ASelectDate>
       <ALite>
         <TransitionGroup>
           <DbNavigation>
             <VContent>
               <VApp>
                 <Root>
warn @ vue.js:616
logError @ vue.js:1824
globalHandleError @ vue.js:1819
handleError @ vue.js:1808
Vue._render @ vue.js:4637
updateComponent @ vue.js:2893
get @ vue.js:3261
Watcher @ vue.js:3250
mountComponent @ vue.js:2900
Vue.$mount @ vue.js:8642
Vue.$mount @ vue.js:11045
init @ vue.js:4225
createComponent @ vue.js:5696
createElm @ vue.js:5643
addVnodes @ vue.js:5824
updateChildren @ vue.js:5951
patchVnode @ vue.js:6037
patch @ vue.js:6198
Vue._update @ vue.js:2775
updateComponent @ vue.js:2893
get @ vue.js:3261
run @ vue.js:3336
flushSchedulerQueue @ vue.js:3094
(anonymous) @ vue.js:1925
flushCallbacks @ vue.js:1844
Promise.then (async)
microTimerFunc @ vue.js:1892
nextTick @ vue.js:1938
queueWatcher @ vue.js:3186
update @ vue.js:3326
notify @ vue.js:727
mutator @ vue.js:879
goto_date @ lite.js:82
invoker @ vue.js:2128
Vue.$emit @ vue.js:2646
Vue.<computed> @ backend.js:1793
success @ select_year_trim.js:296
tryCatcher @ -internal.js:39
invokeCallback @ -internal.js:211
publish @ -internal.js:197
flush @ asap.js:80
characterData (async)
(anonymous) @ asap.js:54
asap @ asap.js:11
fulfill @ -internal.js:148
handleMaybeThenable @ -internal.js:113
resolve @ -internal.js:121
(anonymous) @ -internal.js:241
(anonymous) @ util.js:37
Request.callback @ superagent.js:1723
(anonymous) @ superagent.js:1550
Emitter.emit @ superagent.js:1080
xhr.onreadystatechange @ superagent.js:1817
XMLHttpRequest.send (async)
Request._end @ superagent.js:1884
Request.end @ superagent.js:1788
(anonymous) @ util.js:34
initializePromise @ -internal.js:236
Promise @ promise.js:142
superagent.Request.promise @ util.js:33
common_setup @ managers.js:33
self.get_availability @ managers.js:163
select_car @ select_year_trim.js:272
select @ VM2579:1
invoker @ vue.js:2128
Vue.$emit @ vue.js:2646
Vue.<computed> @ backend.js:1793
click @ VM2609:3
invoker @ vue.js:2128
Vue.$emit @ vue.js:2646
Vue.<computed> @ backend.js:1793
click @ VBtn.ts:114
invoker @ vue.js:2128
fn._withTask.fn._withTask @ vue.js:1913

vue.js:1828 TypeError: Cannot read property 'name' of undefined
    at Proxy.eval (eval at createFunction (vue.js:10785), <anonymous>:2:39)
    at VueComponent.Vue._render (vue.js:4635)
    at VueComponent.updateComponent (vue.js:2893)
    at Watcher.get (vue.js:3261)
    at new Watcher (vue.js:3250)
    at mountComponent (vue.js:2900)
    at VueComponent.Vue.$mount (vue.js:8642)
    at VueComponent.Vue.$mount (vue.js:11045)
    at init (vue.js:4225)
    at createComponent (vue.js:5696)

While TypeError: Cannot read property 'name' of undefined and the template it occurred in is of course quite useful information it could be better if there are many references to 'name' in <ASelectDate> and the exact location of the error is not obvious. I'm proposing a feature enhancement that would include a line number relative to the template itself (assuming it is not just a render function) and also output the line before, the line of the error and the line following it from the source template to provide context information to the developer.

I believe this can be achieved using the same techniques that are used in compilers when debugging information is enabled and generated. In development mode, as a template is compiled, context information is maintained (line numbers and the source lines of the template) and as each piece is compiled and converted into render function code this information is captured as "debugging symbols" (using compiler terms). If this debugging information is available when a render error occurs, the stack trace is examined and used with the debugging information to determine the line number and template lines to display with the warning.

The result would be an error report that looks something like:

vue.js:616 [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined"

found in

---> <ASelectDate>
       <ALite>
         <TransitionGroup>
           <DbNavigation>
             <VContent>
               <VApp>
                 <Root>

on line 34

        <p class="model-year">{{ model.year }}</p>
--->    <p class="model-name">{{ model.name }}</p>
        <p class="model-tagline">{{ model.tag_line }}</p>

What does the proposed API look like?

In terms of implementation details, this feature would be enabled in development mode. The debugging information would be generated during template compilation and could be attached to the render function itself when compiled and emitted so that no additional files need to be produced, packaged or loaded. If the debugging information is available, the error message as envisioned above is produced. If not, the current style of warning is emitted instead along with a message that says for better details, reproduce the error in development mode.

@davidkhess davidkhess changed the title Add line number and a snippet of the source template to template render warning reports Add line number and a snippet of the source template to template render error reports Dec 30, 2019
@posva
Copy link
Member

posva commented Dec 30, 2019

I don't think this will be technically possible for current Vue 2 but the source maps in Vue 3 does already allow breaking in the middle of the template so I think it might be possible to have this. @znck do you happen to know more?

@znck
Copy link
Member

znck commented Dec 30, 2019

You can write a custom directive but let me try it and confirm.

@davidkhess
Copy link
Author

davidkhess commented Dec 30, 2019

I wasn't aware of the source map support in Vue 3 - that's some good news!

Looks like this might be useful in that scenario:

https://www.stacktracejs.com/#!/docs/stacktrace-gps

It appears to load and parse a source map and convert a stack trace frame to a location in the context of the source map.

It also has an MIT license and isn't a lot of code so it could be readily adapted and integrated.

@literakl
Copy link

literakl commented Apr 3, 2020

I vote for this proposal as well

@pedro380085
Copy link

This is a great idea, I don't know how people debug templates with hundreds of lines today.

@davidkhess
Copy link
Author

@posva has there been any action on this in Vue 3? If not, I may have the cycles to put together a PR for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants