Skip to content

Commit

Permalink
Merge pull request #679 from jprichardson/fix-max-call-stack
Browse files Browse the repository at this point in the history
util/stat: fix max call stack size exceeded
  • Loading branch information
manidlou committed May 13, 2019
2 parents 23b0c0c + 72278dc commit 7c251d6
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 7 deletions.
80 changes: 80 additions & 0 deletions lib/util/__tests__/stat.test.js
@@ -0,0 +1,80 @@
'use strict'

const fs = require(process.cwd())
const os = require('os')
const path = require('path')
const assert = require('assert')
const semver = require('semver')
const stat = require('../stat.js')

const NODE_VERSION_WITH_BIGINT = '10.5.0'

/* global beforeEach, afterEach, describe, it */

describe('util/stat', () => {
let TEST_DIR

beforeEach(done => {
TEST_DIR = path.join(os.tmpdir(), 'fs-extra', 'util-stat')
fs.emptyDir(TEST_DIR, done)
})

afterEach(done => fs.remove(TEST_DIR, done))

describe('should use stats with bigint type for node versions >= 10.5.0 and number type for older versions', done => {
it('stat.checkPaths()', () => {
const nodeVersion = process.versions.node
const src = path.join(TEST_DIR, 'src')
const dest = path.join(TEST_DIR, 'dest')
fs.ensureFileSync(src)
fs.ensureFileSync(dest)
stat.checkPaths(src, dest, 'copy', (err, stats) => {
assert.ifError(err)
const { srcStat } = stats
if (semver.gte(nodeVersion, NODE_VERSION_WITH_BIGINT)) {
assert.strictEqual(typeof srcStat.ino, 'bigint')
} else {
assert.strictEqual(typeof srcStat.ino, 'number')
}
})
})

it('stat.checkPathsSync()', () => {
const nodeVersion = process.versions.node
const src = path.join(TEST_DIR, 'src')
const dest = path.join(TEST_DIR, 'dest')
fs.ensureFileSync(src)
fs.ensureFileSync(dest)
const { srcStat } = stat.checkPathsSync(src, dest, 'copy')
if (semver.gte(nodeVersion, NODE_VERSION_WITH_BIGINT)) {
assert.strictEqual(typeof srcStat.ino, 'bigint')
} else {
assert.strictEqual(typeof srcStat.ino, 'number')
}
})
})

describe('should stop at src or root path and not throw max call stack size error', done => {
it('stat.checkParentPaths()', () => {
const src = path.join(TEST_DIR, 'src')
let dest = path.join(TEST_DIR, 'dest')
fs.ensureFileSync(src)
fs.ensureFileSync(dest)
dest = path.basename(dest)
const srcStat = fs.statSync(src)
stat.checkParentPaths(src, srcStat, dest, 'copy', err => {
assert.ifError(err)
})
})

it('stat.checkParentPathsSync()', () => {
const src = path.join(TEST_DIR, 'src')
let dest = path.join(TEST_DIR, 'dest')
fs.ensureFileSync(src)
fs.ensureFileSync(dest)
dest = path.basename(dest)
const srcStat = fs.statSync(src)
stat.checkParentPathsSync(src, srcStat, dest, 'copy')
})
})
})
13 changes: 6 additions & 7 deletions lib/util/stat.js
Expand Up @@ -104,11 +104,9 @@ function checkPathsSync (src, dest, funcName) {
// checks the src and dest inodes. It starts from the deepest
// parent and stops once it reaches the src parent or the root path.
function checkParentPaths (src, srcStat, dest, funcName, cb) {
const destParent = path.dirname(dest)
if (destParent &&
(destParent === path.dirname(src) ||
destParent === path.parse(destParent).root)
) return cb()
const srcParent = path.resolve(path.dirname(src))
const destParent = path.resolve(path.dirname(dest))
if (destParent === srcParent || destParent === path.parse(destParent).root) return cb()
if (nodeSupportsBigInt()) {
fs.stat(destParent, { bigint: true }, (err, destStat) => {
if (err) {
Expand All @@ -135,8 +133,9 @@ function checkParentPaths (src, srcStat, dest, funcName, cb) {
}

function checkParentPathsSync (src, srcStat, dest, funcName) {
const destParent = path.dirname(dest)
if (destParent && (destParent === path.dirname(src) || destParent === path.parse(destParent).root)) return
const srcParent = path.resolve(path.dirname(src))
const destParent = path.resolve(path.dirname(dest))
if (destParent === srcParent || destParent === path.parse(destParent).root) return
let destStat
try {
if (nodeSupportsBigInt()) {
Expand Down

0 comments on commit 7c251d6

Please sign in to comment.