From d9f3f54585024827d29d37f7d99a9d280da98e15 Mon Sep 17 00:00:00 2001 From: threadhoard-vps Date: Mon, 1 Jun 2026 18:45:45 +0000 Subject: [PATCH] fix: validate PerformanceObserver observe options --- .../performance/PerformanceObserver.js | 20 ++++++++++++--- .../__tests__/PerformanceObserver-itest.js | 25 +++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/packages/react-native/src/private/webapis/performance/PerformanceObserver.js b/packages/react-native/src/private/webapis/performance/PerformanceObserver.js index c1b2a47a0ba9..57a0e1d89466 100644 --- a/packages/react-native/src/private/webapis/performance/PerformanceObserver.js +++ b/packages/react-native/src/private/webapis/performance/PerformanceObserver.js @@ -203,18 +203,30 @@ export class PerformanceObserver { return observerHandle; } - #validateObserveOptions(options: PerformanceObserverInit): void { - const {type, entryTypes, durationThreshold} = options; + #validateObserveOptions(options: ?PerformanceObserverInit): void { + if (options == null) { + throw new TypeError( + "Failed to execute 'observe' on 'PerformanceObserver': 1 argument required, but only 0 present.", + ); + } + + const {type, entryTypes, durationThreshold, buffered} = options; if (!type && !entryTypes) { throw new TypeError( - "Failed to execute 'observe' on 'PerformanceObserver': An observe() call must not include both entryTypes and type arguments.", + "Failed to execute 'observe' on 'PerformanceObserver': An observe() call must include either entryTypes or type arguments.", ); } if (entryTypes && type) { throw new TypeError( - "Failed to execute 'observe' on 'PerformanceObserver': An observe() call must include either entryTypes or type arguments.", + "Failed to execute 'observe' on 'PerformanceObserver': An observe() call must not include both entryTypes and type arguments.", + ); + } + + if (entryTypes && buffered != null) { + throw new TypeError( + "Failed to execute 'observe' on 'PerformanceObserver': An observe() call must not include both entryTypes and buffered arguments.", ); } diff --git a/packages/react-native/src/private/webapis/performance/__tests__/PerformanceObserver-itest.js b/packages/react-native/src/private/webapis/performance/__tests__/PerformanceObserver-itest.js index 41ddaa4be8f3..3924e5e24356 100644 --- a/packages/react-native/src/private/webapis/performance/__tests__/PerformanceObserver-itest.js +++ b/packages/react-native/src/private/webapis/performance/__tests__/PerformanceObserver-itest.js @@ -96,6 +96,31 @@ describe('PerformanceObserver', () => { expect(entries2.getEntries()[1]).toBe(measure); }); + describe('observe()', () => { + it('rejects invalid entry type option combinations before registering with native', () => { + const callback = jest.fn(); + const observer = new PerformanceObserver(callback); + + // $FlowExpectedError[incompatible-call] + expect(() => observer.observe()).toThrow( + "Failed to execute 'observe' on 'PerformanceObserver': 1 argument required, but only 0 present.", + ); + expect(() => observer.observe({})).toThrow( + "Failed to execute 'observe' on 'PerformanceObserver': An observe() call must include either entryTypes or type arguments.", + ); + expect(() => + observer.observe({entryTypes: ['mark'], type: 'measure'}), + ).toThrow( + "Failed to execute 'observe' on 'PerformanceObserver': An observe() call must not include both entryTypes and type arguments.", + ); + expect(() => + observer.observe({entryTypes: ['mark'], buffered: true}), + ).toThrow( + "Failed to execute 'observe' on 'PerformanceObserver': An observe() call must not include both entryTypes and buffered arguments.", + ); + }); + }); + describe('takeRecords()', () => { it('provides all buffered events and clears the buffer', () => { const callback = jest.fn();