Skip to content

[6.22] [vueAttribute/assertVue] javascript error: Converting circular structure to JSON  #968

@lk77

Description

@lk77
  • Dusk Version: 6.22
  • Laravel Version: 8.33.5
  • PHP Version: 7.4.24
  • Database Driver & Version: mysql 5.7

Description:

assertVue does not work on vue 3 in some cases due to the presence of $vnode and $root in the ctx object,
because it tries to json encode it which can cause an error "Converting circular structure to JSON"

It seems that keeping the app instance globally like for example with a mixin trigger the issue

Steps To Reproduce:

create a hello-word project

vue create hello-world

create a circular reference in the main.js, for example with a mixin that makes the app object globally available :

let app = createApp(App)

app.mixin({
    beforeCreate() {
        this.$app = app;
    }
})

app.mount('#app')

in console :

JSON.stringify(document.querySelector('.hello').__vueParentComponent.ctx)

it should trigger something like that :

Uncaught (in promise) TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Object'
    |     property 'component' -> object with constructor 'Object'
    --- property 'vnode' closes the circle

the error is in vueAttribute method :

public function vueAttribute($componentSelector, $key)
    {
        $fullSelector = $this->resolver->format($componentSelector);

        return $this->driver->executeScript(
            "var el = document.querySelector('".$fullSelector."');".
            "return typeof el.__vue__ === 'undefined' ".
                '? JSON.parse(JSON.stringify(el.__vueParentComponent.ctx)).'.$key.
                ': el.__vue__.'.$key
        );
    }

here is th PR that added vue 3 support : #968

it might be safer to remove $root and $vnode before JSON.stringify

in my side, the fix i did is that :

app.mixin({
    beforeCreate() {
        this.$getApp = () => {
            return app;
        }
    }
})

it prevent any circular reference.

i'm doing that because i need a better way to retrieve the vue instance than using getCurrentInstance which can return null in some contexts

thanks.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions