feat: fix vue3 render warning loop - #6010

Closed
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop
Closed

feat: fix vue3 render warning loop#6010
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop

Conversation

@Rockergmail

Copy link
Copy Markdown
Contributor

Before submitting a pull request, please take a look at our
Contributing guidelines and verify:

  • If you've added code that should be tested, please add tests.
  • Ensure your code lints and the test suite passes (yarn lint) & (yarn test).

fix issues:
#5916
#4743

why this happens:

  1. vue3 support the property ref in the second arg of h method, to support this feature: https://cn.vuejs.org/guide/essentials/template-refs.html
  2. when a template render with a undecalred variable, vue3 will call console.warn to print error stacks.
  3. sentry hijacked console, and add the message to breadcrumb with safeJoin
  4. safeJoin will transfer variables to string. The ref variable is a proxied object via Proxy. so, when called String(value), will trigger the getter of Proxy, and got undefined, so again vue3 will call console.warn to print error stacks
  5. just loop infinitely.

solutions:

  1. tried to test the variable is Proxy. No matter how you test, will trigger proxy getter or other handlers, so it loops.
  2. the only way can test is the stack information from vue3

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Rockergmail and thanks for opening up this PR! Would be great to fix this long-standing bug.

I have a couple of questions. I'm not a Vue expert so it'd be great if you could tell me how the fix you're proposing works and why we need to modify the args that way. I'm not yet sure if we can fix this in the proposed way but I'll take it to the team.

EDIT: Seeing the CI results, our linter is not yet happy. Running yarn lint should tell you what's wrong

@Rockergmail

Rockergmail commented Oct 21, 2022

Copy link
Copy Markdown
ContributorAuthor

@Lms24 It seens I have explained why . And you can see the debug process here: #5916

let's take the demo for example: https://stackblitz.com/edit/vue-g6usgy?file=src%2Fmain.js

Or can you suggest me how can I explain to you in which way ? the vue3 render process ? vue3 render Mycomp.vue, when it comes to _ctx.test, it needs to get value of test. But due to vue3's mvvm, using Proxy to hijack varibles in the rendering context, so that it can collecte dependencies. When you try to modify the variable. It will trigger updates.

so when we try to get the value of test, will trigger getter handler of Proxified test, if the context get a test variable, it will return the value before collect dependence. if get no test variable, will call warn
image
(you can see the full function PublicInstanceProxyHandlers in packages/runtime-core/src/componentPublicInstance.ts of vue source code)

warn will print the stack of component's info.

component has a prop called ref which is a Proxified variable.

so, when we reach _consoleBreadcrumb of sentry/javascript, will call safeJoin to strinify the variable so that we can send it to the server and log it.

Because ref is a Proxified variable, when we call String(value) in the safeJoin, so it will call getter of ref. Due to the context has no ref variable, so the vue will warn again and agiain

As to why we need to modify the args that way:

  1. If we try to call String(value) to get the value, will loop. So we need to avoid doing this.
  2. If we try to test a variable is Proxy, there is no way. Because it will loop too.
  3. The only way to know the varibale is Proxy I can figure out is the print info from vue3 [Vue warn]: Property "test" was accessed during render but is not defined on instance. at <Anonymous ref=Ref< undefined > > at <App>. So I just modify the arg when we meet the ref=Ref<, which is for vue3 only.

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining. Sat down with the team and we think this is good to go. It's too bad that we can't more securely check for a Proxy but it seems like this really isn't possible and therefore I think your solution makes sense.

Tbh, we're overall not too happy with this small hack being in the framework-agnostic breadcrumbs integration. However, creating a Vue-specific integration (that's extending this integration) just for this one bug would also be a lot of work.

For future readers: This might however very well become an option in case we need to do more Vue-specific stuff in this integration.

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

Comment threadpackages/browser/src/integrations/breadcrumbs.ts
@Lms24Lms24 self-assigned this Oct 21, 2022
lgmt
Co-authored-by: Lukas Stracke <lukas.stracke@sentry.io>
@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

sorry, i am not sure if i am clear what you mean.

  1. I should create this branch base on 80f586e ,right?
  2. rebase this to the current master? what is this and what is the current master? is this means my branch ? the current master means master branch of getsentry/sentry-javascript, right?

@Lms24

@Lms24

Copy link
Copy Markdown
Member

Yes, I mean rebase your branch to master of getsentry/sentry-javascript.
Sorry for the confusion.

@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

done. here: #6014@Lms24

@Lms24

Copy link
Copy Markdown
Member

Closing this in Favour of #6014

@Lms24Lms24 closed this Oct 24, 2022
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Rockergmail@Lms24
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat: fix vue3 render warning loop - #6010

