Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 12fff33

Browse files
author
Akos Kitta
committed
feat: generalized Node.js error handling
gracefully handle when sketch folder has been deleted Closes #1596 Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
1 parent f6275f9 commit 12fff33

File tree

5 files changed

+46
-8
lines changed

5 files changed

+46
-8
lines changed

‎arduino-ide-extension/src/electron-main/theia/electron-main-application.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
SHOW_PLOTTER_WINDOW,
2929
} from '../../common/ipc-communication';
3030
import isValidPath = require('is-valid-path');
31+
import { ErrnoException } from '../../node/utils/errors';
3132

3233
app.commandLine.appendSwitch('disable-http-cache');
3334

@@ -172,7 +173,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
172173
try {
173174
stats = await fs.stat(path);
174175
} catch (err) {
175-
if ('code'inerr&&err.code==='ENOENT') {
176+
if (ErrnoException.isENOENT(err)) {
176177
return undefined;
177178
}
178179
throw err;
@@ -215,7 +216,7 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
215216
const resolved = await fs.realpath(resolve(cwd, maybePath));
216217
return resolved;
217218
} catch (err) {
218-
if ('code'inerr&&err.code==='ENOENT') {
219+
if (ErrnoException.isENOENT(err)) {
219220
return undefined;
220221
}
221222
throw err;

‎arduino-ide-extension/src/node/arduino-daemon-impl.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { BackendApplicationContribution } from '@theia/core/lib/node/backend-app
1616
import { ArduinoDaemon, NotificationServiceServer } from '../common/protocol';
1717
import { CLI_CONFIG } from './cli-config';
1818
import { getExecPath, spawnCommand } from './exec-util';
19+
import { ErrnoException } from './utils/errors';
1920

2021
@injectable()
2122
export class ArduinoDaemonImpl
@@ -184,7 +185,7 @@ export class ArduinoDaemonImpl
184185
}
185186
return false;
186187
} catch (error) {
187-
if ('code'inerror&&error.code==='ENOENT') {
188+
if (ErrnoException.isENOENT(error)) {
188189
return false;
189190
}
190191
throw error;

‎arduino-ide-extension/src/node/config-service-impl.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { DefaultCliConfig, CLI_CONFIG } from './cli-config';
2626
import { Deferred } from '@theia/core/lib/common/promise-util';
2727
import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
2828
import { deepClone } from '@theia/core';
29+
import { ErrnoException } from './utils/errors';
2930

3031
const deepmerge = require('deepmerge');
3132

@@ -146,7 +147,7 @@ export class ConfigServiceImpl
146147
const fallbackModel = await this.getFallbackCliConfig();
147148
return deepmerge(fallbackModel, model) as DefaultCliConfig;
148149
} catch (error) {
149-
if ('code'inerror&&error.code==='ENOENT') {
150+
if (ErrnoException.isENOENT(error)) {
150151
if (initializeIfAbsent) {
151152
await this.initCliConfigTo(dirname(cliConfigPath));
152153
return this.loadCliConfig(false);

‎arduino-ide-extension/src/node/sketches-service-impl.ts‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
TempSketchPrefix,
3434
} from './is-temp-sketch';
3535
import { join } from 'path';
36+
import { ErrnoException } from './utils/errors';
3637

3738
const RecentSketches = 'recent-sketches.json';
3839
const DefaultIno = `void setup() {
@@ -278,7 +279,7 @@ export class SketchesServiceImpl
278279
);
279280
}
280281
} catch (err) {
281-
if ('code'inerr&&err.code==='ENOENT') {
282+
if (ErrnoException.isENOENT(err)) {
282283
this.logger.debug(
283284
`<<< '${RecentSketches}' does not exist yet. This is normal behavior. Falling back to empty data.`
284285
);
@@ -666,7 +667,7 @@ export class SketchesServiceImpl
666667

667668
return this.tryParse(raw);
668669
} catch (err) {
669-
if ('code'inerr&&err.code==='ENOENT') {
670+
if (ErrnoException.isENOENT(err)) {
670671
return undefined;
671672
}
672673
throw err;
@@ -695,7 +696,7 @@ export class SketchesServiceImpl
695696
});
696697
this.inoContent.resolve(inoContent);
697698
} catch (err) {
698-
if ('code'inerr&&err.code==='ENOENT') {
699+
if (ErrnoException.isENOENT(err)) {
699700
// Ignored. The custom `.ino` blueprint file is optional.
700701
} else {
701702
throw err;
@@ -763,7 +764,7 @@ async function isInvalidSketchNameError(
763764
.map((name) => path.join(requestSketchPath, name))[0]
764765
);
765766
} catch (err) {
766-
if ('code'inerr&&err.code==='ENOTDIR') {
767+
if (ErrnoException.isENOENT(err)||ErrnoException.isENOTDIR(err)) {
767768
return undefined;
768769
}
769770
throw err;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
export type ErrnoException = Error & { code: string; errno: number };
2+
export namespace ErrnoException {
3+
export function is(arg: unknown): arg is ErrnoException {
4+
if (arg instanceof Error) {
5+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
6+
const error = arg as any;
7+
return (
8+
'code' in error &&
9+
'errno' in error &&
10+
typeof error['code'] === 'string' &&
11+
typeof error['errno'] === 'number'
12+
);
13+
}
14+
return false;
15+
}
16+
17+
/**
18+
* (No such file or directory): Commonly raised by `fs` operations to indicate that a component of the specified pathname does not exist — no entity (file or directory) could be found by the given path.
19+
*/
20+
export function isENOENT(
21+
arg: unknown
22+
): arg is ErrnoException & { code: 'ENOENT' } {
23+
return is(arg) && arg.code === 'ENOENT';
24+
}
25+
26+
/**
27+
* (Not a directory): A component of the given pathname existed, but was not a directory as expected. Commonly raised by `fs.readdir`.
28+
*/
29+
export function isENOTDIR(
30+
arg: unknown
31+
): arg is ErrnoException & { code: 'ENOTDIR' } {
32+
return is(arg) && arg.code === 'ENOTDIR';
33+
}
34+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /