me;
  }

  get redirectEnd() {
    return this[kTimingInfo].redirectEndTime;
  }

  get fetchStart() {
    return this[kTimingInfo].postRedirectStartTime;
  }

  get domainLookupStart() {
    return this[kTimingInfo].finalConnectionTimingInfo?.domainLookupStartTime;
  }

  get domainLookupEnd() {
    return this[kTimingInfo].finalConnectionTimingInfo?.domainLookupEndTime;
  }

  get connectStart() {
    return this[kTimingInfo].finalConnectionTimingInfo?.connectionStartTime;
  }

  get connectEnd() {
    return this[kTimingInfo].finalConnectionTimingInfo?.connectionEndTime;
  }

  get secureConnectionStart() {
    return this[kTimingInfo]
      .finalConnectionTimingInfo?.secureConnectionStartTime;
  }

  get nextHopProtocol() {
    return this[kTimingInfo]
      .finalConnectionTimingInfo?.ALPNNegotiatedProtocol;
  }

  get requestStart() {
    return this[kTimingInfo].finalNetworkRequestStartTime;
  }

  get responseStart() {
    return this[kTimingInfo].finalNetworkResponseStartTime;
  }

  get responseEnd() {
    return this[kTimingInfo].endTime;
  }

  get encodedBodySize() {
    return this[kTimingInfo].encodedBodySize;
  }

  get decodedBodySize() {
    return this[kTimingInfo].decodedBodySize;
  }

  get transferSize() {
    if (this[kCacheMode] === 'local') return 0;
    if (this[kCacheMode] === 'validated') return 300;

    return this[kTimingInfo].encodedBodySize + 300;
  }

  toJSON() {
    return {
      name: this.name,
      entryType: this.entryType,
      startTime: this.startTime,
      duration: this.duration,
      initiatorType: this[kInitiatorType],
      nextHopProtocol: this.nextHopProtocol,
      workerStart: this.workerStart,
      redirectStart: this.redirectStart,
      redirectEnd: this.redirectEnd,
      fetchStart: this.fetchStart,
      domainLookupStart: this.domainLookupStart,
      domainLookupEnd: this.domainLookupEnd,
      connectStart: this.connectStart,
      connectEnd: this.connectEnd,
      secureConnectionStart: this.secureConnectionStart,
      requestStart: this.requestStart,
      responseStart: this.responseStart,
      responseEnd: this.responseEnd,
      transferSize: this.transferSize,
      encodedBodySize: this.encodedBodySize,
      decodedBodySize: this.decodedBodySize,
    };
  }
}

class PerformanceResourceTiming extends InternalPerformanceResourceTiming {
  constructor() {
    throw new ERR_ILLEGAL_CONSTRUCTOR();
  }
}

// https://w3c.github.io/resource-timing/#dfn-mark-resource-timing
function markResourceTiming(
  timingInfo,
  requestedUrl,
  initiatorType,
  global,
  cacheMode,
) {
  // https://w3c.github.io/resource-timing/#dfn-setup-the-resource-timing-entry
  assert(
    cacheMode === '' || cacheMode === 'local',
    'cache must be an empty string or \'local\'',
  );
  const resource = new InternalPerformanceResourceTiming(
    requestedUrl,
    initiatorType,
    timingInfo,
    cacheMode,
  );

  ObjectSetPrototypeOf(resource, PerformanceResourceTiming.prototype);
  enqueue(resource);
  bufferResourceTiming(resource);
  return resource;
}

module.exports = {
  PerformanceResourceTiming,
  markResourceTiming,
};