Closed
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop
Closed

feat: fix vue3 render warning loop#6010
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop

Conversation

@Rockergmail

Copy link
Copy Markdown
Contributor

Before submitting a pull request, please take a look at our
Contributing guidelines and verify:

  • If you've added code that should be tested, please add tests.
  • Ensure your code lints and the test suite passes (yarn lint) & (yarn test).

fix issues:
#5916
#4743

why this happens:

  1. vue3 support the property ref in the second arg of h method, to support this feature: https://cn.vuejs.org/guide/essentials/template-refs.html
  2. when a template render with a undecalred variable, vue3 will call console.warn to print error stacks.
  3. sentry hijacked console, and add the message to breadcrumb with safeJoin
  4. safeJoin will transfer variables to string. The ref variable is a proxied object via Proxy. so, when called String(value), will trigger the getter of Proxy, and got undefined, so again vue3 will call console.warn to print error stacks
  5. just loop infinitely.

solutions:

  1. tried to test the variable is Proxy. No matter how you test, will trigger proxy getter or other handlers, so it loops.
  2. the only way can test is the stack information from vue3

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Rockergmail and thanks for opening up this PR! Would be great to fix this long-standing bug.

I have a couple of questions. I'm not a Vue expert so it'd be great if you could tell me how the fix you're proposing works and why we need to modify the args that way. I'm not yet sure if we can fix this in the proposed way but I'll take it to the team.

EDIT: Seeing the CI results, our linter is not yet happy. Running yarn lint should tell you what's wrong

@Rockergmail

Rockergmail commented Oct 21, 2022

Copy link
Copy Markdown
ContributorAuthor

@Lms24 It seens I have explained why . And you can see the debug process here: #5916

let's take the demo for example: https://stackblitz.com/edit/vue-g6usgy?file=src%2Fmain.js

Or can you suggest me how can I explain to you in which way ? the vue3 render process ? vue3 render Mycomp.vue, when it comes to _ctx.test, it needs to get value of test. But due to vue3's mvvm, using Proxy to hijack varibles in the rendering context, so that it can collecte dependencies. When you try to modify the variable. It will trigger updates.

so when we try to get the value of test, will trigger getter handler of Proxified test, if the context get a test variable, it will return the value before collect dependence. if get no test variable, will call warn
image
(you can see the full function PublicInstanceProxyHandlers in packages/runtime-core/src/componentPublicInstance.ts of vue source code)

warn will print the stack of component's info.

component has a prop called ref which is a Proxified variable.

so, when we reach _consoleBreadcrumb of sentry/javascript, will call safeJoin to strinify the variable so that we can send it to the server and log it.

Because ref is a Proxified variable, when we call String(value) in the safeJoin, so it will call getter of ref. Due to the context has no ref variable, so the vue will warn again and agiain

As to why we need to modify the args that way:

  1. If we try to call String(value) to get the value, will loop. So we need to avoid doing this.
  2. If we try to test a variable is Proxy, there is no way. Because it will loop too.
  3. The only way to know the varibale is Proxy I can figure out is the print info from vue3 [Vue warn]: Property "test" was accessed during render but is not defined on instance. at <Anonymous ref=Ref< undefined > > at <App>. So I just modify the arg when we meet the ref=Ref<, which is for vue3 only.

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining. Sat down with the team and we think this is good to go. It's too bad that we can't more securely check for a Proxy but it seems like this really isn't possible and therefore I think your solution makes sense.

Tbh, we're overall not too happy with this small hack being in the framework-agnostic breadcrumbs integration. However, creating a Vue-specific integration (that's extending this integration) just for this one bug would also be a lot of work.

For future readers: This might however very well become an option in case we need to do more Vue-specific stuff in this integration.

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

Comment threadpackages/browser/src/integrations/breadcrumbs.ts
@Lms24Lms24 self-assigned this Oct 21, 2022
lgmt
Co-authored-by: Lukas Stracke <lukas.stracke@sentry.io>
@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

sorry, i am not sure if i am clear what you mean.

  1. I should create this branch base on 80f586e ,right?
  2. rebase this to the current master? what is this and what is the current master? is this means my branch ? the current master means master branch of getsentry/sentry-javascript, right?

@Lms24

@Lms24

Copy link
Copy Markdown
Member

Yes, I mean rebase your branch to master of getsentry/sentry-javascript.
Sorry for the confusion.

@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

done. here: #6014@Lms24

@Lms24

Copy link
Copy Markdown
Member

Closing this in Favour of #6014

@Lms24Lms24 closed this Oct 24, 2022
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Rockergmail@Lms24
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: fix vue3 render warning loop - #6010

Closed
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop
Closed

