Skip to content

Commit b5e9c09

Browse files
dannysufacebook-github-bot
authored andcommitted
Support captureNumericValue for HeapProfiler domain
Summary: Original Author: [email protected] Original Git: 05ee71f Original Reviewed By: mattbfb Original Revision: D60871373 Adds support for the `captureNumericValue` flag for `HeapProfiler.takeHeapSnapshot` and `HeapProfiler.stopTrackingHeapObjects` of the CDP protocol. Reviewed By: lavenzg Differential Revision: D61574205 fbshipit-source-id: c4ebca21e0874d65d61bf03431185c0bf6d810b5
1 parent 78234e5 commit b5e9c09

File tree

3 files changed

+81
-10
lines changed

3 files changed

+81
-10
lines changed

API/hermes/cdp/HeapProfilerDomainAgent.cpp

+14-4
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,20 @@ HeapProfilerDomainAgent::~HeapProfilerDomainAgent() {
6464
void HeapProfilerDomainAgent::takeHeapSnapshot(
6565
const m::heapProfiler::TakeHeapSnapshotRequest &req) {
6666
#ifdef HERMES_MEMORY_INSTRUMENTATION
67-
sendSnapshot(req.id, req.reportProgress && *req.reportProgress);
67+
sendSnapshot(
68+
req.id,
69+
req.reportProgress && *req.reportProgress,
70+
req.captureNumericValue && *req.captureNumericValue);
6871
#else
6972
sendResponseToClient(m::makeErrorResponse(
7073
req.id, m::ErrorCode::InvalidRequest, kNoInstrumentation));
7174
#endif // HERMES_MEMORY_INSTRUMENTATION
7275
}
7376

74-
void HeapProfilerDomainAgent::sendSnapshot(int reqId, bool reportProgress) {
77+
void HeapProfilerDomainAgent::sendSnapshot(
78+
int reqId,
79+
bool reportProgress,
80+
bool captureNumericValue) {
7581
if (reportProgress) {
7682
// A progress notification with finished = true indicates the
7783
// snapshot has been captured and is ready to be sent. Our
@@ -100,7 +106,8 @@ void HeapProfilerDomainAgent::sendSnapshot(int reqId, bool reportProgress) {
100106
return true;
101107
});
102108

103-
runtime_.instrumentation().createSnapshotToStream(cos);
109+
runtime_.instrumentation().createSnapshotToStream(
110+
cos, {captureNumericValue});
104111
}
105112
sendResponseToClient(m::makeOkResponse(reqId));
106113
}
@@ -238,7 +245,10 @@ void HeapProfilerDomainAgent::stopTrackingHeapObjects(
238245

239246
runtime_.instrumentation().stopTrackingHeapObjectStackTraces();
240247
trackingHeapObjectStackTraces_ = false;
241-
sendSnapshot(req.id, req.reportProgress && *req.reportProgress);
248+
sendSnapshot(
249+
req.id,
250+
req.reportProgress && *req.reportProgress,
251+
req.captureNumericValue && *req.captureNumericValue);
242252
#else
243253
sendResponseToClient(m::makeErrorResponse(
244254
req.id, m::ErrorCode::InvalidRequest, kNoInstrumentation));

API/hermes/cdp/HeapProfilerDomainAgent.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class HeapProfilerDomainAgent : public DomainAgent {
5555
void stopSampling(const m::heapProfiler::StopSamplingRequest &req);
5656

5757
private:
58-
void sendSnapshot(int reqId, bool reportProgress);
58+
void sendSnapshot(int reqId, bool reportProgress, bool captureNumericValue);
5959

6060
HermesRuntime &runtime_;
6161

unittests/API/CDPAgentTest.cpp

+66-5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <hermes/CompileJS.h>
1818
#include <hermes/Support/JSONEmitter.h>
1919
#include <hermes/Support/SerialExecutor.h>
20+
#include <hermes/VM/HeapSnapshot.h>
2021
#include <hermes/cdp/CDPAgent.h>
2122
#include <hermes/cdp/CDPDebugAPI.h>
2223
#include <hermes/cdp/JSONValueInterfaces.h>
@@ -149,7 +150,8 @@ class CDPAgentTest : public ::testing::Test {
149150
/// \p messageID specifies the id of the snapshot request.
150151
/// \p ignoreTrackingNotifications indicates whether lastSeenObjectId and
151152
/// heapStatsUpdate notifications are tolerated before the snapshot arrives.
152-
void expectHeapSnapshot(
153+
/// \return the completed heap snapshot JSON object
154+
JSONObject *expectHeapSnapshot(
153155
int messageID,
154156
bool ignoreTrackingNotifications = false);
155157

@@ -381,7 +383,7 @@ void CDPAgentTest::expectErrorMessageContaining(
381383
ASSERT_NE(errorMessage.find(substring), std::string::npos);
382384
}
383385

384-
void CDPAgentTest::expectHeapSnapshot(
386+
JSONObject *CDPAgentTest::expectHeapSnapshot(
385387
int messageID,
386388
bool ignoreTrackingNotifications) {
387389
// Expect chunk notifications until the snapshot object is complete. Fail if
@@ -398,12 +400,14 @@ void CDPAgentTest::expectHeapSnapshot(
398400
continue;
399401
}
400402

401-
ASSERT_EQ(method, "HeapProfiler.addHeapSnapshotChunk");
403+
EXPECT_EQ(method, "HeapProfiler.addHeapSnapshotChunk");
402404
snapshot << jsonScope_.getString(note, {"params", "chunk"});
403405
} while (!jsonScope_.tryParseObject(snapshot.str()).has_value());
404406

405407
// Expect the snapshot response after all chunks have been received.
406408
ensureOkResponse(waitForMessage(), messageID);
409+
410+
return jsonScope_.parseObject(snapshot.str());
407411
}
408412

409413
jsi::Value CDPAgentTest::shouldStop(
@@ -3393,7 +3397,7 @@ TEST_F(CDPAgentTest, RuntimeValidatesExecutionContextId) {
33933397
expectErrorMessageContaining(kExecutionContextSubstring, msgId++);
33943398
}
33953399

3396-
TEST_F(CDPAgentTest, HeapProfilerSnapshot) {
3400+
TEST_F(CDPAgentTest, HeapProfilerSnapshotCaptureNumeric) {
33973401
int msgId = 1;
33983402

33993403
#ifdef HERMES_MEMORY_INSTRUMENTATION
@@ -3410,8 +3414,65 @@ TEST_F(CDPAgentTest, HeapProfilerSnapshot) {
34103414
sendRequest(
34113415
"HeapProfiler.takeHeapSnapshot", msgId, [](::hermes::JSONEmitter &json) {
34123416
json.emitKeyValue("reportProgress", false);
3417+
json.emitKeyValue("captureNumericValue", true);
34133418
});
3414-
expectHeapSnapshot(msgId);
3419+
JSONObject *root = expectHeapSnapshot(msgId);
3420+
const JSONArray &nodes = *llvh::cast<JSONArray>(root->at("nodes"));
3421+
3422+
bool found = false;
3423+
auto nodesIt = nodes.begin();
3424+
const auto nodesEnd = nodes.end();
3425+
while (nodesIt != nodesEnd) {
3426+
auto type = static_cast<::hermes::vm::HeapSnapshot::NodeType>(
3427+
static_cast<unsigned>(llvh::cast<JSONNumber>(*nodesIt)->getValue()));
3428+
if (type == ::hermes::vm::HeapSnapshot::NodeType::Number) {
3429+
found = true;
3430+
}
3431+
nodesIt += ::hermes::vm::HeapSnapshot::V8_SNAPSHOT_NODE_FIELD_COUNT;
3432+
}
3433+
EXPECT_TRUE(found);
3434+
3435+
// Expect no more chunks are pending.
3436+
expectNothing();
3437+
#else
3438+
sendRequest(
3439+
"HeapProfiler.takeHeapSnapshot", msgId, [](::hermes::JSONEmitter &json) {
3440+
json.emitKeyValue("reportProgress", false);
3441+
json.emitKeyValue("captureNumericValue", true);
3442+
});
3443+
expectErrorMessageContaining(kMemoryInstrumentationSubstring, msgId);
3444+
#endif // HERMES_MEMORY_INSTRUMENTATION
3445+
}
3446+
3447+
TEST_F(CDPAgentTest, HeapProfilerSnapshotNoNumeric) {
3448+
int msgId = 1;
3449+
3450+
#ifdef HERMES_MEMORY_INSTRUMENTATION
3451+
auto setStopFlag = llvh::make_scope_exit([this] {
3452+
// break out of loop
3453+
stopFlag_.store(true);
3454+
});
3455+
3456+
scheduleScript(R"(
3457+
while(!shouldStop());
3458+
)");
3459+
3460+
// Request a heap snapshot and expect it to arrive.
3461+
// Expect captureNumericValue to default to false when not provided.
3462+
sendRequest(
3463+
"HeapProfiler.takeHeapSnapshot", msgId, [](::hermes::JSONEmitter &json) {
3464+
json.emitKeyValue("reportProgress", false);
3465+
});
3466+
JSONObject *root = expectHeapSnapshot(msgId);
3467+
const JSONArray &nodes = *llvh::cast<JSONArray>(root->at("nodes"));
3468+
auto nodesIt = nodes.begin();
3469+
const auto nodesEnd = nodes.end();
3470+
while (nodesIt != nodesEnd) {
3471+
auto type = static_cast<::hermes::vm::HeapSnapshot::NodeType>(
3472+
static_cast<unsigned>(llvh::cast<JSONNumber>(*nodesIt)->getValue()));
3473+
EXPECT_NE(type, ::hermes::vm::HeapSnapshot::NodeType::Number);
3474+
nodesIt += ::hermes::vm::HeapSnapshot::V8_SNAPSHOT_NODE_FIELD_COUNT;
3475+
}
34153476

34163477
// Expect no more chunks are pending.
34173478
expectNothing();

0 commit comments

Comments
 (0)