1

I have a Laravel / Vue app using SSR so have JavaScript running server side and client side.

I had a bug in my code where I was checking user.id when the user object was null.

If this had been running client side I would have seen the error in the console and easily fixed it.

However because this was running in v8js I got no output at all and was just a case of trial and error to locate and fix the bug. This reminded me of fixing JS errors in IE6 - not something I want to repeat!

I did try the getPendingException() method but this just gave me a warning about it being deprecated.

Note some errors are generated....

Obvious syntax errors are picked up straight away when I run webpack.

Some errors throw a V8JsScriptException:

if(foo.bar) {}

This generates the error:

V8Js::compileString():86354: ReferenceError: foo is not defined

If I wrap foo in a function and then call it:

function test() {
    if(foo.bar) {}
}
test()

No exception is thrown, but the only output returned is:

ReferenceError: foo is not defined 

However this code that is for my Vue router produces no output at all:

import Vue from 'vue'
import Router from 'vue-router'
import routes from './routes'

Vue.use(Router)

export function createRouter () {
    const router = new Router({
        mode: 'history',
        routes: routes
    })

    router.beforeEach(async (to, from, next) => {
        if(foo.bar) {}
        next()
    })

    return router
}

When I run this same code in the browser the console shows:

ReferenceError: foo is not defined

So it seems JS is creating an error - but somehow V8Js is not passing it on.

Why does the undefined error in the Vue router not throw an exception when run in v8js?

Felix Eve
  • 3,811
  • 3
  • 40
  • 50
  • Never used v8js but from the docs it seems wrapping your code in a [V8JsException](https://www.php.net/manual/en/class.v8jsexception.php) and catching it might give you a clue if an error occurs. [Here's](https://dzone.com/articles/running-javascript-inside-php) also a short tutorial mentioning catching exceptions. – SaschaM78 May 27 '20 at 15:10
  • Sometimes an V8JsException is thrown - but sometimes not. I've updated my question to describe the problem in more depth. – Felix Eve May 28 '20 at 07:33

1 Answers1

1

Use an onError handler on your router: router.onError

And, since your beforeEnter guard is async, you'll need to call next with the error:

export function createRouter () {
    const router = new Router({
        mode: 'history',
        routes: routes
    })

    router.beforeEach(async (to, from, next) => {
      try {
        if(foo.bar) {}
        next()
      } catch (e) {
        next(e)
      } 
    })

    router.onError(err => {
       print('<!-- router error: ' + err.message + ' -->')
    })

    return router
}

For your example, you could use a synchronous guard and do without the try/catch:

router.beforeEach((to, from, next) => {
    if(foo.bar) {}
    next()
})
  • This logic seems flawless - however it's not actually producing any output for me. However I'm still going to keep this in my code just in case it ever picks anything up. – Felix Eve Jun 05 '20 at 08:41
  • I have a similar situation where `renderVueComponentToString` returns an empty string and no exceptions are thrown. For me, it happens on a component with a specific vue-apollo smart query. It works without error on the client, but seems to bomb during ssr. I traced into vue-server-renderer-basic.js but without the ability to connect a debugger to v8js I wasn't able to figure it out either. I did try your example of the undefined variable `foo` with the `onError` handler and the `onError` handler picked it up for me. Whatever is causing this is very obscure. – wmjasonward Jun 05 '20 at 16:15
  • @FelixEve - Rebuilding v8 and v8js (I went to versions 8.5.77 and 2.1.1, respectively) solved the problem for me. – wmjasonward Jun 06 '20 at 14:24