feat: fix vue3 render warning loop#6010
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop

Conversation

@Rockergmail

Copy link
Copy Markdown
Contributor

Before submitting a pull request, please take a look at our
Contributing guidelines and verify:

  • If you've added code that should be tested, please add tests.
  • Ensure your code lints and the test suite passes (yarn lint) & (yarn test).

fix issues:
#5916
#4743

why this happens:

  1. vue3 support the property ref in the second arg of h method, to support this feature: https://cn.vuejs.org/guide/essentials/template-refs.html
  2. when a template render with a undecalred variable, vue3 will call console.warn to print error stacks.
  3. sentry hijacked console, and add the message to breadcrumb with safeJoin
  4. safeJoin will transfer variables to string. The ref variable is a proxied object via Proxy. so, when called String(value), will trigger the getter of Proxy, and got undefined, so again vue3 will call console.warn to print error stacks
  5. just loop infinitely.

solutions:

  1. tried to test the variable is Proxy. No matter how you test, will trigger proxy getter or other handlers, so it loops.
  2. the only way can test is the stack information from vue3

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Rockergmail and thanks for opening up this PR! Would be great to fix this long-standing bug.

I have a couple of questions. I'm not a Vue expert so it'd be great if you could tell me how the fix you're proposing works and why we need to modify the args that way. I'm not yet sure if we can fix this in the proposed way but I'll take it to the team.

EDIT: Seeing the CI results, our linter is not yet happy. Running yarn lint should tell you what's wrong

@Rockergmail

Rockergmail commented Oct 21, 2022

Copy link
Copy Markdown
ContributorAuthor

@Lms24 It seens I have explained why . And you can see the debug process here: #5916

let's take the demo for example: https://stackblitz.com/edit/vue-g6usgy?file=src%2Fmain.js

Or can you suggest me how can I explain to you in which way ? the vue3 render process ? vue3 render Mycomp.vue, when it comes to _ctx.test, it needs to get value of test. But due to vue3's mvvm, using Proxy to hijack varibles in the rendering context, so that it can collecte dependencies. When you try to modify the variable. It will trigger updates.

so when we try to get the value of test, will trigger getter handler of Proxified test, if the context get a test variable, it will return the value before collect dependence. if get no test variable, will call warn
image
(you can see the full function PublicInstanceProxyHandlers in packages/runtime-core/src/componentPublicInstance.ts of vue source code)

warn will print the stack of component's info.

component has a prop called ref which is a Proxified variable.

so, when we reach _consoleBreadcrumb of sentry/javascript, will call safeJoin to strinify the variable so that we can send it to the server and log it.

Because ref is a Proxified variable, when we call String(value) in the safeJoin, so it will call getter of ref. Due to the context has no ref variable, so the vue will warn again and agiain

As to why we need to modify the args that way:

  1. If we try to call String(value) to get the value, will loop. So we need to avoid doing this.
  2. If we try to test a variable is Proxy, there is no way. Because it will loop too.
  3. The only way to know the varibale is Proxy I can figure out is the print info from vue3 [Vue warn]: Property "test" was accessed during render but is not defined on instance. at <Anonymous ref=Ref< undefined > > at <App>. So I just modify the arg when we meet the ref=Ref<, which is for vue3 only.

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining. Sat down with the team and we think this is good to go. It's too bad that we can't more securely check for a Proxy but it seems like this really isn't possible and therefore I think your solution makes sense.

Tbh, we're overall not too happy with this small hack being in the framework-agnostic breadcrumbs integration. However, creating a Vue-specific integration (that's extending this integration) just for this one bug would also be a lot of work.

For future readers: This might however very well become an option in case we need to do more Vue-specific stuff in this integration.

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

Comment threadpackages/browser/src/integrations/breadcrumbs.ts
@Lms24Lms24 self-assigned this Oct 21, 2022
lgmt
Co-authored-by: Lukas Stracke <lukas.stracke@sentry.io>
@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

sorry, i am not sure if i am clear what you mean.

  1. I should create this branch base on 80f586e ,right?
  2. rebase this to the current master? what is this and what is the current master? is this means my branch ? the current master means master branch of getsentry/sentry-javascript, right?

@Lms24

@Lms24

Copy link
Copy Markdown
Member

Yes, I mean rebase your branch to master of getsentry/sentry-javascript.
Sorry for the confusion.

@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

done. here: #6014@Lms24

@Lms24

Copy link
Copy Markdown
Member

Closing this in Favour of #6014

@Lms24Lms24 closed this Oct 24, 2022
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Rockergmail@Lms24
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: fix vue3 render warning loop - #6010

Closed
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop
Closed

feat: fix vue3 render warning loop#6010
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop

Conversation

@Rockergmail

Copy link
Copy Markdown
Contributor

Before submitting a pull request, please take a look at our
Contributing guidelines and verify:

  • If you've added code that should be tested, please add tests.
  • Ensure your code lints and the test suite passes (yarn lint) & (yarn test).

fix issues:
#5916
#4743

why this happens:

  1. vue3 support the property ref in the second arg of h method, to support this feature: https://cn.vuejs.org/guide/essentials/template-refs.html
  2. when a template render with a undecalred variable, vue3 will call console.warn to print error stacks.
  3. sentry hijacked console, and add the message to breadcrumb with safeJoin
  4. safeJoin will transfer variables to string. The ref variable is a proxied object via Proxy. so, when called String(value), will trigger the getter of Proxy, and got undefined, so again vue3 will call console.warn to print error stacks
  5. just loop infinitely.

solutions:

  1. tried to test the variable is Proxy. No matter how you test, will trigger proxy getter or other handlers, so it loops.
  2. the only way can test is the stack information from vue3

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Rockergmail and thanks for opening up this PR! Would be great to fix this long-standing bug.

I have a couple of questions. I'm not a Vue expert so it'd be great if you could tell me how the fix you're proposing works and why we need to modify the args that way. I'm not yet sure if we can fix this in the proposed way but I'll take it to the team.

EDIT: Seeing the CI results, our linter is not yet happy. Running yarn lint should tell you what's wrong

@Rockergmail

Rockergmail commented Oct 21, 2022

Copy link
Copy Markdown
ContributorAuthor

@Lms24 It seens I have explained why . And you can see the debug process here: #5916

let's take the demo for example: https://stackblitz.com/edit/vue-g6usgy?file=src%2Fmain.js

Or can you suggest me how can I explain to you in which way ? the vue3 render process ? vue3 render Mycomp.vue, when it comes to _ctx.test, it needs to get value of test. But due to vue3's mvvm, using Proxy to hijack varibles in the rendering context, so that it can collecte dependencies. When you try to modify the variable. It will trigger updates.

so when we try to get the value of test, will trigger getter handler of Proxified test, if the context get a test variable, it will return the value before collect dependence. if get no test variable, will call warn
image
(you can see the full function PublicInstanceProxyHandlers in packages/runtime-core/src/componentPublicInstance.ts of vue source code)

warn will print the stack of component's info.

component has a prop called ref which is a Proxified variable.

so, when we reach _consoleBreadcrumb of sentry/javascript, will call safeJoin to strinify the variable so that we can send it to the server and log it.

Because ref is a Proxified variable, when we call String(value) in the safeJoin, so it will call getter of ref. Due to the context has no ref variable, so the vue will warn again and agiain

As to why we need to modify the args that way:

  1. If we try to call String(value) to get the value, will loop. So we need to avoid doing this.
  2. If we try to test a variable is Proxy, there is no way. Because it will loop too.
  3. The only way to know the varibale is Proxy I can figure out is the print info from vue3 [Vue warn]: Property "test" was accessed during render but is not defined on instance. at <Anonymous ref=Ref< undefined > > at <App>. So I just modify the arg when we meet the ref=Ref<, which is for vue3 only.

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining. Sat down with the team and we think this is good to go. It's too bad that we can't more securely check for a Proxy but it seems like this really isn't possible and therefore I think your solution makes sense.

Tbh, we're overall not too happy with this small hack being in the framework-agnostic breadcrumbs integration. However, creating a Vue-specific integration (that's extending this integration) just for this one bug would also be a lot of work.

For future readers: This might however very well become an option in case we need to do more Vue-specific stuff in this integration.

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

Comment threadpackages/browser/src/integrations/breadcrumbs.ts
@Lms24Lms24 self-assigned this Oct 21, 2022
lgmt
Co-authored-by: Lukas Stracke <lukas.stracke@sentry.io>
@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

sorry, i am not sure if i am clear what you mean.

  1. I should create this branch base on 80f586e ,right?
  2. rebase this to the current master? what is this and what is the current master? is this means my branch ? the current master means master branch of getsentry/sentry-javascript, right?

@Lms24

@Lms24

Copy link
Copy Markdown
Member

Yes, I mean rebase your branch to master of getsentry/sentry-javascript.
Sorry for the confusion.

@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

done. here: #6014@Lms24

@Lms24

Copy link
Copy Markdown
Member

Closing this in Favour of #6014

@Lms24Lms24 closed this Oct 24, 2022
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Rockergmail@Lms24
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat: fix vue3 render warning loop - #6010

Closed
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop
Closed

feat: fix vue3 render warning loop#6010
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop

Conversation

@Rockergmail

Copy link
Copy Markdown
Contributor

