Skip to content

Commit e6eafd0

Browse files
authored
Merge branch 'main' into 6181
2 parents ec50793 + 8ec09d6 commit e6eafd0

File tree

8 files changed

+148
-21
lines changed

8 files changed

+148
-21
lines changed

.changeset/giant-ads-hammer.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"hardhat": patch
3+
---
4+
5+
Don't swallow the original error when trying to improve installation error messages

v-next/hardhat-test-utils/src/hardhat-error.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ import { ensureError } from "@nomicfoundation/hardhat-utils/error";
1212
* @param error The error.
1313
* @param descriptor The error descriptor.
1414
* @param messageArguments The message arguments.
15+
* @param cause The error cause. Only checked if not `undefined`.
1516
*/
1617
export function assertIsHardhatError<ErrorDescriptorT extends ErrorDescriptor>(
1718
error: unknown,
1819
descriptor: ErrorDescriptorT,
1920
messageArguments: HardhatError<ErrorDescriptorT>["messageArguments"],
21+
cause?: Error,
2022
): asserts error is HardhatError<ErrorDescriptorT> {
2123
assert.ok(HardhatError.isHardhatError(error), "Error is not a HardhatError");
2224

@@ -31,6 +33,14 @@ export function assertIsHardhatError<ErrorDescriptorT extends ErrorDescriptor>(
3133
assert.deepEqual(error.descriptor, descriptor);
3234

3335
assert.deepEqual(error.messageArguments, messageArguments);
36+
37+
if (cause !== undefined) {
38+
assert.equal(
39+
error.cause,
40+
cause,
41+
"Error cause is not what's expected (comparing by reference)",
42+
);
43+
}
3444
}
3545

3646
/**
@@ -40,19 +50,21 @@ export function assertIsHardhatError<ErrorDescriptorT extends ErrorDescriptor>(
4050
* @param f The function that should throw.
4151
* @param descriptor The error descriptor.
4252
* @param messageArguments The message arguments.
53+
* @param cause The error cause. Only checked if not `undefined`.
4354
*/
4455
export function assertThrowsHardhatError<
4556
ErrorDescriptorT extends ErrorDescriptor,
4657
>(
4758
f: () => any,
4859
descriptor: ErrorDescriptorT,
4960
messageArguments: HardhatError<ErrorDescriptorT>["messageArguments"],
61+
cause?: Error,
5062
): void {
5163
try {
5264
f();
5365
} catch (error) {
5466
ensureError(error);
55-
assertIsHardhatError(error, descriptor, messageArguments);
67+
assertIsHardhatError(error, descriptor, messageArguments, cause);
5668

5769
return;
5870
}
@@ -68,13 +80,15 @@ export function assertThrowsHardhatError<
6880
* @param op The async operation. If it's a function, it's called and awaited.
6981
* @param descriptor The error descriptor.
7082
* @param messageArguments The message arguments.
83+
* @param cause The error cause. Only checked if not `undefined`.
7184
*/
7285
export async function assertRejectsWithHardhatError<
7386
ErrorDescriptorT extends ErrorDescriptor,
7487
>(
7588
op: (() => Promise<any>) | Promise<any>,
7689
descriptor: ErrorDescriptorT,
7790
messageArguments: HardhatError<ErrorDescriptorT>["messageArguments"],
91+
cause?: Error,
7892
): Promise<void> {
7993
try {
8094
if (op instanceof Promise) {
@@ -84,7 +98,7 @@ export async function assertRejectsWithHardhatError<
8498
}
8599
} catch (error) {
86100
ensureError(error);
87-
assertIsHardhatError(error, descriptor, messageArguments);
101+
assertIsHardhatError(error, descriptor, messageArguments, cause);
88102

89103
return;
90104
}

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

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,50 @@ describe("HardhatError helpers", () => {
5555
});
5656
});
5757

58-
it("Should not throw if the error is a HardhatError with the same descriptor and message arguments", () => {
59-
assertIsHardhatError(
60-
new HardhatError(
58+
describe("Error cause", () => {
59+
it("Should not throw if the error cause is provided and its the same", () => {
60+
const cause = new Error("cause");
61+
62+
assertIsHardhatError(
63+
new HardhatError(
64+
HardhatError.ERRORS.CORE.TASK_DEFINITIONS.UNRECOGNIZED_TASK_OPTION,
65+
{ option: "foo", task: "bar" },
66+
cause,
67+
),
6168
HardhatError.ERRORS.CORE.TASK_DEFINITIONS.UNRECOGNIZED_TASK_OPTION,
6269
{ option: "foo", task: "bar" },
63-
),
64-
HardhatError.ERRORS.CORE.TASK_DEFINITIONS.UNRECOGNIZED_TASK_OPTION,
65-
{ option: "foo", task: "bar" },
66-
);
70+
cause,
71+
);
72+
});
73+
74+
it("Should throw if a cause is provided and doesn't match the error cause (by reference)", () => {
75+
assert.throws(() => {
76+
assertIsHardhatError(
77+
new HardhatError(
78+
HardhatError.ERRORS.CORE.TASK_DEFINITIONS.UNRECOGNIZED_TASK_OPTION,
79+
{ option: "foo", task: "bar" },
80+
new Error("cause"),
81+
),
82+
HardhatError.ERRORS.CORE.TASK_DEFINITIONS.UNRECOGNIZED_TASK_OPTION,
83+
{ option: "foo", task: "bar" },
84+
new Error("cause"),
85+
);
86+
});
87+
});
88+
89+
it("Should throw if the cause is provided but there's none", () => {
90+
assert.throws(() => {
91+
assertIsHardhatError(
92+
new HardhatError(
93+
HardhatError.ERRORS.CORE.TASK_DEFINITIONS.UNRECOGNIZED_TASK_OPTION,
94+
{ option: "foo", task: "bar" },
95+
),
96+
HardhatError.ERRORS.CORE.TASK_DEFINITIONS.UNRECOGNIZED_TASK_OPTION,
97+
{ option: "foo", task: "bar" },
98+
new Error("cause"),
99+
);
100+
});
101+
});
67102
});
68103
});
69104

@@ -103,6 +138,24 @@ describe("HardhatError helpers", () => {
103138
{ option: "foo", task: "bar" },
104139
);
105140
});
141+
142+
it("asserts the cause", () => {
143+
assert.throws(() => {
144+
assertThrowsHardhatError(
145+
() => {
146+
throw new HardhatError(
147+
HardhatError.ERRORS.CORE.TASK_DEFINITIONS.UNRECOGNIZED_TASK_OPTION,
148+
{ option: "foo", task: "bar" },
149+
new Error("cause"),
150+
);
151+
},
152+
153+
HardhatError.ERRORS.CORE.TASK_DEFINITIONS.UNRECOGNIZED_TASK_OPTION,
154+
{ option: "foo", task: "bar" },
155+
new Error("cause"),
156+
);
157+
});
158+
});
106159
});
107160

108161
describe("assertRejectsWithHardhatError", () => {
@@ -164,5 +217,22 @@ describe("HardhatError helpers", () => {
164217
{ option: "foo", task: "bar" },
165218
);
166219
});
220+
221+
it("asserts the cause", async () => {
222+
await assert.rejects(async () => {
223+
await assertRejectsWithHardhatError(
224+
async () => {
225+
throw new HardhatError(
226+
HardhatError.ERRORS.CORE.TASK_DEFINITIONS.UNRECOGNIZED_TASK_OPTION,
227+
{ option: "foo", task: "bar" },
228+
new Error("cause"),
229+
);
230+
},
231+
HardhatError.ERRORS.CORE.TASK_DEFINITIONS.UNRECOGNIZED_TASK_OPTION,
232+
{ option: "foo", task: "bar" },
233+
new Error("cause"),
234+
);
235+
});
236+
});
167237
});
168238
});

v-next/hardhat/src/internal/core/hook-manager.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type { HardhatPlugin } from "../../types/plugins.js";
1313
import type { LastParameter, Return } from "../../types/utils.js";
1414

1515
import { assertHardhatInvariant } from "@nomicfoundation/hardhat-errors";
16+
import { ensureError } from "@nomicfoundation/hardhat-utils/error";
1617
import { AsyncMutex } from "@nomicfoundation/hardhat-utils/synchronization";
1718

