114 lines
2.3 KiB
JavaScript
114 lines
2.3 KiB
JavaScript
|
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
|
||
|
|
||
|
export default 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)
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
}
|