Before submitting a pull request, please take a look at our
Contributing guidelines and verify:

  • If you've added code that should be tested, please add tests.
  • Ensure your code lints and the test suite passes (yarn lint) & (yarn test).

fix issues:
#5916
#4743

why this happens:

  1. vue3 support the property ref in the second arg of h method, to support this feature: https://cn.vuejs.org/guide/essentials/template-refs.html
  2. when a template render with a undecalred variable, vue3 will call console.warn to print error stacks.
  3. sentry hijacked console, and add the message to breadcrumb with safeJoin
  4. safeJoin will transfer variables to string. The ref variable is a proxied object via Proxy. so, when called String(value), will trigger the getter of Proxy, and got undefined, so again vue3 will call console.warn to print error stacks
  5. just loop infinitely.

solutions:

  1. tried to test the variable is Proxy. No matter how you test, will trigger proxy getter or other handlers, so it loops.
  2. the only way can test is the stack information from vue3

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Rockergmail and thanks for opening up this PR! Would be great to fix this long-standing bug.

I have a couple of questions. I'm not a Vue expert so it'd be great if you could tell me how the fix you're proposing works and why we need to modify the args that way. I'm not yet sure if we can fix this in the proposed way but I'll take it to the team.

EDIT: Seeing the CI results, our linter is not yet happy. Running yarn lint should tell you what's wrong

@Rockergmail

Rockergmail commented Oct 21, 2022

Copy link
Copy Markdown
ContributorAuthor

@Lms24 It seens I have explained why . And you can see the debug process here: #5916

let's take the demo for example: https://stackblitz.com/edit/vue-g6usgy?file=src%2Fmain.js

Or can you suggest me how can I explain to you in which way ? the vue3 render process ? vue3 render Mycomp.vue, when it comes to _ctx.test, it needs to get value of test. But due to vue3's mvvm, using Proxy to hijack varibles in the rendering context, so that it can collecte dependencies. When you try to modify the variable. It will trigger updates.

so when we try to get the value of test, will trigger getter handler of Proxified test, if the context get a test variable, it will return the value before collect dependence. if get no test variable, will call warn
image
(you can see the full function PublicInstanceProxyHandlers in packages/runtime-core/src/componentPublicInstance.ts of vue source code)

warn will print the stack of component's info.

component has a prop called ref which is a Proxified variable.

so, when we reach _consoleBreadcrumb of sentry/javascript, will call safeJoin to strinify the variable so that we can send it to the server and log it.

Because ref is a Proxified variable, when we call String(value) in the safeJoin, so it will call getter of ref. Due to the context has no ref variable, so the vue will warn again and agiain

As to why we need to modify the args that way:

  1. If we try to call String(value) to get the value, will loop. So we need to avoid doing this.
  2. If we try to test a variable is Proxy, there is no way. Because it will loop too.
  3. The only way to know the varibale is Proxy I can figure out is the print info from vue3 [Vue warn]: Property "test" was accessed during render but is not defined on instance. at <Anonymous ref=Ref< undefined > > at <App>. So I just modify the arg when we meet the ref=Ref<, which is for vue3 only.

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining. Sat down with the team and we think this is good to go. It's too bad that we can't more securely check for a Proxy but it seems like this really isn't possible and therefore I think your solution makes sense.

Tbh, we're overall not too happy with this small hack being in the framework-agnostic breadcrumbs integration. However, creating a Vue-specific integration (that's extending this integration) just for this one bug would also be a lot of work.

For future readers: This might however very well become an option in case we need to do more Vue-specific stuff in this integration.

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

Comment threadpackages/browser/src/integrations/breadcrumbs.ts
@Lms24Lms24 self-assigned this Oct 21, 2022
lgmt
Co-authored-by: Lukas Stracke <lukas.stracke@sentry.io>
@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

sorry, i am not sure if i am clear what you mean.

  1. I should create this branch base on 80f586e ,right?
  2. rebase this to the current master? what is this and what is the current master? is this means my branch ? the current master means master branch of getsentry/sentry-javascript, right?

@Lms24

@Lms24

Copy link
Copy Markdown
Member

Yes, I mean rebase your branch to master of getsentry/sentry-javascript.
Sorry for the confusion.

@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

done. here: #6014@Lms24

@Lms24

Copy link
Copy Markdown
Member

Closing this in Favour of #6014

@Lms24Lms24 closed this Oct 24, 2022
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Rockergmail@Lms24
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: fix vue3 render warning loop - #6010

Closed
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop
Closed

feat: fix vue3 render warning loop#6010
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop

Conversation

@Rockergmail

Copy link
Copy Markdown
Contributor

