GeezerVison is showing github.com — lib: add throws option to fs.f/l/statSync · nodejs/node@5e77bcd
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboard +28Lines changed: 28 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | +const fs = require('fs'); | | 5 | +const path = require('path'); | | 6 | + | | 7 | +const bench = common.createBenchmark(main, { | | 8 | + n: [1e6], | | 9 | + statSyncType: ['throw', 'noThrow'] | | 10 | +}); | | 11 | + | | 12 | + | | 13 | +function main({ n, statSyncType }) { | | 14 | + const arg = path.join(__dirname, 'non.existent'); | | 15 | + | | 16 | + bench.start(); | | 17 | + for (let i = 0; i < n; i++) { | | 18 | + if (statSyncType === 'noThrow') { | | 19 | + fs.statSync(arg, { throwIfNoEntry: false }); | | 20 | + } else { | | 21 | + try { | | 22 | + fs.statSync(arg); | | 23 | + } catch { | | 24 | + } | | 25 | + } | | 26 | + } | | 27 | + bench.end(n); | | 28 | +} |
Collapse file Copy file name to clipboardExpand all lines: doc/api/fs.md +6Lines changed: 6 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -2560,6 +2560,9 @@ changes: | 2560 | 2560 | * `options` {Object} | 2561 | 2561 | * `bigint` {boolean} Whether the numeric values in the returned | 2562 | 2562 | [`fs.Stats`][] object should be `bigint`. **Default:** `false`. | | 2563 | + * `throwIfNoEntry` {boolean} Whether an exception will be thrown | | 2564 | + if no file system entry exists, rather than returning `undefined`. | | 2565 | + **Default:** `true`. | 2563 | 2566 | * Returns: {fs.Stats} | 2564 | 2567 |
| 2565 | 2568 | Synchronous lstat(2). | @@ -3765,6 +3768,9 @@ changes: | 3765 | 3768 | * `options` {Object} | 3766 | 3769 | * `bigint` {boolean} Whether the numeric values in the returned | 3767 | 3770 | [`fs.Stats`][] object should be `bigint`. **Default:** `false`. | | 3771 | + * `throwIfNoEntry` {boolean} Whether an exception will be thrown | | 3772 | + if no file system entry exists, rather than returning `undefined`. | | 3773 | + **Default:** `true`. | 3768 | 3774 | * Returns: {fs.Stats} | 3769 | 3775 |
| 3770 | 3776 | Synchronous stat(2). | |
Collapse file Copy file name to clipboardExpand all lines: lib/fs.js +23-3Lines changed: 23 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -71,6 +71,7 @@ const { | 71 | 71 | ERR_INVALID_CALLBACK, | 72 | 72 | ERR_FEATURE_UNAVAILABLE_ON_PLATFORM | 73 | 73 | }, | | 74 | + uvErrmapGet, | 74 | 75 | uvException | 75 | 76 | } = require('internal/errors'); | 76 | 77 |
| @@ -1061,28 +1062,47 @@ function stat(path, options = { bigint: false }, callback) { | 1061 | 1062 | binding.stat(pathModule.toNamespacedPath(path), options.bigint, req); | 1062 | 1063 | } | 1063 | 1064 |
| 1064 | | -function fstatSync(fd, options = { bigint: false }) { | | 1065 | +function hasNoEntryError(ctx) { | | 1066 | + if (ctx.errno) { | | 1067 | + const uvErr = uvErrmapGet(ctx.errno); | | 1068 | + return uvErr && uvErr[0] === 'ENOENT'; | | 1069 | + } | | 1070 | + | | 1071 | + if (ctx.error) { | | 1072 | + return ctx.error.code === 'ENOENT'; | | 1073 | + } | | 1074 | + | | 1075 | + return false; | | 1076 | +} | | 1077 | + | | 1078 | +function fstatSync(fd, options = { bigint: false, throwIfNoEntry: true }) { | 1065 | 1079 | validateInt32(fd, 'fd', 0); | 1066 | 1080 | const ctx = { fd }; | 1067 | 1081 | const stats = binding.fstat(fd, options.bigint, undefined, ctx); | 1068 | 1082 | handleErrorFromBinding(ctx); | 1069 | 1083 | return getStatsFromBinding(stats); | 1070 | 1084 | } | 1071 | 1085 |
| 1072 | | -function lstatSync(path, options = { bigint: false }) { | | 1086 | +function lstatSync(path, options = { bigint: false, throwIfNoEntry: true }) { | 1073 | 1087 | path = getValidatedPath(path); | 1074 | 1088 | const ctx = { path }; | 1075 | 1089 | const stats = binding.lstat(pathModule.toNamespacedPath(path), | 1076 | 1090 | options.bigint, undefined, ctx); | | 1091 | + if (options.throwIfNoEntry === false && hasNoEntryError(ctx)) { | | 1092 | + return undefined; | | 1093 | + } | 1077 | 1094 | handleErrorFromBinding(ctx); | 1078 | 1095 | return getStatsFromBinding(stats); | 1079 | 1096 | } | 1080 | 1097 |
| 1081 | | -function statSync(path, options = { bigint: false }) { | | 1098 | +function statSync(path, options = { bigint: false, throwIfNoEntry: true }) { | 1082 | 1099 | path = getValidatedPath(path); | 1083 | 1100 | const ctx = { path }; | 1084 | 1101 | const stats = binding.stat(pathModule.toNamespacedPath(path), | 1085 | 1102 | options.bigint, undefined, ctx); | | 1103 | + if (options.throwIfNoEntry === false && hasNoEntryError(ctx)) { | | 1104 | + return undefined; | | 1105 | + } | 1086 | 1106 | handleErrorFromBinding(ctx); | 1087 | 1107 | return getStatsFromBinding(stats); | 1088 | 1108 | } | |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-fs-stat-bigint.js +27Lines changed: 27 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -122,6 +122,33 @@ if (!common.isWindows) { | 122 | 122 | fs.closeSync(fd); | 123 | 123 | } | 124 | 124 |
| | 125 | +{ | | 126 | + assert.throws( | | 127 | + () => fs.statSync('does_not_exist'), | | 128 | + { code: 'ENOENT' }); | | 129 | + assert.strictEqual( | | 130 | + fs.statSync('does_not_exist', { throwIfNoEntry: false }), | | 131 | + undefined); | | 132 | +} | | 133 | + | | 134 | +{ | | 135 | + assert.throws( | | 136 | + () => fs.lstatSync('does_not_exist'), | | 137 | + { code: 'ENOENT' }); | | 138 | + assert.strictEqual( | | 139 | + fs.lstatSync('does_not_exist', { throwIfNoEntry: false }), | | 140 | + undefined); | | 141 | +} | | 142 | + | | 143 | +{ | | 144 | + assert.throws( | | 145 | + () => fs.fstatSync(9999), | | 146 | + { code: 'EBADF' }); | | 147 | + assert.throws( | | 148 | + () => fs.fstatSync(9999, { throwIfNoEntry: false }), | | 149 | + { code: 'EBADF' }); | | 150 | +} | | 151 | + | 125 | 152 | const runCallbackTest = (func, arg, done) => { | 126 | 153 | const startTime = process.hrtime.bigint(); | 127 | 154 | func(arg, { bigint: true }, common.mustCall((err, bigintStats) => { | |
|