Skip to content

Commit 0091a89

Browse files
committed
fix: remove unsafe casting with ensureError
1 parent 899e2eb commit 0091a89

File tree

5 files changed

+53
-20
lines changed

5 files changed

+53
-20
lines changed

v-next/hardhat-utils/src/errors/request.ts

+38-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type UndiciT from "undici";
22

33
import { CustomError } from "../error.js";
44
import { sanitizeUrl } from "../internal/request.js";
5+
import { isObject } from "../lang.js";
56

67
export class RequestError extends CustomError {
78
constructor(url: string, type: UndiciT.Dispatcher.HttpMethod, cause?: Error) {
@@ -41,10 +42,43 @@ export class ResponseStatusCodeError extends CustomError {
4142
| null;
4243
public readonly body: null | Record<string, any> | string;
4344

44-
constructor(url: string, cause: UndiciT.errors.ResponseStatusCodeError) {
45+
constructor(url: string, cause: Error) {
4546
super(`Received an unexpected status code from ${sanitizeUrl(url)}`, cause);
46-
this.statusCode = cause.statusCode;
47-
this.headers = cause.headers;
48-
this.body = cause.body;
47+
this.statusCode =
48+
"statusCode" in cause && typeof cause.statusCode === "number"
49+
? cause.statusCode
50+
: -1;
51+
this.headers = this.#extractHeaders(cause);
52+
this.body = "body" in cause && isObject(cause.body) ? cause.body : null;
53+
}
54+
55+
#extractHeaders(
56+
cause: Error,
57+
): string[] | Record<string, string | string[] | undefined> | null {
58+
if ("headers" in cause) {
59+
const headers = cause.headers;
60+
if (Array.isArray(headers)) {
61+
return headers;
62+
} else if (this.#isValidHeaders(headers)) {
63+
return headers;
64+
}
65+
}
66+
return null;
67+
}
68+
69+
#isValidHeaders(
70+
headers: unknown,
71+
): headers is Record<string, string | string[] | undefined> {
72+
if (!isObject(headers)) {
73+
return false;
74+
}
75+
76+
return Object.values(headers).every(
77+
(header) =>
78+
typeof header === "string" ||
79+
(Array.isArray(header) &&
80+
header.every((item: unknown) => typeof item === "string")) ||
81+
header === undefined,
82+
);
4983
}
5084
}

v-next/hardhat-utils/src/internal/request.ts

+5-10
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import type UndiciT from "undici";
55
import path from "node:path";
66
import url from "node:url";
77

8-
import { ensureError } from "../error.js";
98
import { mkdir } from "../fs.js";
9+
import { isObject } from "../lang.js";
1010
import {
1111
ConnectionRefusedError,
1212
DEFAULT_MAX_REDIRECTS,
@@ -140,16 +140,12 @@ export function sanitizeUrl(requestUrl: string): string {
140140
return url.format(parsedUrl, { auth: false, search: false, fragment: false });
141141
}
142142

143-
export function handleError(
144-
e: NodeJS.ErrnoException,
145-
requestUrl: string,
146-
): void {
147-
let causeCode;
148-
if (e.cause !== undefined) {
149-
ensureError<NodeJS.ErrnoException>(e.cause);
143+
export function handleError(e: Error, requestUrl: string): void {
144+
let causeCode: unknown;
145+
if (isObject(e.cause)) {
150146
causeCode = e.cause.code;
151147
}
152-
const errorCode = e.code ?? causeCode;
148+
const errorCode = "code" in e ? e.code : causeCode;
153149

154150
if (errorCode === "ECONNREFUSED") {
155151
throw new ConnectionRefusedError(requestUrl, e);
@@ -164,7 +160,6 @@ export function handleError(
164160
}
165161

166162
if (errorCode === "UND_ERR_RESPONSE_STATUS_CODE") {
167-
ensureError<UndiciT.errors.ResponseStatusCodeError>(e);
168163
throw new ResponseStatusCodeError(requestUrl, e);
169164
}
170165
}

v-next/hardhat-utils/src/request.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export async function getRequest(
9191
...baseRequestOptions,
9292
});
9393
} catch (e) {
94-
ensureError<NodeJS.ErrnoException>(e);
94+
ensureError(e);
9595

9696
handleError(e, url);
9797

@@ -135,7 +135,7 @@ export async function postJsonRequest(
135135
body: JSON.stringify(body),
136136
});
137137
} catch (e) {
138-
ensureError<NodeJS.ErrnoException>(e);
138+
ensureError(e);
139139

140140
handleError(e, url);
141141

@@ -180,7 +180,7 @@ export async function postFormRequest(
180180
body: querystring.stringify(body as ParsedUrlQueryInput),
181181
});
182182
} catch (e) {
183-
ensureError<NodeJS.ErrnoException>(e);
183+
ensureError(e);
184184

185185
handleError(e, url);
186186

@@ -225,7 +225,7 @@ export async function download(
225225
await stream.pipeline(body, fileStream);
226226
await move(tempFilePath, destination);
227227
} catch (e) {
228-
ensureError<NodeJS.ErrnoException>(e);
228+
ensureError(e);
229229

230230
handleError(e, url);
231231

v-next/hardhat-utils/test/lang.ts

+4
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,10 @@ describe("lang", () => {
359359
isObject(new Set()),
360360
"new Set() is an object, but isObject returned false",
361361
);
362+
assert.ok(
363+
isObject(new Error()),
364+
"new Error() is an object, but isObject returned false",
365+
);
362366
});
363367

364368
it("Should return false for non-objects", () => {

v-next/hardhat/src/internal/network/http-provider.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,9 @@ export class HttpProvider extends EventEmitter implements EthereumProvider {
153153
result,
154154
};
155155
} catch (error) {
156-
ensureError<Error & { code: unknown }>(error);
156+
ensureError(error);
157157

158-
if (error.code === undefined) {
158+
if (!("code" in error) || error.code === undefined) {
159159
throw error;
160160
}
161161

0 commit comments

Comments
 (0)