Before submitting a pull request, please take a look at our
Contributing guidelines and verify:

  • If you've added code that should be tested, please add tests.
  • Ensure your code lints and the test suite passes (yarn lint) & (yarn test).

fix issues:
#5916
#4743

why this happens:

  1. vue3 support the property ref in the second arg of h method, to support this feature: https://cn.vuejs.org/guide/essentials/template-refs.html
  2. when a template render with a undecalred variable, vue3 will call console.warn to print error stacks.
  3. sentry hijacked console, and add the message to breadcrumb with safeJoin
  4. safeJoin will transfer variables to string. The ref variable is a proxied object via Proxy. so, when called String(value), will trigger the getter of Proxy, and got undefined, so again vue3 will call console.warn to print error stacks
  5. just loop infinitely.

solutions:

  1. tried to test the variable is Proxy. No matter how you test, will trigger proxy getter or other handlers, so it loops.
  2. the only way can test is the stack information from vue3

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Rockergmail and thanks for opening up this PR! Would be great to fix this long-standing bug.

I have a couple of questions. I'm not a Vue expert so it'd be great if you could tell me how the fix you're proposing works and why we need to modify the args that way. I'm not yet sure if we can fix this in the proposed way but I'll take it to the team.

EDIT: Seeing the CI results, our linter is not yet happy. Running yarn lint should tell you what's wrong

@Rockergmail

Rockergmail commented Oct 21, 2022

Copy link
Copy Markdown
ContributorAuthor

@Lms24 It seens I have explained why . And you can see the debug process here: #5916

let's take the demo for example: https://stackblitz.com/edit/vue-g6usgy?file=src%2Fmain.js

Or can you suggest me how can I explain to you in which way ? the vue3 render process ? vue3 render Mycomp.vue, when it comes to _ctx.test, it needs to get value of test. But due to vue3's mvvm, using Proxy to hijack varibles in the rendering context, so that it can collecte dependencies. When you try to modify the variable. It will trigger updates.

so when we try to get the value of test, will trigger getter handler of Proxified test, if the context get a test variable, it will return the value before collect dependence. if get no test variable, will call warn
image
(you can see the full function PublicInstanceProxyHandlers in packages/runtime-core/src/componentPublicInstance.ts of vue source code)

warn will print the stack of component's info.

component has a prop called ref which is a Proxified variable.

so, when we reach _consoleBreadcrumb of sentry/javascript, will call safeJoin to strinify the variable so that we can send it to the server and log it.

Because ref is a Proxified variable, when we call String(value) in the safeJoin, so it will call getter of ref. Due to the context has no ref variable, so the vue will warn again and agiain

As to why we need to modify the args that way:

  1. If we try to call String(value) to get the value, will loop. So we need to avoid doing this.
  2. If we try to test a variable is Proxy, there is no way. Because it will loop too.
  3. The only way to know the varibale is Proxy I can figure out is the print info from vue3 [Vue warn]: Property "test" was accessed during render but is not defined on instance. at <Anonymous ref=Ref< undefined > > at <App>. So I just modify the arg when we meet the ref=Ref<, which is for vue3 only.

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining. Sat down with the team and we think this is good to go. It's too bad that we can't more securely check for a Proxy but it seems like this really isn't possible and therefore I think your solution makes sense.

Tbh, we're overall not too happy with this small hack being in the framework-agnostic breadcrumbs integration. However, creating a Vue-specific integration (that's extending this integration) just for this one bug would also be a lot of work.

For future readers: This might however very well become an option in case we need to do more Vue-specific stuff in this integration.

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

Comment threadpackages/browser/src/integrations/breadcrumbs.ts
@Lms24Lms24 self-assigned this Oct 21, 2022
lgmt
Co-authored-by: Lukas Stracke <lukas.stracke@sentry.io>
@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

sorry, i am not sure if i am clear what you mean.

  1. I should create this branch base on 80f586e ,right?
  2. rebase this to the current master? what is this and what is the current master? is this means my branch ? the current master means master branch of getsentry/sentry-javascript, right?

@Lms24

@Lms24

Copy link
Copy Markdown
Member

Yes, I mean rebase your branch to master of getsentry/sentry-javascript.
Sorry for the confusion.

@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

done. here: #6014@Lms24

@Lms24

Copy link
Copy Markdown
Member

Closing this in Favour of #6014

@Lms24Lms24 closed this Oct 24, 2022
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Rockergmail@Lms24
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: fix vue3 render warning loop - #6010

Closed
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop
Closed

feat: fix vue3 render warning loop#6010
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop

Conversation

@Rockergmail

Copy link
Copy Markdown
Contributor

