Skip to content

Commit ea73a66

Browse files
rshestfacebook-github-bot
authored andcommitted
Scaffolding for the PerformanceObserver TurboModule (C++ side) (facebook#35226)
Summary: Pull Request resolved: facebook#35226 Changelog: [Internal] This adds scaffolding for the C++ side of NativePerformanceObserver module. Thanks to christophpurrer for helping set this up, as this is the first one of this kind inside core/OSS. Reviewed By: rubennorte Differential Revision: D41028555 fbshipit-source-id: 4acf0e71a254a42044cbbe5f94f40938342c6aa2
1 parent ea1d729 commit ea73a66

File tree

6 files changed

+200
-19
lines changed

6 files changed

+200
-19
lines changed

BUCK

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ load(
1010
)
1111
load(
1212
"//tools/build_defs/oss:rn_defs.bzl",
13+
"ANDROID",
14+
"APPLE",
15+
"CXX",
1316
"HERMES_BYTECODE_VERSION",
1417
"IOS",
1518
"RCT_IMAGE_DATA_DECODER_SOCKET",
@@ -1453,3 +1456,28 @@ rn_xplat_cxx_library2(
14531456
"//fbobjc/VendorLib/react-native-maps:react-native-maps",
14541457
],
14551458
)
1459+
1460+
rn_xplat_cxx_library2(
1461+
name = "RCTWebPerformance",
1462+
srcs = glob([
1463+
"Libraries/WebPerformance/**/*.cpp",
1464+
]),
1465+
header_namespace = "",
1466+
exported_headers = subdir_glob(
1467+
[("Libraries/WebPerformance", "*.h")],
1468+
prefix = "RCTWebPerformance",
1469+
),
1470+
fbandroid_compiler_flags = [
1471+
"-fexceptions",
1472+
"-frtti",
1473+
],
1474+
labels = [
1475+
"depslint_never_remove",
1476+
"pfh:ReactNative_CommonInfrastructurePlaceholder",
1477+
],
1478+
platforms = (ANDROID, APPLE, CXX),
1479+
visibility = ["PUBLIC"],
1480+
deps = [
1481+
":FBReactNativeSpecJSI",
1482+
],
1483+
)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include "NativePerformanceObserver.h"
9+
#include <glog/logging.h>
10+
11+
namespace facebook::react {
12+
13+
NativePerformanceObserver::NativePerformanceObserver(
14+
std::shared_ptr<CallInvoker> jsInvoker)
15+
: NativePerformanceObserverCxxSpec(std::move(jsInvoker)) {}
16+
17+
void NativePerformanceObserver::startReporting(
18+
jsi::Runtime &rt,
19+
std::string entryType) {
20+
LOG(INFO) << "Started reporting perf entry type: " << entryType;
21+
}
22+
23+
void NativePerformanceObserver::stopReporting(
24+
jsi::Runtime &rt,
25+
std::string entryType) {
26+
LOG(INFO) << "Stopped reporting perf entry type: " << entryType;
27+
}
28+
29+
std::vector<RawPerformanceEntry> NativePerformanceObserver::getPendingEntries(
30+
jsi::Runtime &rt) {
31+
return std::vector<RawPerformanceEntry>{};
32+
}
33+
34+
void NativePerformanceObserver::setOnPerformanceEntryCallback(
35+
jsi::Runtime &rt,
36+
std::optional<AsyncCallback<>> callback) {
37+
callback_ = callback;
38+
LOG(INFO) << "setOnPerformanceEntryCallback: "
39+
<< (callback ? "non-empty" : "empty");
40+
}
41+
42+
} // namespace facebook::react
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <FBReactNativeSpec/FBReactNativeSpecJSI.h>
11+
#include <functional>
12+
#include <memory>
13+
#include <optional>
14+
#include <string>
15+
#include <vector>
16+
#include "NativePerformanceObserver_RawPerformanceEntry.h"
17+
18+
namespace facebook::react {
19+
20+
class NativePerformanceObserver
21+
: public NativePerformanceObserverCxxSpec<NativePerformanceObserver>,
22+
std::enable_shared_from_this<NativePerformanceObserver> {
23+
public:
24+
NativePerformanceObserver(std::shared_ptr<CallInvoker> jsInvoker);
25+
26+
void startReporting(jsi::Runtime &rt, std::string entryType);
27+
28+
void stopReporting(jsi::Runtime &rt, std::string entryType);
29+
30+
std::vector<RawPerformanceEntry> getPendingEntries(jsi::Runtime &rt);
31+
32+
void setOnPerformanceEntryCallback(
33+
jsi::Runtime &rt,
34+
std::optional<AsyncCallback<>> callback);
35+
36+
private:
37+
std::optional<AsyncCallback<>> callback_;
38+
};
39+
40+
} // namespace facebook::react

Libraries/NativeModules/specs/NativePerformanceObserverCxx.js renamed to Libraries/WebPerformance/NativePerformanceObserver.js

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@
88
* @format
99
*/
1010

11-
import type {TurboModule} from '../../TurboModule/RCTExport';
11+
import type {TurboModule} from '../TurboModule/RCTExport';
1212

13-
import * as TurboModuleRegistry from '../../TurboModule/TurboModuleRegistry';
14-
15-
export type RawTimeStamp = number;
13+
import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';
1614

1715
export const RawPerformanceEntryTypeValues = {
1816
UNDEFINED: 0,
@@ -23,22 +21,21 @@ export type RawPerformanceEntryType = number;
2321
export type RawPerformanceEntry = $ReadOnly<{
2422
name: string,
2523
entryType: RawPerformanceEntryType,
26-
startTime: RawTimeStamp,
24+
startTime: number,
2725
duration: number,
28-
2926
// For "event" entries only:
30-
processingStart?: RawTimeStamp,
31-
processingEnd?: RawTimeStamp,
32-
interactionId?: RawTimeStamp,
27+
processingStart?: number,
28+
processingEnd?: number,
29+
interactionId?: number,
3330
}>;
3431

35-
export type RawPerformanceEntryList = $ReadOnlyArray<RawPerformanceEntry>;
36-
3732
export interface Spec extends TurboModule {
3833
+startReporting: (entryType: string) => void;
3934
+stopReporting: (entryType: string) => void;
40-
+getPendingEntries: () => RawPerformanceEntryList;
35+
+getPendingEntries: () => $ReadOnlyArray<RawPerformanceEntry>;
4136
+setOnPerformanceEntryCallback: (callback?: () => void) => void;
4237
}
4338

44-
export default (TurboModuleRegistry.get<Spec>('PerformanceObserver'): ?Spec);
39+
export default (TurboModuleRegistry.get<Spec>(
40+
'NativePerformanceObserverCxx',
41+
): ?Spec);
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <react/bridging/Bridging.h>
11+
#include <optional>
12+
#include <string>
13+
14+
namespace facebook::react {
15+
16+
struct RawPerformanceEntry {
17+
std::string name;
18+
int32_t entryType;
19+
double startTime;
20+
double duration;
21+
// For "event" entries only:
22+
std::optional<double> processingStart;
23+
std::optional<double> processingEnd;
24+
std::optional<double> interactionId;
25+
};
26+
27+
template <>
28+
struct Bridging<RawPerformanceEntry> {
29+
static RawPerformanceEntry fromJs(
30+
jsi::Runtime &rt,
31+
const jsi::Object &value,
32+
const std::shared_ptr<CallInvoker> &jsInvoker) {
33+
RawPerformanceEntry result{
34+
bridging::fromJs<std::string>(
35+
rt, value.getProperty(rt, "name"), jsInvoker),
36+
bridging::fromJs<int32_t>(
37+
rt, value.getProperty(rt, "entryType"), jsInvoker),
38+
bridging::fromJs<double>(
39+
rt, value.getProperty(rt, "startTime"), jsInvoker),
40+
bridging::fromJs<double>(
41+
rt, value.getProperty(rt, "duration"), jsInvoker),
42+
bridging::fromJs<std::optional<double>>(
43+
rt, value.getProperty(rt, "processingStart"), jsInvoker),
44+
bridging::fromJs<std::optional<double>>(
45+
rt, value.getProperty(rt, "processingEnd"), jsInvoker),
46+
bridging::fromJs<std::optional<double>>(
47+
rt, value.getProperty(rt, "interactionId"), jsInvoker),
48+
};
49+
return result;
50+
}
51+
52+
static jsi::Object toJs(jsi::Runtime &rt, const RawPerformanceEntry &value) {
53+
auto result = facebook::jsi::Object(rt);
54+
result.setProperty(rt, "name", bridging::toJs(rt, value.name));
55+
result.setProperty(rt, "entryType", bridging::toJs(rt, value.entryType));
56+
result.setProperty(rt, "startTime", bridging::toJs(rt, value.startTime));
57+
result.setProperty(rt, "duration", bridging::toJs(rt, value.duration));
58+
if (value.processingStart) {
59+
result.setProperty(
60+
rt,
61+
"processingStart",
62+
bridging::toJs(rt, value.processingStart.value()));
63+
}
64+
if (value.processingEnd) {
65+
result.setProperty(
66+
rt, "processingEnd", bridging::toJs(rt, value.processingEnd.value()));
67+
}
68+
if (value.interactionId) {
69+
result.setProperty(
70+
rt, "interactionId", bridging::toJs(rt, value.interactionId.value()));
71+
}
72+
return result;
73+
}
74+
};
75+
76+
} // namespace facebook::react

Libraries/WebPerformance/PerformanceObserver.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@
1010

1111
import type {
1212
RawPerformanceEntry,
13-
RawPerformanceEntryList,
1413
RawPerformanceEntryType,
15-
} from '../NativeModules/specs/NativePerformanceObserverCxx';
14+
} from './NativePerformanceObserver';
1615

17-
import NativePerformanceObserver from '../NativeModules/specs/NativePerformanceObserverCxx';
1816
import warnOnce from '../Utilities/warnOnce';
17+
import NativePerformanceObserver from './NativePerformanceObserver';
1918

2019
export type HighResTimeStamp = number;
2120
// TODO: Extend once new types (such as event) are supported.
@@ -195,7 +194,7 @@ export default class PerformanceObserver {
195194
});
196195
_observers.delete(this);
197196
if (_observers.size === 0) {
198-
NativePerformanceObserver.setOnPerformanceEntryCallback();
197+
NativePerformanceObserver.setOnPerformanceEntryCallback(undefined);
199198
_onPerformanceEntryCallbackIsSet = false;
200199
}
201200
}
@@ -210,8 +209,7 @@ function onPerformanceEntry() {
210209
if (!NativePerformanceObserver) {
211210
return;
212211
}
213-
const rawEntries: RawPerformanceEntryList =
214-
NativePerformanceObserver.getPendingEntries();
212+
const rawEntries = NativePerformanceObserver.getPendingEntries();
215213
const entries = rawEntries.map(rawToPerformanceEntry);
216214
_observers.forEach(observer => {
217215
const entriesForObserver: PerformanceEntryList = entries.filter(entry =>

0 commit comments

Comments
 (0)