| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1372,6 +1372,102 @@ function mkdirSync(path, options) { | |||
| 1372 | 1372 | } | |
| 1373 | 1373 | } | |
| 1374 | 1374 | ||
| 1375 | + /* | ||
| 1376 | + * An recursive algorithm for reading the entire contents of the `basePath` directory. | ||
| 1377 | + * This function does not validate `basePath` as a directory. It is passed directly to | ||
| 1378 | + * `binding.readdir`. | ||
| 1379 | + * @param {string} basePath | ||
| 1380 | + * @param {{ encoding: string, withFileTypes: boolean }} options | ||
| 1381 | + * @param {( | ||
| 1382 | + * err?: Error, | ||
| 1383 | + * files?: string[] | Buffer[] | Dirent[] | ||
| 1384 | + * ) => any} callback | ||
| 1385 | + * @returns {void} | ||
| 1386 | + */ | ||
| 1387 | + function readdirRecursive(basePath, options, callback) { | ||
| 1388 | + const context = { | ||
| 1389 | + withFileTypes: Boolean(options.withFileTypes), | ||
| 1390 | + encoding: options.encoding, | ||
| 1391 | + basePath, | ||
| 1392 | + readdirResults: [], | ||
| 1393 | + pathsQueue: [basePath], | ||
| 1394 | + }; | ||
| 1395 | + | ||
| 1396 | + let i = 0; | ||
| 1397 | + | ||
| 1398 | + function read(path) { | ||
| 1399 | + const req = new FSReqCallback(); | ||
| 1400 | + req.oncomplete = (err, result) => { | ||
| 1401 | + if (err) { | ||
| 1402 | + callback(err); | ||
| 1403 | + return; | ||
| 1404 | + } | ||
| 1405 | + | ||
| 1406 | + if (result === undefined) { | ||
| 1407 | + callback(null, context.readdirResults); | ||
| 1408 | + return; | ||
| 1409 | + } | ||
| 1410 | + | ||
| 1411 | + processReaddirResult({ | ||
| 1412 | + result, | ||
| 1413 | + currentPath: path, | ||
| 1414 | + context, | ||
| 1415 | + }); | ||
| 1416 | + | ||
| 1417 | + if (i < context.pathsQueue.length) { | ||
| 1418 | + read(context.pathsQueue[i++]); | ||
| 1419 | + } else { | ||
| 1420 | + callback(null, context.readdirResults); | ||
| 1421 | + } | ||
| 1422 | + }; | ||
| 1423 | + | ||
| 1424 | + binding.readdir( | ||
| 1425 | + path, | ||
| 1426 | + context.encoding, | ||
| 1427 | + context.withFileTypes, | ||
| 1428 | + req, | ||
| 1429 | + ); | ||
| 1430 | + } | ||
| 1431 | + | ||
| 1432 | + read(context.pathsQueue[i++]); | ||
| 1433 | + } | ||
| 1434 | + | ||
| 1435 | + // Calling `readdir` with `withFileTypes=true`, the result is an array of arrays. | ||
| 1436 | + // The first array is the names, and the second array is the types. | ||
| 1437 | + // They are guaranteed to be the same length; hence, setting `length` to the length | ||
| 1438 | + // of the first array within the result. | ||
| 1439 | + const processReaddirResult = (args) => (args.context.withFileTypes ? handleDirents(args) : handleFilePaths(args)); | ||
| 1440 | + | ||
| 1441 | + function handleDirents({ result, currentPath, context }) { | ||
| 1442 | + const { 0: names, 1: types } = result; | ||
| 1443 | + const { length } = names; | ||
| 1444 | + | ||
| 1445 | + for (let i = 0; i < length; i++) { | ||
| 1446 | + // Avoid excluding symlinks, as they are not directories. | ||
| 1447 | + // Refs: https://github.com/nodejs/node/issues/52663 | ||
| 1448 | + const fullPath = pathModule.join(currentPath, names[i]); | ||
| 1449 | + const dirent = getDirent(currentPath, names[i], types[i]); | ||
| 1450 | + ArrayPrototypePush(context.readdirResults, dirent); | ||
| 1451 | + | ||
| 1452 | + if (dirent.isDirectory() || binding.internalModuleStat(binding, fullPath) === 1) { | ||
| 1453 | + ArrayPrototypePush(context.pathsQueue, fullPath); | ||
| 1454 | + } | ||
| 1455 | + } | ||
| 1456 | + } | ||
| 1457 | + | ||
| 1458 | + function handleFilePaths({ result, currentPath, context }) { | ||
| 1459 | + for (let i = 0; i < result.length; i++) { | ||
| 1460 | + const resultPath = pathModule.join(currentPath, result[i]); | ||
| 1461 | + const relativeResultPath = pathModule.relative(context.basePath, resultPath); | ||
| 1462 | + const stat = binding.internalModuleStat(binding, resultPath); | ||
| 1463 | + ArrayPrototypePush(context.readdirResults, relativeResultPath); | ||
| 1464 | + | ||
| 1465 | + if (stat === 1) { | ||
| 1466 | + ArrayPrototypePush(context.pathsQueue, resultPath); | ||
| 1467 | + } | ||
| 1468 | + } | ||
| 1469 | + } | ||
| 1470 | + | ||
| 1375 | 1471 | /** | |
| 1376 | 1472 | * An iterative algorithm for reading the entire contents of the `basePath` directory. | |
| 1377 | 1473 | * This function does not validate `basePath` as a directory. It is passed directly to | |
@@ -1381,58 +1477,37 @@ function mkdirSync(path, options) { | |||
| 1381 | 1477 | * @returns {string[] | Dirent[]} | |
| 1382 | 1478 | */ | |
| 1383 | 1479 | function readdirSyncRecursive(basePath, options) { | |
| 1384 | - const withFileTypes = Boolean(options.withFileTypes); | ||
| 1385 | - const encoding = options.encoding; | ||
| 1386 | - | ||
| 1387 | - const readdirResults = []; | ||
| 1388 | - const pathsQueue = [basePath]; | ||
| 1480 | + const context = { | ||
| 1481 | + withFileTypes: Boolean(options.withFileTypes), | ||
| 1482 | + encoding: options.encoding, | ||
| 1483 | + basePath, | ||
| 1484 | + readdirResults: [], | ||
| 1485 | + pathsQueue: [basePath], | ||
| 1486 | + }; | ||
| 1389 | 1487 | ||
| 1390 | 1488 | function read(path) { | |
| 1391 | 1489 | const readdirResult = binding.readdir( | |
| 1392 | 1490 | path, | |
| 1393 | - encoding, | ||
| 1394 | - withFileTypes, | ||
| 1491 | + context.encoding, | ||
| 1492 | + context.withFileTypes, | ||
| 1395 | 1493 | ); | |
| 1396 | 1494 | ||
| 1397 | 1495 | if (readdirResult === undefined) { | |
| 1398 | 1496 | return; | |
| 1399 | 1497 | } | |
| 1400 | 1498 | ||
| 1401 | - if (withFileTypes) { | ||
| 1402 | - // Calling `readdir` with `withFileTypes=true`, the result is an array of arrays. | ||
| 1403 | - // The first array is the names, and the second array is the types. | ||
| 1404 | - // They are guaranteed to be the same length; hence, setting `length` to the length | ||
| 1405 | - // of the first array within the result. | ||
| 1406 | - const length = readdirResult[0].length; | ||
| 1407 | - for (let i = 0; i < length; i++) { | ||
| 1408 | - // Avoid excluding symlinks, as they are not directories. | ||
| 1409 | - // Refs: https://github.com/nodejs/node/issues/52663 | ||
| 1410 | - const stat = binding.internalModuleStat(binding, pathModule.join(path, readdirResult[0][i])); | ||
| 1411 | - const dirent = getDirent(path, readdirResult[0][i], readdirResult[1][i]); | ||
| 1412 | - ArrayPrototypePush(readdirResults, dirent); | ||
| 1413 | - if (dirent.isDirectory() || stat === 1) { | ||
| 1414 | - ArrayPrototypePush(pathsQueue, pathModule.join(dirent.parentPath, dirent.name)); | ||
| 1415 | - } | ||
| 1416 | - } | ||
| 1417 | - } else { | ||
| 1418 | - for (let i = 0; i < readdirResult.length; i++) { | ||
| 1419 | - const resultPath = pathModule.join(path, readdirResult[i]); | ||
| 1420 | - const relativeResultPath = pathModule.relative(basePath, resultPath); | ||
| 1421 | - const stat = binding.internalModuleStat(binding, resultPath); | ||
| 1422 | - ArrayPrototypePush(readdirResults, relativeResultPath); | ||
| 1423 | - // 1 indicates directory | ||
| 1424 | - if (stat === 1) { | ||
| 1425 | - ArrayPrototypePush(pathsQueue, resultPath); | ||
| 1426 | - } | ||
| 1427 | - } | ||
| 1428 | - } | ||
| 1499 | + processReaddirResult({ | ||
| 1500 | + result: readdirResult, | ||
| 1501 | + currentPath: path, | ||
| 1502 | + context, | ||
| 1503 | + }); | ||
| 1429 | 1504 | } | |
| 1430 | 1505 | ||
| 1431 | - for (let i = 0; i < pathsQueue.length; i++) { | ||
| 1432 | - read(pathsQueue[i]); | ||
| 1506 | + for (let i = 0; i < context.pathsQueue.length; i++) { | ||
| 1507 | + read(context.pathsQueue[i]); | ||
| 1433 | 1508 | } | |
| 1434 | 1509 | ||
| 1435 | - return readdirResults; | ||
| 1510 | + return context.readdirResults; | ||
| 1436 | 1511 | } | |
| 1437 | 1512 | ||
| 1438 | 1513 | /** | |
@@ -1458,7 +1533,7 @@ function readdir(path, options, callback) { | |||
| 1458 | 1533 | } | |
| 1459 | 1534 | ||
| 1460 | 1535 | if (options.recursive) { | |
| 1461 | - callback(null, readdirSyncRecursive(path, options)); | ||
| 1536 | + readdirRecursive(path, options, callback); | ||
| 1462 | 1537 | return; | |
| 1463 | 1538 | } | |
| 1464 | 1539 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -289,6 +289,11 @@ const regularFile = __filename; | |||
| 289 | 289 | permission: 'FileSystemRead', | |
| 290 | 290 | resource: path.toNamespacedPath(blockedFolder), | |
| 291 | 291 | })); | |
| 292 | + fs.readdir(blockedFolder, { recursive: true }, common.expectsError({ | ||
| 293 | + code: 'ERR_ACCESS_DENIED', | ||
| 294 | + permission: 'FileSystemRead', | ||
| 295 | + resource: path.toNamespacedPath(blockedFolder), | ||
| 296 | + })); | ||
| 292 | 297 | assert.throws(() => { | |
| 293 | 298 | fs.readdirSync(blockedFolder); | |
| 294 | 299 | }, common.expectsError({ | |
| Back | FazBrowse Home | New Git URL |
0 commit comments