var fs = require('fs'); var os = require('os'); var path = require('path'); var is = require('./is'); var IS_SUPPORT; var TEMP_DIR = os.tmpdir && os.tmpdir() || process.env.TMPDIR || process.env.TEMP || process.cwd(); function TempStack() { this.stack = []; } TempStack.prototype = { create: function(type, base) { var name = path.join(base, 'node-watch-' + Math.random().toString(16).substr(2) ); this.stack.push({ name: name, type: type }); return name; }, write: function(/* file */) { for (var i = 0; i < arguments.length; ++i) { fs.writeFileSync(arguments[i], ' '); } }, mkdir: function(/* dirs */) { for (var i = 0; i < arguments.length; ++i) { fs.mkdirSync(arguments[i]); } }, cleanup: function(fn) { try { var temp; while ((temp = this.stack.pop())) { var type = temp.type; var name = temp.name; if (type === 'file' && is.file(name)) { fs.unlinkSync(name); } else if (type === 'dir' && is.directory(name)) { fs.rmdirSync(name); } } } finally { if (is.func(fn)) fn(); } } }; var pending = false; module.exports = function hasNativeRecursive(fn) { if (!is.func(fn)) { return false; } if (IS_SUPPORT !== undefined) { return fn(IS_SUPPORT); } if (!pending) { pending = true; } // check again later else { return setTimeout(function() { hasNativeRecursive(fn); }, 300); } var stack = new TempStack(); var parent = stack.create('dir', TEMP_DIR); var child = stack.create('dir', parent); var file = stack.create('file', child); stack.mkdir(parent, child); var options = { recursive: true }; var watcher; try { watcher = fs.watch(parent, options); } catch (e) { if (e.code == 'ERR_FEATURE_UNAVAILABLE_ON_PLATFORM') { return fn(IS_SUPPORT = false); } else { throw e; } } if (!watcher) { return false; } var timer = setTimeout(function() { watcher.close(); stack.cleanup(function() { fn(IS_SUPPORT = false); }); }, 200); watcher.on('change', function(evt, name) { if (path.basename(file) === path.basename(name)) { watcher.close(); clearTimeout(timer); stack.cleanup(function() { fn(IS_SUPPORT = true); }); } }); stack.write(file); }