_synthesizeTraceEventsForTransition(
      earliestPossibleTimestamp,
      latestPossibleTimestamp,
      previousNodeIds,
      currentNodeIds
  ) {
    const startNodes = currentNodeIds
      .filter(id => !previousNodeIds.includes(id))
      .map(id => this._nodesById.get(id))
      .filter(node => !!node);
    const endNodes = previousNodeIds
      .filter(id => !currentNodeIds.includes(id))
      .map(id => this._nodesById.get(id))
      .filter(node => !!node);

    /** @param {CpuProfile['nodes'][0]} node @return {SynthethicEvent} */
    const createSyntheticEvent = node => ({
      ts: Number.isFinite(latestPossibleTimestamp)
        ? latestPossibleTimestamp
        : earliestPossibleTimestamp,
      pid: this._profile.pid,
      tid: this._profile.tid,
      dur: 0,
      ph: 'I',
      // This trace event name is Lighthouse-specific and wouldn't be found in a real trace.
      // Attribution logic in main-thread-tasks.js special cases this event.
      name: SAMPLER_TRACE_EVENT_NAME,
      cat: 'lighthouse',
      args: {
        data: {
          callFrame: node.callFrame,
          _syntheticProfilerRange: {earliestPossibleTimestamp, latestPossibleTimestamp},
        },
      },
    });

    /** @type {Array<SynthethicEvent>} */
    const startEvents = startNodes.map(createSyntheticEvent).map(evt => ({...evt, ph: 'B'}));
    /** @type {Array<SynthethicEvent>} */
    const endEvents = endNodes.map(createSyntheticEvent).map(evt => ({...evt, ph: 'E'}));
    // Ensure we put end events in first to finish prior tasks before starting new ones.
    return [...endEvents.reverse(), ...startEvents];
  }
Generates the necessary B/E-style trace events for a single transition from stack A to stack B
at the given latest timestamp (includes possible range in event.args.data).

Example:

   latestPossibleTimestamp 1234
   previousNodeIds 1,2,3
   currentNodeIds 1,2,4

   yields [end 3 at ts 1234, begin 4 at ts 1234]

@param {number} earliestPossibleTimestamp
@param {number} latestPossibleTimestamp
@param {Array<number>} previousNodeIds
@param {Array<number>} currentNodeIds
@return {Array<SynthethicEvent>}