-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
fix: inserted styles lost when moving elements #1357
base: master
Are you sure you want to change the base?
Conversation
|
d455e0b
to
9c4d539
Compare
The original approach I took w/ copying cssRules into the virtual nodes created an issue w/ duplicate styles being applied after the diff. This was because that approach wasn't surgical enough and applied to all style sheets - not just the ones that were being moved. To address that, I moved the fix into the diff work to only copy inserted styles over when insertBefore() is being used. I also added a test case in replayer.test that fails if you run w/o my changes (demonstrating the issue) and passes w/ my changes. I'm not sure if the written code satisfies rrweb style/standards, so I haven't written tests for the 'util' functions that were added to diff.ts. Happy to adjust where that code lives based on comments. :) |
packages/rrweb/test/replayer.test.ts
Outdated
@@ -718,7 +735,7 @@ describe('replayer', function () { | |||
const replayer = new Replayer(events); | |||
replayer.play(); | |||
`); | |||
await page.waitForTimeout(50); | |||
await page.waitForTimeout(150); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a more reliable way of forcing a wait
await page.waitForTimeout(150); | |
await waitForRAF(page); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated and thank you!
9c4d539
to
c6de322
Compare
@YunFeng0817 could you check this one out, see if this is the best way to do this in rrdom? @eoghanmurray and I started reviewing this, tests look good, but we're also not sure if this is the best way to implement this. @jaj1014 Thanks for taking the time to debug this and create a fix for it! |
404c950
to
f4537e6
Compare
Finally got around to adding unit test coverage for the added functions. |
fb5143a
to
8b10795
Compare
if ( | ||
iframeSourceWindow == window.parent && | ||
window != window.parent && | ||
message.data.snapshot |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Annoyingly, typescript (eslint) is failing here; you could define your own message type (see CrossOriginIframeMessageEventContent) and cast to that message type with the as
keyword, or maybe the following will work
message.data.snapshot | |
'snapshot' in message.data |
@@ -93,7 +91,7 @@ export function initMutationObserver( | |||
// see mutation.ts for details | |||
mutationBuffer.init(options); | |||
let mutationObserverCtor = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No idea what all the angularZoneSymbol stuff is, but now that this is no longer reassigned by that code, eslint requires us to change to a const
let mutationObserverCtor = | |
const mutationObserverCtor = |
sorry @eoghanmurray my branch got screwed up w/ some other commits. I'll try to get it clean up and back to only the changes pertinent to this PR. or worst case, close and open a clean one. sorry about this. |
The new For this PR though, I feel like it might be overkill and that it adds too much complexity; I feel like the underlying problem should be fixed instead (that elements don't get moved around after diffChildren). But maybe I'm missing something and this PR is the only way of doing it? |
cae6981 has the changes pertinent to the originally described problem. all the other commits got mixed in unintentionally. unsure if the complexity you're referring to is contained in this one commit, or if you're referring to the others. you're correct on the gist of the code: it rectifies the issue caused by It's been a while since I've been in this code, and what I thought I know may not even be right. I was thinking that moving elements was just applying the result of diffing with the virtualDom. When not using the virtualDom optimization, this issue doesn't happen. I'm don't know if it is possible to not move elements after diffChildren |
Ah okay; if you wish you could cherry-pick that commit onto an up to date trunk and push here. Until then I'll leave it to @YunFeng0817 to look at the code and see if this is the best approach or if there is a simpler way of achieving the same thing with rrdom. |
ef06778
to
e87e9df
Compare
fix code for nodejs tests change fix direction to avoid issues with duplicate styles format issues swap waitForTimeout for waitForRAF in test that flaked Add unit tests for new functions Fix broken test causes by file formatting removing spaced
f890bc9
to
cf4b340
Compare
I've been trying this out and I think this causes a perf regression. I'm seeing the differ go from ~300-400 to ~600-700ms. The profiler indicates that |
Interesting. It makes sense that it's going to cause a performance hit to diff since it's running code that wasn't there before, but it should only run for style elements since those are the ones it's concerned with - and I'm not sure what in that function would cause a reflow... Was there something specific you saw w/ The forEach that goes through the inserted styles found by |
couldn't resist and was curious... maybe because it uses Based on the article, it looks like |
hello 👋 - I created an issue a couple weeks back and had some time to dig in a bit more to see if I could figure out a potential solution.
The issue linked above has more detail, but the tl;dr; is that styles which are inserted using
CSSStyleSheet.insertRule()
are lost during diff operations that result in that style element getting moved.In order to better demonstrate the problem, I was finally able to create a recording (linked below): If you skip from 0:04 seconds to 0:15, you'll see the teal div at the top loses it's teal color. If you let it play through from 0:04 seconds to 0:15, you'll notice the teal div is still teal. This is because skipping triggers the style element which had the teal styles inserted gets moved as a result of the diff, so the inserted styles get lost. Letting it play through, they aren't lost because diff isn't run and things get mutated normally (w/o virtual dom).
https://rrwebdebug.com/play/index.html?url=https%3A%2F%2Fgist.github.com%2Fjaj1014%2F6e6658d0f24ea297d31edbcfdd44379e&version=2.0.0-alpha.8&virtual-dom=on&play=on
Because the issue has several things contributing to the issue, I wasn't sure where it made the most sense to apply a fix. I took a stab at applying a fix during the diff process inside
buildFromNode
to copy CSSRules from the domnode
into therrNode
for style elements. Later in the diff flow, there is code that will take those style rules copied from the original and apply them.