Skip to content

Commit

Permalink
fix(Headers): ensure <fn>.length is correct (nodejs#1428)
Browse files Browse the repository at this point in the history
  • Loading branch information
KhafraDev authored and metcoder95 committed Dec 26, 2022
1 parent 639fcb6 commit 0f507cd
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 32 deletions.
72 changes: 40 additions & 32 deletions lib/fetch/headers.js
Expand Up @@ -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')
Expand All @@ -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')
Expand All @@ -259,62 +263,68 @@ 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.`
)
}

if (this[kGuard] === 'immutable') {
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] () {
Expand Down Expand Up @@ -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
Expand All @@ -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'."
Expand Down
28 changes: 28 additions & 0 deletions test/fetch/headers.js
Expand Up @@ -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({})
Expand Down

0 comments on commit 0f507cd

Please sign in to comment.