Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
4482 lines (4413 sloc) 204 KB
#!/usr/bin/env python
"""
Copyright 2016 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import gzip
import logging
import math
import os
import re
import time
import urlparse
# try a fast json parser if it is installed
try:
import ujson as json
except BaseException:
import json
##########################################################################
# Trace processing
##########################################################################
class Trace():
"""Main class"""
def __init__(self):
self.thread_stack = {}
self.ignore_threads = {}
self.threads = {}
self.user_timing = []
self.event_names = {}
self.event_name_lookup = {}
self.scripts = None
self.timeline_events = []
self.trace_events = []
self.interactive = []
self.interactive_start = 0
self.interactive_end = None
self.start_time = None
self.end_time = None
self.cpu = {'main_thread': None, 'main_threads':[], 'subframes': []}
self.feature_usage = None
self.feature_usage_start_time = None
self.netlog = {'bytes_in': 0, 'bytes_out': 0, 'next_request_id': 1000000}
self.netlog_requests = None
self.v8stats = None
self.v8stack = {}
return
##########################################################################
# Output Logging
##########################################################################
def write_json(self, out_file, json_data):
"""Write out one of the internal structures as a json blob"""
try:
_, ext = os.path.splitext(out_file)
if ext.lower() == '.gz':
with gzip.open(out_file, 'wb') as f:
json.dump(json_data, f)
else:
with open(out_file, 'w') as f:
json.dump(json_data, f)
except BaseException:
logging.critical("Error writing to " + out_file)
def WriteUserTiming(self, out_file):
out = self.post_process_netlog_events()
out = self.post_process_user_timing()
if out is not None:
self.write_json(out_file, out)
def WriteCPUSlices(self, out_file):
self.write_json(out_file, self.cpu)
def WriteScriptTimings(self, out_file):
if self.scripts is not None:
self.write_json(out_file, self.scripts)
def WriteFeatureUsage(self, out_file):
self.post_process_netlog_events()
out = self.post_process_feature_usage()
if out is not None:
self.write_json(out_file, out)
def WriteInteractive(self, out_file):
self.write_json(out_file, self.interactive)
def WriteNetlog(self, out_file):
out = self.post_process_netlog_events()
if out is not None:
self.write_json(out_file, out)
def WriteV8Stats(self, out_file):
if self.v8stats is not None:
self.v8stats["main_thread"] = self.cpu['main_thread']
self.v8stats["main_threads"] = self.cpu['main_threads']
self.write_json(out_file, self.v8stats)
##########################################################################
# Top-level processing
##########################################################################
def Process(self, trace):
f = None
line_mode = False
self.__init__()
logging.debug("Loading trace: %s", trace)
try:
_, ext = os.path.splitext(trace)
if ext.lower() == '.gz':
f = gzip.open(trace, 'rb')
else:
f = open(trace, 'r')
for line in f:
try:
trace_event = json.loads(line.strip("\r\n\t ,"))
if not line_mode and 'traceEvents' in trace_event:
for sub_event in trace_event['traceEvents']:
self.FilterTraceEvent(sub_event)
else:
line_mode = True
self.FilterTraceEvent(trace_event)
except BaseException:
pass
except BaseException:
logging.critical("Error processing trace " + trace)
if f is not None:
f.close()
self.ProcessTraceEvents()
def ProcessTimeline(self, timeline):
self.__init__()
self.cpu['main_thread'] = '0'
self.threads['0'] = {}
events = None
f = None
try:
_, ext = os.path.splitext(timeline)
if ext.lower() == '.gz':
f = gzip.open(timeline, 'rb')
else:
f = open(timeline, 'r')
events = json.load(f)
if events:
# convert the old format timeline events into our internal
# representation
for event in events:
if 'method' in event and 'params' in event:
if self.start_time is None:
if event['method'] == 'Network.requestWillBeSent' and \
'timestamp' in event['params']:
self.start_time = event['params']['timestamp'] * 1000000.0
self.end_time = event['params']['timestamp'] * 1000000.0
else:
if 'timestamp' in event['params']:
t = event['params']['timestamp'] * 1000000.0
if t > self.end_time:
self.end_time = t
if event['method'] == 'Timeline.eventRecorded' and \
'record' in event['params']:
e = self.ProcessOldTimelineEvent(
event['params']['record'], None)
if e is not None:
self.timeline_events.append(e)
self.ProcessTimelineEvents()
except BaseException:
logging.critical("Error processing timeline " + timeline)
if f is not None:
f.close()
def FilterTraceEvent(self, trace_event):
cat = trace_event['cat']
if cat == 'toplevel' or cat == 'ipc,toplevel':
return
if cat == 'devtools.timeline' or \
cat == '__metadata' or \
cat.find('devtools.timeline') >= 0 or \
cat.find('blink.feature_usage') >= 0 or \
cat.find('blink.user_timing') >= 0 or \
cat.find('loading') >= 0 or \
cat.find('navigation') >= 0 or \
cat.find('rail') >= 0 or \
cat.find('netlog') >= 0 or \
cat.find('v8') >= 0:
self.trace_events.append(trace_event)
def ProcessTraceEvents(self):
# sort the raw trace events by timestamp and then process them
if len(self.trace_events):
logging.debug("Sorting %d trace events", len(self.trace_events))
self.trace_events.sort(key=lambda trace_event: trace_event['ts'])
logging.debug("Processing trace events")
for trace_event in self.trace_events:
self.ProcessTraceEvent(trace_event)
self.trace_events = []
# Post-process the netlog events (may shift the start time)
logging.debug("Processing netlog events")
self.post_process_netlog_events()
# Do the post-processing on timeline events
logging.debug("Processing timeline events")
self.ProcessTimelineEvents()
logging.debug("Done processing trace events")
def ProcessTraceEvent(self, trace_event):
cat = trace_event['cat']
if cat.find('blink.user_timing') >= 0 or cat.find('rail') >= 0 or \
cat.find('loading') >= 0 or cat.find('navigation') >= 0:
keep = False
if 'args' in trace_event and \
'data' in trace_event['args'] and \
'inMainFrame' in trace_event['args']['data'] and \
trace_event['args']['data']['inMainFrame']:
keep = True
elif 'args' in trace_event and 'frame' in trace_event['args']:
keep = True
elif 'name' in trace_event and trace_event['name'] in [
'navigationStart', 'unloadEventStart', 'redirectStart', 'domLoading']:
keep = True
if keep:
self.user_timing.append(trace_event)
if 'name' in trace_event and trace_event['name'].find('navigationStart') >= 0:
if self.start_time is None or trace_event['ts'] < self.start_time:
self.start_time = trace_event['ts']
if self.cpu['main_thread'] is None and 'name' in trace_event and \
trace_event['name'] in ['navigationStart', 'fetchStart']:
thread = '{0}:{1}'.format(trace_event['pid'], trace_event['tid'])
self.cpu['main_thread'] = thread
if thread not in self.cpu['main_threads']:
self.cpu['main_threads'].append(thread)
if 'args' in trace_event and \
'data' in trace_event['args'] and \
'inMainFrame' in trace_event['args']['data'] and \
trace_event['args']['data']['inMainFrame']:
thread = '{0}:{1}'.format(trace_event['pid'], trace_event['tid'])
if thread not in self.cpu['main_threads']:
self.cpu['main_threads'].append(thread)
if cat == '__metadata' and 'name' in trace_event and \
trace_event['name'] == 'process_labels' and \
'pid' in trace_event and 'args' in trace_event and \
'labels' in trace_event['args'] and \
trace_event['args']['labels'].startswith('Subframe:'):
self.cpu['subframes'].append(str(trace_event['pid']))
if cat == '__metadata' and 'name' in trace_event and \
trace_event['name'] == 'thread_name' and \
'args' in trace_event and \
'name' in trace_event['args'] and \
trace_event['args']['name'] == 'CrRendererMain':
thread = '{0}:{1}'.format(trace_event['pid'], trace_event['tid'])
if thread not in self.cpu['main_threads']:
self.cpu['main_threads'].append(thread)
if cat == 'netlog' or cat.find('netlog') >= 0:
self.ProcessNetlogEvent(trace_event)
elif cat == 'devtools.timeline' or cat.find('devtools.timeline') >= 0:
self.ProcessTimelineTraceEvent(trace_event)
elif cat.find('blink.feature_usage') >= 0:
self.ProcessFeatureUsageEvent(trace_event)
if cat.find('v8') >= 0:
self.ProcessV8Event(trace_event)
def post_process_user_timing(self):
out = None
if self.user_timing is not None:
self.user_timing.sort(key=lambda trace_event: trace_event['ts'])
out = []
lcp_event = None
for event in self.user_timing:
try:
if event['cat'].find('loading') >= 0 and 'name' in event and event['name'].startswith('NavStartToLargestContentfulPaint'):
if event['name'].find('Invalidate') >= 0:
lcp_event = None
elif event['name'].find('Candidate') >= 0:
lcp_event = dict(event)
else:
out.append(event)
except Exception:
pass
if lcp_event is not None:
lcp_event['name'] = 'LargestContentfulPaint'
out.append(lcp_event)
out.append({'startTime': self.start_time})
return out
##########################################################################
# Timeline
##########################################################################
def ProcessTimelineTraceEvent(self, trace_event):
thread = '{0}:{1}'.format(trace_event['pid'], trace_event['tid'])
if trace_event['name'] == 'thread_name' and \
'args' in trace_event and \
'name' in trace_event['args'] and \
trace_event['args']['name'] == 'CrRendererMain' and \
thread not in self.cpu['main_threads']:
self.cpu['main_threads'].append(thread)
# Keep track of the main thread
if 'args' in trace_event and 'data' in trace_event['args'] and \
thread not in self.ignore_threads:
if 'url' in trace_event['args']['data'] and \
trace_event['args']['data']['url'].startswith('http://127.0.0.1:8888'):
self.ignore_threads[thread] = True
if self.cpu['main_thread'] is None or 'isMainFrame' in trace_event['args']['data']:
if ('isMainFrame' in trace_event['args']['data'] and \
trace_event['args']['data']['isMainFrame']) or \
(trace_event['name'] == 'ResourceSendRequest' and \
'url' in trace_event['args']['data']):
if thread not in self.threads:
self.threads[thread] = {}
if self.start_time is None or trace_event['ts'] < self.start_time:
self.start_time = trace_event['ts']
self.cpu['main_thread'] = thread
if thread not in self.cpu['main_threads']:
self.cpu['main_threads'].append(thread)
if 'dur' not in trace_event:
trace_event['dur'] = 1
# Make sure each thread has a numerical ID
if self.cpu['main_thread'] is not None and \
thread not in self.threads and \
thread not in self.ignore_threads and \
trace_event['name'] != 'Program':
self.threads[thread] = {}
# Build timeline events on a stack. 'B' begins an event, 'E' ends an
# event
if (thread in self.threads and (
'dur' in trace_event or trace_event['ph'] == 'B' or trace_event['ph'] == 'E')):
trace_event['thread'] = self.threads[thread]
if thread not in self.thread_stack:
self.thread_stack[thread] = []
if trace_event['name'] not in self.event_names:
self.event_names[trace_event['name']] = len(self.event_names)
self.event_name_lookup[self.event_names[trace_event['name']]] = trace_event['name']
if trace_event['name'] not in self.threads[thread]:
self.threads[thread][trace_event['name']] = self.event_names[trace_event['name']]
e = None
if trace_event['ph'] == 'E':
if len(self.thread_stack[thread]) > 0:
e = self.thread_stack[thread].pop()
if e['n'] == self.event_names[trace_event['name']]:
e['e'] = trace_event['ts']
else:
e = {'t': thread, 'n': self.event_names[trace_event['name']], 's': trace_event['ts']}
if trace_event['name'] in ['EvaluateScript', 'v8.compile', 'v8.parseOnBackground'] and \
'args' in trace_event and 'data' in trace_event['args'] and \
'url' in trace_event['args']['data'] and \
trace_event['args']['data']['url'].startswith('http'):
e['js'] = trace_event['args']['data']['url']
if trace_event['name'] == 'FunctionCall' and 'args' in trace_event and 'data' in trace_event['args']:
if 'scriptName' in trace_event['args']['data'] and trace_event['args']['data']['scriptName'].startswith(
'http'):
e['js'] = trace_event['args']['data']['scriptName']
elif 'url' in trace_event['args']['data'] and trace_event['args']['data']['url'].startswith('http'):
e['js'] = trace_event['args']['data']['url'].split('#', 1)[0]
if trace_event['ph'] == 'B':
self.thread_stack[thread].append(e)
e = None
elif 'dur' in trace_event:
e['e'] = e['s'] + trace_event['dur']
if e is not None and 'e' in e and e['s'] >= self.start_time and e['e'] >= e['s']:
if self.end_time is None or e['e'] > self.end_time:
self.end_time = e['e']
# attach it to a parent event if there is one
if len(self.thread_stack[thread]) > 0:
parent = self.thread_stack[thread].pop()
if 'c' not in parent:
parent['c'] = []
parent['c'].append(e)
self.thread_stack[thread].append(parent)
else:
self.timeline_events.append(e)
def ProcessOldTimelineEvent(self, event, type):
e = None
thread = '0'
if 'type' in event:
type = event['type']
if type not in self.event_names:
self.event_names[type] = len(self.event_names)
self.event_name_lookup[self.event_names[type]] = type
if type not in self.threads[thread]:
self.threads[thread][type] = self.event_names[type]
start = None
end = None
if 'startTime' in event and 'endTime' in event:
start = event['startTime'] * 1000000.0
end = event['endTime'] * 1000000.0
if 'callInfo' in event:
if 'startTime' in event['callInfo'] and 'endTime' in event['callInfo']:
start = event['callInfo']['startTime'] * 1000000.0
end = event['callInfo']['endTime'] * 1000000.0
if start is not None and end is not None and end >= start and type is not None:
if end > self.end_time:
self.end_time = end
e = {'t': thread,
'n': self.event_names[type], 's': start, 'e': end}
if 'callInfo' in event and 'url' in event and event['url'].startswith(
'http'):
e['js'] = event['url'].split('#', 1)[0]
elif 'data' in event and 'url' in event['data'] and \
event['data']['url'].startswith('http'):
e['js'] = event['data']['url'].split('#', 1)[0]
elif 'data' in event and 'scriptName' in event['data'] and \
event['data']['scriptName'].startswith('http'):
e['js'] = event['data']['scriptName'].split('#', 1)[0]
elif 'stackTrace' in event and event['stackTrace']:
for stack_frame in event['stackTrace']:
if 'url' in stack_frame and stack_frame['url'].startswith('http'):
e['js'] = stack_frame['url'].split('#', 1)[0]
break
# Process profile child events
if 'data' in event and 'profile' in event['data'] and 'rootNodes' in event['data']['profile']:
for child in event['data']['profile']['rootNodes']:
c = self.ProcessOldTimelineEvent(child, type)
if c is not None:
if 'c' not in e:
e['c'] = []
e['c'].append(c)
# recursively process any child events
if 'children' in event:
for child in event['children']:
c = self.ProcessOldTimelineEvent(child, type)
if c is not None:
if 'c' not in e:
e['c'] = []
e['c'].append(c)
return e
def ProcessTimelineEvents(self):
if len(self.timeline_events) and self.end_time > self.start_time:
# Figure out how big each slice should be in usecs. Size it to a
# power of 10 where we have at least 2000 slices
exp = 0
last_exp = 0
slice_count = self.end_time - self.start_time
while slice_count > 2000:
last_exp = exp
exp += 1
slice_count = int(
math.ceil(float(self.end_time - self.start_time) / float(pow(10, exp))))
self.cpu['total_usecs'] = self.end_time - self.start_time
self.cpu['slice_usecs'] = int(pow(10, last_exp))
slice_count = int(math.ceil(
float(self.end_time - self.start_time) / float(self.cpu['slice_usecs'])))
# Create the empty time slices for all of the threads
self.cpu['slices'] = {}
for thread in self.threads.keys():
self.cpu['slices'][thread] = {'total': [0.0] * slice_count}
for name in self.threads[thread].keys():
self.cpu['slices'][thread][name] = [0.0] * slice_count
# Go through all of the timeline events recursively and account for
# the time they consumed
for timeline_event in self.timeline_events:
self.ProcessTimelineEvent(timeline_event, None)
if self.interactive_end is not None and self.interactive_end - \
self.interactive_start > 500000:
self.interactive.append([int(math.ceil(self.interactive_start / 1000.0)),
int(math.floor(self.interactive_end / 1000.0))])
# Go through all of the fractional times and convert the float
# fractional times to integer usecs
for thread in self.cpu['slices'].keys():
del self.cpu['slices'][thread]['total']
for name in self.cpu['slices'][thread].keys():
for slice in range(len(self.cpu['slices'][thread][name])):
self.cpu['slices'][thread][name][slice] =\
int(self.cpu['slices'][thread][name]
[slice] * self.cpu['slice_usecs'])
# Pick the candidate main thread with the most activity
main_threads = list(self.cpu['main_threads'])
if len(main_threads) == 0:
main_threads = self.cpu['slices'].keys()
main_thread = None
main_thread_cpu = 0
for thread in main_threads:
try:
thread_cpu = 0
if thread in self.cpu['slices']:
for name in self.cpu['slices'][thread].keys():
for slice in range(len(self.cpu['slices'][thread][name])):
thread_cpu += self.cpu['slices'][thread][name][slice]
if main_thread is None or thread_cpu > main_thread_cpu:
main_thread = thread
main_thread_cpu = thread_cpu
except Exception:
pass
if main_thread is not None:
self.cpu['main_thread'] = main_thread
def ProcessTimelineEvent(self, timeline_event, parent, stack=None):
start = timeline_event['s'] - self.start_time
end = timeline_event['e'] - self.start_time
if stack is None:
stack = {}
if end > start:
elapsed = end - start
thread = timeline_event['t']
name = self.event_name_lookup[timeline_event['n']]
# Keep track of periods on the main thread where at least 500ms are
# available with no tasks longer than 50ms
if 'main_thread' in self.cpu and thread == self.cpu['main_thread']:
if elapsed > 50000:
if start - self.interactive_start > 500000:
self.interactive.append(
[int(math.ceil(self.interactive_start / 1000.0)),
int(math.floor(start / 1000.0))])
self.interactive_start = end
self.interactive_end = None
else:
self.interactive_end = end
if 'js' in timeline_event:
script = timeline_event['js']
js_start = start / 1000.0
js_end = end / 1000.0
if self.scripts is None:
self.scripts = {}
if 'main_thread' not in self.scripts and 'main_thread' in self.cpu:
self.scripts['main_thread'] = self.cpu['main_thread']
if thread not in self.scripts:
self.scripts[thread] = {}
if script not in self.scripts[thread]:
self.scripts[thread][script] = {}
if name not in self.scripts[thread][script]:
self.scripts[thread][script][name] = []
if thread not in stack:
stack[thread] = {}
if script not in stack[thread]:
stack[thread][script] = {}
if name not in stack[thread][script]:
stack[thread][script][name] = []
# make sure the script duration isn't already covered by a
# parent event
new_duration = True
if len(stack[thread][script][name]):
for period in stack[thread][script][name]:
if len(period) >= 2 and js_start >= period[0] and js_end <= period[1]:
new_duration = False
break
if new_duration:
self.scripts[thread][script][name].append([js_start, js_end])
stack[thread][script][name].append([js_start, js_end])
slice_usecs = self.cpu['slice_usecs']
first_slice = int(float(start) / float(slice_usecs))
last_slice = int(float(end) / float(slice_usecs))
for slice_number in xrange(first_slice, last_slice + 1):
slice_start = slice_number * slice_usecs
slice_end = slice_start + slice_usecs
used_start = max(slice_start, start)
used_end = min(slice_end, end)
slice_elapsed = used_end - used_start
self.AdjustTimelineSlice(
thread, slice_number, name, parent, slice_elapsed)
# Recursively process any child events
if 'c' in timeline_event:
for child in timeline_event['c']:
self.ProcessTimelineEvent(child, name, dict(stack))
# Add the time to the given slice and subtract the time from a parent event
def AdjustTimelineSlice(self, thread, slice_number, name, parent, elapsed):
try:
# Don't bother adjusting if both the current event and parent are the same category
# since they would just cancel each other out.
if name != parent:
fraction = min(1.0, float(elapsed) /
float(self.cpu['slice_usecs']))
self.cpu['slices'][thread][name][slice_number] += fraction
self.cpu['slices'][thread]['total'][slice_number] += fraction
if parent is not None and \
self.cpu['slices'][thread][parent][slice_number] >= fraction:
self.cpu['slices'][thread][parent][slice_number] -= fraction
self.cpu['slices'][thread]['total'][slice_number] -= fraction
# Make sure we didn't exceed 100% in this slice
self.cpu['slices'][thread][name][slice_number] = min(
1.0, self.cpu['slices'][thread][name][slice_number])
# make sure we don't exceed 100% for any slot
if self.cpu['slices'][thread]['total'][slice_number] > 1.0:
available = max(0.0, 1.0 - fraction)
for slice_name in self.cpu['slices'][thread].keys():
if slice_name != name:
self.cpu['slices'][thread][slice_name][slice_number] =\
min(self.cpu['slices'][thread]
[slice_name][slice_number], available)
available = max(0.0, available - \
self.cpu['slices'][thread][slice_name][slice_number])
self.cpu['slices'][thread]['total'][slice_number] = min(
1.0, max(0.0, 1.0 - available))
except BaseException:
pass
##########################################################################
# Blink Features
##########################################################################
def ProcessFeatureUsageEvent(self, trace_event):
global BLINK_FEATURES
if 'name' in trace_event and\
'args' in trace_event and\
'feature' in trace_event['args'] and\
(trace_event['name'] == 'FeatureFirstUsed' or trace_event['name'] == 'CSSFirstUsed'):
if self.feature_usage is None:
self.feature_usage = {
'Features': {}, 'CSSFeatures': {}, 'AnimatedCSSFeatures': {}}
id = '{0:d}'.format(trace_event['args']['feature'])
if trace_event['name'] == 'FeatureFirstUsed':
if id in BLINK_FEATURES:
name = BLINK_FEATURES[id]
else:
name = 'Feature_{0}'.format(id)
if name not in self.feature_usage['Features']:
self.feature_usage['Features'][name] = []
self.feature_usage['Features'][name].append(trace_event['ts'])
elif trace_event['name'] == 'CSSFirstUsed':
if id in CSS_FEATURES:
name = CSS_FEATURES[id]
else:
name = 'CSSFeature_{0}'.format(id)
if name not in self.feature_usage['CSSFeatures']:
self.feature_usage['CSSFeatures'][name] = []
self.feature_usage['CSSFeatures'][name].append(trace_event['ts'])
elif trace_event['name'] == 'AnimatedCSSFirstUsed':
if id in CSS_FEATURES:
name = CSS_FEATURES[id]
else:
name = 'CSSFeature_{0}'.format(id)
if name not in self.feature_usage['AnimatedCSSFeatures']:
self.feature_usage['AnimatedCSSFeatures'][name] = []
self.feature_usage['AnimatedCSSFeatures'][name].append(trace_event['ts'])
def post_process_feature_usage(self):
out = None
if self.feature_usage is not None and self.start_time is not None:
out = {}
for category in self.feature_usage:
out[category] = {}
for name in self.feature_usage[category]:
feature_time = None
for ts in self.feature_usage[category][name]:
timestamp = float('{0:0.3f}'.format((ts - self.start_time) / 1000.0))
if timestamp > 0:
if feature_time is None or timestamp < feature_time:
feature_time = timestamp
if feature_time is not None:
out[category][name] = feature_time
return out
##########################################################################
# Netlog
##########################################################################
def ProcessNetlogEvent(self, trace_event):
if 'args' in trace_event and 'id' in trace_event and 'name' in trace_event and \
'source_type' in trace_event['args']:
try:
if isinstance(trace_event['id'], (str, unicode)):
trace_event['id'] = int(trace_event['id'], 16)
event_type = trace_event['args']['source_type']
if event_type == 'HOST_RESOLVER_IMPL_JOB' or \
trace_event['name'].startswith('HOST_RESOLVER'):
self.ProcessNetlogDnsEvent(trace_event)
elif event_type == 'CONNECT_JOB' or \
event_type == 'SSL_CONNECT_JOB' or \
event_type == 'TRANSPORT_CONNECT_JOB':
self.ProcessNetlogConnectJobEvent(trace_event)
elif event_type == 'HTTP_STREAM_JOB':
self.ProcessNetlogStreamJobEvent(trace_event)
elif event_type == 'HTTP2_SESSION':
self.ProcessNetlogHttp2SessionEvent(trace_event)
elif event_type == 'SOCKET':
self.ProcessNetlogSocketEvent(trace_event)
elif event_type == 'URL_REQUEST':
self.ProcessNetlogUrlRequestEvent(trace_event)
except Exception:
pass
def post_process_netlog_events(self):
"""Post-process the raw netlog events into request data"""
if self.netlog_requests is not None:
return self.netlog_requests
requests = []
if 'url_request' in self.netlog:
for request_id in self.netlog['url_request']:
request = self.netlog['url_request'][request_id]
request['fromNet'] = bool('start' in request)
if 'url' in request and not request['url'].startswith('http://127.0.0.1') and \
not request['url'].startswith('http://192.168.10.'):
# Match orphaned request streams with their h2 sessions
if 'stream_id' in request and 'h2_session' not in request and 'url' in request:
request_host = urlparse.urlparse(request['url']).hostname
for h2_session_id in self.netlog['h2_session']:
h2_session = self.netlog['h2_session'][h2_session_id]
if 'host' in h2_session:
session_host = h2_session['host'].split(':')[0]
if 'stream' in h2_session and \
request['stream_id'] in h2_session['stream'] and \
session_host == request_host and \
'request_headers' in request and \
'request_headers' in h2_session['stream'][request['stream_id']]:
# See if the path header matches
stream = h2_session['stream'][request['stream_id']]
request_path = None
stream_path = None
for header in request['request_headers']:
if header.startswith(':path:'):
request_path = header
break
for header in stream['request_headers']:
if header.startswith(':path:'):
stream_path = header
break
if request_path is not None and request_path == stream_path:
request['h2_session'] = h2_session_id
break
# Copy any http/2 info over
if 'h2_session' in self.netlog and \
'h2_session' in request and \
request['h2_session'] in self.netlog['h2_session']:
h2_session = self.netlog['h2_session'][request['h2_session']]
if 'socket' not in request and 'socket' in h2_session:
request['socket'] = h2_session['socket']
if 'stream_id' in request and \
'stream' in h2_session and \
request['stream_id'] in h2_session['stream']:
stream = h2_session['stream'][request['stream_id']]
if 'request_headers' in stream:
request['request_headers'] = stream['request_headers']
if 'response_headers' in stream:
request['response_headers'] = stream['response_headers']
if 'exclusive' in stream:
request['exclusive'] = 1 if stream['exclusive'] else 0
if 'parent_stream_id' in stream:
request['parent_stream_id'] = stream['parent_stream_id']
if 'weight' in stream:
request['weight'] = stream['weight']
if 'first_byte' not in request and 'first_byte' in stream:
request['first_byte'] = stream['first_byte']
if 'end' not in request and 'end' in stream:
request['end'] = stream['end']
if stream['bytes_in'] > request['bytes_in']:
request['bytes_in'] = stream['bytes_in']
request['chunks'] = stream['chunks']
if 'phantom' not in request and 'request_headers' in request:
requests.append(request)
if len(requests):
# Sort the requests by the start time
requests.sort(key=lambda x: x['start'] if 'start' in x else x['created'])
# Assign the socket connect time to the first request on each socket
if 'socket' in self.netlog:
for request in requests:
if 'socket' in request and request['socket'] in self.netlog['socket']:
socket = self.netlog['socket'][request['socket']]
if 'address' in socket:
request['server_address'] = socket['address']
if 'source_address' in socket:
request['client_address'] = socket['source_address']
if 'group' in socket:
request['socket_group'] = socket['group']
if 'claimed' not in socket:
socket['claimed'] = True
if 'connect_start' in socket:
request['connect_start'] = socket['connect_start']
if 'connect_end' in socket:
request['connect_end'] = socket['connect_end']
if 'ssl_start' in socket:
request['ssl_start'] = socket['ssl_start']
if 'ssl_end' in socket:
request['ssl_end'] = socket['ssl_end']
if 'certificates' in socket:
request['certificates'] = socket['certificates']
if 'h2_session' in request and request['h2_session'] in self.netlog['h2_session']:
h2_session = self.netlog['h2_session'][request['h2_session']]
if 'server_settings' in h2_session:
request['http2_server_settings'] = h2_session['server_settings']
if 'tls_version' in socket:
request['tls_version'] = socket['tls_version']
if 'tls_resumed' in socket:
request['tls_resumed'] = socket['tls_resumed']
if 'tls_next_proto' in socket:
request['tls_next_proto'] = socket['tls_next_proto']
if 'tls_cipher_suite' in socket:
request['tls_cipher_suite'] = socket['tls_cipher_suite']
# Assign the DNS lookup to the first request that connected to the DocumentSetDomain
if 'dns' in self.netlog:
# Build a mapping of the DNS lookups for each domain
dns_lookups = {}
for dns_id in self.netlog['dns']:
dns = self.netlog['dns'][dns_id]
if 'host' in dns and 'start' in dns and 'end' in dns \
and dns['end'] >= dns['start'] and 'address_list' in dns:
hostname = dns['host']
separator = hostname.find(':')
if separator > 0:
hostname = hostname[:separator]
dns['elapsed'] = dns['end'] - dns['start']
if hostname not in dns_lookups:
dns_lookups[hostname] = dns
# collect all of the times for all of the DNS lookups for that host
if 'times' not in dns_lookups[hostname]:
dns_lookups[hostname]['times'] = []
dns_lookups[hostname]['times'].append({
'start': dns['start'],
'end': dns['end'],
'elapsed': dns['elapsed'],
})
# Go through the requests and assign the DNS lookups as needed
for request in requests:
if 'connect_start' in request:
hostname = urlparse.urlparse(request['url']).hostname
if hostname in dns_lookups and 'claimed' not in dns_lookups[hostname]:
dns = dns_lookups[hostname]
dns['claimed'] = True
# Find the longest DNS time that completed before connect_start
if 'times' in dns_lookups[hostname]:
elapsed = None
for dns in dns_lookups[hostname]['times']:
dns['end'] = min(dns['end'], request['connect_start'])
if dns['end'] >= dns['start']:
dns['elapsed'] = dns['end'] - dns['start']
if elapsed is None or dns['elapsed'] > elapsed:
elapsed = dns['elapsed']
request['dns_start'] = dns['start']
request['dns_end'] = dns['end']
# Find the start timestamp if we didn't have one already
times = ['dns_start', 'dns_end',
'connect_start', 'connect_end',
'ssl_start', 'ssl_end',
'start', 'created', 'first_byte', 'end']
for request in requests:
for time_name in times:
if time_name in request:
if self.start_time is None or request[time_name] < self.start_time:
self.start_time = request[time_name]
# Go through and adjust all of the times to be relative in ms
if self.start_time is not None:
for request in requests:
for time_name in times:
if time_name in request:
request[time_name] = \
float(request[time_name] - self.start_time) / 1000.0
for key in ['chunks', 'chunks_in', 'chunks_out']:
if key in request:
for chunk in request[key]:
if 'ts' in chunk:
chunk['ts'] = float(chunk['ts'] - self.start_time) / 1000.0
else:
requests = []
if not len(requests):
requests = None
self.netlog_requests = requests
return requests
def ProcessNetlogConnectJobEvent(self, trace_event):
"""Connect jobs link sockets to DNS lookups/group names"""
if 'connect_job' not in self.netlog:
self.netlog['connect_job'] = {}
request_id = trace_event['id']
if request_id not in self.netlog['connect_job']:
self.netlog['connect_job'][request_id] = {}
params = trace_event['args']['params'] if 'params' in trace_event['args'] else {}
entry = self.netlog['connect_job'][request_id]
name = trace_event['name']
if 'source_dependency' in params and 'id' in params['source_dependency']:
if name == 'CONNECT_JOB_SET_SOCKET':
socket_id = params['source_dependency']['id']
entry['socket'] = socket_id
if 'socket' in self.netlog and socket_id in self.netlog['socket']:
if 'group' in entry:
self.netlog['socket'][socket_id]['group'] = entry['group']
if 'dns' in entry:
self.netlog['socket'][socket_id]['dns'] = entry['dns']
if 'group_name' in params:
entry['group'] = params['group_name']
def ProcessNetlogStreamJobEvent(self, trace_event):
"""Strem jobs leank requests to sockets"""
if 'stream_job' not in self.netlog:
self.netlog['stream_job'] = {}
request_id = trace_event['id']
if request_id not in self.netlog['stream_job']:
self.netlog['stream_job'][request_id] = {}
params = trace_event['args']['params'] if 'params' in trace_event['args'] else {}
entry = self.netlog['stream_job'][request_id]
name = trace_event['name']
if 'source_dependency' in params and 'id' in params['source_dependency']:
if name == 'SOCKET_POOL_BOUND_TO_SOCKET':
socket_id = params['source_dependency']['id']
entry['socket'] = socket_id
if 'url_request' in entry and entry['urlrequest'] in self.netlog['urlrequest']:
self.netlog['urlrequest'][entry['urlrequest']]['socket'] = socket_id
if name == 'HTTP_STREAM_JOB_BOUND_TO_REQUEST':
url_request_id = params['source_dependency']['id']
entry['url_request'] = url_request_id
if url_request_id in self.netlog['url_request']:
url_request = self.netlog['url_request'][url_request_id]
if 'socket' in entry:
url_request['socket'] = entry['socket']
if 'h2_session' in entry:
url_request['h2_session'] = entry['h2_session']
if name == 'HTTP2_SESSION_POOL_IMPORTED_SESSION_FROM_SOCKET' or \
name == 'HTTP2_SESSION_POOL_FOUND_EXISTING_SESSION' or \
name == 'HTTP2_SESSION_POOL_FOUND_EXISTING_SESSION_FROM_IP_POOL':
h2_session_id = params['source_dependency']['id']
entry['h2_session'] = h2_session_id
if h2_session_id in self.netlog['h2_session'] and 'socket' in self.netlog['h2_session'][h2_session_id]:
entry['socket'] = self.netlog['h2_session'][h2_session_id]['socket']
if 'url_request' in entry and entry['urlrequest'] in self.netlog['urlrequest']:
self.netlog['urlrequest'][entry['urlrequest']]['h2_session'] = h2_session_id
def ProcessNetlogHttp2SessionEvent(self, trace_event):
"""Raw H2 session information (linked to sockets and requests)"""
if 'h2_session' not in self.netlog:
self.netlog['h2_session'] = {}
session_id = trace_event['id']
if session_id not in self.netlog['h2_session']:
self.netlog['h2_session'][session_id] = {'stream': {}}
params = trace_event['args']['params'] if 'params' in trace_event['args'] else {}
entry = self.netlog['h2_session'][session_id]
name = trace_event['name']
if 'source_dependency' in params and 'id' in params['source_dependency']:
if name == 'HTTP2_SESSION_INITIALIZED':
socket_id = params['source_dependency']['id']
entry['socket'] = socket_id
if 'socket' in self.netlog and socket_id in self.netlog['socket']:
self.netlog['socket']['h2_session'] = session_id
if 'host' not in entry and 'host' in params:
entry['host'] = params['host']
if 'protocol' not in entry and 'protocol' in params:
entry['protocol'] = params['protocol']
if 'stream_id' in params:
stream_id = params['stream_id']
if stream_id not in entry['stream']:
entry['stream'][stream_id] = {'bytes_in': 0, 'chunks': []}
stream = entry['stream'][stream_id]
if 'exclusive' in params:
stream['exclusive'] = params['exclusive']
if 'parent_stream_id' in params:
stream['parent_stream_id'] = params['parent_stream_id']
if 'weight' in params:
stream['weight'] = params['weight']
if 'url' in params:
stream['url'] = params['url'].split('#', 1)[0]
if 'url_request' in stream:
request_id = stream['url_request']
if 'url_request' in self.netlog and request_id in self.netlog['url_request']:
request = self.netlog['url_request'][request_id]
request['url'] = params['url'].split('#', 1)[0]
if name == 'HTTP2_SESSION_RECV_DATA' and 'size' in params:
stream['end'] = trace_event['ts']
if 'first_byte' not in stream:
stream['first_byte'] = trace_event['ts']
stream['bytes_in'] += params['size']
stream['chunks'].append({'ts': trace_event['ts'], 'bytes': params['size']})
if name == 'HTTP2_SESSION_SEND_HEADERS':
if 'headers' in params:
stream['request_headers'] = params['headers']
if name == 'HTTP2_SESSION_RECV_HEADERS':
if 'first_byte' not in stream:
stream['first_byte'] = trace_event['ts']
stream['end'] = trace_event['ts']
if 'headers' in params:
stream['response_headers'] = params['headers']
if name == 'HTTP2_STREAM_ADOPTED_PUSH_STREAM' and 'url' in params and \
'url_request' in self.netlog:
# Find the phantom request with the matching url and mark it
url = params['url'].split('#', 1)[0]
for request_id in self.netlog['url_request']:
request = self.netlog['url_request'][request_id]
if 'url' in request and url == request['url'] and 'start' not in request:
request['phantom'] = True
break
if name == 'HTTP2_SESSION_RECV_PUSH_PROMISE' and 'promised_stream_id' in params:
# Create a fake request to match the push
if 'url_request' not in self.netlog:
self.netlog['url_request'] = {}
request_id = self.netlog['next_request_id']
self.netlog['next_request_id'] += 1
self.netlog['url_request'][request_id] = {'bytes_in': 0,
'chunks': [],
'created': trace_event['ts']}
request = self.netlog['url_request'][request_id]
stream_id = params['promised_stream_id']
if stream_id not in entry['stream']:
entry['stream'][stream_id] = {'bytes_in': 0, 'chunks': []}
stream = entry['stream'][stream_id]
if 'headers' in params:
stream['request_headers'] = params['headers']
# synthesize a URL from the request headers
scheme = None
authority = None
path = None
for header in params['headers']:
match = re.search(r':scheme: (.+)', header)
if match:
scheme = match.group(1)
match = re.search(r':authority: (.+)', header)
if match:
authority = match.group(1)
match = re.search(r':path: (.+)', header)
if match:
path = match.group(1)
if scheme is not None and authority is not None and path is not None:
url = '{0}://{1}{2}'.format(scheme, authority, path).split('#', 1)[0]
request['url'] = url
stream['url'] = url
request['protocol'] = 'HTTP/2'
request['h2_session'] = session_id
request['stream_id'] = stream_id
request['start'] = trace_event['ts']
request['pushed'] = True
stream['pushed'] = True
stream['url_request'] = request_id
if 'socket' in entry:
request['socket'] = entry['socket']
if name == 'HTTP2_SESSION_RECV_SETTING' and 'id' in params and 'value' in params:
setting_id = None
match = re.search(r'\d+ \((.+)\)', params['id'])
if match:
setting_id = match.group(1)
if 'server_settings' not in entry:
entry['server_settings'] = {}
entry['server_settings'][setting_id] = params['value']
def ProcessNetlogDnsEvent(self, trace_event):
if 'dns' not in self.netlog:
self.netlog['dns'] = {}
request_id = trace_event['id']
if request_id not in self.netlog['dns']:
self.netlog['dns'][request_id] = {}
params = trace_event['args']['params'] if 'params' in trace_event['args'] else {}
entry = self.netlog['dns'][request_id]
name = trace_event['name']
if 'source_dependency' in params and 'id' in params['source_dependency']:
parent_id = params['source_dependency']['id']
if 'connect_job' in self.netlog and parent_id in self.netlog['connect_job']:
self.netlog['connect_job'][parent_id]['dns'] = request_id
if name == 'HOST_RESOLVER_IMPL_REQUEST' and 'ph' in trace_event:
if trace_event['ph'] == 'b':
if 'start' not in entry or trace_event['ts'] < entry['start']:
entry['start'] = trace_event['ts']
if trace_event['ph'] == 'e':
if 'end' not in entry or trace_event['ts'] > entry['end']:
entry['end'] = trace_event['ts']
if 'start' not in entry and name == 'HOST_RESOLVER_IMPL_ATTEMPT_STARTED':
entry['start'] = trace_event['ts']
if name == 'HOST_RESOLVER_IMPL_ATTEMPT_FINISHED':
entry['end'] = trace_event['ts']
if name == 'HOST_RESOLVER_IMPL_CACHE_HIT':
if 'end' not in entry or trace_event['ts'] > entry['end']:
entry['end'] = trace_event['ts']
if 'host' not in entry and 'host' in params:
entry['host'] = params['host']
if 'address_list' in params:
entry['address_list'] = params['address_list']
def ProcessNetlogSocketEvent(self, trace_event):
if 'socket' not in self.netlog:
self.netlog['socket'] = {}
request_id = trace_event['id']
if request_id not in self.netlog['socket']:
self.netlog['socket'][request_id] = {'bytes_out': 0, 'bytes_in': 0,
'chunks_out': [], 'chunks_in': []}
params = trace_event['args']['params'] if 'params' in trace_event['args'] else {}
entry = self.netlog['socket'][request_id]
name = trace_event['name']
if 'address' in params:
entry['address'] = params['address']
if 'source_address' in params:
entry['source_address'] = params['source_address']
if 'connect_start' not in entry and name == 'TCP_CONNECT_ATTEMPT' and \
trace_event['ph'] == 'b':
entry['connect_start'] = trace_event['ts']
if name == 'TCP_CONNECT_ATTEMPT' and trace_event['ph'] == 'e':
entry['connect_end'] = trace_event['ts']
if 'ssl_start' not in entry and name == 'SSL_CONNECT' and trace_event['ph'] == 'b':
entry['ssl_start'] = trace_event['ts']
if name == 'SSL_CONNECT' and trace_event['ph'] == 'e':
entry['ssl_end'] = trace_event['ts']
if 'version' in params:
entry['tls_version'] = params['version']
if 'is_resumed' in params:
entry['tls_resumed'] = params['is_resumed']
if 'next_proto' in params:
entry['tls_next_proto'] = params['next_proto']
if 'cipher_suite' in params:
entry['tls_cipher_suite'] = params['cipher_suite']
if name == 'SOCKET_BYTES_SENT' and 'byte_count' in params:
entry['bytes_out'] += params['byte_count']
entry['chunks_out'].append({'ts': trace_event['ts'], 'bytes': params['byte_count']})
if name == 'SOCKET_BYTES_RECEIVED' and 'byte_count' in params:
entry['bytes_in'] += params['byte_count']
entry['chunks_in'].append({'ts': trace_event['ts'], 'bytes': params['byte_count']})
if name == 'SSL_CERTIFICATES_RECEIVED' and 'certificates' in params:
if 'certificates' not in entry:
entry['certificates'] = []
entry['certificates'].extend(params['certificates'])
def ProcessNetlogUrlRequestEvent(self, trace_event):
if 'url_request' not in self.netlog:
self.netlog['url_request'] = {}
request_id = trace_event['id']
if request_id not in self.netlog['url_request']:
self.netlog['url_request'][request_id] = {'bytes_in': 0,
'chunks': [],
'created': trace_event['ts']}
params = trace_event['args']['params'] if 'params' in trace_event['args'] else {}
entry = self.netlog['url_request'][request_id]
name = trace_event['name']
if 'priority' in params:
entry['priority'] = params['priority']
if 'method' in params:
entry['method'] = params['method']
if 'url' in params:
entry['url'] = params['url'].split('#', 1)[0]
if 'start' not in entry and name == 'HTTP_TRANSACTION_SEND_REQUEST' and \
trace_event['ph'] == 'e':
entry['start'] = trace_event['ts']
if 'headers' in params and name == 'HTTP_TRANSACTION_SEND_REQUEST_HEADERS':
entry['request_headers'] = params['headers']
if 'headers' in params and name == 'HTTP_TRANSACTION_HTTP2_SEND_REQUEST_HEADERS':
if isinstance(params['headers'], dict):
entry['request_headers'] = []
for key in params['headers']:
entry['request_headers'].append('{0}: {1}'.format(key, params['headers'][key]))
else:
entry['request_headers'] = params['headers']
entry['protocol'] = 'HTTP/2'
if 'headers' in params and name == 'HTTP_TRANSACTION_READ_RESPONSE_HEADERS':
entry['response_headers'] = params['headers']
if 'first_byte' not in entry:
entry['first_byte'] = trace_event['ts']
entry['end'] = trace_event['ts']
if 'byte_count' in params and name == 'URL_REQUEST_JOB_BYTES_READ':
entry['has_raw_bytes'] = True
entry['end'] = trace_event['ts']
entry['bytes_in'] += params['byte_count']
entry['chunks'].append({'ts': trace_event['ts'], 'bytes': params['byte_count']})
if 'byte_count' in params and name == 'URL_REQUEST_JOB_FILTERED_BYTES_READ':
entry['end'] = trace_event['ts']
if 'uncompressed_bytes_in' not in entry:
entry['uncompressed_bytes_in'] = 0
entry['uncompressed_bytes_in'] += params['byte_count']
if 'has_raw_bytes' not in entry or not entry['has_raw_bytes']:
entry['bytes_in'] += params['byte_count']
entry['chunks'].append({'ts': trace_event['ts'], 'bytes': params['byte_count']})
if 'stream_id' in params:
entry['stream_id'] = params['stream_id']
if name == 'URL_REQUEST_REDIRECTED':
new_id = self.netlog['next_request_id']
self.netlog['next_request_id'] += 1
self.netlog['url_request'][new_id] = entry
del self.netlog['url_request'][request_id]
#######################################################################
# V8 call stats
#######################################################################
def ProcessV8Event(self, trace_event):
try:
if self.start_time is not None and self.cpu['main_thread'] is not None and trace_event['ts'] >= self.start_time and \
"name" in trace_event:
thread = '{0}:{1}'.format(
trace_event['pid'], trace_event['tid'])
if trace_event["ph"] == "B":
if thread not in self.v8stack:
self.v8stack[thread] = []
self.v8stack[thread].append(trace_event)
else:
duration = 0.0
if trace_event["ph"] == "E" and thread in self.v8stack:
start_event = self.v8stack[thread].pop()
if start_event['name'] == trace_event['name'] and 'ts' in start_event and start_event['ts'] <= trace_event['ts']:
duration = trace_event['ts'] - start_event['ts']
elif trace_event['ph'] == 'X' and 'dur' in trace_event:
duration = trace_event['dur']
if self.v8stats is None:
self.v8stats = {'threads': {}}
if thread not in self.v8stats['threads']:
self.v8stats['threads'][thread] = {}
name = trace_event["name"]
if name not in self.v8stats['threads'][thread]:
self.v8stats['threads'][thread][name] = {"dur": 0.0, "count": 0}
self.v8stats['threads'][thread][name]['dur'] += float(duration) / 1000.0
self.v8stats['threads'][thread][name]['count'] += 1
if 'args' in trace_event and 'runtime-call-stats' in trace_event["args"]:
for stat in trace_event["args"]["runtime-call-stats"]:
if len(trace_event["args"]["runtime-call-stats"][stat]) == 2:
if 'breakdown' not in self.v8stats['threads'][thread][name]:
self.v8stats['threads'][thread][name]['breakdown'] = {}
if stat not in self.v8stats['threads'][thread][name]['breakdown']:
self.v8stats['threads'][thread][name]['breakdown'][stat] = {"count": 0, "dur": 0.0}
self.v8stats['threads'][thread][name]['breakdown'][stat]["count"] += int(trace_event["args"]["runtime-call-stats"][stat][0])
self.v8stats['threads'][thread][name]['breakdown'][stat]["dur"] += float(trace_event["args"]["runtime-call-stats"][stat][1]) / 1000.0
except BaseException:
pass
pass
##########################################################################
# Main Entry Point
##########################################################################
def main():
import argparse
parser = argparse.ArgumentParser(description='Chrome trace parser.',
prog='trace-parser')
parser.add_argument('-v', '--verbose', action='count',
help="Increase verbosity (specify multiple times for more). -vvvv for full debug output.")
parser.add_argument('-t', '--trace', help="Input trace file.")
parser.add_argument('-l', '--timeline',
help="Input timeline file (iOS or really old Chrome).")
parser.add_argument('-c', '--cpu', help="Output CPU time slices file.")
parser.add_argument(
'-j', '--js', help="Output Javascript per-script parse/evaluate/execute timings.")
parser.add_argument('-u', '--user', help="Output user timing file.")
parser.add_argument('-f', '--features',
help="Output blink feature usage file.")
parser.add_argument('-i', '--interactive',
help="Output list of interactive times.")
parser.add_argument('-n', '--netlog', help="Output netlog details file.")
parser.add_argument('-s', '--stats', help="Output v8 Call stats file.")
options, unknown = parser.parse_known_args()
# Set up logging
log_level = logging.CRITICAL
if options.verbose == 1:
log_level = logging.ERROR
elif options.verbose == 2:
log_level = logging.WARNING
elif options.verbose == 3:
log_level = logging.INFO
elif options.verbose >= 4:
log_level = logging.DEBUG
logging.basicConfig(
level=log_level, format="%(asctime)s.%(msecs)03d - %(message)s", datefmt="%H:%M:%S")
if not options.trace and not options.timeline:
parser.error("Input trace or timeline file is not specified.")
start = time.time()
trace = Trace()
if options.trace:
trace.Process(options.trace)
elif options.timeline:
trace.ProcessTimeline(options.timeline)
if options.user:
trace.WriteUserTiming(options.user)
if options.cpu:
trace.WriteCPUSlices(options.cpu)
if options.js:
trace.WriteScriptTimings(options.js)
if options.features:
trace.WriteFeatureUsage(options.features)
if options.interactive:
trace.WriteInteractive(options.interactive)
if options.netlog:
trace.WriteNetlog(options.netlog)
if options.stats:
trace.WriteV8Stats(options.stats)
end = time.time()
elapsed = end - start
logging.debug("Elapsed Time: {0:0.4f}".format(elapsed))
##########################################################################
# Blink feature names from https://cs.chromium.org/chromium/src/third_party/blink/public/mojom/web_feature/web_feature.mojom
##########################################################################
BLINK_FEATURES = {
"0": "PageDestruction",
"3": "PrefixedIndexedDB",
"4": "WorkerStart",
"5": "SharedWorkerStart",
"9": "UnprefixedIndexedDB",
"10": "OpenWebDatabase",
"13": "UnprefixedRequestAnimationFrame",
"14": "PrefixedRequestAnimationFrame",
"15": "ContentSecurityPolicy",
"16": "ContentSecurityPolicyReportOnly",
"18": "PrefixedTransitionEndEvent",
"19": "UnprefixedTransitionEndEvent",
"20": "PrefixedAndUnprefixedTransitionEndEvent",
"21": "AutoFocusAttribute",
"23": "DataListElement",
"24": "FormAttribute",
"25": "IncrementalAttribute",
"26": "InputTypeColor",
"27": "InputTypeDate",
"29": "InputTypeDateTimeFallback",
"30": "InputTypeDateTimeLocal",
"31": "InputTypeEmail",
"32": "InputTypeMonth",
"33": "InputTypeNumber",
"34": "InputTypeRange",
"35": "InputTypeSearch",
"36": "InputTypeTel",
"37": "InputTypeTime",
"38": "InputTypeURL",
"39": "InputTypeWeek",
"40": "InputTypeWeekFallback",
"41": "ListAttribute",
"42": "MaxAttribute",
"43": "MinAttribute",
"44": "PatternAttribute",
"45": "PlaceholderAttribute",
"47": "PrefixedDirectoryAttribute",
"49": "RequiredAttribute",
"51": "StepAttribute",
"52": "PageVisits",
"53": "HTMLMarqueeElement",
"55": "Reflection",
"57": "PrefixedStorageInfo",
"58": "XFrameOptions",
"59": "XFrameOptionsSameOrigin",
"60": "XFrameOptionsSameOriginWithBadAncestorChain",
"61": "DeprecatedFlexboxWebContent",
"62": "DeprecatedFlexboxChrome",
"63": "DeprecatedFlexboxChromeExtension",
"65": "UnprefixedPerformanceTimeline",
"67": "UnprefixedUserTiming",
"69": "WindowEvent",
"70": "ContentSecurityPolicyWithBaseElement",
"74": "DocumentClear",
"77": "XMLDocument",
"78": "XSLProcessingInstruction",
"79": "XSLTProcessor",
"80": "SVGSwitchElement",
"83": "DocumentAll",
"84": "FormElement",
"85": "DemotedFormElement",
"90": "SVGAnimationElement",
"96": "LineClamp",
"97": "SubFrameBeforeUnloadRegistered",
"98": "SubFrameBeforeUnloadFired",
"102": "ConsoleMarkTimeline",
"111": "DocumentCreateAttribute",
"112": "DocumentCreateAttributeNS",
"113": "DocumentCreateCDATASection",
"115": "DocumentXMLEncoding",
"116": "DocumentXMLStandalone",
"117": "DocumentXMLVersion",
"123": "NavigatorProductSub",
"124": "NavigatorVendor",
"125": "NavigatorVendorSub",
"128": "PrefixedAnimationEndEvent",
"129": "UnprefixedAnimationEndEvent",
"130": "PrefixedAndUnprefixedAnimationEndEvent",
"131": "PrefixedAnimationStartEvent",
"132": "UnprefixedAnimationStartEvent",
"133": "PrefixedAndUnprefixedAnimationStartEvent",
"134": "PrefixedAnimationIterationEvent",
"135": "UnprefixedAnimationIterationEvent",
"136": "PrefixedAndUnprefixedAnimationIterationEvent",
"137": "EventReturnValue",
"138": "SVGSVGElement",
"143": "DOMSubtreeModifiedEvent",
"144": "DOMNodeInsertedEvent",
"145": "DOMNodeRemovedEvent",
"146": "DOMNodeRemovedFromDocumentEvent",
"147": "DOMNodeInsertedIntoDocumentEvent",
"148": "DOMCharacterDataModifiedEvent",
"150": "DocumentAllLegacyCall",
"152": "HTMLEmbedElementLegacyCall",
"153": "HTMLObjectElementLegacyCall",
"155": "GetMatchedCSSRules",
"160": "AttributeOwnerElement",
"162": "AttributeSpecified",
"164": "PrefixedAudioDecodedByteCount",
"165": "PrefixedVideoDecodedByteCount",
"166": "PrefixedVideoSupportsFullscreen",
"167": "PrefixedVideoDisplayingFullscreen",
"168": "PrefixedVideoEnterFullscreen",
"169": "PrefixedVideoExitFullscreen",
"170": "PrefixedVideoEnterFullScreen",
"171": "PrefixedVideoExitFullScreen",
"172": "PrefixedVideoDecodedFrameCount",
"173": "PrefixedVideoDroppedFrameCount",
"176": "PrefixedElementRequestFullscreen",
"177": "PrefixedElementRequestFullScreen",
"178": "BarPropLocationbar",
"179": "BarPropMenubar",
"180": "BarPropPersonalbar",
"181": "BarPropScrollbars",
"182": "BarPropStatusbar",
"183": "BarPropToolbar",
"184": "InputTypeEmailMultiple",
"185": "InputTypeEmailMaxLength",
"186": "InputTypeEmailMultipleMaxLength",
"190": "InputTypeText",
"191": "InputTypeTextMaxLength",
"192": "InputTypePassword",
"193": "InputTypePasswordMaxLength",
"196": "PrefixedPageVisibility",
"198": "CSSStyleSheetInsertRuleOptionalArg",
"200": "DocumentBeforeUnloadRegistered",
"201": "DocumentBeforeUnloadFired",
"202": "DocumentUnloadRegistered",
"203": "DocumentUnloadFired",
"204": "SVGLocatableNearestViewportElement",
"205": "SVGLocatableFarthestViewportElement",
"209": "SVGPointMatrixTransform",
"211": "DOMFocusInOutEvent",
"212": "FileGetLastModifiedDate",
"213": "HTMLElementInnerText",
"214": "HTMLElementOuterText",
"215": "ReplaceDocumentViaJavaScriptURL",
"217": "ElementPrefixedMatchesSelector",
"219": "CSSStyleSheetRules",
"220": "CSSStyleSheetAddRule",
"221": "CSSStyleSheetRemoveRule",
"222": "InitMessageEvent",
"233": "PrefixedDevicePixelRatioMediaFeature",
"234": "PrefixedMaxDevicePixelRatioMediaFeature",
"235": "PrefixedMinDevicePixelRatioMediaFeature",
"237": "PrefixedTransform3dMediaFeature",
"240": "PrefixedStorageQuota",
"243": "ResetReferrerPolicy",
"244": "CaseInsensitiveAttrSelectorMatch",
"246": "FormNameAccessForImageElement",
"247": "FormNameAccessForPastNamesMap",
"248": "FormAssociationByParser",
"250": "SVGSVGElementInDocument",
"251": "SVGDocumentRootElement",
"257": "WorkerSubjectToCSP",
"258": "WorkerAllowedByChildBlockedByScript",
"260": "DeprecatedWebKitGradient",
"261": "DeprecatedWebKitLinearGradient",
"262": "DeprecatedWebKitRepeatingLinearGradient",
"263": "DeprecatedWebKitRadialGradient",
"264": "DeprecatedWebKitRepeatingRadialGradient",
"267": "PrefixedImageSmoothingEnabled",
"268": "UnprefixedImageSmoothingEnabled",
"274": "TextAutosizing",
"276": "HTMLAnchorElementPingAttribute",
"279": "SVGClassName",
"281": "HTMLMediaElementSeekToFragmentStart",
"282": "HTMLMediaElementPauseAtFragmentEnd",
"283": "PrefixedWindowURL",
"285": "WindowOrientation",
"286": "DOMStringListContains",
"287": "DocumentCaptureEvents",
"288": "DocumentReleaseEvents",
"289": "WindowCaptureEvents",
"290": "WindowReleaseEvents",
"295": "DocumentXPathCreateExpression",
"296": "DocumentXPathCreateNSResolver",
"297": "DocumentXPathEvaluate",
"298": "AttrGetValue",
"299": "AttrSetValue",
"300": "AnimationConstructorKeyframeListEffectObjectTiming",
"302": "AnimationConstructorKeyframeListEffectNoTiming",
"303": "AttrSetValueWithElement",
"304": "PrefixedCancelAnimationFrame",
"305": "PrefixedCancelRequestAnimationFrame",
"306": "NamedNodeMapGetNamedItem",
"307": "NamedNodeMapSetNamedItem",
"308": "NamedNodeMapRemoveNamedItem",
"309": "NamedNodeMapItem",
"310": "NamedNodeMapGetNamedItemNS",
"311": "NamedNodeMapSetNamedItemNS",
"312": "NamedNodeMapRemoveNamedItemNS",
"318": "PrefixedDocumentIsFullscreen",
"320": "PrefixedDocumentCurrentFullScreenElement",
"321": "PrefixedDocumentCancelFullScreen",
"322": "PrefixedDocumentFullscreenEnabled",
"323": "PrefixedDocumentFullscreenElement",
"324": "PrefixedDocumentExitFullscreen",
"325": "SVGForeignObjectElement",
"327": "SelectionSetPosition",
"328": "AnimationFinishEvent",
"329": "SVGSVGElementInXMLDocument",
"341": "PrefixedPerformanceClearResourceTimings",
"342": "PrefixedPerformanceSetResourceTimingBufferSize",
"343": "EventSrcElement",
"344": "EventCancelBubble",
"345": "EventPath",
"347": "NodeIteratorDetach",
"348": "AttrNodeValue",
"349": "AttrTextContent",
"350": "EventGetReturnValueTrue",
"351": "EventGetReturnValueFalse",
"352": "EventSetReturnValueTrue",
"353": "EventSetReturnValueFalse",
"356": "WindowOffscreenBuffering",
"357": "WindowDefaultStatus",
"358": "WindowDefaultstatus",
"361": "PrefixedTransitionEventConstructor",
"362": "PrefixedMutationObserverConstructor",
"363": "PrefixedIDBCursorConstructor",
"364": "PrefixedIDBDatabaseConstructor",
"365": "PrefixedIDBFactoryConstructor",
"366": "PrefixedIDBIndexConstructor",
"367": "PrefixedIDBKeyRangeConstructor",
"368": "PrefixedIDBObjectStoreConstructor",
"369": "PrefixedIDBRequestConstructor",
"370": "PrefixedIDBTransactionConstructor",
"371": "NotificationPermission",
"372": "RangeDetach",
"386": "PrefixedFileRelativePath",
"387": "DocumentCaretRangeFromPoint",
"389": "ElementScrollIntoViewIfNeeded",
"393": "RangeExpand",
"396": "HTMLImageElementX",
"397": "HTMLImageElementY",
"400": "SelectionBaseNode",
"401": "SelectionBaseOffset",
"402": "SelectionExtentNode",
"403": "SelectionExtentOffset",
"404": "SelectionType",
"405": "SelectionModify",
"406": "SelectionSetBaseAndExtent",
"407": "SelectionEmpty",
"409": "VTTCue",
"410": "VTTCueRender",
"411": "VTTCueRenderVertical",
"412": "VTTCueRenderSnapToLinesFalse",
"413": "VTTCueRenderLineNotAuto",
"414": "VTTCueRenderPositionNot50",
"415": "VTTCueRenderSizeNot100",
"416": "VTTCueRenderAlignNotMiddle",
"417": "ElementRequestPointerLock",
"418": "VTTCueRenderRtl",
"419": "PostMessageFromSecureToInsecure",
"420": "PostMessageFromInsecureToSecure",
"421": "DocumentExitPointerLock",
"422": "DocumentPointerLockElement",
"424": "PrefixedCursorZoomIn",
"425": "PrefixedCursorZoomOut",
"429": "TextEncoderConstructor",
"430": "TextEncoderEncode",
"431": "TextDecoderConstructor",
"432": "TextDecoderDecode",
"433": "FocusInOutEvent",
"434": "MouseEventMovementX",
"435": "MouseEventMovementY",
"440": "DocumentFonts",
"441": "MixedContentFormsSubmitted",
"442": "FormsSubmitted",
"443": "TextInputEventOnInput",
"444": "TextInputEventOnTextArea",
"445": "TextInputEventOnContentEditable",
"446": "TextInputEventOnNotNode",
"447": "WebkitBeforeTextInsertedOnInput",
"448": "WebkitBeforeTextInsertedOnTextArea",
"449": "WebkitBeforeTextInsertedOnContentEditable",
"450": "WebkitBeforeTextInsertedOnNotNode",
"451": "WebkitEditableContentChangedOnInput",
"452": "WebkitEditableContentChangedOnTextArea",
"453": "WebkitEditableContentChangedOnContentEditable",
"454": "WebkitEditableContentChangedOnNotNode",
"455": "HTMLImports",
"456": "ElementCreateShadowRoot",
"457": "DocumentRegisterElement",
"458": "EditingAppleInterchangeNewline",
"459": "EditingAppleConvertedSpace",
"460": "EditingApplePasteAsQuotation",
"461": "EditingAppleStyleSpanClass",
"462": "EditingAppleTabSpanClass",
"463": "HTMLImportsAsyncAttribute",
"465": "XMLHttpRequestSynchronous",
"466": "CSSSelectorPseudoUnresolved",
"467": "CSSSelectorPseudoShadow",
"468": "CSSSelectorPseudoContent",
"469": "CSSSelectorPseudoHost",
"470": "CSSSelectorPseudoHostContext",
"471": "CSSDeepCombinator",
"473": "UseAsm",
"475": "DOMWindowOpen",
"476": "DOMWindowOpenFeatures",
"478": "MediaStreamTrackGetSources",
"479": "AspectRatioFlexItem",
"480": "DetailsElement",
"481": "DialogElement",
"482": "MapElement",
"483": "MeterElement",
"484": "ProgressElement",
"490": "PrefixedHTMLElementDropzone",
"491": "WheelEventWheelDeltaX",
"492": "WheelEventWheelDeltaY",
"493": "WheelEventWheelDelta",
"494": "SendBeacon",
"495": "SendBeaconQuotaExceeded",
"501": "SVGSMILElementInDocument",
"502": "MouseEventOffsetX",
"503": "MouseEventOffsetY",
"504": "MouseEventX",
"505": "MouseEventY",
"506": "MouseEventFromElement",
"507": "MouseEventToElement",
"508": "RequestFileSystem",
"509": "RequestFileSystemWorker",
"510": "RequestFileSystemSyncWorker",
"519": "SVGStyleElementTitle",
"520": "PictureSourceSrc",
"521": "Picture",
"522": "Sizes",
"523": "SrcsetXDescriptor",
"524": "SrcsetWDescriptor",
"525": "SelectionContainsNode",
"529": "XMLExternalResourceLoad",
"530": "MixedContentPrivateHostnameInPublicHostname",
"531": "LegacyProtocolEmbeddedAsSubresource",
"532": "RequestedSubresourceWithEmbeddedCredentials",
"533": "NotificationCreated",
"534": "NotificationClosed",
"535": "NotificationPermissionRequested",
"538": "ConsoleTimeline",
"539": "ConsoleTimelineEnd",
"540": "SRIElementWithMatchingIntegrityAttribute",
"541": "SRIElementWithNonMatchingIntegrityAttribute",
"542": "SRIElementWithUnparsableIntegrityAttribute",
"545": "V8Animation_StartTime_AttributeGetter",
"546": "V8Animation_StartTime_AttributeSetter",
"547": "V8Animation_CurrentTime_AttributeGetter",
"548": "V8Animation_CurrentTime_AttributeSetter",
"549": "V8Animation_PlaybackRate_AttributeGetter",
"550": "V8Animation_PlaybackRate_AttributeSetter",
"551": "V8Animation_PlayState_AttributeGetter",
"552": "V8Animation_Finish_Method",
"553": "V8Animation_Play_Method",
"554": "V8Animation_Pause_Method",
"555": "V8Animation_Reverse_Method",
"556": "BreakIterator",
"557": "ScreenOrientationAngle",
"558": "ScreenOrientationType",
"559": "ScreenOrientationLock",
"560": "ScreenOrientationUnlock",
"561": "GeolocationSecureOrigin",
"562": "GeolocationInsecureOrigin",
"563": "NotificationSecureOrigin",
"564": "NotificationInsecureOrigin",
"565": "NotificationShowEvent",
"569": "SVGTransformListConsolidate",
"570": "SVGAnimatedTransformListBaseVal",
"571": "QuotedAnimationName",
"572": "QuotedKeyframesRule",
"573": "SrcsetDroppedCandidate",
"574": "WindowPostMessage",
"575": "WindowPostMessageWithLegacyTargetOriginArgument",
"576": "RenderRuby",
"578": "ScriptElementWithInvalidTypeHasSrc",
"581": "XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload",
"582": "CSSSelectorPseudoScrollbar",
"583": "CSSSelectorPseudoScrollbarButton",
"584": "CSSSelectorPseudoScrollbarThumb",
"585": "CSSSelectorPseudoScrollbarTrack",
"586": "CSSSelectorPseudoScrollbarTrackPiece",
"587": "LangAttribute",
"588": "LangAttributeOnHTML",
"589": "LangAttributeOnBody",
"590": "LangAttributeDoesNotMatchToUILocale",
"591": "InputTypeSubmit",
"592": "InputTypeSubmitWithValue",
"593": "SetReferrerPolicy",
"595": "MouseEventWhich",
"598": "UIEventWhich",
"599": "TextWholeText",
"603": "NotificationCloseEvent",
"606": "StyleMedia",
"607": "StyleMediaType",
"608": "StyleMediaMatchMedium",
"609": "MixedContentPresent",
"610": "MixedContentBlockable",
"611": "MixedContentAudio",
"612": "MixedContentDownload",
"613": "MixedContentFavicon",
"614": "MixedContentImage",
"615": "MixedContentInternal",
"616": "MixedContentPlugin",
"617": "MixedContentPrefetch",
"618": "MixedContentVideo",
"620": "AudioListenerDopplerFactor",
"621": "AudioListenerSpeedOfSound",
"622": "AudioListenerSetVelocity",
"628": "CSSSelectorPseudoFullScreenAncestor",
"629": "CSSSelectorPseudoFullScreen",
"630": "WebKitCSSMatrix",
"631": "AudioContextCreateAnalyser",
"632": "AudioContextCreateBiquadFilter",
"633": "AudioContextCreateBufferSource",
"634": "AudioContextCreateChannelMerger",
"635": "AudioContextCreateChannelSplitter",
"636": "AudioContextCreateConvolver",
"637": "AudioContextCreateDelay",
"638": "AudioContextCreateDynamicsCompressor",
"639": "AudioContextCreateGain",
"640": "AudioContextCreateMediaElementSource",
"641": "AudioContextCreateMediaStreamDestination",
"642": "AudioContextCreateMediaStreamSource",
"643": "AudioContextCreateOscillator",
"645": "AudioContextCreatePeriodicWave",
"646": "AudioContextCreateScriptProcessor",
"647": "AudioContextCreateStereoPanner",
"648": "AudioContextCreateWaveShaper",
"649": "AudioContextDecodeAudioData",
"650": "AudioContextResume",
"651": "AudioContextSuspend",
"652": "AudioContext",
"653": "OfflineAudioContext",
"654": "PrefixedAudioContext",
"655": "PrefixedOfflineAudioContext",
"661": "MixedContentInNonHTTPSFrameThatRestrictsMixedContent",
"662": "MixedContentInSecureFrameThatDoesNotRestrictMixedContent",
"663": "MixedContentWebSocket",
"664": "SyntheticKeyframesInCompositedCSSAnimation",
"665": "MixedContentFormPresent",
"666": "GetUserMediaInsecureOrigin",
"667": "GetUserMediaSecureOrigin",
"668": "DeviceMotionInsecureOrigin",
"669": "DeviceMotionSecureOrigin",
"670": "DeviceOrientationInsecureOrigin",
"671": "DeviceOrientationSecureOrigin",
"672": "SandboxViaIFrame",
"673": "SandboxViaCSP",
"674": "BlockedSniffingImageToScript",
"675": "Fetch",
"676": "FetchBodyStream",
"677": "XMLHttpRequestAsynchronous",
"679": "WhiteSpacePreFromXMLSpace",
"680": "WhiteSpaceNowrapFromXMLSpace",
"685": "SVGSVGElementForceRedraw",
"686": "SVGSVGElementSuspendRedraw",
"687": "SVGSVGElementUnsuspendRedraw",
"688": "SVGSVGElementUnsuspendRedrawAll",
"689": "AudioContextClose",
"691": "CSSZoomNotEqualToOne",
"694": "ClientRectListItem",
"695": "WindowClientInformation",
"696": "WindowFind",
"697": "WindowScreenLeft",
"698": "WindowScreenTop",
"699": "V8Animation_Cancel_Method",
"700": "V8Animation_Onfinish_AttributeGetter",
"701": "V8Animation_Onfinish_AttributeSetter",
"707": "V8Window_WebKitAnimationEvent_ConstructorGetter",
"710": "CryptoGetRandomValues",
"711": "SubtleCryptoEncrypt",
"712": "SubtleCryptoDecrypt",
"713": "SubtleCryptoSign",
"714": "SubtleCryptoVerify",
"715": "SubtleCryptoDigest",
"716": "SubtleCryptoGenerateKey",
"717": "SubtleCryptoImportKey",
"718": "SubtleCryptoExportKey",
"719": "SubtleCryptoDeriveBits",
"720": "SubtleCryptoDeriveKey",
"721": "SubtleCryptoWrapKey",
"722": "SubtleCryptoUnwrapKey",
"723": "CryptoAlgorithmAesCbc",
"724": "CryptoAlgorithmHmac",
"725": "CryptoAlgorithmRsaSsaPkcs1v1_5",
"726": "CryptoAlgorithmSha1",
"727": "CryptoAlgorithmSha256",
"728": "CryptoAlgorithmSha384",
"729": "CryptoAlgorithmSha512",
"730": "CryptoAlgorithmAesGcm",
"731": "CryptoAlgorithmRsaOaep",
"732": "CryptoAlgorithmAesCtr",
"733": "CryptoAlgorithmAesKw",
"734": "CryptoAlgorithmRsaPss",
"735": "CryptoAlgorithmEcdsa",
"736": "CryptoAlgorithmEcdh",
"737": "CryptoAlgorithmHkdf",
"738": "CryptoAlgorithmPbkdf2",
"739": "DocumentSetDomain",
"740": "UpgradeInsecureRequestsEnabled",
"741": "UpgradeInsecureRequestsUpgradedRequest",
"742": "DocumentDesignMode",
"743": "GlobalCacheStorage",
"744": "NetInfo",
"745": "BackgroundSync",
"748": "LegacyConst",
"750": "V8Permissions_Query_Method",
"754": "V8HTMLInputElement_Autocapitalize_AttributeGetter",
"755": "V8HTMLInputElement_Autocapitalize_AttributeSetter",
"756": "V8HTMLTextAreaElement_Autocapitalize_AttributeGetter",
"757": "V8HTMLTextAreaElement_Autocapitalize_AttributeSetter",
"758": "SVGHrefBaseVal",
"759": "SVGHrefAnimVal",
"760": "V8CSSRuleList_Item_Method",
"761": "V8MediaList_Item_Method",
"762": "V8StyleSheetList_Item_Method",
"763": "StyleSheetListAnonymousNamedGetter",
"764": "AutocapitalizeAttribute",
"765": "FullscreenSecureOrigin",
"766": "FullscreenInsecureOrigin",
"767": "DialogInSandboxedContext",
"768": "SVGSMILAnimationInImageRegardlessOfCache",
"770": "EncryptedMediaSecureOrigin",
"771": "EncryptedMediaInsecureOrigin",
"772": "PerformanceFrameTiming",
"773": "V8Element_Animate_Method",
"778": "V8SVGSVGElement_GetElementById_Method",
"779": "ElementCreateShadowRootMultiple",
"780": "V8MessageChannel_Constructor",
"781": "V8MessagePort_PostMessage_Method",
"782": "V8MessagePort_Start_Method",
"783": "V8MessagePort_Close_Method",
"784": "MessagePortsTransferred",
"785": "CSSKeyframesRuleAnonymousIndexedGetter",
"786": "V8Screen_AvailLeft_AttributeGetter",
"787": "V8Screen_AvailTop_AttributeGetter",
"791": "V8SVGFEConvolveMatrixElement_PreserveAlpha_AttributeGetter",
"798": "V8SVGStyleElement_Disabled_AttributeGetter",
"799": "V8SVGStyleElement_Disabled_AttributeSetter",
"801": "InputTypeFileSecureOrigin",
"802": "InputTypeFileInsecureOrigin",
"804": "ElementAttachShadow",
"806": "V8SecurityPolicyViolationEvent_DocumentURI_AttributeGetter",
"807": "V8SecurityPolicyViolationEvent_BlockedURI_AttributeGetter",
"808": "V8SecurityPolicyViolationEvent_StatusCode_AttributeGetter",
"809": "HTMLLinkElementDisabled",
"810": "V8HTMLLinkElement_Disabled_AttributeGetter",
"811": "V8HTMLLinkElement_Disabled_AttributeSetter",
"812": "V8HTMLStyleElement_Disabled_AttributeGetter",
"813": "V8HTMLStyleElement_Disabled_AttributeSetter",
"816": "V8DOMError_Constructor",
"817": "V8DOMError_Name_AttributeGetter",
"818": "V8DOMError_Message_AttributeGetter",
"823": "V8Location_AncestorOrigins_AttributeGetter",
"824": "V8IDBDatabase_ObjectStoreNames_AttributeGetter",
"825": "V8IDBObjectStore_IndexNames_AttributeGetter",
"826": "V8IDBTransaction_ObjectStoreNames_AttributeGetter",
"830": "TextInputFired",
"831": "V8TextEvent_Data_AttributeGetter",
"832": "V8TextEvent_InitTextEvent_Method",
"833": "V8SVGSVGElement_UseCurrentView_AttributeGetter",
"834": "V8SVGSVGElement_CurrentView_AttributeGetter",
"835": "ClientHintsDPR",
"836": "ClientHintsResourceWidth",
"837": "ClientHintsViewportWidth",
"838": "SRIElementIntegrityAttributeButIneligible",
"839": "FormDataAppendFile",
"840": "FormDataAppendFileWithFilename",
"841": "FormDataAppendBlob",
"842": "FormDataAppendBlobWithFilename",
"843": "FormDataAppendNull",
"844": "HTMLDocumentCreateAttributeNameNotLowercase",
"845": "NonHTMLElementSetAttributeNodeFromHTMLDocumentNameNotLowercase",
"846": "DOMStringList_Item_AttributeGetter_IndexedDB",
"847": "DOMStringList_Item_AttributeGetter_Location",
"848": "DOMStringList_Contains_Method_IndexedDB",
"849": "DOMStringList_Contains_Method_Location",
"850": "NavigatorVibrate",
"851": "NavigatorVibrateSubFrame",
"853": "V8XPathEvaluator_Constructor",
"854": "V8XPathEvaluator_CreateExpression_Method",
"855": "V8XPathEvaluator_CreateNSResolver_Method",
"856": "V8XPathEvaluator_Evaluate_Method",
"857": "RequestMIDIAccess",
"858": "V8MouseEvent_LayerX_AttributeGetter",
"859": "V8MouseEvent_LayerY_AttributeGetter",
"860": "InnerTextWithShadowTree",
"861": "SelectionToStringWithShadowTree",
"862": "WindowFindWithShadowTree",
"863": "V8CompositionEvent_InitCompositionEvent_Method",
"864": "V8CustomEvent_InitCustomEvent_Method",
"865": "V8DeviceMotionEvent_InitDeviceMotionEvent_Method",
"866": "V8DeviceOrientationEvent_InitDeviceOrientationEvent_Method",
"867": "V8Event_InitEvent_Method",
"868": "V8KeyboardEvent_InitKeyboardEvent_Method",
"869": "V8MouseEvent_InitMouseEvent_Method",
"870": "V8MutationEvent_InitMutationEvent_Method",
"871": "V8StorageEvent_InitStorageEvent_Method",
"872": "V8TouchEvent_InitTouchEvent_Method",
"873": "V8UIEvent_InitUIEvent_Method",
"874": "V8Document_CreateTouch_Method",
"876": "RequestFileSystemNonWebbyOrigin",
"879": "V8MemoryInfo_TotalJSHeapSize_AttributeGetter",
"880": "V8MemoryInfo_UsedJSHeapSize_AttributeGetter",
"881": "V8MemoryInfo_JSHeapSizeLimit_AttributeGetter",
"882": "V8Performance_Timing_AttributeGetter",
"883": "V8Performance_Navigation_AttributeGetter",
"884": "V8Performance_Memory_AttributeGetter",
"885": "V8SharedWorker_WorkerStart_AttributeGetter",
"886": "HTMLKeygenElement",
"892": "HTMLMediaElementPreloadNone",
"893": "HTMLMediaElementPreloadMetadata",
"894": "HTMLMediaElementPreloadAuto",
"895": "HTMLMediaElementPreloadDefault",
"896": "MixedContentBlockableAllowed",
"897": "PseudoBeforeAfterForInputElement",
"898": "V8Permissions_Revoke_Method",
"899": "LinkRelDnsPrefetch",
"900": "LinkRelPreconnect",
"901": "LinkRelPreload",
"902": "LinkHeaderDnsPrefetch",
"903": "LinkHeaderPreconnect",
"904": "ClientHintsMetaAcceptCH",
"905": "HTMLElementDeprecatedWidth",
"906": "ClientHintsContentDPR",
"907": "ElementAttachShadowOpen",
"908": "ElementAttachShadowClosed",
"909": "AudioParamSetValueAtTime",
"910": "AudioParamLinearRampToValueAtTime",
"911": "AudioParamExponentialRampToValueAtTime",
"912": "AudioParamSetTargetAtTime",
"913": "AudioParamSetValueCurveAtTime",
"914": "AudioParamCancelScheduledValues",
"915": "V8Permissions_Request_Method",
"917": "LinkRelPrefetch",
"918": "LinkRelPrerender",
"919": "LinkRelNext",
"920": "PrefixedPerformanceResourceTimingBufferFull",
"921": "CSSValuePrefixedMinContent",
"922": "CSSValuePrefixedMaxContent",
"923": "CSSValuePrefixedFitContent",
"924": "CSSValuePrefixedFillAvailable",
"926": "PresentationDefaultRequest",
"927": "PresentationAvailabilityChangeEventListener",
"928": "PresentationRequestConstructor",
"929": "PresentationRequestStart",
"930": "PresentationRequestReconnect",
"931": "PresentationRequestGetAvailability",
"932": "PresentationRequestConnectionAvailableEventListener",
"933": "PresentationConnectionTerminate",
"934": "PresentationConnectionSend",
"936": "PresentationConnectionMessageEventListener",
"937": "CSSAnimationsStackedNeutralKeyframe",
"938": "ReadingCheckedInClickHandler",
"939": "FlexboxIntrinsicSizeAlgorithmIsDifferent",
"940": "HTMLImportsHasStyleSheets",
"944": "ClipPathOfPositionedElement",
"945": "ClipCssOfPositionedElement",
"946": "NetInfoType",
"947": "NetInfoDownlinkMax",
"948": "NetInfoOnChange",
"949": "NetInfoOnTypeChange",
"950": "V8Window_Alert_Method",
"951": "V8Window_Confirm_Method",
"952": "V8Window_Prompt_Method",
"953": "V8Window_Print_Method",
"954": "V8Window_RequestIdleCallback_Method",
"955": "FlexboxPercentagePaddingVertical",
"956": "FlexboxPercentageMarginVertical",
"957": "BackspaceNavigatedBack",
"958": "BackspaceNavigatedBackAfterFormInteraction",
"959": "CSPSourceWildcardWouldMatchExactHost",
"960": "CredentialManagerGet",
"961": "CredentialManagerGetWithUI",
"962": "CredentialManagerGetWithoutUI",
"963": "CredentialManagerStore",
"964": "CredentialManagerRequireUserMediation",
"966": "BlockableMixedContentInSubframeBlocked",
"967": "AddEventListenerThirdArgumentIsObject",
"968": "RemoveEventListenerThirdArgumentIsObject",
"969": "CSSAtRuleCharset",
"970": "CSSAtRuleFontFace",
"971": "CSSAtRuleImport",
"972": "CSSAtRuleKeyframes",
"973": "CSSAtRuleMedia",
"974": "CSSAtRuleNamespace",
"975": "CSSAtRulePage",
"976": "CSSAtRuleSupports",
"977": "CSSAtRuleViewport",
"978": "CSSAtRuleWebkitKeyframes",
"979": "V8HTMLFieldSetElement_Elements_AttributeGetter",
"980": "HTMLMediaElementPreloadForcedNone",
"981": "ExternalAddSearchProvider",
"982": "ExternalIsSearchProviderInstalled",
"983": "V8Permissions_RequestAll_Method",
"987": "DeviceOrientationAbsoluteInsecureOrigin",
"988": "DeviceOrientationAbsoluteSecureOrigin",
"989": "FontFaceConstructor",
"990": "ServiceWorkerControlledPage",
"993": "MeterElementWithMeterAppearance",
"994": "MeterElementWithNoneAppearance",
"997": "SelectionAnchorNode",
"998": "SelectionAnchorOffset",
"999": "SelectionFocusNode",
"1000": "SelectionFocusOffset",
"1001": "SelectionIsCollapsed",
"1002": "SelectionRangeCount",
"1003": "SelectionGetRangeAt",
"1004": "SelectionAddRange",
"1005": "SelectionRemoveAllRanges",
"1006": "SelectionCollapse",
"1007": "SelectionCollapseToStart",
"1008": "SelectionCollapseToEnd",
"1009": "SelectionExtend",
"1010": "SelectionSelectAllChildren",
"1011": "SelectionDeleteDromDocument",
"1012": "SelectionDOMString",
"1013": "InputTypeRangeVerticalAppearance",
"1014": "CSSFilterReference",
"1015": "CSSFilterGrayscale",
"1016": "CSSFilterSepia",
"1017": "CSSFilterSaturate",
"1018": "CSSFilterHueRotate",
"1019": "CSSFilterInvert",
"1020": "CSSFilterOpacity",
"1021": "CSSFilterBrightness",
"1022": "CSSFilterContrast",
"1023": "CSSFilterBlur",
"1024": "CSSFilterDropShadow",
"1025": "BackgroundSyncRegister",
"1027": "ExecCommandOnInputOrTextarea",
"1028": "V8History_ScrollRestoration_AttributeGetter",
"1029": "V8History_ScrollRestoration_AttributeSetter",
"1030": "SVG1DOMFilter",
"1031": "OfflineAudioContextStartRendering",
"1032": "OfflineAudioContextSuspend",
"1033": "OfflineAudioContextResume",
"1034": "AttrCloneNode",
"1035": "SVG1DOMPaintServer",
"1036": "SVGSVGElementFragmentSVGView",
"1037": "SVGSVGElementFragmentSVGViewElement",
"1038": "PresentationConnectionClose",
"1039": "SVG1DOMShape",
"1040": "SVG1DOMText",
"1041": "RTCPeerConnectionConstructorConstraints",
"1042": "RTCPeerConnectionConstructorCompliant",
"1044": "RTCPeerConnectionCreateOfferLegacyFailureCallback",
"1045": "RTCPeerConnectionCreateOfferLegacyConstraints",
"1046": "RTCPeerConnectionCreateOfferLegacyOfferOptions",
"1047": "RTCPeerConnectionCreateOfferLegacyCompliant",
"1049": "RTCPeerConnectionCreateAnswerLegacyFailureCallback",
"1050": "RTCPeerConnectionCreateAnswerLegacyConstraints",
"1051": "RTCPeerConnectionCreateAnswerLegacyCompliant",
"1052": "RTCPeerConnectionSetLocalDescriptionLegacyNoSuccessCallback",
"1053": "RTCPeerConnectionSetLocalDescriptionLegacyNoFailureCallback",
"1054": "RTCPeerConnectionSetLocalDescriptionLegacyCompliant",
"1055": "RTCPeerConnectionSetRemoteDescriptionLegacyNoSuccessCallback",
"1056": "RTCPeerConnectionSetRemoteDescriptionLegacyNoFailureCallback",
"1057": "RTCPeerConnectionSetRemoteDescriptionLegacyCompliant",
"1058": "RTCPeerConnectionGetStatsLegacyNonCompliant",
"1059": "NodeFilterIsFunction",
"1060": "NodeFilterIsObject",
"1062": "CSSSelectorInternalPseudoListBox",
"1063": "CSSSelectorInternalMediaControlsCastButton",
"1064": "CSSSelectorInternalMediaControlsOverlayCastButton",
"1065": "CSSSelectorInternalPseudoSpatialNavigationFocus",
"1066": "SameOriginTextScript",
"1067": "SameOriginApplicationScript",
"1068": "SameOriginOtherScript",
"1069": "CrossOriginTextScript",
"1070": "CrossOriginApplicationScript",
"1071": "CrossOriginOtherScript",
"1072": "SVG1DOMSVGTests",
"1073": "V8SVGViewElement_ViewTarget_AttributeGetter",
"1074": "DisableRemotePlaybackAttribute",
"1075": "V8SloppyMode",
"1076": "V8StrictMode",
"1077": "V8StrongMode",
"1078": "AudioNodeConnectToAudioNode",
"1079": "AudioNodeConnectToAudioParam",
"1080": "AudioNodeDisconnectFromAudioNode",
"1081": "AudioNodeDisconnectFromAudioParam",
"1082": "V8CSSFontFaceRule_Style_AttributeGetter",
"1083": "SelectionCollapseNull",
"1084": "SelectionSetBaseAndExtentNull",
"1085": "V8SVGSVGElement_CreateSVGNumber_Method",
"1086": "V8SVGSVGElement_CreateSVGLength_Method",
"1087": "V8SVGSVGElement_CreateSVGAngle_Method",
"1088": "V8SVGSVGElement_CreateSVGPoint_Method",
"1089": "V8SVGSVGElement_CreateSVGMatrix_Method",
"1090": "V8SVGSVGElement_CreateSVGRect_Method",
"1091": "V8SVGSVGElement_CreateSVGTransform_Method",
"1092": "V8SVGSVGElement_CreateSVGTransformFromMatrix_Method",
"1093": "FormNameAccessForNonDescendantImageElement",
"1095": "V8SVGSVGElement_Viewport_AttributeGetter",
"1096": "V8RegExpPrototypeStickyGetter",
"1097": "V8RegExpPrototypeToString",
"1098": "V8InputDeviceCapabilities_FiresTouchEvents_AttributeGetter",
"1099": "DataElement",
"1100": "TimeElement",
"1101": "SVG1DOMUriReference",
"1102": "SVG1DOMZoomAndPan",
"1103": "V8SVGGraphicsElement_Transform_AttributeGetter",
"1104": "MenuItemElement",
"1105": "MenuItemCloseTag",
"1106": "SVG1DOMMarkerElement",
"1107": "SVG1DOMUseElement",
"1108": "SVG1DOMMaskElement",
"1109": "V8SVGAElement_Target_AttributeGetter",
"1110": "V8SVGClipPathElement_ClipPathUnits_AttributeGetter",
"1111": "SVG1DOMFitToViewBox",
"1112": "SVG1DOMCursorElement",
"1113": "V8SVGPathElement_PathLength_AttributeGetter",
"1114": "SVG1DOMSVGElement",
"1115": "SVG1DOMImageElement",
"1116": "SVG1DOMForeignObjectElement",
"1117": "AudioContextCreateIIRFilter",
"1118": "CSSSelectorPseudoSlotted",
"1119": "MediaDevicesEnumerateDevices",
"1120": "NonSecureSharedWorkerAccessedFromSecureContext",
"1121": "SecureSharedWorkerAccessedFromNonSecureContext",
"1123": "EventComposedPath",
"1124": "LinkHeaderPreload",
"1125": "MouseWheelEvent",
"1126": "WheelEvent",
"1127": "MouseWheelAndWheelEvent",
"1128": "BodyScrollsInAdditionToViewport",
"1129": "DocumentDesignModeEnabeld",
"1130": "ContentEditableTrue",
"1131": "ContentEditableTrueOnHTML",
"1132": "ContentEditablePlainTextOnly",
"1133": "V8RegExpPrototypeUnicodeGetter",
"1134": "V8IntlV8Parse",
"1135": "V8IntlPattern",
"1136": "V8IntlResolved",
"1137": "V8PromiseChain",
"1138": "V8PromiseAccept",
"1139": "V8PromiseDefer",
"1140": "EventComposed",
"1141": "GeolocationInsecureOriginIframe",
"1142": "GeolocationSecureOriginIframe",
"1143": "RequestMIDIAccessIframe",
"1144": "GetUserMediaInsecureOriginIframe",
"1145": "GetUserMediaSecureOriginIframe",
"1146": "ElementRequestPointerLockIframe",
"1147": "NotificationAPIInsecureOriginIframe",
"1148": "NotificationAPISecureOriginIframe",
"1149": "WebSocket",
"1150": "MediaStreamConstraintsNameValue",
"1151": "MediaStreamConstraintsFromDictionary",
"1152": "MediaStreamConstraintsConformant",
"1153": "CSSSelectorIndirectAdjacent",
"1156": "CreateImageBitmap",
"1157": "PresentationConnectionConnectEventListener",
"1158": "PresentationConnectionCloseEventListener",
"1159": "PresentationConnectionTerminateEventListener",
"1160": "DocumentCreateEventFontFaceSetLoadEvent",
"1161": "DocumentCreateEventMediaQueryListEvent",
"1162": "DocumentCreateEventAnimationEvent",
"1164": "DocumentCreateEventApplicationCacheErrorEvent",
"1166": "DocumentCreateEventBeforeUnloadEvent",
"1167": "DocumentCreateEventClipboardEvent",
"1168": "DocumentCreateEventCompositionEvent",
"1169": "DocumentCreateEventDragEvent",
"1170": "DocumentCreateEventErrorEvent",
"1171": "DocumentCreateEventFocusEvent",
"1172": "DocumentCreateEventHashChangeEvent",
"1173": "DocumentCreateEventMutationEvent",
"1174": "DocumentCreateEventPageTransitionEvent",
"1176": "DocumentCreateEventPopStateEvent",
"1177": "DocumentCreateEventProgressEvent",
"1178": "DocumentCreateEventPromiseRejectionEvent",
"1180": "DocumentCreateEventResourceProgressEvent",
"1181": "DocumentCreateEventSecurityPolicyViolationEvent",
"1182": "DocumentCreateEventTextEvent",
"1183": "DocumentCreateEventTransitionEvent",
"1184": "DocumentCreateEventWheelEvent",
"1186": "DocumentCreateEventTrackEvent",
"1187": "DocumentCreateEventWebKitAnimationEvent",
"1188": "DocumentCreateEventMutationEvents",
"1189": "DocumentCreateEventOrientationEvent",
"1190": "DocumentCreateEventSVGEvents",
"1191": "DocumentCreateEventWebKitTransitionEvent",
"1192": "DocumentCreateEventBeforeInstallPromptEvent",
"1193": "DocumentCreateEventSyncEvent",
"1195": "DocumentCreateEventDeviceMotionEvent",
"1196": "DocumentCreateEventDeviceOrientationEvent",
"1197": "DocumentCreateEventMediaEncryptedEvent",
"1198": "DocumentCreateEventMediaKeyMessageEvent",
"1199": "DocumentCreateEventGamepadEvent",
"1201": "DocumentCreateEventIDBVersionChangeEvent",
"1202": "DocumentCreateEventBlobEvent",
"1203": "DocumentCreateEventMediaStreamEvent",
"1204": "DocumentCreateEventMediaStreamTrackEvent",
"1205": "DocumentCreateEventRTCDTMFToneChangeEvent",
"1206": "DocumentCreateEventRTCDataChannelEvent",
"1207": "DocumentCreateEventRTCIceCandidateEvent",
"1209": "DocumentCreateEventNotificationEvent",
"1210": "DocumentCreateEventPresentationConnectionAvailableEvent",
"1211": "DocumentCreateEventPresentationConnectionCloseEvent",
"1212": "DocumentCreateEventPushEvent",
"1213": "DocumentCreateEventExtendableEvent",
"1214": "DocumentCreateEventExtendableMessageEvent",
"1215": "DocumentCreateEventFetchEvent",
"1217": "DocumentCreateEventServiceWorkerMessageEvent",
"1218": "DocumentCreateEventSpeechRecognitionError",
"1219": "DocumentCreateEventSpeechRecognitionEvent",
"1220": "DocumentCreateEventSpeechSynthesisEvent",
"1221": "DocumentCreateEventStorageEvent",
"1222": "DocumentCreateEventAudioProcessingEvent",
"1223": "DocumentCreateEventOfflineAudioCompletionEvent",
"1224": "DocumentCreateEventWebGLContextEvent",
"1225": "DocumentCreateEventMIDIConnectionEvent",
"1226": "DocumentCreateEventMIDIMessageEvent",
"1227": "DocumentCreateEventCloseEvent",
"1228": "DocumentCreateEventKeyboardEvents",
"1229": "HTMLMediaElement",
"1230": "HTMLMediaElementInDocument",
"1231": "HTMLMediaElementControlsAttribute",
"1233": "V8Animation_Oncancel_AttributeGetter",
"1234": "V8Animation_Oncancel_AttributeSetter",
"1235": "V8HTMLCommentInExternalScript",
"1236": "V8HTMLComment",
"1237": "V8SloppyModeBlockScopedFunctionRedefinition",
"1238": "V8ForInInitializer",
"1239": "V8Animation_Id_AttributeGetter",
"1240": "V8Animation_Id_AttributeSetter",
"1243": "WebAnimationHyphenatedProperty",
"1244": "FormControlsCollectionReturnsRadioNodeListForFieldSet",
"1245": "ApplicationCacheManifestSelectInsecureOrigin",
"1246": "ApplicationCacheManifestSelectSecureOrigin",
"1247": "ApplicationCacheAPIInsecureOrigin",
"1248": "ApplicationCacheAPISecureOrigin",
"1249": "CSSAtRuleApply",
"1250": "CSSSelectorPseudoAny",
"1251": "PannerNodeSetVelocity",
"1252": "DocumentAllItemNoArguments",
"1253": "DocumentAllItemNamed",
"1254": "DocumentAllItemIndexed",
"1255": "DocumentAllItemIndexedWithNonNumber",
"1256": "DocumentAllLegacyCallNoArguments",
"1257": "DocumentAllLegacyCallNamed",
"1258": "DocumentAllLegacyCallIndexed",
"1259": "DocumentAllLegacyCallIndexedWithNonNumber",
"1260": "DocumentAllLegacyCallTwoArguments",
"1263": "HTMLLabelElementControlForNonFormAssociatedElement",
"1265": "HTMLMediaElementLoadNetworkEmptyNotPaused",
"1267": "V8Window_WebkitSpeechGrammar_ConstructorGetter",
"1268": "V8Window_WebkitSpeechGrammarList_ConstructorGetter",
"1269": "V8Window_WebkitSpeechRecognition_ConstructorGetter",
"1270": "V8Window_WebkitSpeechRecognitionError_ConstructorGetter",
"1271": "V8Window_WebkitSpeechRecognitionEvent_ConstructorGetter",
"1272": "V8Window_SpeechSynthesis_AttributeGetter",
"1273": "V8IDBFactory_WebkitGetDatabaseNames_Method",
"1274": "ImageDocument",
"1275": "ScriptPassesCSPDynamic",
"1277": "CSPWithStrictDynamic",
"1278": "ScrollAnchored",
"1279": "AddEventListenerFourArguments",
"1280": "RemoveEventListenerFourArguments",
"1281": "InvalidReportUriDirectiveInMetaCSP",
"1282": "InvalidSandboxDirectiveInMetaCSP",
"1283": "InvalidFrameAncestorsDirectiveInMetaCSP",
"1287": "SVGCalcModeDiscrete",
"1288": "SVGCalcModeLinear",
"1289": "SVGCalcModePaced",
"1290": "SVGCalcModeSpline",
"1291": "FormSubmissionStarted",
"1292": "FormValidationStarted",
"1293": "FormValidationAbortedSubmission",
"1294": "FormValidationShowedMessage",
"1295": "WebAnimationsEasingAsFunctionLinear",
"1296": "WebAnimationsEasingAsFunctionOther",
"1297": "V8Document_Images_AttributeGetter",
"1298": "V8Document_Embeds_AttributeGetter",
"1299": "V8Document_Plugins_AttributeGetter",
"1300": "V8Document_Links_AttributeGetter",
"1301": "V8Document_Forms_AttributeGetter",
"1302": "V8Document_Scripts_AttributeGetter",
"1303": "V8Document_Anchors_AttributeGetter",
"1304": "V8Document_Applets_AttributeGetter",
"1305": "XMLHttpRequestCrossOriginWithCredentials",
"1306": "MediaStreamTrackRemote",
"1307": "V8Node_IsConnected_AttributeGetter",
"1308": "ShadowRootDelegatesFocus",
"1309": "MixedShadowRootV0AndV1",
"1310": "ImageDocumentInFrame",
"1311": "MediaDocument",
"1312": "MediaDocumentInFrame",
"1313": "PluginDocument",
"1314": "PluginDocumentInFrame",
"1315": "SinkDocument",
"1316": "SinkDocumentInFrame",
"1317": "TextDocument",
"1318": "TextDocumentInFrame",
"1319": "ViewSourceDocument",
"1320": "FileAPINativeLineEndings",
"1321": "PointerEventAttributeCount",
"1322": "CompositedReplication",
"1323": "EncryptedMediaAllSelectedContentTypesHaveCodecs",
"1324": "EncryptedMediaAllSelectedContentTypesMissingCodecs",
"1325": "V8DataTransferItem_WebkitGetAsEntry_Method",
"1326": "V8HTMLInputElement_WebkitEntries_AttributeGetter",
"1327": "Entry_Filesystem_AttributeGetter_IsolatedFileSystem",
"1328": "Entry_GetMetadata_Method_IsolatedFileSystem",
"1329": "Entry_MoveTo_Method_IsolatedFileSystem",
"1330": "Entry_CopyTo_Method_IsolatedFileSystem",
"1331": "Entry_Remove_Method_IsolatedFileSystem",
"1332": "Entry_GetParent_Method_IsolatedFileSystem",
"1333": "Entry_ToURL_Method_IsolatedFileSystem",
"1334": "During_Microtask_Alert",
"1335": "During_Microtask_Confirm",
"1336": "During_Microtask_Print",
"1337": "During_Microtask_Prompt",
"1338": "During_Microtask_SyncXHR",
"1342": "CredentialManagerGetReturnedCredential",
"1343": "GeolocationInsecureOriginDeprecatedNotRemoved",
"1344": "GeolocationInsecureOriginIframeDeprecatedNotRemoved",
"1345": "ProgressElementWithNoneAppearance",
"1346": "ProgressElementWithProgressBarAppearance",
"1347": "PointerEventAddListenerCount",
"1348": "EventCancelBubbleAffected",
"1349": "EventCancelBubbleWasChangedToTrue",
"1350": "EventCancelBubbleWasChangedToFalse",
"1351": "CSSValueAppearanceNone",
"1352": "CSSValueAppearanceNotNone",
"1353": "CSSValueAppearanceOthers",
"1354": "CSSValueAppearanceButton",
"1355": "CSSValueAppearanceCaret",
"1356": "CSSValueAppearanceCheckbox",
"1357": "CSSValueAppearanceMenulist",
"1358": "CSSValueAppearanceMenulistButton",
"1359": "CSSValueAppearanceListbox",
"1360": "CSSValueAppearanceRadio",
"1361": "CSSValueAppearanceSearchField",
"1362": "CSSValueAppearanceTextField",
"1363": "AudioContextCreatePannerAutomated",
"1364": "PannerNodeSetPosition",
"1365": "PannerNodeSetOrientation",
"1366": "AudioListenerSetPosition",
"1367": "AudioListenerSetOrientation",
"1368": "IntersectionObserver_Constructor",
"1369": "DurableStoragePersist",
"1370": "DurableStoragePersisted",
"1371": "DurableStorageEstimate",
"1372": "UntrustedEventDefaultHandled",
"1375": "CSSDeepCombinatorAndShadow",
"1376": "OpacityWithPreserve3DQuirk",
"1377": "CSSSelectorPseudoReadOnly",
"1378": "CSSSelectorPseudoReadWrite",
"1379": "UnloadHandler_Navigation",
"1380": "TouchStartUserGestureUtilized",
"1381": "TouchMoveUserGestureUtilized",
"1382": "TouchEndDuringScrollUserGestureUtilized",
"1383": "CSSSelectorPseudoDefined",
"1384": "RTCPeerConnectionAddIceCandidatePromise",
"1385": "RTCPeerConnectionAddIceCandidateLegacy",
"1386": "RTCIceCandidateDefaultSdpMLineIndex",
"1389": "MediaStreamConstraintsOldAndNew",
"1390": "V8ArrayProtectorDirtied",
"1391": "V8ArraySpeciesModified",
"1392": "V8ArrayPrototypeConstructorModified",
"1393": "V8ArrayInstanceProtoModified",
"1394": "V8ArrayInstanceConstructorModified",
"1395": "V8LegacyFunctionDeclaration",
"1396": "V8RegExpPrototypeSourceGetter",
"1397": "V8RegExpPrototypeOldFlagGetter",
"1398": "V8DecimalWithLeadingZeroInStrictMode",
"1399": "FormSubmissionNotInDocumentTree",
"1400": "GetUserMediaPrefixed",
"1401": "GetUserMediaLegacy",
"1402": "GetUserMediaPromise",
"1403": "CSSFilterFunctionNoArguments",
"1404": "V8LegacyDateParser",
"1405": "OpenSearchInsecureOriginInsecureTarget",
"1406": "OpenSearchInsecureOriginSecureTarget",
"1407": "OpenSearchSecureOriginInsecureTarget",
"1408": "OpenSearchSecureOriginSecureTarget",
"1409": "RegisterProtocolHandlerSecureOrigin",
"1410": "RegisterProtocolHandlerInsecureOrigin",
"1411": "CrossOriginWindowAlert",
"1412": "CrossOriginWindowConfirm",
"1413": "CrossOriginWindowPrompt",
"1414": "CrossOriginWindowPrint",
"1415": "MediaStreamOnActive",
"1416": "MediaStreamOnInactive",
"1417": "AddEventListenerPassiveTrue",
"1418": "AddEventListenerPassiveFalse",
"1419": "CSPReferrerDirective",
"1420": "DocumentOpen",
"1421": "ElementRequestPointerLockInShadow",
"1422": "ShadowRootPointerLockElement",
"1423": "DocumentPointerLockElementInV0Shadow",
"1424": "TextAreaMaxLength",
"1425": "TextAreaMinLength",
"1426": "TopNavigationFromSubFrame",
"1427": "PrefixedElementRequestFullscreenInShadow",
"1428": "MediaSourceAbortRemove",
"1429": "MediaSourceDurationTruncatingBuffered",
"1430": "AudioContextCrossOriginIframe",
"1431": "PointerEventSetCapture",
"1432": "PointerEventDispatch",
"1433": "MIDIMessageEventReceivedTime",
"1434": "SummaryElementWithDisplayBlockAuthorRule",
"1435": "V8MediaStream_Active_AttributeGetter",
"1436": "BeforeInstallPromptEvent",
"1437": "BeforeInstallPromptEventUserChoice",
"1438": "BeforeInstallPromptEventPreventDefault",
"1439": "BeforeInstallPromptEventPrompt",
"1440": "ExecCommandAltersHTMLStructure",
"1441": "SecureContextCheckPassed",
"1442": "SecureContextCheckFailed",
"1443": "SecureContextCheckForSandboxedOriginPassed",
"1444": "SecureContextCheckForSandboxedOriginFailed",
"1445": "V8DefineGetterOrSetterWouldThrow",
"1446": "V8FunctionConstructorReturnedUndefined",
"1447": "V8BroadcastChannel_Constructor",
"1448": "V8BroadcastChannel_PostMessage_Method",
"1449": "V8BroadcastChannel_Close_Method",
"1450": "TouchStartFired",
"1451": "MouseDownFired",
"1452": "PointerDownFired",
"1453": "PointerDownFiredForTouch",
"1454": "PointerEventDispatchPointerDown",
"1455": "SVGSMILBeginOrEndEventValue",
"1456": "SVGSMILBeginOrEndSyncbaseValue",
"1457": "SVGSMILElementInsertedAfterLoad",
"1458": "V8VisualViewport_ScrollLeft_AttributeGetter",
"1459": "V8VisualViewport_ScrollTop_AttributeGetter",
"1460": "V8VisualViewport_PageX_AttributeGetter",
"1461": "V8VisualViewport_PageY_AttributeGetter",
"1462": "V8VisualViewport_ClientWidth_AttributeGetter",
"1463": "V8VisualViewport_ClientHeight_AttributeGetter",
"1464": "V8VisualViewport_Scale_AttributeGetter",
"1465": "VisualViewportScrollFired",
"1466": "VisualViewportResizeFired",
"1467": "NodeGetRootNode",
"1468": "SlotChangeEventAddListener",
"1469": "CSSValueAppearanceButtonRendered",
"1470": "CSSValueAppearanceButtonForAnchor",
"1471": "CSSValueAppearanceButtonForButton",
"1472": "CSSValueAppearanceButtonForOtherButtons",
"1473": "CSSValueAppearanceTextFieldRendered",
"1474": "CSSValueAppearanceTextFieldForSearch",
"1475": "CSSValueAppearanceTextFieldForTextField",
"1476": "RTCPeerConnectionGetStats",
"1477": "SVGSMILAnimationAppliedEffect",
"1478": "PerformanceResourceTimingSizes",
"1479": "EventSourceDocument",
"1480": "EventSourceWorker",
"1481": "SingleOriginInTimingAllowOrigin",
"1482": "MultipleOriginsInTimingAllowOrigin",
"1483": "StarInTimingAllowOrigin",
"1484": "SVGSMILAdditiveAnimation",
"1485": "SendBeaconWithNonSimpleContentType",
"1486": "ChromeLoadTimesRequestTime",
"1487": "ChromeLoadTimesStartLoadTime",
"1488": "ChromeLoadTimesCommitLoadTime",
"1489": "ChromeLoadTimesFinishDocumentLoadTime",
"1490": "ChromeLoadTimesFinishLoadTime",
"1491": "ChromeLoadTimesFirstPaintTime",
"1492": "ChromeLoadTimesFirstPaintAfterLoadTime",
"1493": "ChromeLoadTimesNavigationType",
"1494": "ChromeLoadTimesWasFetchedViaSpdy",
"1495": "ChromeLoadTimesWasNpnNegotiated",
"1496": "ChromeLoadTimesNpnNegotiatedProtocol",
"1497": "ChromeLoadTimesWasAlternateProtocolAvailable",
"1498": "ChromeLoadTimesConnectionInfo",
"1499": "ChromeLoadTimesUnknown",
"1500": "SVGViewElement",
"1501": "WebShareShare",
"1502": "AuxclickAddListenerCount",
"1503": "HTMLCanvasElement",
"1504": "SVGSMILAnimationElementTiming",
"1505": "SVGSMILBeginEndAnimationElement",
"1506": "SVGSMILPausing",
"1507": "SVGSMILCurrentTime",
"1508": "HTMLBodyElementOnSelectionChangeAttribute",
"1509": "ForeignFetchInterception",
"1510": "MapNameMatchingStrict",
"1511": "MapNameMatchingASCIICaseless",
"1512": "MapNameMatchingUnicodeLower",
"1513": "RadioNameMatchingStrict",
"1514": "RadioNameMatchingASCIICaseless",
"1515": "RadioNameMatchingCaseFolding",
"1517": "InputSelectionGettersThrow",
"1519": "UsbGetDevices",
"1520": "UsbRequestDevice",
"1521": "UsbDeviceOpen",
"1522": "UsbDeviceClose",
"1523": "UsbDeviceSelectConfiguration",
"1524": "UsbDeviceClaimInterface",
"1525": "UsbDeviceReleaseInterface",
"1526": "UsbDeviceSelectAlternateInterface",
"1527": "UsbDeviceControlTransferIn",
"1528": "UsbDeviceControlTransferOut",
"1529": "UsbDeviceClearHalt",
"1530": "UsbDeviceTransferIn",
"1531": "UsbDeviceTransferOut",
"1532": "UsbDeviceIsochronousTransferIn",
"1533": "UsbDeviceIsochronousTransferOut",
"1534": "UsbDeviceReset",
"1535": "PointerEnterLeaveFired",
"1536": "PointerOverOutFired",
"1539": "DraggableAttribute",
"1540": "CleanScriptElementWithNonce",
"1541": "PotentiallyInjectedScriptElementWithNonce",
"1542": "PendingStylesheetAddedAfterBodyStarted",
"1543": "UntrustedMouseDownEventDispatchedToSelect",
"1544": "BlockedSniffingAudioToScript",
"1545": "BlockedSniffingVideoToScript",
"1546": "BlockedSniffingCSVToScript",
"1547": "MetaSetCookie",
"1548": "MetaRefresh",
"1549": "MetaSetCookieWhenCSPBlocksInlineScript",
"1550": "MetaRefreshWhenCSPBlocksInlineScript",
"1551": "MiddleClickAutoscrollStart",
"1552": "ClipCssOfFixedPositionElement",
"1553": "RTCPeerConnectionCreateOfferOptionsOfferToReceive",
"1554": "DragAndDropScrollStart",
"1555": "PresentationConnectionListConnectionAvailableEventListener",
"1556": "WebAudioAutoplayCrossOriginIframe",
"1557": "ScriptInvalidTypeOrLanguage",
"1558": &quo