aboutsummaryrefslogtreecommitdiff
path: root/node_modules/jsdom/lib/jsdom/living/fetch/Headers-impl.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/jsdom/lib/jsdom/living/fetch/Headers-impl.js')
-rw-r--r--node_modules/jsdom/lib/jsdom/living/fetch/Headers-impl.js165
1 files changed, 165 insertions, 0 deletions
diff --git a/node_modules/jsdom/lib/jsdom/living/fetch/Headers-impl.js b/node_modules/jsdom/lib/jsdom/living/fetch/Headers-impl.js
new file mode 100644
index 0000000..e84ba3f
--- /dev/null
+++ b/node_modules/jsdom/lib/jsdom/living/fetch/Headers-impl.js
@@ -0,0 +1,165 @@
+"use strict";
+
+const {
+ isForbidden,
+ isForbiddenResponse,
+ isPrivilegedNoCORSRequest,
+ isNoCORSSafelistedRequest,
+ isCORSWhitelisted
+} = require("./header-types");
+const HeaderList = require("./header-list");
+
+function assertName(name) {
+ if (!name.match(/^[!#$%&'*+\-.^`|~\w]+$/)) {
+ throw new TypeError("name is invalid");
+ }
+}
+
+function assertValue(value) {
+ if (value.match(/[\0\r\n]/)) {
+ throw new TypeError("value is invalid");
+ }
+}
+
+class HeadersImpl {
+ constructor(globalObject, args) {
+ this.guard = "none";
+ this.headersList = new HeaderList();
+
+ if (args[0]) {
+ this._fill(args[0]);
+ }
+ }
+
+ _fill(init) {
+ if (Array.isArray(init)) {
+ for (const header of init) {
+ if (header.length !== 2) {
+ throw new TypeError("init is invalid");
+ }
+ this.append(header[0], header[1]);
+ }
+ } else {
+ for (const key of Object.keys(init)) {
+ this.append(key, init[key]);
+ }
+ }
+ }
+
+ has(name) {
+ assertName(name);
+ return this.headersList.contains(name);
+ }
+
+ get(name) {
+ assertName(name);
+ return this.headersList.get(name);
+ }
+
+ _removePrivilegedNoCORSHeaders() {
+ this.headersList.delete("range");
+ }
+
+ append(name, value) {
+ value = value.trim();
+ assertName(name);
+ assertValue(value);
+
+ switch (this.guard) {
+ case "immutable":
+ throw new TypeError("Headers is immutable");
+ case "request":
+ if (isForbidden(name)) {
+ return;
+ }
+ break;
+ case "request-no-cors": {
+ let temporaryValue = this.get(name);
+ if (temporaryValue === null) {
+ temporaryValue = value;
+ } else {
+ temporaryValue += `, ${value}`;
+ }
+ if (!isCORSWhitelisted(name, value)) {
+ return;
+ }
+ break;
+ }
+ case "response":
+ if (isForbiddenResponse(name)) {
+ return;
+ }
+ break;
+ }
+
+ this.headersList.append(name, value);
+ this._removePrivilegedNoCORSHeaders();
+ }
+
+ set(name, value) {
+ value = value.trim();
+ assertName(name);
+ assertValue(value);
+
+ switch (this.guard) {
+ case "immutable":
+ throw new TypeError("Headers is immutable");
+ case "request":
+ if (isForbidden(name)) {
+ return;
+ }
+ break;
+ case "request-no-cors": {
+ if (!isCORSWhitelisted(name, value)) {
+ return;
+ }
+ break;
+ }
+ case "response":
+ if (isForbiddenResponse(name)) {
+ return;
+ }
+ break;
+ }
+ this.headersList.set(name, value);
+ this._removePrivilegedNoCORSHeaders();
+ }
+
+ delete(name) {
+ assertName(name);
+
+ switch (this.guard) {
+ case "immutable":
+ throw new TypeError("Headers is immutable");
+ case "request":
+ if (isForbidden(name)) {
+ return;
+ }
+ break;
+ case "request-no-cors": {
+ if (
+ !isNoCORSSafelistedRequest(name) &&
+ !isPrivilegedNoCORSRequest(name)
+ ) {
+ return;
+ }
+ break;
+ }
+ case "response":
+ if (isForbiddenResponse(name)) {
+ return;
+ }
+ break;
+ }
+ this.headersList.delete(name);
+ this._removePrivilegedNoCORSHeaders();
+ }
+
+ * [Symbol.iterator]() {
+ for (const header of this.headersList.sortAndCombine()) {
+ yield header;
+ }
+ }
+}
+
+exports.implementation = HeadersImpl;