This repository has been archived by the owner on Dec 29, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 200
/
wtf-trace-closure.js
852 lines (743 loc) · 27.6 KB
/
wtf-trace-closure.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
/**
* https://github.com/google/tracing-framework
* Copyright 2013 Google, Inc. All Rights Reserved.
* Use of this source code is governed by a BSD-style license that can be
* found at https://github.com/google/tracing-framework/blob/master/LICENSE.
*/
/**
* @fileoverview Web Tracing Framework shim.
* This file gives compile-time control over the WTF API, allowing it to be
* type-checked and extern-free when enabled and completely compiled out when
* disabled.
*
* WTF, when used in release projects, should always be called through this
* API. *Never* use the global 'wtf' object directly, as it may not exist or
* may change. This file is versioned to prevent such issues.
*
* This file contains only the tracing-related functions that are exported in
* compiled WTF builds. The signatures and descriptions are copied out
* verbatim. Any types required to keep the compiler happy when looking at this
* file are exposed as either dummy typedefs or mock objects.
*
* When this file is included in a compiled library all of these methods will
* be renamed. By using 'WTF' as a namespace instead of 'wtf' there's no
* risk of collision when running uncompiled.
*
* Original source: https://www.github.com/google/tracing-framework/
*
* @author benvanik@google.com (Ben Vanik)
*/
goog.provide('WTF');
goog.provide('WTF.data.EventFlag');
goog.provide('WTF.io.ByteArray');
goog.provide('WTF.trace');
goog.provide('WTF.trace.Flow');
goog.provide('WTF.trace.Scope');
goog.provide('WTF.trace.TimeRange');
goog.provide('WTF.trace.Zone');
goog.provide('WTF.trace.events');
/**
* @define {boolean} True if WTF is enabled.
* This should be defined to false in release builds to ensure that WTF is not
* compiled in at all. It flips all functions to nullFunction (or some
* equivalent) and will allow the compiler to strip them out.
*/
WTF.ENABLED = true;
/**
* The API version expected by the shim.
* If WTF is present but its {@code wtf.trace.API_VERSION} does not match
* this value it will be ignored. This allows code instrumented with older
* versions of the API to keep working (without tracing) when a newer version
* of the API is present in the page. Since we are a debugging tool no effort is
* made to allow differing versions to work together.
* @type {number}
* @const
* @private
*/
WTF.EXPECTED_API_VERSION_ = 2;
/**
* Whether WTF is enabled and present in the current global context.
* This will only be true if the master enabled flag is true, 'wtf' is in the
* global scope, and the version of WTF matches this shim.
* If code really wants to see if WTF is present and usable, use this instead of
* just {@see #ENABLED}.
* @type {boolean}
* @const
*/
WTF.PRESENT = WTF.ENABLED && !!goog.global['wtf'] &&
(goog.global['wtf']['trace']['API_VERSION'] ==
WTF.EXPECTED_API_VERSION_);
/**
* Whether the runtime can provide high-resolution times.
* If this is false times are likely in milliseconds and largely useless.
* @type {boolean}
*/
WTF.hasHighResolutionTimes = WTF.PRESENT ?
goog.global['wtf']['hasHighResolutionTimes'] : false;
/**
* Returns the wall time that {@see wtf#now} is relative to.
* This is often the page load time.
*
* @return {number} A time, in ms.
*/
WTF.timebase = WTF.PRESENT ?
goog.global['wtf']['timebase'] : function() { return 0; };
/**
* Returns a non-wall time timestamp in milliseconds.
* If available this will use a high precision timer. Otherwise it will fall
* back to the default browser time.
*
* The time value is relative to page navigation, not wall time. Only use it for
* relative measurements.
*
* @return {number} A monotonically increasing timer with sub-millisecond
* resolution (if supported).
*/
WTF.now = WTF.PRESENT ?
goog.global['wtf']['now'] : function() { return 0; };
/**
* @typedef {Array.<number>|Uint8Array}
*/
WTF.io.ByteArray;
/**
* @typedef {Object}
*/
WTF.trace.Zone;
/**
* @typedef {Object}
*/
WTF.trace.Scope;
/**
* @typedef {Object}
*/
WTF.trace.Flow;
/**
* @typedef {Object}
*/
WTF.trace.TimeRange;
/**
* Event behavior flag bitmask.
* Values can be ORed together to indicate different behaviors an event has.
*
* This is copied from {@code wtf/data/eventflag.js}.
* @enum {number}
*/
WTF.data.EventFlag = {
/**
* Event is expected to occur at a very high frequency.
* High frequency events will be optimized for size more than other event
* types. Event arguments may also receive more preprocessing when being
* recorded, such as string interning/etc.
*/
HIGH_FREQUENCY: (1 << 1),
/**
* Event represents some system event that should not be counted towards user
* code. This can include things such as runtime events (GCs/etc) and tracing
* framework time (buffer swaps/etc).
*/
SYSTEM_TIME: (1 << 2),
/**
* Event represents some internal system event such as flow control events.
* If an event has this flag then it will never be shown in the UI and most
* parts of the system will ignore it. For some special events they will be
* handled at load-time and never even delivered to the database.
*/
INTERNAL: (1 << 3),
/**
* Event arguments will be appended to the containing scope's arguments,
* overwritting any with the same name.
*
* If this is combined with the INTERNAL flag then the event is assumed to
* be a built-in system append event and will have special handling.
*/
APPEND_SCOPE_DATA: (1 << 4),
/**
* Event is a builtin event.
* Only events defined by the tracing framework should set this bit. User
* events should not have this flag set and may be ignored if they do.
*/
BUILTIN: (1 << 5),
/**
* Event arguments will be appended to the given flow's data, overwritting
* any with the same name. The first argument must be a flow ID named
* 'id' like 'flowId id'.
*
* If this is combined with the INTERNAL flag then the event is assumed to
* be a built-in system append event and will have special handling.
*/
APPEND_FLOW_DATA: (1 << 6)
};
/**
* Default zone types.
* Any string value is valid, however these are standard ones.
*
* This is copied from {@code wtf/data/zonetype.js}.
* @enum {string}
*/
WTF.data.ZoneType = {
/**
* Primary script context.
* Usually just user JavaScript scopes. This is the default scope created for
* all traces.
*/
SCRIPT: 'script',
/**
* Native script context.
* Native runtime scopes, such as the C++ calls above the JavaScript.
*/
NATIVE_SCRIPT: 'native_script',
/**
* Native GPU thread context.
* This is not the GPU itself but instead the thread calling GPU driver
* methods.
*/
NATIVE_GPU: 'native_gpu',
/**
* Native browser context.
* This is the browser thread that usually routes input events and other
* global operations.
*/
NATIVE_BROWSER: 'native_browser'
};
/**
* Main entry point for the tracing API.
* This must be called as soon as possible and preferably before any application
* code is executed (or even included on the page).
*
* This method does not setup a tracing session, but prepares the environment
* for one. It can be called many times but the options provided are not updated
* once it's been called.
*
* @param {Object=} opt_options Options overrides.
* @return {*} Ignored.
*/
WTF.trace.prepare = WTF.PRESENT ?
goog.global['wtf']['trace']['prepare'] : goog.nullFunction;
/**
* Shuts down the tracing system.
*/
WTF.trace.shutdown = WTF.PRESENT ?
goog.global['wtf']['trace']['shutdown'] : goog.nullFunction;
/**
* Starts a new tracing session.
* The session mode is determined by the options provided, defaulting to
* snapshotting. See {@code wtf.trace.mode} and {@code wtf.trace.target} for
* more information.
*
* {@see WTF.trace#prepare} must have been called prior to calling this
* function.
*
* @param {Object=} opt_options Options overrides.
*/
WTF.trace.start = WTF.PRESENT ?
goog.global['wtf']['trace']['start'] : goog.nullFunction;
/**
* Takes a snapshot of the current state.
* A session must be actively recording. This call is ignored if the session
* does not support snapshotting.
* @param {*=} opt_targetValue Stream target value.
*/
WTF.trace.snapshot = WTF.PRESENT ?
goog.global['wtf']['trace']['snapshot'] : goog.nullFunction;
/**
* Asynchronously snapshots all contexts.
* This will take a snapshot of the current context as well as any dependent
* ones such as servers or worker threads. The results are sent to the callback
* when they have all been returned.
* If the call is going to be ignored (no active session) or fails the callback
* will fire on the next javascript tick with a null value.
*
* @param {function(this:T, Array.<!WTF.io.ByteArray>)} callback Function called
* when all buffers are available. The value will be null if an error
* occurred.
* @param {T=} opt_scope Callback scope.
* @template T
*/
WTF.trace.snapshotAll = WTF.PRESENT ?
goog.global['wtf']['trace']['snapshotAll'] : goog.nullFunction;
/**
* Clears all data in the current session by resetting all buffers.
* This is only valid in snapshotting sessions.
*/
WTF.trace.reset = WTF.PRESENT ?
goog.global['wtf']['trace']['reset'] : goog.nullFunction;
/**
* Stops the current session and disposes it.
*/
WTF.trace.stop = WTF.PRESENT ?
goog.global['wtf']['trace']['stop'] : goog.nullFunction;
/**
* Creates a new execution zone.
* Execution zones are used to group regions of code in the trace stream.
* For example, one zone may be 'Page' to indicate all page JS and another
* 'Worker' to show events from a web worker.
* @param {string} name Zone name.
* @param {string} type Zone type. This should be one of the
* {@see WTF.data.ZoneType} values.
* @param {string} location Zone location (such as URI of the script).
* @return {WTF.trace.Zone} Zone used for future calls.
*/
WTF.trace.createZone = WTF.PRESENT ?
goog.global['wtf']['trace']['createZone'] : goog.nullFunction;
/**
* Deletes an execution zone.
* The zone ID may be reused.
* @param {WTF.trace.Zone} zone Zone returned from {@see #createZone}.
*/
WTF.trace.deleteZone = WTF.PRESENT ?
goog.global['wtf']['trace']['deleteZone'] : goog.nullFunction;
/**
* Pushes a zone.
* @param {WTF.trace.Zone} zone Zone returned from {@see #createZone}.
*/
WTF.trace.pushZone = WTF.PRESENT ?
goog.global['wtf']['trace']['pushZone'] : goog.nullFunction;
/**
* Pops the active zone.
*/
WTF.trace.popZone = WTF.PRESENT ?
goog.global['wtf']['trace']['popZone'] : goog.nullFunction;
/**
* This must be matched with a {@see #leaveScope} that takes the return value.
*
* It is strongly recommended that a custom enter scope event should be used
* instead of this, as the overhead required to write the scope name is
* non-trivial. Only use this when the name changes many times at runtime or
* you're hacking something together. See {@see WTF.trace.events.createScope}.
*
* Example:
* <code>
* function myFunction() {
* var scope = WTF.trace.enterScope('myFunction');
* var result = ...;
* return WTF.trace.leaveScope(scope, result);
* }
* </code>
*
* @param {string} name Scope name.
* @param {number=} opt_time Time for the enter; omit to use the current time.
* @return {WTF.trace.Scope} An initialized scope object.
*/
WTF.trace.enterScope = WTF.PRESENT ?
goog.global['wtf']['trace']['enterScope'] : goog.nullFunction;
/**
* Enters a tracing implementation overhead scope.
* This should only be used by the tracing framework and extension to indicate
* time used by non-user tasks.
* @param {number=} opt_time Time for the enter; omit to use the current time.
* @return {WTF.trace.Scope} An initialized scope object.
*/
WTF.trace.enterTracingScope = WTF.PRESENT ?
goog.global['wtf']['trace']['enterTracingScope'] : goog.nullFunction;
/**
* Leaves a scope.
* @param {WTF.trace.Scope} scope Scope to leave. This is the result of a
* previous call to {@see #enterScope} or a custom enter scope function.
* @param {T=} opt_result Optional result to chain.
* @param {number=} opt_time Time for the leave; omit to use the current time.
* @return {T|undefined} The value of the {@code opt_result} parameter.
* @template T
*/
WTF.trace.leaveScope = WTF.PRESENT ?
goog.global['wtf']['trace']['leaveScope'] :
function(scope, opt_result, opt_time) {
return opt_result;
};
/**
* Appends a named argument of any type to the current scope.
* The data added is keyed by name, and existing data with the same name will
* be overwritten.
*
* Repeated calls with the same name and value type will be optimized at
* runtime. To ensure predictable performance it's better to use a custom
* instance event with the {@see WTF.data.EventFlag#APPEND_SCOPE_DATA} flag set.
*
* But, in general, you should avoid using this if you can. Appending data
* involves additional overhead at runtime and in the file compared to just
* passing the arguments to the function.
*
* No, really, this JSON stringifies whatever is passed to it and will skew
* your results. Don't use it.
*
* Example:
* <code>
* my.Type.prototype.someMethod = function() {
* // This method is traced automatically by traceMethods, but more data
* // is needed:
* WTF.trace.appendScopeData('bar', 123);
* WTF.trace.appendScopeData('foo', {
* 'complex': ['data']
* });
* };
* WTF.trace.instrumentType(...my.Type...);
* </code>
*
* @param {string} name Argument name. Must be ASCII.
* @param {*} value Value. Will be JSON stringified. If this is a number it
* will be converted to an int32.
* @param {number=} opt_time Time for the enter; omit to use the current time.
*/
WTF.trace.appendScopeData = WTF.PRESENT ?
goog.global['wtf']['trace']['appendScopeData'] : goog.nullFunction;
/**
* Branches the flow.
* If no parent flow is given then the current scope flow is used.
* @param {string} name Flow name.
* @param {*=} opt_value Optional data value.
* @param {WTF.trace.Flow=} opt_parentFlow Parent flow, if any.
* @param {number=} opt_time Time for the branch; omit to use the current time.
* @return {!WTF.trace.Flow} An initialized flow object.
*/
WTF.trace.branchFlow = WTF.PRESENT ?
goog.global['wtf']['trace']['branchFlow'] : goog.nullFunction;
/**
* Extends the flow into the current scope.
* @param {WTF.trace.Flow} flow Flow to extend.
* @param {string} name Flow stage name.
* @param {*=} opt_value Optional data value.
* @param {number=} opt_time Time for the extend; omit to use the current time.
*/
WTF.trace.extendFlow = WTF.PRESENT ?
goog.global['wtf']['trace']['extendFlow'] : goog.nullFunction;
/**
* Terminates a flow.
* @param {WTF.trace.Flow} flow Flow to terminate.
* @param {*=} opt_value Optional data value.
* @param {number=} opt_time Time for the terminate; omit to use the current
* time.
*/
WTF.trace.terminateFlow = WTF.PRESENT ?
goog.global['wtf']['trace']['terminateFlow'] : goog.nullFunction;
/**
* Appends a named argument of any type to the given flow.
* This is slow and should only be used for very infrequent appends.
* Prefer instead to use a custom instance event with the
* {@see WTF.data.EventFlag#APPEND_FLOW_DATA} flag set.
*
* @param {WTF.trace.Flow} flow Flow to append.
* @param {string} name Argument name. Must be ASCII.
* @param {*} value Value. Will be JSON stringified.
* @param {number=} opt_time Time for the event; omit to use the current time.
*/
WTF.trace.appendFlowData = WTF.PRESENT ?
goog.global['wtf']['trace']['appendFlowData'] : goog.nullFunction;
/**
* Clears the current scope flow.
*/
WTF.trace.clearFlow = WTF.PRESENT ?
goog.global['wtf']['trace']['clearFlow'] : goog.nullFunction;
/**
* Spans the flow across processes.
* Flows must have been branched before this can be used.
* @param {number} flowId Flow ID.
* @return {!WTF.trace.Flow} An initialized flow object.
*/
WTF.trace.spanFlow = WTF.PRESENT ?
goog.global['wtf']['trace']['spanFlow'] : goog.nullFunction;
/**
* Marks the stream with a named bookmark.
* This is used by the UI to construct a simple navigation structure.
* Each mark is then turned into a navigation point in a table of contents.
* This should only be used for modal application state changes, such as
* initial load, entry into a modal dialog or mode, etc. There is only ever one
* marked range active at a time and if you are calling this more frequently
* than 1s you should use something else.
*
* For high-frequency time stamps instead use {@see #timeStamp} and for async
* timers use {@see #beginTimeRange}.
*
* @param {string} name Marker name.
* @param {*=} opt_value Optional data value.
* @param {number=} opt_time Time for the mark; omit to use the current time.
*/
WTF.trace.mark = WTF.PRESENT ?
goog.global['wtf']['trace']['mark'] : goog.nullFunction;
/**
* Adds a timestamped event to the stream.
* This is synonymous to {@code console.timeStamp}, and can be used to place
* simple arg-less instance events in the timeline.
* Prefer using custom events for faster, more flexible events.
* @param {string} name Time stamp name.
* @param {*=} opt_value Optional data value.
* @param {number=} opt_time Time for the stamp; omit to use the current time.
*/
WTF.trace.timeStamp = WTF.PRESENT ?
goog.global['wtf']['trace']['timeStamp'] : goog.nullFunction;
/**
* Begins an async time range.
* This tracks time outside of normal scope flow control, and should be limited
* to only those events that span frames or JavaScript ticks.
* If you're trying to track call flow instead use {@see #traceMethods}.
*
* A limited number of active timers will be displayed in the UI. Do not abuse
* this feature by adding timers for everything (like network requests). Prefer
* to use flows to track complex async operations.
*
* Example:
* <code>
* my.Type.startJob = function(actionName) {
* var job = {...};
* job.tracingRange = WTF.trace.beginTimeRange('my.Type:job', actionName);
* };
* my.Type.endJob = function(job) {
* WTF.trace.endTimeRange(job.tracingRange);
* };
* </code>
*
* @param {string} name Time range name.
* @param {*=} opt_value Optional data value.
* @return {WTF.trace.TimeRange} Time range handle.
*/
WTF.trace.beginTimeRange = WTF.PRESENT ?
goog.global['wtf']['trace']['beginTimeRange'] : goog.nullFunction;
/**
* Ends an async time range previously started with {@see #beginTimeRange}.
* @param {WTF.trace.TimeRange} timeRange Time range handle.
* @param {number=} opt_time Time for the stamp; omit to use the current time.
*/
WTF.trace.endTimeRange = WTF.PRESENT ?
goog.global['wtf']['trace']['endTimeRange'] : goog.nullFunction;
/**
* Marks an event listener as being ignored, meaning that it will not show up
* in traces.
* This should only be used by debugging code as it will cause weird
* gaps in timing data. Alternatively one could use {@see #enterTracingScope}
* so that the time is properly shown as inside tracing code.
*
* Example:
* <code>
* myElement.onclick = WTF.trace.ignoreListener(function(e) {
* // This callback will not be auto-traced.
* });
* </code>
*
* @param {!T} listener Event listener.
* @return {!T} The parameter, for chaining.
* @template T
*/
WTF.trace.ignoreListener = WTF.PRESENT ?
goog.global['wtf']['trace']['ignoreListener'] : goog.nullFunction;
/**
* Marks an entire tree of DOM elements as being ignored, meaning that no
* events from them will show up in traces.
* @param {!Element} el Root DOM element.
*/
WTF.trace.ignoreDomTree = WTF.PRESENT ?
goog.global['wtf']['trace']['ignoreDomTree'] : goog.nullFunction;
/**
* Initializes on* event properties on the given DOM element and optionally
* for all children.
* This must be called to ensure the properties work correctly. It can be
* called repeatedly on the same elements (but you should avoid that). Try
* calling it after any new DOM tree is added recursively on the root of the
* tree.
*
* If this method is not called not all browsers will report events registered
* via their on* properties. Events registered with addEventListener will always
* be traced.
*
* @param {!Element} target Target DOM element.
* @param {boolean=} opt_recursive Also initialize for all children.
*/
WTF.trace.initializeDomEventProperties = WTF.PRESENT ?
goog.global['wtf']['trace']['initializeDomEventProperties'] :
goog.nullFunction;
/**
* Creates and registers a new event type, returning a function that can be used
* to trace the event in the WTF event stream.
* Created events should be cached and reused - do *not* redefine events.
*
* Events are defined by a signature that can be a simple string such as
* {@code 'myEvent'} or a reference string like {@code 'namespace.Type#method'}
* and can optionally include typed parameters like
* {@code 'myEvent(uint32 a, ascii b)'}.
*
* For more information on this API, see:
* https://github.com/google/tracing-framework/blob/master/docs/api.md
*
* When tracing is disabled {@code goog.nullFunction} will be returned for
* all events.
*
* Example:
* <code>
* // Create the event once, statically.
* my.Type.fooEvent_ = WTF.trace.events.createInstance(
* 'my.Type#foo(uint32 a, ascii b)');
* my.Type.prototype.someMethod = function() {
* // Trace the event each function call with custom args.
* my.Type.fooEvent_(123, 'hello');
* };
* </code>
*
* @param {string} signature Event signature.
* @param {number=} opt_flags A bitmask of {@see WTF.data.EventFlag} values.
* @return {Function} New event type.
*/
WTF.trace.events.createInstance = WTF.PRESENT ?
goog.global['wtf']['trace']['events']['createInstance'] :
function(signature, opt_flags) {
return goog.nullFunction;
};
/**
* Creates and registers a new event type, returning a function that can be used
* to trace the event in the WTF event stream.
* Created events should be cached and reused - do *not* redefine events.
*
* Events are defined by a signature that can be a simple string such as
* {@code 'myEvent'} or a reference string like {@code 'namespace.Type#method'}
* and can optionally include typed parameters like
* {@code 'myEvent(uint32 a, ascii b)'}.
*
* For more information on this API, see:
* https://github.com/google/tracing-framework/blob/master/docs/api.md
*
* When tracing is disabled {@code goog.nullFunction} will be returned for
* all events.
*
* Example:
* <code>
* // Create the event once, statically.
* my.Type.someMethodEvent_ = WTF.trace.events.createScope(
* 'my.Type#foo(uint32 a, ascii b)');
* my.Type.prototype.someMethod = function() {
* // Enter and leave each function call with custom args.
* var scope = my.Type.someMethodEvent_(123, 'hello');
* var result = 5; // ...
* return WTF.trace.leaveScope(scope, result);
* };
* </code>
*
* @param {string} signature Event signature.
* @param {number=} opt_flags A bitmask of {@see WTF.data.EventFlag} values.
* @return {Function} New event type.
*/
WTF.trace.events.createScope = WTF.PRESENT ?
goog.global['wtf']['trace']['events']['createScope'] :
function(signature, opt_flags) {
return goog.nullFunction;
};
/**
* Automatically instruments a method.
* This will likely produce code slower than manually instrumenting, but is
* much more readable.
*
* <code>
* my.Type.prototype.foo = WTF.trace.instrument(function(a, b) {
* return a + b;
* }, 'my.Type.foo(uint8 b@1)');
* </code>
*
* @param {T} value Target function.
* @param {string} signature Method signature.
* @param {string=} opt_namePrefix String to prepend to the name.
* @param {(function(Function, Function):Function)=} opt_generator
* A custom function generator that is responsible for taking the given
* {@code value} and returning a wrapped function that emits the given
* event type.
* @param {(function())=} opt_pre Code to execute before the scope is entered.
* This is only called if {@code opt_generator} is not provided.
* @return {T} The instrumented input value.
* @template T
*/
WTF.trace.instrument = WTF.PRESENT ?
goog.global['wtf']['trace']['instrument'] : goog.identityFunction;
/**
* Automatically instruments an entire type.
*
* <code>
* my.Type = function(a, b) {
* goog.base(this);
* this.value = a + b;
* };
* goog.inherits(my.Type, some.BaseType);
* my.Type.prototype.foo = function(a) { return a; };
* my.Type = WTF.trace.instrumentType(
* my.Type, 'my.Type(uint8 a, uint8 b)',
* goog.reflect.object(my.Type, {
* foo: 'foo(uint8 a)'
* }));
* </code>
*
* @param {T} value Target type.
* @param {string} constructorSignature Type name and constructor signature.
* @param {Object|!Object.<string>} methodMap A map of translated method names
* to method signatures. Only the methods in this map will be
* auto-instrumented.
* @return {T} The instrumented input value.
* @template T
*/
WTF.trace.instrumentType = WTF.PRESENT ?
goog.global['wtf']['trace']['instrumentType'] : goog.identityFunction;
/**
* Automatically instruments the given prototype methods.
* This is a simple variant of {@see WTF.trace.instrumentType} that does not
* provide method arguments or work with overridden methods.
*
* @param {string} prefix A common prefix to use for all trace labels.
* @param {!Object} classPrototype The prototype of the class.
* @param {!Object.<!Function>} methodMap A mapping between method names
* and the methods themselves.
*/
WTF.trace.instrumentTypeSimple = WTF.PRESENT ?
goog.global['wtf']['trace']['instrumentTypeSimple'] : goog.nullFunction;
/**
* @define {boolean} True to replace goog.base with a version that supports
* WTF instrumented methods.
*
* This, when goog.base is present, will enable the replacement of the
* goog.base in base.js to support methods instrumented by WTF. Without this,
* calls with goog.base will throw exceptions.
*
* Enabling this should have no side effects in compiled code.
*/
WTF.REPLACE_GOOG_BASE = true;
// Replace goog.base in debug mode.
if (!COMPILED &&
WTF.REPLACE_GOOG_BASE &&
WTF.PRESENT &&
goog.global['goog'] && goog.global['goog']['base']) {
/**
* A variant of {@code goog.base} that supports our method rewriting.
* This should only be used in uncompiled builds.
*
* To use, replace {@code goog.base} with this method as soon as possible.
*
* @param {!Object} me Should always be "this".
* @param {*=} opt_methodName The method name if calling a super method.
* @param {...*} var_args The rest of the arguments.
* @return {*} The return value of the superclass method.
* @suppress {es5Strict}
*/
goog.global['goog']['base'] = function(me, opt_methodName, var_args) {
var caller = arguments.callee.caller;
if (caller.superClass_) {
// This is a constructor. Call the superclass constructor.
return (/** @type {!Function} */ (caller.superClass_)).constructor.apply(
me, Array.prototype.slice.call(arguments, 1));
}
var args = Array.prototype.slice.call(arguments, 2);
var foundCaller = false;
for (var ctor = me.constructor;
ctor; ctor = ctor.superClass_ &&
(/** @type {!Function} */ (ctor.superClass_)).constructor) {
if (ctor.prototype[opt_methodName] === caller ||
ctor.prototype[opt_methodName]['uninstrumented'] === caller) {
foundCaller = true;
} else if (foundCaller) {
return ctor.prototype[opt_methodName].apply(me, args);
}
}
// If we did not find the caller in the prototype chain,
// then one of two things happened:
// 1) The caller is an instance method.
// 2) This method was not called by the right caller.
if (me[opt_methodName] === caller ||
me[opt_methodName]['uninstrumented'] === caller) {
return me.constructor.prototype[opt_methodName].apply(me, args);
} else {
throw Error(
'goog.base called from a method of one name ' +
'to a method of a different name');
}
};
}