Skip to content

Commit 651cdb8

Browse files
committed
fix(cp): implement errors
1 parent 804556c commit 651cdb8

File tree

2 files changed

+122
-20
lines changed

2 files changed

+122
-20
lines changed

lib/cp/polyfill.js

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,27 @@
1313
'use strict';
1414

1515
const {
16-
codes: {
17-
ERR_FS_CP_DIR_TO_NON_DIR,
18-
ERR_FS_CP_EEXIST,
19-
ERR_FS_CP_EINVAL,
20-
ERR_FS_CP_FIFO_PIPE,
21-
ERR_FS_CP_NON_DIR_TO_DIR,
22-
ERR_FS_CP_SOCKET,
23-
ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY,
24-
ERR_FS_CP_UNKNOWN,
25-
ERR_FS_EISDIR,
26-
},
27-
} = require('internal/errors');
16+
ERR_FS_CP_DIR_TO_NON_DIR,
17+
ERR_FS_CP_EEXIST,
18+
ERR_FS_CP_EINVAL,
19+
ERR_FS_CP_FIFO_PIPE,
20+
ERR_FS_CP_NON_DIR_TO_DIR,
21+
ERR_FS_CP_SOCKET,
22+
ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY,
23+
ERR_FS_CP_UNKNOWN,
24+
ERR_FS_EISDIR,
25+
} = require('../errors.js')
26+
2827
const {
29-
os: {
28+
constants: {
3029
errno: {
3130
EEXIST,
3231
EISDIR,
3332
EINVAL,
3433
ENOTDIR,
3534
}
3635
}
37-
} = internalBinding('constants');
36+
} = require('os')
3837
const {
3938
chmod,
4039
copyFile,
@@ -56,7 +55,7 @@ const {
5655
sep,
5756
} = require('path');
5857

59-
async function cpFn(src, dest, opts) {
58+
async function cp(src, dest, opts) {
6059
// Warn about using preserveTimestamps on 32-bit node
6160
if (opts.preserveTimestamps && process.arch === 'ia32') {
6261
const warning = 'Using the preserveTimestamps option in 32-bit ' +
@@ -375,8 +374,4 @@ async function copyLink(resolvedSrc, dest) {
375374
return symlink(resolvedSrc, dest);
376375
}
377376

378-
module.exports = {
379-
areIdentical,
380-
cpFn,
381-
isSrcSubdir,
382-
};
377+
module.exports = cp

lib/errors.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
'use strict'
2+
3+
// adapted from node's internal/errors
4+
// https://github.com/nodejs/node/blob/c8a04049be96d2a6d625d4417df095fc0f3eaa7b/lib/internal/errors.js
5+
6+
// close copy of node's internal SystemError class.
7+
class SystemError {
8+
constructor(code, prefix, context) {
9+
// XXX context.code is undefined in all constructors used in cp/polyfill
10+
// that may be a bug copied from node
11+
// await require('fs/promises').cp('error.ts', 'error.ts')
12+
//
13+
// Uncaught:
14+
// SystemError [ERR_FS_CP_EINVAL]: Invalid src or dest: cp returned undefined (src and dest cannot be the same) error.ts
15+
// maybe the constructor should use `code` not `errno`?
16+
// nodejs/node#41104
17+
let message = `${prefix}: ${context.syscall} returned ` +
18+
`${context.code} (${context.message})`
19+
20+
if (context.path !== undefined)
21+
message += ` ${context.path}`
22+
if (context.dest !== undefined)
23+
message += ` => ${context.dest}`
24+
25+
this.code = code
26+
Object.defineProperties(this, {
27+
name: {
28+
value: 'SystemError',
29+
enumerable: false,
30+
writable: true,
31+
configurable: true,
32+
},
33+
message: {
34+
value: message,
35+
enumerable: false,
36+
writable: true,
37+
configurable: true,
38+
},
39+
info: {
40+
value: context,
41+
enumerable: true,
42+
configurable: true,
43+
writable: false,
44+
},
45+
errno: {
46+
get() { return context.errno },
47+
set(value) { context.errno = value },
48+
enumerable: true,
49+
configurable: true,
50+
},
51+
syscall: {
52+
get() { return context.syscall },
53+
set(value) { context.syscall = value },
54+
enumerable: true,
55+
configurable: true,
56+
},
57+
})
58+
59+
if (context.path !== undefined) {
60+
Object.defineProperty(this, 'path', {
61+
get() { return context.path },
62+
set(value) { context.path = value },
63+
enumerable: true,
64+
configurable: true
65+
})
66+
}
67+
68+
if (context.dest !== undefined) {
69+
Object.defineProperty(this, 'dest', {
70+
get() { return context.dest },
71+
set(value) { context.dest = value },
72+
enumerable: true,
73+
configurable: true
74+
})
75+
}
76+
}
77+
78+
toString() {
79+
return `${this.name} [${this.code}]: ${this.message}`
80+
}
81+
82+
[Symbol.for('nodejs.util.inspect.custom')](_recurseTimes, ctx) {
83+
return lazyInternalUtilInspect().inspect(this, {
84+
...ctx,
85+
getters: true,
86+
customInspect: false
87+
})
88+
}
89+
}
90+
91+
function E (code, message) {
92+
module.exports[code] = class NodeError extends SystemError {
93+
constructor(ctx) {
94+
super(code, message, ctx)
95+
}
96+
}
97+
}
98+
99+
E('ERR_FS_CP_DIR_TO_NON_DIR', 'Cannot overwrite directory with non-directory')
100+
E('ERR_FS_CP_EEXIST', 'Target already exists')
101+
E('ERR_FS_CP_EINVAL', 'Invalid src or dest')
102+
E('ERR_FS_CP_FIFO_PIPE', 'Cannot copy a FIFO pipe')
103+
E('ERR_FS_CP_NON_DIR_TO_DIR', 'Cannot overwrite non-directory with directory')
104+
E('ERR_FS_CP_SOCKET', 'Cannot copy a socket file')
105+
E('ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY', 'Cannot overwrite symlink in subdirectory of self')
106+
E('ERR_FS_CP_UNKNOWN', 'Cannot copy an unknown file type')
107+
E('ERR_FS_EISDIR', 'Path is a directory')

0 commit comments

Comments
 (0)