2023-09-02 08:23:26 +00:00
|
|
|
import fs from 'fs'
|
|
|
|
import os from 'os'
|
|
|
|
import path from 'path'
|
|
|
|
import * as is from './is.mjs'
|
|
|
|
|
|
|
|
let IS_SUPPORT
|
|
|
|
let TEMP_DIR = os.tmpdir && os.tmpdir()
|
|
|
|
|| process.env.TMPDIR
|
|
|
|
|| process.env.TEMP
|
|
|
|
|| process.cwd()
|
|
|
|
|
|
|
|
function TempStack() {
|
|
|
|
this.stack = []
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TempStack.prototype.create = function(type, base) {
|
|
|
|
let name = path.join(base,
|
|
|
|
'node-watch-' + Math.random().toString(16).substr(2)
|
|
|
|
)
|
|
|
|
this.stack.push({ name: name, type: type })
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
TempStack.prototype.write = function(/* file */) {
|
|
|
|
for (let i = 0; i < arguments.length; ++i) {
|
|
|
|
fs.writeFileSync(arguments[i], ' ')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TempStack.prototype.mkdir = function(/* dirs */) {
|
|
|
|
for (let i = 0; i < arguments.length; ++i) {
|
|
|
|
fs.mkdirSync(arguments[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TempStack.prototype.cleanup = function(fn) {
|
|
|
|
try {
|
|
|
|
let temp
|
|
|
|
while ((temp = this.stack.pop())) {
|
|
|
|
let type = temp.type
|
|
|
|
let 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()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let pending = false
|
|
|
|
|
2023-09-28 09:33:43 +00:00
|
|
|
export default function hasNativeRecursive(fn, opts = {}) {
|
2023-09-02 08:23:26 +00:00
|
|
|
if (!is.func(fn)) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if (IS_SUPPORT !== undefined) {
|
|
|
|
return fn(IS_SUPPORT)
|
|
|
|
}
|
2023-09-28 09:33:43 +00:00
|
|
|
|
|
|
|
if (opts.quickCheck) {
|
|
|
|
return fn(IS_SUPPORT = (process.platform === 'darwin' || process.platform === 'win32'))
|
|
|
|
}
|
2023-09-02 08:23:26 +00:00
|
|
|
|
|
|
|
if (!pending) {
|
|
|
|
pending = true
|
|
|
|
}
|
|
|
|
// check again later
|
|
|
|
else {
|
|
|
|
return setTimeout(function() {
|
|
|
|
hasNativeRecursive(fn)
|
|
|
|
}, 300)
|
|
|
|
}
|
|
|
|
|
|
|
|
let stack = new TempStack()
|
|
|
|
let parent = stack.create('dir', TEMP_DIR)
|
|
|
|
let child = stack.create('dir', parent)
|
|
|
|
let file = stack.create('file', child)
|
|
|
|
|
|
|
|
stack.mkdir(parent, child)
|
|
|
|
|
|
|
|
let options = { recursive: true }
|
|
|
|
let 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
|
|
|
|
}
|
|
|
|
|
|
|
|
let 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)
|
|
|
|
}
|