vuejs / repl

Vue SFC REPL as a Vue 3 component
https://repl-vuejs.vercel.app
MIT License
927 stars 172 forks source link

Playground: When console logging a reactive object in watchEffect, it will track the whole object #273

Open LinusBorg opened 2 months ago

LinusBorg commented 2 months ago

Vue version

all

Link to minimal reproduction

https://play.vuejs.org/#eNp9kctOwzAQRX9l5E1SqUoXsCppJUBdUImHoEtvQjJJUxLb8iMtqvLvjF0aggTdRPGcM/Yd+8hulUo6h2zOUpPrWlkwaJ1aclG3SmoLR5DiUTphsYAeSi1biKghuhkZ+8zm21VZYm7/dTSWvxgXXORSGAvyfQcLz+MjFwAia3EO0Ua25PQT7432j+MJLJbgO2WDSSOrmPqTLmscToI8xP1WB5z4nemkaI1af0Ykp7PTzDQtLSy2qsks0gogLepumc7813sjxqbMGjq/rKtkZ6Sgqwu5Octlq+oG9bOyNeXjbA6BeJY1jdyvQ81qh9NzPd9i/vFHfWcOvsbZi0aDukPOBmYzXaE94dXbEx7of4CtLFxD9gX4inR3zmc8aXdOFBR75IW0D+HpalFtzOpgUZjzUD6oN/vgc0bPeX9h9J+4V8l16KN3Zf0XPxTU/w==

Steps to reproduce

  1. Open the reproduction link
  2. Check the console

What is expected?

  1. Log the object in its initial state
  2. Don't log the object again after the name property has been changed in the onMounted hook

What is actually happening?

  1. Log the object in its initial state
  2. Does log the object again after the name property has been changed in the onMounted hook

System Info

not applicable

Any additional comments?

This happens because the playground monkeypatches console.log (etc) and in that code, it stringifies all arguments to send them to the iframe's parent window.

This code runs synchronously within the effect, which leads to a deep traversal of the whole reactive proxy and results in the effect tracking all (deeply nested) properties of the object instead of only tracking the ref itself.

yyx990803 commented 2 months ago

This has to be fixed in @vue/repl as the patching happens here https://github.com/vuejs/repl/blob/main/src/output/srcdoc.html#L158

Maybe we can workaround this by stringifying + postMessage in an async tick.