1'use strict'
2
3const { MessageChannel, receiveMessageOnPort } = require('worker_threads')
4
5const corsSafeListedMethods = ['GET', 'HEAD', 'POST']
6const corsSafeListedMethodsSet = new Set(corsSafeListedMethods)
7
8const nullBodyStatus = [101, 204, 205, 304]
9
10const redirectStatus = [301, 302, 303, 307, 308]
11const redirectStatusSet = new Set(redirectStatus)
12
13// https://fetch.spec.whatwg.org/#block-bad-port
14const badPorts = [
15  '1', '7', '9', '11', '13', '15', '17', '19', '20', '21', '22', '23', '25', '37', '42', '43', '53', '69', '77', '79',
16  '87', '95', '101', '102', '103', '104', '109', '110', '111', '113', '115', '117', '119', '123', '135', '137',
17  '139', '143', '161', '179', '389', '427', '465', '512', '513', '514', '515', '526', '530', '531', '532',
18  '540', '548', '554', '556', '563', '587', '601', '636', '989', '990', '993', '995', '1719', '1720', '1723',
19  '2049', '3659', '4045', '5060', '5061', '6000', '6566', '6665', '6666', '6667', '6668', '6669', '6697',
20  '10080'
21]
22
23const badPortsSet = new Set(badPorts)
24
25// https://w3c.github.io/webappsec-referrer-policy/#referrer-policies
26const referrerPolicy = [
27  '',
28  'no-referrer',
29  'no-referrer-when-downgrade',
30  'same-origin',
31  'origin',
32  'strict-origin',
33  'origin-when-cross-origin',
34  'strict-origin-when-cross-origin',
35  'unsafe-url'
36]
37const referrerPolicySet = new Set(referrerPolicy)
38
39const requestRedirect = ['follow', 'manual', 'error']
40
41const safeMethods = ['GET', 'HEAD', 'OPTIONS', 'TRACE']
42const safeMethodsSet = new Set(safeMethods)
43
44const requestMode = ['navigate', 'same-origin', 'no-cors', 'cors']
45
46const requestCredentials = ['omit', 'same-origin', 'include']
47
48const requestCache = [
49  'default',
50  'no-store',
51  'reload',
52  'no-cache',
53  'force-cache',
54  'only-if-cached'
55]
56
57// https://fetch.spec.whatwg.org/#request-body-header-name
58const requestBodyHeader = [
59  'content-encoding',
60  'content-language',
61  'content-location',
62  'content-type',
63  // See https://github.com/nodejs/undici/issues/2021
64  // 'Content-Length' is a forbidden header name, which is typically
65  // removed in the Headers implementation. However, undici doesn't
66  // filter out headers, so we add it here.
67  'content-length'
68]
69
70// https://fetch.spec.whatwg.org/#enumdef-requestduplex
71const requestDuplex = [
72  'half'
73]
74
75// http://fetch.spec.whatwg.org/#forbidden-method
76const forbiddenMethods = ['CONNECT', 'TRACE', 'TRACK']
77const forbiddenMethodsSet = new Set(forbiddenMethods)
78
79const subresource = [
80  'audio',
81  'audioworklet',
82  'font',
83  'image',
84  'manifest',
85  'paintworklet',
86  'script',
87  'style',
88  'track',
89  'video',
90  'xslt',
91  ''
92]
93const subresourceSet = new Set(subresource)
94
95/** @type {globalThis['DOMException']} */
96const DOMException = globalThis.DOMException ?? (() => {
97  // DOMException was only made a global in Node v17.0.0,
98  // but fetch supports >= v16.8.
99  try {
100    atob('~')
101  } catch (err) {
102    return Object.getPrototypeOf(err).constructor
103  }
104})()
105
106let channel
107
108/** @type {globalThis['structuredClone']} */
109const structuredClone =
110  globalThis.structuredClone ??
111  // https://github.com/nodejs/node/blob/b27ae24dcc4251bad726d9d84baf678d1f707fed/lib/internal/structured_clone.js
112  // structuredClone was added in v17.0.0, but fetch supports v16.8
113  function structuredClone (value, options = undefined) {
114    if (arguments.length === 0) {
115      throw new TypeError('missing argument')
116    }
117
118    if (!channel) {
119      channel = new MessageChannel()
120    }
121    channel.port1.unref()
122    channel.port2.unref()
123    channel.port1.postMessage(value, options?.transfer)
124    return receiveMessageOnPort(channel.port2).message
125  }
126
127module.exports = {
128  DOMException,
129  structuredClone,
130  subresource,
131  forbiddenMethods,
132  requestBodyHeader,
133  referrerPolicy,
134  requestRedirect,
135  requestMode,
136  requestCredentials,
137  requestCache,
138  redirectStatus,
139  corsSafeListedMethods,
140  nullBodyStatus,
141  safeMethods,
142  badPorts,
143  requestDuplex,
144  subresourceSet,
145  badPortsSet,
146  redirectStatusSet,
147  corsSafeListedMethodsSet,
148  safeMethodsSet,
149  forbiddenMethodsSet,
150  referrerPolicySet
151}
152