@paulirish/trace_engine 0.0.28 → 0.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/platform/platform-tsconfig.json +0 -1
- package/core/platform/platform.d.ts +1 -2
- package/core/platform/platform.js +1 -2
- package/core/platform/platform.js.map +1 -1
- package/generated/protocol.d.ts +103 -6
- package/models/trace/LanternComputationData.js +4 -4
- package/models/trace/LanternComputationData.js.map +1 -1
- package/models/trace/ModelImpl.d.ts +23 -23
- package/models/trace/ModelImpl.js +20 -12
- package/models/trace/ModelImpl.js.map +1 -1
- package/models/trace/Processor.d.ts +6 -7
- package/models/trace/Processor.js +102 -29
- package/models/trace/Processor.js.map +1 -1
- package/models/trace/extras/URLForEntry.js +1 -1
- package/models/trace/extras/URLForEntry.js.map +1 -1
- package/models/trace/handlers/ExtensionTraceDataHandler.js +2 -6
- package/models/trace/handlers/ExtensionTraceDataHandler.js.map +1 -1
- package/models/trace/handlers/InvalidationsHandler.d.ts +1 -1
- package/models/trace/handlers/InvalidationsHandler.js +2 -21
- package/models/trace/handlers/InvalidationsHandler.js.map +1 -1
- package/models/trace/handlers/LayoutShiftsHandler.d.ts +1 -0
- package/models/trace/handlers/LayoutShiftsHandler.js +5 -0
- package/models/trace/handlers/LayoutShiftsHandler.js.map +1 -1
- package/models/trace/handlers/MetaHandler.d.ts +2 -2
- package/models/trace/handlers/MetaHandler.js.map +1 -1
- package/models/trace/handlers/NetworkRequestsHandler.d.ts +15 -0
- package/models/trace/handlers/NetworkRequestsHandler.js +98 -2
- package/models/trace/handlers/NetworkRequestsHandler.js.map +1 -1
- package/models/trace/handlers/SamplesHandler.js.map +1 -1
- package/models/trace/handlers/types.d.ts +1 -8
- package/models/trace/handlers/types.js +1 -17
- package/models/trace/handlers/types.js.map +1 -1
- package/models/trace/helpers/Extensions.d.ts +1 -1
- package/models/trace/helpers/Extensions.js +22 -8
- package/models/trace/helpers/Extensions.js.map +1 -1
- package/models/trace/helpers/Network.d.ts +2 -0
- package/models/trace/helpers/Network.js +7 -0
- package/models/trace/helpers/Network.js.map +1 -0
- package/models/trace/helpers/SyntheticEvents.d.ts +3 -8
- package/models/trace/helpers/SyntheticEvents.js +16 -25
- package/models/trace/helpers/SyntheticEvents.js.map +1 -1
- package/models/trace/helpers/Timing.d.ts +1 -0
- package/models/trace/helpers/Timing.js +3 -0
- package/models/trace/helpers/Timing.js.map +1 -1
- package/models/trace/helpers/Trace.d.ts +2 -0
- package/models/trace/helpers/Trace.js +3 -3
- package/models/trace/helpers/Trace.js.map +1 -1
- package/models/trace/helpers/helpers-tsconfig.json +1 -0
- package/models/trace/helpers/helpers.d.ts +1 -0
- package/models/trace/helpers/helpers.js +1 -0
- package/models/trace/helpers/helpers.js.map +1 -1
- package/models/trace/insights/DocumentLatency.d.ts +8 -0
- package/models/trace/insights/DocumentLatency.js +44 -0
- package/models/trace/insights/DocumentLatency.js.map +1 -0
- package/models/trace/insights/InsightRunners.d.ts +1 -0
- package/models/trace/insights/InsightRunners.js +1 -0
- package/models/trace/insights/InsightRunners.js.map +1 -1
- package/models/trace/insights/LargestContentfulPaint.d.ts +2 -8
- package/models/trace/insights/LargestContentfulPaint.js +9 -5
- package/models/trace/insights/LargestContentfulPaint.js.map +1 -1
- package/models/trace/insights/RenderBlocking.d.ts +4 -2
- package/models/trace/insights/RenderBlocking.js +76 -1
- package/models/trace/insights/RenderBlocking.js.map +1 -1
- package/models/trace/insights/insights-tsconfig.json +4 -0
- package/models/trace/insights/types.d.ts +27 -19
- package/models/trace/insights/types.js.map +1 -1
- package/models/trace/lantern/core/NetworkAnalyzer.js +2 -1
- package/models/trace/lantern/core/NetworkAnalyzer.js.map +1 -1
- package/models/trace/lantern/graph/BaseNode.d.ts +5 -1
- package/models/trace/lantern/graph/BaseNode.js +11 -6
- package/models/trace/lantern/graph/BaseNode.js.map +1 -1
- package/models/trace/lantern/graph/PageDependencyGraph.js +8 -8
- package/models/trace/lantern/graph/PageDependencyGraph.js.map +1 -1
- package/models/trace/lantern/metrics/Interactive.d.ts +1 -1
- package/models/trace/lantern/metrics/Interactive.js +5 -4
- package/models/trace/lantern/metrics/Interactive.js.map +1 -1
- package/models/trace/lantern/metrics/LargestContentfulPaint.d.ts +1 -1
- package/models/trace/lantern/metrics/LargestContentfulPaint.js +3 -3
- package/models/trace/lantern/metrics/LargestContentfulPaint.js.map +1 -1
- package/models/trace/lantern/metrics/MaxPotentialFID.d.ts +1 -1
- package/models/trace/lantern/metrics/MaxPotentialFID.js +3 -2
- package/models/trace/lantern/metrics/MaxPotentialFID.js.map +1 -1
- package/models/trace/lantern/metrics/Metric.d.ts +1 -1
- package/models/trace/lantern/metrics/Metric.js +5 -4
- package/models/trace/lantern/metrics/Metric.js.map +1 -1
- package/models/trace/lantern/metrics/SpeedIndex.d.ts +1 -1
- package/models/trace/lantern/metrics/SpeedIndex.js +6 -5
- package/models/trace/lantern/metrics/SpeedIndex.js.map +1 -1
- package/models/trace/lantern/metrics/TotalBlockingTime.d.ts +1 -1
- package/models/trace/lantern/metrics/TotalBlockingTime.js +6 -5
- package/models/trace/lantern/metrics/TotalBlockingTime.js.map +1 -1
- package/models/trace/lantern/simulation/ConnectionPool.js +3 -3
- package/models/trace/lantern/simulation/ConnectionPool.js.map +1 -1
- package/models/trace/lantern/simulation/SimulationTimingMap.d.ts +0 -7
- package/models/trace/lantern/simulation/SimulationTimingMap.js +15 -14
- package/models/trace/lantern/simulation/SimulationTimingMap.js.map +1 -1
- package/models/trace/lantern/simulation/Simulator.js +10 -9
- package/models/trace/lantern/simulation/Simulator.js.map +1 -1
- package/models/trace/lantern/simulation/simulation-tsconfig.json +3 -0
- package/models/trace/lantern/types/Lantern.d.ts +1 -1
- package/models/trace/lantern/types/Lantern.js.map +1 -1
- package/models/trace/trace-tsconfig.json +0 -1
- package/models/trace/trace.d.ts +1 -2
- package/models/trace/trace.js +1 -2
- package/models/trace/trace.js.map +1 -1
- package/models/trace/types/Extensions.d.ts +30 -37
- package/models/trace/types/Extensions.js +7 -3
- package/models/trace/types/Extensions.js.map +1 -1
- package/models/trace/types/File.d.ts +29 -0
- package/models/trace/types/File.js.map +1 -1
- package/models/trace/types/TraceEvents.d.ts +31 -13
- package/models/trace/types/TraceEvents.js +14 -3
- package/models/trace/types/TraceEvents.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModelImpl.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/ModelImpl.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,iCAAiC,CAAC;AAE5D,OAAO,KAAK,QAAQ,MAAM,wBAAwB,CAAC;AACnD,OAAO,KAAK,OAAO,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAAC,uBAAuB,EAAE,cAAc,EAAC,MAAM,gBAAgB,CAAC;AACvE,OAAO,KAAK,KAAK,MAAM,kBAAkB,CAAC;AAY1C;;;;;;;;;;;;IAYI;AACJ,MAAM,OAAO,KACsE,SAAQ,WAAW;IAC3F,OAAO,GAA4C,EAAE,CAAC;IACtD,8BAA8B,GAAqD,EAAE,CAAC;IACtF,mBAAmB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEhD,oBAAoB,GAAa,EAAE,CAAC;IAC7C,mBAAmB,GAAG,CAAC,CAAC;IACxB,UAAU,CAAwE;IAClF,OAAO,GAAsC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;IAE5E,MAAM,CAAC,qBAAqB,CAAC,MAA0C;QACrE,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACnD,CAAC;IAED,YAAY,QAA8B,EAAE,MAA0C;QACpF,KAAK,EAAE,CAAC;QACR,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACxB,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,IAAI,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/D,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;QA0BI;IACJ,KAAK,CAAC,KAAK,CAAC,WAAwD,EAAE,MAAoB;QACxF,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC;QACxC,MAAM,gBAAgB,GAAG,MAAM,EAAE,gBAAgB,IAAI,KAAK,CAAC;QAC3D,wEAAwE;QACxE,uCAAuC;QACvC,MAAM,aAAa,GAAG,CAAC,KAAY,EAAQ,EAAE;YAC3C,MAAM,EAAC,IAAI,EAAC,GAAG,KAAgC,CAAC;YAChD,IAAI,CAAC,aAAa,CAAC,IAAI,gBAAgB,CAAC,EAAC,IAAI,yDAAiC,EAAE,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;QAChG,CAAC,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAEnF,kFAAkF;QAClF,MAAM,IAAI,GAA0C;YAClD,WAAW;YACX,QAAQ;YACR,eAAe,EAAE,IAAI;YACrB,aAAa,EAAE,IAAI;SACpB,CAAC;QAEF,IAAI,CAAC;YACH,0EAA0E;YAC1E,qCAAqC;YACrC,MAAM,sBAAsB,GACxB,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,kCAAkC,CAAC,WAAW,CAAC,CAAC;YACnG,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;YAC3D,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,eAAe,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC3F,uEAAuE;YACvE,6CAA6C;YAC7C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACnE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,CAAC;QACV,CAAC;gBAAS,CAAC;YACT,sEAAsE;YACtE,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,uBAAuB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;YACtF,gEAAgE;YAChE,IAAI,CAAC,aAAa,CAAC,IAAI,gBAAgB,CAAC,EAAC,IAAI,2CAA0B,EAAE,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC,CAAC;QAC3F,CAAC;IACH,CAAC;IAED,oBAAoB,CAChB,IAA2C,EAC3C,IAA0E,EAC1E,QAAoE;QACtE,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,aAAa,GAAG,SAAS,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACxD,IAAI,MAAM,GAAgB,IAAI,CAAC;QAC/B,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACtF,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,qBAAqB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,mBAAmB,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC9G,aAAa,GAAG,GAAG,MAAM,KAAK,qBAAqB,GAAG,CAAC;gBACvD,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,qBAAqB,GAAG,CAAC,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QACD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAChD,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,QAAgB,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QAErD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,eAAe,CAAC;IAC7C,CAAC;IAED,aAAa,CAAC,QAAgB,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QACnD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC;IAC3C,CAAC;IAED,QAAQ,CAAC,QAAgB,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC;IACtC,CAAC;IAED,qBAAqB,CAAC,KAAa,EAAE,gBAA0C;QAC7E,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,aAAa,GAAG,gBAAgB,CAAC;QAChE,CAAC;IACH,CAAC;IAED,cAAc,CAAC,QAAgB,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QACpD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC;IACzC,CAAC;IACD,2BAA2B,CAAC,QAAgB,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;QAEjE,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAC,KAAK,CAAC,EAAE,CAAC;YAChD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,8BAA8B,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7B,CAAC;IAED,kBAAkB,CAAC,cAAsB;QACvC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QACvC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,sBAAsB;QACpB,OAAO,IAAI,CAAC,oBAAoB,CAAC;IACnC,CAAC;IAED,cAAc;QACZ,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;CACF;AAiCD,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAEtB;IADnB,MAAM,CAAU,SAAS,GAAG,aAAa,CAAC;IAC1C,YAAmB,IAA0B;QAC3C,KAAK,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;QADjB,SAAI,GAAJ,IAAI,CAAsB;IAE7C,CAAC;;AASH,MAAM,UAAU,yBAAyB,CAAC,SAA+B;IACvE,OAAO,SAAS,CAAC,IAAI,8CAA6B,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,SAA+B;IACvE,OAAO,SAAS,CAAC,IAAI,4DAAoC,CAAC;AAC5D,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../core/platform/platform.js';\n\nimport * as Handlers from './handlers/handlers.js';\nimport * as Helpers from './helpers/helpers.js';\nimport type * as Insights from './insights/insights.js';\nimport {TraceParseProgressEvent, TraceProcessor} from './Processor.js';\nimport * as Types from './types/types.js';\n\n// Note: this model is implemented in a way that can support multiple trace\n// processors. Currently there is only one implemented, but you will see\n// references to \"processors\" plural because it can easily be extended in the future.\n\nexport interface ParseConfig {\n metadata?: Types.File.MetaData;\n // Unused but will eventually be consumed by UIUtils Linkifier, etc.\n isFreshRecording?: boolean;\n}\n\n/**\n * The new trace engine model we are migrating to. The Model is responsible for\n * parsing arrays of raw trace events and storing the resulting data. It can\n * store multiple traces at once, and can return the data for any of them.\n * Currently as we migrate from the old engine to this, we are turning on the\n * model handlers incrementally as we need the data, to save performance costs\n * of running handlers that we do not use. Therefore, when the model is\n * constructed we pass through a set of handlers that should be used. Once we\n * have migrated all tracks in the Performance Panel to this model, we can\n * remove this ability to run a subset of handlers, as we will need all handlers\n * to be used at that point. For tests, if you want to construct a model with\n * all handlers, you can use the static `Model.createWithAllHandlers` method.\n **/\nexport class Model<EnabledModelHandlers extends {[key: string]: Handlers.Types.TraceEventHandler} =\n typeof Handlers.ModelHandlers> extends EventTarget {\n readonly #traces: ParsedTraceFile<EnabledModelHandlers>[] = [];\n readonly #syntheticEventsManagerByTrace: Helpers.SyntheticEvents.SyntheticEventsManager[] = [];\n readonly #nextNumberByDomain = new Map<string, number>();\n\n readonly #recordingsAvailable: string[] = [];\n #lastRecordingIndex = 0;\n #processor: TraceProcessor<Handlers.Types.HandlersWithMeta<EnabledModelHandlers>>;\n #config: Types.Configuration.Configuration = Types.Configuration.defaults();\n\n static createWithAllHandlers(config?: Types.Configuration.Configuration): Model<typeof Handlers.ModelHandlers> {\n return new Model(Handlers.ModelHandlers, config);\n }\n\n constructor(handlers: EnabledModelHandlers, config?: Types.Configuration.Configuration) {\n super();\n if (config) {\n this.#config = config;\n }\n this.#processor = new TraceProcessor(handlers, this.#config);\n }\n\n /**\n * Parses an array of trace events into a structured object containing all the\n * information parsed by the trace handlers.\n * You can `await` this function to pause execution until parsing is complete,\n * or instead rely on the `ModuleUpdateEvent` that is dispatched when the\n * parsing is finished.\n *\n * Once parsed, you then have to call the `traceParsedData` method, providing an\n * index of the trace you want to have the data for. This is because any model\n * can store a number of traces. Each trace is given an index, which starts at 0\n * and increments by one as a new trace is parsed.\n *\n * @example\n * // Awaiting the parse method() to block until parsing complete\n * await this.traceModel.parse(events);\n * const data = this.traceModel.traceParsedData(0)\n *\n * @example\n * // Using an event listener to be notified when tracing is complete.\n * this.traceModel.addEventListener(Trace.ModelUpdateEvent.eventName, (event) => {\n * if(event.data.data === 'done') {\n * // trace complete\n * const data = this.traceModel.traceParsedData(0);\n * }\n * });\n * void this.traceModel.parse(events);\n **/\n async parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], config?: ParseConfig): Promise<void> {\n const metadata = config?.metadata || {};\n const isFreshRecording = config?.isFreshRecording || false;\n // During parsing, periodically update any listeners on each processors'\n // progress (if they have any updates).\n const onTraceUpdate = (event: Event): void => {\n const {data} = event as TraceParseProgressEvent;\n this.dispatchEvent(new ModelUpdateEvent({type: ModelUpdateType.PROGRESS_UPDATE, data: data}));\n };\n\n this.#processor.addEventListener(TraceParseProgressEvent.eventName, onTraceUpdate);\n\n // Create a parsed trace file. It will be populated with data from the processor.\n const file: ParsedTraceFile<EnabledModelHandlers> = {\n traceEvents,\n metadata,\n traceParsedData: null,\n traceInsights: null,\n };\n\n try {\n // Wait for all outstanding promises before finishing the async execution,\n // but perform all tasks in parallel.\n const syntheticEventsManager =\n Helpers.SyntheticEvents.SyntheticEventsManager.initSyntheticEventsManagerForTrace(traceEvents);\n await this.#processor.parse(traceEvents, isFreshRecording);\n this.#storeParsedFileData(file, this.#processor.traceParsedData, this.#processor.insights);\n // We only push the file onto this.#traces here once we know it's valid\n // and there's been no errors in the parsing.\n this.#traces.push(file);\n this.#syntheticEventsManagerByTrace.push(syntheticEventsManager);\n } catch (e) {\n throw e;\n } finally {\n // All processors have finished parsing, no more updates are expected.\n this.#processor.removeEventListener(TraceParseProgressEvent.eventName, onTraceUpdate);\n // Finally, update any listeners that all processors are 'done'.\n this.dispatchEvent(new ModelUpdateEvent({type: ModelUpdateType.COMPLETE, data: 'done'}));\n }\n }\n\n #storeParsedFileData(\n file: ParsedTraceFile<EnabledModelHandlers>,\n data: Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>|null,\n insights: Insights.Types.TraceInsightData<EnabledModelHandlers>|null): void {\n file.traceParsedData = data;\n file.traceInsights = insights;\n this.#lastRecordingIndex++;\n let recordingName = `Trace ${this.#lastRecordingIndex}`;\n let origin: string|null = null;\n if (file.traceParsedData) {\n origin = Helpers.Trace.extractOriginFromTrace(file.traceParsedData.Meta.mainFrameURL);\n if (origin) {\n const nextSequenceForDomain = Platform.MapUtilities.getWithDefault(this.#nextNumberByDomain, origin, () => 1);\n recordingName = `${origin} (${nextSequenceForDomain})`;\n this.#nextNumberByDomain.set(origin, nextSequenceForDomain + 1);\n }\n }\n this.#recordingsAvailable.push(recordingName);\n }\n\n /**\n * Returns the parsed trace data indexed by the order in which it was stored.\n * If no index is given, the last stored parsed data is returned.\n */\n traceParsedData(index: number = this.#traces.length - 1):\n Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>|null {\n if (!this.#traces[index]) {\n return null;\n }\n\n return this.#traces[index].traceParsedData;\n }\n\n traceInsights(index: number = this.#traces.length - 1): Insights.Types.TraceInsightData<EnabledModelHandlers>|null {\n if (!this.#traces[index]) {\n return null;\n }\n\n return this.#traces[index].traceInsights;\n }\n\n metadata(index: number = this.#traces.length - 1): Types.File.MetaData|null {\n if (!this.#traces[index]) {\n return null;\n }\n\n return this.#traces[index].metadata;\n }\n\n overrideModifications(index: number, newModifications: Types.File.Modifications): void {\n if (this.#traces[index]) {\n this.#traces[index].metadata.modifications = newModifications;\n }\n }\n\n rawTraceEvents(index: number = this.#traces.length - 1): readonly Types.TraceEvents.TraceEventData[]|null {\n if (!this.#traces[index]) {\n return null;\n }\n\n return this.#traces[index].traceEvents;\n }\n syntheticTraceEventsManager(index: number = this.#traces.length - 1): Helpers.SyntheticEvents.SyntheticEventsManager\n |null {\n if (!this.#syntheticEventsManagerByTrace[index]) {\n return null;\n }\n\n return this.#syntheticEventsManagerByTrace[index];\n }\n\n size(): number {\n return this.#traces.length;\n }\n\n deleteTraceByIndex(recordingIndex: number): void {\n this.#traces.splice(recordingIndex, 1);\n this.#recordingsAvailable.splice(recordingIndex, 1);\n }\n\n getRecordingsAvailable(): string[] {\n return this.#recordingsAvailable;\n }\n\n resetProcessor(): void {\n this.#processor.reset();\n }\n}\n\n/**\n * This parsed trace file is used by the Model. It keeps multiple instances\n * of these so that the user can swap between them. The key is that it is\n * essentially the TraceFile plus whatever the model has parsed from it.\n */\nexport type ParsedTraceFile<Handlers extends {[key: string]: Handlers.Types.TraceEventHandler}> = Types.File.TraceFile&{\n traceParsedData: Handlers.Types.EnabledHandlerDataWithMeta<Handlers>| null,\n traceInsights: Insights.Types.TraceInsightData<Handlers>| null,\n};\n\nexport const enum ModelUpdateType {\n COMPLETE = 'COMPLETE',\n PROGRESS_UPDATE = 'PROGRESS_UPDATE',\n}\n\nexport type ModelUpdateEventData = ModelUpdateEventComplete|ModelUpdateEventProgress;\n\nexport type ModelUpdateEventComplete = {\n type: ModelUpdateType.COMPLETE,\n data: 'done',\n};\nexport type ModelUpdateEventProgress = {\n type: ModelUpdateType.PROGRESS_UPDATE,\n data: TraceParseEventProgressData,\n};\n\nexport type TraceParseEventProgressData = {\n index: number,\n total: number,\n};\n\nexport class ModelUpdateEvent extends Event {\n static readonly eventName = 'modelupdate';\n constructor(public data: ModelUpdateEventData) {\n super(ModelUpdateEvent.eventName);\n }\n}\n\ndeclare global {\n interface HTMLElementEventMap {\n [ModelUpdateEvent.eventName]: ModelUpdateEvent;\n }\n}\n\nexport function isModelUpdateDataComplete(eventData: ModelUpdateEventData): eventData is ModelUpdateEventComplete {\n return eventData.type === ModelUpdateType.COMPLETE;\n}\n\nexport function isModelUpdateDataProgress(eventData: ModelUpdateEventData): eventData is ModelUpdateEventProgress {\n return eventData.type === ModelUpdateType.PROGRESS_UPDATE;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ModelImpl.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/ModelImpl.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../core/platform/platform.js';\n\nimport * as Handlers from './handlers/handlers.js';\nimport * as Helpers from './helpers/helpers.js';\nimport type * as Insights from './insights/insights.js';\nimport {TraceParseProgressEvent, TraceProcessor} from './Processor.js';\nimport * as Types from './types/types.js';\n\n// Note: this model is implemented in a way that can support multiple trace\n// processors. Currently there is only one implemented, but you will see\n// references to \"processors\" plural because it can easily be extended in the future.\n\nexport interface ParseConfig {\n metadata?: Types.File.MetaData;\n // Unused but will eventually be consumed by UIUtils Linkifier, etc.\n isFreshRecording?: boolean;\n}\n\n/**\n * The Model is responsible for parsing arrays of raw trace events and storing the\n * resulting data. It can store multiple traces at once, and can return the data for\n * any of them.\n *\n * Most uses of this class should be through `createWithAllHandlers`, but\n * `createWithSubsetOfHandlers` can be used to run just some handlers.\n **/\nexport class Model extends EventTarget {\n readonly #traces: ParsedTraceFile[] = [];\n readonly #syntheticEventsManagerByTrace: Helpers.SyntheticEvents.SyntheticEventsManager[] = [];\n readonly #nextNumberByDomain = new Map<string, number>();\n\n readonly #recordingsAvailable: string[] = [];\n #lastRecordingIndex = 0;\n #processor: TraceProcessor;\n #config: Types.Configuration.Configuration = Types.Configuration.defaults();\n\n static createWithAllHandlers(config?: Types.Configuration.Configuration): Model {\n return new Model(Handlers.ModelHandlers, config);\n }\n\n /**\n * Runs only the provided handlers.\n *\n * Callers must ensure they are providing all dependant handlers (although Meta is included automatically),\n * and must know that the result of `.traceParsedData` will be limited to the handlers provided, even though\n * the type won't reflect that.\n */\n static createWithSubsetOfHandlers(\n traceHandlers: Partial<Handlers.Types.Handlers>, config?: Types.Configuration.Configuration): Model {\n return new Model(traceHandlers as Handlers.Types.Handlers, config);\n }\n\n constructor(handlers: Handlers.Types.Handlers, config?: Types.Configuration.Configuration) {\n super();\n if (config) {\n this.#config = config;\n }\n this.#processor = new TraceProcessor(handlers, this.#config);\n }\n\n /**\n * Parses an array of trace events into a structured object containing all the\n * information parsed by the trace handlers.\n * You can `await` this function to pause execution until parsing is complete,\n * or instead rely on the `ModuleUpdateEvent` that is dispatched when the\n * parsing is finished.\n *\n * Once parsed, you then have to call the `traceParsedData` method, providing an\n * index of the trace you want to have the data for. This is because any model\n * can store a number of traces. Each trace is given an index, which starts at 0\n * and increments by one as a new trace is parsed.\n *\n * @example\n * // Awaiting the parse method() to block until parsing complete\n * await this.traceModel.parse(events);\n * const data = this.traceModel.traceParsedData(0)\n *\n * @example\n * // Using an event listener to be notified when tracing is complete.\n * this.traceModel.addEventListener(Trace.ModelUpdateEvent.eventName, (event) => {\n * if(event.data.data === 'done') {\n * // trace complete\n * const data = this.traceModel.traceParsedData(0);\n * }\n * });\n * void this.traceModel.parse(events);\n **/\n async parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], config?: ParseConfig): Promise<void> {\n const metadata = config?.metadata || {};\n const isFreshRecording = config?.isFreshRecording || false;\n // During parsing, periodically update any listeners on each processors'\n // progress (if they have any updates).\n const onTraceUpdate = (event: Event): void => {\n const {data} = event as TraceParseProgressEvent;\n this.dispatchEvent(new ModelUpdateEvent({type: ModelUpdateType.PROGRESS_UPDATE, data: data}));\n };\n\n this.#processor.addEventListener(TraceParseProgressEvent.eventName, onTraceUpdate);\n\n // Create a parsed trace file. It will be populated with data from the processor.\n const file: ParsedTraceFile = {\n traceEvents,\n metadata,\n traceParsedData: null,\n traceInsights: null,\n };\n\n try {\n // Wait for all outstanding promises before finishing the async execution,\n // but perform all tasks in parallel.\n const syntheticEventsManager = Helpers.SyntheticEvents.SyntheticEventsManager.initAndActivate(traceEvents);\n await this.#processor.parse(traceEvents, isFreshRecording);\n this.#storeParsedFileData(file, this.#processor.traceParsedData, this.#processor.insights);\n // We only push the file onto this.#traces here once we know it's valid\n // and there's been no errors in the parsing.\n this.#traces.push(file);\n this.#syntheticEventsManagerByTrace.push(syntheticEventsManager);\n } catch (e) {\n throw e;\n } finally {\n // All processors have finished parsing, no more updates are expected.\n this.#processor.removeEventListener(TraceParseProgressEvent.eventName, onTraceUpdate);\n // Finally, update any listeners that all processors are 'done'.\n this.dispatchEvent(new ModelUpdateEvent({type: ModelUpdateType.COMPLETE, data: 'done'}));\n }\n }\n\n #storeParsedFileData(\n file: ParsedTraceFile, data: Handlers.Types.TraceParseData|null,\n insights: Insights.Types.TraceInsightData|null): void {\n file.traceParsedData = data;\n file.traceInsights = insights;\n this.#lastRecordingIndex++;\n let recordingName = `Trace ${this.#lastRecordingIndex}`;\n let origin: string|null = null;\n if (file.traceParsedData) {\n origin = Helpers.Trace.extractOriginFromTrace(file.traceParsedData.Meta.mainFrameURL);\n if (origin) {\n const nextSequenceForDomain = Platform.MapUtilities.getWithDefault(this.#nextNumberByDomain, origin, () => 1);\n recordingName = `${origin} (${nextSequenceForDomain})`;\n this.#nextNumberByDomain.set(origin, nextSequenceForDomain + 1);\n }\n }\n this.#recordingsAvailable.push(recordingName);\n }\n\n lastTraceIndex(): number {\n return this.size() - 1;\n }\n\n /**\n * Returns the parsed trace data indexed by the order in which it was stored.\n * If no index is given, the last stored parsed data is returned.\n */\n traceParsedData(index: number = this.#traces.length - 1): Handlers.Types.TraceParseData|null {\n if (!this.#traces[index]) {\n return null;\n }\n\n return this.#traces[index].traceParsedData;\n }\n\n traceInsights(index: number = this.#traces.length - 1): Insights.Types.TraceInsightData|null {\n if (!this.#traces[index]) {\n return null;\n }\n\n return this.#traces[index].traceInsights;\n }\n\n metadata(index: number = this.#traces.length - 1): Types.File.MetaData|null {\n if (!this.#traces[index]) {\n return null;\n }\n\n return this.#traces[index].metadata;\n }\n\n overrideModifications(index: number, newModifications: Types.File.Modifications): void {\n if (this.#traces[index]) {\n this.#traces[index].metadata.modifications = newModifications;\n }\n }\n\n rawTraceEvents(index: number = this.#traces.length - 1): readonly Types.TraceEvents.TraceEventData[]|null {\n if (!this.#traces[index]) {\n return null;\n }\n\n return this.#traces[index].traceEvents;\n }\n syntheticTraceEventsManager(index: number = this.#traces.length - 1): Helpers.SyntheticEvents.SyntheticEventsManager\n |null {\n if (!this.#syntheticEventsManagerByTrace[index]) {\n return null;\n }\n\n return this.#syntheticEventsManagerByTrace[index];\n }\n\n size(): number {\n return this.#traces.length;\n }\n\n deleteTraceByIndex(recordingIndex: number): void {\n this.#traces.splice(recordingIndex, 1);\n this.#recordingsAvailable.splice(recordingIndex, 1);\n }\n\n getRecordingsAvailable(): string[] {\n return this.#recordingsAvailable;\n }\n\n resetProcessor(): void {\n this.#processor.reset();\n }\n}\n\n/**\n * This parsed trace file is used by the Model. It keeps multiple instances\n * of these so that the user can swap between them. The key is that it is\n * essentially the TraceFile plus whatever the model has parsed from it.\n */\nexport type ParsedTraceFile = Types.File.TraceFile&{\n traceParsedData: Handlers.Types.TraceParseData | null,\n traceInsights: Insights.Types.TraceInsightData | null,\n};\n\nexport const enum ModelUpdateType {\n COMPLETE = 'COMPLETE',\n PROGRESS_UPDATE = 'PROGRESS_UPDATE',\n}\n\nexport type ModelUpdateEventData = ModelUpdateEventComplete|ModelUpdateEventProgress;\n\nexport type ModelUpdateEventComplete = {\n type: ModelUpdateType.COMPLETE,\n data: 'done',\n};\nexport type ModelUpdateEventProgress = {\n type: ModelUpdateType.PROGRESS_UPDATE,\n data: TraceParseEventProgressData,\n};\n\nexport type TraceParseEventProgressData = {\n index: number,\n total: number,\n};\n\nexport class ModelUpdateEvent extends Event {\n static readonly eventName = 'modelupdate';\n constructor(public data: ModelUpdateEventData) {\n super(ModelUpdateEvent.eventName);\n }\n}\n\ndeclare global {\n interface HTMLElementEventMap {\n [ModelUpdateEvent.eventName]: ModelUpdateEvent;\n }\n}\n\nexport function isModelUpdateDataComplete(eventData: ModelUpdateEventData): eventData is ModelUpdateEventComplete {\n return eventData.type === ModelUpdateType.COMPLETE;\n}\n\nexport function isModelUpdateDataProgress(eventData: ModelUpdateEventData): eventData is ModelUpdateEventProgress {\n return eventData.type === ModelUpdateType.PROGRESS_UPDATE;\n}\n"]}
|
|
@@ -15,16 +15,15 @@ declare global {
|
|
|
15
15
|
[TraceParseProgressEvent.eventName]: TraceParseProgressEvent;
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
export declare class TraceProcessor
|
|
19
|
-
[key: string]: Handlers.Types.TraceEventHandler;
|
|
20
|
-
}> extends EventTarget {
|
|
18
|
+
export declare class TraceProcessor extends EventTarget {
|
|
21
19
|
#private;
|
|
22
|
-
static createWithAllHandlers(): TraceProcessor
|
|
23
|
-
|
|
20
|
+
static createWithAllHandlers(): TraceProcessor;
|
|
21
|
+
static getEnabledInsightRunners(traceParsedData: Handlers.Types.TraceParseData): Partial<Insights.Types.InsightRunnersType>;
|
|
22
|
+
constructor(traceHandlers: Partial<Handlers.Types.Handlers>, modelConfiguration?: Types.Configuration.Configuration);
|
|
24
23
|
reset(): void;
|
|
25
24
|
parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording?: boolean): Promise<void>;
|
|
26
|
-
get traceParsedData(): Handlers.Types.
|
|
27
|
-
get insights(): Insights.Types.TraceInsightData
|
|
25
|
+
get traceParsedData(): Handlers.Types.TraceParseData | null;
|
|
26
|
+
get insights(): Insights.Types.TraceInsightData | null;
|
|
28
27
|
}
|
|
29
28
|
/**
|
|
30
29
|
* Some Handlers need data provided by others. Dependencies of a handler handler are
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
// found in the LICENSE file.
|
|
4
4
|
import * as Handlers from './handlers/handlers.js';
|
|
5
5
|
import * as Insights from './insights/insights.js';
|
|
6
|
+
import * as Lantern from './lantern/lantern.js';
|
|
7
|
+
import * as LanternComputationData from './LanternComputationData.js';
|
|
6
8
|
import * as Types from './types/types.js';
|
|
7
9
|
export class TraceParseProgressEvent extends Event {
|
|
8
10
|
data;
|
|
@@ -23,6 +25,17 @@ export class TraceProcessor extends EventTarget {
|
|
|
23
25
|
static createWithAllHandlers() {
|
|
24
26
|
return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.defaults());
|
|
25
27
|
}
|
|
28
|
+
static getEnabledInsightRunners(traceParsedData) {
|
|
29
|
+
const enabledInsights = {};
|
|
30
|
+
for (const [name, insight] of Object.entries(Insights.InsightRunners)) {
|
|
31
|
+
const deps = insight.deps();
|
|
32
|
+
if (deps.some(dep => !traceParsedData[dep])) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
Object.assign(enabledInsights, { [name]: insight });
|
|
36
|
+
}
|
|
37
|
+
return enabledInsights;
|
|
38
|
+
}
|
|
26
39
|
constructor(traceHandlers, modelConfiguration) {
|
|
27
40
|
super();
|
|
28
41
|
this.#verifyHandlers(traceHandlers);
|
|
@@ -63,7 +76,8 @@ export class TraceProcessor extends EventTarget {
|
|
|
63
76
|
const requiredHandlerKeys = new Set();
|
|
64
77
|
for (const [handlerName, handler] of Object.entries(providedHandlers)) {
|
|
65
78
|
requiredHandlerKeys.add(handlerName);
|
|
66
|
-
|
|
79
|
+
const deps = 'deps' in handler ? handler.deps() : [];
|
|
80
|
+
for (const depName of deps) {
|
|
67
81
|
requiredHandlerKeys.add(depName);
|
|
68
82
|
}
|
|
69
83
|
}
|
|
@@ -96,7 +110,10 @@ export class TraceProcessor extends EventTarget {
|
|
|
96
110
|
}
|
|
97
111
|
try {
|
|
98
112
|
this.#status = "PARSING" /* Status.PARSING */;
|
|
99
|
-
await this.#
|
|
113
|
+
await this.#computeTraceParsedData(traceEvents, freshRecording);
|
|
114
|
+
if (this.#data) {
|
|
115
|
+
this.#computeInsights(this.#data, traceEvents);
|
|
116
|
+
}
|
|
100
117
|
this.#status = "FINISHED_PARSING" /* Status.FINISHED_PARSING */;
|
|
101
118
|
}
|
|
102
119
|
catch (e) {
|
|
@@ -104,7 +121,10 @@ export class TraceProcessor extends EventTarget {
|
|
|
104
121
|
throw e;
|
|
105
122
|
}
|
|
106
123
|
}
|
|
107
|
-
|
|
124
|
+
/**
|
|
125
|
+
* Run all the handlers and set the result to `#data`.
|
|
126
|
+
*/
|
|
127
|
+
async #computeTraceParsedData(traceEvents, freshRecording) {
|
|
108
128
|
/**
|
|
109
129
|
* We want to yield regularly to maintain responsiveness. If we yield too often, we're wasting idle time.
|
|
110
130
|
* We could do this by checking `performance.now()` regularly, but it's an expensive call in such a hot loop.
|
|
@@ -147,14 +167,6 @@ export class TraceProcessor extends EventTarget {
|
|
|
147
167
|
await handler.finalize();
|
|
148
168
|
}
|
|
149
169
|
}
|
|
150
|
-
}
|
|
151
|
-
get traceParsedData() {
|
|
152
|
-
if (this.#status !== "FINISHED_PARSING" /* Status.FINISHED_PARSING */) {
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
if (this.#data) {
|
|
156
|
-
return this.#data;
|
|
157
|
-
}
|
|
158
170
|
// Handlers that depend on other handlers do so via .data(), which used to always
|
|
159
171
|
// return a shallow clone of its internal data structures. However, that pattern
|
|
160
172
|
// easily results in egregious amounts of allocation. Now .data() does not do any
|
|
@@ -186,41 +198,103 @@ export class TraceProcessor extends EventTarget {
|
|
|
186
198
|
Object.assign(traceParsedData, { [name]: data });
|
|
187
199
|
}
|
|
188
200
|
this.#data = traceParsedData;
|
|
189
|
-
return this.#data;
|
|
190
201
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
const deps = insight.deps();
|
|
195
|
-
if (deps.some(dep => !traceParsedData[dep])) {
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
Object.assign(enabledInsights, { [name]: insight.generateInsight });
|
|
202
|
+
get traceParsedData() {
|
|
203
|
+
if (this.#status !== "FINISHED_PARSING" /* Status.FINISHED_PARSING */) {
|
|
204
|
+
return null;
|
|
199
205
|
}
|
|
200
|
-
return
|
|
206
|
+
return this.#data;
|
|
201
207
|
}
|
|
202
208
|
get insights() {
|
|
203
|
-
if (
|
|
209
|
+
if (this.#status !== "FINISHED_PARSING" /* Status.FINISHED_PARSING */) {
|
|
204
210
|
return null;
|
|
205
211
|
}
|
|
206
|
-
|
|
207
|
-
|
|
212
|
+
return this.#insights;
|
|
213
|
+
}
|
|
214
|
+
#createLanternContext(traceParsedData, traceEvents) {
|
|
215
|
+
// Check for required handlers.
|
|
216
|
+
if (!traceParsedData.NetworkRequests || !traceParsedData.Workers || !traceParsedData.PageLoadMetrics) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (!traceParsedData.NetworkRequests.byTime.length) {
|
|
220
|
+
throw new Lantern.Core.LanternError('No network requests found in trace');
|
|
208
221
|
}
|
|
222
|
+
// Lantern.Types.TraceEvent and Types.TraceEvents.TraceEventData represent the same
|
|
223
|
+
// object - a trace event - but one is more flexible than the other. It should be safe to cast between them.
|
|
224
|
+
const trace = {
|
|
225
|
+
traceEvents: traceEvents,
|
|
226
|
+
};
|
|
227
|
+
const requests = LanternComputationData.createNetworkRequests(trace, traceParsedData);
|
|
228
|
+
const graph = LanternComputationData.createGraph(requests, trace, traceParsedData);
|
|
229
|
+
const processedNavigation = LanternComputationData.createProcessedNavigation(traceParsedData);
|
|
230
|
+
const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);
|
|
231
|
+
const simulator = Lantern.Simulation.Simulator.createSimulator({
|
|
232
|
+
networkAnalysis,
|
|
233
|
+
throttlingMethod: 'simulate',
|
|
234
|
+
});
|
|
235
|
+
const computeData = { graph, simulator, processedNavigation };
|
|
236
|
+
const fcpResult = Lantern.Metrics.FirstContentfulPaint.compute(computeData);
|
|
237
|
+
const lcpResult = Lantern.Metrics.LargestContentfulPaint.compute(computeData, { fcpResult });
|
|
238
|
+
const interactiveResult = Lantern.Metrics.Interactive.compute(computeData, { lcpResult });
|
|
239
|
+
const tbtResult = Lantern.Metrics.TotalBlockingTime.compute(computeData, { fcpResult, interactiveResult });
|
|
240
|
+
const metrics = {
|
|
241
|
+
firstContentfulPaint: fcpResult,
|
|
242
|
+
interactive: interactiveResult,
|
|
243
|
+
largestContentfulPaint: lcpResult,
|
|
244
|
+
totalBlockingTime: tbtResult,
|
|
245
|
+
};
|
|
246
|
+
return { graph, simulator, metrics };
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Run all the insights and set the result to `#insights`.
|
|
250
|
+
*/
|
|
251
|
+
#computeInsights(traceParsedData, traceEvents) {
|
|
209
252
|
this.#insights = new Map();
|
|
210
|
-
const enabledInsightRunners =
|
|
211
|
-
|
|
253
|
+
const enabledInsightRunners = TraceProcessor.getEnabledInsightRunners(traceParsedData);
|
|
254
|
+
// The lantern sub-context is optional on NavigationInsightContext, so not setting it is OK.
|
|
255
|
+
// This is also a hedge against an error inside Lantern resulting in breaking the entire performance panel.
|
|
256
|
+
// Additionally, many trace fixtures are too old to be processed by Lantern.
|
|
257
|
+
// TODO(crbug.com/313905799): should be created and scoped per-navigation.
|
|
258
|
+
let lantern;
|
|
259
|
+
try {
|
|
260
|
+
lantern = this.#createLanternContext(traceParsedData, traceEvents);
|
|
261
|
+
}
|
|
262
|
+
catch (e) {
|
|
263
|
+
// Don't allow an error in constructing the Lantern graphs to break the rest of the trace processor.
|
|
264
|
+
// Log unexpected errors, but suppress anything that occurs from a trace being too old.
|
|
265
|
+
// Otherwise tests using old fixtures become way too noisy.
|
|
266
|
+
const expectedErrors = [
|
|
267
|
+
'mainDocumentRequest not found',
|
|
268
|
+
'missing metric scores for main frame',
|
|
269
|
+
'missing metric: FCP',
|
|
270
|
+
'missing metric: LCP',
|
|
271
|
+
'No network requests found in trace',
|
|
272
|
+
'Trace is too old',
|
|
273
|
+
];
|
|
274
|
+
if (!(e instanceof Lantern.Core.LanternError)) {
|
|
275
|
+
// If this wasn't a managed LanternError, the stack trace is likely needed for debugging.
|
|
276
|
+
console.error(e);
|
|
277
|
+
}
|
|
278
|
+
else if (!expectedErrors.some(err => e.message === err)) {
|
|
279
|
+
// To reduce noise from tests, only print errors that are not expected to occur because a trace is
|
|
280
|
+
// too old (for which there is no single check).
|
|
281
|
+
console.error(e.message);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
for (const nav of traceParsedData.Meta.mainFrameNavigations) {
|
|
212
285
|
if (!nav.args.frame || !nav.args.data?.navigationId) {
|
|
213
286
|
continue;
|
|
214
287
|
}
|
|
215
288
|
const context = {
|
|
216
289
|
frameId: nav.args.frame,
|
|
217
290
|
navigationId: nav.args.data.navigationId,
|
|
291
|
+
lantern,
|
|
218
292
|
};
|
|
219
293
|
const navInsightData = {};
|
|
220
|
-
for (const [name,
|
|
294
|
+
for (const [name, insight] of Object.entries(enabledInsightRunners)) {
|
|
221
295
|
let insightResult;
|
|
222
296
|
try {
|
|
223
|
-
insightResult = generateInsight(
|
|
297
|
+
insightResult = insight.generateInsight(traceParsedData, context);
|
|
224
298
|
}
|
|
225
299
|
catch (err) {
|
|
226
300
|
insightResult = err;
|
|
@@ -229,7 +303,6 @@ export class TraceProcessor extends EventTarget {
|
|
|
229
303
|
}
|
|
230
304
|
this.#insights.set(context.navigationId, navInsightData);
|
|
231
305
|
}
|
|
232
|
-
return this.#insights;
|
|
233
306
|
}
|
|
234
307
|
}
|
|
235
308
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Processor.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/Processor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Handlers from './handlers/handlers.js';\nimport * as Insights from './insights/insights.js';\nimport * as Types from './types/types.js';\n\nconst enum Status {\n IDLE = 'IDLE',\n PARSING = 'PARSING',\n FINISHED_PARSING = 'FINISHED_PARSING',\n ERRORED_WHILE_PARSING = 'ERRORED_WHILE_PARSING',\n}\n\nexport type TraceParseEventProgressData = {\n index: number,\n total: number,\n};\n\nexport class TraceParseProgressEvent extends Event {\n static readonly eventName = 'traceparseprogress';\n constructor(public data: TraceParseEventProgressData, init: EventInit = {bubbles: true}) {\n super(TraceParseProgressEvent.eventName, init);\n }\n}\ndeclare global {\n interface HTMLElementEventMap {\n [TraceParseProgressEvent.eventName]: TraceParseProgressEvent;\n }\n}\n\nexport class TraceProcessor<EnabledModelHandlers extends {[key: string]: Handlers.Types.TraceEventHandler}> extends\n EventTarget {\n // We force the Meta handler to be enabled, so the TraceHandlers type here is\n // the model handlers the user passes in and the Meta handler.\n readonly #traceHandlers: Handlers.Types.HandlersWithMeta<EnabledModelHandlers>;\n #status = Status.IDLE;\n #modelConfiguration = Types.Configuration.defaults();\n #data: Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>|null = null;\n #insights: Insights.Types.TraceInsightData<EnabledModelHandlers>|null = null;\n\n static createWithAllHandlers(): TraceProcessor<typeof Handlers.ModelHandlers> {\n return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.defaults());\n }\n\n constructor(traceHandlers: EnabledModelHandlers, modelConfiguration?: Types.Configuration.Configuration) {\n super();\n\n this.#verifyHandlers(traceHandlers);\n this.#traceHandlers = {\n Meta: Handlers.ModelHandlers.Meta,\n ...traceHandlers,\n };\n if (modelConfiguration) {\n this.#modelConfiguration = modelConfiguration;\n }\n this.#passConfigToHandlers();\n }\n\n #passConfigToHandlers(): void {\n for (const handler of Object.values(this.#traceHandlers)) {\n // Bit of an odd double check, but without this TypeScript refuses to let\n // you call the function as it thinks it might be undefined.\n if ('handleUserConfig' in handler && handler.handleUserConfig) {\n handler.handleUserConfig(this.#modelConfiguration);\n }\n }\n }\n\n /**\n * When the user passes in a set of handlers, we want to ensure that we have all\n * the required handlers. Handlers can depend on other handlers, so if the user\n * passes in FooHandler which depends on BarHandler, they must also pass in\n * BarHandler too. This method verifies that all dependencies are met, and\n * throws if not.\n **/\n #verifyHandlers(providedHandlers: EnabledModelHandlers): void {\n // Tiny optimisation: if the amount of provided handlers matches the amount\n // of handlers in the Handlers.ModelHandlers object, that means that the\n // user has passed in every handler we have. So therefore they cannot have\n // missed any, and there is no need to iterate through the handlers and\n // check the dependencies.\n if (Object.keys(providedHandlers).length === Object.keys(Handlers.ModelHandlers).length) {\n return;\n }\n const requiredHandlerKeys: Set<Handlers.Types.TraceEventHandlerName> = new Set();\n for (const [handlerName, handler] of Object.entries(providedHandlers)) {\n requiredHandlerKeys.add(handlerName as Handlers.Types.TraceEventHandlerName);\n for (const depName of (handler.deps?.() || [])) {\n requiredHandlerKeys.add(depName);\n }\n }\n\n const providedHandlerKeys = new Set(Object.keys(providedHandlers));\n // We always force the Meta handler to be enabled when creating the\n // Processor, so if it is missing from the set the user gave us that is OK,\n // as we will have enabled it anyway.\n requiredHandlerKeys.delete('Meta');\n\n for (const requiredKey of requiredHandlerKeys) {\n if (!providedHandlerKeys.has(requiredKey)) {\n throw new Error(`Required handler ${requiredKey} not provided.`);\n }\n }\n }\n\n reset(): void {\n if (this.#status === Status.PARSING) {\n throw new Error('Trace processor can\\'t reset while parsing.');\n }\n\n const handlers = Object.values(this.#traceHandlers);\n for (const handler of handlers) {\n handler.reset();\n }\n\n this.#data = null;\n this.#insights = null;\n this.#status = Status.IDLE;\n }\n\n async parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording = false): Promise<void> {\n if (this.#status !== Status.IDLE) {\n throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);\n }\n try {\n this.#status = Status.PARSING;\n await this.#parse(traceEvents, freshRecording);\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n }\n }\n\n async #parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording: boolean): Promise<void> {\n /**\n * We want to yield regularly to maintain responsiveness. If we yield too often, we're wasting idle time.\n * We could do this by checking `performance.now()` regularly, but it's an expensive call in such a hot loop.\n * `eventsPerChunk` is an approximated proxy metric.\n * But how big a chunk? We're aiming for long tasks that are no smaller than 100ms and not bigger than 200ms.\n * It's CPU dependent, so it should be calibrated on oldish hardware.\n * Illustration of a previous change to `eventsPerChunk`: https://imgur.com/wzp8BnR\n */\n const eventsPerChunk = 50_000;\n // Convert to array so that we are able to iterate all handlers multiple times.\n const sortedHandlers = [...sortHandlers(this.#traceHandlers).values()];\n\n // Reset.\n for (const handler of sortedHandlers) {\n handler.reset();\n }\n\n // Initialize.\n for (const handler of sortedHandlers) {\n handler.initialize?.(freshRecording);\n }\n\n // Handle each event.\n for (let i = 0; i < traceEvents.length; ++i) {\n // Every so often we take a break just to render.\n if (i % eventsPerChunk === 0 && i) {\n // Take the opportunity to provide status update events.\n this.dispatchEvent(new TraceParseProgressEvent({index: i, total: traceEvents.length}));\n // TODO(paulirish): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n const event = traceEvents[i];\n for (let j = 0; j < sortedHandlers.length; ++j) {\n sortedHandlers[j].handleEvent(event);\n }\n }\n\n // Finalize.\n for (const handler of sortedHandlers) {\n if (handler.finalize) {\n // Yield to the UI because finalize() calls can be expensive\n // TODO(jacktfranklin): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n await handler.finalize();\n }\n }\n }\n\n get traceParsedData(): Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n if (this.#data) {\n return this.#data;\n }\n\n // Handlers that depend on other handlers do so via .data(), which used to always\n // return a shallow clone of its internal data structures. However, that pattern\n // easily results in egregious amounts of allocation. Now .data() does not do any\n // cloning, and it happens here instead so that users of the trace processor may\n // still assume that the parsed data is theirs.\n // See: crbug/41484172\n const shallowClone = (value: unknown, recurse = true): unknown => {\n if (value instanceof Map) {\n return new Map(value);\n }\n if (value instanceof Set) {\n return new Set(value);\n }\n if (Array.isArray(value)) {\n return [...value];\n }\n if (typeof value === 'object' && value && recurse) {\n const obj: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value)) {\n obj[key] = shallowClone(v, false);\n }\n return obj;\n }\n return value;\n };\n\n const traceParsedData = {};\n for (const [name, handler] of Object.entries(this.#traceHandlers)) {\n const data = shallowClone(handler.data());\n Object.assign(traceParsedData, {[name]: data});\n }\n\n this.#data = traceParsedData as Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>;\n return this.#data;\n }\n\n #getEnabledInsightRunners(traceParsedData: Handlers.Types.EnabledHandlerDataWithMeta<EnabledModelHandlers>):\n Insights.Types.EnabledInsightRunners<EnabledModelHandlers> {\n const enabledInsights = {} as Insights.Types.EnabledInsightRunners<EnabledModelHandlers>;\n for (const [name, insight] of Object.entries(Insights.InsightRunners)) {\n const deps = insight.deps();\n if (deps.some(dep => !traceParsedData[dep])) {\n continue;\n }\n Object.assign(enabledInsights, {[name]: insight.generateInsight});\n }\n return enabledInsights;\n }\n\n get insights(): Insights.Types.TraceInsightData<EnabledModelHandlers>|null {\n if (!this.traceParsedData) {\n return null;\n }\n\n if (this.#insights) {\n return this.#insights;\n }\n\n this.#insights = new Map();\n\n const enabledInsightRunners = this.#getEnabledInsightRunners(this.traceParsedData);\n\n for (const nav of this.traceParsedData.Meta.mainFrameNavigations) {\n if (!nav.args.frame || !nav.args.data?.navigationId) {\n continue;\n }\n\n const context = {\n frameId: nav.args.frame,\n navigationId: nav.args.data.navigationId,\n };\n\n const navInsightData = {} as Insights.Types.NavigationInsightData<EnabledModelHandlers>;\n for (const [name, generateInsight] of Object.entries(enabledInsightRunners)) {\n let insightResult;\n try {\n insightResult = generateInsight(this.traceParsedData, context);\n } catch (err) {\n insightResult = err;\n }\n Object.assign(navInsightData, {[name]: insightResult});\n }\n\n this.#insights.set(context.navigationId, navInsightData);\n }\n\n return this.#insights;\n }\n}\n\n/**\n * Some Handlers need data provided by others. Dependencies of a handler handler are\n * declared in the `deps` field.\n * @returns A map from trace event handler name to trace event hander whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(\n traceHandlers: Partial<{[key in Handlers.Types.TraceEventHandlerName]: Handlers.Types.TraceEventHandler}>):\n Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler> {\n const sortedMap = new Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler>();\n const visited = new Set<Handlers.Types.TraceEventHandlerName>();\n const visitHandler = (handlerName: Handlers.Types.TraceEventHandlerName): void => {\n if (sortedMap.has(handlerName)) {\n return;\n }\n if (visited.has(handlerName)) {\n let stackPath = '';\n for (const handler of visited) {\n if (stackPath || handler === handlerName) {\n stackPath += `${handler}->`;\n }\n }\n stackPath += handlerName;\n throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);\n }\n visited.add(handlerName);\n const handler = traceHandlers[handlerName];\n if (!handler) {\n return;\n }\n const deps = handler.deps?.();\n if (deps) {\n deps.forEach(visitHandler);\n }\n sortedMap.set(handlerName, handler);\n };\n\n for (const handlerName of Object.keys(traceHandlers)) {\n visitHandler(handlerName as Handlers.Types.TraceEventHandlerName);\n }\n return sortedMap;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Processor.js","sourceRoot":"","sources":["../../../../../../front_end/models/trace/Processor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Handlers from './handlers/handlers.js';\nimport * as Insights from './insights/insights.js';\nimport * as Lantern from './lantern/lantern.js';\nimport * as LanternComputationData from './LanternComputationData.js';\nimport * as Types from './types/types.js';\n\nconst enum Status {\n IDLE = 'IDLE',\n PARSING = 'PARSING',\n FINISHED_PARSING = 'FINISHED_PARSING',\n ERRORED_WHILE_PARSING = 'ERRORED_WHILE_PARSING',\n}\n\nexport type TraceParseEventProgressData = {\n index: number,\n total: number,\n};\n\nexport class TraceParseProgressEvent extends Event {\n static readonly eventName = 'traceparseprogress';\n constructor(public data: TraceParseEventProgressData, init: EventInit = {bubbles: true}) {\n super(TraceParseProgressEvent.eventName, init);\n }\n}\ndeclare global {\n interface HTMLElementEventMap {\n [TraceParseProgressEvent.eventName]: TraceParseProgressEvent;\n }\n}\n\nexport class TraceProcessor extends EventTarget {\n // We force the Meta handler to be enabled, so the TraceHandlers type here is\n // the model handlers the user passes in and the Meta handler.\n readonly #traceHandlers: Partial<Handlers.Types.Handlers>;\n #status = Status.IDLE;\n #modelConfiguration = Types.Configuration.defaults();\n #data: Handlers.Types.TraceParseData|null = null;\n #insights: Insights.Types.TraceInsightData|null = null;\n\n static createWithAllHandlers(): TraceProcessor {\n return new TraceProcessor(Handlers.ModelHandlers, Types.Configuration.defaults());\n }\n\n static getEnabledInsightRunners(traceParsedData: Handlers.Types.TraceParseData):\n Partial<Insights.Types.InsightRunnersType> {\n const enabledInsights = {} as Insights.Types.InsightRunnersType;\n for (const [name, insight] of Object.entries(Insights.InsightRunners)) {\n const deps = insight.deps();\n if (deps.some(dep => !traceParsedData[dep])) {\n continue;\n }\n Object.assign(enabledInsights, {[name]: insight});\n }\n return enabledInsights;\n }\n\n constructor(traceHandlers: Partial<Handlers.Types.Handlers>, modelConfiguration?: Types.Configuration.Configuration) {\n super();\n\n this.#verifyHandlers(traceHandlers);\n this.#traceHandlers = {\n Meta: Handlers.ModelHandlers.Meta,\n ...traceHandlers,\n };\n if (modelConfiguration) {\n this.#modelConfiguration = modelConfiguration;\n }\n this.#passConfigToHandlers();\n }\n\n #passConfigToHandlers(): void {\n for (const handler of Object.values(this.#traceHandlers)) {\n // Bit of an odd double check, but without this TypeScript refuses to let\n // you call the function as it thinks it might be undefined.\n if ('handleUserConfig' in handler && handler.handleUserConfig) {\n handler.handleUserConfig(this.#modelConfiguration);\n }\n }\n }\n\n /**\n * When the user passes in a set of handlers, we want to ensure that we have all\n * the required handlers. Handlers can depend on other handlers, so if the user\n * passes in FooHandler which depends on BarHandler, they must also pass in\n * BarHandler too. This method verifies that all dependencies are met, and\n * throws if not.\n **/\n #verifyHandlers(providedHandlers: Partial<Handlers.Types.Handlers>): void {\n // Tiny optimisation: if the amount of provided handlers matches the amount\n // of handlers in the Handlers.ModelHandlers object, that means that the\n // user has passed in every handler we have. So therefore they cannot have\n // missed any, and there is no need to iterate through the handlers and\n // check the dependencies.\n if (Object.keys(providedHandlers).length === Object.keys(Handlers.ModelHandlers).length) {\n return;\n }\n const requiredHandlerKeys: Set<Handlers.Types.TraceEventHandlerName> = new Set();\n for (const [handlerName, handler] of Object.entries(providedHandlers)) {\n requiredHandlerKeys.add(handlerName as Handlers.Types.TraceEventHandlerName);\n const deps = 'deps' in handler ? handler.deps() : [];\n for (const depName of deps) {\n requiredHandlerKeys.add(depName);\n }\n }\n\n const providedHandlerKeys = new Set(Object.keys(providedHandlers));\n // We always force the Meta handler to be enabled when creating the\n // Processor, so if it is missing from the set the user gave us that is OK,\n // as we will have enabled it anyway.\n requiredHandlerKeys.delete('Meta');\n\n for (const requiredKey of requiredHandlerKeys) {\n if (!providedHandlerKeys.has(requiredKey)) {\n throw new Error(`Required handler ${requiredKey} not provided.`);\n }\n }\n }\n\n reset(): void {\n if (this.#status === Status.PARSING) {\n throw new Error('Trace processor can\\'t reset while parsing.');\n }\n\n const handlers = Object.values(this.#traceHandlers);\n for (const handler of handlers) {\n handler.reset();\n }\n\n this.#data = null;\n this.#insights = null;\n this.#status = Status.IDLE;\n }\n\n async parse(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording = false): Promise<void> {\n if (this.#status !== Status.IDLE) {\n throw new Error(`Trace processor can't start parsing when not idle. Current state: ${this.#status}`);\n }\n try {\n this.#status = Status.PARSING;\n await this.#computeTraceParsedData(traceEvents, freshRecording);\n if (this.#data) {\n this.#computeInsights(this.#data, traceEvents);\n }\n this.#status = Status.FINISHED_PARSING;\n } catch (e) {\n this.#status = Status.ERRORED_WHILE_PARSING;\n throw e;\n }\n }\n\n /**\n * Run all the handlers and set the result to `#data`.\n */\n async #computeTraceParsedData(traceEvents: readonly Types.TraceEvents.TraceEventData[], freshRecording: boolean):\n Promise<void> {\n /**\n * We want to yield regularly to maintain responsiveness. If we yield too often, we're wasting idle time.\n * We could do this by checking `performance.now()` regularly, but it's an expensive call in such a hot loop.\n * `eventsPerChunk` is an approximated proxy metric.\n * But how big a chunk? We're aiming for long tasks that are no smaller than 100ms and not bigger than 200ms.\n * It's CPU dependent, so it should be calibrated on oldish hardware.\n * Illustration of a previous change to `eventsPerChunk`: https://imgur.com/wzp8BnR\n */\n const eventsPerChunk = 50_000;\n // Convert to array so that we are able to iterate all handlers multiple times.\n const sortedHandlers = [...sortHandlers(this.#traceHandlers).values()];\n\n // Reset.\n for (const handler of sortedHandlers) {\n handler.reset();\n }\n\n // Initialize.\n for (const handler of sortedHandlers) {\n handler.initialize?.(freshRecording);\n }\n\n // Handle each event.\n for (let i = 0; i < traceEvents.length; ++i) {\n // Every so often we take a break just to render.\n if (i % eventsPerChunk === 0 && i) {\n // Take the opportunity to provide status update events.\n this.dispatchEvent(new TraceParseProgressEvent({index: i, total: traceEvents.length}));\n // TODO(paulirish): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n const event = traceEvents[i];\n for (let j = 0; j < sortedHandlers.length; ++j) {\n sortedHandlers[j].handleEvent(event);\n }\n }\n\n // Finalize.\n for (const handler of sortedHandlers) {\n if (handler.finalize) {\n // Yield to the UI because finalize() calls can be expensive\n // TODO(jacktfranklin): consider using `scheduler.yield()` or `scheduler.postTask(() => {}, {priority: 'user-blocking'})`\n await new Promise(resolve => setTimeout(resolve, 0));\n await handler.finalize();\n }\n }\n\n // Handlers that depend on other handlers do so via .data(), which used to always\n // return a shallow clone of its internal data structures. However, that pattern\n // easily results in egregious amounts of allocation. Now .data() does not do any\n // cloning, and it happens here instead so that users of the trace processor may\n // still assume that the parsed data is theirs.\n // See: crbug/41484172\n const shallowClone = (value: unknown, recurse = true): unknown => {\n if (value instanceof Map) {\n return new Map(value);\n }\n if (value instanceof Set) {\n return new Set(value);\n }\n if (Array.isArray(value)) {\n return [...value];\n }\n if (typeof value === 'object' && value && recurse) {\n const obj: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(value)) {\n obj[key] = shallowClone(v, false);\n }\n return obj;\n }\n return value;\n };\n\n const traceParsedData = {};\n for (const [name, handler] of Object.entries(this.#traceHandlers)) {\n const data = shallowClone(handler.data());\n Object.assign(traceParsedData, {[name]: data});\n }\n\n this.#data = traceParsedData as Handlers.Types.TraceParseData;\n }\n\n get traceParsedData(): Handlers.Types.TraceParseData|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#data;\n }\n\n get insights(): Insights.Types.TraceInsightData|null {\n if (this.#status !== Status.FINISHED_PARSING) {\n return null;\n }\n\n return this.#insights;\n }\n\n #createLanternContext(\n traceParsedData: Handlers.Types.TraceParseData,\n traceEvents: readonly Types.TraceEvents.TraceEventData[]): Insights.Types.LanternContext|undefined {\n // Check for required handlers.\n if (!traceParsedData.NetworkRequests || !traceParsedData.Workers || !traceParsedData.PageLoadMetrics) {\n return;\n }\n if (!traceParsedData.NetworkRequests.byTime.length) {\n throw new Lantern.Core.LanternError('No network requests found in trace');\n }\n\n // Lantern.Types.TraceEvent and Types.TraceEvents.TraceEventData represent the same\n // object - a trace event - but one is more flexible than the other. It should be safe to cast between them.\n const trace: Lantern.Types.Trace = {\n traceEvents: traceEvents as unknown as Lantern.Types.TraceEvent[],\n };\n\n const requests = LanternComputationData.createNetworkRequests(trace, traceParsedData);\n const graph = LanternComputationData.createGraph(requests, trace, traceParsedData);\n const processedNavigation = LanternComputationData.createProcessedNavigation(traceParsedData);\n\n const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);\n const simulator: Lantern.Simulation.Simulator<Types.TraceEvents.SyntheticNetworkRequest> =\n Lantern.Simulation.Simulator.createSimulator({\n networkAnalysis,\n throttlingMethod: 'simulate',\n });\n\n const computeData = {graph, simulator, processedNavigation};\n const fcpResult = Lantern.Metrics.FirstContentfulPaint.compute(computeData);\n const lcpResult = Lantern.Metrics.LargestContentfulPaint.compute(computeData, {fcpResult});\n const interactiveResult = Lantern.Metrics.Interactive.compute(computeData, {lcpResult});\n const tbtResult = Lantern.Metrics.TotalBlockingTime.compute(computeData, {fcpResult, interactiveResult});\n const metrics = {\n firstContentfulPaint: fcpResult,\n interactive: interactiveResult,\n largestContentfulPaint: lcpResult,\n totalBlockingTime: tbtResult,\n };\n\n return {graph, simulator, metrics};\n }\n\n /**\n * Run all the insights and set the result to `#insights`.\n */\n #computeInsights(\n traceParsedData: Handlers.Types.TraceParseData, traceEvents: readonly Types.TraceEvents.TraceEventData[]): void {\n this.#insights = new Map();\n\n const enabledInsightRunners = TraceProcessor.getEnabledInsightRunners(traceParsedData);\n\n // The lantern sub-context is optional on NavigationInsightContext, so not setting it is OK.\n // This is also a hedge against an error inside Lantern resulting in breaking the entire performance panel.\n // Additionally, many trace fixtures are too old to be processed by Lantern.\n // TODO(crbug.com/313905799): should be created and scoped per-navigation.\n let lantern;\n try {\n lantern = this.#createLanternContext(traceParsedData, traceEvents);\n } catch (e) {\n // Don't allow an error in constructing the Lantern graphs to break the rest of the trace processor.\n // Log unexpected errors, but suppress anything that occurs from a trace being too old.\n // Otherwise tests using old fixtures become way too noisy.\n const expectedErrors = [\n 'mainDocumentRequest not found',\n 'missing metric scores for main frame',\n 'missing metric: FCP',\n 'missing metric: LCP',\n 'No network requests found in trace',\n 'Trace is too old',\n ];\n if (!(e instanceof Lantern.Core.LanternError)) {\n // If this wasn't a managed LanternError, the stack trace is likely needed for debugging.\n console.error(e);\n } else if (!expectedErrors.some(err => e.message === err)) {\n // To reduce noise from tests, only print errors that are not expected to occur because a trace is\n // too old (for which there is no single check).\n console.error(e.message);\n }\n }\n\n for (const nav of traceParsedData.Meta.mainFrameNavigations) {\n if (!nav.args.frame || !nav.args.data?.navigationId) {\n continue;\n }\n\n const context: Insights.Types.NavigationInsightContext = {\n frameId: nav.args.frame,\n navigationId: nav.args.data.navigationId,\n lantern,\n };\n\n const navInsightData = {} as Insights.Types.NavigationInsightData;\n for (const [name, insight] of Object.entries(enabledInsightRunners)) {\n let insightResult;\n try {\n insightResult = insight.generateInsight(traceParsedData, context);\n } catch (err) {\n insightResult = err;\n }\n Object.assign(navInsightData, {[name]: insightResult});\n }\n\n this.#insights.set(context.navigationId, navInsightData);\n }\n }\n}\n\n/**\n * Some Handlers need data provided by others. Dependencies of a handler handler are\n * declared in the `deps` field.\n * @returns A map from trace event handler name to trace event hander whose entries\n * iterate in such a way that each handler is visited after its dependencies.\n */\nexport function sortHandlers(\n traceHandlers: Partial<{[key in Handlers.Types.TraceEventHandlerName]: Handlers.Types.TraceEventHandler}>):\n Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler> {\n const sortedMap = new Map<Handlers.Types.TraceEventHandlerName, Handlers.Types.TraceEventHandler>();\n const visited = new Set<Handlers.Types.TraceEventHandlerName>();\n const visitHandler = (handlerName: Handlers.Types.TraceEventHandlerName): void => {\n if (sortedMap.has(handlerName)) {\n return;\n }\n if (visited.has(handlerName)) {\n let stackPath = '';\n for (const handler of visited) {\n if (stackPath || handler === handlerName) {\n stackPath += `${handler}->`;\n }\n }\n stackPath += handlerName;\n throw new Error(`Found dependency cycle in trace event handlers: ${stackPath}`);\n }\n visited.add(handlerName);\n const handler = traceHandlers[handlerName];\n if (!handler) {\n return;\n }\n const deps = handler.deps?.();\n if (deps) {\n deps.forEach(visitHandler);\n }\n sortedMap.set(handlerName, handler);\n };\n\n for (const handlerName of Object.keys(traceHandlers)) {\n visitHandler(handlerName as Handlers.Types.TraceEventHandlerName);\n }\n return sortedMap;\n}\n"]}
|
|
@@ -9,7 +9,7 @@ export function get(traceParsedData, entry) {
|
|
|
9
9
|
if (entry.args?.data?.stackTrace && entry.args.data.stackTrace.length > 0) {
|
|
10
10
|
return entry.args.data.stackTrace[0].url;
|
|
11
11
|
}
|
|
12
|
-
if (Types.TraceEvents.
|
|
12
|
+
if (Types.TraceEvents.isSyntheticNetworkRequestEvent(entry)) {
|
|
13
13
|
return entry.args.data.url;
|
|
14
14
|
}
|
|
15
15
|
// DecodeImage events use the URL from the relevant PaintImage event.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"URLForEntry.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/URLForEntry.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,MAAM,UAAU,GAAG,CAAC,eAA8C,EAAE,KAAuC;IAEzG,IAAI,KAAK,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC,SAAS,CAAC,GAAsC,CAAC;IAChE,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAsC,CAAC;IAC9E,CAAC;IAED,IAAI,KAAK,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"URLForEntry.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/extras/URLForEntry.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,MAAM,UAAU,GAAG,CAAC,eAA8C,EAAE,KAAuC;IAEzG,IAAI,KAAK,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC,SAAS,CAAC,GAAsC,CAAC;IAChE,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAsC,CAAC;IAC9E,CAAC;IAED,IAAI,KAAK,CAAC,WAAW,CAAC,8BAA8B,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAsC,CAAC;IAChE,CAAC;IAED,qEAAqE;IACrE,IAAI,KAAK,CAAC,WAAW,CAAC,uBAAuB,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,MAAM,UAAU,GAAG,eAAe,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC/E,OAAO,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9D,CAAC;IAED,0EAA0E;IAC1E,IAAI,KAAK,CAAC,WAAW,CAAC,4BAA4B,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;QACtF,MAAM,UAAU,GAAG,eAAe,CAAC,aAAa,CAAC,4BAA4B,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3G,OAAO,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9D,CAAC;IAED,4DAA4D;IAC5D,IAAI,KAAK,CAAC,WAAW,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;QACnD,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAsC,CAAC;IACrE,CAAC;IAED,6EAA6E;IAC7E,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAsC,CAAC;IAChE,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Platform from '../../../core/platform/platform.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Types from '../types/types.js';\n\nexport function get(traceParsedData: Handlers.Types.TraceParseData, entry: Types.TraceEvents.TraceEventData):\n Platform.DevToolsPath.UrlString|null {\n if (Types.TraceEvents.isProfileCall(entry)) {\n return entry.callFrame.url as Platform.DevToolsPath.UrlString;\n }\n\n if (entry.args?.data?.stackTrace && entry.args.data.stackTrace.length > 0) {\n return entry.args.data.stackTrace[0].url as Platform.DevToolsPath.UrlString;\n }\n\n if (Types.TraceEvents.isSyntheticNetworkRequestEvent(entry)) {\n return entry.args.data.url as Platform.DevToolsPath.UrlString;\n }\n\n // DecodeImage events use the URL from the relevant PaintImage event.\n if (Types.TraceEvents.isTraceEventDecodeImage(entry)) {\n const paintEvent = traceParsedData.ImagePainting.paintImageForEvent.get(entry);\n return paintEvent ? get(traceParsedData, paintEvent) : null;\n }\n\n // DrawLazyPixelRef events use the URL from the relevant PaintImage event.\n if (Types.TraceEvents.isTraceEventDrawLazyPixelRef(entry) && entry.args?.LazyPixelRef) {\n const paintEvent = traceParsedData.ImagePainting.paintImageByDrawLazyPixelRef.get(entry.args.LazyPixelRef);\n return paintEvent ? get(traceParsedData, paintEvent) : null;\n }\n\n // ParseHTML events store the URL under beginData, not data.\n if (Types.TraceEvents.isTraceEventParseHTML(entry)) {\n return entry.args.beginData.url as Platform.DevToolsPath.UrlString;\n }\n\n // For all other events, try to see if the URL is provided, else return null.\n if (entry.args?.data?.url) {\n return entry.args.data.url as Platform.DevToolsPath.UrlString;\n }\n\n return null;\n}\n"]}
|
|
@@ -38,10 +38,6 @@ export function extractExtensionEntries(timings) {
|
|
|
38
38
|
// Not an extension user timing.
|
|
39
39
|
continue;
|
|
40
40
|
}
|
|
41
|
-
const extensionName = extensionPayload.metadata.extensionName;
|
|
42
|
-
if (!extensionName) {
|
|
43
|
-
continue;
|
|
44
|
-
}
|
|
45
41
|
const extensionSyntheticEntry = {
|
|
46
42
|
name: timing.name,
|
|
47
43
|
ph: "X" /* Types.TraceEvents.Phase.COMPLETE */,
|
|
@@ -57,7 +53,7 @@ export function extractExtensionEntries(timings) {
|
|
|
57
53
|
extensionMarkers.push(extensionSyntheticEntry);
|
|
58
54
|
continue;
|
|
59
55
|
}
|
|
60
|
-
if (Types.Extensions.
|
|
56
|
+
if (Types.Extensions.isExtensionPayloadTrackEntry(extensionPayload)) {
|
|
61
57
|
extensionFlameChartEntries.push(extensionSyntheticEntry);
|
|
62
58
|
continue;
|
|
63
59
|
}
|
|
@@ -80,7 +76,7 @@ export function extensionDataInTiming(timing) {
|
|
|
80
76
|
if (!('devtools' in detailObj)) {
|
|
81
77
|
return null;
|
|
82
78
|
}
|
|
83
|
-
if (!(
|
|
79
|
+
if (!Types.Extensions.isValidExtensionPayload(detailObj.devtools)) {
|
|
84
80
|
return null;
|
|
85
81
|
}
|
|
86
82
|
return detailObj.devtools;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExtensionTraceDataHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ExtensionTraceDataHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EAAC,IAAI,IAAI,eAAe,EAAC,MAAM,yBAAyB,CAAC;AAEhE,MAAM,0BAA0B,GAAyD,EAAE,CAAC;AAC5F,MAAM,kBAAkB,GAA0C,EAAE,CAAC;AACrE,MAAM,gBAAgB,GAAgD,EAAE,CAAC;AAMzE,IAAI,YAAY,qCAA6B,CAAC;AAE9C,MAAM,UAAU,WAAW,CAAC,MAAwC;IAClE,4EAA4E;AAC9E,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,YAAY,mCAA2B,CAAC;IACxC,0BAA0B,CAAC,MAAM,GAAG,CAAC,CAAC;IACtC,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9B,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IACD,gCAAgC,EAAE,CAAC;IACnC,YAAY,iCAAyB,CAAC;AACxC,CAAC;AAED,SAAS,gCAAgC;IACvC,MAAM,cAAc,GAAyD,eAAe,EAAE,CAAC,mBAAmB,CAAC;IACnH,MAAM,KAAK,GAA2D,eAAe,EAAE,CAAC,gBAAgB,CAAC;IACzG,MAAM,wBAAwB,GAAG,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IAEzF,uBAAuB,CAAC,wBAAwB,CAAC,CAAC;IAClD,OAAO,CAAC,UAAU,CAAC,kCAAkC,CAAC,0BAA0B,EAAE,kBAAkB,CAAC,CAAC;AACxG,CAAC;AAED,MAAM,UAAU,uBAAuB,CACnC,OAAkG;IACpG,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;QACvD,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,gCAAgC;YAChC,SAAS;QACX,CAAC;
|
|
1
|
+
{"version":3,"file":"ExtensionTraceDataHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ExtensionTraceDataHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {HandlerState, type TraceEventHandlerName} from './types.js';\nimport {data as userTimingsData} from './UserTimingsHandler.js';\n\nconst extensionFlameChartEntries: Types.Extensions.SyntheticExtensionTrackChartEntry[] = [];\nconst extensionTrackData: Types.Extensions.ExtensionTrackData[] = [];\nconst extensionMarkers: Types.Extensions.SyntheticExtensionMarker[] = [];\n\nexport interface ExtensionTraceData {\n extensionTrackData: readonly Types.Extensions.ExtensionTrackData[];\n extensionMarkers: readonly Types.Extensions.SyntheticExtensionMarker[];\n}\nlet handlerState = HandlerState.UNINITIALIZED;\n\nexport function handleEvent(_event: Types.TraceEvents.TraceEventData): void {\n // Implementation not needed because data is sourced from UserTimingsHandler\n}\n\nexport function reset(): void {\n handlerState = HandlerState.INITIALIZED;\n extensionFlameChartEntries.length = 0;\n extensionTrackData.length = 0;\n extensionMarkers.length = 0;\n}\n\nexport async function finalize(): Promise<void> {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('ExtensionTraceData handler is not initialized');\n }\n createExtensionFlameChartEntries();\n handlerState = HandlerState.FINALIZED;\n}\n\nfunction createExtensionFlameChartEntries(): void {\n const pairedMeasures: readonly Types.TraceEvents.SyntheticUserTimingPair[] = userTimingsData().performanceMeasures;\n const marks: readonly Types.TraceEvents.TraceEventPerformanceMark[] = userTimingsData().performanceMarks;\n const mergedRawExtensionEvents = Helpers.Trace.mergeEventsInOrder(pairedMeasures, marks);\n\n extractExtensionEntries(mergedRawExtensionEvents);\n Helpers.Extensions.buildTrackDataFromExtensionEntries(extensionFlameChartEntries, extensionTrackData);\n}\n\nexport function extractExtensionEntries(\n timings: (Types.TraceEvents.SyntheticUserTimingPair|Types.TraceEvents.TraceEventPerformanceMark)[]): void {\n for (const timing of timings) {\n const extensionPayload = extensionDataInTiming(timing);\n if (!extensionPayload) {\n // Not an extension user timing.\n continue;\n }\n\n const extensionSyntheticEntry = {\n name: timing.name,\n ph: Types.TraceEvents.Phase.COMPLETE,\n pid: Types.TraceEvents.ProcessID(0),\n tid: Types.TraceEvents.ThreadID(0),\n ts: timing.ts,\n selfTime: Types.Timing.MicroSeconds(0),\n dur: timing.dur as Types.Timing.MicroSeconds,\n cat: 'devtools.extension',\n args: extensionPayload,\n };\n if (Types.Extensions.isExtensionPayloadMarker(extensionPayload)) {\n extensionMarkers.push(extensionSyntheticEntry as Types.Extensions.SyntheticExtensionMarker);\n continue;\n }\n if (Types.Extensions.isExtensionPayloadTrackEntry(extensionPayload)) {\n extensionFlameChartEntries.push(extensionSyntheticEntry as Types.Extensions.SyntheticExtensionTrackChartEntry);\n continue;\n }\n }\n}\n\nexport function extensionDataInTiming(timing: Types.TraceEvents.SyntheticUserTimingPair|\n Types.TraceEvents.TraceEventPerformanceMark):\n Types.Extensions.ExtensionDataPayload|null {\n const timingDetail = Types.TraceEvents.isTraceEventPerformanceMark(timing) ? timing.args.data?.detail :\n timing.args.data.beginEvent.args.detail;\n if (!timingDetail) {\n return null;\n }\n try {\n // Attempt to parse the detail as an object that might be coming from a\n // DevTools Perf extension.\n // Wrapped in a try-catch because timingDetail might either:\n // 1. Not be `json.parse`-able (it should, but just in case...)\n // 2.Not be an object - in which case the `in` check will error.\n // If we hit either of these cases, we just ignore this mark and move on.\n const detailObj = JSON.parse(timingDetail);\n if (!('devtools' in detailObj)) {\n return null;\n }\n if (!Types.Extensions.isValidExtensionPayload(detailObj.devtools)) {\n return null;\n }\n return detailObj.devtools;\n } catch (e) {\n // No need to worry about this error, just discard this event and don't\n // treat it as having any useful information for the purposes of extensions\n return null;\n }\n}\n\nexport function data(): ExtensionTraceData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('ExtensionTraceData handler is not finalized');\n }\n\n return {\n extensionTrackData: [...extensionTrackData],\n extensionMarkers: [...extensionMarkers],\n };\n}\n\nexport function deps(): TraceEventHandlerName[] {\n return ['UserTimings'];\n}\n"]}
|
|
@@ -4,7 +4,7 @@ export declare function initialize(): void;
|
|
|
4
4
|
export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void;
|
|
5
5
|
export declare function finalize(): Promise<void>;
|
|
6
6
|
interface InvalidationsData {
|
|
7
|
-
invalidationsForEvent: Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.
|
|
7
|
+
invalidationsForEvent: Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.InvalidationTrackingEvent[]>;
|
|
8
8
|
}
|
|
9
9
|
export declare function data(): InvalidationsData;
|
|
10
10
|
export {};
|
|
@@ -23,23 +23,7 @@ export function initialize() {
|
|
|
23
23
|
}
|
|
24
24
|
function addInvalidationToEvent(event, invalidation) {
|
|
25
25
|
const existingInvalidations = invalidationsForEvent.get(event) || [];
|
|
26
|
-
|
|
27
|
-
...invalidation,
|
|
28
|
-
name: 'SyntheticInvalidation',
|
|
29
|
-
frame: invalidation.args.data.frame,
|
|
30
|
-
nodeId: invalidation.args.data.nodeId,
|
|
31
|
-
rawEvent: invalidation,
|
|
32
|
-
};
|
|
33
|
-
if (invalidation.args.data.nodeName) {
|
|
34
|
-
syntheticInvalidation.nodeName = invalidation.args.data.nodeName;
|
|
35
|
-
}
|
|
36
|
-
if (invalidation.args.data.reason) {
|
|
37
|
-
syntheticInvalidation.reason = invalidation.args.data.reason;
|
|
38
|
-
}
|
|
39
|
-
if (invalidation.args.data.stackTrace) {
|
|
40
|
-
syntheticInvalidation.stackTrace = invalidation.args.data.stackTrace;
|
|
41
|
-
}
|
|
42
|
-
existingInvalidations.push(syntheticInvalidation);
|
|
26
|
+
existingInvalidations.push(invalidation);
|
|
43
27
|
invalidationsForEvent.set(event, existingInvalidations);
|
|
44
28
|
}
|
|
45
29
|
export function handleEvent(event) {
|
|
@@ -59,10 +43,7 @@ export function handleEvent(event) {
|
|
|
59
43
|
}
|
|
60
44
|
return;
|
|
61
45
|
}
|
|
62
|
-
if (Types.TraceEvents.
|
|
63
|
-
Types.TraceEvents.isTraceEventStyleRecalcInvalidationTracking(event) ||
|
|
64
|
-
Types.TraceEvents.isTraceEventStyleInvalidatorInvalidationTracking(event) ||
|
|
65
|
-
Types.TraceEvents.isTraceEventLayoutInvalidationTracking(event)) {
|
|
46
|
+
if (Types.TraceEvents.isTraceEventInvalidationTracking(event)) {
|
|
66
47
|
if (hasPainted) {
|
|
67
48
|
// If we have painted, then we can clear out the list of all existing
|
|
68
49
|
// invalidations, as we cannot associate them across frames.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InvalidationsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/InvalidationsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nconst invalidationsForEvent = new Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.SyntheticInvalidation[]>();\n\nlet lastRecalcStyleEvent: Types.TraceEvents.TraceEventUpdateLayoutTree|null = null;\n\n// Used to track paints so we track invalidations correctly per paint.\nlet hasPainted = false;\n\nconst allInvalidationTrackingEvents:\n Array<Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking|\n Types.TraceEvents.TraceEventStyleRecalcInvalidationTracking|Types.TraceEvents\n .TraceEventStyleInvalidatorInvalidationTracking|Types.TraceEvents.TraceEventLayoutInvalidationTracking> =\n [];\n\nexport function reset(): void {\n handlerState = HandlerState.UNINITIALIZED;\n invalidationsForEvent.clear();\n lastRecalcStyleEvent = null;\n allInvalidationTrackingEvents.length = 0;\n hasPainted = false;\n}\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('InvalidationsHandler was not reset before being initialized');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nfunction addInvalidationToEvent(\n event: Types.TraceEvents.TraceEventData,\n invalidation: Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking|\n Types.TraceEvents.TraceEventStyleRecalcInvalidationTracking|\n Types.TraceEvents.TraceEventStyleInvalidatorInvalidationTracking|\n Types.TraceEvents.TraceEventLayoutInvalidationTracking): void {\n const existingInvalidations = invalidationsForEvent.get(event) || [];\n\n const syntheticInvalidation: Types.TraceEvents.SyntheticInvalidation = {\n ...invalidation,\n name: 'SyntheticInvalidation',\n frame: invalidation.args.data.frame,\n nodeId: invalidation.args.data.nodeId,\n rawEvent: invalidation,\n };\n\n if (invalidation.args.data.nodeName) {\n syntheticInvalidation.nodeName = invalidation.args.data.nodeName;\n }\n if (invalidation.args.data.reason) {\n syntheticInvalidation.reason = invalidation.args.data.reason;\n }\n if (invalidation.args.data.stackTrace) {\n syntheticInvalidation.stackTrace = invalidation.args.data.stackTrace;\n }\n\n existingInvalidations.push(syntheticInvalidation);\n invalidationsForEvent.set(event, existingInvalidations);\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {\n lastRecalcStyleEvent = event;\n\n // Associate any prior invalidations with this recalc event.\n for (const invalidation of allInvalidationTrackingEvents) {\n if (Types.TraceEvents.isTraceEventLayoutInvalidationTracking(invalidation)) {\n // LayoutInvalidation events cannot be associated with a LayoutTree\n // event.\n continue;\n }\n\n const recalcFrameId = lastRecalcStyleEvent.args.beginData?.frame;\n\n if (recalcFrameId && invalidation.args.data.frame === recalcFrameId) {\n addInvalidationToEvent(event, invalidation);\n }\n }\n return;\n }\n\n if (Types.TraceEvents.isTraceEventScheduleStyleInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleRecalcInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleInvalidatorInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventLayoutInvalidationTracking(event)) {\n if (hasPainted) {\n // If we have painted, then we can clear out the list of all existing\n // invalidations, as we cannot associate them across frames.\n allInvalidationTrackingEvents.length = 0;\n lastRecalcStyleEvent = null;\n hasPainted = false;\n }\n\n // Style invalidation events can occur before and during recalc styles. When we get a recalc style event (aka TraceEventUpdateLayoutTree), we check and associate any prior invalidations with it.\n // But any invalidations that occur during a TraceEventUpdateLayoutTree\n // event would be reported in trace events after. So each time we get an\n // invalidation that might be due to a style recalc, we check if the\n // timings overlap and if so associate them.\n if (lastRecalcStyleEvent &&\n (Types.TraceEvents.isTraceEventScheduleStyleInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleRecalcInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleInvalidatorInvalidationTracking(event))) {\n const recalcEndTime = lastRecalcStyleEvent.ts + (lastRecalcStyleEvent.dur || 0);\n if (event.ts >= lastRecalcStyleEvent.ts && event.ts <= recalcEndTime &&\n lastRecalcStyleEvent.args.beginData?.frame === event.args.data.frame) {\n addInvalidationToEvent(lastRecalcStyleEvent, event);\n }\n }\n\n allInvalidationTrackingEvents.push(event);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventPaint(event)) {\n // Used to ensure that we do not create relationships across frames.\n hasPainted = true;\n return;\n }\n\n if (Types.TraceEvents.isTraceEventLayout(event)) {\n const layoutFrame = event.args.beginData.frame;\n for (const invalidation of allInvalidationTrackingEvents) {\n // The only invalidations that cause a Layout are LayoutInvalidations :)\n if (!Types.TraceEvents.isTraceEventLayoutInvalidationTracking(invalidation)) {\n continue;\n }\n\n if (invalidation.args.data.frame === layoutFrame) {\n addInvalidationToEvent(event, invalidation);\n }\n }\n }\n}\n\nexport async function finalize(): Promise<void> {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('InvalidationsHandler is not initialized');\n }\n\n handlerState = HandlerState.FINALIZED;\n}\n\ninterface InvalidationsData {\n invalidationsForEvent: Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.SyntheticInvalidation[]>;\n}\n\nexport function data(): InvalidationsData {\n return {\n invalidationsForEvent,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"InvalidationsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/InvalidationsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nconst invalidationsForEvent =\n new Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.InvalidationTrackingEvent[]>();\n\nlet lastRecalcStyleEvent: Types.TraceEvents.TraceEventUpdateLayoutTree|null = null;\n\n// Used to track paints so we track invalidations correctly per paint.\nlet hasPainted = false;\n\nconst allInvalidationTrackingEvents: Array<Types.TraceEvents.InvalidationTrackingEvent> = [];\n\nexport function reset(): void {\n handlerState = HandlerState.UNINITIALIZED;\n invalidationsForEvent.clear();\n lastRecalcStyleEvent = null;\n allInvalidationTrackingEvents.length = 0;\n hasPainted = false;\n}\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('InvalidationsHandler was not reset before being initialized');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nfunction addInvalidationToEvent(\n event: Types.TraceEvents.TraceEventData, invalidation: Types.TraceEvents.InvalidationTrackingEvent): void {\n const existingInvalidations = invalidationsForEvent.get(event) || [];\n existingInvalidations.push(invalidation);\n invalidationsForEvent.set(event, existingInvalidations);\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {\n lastRecalcStyleEvent = event;\n\n // Associate any prior invalidations with this recalc event.\n for (const invalidation of allInvalidationTrackingEvents) {\n if (Types.TraceEvents.isTraceEventLayoutInvalidationTracking(invalidation)) {\n // LayoutInvalidation events cannot be associated with a LayoutTree\n // event.\n continue;\n }\n\n const recalcFrameId = lastRecalcStyleEvent.args.beginData?.frame;\n\n if (recalcFrameId && invalidation.args.data.frame === recalcFrameId) {\n addInvalidationToEvent(event, invalidation);\n }\n }\n return;\n }\n\n if (Types.TraceEvents.isTraceEventInvalidationTracking(event)) {\n if (hasPainted) {\n // If we have painted, then we can clear out the list of all existing\n // invalidations, as we cannot associate them across frames.\n allInvalidationTrackingEvents.length = 0;\n lastRecalcStyleEvent = null;\n hasPainted = false;\n }\n\n // Style invalidation events can occur before and during recalc styles. When we get a recalc style event (aka TraceEventUpdateLayoutTree), we check and associate any prior invalidations with it.\n // But any invalidations that occur during a TraceEventUpdateLayoutTree\n // event would be reported in trace events after. So each time we get an\n // invalidation that might be due to a style recalc, we check if the\n // timings overlap and if so associate them.\n if (lastRecalcStyleEvent &&\n (Types.TraceEvents.isTraceEventScheduleStyleInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleRecalcInvalidationTracking(event) ||\n Types.TraceEvents.isTraceEventStyleInvalidatorInvalidationTracking(event))) {\n const recalcEndTime = lastRecalcStyleEvent.ts + (lastRecalcStyleEvent.dur || 0);\n if (event.ts >= lastRecalcStyleEvent.ts && event.ts <= recalcEndTime &&\n lastRecalcStyleEvent.args.beginData?.frame === event.args.data.frame) {\n addInvalidationToEvent(lastRecalcStyleEvent, event);\n }\n }\n\n allInvalidationTrackingEvents.push(event);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventPaint(event)) {\n // Used to ensure that we do not create relationships across frames.\n hasPainted = true;\n return;\n }\n\n if (Types.TraceEvents.isTraceEventLayout(event)) {\n const layoutFrame = event.args.beginData.frame;\n for (const invalidation of allInvalidationTrackingEvents) {\n // The only invalidations that cause a Layout are LayoutInvalidations :)\n if (!Types.TraceEvents.isTraceEventLayoutInvalidationTracking(invalidation)) {\n continue;\n }\n\n if (invalidation.args.data.frame === layoutFrame) {\n addInvalidationToEvent(event, invalidation);\n }\n }\n }\n}\n\nexport async function finalize(): Promise<void> {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('InvalidationsHandler is not initialized');\n }\n\n handlerState = HandlerState.FINALIZED;\n}\n\ninterface InvalidationsData {\n invalidationsForEvent: Map<Types.TraceEvents.TraceEventData, Types.TraceEvents.InvalidationTrackingEvent[]>;\n}\n\nexport function data(): InvalidationsData {\n return {\n invalidationsForEvent,\n };\n}\n"]}
|