Skip to content

update markresourcetiming #229

@github-actions

Description

@github-actions

https://github.com/hoverkraft-tech/compose-action/blob/2ab47e7e09da3e8e47398d6c26b9bd345071a442/dist/index.js#L22818

// https://fetch.spec.whatwg.org/#fetch-finale
function fetchFinale (fetchParams, response) {
  // 1. Let timingInfo be fetchParams’s timing info.
  let timingInfo = fetchParams.timingInfo

  // 2. If response is not a network error and fetchParams’s request’s client is a secure context,
  //    then set timingInfo’s server-timing headers to the result of getting, decoding, and splitting
  //    `Server-Timing` from response’s internal response’s header list.
  // TODO

  // 3. Let processResponseEndOfBody be the following steps:
  const processResponseEndOfBody = () => {
    // 1. Let unsafeEndTime be the unsafe shared current time.
    const unsafeEndTime = Date.now() // ?

    // 2. If fetchParams’s request’s destination is "document", then set fetchParams’s controller’s
    //    full timing info to fetchParams’s timing info.
    if (fetchParams.request.destination === 'document') {
      fetchParams.controller.fullTimingInfo = timingInfo
    }

    // 3. Set fetchParams’s controller’s report timing steps to the following steps given a global object global:
    fetchParams.controller.reportTimingSteps = () => {
      // 1. If fetchParams’s request’s URL’s scheme is not an HTTP(S) scheme, then return.
      if (fetchParams.request.url.protocol !== 'https:') {
        return
      }

      // 2. Set timingInfo’s end time to the relative high resolution time given unsafeEndTime and global.
      timingInfo.endTime = unsafeEndTime

      // 3. Let cacheState be response’s cache state.
      let cacheState = response.cacheState

      // 4. Let bodyInfo be response’s body info.
      const bodyInfo = response.bodyInfo

      // 5. If response’s timing allow passed flag is not set, then set timingInfo to the result of creating an
      //    opaque timing info for timingInfo and set cacheState to the empty string.
      if (!response.timingAllowPassed) {
        timingInfo = createOpaqueTimingInfo(timingInfo)

        cacheState = ''
      }

      // 6. Let responseStatus be 0.
      let responseStatus = 0

      // 7. If fetchParams’s request’s mode is not "navigate" or response’s has-cross-origin-redirects is false:
      if (fetchParams.request.mode !== 'navigator' || !response.hasCrossOriginRedirects) {
        // 1. Set responseStatus to response’s status.
        responseStatus = response.status

        // 2. Let mimeType be the result of extracting a MIME type from response’s header list.
        const mimeType = extractMimeType(response.headersList)

        // 3. If mimeType is not failure, then set bodyInfo’s content type to the result of minimizing a supported MIME type given mimeType.
        if (mimeType !== 'failure') {
          bodyInfo.contentType = minimizeSupportedMimeType(mimeType)
        }
      }

      // 8. If fetchParams’s request’s initiator type is non-null, then mark resource timing given timingInfo,
      //    fetchParams’s request’s URL, fetchParams’s request’s initiator type, global, cacheState, bodyInfo,
      //    and responseStatus.
      if (fetchParams.request.initiatorType != null) {
        // TODO: update markresourcetiming
        markResourceTiming(timingInfo, fetchParams.request.url.href, fetchParams.request.initiatorType, globalThis, cacheState, bodyInfo, responseStatus)
      }
    }

    // 4. Let processResponseEndOfBodyTask be the following steps:
    const processResponseEndOfBodyTask = () => {
      // 1. Set fetchParams’s request’s done flag.
      fetchParams.request.done = true

      // 2. If fetchParams’s process response end-of-body is non-null, then run fetchParams’s process
      //    response end-of-body given response.
      if (fetchParams.processResponseEndOfBody != null) {
        queueMicrotask(() => fetchParams.processResponseEndOfBody(response))
      }

      // 3. If fetchParams’s request’s initiator type is non-null and fetchParams’s request’s client’s
      //    global object is fetchParams’s task destination, then run fetchParams’s controller’s report
      //    timing steps given fetchParams’s request’s client’s global object.
      if (fetchParams.request.initiatorType != null) {
        fetchParams.controller.reportTimingSteps()
      }
    }

    // 5. Queue a fetch task to run processResponseEndOfBodyTask with fetchParams’s task destination
    queueMicrotask(() => processResponseEndOfBodyTask())
  }

  // 4. If fetchParams’s process response is non-null, then queue a fetch task to run fetchParams’s
  //    process response given response, with fetchParams’s task destination.
  if (fetchParams.processResponse != null) {
    queueMicrotask(() => {
      fetchParams.processResponse(response)
      fetchParams.processResponse = null
    })
  }

  // 5. Let internalResponse be response, if response is a network error; otherwise response’s internal response.
  const internalResponse = response.type === 'error' ? response : (response.internalResponse ?? response)

  // 6. If internalResponse’s body is null, then run processResponseEndOfBody.
  // 7. Otherwise:
  if (internalResponse.body == null) {
    processResponseEndOfBody()
  } else {
    // mcollina: all the following steps of the specs are skipped.
    // The internal transform stream is not needed.
    // See https://github.com/nodejs/undici/pull/3093#issuecomment-2050198541

    // 1. Let transformStream be a new TransformStream.
    // 2. Let identityTransformAlgorithm be an algorithm which, given chunk, enqueues chunk in transformStream.
    // 3. Set up transformStream with transformAlgorithm set to identityTransformAlgorithm and flushAlgorithm
    //    set to processResponseEndOfBody.
    // 4. Set internalResponse’s body’s stream to the result of internalResponse’s body’s stream piped through transformStream.

    finished(internalResponse.body.stream, () => {
      processResponseEndOfBody()
    })
  }
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions