Skip to content

Commit

Permalink
add --hermes-coverage option
Browse files Browse the repository at this point in the history
Summary: adds a --hermes-coverage option used to symbolicate Hermes coverage traces.

Reviewed By: motiz88

Differential Revision: D26050063

fbshipit-source-id: aa4010689578744996349daa3d4aadb8826d7a5f
  • Loading branch information
GijsWeterings authored and facebook-github-bot committed Feb 10, 2021
1 parent 9ae2e00 commit fc3b6b3
Show file tree
Hide file tree
Showing 5 changed files with 240 additions and 86 deletions.
59 changes: 57 additions & 2 deletions packages/metro-symbolicate/src/Symbolication.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
* @format
*/

'use strict';

const SourceMetadataMapConsumer = require('./SourceMetadataMapConsumer');

const fs = require('fs');
Expand Down Expand Up @@ -81,6 +79,15 @@ type HermesMinidumpStackFrame = $ReadOnly<{|
SourceLocation?: string,
|}>;

type HermesCoverageInfo = {
+executedFunctions: $ReadOnlyArray<HermesCoverageStackFrame>,
};

type HermesCoverageStackFrame = $ReadOnly<{
SegmentID: number,
VirtualOffset: number,
}>;

type NativeCodeStackFrame = $ReadOnly<{|
NativeCode: true,
StackFrameRegOffs: string,
Expand Down Expand Up @@ -439,6 +446,32 @@ class SymbolicationContext<ModuleIdsT> {
return snapshotData;
}

/*
* Symbolicates the JavaScript stack trace extracted from the coverage information
* produced by HermesRuntime::getExecutedFunctions.
*/
symbolicateHermesCoverageTrace(
coverageInfo: HermesCoverageInfo,
): SymbolicatedStackTrace {
const symbolicatedTrace = [];
const {executedFunctions} = coverageInfo;

if (executedFunctions != null) {
for (const stackItem of executedFunctions) {
const {SegmentID, VirtualOffset: localOffset} = stackItem;
const generatedLine = SegmentID + this.options.inputLineStart;
const generatedColumn = localOffset + this.options.inputColumnStart;

const originalPosition = this.getOriginalPositionDetailsFor(
generatedLine,
generatedColumn,
);
symbolicatedTrace.push(originalPosition);
}
}
return symbolicatedTrace;
}

/*
* An internal helper function similar to getOriginalPositionFor. This one
* returns both `name` and `functionName` fields so callers can distinguish the
Expand Down Expand Up @@ -576,6 +609,28 @@ class SingleMapSymbolicationContext extends SymbolicationContext<SingleMapModule
return symbolicatedTrace;
}

symbolicateHermesCoverageTrace(
coverageInfo: HermesCoverageInfo,
): SymbolicatedStackTrace {
const symbolicatedTrace = [];
const {executedFunctions} = coverageInfo;

if (executedFunctions != null) {
for (const stackItem of executedFunctions) {
const {SegmentID, VirtualOffset: localOffset} = stackItem;
const generatedLine = SegmentID + this.options.inputLineStart;
const generatedColumn = localOffset + this.options.inputColumnStart;

const originalPosition = this.getOriginalPositionDetailsFor(
generatedLine,
generatedColumn,
);
symbolicatedTrace.push(originalPosition);
}
}
return symbolicatedTrace;
}

/*
* An internal helper function similar to getOriginalPositionFor. This one
* returns both `name` and `functionName` fields so callers can distinguish the
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"executedFunctions": [
{
"SegmentID": 0,
"VirtualOffset": 23819
},
{
"SegmentID": 0,
"VirtualOffset": 22579
}
]
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`coverage option symbolicating a coverage stack trace CJS 1`] = `
Array [
Object {
"column": 2,
"functionName": "<global>",
"line": 16,
"name": null,
"source": "/js/react-native-github/Libraries/Utilities/createPerformanceLogger.js",
},
Object {
"column": 2,
"functionName": "<global>",
"line": 25,
"name": null,
"source": "/js/RKJSModules/Libraries/MobileConfig/MobileConfig.js",
},
]
`;

exports[`directory context does not read source maps outside the root dir, with relative or absolute paths 1`] = `
"<testDir>/__fixtures__/testfile.js:1:null
../testfile.js:1:null
Expand All @@ -20,7 +39,7 @@ exports[`directory context symbolicating a stack trace with absolute paths 1`] =
"
`;
exports[`symbolicating a hermes stack trace 1`] = `
exports[`hermes-crash option symbolicating a hermes stack trace 1`] = `
Array [
Object {
"column": 21,
Expand Down Expand Up @@ -63,7 +82,7 @@ Array [
]
`;
exports[`symbolicating a hermes stack trace CJS 1`] = `
exports[`hermes-crash option symbolicating a hermes stack trace CJS 1`] = `
Array [
Object {
"column": 36,
Expand Down Expand Up @@ -99,7 +118,7 @@ Array [
]
`;
exports[`symbolicating a hermes stack trace CJS with SegmentID 1`] = `
exports[`hermes-crash option symbolicating a hermes stack trace CJS with SegmentID 1`] = `
Array [
Object {
"column": 36,
Expand Down
173 changes: 112 additions & 61 deletions packages/metro-symbolicate/src/__tests__/symbolicate-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,71 +62,122 @@ const TESTFILE_RAM_MAP = resolve('testfile.ram.js.map');
const HERMES_MAP = resolve('hermes.js.hbc.map');
const HERMES_MAP_CJS = resolve('hermescjs.js.hbc.map');

test('symbolicating a hermes stack trace', async () => {
const output = JSON.parse(
await execute(
[HERMES_MAP, '--hermes-crash'],
read('hermesStackTrace.json'),
),
);
expect(output).toMatchSnapshot();
});
describe('hermes-crash option', () => {
test('symbolicating a hermes stack trace', async () => {
const output = JSON.parse(
await execute(
[HERMES_MAP, '--hermes-crash'],
read('hermesStackTrace.json'),
),
);
expect(output).toMatchSnapshot();
});

test('symbolicating a hermes stack trace with input-line-start and input-column-start', async () => {
const output0Based = JSON.parse(
await execute(
[
HERMES_MAP,
'--hermes-crash',
'--input-line-start',
'0',
'--input-column-start',
'0',
],
read('hermesStackTrace.json'),
),
);
const output1Based = JSON.parse(
await execute(
[
HERMES_MAP,
'--hermes-crash',
'--input-line-start',
'1',
'--input-column-start',
'1',
],
read('hermesStackTrace.json'),
),
);
const outputNoFlag = JSON.parse(
await execute(
[HERMES_MAP, '--hermes-crash'],
read('hermesStackTrace.json'),
),
);
expect(outputNoFlag).toMatchObject(output0Based);
expect(outputNoFlag).toMatchObject(output1Based);
});
test('symbolicating a hermes stack trace with input-line-start and input-column-start', async () => {
const output0Based = JSON.parse(
await execute(
[
HERMES_MAP,
'--hermes-crash',
'--input-line-start',
'0',
'--input-column-start',
'0',
],
read('hermesStackTrace.json'),
),
);
const output1Based = JSON.parse(
await execute(
[
HERMES_MAP,
'--hermes-crash',
'--input-line-start',
'1',
'--input-column-start',
'1',
],
read('hermesStackTrace.json'),
),
);
const outputNoFlag = JSON.parse(
await execute(
[HERMES_MAP, '--hermes-crash'],
read('hermesStackTrace.json'),
),
);
expect(outputNoFlag).toMatchObject(output0Based);
expect(outputNoFlag).toMatchObject(output1Based);
});

test('symbolicating a hermes stack trace CJS', async () => {
const output = JSON.parse(
await execute(
[HERMES_MAP_CJS, '--hermes-crash'],
read('hermesStackTraceCJS.json'),
),
);
expect(output).toMatchSnapshot();
test('symbolicating a hermes stack trace CJS', async () => {
const output = JSON.parse(
await execute(
[HERMES_MAP_CJS, '--hermes-crash'],
read('hermesStackTraceCJS.json'),
),
);
expect(output).toMatchSnapshot();
});

test('symbolicating a hermes stack trace CJS with SegmentID', async () => {
const output = JSON.parse(
await execute(
[HERMES_MAP_CJS, '--hermes-crash'],
read('hermesStackTraceCJS-SegmentID.json'),
),
);
expect(output).toMatchSnapshot();
});
});

test('symbolicating a hermes stack trace CJS with SegmentID', async () => {
const output = JSON.parse(
await execute(
[HERMES_MAP_CJS, '--hermes-crash'],
read('hermesStackTraceCJS-SegmentID.json'),
),
);
expect(output).toMatchSnapshot();
describe('coverage option', () => {
test('ignores input-line-start and input-column-start', async () => {
const output0Based = JSON.parse(
await execute(
[
HERMES_MAP_CJS,
'--hermes-coverage',
'--input-line-start',
'0',
'--input-column-start',
'0',
],
read('coverageStackTraceCJS.json'),
),
);
const output1Based = JSON.parse(
await execute(
[
HERMES_MAP_CJS,
'--hermes-coverage',
'--input-line-start',
'1',
'--input-column-start',
'1',
],
read('coverageStackTraceCJS.json'),
),
);
const outputNoFlag = JSON.parse(
await execute(
[HERMES_MAP_CJS, '--hermes-coverage'],
read('coverageStackTraceCJS.json'),
),
);
expect(outputNoFlag).toMatchObject(output0Based);
expect(outputNoFlag).toMatchObject(output1Based);
});

test('symbolicating a coverage stack trace CJS', async () => {
const output = JSON.parse(
await execute(
[HERMES_MAP_CJS, '--hermes-coverage'],
read('coverageStackTraceCJS.json'),
),
);
expect(output).toMatchSnapshot();
});
});

test('symbolicating a stack trace', async () =>
Expand Down
Loading

0 comments on commit fc3b6b3

Please sign in to comment.