{"version":3,"file":"network.mjs","sourceRoot":"","sources":["../../../src/common/endowments/network.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert } from '@metamask/utils';\n\nimport type { EndowmentFactoryOptions } from './commonEndowmentFactory';\nimport { withTeardown } from '../utils';\n\n/**\n * This class wraps a Response object.\n * That way, a teardown process can stop any processes left.\n */\nexport class ResponseWrapper implements Response {\n  readonly #teardownRef: { lastTeardown: number };\n\n  readonly #ogResponse: Response;\n\n  readonly #onStart: () => Promise<void>;\n\n  readonly #onFinish: () => Promise<void>;\n\n  constructor(\n    ogResponse: Response,\n    teardownRef: { lastTeardown: number },\n    onStart: () => Promise<void>,\n    onFinish: () => Promise<void>,\n  ) {\n    this.#ogResponse = ogResponse;\n    this.#teardownRef = teardownRef;\n    this.#onStart = onStart;\n    this.#onFinish = onFinish;\n  }\n\n  get body(): ReadableStream<Uint8Array> | null {\n    return this.#ogResponse.body;\n  }\n\n  get bodyUsed() {\n    return this.#ogResponse.bodyUsed;\n  }\n\n  get headers() {\n    return this.#ogResponse.headers;\n  }\n\n  get ok() {\n    return this.#ogResponse.ok;\n  }\n\n  get redirected() {\n    return this.#ogResponse.redirected;\n  }\n\n  get status() {\n    return this.#ogResponse.status;\n  }\n\n  get statusText() {\n    return this.#ogResponse.statusText;\n  }\n\n  get type() {\n    return this.#ogResponse.type;\n  }\n\n  get url() {\n    return this.#ogResponse.url;\n  }\n\n  async text() {\n    return await withTeardown<string>(\n      (async () => {\n        await this.#onStart();\n        try {\n          return await this.#ogResponse.text();\n        } finally {\n          await this.#onFinish();\n        }\n      })(),\n      this.#teardownRef,\n    );\n  }\n\n  async arrayBuffer(): Promise<ArrayBuffer> {\n    return await withTeardown<ArrayBuffer>(\n      (async () => {\n        await this.#onStart();\n        try {\n          return await this.#ogResponse.arrayBuffer();\n        } finally {\n          await this.#onFinish();\n        }\n      })(),\n      this.#teardownRef,\n    );\n  }\n\n  async blob(): Promise<Blob> {\n    return await withTeardown<Blob>(\n      (async () => {\n        await this.#onStart();\n        try {\n          return await this.#ogResponse.blob();\n        } finally {\n          await this.#onFinish();\n        }\n      })(),\n      this.#teardownRef,\n    );\n  }\n\n  clone(): Response {\n    const newResponse = this.#ogResponse.clone();\n    return new ResponseWrapper(\n      newResponse,\n      this.#teardownRef,\n      this.#onStart,\n      this.#onFinish,\n    );\n  }\n\n  async formData(): Promise<FormData> {\n    return await withTeardown<FormData>(\n      (async () => {\n        await this.#onStart();\n        try {\n          return await this.#ogResponse.formData();\n        } finally {\n          await this.#onFinish();\n        }\n      })(),\n      this.#teardownRef,\n    );\n  }\n\n  async json(): Promise<any> {\n    return await withTeardown(\n      (async () => {\n        await this.#onStart();\n        try {\n          return await this.#ogResponse.json();\n        } finally {\n          await this.#onFinish();\n        }\n      })(),\n      this.#teardownRef,\n    );\n  }\n}\n\n// We redefine the global Response class to overwrite [Symbol.hasInstance].\n// This fixes problems where the response from `fetch` would not pass\n// instance of checks, leading to failures in WASM bindgen.\nclass AlteredResponse extends Response {\n  static [Symbol.hasInstance](instance: unknown) {\n    return instance instanceof Response || instance instanceof ResponseWrapper;\n  }\n}\n\n/**\n * Create a network endowment, consisting of a `fetch` function.\n * This allows us to provide a teardown function, so that we can cancel\n * any pending requests, connections, streams, etc. that may be open when the\n * execution context is torn down.\n *\n * This wraps the original implementation of `fetch`,\n * to ensure that a bad actor cannot get access to the original function, thus\n * potentially preventing the network requests from being torn down.\n *\n * @param options - An options bag.\n * @param options.notify - A notification callback for outbound request\n * lifecycle events.\n * @returns An object containing a wrapped `fetch`\n * function, as well as a teardown function.\n */\nconst createNetwork = ({ notify }: EndowmentFactoryOptions = {}) => {\n  assert(\n    notify,\n    'The \"notify\" callback is required by the network endowment factory.',\n  );\n  // Open fetch calls or open body streams\n  const openConnections = new Set<{ cancel: () => Promise<void> }>();\n  // Track last teardown count\n  const teardownRef = { lastTeardown: 0 };\n\n  // Remove items from openConnections after they were garbage collected\n  const cleanup = new FinalizationRegistry<() => void>(\n    /* istanbul ignore next: can't test garbage collection without modifying node parameters */\n    (callback) => callback(),\n  );\n\n  const _fetch: typeof fetch = async (\n    input: RequestInfo | URL,\n    init?: RequestInit,\n  ): Promise<Response> => {\n    const abortController = new AbortController();\n    if (init?.signal !== null && init?.signal !== undefined) {\n      const originalSignal = init.signal;\n      // Merge abort controllers\n      originalSignal.addEventListener(\n        'abort',\n        () => {\n          abortController.abort((originalSignal as any).reason);\n        },\n        { once: true },\n      );\n    }\n\n    let started = false;\n    const onStart = async () => {\n      if (!started) {\n        started = true;\n        await notify({\n          method: 'OutboundRequest',\n          params: { source: 'fetch' },\n        });\n      }\n    };\n\n    let finished = false;\n    const onFinish = async () => {\n      if (!finished) {\n        finished = true;\n        await notify({\n          method: 'OutboundResponse',\n          params: { source: 'fetch' },\n        });\n      }\n    };\n\n    let res: Response;\n    let openFetchConnection: { cancel: () => Promise<void> } | undefined;\n    return await withTeardown(\n      (async () => {\n        try {\n          const fetchPromise = fetch(input, {\n            ...init,\n            signal: abortController.signal,\n          });\n\n          await notify({\n            method: 'OutboundRequest',\n            params: { source: 'fetch' },\n          });\n\n          openFetchConnection = {\n            cancel: async () => {\n              abortController.abort();\n              try {\n                await fetchPromise;\n              } catch {\n                /* do nothing */\n              }\n            },\n          };\n          openConnections.add(openFetchConnection);\n\n          res = new ResponseWrapper(\n            await fetchPromise,\n            teardownRef,\n            onStart,\n            onFinish,\n          );\n        } finally {\n          if (openFetchConnection !== undefined) {\n            openConnections.delete(openFetchConnection);\n          }\n          await notify({\n            method: 'OutboundResponse',\n            params: { source: 'fetch' },\n          });\n        }\n\n        if (res.body !== null) {\n          const body = new WeakRef<ReadableStream>(res.body);\n\n          const openBodyConnection = {\n            cancel:\n              /* istanbul ignore next: see it.todo('can be torn down during body read') test */\n              async () => {\n                try {\n                  await body.deref()?.cancel();\n                } catch {\n                  /* do nothing */\n                }\n              },\n          };\n          openConnections.add(openBodyConnection);\n          cleanup.register(\n            res.body,\n            /* istanbul ignore next: can't test garbage collection without modifying node parameters */\n            () => openConnections.delete(openBodyConnection),\n          );\n        }\n        return harden(res);\n      })(),\n      teardownRef,\n    );\n  };\n\n  const teardownFunction = async () => {\n    teardownRef.lastTeardown += 1;\n    const promises: Promise<void>[] = [];\n    openConnections.forEach(({ cancel }) => promises.push(cancel()));\n    openConnections.clear();\n    await Promise.all(promises);\n  };\n\n  return {\n    fetch: harden(_fetch),\n    // Request, Headers and Response are the endowments injected alongside fetch\n    // only when 'endowment:network-access' permission is requested,\n    // therefore these are hardened as part of fetch dependency injection within its factory.\n    // These endowments are not (and should never be) available by default.\n    Request: harden(Request),\n    Headers: harden(Headers),\n    Response: harden(AlteredResponse),\n    teardownFunction,\n  };\n};\n\nconst endowmentModule = {\n  names: ['fetch', 'Request', 'Headers', 'Response'] as const,\n  factory: createNetwork,\n};\nexport default endowmentModule;\n"]}