From 36c2df593fc89bf88ebe45395e346795246b132a Mon Sep 17 00:00:00 2001 From: Patrick Hulce Date: Fri, 14 Jul 2017 11:27:04 -0700 Subject: [PATCH] fix(driver): prevent PerfObserver from being garbage collected (#2682) * fix(driver): add interval and timeout hacks to PerfObserver * more sensible hack * feedback * more feedback --- lighthouse-core/gather/driver.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lighthouse-core/gather/driver.js b/lighthouse-core/gather/driver.js index 0bc42941b812..4ee299b5fc4e 100644 --- a/lighthouse-core/gather/driver.js +++ b/lighthouse-core/gather/driver.js @@ -436,8 +436,11 @@ class Driver { } let lastTimeout; + let cancelled = false; let isResolvable = false; function checkForQuiet(driver, resolve) { + if (cancelled) return; + const tryLater = timeToWait => { lastTimeout = setTimeout(() => checkForQuiet(driver, resolve), timeToWait); }; @@ -448,6 +451,8 @@ class Driver { return driver.evaluateAsync(`(${checkTimeSinceLastLongTask.toString()})()`) .then(timeSinceLongTask => { + if (cancelled) return; + if (typeof timeSinceLongTask === 'number' && timeSinceLongTask >= waitForCPUQuiet) { log.verbose('Driver', `CPU has been idle for ${timeSinceLongTask} ms`); resolve(); @@ -462,6 +467,7 @@ class Driver { const promise = new Promise((resolve, reject) => { checkForQuiet(this, resolve); cancel = () => { + cancelled = true; if (lastTimeout) clearTimeout(lastTimeout); reject(new Error('Wait for CPU idle cancelled')); }; @@ -1107,7 +1113,12 @@ function registerPerformanceObserverInPage() { } } }); + observer.observe({entryTypes: ['longtask']}); + // HACK: A PerformanceObserver will be GC'd if there are no more references to it, so attach it to + // window to ensure we still receive longtask notifications. See https://crbug.com/742530. + // For an example test of this behavior see https://gist.github.com/patrickhulce/69d8bed1807e762218994b121d06fea6. + window.____lhPerformanceObserver = observer; }