1819
import { detectPluginNpmDependencyProblems } from "./plugins/detect-plugin-npm-dependency-problems.js";
@@ -297,7 +298,14 @@ export class HookManagerImplementation implements HookManager {
297298
try {
298299
factory = (await hookHandlerCategoryFactory()).default;
299300
} catch (error) {
300-
await detectPluginNpmDependencyProblems(this.#projectRoot, plugin);
301+
ensureError(error);
302+
303+
await detectPluginNpmDependencyProblems(
304+
this.#projectRoot,
305+
plugin,
306+
error,
307+
);
308+
301309
throw error;
302310
}
303311

v-next/hardhat/src/internal/core/plugins/detect-plugin-npm-dependency-problems.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
*
1616
* @param basePathForNpmResolution the dir path for node module resolution
1717
* @param plugin the plugin to be validated
18+
* @param originalError the original error why we are running this function
1819
* @throws {HardhatError} with descriptor:
1920
* - {@link HardhatError.ERRORS.CORE.PLUGINS.PLUGIN_NOT_INSTALLED} if the plugin is
2021
* not installed as an npm package
@@ -26,6 +27,7 @@ import {
2627
export async function detectPluginNpmDependencyProblems(
2728
basePathForNpmResolution: string,
2829
plugin: HardhatPlugin,
30+
originalError: Error,
2931
): Promise<void> {
3032
if (plugin.npmPackage === null) {
3133
return;
@@ -43,6 +45,7 @@ export async function detectPluginNpmDependencyProblems(
4345
{
4446
pluginId: plugin.id,
4547
},
48+
originalError,
4649
);
4750
}
4851

@@ -71,6 +74,7 @@ export async function detectPluginNpmDependencyProblems(
7174
pluginId: plugin.id,
7275
peerDependencyName: dependencyName,
7376
},
77+
originalError,
7478
);
7579
}
7680

@@ -91,6 +95,7 @@ export async function detectPluginNpmDependencyProblems(
9195
installedVersion,
9296
expectedVersion: versionSpec,
9397
},
98+
originalError,
9499
);
95100
}
96101
}

v-next/hardhat/src/internal/core/plugins/resolve-plugin-list.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ async function reverseTopologicalSort(
5353
dependencyModules = await Promise.all(plugin.dependencies());
5454
} catch (error) {
5555
ensureError(error);
56-
await detectPluginNpmDependencyProblems(projectRoot, plugin);
56+
await detectPluginNpmDependencyProblems(projectRoot, plugin, error);
5757

5858
throw new HardhatError(
5959
HardhatError.ERRORS.CORE.PLUGINS.PLUGIN_DEPENDENCY_FAILED_LOAD,
@@ -114,7 +114,7 @@ async function reverseTopologicalSort(
114114
pluginModule = await conditionalDependency.plugin();
115115
} catch (error) {
116116
ensureError(error);
117-
await detectPluginNpmDependencyProblems(projectRoot, plugin);
117+
await detectPluginNpmDependencyProblems(projectRoot, plugin, error);
118118

119119
throw new HardhatError(
120120
HardhatError.ERRORS.CORE.PLUGINS.PLUGIN_DEPENDENCY_FAILED_LOAD,

v-next/hardhat/src/internal/core/tasks/resolved-task.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ export class ResolvedTask implements Task {
244244
await detectPluginNpmDependencyProblems(
245245
this.#hre.config.paths.root,
246246
plugin,
247+
error,
247248
);
248249
}
249250

0 commit comments

Comments
 (0)