Skip to content

Commit 1716b3c

Browse files
rubennortefacebook-github-bot
authored andcommitted
Implement private constructors for Performance APIs (#53430)
Summary: Pull Request resolved: #53430 Changelog: [internal] This fixes the spec-compliance of several classes in the Performance API by not allowing userland code to instantiate them directly. This also exposes some missing interfaces from the Performance API in the global scope. Reviewed By: rshest Differential Revision: D80800076 fbshipit-source-id: f6439b9c7914817ef552e78fd61646ccab1e1de2
1 parent bb508a4 commit 1716b3c

File tree

13 files changed

+234
-17
lines changed

13 files changed

+234
-17
lines changed

packages/react-native/src/private/setup/setUpPerformanceObserver.js

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,34 @@ export default function setUpPerformanceObserver() {
2020
initialized = true;
2121

2222
polyfillGlobal(
23-
'PerformanceObserver',
23+
'EventCounts',
24+
() => require('../webapis/performance/EventTiming').EventCounts_public,
25+
);
26+
27+
polyfillGlobal(
28+
'Performance',
29+
() => require('../webapis/performance/Performance').Performance_public,
30+
);
31+
32+
polyfillGlobal(
33+
'PerformanceEntry',
2434
() =>
25-
require('../webapis/performance/PerformanceObserver').PerformanceObserver,
35+
require('../webapis/performance/PerformanceEntry')
36+
.PerformanceEntry_public,
2637
);
2738

2839
polyfillGlobal(
29-
'PerformanceObserverEntryList',
40+
'PerformanceEventTiming',
3041
() =>
31-
require('../webapis/performance/PerformanceObserver')
32-
.PerformanceObserverEntryList,
42+
require('../webapis/performance/EventTiming')
43+
.PerformanceEventTiming_public,
3344
);
3445

3546
polyfillGlobal(
36-
'PerformanceEntry',
37-
() => require('../webapis/performance/PerformanceEntry').PerformanceEntry,
47+
'PerformanceLongTaskTiming',
48+
() =>
49+
require('../webapis/performance/LongTasks')
50+
.PerformanceLongTaskTiming_public,
3851
);
3952

4053
polyfillGlobal(
@@ -44,28 +57,33 @@ export default function setUpPerformanceObserver() {
4457

4558
polyfillGlobal(
4659
'PerformanceMeasure',
47-
() => require('../webapis/performance/UserTiming').PerformanceMeasure,
60+
() =>
61+
require('../webapis/performance/UserTiming').PerformanceMeasure_public,
4862
);
4963

5064
polyfillGlobal(
51-
'PerformanceEventTiming',
52-
() => require('../webapis/performance/EventTiming').PerformanceEventTiming,
65+
'PerformanceObserver',
66+
() =>
67+
require('../webapis/performance/PerformanceObserver').PerformanceObserver,
5368
);
5469

5570
polyfillGlobal(
56-
'PerformanceResourceTiming',
71+
'PerformanceObserverEntryList',
5772
() =>
58-
require('../webapis/performance/ResourceTiming')
59-
.PerformanceResourceTiming,
73+
require('../webapis/performance/PerformanceObserver')
74+
.PerformanceObserverEntryList_public,
6075
);
6176

6277
polyfillGlobal(
63-
'TaskAttributionTiming',
64-
() => require('../webapis/performance/LongTasks').TaskAttributionTiming,
78+
'PerformanceResourceTiming',
79+
() =>
80+
require('../webapis/performance/ResourceTiming')
81+
.PerformanceResourceTiming_public,
6582
);
6683

6784
polyfillGlobal(
68-
'PerformanceLongTaskTiming',
69-
() => require('../webapis/performance/LongTasks').PerformanceLongTaskTiming,
85+
'TaskAttributionTiming',
86+
() =>
87+
require('../webapis/performance/LongTasks').TaskAttributionTiming_public,
7088
);
7189
}

packages/react-native/src/private/webapis/performance/EventTiming.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ export class PerformanceEventTiming extends PerformanceEntry {
7070
}
7171
}
7272

73+
export const PerformanceEventTiming_public: typeof PerformanceEventTiming =
74+
/* eslint-disable no-shadow */
75+
// $FlowExpectedError[incompatible-type]
76+
function PerformanceEventTiming() {
77+
throw new TypeError(
78+
"Failed to construct 'PerformanceEventTiming': Illegal constructor",
79+
);
80+
};
81+
82+
// $FlowExpectedError[prop-missing]
83+
PerformanceEventTiming_public.prototype = PerformanceEventTiming.prototype;
84+
7385
type EventCountsForEachCallbackType =
7486
| (() => void)
7587
| ((value: number) => void)
@@ -134,3 +146,15 @@ export class EventCounts {
134146
return getCachedEventCounts().values();
135147
}
136148
}
149+
150+
export const EventCounts_public: typeof EventCounts =
151+
/* eslint-disable no-shadow */
152+
// $FlowExpectedError[incompatible-type]
153+
function EventCounts() {
154+
throw new TypeError(
155+
"Failed to construct 'EventCounts': Illegal constructor",
156+
);
157+
};
158+
159+
// $FlowExpectedError[prop-missing]
160+
EventCounts_public.prototype = EventCounts.prototype;

packages/react-native/src/private/webapis/performance/LongTasks.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ export type PerformanceLongTaskTimingJSON = {
2424

2525
export class TaskAttributionTiming extends PerformanceEntry {}
2626

27+
export const TaskAttributionTiming_public: typeof TaskAttributionTiming =
28+
/* eslint-disable no-shadow */
29+
// $FlowExpectedError[incompatible-type]
30+
function TaskAttributionTiming() {
31+
throw new TypeError(
32+
"Failed to construct 'TaskAttributionTiming': Illegal constructor",
33+
);
34+
};
35+
36+
// $FlowExpectedError[prop-missing]
37+
TaskAttributionTiming_public.prototype = TaskAttributionTiming.prototype;
38+
2739
const EMPTY_ATTRIBUTION: $ReadOnlyArray<TaskAttributionTiming> =
2840
Object.preventExtensions([]);
2941

@@ -45,3 +57,16 @@ export class PerformanceLongTaskTiming extends PerformanceEntry {
4557
};
4658
}
4759
}
60+
61+
export const PerformanceLongTaskTiming_public: typeof PerformanceLongTaskTiming =
62+
/* eslint-disable no-shadow */
63+
// $FlowExpectedError[incompatible-type]
64+
function PerformanceLongTaskTiming() {
65+
throw new TypeError(
66+
"Failed to construct 'PerformanceLongTaskTiming': Illegal constructor",
67+
);
68+
};
69+
70+
// $FlowExpectedError[prop-missing]
71+
PerformanceLongTaskTiming_public.prototype =
72+
PerformanceLongTaskTiming.prototype;

