Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clean up usage of null/undefined #380

Merged
merged 17 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions lib/cookie/canonicalDomain.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as punycode from 'punycode/punycode.js'
import { toASCII } from 'punycode/punycode.js'
import { IP_V6_REGEX_OBJECT } from './constants'
import type { Nullable } from '../utils'

// S5.1.2 Canonicalized Host Names
export function canonicalDomain(str: string | null) {
export function canonicalDomain(str: Nullable<string>): string | null {
if (str == null) {
return null
}
Expand All @@ -15,7 +16,7 @@ export function canonicalDomain(str: string | null) {
// convert to IDN if any non-ASCII characters
// eslint-disable-next-line no-control-regex
if (/[^\u0001-\u007f]/.test(_str)) {
_str = punycode.toASCII(_str)
_str = toASCII(_str)
}

return _str.toLowerCase()
Expand Down
11 changes: 11 additions & 0 deletions lib/cookie/cookie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,20 @@ type ParseCookieOptions = {
loose?: boolean | undefined
}

/**
* Parses a string into a Cookie object.
* @param str the Set-Cookie header or a Cookie string to parse. Note: when parsing a Cookie header it must be split by ';' before each Cookie string can be parsed.
* @param options configures strict or loose mode for cookie parsing
* @returns `Cookie` object for valid string inputs, `undefined` for invalid string inputs,
* or `null` for non-string inputs or empty string
*/
function parse(
str: string,
options?: ParseCookieOptions,
// TBD: Should we change the API to have a single "invalid input" return type? I think `undefined`
wjhsf marked this conversation as resolved.
Show resolved Hide resolved
// would be more consistent with the rest of the code, and it would be of minimal impact. Only
// users who are passing an invalid input and doing an explicit null check would be broken, and
// that doesn't seem like it would be a significant number of users.
): Cookie | undefined | null {
if (validators.isEmptyString(str) || !validators.isString(str)) {
return null
Expand Down
28 changes: 13 additions & 15 deletions lib/cookie/cookieJar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import { pathMatch } from '../pathMatch'
import { Cookie } from './cookie'
import {
Callback,
createPromiseCallback,
ErrorCallback,
Nullable,
createPromiseCallback,
inOperator,
safeToString,
} from '../utils'
Expand Down Expand Up @@ -154,7 +155,7 @@ export class CookieJar {
readonly prefixSecurity: string

constructor(
store?: Store | null | undefined,
store?: Nullable<Store>,
options?: CreateCookieJarOptions | boolean,
) {
if (typeof options === 'boolean') {
Expand Down Expand Up @@ -433,16 +434,16 @@ export class CookieJar {
}
}

function withCookie(
err: Error | null,
oldCookie: Cookie | undefined | null,
const withCookie: Callback<Cookie | undefined> = function withCookie(
err,
oldCookie,
): void {
if (err) {
cb(err)
return
}

const next = function (err: Error | null): void {
const next: ErrorCallback = function (err) {
if (err) {
cb(err)
} else if (typeof cookie === 'string') {
Expand Down Expand Up @@ -484,6 +485,7 @@ export class CookieJar {
}
}

// TODO: Refactor to avoid using a callback
store.findCookie(cookie.domain, cookie.path, cookie.key, withCookie)
return promiseCallback.promise
}
Expand Down Expand Up @@ -741,18 +743,13 @@ export class CookieJar {
callback,
)

const next: Callback<Cookie[]> = function (
err: Error | null,
cookies: Cookie[] | undefined,
) {
const next: Callback<Cookie[] | undefined> = function (err, cookies) {
if (err) {
promiseCallback.callback(err)
} else if (cookies === undefined) {
promiseCallback.callback(null, undefined)
} else {
promiseCallback.callback(
null,
cookies.map((c) => {
cookies?.map((c) => {
return c.toString()
}),
)
Expand Down Expand Up @@ -872,7 +869,7 @@ export class CookieJar {

cookies = cookies.slice() // do not modify the original

const putNext = (err: Error | null): void => {
const putNext: ErrorCallback = (err) => {
if (err) {
return callback(err, undefined)
}
Expand Down Expand Up @@ -988,7 +985,8 @@ export class CookieJar {
let completedCount = 0
const removeErrors: Error[] = []

function removeCookieCb(removeErr: Error | null) {
// TODO: Refactor to avoid using callback
const removeCookieCb: ErrorCallback = function removeCookieCb(removeErr) {
if (removeErr) {
removeErrors.push(removeErr)
}
Expand Down
4 changes: 3 additions & 1 deletion lib/cookie/defaultPath.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
// RFC6265 S5.1.4 Paths and Path-Match

import type { Nullable } from '../utils'

/*
* "The user agent MUST use an algorithm equivalent to the following algorithm
* to compute the default-path of a cookie:"
*
* Assumption: the path (and not query part or absolute uri) is passed in.
*/
export function defaultPath(path?: string | null): string {
export function defaultPath(path?: Nullable<string>): string {
// "2. If the uri-path is empty or if the first character of the uri-path is not
// a %x2F ("/") character, output %x2F ("/") and skip the remaining steps.
if (!path || path.slice(0, 1) !== '/') {
Expand Down
9 changes: 5 additions & 4 deletions lib/cookie/domainMatch.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Nullable } from '../utils'
import { canonicalDomain } from './canonicalDomain'

// Dumped from [email protected], with the following changes:
Expand All @@ -9,16 +10,16 @@ const IP_REGEX_LOWERCASE =

// S5.1.3 Domain Matching
export function domainMatch(
str?: string | null,
domStr?: string | null,
str?: Nullable<string>,
domStr?: Nullable<string>,
canonicalize?: boolean,
): boolean | null {
if (str == null || domStr == null) {
return null
}

let _str: string | null
let _domStr: string | null
let _str: Nullable<string>
let _domStr: Nullable<string>

if (canonicalize !== false) {
_str = canonicalDomain(str)
Expand Down
5 changes: 4 additions & 1 deletion lib/cookie/parseDate.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
// date-time parsing constants (RFC6265 S5.1.1)

import type { Nullable } from '../utils'

// eslint-disable-next-line no-control-regex
const DATE_DELIM = /[\x09\x20-\x2F\x3B-\x40\x5B-\x60\x7B-\x7E]/

Expand Down Expand Up @@ -123,7 +126,7 @@ function parseMonth(token: string) {
/*
* RFC6265 S5.1.1 date parser (see RFC for full grammar)
*/
export function parseDate(str: string | undefined | null): Date | undefined {
export function parseDate(str: Nullable<string>): Date | undefined {
if (!str) {
return undefined
}
Expand Down
25 changes: 15 additions & 10 deletions lib/memstore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ import type { Cookie } from './cookie/cookie'
import { pathMatch } from './pathMatch'
import { permuteDomain } from './permuteDomain'
import { Store } from './store'
import { Callback, createPromiseCallback, ErrorCallback } from './utils'
import {
Callback,
createPromiseCallback,
ErrorCallback,
Nullable,
} from './utils'

export type MemoryCookieStoreIndex = {
[domain: string]: {
Expand All @@ -54,20 +59,20 @@ export class MemoryCookieStore extends Store {
}

override findCookie(
domain: string | null,
path: string | null,
key: string | undefined,
domain: Nullable<string>,
path: Nullable<string>,
key: Nullable<string>,
): Promise<Cookie | undefined>
override findCookie(
domain: string | null,
path: string | null,
key: string | undefined,
domain: Nullable<string>,
path: Nullable<string>,
key: Nullable<string>,
callback: Callback<Cookie | undefined>,
): void
override findCookie(
domain: string | null,
path: string | null,
key: string | undefined,
domain: Nullable<string>,
path: Nullable<string>,
key: Nullable<string>,
callback?: Callback<Cookie | undefined>,
): unknown {
const promiseCallback = createPromiseCallback(callback)
Expand Down
62 changes: 31 additions & 31 deletions lib/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
'use strict'

import type { Cookie } from './cookie/cookie'
import type { Callback, ErrorCallback } from './utils'
import type { Callback, ErrorCallback, Nullable } from './utils'

export class Store {
synchronous: boolean
Expand All @@ -46,39 +46,39 @@ export class Store {
}

findCookie(
domain: string | null,
path: string | null,
key: string | undefined,
): Promise<Cookie | null | undefined>
domain: Nullable<string>,
path: Nullable<string>,
key: Nullable<string>,
): Promise<Cookie | undefined>
findCookie(
domain: string | null,
path: string | null,
key: string | undefined,
callback: Callback<Cookie | null | undefined>,
domain: Nullable<string>,
path: Nullable<string>,
key: Nullable<string>,
callback: Callback<Cookie | undefined>,
): void
findCookie(
_domain: string | null,
_path: string | null,
_key: string | undefined,
_callback?: Callback<Cookie | null | undefined>,
_domain: Nullable<string>,
_path: Nullable<string>,
_key: Nullable<string>,
_callback?: Callback<Cookie | undefined>,
): unknown {
throw new Error('findCookie is not implemented')
}

findCookies(
domain: string | null,
path: string | null,
domain: Nullable<string>,
path: Nullable<string>,
allowSpecialUseDomain?: boolean,
): Promise<Cookie[]>
findCookies(
domain: string | null,
path: string | null,
domain: Nullable<string>,
path: Nullable<string>,
allowSpecialUseDomain?: boolean,
callback?: Callback<Cookie[]>,
): void
findCookies(
_domain: string | null,
_path: string | null,
_domain: Nullable<string>,
_path: Nullable<string>,
_allowSpecialUseDomain: boolean | Callback<Cookie[]> = false,
_callback?: Callback<Cookie[]>,
): unknown {
Expand Down Expand Up @@ -108,34 +108,34 @@ export class Store {
}

removeCookie(
domain: string | null | undefined,
path: string | null | undefined,
key: string | null | undefined,
domain: Nullable<string>,
path: Nullable<string>,
key: Nullable<string>,
): Promise<void>
removeCookie(
domain: string | null | undefined,
path: string | null | undefined,
key: string | null | undefined,
domain: Nullable<string>,
path: Nullable<string>,
key: Nullable<string>,
callback: ErrorCallback,
): void
removeCookie(
_domain: string | null | undefined,
_path: string | null | undefined,
_key: string | null | undefined,
_domain: Nullable<string>,
_path: Nullable<string>,
_key: Nullable<string>,
_callback?: ErrorCallback,
): unknown {
throw new Error('removeCookie is not implemented')
}

removeCookies(domain: string, path: string | null): Promise<void>
removeCookies(domain: string, path: Nullable<string>): Promise<void>
removeCookies(
domain: string,
path: string | null,
path: Nullable<string>,
callback: ErrorCallback,
): void
removeCookies(
_domain: string,
_path: string | null,
_path: Nullable<string>,
_callback?: ErrorCallback,
): unknown {
throw new Error('removeCookies is not implemented')
Expand Down
3 changes: 3 additions & 0 deletions lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ export interface ErrorCallback {
(error: Error | null): void
}

/** The inverse of NonNullable<T>. */
export type Nullable<T> = T | null | undefined

/** Wrapped `Object.prototype.toString`, so that you don't need to remember to use `.call()`. */
export const objectToString = (obj: unknown) =>
Object.prototype.toString.call(obj)
Expand Down
Loading