Before submitting a pull request, please take a look at our
Contributing guidelines and verify:

  • If you've added code that should be tested, please add tests.
  • Ensure your code lints and the test suite passes (yarn lint) & (yarn test).

fix issues:
#5916
#4743

why this happens:

  1. vue3 support the property ref in the second arg of h method, to support this feature: https://cn.vuejs.org/guide/essentials/template-refs.html
  2. when a template render with a undecalred variable, vue3 will call console.warn to print error stacks.
  3. sentry hijacked console, and add the message to breadcrumb with safeJoin
  4. safeJoin will transfer variables to string. The ref variable is a proxied object via Proxy. so, when called String(value), will trigger the getter of Proxy, and got undefined, so again vue3 will call console.warn to print error stacks
  5. just loop infinitely.

solutions:

  1. tried to test the variable is Proxy. No matter how you test, will trigger proxy getter or other handlers, so it loops.
  2. the only way can test is the stack information from vue3

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Rockergmail and thanks for opening up this PR! Would be great to fix this long-standing bug.

I have a couple of questions. I'm not a Vue expert so it'd be great if you could tell me how the fix you're proposing works and why we need to modify the args that way. I'm not yet sure if we can fix this in the proposed way but I'll take it to the team.

EDIT: Seeing the CI results, our linter is not yet happy. Running yarn lint should tell you what's wrong

@Rockergmail

Rockergmail commented Oct 21, 2022

Copy link
Copy Markdown
ContributorAuthor

@Lms24 It seens I have explained why . And you can see the debug process here: #5916

let's take the demo for example: https://stackblitz.com/edit/vue-g6usgy?file=src%2Fmain.js

Or can you suggest me how can I explain to you in which way ? the vue3 render process ? vue3 render Mycomp.vue, when it comes to _ctx.test, it needs to get value of test. But due to vue3's mvvm, using Proxy to hijack varibles in the rendering context, so that it can collecte dependencies. When you try to modify the variable. It will trigger updates.

so when we try to get the value of test, will trigger getter handler of Proxified test, if the context get a test variable, it will return the value before collect dependence. if get no test variable, will call warn
image
(you can see the full function PublicInstanceProxyHandlers in packages/runtime-core/src/componentPublicInstance.ts of vue source code)

warn will print the stack of component's info.

component has a prop called ref which is a Proxified variable.

so, when we reach _consoleBreadcrumb of sentry/javascript, will call safeJoin to strinify the variable so that we can send it to the server and log it.

Because ref is a Proxified variable, when we call String(value) in the safeJoin, so it will call getter of ref. Due to the context has no ref variable, so the vue will warn again and agiain

As to why we need to modify the args that way:

  1. If we try to call String(value) to get the value, will loop. So we need to avoid doing this.
  2. If we try to test a variable is Proxy, there is no way. Because it will loop too.
  3. The only way to know the varibale is Proxy I can figure out is the print info from vue3 [Vue warn]: Property "test" was accessed during render but is not defined on instance. at <Anonymous ref=Ref< undefined > > at <App>. So I just modify the arg when we meet the ref=Ref<, which is for vue3 only.

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining. Sat down with the team and we think this is good to go. It's too bad that we can't more securely check for a Proxy but it seems like this really isn't possible and therefore I think your solution makes sense.

Tbh, we're overall not too happy with this small hack being in the framework-agnostic breadcrumbs integration. However, creating a Vue-specific integration (that's extending this integration) just for this one bug would also be a lot of work.

For future readers: This might however very well become an option in case we need to do more Vue-specific stuff in this integration.

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

Comment threadpackages/browser/src/integrations/breadcrumbs.ts
@Lms24Lms24 self-assigned this Oct 21, 2022
lgmt
Co-authored-by: Lukas Stracke <lukas.stracke@sentry.io>
@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

sorry, i am not sure if i am clear what you mean.

  1. I should create this branch base on 80f586e ,right?
  2. rebase this to the current master? what is this and what is the current master? is this means my branch ? the current master means master branch of getsentry/sentry-javascript, right?

@Lms24

@Lms24

Copy link
Copy Markdown
Member

Yes, I mean rebase your branch to master of getsentry/sentry-javascript.
Sorry for the confusion.

@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

done. here: #6014@Lms24

@Lms24

Copy link
Copy Markdown
Member

Closing this in Favour of #6014

@Lms24Lms24 closed this Oct 24, 2022
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Rockergmail@Lms24
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat: fix vue3 render warning loop - #6010

Closed
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop
Closed

feat: fix vue3 render warning loop#6010
Rockergmail wants to merge 3 commits into
getsentry:masterfrom
Rockergmail:feature/fix-vue3-render-loop

Conversation

@Rockergmail

Copy link
Copy Markdown
Contributor

