diff --git a/packages/react-native/src/private/webapis/performance/PerformanceEntry.js b/packages/react-native/src/private/webapis/performance/PerformanceEntry.js index 76daf969c03..f2ddfceda55 100644 --- a/packages/react-native/src/private/webapis/performance/PerformanceEntry.js +++ b/packages/react-native/src/private/webapis/performance/PerformanceEntry.js @@ -29,10 +29,14 @@ export type PerformanceEntryJSON = { }; export class PerformanceEntry { - #name: string; - #entryType: PerformanceEntryType; - #startTime: DOMHighResTimeStamp; - #duration: DOMHighResTimeStamp; + // We don't use private fields because they're significantly slower to + // initialize on construction and to access. + // We also need these to be protected so they can be initialized in subclasses + // where we avoid calling `super()` for performance reasons. + __name: string; + __entryType: PerformanceEntryType; + __startTime: DOMHighResTimeStamp; + __duration: DOMHighResTimeStamp; constructor(init: { name: string, @@ -40,34 +44,34 @@ export class PerformanceEntry { startTime: DOMHighResTimeStamp, duration: DOMHighResTimeStamp, }) { - this.#name = init.name; - this.#entryType = init.entryType; - this.#startTime = init.startTime; - this.#duration = init.duration; + this.__name = init.name; + this.__entryType = init.entryType; + this.__startTime = init.startTime; + this.__duration = init.duration; } get name(): string { - return this.#name; + return this.__name; } get entryType(): PerformanceEntryType { - return this.#entryType; + return this.__entryType; } get startTime(): DOMHighResTimeStamp { - return this.#startTime; + return this.__startTime; } get duration(): DOMHighResTimeStamp { - return this.#duration; + return this.__duration; } toJSON(): PerformanceEntryJSON { return { - name: this.#name, - entryType: this.#entryType, - startTime: this.#startTime, - duration: this.#duration, + name: this.__name, + entryType: this.__entryType, + startTime: this.__startTime, + duration: this.__duration, }; } } diff --git a/packages/react-native/src/private/webapis/performance/UserTiming.js b/packages/react-native/src/private/webapis/performance/UserTiming.js index 6809f3ca5ca..09aaa140d38 100644 --- a/packages/react-native/src/private/webapis/performance/UserTiming.js +++ b/packages/react-native/src/private/webapis/performance/UserTiming.js @@ -29,9 +29,12 @@ export type PerformanceMeasureInit = { duration: DOMHighResTimeStamp, }; -export class PerformanceMark extends PerformanceEntry { - #detail: DetailType; +class PerformanceMarkTemplate extends PerformanceEntry { + // We don't use private fields because they're significantly slower to + // initialize on construction and to access. + _detail: DetailType; + // This constructor isn't really used. See `PerformanceMark` below. constructor(markName: string, markOptions?: PerformanceMarkOptions) { super({ name: markName, @@ -41,18 +44,46 @@ export class PerformanceMark extends PerformanceEntry { }); if (markOptions) { - this.#detail = markOptions.detail; + this._detail = markOptions.detail; } } get detail(): DetailType { - return this.#detail; + return this._detail; } } -export class PerformanceMeasure extends PerformanceEntry { - #detail: DetailType; +// This is the real value we're exporting where we define the class a function +// so we don't need to call `super()` and we can avoid the performance penalty +// of the current code transpiled with Babel. +// We should remove this when we have built-in support for classes in the +// runtime. +export const PerformanceMark: typeof PerformanceMarkTemplate = + // $FlowExpectedError[incompatible-type] + function PerformanceMark( + this: PerformanceMarkTemplate, + markName: string, + markOptions?: PerformanceMarkOptions, + ) { + this.__name = markName; + this.__entryType = 'mark'; + this.__startTime = markOptions?.startTime ?? performance.now(); + this.__duration = 0; + if (markOptions) { + this._detail = markOptions.detail; + } + }; + +// $FlowExpectedError[prop-missing] +PerformanceMark.prototype = PerformanceMarkTemplate.prototype; + +class PerformanceMeasureTemplate extends PerformanceEntry { + // We don't use private fields because they're significantly slower to + // initialize on construction and to access. + _detail: DetailType; + + // This constructor isn't really used. See `PerformanceMeasure` below. constructor(measureName: string, measureOptions: PerformanceMeasureInit) { super({ name: measureName, @@ -62,11 +93,32 @@ export class PerformanceMeasure extends PerformanceEntry { }); if (measureOptions) { - this.#detail = measureOptions.detail; + this._detail = measureOptions.detail; } } get detail(): DetailType { - return this.#detail; + return this._detail; } } + +// We do the same here as we do for `PerformanceMark` for performance reasons. +export const PerformanceMeasure: typeof PerformanceMeasureTemplate = + // $FlowExpectedError[incompatible-type] + function PerformanceMeasure( + this: PerformanceMeasureTemplate, + measureName: string, + measureOptions: PerformanceMeasureInit, + ) { + this.__name = measureName; + this.__entryType = 'measure'; + this.__startTime = measureOptions.startTime; + this.__duration = measureOptions.duration; + + if (measureOptions) { + this._detail = measureOptions.detail; + } + }; + +// $FlowExpectedError[prop-missing] +PerformanceMeasure.prototype = PerformanceMeasureTemplate.prototype;