Comparing version 0.1.0 to 0.1.1
@@ -0,1 +1,7 @@ | ||
0.1.1/2012-04-20 | ||
=== | ||
* Migrated all tests to use [it](http://github.com/doug-martin/it) | ||
* More Tests | ||
* Added functionality to comb.Promise/PromiseList (allowing promises as callbacks and node style callbacks for) | ||
0.1.0/2012-03-02 | ||
@@ -2,0 +8,0 @@ === |
@@ -12,3 +12,2 @@ var objectBase = require("./object"); | ||
require("./regexp"), | ||
require("./proxy"), | ||
require("./inflections")); |
@@ -11,3 +11,3 @@ var comb = exports; | ||
*/ | ||
var argsToArray = comb.argsToArray = function(args) { | ||
var argsToArray = comb.argsToArray = function (args) { | ||
return Array.prototype.slice.call(args); | ||
@@ -23,3 +23,3 @@ }; | ||
*/ | ||
comb.isBoolean = function(obj) { | ||
comb.isBoolean = function (obj) { | ||
var undef, type = typeof obj; | ||
@@ -35,3 +35,3 @@ return obj != undef && type == "boolean" || type == "Boolean"; | ||
*/ | ||
comb.isUndefined = function(obj) { | ||
comb.isUndefined = function (obj) { | ||
var undef; | ||
@@ -49,3 +49,3 @@ return obj !== null && obj === undef; | ||
*/ | ||
comb.isDefined = function(obj){ | ||
comb.isDefined = function (obj) { | ||
return !comb.isUndefined(obj); | ||
@@ -60,3 +60,3 @@ } | ||
*/ | ||
comb.isUndefinedOrNull = function(obj) { | ||
comb.isUndefinedOrNull = function (obj) { | ||
return comb.isUndefined(obj) || comb.isNull(obj); | ||
@@ -72,3 +72,3 @@ } | ||
*/ | ||
comb.isNull = function(obj) { | ||
comb.isNull = function (obj) { | ||
var undef; | ||
@@ -78,3 +78,15 @@ return obj !== undef && obj == null; | ||
var isInstance = function(obj, clazz) { | ||
/** | ||
* Determines if obj is an Arguments object; | ||
* | ||
* @param {Anything} obj the thing to test if it is null | ||
* | ||
* @returns {Boolean} true if it is an Arguments Object false otherwise | ||
*/ | ||
comb.isArguments = function (object) { | ||
return !comb.isUndefinedOrNull(object) && Object.prototype.toString.call(object) == '[object Arguments]'; | ||
}; | ||
var isInstance = function (obj, clazz) { | ||
if (typeof clazz == "function") { | ||
@@ -95,6 +107,43 @@ return obj instanceof clazz; | ||
*/ | ||
comb.isInstanceOf = function(obj, clazz) { | ||
return argsToArray(arguments).slice(1).some(function(c) { | ||
comb.isInstanceOf = function (obj, clazz) { | ||
return argsToArray(arguments).slice(1).some(function (c) { | ||
return isInstance(obj, c); | ||
}); | ||
}; | ||
}; | ||
(function () { | ||
var listeners = []; | ||
var setup = false; | ||
var setupListener = function () { | ||
if (!setup) { | ||
var orig = process.emit; | ||
process.emit = function (event) { | ||
try { | ||
if (event === 'exit') { | ||
listeners.forEach(function (cb) { | ||
cb(); | ||
}); | ||
} | ||
} finally { | ||
orig.apply(this, arguments); | ||
} | ||
}; | ||
setup = true; | ||
} | ||
}; | ||
/** | ||
* Adds listeners to process.exit with out having to change setMaxListeners useful if you | ||
* are writing a library and do not want to change core setting. | ||
* | ||
* @param {Funciton} cb funciton to call when process is exiting | ||
*/ | ||
comb.listenForExit = function (cb) { | ||
setupListener(); | ||
listeners.push(cb); | ||
}; | ||
})(); | ||
@@ -1,4 +0,99 @@ | ||
var comb = exports; | ||
var comb = exports, | ||
misc = require("./misc.js"), | ||
isUndefinedOrNull = misc.isUndefined, | ||
isArguments = misc.isArguments, | ||
pSlice = Array.prototype.slice; | ||
var merge = function(target, source) { | ||
//taken from node js assert.js | ||
//https://github.com/joyent/node/blob/master/lib/assert.js | ||
var _deepEqual = function (actual, expected) { | ||
// 7.1. All identical values are equivalent, as determined by ===. | ||
if (actual === expected) { | ||
return true; | ||
} else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { | ||
if (actual.length != expected.length) return false; | ||
for (var i = 0; i < actual.length; i++) { | ||
if (actual[i] !== expected[i]) return false; | ||
} | ||
return true; | ||
// 7.2. If the expected value is a Date object, the actual value is | ||
// equivalent if it is also a Date object that refers to the same time. | ||
} else if (actual instanceof Date && expected instanceof Date) { | ||
return actual.getTime() === expected.getTime(); | ||
// 7.3 If the expected value is a RegExp object, the actual value is | ||
// equivalent if it is also a RegExp object with the same source and | ||
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). | ||
} else if (actual instanceof RegExp && expected instanceof RegExp) { | ||
return actual.source === expected.source && | ||
actual.global === expected.global && | ||
actual.multiline === expected.multiline && | ||
actual.lastIndex === expected.lastIndex && | ||
actual.ignoreCase === expected.ignoreCase; | ||
// 7.4. Other pairs that do not both pass typeof value == 'object', | ||
// equivalence is determined by ==. | ||
} else if (typeof actual != 'object' && typeof expected != 'object') { | ||
return actual == expected; | ||
// 7.5 For all other Object pairs, including Array objects, equivalence is | ||
// determined by having the same number of owned properties (as verified | ||
// with Object.prototype.hasOwnProperty.call), the same set of keys | ||
// (although not necessarily the same order), equivalent values for every | ||
// corresponding key, and an identical 'prototype' property. Note: this | ||
// accounts for both named and indexed properties on Arrays. | ||
} else { | ||
return objEquiv(actual, expected); | ||
} | ||
}; | ||
var objEquiv = function (a, b) { | ||
if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) | ||
return false; | ||
// an identical 'prototype' property. | ||
if (a.prototype !== b.prototype) return false; | ||
//~~~I've managed to break Object.keys through screwy arguments passing. | ||
// Converting to array solves the problem. | ||
if (isArguments(a)) { | ||
if (!isArguments(b)) { | ||
return false; | ||
} | ||
a = pSlice.call(a); | ||
b = pSlice.call(b); | ||
return _deepEqual(a, b); | ||
} | ||
try { | ||
var ka = Object.keys(a), | ||
kb = Object.keys(b), | ||
key, i; | ||
} catch (e) {//happens when one is a string literal and the other isn't | ||
return false; | ||
} | ||
// having the same number of owned properties (keys incorporates | ||
// hasOwnProperty) | ||
if (ka.length != kb.length) | ||
return false; | ||
//the same set of keys (although not necessarily the same order), | ||
ka.sort(); | ||
kb.sort(); | ||
//~~~cheap key test | ||
for (i = ka.length - 1; i >= 0; i--) { | ||
if (ka[i] != kb[i]) | ||
return false; | ||
} | ||
//equivalent values for every corresponding key, and | ||
//~~~possibly expensive deep test | ||
for (i = ka.length - 1; i >= 0; i--) { | ||
key = ka[i]; | ||
if (!_deepEqual(a[key], b[key])) return false; | ||
} | ||
return true; | ||
} | ||
var merge = function (target, source) { | ||
var name, s; | ||
@@ -14,2 +109,19 @@ for (name in source) { | ||
var deepMerge = function (target, source) { | ||
var name, s, t; | ||
for (name in source) { | ||
s = source[name], t = target[name]; | ||
if (!_deepEqual(t, s)) { | ||
if (comb.isHash(t) && comb.isHash(s)) { | ||
target[name] = deepMerge(t, s); | ||
} else if (comb.isHash(s)) { | ||
target[name] = deepMerge({}, s); | ||
} else { | ||
target[name] = s; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
/** | ||
@@ -38,3 +150,3 @@ * Merges objects together | ||
*/ | ||
comb.merge = function(obj, props) { | ||
comb.merge = function (obj, props) { | ||
if (!obj) { | ||
@@ -50,2 +162,31 @@ obj = {}; | ||
/** | ||
* Merges objects together only overriding properties that are different. | ||
* NOTE: this function takes a variable number of objects to merge | ||
* | ||
* @example | ||
* | ||
* var myObj = {my : {cool : {property1 : 1, property2 : 2}}}; | ||
* comb.deepMerge(myObj, {my : {cool : {property3 : 3}}}); | ||
* | ||
* myObj.my.cool.property1 => 1 | ||
* myObj.my.cool.property2 => 2 | ||
* myObj.my.cool.property3 => 3 | ||
* | ||
* | ||
* @param {Object} obj the object to merge into | ||
* @param {Object} props variable number of objects to merge into the obj | ||
* | ||
* @returns {Object} the merged object | ||
*/ | ||
comb.deepMerge = function (obj, props) { | ||
if (!obj) { | ||
obj = {}; | ||
} | ||
for (var i = 1, l = arguments.length; i < l; i++) { | ||
deepMerge(obj, arguments[i]); | ||
} | ||
return obj; // Object | ||
}; | ||
/** | ||
* Extends the prototype of an object if it exists otherwise it extends the object. | ||
@@ -81,3 +222,3 @@ * | ||
*/ | ||
comb.extend = function(parent, extend){ | ||
comb.extend = function (parent, extend) { | ||
var proto = parent.prototype || parent; | ||
@@ -94,3 +235,3 @@ return exports.merge(proto, extend); | ||
*/ | ||
comb.isObject = function(obj) { | ||
comb.isObject = function (obj) { | ||
var undef; | ||
@@ -119,3 +260,3 @@ return obj != null && obj != undef && typeof obj == "object"; | ||
*/ | ||
comb.isHash = function(obj){ | ||
comb.isHash = function (obj) { | ||
var ret = comb.isObject(obj); | ||
@@ -131,8 +272,9 @@ return ret && obj.constructor === Object; | ||
* comb.isEmpty({}) => true | ||
* comg.isEmpty({a : 1}) => false | ||
* comb.isEmpty({a : 1}) => false | ||
* | ||
* @param object the object to test | ||
* @returns {Boolean} true if the object is empty; | ||
*/ | ||
comb.isEmpty = function(object) { | ||
if (object) { | ||
comb.isEmpty = function (object) { | ||
if (comb.isObject(object)) { | ||
for (var i in object) { | ||
@@ -145,2 +287,22 @@ if (object.hasOwnProperty(i)) { | ||
return true; | ||
}; | ||
/** | ||
* Determines if an two things are deep equal. | ||
* | ||
* @example | ||
* | ||
* comb.deepEqual({a : 1, b : 2}, {a : 1, b : 2}) => true | ||
* comb.deepEqual({a : 1}, {a : 1, b : 2}) => false | ||
* | ||
* @param o1 the first thing to compare | ||
* @param o3 the second thing to compare | ||
* @return {Boolean} | ||
*/ | ||
comb.deepEqual = function (o1, o2) { | ||
return _deepEqual(o1, o2); | ||
} | ||
var define = require("../define").define, | ||
Tree = require("./Tree"), | ||
base = require("../base"), | ||
multiply = base.string.multiply; | ||
Tree = require("./Tree"), | ||
base = require("../base"), | ||
multiply = base.string.multiply; | ||
@@ -9,14 +9,14 @@ var RED = "red", BLACK = "black"; | ||
var nil = {level : 0, data : null}; | ||
var nil = {level:0, data:null}; | ||
var makeNode = function(data, level) { | ||
var makeNode = function (data, level) { | ||
return { | ||
data : data, | ||
level : level, | ||
left : nil, | ||
right : nil | ||
data:data, | ||
level:level, | ||
left:nil, | ||
right:nil | ||
} | ||
}; | ||
var skew = function(root) { | ||
var skew = function (root) { | ||
if (root.level != 0 && root.left.level == root.level) { | ||
@@ -31,3 +31,3 @@ var save = root.left; | ||
var split = function(root) { | ||
var split = function (root) { | ||
if (root.level != 0 && root.right.right.level == root.level) { | ||
@@ -43,3 +43,3 @@ var save = root.right; | ||
var insert = function(root, data, compare) { | ||
var insert = function (root, data, compare) { | ||
if (root == nil) { | ||
@@ -57,3 +57,3 @@ root = makeNode(data, 1); | ||
var remove = function(root, data, compare) { | ||
var remove = function (root, data, compare) { | ||
var rLeft, rRight; | ||
@@ -63,3 +63,3 @@ if (root != nil) { | ||
if (cmp == 0) { | ||
rLeft = root.left,rRight = root.right; | ||
rLeft = root.left, rRight = root.right; | ||
if (rLeft != nil && rRight != nil) { | ||
@@ -111,59 +111,59 @@ var heir = rLeft; | ||
instance : { | ||
/**@lends comb.collections.AnderssonTree.prototype*/ | ||
instance:{ | ||
/**@lends comb.collections.AnderssonTree.prototype*/ | ||
isEmpty : function() { | ||
return this.__root == nil || this._super(arguments); | ||
}, | ||
isEmpty:function () { | ||
return this.__root == nil || this._super(arguments); | ||
}, | ||
insert : function(data) { | ||
if (this.__root == null) this.__root = nil; | ||
this.__root = insert(this.__root, data, this.compare); | ||
}, | ||
insert:function (data) { | ||
if (this.__root == null) this.__root = nil; | ||
this.__root = insert(this.__root, data, this.compare); | ||
}, | ||
remove : function(data) { | ||
this.__root = remove(this.__root, data, this.compare); | ||
}, | ||
remove:function (data) { | ||
this.__root = remove(this.__root, data, this.compare); | ||
}, | ||
traverseWithCondition : function(node, order, callback) { | ||
var cont = true; | ||
if (node != nil) { | ||
return this._super(arguments); | ||
} | ||
return cont; | ||
}, | ||
traverseWithCondition:function (node, order, callback) { | ||
var cont = true; | ||
if (node != nil) { | ||
return this._super(arguments); | ||
} | ||
return cont; | ||
}, | ||
traverse : function(node, order, callback) { | ||
if (node != nil) { | ||
this._super(arguments); | ||
} | ||
}, | ||
traverse:function (node, order, callback) { | ||
if (node != nil) { | ||
this._super(arguments); | ||
} | ||
}, | ||
contains : function(value) { | ||
if (this.__root != nil) { | ||
return this._super(arguments); | ||
} | ||
return false; | ||
}, | ||
contains:function (value) { | ||
if (this.__root != nil) { | ||
return this._super(arguments); | ||
} | ||
return false; | ||
}, | ||
__printNode : function(node, level) { | ||
var str = []; | ||
if (node.data == null || node == null) { | ||
str.push(multiply('\t', level)); | ||
str.push("~"); | ||
console.log(str.join("")); | ||
} else { | ||
this.__printNode(node.right, level + 1); | ||
str.push(multiply('\t', level)); | ||
str.push(node.data + ":" + node.level + "\n"); | ||
console.log(str.join("")); | ||
this.__printNode(node.left, level + 1); | ||
} | ||
} | ||
__printNode:function (node, level) { | ||
var str = []; | ||
if (node.data == null || node == null) { | ||
str.push(multiply('\t', level)); | ||
str.push("~"); | ||
console.log(str.join("")); | ||
} else { | ||
this.__printNode(node.right, level + 1); | ||
str.push(multiply('\t', level)); | ||
str.push(node.data + ":" + node.level + "\n"); | ||
console.log(str.join("")); | ||
this.__printNode(node.left, level + 1); | ||
} | ||
} | ||
}); | ||
} | ||
}); | ||
@@ -13,2 +13,4 @@ var define = require("../define").define, | ||
return -1; | ||
}else if(!b){ | ||
return 1; | ||
} | ||
@@ -252,5 +254,3 @@ return ret; | ||
var args = [fun]; | ||
if (!base.isUndefined(accumulator) && !base.isNull(accumulator)) { | ||
args.push(accumulator); | ||
} | ||
!base.isUndefinedOrNull(accumulator) && args.push(accumulator) | ||
return arr.reduce.apply(arr, args); | ||
@@ -271,5 +271,3 @@ }, | ||
var args = [fun]; | ||
if (!base.isUndefined(accumulator) && !base.isNull(accumulator)) { | ||
args.push(accumulator); | ||
} | ||
!base.isUndefinedOrNull(accumulator) && args.push(accumulator) | ||
return arr.reduceRight.apply(arr, args); | ||
@@ -276,0 +274,0 @@ }, |
@@ -114,3 +114,6 @@ /** | ||
var mixinSupers = function (sup, arr, bases) { | ||
var meta = sup.__meta; | ||
!meta && (meta = (sup.__meta = {})); | ||
var unique = sup.__meta.unique; | ||
!unique && (meta.unique = "define" + ++classCounter); | ||
//check it we already have this super mixed into our prototype chain | ||
@@ -117,0 +120,0 @@ //if true then we have already looped their supers! |
@@ -13,5 +13,10 @@ var base = require("./base"); | ||
comb.definePlugin = function (obj) { | ||
if (comb.isHash(obj)) { | ||
comb.deepMerge(comb, obj); | ||
} | ||
return comb; | ||
}; | ||
var define = require("../../define.js").define, | ||
base = require("../../base"), | ||
promise = require("../../promise"), | ||
string = base.string, | ||
Promise = promise.Promise, | ||
PromiseList = promise.PromiseList, | ||
style = string.style, | ||
format = string.format, | ||
Appender = require("./appender"), | ||
Level = require("../level"), | ||
fs = require("fs"); | ||
base = require("../../base"), | ||
promise = require("../../promise"), | ||
string = base.string, | ||
Promise = promise.Promise, | ||
PromiseList = promise.PromiseList, | ||
style = string.style, | ||
format = string.format, | ||
Appender = require("./appender"), | ||
Level = require("../level"), | ||
fs = require("fs"); | ||
/** | ||
@@ -49,34 +51,37 @@ * @class Appends messages to a file. | ||
exports = module.exports = define(Appender, { | ||
instance : { | ||
instance:{ | ||
constructor : function(options) { | ||
options = options || {}; | ||
!options.name && (options.name = "fileAppender"); | ||
this.__file = options.file || "./log.log"; | ||
this.__encoding = options.encoding || "utf8"; | ||
this.__overwrite = options.overwrite || false; | ||
this.__writeStream = options.writeStream || fs.createWriteStream(this.__file, { flags: this.__overwrite ? "w" : 'a', encoding: this.__encoding}); | ||
this._super([options]); | ||
this.__pattern += "\n"; | ||
process.addListener("exit", base.hitch(this, "__onExit")); | ||
}, | ||
constructor:function (options) { | ||
options = options || {}; | ||
!options.name && (options.name = "fileAppender"); | ||
this.__file = options.file || "./log.log"; | ||
this.__encoding = options.encoding || "utf8"; | ||
this.__overwrite = options.overwrite || false; | ||
this.__writeStream = options.writeStream || fs.createWriteStream(this.__file, { flags:this.__overwrite ? "w" : 'a', encoding:this.__encoding}); | ||
this._super([options]); | ||
this.__pattern += "\n"; | ||
process.setMaxListeners(-1) | ||
base.listenForExit(base.hitch(this, "__onExit")); | ||
}, | ||
__onExit : function() { | ||
var ret = new Promise(); | ||
var ws = this.__writeStream; | ||
this.__writeStream = null; | ||
ws.on("close", base.hitch(ret, "callback")); | ||
ws.destroySoon(); | ||
return ret; | ||
}, | ||
append : function(event) { | ||
var ws = this.__writeStream; | ||
if (this._canAppend(event) && ws && ws.writable) { | ||
var message = format(this.__pattern, event); | ||
var level = event.level; | ||
ws.write(message); | ||
} | ||
} | ||
} | ||
}); | ||
__onExit:function () { | ||
var ret = new Promise(); | ||
var ws = this.__writeStream; | ||
this.__writeStream = null; | ||
ws.on("close", base.hitch(ret, "callback")); | ||
ws.destroySoon(); | ||
return ret; | ||
}, | ||
append:function (event) { | ||
var ws = this.__writeStream; | ||
if (this._canAppend(event) && ws && ws.writable) { | ||
var message = format(this.__pattern, event); | ||
var level = event.level; | ||
ws.write(message); | ||
} | ||
} | ||
} | ||
}); |
@@ -66,3 +66,3 @@ var define = require("../../define.js").define, | ||
this.__pattern = '{"timestamp" : "{timeStamp}", "level" : "{levelName}", "name" : "{name}", "message" : "{message}"}'; | ||
process.addListener("exit", base.hitch(this, "__onExit")); | ||
base.listenForExit(base.hitch(this, "__onExit")); | ||
}, | ||
@@ -69,0 +69,0 @@ |
@@ -88,3 +88,3 @@ var define = require("../../define.js").define, | ||
this.__inRollover = false; | ||
this._super(arguments, [options]); | ||
this._super([options]); | ||
fs.watchFile(this.__file, hitch(this, "__checkFile")); | ||
@@ -91,0 +91,0 @@ fs.stat(this.__file, hitch(this, function(err, stat) { |
@@ -7,7 +7,13 @@ var define = require("../define.js").define, base = require("../base"), fs = require('fs'); | ||
//if (!isProcessUnCaaughtEception) { | ||
isProcessUnCaaughtEception = true; | ||
var rootLogger = Logger.getRootLogger(); | ||
var rootLogger = Logger.getRootLogger(); | ||
if (!isProcessUnCaaughtEception) { | ||
process.on("uncaughtException", function (err) { | ||
rootLogger.error(err); | ||
if (rootLogger.appenders.length) { | ||
rootLogger.error(err); | ||
} else { | ||
console.error(err.stack); | ||
} | ||
}); | ||
isProcessUnCaaughtEception = true; | ||
} | ||
//} | ||
@@ -14,0 +20,0 @@ }; |
@@ -5,4 +5,3 @@ var comb = exports; | ||
Broadcaster : require("./Broadcaster"), | ||
Middleware : require("./Middleware"), | ||
MethodMissing : require("./MethodMissing") | ||
Middleware : require("./Middleware") | ||
}; |
var hitch = require("./base/functions").hitch, | ||
define = require("./define").define, base = require("./base"); | ||
define = require("./define").define, base = require("./base"); | ||
@@ -58,4 +58,4 @@ var Promise = define(null, { | ||
var cbs = this.__error ? this.__errorCbs : this.__cbs, | ||
len = cbs.length, i, | ||
results = this.__error || this.__results; | ||
len = cbs.length, i, | ||
results = this.__error || this.__results; | ||
for (i = 0; i < len; i++) { | ||
@@ -77,6 +77,11 @@ this.__callNextTick(cbs[i], results); | ||
* | ||
* @param {Function} cb the function to callback when the promise is resolved | ||
* @param {Function|comb.Promise} cb the function or promise to callback when the promise is resolved. | ||
* | ||
* @return {comb.Promise} this promise for chaining | ||
*/ | ||
addCallback:function (cb) { | ||
if (cb) { | ||
if (exports.isPromiseLike(cb)) { | ||
cb = hitch(cb, "callback"); | ||
} | ||
if (this.__fired && this.__results) { | ||
@@ -95,6 +100,11 @@ cb.apply(this, this.__results); | ||
* | ||
* @param {Function} cb the function to callback when the promise errors | ||
* @param {Function|comb.Promise} cb the function or promise to callback when the promise errors | ||
* | ||
* @return {comb.Promise} this promise for chaining | ||
*/ | ||
addErrback:function (cb) { | ||
if (cb) { | ||
if (exports.isPromiseLike(cb)) { | ||
cb = hitch(cb, "errback"); | ||
} | ||
if (this.__fired && this.__error) { | ||
@@ -106,7 +116,22 @@ cb.apply(this, this.__error); | ||
} | ||
return this; | ||
}, | ||
/** | ||
* | ||
* Adds a callback or promise to be resolved for both success | ||
* and error. | ||
* | ||
* @param {Function|comb.Promise} cb callback or promise to be resolved for both success | ||
* and error. | ||
* @return {comb.Promise} this promise for chaining | ||
*/ | ||
both:function (cb) { | ||
this.addCallback(cb); | ||
this.addErrback(cb); | ||
if (exports.isPromiseLike(cb)) { | ||
this.addErrback(hitch(cb, "callback")); | ||
} else { | ||
this.addErrback(cb); | ||
} | ||
return this; | ||
@@ -118,10 +143,10 @@ }, | ||
* | ||
* @param anything variable number of results to pass back to listeners of the promise | ||
* @param {*} args variable number of results to pass back to listeners of the promise | ||
*/ | ||
callback:function () { | ||
var args = base.argsToArray(arguments); | ||
callback:function (args) { | ||
args = base.argsToArray(arguments); | ||
if (this.__fired) { | ||
throw new Error("Already fired!"); | ||
} | ||
this.__results = Array.prototype.slice.call(arguments); | ||
this.__results = args; | ||
this.__resolve(); | ||
@@ -135,9 +160,9 @@ return this; | ||
* | ||
* @param anything variable number of errors to pass back to listeners of the promise | ||
* @param {*} args number of errors to pass back to listeners of the promise | ||
*/ | ||
errback:function (i) { | ||
errback:function (args) { | ||
if (this.__fired) { | ||
throw i || new Error("Already fired"); | ||
throw args || new Error("Already fired"); | ||
} | ||
this.__error = Array.prototype.slice.call(arguments); | ||
this.__error = base.argsToArray(arguments); | ||
this.__resolve(); | ||
@@ -152,6 +177,13 @@ return this; | ||
* @param {Function} [errback=null] function to call if the promise errors | ||
* | ||
* @return {comb.Promise} this promise for chaining | ||
*/ | ||
then:function (callback, errback) { | ||
this.addCallback(callback); | ||
this.addErrback(errback); | ||
if (exports.isPromiseLike(callback)) { | ||
this.addCallback(callback); | ||
this.addErrback(callback); | ||
} else { | ||
this.addCallback(callback); | ||
this.addErrback(errback); | ||
} | ||
return this; | ||
@@ -161,5 +193,39 @@ }, | ||
/** | ||
* Call this function as a classic node callback where the first argument | ||
* will be an error, or null if no error occured. The other arugments will | ||
* be the result from the promise. | ||
* | ||
* @example | ||
* | ||
* promise.classic(function(err, res){ | ||
* if(err){ | ||
* console.log(err); | ||
* }else{ | ||
* console.log(res); | ||
* } | ||
* }); | ||
* | ||
* @param cb callback where the first argument | ||
* will be an error, or null if no error occured. The other arugments will | ||
* be the result from the promise. | ||
* @return {comb.Promise} the promise to chain | ||
*/ | ||
classic:function (cb) { | ||
if ("function" === typeof cb) { | ||
this.addErrback(function (err) { | ||
cb(err); | ||
}); | ||
this.addCallback(function () { | ||
cb.apply(this, [null].concat(base.argsToArray(arguments))); | ||
}); | ||
} | ||
return this; | ||
}, | ||
/** | ||
* Call to chaining of promises | ||
* @param callback method to call that returns a promise to call after this one completes. | ||
* @param errback method to call if this promise errors. | ||
* | ||
* @return {comb.Promise} A new that wraps the promise for chaining | ||
*/ | ||
@@ -169,3 +235,3 @@ chain:function (callback, errback) { | ||
this.addCallback(function (results) { | ||
callback.call(this, results).then(hitch(promise, "callback"), hitch(promise, "errback")); | ||
callback.call(this, results).then(promise); | ||
}); | ||
@@ -187,3 +253,3 @@ this.addErrback(errback); | ||
this.addErrback(function (results) { | ||
callback.call(this, results).then(hitch(p, "callback"), hitch(p, "errback")); | ||
callback.call(this, results).then(p); | ||
}); | ||
@@ -287,4 +353,4 @@ return p; | ||
var cbs = this.__errors.length ? this.__errorCbs : this.__cbs, | ||
len = cbs.length, i, | ||
results = this.__errors.length ? this.__errors : this.__results; | ||
len = cbs.length, i, | ||
results = this.__errors.length ? this.__errors : this.__results; | ||
for (i = 0; i < len; i++) { | ||
@@ -304,2 +370,5 @@ this.__callNextTick(cbs[i], results); | ||
if (cb) { | ||
if (exports.isPromiseLike(cb)) { | ||
cb = hitch(cb, "callback"); | ||
} | ||
if (this.__fired && !this.__errors.length) { | ||
@@ -316,2 +385,5 @@ cb.call(this, this.__results); | ||
if (cb) { | ||
if (exports.isPromiseLike(cb)) { | ||
cb = hitch(cb, "errback"); | ||
} | ||
if (this.__fired && this.__errors.length) { | ||
@@ -368,150 +440,4 @@ cb.call(this, this.__errors); | ||
var createHandler = function (obj, stack) { | ||
return { | ||
delete:function (name) { | ||
stack.push([obj, ["__delete__", [name]], [], obj]); | ||
return true; | ||
}, | ||
get:function (receiver, name) { | ||
var newStack = []; | ||
var handle = getHandler({}, newStack); | ||
var wrapper = base.createFunctionWrapper(handle, function (m) { | ||
var i = stack[stack.indexOf(item)]; | ||
var args = base.argsToArray(arguments); | ||
i[1].push(name === "__apply__" || name === "__new__" ? base.array.flatten(args) : args); | ||
return wrapper; | ||
}); | ||
var item = [obj, [name], newStack, wrapper]; | ||
stack.push(item); | ||
return wrapper; | ||
}, | ||
set:function (receiver, name, val) { | ||
stack.push([obj, ["__set__", [name, val]], [], obj]); | ||
return true; | ||
}, // bad behavior when set fails in non-strict mode | ||
enumerate:function () { | ||
stack.push([obj, ["__enumerate__"], [], obj]); | ||
return []; | ||
} | ||
} | ||
}; | ||
var functionHandler = function (handle, stack) { | ||
var wrapper = base.createFunctionWrapper(handle, function (m) { | ||
return handle.__apply__(base.argsToArray(arguments)); | ||
}, function () { | ||
return handle.__new__(base.argsToArray(arguments)); | ||
}); | ||
return wrapper; | ||
}; | ||
var getHandler = function (obj, stack) { | ||
var prox = base.isObject(obj) || base.isFunction(obj) ? base.handlerProxy({}, createHandler(obj, stack)) : obj, ret; | ||
if (base.isFunction(obj)) { | ||
return functionHandler(prox, stack); | ||
} else { | ||
ret = prox; | ||
} | ||
return ret; | ||
}; | ||
var getValueFromArrayMap = function (arg, pMap, handles) { | ||
var result; | ||
if (base.isProxy(arg)) { | ||
var results = pMap.filter(function (p) { | ||
return p[0] === arg; | ||
}); | ||
if (results.length) { | ||
result = results[0][1]; | ||
} else { | ||
!results.length && (results = handles.filter(function (h) { | ||
return h[1] === arg; | ||
})); | ||
if (results.length) { | ||
result = results[0][0]; | ||
} | ||
} | ||
} else if (base.isHash(arg) || base.isArray(arg)) { | ||
result = arg; | ||
for (var i in arg) { | ||
var a = arg[i]; | ||
arg[i] = getValueFromArrayMap(a, pMap, handles); | ||
} | ||
} else { | ||
result = arg; | ||
} | ||
return result; | ||
}; | ||
var executeStack = function (stack, handles, pMap) { | ||
var ret = new Promise(), l = stack.length, results = []; | ||
pMap = pMap || []; | ||
var errored = false; | ||
if (l) { | ||
var exec = function (i) { | ||
if (i < l) { | ||
var curr = stack[i], obj = getValueFromArrayMap(curr[0], pMap, | ||
handles), m = curr[1], name = m[0], args = m[1], subStack = curr[2], handle = curr[3]; | ||
var p; | ||
try { | ||
if (name === "__set__") { | ||
p = (obj[args[0]] = getValueFromArrayMap(args[1], pMap, handles)); | ||
} else if (name === "__delete__") { | ||
p = delete obj[args[0]]; | ||
} else if (name === "__keys__" || name === "__enumerate__") { | ||
throw new Error(name.replace(/^__|__$/g, "") + " is not supported"); | ||
} else if (name === "__apply__") { | ||
p = (obj.apply(obj, getValueFromArrayMap(args, pMap, handles))); | ||
} else if (name === "__new__") { | ||
try { | ||
p = new obj(); | ||
} catch (ignore) { | ||
} | ||
obj.apply(p, getValueFromArrayMap(args, pMap, handles)); | ||
} else if (base.isUndefined(args)) { | ||
p = obj[name]; | ||
} else { | ||
var f; | ||
if (!base.isUndefined((f = obj[name])) && base.isFunction(f)) { | ||
p = f.apply(obj, args.map(function (arg) { | ||
return getValueFromArrayMap(arg, pMap, handles); | ||
})); | ||
} else { | ||
//Purposely call to throw an ERROR!!!! | ||
obj[name](); | ||
} | ||
} | ||
} catch (e) { | ||
errored = true; | ||
return ret.errback(e); | ||
} | ||
exports.when(p, hitch(this, function (res) { | ||
if (subStack.length) { | ||
subStack.forEach(function (ss) { | ||
ss[0] = res; | ||
}); | ||
executeStack(subStack, handles, pMap).then(hitch(this, function (sres) { | ||
pMap.push([handle, res]); | ||
results.push(sres); | ||
!errored && exec(++i); | ||
}), hitch(ret, "errback")); | ||
} else { | ||
pMap.push([handle, res]); | ||
results.push(res); | ||
!errored && exec(++i); | ||
} | ||
}), hitch(ret, "errback")) | ||
} else { | ||
!errored && ret.callback(results, pMap); | ||
} | ||
}; | ||
exec(0); | ||
} else { | ||
ret.callback(results, pMap); | ||
} | ||
return ret; | ||
}; | ||
base.merge(exports, { | ||
@@ -523,88 +449,2 @@ /** | ||
/** | ||
* This method allows one to code asynchronous code in a synchronous manner. | ||
* | ||
* <p> | ||
* <b> | ||
* Using Object.define[rest of name] on objects passed will result in unexpected behavior.</br> | ||
* Enumerating passed in object keys is not currently supported. i.e for in loops on objects. | ||
* using array enumeration methods will work though!! | ||
* </b> | ||
* </p> | ||
* | ||
* @example | ||
* | ||
* var staticValueFunction = function (value) { | ||
* return comb.argsToArray(arguments).join(" "); | ||
* }; | ||
* | ||
* var promiseValueFunction = function (value) { | ||
* var ret = new comb.Promise(); | ||
* setTimeout(comb.hitch(ret, "callback", comb.argsToArray(arguments).join(" ")), 100); | ||
* return ret; | ||
* }; | ||
* | ||
* var hash = { | ||
* staticValueFunction:staticValueFunction, | ||
* promiseValueFunction:promiseValueFunction | ||
* }; | ||
* | ||
* var p = comb.executeInOrder(hash, staticValueFunction, promiseValueFunction, function (hash, staticValueFunction, promiseValueFunction) { | ||
* var toBe = staticValueFunction(promiseValueFunction("to"), "be"); | ||
* var notToBe = hash.promiseValueFunction("or", hash.staticValueFunction("not", toBe)); | ||
* return hash.promiseValueFunction(toBe, notToBe); | ||
* }); | ||
* p.addCallback(function(ret){ | ||
* console.log(ret); //=>"to be or not to be" | ||
* }); | ||
* @param {Object...} args variable number of objects. | ||
* @param {Function} cb the function to callback to execute in order | ||
* @returns comb.Promise | ||
* | ||
*/ | ||
executeInOrder:function (args, cb) { | ||
args = base.argsToArray(arguments); | ||
cb = base.isFunction(args[args.length - 1]) ? args.pop() : null; | ||
var ret = new Promise(); | ||
if (cb) { | ||
var stack = []; | ||
var newArgs = args.map(function (a) { | ||
return [a, getHandler(a, stack)]; | ||
}); | ||
var cbRet = cb.apply(null, newArgs.map(function (h) { | ||
return h[1]; | ||
})); | ||
executeStack(stack, newArgs).then(function (results, pMap) { | ||
if (base.isUndefined(cbRet)) { | ||
ret.callback(results); | ||
} | ||
else { | ||
var cbResults; | ||
if (base.isArray(cbRet)) { | ||
cbResults = cbRet.map( | ||
function (arg) { | ||
return getValueFromArrayMap(arg, pMap, newArgs); | ||
}).filter(function (r) { | ||
return !base.isUndefined(r) | ||
}); | ||
} else if (base.isHash(cbRet)) { | ||
cbResults = {}; | ||
for (var i in cbRet) { | ||
cbResults[i] = getValueFromArrayMap(cbRet[i], pMap, newArgs); | ||
} | ||
} else if (base.isProxy(cbRet)) { | ||
cbResults = getValueFromArrayMap(cbRet, pMap, newArgs); | ||
} else { | ||
cbResults = cbRet; | ||
} | ||
ret.callback(cbResults); | ||
} | ||
}, hitch(ret, "errback")); | ||
} else { | ||
ret.callback(); | ||
} | ||
return ret; | ||
}, | ||
/** | ||
* Tests if an object is like a promise (i.e. it contains then, addCallback, addErrback) | ||
@@ -615,3 +455,3 @@ * @param obj object to test | ||
return !base.isUndefinedOrNull(obj) && (base.isInstanceOf(obj, Promise) || (base.isFunction(obj.then) | ||
&& base.isFunction(obj.addCallback) && base.isFunction(obj.addErrback))); | ||
&& base.isFunction(obj.addCallback) && base.isFunction(obj.addErrback))); | ||
}, | ||
@@ -763,4 +603,4 @@ | ||
when(base.isFunction(item) ? item() : item, | ||
base.partial(callNextSuccess, list, index, results, isErrored, ret), | ||
base.partial(callNextError, index, results, isErrored, ret)); | ||
base.partial(callNextSuccess, list, index, results, isErrored, ret), | ||
base.partial(callNextError, index, results, isErrored, ret)); | ||
} catch (e) { | ||
@@ -767,0 +607,0 @@ ret.errback(e); |
{ | ||
"name": "comb", | ||
"description": "A framework for node", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"keywords" : ["OO", "Object Oriented", "Collections", "Tree", "HashTable", "Pool", "Logging", "Promise", "Promises", "Proxy"], | ||
@@ -10,5 +10,2 @@ "repository": { | ||
}, | ||
"dependencies" : { | ||
"node-proxy" : ">=0.5.2" | ||
}, | ||
"homepage": "http://pollenware.github.com/comb/symbols/comb.html", | ||
@@ -15,0 +12,0 @@ "author": "Pollenware (http://pollenware.github.com)", |
Comb | ||
========= | ||
##NOTE: v0.1.1 removed proxy code out of core see [comb-proxy](http://github.com/Pollenware/comb-proxy) | ||
Overview | ||
@@ -13,3 +15,2 @@ -------- | ||
* String & date formatting | ||
* Proxy | ||
* Flow control | ||
@@ -60,8 +61,2 @@ * Date Management | ||
* [PromiseLists](http://pollenware.github.com/comb/symbols/comb.PromiseList.html) | ||
* [executeInOrder](http://pollenware.github.com/comb/symbols/comb.html#.executeInOrder) | ||
* Allows you to program asynchronous functions synchronously. | ||
* Proxy helpers | ||
* [methodMissing](http://pollenware.github.com/comb/symbols/comb.html#.methodMissing) - handle those pesky 'has no method exception's | ||
* [functionWrapper](http://pollenware.github.com/comb/symbols/comb.html#.createFunctionWrapper) - wrap an object so you can use it as a function | ||
* [handlerProxy](http://pollenware.github.com/comb/symbols/comb.html#.handlerProxy) - create a proxy for an object | ||
* [Tell me more!](http://pollenware.github.com/comb/symbols/comb.html) | ||
@@ -68,0 +63,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
0
293922
50
8440
119
- Removednode-proxy@>=0.5.2
- Removedbindings@1.5.0(transitive)
- Removedfile-uri-to-path@1.0.0(transitive)
- Removednan@2.22.0(transitive)
- Removednode-proxy@1.0.0(transitive)