[DevTools] Add utils for perfomance marks (#22180)
Juan committed
Aug 26, 2021 at 13:05 UTC
0ba0564aeea73b496264b6b2031b990a783cc142
3 files changed
+240
-292
packages/react-devtools-extensions/src/astUtils.js
+28
-50
@@ -7,7 +7,7 @@
7
* @flow
8
*/
9
10
-import {__PERFORMANCE_PROFILE__} from 'react-devtools-shared/src/constants';
10
+import {withSyncPerformanceMark} from 'react-devtools-shared/src/PerformanceMarks';
11
import traverse, {NodePath, Node} from '@babel/traverse';
12
import {File} from '@babel/types';
13
@@ -28,15 +28,6 @@ export type SourceFileASTWithHookDetails = {
28
29
export const NO_HOOK_NAME = '<no-hook>';
30
31
-function mark(markName: string): void {
32
- performance.mark(markName + '-start');
33
-}
34
-
35
-function measure(markName: string): void {
36
- performance.mark(markName + '-end');
37
- performance.measure(markName, markName + '-start', markName + '-end');
38
-}
39
-
31
const AST_NODE_TYPES = Object.freeze({
32
PROGRAM: 'Program',
33
CALL_EXPRESSION: 'CallExpression',
@@ -141,13 +132,10 @@ export function getHookName(
132
originalSourceLineNumber: number,
133
originalSourceColumnNumber: number,
134
): string | null {
144
- if (__PERFORMANCE_PROFILE__) {
145
- mark('getPotentialHookDeclarationsFromAST(originalSourceAST)');
146
- }
147
- const hooksFromAST = getPotentialHookDeclarationsFromAST(originalSourceAST);
148
- if (__PERFORMANCE_PROFILE__) {
149
- measure('getPotentialHookDeclarationsFromAST(originalSourceAST)');
150
- }
135
+ const hooksFromAST = withSyncPerformanceMark(
136
+ 'getPotentialHookDeclarationsFromAST(originalSourceAST)',
137
+ () => getPotentialHookDeclarationsFromAST(originalSourceAST),
138
+ );
139
140
let potentialReactHookASTNode = null;
141
if (originalSourceColumnNumber === 0) {
@@ -188,29 +176,23 @@ export function getHookName(
176
// nodesAssociatedWithReactHookASTNode could directly be used to obtain the hook variable name
177
// depending on the type of potentialReactHookASTNode
178
try {
191
- if (__PERFORMANCE_PROFILE__) {
192
- mark('getFilteredHookASTNodes()');
193
- }
194
- const nodesAssociatedWithReactHookASTNode = getFilteredHookASTNodes(
195
- potentialReactHookASTNode,
196
- hooksFromAST,
197
- originalSourceCode,
179
+ const nodesAssociatedWithReactHookASTNode = withSyncPerformanceMark(
180
+ 'getFilteredHookASTNodes()',
181
+ () =>
182
+ getFilteredHookASTNodes(
183
+ potentialReactHookASTNode,
184
+ hooksFromAST,
185
+ originalSourceCode,
186
+ ),
187
);
199
- if (__PERFORMANCE_PROFILE__) {
200
- measure('getFilteredHookASTNodes()');
201
- }
188
203
- if (__PERFORMANCE_PROFILE__) {
204
- mark('getHookNameFromNode()');
205
- }
206
- const name = getHookNameFromNode(
207
- hook,
208
- nodesAssociatedWithReactHookASTNode,
209
- potentialReactHookASTNode,
189
+ const name = withSyncPerformanceMark('getHookNameFromNode()', () =>
190
+ getHookNameFromNode(
191
+ hook,
192
+ nodesAssociatedWithReactHookASTNode,
193
+ potentialReactHookASTNode,
194
+ ),
195
);
211
- if (__PERFORMANCE_PROFILE__) {
212
- measure('getHookNameFromNode()');
213
- }
196
197
return name;
198
} catch (error) {
@@ -315,19 +297,15 @@ function getHookVariableName(
297
298
function getPotentialHookDeclarationsFromAST(sourceAST: File): NodePath[] {
299
const potentialHooksFound: NodePath[] = [];
318
- if (__PERFORMANCE_PROFILE__) {
319
- mark('traverse(sourceAST)');
320
- }
321
- traverse(sourceAST, {
322
- enter(path) {
323
- if (path.isVariableDeclarator() && isPotentialHookDeclaration(path)) {
324
- potentialHooksFound.push(path);
325
- }
326
- },
327
- });
328
- if (__PERFORMANCE_PROFILE__) {
329
- measure('traverse(sourceAST)');
330
- }
300
+ withSyncPerformanceMark('traverse(sourceAST)', () =>
301
+ traverse(sourceAST, {
302
+ enter(path) {
303
+ if (path.isVariableDeclarator() && isPotentialHookDeclaration(path)) {
304
+ potentialHooksFound.push(path);
305
+ }
306
+ },
307
+ }),
308
+ );
309
return potentialHooksFound;
310
}
311
packages/react-devtools-extensions/src/parseHookNames/parseHookNames.js
+153
-242
@@ -12,13 +12,15 @@ import LRU from 'lru-cache';
12
import {SourceMapConsumer} from 'source-map-js';
13
import {getHookName} from '../astUtils';
14
import {areSourceMapsAppliedToErrors} from '../ErrorTester';
15
-import {
16
- __DEBUG__,
17
- __PERFORMANCE_PROFILE__,
18
-} from 'react-devtools-shared/src/constants';
15
+import {__DEBUG__} from 'react-devtools-shared/src/constants';
16
import {getHookSourceLocationKey} from 'react-devtools-shared/src/hookNamesCache';
17
import {sourceMapIncludesSource} from '../SourceMapUtils';
18
import {SourceMapMetadataConsumer} from '../SourceMapMetadataConsumer';
19
+import {
20
+ withAsyncPerformanceMark,
21
+ withCallbackPerformanceMark,
22
+ withSyncPerformanceMark,
23
+} from 'react-devtools-shared/src/PerformanceMarks';
24
25
import type {
26
HooksNode,
@@ -26,18 +28,8 @@ import type {
28
HooksTree,
29
} from 'react-debug-tools/src/ReactDebugHooks';
30
import type {HookNames, LRUCache} from 'react-devtools-shared/src/types';
29
-import type {Thenable} from 'shared/ReactTypes';
31
import type {SourceConsumer} from '../astUtils';
32
32
-function mark(markName: string): void {
33
- performance.mark(markName + '-start');
34
-}
35
-
36
-function measure(markName: string): void {
37
- performance.mark(markName + '-end');
38
- performance.measure(markName, markName + '-start', markName + '-end');
39
-}
40
-
33
const MAX_SOURCE_LENGTH = 100_000_000;
34
35
type AST = mixed;
@@ -118,17 +110,20 @@ const originalURLToMetadataCache: LRUCache<
110
111
export async function parseHookNames(
112
hooksTree: HooksTree,
121
-): Thenable<HookNames | null> {
122
- if (__PERFORMANCE_PROFILE__) {
123
- mark('parseHookNames()');
124
- mark('flattenHooksList()');
125
- }
113
+): Promise<HookNames | null> {
114
const hooksList: Array<HooksNode> = [];
127
- flattenHooksList(hooksTree, hooksList);
128
- if (__PERFORMANCE_PROFILE__) {
129
- measure('flattenHooksList()');
130
- }
115
+ withSyncPerformanceMark('flattenHooksList()', () => {
116
+ flattenHooksList(hooksTree, hooksList);
117
+ });
118
+
119
+ return withAsyncPerformanceMark('parseHookNames()', () =>
120
+ parseHookNamesImpl(hooksList),
121
+ );
122
+}
123
124
+async function parseHookNamesImpl(
125
+ hooksList: HooksNode[],
126
+): Promise<HookNames | null> {
127
if (__DEBUG__) {
128
console.log('parseHookNames() hooksList:', hooksList);
129
}
@@ -183,56 +178,25 @@ export async function parseHookNames(
178
}
179
}
180
186
- if (__PERFORMANCE_PROFILE__) {
187
- mark('loadSourceFiles()');
188
- }
181
+ await withAsyncPerformanceMark('loadSourceFiles()', () =>
182
+ loadSourceFiles(locationKeyToHookSourceData),
183
+ );
184
190
- let promise = loadSourceFiles(locationKeyToHookSourceData);
191
- if (__PERFORMANCE_PROFILE__) {
192
- promise = promise.then(data => {
193
- mark('extractAndLoadSourceMaps()');
194
- measure('loadSourceFiles()');
195
- return data;
196
- });
197
- }
198
- promise = promise.then(() =>
185
+ await withAsyncPerformanceMark('extractAndLoadSourceMaps()', () =>
186
extractAndLoadSourceMaps(locationKeyToHookSourceData),
187
);
201
- if (__PERFORMANCE_PROFILE__) {
202
- promise = promise.then(data => {
203
- mark('parseSourceAST()');
204
- measure('extractAndLoadSourceMaps()');
205
- return data;
206
- });
207
- }
208
- promise = promise.then(() => parseSourceAST(locationKeyToHookSourceData));
209
- if (__PERFORMANCE_PROFILE__) {
210
- promise = promise.then(data => {
211
- mark('updateLruCache()');
212
- measure('parseSourceAST()');
213
- return data;
214
- });
215
- }
216
- promise = promise.then(() => updateLruCache(locationKeyToHookSourceData));
217
- if (__PERFORMANCE_PROFILE__) {
218
- promise = promise.then(data => {
219
- mark('findHookNames()');
220
- measure('updateLruCache()');
221
- return data;
222
- });
223
- }
224
- promise = promise.then(() =>
225
- findHookNames(hooksList, locationKeyToHookSourceData),
188
+
189
+ withSyncPerformanceMark('parseSourceAST()', () =>
190
+ parseSourceAST(locationKeyToHookSourceData),
191
);
227
- if (__PERFORMANCE_PROFILE__) {
228
- promise = promise.then(data => {
229
- measure('findHookNames()');
230
- measure('parseHookNames()');
231
- return data;
232
- });
233
- }
192
235
- return promise;
193
+ withSyncPerformanceMark('updateLruCache()', () =>
194
+ updateLruCache(locationKeyToHookSourceData),
195
+ );
196
+
197
+ return withSyncPerformanceMark('findHookNames()', () =>
198
+ findHookNames(hooksList, locationKeyToHookSourceData),
199
+ );
200
}
201
202
function decodeBase64String(encoded: string): Object {
@@ -279,13 +243,10 @@ function extractAndLoadSourceMaps(
243
const sourceMapRegex = / ?sourceMappingURL=([^\s'"]+)/gm;
244
const runtimeSourceCode = ((hookSourceData.runtimeSourceCode: any): string);
245
282
- if (__PERFORMANCE_PROFILE__) {
283
- mark('sourceMapRegex.exec(runtimeSourceCode)');
284
- }
285
- let sourceMappingURLMatch = sourceMapRegex.exec(runtimeSourceCode);
286
- if (__PERFORMANCE_PROFILE__) {
287
- measure('sourceMapRegex.exec(runtimeSourceCode)');
288
- }
246
+ let sourceMappingURLMatch = withSyncPerformanceMark(
247
+ 'sourceMapRegex.exec(runtimeSourceCode)',
248
+ () => sourceMapRegex.exec(runtimeSourceCode),
249
+ );
250
251
if (sourceMappingURLMatch == null) {
252
// Maybe file has not been transformed; we'll try to parse it as-is in parseSourceAST().
@@ -309,21 +270,13 @@ function extractAndLoadSourceMaps(
270
const trimmed = ((sourceMappingURL.match(
271
/base64,([a-zA-Z0-9+\/=]+)/,
272
): any): Array<string>)[1];
312
- if (__PERFORMANCE_PROFILE__) {
313
- mark('decodeBase64String()');
314
- }
315
- const decoded = decodeBase64String(trimmed);
316
- if (__PERFORMANCE_PROFILE__) {
317
- measure('decodeBase64String()');
318
- }
273
+ const decoded = withSyncPerformanceMark('decodeBase64String()', () =>
274
+ decodeBase64String(trimmed),
275
+ );
276
320
- if (__PERFORMANCE_PROFILE__) {
321
- mark('JSON.parse(decoded)');
322
- }
323
- const parsed = JSON.parse(decoded);
324
- if (__PERFORMANCE_PROFILE__) {
325
- measure('JSON.parse(decoded)');
326
- }
277
+ const parsed = withSyncPerformanceMark('JSON.parse(decoded)', () =>
278
+ JSON.parse(decoded),
279
+ );
280
281
if (__DEBUG__) {
282
console.groupCollapsed(
@@ -336,27 +289,24 @@ function extractAndLoadSourceMaps(
289
// Hook source might be a URL like "https://4syus.csb.app/src/App.js"
290
// Parsed source map might be a partial path like "src/App.js"
291
if (sourceMapIncludesSource(parsed, runtimeSourceURL)) {
339
- if (__PERFORMANCE_PROFILE__) {
340
- mark('new SourceMapMetadataConsumer(parsed)');
341
- }
342
- hookSourceData.metadataConsumer = new SourceMapMetadataConsumer(
343
- parsed,
292
+ hookSourceData.metadataConsumer = withSyncPerformanceMark(
293
+ 'new SourceMapMetadataConsumer(parsed)',
294
+ () => new SourceMapMetadataConsumer(parsed),
295
+ );
296
+ hookSourceData.sourceConsumer = withSyncPerformanceMark(
297
+ 'new SourceMapConsumer(parsed)',
298
+ () => new SourceMapConsumer(parsed),
299
);
345
- if (__PERFORMANCE_PROFILE__) {
346
- measure('new SourceMapMetadataConsumer(parsed)');
347
- mark('new SourceMapConsumer(parsed)');
348
- }
349
- hookSourceData.sourceConsumer = new SourceMapConsumer(parsed);
350
- if (__PERFORMANCE_PROFILE__) {
351
- measure('new SourceMapConsumer(parsed)');
352
- }
300
break;
301
}
302
} else {
303
externalSourceMapURLs.push(sourceMappingURL);
304
}
305
359
- sourceMappingURLMatch = sourceMapRegex.exec(runtimeSourceCode);
306
+ sourceMappingURLMatch = withSyncPerformanceMark(
307
+ 'sourceMapRegex.exec(runtimeSourceCode)',
308
+ () => sourceMapRegex.exec(runtimeSourceCode),
309
+ );
310
}
311
312
const foundInlineSourceMap =
@@ -395,29 +345,20 @@ function extractAndLoadSourceMaps(
345
fetchPromises.get(url) ||
346
fetchFile(url).then(
347
sourceMapContents => {
398
- if (__PERFORMANCE_PROFILE__) {
399
- mark('JSON.parse(sourceMapContents)');
400
- }
401
- const parsed = JSON.parse(sourceMapContents);
402
- if (__PERFORMANCE_PROFILE__) {
403
- measure('JSON.parse(sourceMapContents)');
404
- }
348
+ const parsed = withSyncPerformanceMark(
349
+ 'JSON.parse(sourceMapContents)',
350
+ () => JSON.parse(sourceMapContents),
351
+ );
352
406
- if (__PERFORMANCE_PROFILE__) {
407
- mark('SourceMapConsumer(parsed)');
408
- }
409
- const sourceConsumer = new SourceMapConsumer(parsed);
410
- if (__PERFORMANCE_PROFILE__) {
411
- measure('SourceMapConsumer(parsed)');
412
- }
353
+ const sourceConsumer = withSyncPerformanceMark(
354
+ 'new SourceMapConsumer(parsed)',
355
+ () => new SourceMapConsumer(parsed),
356
+ );
357
414
- if (__PERFORMANCE_PROFILE__) {
415
- mark('SourceMapMetadataConsumer(parsed)');
416
- }
417
- const metadataConsumer = new SourceMapMetadataConsumer(parsed);
418
- if (__PERFORMANCE_PROFILE__) {
419
- measure('SourceMapMetadataConsumer(parsed)');
420
- }
358
+ const metadataConsumer = withSyncPerformanceMark(
359
+ 'new SourceMapMetadataConsumer(parsed)',
360
+ () => new SourceMapMetadataConsumer(parsed),
361
+ );
362
363
return {sourceConsumer, metadataConsumer};
364
},
@@ -451,51 +392,43 @@ function extractAndLoadSourceMaps(
392
}
393
394
function fetchFile(url: string): Promise<string> {
454
- if (__PERFORMANCE_PROFILE__) {
455
- mark('fetchFile("' + url + '")');
456
- }
457
-
458
- return new Promise((resolve, reject) => {
459
- fetch(url).then(
460
- response => {
461
- if (response.ok) {
462
- response
463
- .text()
464
- .then(text => {
465
- if (__PERFORMANCE_PROFILE__) {
466
- measure('fetchFile("' + url + '")');
467
- }
468
- resolve(text);
469
- })
470
- .catch(error => {
471
- if (__DEBUG__) {
472
- console.log(`fetchFile() Could not read text for url "${url}"`);
473
- }
474
- if (__PERFORMANCE_PROFILE__) {
475
- measure('fetchFile("' + url + '")');
476
- }
477
- reject(null);
478
- });
479
- } else {
480
- if (__DEBUG__) {
481
- console.log(`fetchFile() Got bad response for url "${url}"`);
395
+ return withCallbackPerformanceMark('fetchFile("' + url + '")', done => {
396
+ return new Promise((resolve, reject) => {
397
+ fetch(url).then(
398
+ response => {
399
+ if (response.ok) {
400
+ response
401
+ .text()
402
+ .then(text => {
403
+ done();
404
+ resolve(text);
405
+ })
406
+ .catch(error => {
407
+ if (__DEBUG__) {
408
+ console.log(
409
+ `fetchFile() Could not read text for url "${url}"`,
410
+ );
411
+ }
412
+ done();
413
+ reject(null);
414
+ });
415
+ } else {
416
+ if (__DEBUG__) {
417
+ console.log(`fetchFile() Got bad response for url "${url}"`);
418
+ }
419
+ done();
420
+ reject(null);
421
}
483
- if (__PERFORMANCE_PROFILE__) {
484
- measure('fetchFile("' + url + '")');
422
+ },
423
+ error => {
424
+ if (__DEBUG__) {
425
+ console.log(`fetchFile() Could not fetch file: ${error.message}`);
426
}
427
+ done();
428
reject(null);
487
- }
488
- },
489
- error => {
490
- if (__DEBUG__) {
491
- console.log(`fetchFile() Could not fetch file: ${error.message}`);
492
- }
493
- if (__PERFORMANCE_PROFILE__) {
494
- measure('fetchFile("' + url + '")');
495
- }
496
- reject(null);
497
- },
498
- );
429
+ },
430
+ );
431
+ });
432
});
433
}
434
@@ -535,20 +468,18 @@ function findHookNames(
468
originalSourceColumnNumber = columnNumber;
469
originalSourceLineNumber = lineNumber;
470
} else {
538
- if (__PERFORMANCE_PROFILE__) {
539
- mark('sourceConsumer.originalPositionFor()');
540
- }
541
- const position = sourceConsumer.originalPositionFor({
542
- line: lineNumber,
543
-
544
- // Column numbers are represented differently between tools/engines.
545
- // Error.prototype.stack columns are 1-based (like most IDEs) but ASTs are 0-based.
546
- // For more info see https://github.com/facebook/react/issues/21792#issuecomment-873171991
547
- column: columnNumber - 1,
548
- });
549
- if (__PERFORMANCE_PROFILE__) {
550
- measure('sourceConsumer.originalPositionFor()');
551
- }
471
+ const position = withSyncPerformanceMark(
472
+ 'sourceConsumer.originalPositionFor()',
473
+ () =>
474
+ sourceConsumer.originalPositionFor({
475
+ line: lineNumber,
476
+
477
+ // Column numbers are represented differently between tools/engines.
478
+ // Error.prototype.stack columns are 1-based (like most IDEs) but ASTs are 0-based.
479
+ // For more info see https://github.com/facebook/react/issues/21792#issuecomment-873171991
480
+ column: columnNumber - 1,
481
+ }),
482
+ );
483
484
originalSourceColumnNumber = position.column;
485
originalSourceLineNumber = position.line;
@@ -571,33 +502,25 @@ function findHookNames(
502
let name;
503
const {metadataConsumer} = hookSourceData;
504
if (metadataConsumer != null) {
574
- if (__PERFORMANCE_PROFILE__) {
575
- mark('metadataConsumer.hookNameFor()');
576
- }
577
- name = metadataConsumer.hookNameFor({
578
- line: originalSourceLineNumber,
579
- column: originalSourceColumnNumber,
580
- source: originalSourceURL,
581
- });
582
- if (__PERFORMANCE_PROFILE__) {
583
- measure('metadataConsumer.hookNameFor()');
584
- }
505
+ name = withSyncPerformanceMark('metadataConsumer.hookNameFor()', () =>
506
+ metadataConsumer.hookNameFor({
507
+ line: originalSourceLineNumber,
508
+ column: originalSourceColumnNumber,
509
+ source: originalSourceURL,
510
+ }),
511
+ );
512
}
513
514
if (name == null) {
588
- if (__PERFORMANCE_PROFILE__) {
589
- mark('getHookName()');
590
- }
591
- name = getHookName(
592
- hook,
593
- hookSourceData.originalSourceAST,
594
- ((hookSourceData.originalSourceCode: any): string),
595
- ((originalSourceLineNumber: any): number),
596
- originalSourceColumnNumber,
515
+ name = withSyncPerformanceMark('getHookName()', () =>
516
+ getHookName(
517
+ hook,
518
+ hookSourceData.originalSourceAST,
519
+ ((hookSourceData.originalSourceCode: any): string),
520
+ ((originalSourceLineNumber: any): number),
521
+ originalSourceColumnNumber,
522
+ ),
523
);
598
- if (__PERFORMANCE_PROFILE__) {
599
- measure('getHookName()');
600
- }
524
}
525
526
if (__DEBUG__) {
@@ -645,9 +568,9 @@ function loadSourceFiles(
568
return Promise.all(setPromises);
569
}
570
648
-async function parseSourceAST(
571
+function parseSourceAST(
572
locationKeyToHookSourceData: Map<string, HookSourceData>,
650
-): Promise<*> {
573
+): void {
574
locationKeyToHookSourceData.forEach(hookSourceData => {
575
if (hookSourceData.originalSourceAST !== null) {
576
// Use cached metadata.
@@ -665,22 +588,20 @@ async function parseSourceAST(
588
if (lineNumber == null || columnNumber == null) {
589
throw Error('Hook source code location not found.');
590
}
668
- if (__PERFORMANCE_PROFILE__) {
669
- mark('sourceConsumer.originalPositionFor()');
670
- }
591
// Now that the source map has been loaded,
592
// extract the original source for later.
673
- const {source} = sourceConsumer.originalPositionFor({
674
- line: lineNumber,
675
-
676
- // Column numbers are represented differently between tools/engines.
677
- // Error.prototype.stack columns are 1-based (like most IDEs) but ASTs are 0-based.
678
- // For more info see https://github.com/facebook/react/issues/21792#issuecomment-873171991
679
- column: columnNumber - 1,
680
- });
681
- if (__PERFORMANCE_PROFILE__) {
682
- measure('sourceConsumer.originalPositionFor()');
683
- }
593
+ const {source} = withSyncPerformanceMark(
594
+ 'sourceConsumer.originalPositionFor()',
595
+ () =>
596
+ sourceConsumer.originalPositionFor({
597
+ line: lineNumber,
598
+
599
+ // Column numbers are represented differently between tools/engines.
600
+ // Error.prototype.stack columns are 1-based (like most IDEs) but ASTs are 0-based.
601
+ // For more info see https://github.com/facebook/react/issues/21792#issuecomment-873171991
602
+ column: columnNumber - 1,
603
+ }),
604
+ );
605
606
if (source == null) {
607
// TODO (named hooks) maybe fall back to the runtime source instead of throwing?
@@ -693,16 +614,10 @@ async function parseSourceAST(
614
// It can be relative if the source map specifies it that way,
615
// but we use it as a cache key across different source maps and there can be collisions.
616
originalSourceURL = (source: string);
696
- if (__PERFORMANCE_PROFILE__) {
697
- mark('sourceConsumer.sourceContentFor()');
698
- }
699
- originalSourceCode = (sourceConsumer.sourceContentFor(
700
- source,
701
- true,
702
- ): string);
703
- if (__PERFORMANCE_PROFILE__) {
704
- measure('sourceConsumer.sourceContentFor()');
705
- }
617
+ originalSourceCode = withSyncPerformanceMark(
618
+ 'sourceConsumer.sourceContentFor()',
619
+ () => (sourceConsumer.sourceContentFor(source, true): string),
620
+ );
621
622
if (__DEBUG__) {
623
console.groupCollapsed(
@@ -756,16 +671,14 @@ async function parseSourceAST(
671
originalSourceCode.indexOf('@flow') > 0 ? 'flow' : 'typescript';
672
673
// TODO (named hooks) Parsing should ideally be done off of the main thread.
759
- if (__PERFORMANCE_PROFILE__) {
760
- mark('[@babel/parser] parse(originalSourceCode)');
761
- }
762
- const originalSourceAST = parse(originalSourceCode, {
763
- sourceType: 'unambiguous',
764
- plugins: ['jsx', plugin],
765
- });
766
- if (__PERFORMANCE_PROFILE__) {
767
- measure('[@babel/parser] parse(originalSourceCode)');
768
- }
674
+ const originalSourceAST = withSyncPerformanceMark(
675
+ '[@babel/parser] parse(originalSourceCode)',
676
+ () =>
677
+ parse(originalSourceCode, {
678
+ sourceType: 'unambiguous',
679
+ plugins: ['jsx', plugin],
680
+ }),
681
+ );
682
hookSourceData.originalSourceAST = originalSourceAST;
683
if (__DEBUG__) {
684
console.log(
@@ -778,7 +691,6 @@ async function parseSourceAST(
691
});
692
}
693
});
781
- return Promise.resolve();
694
}
695
696
function flattenHooksList(
@@ -812,7 +724,7 @@ function isUnnamedBuiltInHook(hook: HooksNode) {
724
725
function updateLruCache(
726
locationKeyToHookSourceData: Map<string, HookSourceData>,
815
-): Promise<*> {
727
+): void {
728
locationKeyToHookSourceData.forEach(
729
({metadataConsumer, sourceConsumer, runtimeSourceURL}) => {
730
// Only set once to avoid triggering eviction/cleanup code.
@@ -830,7 +742,6 @@ function updateLruCache(
742
}
743
},
744
);
833
- return Promise.resolve();
745
}
746
747
export function purgeCachedMetadata(): void {
packages/react-devtools-shared/src/PerformanceMarks.js
new
+59
@@ -0,0 +1,59 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its 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
+ * @flow strict-local
8
+ */
9
+
10
+import {__PERFORMANCE_PROFILE__} from './constants';
11
+
12
+function mark(markName: string): void {
13
+ performance.mark(markName + '-start');
14
+}
15
+
16
+function measure(markName: string): void {
17
+ performance.mark(markName + '-end');
18
+ performance.measure(markName, markName + '-start', markName + '-end');
19
+}
20
+
21
+export async function withAsyncPerformanceMark<TReturn>(
22
+ markName: string,
23
+ callback: () => Promise<TReturn>,
24
+): Promise<TReturn> {
25
+ if (__PERFORMANCE_PROFILE__) {
26
+ mark(markName);
27
+ const result = await callback();
28
+ measure(markName);
29
+ return result;
30
+ }
31
+ return callback();
32
+}
33
+
34
+export function withSyncPerformanceMark<TReturn>(
35
+ markName: string,
36
+ callback: () => TReturn,
37
+): TReturn {
38
+ if (__PERFORMANCE_PROFILE__) {
39
+ mark(markName);
40
+ const result = callback();
41
+ measure(markName);
42
+ return result;
43
+ }
44
+ return callback();
45
+}
46
+
47
+export function withCallbackPerformanceMark<TReturn>(
48
+ markName: string,
49
+ callback: (done: () => void) => TReturn,
50
+): TReturn {
51
+ if (__PERFORMANCE_PROFILE__) {
52
+ mark(markName);
53
+ const done = () => {
54
+ measure(markName);
55
+ };
56
+ return callback(done);
57
+ }
58
+ return callback(() => {});
59
+}