overleaf/services/web/public/js/ace/test/asyncjs/async.js
2014-02-12 10:23:40 +00:00

529 lines
15 KiB
JavaScript
Executable file

/*!
* async.js
* Copyright(c) 2010 Fabian Jakobs <fabian.jakobs@web.de>
* MIT Licensed
*/
define(function(require, exports, module) {
var STOP = exports.STOP = {}
exports.Generator = function(source) {
if (typeof source == "function")
this.source = {
next: source
}
else
this.source = source
}
;(function() {
this.next = function(callback) {
this.source.next(callback)
}
this.map = function(mapper) {
if (!mapper)
return this
mapper = makeAsync(1, mapper)
var source = this.source
this.next = function(callback) {
source.next(function(err, value) {
if (err)
callback(err)
else {
mapper(value, function(err, value) {
if (err)
callback(err)
else
callback(null, value)
})
}
})
}
return new this.constructor(this)
}
this.filter = function(filter) {
if (!filter)
return this
filter = makeAsync(1, filter)
var source = this.source
this.next = function(callback) {
source.next(function handler(err, value) {
if (err)
callback(err)
else {
filter(value, function(err, takeIt) {
if (err)
callback(err)
else if (takeIt)
callback(null, value)
else
source.next(handler)
})
}
})
}
return new this.constructor(this)
}
this.slice = function(begin, end) {
var count = -1
if (!end || end < 0)
var end = Infinity
var source = this.source
this.next = function(callback) {
source.next(function handler(err, value) {
count++
if (err)
callback(err)
else if (count >= begin && count < end)
callback(null, value)
else if (count >= end)
callback(STOP)
else
source.next(handler)
})
}
return new this.constructor(this)
}
this.reduce = function(reduce, initialValue) {
reduce = makeAsync(3, reduce)
var index = 0
var done = false
var previousValue = initialValue
var source = this.source
this.next = function(callback) {
if (done)
return callback(STOP)
if (initialValue === undefined) {
source.next(function(err, currentValue) {
if (err)
return callback(err, previousValue)
previousValue = currentValue
reduceAll()
})
}
else
reduceAll()
function reduceAll() {
source.next(function handler(err, currentValue) {
if (err) {
done = true
if (err == STOP)
return callback(null, previousValue)
else
return(err)
}
reduce(previousValue, currentValue, index++, function(err, value) {
previousValue = value
source.next(handler)
})
})
}
}
return new this.constructor(this)
}
this.forEach =
this.each = function(fn) {
fn = makeAsync(1, fn)
var source = this.source
this.next = function(callback) {
source.next(function handler(err, value) {
if (err)
callback(err)
else {
fn(value, function(err) {
callback(err, value)
})
}
})
}
return new this.constructor(this)
}
this.some = function(condition) {
condition = makeAsync(1, condition)
var source = this.source
var done = false
this.next = function(callback) {
if (done)
return callback(STOP)
source.next(function handler(err, value) {
if (err)
return callback(err)
condition(value, function(err, result) {
if (err) {
done = true
if (err == STOP)
callback(null, false)
else
callback(err)
}
else if (result) {
done = true
callback(null, true)
}
else
source.next(handler)
})
})
}
return new this.constructor(this)
}
this.every = function(condition) {
condition = makeAsync(1, condition)
var source = this.source
var done = false
this.next = function(callback) {
if (done)
return callback(STOP)
source.next(function handler(err, value) {
if (err)
return callback(err)
condition(value, function(err, result) {
if (err) {
done = true
if (err == STOP)
callback(null, true)
else
callback(err)
}
else if (!result) {
done = true
callback(null, false)
}
else
source.next(handler)
})
})
}
return new this.constructor(this)
}
this.call = function(context) {
var source = this.source
return this.map(function(fn, next) {
fn = makeAsync(0, fn, context)
fn.call(context, function(err, value) {
next(err, value)
})
})
}
this.concat = function(generator) {
var generators = [this]
generators.push.apply(generators, arguments)
var index = 0
var source = generators[index++]
return new this.constructor(function(callback) {
source.next(function handler(err, value) {
if (err) {
if (err == STOP) {
source = generators[index++]
if (!source)
return callback(STOP)
else
return source.next(handler)
}
else
return callback(err)
}
else
return callback(null, value)
})
})
}
this.zip = function(generator) {
var generators = [this]
generators.push.apply(generators, arguments)
return new this.constructor(function(callback) {
exports.list(generators)
.map(function(gen, next) {
gen.next(next)
})
.toArray(callback)
})
}
this.expand = function(inserter, constructor) {
if (!inserter)
return this
var inserter = makeAsync(1, inserter)
var constructor = constructor || this.constructor
var source = this.source;
var spliced = null;
return new constructor(function next(callback) {
if (!spliced) {
source.next(function(err, value) {
if (err)
return callback(err)
inserter(value, function(err, toInsert) {
if (err)
return callback(err)
spliced = toInsert
next(callback)
})
})
}
else {
spliced.next(function(err, value) {
if (err == STOP) {
spliced = null
return next(callback)
}
else if (err)
return callback(err)
callback(err, value)
})
}
})
}
this.sort = function(compare) {
var self = this
var arrGen
this.next = function(callback) {
if (arrGen)
return arrGen.next(callback)
self.toArray(function(err, arr) {
if (err)
callback(err)
else {
arrGen = exports.list(arr.sort(compare))
arrGen.next(callback)
}
})
}
return new this.constructor(this)
}
this.join = function(separator) {
return this.$arrayOp(Array.prototype.join, separator !== undefined ? [separator] : null)
}
this.reverse = function() {
return this.$arrayOp(Array.prototype.reverse)
}
this.$arrayOp = function(arrayMethod, args) {
var self = this
var i = 0
this.next = function(callback) {
if (i++ > 0)
return callback(STOP)
self.toArray(function(err, arr) {
if (err)
callback(err, "")
else {
if (args)
callback(null, arrayMethod.apply(arr, args))
else
callback(null, arrayMethod.call(arr))
}
})
}
return new this.constructor(this)
}
this.end = function(breakOnError, callback) {
if (!callback) {
callback = arguments[0]
breakOnError = true
}
var source = this.source
var last
var lastError
source.next(function handler(err, value) {
if (err) {
if (err == STOP)
callback && callback(lastError, last)
else if (!breakOnError) {
lastError = err
source.next(handler)
}
else
callback && callback(err, value)
}
else {
last = value
source.next(handler)
}
})
}
this.toArray = function(breakOnError, callback) {
if (!callback) {
callback = arguments[0]
breakOnError = true
}
var values = []
var errors = []
var source = this.source
source.next(function handler(err, value) {
if (err) {
if (err == STOP) {
if (breakOnError)
return callback(null, values)
else {
errors.length = values.length
return callback(errors, values)
}
}
else {
if (breakOnError)
return callback(err)
else
errors[values.length] = err
}
}
values.push(value)
source.next(handler)
})
}
}).call(exports.Generator.prototype)
var makeAsync = exports.makeAsync = function(args, fn, context) {
if (fn.length > args)
return fn
else {
return function() {
var value
var next = arguments[args]
try {
value = fn.apply(context || this, arguments)
} catch(e) {
return next(e)
}
next(null, value)
}
}
}
exports.list = function(arr, construct) {
var construct = construct || exports.Generator
var i = 0
var len = arr.length
return new construct(function(callback) {
if (i < len)
callback(null, arr[i++])
else
callback(STOP)
})
}
exports.values = function(map, construct) {
var values = []
for (var key in map)
values.push(map[key])
return exports.list(values, construct)
}
exports.keys = function(map, construct) {
var keys = []
for (var key in map)
keys.push(key)
return exports.list(keys, construct)
}
/*
* range([start,] stop[, step]) -> generator of integers
*
* Return a generator containing an arithmetic progression of integers.
* range(i, j) returns [i, i+1, i+2, ..., j-1] start (!) defaults to 0.
* When step is given, it specifies the increment (or decrement).
*/
exports.range = function(start, stop, step, construct) {
var construct = construct || exports.Generator
start = start || 0
step = step || 1
if (stop === undefined || stop === null)
stop = step > 0 ? Infinity : -Infinity
var value = start
return new construct(function(callback) {
if (step > 0 && value >= stop || step < 0 && value <= stop)
callback(STOP)
else {
var current = value
value += step
callback(null, current)
}
})
}
exports.concat = function(first, varargs) {
if (arguments.length > 1)
return first.concat.apply(first, Array.prototype.slice.call(arguments, 1))
else
return first
}
exports.zip = function(first, varargs) {
if (arguments.length > 1)
return first.zip.apply(first, Array.prototype.slice.call(arguments, 1))
else
return first.map(function(item, next) {
next(null, [item])
})
}
exports.plugin = function(members, constructors) {
if (members) {
for (var key in members) {
exports.Generator.prototype[key] = members[key]
}
}
if (constructors) {
for (var key in constructors) {
exports[key] = constructors[key]
}
}
}
})