From 0f507cd42ab06be7add4df6ea5ef58d1d9ef16e8 Mon Sep 17 00:00:00 2001 From: Khafra <42794878+KhafraDev@users.noreply.github.com> Date: Tue, 10 May 2022 01:19:11 -0400 Subject: [PATCH] fix(Headers): ensure .length is correct (#1428) --- lib/fetch/headers.js | 72 ++++++++++++++++++++++++------------------- test/fetch/headers.js | 28 +++++++++++++++++ 2 files changed, 68 insertions(+), 32 deletions(-) diff --git a/lib/fetch/headers.js b/lib/fetch/headers.js index 7f603b2e212..1749a329169 100644 --- a/lib/fetch/headers.js +++ b/lib/fetch/headers.js @@ -200,17 +200,19 @@ class Headers { return Object.prototype.toString.call(this) } - append (...args) { + // https://fetch.spec.whatwg.org/#dom-headers-append + append (name, value) { if (!(this instanceof Headers)) { throw new TypeError('Illegal invocation') } - if (args.length < 2) { + + if (arguments.length < 2) { throw new TypeError( - `Failed to execute 'append' on 'Headers': 2 arguments required, but only ${args.length} present.` + `Failed to execute 'append' on 'Headers': 2 arguments required, but only ${arguments.length} present.` ) } - const normalizedName = normalizeAndValidateHeaderName(String(args[0])) + const normalizedName = normalizeAndValidateHeaderName(String(name)) if (this[kGuard] === 'immutable') { throw new TypeError('immutable') @@ -228,20 +230,22 @@ class Headers { return } - return this[kHeadersList].append(String(args[0]), String(args[1])) + return this[kHeadersList].append(String(name), String(value)) } - delete (...args) { + // https://fetch.spec.whatwg.org/#dom-headers-delete + delete (name) { if (!(this instanceof Headers)) { throw new TypeError('Illegal invocation') } - if (args.length < 1) { + + if (arguments.length < 1) { throw new TypeError( - `Failed to execute 'delete' on 'Headers': 1 argument required, but only ${args.length} present.` + `Failed to execute 'delete' on 'Headers': 1 argument required, but only ${arguments.length} present.` ) } - const normalizedName = normalizeAndValidateHeaderName(String(args[0])) + const normalizedName = normalizeAndValidateHeaderName(String(name)) if (this[kGuard] === 'immutable') { throw new TypeError('immutable') @@ -259,42 +263,48 @@ class Headers { return } - return this[kHeadersList].delete(String(args[0])) + return this[kHeadersList].delete(String(name)) } - get (...args) { + // https://fetch.spec.whatwg.org/#dom-headers-get + get (name) { if (!(this instanceof Headers)) { throw new TypeError('Illegal invocation') } - if (args.length < 1) { + + if (arguments.length < 1) { throw new TypeError( - `Failed to execute 'get' on 'Headers': 1 argument required, but only ${args.length} present.` + `Failed to execute 'get' on 'Headers': 1 argument required, but only ${arguments.length} present.` ) } - return this[kHeadersList].get(String(args[0])) + return this[kHeadersList].get(String(name)) } - has (...args) { + // https://fetch.spec.whatwg.org/#dom-headers-has + has (name) { if (!(this instanceof Headers)) { throw new TypeError('Illegal invocation') } - if (args.length < 1) { + + if (arguments.length < 1) { throw new TypeError( - `Failed to execute 'has' on 'Headers': 1 argument required, but only ${args.length} present.` + `Failed to execute 'has' on 'Headers': 1 argument required, but only ${arguments.length} present.` ) } - return this[kHeadersList].has(String(args[0])) + return this[kHeadersList].has(String(name)) } - set (...args) { + // https://fetch.spec.whatwg.org/#dom-headers-set + set (name, value) { if (!(this instanceof Headers)) { throw new TypeError('Illegal invocation') } - if (args.length < 2) { + + if (arguments.length < 2) { throw new TypeError( - `Failed to execute 'set' on 'Headers': 2 arguments required, but only ${args.length} present.` + `Failed to execute 'set' on 'Headers': 2 arguments required, but only ${arguments.length} present.` ) } @@ -302,19 +312,19 @@ class Headers { throw new TypeError('immutable') } else if ( this[kGuard] === 'request' && - forbiddenHeaderNames.includes(String(args[0]).toLocaleLowerCase()) + forbiddenHeaderNames.includes(String(name).toLocaleLowerCase()) ) { return } else if (this[kGuard] === 'request-no-cors') { // TODO } else if ( this[kGuard] === 'response' && - forbiddenResponseHeaderNames.includes(String(args[0]).toLocaleLowerCase()) + forbiddenResponseHeaderNames.includes(String(name).toLocaleLowerCase()) ) { return } - return this[kHeadersList].set(String(args[0]), String(args[1])) + return this[kHeadersList].set(String(name), String(value)) } get [kHeadersSortedMap] () { @@ -346,14 +356,6 @@ class Headers { return makeHeadersIterator(this[kHeadersSortedMap].entries()) } - [Symbol.iterator] () { - if (!(this instanceof Headers)) { - throw new TypeError('Illegal invocation') - } - - return makeHeadersIterator(this[kHeadersSortedMap]) - } - /** * @param {(value: string, key: string, self: Headers) => void} callbackFn * @param {unknown} thisArg @@ -363,6 +365,12 @@ class Headers { throw new TypeError('Illegal invocation') } + if (arguments.length < 1) { + throw new TypeError( + `Failed to execute 'forEach' on 'Headers': 1 argument required, but only ${arguments.length} present.` + ) + } + if (typeof callbackFn !== 'function') { throw new TypeError( "Failed to execute 'forEach' on 'Headers': parameter 1 is not of type 'Function'." diff --git a/test/fetch/headers.js b/test/fetch/headers.js index 43f0556a611..1ef629405ed 100644 --- a/test/fetch/headers.js +++ b/test/fetch/headers.js @@ -586,6 +586,34 @@ tap.test('arg validation', (t) => { t.end() }) +tap.test('function signature verification', (t) => { + t.test('function length', (t) => { + t.equal(Headers.prototype.append.length, 2) + t.equal(Headers.prototype.constructor.length, 0) + t.equal(Headers.prototype.delete.length, 1) + t.equal(Headers.prototype.entries.length, 0) + t.equal(Headers.prototype.forEach.length, 1) + t.equal(Headers.prototype.get.length, 1) + t.equal(Headers.prototype.has.length, 1) + t.equal(Headers.prototype.keys.length, 0) + t.equal(Headers.prototype.set.length, 2) + t.equal(Headers.prototype.values.length, 0) + t.equal(Headers.prototype[Symbol.iterator].length, 0) + t.equal(Headers.prototype.toString.length, 0) + + t.end() + }) + + t.test('function equality', (t) => { + t.equal(Headers.prototype.entries, Headers.prototype[Symbol.iterator]) + // TODO(@KhafraDev): ensure Headers.prototype.toString === Object.prototype.toString + + t.end() + }) + + t.end() +}) + tap.test('various init paths of Headers', (t) => { const h1 = new Headers() const h2 = new Headers({})