massive update, probably broken
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / graceful-fs / graceful-fs.js
1 var fs = require('fs')
2 var polyfills = require('./polyfills.js')
3 var legacy = require('./legacy-streams.js')
4 var clone = require('./clone.js')
5
6 var util = require('util')
7
8 /* istanbul ignore next - node 0.x polyfill */
9 var gracefulQueue
10 var previousSymbol
11
12 /* istanbul ignore else - node 0.x polyfill */
13 if (typeof Symbol === 'function' && typeof Symbol.for === 'function') {
14   gracefulQueue = Symbol.for('graceful-fs.queue')
15   // This is used in testing by future versions
16   previousSymbol = Symbol.for('graceful-fs.previous')
17 } else {
18   gracefulQueue = '___graceful-fs.queue'
19   previousSymbol = '___graceful-fs.previous'
20 }
21
22 function noop () {}
23
24 function publishQueue(context, queue) {
25   Object.defineProperty(context, gracefulQueue, {
26     get: function() {
27       return queue
28     }
29   })
30 }
31
32 var debug = noop
33 if (util.debuglog)
34   debug = util.debuglog('gfs4')
35 else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || ''))
36   debug = function() {
37     var m = util.format.apply(util, arguments)
38     m = 'GFS4: ' + m.split(/\n/).join('\nGFS4: ')
39     console.error(m)
40   }
41
42 // Once time initialization
43 if (!fs[gracefulQueue]) {
44   // This queue can be shared by multiple loaded instances
45   var queue = global[gracefulQueue] || []
46   publishQueue(fs, queue)
47
48   // Patch fs.close/closeSync to shared queue version, because we need
49   // to retry() whenever a close happens *anywhere* in the program.
50   // This is essential when multiple graceful-fs instances are
51   // in play at the same time.
52   fs.close = (function (fs$close) {
53     function close (fd, cb) {
54       return fs$close.call(fs, fd, function (err) {
55         // This function uses the graceful-fs shared queue
56         if (!err) {
57           resetQueue()
58         }
59
60         if (typeof cb === 'function')
61           cb.apply(this, arguments)
62       })
63     }
64
65     Object.defineProperty(close, previousSymbol, {
66       value: fs$close
67     })
68     return close
69   })(fs.close)
70
71   fs.closeSync = (function (fs$closeSync) {
72     function closeSync (fd) {
73       // This function uses the graceful-fs shared queue
74       fs$closeSync.apply(fs, arguments)
75       resetQueue()
76     }
77
78     Object.defineProperty(closeSync, previousSymbol, {
79       value: fs$closeSync
80     })
81     return closeSync
82   })(fs.closeSync)
83
84   if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || '')) {
85     process.on('exit', function() {
86       debug(fs[gracefulQueue])
87       require('assert').equal(fs[gracefulQueue].length, 0)
88     })
89   }
90 }
91
92 if (!global[gracefulQueue]) {
93   publishQueue(global, fs[gracefulQueue]);
94 }
95
96 module.exports = patch(clone(fs))
97 if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) {
98     module.exports = patch(fs)
99     fs.__patched = true;
100 }
101
102 function patch (fs) {
103   // Everything that references the open() function needs to be in here
104   polyfills(fs)
105   fs.gracefulify = patch
106
107   fs.createReadStream = createReadStream
108   fs.createWriteStream = createWriteStream
109   var fs$readFile = fs.readFile
110   fs.readFile = readFile
111   function readFile (path, options, cb) {
112     if (typeof options === 'function')
113       cb = options, options = null
114
115     return go$readFile(path, options, cb)
116
117     function go$readFile (path, options, cb, startTime) {
118       return fs$readFile(path, options, function (err) {
119         if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
120           enqueue([go$readFile, [path, options, cb], err, startTime || Date.now(), Date.now()])
121         else {
122           if (typeof cb === 'function')
123             cb.apply(this, arguments)
124         }
125       })
126     }
127   }
128
129   var fs$writeFile = fs.writeFile
130   fs.writeFile = writeFile
131   function writeFile (path, data, options, cb) {
132     if (typeof options === 'function')
133       cb = options, options = null
134
135     return go$writeFile(path, data, options, cb)
136
137     function go$writeFile (path, data, options, cb, startTime) {
138       return fs$writeFile(path, data, options, function (err) {
139         if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
140           enqueue([go$writeFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()])
141         else {
142           if (typeof cb === 'function')
143             cb.apply(this, arguments)
144         }
145       })
146     }
147   }
148
149   var fs$appendFile = fs.appendFile
150   if (fs$appendFile)
151     fs.appendFile = appendFile
152   function appendFile (path, data, options, cb) {
153     if (typeof options === 'function')
154       cb = options, options = null
155
156     return go$appendFile(path, data, options, cb)
157
158     function go$appendFile (path, data, options, cb, startTime) {
159       return fs$appendFile(path, data, options, function (err) {
160         if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
161           enqueue([go$appendFile, [path, data, options, cb], err, startTime || Date.now(), Date.now()])
162         else {
163           if (typeof cb === 'function')
164             cb.apply(this, arguments)
165         }
166       })
167     }
168   }
169
170   var fs$copyFile = fs.copyFile
171   if (fs$copyFile)
172     fs.copyFile = copyFile
173   function copyFile (src, dest, flags, cb) {
174     if (typeof flags === 'function') {
175       cb = flags
176       flags = 0
177     }
178     return go$copyFile(src, dest, flags, cb)
179
180     function go$copyFile (src, dest, flags, cb, startTime) {
181       return fs$copyFile(src, dest, flags, function (err) {
182         if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
183           enqueue([go$copyFile, [src, dest, flags, cb], err, startTime || Date.now(), Date.now()])
184         else {
185           if (typeof cb === 'function')
186             cb.apply(this, arguments)
187         }
188       })
189     }
190   }
191
192   var fs$readdir = fs.readdir
193   fs.readdir = readdir
194   function readdir (path, options, cb) {
195     if (typeof options === 'function')
196       cb = options, options = null
197
198     return go$readdir(path, options, cb)
199
200     function go$readdir (path, options, cb, startTime) {
201       return fs$readdir(path, options, function (err, files) {
202         if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
203           enqueue([go$readdir, [path, options, cb], err, startTime || Date.now(), Date.now()])
204         else {
205           if (files && files.sort)
206             files.sort()
207
208           if (typeof cb === 'function')
209             cb.call(this, err, files)
210         }
211       })
212     }
213   }
214
215   if (process.version.substr(0, 4) === 'v0.8') {
216     var legStreams = legacy(fs)
217     ReadStream = legStreams.ReadStream
218     WriteStream = legStreams.WriteStream
219   }
220
221   var fs$ReadStream = fs.ReadStream
222   if (fs$ReadStream) {
223     ReadStream.prototype = Object.create(fs$ReadStream.prototype)
224     ReadStream.prototype.open = ReadStream$open
225   }
226
227   var fs$WriteStream = fs.WriteStream
228   if (fs$WriteStream) {
229     WriteStream.prototype = Object.create(fs$WriteStream.prototype)
230     WriteStream.prototype.open = WriteStream$open
231   }
232
233   Object.defineProperty(fs, 'ReadStream', {
234     get: function () {
235       return ReadStream
236     },
237     set: function (val) {
238       ReadStream = val
239     },
240     enumerable: true,
241     configurable: true
242   })
243   Object.defineProperty(fs, 'WriteStream', {
244     get: function () {
245       return WriteStream
246     },
247     set: function (val) {
248       WriteStream = val
249     },
250     enumerable: true,
251     configurable: true
252   })
253
254   // legacy names
255   var FileReadStream = ReadStream
256   Object.defineProperty(fs, 'FileReadStream', {
257     get: function () {
258       return FileReadStream
259     },
260     set: function (val) {
261       FileReadStream = val
262     },
263     enumerable: true,
264     configurable: true
265   })
266   var FileWriteStream = WriteStream
267   Object.defineProperty(fs, 'FileWriteStream', {
268     get: function () {
269       return FileWriteStream
270     },
271     set: function (val) {
272       FileWriteStream = val
273     },
274     enumerable: true,
275     configurable: true
276   })
277
278   function ReadStream (path, options) {
279     if (this instanceof ReadStream)
280       return fs$ReadStream.apply(this, arguments), this
281     else
282       return ReadStream.apply(Object.create(ReadStream.prototype), arguments)
283   }
284
285   function ReadStream$open () {
286     var that = this
287     open(that.path, that.flags, that.mode, function (err, fd) {
288       if (err) {
289         if (that.autoClose)
290           that.destroy()
291
292         that.emit('error', err)
293       } else {
294         that.fd = fd
295         that.emit('open', fd)
296         that.read()
297       }
298     })
299   }
300
301   function WriteStream (path, options) {
302     if (this instanceof WriteStream)
303       return fs$WriteStream.apply(this, arguments), this
304     else
305       return WriteStream.apply(Object.create(WriteStream.prototype), arguments)
306   }
307
308   function WriteStream$open () {
309     var that = this
310     open(that.path, that.flags, that.mode, function (err, fd) {
311       if (err) {
312         that.destroy()
313         that.emit('error', err)
314       } else {
315         that.fd = fd
316         that.emit('open', fd)
317       }
318     })
319   }
320
321   function createReadStream (path, options) {
322     return new fs.ReadStream(path, options)
323   }
324
325   function createWriteStream (path, options) {
326     return new fs.WriteStream(path, options)
327   }
328
329   var fs$open = fs.open
330   fs.open = open
331   function open (path, flags, mode, cb) {
332     if (typeof mode === 'function')
333       cb = mode, mode = null
334
335     return go$open(path, flags, mode, cb)
336
337     function go$open (path, flags, mode, cb, startTime) {
338       return fs$open(path, flags, mode, function (err, fd) {
339         if (err && (err.code === 'EMFILE' || err.code === 'ENFILE'))
340           enqueue([go$open, [path, flags, mode, cb], err, startTime || Date.now(), Date.now()])
341         else {
342           if (typeof cb === 'function')
343             cb.apply(this, arguments)
344         }
345       })
346     }
347   }
348
349   return fs
350 }
351
352 function enqueue (elem) {
353   debug('ENQUEUE', elem[0].name, elem[1])
354   fs[gracefulQueue].push(elem)
355   retry()
356 }
357
358 // keep track of the timeout between retry() calls
359 var retryTimer
360
361 // reset the startTime and lastTime to now
362 // this resets the start of the 60 second overall timeout as well as the
363 // delay between attempts so that we'll retry these jobs sooner
364 function resetQueue () {
365   var now = Date.now()
366   for (var i = 0; i < fs[gracefulQueue].length; ++i) {
367     // entries that are only a length of 2 are from an older version, don't
368     // bother modifying those since they'll be retried anyway.
369     if (fs[gracefulQueue][i].length > 2) {
370       fs[gracefulQueue][i][3] = now // startTime
371       fs[gracefulQueue][i][4] = now // lastTime
372     }
373   }
374   // call retry to make sure we're actively processing the queue
375   retry()
376 }
377
378 function retry () {
379   // clear the timer and remove it to help prevent unintended concurrency
380   clearTimeout(retryTimer)
381   retryTimer = undefined
382
383   if (fs[gracefulQueue].length === 0)
384     return
385
386   var elem = fs[gracefulQueue].shift()
387   var fn = elem[0]
388   var args = elem[1]
389   // these items may be unset if they were added by an older graceful-fs
390   var err = elem[2]
391   var startTime = elem[3]
392   var lastTime = elem[4]
393
394   // if we don't have a startTime we have no way of knowing if we've waited
395   // long enough, so go ahead and retry this item now
396   if (startTime === undefined) {
397     debug('RETRY', fn.name, args)
398     fn.apply(null, args)
399   } else if (Date.now() - startTime >= 60000) {
400     // it's been more than 60 seconds total, bail now
401     debug('TIMEOUT', fn.name, args)
402     var cb = args.pop()
403     if (typeof cb === 'function')
404       cb.call(null, err)
405   } else {
406     // the amount of time between the last attempt and right now
407     var sinceAttempt = Date.now() - lastTime
408     // the amount of time between when we first tried, and when we last tried
409     // rounded up to at least 1
410     var sinceStart = Math.max(lastTime - startTime, 1)
411     // backoff. wait longer than the total time we've been retrying, but only
412     // up to a maximum of 100ms
413     var desiredDelay = Math.min(sinceStart * 1.2, 100)
414     // it's been long enough since the last retry, do it again
415     if (sinceAttempt >= desiredDelay) {
416       debug('RETRY', fn.name, args)
417       fn.apply(null, args.concat([startTime]))
418     } else {
419       // if we can't do this job yet, push it to the end of the queue
420       // and let the next iteration check again
421       fs[gracefulQueue].push(elem)
422     }
423   }
424
425   // schedule our next run if one isn't already scheduled
426   if (retryTimer === undefined) {
427     retryTimer = setTimeout(retry, 0)
428   }
429 }