Before submitting a pull request, please take a look at our
Contributing guidelines and verify:

  • If you've added code that should be tested, please add tests.
  • Ensure your code lints and the test suite passes (yarn lint) & (yarn test).

fix issues:
#5916
#4743

why this happens:

  1. vue3 support the property ref in the second arg of h method, to support this feature: https://cn.vuejs.org/guide/essentials/template-refs.html
  2. when a template render with a undecalred variable, vue3 will call console.warn to print error stacks.
  3. sentry hijacked console, and add the message to breadcrumb with safeJoin
  4. safeJoin will transfer variables to string. The ref variable is a proxied object via Proxy. so, when called String(value), will trigger the getter of Proxy, and got undefined, so again vue3 will call console.warn to print error stacks
  5. just loop infinitely.

solutions:

  1. tried to test the variable is Proxy. No matter how you test, will trigger proxy getter or other handlers, so it loops.
  2. the only way can test is the stack information from vue3

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Rockergmail and thanks for opening up this PR! Would be great to fix this long-standing bug.

I have a couple of questions. I'm not a Vue expert so it'd be great if you could tell me how the fix you're proposing works and why we need to modify the args that way. I'm not yet sure if we can fix this in the proposed way but I'll take it to the team.

EDIT: Seeing the CI results, our linter is not yet happy. Running yarn lint should tell you what's wrong

@Rockergmail

Rockergmail commented Oct 21, 2022

Copy link
Copy Markdown
ContributorAuthor

@Lms24 It seens I have explained why . And you can see the debug process here: #5916

let's take the demo for example: https://stackblitz.com/edit/vue-g6usgy?file=src%2Fmain.js

Or can you suggest me how can I explain to you in which way ? the vue3 render process ? vue3 render Mycomp.vue, when it comes to _ctx.test, it needs to get value of test. But due to vue3's mvvm, using Proxy to hijack varibles in the rendering context, so that it can collecte dependencies. When you try to modify the variable. It will trigger updates.

so when we try to get the value of test, will trigger getter handler of Proxified test, if the context get a test variable, it will return the value before collect dependence. if get no test variable, will call warn
image
(you can see the full function PublicInstanceProxyHandlers in packages/runtime-core/src/componentPublicInstance.ts of vue source code)

warn will print the stack of component's info.

component has a prop called ref which is a Proxified variable.

so, when we reach _consoleBreadcrumb of sentry/javascript, will call safeJoin to strinify the variable so that we can send it to the server and log it.

Because ref is a Proxified variable, when we call String(value) in the safeJoin, so it will call getter of ref. Due to the context has no ref variable, so the vue will warn again and agiain

As to why we need to modify the args that way:

  1. If we try to call String(value) to get the value, will loop. So we need to avoid doing this.
  2. If we try to test a variable is Proxy, there is no way. Because it will loop too.
  3. The only way to know the varibale is Proxy I can figure out is the print info from vue3 [Vue warn]: Property "test" was accessed during render but is not defined on instance. at <Anonymous ref=Ref< undefined > > at <App>. So I just modify the arg when we meet the ref=Ref<, which is for vue3 only.

@Lms24Lms24 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining. Sat down with the team and we think this is good to go. It's too bad that we can't more securely check for a Proxy but it seems like this really isn't possible and therefore I think your solution makes sense.

Tbh, we're overall not too happy with this small hack being in the framework-agnostic breadcrumbs integration. However, creating a Vue-specific integration (that's extending this integration) just for this one bug would also be a lot of work.

For future readers: This might however very well become an option in case we need to do more Vue-specific stuff in this integration.

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

Comment threadpackages/browser/src/integrations/breadcrumbs.ts
@Lms24Lms24 self-assigned this Oct 21, 2022
lgmt
Co-authored-by: Lukas Stracke <lukas.stracke@sentry.io>
@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

It seems like our E2E tests are failing because our Auth token was not set for PRs coming from forks. Any chance that you created this branch before we merged #5986? Would you mind rebasing this to the current master?

sorry, i am not sure if i am clear what you mean.

  1. I should create this branch base on 80f586e ,right?
  2. rebase this to the current master? what is this and what is the current master? is this means my branch ? the current master means master branch of getsentry/sentry-javascript, right?

@Lms24

@Lms24

Copy link
Copy Markdown
Member

Yes, I mean rebase your branch to master of getsentry/sentry-javascript.
Sorry for the confusion.

@Rockergmail

Copy link
Copy Markdown
ContributorAuthor

done. here: #6014@Lms24

@Lms24

Copy link
Copy Markdown
Member

Closing this in Favour of #6014

@Lms24Lms24 closed this Oct 24, 2022
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Rockergmail@Lms24