packages/react-native/src/private/webapis/performance/Performance.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,4 +443,16 @@ export default class Performance {
443443
}
444444
}
445445

446+
export const Performance_public: typeof Performance =
447+
/* eslint-disable no-shadow */
448+
// $FlowExpectedError[incompatible-type]
449+
function Performance() {
450+
throw new TypeError(
451+
"Failed to construct 'Performance': Illegal constructor",
452+
);
453+
};
454+
455+
// $FlowExpectedError[prop-missing]
456+
Performance_public.prototype = Performance.prototype;
457+
446458
setPlatformObject(Performance);

packages/react-native/src/private/webapis/performance/PerformanceEntry.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,18 @@ export class PerformanceEntry {
7777
}
7878
}
7979

80+
export const PerformanceEntry_public: typeof PerformanceEntry =
81+
/* eslint-disable no-shadow */
82+
// $FlowExpectedError[incompatible-type]
83+
function PerformanceEntry() {
84+
throw new TypeError(
85+
"Failed to construct 'PerformanceEntry': Illegal constructor",
86+
);
87+
};
88+
89+
// $FlowExpectedError[prop-missing]
90+
PerformanceEntry_public.prototype = PerformanceEntry.prototype;
91+
8092
setPlatformObject(PerformanceEntry);
8193

8294
export type PerformanceEntryList = $ReadOnlyArray<PerformanceEntry>;

