_synthesizeNaiveTraceEvents() {
    const profile = this._profile;
    const length = profile.samples.length;
    if (profile.timeDeltas.length !== length) throw new Error(`Invalid CPU profile length`);

    /** @type {Array<SynthethicEvent>} */
    const events = [];

    let currentProfilerTimestamp = profile.startTime;
    let earliestPossibleTimestamp = -Infinity;

    /** @type {Array<number>} */
    let lastActiveNodeIds = [];
    for (let i = 0; i < profile.samples.length; i++) {
      const nodeId = profile.samples[i];
      const timeDelta = Math.max(profile.timeDeltas[i], 1);
      const node = this._nodesById.get(nodeId);
      if (!node) throw new Error(`Missing node ${nodeId}`);

      currentProfilerTimestamp += timeDelta;

      const activeNodeIds = this._getActiveNodeIds(nodeId);
      events.push(
        ...this._synthesizeTraceEventsForTransition(
          earliestPossibleTimestamp,
          currentProfilerTimestamp,
          lastActiveNodeIds,
          activeNodeIds
        )
      );

      earliestPossibleTimestamp = currentProfilerTimestamp;
      lastActiveNodeIds = activeNodeIds;
    }

    events.push(
      ...this._synthesizeTraceEventsForTransition(
        currentProfilerTimestamp,
        Infinity,
        lastActiveNodeIds,
        []
      )
    );

    return events;
  }
Creates the B/E-style trace events using only data from the profile itself. Each B/E event will
include the actual _range_ the timestamp could have been in its metadata that is used for
refinement later.

@return {Array<SynthethicEvent>}