module.exports = (function(){
'use strict';

var ArrayClass = [].constructor;

function isArray(o) {
	return o instanceof ArrayClass;
}

function isStatic(o) {
	return !o || !isFunction(o) && !isObject(o);
}

function isFunction(o) {
	return typeof o === 'function';
}

function isObject(o) {
	return typeof o === 'object';
}

function noop() {}

function solve(o, callback) {
	callback = callback || noop;

	var bind = function (key) {
			var initial = o[key];

			// don't bother changing static values
			if (!isStatic(initial)) {
				solve(initial, function (value) {
					// got a value, put it in place
					o[key] = value;

					// go through all properties once before calling callback here
					if (ran) {
						callback(o);
					}
				});
			}
		},

		// handler for functions and promises
		done = function (value) {
			// remember that this callback was called
			ran = 1;

			// solve the value
			solve(value, callback);
		},

		// used for return value of function
		result,

		// iterator
		k,

		// used to see if function callback ran
		// also used to check if we're done first run of object properties
		ran;

	// statics, we're done
	if (isStatic(o)) {
		callback(o);

	// functions, solve the return value, and pass in a callback too
	} else if (isFunction(o)) {
		result = o(done);

		// if the callback wasn't already called synchronously, process the return value
		// note: if result is undefined, then that's what we'll start off with
		if (!ran) {
			solve(result, callback);
		}

	// promises (thenable), resolve via then & catch & progress (maybe)
	} else if (isFunction(o.then)) {
		o.then(done);

		// promises start off undefined, unless somehow the promise was already resolved
		if (!ran) {
			callback();
		}

	} else {
		if (isArray(o)) {
			// iterate over arrays
			for (k=0;k < o.length;k++) {
				bind(k);
			}
		} else {
			// other objects, solve each property
			for (k in o) {
				bind(k);
			}
		}

		// we've ran through it once, now bindings can call callback
		ran = 1;

		// definitely call callback after first run through
		callback(o);
	}

	// always return whatever was passed in
	return o;
}

return solve;

})();
@@ -42,41 +42,57 @@
 ';%0A%0A
-var ArrayClass = %5B%5D.constructor;%0A
+// is this a static value that is already solved?
 %0Afun
@@ -103,77 +103,137 @@
 n is
-Array
+Static
 (o) %7B%0A%09
-return o instanceof ArrayClass;%0A%7D%0A%0Afunction isStatic(o) %7B
+// anything falsey is static (especially null)%0A%09// otherwise, consider it static if it's not a function or an object
 %0A%09re
@@ -274,24 +274,47 @@
 ject(o);%0A%7D%0A%0A
+// is this a function?%0A
 function isF
@@ -358,24 +358,125 @@
 nction';%0A%7D%0A%0A
+// is this an array?%0Afunction isArray(o) %7B%0A%09return o.constructor === Array;%0A%7D%0A%0A// is this an object?%0A
 function isO
@@ -524,27 +524,30 @@
 %0A%7D%0A%0A
-function noop() %7B%7D%0A
+// main solve function
 %0Afun
@@ -578,37 +578,217 @@
  %7B%0A%09
-callback = callback %7C%7C noop;%0A
+// callback is theoretically optional%0A%09// we could check for it everywhere, but this is easier%0A%09callback = callback %7C%7C function () %7B%7D;%0A%0A%09// bind makes sure results are mapped back to the array or object member
 %0A%09va
@@ -1930,35 +1930,8 @@
 then
- & catch & progress (maybe)
 %0A%09%7D 
@@ -2096,24 +2096,99 @@
 ;%0A%09%09%7D%0A%0A%09
-%7D else %7B
+// otherwise either an array or an object%0A%09%7D else %7B%0A%09%09// check for array explicitly
 %0A%09%09if (i
@@ -2225,16 +2225,34 @@
 r arrays
+, solve each index
 %0A%09%09%09for 
@@ -2289,24 +2289,56 @@
 ind(k);%0A%09%09%09%7D
+%0A%0A%09%09// everything else (objects)
 %0A%09%09%7D else %7B%0A
@@ -2347,21 +2347,33 @@
 %09// 
-o
+solve each of 
 the
-r
  objects
 , so
@@ -2372,28 +2372,20 @@
 ects
-, solve each
+ own
  propert
 y%0A%09%09
@@ -2380,17 +2380,19 @@
  propert
-y
+ies
 %0A%09%09%09for 
@@ -2632,22 +2632,85 @@
 %0A%7D%0A%0A
-return solve;%0A
+// expose the solve function%0Areturn solve;%0A%0A// execute this scope immediately
 %0A%7D)(

Tidy up, comments