diff --git a/src/service/performance-impl.js b/src/service/performance-impl.js index 038ba43f8564..94271cfec7aa 100644 --- a/src/service/performance-impl.js +++ b/src/service/performance-impl.js @@ -556,9 +556,14 @@ export class Performance { * @param {!LayoutShift} entry */ tickLayoutShiftScore_(entry) { + if (!this.ampdoc_) { + return; + } + if (this.isVisibilityHidden_()) { return; } + const entries = this.layoutShiftEntries_; if (entries.length > 0) { const first = entries[0]; diff --git a/test/unit/test-performance.js b/test/unit/test-performance.js index 488b48f73b7b..b1721ab4b8d8 100644 --- a/test/unit/test-performance.js +++ b/test/unit/test-performance.js @@ -1167,6 +1167,22 @@ describes.realWin('PeformanceObserver metrics', {amp: true}, (env) => { return Services.performanceFor(env.win); } + it('should not throw when layout-shift occurs before core services available', () => { + // Fake the Performance API. + env.win.PerformanceObserver.supportedEntryTypes = ['layout-shift']; + const perf = getPerformance(); + + // Fake layout-shift that occured before core services registered + performanceObserver.triggerCallback({ + getEntries() { + return [ + {entryType: 'layout-shift', value: 0.3, hadRecentInput: false}, + ]; + }, + }); + perf.coreServicesAvailable(); + }); + it('when the viewer visibility changes to inactive', () => { // Specify an Android Chrome user agent. env.sandbox