async keys (request = undefined, options = {}) {
    webidl.brandCheck(this, Cache)

    const prefix = 'Cache.keys'

    if (request !== undefined) request = webidl.converters.RequestInfo(request, prefix, 'request')
    options = webidl.converters.CacheQueryOptions(options, prefix, 'options')

    // 1.
    let r = null

    // 2.
    if (request !== undefined) {
      // 2.1
      if (webidl.is.Request(request)) {
        // 2.1.1
        r = getRequestState(request)

        // 2.1.2
        if (r.method !== 'GET' && !options.ignoreMethod) {
          return []
        }
      } else if (typeof request === 'string') { // 2.2
        r = getRequestState(new Request(request))
      }
    }

    // 4.
    const promise = createDeferredPromise()

    // 5.
    // 5.1
    const requests = []

    // 5.2
    if (request === undefined) {
      // 5.2.1
      for (const requestResponse of this.#relevantRequestResponseList) {
        // 5.2.1.1
        requests.push(requestResponse[0])
      }
    } else { // 5.3
      // 5.3.1
      const requestResponses = this.#queryCache(r, options)

      // 5.3.2
      for (const requestResponse of requestResponses) {
        // 5.3.2.1
        requests.push(requestResponse[0])
      }
    }

    // 5.4
    queueMicrotask(() => {
      // 5.4.1
      const requestList = []

      // 5.4.2
      for (const request of requests) {
        const requestObject = fromInnerRequest(
          request,
          undefined,
          new AbortController().signal,
          'immutable'
        )
        // 5.4.2.1
        requestList.push(requestObject)
      }

      // 5.4.3
      promise.resolve(Object.freeze(requestList))
    })

    return promise.promise
  }
@see https://w3c.github.io/ServiceWorker/#dom-cache-keys
@param {any} request
@param {import('../../types/cache').CacheQueryOptions} options
@returns {Promise<readonly Request[]>}