11cb0ef41Sopenharmony_ci'use strict'
21cb0ef41Sopenharmony_ciconst invalidTokenRegex = /[^^_`a-zA-Z\-0-9!#$%&'*+.|~]/
31cb0ef41Sopenharmony_ciconst invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciconst validateName = name => {
61cb0ef41Sopenharmony_ci  name = `${name}`
71cb0ef41Sopenharmony_ci  if (invalidTokenRegex.test(name) || name === '') {
81cb0ef41Sopenharmony_ci    throw new TypeError(`${name} is not a legal HTTP header name`)
91cb0ef41Sopenharmony_ci  }
101cb0ef41Sopenharmony_ci}
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciconst validateValue = value => {
131cb0ef41Sopenharmony_ci  value = `${value}`
141cb0ef41Sopenharmony_ci  if (invalidHeaderCharRegex.test(value)) {
151cb0ef41Sopenharmony_ci    throw new TypeError(`${value} is not a legal HTTP header value`)
161cb0ef41Sopenharmony_ci  }
171cb0ef41Sopenharmony_ci}
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciconst find = (map, name) => {
201cb0ef41Sopenharmony_ci  name = name.toLowerCase()
211cb0ef41Sopenharmony_ci  for (const key in map) {
221cb0ef41Sopenharmony_ci    if (key.toLowerCase() === name) {
231cb0ef41Sopenharmony_ci      return key
241cb0ef41Sopenharmony_ci    }
251cb0ef41Sopenharmony_ci  }
261cb0ef41Sopenharmony_ci  return undefined
271cb0ef41Sopenharmony_ci}
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ciconst MAP = Symbol('map')
301cb0ef41Sopenharmony_ciclass Headers {
311cb0ef41Sopenharmony_ci  constructor (init = undefined) {
321cb0ef41Sopenharmony_ci    this[MAP] = Object.create(null)
331cb0ef41Sopenharmony_ci    if (init instanceof Headers) {
341cb0ef41Sopenharmony_ci      const rawHeaders = init.raw()
351cb0ef41Sopenharmony_ci      const headerNames = Object.keys(rawHeaders)
361cb0ef41Sopenharmony_ci      for (const headerName of headerNames) {
371cb0ef41Sopenharmony_ci        for (const value of rawHeaders[headerName]) {
381cb0ef41Sopenharmony_ci          this.append(headerName, value)
391cb0ef41Sopenharmony_ci        }
401cb0ef41Sopenharmony_ci      }
411cb0ef41Sopenharmony_ci      return
421cb0ef41Sopenharmony_ci    }
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci    // no-op
451cb0ef41Sopenharmony_ci    if (init === undefined || init === null) {
461cb0ef41Sopenharmony_ci      return
471cb0ef41Sopenharmony_ci    }
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci    if (typeof init === 'object') {
501cb0ef41Sopenharmony_ci      const method = init[Symbol.iterator]
511cb0ef41Sopenharmony_ci      if (method !== null && method !== undefined) {
521cb0ef41Sopenharmony_ci        if (typeof method !== 'function') {
531cb0ef41Sopenharmony_ci          throw new TypeError('Header pairs must be iterable')
541cb0ef41Sopenharmony_ci        }
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci        // sequence<sequence<ByteString>>
571cb0ef41Sopenharmony_ci        // Note: per spec we have to first exhaust the lists then process them
581cb0ef41Sopenharmony_ci        const pairs = []
591cb0ef41Sopenharmony_ci        for (const pair of init) {
601cb0ef41Sopenharmony_ci          if (typeof pair !== 'object' ||
611cb0ef41Sopenharmony_ci              typeof pair[Symbol.iterator] !== 'function') {
621cb0ef41Sopenharmony_ci            throw new TypeError('Each header pair must be iterable')
631cb0ef41Sopenharmony_ci          }
641cb0ef41Sopenharmony_ci          const arrPair = Array.from(pair)
651cb0ef41Sopenharmony_ci          if (arrPair.length !== 2) {
661cb0ef41Sopenharmony_ci            throw new TypeError('Each header pair must be a name/value tuple')
671cb0ef41Sopenharmony_ci          }
681cb0ef41Sopenharmony_ci          pairs.push(arrPair)
691cb0ef41Sopenharmony_ci        }
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci        for (const pair of pairs) {
721cb0ef41Sopenharmony_ci          this.append(pair[0], pair[1])
731cb0ef41Sopenharmony_ci        }
741cb0ef41Sopenharmony_ci      } else {
751cb0ef41Sopenharmony_ci        // record<ByteString, ByteString>
761cb0ef41Sopenharmony_ci        for (const key of Object.keys(init)) {
771cb0ef41Sopenharmony_ci          this.append(key, init[key])
781cb0ef41Sopenharmony_ci        }
791cb0ef41Sopenharmony_ci      }
801cb0ef41Sopenharmony_ci    } else {
811cb0ef41Sopenharmony_ci      throw new TypeError('Provided initializer must be an object')
821cb0ef41Sopenharmony_ci    }
831cb0ef41Sopenharmony_ci  }
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci  get (name) {
861cb0ef41Sopenharmony_ci    name = `${name}`
871cb0ef41Sopenharmony_ci    validateName(name)
881cb0ef41Sopenharmony_ci    const key = find(this[MAP], name)
891cb0ef41Sopenharmony_ci    if (key === undefined) {
901cb0ef41Sopenharmony_ci      return null
911cb0ef41Sopenharmony_ci    }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci    return this[MAP][key].join(', ')
941cb0ef41Sopenharmony_ci  }
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  forEach (callback, thisArg = undefined) {
971cb0ef41Sopenharmony_ci    let pairs = getHeaders(this)
981cb0ef41Sopenharmony_ci    for (let i = 0; i < pairs.length; i++) {
991cb0ef41Sopenharmony_ci      const [name, value] = pairs[i]
1001cb0ef41Sopenharmony_ci      callback.call(thisArg, value, name, this)
1011cb0ef41Sopenharmony_ci      // refresh in case the callback added more headers
1021cb0ef41Sopenharmony_ci      pairs = getHeaders(this)
1031cb0ef41Sopenharmony_ci    }
1041cb0ef41Sopenharmony_ci  }
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  set (name, value) {
1071cb0ef41Sopenharmony_ci    name = `${name}`
1081cb0ef41Sopenharmony_ci    value = `${value}`
1091cb0ef41Sopenharmony_ci    validateName(name)
1101cb0ef41Sopenharmony_ci    validateValue(value)
1111cb0ef41Sopenharmony_ci    const key = find(this[MAP], name)
1121cb0ef41Sopenharmony_ci    this[MAP][key !== undefined ? key : name] = [value]
1131cb0ef41Sopenharmony_ci  }
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci  append (name, value) {
1161cb0ef41Sopenharmony_ci    name = `${name}`
1171cb0ef41Sopenharmony_ci    value = `${value}`
1181cb0ef41Sopenharmony_ci    validateName(name)
1191cb0ef41Sopenharmony_ci    validateValue(value)
1201cb0ef41Sopenharmony_ci    const key = find(this[MAP], name)
1211cb0ef41Sopenharmony_ci    if (key !== undefined) {
1221cb0ef41Sopenharmony_ci      this[MAP][key].push(value)
1231cb0ef41Sopenharmony_ci    } else {
1241cb0ef41Sopenharmony_ci      this[MAP][name] = [value]
1251cb0ef41Sopenharmony_ci    }
1261cb0ef41Sopenharmony_ci  }
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci  has (name) {
1291cb0ef41Sopenharmony_ci    name = `${name}`
1301cb0ef41Sopenharmony_ci    validateName(name)
1311cb0ef41Sopenharmony_ci    return find(this[MAP], name) !== undefined
1321cb0ef41Sopenharmony_ci  }
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci  delete (name) {
1351cb0ef41Sopenharmony_ci    name = `${name}`
1361cb0ef41Sopenharmony_ci    validateName(name)
1371cb0ef41Sopenharmony_ci    const key = find(this[MAP], name)
1381cb0ef41Sopenharmony_ci    if (key !== undefined) {
1391cb0ef41Sopenharmony_ci      delete this[MAP][key]
1401cb0ef41Sopenharmony_ci    }
1411cb0ef41Sopenharmony_ci  }
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  raw () {
1441cb0ef41Sopenharmony_ci    return this[MAP]
1451cb0ef41Sopenharmony_ci  }
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci  keys () {
1481cb0ef41Sopenharmony_ci    return new HeadersIterator(this, 'key')
1491cb0ef41Sopenharmony_ci  }
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  values () {
1521cb0ef41Sopenharmony_ci    return new HeadersIterator(this, 'value')
1531cb0ef41Sopenharmony_ci  }
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  [Symbol.iterator] () {
1561cb0ef41Sopenharmony_ci    return new HeadersIterator(this, 'key+value')
1571cb0ef41Sopenharmony_ci  }
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  entries () {
1601cb0ef41Sopenharmony_ci    return new HeadersIterator(this, 'key+value')
1611cb0ef41Sopenharmony_ci  }
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci  get [Symbol.toStringTag] () {
1641cb0ef41Sopenharmony_ci    return 'Headers'
1651cb0ef41Sopenharmony_ci  }
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  static exportNodeCompatibleHeaders (headers) {
1681cb0ef41Sopenharmony_ci    const obj = Object.assign(Object.create(null), headers[MAP])
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci    // http.request() only supports string as Host header. This hack makes
1711cb0ef41Sopenharmony_ci    // specifying custom Host header possible.
1721cb0ef41Sopenharmony_ci    const hostHeaderKey = find(headers[MAP], 'Host')
1731cb0ef41Sopenharmony_ci    if (hostHeaderKey !== undefined) {
1741cb0ef41Sopenharmony_ci      obj[hostHeaderKey] = obj[hostHeaderKey][0]
1751cb0ef41Sopenharmony_ci    }
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci    return obj
1781cb0ef41Sopenharmony_ci  }
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  static createHeadersLenient (obj) {
1811cb0ef41Sopenharmony_ci    const headers = new Headers()
1821cb0ef41Sopenharmony_ci    for (const name of Object.keys(obj)) {
1831cb0ef41Sopenharmony_ci      if (invalidTokenRegex.test(name)) {
1841cb0ef41Sopenharmony_ci        continue
1851cb0ef41Sopenharmony_ci      }
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci      if (Array.isArray(obj[name])) {
1881cb0ef41Sopenharmony_ci        for (const val of obj[name]) {
1891cb0ef41Sopenharmony_ci          if (invalidHeaderCharRegex.test(val)) {
1901cb0ef41Sopenharmony_ci            continue
1911cb0ef41Sopenharmony_ci          }
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci          if (headers[MAP][name] === undefined) {
1941cb0ef41Sopenharmony_ci            headers[MAP][name] = [val]
1951cb0ef41Sopenharmony_ci          } else {
1961cb0ef41Sopenharmony_ci            headers[MAP][name].push(val)
1971cb0ef41Sopenharmony_ci          }
1981cb0ef41Sopenharmony_ci        }
1991cb0ef41Sopenharmony_ci      } else if (!invalidHeaderCharRegex.test(obj[name])) {
2001cb0ef41Sopenharmony_ci        headers[MAP][name] = [obj[name]]
2011cb0ef41Sopenharmony_ci      }
2021cb0ef41Sopenharmony_ci    }
2031cb0ef41Sopenharmony_ci    return headers
2041cb0ef41Sopenharmony_ci  }
2051cb0ef41Sopenharmony_ci}
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ciObject.defineProperties(Headers.prototype, {
2081cb0ef41Sopenharmony_ci  get: { enumerable: true },
2091cb0ef41Sopenharmony_ci  forEach: { enumerable: true },
2101cb0ef41Sopenharmony_ci  set: { enumerable: true },
2111cb0ef41Sopenharmony_ci  append: { enumerable: true },
2121cb0ef41Sopenharmony_ci  has: { enumerable: true },
2131cb0ef41Sopenharmony_ci  delete: { enumerable: true },
2141cb0ef41Sopenharmony_ci  keys: { enumerable: true },
2151cb0ef41Sopenharmony_ci  values: { enumerable: true },
2161cb0ef41Sopenharmony_ci  entries: { enumerable: true },
2171cb0ef41Sopenharmony_ci})
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ciconst getHeaders = (headers, kind = 'key+value') =>
2201cb0ef41Sopenharmony_ci  Object.keys(headers[MAP]).sort().map(
2211cb0ef41Sopenharmony_ci    kind === 'key' ? k => k.toLowerCase()
2221cb0ef41Sopenharmony_ci    : kind === 'value' ? k => headers[MAP][k].join(', ')
2231cb0ef41Sopenharmony_ci    : k => [k.toLowerCase(), headers[MAP][k].join(', ')]
2241cb0ef41Sopenharmony_ci  )
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ciconst INTERNAL = Symbol('internal')
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ciclass HeadersIterator {
2291cb0ef41Sopenharmony_ci  constructor (target, kind) {
2301cb0ef41Sopenharmony_ci    this[INTERNAL] = {
2311cb0ef41Sopenharmony_ci      target,
2321cb0ef41Sopenharmony_ci      kind,
2331cb0ef41Sopenharmony_ci      index: 0,
2341cb0ef41Sopenharmony_ci    }
2351cb0ef41Sopenharmony_ci  }
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci  get [Symbol.toStringTag] () {
2381cb0ef41Sopenharmony_ci    return 'HeadersIterator'
2391cb0ef41Sopenharmony_ci  }
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci  next () {
2421cb0ef41Sopenharmony_ci    /* istanbul ignore if: should be impossible */
2431cb0ef41Sopenharmony_ci    if (!this || Object.getPrototypeOf(this) !== HeadersIterator.prototype) {
2441cb0ef41Sopenharmony_ci      throw new TypeError('Value of `this` is not a HeadersIterator')
2451cb0ef41Sopenharmony_ci    }
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci    const { target, kind, index } = this[INTERNAL]
2481cb0ef41Sopenharmony_ci    const values = getHeaders(target, kind)
2491cb0ef41Sopenharmony_ci    const len = values.length
2501cb0ef41Sopenharmony_ci    if (index >= len) {
2511cb0ef41Sopenharmony_ci      return {
2521cb0ef41Sopenharmony_ci        value: undefined,
2531cb0ef41Sopenharmony_ci        done: true,
2541cb0ef41Sopenharmony_ci      }
2551cb0ef41Sopenharmony_ci    }
2561cb0ef41Sopenharmony_ci
2571cb0ef41Sopenharmony_ci    this[INTERNAL].index++
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci    return { value: values[index], done: false }
2601cb0ef41Sopenharmony_ci  }
2611cb0ef41Sopenharmony_ci}
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci// manually extend because 'extends' requires a ctor
2641cb0ef41Sopenharmony_ciObject.setPrototypeOf(HeadersIterator.prototype,
2651cb0ef41Sopenharmony_ci  Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())))
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_cimodule.exports = Headers
268