-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
core(driver): use execution context isolation when necessary #3500
Conversation
1a3eaf8
to
03c5e29
Compare
lighthouse-core/gather/driver.js
Outdated
}).then(result => { | ||
}; | ||
|
||
if (useIsolation && typeof this._isolatedExecutionContextId === 'number') { |
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.
if isolation is requested but there is no contextId... should we throw?
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.
I had this originally to check for leaks and it seemed ok, but it's definitely possible and seemed bad to tank the run because it since it won't matter most of the time
perhaps something to add to sentry though when it lands?
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.
Seems like we should be able to figure out definitively if it's possible to reach here without having created a new context? Then future violations of this can complain loudly by throwing (alternatively, see other comment about lazily calling _createIsolatedWorld()
)
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.
going the lazy route 👍
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" | ||
|
||
for d in "$DIR"/*/ ; do | ||
bash "${d}run-tests.sh" |
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.
there are a few other ways to do this, but the benefit of this approach is the failures won't be silent. :)
sgtm
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.
can we just manually list the files in here? If I'm messing with some smoke tests it's a lot easier to comment out lines in one place by name than look up where the individual run-tests file is
also it'd probably be better to just get rid of all the run-tests.sh
files since they're all exactly the same except for the expectations and config filename strings :)
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.
will nuke 'em all in a follow up PR and improve this file here 👍
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.
for future calls to evaluateAsync
, how does one know if it should be isolated or not? Try the default out and if it fails (returns nothing when expected something?) try turning off isolation? :)
Is there anything we can do for these non-isolated ones (js-libraries, function callsites, and check for quiet) to make them isolated? I guess it's just unclear what's isolated and what's not if the axe checks work but js-library-detector
does not
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" | ||
|
||
for d in "$DIR"/*/ ; do | ||
bash "${d}run-tests.sh" |
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.
can we just manually list the files in here? If I'm messing with some smoke tests it's a lot easier to comment out lines in one place by name than look up where the individual run-tests file is
also it'd probably be better to just get rid of all the run-tests.sh
files since they're all exactly the same except for the expectations and config filename strings :)
lighthouse-core/gather/driver.js
Outdated
* @return {!Promise<*>} | ||
*/ | ||
evaluateAsync(expression) { | ||
evaluateAsync(expression, options) { | ||
const {useIsolation = true} = options || {}; |
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.
the double defaults here is kind of confusing. Maybe move the {}
default for options
to the params?
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.
done
lighthouse-core/gather/driver.js
Outdated
}).then(result => { | ||
}; | ||
|
||
if (useIsolation && typeof this._isolatedExecutionContextId === 'number') { |
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.
Seems like we should be able to figure out definitively if it's possible to reach here without having created a new context? Then future violations of this can complain loudly by throwing (alternatively, see other comment about lazily calling _createIsolatedWorld()
)
lighthouse-core/gather/driver.js
Outdated
@@ -633,6 +661,7 @@ class Driver { | |||
}) | |||
.then(_ => waitForLoad && this._waitForFullyLoaded(pauseAfterLoadMs, | |||
networkQuietThresholdMs, cpuQuietThresholdMs, maxWaitMs)) | |||
.then(_ => this._createIsolatedWorld()) |
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.
Would there be downsides to clearing on all navigations (as above) but calling _createIsolatedWorld
lazily on next evaluateAsync()
when _isolatedExecutionContextId
isn't defined?
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.
done
discussed offline, decided to switch the default to useIsolation=false and just opt-in a11y for now |
03c5e29
to
2779925
Compare
2779925
to
9c446ec
Compare
9c446ec
to
a860423
Compare
PTAL :) |
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 lgtm in general. just nits
@@ -197,5 +197,13 @@ | |||
<section> | |||
<video id="video-description"></video> | |||
</section> | |||
<script> | |||
// axe fails if `define` is present but misbehaves, create a bogus implementation to exercise our |
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.
I don't totally get this. I'll ask you in person if i'm interpreting it correctly, but it could probably use a slightly more extended comment. :)
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.
// axe fails if a different UMD loader like almond.js is used on the page, see https://github.com/GoogleChrome/lighthouse/issues/2505
// We can simulate this behavior by defining a similarly misbehaving `define` function.
sounds better?
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.
YESSS so good
settings: { | ||
onlyCategories: [ | ||
'accessibility', | ||
], |
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.
since we were talking about it yesterday... is it possible to reuse an existing smoketest?
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.
I know we were literally just talking about not adding more yesterday but of all the testers that should probably get their own one, I think a11y is one of them 😆
maybe we can start by reducing DBW's 6 passes instead? :)
lighthouse-core/gather/driver.js
Outdated
@@ -596,6 +619,26 @@ class Driver { | |||
} | |||
|
|||
/** | |||
* @return {!Promise<number>} | |||
*/ | |||
_getOrCreateIsolatedContextId() { |
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.
_acquireIsolatedContextId()
?
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.
discussed offline, Paul's a huge fan of getOrCreate
now 🚗 🎏 🎉
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.
lol
lighthouse-core/gather/driver.js
Outdated
return this.sendCommand('Page.getResourceTree') | ||
.then(data => { | ||
const frameId = data.frameTree.frame.id; | ||
return this.sendCommand('Page.createIsolatedWorld', {frameId}); |
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.
let's give it a worldName
while we're at it.
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.
done
lighthouse-core/gather/driver.js
Outdated
|
||
return this.sendCommand('Page.getResourceTree') | ||
.then(data => { | ||
const frameId = data.frameTree.frame.id; |
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.
frameId => mainFrameId
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.
done
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.
LGTM. ⛰ 💻 🔐
* Evaluate an expression in the context of the current page. | ||
* Evaluate an expression in the context of the current page. If useIsolation is true, the expression | ||
* will be evaluated in a content script that has access to the page's DOM but whose JavaScript state | ||
* is completely separate. |
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.
👍 👍
* Evaluate an expression in the given execution context; an undefined contextId implies the main | ||
* page without isolation. | ||
* @param {string} expression | ||
* @param {number|undefined} contextId |
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.
can be {number=}
FWIW
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.
yeah just seemed more explicit since something is always passed in but doesn't matter to me
lighthouse-core/gather/driver.js
Outdated
@@ -596,6 +619,26 @@ class Driver { | |||
} | |||
|
|||
/** | |||
* @return {!Promise<number>} | |||
*/ | |||
_getOrCreateIsolatedContextId() { |
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.
maybe a jsdoc comment here that the contextId won't persist past a page load (so should be cleared and recreated)?
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.
good call, done
closes #2511
fixes #2505