-
-
Notifications
You must be signed in to change notification settings - Fork 368
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 bug in WaitLoad when event has circular reference #1150
base: main
Are you sure you want to change the base?
Conversation
@@ -248,12 +248,12 @@ const functions = { | |||
return new Promise((resolve, reject) => { | |||
if (isWin) { | |||
if (document.readyState === 'complete') return resolve() | |||
window.addEventListener('load', resolve) | |||
window.addEventListener('load', _=>resolve()) |
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.
window.addEventListener('load', _=>resolve()) | |
window.addEventListener('load', resolve) |
} else { | ||
if (this.complete === undefined || this.complete) { | ||
resolve() | ||
} else { | ||
this.addEventListener('load', resolve) | ||
this.addEventListener('load', _=>resolve()) |
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.addEventListener('load', _=>resolve()) | |
this.addEventListener('load', resolve) |
@ysmood Could you explain your latest suggestions? I'm afraid I'm missing something. It looks like you're suggesting that I revert all my changes to helper.js. |
It's been a week so I'm going to re-request review as a reminder. Could you explain your latest suggestions? I'm afraid I'm missing something. It looks like you're suggesting that I revert all my changes to helper.js. |
Sorry for the late reply, it has been a busy season for me. For javascript code like: this.addEventListener('load', _=>resolve()) Is effectively the same as: this.addEventListener('load', resolve) Can you tell me in what case they will behave differently? |
No worries! These two expressions are actually not the same at all. Let me explain:
My change is This is a critical distinction, because whatever value is passed to the resolve function, rod tries to load it into the Go process from the browser. In the case I explained in the PR description, when the event object has a circular reference, rod will get an "Object reference chain is too long" error if it tries to load the event object from the browser. But if we instead call |
This fixes a bug in WaitLoad that causes it to fail with "Object reference chain is too long". This happens when we take the branch of the WaitLoad js that listens for the "load" event. In this case the load event object is returned by the function, and the object's value is loaded from the browser by rod. Sometimes this object can have a circular reference, causing the CDP to throw the Object reference chain is too long error.
I have seen the event object have a circular reference on sites using bootstrap.bundle.min.js. That library adds a
delegateTarget
property to event objects. The way it does this is by mutating the event object in a "load" event handler, so delegateTarget may not always be added to the event object received by other "load" event listeners depending on the order in which the handlers fire. I set up an example site that shows the issue - here is a small script to hit the site over and over until the issue occurs. It usually only takes two tries for me to reproduce the issue.The fix was very simple - just stop returning the event object from WaitLoad, because it's not necessary.
I added a unit test, but given the complex and timing-dependent nature of the bug, the test ended up being pretty complicated. And it's still not 100% robust as ultimately it depends on the firing order of event handlers.
I didn't look to see whether the same bug might be possible in any of the other js functions.