packages/react-native/src/private/webapis/performance/PerformanceObserver.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,19 @@ export class PerformanceObserverEntryList {
5757
}
5858
}
5959

60+
export const PerformanceObserverEntryList_public: typeof PerformanceObserverEntryList =
61+
/* eslint-disable no-shadow */
62+
// $FlowExpectedError[incompatible-type]
63+
function PerformanceObserverEntryList() {
64+
throw new TypeError(
65+
"Failed to construct 'PerformanceObserverEntryList': Illegal constructor",
66+
);
67+
};
68+
69+
// $FlowExpectedError[prop-missing]
70+
PerformanceObserverEntryList_public.prototype =
71+
PerformanceObserverEntryList.prototype;
72+
6073
export type PerformanceObserverCallbackOptions = {
6174
droppedEntriesCount: number,
6275
};

packages/react-native/src/private/webapis/performance/ResourceTiming.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,16 @@ export class PerformanceResourceTiming extends PerformanceEntry {
104104
};
105105
}
106106
}
107+
108+
export const PerformanceResourceTiming_public: typeof PerformanceResourceTiming =
109+
/* eslint-disable no-shadow */
110+
// $FlowExpectedError[incompatible-type]
111+
function PerformanceResourceTiming() {
112+
throw new TypeError(
113+
"Failed to construct 'PerformanceResourceTiming': Illegal constructor",
114+
);
115+
};
116+
117+
// $FlowExpectedError[prop-missing]
118+
PerformanceResourceTiming_public.prototype =
119+
PerformanceResourceTiming.prototype;

packages/react-native/src/private/webapis/performance/UserTiming.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,15 @@ export const PerformanceMeasure: typeof PerformanceMeasureTemplate =
116116

117117
// $FlowExpectedError[prop-missing]
118118
PerformanceMeasure.prototype = PerformanceMeasureTemplate.prototype;
119+
120+
export const PerformanceMeasure_public: typeof PerformanceMeasure =
121+
/* eslint-disable no-shadow */
122+
// $FlowExpectedError[incompatible-type]
123+
function PerformanceMeasure() {
124+
throw new TypeError(
125+
"Failed to construct 'PerformanceMeasure': Illegal constructor",
126+
);
127+
};
128+
129+
// $FlowExpectedError[prop-missing]
130+
PerformanceMeasure_public.prototype = PerformanceMeasure.prototype;

packages/react-native/src/private/webapis/performance/__tests__/EventTimingAPI-itest.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,21 @@ describe('Event Timing API', () => {
244244
expect([...performance.eventCounts.values()]).toEqual([1, 1, 3]);
245245
});
246246

247+
it('does NOT allow creating instances of PerformanceEventTiming directly', () => {
248+
expect(() => {
249+
return new PerformanceEventTiming();
250+
}).toThrow(
251+
"Failed to construct 'PerformanceEventTiming': Illegal constructor",
252+
);
253+
});
254+
255+
it('does NOT allow creating instances of EventCounts directly', () => {
256+
expect(() => {
257+
// $FlowExpectedError[cannot-resolve-name]
258+
return new EventCounts();
259+
}).toThrow("Failed to construct 'EventCounts': Illegal constructor");
260+
});
261+
247262
describe('durationThreshold option', () => {
248263
it('works when used with `type`', () => {
249264
const callback = jest.fn();

packages/react-native/src/private/webapis/performance/__tests__/LongTasksAPI-itest.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,20 @@ describe('LongTasks API', () => {
191191
expect(entry.attribution).toEqual([]);
192192
});
193193
});
194+
195+
it('does NOT allow creating instances of PerformanceLongTaskTiming directly', () => {
196+
expect(() => {
197+
return new PerformanceLongTaskTiming();
198+
}).toThrow(
199+
"Failed to construct 'PerformanceLongTaskTiming': Illegal constructor",
200+
);
201+
});
202+
203+
it('does NOT allow creating instances of TaskAttributionTiming directly', () => {
204+
expect(() => {
205+
return new TaskAttributionTiming();
206+
}).toThrow(
207+
"Failed to construct 'TaskAttributionTiming': Illegal constructor",
208+
);
209+
});
194210
});

0 commit comments

Comments
 (0)