diff options
author | Florian Dold <florian.dold@gmail.com> | 2016-10-10 03:43:44 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2016-10-10 03:43:44 +0200 |
commit | abd94a7f5a50f43c797a11b53549ae48fff667c3 (patch) | |
tree | ab8ed457f65cdd72e13e0571d2975729428f1551 /node_modules/asap/raw.js | |
parent | a0247c6a3fd6a09a41a7e35a3441324c4dcb58be (diff) | |
download | wallet-core-abd94a7f5a50f43c797a11b53549ae48fff667c3.tar.xz |
add node_modules to address #4364
Diffstat (limited to 'node_modules/asap/raw.js')
-rw-r--r-- | node_modules/asap/raw.js | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/node_modules/asap/raw.js b/node_modules/asap/raw.js new file mode 100644 index 000000000..ae3b89231 --- /dev/null +++ b/node_modules/asap/raw.js @@ -0,0 +1,101 @@ +"use strict"; + +var domain; // The domain module is executed on demand +var hasSetImmediate = typeof setImmediate === "function"; + +// Use the fastest means possible to execute a task in its own turn, with +// priority over other events including network IO events in Node.js. +// +// An exception thrown by a task will permanently interrupt the processing of +// subsequent tasks. The higher level `asap` function ensures that if an +// exception is thrown by a task, that the task queue will continue flushing as +// soon as possible, but if you use `rawAsap` directly, you are responsible to +// either ensure that no exceptions are thrown from your task, or to manually +// call `rawAsap.requestFlush` if an exception is thrown. +module.exports = rawAsap; +function rawAsap(task) { + if (!queue.length) { + requestFlush(); + flushing = true; + } + // Avoids a function call + queue[queue.length] = task; +} + +var queue = []; +// Once a flush has been requested, no further calls to `requestFlush` are +// necessary until the next `flush` completes. +var flushing = false; +// The position of the next task to execute in the task queue. This is +// preserved between calls to `flush` so that it can be resumed if +// a task throws an exception. +var index = 0; +// If a task schedules additional tasks recursively, the task queue can grow +// unbounded. To prevent memory excaustion, the task queue will periodically +// truncate already-completed tasks. +var capacity = 1024; + +// The flush function processes all tasks that have been scheduled with +// `rawAsap` unless and until one of those tasks throws an exception. +// If a task throws an exception, `flush` ensures that its state will remain +// consistent and will resume where it left off when called again. +// However, `flush` does not make any arrangements to be called again if an +// exception is thrown. +function flush() { + while (index < queue.length) { + var currentIndex = index; + // Advance the index before calling the task. This ensures that we will + // begin flushing on the next task the task throws an error. + index = index + 1; + queue[currentIndex].call(); + // Prevent leaking memory for long chains of recursive calls to `asap`. + // If we call `asap` within tasks scheduled by `asap`, the queue will + // grow, but to avoid an O(n) walk for every task we execute, we don't + // shift tasks off the queue after they have been executed. + // Instead, we periodically shift 1024 tasks off the queue. + if (index > capacity) { + // Manually shift all values starting at the index back to the + // beginning of the queue. + for (var scan = 0, newLength = queue.length - index; scan < newLength; scan++) { + queue[scan] = queue[scan + index]; + } + queue.length -= index; + index = 0; + } + } + queue.length = 0; + index = 0; + flushing = false; +} + +rawAsap.requestFlush = requestFlush; +function requestFlush() { + // Ensure flushing is not bound to any domain. + // It is not sufficient to exit the domain, because domains exist on a stack. + // To execute code outside of any domain, the following dance is necessary. + var parentDomain = process.domain; + if (parentDomain) { + if (!domain) { + // Lazy execute the domain module. + // Only employed if the user elects to use domains. + domain = require("domain"); + } + domain.active = process.domain = null; + } + + // `setImmediate` is slower that `process.nextTick`, but `process.nextTick` + // cannot handle recursion. + // `requestFlush` will only be called recursively from `asap.js`, to resume + // flushing after an error is thrown into a domain. + // Conveniently, `setImmediate` was introduced in the same version + // `process.nextTick` started throwing recursion errors. + if (flushing && hasSetImmediate) { + setImmediate(flush); + } else { + process.nextTick(flush); + } + + if (parentDomain) { + domain.active = process.domain = parentDomain; + } +} |