You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by sh...@apache.org on 2015/01/07 01:45:15 UTC

[01/10] ios commit: CB-5706 convert some of the bash scripts to nodejs (closes #118)

Repository: cordova-ios
Updated Branches:
  refs/heads/wkwebview 1d4ba9778 -> e0dc7443b


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/node_modules/q/q.js
----------------------------------------------------------------------
diff --git a/bin/node_modules/q/q.js b/bin/node_modules/q/q.js
new file mode 100644
index 0000000..df36027
--- /dev/null
+++ b/bin/node_modules/q/q.js
@@ -0,0 +1,1904 @@
+// vim:ts=4:sts=4:sw=4:
+/*!
+ *
+ * Copyright 2009-2012 Kris Kowal under the terms of the MIT
+ * license found at http://github.com/kriskowal/q/raw/master/LICENSE
+ *
+ * With parts by Tyler Close
+ * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found
+ * at http://www.opensource.org/licenses/mit-license.html
+ * Forked at ref_send.js version: 2009-05-11
+ *
+ * With parts by Mark Miller
+ * Copyright (C) 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+(function (definition) {
+    // Turn off strict mode for this function so we can assign to global.Q
+    /* jshint strict: false */
+
+    // This file will function properly as a <script> tag, or a module
+    // using CommonJS and NodeJS or RequireJS module formats.  In
+    // Common/Node/RequireJS, the module exports the Q API and when
+    // executed as a simple <script>, it creates a Q global instead.
+
+    // Montage Require
+    if (typeof bootstrap === "function") {
+        bootstrap("promise", definition);
+
+    // CommonJS
+    } else if (typeof exports === "object") {
+        module.exports = definition();
+
+    // RequireJS
+    } else if (typeof define === "function" && define.amd) {
+        define(definition);
+
+    // SES (Secure EcmaScript)
+    } else if (typeof ses !== "undefined") {
+        if (!ses.ok()) {
+            return;
+        } else {
+            ses.makeQ = definition;
+        }
+
+    // <script>
+    } else {
+        Q = definition();
+    }
+
+})(function () {
+"use strict";
+
+var hasStacks = false;
+try {
+    throw new Error();
+} catch (e) {
+    hasStacks = !!e.stack;
+}
+
+// All code after this point will be filtered from stack traces reported
+// by Q.
+var qStartingLine = captureLine();
+var qFileName;
+
+// shims
+
+// used for fallback in "allResolved"
+var noop = function () {};
+
+// Use the fastest possible means to execute a task in a future turn
+// of the event loop.
+var nextTick =(function () {
+    // linked list of tasks (single, with head node)
+    var head = {task: void 0, next: null};
+    var tail = head;
+    var flushing = false;
+    var requestTick = void 0;
+    var isNodeJS = false;
+
+    function flush() {
+        /* jshint loopfunc: true */
+
+        while (head.next) {
+            head = head.next;
+            var task = head.task;
+            head.task = void 0;
+            var domain = head.domain;
+
+            if (domain) {
+                head.domain = void 0;
+                domain.enter();
+            }
+
+            try {
+                task();
+
+            } catch (e) {
+                if (isNodeJS) {
+                    // In node, uncaught exceptions are considered fatal errors.
+                    // Re-throw them synchronously to interrupt flushing!
+
+                    // Ensure continuation if the uncaught exception is suppressed
+                    // listening "uncaughtException" events (as domains does).
+                    // Continue in next event to avoid tick recursion.
+                    if (domain) {
+                        domain.exit();
+                    }
+                    setTimeout(flush, 0);
+                    if (domain) {
+                        domain.enter();
+                    }
+
+                    throw e;
+
+                } else {
+                    // In browsers, uncaught exceptions are not fatal.
+                    // Re-throw them asynchronously to avoid slow-downs.
+                    setTimeout(function() {
+                       throw e;
+                    }, 0);
+                }
+            }
+
+            if (domain) {
+                domain.exit();
+            }
+        }
+
+        flushing = false;
+    }
+
+    nextTick = function (task) {
+        tail = tail.next = {
+            task: task,
+            domain: isNodeJS && process.domain,
+            next: null
+        };
+
+        if (!flushing) {
+            flushing = true;
+            requestTick();
+        }
+    };
+
+    if (typeof process !== "undefined" && process.nextTick) {
+        // Node.js before 0.9. Note that some fake-Node environments, like the
+        // Mocha test runner, introduce a `process` global without a `nextTick`.
+        isNodeJS = true;
+
+        requestTick = function () {
+            process.nextTick(flush);
+        };
+
+    } else if (typeof setImmediate === "function") {
+        // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
+        if (typeof window !== "undefined") {
+            requestTick = setImmediate.bind(window, flush);
+        } else {
+            requestTick = function () {
+                setImmediate(flush);
+            };
+        }
+
+    } else if (typeof MessageChannel !== "undefined") {
+        // modern browsers
+        // http://www.nonblocking.io/2011/06/windownexttick.html
+        var channel = new MessageChannel();
+        // At least Safari Version 6.0.5 (8536.30.1) intermittently cannot create
+        // working message ports the first time a page loads.
+        channel.port1.onmessage = function () {
+            requestTick = requestPortTick;
+            channel.port1.onmessage = flush;
+            flush();
+        };
+        var requestPortTick = function () {
+            // Opera requires us to provide a message payload, regardless of
+            // whether we use it.
+            channel.port2.postMessage(0);
+        };
+        requestTick = function () {
+            setTimeout(flush, 0);
+            requestPortTick();
+        };
+
+    } else {
+        // old browsers
+        requestTick = function () {
+            setTimeout(flush, 0);
+        };
+    }
+
+    return nextTick;
+})();
+
+// Attempt to make generics safe in the face of downstream
+// modifications.
+// There is no situation where this is necessary.
+// If you need a security guarantee, these primordials need to be
+// deeply frozen anyway, and if you don’t need a security guarantee,
+// this is just plain paranoid.
+// However, this **might** have the nice side-effect of reducing the size of
+// the minified code by reducing x.call() to merely x()
+// See Mark Miller’s explanation of what this does.
+// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
+var call = Function.call;
+function uncurryThis(f) {
+    return function () {
+        return call.apply(f, arguments);
+    };
+}
+// This is equivalent, but slower:
+// uncurryThis = Function_bind.bind(Function_bind.call);
+// http://jsperf.com/uncurrythis
+
+var array_slice = uncurryThis(Array.prototype.slice);
+
+var array_reduce = uncurryThis(
+    Array.prototype.reduce || function (callback, basis) {
+        var index = 0,
+            length = this.length;
+        // concerning the initial value, if one is not provided
+        if (arguments.length === 1) {
+            // seek to the first value in the array, accounting
+            // for the possibility that is is a sparse array
+            do {
+                if (index in this) {
+                    basis = this[index++];
+                    break;
+                }
+                if (++index >= length) {
+                    throw new TypeError();
+                }
+            } while (1);
+        }
+        // reduce
+        for (; index < length; index++) {
+            // account for the possibility that the array is sparse
+            if (index in this) {
+                basis = callback(basis, this[index], index);
+            }
+        }
+        return basis;
+    }
+);
+
+var array_indexOf = uncurryThis(
+    Array.prototype.indexOf || function (value) {
+        // not a very good shim, but good enough for our one use of it
+        for (var i = 0; i < this.length; i++) {
+            if (this[i] === value) {
+                return i;
+            }
+        }
+        return -1;
+    }
+);
+
+var array_map = uncurryThis(
+    Array.prototype.map || function (callback, thisp) {
+        var self = this;
+        var collect = [];
+        array_reduce(self, function (undefined, value, index) {
+            collect.push(callback.call(thisp, value, index, self));
+        }, void 0);
+        return collect;
+    }
+);
+
+var object_create = Object.create || function (prototype) {
+    function Type() { }
+    Type.prototype = prototype;
+    return new Type();
+};
+
+var object_hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);
+
+var object_keys = Object.keys || function (object) {
+    var keys = [];
+    for (var key in object) {
+        if (object_hasOwnProperty(object, key)) {
+            keys.push(key);
+        }
+    }
+    return keys;
+};
+
+var object_toString = uncurryThis(Object.prototype.toString);
+
+function isObject(value) {
+    return value === Object(value);
+}
+
+// generator related shims
+
+// FIXME: Remove this function once ES6 generators are in SpiderMonkey.
+function isStopIteration(exception) {
+    return (
+        object_toString(exception) === "[object StopIteration]" ||
+        exception instanceof QReturnValue
+    );
+}
+
+// FIXME: Remove this helper and Q.return once ES6 generators are in
+// SpiderMonkey.
+var QReturnValue;
+if (typeof ReturnValue !== "undefined") {
+    QReturnValue = ReturnValue;
+} else {
+    QReturnValue = function (value) {
+        this.value = value;
+    };
+}
+
+// long stack traces
+
+var STACK_JUMP_SEPARATOR = "From previous event:";
+
+function makeStackTraceLong(error, promise) {
+    // If possible, transform the error stack trace by removing Node and Q
+    // cruft, then concatenating with the stack trace of `promise`. See #57.
+    if (hasStacks &&
+        promise.stack &&
+        typeof error === "object" &&
+        error !== null &&
+        error.stack &&
+        error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1
+    ) {
+        var stacks = [];
+        for (var p = promise; !!p; p = p.source) {
+            if (p.stack) {
+                stacks.unshift(p.stack);
+            }
+        }
+        stacks.unshift(error.stack);
+
+        var concatedStacks = stacks.join("\n" + STACK_JUMP_SEPARATOR + "\n");
+        error.stack = filterStackString(concatedStacks);
+    }
+}
+
+function filterStackString(stackString) {
+    var lines = stackString.split("\n");
+    var desiredLines = [];
+    for (var i = 0; i < lines.length; ++i) {
+        var line = lines[i];
+
+        if (!isInternalFrame(line) && !isNodeFrame(line) && line) {
+            desiredLines.push(line);
+        }
+    }
+    return desiredLines.join("\n");
+}
+
+function isNodeFrame(stackLine) {
+    return stackLine.indexOf("(module.js:") !== -1 ||
+           stackLine.indexOf("(node.js:") !== -1;
+}
+
+function getFileNameAndLineNumber(stackLine) {
+    // Named functions: "at functionName (filename:lineNumber:columnNumber)"
+    // In IE10 function name can have spaces ("Anonymous function") O_o
+    var attempt1 = /at .+ \((.+):(\d+):(?:\d+)\)$/.exec(stackLine);
+    if (attempt1) {
+        return [attempt1[1], Number(attempt1[2])];
+    }
+
+    // Anonymous functions: "at filename:lineNumber:columnNumber"
+    var attempt2 = /at ([^ ]+):(\d+):(?:\d+)$/.exec(stackLine);
+    if (attempt2) {
+        return [attempt2[1], Number(attempt2[2])];
+    }
+
+    // Firefox style: "function@filename:lineNumber or @filename:lineNumber"
+    var attempt3 = /.*@(.+):(\d+)$/.exec(stackLine);
+    if (attempt3) {
+        return [attempt3[1], Number(attempt3[2])];
+    }
+}
+
+function isInternalFrame(stackLine) {
+    var fileNameAndLineNumber = getFileNameAndLineNumber(stackLine);
+
+    if (!fileNameAndLineNumber) {
+        return false;
+    }
+
+    var fileName = fileNameAndLineNumber[0];
+    var lineNumber = fileNameAndLineNumber[1];
+
+    return fileName === qFileName &&
+        lineNumber >= qStartingLine &&
+        lineNumber <= qEndingLine;
+}
+
+// discover own file name and line number range for filtering stack
+// traces
+function captureLine() {
+    if (!hasStacks) {
+        return;
+    }
+
+    try {
+        throw new Error();
+    } catch (e) {
+        var lines = e.stack.split("\n");
+        var firstLine = lines[0].indexOf("@") > 0 ? lines[1] : lines[2];
+        var fileNameAndLineNumber = getFileNameAndLineNumber(firstLine);
+        if (!fileNameAndLineNumber) {
+            return;
+        }
+
+        qFileName = fileNameAndLineNumber[0];
+        return fileNameAndLineNumber[1];
+    }
+}
+
+function deprecate(callback, name, alternative) {
+    return function () {
+        if (typeof console !== "undefined" &&
+            typeof console.warn === "function") {
+            console.warn(name + " is deprecated, use " + alternative +
+                         " instead.", new Error("").stack);
+        }
+        return callback.apply(callback, arguments);
+    };
+}
+
+// end of shims
+// beginning of real work
+
+/**
+ * Constructs a promise for an immediate reference, passes promises through, or
+ * coerces promises from different systems.
+ * @param value immediate reference or promise
+ */
+function Q(value) {
+    // If the object is already a Promise, return it directly.  This enables
+    // the resolve function to both be used to created references from objects,
+    // but to tolerably coerce non-promises to promises.
+    if (isPromise(value)) {
+        return value;
+    }
+
+    // assimilate thenables
+    if (isPromiseAlike(value)) {
+        return coerce(value);
+    } else {
+        return fulfill(value);
+    }
+}
+Q.resolve = Q;
+
+/**
+ * Performs a task in a future turn of the event loop.
+ * @param {Function} task
+ */
+Q.nextTick = nextTick;
+
+/**
+ * Controls whether or not long stack traces will be on
+ */
+Q.longStackSupport = false;
+
+/**
+ * Constructs a {promise, resolve, reject} object.
+ *
+ * `resolve` is a callback to invoke with a more resolved value for the
+ * promise. To fulfill the promise, invoke `resolve` with any value that is
+ * not a thenable. To reject the promise, invoke `resolve` with a rejected
+ * thenable, or invoke `reject` with the reason directly. To resolve the
+ * promise to another thenable, thus putting it in the same state, invoke
+ * `resolve` with that other thenable.
+ */
+Q.defer = defer;
+function defer() {
+    // if "messages" is an "Array", that indicates that the promise has not yet
+    // been resolved.  If it is "undefined", it has been resolved.  Each
+    // element of the messages array is itself an array of complete arguments to
+    // forward to the resolved promise.  We coerce the resolution value to a
+    // promise using the `resolve` function because it handles both fully
+    // non-thenable values and other thenables gracefully.
+    var messages = [], progressListeners = [], resolvedPromise;
+
+    var deferred = object_create(defer.prototype);
+    var promise = object_create(Promise.prototype);
+
+    promise.promiseDispatch = function (resolve, op, operands) {
+        var args = array_slice(arguments);
+        if (messages) {
+            messages.push(args);
+            if (op === "when" && operands[1]) { // progress operand
+                progressListeners.push(operands[1]);
+            }
+        } else {
+            nextTick(function () {
+                resolvedPromise.promiseDispatch.apply(resolvedPromise, args);
+            });
+        }
+    };
+
+    // XXX deprecated
+    promise.valueOf = function () {
+        if (messages) {
+            return promise;
+        }
+        var nearerValue = nearer(resolvedPromise);
+        if (isPromise(nearerValue)) {
+            resolvedPromise = nearerValue; // shorten chain
+        }
+        return nearerValue;
+    };
+
+    promise.inspect = function () {
+        if (!resolvedPromise) {
+            return { state: "pending" };
+        }
+        return resolvedPromise.inspect();
+    };
+
+    if (Q.longStackSupport && hasStacks) {
+        try {
+            throw new Error();
+        } catch (e) {
+            // NOTE: don't try to use `Error.captureStackTrace` or transfer the
+            // accessor around; that causes memory leaks as per GH-111. Just
+            // reify the stack trace as a string ASAP.
+            //
+            // At the same time, cut off the first line; it's always just
+            // "[object Promise]\n", as per the `toString`.
+            promise.stack = e.stack.substring(e.stack.indexOf("\n") + 1);
+        }
+    }
+
+    // NOTE: we do the checks for `resolvedPromise` in each method, instead of
+    // consolidating them into `become`, since otherwise we'd create new
+    // promises with the lines `become(whatever(value))`. See e.g. GH-252.
+
+    function become(newPromise) {
+        resolvedPromise = newPromise;
+        promise.source = newPromise;
+
+        array_reduce(messages, function (undefined, message) {
+            nextTick(function () {
+                newPromise.promiseDispatch.apply(newPromise, message);
+            });
+        }, void 0);
+
+        messages = void 0;
+        progressListeners = void 0;
+    }
+
+    deferred.promise = promise;
+    deferred.resolve = function (value) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(Q(value));
+    };
+
+    deferred.fulfill = function (value) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(fulfill(value));
+    };
+    deferred.reject = function (reason) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        become(reject(reason));
+    };
+    deferred.notify = function (progress) {
+        if (resolvedPromise) {
+            return;
+        }
+
+        array_reduce(progressListeners, function (undefined, progressListener) {
+            nextTick(function () {
+                progressListener(progress);
+            });
+        }, void 0);
+    };
+
+    return deferred;
+}
+
+/**
+ * Creates a Node-style callback that will resolve or reject the deferred
+ * promise.
+ * @returns a nodeback
+ */
+defer.prototype.makeNodeResolver = function () {
+    var self = this;
+    return function (error, value) {
+        if (error) {
+            self.reject(error);
+        } else if (arguments.length > 2) {
+            self.resolve(array_slice(arguments, 1));
+        } else {
+            self.resolve(value);
+        }
+    };
+};
+
+/**
+ * @param resolver {Function} a function that returns nothing and accepts
+ * the resolve, reject, and notify functions for a deferred.
+ * @returns a promise that may be resolved with the given resolve and reject
+ * functions, or rejected by a thrown exception in resolver
+ */
+Q.Promise = promise; // ES6
+Q.promise = promise;
+function promise(resolver) {
+    if (typeof resolver !== "function") {
+        throw new TypeError("resolver must be a function.");
+    }
+    var deferred = defer();
+    try {
+        resolver(deferred.resolve, deferred.reject, deferred.notify);
+    } catch (reason) {
+        deferred.reject(reason);
+    }
+    return deferred.promise;
+}
+
+promise.race = race; // ES6
+promise.all = all; // ES6
+promise.reject = reject; // ES6
+promise.resolve = Q; // ES6
+
+// XXX experimental.  This method is a way to denote that a local value is
+// serializable and should be immediately dispatched to a remote upon request,
+// instead of passing a reference.
+Q.passByCopy = function (object) {
+    //freeze(object);
+    //passByCopies.set(object, true);
+    return object;
+};
+
+Promise.prototype.passByCopy = function () {
+    //freeze(object);
+    //passByCopies.set(object, true);
+    return this;
+};
+
+/**
+ * If two promises eventually fulfill to the same value, promises that value,
+ * but otherwise rejects.
+ * @param x {Any*}
+ * @param y {Any*}
+ * @returns {Any*} a promise for x and y if they are the same, but a rejection
+ * otherwise.
+ *
+ */
+Q.join = function (x, y) {
+    return Q(x).join(y);
+};
+
+Promise.prototype.join = function (that) {
+    return Q([this, that]).spread(function (x, y) {
+        if (x === y) {
+            // TODO: "===" should be Object.is or equiv
+            return x;
+        } else {
+            throw new Error("Can't join: not the same: " + x + " " + y);
+        }
+    });
+};
+
+/**
+ * Returns a promise for the first of an array of promises to become fulfilled.
+ * @param answers {Array[Any*]} promises to race
+ * @returns {Any*} the first promise to be fulfilled
+ */
+Q.race = race;
+function race(answerPs) {
+    return promise(function(resolve, reject) {
+        // Switch to this once we can assume at least ES5
+        // answerPs.forEach(function(answerP) {
+        //     Q(answerP).then(resolve, reject);
+        // });
+        // Use this in the meantime
+        for (var i = 0, len = answerPs.length; i < len; i++) {
+            Q(answerPs[i]).then(resolve, reject);
+        }
+    });
+}
+
+Promise.prototype.race = function () {
+    return this.then(Q.race);
+};
+
+/**
+ * Constructs a Promise with a promise descriptor object and optional fallback
+ * function.  The descriptor contains methods like when(rejected), get(name),
+ * set(name, value), post(name, args), and delete(name), which all
+ * return either a value, a promise for a value, or a rejection.  The fallback
+ * accepts the operation name, a resolver, and any further arguments that would
+ * have been forwarded to the appropriate method above had a method been
+ * provided with the proper name.  The API makes no guarantees about the nature
+ * of the returned object, apart from that it is usable whereever promises are
+ * bought and sold.
+ */
+Q.makePromise = Promise;
+function Promise(descriptor, fallback, inspect) {
+    if (fallback === void 0) {
+        fallback = function (op) {
+            return reject(new Error(
+                "Promise does not support operation: " + op
+            ));
+        };
+    }
+    if (inspect === void 0) {
+        inspect = function () {
+            return {state: "unknown"};
+        };
+    }
+
+    var promise = object_create(Promise.prototype);
+
+    promise.promiseDispatch = function (resolve, op, args) {
+        var result;
+        try {
+            if (descriptor[op]) {
+                result = descriptor[op].apply(promise, args);
+            } else {
+                result = fallback.call(promise, op, args);
+            }
+        } catch (exception) {
+            result = reject(exception);
+        }
+        if (resolve) {
+            resolve(result);
+        }
+    };
+
+    promise.inspect = inspect;
+
+    // XXX deprecated `valueOf` and `exception` support
+    if (inspect) {
+        var inspected = inspect();
+        if (inspected.state === "rejected") {
+            promise.exception = inspected.reason;
+        }
+
+        promise.valueOf = function () {
+            var inspected = inspect();
+            if (inspected.state === "pending" ||
+                inspected.state === "rejected") {
+                return promise;
+            }
+            return inspected.value;
+        };
+    }
+
+    return promise;
+}
+
+Promise.prototype.toString = function () {
+    return "[object Promise]";
+};
+
+Promise.prototype.then = function (fulfilled, rejected, progressed) {
+    var self = this;
+    var deferred = defer();
+    var done = false;   // ensure the untrusted promise makes at most a
+                        // single call to one of the callbacks
+
+    function _fulfilled(value) {
+        try {
+            return typeof fulfilled === "function" ? fulfilled(value) : value;
+        } catch (exception) {
+            return reject(exception);
+        }
+    }
+
+    function _rejected(exception) {
+        if (typeof rejected === "function") {
+            makeStackTraceLong(exception, self);
+            try {
+                return rejected(exception);
+            } catch (newException) {
+                return reject(newException);
+            }
+        }
+        return reject(exception);
+    }
+
+    function _progressed(value) {
+        return typeof progressed === "function" ? progressed(value) : value;
+    }
+
+    nextTick(function () {
+        self.promiseDispatch(function (value) {
+            if (done) {
+                return;
+            }
+            done = true;
+
+            deferred.resolve(_fulfilled(value));
+        }, "when", [function (exception) {
+            if (done) {
+                return;
+            }
+            done = true;
+
+            deferred.resolve(_rejected(exception));
+        }]);
+    });
+
+    // Progress propagator need to be attached in the current tick.
+    self.promiseDispatch(void 0, "when", [void 0, function (value) {
+        var newValue;
+        var threw = false;
+        try {
+            newValue = _progressed(value);
+        } catch (e) {
+            threw = true;
+            if (Q.onerror) {
+                Q.onerror(e);
+            } else {
+                throw e;
+            }
+        }
+
+        if (!threw) {
+            deferred.notify(newValue);
+        }
+    }]);
+
+    return deferred.promise;
+};
+
+/**
+ * Registers an observer on a promise.
+ *
+ * Guarantees:
+ *
+ * 1. that fulfilled and rejected will be called only once.
+ * 2. that either the fulfilled callback or the rejected callback will be
+ *    called, but not both.
+ * 3. that fulfilled and rejected will not be called in this turn.
+ *
+ * @param value      promise or immediate reference to observe
+ * @param fulfilled  function to be called with the fulfilled value
+ * @param rejected   function to be called with the rejection exception
+ * @param progressed function to be called on any progress notifications
+ * @return promise for the return value from the invoked callback
+ */
+Q.when = when;
+function when(value, fulfilled, rejected, progressed) {
+    return Q(value).then(fulfilled, rejected, progressed);
+}
+
+Promise.prototype.thenResolve = function (value) {
+    return this.then(function () { return value; });
+};
+
+Q.thenResolve = function (promise, value) {
+    return Q(promise).thenResolve(value);
+};
+
+Promise.prototype.thenReject = function (reason) {
+    return this.then(function () { throw reason; });
+};
+
+Q.thenReject = function (promise, reason) {
+    return Q(promise).thenReject(reason);
+};
+
+/**
+ * If an object is not a promise, it is as "near" as possible.
+ * If a promise is rejected, it is as "near" as possible too.
+ * If it’s a fulfilled promise, the fulfillment value is nearer.
+ * If it’s a deferred promise and the deferred has been resolved, the
+ * resolution is "nearer".
+ * @param object
+ * @returns most resolved (nearest) form of the object
+ */
+
+// XXX should we re-do this?
+Q.nearer = nearer;
+function nearer(value) {
+    if (isPromise(value)) {
+        var inspected = value.inspect();
+        if (inspected.state === "fulfilled") {
+            return inspected.value;
+        }
+    }
+    return value;
+}
+
+/**
+ * @returns whether the given object is a promise.
+ * Otherwise it is a fulfilled value.
+ */
+Q.isPromise = isPromise;
+function isPromise(object) {
+    return isObject(object) &&
+        typeof object.promiseDispatch === "function" &&
+        typeof object.inspect === "function";
+}
+
+Q.isPromiseAlike = isPromiseAlike;
+function isPromiseAlike(object) {
+    return isObject(object) && typeof object.then === "function";
+}
+
+/**
+ * @returns whether the given object is a pending promise, meaning not
+ * fulfilled or rejected.
+ */
+Q.isPending = isPending;
+function isPending(object) {
+    return isPromise(object) && object.inspect().state === "pending";
+}
+
+Promise.prototype.isPending = function () {
+    return this.inspect().state === "pending";
+};
+
+/**
+ * @returns whether the given object is a value or fulfilled
+ * promise.
+ */
+Q.isFulfilled = isFulfilled;
+function isFulfilled(object) {
+    return !isPromise(object) || object.inspect().state === "fulfilled";
+}
+
+Promise.prototype.isFulfilled = function () {
+    return this.inspect().state === "fulfilled";
+};
+
+/**
+ * @returns whether the given object is a rejected promise.
+ */
+Q.isRejected = isRejected;
+function isRejected(object) {
+    return isPromise(object) && object.inspect().state === "rejected";
+}
+
+Promise.prototype.isRejected = function () {
+    return this.inspect().state === "rejected";
+};
+
+//// BEGIN UNHANDLED REJECTION TRACKING
+
+// This promise library consumes exceptions thrown in handlers so they can be
+// handled by a subsequent promise.  The exceptions get added to this array when
+// they are created, and removed when they are handled.  Note that in ES6 or
+// shimmed environments, this would naturally be a `Set`.
+var unhandledReasons = [];
+var unhandledRejections = [];
+var trackUnhandledRejections = true;
+
+function resetUnhandledRejections() {
+    unhandledReasons.length = 0;
+    unhandledRejections.length = 0;
+
+    if (!trackUnhandledRejections) {
+        trackUnhandledRejections = true;
+    }
+}
+
+function trackRejection(promise, reason) {
+    if (!trackUnhandledRejections) {
+        return;
+    }
+
+    unhandledRejections.push(promise);
+    if (reason && typeof reason.stack !== "undefined") {
+        unhandledReasons.push(reason.stack);
+    } else {
+        unhandledReasons.push("(no stack) " + reason);
+    }
+}
+
+function untrackRejection(promise) {
+    if (!trackUnhandledRejections) {
+        return;
+    }
+
+    var at = array_indexOf(unhandledRejections, promise);
+    if (at !== -1) {
+        unhandledRejections.splice(at, 1);
+        unhandledReasons.splice(at, 1);
+    }
+}
+
+Q.resetUnhandledRejections = resetUnhandledRejections;
+
+Q.getUnhandledReasons = function () {
+    // Make a copy so that consumers can't interfere with our internal state.
+    return unhandledReasons.slice();
+};
+
+Q.stopUnhandledRejectionTracking = function () {
+    resetUnhandledRejections();
+    trackUnhandledRejections = false;
+};
+
+resetUnhandledRejections();
+
+//// END UNHANDLED REJECTION TRACKING
+
+/**
+ * Constructs a rejected promise.
+ * @param reason value describing the failure
+ */
+Q.reject = reject;
+function reject(reason) {
+    var rejection = Promise({
+        "when": function (rejected) {
+            // note that the error has been handled
+            if (rejected) {
+                untrackRejection(this);
+            }
+            return rejected ? rejected(reason) : this;
+        }
+    }, function fallback() {
+        return this;
+    }, function inspect() {
+        return { state: "rejected", reason: reason };
+    });
+
+    // Note that the reason has not been handled.
+    trackRejection(rejection, reason);
+
+    return rejection;
+}
+
+/**
+ * Constructs a fulfilled promise for an immediate reference.
+ * @param value immediate reference
+ */
+Q.fulfill = fulfill;
+function fulfill(value) {
+    return Promise({
+        "when": function () {
+            return value;
+        },
+        "get": function (name) {
+            return value[name];
+        },
+        "set": function (name, rhs) {
+            value[name] = rhs;
+        },
+        "delete": function (name) {
+            delete value[name];
+        },
+        "post": function (name, args) {
+            // Mark Miller proposes that post with no name should apply a
+            // promised function.
+            if (name === null || name === void 0) {
+                return value.apply(void 0, args);
+            } else {
+                return value[name].apply(value, args);
+            }
+        },
+        "apply": function (thisp, args) {
+            return value.apply(thisp, args);
+        },
+        "keys": function () {
+            return object_keys(value);
+        }
+    }, void 0, function inspect() {
+        return { state: "fulfilled", value: value };
+    });
+}
+
+/**
+ * Converts thenables to Q promises.
+ * @param promise thenable promise
+ * @returns a Q promise
+ */
+function coerce(promise) {
+    var deferred = defer();
+    nextTick(function () {
+        try {
+            promise.then(deferred.resolve, deferred.reject, deferred.notify);
+        } catch (exception) {
+            deferred.reject(exception);
+        }
+    });
+    return deferred.promise;
+}
+
+/**
+ * Annotates an object such that it will never be
+ * transferred away from this process over any promise
+ * communication channel.
+ * @param object
+ * @returns promise a wrapping of that object that
+ * additionally responds to the "isDef" message
+ * without a rejection.
+ */
+Q.master = master;
+function master(object) {
+    return Promise({
+        "isDef": function () {}
+    }, function fallback(op, args) {
+        return dispatch(object, op, args);
+    }, function () {
+        return Q(object).inspect();
+    });
+}
+
+/**
+ * Spreads the values of a promised array of arguments into the
+ * fulfillment callback.
+ * @param fulfilled callback that receives variadic arguments from the
+ * promised array
+ * @param rejected callback that receives the exception if the promise
+ * is rejected.
+ * @returns a promise for the return value or thrown exception of
+ * either callback.
+ */
+Q.spread = spread;
+function spread(value, fulfilled, rejected) {
+    return Q(value).spread(fulfilled, rejected);
+}
+
+Promise.prototype.spread = function (fulfilled, rejected) {
+    return this.all().then(function (array) {
+        return fulfilled.apply(void 0, array);
+    }, rejected);
+};
+
+/**
+ * The async function is a decorator for generator functions, turning
+ * them into asynchronous generators.  Although generators are only part
+ * of the newest ECMAScript 6 drafts, this code does not cause syntax
+ * errors in older engines.  This code should continue to work and will
+ * in fact improve over time as the language improves.
+ *
+ * ES6 generators are currently part of V8 version 3.19 with the
+ * --harmony-generators runtime flag enabled.  SpiderMonkey has had them
+ * for longer, but under an older Python-inspired form.  This function
+ * works on both kinds of generators.
+ *
+ * Decorates a generator function such that:
+ *  - it may yield promises
+ *  - execution will continue when that promise is fulfilled
+ *  - the value of the yield expression will be the fulfilled value
+ *  - it returns a promise for the return value (when the generator
+ *    stops iterating)
+ *  - the decorated function returns a promise for the return value
+ *    of the generator or the first rejected promise among those
+ *    yielded.
+ *  - if an error is thrown in the generator, it propagates through
+ *    every following yield until it is caught, or until it escapes
+ *    the generator function altogether, and is translated into a
+ *    rejection for the promise returned by the decorated generator.
+ */
+Q.async = async;
+function async(makeGenerator) {
+    return function () {
+        // when verb is "send", arg is a value
+        // when verb is "throw", arg is an exception
+        function continuer(verb, arg) {
+            var result;
+
+            // Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only
+            // engine that has a deployed base of browsers that support generators.
+            // However, SM's generators use the Python-inspired semantics of
+            // outdated ES6 drafts.  We would like to support ES6, but we'd also
+            // like to make it possible to use generators in deployed browsers, so
+            // we also support Python-style generators.  At some point we can remove
+            // this block.
+
+            if (typeof StopIteration === "undefined") {
+                // ES6 Generators
+                try {
+                    result = generator[verb](arg);
+                } catch (exception) {
+                    return reject(exception);
+                }
+                if (result.done) {
+                    return result.value;
+                } else {
+                    return when(result.value, callback, errback);
+                }
+            } else {
+                // SpiderMonkey Generators
+                // FIXME: Remove this case when SM does ES6 generators.
+                try {
+                    result = generator[verb](arg);
+                } catch (exception) {
+                    if (isStopIteration(exception)) {
+                        return exception.value;
+                    } else {
+                        return reject(exception);
+                    }
+                }
+                return when(result, callback, errback);
+            }
+        }
+        var generator = makeGenerator.apply(this, arguments);
+        var callback = continuer.bind(continuer, "next");
+        var errback = continuer.bind(continuer, "throw");
+        return callback();
+    };
+}
+
+/**
+ * The spawn function is a small wrapper around async that immediately
+ * calls the generator and also ends the promise chain, so that any
+ * unhandled errors are thrown instead of forwarded to the error
+ * handler. This is useful because it's extremely common to run
+ * generators at the top-level to work with libraries.
+ */
+Q.spawn = spawn;
+function spawn(makeGenerator) {
+    Q.done(Q.async(makeGenerator)());
+}
+
+// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.
+/**
+ * Throws a ReturnValue exception to stop an asynchronous generator.
+ *
+ * This interface is a stop-gap measure to support generator return
+ * values in older Firefox/SpiderMonkey.  In browsers that support ES6
+ * generators like Chromium 29, just use "return" in your generator
+ * functions.
+ *
+ * @param value the return value for the surrounding generator
+ * @throws ReturnValue exception with the value.
+ * @example
+ * // ES6 style
+ * Q.async(function* () {
+ *      var foo = yield getFooPromise();
+ *      var bar = yield getBarPromise();
+ *      return foo + bar;
+ * })
+ * // Older SpiderMonkey style
+ * Q.async(function () {
+ *      var foo = yield getFooPromise();
+ *      var bar = yield getBarPromise();
+ *      Q.return(foo + bar);
+ * })
+ */
+Q["return"] = _return;
+function _return(value) {
+    throw new QReturnValue(value);
+}
+
+/**
+ * The promised function decorator ensures that any promise arguments
+ * are settled and passed as values (`this` is also settled and passed
+ * as a value).  It will also ensure that the result of a function is
+ * always a promise.
+ *
+ * @example
+ * var add = Q.promised(function (a, b) {
+ *     return a + b;
+ * });
+ * add(Q(a), Q(B));
+ *
+ * @param {function} callback The function to decorate
+ * @returns {function} a function that has been decorated.
+ */
+Q.promised = promised;
+function promised(callback) {
+    return function () {
+        return spread([this, all(arguments)], function (self, args) {
+            return callback.apply(self, args);
+        });
+    };
+}
+
+/**
+ * sends a message to a value in a future turn
+ * @param object* the recipient
+ * @param op the name of the message operation, e.g., "when",
+ * @param args further arguments to be forwarded to the operation
+ * @returns result {Promise} a promise for the result of the operation
+ */
+Q.dispatch = dispatch;
+function dispatch(object, op, args) {
+    return Q(object).dispatch(op, args);
+}
+
+Promise.prototype.dispatch = function (op, args) {
+    var self = this;
+    var deferred = defer();
+    nextTick(function () {
+        self.promiseDispatch(deferred.resolve, op, args);
+    });
+    return deferred.promise;
+};
+
+/**
+ * Gets the value of a property in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of property to get
+ * @return promise for the property value
+ */
+Q.get = function (object, key) {
+    return Q(object).dispatch("get", [key]);
+};
+
+Promise.prototype.get = function (key) {
+    return this.dispatch("get", [key]);
+};
+
+/**
+ * Sets the value of a property in a future turn.
+ * @param object    promise or immediate reference for object object
+ * @param name      name of property to set
+ * @param value     new value of property
+ * @return promise for the return value
+ */
+Q.set = function (object, key, value) {
+    return Q(object).dispatch("set", [key, value]);
+};
+
+Promise.prototype.set = function (key, value) {
+    return this.dispatch("set", [key, value]);
+};
+
+/**
+ * Deletes a property in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of property to delete
+ * @return promise for the return value
+ */
+Q.del = // XXX legacy
+Q["delete"] = function (object, key) {
+    return Q(object).dispatch("delete", [key]);
+};
+
+Promise.prototype.del = // XXX legacy
+Promise.prototype["delete"] = function (key) {
+    return this.dispatch("delete", [key]);
+};
+
+/**
+ * Invokes a method in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of method to invoke
+ * @param value     a value to post, typically an array of
+ *                  invocation arguments for promises that
+ *                  are ultimately backed with `resolve` values,
+ *                  as opposed to those backed with URLs
+ *                  wherein the posted value can be any
+ *                  JSON serializable object.
+ * @return promise for the return value
+ */
+// bound locally because it is used by other methods
+Q.mapply = // XXX As proposed by "Redsandro"
+Q.post = function (object, name, args) {
+    return Q(object).dispatch("post", [name, args]);
+};
+
+Promise.prototype.mapply = // XXX As proposed by "Redsandro"
+Promise.prototype.post = function (name, args) {
+    return this.dispatch("post", [name, args]);
+};
+
+/**
+ * Invokes a method in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @param name      name of method to invoke
+ * @param ...args   array of invocation arguments
+ * @return promise for the return value
+ */
+Q.send = // XXX Mark Miller's proposed parlance
+Q.mcall = // XXX As proposed by "Redsandro"
+Q.invoke = function (object, name /*...args*/) {
+    return Q(object).dispatch("post", [name, array_slice(arguments, 2)]);
+};
+
+Promise.prototype.send = // XXX Mark Miller's proposed parlance
+Promise.prototype.mcall = // XXX As proposed by "Redsandro"
+Promise.prototype.invoke = function (name /*...args*/) {
+    return this.dispatch("post", [name, array_slice(arguments, 1)]);
+};
+
+/**
+ * Applies the promised function in a future turn.
+ * @param object    promise or immediate reference for target function
+ * @param args      array of application arguments
+ */
+Q.fapply = function (object, args) {
+    return Q(object).dispatch("apply", [void 0, args]);
+};
+
+Promise.prototype.fapply = function (args) {
+    return this.dispatch("apply", [void 0, args]);
+};
+
+/**
+ * Calls the promised function in a future turn.
+ * @param object    promise or immediate reference for target function
+ * @param ...args   array of application arguments
+ */
+Q["try"] =
+Q.fcall = function (object /* ...args*/) {
+    return Q(object).dispatch("apply", [void 0, array_slice(arguments, 1)]);
+};
+
+Promise.prototype.fcall = function (/*...args*/) {
+    return this.dispatch("apply", [void 0, array_slice(arguments)]);
+};
+
+/**
+ * Binds the promised function, transforming return values into a fulfilled
+ * promise and thrown errors into a rejected one.
+ * @param object    promise or immediate reference for target function
+ * @param ...args   array of application arguments
+ */
+Q.fbind = function (object /*...args*/) {
+    var promise = Q(object);
+    var args = array_slice(arguments, 1);
+    return function fbound() {
+        return promise.dispatch("apply", [
+            this,
+            args.concat(array_slice(arguments))
+        ]);
+    };
+};
+Promise.prototype.fbind = function (/*...args*/) {
+    var promise = this;
+    var args = array_slice(arguments);
+    return function fbound() {
+        return promise.dispatch("apply", [
+            this,
+            args.concat(array_slice(arguments))
+        ]);
+    };
+};
+
+/**
+ * Requests the names of the owned properties of a promised
+ * object in a future turn.
+ * @param object    promise or immediate reference for target object
+ * @return promise for the keys of the eventually settled object
+ */
+Q.keys = function (object) {
+    return Q(object).dispatch("keys", []);
+};
+
+Promise.prototype.keys = function () {
+    return this.dispatch("keys", []);
+};
+
+/**
+ * Turns an array of promises into a promise for an array.  If any of
+ * the promises gets rejected, the whole array is rejected immediately.
+ * @param {Array*} an array (or promise for an array) of values (or
+ * promises for values)
+ * @returns a promise for an array of the corresponding values
+ */
+// By Mark Miller
+// http://wiki.ecmascript.org/doku.php?id=strawman:concurrency&rev=1308776521#allfulfilled
+Q.all = all;
+function all(promises) {
+    return when(promises, function (promises) {
+        var countDown = 0;
+        var deferred = defer();
+        array_reduce(promises, function (undefined, promise, index) {
+            var snapshot;
+            if (
+                isPromise(promise) &&
+                (snapshot = promise.inspect()).state === "fulfilled"
+            ) {
+                promises[index] = snapshot.value;
+            } else {
+                ++countDown;
+                when(
+                    promise,
+                    function (value) {
+                        promises[index] = value;
+                        if (--countDown === 0) {
+                            deferred.resolve(promises);
+                        }
+                    },
+                    deferred.reject,
+                    function (progress) {
+                        deferred.notify({ index: index, value: progress });
+                    }
+                );
+            }
+        }, void 0);
+        if (countDown === 0) {
+            deferred.resolve(promises);
+        }
+        return deferred.promise;
+    });
+}
+
+Promise.prototype.all = function () {
+    return all(this);
+};
+
+/**
+ * Waits for all promises to be settled, either fulfilled or
+ * rejected.  This is distinct from `all` since that would stop
+ * waiting at the first rejection.  The promise returned by
+ * `allResolved` will never be rejected.
+ * @param promises a promise for an array (or an array) of promises
+ * (or values)
+ * @return a promise for an array of promises
+ */
+Q.allResolved = deprecate(allResolved, "allResolved", "allSettled");
+function allResolved(promises) {
+    return when(promises, function (promises) {
+        promises = array_map(promises, Q);
+        return when(all(array_map(promises, function (promise) {
+            return when(promise, noop, noop);
+        })), function () {
+            return promises;
+        });
+    });
+}
+
+Promise.prototype.allResolved = function () {
+    return allResolved(this);
+};
+
+/**
+ * @see Promise#allSettled
+ */
+Q.allSettled = allSettled;
+function allSettled(promises) {
+    return Q(promises).allSettled();
+}
+
+/**
+ * Turns an array of promises into a promise for an array of their states (as
+ * returned by `inspect`) when they have all settled.
+ * @param {Array[Any*]} values an array (or promise for an array) of values (or
+ * promises for values)
+ * @returns {Array[State]} an array of states for the respective values.
+ */
+Promise.prototype.allSettled = function () {
+    return this.then(function (promises) {
+        return all(array_map(promises, function (promise) {
+            promise = Q(promise);
+            function regardless() {
+                return promise.inspect();
+            }
+            return promise.then(regardless, regardless);
+        }));
+    });
+};
+
+/**
+ * Captures the failure of a promise, giving an oportunity to recover
+ * with a callback.  If the given promise is fulfilled, the returned
+ * promise is fulfilled.
+ * @param {Any*} promise for something
+ * @param {Function} callback to fulfill the returned promise if the
+ * given promise is rejected
+ * @returns a promise for the return value of the callback
+ */
+Q.fail = // XXX legacy
+Q["catch"] = function (object, rejected) {
+    return Q(object).then(void 0, rejected);
+};
+
+Promise.prototype.fail = // XXX legacy
+Promise.prototype["catch"] = function (rejected) {
+    return this.then(void 0, rejected);
+};
+
+/**
+ * Attaches a listener that can respond to progress notifications from a
+ * promise's originating deferred. This listener receives the exact arguments
+ * passed to ``deferred.notify``.
+ * @param {Any*} promise for something
+ * @param {Function} callback to receive any progress notifications
+ * @returns the given promise, unchanged
+ */
+Q.progress = progress;
+function progress(object, progressed) {
+    return Q(object).then(void 0, void 0, progressed);
+}
+
+Promise.prototype.progress = function (progressed) {
+    return this.then(void 0, void 0, progressed);
+};
+
+/**
+ * Provides an opportunity to observe the settling of a promise,
+ * regardless of whether the promise is fulfilled or rejected.  Forwards
+ * the resolution to the returned promise when the callback is done.
+ * The callback can return a promise to defer completion.
+ * @param {Any*} promise
+ * @param {Function} callback to observe the resolution of the given
+ * promise, takes no arguments.
+ * @returns a promise for the resolution of the given promise when
+ * ``fin`` is done.
+ */
+Q.fin = // XXX legacy
+Q["finally"] = function (object, callback) {
+    return Q(object)["finally"](callback);
+};
+
+Promise.prototype.fin = // XXX legacy
+Promise.prototype["finally"] = function (callback) {
+    callback = Q(callback);
+    return this.then(function (value) {
+        return callback.fcall().then(function () {
+            return value;
+        });
+    }, function (reason) {
+        // TODO attempt to recycle the rejection with "this".
+        return callback.fcall().then(function () {
+            throw reason;
+        });
+    });
+};
+
+/**
+ * Terminates a chain of promises, forcing rejections to be
+ * thrown as exceptions.
+ * @param {Any*} promise at the end of a chain of promises
+ * @returns nothing
+ */
+Q.done = function (object, fulfilled, rejected, progress) {
+    return Q(object).done(fulfilled, rejected, progress);
+};
+
+Promise.prototype.done = function (fulfilled, rejected, progress) {
+    var onUnhandledError = function (error) {
+        // forward to a future turn so that ``when``
+        // does not catch it and turn it into a rejection.
+        nextTick(function () {
+            makeStackTraceLong(error, promise);
+            if (Q.onerror) {
+                Q.onerror(error);
+            } else {
+                throw error;
+            }
+        });
+    };
+
+    // Avoid unnecessary `nextTick`ing via an unnecessary `when`.
+    var promise = fulfilled || rejected || progress ?
+        this.then(fulfilled, rejected, progress) :
+        this;
+
+    if (typeof process === "object" && process && process.domain) {
+        onUnhandledError = process.domain.bind(onUnhandledError);
+    }
+
+    promise.then(void 0, onUnhandledError);
+};
+
+/**
+ * Causes a promise to be rejected if it does not get fulfilled before
+ * some milliseconds time out.
+ * @param {Any*} promise
+ * @param {Number} milliseconds timeout
+ * @param {String} custom error message (optional)
+ * @returns a promise for the resolution of the given promise if it is
+ * fulfilled before the timeout, otherwise rejected.
+ */
+Q.timeout = function (object, ms, message) {
+    return Q(object).timeout(ms, message);
+};
+
+Promise.prototype.timeout = function (ms, message) {
+    var deferred = defer();
+    var timeoutId = setTimeout(function () {
+        deferred.reject(new Error(message || "Timed out after " + ms + " ms"));
+    }, ms);
+
+    this.then(function (value) {
+        clearTimeout(timeoutId);
+        deferred.resolve(value);
+    }, function (exception) {
+        clearTimeout(timeoutId);
+        deferred.reject(exception);
+    }, deferred.notify);
+
+    return deferred.promise;
+};
+
+/**
+ * Returns a promise for the given value (or promised value), some
+ * milliseconds after it resolved. Passes rejections immediately.
+ * @param {Any*} promise
+ * @param {Number} milliseconds
+ * @returns a promise for the resolution of the given promise after milliseconds
+ * time has elapsed since the resolution of the given promise.
+ * If the given promise rejects, that is passed immediately.
+ */
+Q.delay = function (object, timeout) {
+    if (timeout === void 0) {
+        timeout = object;
+        object = void 0;
+    }
+    return Q(object).delay(timeout);
+};
+
+Promise.prototype.delay = function (timeout) {
+    return this.then(function (value) {
+        var deferred = defer();
+        setTimeout(function () {
+            deferred.resolve(value);
+        }, timeout);
+        return deferred.promise;
+    });
+};
+
+/**
+ * Passes a continuation to a Node function, which is called with the given
+ * arguments provided as an array, and returns a promise.
+ *
+ *      Q.nfapply(FS.readFile, [__filename])
+ *      .then(function (content) {
+ *      })
+ *
+ */
+Q.nfapply = function (callback, args) {
+    return Q(callback).nfapply(args);
+};
+
+Promise.prototype.nfapply = function (args) {
+    var deferred = defer();
+    var nodeArgs = array_slice(args);
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.fapply(nodeArgs).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * Passes a continuation to a Node function, which is called with the given
+ * arguments provided individually, and returns a promise.
+ * @example
+ * Q.nfcall(FS.readFile, __filename)
+ * .then(function (content) {
+ * })
+ *
+ */
+Q.nfcall = function (callback /*...args*/) {
+    var args = array_slice(arguments, 1);
+    return Q(callback).nfapply(args);
+};
+
+Promise.prototype.nfcall = function (/*...args*/) {
+    var nodeArgs = array_slice(arguments);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.fapply(nodeArgs).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * Wraps a NodeJS continuation passing function and returns an equivalent
+ * version that returns a promise.
+ * @example
+ * Q.nfbind(FS.readFile, __filename)("utf-8")
+ * .then(console.log)
+ * .done()
+ */
+Q.nfbind =
+Q.denodeify = function (callback /*...args*/) {
+    var baseArgs = array_slice(arguments, 1);
+    return function () {
+        var nodeArgs = baseArgs.concat(array_slice(arguments));
+        var deferred = defer();
+        nodeArgs.push(deferred.makeNodeResolver());
+        Q(callback).fapply(nodeArgs).fail(deferred.reject);
+        return deferred.promise;
+    };
+};
+
+Promise.prototype.nfbind =
+Promise.prototype.denodeify = function (/*...args*/) {
+    var args = array_slice(arguments);
+    args.unshift(this);
+    return Q.denodeify.apply(void 0, args);
+};
+
+Q.nbind = function (callback, thisp /*...args*/) {
+    var baseArgs = array_slice(arguments, 2);
+    return function () {
+        var nodeArgs = baseArgs.concat(array_slice(arguments));
+        var deferred = defer();
+        nodeArgs.push(deferred.makeNodeResolver());
+        function bound() {
+            return callback.apply(thisp, arguments);
+        }
+        Q(bound).fapply(nodeArgs).fail(deferred.reject);
+        return deferred.promise;
+    };
+};
+
+Promise.prototype.nbind = function (/*thisp, ...args*/) {
+    var args = array_slice(arguments, 0);
+    args.unshift(this);
+    return Q.nbind.apply(void 0, args);
+};
+
+/**
+ * Calls a method of a Node-style object that accepts a Node-style
+ * callback with a given array of arguments, plus a provided callback.
+ * @param object an object that has the named method
+ * @param {String} name name of the method of object
+ * @param {Array} args arguments to pass to the method; the callback
+ * will be provided by Q and appended to these arguments.
+ * @returns a promise for the value or error
+ */
+Q.nmapply = // XXX As proposed by "Redsandro"
+Q.npost = function (object, name, args) {
+    return Q(object).npost(name, args);
+};
+
+Promise.prototype.nmapply = // XXX As proposed by "Redsandro"
+Promise.prototype.npost = function (name, args) {
+    var nodeArgs = array_slice(args || []);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * Calls a method of a Node-style object that accepts a Node-style
+ * callback, forwarding the given variadic arguments, plus a provided
+ * callback argument.
+ * @param object an object that has the named method
+ * @param {String} name name of the method of object
+ * @param ...args arguments to pass to the method; the callback will
+ * be provided by Q and appended to these arguments.
+ * @returns a promise for the value or error
+ */
+Q.nsend = // XXX Based on Mark Miller's proposed "send"
+Q.nmcall = // XXX Based on "Redsandro's" proposal
+Q.ninvoke = function (object, name /*...args*/) {
+    var nodeArgs = array_slice(arguments, 2);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    Q(object).dispatch("post", [name, nodeArgs]).fail(deferred.reject);
+    return deferred.promise;
+};
+
+Promise.prototype.nsend = // XXX Based on Mark Miller's proposed "send"
+Promise.prototype.nmcall = // XXX Based on "Redsandro's" proposal
+Promise.prototype.ninvoke = function (name /*...args*/) {
+    var nodeArgs = array_slice(arguments, 1);
+    var deferred = defer();
+    nodeArgs.push(deferred.makeNodeResolver());
+    this.dispatch("post", [name, nodeArgs]).fail(deferred.reject);
+    return deferred.promise;
+};
+
+/**
+ * If a function would like to support both Node continuation-passing-style and
+ * promise-returning-style, it can end its internal promise chain with
+ * `nodeify(nodeback)`, forwarding the optional nodeback argument.  If the user
+ * elects to use a nodeback, the result will be sent there.  If they do not
+ * pass a nodeback, they will receive the result promise.
+ * @param object a result (or a promise for a result)
+ * @param {Function} nodeback a Node.js-style callback
+ * @returns either the promise or nothing
+ */
+Q.nodeify = nodeify;
+function nodeify(object, nodeback) {
+    return Q(object).nodeify(nodeback);
+}
+
+Promise.prototype.nodeify = function (nodeback) {
+    if (nodeback) {
+        this.then(function (value) {
+            nextTick(function () {
+                nodeback(null, value);
+            });
+        }, function (error) {
+            nextTick(function () {
+                nodeback(error);
+            });
+        });
+    } else {
+        return this;
+    }
+};
+
+// All code before this point will be filtered from stack traces.
+var qEndingLine = captureLine();
+
+return Q;
+
+});

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/node_modules/q/queue.js
----------------------------------------------------------------------
diff --git a/bin/node_modules/q/queue.js b/bin/node_modules/q/queue.js
new file mode 100644
index 0000000..1505fd0
--- /dev/null
+++ b/bin/node_modules/q/queue.js
@@ -0,0 +1,35 @@
+
+var Q = require("./q");
+
+module.exports = Queue;
+function Queue() {
+    var ends = Q.defer();
+    var closed = Q.defer();
+    return {
+        put: function (value) {
+            var next = Q.defer();
+            ends.resolve({
+                head: value,
+                tail: next.promise
+            });
+            ends.resolve = next.resolve;
+        },
+        get: function () {
+            var result = ends.promise.get("head");
+            ends.promise = ends.promise.get("tail");
+            return result.fail(function (error) {
+                closed.resolve(error);
+                throw error;
+            });
+        },
+        closed: closed.promise,
+        close: function (error) {
+            error = error || new Error("Can't get value from closed queue");
+            var end = {head: Q.reject(error)};
+            end.tail = end;
+            ends.resolve(end);
+            return closed.promise;
+        }
+    };
+}
+

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/node_modules/which/LICENSE
----------------------------------------------------------------------
diff --git a/bin/node_modules/which/LICENSE b/bin/node_modules/which/LICENSE
new file mode 100644
index 0000000..05a4010
--- /dev/null
+++ b/bin/node_modules/which/LICENSE
@@ -0,0 +1,23 @@
+Copyright 2009, 2010, 2011 Isaac Z. Schlueter.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/node_modules/which/README.md
----------------------------------------------------------------------
diff --git a/bin/node_modules/which/README.md b/bin/node_modules/which/README.md
new file mode 100644
index 0000000..ff1eb53
--- /dev/null
+++ b/bin/node_modules/which/README.md
@@ -0,0 +1,5 @@
+The "which" util from npm's guts.
+
+Finds the first instance of a specified executable in the PATH
+environment variable.  Does not cache the results, so `hash -r` is not
+needed when the PATH changes.

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/node_modules/which/bin/which
----------------------------------------------------------------------
diff --git a/bin/node_modules/which/bin/which b/bin/node_modules/which/bin/which
new file mode 100755
index 0000000..8432ce2
--- /dev/null
+++ b/bin/node_modules/which/bin/which
@@ -0,0 +1,14 @@
+#!/usr/bin/env node
+var which = require("../")
+if (process.argv.length < 3) {
+  console.error("Usage: which <thing>")
+  process.exit(1)
+}
+
+which(process.argv[2], function (er, thing) {
+  if (er) {
+    console.error(er.message)
+    process.exit(er.errno || 127)
+  }
+  console.log(thing)
+})

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/node_modules/which/package.json
----------------------------------------------------------------------
diff --git a/bin/node_modules/which/package.json b/bin/node_modules/which/package.json
new file mode 100644
index 0000000..6c5ccb3
--- /dev/null
+++ b/bin/node_modules/which/package.json
@@ -0,0 +1,31 @@
+{
+  "author": {
+    "name": "Isaac Z. Schlueter",
+    "email": "i@izs.me",
+    "url": "http://blog.izs.me"
+  },
+  "name": "which",
+  "description": "Like which(1) unix command. Find the first instance of an executable in the PATH.",
+  "version": "1.0.5",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/node-which.git"
+  },
+  "main": "which.js",
+  "bin": {
+    "which": "./bin/which"
+  },
+  "engines": {
+    "node": "*"
+  },
+  "dependencies": {},
+  "devDependencies": {},
+  "readme": "The \"which\" util from npm's guts.\n\nFinds the first instance of a specified executable in the PATH\nenvironment variable.  Does not cache the results, so `hash -r` is not\nneeded when the PATH changes.\n",
+  "readmeFilename": "README.md",
+  "bugs": {
+    "url": "https://github.com/isaacs/node-which/issues"
+  },
+  "homepage": "https://github.com/isaacs/node-which",
+  "_id": "which@1.0.5",
+  "_from": "which@"
+}

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/node_modules/which/which.js
----------------------------------------------------------------------
diff --git a/bin/node_modules/which/which.js b/bin/node_modules/which/which.js
new file mode 100644
index 0000000..db7e8f7
--- /dev/null
+++ b/bin/node_modules/which/which.js
@@ -0,0 +1,104 @@
+module.exports = which
+which.sync = whichSync
+
+var path = require("path")
+  , fs
+  , COLON = process.platform === "win32" ? ";" : ":"
+  , isExe
+
+try {
+  fs = require("graceful-fs")
+} catch (ex) {
+  fs = require("fs")
+}
+
+if (process.platform == "win32") {
+  // On windows, there is no good way to check that a file is executable
+  isExe = function isExe () { return true }
+} else {
+  isExe = function isExe (mod, uid, gid) {
+    //console.error(mod, uid, gid);
+    //console.error("isExe?", (mod & 0111).toString(8))
+    var ret = (mod & 0001)
+        || (mod & 0010) && process.getgid && gid === process.getgid()
+        || (mod & 0100) && process.getuid && uid === process.getuid()
+    //console.error("isExe?", ret)
+    return ret
+  }
+}
+
+
+
+function which (cmd, cb) {
+  if (isAbsolute(cmd)) return cb(null, cmd)
+  var pathEnv = (process.env.PATH || "").split(COLON)
+    , pathExt = [""]
+  if (process.platform === "win32") {
+    pathEnv.push(process.cwd())
+    pathExt = (process.env.PATHEXT || ".EXE").split(COLON)
+    if (cmd.indexOf(".") !== -1) pathExt.unshift("")
+  }
+  //console.error("pathEnv", pathEnv)
+  ;(function F (i, l) {
+    if (i === l) return cb(new Error("not found: "+cmd))
+    var p = path.resolve(pathEnv[i], cmd)
+    ;(function E (ii, ll) {
+      if (ii === ll) return F(i + 1, l)
+      var ext = pathExt[ii]
+      //console.error(p + ext)
+      fs.stat(p + ext, function (er, stat) {
+        if (!er &&
+            stat &&
+            stat.isFile() &&
+            isExe(stat.mode, stat.uid, stat.gid)) {
+          //console.error("yes, exe!", p + ext)
+          return cb(null, p + ext)
+        }
+        return E(ii + 1, ll)
+      })
+    })(0, pathExt.length)
+  })(0, pathEnv.length)
+}
+
+function whichSync (cmd) {
+  if (isAbsolute(cmd)) return cmd
+  var pathEnv = (process.env.PATH || "").split(COLON)
+    , pathExt = [""]
+  if (process.platform === "win32") {
+    pathEnv.push(process.cwd())
+    pathExt = (process.env.PATHEXT || ".EXE").split(COLON)
+    if (cmd.indexOf(".") !== -1) pathExt.unshift("")
+  }
+  for (var i = 0, l = pathEnv.length; i < l; i ++) {
+    var p = path.join(pathEnv[i], cmd)
+    for (var j = 0, ll = pathExt.length; j < ll; j ++) {
+      var cur = p + pathExt[j]
+      var stat
+      try { stat = fs.statSync(cur) } catch (ex) {}
+      if (stat &&
+          stat.isFile() &&
+          isExe(stat.mode, stat.uid, stat.gid)) return cur
+    }
+  }
+  throw new Error("not found: "+cmd)
+}
+
+var isAbsolute = process.platform === "win32" ? absWin : absUnix
+
+function absWin (p) {
+  if (absUnix(p)) return true
+  // pull off the device/UNC bit from a windows path.
+  // from node's lib/path.js
+  var splitDeviceRe =
+        /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?/
+    , result = splitDeviceRe.exec(p)
+    , device = result[1] || ''
+    , isUnc = device && device.charAt(1) !== ':'
+    , isAbsolute = !!result[2] || isUnc // UNC paths are always absolute
+
+  return isAbsolute
+}
+
+function absUnix (p) {
+  return p.charAt(0) === "/" || p === ""
+}

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/replaces
----------------------------------------------------------------------
diff --git a/bin/replaces b/bin/replaces
deleted file mode 100755
index 4aee85a..0000000
--- a/bin/replaces
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /bin/sh
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-# 
-# http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#  KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-# 
-# USAGE
-#   ./replaces path from to
-#
-# EXAMPLE
-#   ./replaces ./foo.txt FOO BAR
-#
-sed "s/$2/$3/g" "$1" > tmpFile ; mv tmpFile "$1"

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/templates/scripts/cordova/version
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/version b/bin/templates/scripts/cordova/version
index c2dcab0..566a73b 100755
--- a/bin/templates/scripts/cordova/version
+++ b/bin/templates/scripts/cordova/version
@@ -1,29 +1,30 @@
-#!/bin/bash
+#!/usr/bin/env node
 
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-# 
-# http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#  KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
 
-#
-# Returns the VERSION of CordovaLib used. 
-# Note: it does not work if the --shared option was used to create the project.
-#
+    http://www.apache.org/licenses/LICENSE-2.0
 
-VERSION="3.8.0-dev"
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
 
-echo $VERSION 
+/*
+
+    Returns the VERSION of CordovaLib used.
+    Note: it does not work if the --shared option was used to create the project.
+*/
+
+var VERSION = "3.8.0-dev";
+
+console.log(VERSION);

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/templates/scripts/cordova/version.bat
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/version.bat b/bin/templates/scripts/cordova/version.bat
new file mode 100644
index 0000000..84c86b4
--- /dev/null
+++ b/bin/templates/scripts/cordova/version.bat
@@ -0,0 +1,26 @@
+:: Licensed to the Apache Software Foundation (ASF) under one
+:: or more contributor license agreements. See the NOTICE file
+:: distributed with this work for additional information
+:: regarding copyright ownership. The ASF licenses this file
+:: to you under the Apache License, Version 2.0 (the
+:: "License"); you may not use this file except in compliance
+:: with the License. You may obtain a copy of the License at
+::
+:: http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing,
+:: software distributed under the License is distributed on an
+:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+:: KIND, either express or implied. See the License for the
+:: specific language governing permissions and limitations
+:: under the License.
+
+@ECHO OFF
+SET script="%~dp0version"
+IF EXIST %script% (
+    node %script% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'version' script in 'cordova' folder, aborting...>&2
+    EXIT /B 1
+)

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/update
----------------------------------------------------------------------
diff --git a/bin/update b/bin/update
index 0a97a0e..5ea1974 100755
--- a/bin/update
+++ b/bin/update
@@ -1,79 +1,30 @@
 #!/usr/bin/env node
 
 /*
-       Licensed to the Apache Software Foundation (ASF) under one
-       or more contributor license agreements.  See the NOTICE file
-       distributed with this work for additional information
-       regarding copyright ownership.  The ASF licenses this file
-       to you under the Apache License, Version 2.0 (the
-       "License"); you may not use this file except in compliance
-       with the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing,
-       software distributed under the License is distributed on an
-       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-       KIND, either express or implied.  See the License for the
-       specific language governing permissions and limitations
-       under the License.
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
 */
-var shell = require('shelljs'),
-    path  = require('path'),
-    fs    = require('fs'),
-    ROOT    = path.join(__dirname, '..');
-
-function setShellFatal(value, func) {
-    var oldVal = shell.config.fatal;
-    shell.config.fatal = value;
-    func();
-    shell.config.fatal = oldVal;
-}
-
-function copyJsAndCordovaLib(projectPath) {
-    shell.cp('-f', path.join(ROOT, 'CordovaLib', 'cordova.js'), path.join(projectPath, 'www'));
-    shell.rm('-rf', path.join(projectPath, 'CordovaLib'));
-    shell.cp('-r', path.join(ROOT, 'CordovaLib'), projectPath);
-    // Ensure no workspace files got copied over.
-    var entries = fs.readdirSync(path.join(projectPath, 'CordovaLib', 'CordovaLib.xcodeproj'));
-    entries.forEach(function(p) {
-        if (/.*xc.*/.test(p)) {
-            shell.rm('-rf', path.join(projectPath, 'CordovaLib', 'CordovaLib.xcodeproj', p));
-        }
-    });
-}
-
-function copyScripts(projectPath) {
-    var srcScriptsDir = path.join(ROOT, 'bin', 'templates', 'scripts', 'cordova');
-    var destScriptsDir = path.join(projectPath, 'cordova');
-    // Delete old scripts directory.
-    shell.rm('-rf', destScriptsDir);
-    // Copy in the new ones.
-    shell.cp('-r', srcScriptsDir, projectPath);
-    shell.cp(path.join(ROOT, 'bin', 'check_reqs'), path.join(destScriptsDir, 'check_reqs'));
-    // Make sure they are executable.
-    shell.find(destScriptsDir).forEach(function(entry) {
-        shell.chmod(755, entry);
-    });
-}
 
-exports.updateProject = function(projectPath) {
-    var version = fs.readFileSync(path.join(ROOT, 'CordovaLib', 'VERSION'), 'utf-8').trim();
-    setShellFatal(true, function() {
-        copyJsAndCordovaLib(projectPath);
-        copyScripts(projectPath);
-        console.log('iOS project is now at version ' + version);
-    });
-};
+var update = require('./lib/update');
 
-if (require.main === module) {
-    (function() {
-        var args = process.argv;
-        if (args.length < 3 || (args[2] == '--help' || args[2] == '-h')) {
-            console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'update')) + ' <path_to_project>');
-            process.exit(1);
-        } else {
-            exports.updateProject(args[2]);
-        }
-    })();
+var args = process.argv;
+if (args.length < 3 || (args[2] == '--help' || args[2] == '-h')) {
+    console.log('Usage: ' + path.relative(process.cwd(), path.join(__dirname, 'update')) + ' <path_to_project>');
+    process.exit(1);
+} else {
+    update.updateProject(args[2]);
 }

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/update.bat
----------------------------------------------------------------------
diff --git a/bin/update.bat b/bin/update.bat
new file mode 100644
index 0000000..48c451a
--- /dev/null
+++ b/bin/update.bat
@@ -0,0 +1,26 @@
+:: Licensed to the Apache Software Foundation (ASF) under one
+:: or more contributor license agreements. See the NOTICE file
+:: distributed with this work for additional information
+:: regarding copyright ownership. The ASF licenses this file
+:: to you under the Apache License, Version 2.0 (the
+:: "License"); you may not use this file except in compliance
+:: with the License. You may obtain a copy of the License at
+::
+:: http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing,
+:: software distributed under the License is distributed on an
+:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+:: KIND, either express or implied. See the License for the
+:: specific language governing permissions and limitations
+:: under the License.
+
+@ECHO OFF
+SET script="%~dp0update"
+IF EXIST %script% (
+    node %script% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'update' script in 'bin' folder, aborting...>&2
+    EXIT /B 1
+)

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/update_cordova_subproject
----------------------------------------------------------------------
diff --git a/bin/update_cordova_subproject b/bin/update_cordova_subproject
index 07b257a..88e933e 100755
--- a/bin/update_cordova_subproject
+++ b/bin/update_cordova_subproject
@@ -1,106 +1,31 @@
-#!/usr/bin/python
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-"""
-Updates the subproject path of the CordovaLib entry to point to this script's version of Cordova.
-
-Usage: CordovaVersion/bin/update_cordova_project path/to/your/app.xcodeproj [path/to/CordovaLib.xcodeproj]
-"""
-
-import fileinput
-import os
-import re
-import sys
-from posixpath import curdir, sep, pardir, join, abspath, commonprefix
-
-def Usage():
-  print __doc__
-  sys.exit(1)
-
-def AbsParentPath(path):
-  return os.path.abspath(os.path.join(path, os.path.pardir))
-
-def AbsFrameworkPath(argv0):
-  script_path = argv0
-  # This can happen if the script's dir is in the user's PATH
-  if not os.path.exists(script_path):
-    raise Exception('Could not locale framework directory.')
-  return AbsParentPath(AbsParentPath(script_path))
-
-def AbsProjectPath(relative_path):
-  # Do an extra abspath here to strip off trailing / if present.
-  project_path = os.path.abspath(relative_path)
-  if project_path.endswith('.pbxproj'):
-    project_path = AbsParentPath(project_path)
-  elif project_path.endswith('.xcodeproj'):
-    pass
-  else:
-    raise Exception('The following is not a valid path to an XCode project: %s' % project_path)
-  return project_path
-
-def relpath(path, start=curdir):
-  # it would be nice to use os.path.relpath, 
-  # but that leaves out those with python < v2.6
-  if not path:
-    raise ValueError("no path specified")
-  start_list = abspath(start).split(sep)
-  path_list = abspath(path).split(sep)
-  # Work out how much of the filepath is shared by start and path.
-  i = len(commonprefix([start_list, path_list]))
-  rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
-  if not rel_list:
-    return curdir
-  return join(*rel_list)
-
-
-def main(argv):
-  if len(argv) < 2 or len(argv) > 3:
-    Usage()
-
-  project_path = AbsProjectPath(argv[1])
-  if len(argv) < 3:
-    framework_path = AbsFrameworkPath(argv[0])
-    cordova_lib_xcode_path = os.path.join(framework_path, 'CordovaLib', 'CordovaLib.xcodeproj')
-  else:
-    cordova_lib_xcode_path = AbsProjectPath(argv[2])
-
-  parent_project_path = AbsParentPath(project_path)
-  subproject_path = relpath(cordova_lib_xcode_path, parent_project_path)
-
-  # /* CordovaLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = CordovaLib.xcodeproj; sourceTree = "<group>"; };
-  REGEX = re.compile(r'(.+PBXFileReference.+wrapper.pb-project.+)(path = .+?;)(.*)(sourceTree.+;)(.+)')
-
-  file_handle = fileinput.input(os.path.join(project_path, 'project.pbxproj'), inplace=1)
-  found = False
-  for line in file_handle:
-    if 'CordovaLib.xcodeproj' in line:
-      m = REGEX.match(line)
-      if m:
-        found = True
-        line = m.expand(r'\1path = "%s";\3sourceTree = "<group>";\5\n') % subproject_path
-        if 'name =' not in line:
-            line = line.replace('path = ', 'name = CordovaLib.xcodeproj; path = ')
-    print line,
-  file_handle.close()
-
-  if not found:
-    raise Exception('Sub-project entry not found in project file.')
-  print('CordovaLib set to path: %s' % subproject_path)
-
-
-if __name__ == '__main__':
-  main(sys.argv)
+#!/usr/bin/env node
+
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+var create = require('./lib/create'),
+    args;
+
+if (process.argv.length < 3) {
+    create.updateSubprojectHelp();
+}
+else {
+    args = process.argv.slice(2);
+    create.update_cordova_subproject(args);
+}

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/update_cordova_subproject.bat
----------------------------------------------------------------------
diff --git a/bin/update_cordova_subproject.bat b/bin/update_cordova_subproject.bat
new file mode 100644
index 0000000..1f1c1c9
--- /dev/null
+++ b/bin/update_cordova_subproject.bat
@@ -0,0 +1,26 @@
+:: Licensed to the Apache Software Foundation (ASF) under one
+:: or more contributor license agreements. See the NOTICE file
+:: distributed with this work for additional information
+:: regarding copyright ownership. The ASF licenses this file
+:: to you under the Apache License, Version 2.0 (the
+:: "License"); you may not use this file except in compliance
+:: with the License. You may obtain a copy of the License at
+::
+:: http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing,
+:: software distributed under the License is distributed on an
+:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+:: KIND, either express or implied. See the License for the
+:: specific language governing permissions and limitations
+:: under the License.
+
+@ECHO OFF
+SET script="%~dp0update_cordova_subproject"
+IF EXIST %script% (
+    node %script% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'update_cordova_subproject' script in 'bin' folder, aborting...>&2
+    EXIT /B 1
+)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[07/10] ios commit: [CB-8044] updated run script to properly handle --nobuild flag in all cases

Posted by sh...@apache.org.
[CB-8044] updated run script to properly handle --nobuild flag in all cases


Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/b53b305d
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/b53b305d
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/b53b305d

Branch: refs/heads/wkwebview
Commit: b53b305d88ce3b9cf74232c083d962e5b6d778da
Parents: 19e9545
Author: Lorin Beer <lo...@gmail.com>
Authored: Fri Dec 12 13:22:40 2014 -0800
Committer: Lorin Beer <lo...@gmail.com>
Committed: Fri Dec 12 13:22:40 2014 -0800

----------------------------------------------------------------------
 bin/templates/scripts/cordova/run | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/b53b305d/bin/templates/scripts/cordova/run
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/run b/bin/templates/scripts/cordova/run
index f66f703..12633bf 100755
--- a/bin/templates/scripts/cordova/run
+++ b/bin/templates/scripts/cordova/run
@@ -115,7 +115,7 @@ if "$USE_DEVICE"; then
         USE_SIMULATOR=true
     else
         # if we got here, we can deploy the app, then exit success
-        if [ ! $NO_BUILD ]; then
+        if ! [ "$NO_BUILD" = true ]; then
             "$CORDOVA_PATH/build" --device || exit $?
         fi
         ios-deploy -d -b "$DEVICE_APP_PATH"
@@ -139,7 +139,7 @@ if "$USE_SIMULATOR"; then
     fi
     
     # launch using ios-sim
-    if [ ! $NO_BUILD ]; then
+    if ! [ "$NO_BUILD" = true ]; then
         "$CORDOVA_PATH/build" --emulator || exit $?
     fi
     ios-sim launch "$SIMULATOR_APP_PATH" --stderr "$CORDOVA_PATH/console.log" --stdout "$CORDOVA_PATH/console.log" --devicetypeid com.apple.CoreSimulator.SimDeviceType.$TARGET --exit


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[05/10] ios commit: [CB-8044] support for --nobuild flag

Posted by sh...@apache.org.
[CB-8044] support for --nobuild flag


Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/9ea4c782
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/9ea4c782
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/9ea4c782

Branch: refs/heads/wkwebview
Commit: 9ea4c782c64beec4a9c569f9ca61575bd25a733e
Parents: ea2a946
Author: Lorin Beer <lo...@gmail.com>
Authored: Fri Dec 12 11:38:54 2014 -0800
Committer: Lorin Beer <lo...@gmail.com>
Committed: Fri Dec 12 11:38:54 2014 -0800

----------------------------------------------------------------------
 bin/templates/scripts/cordova/run | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/9ea4c782/bin/templates/scripts/cordova/run
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/run b/bin/templates/scripts/cordova/run
index ff60876..12334ac 100755
--- a/bin/templates/scripts/cordova/run
+++ b/bin/templates/scripts/cordova/run
@@ -37,6 +37,9 @@ TARGET="iPhone-6"
 USE_DEVICE=true
 USE_SIMULATOR=false
 
+# options
+NO_BUILD=false
+
 # separates "key=value", sets an array with 0th index as key, 1st index as value
 _parseOption()
 {
@@ -71,6 +74,9 @@ _parseArgs()
       USE_DEVICE=false
       USE_SIMULATOR=true
       ;;
+    "--nobuild")
+      NO_BUILD=true
+      ;;
     esac
   done
 }
@@ -109,7 +115,9 @@ if "$USE_DEVICE"; then
         USE_SIMULATOR=true
     else
         # if we got here, we can deploy the app, then exit success
-        "$CORDOVA_PATH/build" --device || exit $?
+        if [ ! $NO_BUILD ] then
+            "$CORDOVA_PATH/build" --device || exit $?
+        fi
         ios-deploy -d -b "$DEVICE_APP_PATH"
     	exit 0
     fi
@@ -131,7 +139,9 @@ if "$USE_SIMULATOR"; then
     fi
     
     # launch using ios-sim
-    "$CORDOVA_PATH/build" --emulator || exit $?
+    if [ ! $NO_BUILD ] then
+        "$CORDOVA_PATH/build" --emulator || exit $?
+    fi
     ios-sim launch "$SIMULATOR_APP_PATH" --stderr "$CORDOVA_PATH/console.log" --stdout "$CORDOVA_PATH/console.log" --devicetypeid com.apple.CoreSimulator.SimDeviceType.$TARGET --exit
 fi
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[02/10] ios commit: CB-5706 convert some of the bash scripts to nodejs (closes #118)

Posted by sh...@apache.org.
CB-5706 convert some of the bash scripts to nodejs (closes #118)


Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/dd54d96b
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/dd54d96b
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/dd54d96b

Branch: refs/heads/wkwebview
Commit: dd54d96bd0eddb7f8967d0d1fcfb90f2635ed22a
Parents: 5769d58
Author: Edna Morales <ed...@gmail.com>
Authored: Mon Nov 3 15:18:05 2014 -0500
Committer: Shazron Abdullah <sh...@apache.org>
Committed: Wed Nov 19 16:26:28 2014 -0800

----------------------------------------------------------------------
 bin/apple_ios_version                           |   47 +-
 bin/apple_ios_version.bat                       |   26 +
 bin/apple_osx_version                           |   47 +-
 bin/apple_osx_version.bat                       |   26 +
 bin/apple_xcode_version                         |   47 +-
 bin/apple_xcode_version.bat                     |   26 +
 bin/create                                      |  205 +-
 bin/create.bat                                  |   26 +
 bin/lib/create.js                               |  255 +++
 bin/lib/update.js                               |   72 +
 bin/lib/versions.js                             |  101 +
 bin/node_modules/q/CONTRIBUTING.md              |   40 +
 bin/node_modules/q/LICENSE                      |   18 +
 bin/node_modules/q/README.md                    |  820 ++++++++
 .../q/benchmark/compare-with-callbacks.js       |   71 +
 bin/node_modules/q/benchmark/scenarios.js       |   36 +
 bin/node_modules/q/package.json                 |  112 ++
 bin/node_modules/q/q.js                         | 1904 ++++++++++++++++++
 bin/node_modules/q/queue.js                     |   35 +
 bin/node_modules/which/LICENSE                  |   23 +
 bin/node_modules/which/README.md                |    5 +
 bin/node_modules/which/bin/which                |   14 +
 bin/node_modules/which/package.json             |   31 +
 bin/node_modules/which/which.js                 |  104 +
 bin/replaces                                    |   28 -
 bin/templates/scripts/cordova/version           |   51 +-
 bin/templates/scripts/cordova/version.bat       |   26 +
 bin/update                                      |   95 +-
 bin/update.bat                                  |   26 +
 bin/update_cordova_subproject                   |  137 +-
 bin/update_cordova_subproject.bat               |   26 +
 31 files changed, 4019 insertions(+), 461 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/apple_ios_version
----------------------------------------------------------------------
diff --git a/bin/apple_ios_version b/bin/apple_ios_version
index 8a5aa7d..d397bb6 100755
--- a/bin/apple_ios_version
+++ b/bin/apple_ios_version
@@ -1,24 +1,27 @@
-#! /bin/sh
+#!/usr/bin/env node
 
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#  KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
 
-# outputs the highest level of iOS sdk installed
-iOS_X_VERSIONS=$(xcodebuild -showsdks | sed -e '/./{H;$!d;}' -e 'x;/iOS SDKs/!d;' | grep -o '[0-9]*\.[0-9]* ');
-echo $iOS_X_VERSIONS | tr " " "\n" | sort -g | tail -1;
\ No newline at end of file
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+var versions = require('./lib/versions.js');
+
+versions.get_apple_ios_version().done(null, function(err) {
+    console.log(err);
+    process.exit(2);
+});

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/apple_ios_version.bat
----------------------------------------------------------------------
diff --git a/bin/apple_ios_version.bat b/bin/apple_ios_version.bat
new file mode 100644
index 0000000..8219312
--- /dev/null
+++ b/bin/apple_ios_version.bat
@@ -0,0 +1,26 @@
+:: Licensed to the Apache Software Foundation (ASF) under one
+:: or more contributor license agreements. See the NOTICE file
+:: distributed with this work for additional information
+:: regarding copyright ownership. The ASF licenses this file
+:: to you under the Apache License, Version 2.0 (the
+:: "License"); you may not use this file except in compliance
+:: with the License. You may obtain a copy of the License at
+::
+:: http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing,
+:: software distributed under the License is distributed on an
+:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+:: KIND, either express or implied. See the License for the
+:: specific language governing permissions and limitations
+:: under the License.
+
+@ECHO OFF
+SET script="%~dp0apple_ios_version"
+IF EXIST %script% (
+    node %script% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'apple_ios_version' script in 'bin' folder, aborting...>&2
+    EXIT /B 1
+)

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/apple_osx_version
----------------------------------------------------------------------
diff --git a/bin/apple_osx_version b/bin/apple_osx_version
index 401e9cb..6e697ad 100755
--- a/bin/apple_osx_version
+++ b/bin/apple_osx_version
@@ -1,24 +1,27 @@
-#! /bin/sh
+#!/usr/bin/env node
 
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#  KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
 
-# outputs the highest level of OS X sdk installed
-OS_X_VERSIONS=$(xcodebuild -showsdks | sed -e '/./{H;$!d;}' -e 'x;/OS X SDKs/!d;' | grep -o '[0-9]*\.[0-9]* ');
-echo $OS_X_VERSIONS | tr " " "\n" | sort -g | tail -1;
\ No newline at end of file
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+var versions = require('./lib/versions.js');
+
+versions.get_apple_osx_version().done(null, function(err) {
+    console.log(err);
+    process.exit(2);
+});

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/apple_osx_version.bat
----------------------------------------------------------------------
diff --git a/bin/apple_osx_version.bat b/bin/apple_osx_version.bat
new file mode 100644
index 0000000..d2acec7
--- /dev/null
+++ b/bin/apple_osx_version.bat
@@ -0,0 +1,26 @@
+:: Licensed to the Apache Software Foundation (ASF) under one
+:: or more contributor license agreements. See the NOTICE file
+:: distributed with this work for additional information
+:: regarding copyright ownership. The ASF licenses this file
+:: to you under the Apache License, Version 2.0 (the
+:: "License"); you may not use this file except in compliance
+:: with the License. You may obtain a copy of the License at
+::
+:: http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing,
+:: software distributed under the License is distributed on an
+:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+:: KIND, either express or implied. See the License for the
+:: specific language governing permissions and limitations
+:: under the License.
+
+@ECHO OFF
+SET script="%~dp0apple_osx_version"
+IF EXIST %script% (
+    node %script% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'apple_osx_version' script in 'bin' folder, aborting...>&2
+    EXIT /B 1
+)

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/apple_xcode_version
----------------------------------------------------------------------
diff --git a/bin/apple_xcode_version b/bin/apple_xcode_version
index d459b30..5dfe501 100755
--- a/bin/apple_xcode_version
+++ b/bin/apple_xcode_version
@@ -1,24 +1,27 @@
-#! /bin/sh
+#!/usr/bin/env node
 
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#  KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
 
-# outputs which version of XCODE is installed
-XCODEBUILD_VERSION=$(xcodebuild -version | head -n 1 | sed -e 's/Xcode //')
-echo $XCODEBUILD_VERSION
\ No newline at end of file
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+var versions = require('./lib/versions.js');
+
+versions.get_apple_xcode_version().done(null, function(err) {
+    console.log(err);
+    process.exit(2);
+});

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/apple_xcode_version.bat
----------------------------------------------------------------------
diff --git a/bin/apple_xcode_version.bat b/bin/apple_xcode_version.bat
new file mode 100644
index 0000000..c19f911
--- /dev/null
+++ b/bin/apple_xcode_version.bat
@@ -0,0 +1,26 @@
+:: Licensed to the Apache Software Foundation (ASF) under one
+:: or more contributor license agreements. See the NOTICE file
+:: distributed with this work for additional information
+:: regarding copyright ownership. The ASF licenses this file
+:: to you under the Apache License, Version 2.0 (the
+:: "License"); you may not use this file except in compliance
+:: with the License. You may obtain a copy of the License at
+::
+:: http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing,
+:: software distributed under the License is distributed on an
+:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+:: KIND, either express or implied. See the License for the
+:: specific language governing permissions and limitations
+:: under the License.
+
+@ECHO OFF
+SET script="%~dp0apple_xcode_version"
+IF EXIST %script% (
+    node %script% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'apple_xcode_version' script in 'bin' folder, aborting...>&2
+    EXIT /B 1
+)

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/create
----------------------------------------------------------------------
diff --git a/bin/create b/bin/create
index b652adf..eeffc10 100755
--- a/bin/create
+++ b/bin/create
@@ -1,165 +1,42 @@
-#! /bin/sh
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#  KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-#
-# create a Cordova/iOS project
-#
-# USAGE
-#   ./create <path_to_new_project> <package_name> <project_name>
-#
-# EXAMPLE
-#  ./create ~/Desktop/radness org.apache.cordova.radness Radness
-#
-set -e
-
-function usage() {
-  echo "Usage: $0 [--shared] [--cli] <path_to_new_project> <package_name> <project_name> [<project_template_dir>]"
-  echo "	--shared (optional): Link directly against the shared copy of the CordovaLib instead of a copy of it."
-  echo "	--cli (optional): Use the CLI-project template."
-  echo "	<path_to_new_project>: Path to your new Cordova iOS project"
-  echo "	<package_name>: Package name, following reverse-domain style convention"
-  echo "	<project_name>: Project name"
-  echo "	<project_template_dir>: Path to project template (override)."
-  exit 1
+#!/usr/bin/env node
+
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+/*
+ * create a Cordova/iOS project
+ *
+ * USAGE
+ *   ./create <path_to_new_project> <package_name> <project_name>
+ *
+ * EXAMPLE
+ *  ./create ~/Desktop/radness org.apache.cordova.radness Radness
+ */
+
+var create = require('./lib/create');
+
+if (process.argv.length < 3 || process.argv[2].indexOf('--help') > -1) {
+    create.createHelp();
+}
+else {
+    create.createProject(process.argv).done(null, function(err) {
+        console.error('Failed to create project because of error: ' + err);
+        process.exit(2);
+    });
 }
-
-USE_SHARED=0
-USE_CLI=0
-while [ $# -gt 0 ]; do
-    case "$1" in
-    --shared) USE_SHARED=1 ;;
-    --cli) USE_CLI=1 ;;
-    -*) ;;
-    *)
-        if [[ -z "$PROJECT_PATH" ]]; then
-            PROJECT_PATH="$1"
-        elif [[ -z "$PACKAGE" ]]; then
-            PACKAGE="$1"
-        elif [[ -z "$PROJECT_NAME" ]]; then
-            PROJECT_NAME="$1"
-        elif [[ -z "$PROJECT_TEMPLATE_DIR" ]]; then
-            PROJECT_TEMPLATE_DIR="$1"
-        else
-            echo "Too many arguments to $0". >&2
-            usage
-        fi
-    esac
-    shift
-done
-
-# check whether it is a proper create command (at least 3 arguments)
-if [[ -z "$PROJECT_NAME" ]]; then
-	usage
-fi
-
-# the two lines below are to get the current folder, and resolve symlinks
-SCRIPT="$0"
-# need this for relative symlinks
-while [ -h "$SCRIPT" ] ; do
-   SCRIPT=`readlink "$SCRIPT"`
-done
-
-BINDIR=$( cd "$( dirname "$SCRIPT" )" && pwd )
-CORDOVALIB_DIR="$BINDIR/../CordovaLib"
-CDV_VER=$(cat "$CORDOVALIB_DIR/VERSION")
-
-PROJECT_PARENT=$(dirname "$PROJECT_PATH")
-PROJECT_TEMPLATE_DIR=${PROJECT_TEMPLATE_DIR:-"$BINDIR/templates/project"}
-SCRIPT_TEMPLATE_DIR=$BINDIR/templates/scripts
-
-"$BINDIR/check_reqs" || exit $?
-
-# check whether the project path exists and is not empty
-if [ -d "$PROJECT_PATH" ]; then
-	if [ "$(ls -1A "$PROJECT_PATH")" ]; then
-		echo "\033[31mError: $PROJECT_PATH is not empty. Please specify an empty folder.\033[m"
-		exit 1
-	fi
-fi
-
-#Ensure the parent directory exists so cp -r will not fail
-if [ ! -d "$PROJECT_PARENT" ]; then
-	echo "\033[31mError: $PROJECT_PARENT does not exist. Please specify an existing parent folder.\033[m"
-	exit 1
-fi
-
-mkdir -p "$PROJECT_PATH"
-cp -r "$PROJECT_TEMPLATE_DIR/www" "$PROJECT_PATH"/www
-cp "$CORDOVALIB_DIR/cordova.js" "$PROJECT_PATH/www/cordova.js"
-if (($USE_CLI)); then
-    cp -r "$PROJECT_TEMPLATE_DIR/__CLI__.xcodeproj" "$PROJECT_PATH/$PROJECT_NAME.xcodeproj"
-else
-    cp -r "$PROJECT_TEMPLATE_DIR/__NON-CLI__.xcodeproj" "$PROJECT_PATH/$PROJECT_NAME.xcodeproj"
-fi
-cp -r "$PROJECT_TEMPLATE_DIR/__PROJECT_NAME__" "$PROJECT_PATH/$PROJECT_NAME"
-
-R=$PROJECT_PATH/$PROJECT_NAME
-mv "$R/__PROJECT_NAME__-Info.plist" "$R/$PROJECT_NAME-Info.plist"
-mv "$R/__PROJECT_NAME__-Prefix.pch" "$R/$PROJECT_NAME-Prefix.pch"
-mv "$R/gitignore" "$R/.gitignore"
-
-# replace __PROJECT_NAME__ and --ID-- with ACTIVITY and ID strings, respectively, in:
-#
-# - ./__PROJECT_NAME__.xcodeproj/project.pbxproj
-# - ./__PROJECT_NAME__/Classes/AppDelegate.h
-# - ./__PROJECT_NAME__/Classes/AppDelegate.m
-# - ./__PROJECT_NAME__/Resources/main.m
-# - ./__PROJECT_NAME__/Resources/__PROJECT_NAME__-info.plist
-# - ./__PROJECT_NAME__/Resources/__PROJECT_NAME__-Prefix.plist
-
-PROJECT_NAME_ESC="${PROJECT_NAME//&/\\&}"
-"$BINDIR/replaces" "$R.xcodeproj/project.pbxproj" __PROJECT_NAME__ "$PROJECT_NAME_ESC"
-"$BINDIR/replaces" "$R/Classes/AppDelegate.h"     __PROJECT_NAME__ "$PROJECT_NAME_ESC"
-"$BINDIR/replaces" "$R/Classes/AppDelegate.m"     __PROJECT_NAME__ "$PROJECT_NAME_ESC"
-"$BINDIR/replaces" "$R/Classes/MainViewController.h" __PROJECT_NAME__ "$PROJECT_NAME_ESC"
-"$BINDIR/replaces" "$R/Classes/MainViewController.m" __PROJECT_NAME__ "$PROJECT_NAME_ESC"
-"$BINDIR/replaces" "$R/main.m"                    __PROJECT_NAME__ "$PROJECT_NAME_ESC"
-"$BINDIR/replaces" "$R/$PROJECT_NAME-Info.plist"  __PROJECT_NAME__ "$PROJECT_NAME_ESC"
-"$BINDIR/replaces" "$R/$PROJECT_NAME-Prefix.pch"  __PROJECT_NAME__ "$PROJECT_NAME_ESC"
-
-"$BINDIR/replaces" "$R/$PROJECT_NAME-Info.plist" --ID-- $PACKAGE
-
-if [[ $USE_SHARED = 1 ]]; then
-    # Make the sub-project reference to Cordova have the correct path.
-    "$BINDIR/update_cordova_subproject" "$R.xcodeproj/project.pbxproj" > /dev/null
-else
-    # Copy in the CordovaLib directory.
-    mkdir -p "$PROJECT_PATH/CordovaLib/CordovaLib.xcodeproj"
-    cp "$R/.gitignore" "$PROJECT_PATH/"
-    cp -r "$BINDIR/../CordovaLib/Classes" "$PROJECT_PATH/CordovaLib"
-    cp "$BINDIR/../CordovaLib/VERSION" "$PROJECT_PATH/CordovaLib"
-    cp "$BINDIR/../CordovaLib/cordova.js" "$PROJECT_PATH/CordovaLib"
-    cp "$BINDIR/../CordovaLib/CordovaLib_Prefix.pch" "$PROJECT_PATH/CordovaLib"
-    cp "$BINDIR/../CordovaLib/CordovaLib.xcodeproj/project.pbxproj" "$PROJECT_PATH/CordovaLib/CordovaLib.xcodeproj"
-    # Make the sub-project reference to Cordova have the correct path.
-    "$BINDIR/update_cordova_subproject" "$R.xcodeproj/project.pbxproj" "$PROJECT_PATH/CordovaLib/CordovaLib.xcodeproj/project.pbxproj" > /dev/null
-fi
-
-# Finally copy the scripts
-cp -r "$SCRIPT_TEMPLATE_DIR"/* "$PROJECT_PATH/"
-
-# copy the check_reqs script
-cp "$BINDIR/check_reqs" "$PROJECT_PATH"/cordova
-
-# copy the version scripts script
-cp "$BINDIR/apple_ios_version" "$PROJECT_PATH"/cordova
-cp "$BINDIR/apple_osx_version" "$PROJECT_PATH"/cordova
-cp "$BINDIR/apple_xcode_version" "$PROJECT_PATH"/cordova

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/create.bat
----------------------------------------------------------------------
diff --git a/bin/create.bat b/bin/create.bat
new file mode 100644
index 0000000..43172a6
--- /dev/null
+++ b/bin/create.bat
@@ -0,0 +1,26 @@
+:: Licensed to the Apache Software Foundation (ASF) under one
+:: or more contributor license agreements. See the NOTICE file
+:: distributed with this work for additional information
+:: regarding copyright ownership. The ASF licenses this file
+:: to you under the Apache License, Version 2.0 (the
+:: "License"); you may not use this file except in compliance
+:: with the License. You may obtain a copy of the License at
+::
+:: http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing,
+:: software distributed under the License is distributed on an
+:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+:: KIND, either express or implied. See the License for the
+:: specific language governing permissions and limitations
+:: under the License.
+
+@ECHO OFF
+SET script="%~dp0create"
+IF EXIST %script% (
+    node %script% %*
+) ELSE (
+    ECHO.
+    ECHO ERROR: Could not find 'create' script in 'bin' folder, aborting...>&2
+    EXIT /B 1
+)

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/lib/create.js
----------------------------------------------------------------------
diff --git a/bin/lib/create.js b/bin/lib/create.js
new file mode 100755
index 0000000..8c37c80
--- /dev/null
+++ b/bin/lib/create.js
@@ -0,0 +1,255 @@
+#!/usr/bin/env node
+
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements. See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership. The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License. You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied. See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+var shell = require('shelljs'),
+    Q = require ('q'),
+    path = require('path'),
+    fs = require('fs'),
+    root = path.join(__dirname, '..', '..');
+
+function createHelp() {
+    console.log("Usage: $0 [--shared] [--cli] <path_to_new_project> <package_name> <project_name> [<project_template_dir>]");
+    console.log("   --shared (optional): Link directly against the shared copy of the CordovaLib instead of a copy of it.");
+    console.log("   --cli (optional): Use the CLI-project template.");
+    console.log("   <path_to_new_project>: Path to your new Cordova iOS project");
+    console.log("   <package_name>: Package name, following reverse-domain style convention");
+    console.log("   <project_name>: Project name");
+    console.log("   <project_template_dir>: Path to project template (override).");
+}
+
+function updateSubprojectHelp() {
+    console.log('Updates the subproject path of the CordovaLib entry to point to this script\'s version of Cordova.')
+    console.log("Usage: CordovaVersion/bin/update_cordova_project path/to/your/app.xcodeproj [path/to/CordovaLib.xcodeproj]");
+}
+
+function AbsParentPath(_path) {
+    return path.resolve(path.dirname(_path));
+}
+
+function AbsProjectPath(relative_path) {
+    var absolute_path = path.resolve(relative_path);
+    if (/.pbxproj$/.test(absolute_path)) {
+        absolute_path = AbsParentPath(absolute_path);
+    }
+    else if (!(/.xcodeproj$/.test(absolute_path))) {
+        throw new Error('The following is not a valid path to an Xcode project' + absolute_path);
+    }
+    return absolute_path;
+}
+
+function relpath(_path, start) {
+    start = start || process.cwd();
+    return path.relative(path.resolve(start), path.resolve(_path));
+}
+
+/*
+ * Creates a new iOS project with the following options:
+ *
+ * - --shared (optional): Link directly against the shared copy of the CordovaLib instead of a copy of it
+ * - --cli (optional): Use the CLI-project template
+ * - <path_to_new_project>: Path to your new Cordova iOS project
+ * - <package_name>: Package name, following reverse-domain style convention
+ * - <project_name>: Project name
+ * - <project_template_dir>: Path to a project template (override)
+ *
+ */
+
+exports.createProject = function(argv) {
+    var project_path,
+        package_name,
+        project_name,
+        project_template_dir,
+        use_shared = false,
+        use_cli = false;
+
+    //get arguments
+    var args = argv.slice(2);
+
+    //check and set arguments
+    if (args.length < 3)
+    {
+        createHelp();
+        return Q.reject('Too few arguments');
+    }
+
+    for (var i = 0; i < args.length; i++) {
+        if (args[i] === '--shared')
+            use_shared = true;
+        else if (args[i] === '--cli')
+            use_cli = true;
+        else
+        {
+            if (!project_path)
+                project_path = args[i];
+            else if (!package_name)
+                package_name = args[i];
+            else if (!project_name)
+                project_name = args[i];
+            else if (!project_template_dir)
+                project_template_dir = args[i];
+            else
+            {
+                createHelp();
+                return Q.reject('Too many arguments');
+            }
+        }
+    }
+
+    var bin_dir = path.join(root, 'bin'),
+        cordovalib_dir = path.join(root, 'CordovaLib'),
+        cordovalib_ver = fs.readFileSync(path.join(cordovalib_dir, 'VERSION'), 'utf-8').trim();
+        project_parent = path.dirname(project_path),
+        project_template_dir = project_template_dir ? project_template_dir : path.join(bin_dir, 'templates', 'project'),
+        script_template_dir = path.join(bin_dir, 'templates', 'scripts');
+
+    //check that project path doesn't exist
+    if (fs.existsSync(project_path)) {
+        return Q.reject('Project already exists');
+    }
+
+    //check that parent directory does exist so cp -r will not fail
+    if (!fs.existsSync(project_parent)) {
+        return Q.reject(project_parent + ' does not exist. Please specify an existing parent folder');
+    }
+
+    //create the project directory and copy over files
+    shell.mkdir('-p', project_path);
+    shell.cp('-rf', path.join(project_template_dir, 'www'), project_path);
+    shell.cp('-f', path.join(cordovalib_dir, 'cordova.js'), path.join(project_path, 'www', 'cordova.js'));
+    if (use_cli) {
+        shell.cp('-rf', path.join(project_template_dir, '__CLI__.xcodeproj'), project_path);
+        shell.mv(path.join(project_path, '__CLI__.xcodeproj'), path.join(project_path, project_name+'.xcodeproj'));
+    }
+    else {
+        shell.cp('-rf', path.join(project_template_dir, '__NON-CLI__.xcodeproj'), project_path);
+        shell.mv(path.join(project_path, '__NON-CLI__.xcodeproj'), path.join(project_path, project_name+'.xcodeproj'));
+    }
+    shell.cp('-rf', path.join(project_template_dir, '__PROJECT_NAME__'), project_path);
+    shell.mv(path.join(project_path, '__PROJECT_NAME__'), path.join(project_path, project_name));
+
+    var r = path.join(project_path, project_name);
+    shell.mv(path.join(r, '__PROJECT_NAME__-Info.plist'), path.join(r, project_name+'-Info.plist'));
+    shell.mv(path.join(r, '__PROJECT_NAME__-Prefix.pch'), path.join(r, project_name+'-Prefix.pch'));
+    shell.mv(path.join(r, 'gitignore'), path.join(r, '.gitignore'));
+
+    /*replace __PROJECT_NAME__ and --ID-- with ACTIVITY and ID strings, respectively, in:
+     *
+     * - ./__PROJECT_NAME__.xcodeproj/project.pbxproj
+     * - ./__PROJECT_NAME__/Classes/AppDelegate.h
+     * - ./__PROJECT_NAME__/Classes/AppDelegate.m
+     * - ./__PROJECT_NAME__/Resources/main.m
+     * - ./__PROJECT_NAME__/Resources/__PROJECT_NAME__-info.plist
+     * - ./__PROJECT_NAME__/Resources/__PROJECT_NAME__-Prefix.plist
+     */
+    var project_name_esc = project_name.replace(/&/g, '\\&');
+    shell.sed('-i', /__PROJECT_NAME__/g, project_name_esc, path.join(r+'.xcodeproj', 'project.pbxproj'));
+    shell.sed('-i', /__PROJECT_NAME__/g, project_name_esc, path.join(r, 'Classes', 'AppDelegate.h'));
+    shell.sed('-i', /__PROJECT_NAME__/g, project_name_esc, path.join(r, 'Classes', 'AppDelegate.m'));
+    shell.sed('-i', /__PROJECT_NAME__/g, project_name_esc, path.join(r, 'Classes', 'MainViewController.h'));
+    shell.sed('-i', /__PROJECT_NAME__/g, project_name_esc, path.join(r, 'Classes', 'MainViewController.m'));
+    shell.sed('-i', /__PROJECT_NAME__/g, project_name_esc, path.join(r, 'main.m'));
+    shell.sed('-i', /__PROJECT_NAME__/g, project_name_esc, path.join(r, project_name+'-Info.plist'));
+    shell.sed('-i', /__PROJECT_NAME__/g, project_name_esc, path.join(r, project_name+'-Prefix.pch'));
+    shell.sed('-i', /--ID--/g, package_name, path.join(r, project_name+'-Info.plist'));
+
+    //CordovaLib stuff
+    if (use_shared) {
+        update_cordova_subproject([path.join(r+'.xcodeproj', 'project.pbxproj')]);
+    }
+    else {
+        //copy in the CordovaLib directory
+        shell.mkdir('-p', path.join(project_path, 'CordovaLib', 'CordovaLib.xcodeproj'));
+        shell.cp('-f', path.join(r, '.gitignore'), project_path);
+        shell.cp('-rf', path.join(bin_dir, '..', 'CordovaLib', 'Classes'), path.join(project_path, 'CordovaLib'));
+        shell.cp('-f', path.join(bin_dir, '..', 'CordovaLib', 'VERSION'), path.join(project_path, 'CordovaLib'));
+        shell.cp('-f', path.join(bin_dir, '..', 'CordovaLib', 'cordova.js'), path.join(project_path, 'CordovaLib'));
+        shell.cp('-f', path.join(bin_dir, '..', 'CordovaLib', 'CordovaLib_Prefix.pch'), path.join(project_path, 'CordovaLib'));
+        shell.cp('-f', path.join(bin_dir, '..', 'CordovaLib', 'CordovaLib.xcodeproj', 'project.pbxproj'), path.join(project_path, 'CordovaLib', 'CordovaLib.xcodeproj'));
+        update_cordova_subproject([path.join(r+'.xcodeproj', 'project.pbxproj'), path.join(project_path, 'CordovaLib', 'CordovaLib.xcodeproj', 'project.pbxproj')]);
+    }
+
+    //Finally copy the scripts
+    shell.cp('-r', path.join(script_template_dir, '*'), project_path);
+    shell.cp('-r', path.join(bin_dir, 'node_modules'), path.join(project_path, 'cordova'));
+
+    //copy the check_reqs script
+    shell.cp(path.join(bin_dir, 'check_reqs'), path.join(project_path, 'cordova'));
+
+    //copy the version scripts script
+    shell.cp(path.join(bin_dir, 'apple_ios_version'), path.join(project_path, 'cordova'));
+    shell.cp(path.join(bin_dir, 'apple_osx_version'), path.join(project_path, 'cordova'));
+    shell.cp(path.join(bin_dir, 'apple_xcode_version'), path.join(project_path, 'cordova'));
+    shell.cp(path.join(bin_dir, 'lib', 'versions.js'), path.join(project_path, 'cordova', 'lib'));
+
+    //Make scripts executable
+    shell.find(path.join(project_path, 'cordova')).forEach(function(entry) {
+        shell.chmod(755, entry);
+    });
+
+    return Q.resolve();
+}
+
+
+function update_cordova_subproject(argv) {
+    if (argv.length < 1 || argv.length > 2)
+    {
+        updateSubprojectHelp();
+        throw new Error('Usage error for update_cordova_subproject');
+    }
+
+    var projectPath = AbsProjectPath(argv[0]),
+        cordovaLibXcodePath;
+    if (argv.length < 2) {
+        cordovaLibXcodePath = path.join(root, 'CordovaLib', 'CordovaLib.xcodeproj');
+    }
+    else {
+        cordovaLibXcodePath = AbsProjectPath(argv[1]);
+    }
+
+    var parentProjectPath = AbsParentPath(projectPath),
+        subprojectPath = relpath(cordovaLibXcodePath, parentProjectPath),
+        REGEX = /(.+PBXFileReference.+wrapper.pb-project.+)(path = .+?;)(.*)(sourceTree.+;)(.+)/,
+        newLine,
+        lines = shell.grep('CordovaLib.xcodeproj', path.join(projectPath, 'project.pbxproj')),
+        found = false;
+
+    subprojectPath = subprojectPath.replace(/\\/g, '/');
+    lines = lines.split('\n');
+    for (var i = 0; i < lines.length; ++i) {
+        if (lines[i].match(REGEX)) {
+            found = true;
+            newLine = lines[i].replace(/path = .+?;/, 'path = ' + subprojectPath + ';');
+            newLine = newLine.replace(/sourceTree.+?;/, 'sourceTree = \"<group>\";');
+            if (!newLine.match('name')) {
+                newLine = newLine.replace('path = ', 'name = CordovaLib.xcodeproj; path = ');
+            }
+            shell.sed('-i', lines[i], newLine, path.join(projectPath, 'project.pbxproj'));
+        }
+    }
+
+    if (!found) {
+        throw new Error('Subproject: ' + subprojectPath + ' entry not found in project file');
+    }
+}
+
+exports.createHelp = createHelp;
+exports.updateSubprojectHelp = updateSubprojectHelp;
+exports.update_cordova_subproject = update_cordova_subproject;

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/lib/update.js
----------------------------------------------------------------------
diff --git a/bin/lib/update.js b/bin/lib/update.js
new file mode 100755
index 0000000..e023e58
--- /dev/null
+++ b/bin/lib/update.js
@@ -0,0 +1,72 @@
+#!/usr/bin/env node
+
+/*
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+*/
+var shell = require('shelljs'),
+    path  = require('path'),
+    fs    = require('fs'),
+    ROOT    = path.join(__dirname, '..', '..');
+
+function setShellFatal(value, func) {
+    var oldVal = shell.config.fatal;
+    shell.config.fatal = value;
+    func();
+    shell.config.fatal = oldVal;
+}
+
+function copyJsAndCordovaLib(projectPath) {
+    shell.cp('-f', path.join(ROOT, 'CordovaLib', 'cordova.js'), path.join(projectPath, 'www'));
+    shell.rm('-rf', path.join(projectPath, 'CordovaLib'));
+    shell.cp('-r', path.join(ROOT, 'CordovaLib'), projectPath);
+    // Ensure no workspace files got copied over.
+    var entries = fs.readdirSync(path.join(projectPath, 'CordovaLib', 'CordovaLib.xcodeproj'));
+    entries.forEach(function(p) {
+        if (/.*xc.*/.test(p)) {
+            shell.rm('-rf', path.join(projectPath, 'CordovaLib', 'CordovaLib.xcodeproj', p));
+        }
+    });
+}
+
+function copyScripts(projectPath) {
+    var srcScriptsDir = path.join(ROOT, 'bin', 'templates', 'scripts', 'cordova');
+    var destScriptsDir = path.join(projectPath, 'cordova');
+    // Delete old scripts directory.
+    shell.rm('-rf', destScriptsDir);
+    // Copy in the new ones.
+    shell.cp('-r', srcScriptsDir, projectPath);
+    shell.cp('-r', path.join(ROOT, 'bin', 'node_modules'), destScriptsDir);
+    shell.cp(path.join(ROOT, 'bin', 'check_reqs'), path.join(destScriptsDir, 'check_reqs'));
+    shell.cp(path.join(ROOT, 'bin', 'apple_ios_version'), destScriptsDir);
+    shell.cp(path.join(ROOT, 'bin', 'apple_osx_version'), destScriptsDir);
+    shell.cp(path.join(ROOT, 'bin', 'apple_xcode_version'), destScriptsDir);
+    shell.cp(path.join(ROOT, 'bin', 'lib', 'versions.js'), path.join(destScriptsDir, 'lib'));
+    // Make sure they are executable.
+    shell.find(destScriptsDir).forEach(function(entry) {
+        shell.chmod(755, entry);
+    });
+}
+
+exports.updateProject = function(projectPath) {
+    var version = fs.readFileSync(path.join(ROOT, 'CordovaLib', 'VERSION'), 'utf-8').trim();
+    setShellFatal(true, function() {
+        copyJsAndCordovaLib(projectPath);
+        copyScripts(projectPath);
+        console.log('iOS project is now at version ' + version);
+    });
+};

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/lib/versions.js
----------------------------------------------------------------------
diff --git a/bin/lib/versions.js b/bin/lib/versions.js
new file mode 100755
index 0000000..9a8eaec
--- /dev/null
+++ b/bin/lib/versions.js
@@ -0,0 +1,101 @@
+#!/usr/bin/env node
+
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+var child_process = require('child_process'),
+    Q = require('q');
+
+exports.get_apple_ios_version = function() {
+    var d = Q.defer();
+    child_process.exec('xcodebuild -showsdks', function(error, stdout, stderr) {
+        if (error) {
+            d.reject(stderr);
+        }
+        else {
+            d.resolve(stdout);
+        }
+    });
+
+    return d.promise.then(function(output) {
+        var regex = /[0-9]*\.[0-9]*/,
+            versions = [],
+            regexIOS = /^iOS \d+/;
+        output = output.split('\n');
+        for (var i = 0; i < output.length; i++) {
+            if (output[i].trim().match(regexIOS)) {
+                versions[versions.length] = parseFloat(output[i].match(regex)[0]);
+                }
+        }
+        versions.sort();
+        console.log(versions[0]);
+        return Q();
+    }, function(stderr) {
+        return Q.reject(stderr);
+    });
+}
+
+exports.get_apple_osx_version = function() {
+    var d = Q.defer();
+    child_process.exec('xcodebuild -showsdks', function(error, stdout, stderr) {
+        if (error) {
+            d.reject(stderr);
+        }
+        else {
+            d.resolve(stdout);
+        }
+    });
+
+    return d.promise.then(function(output) {
+        var regex = /[0-9]*\.[0-9]*/,
+            versions = [],
+            regexOSX = /^OS X \d+/;
+        output = output.split('\n');
+        for (var i = 0; i < output.length; i++) {
+            if (output[i].trim().match(regexOSX)) {
+                versions[versions.length] = parseFloat(output[i].match(regex)[0]);
+            }
+        }
+        versions.sort();
+        console.log(versions[0]);
+        return Q();
+    }, function(stderr) {
+        return Q.reject(stderr);
+    });
+}
+
+exports.get_apple_xcode_version = function() {
+    var d = Q.defer();
+    child_process.exec('xcodebuild -version', function(error, stdout, stderr) {
+        if (error) {
+            d.reject(stderr);
+        }
+        else {
+            d.resolve(stdout);
+        }
+    });
+
+    return d.promise.then(function(output) {
+        output = output.split('\n');
+        console.log(output[0].slice(6));
+        return Q();
+    }, function(stderr) {
+        return Q.reject(stderr);
+    });
+}

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/node_modules/q/CONTRIBUTING.md
----------------------------------------------------------------------
diff --git a/bin/node_modules/q/CONTRIBUTING.md b/bin/node_modules/q/CONTRIBUTING.md
new file mode 100644
index 0000000..500ab17
--- /dev/null
+++ b/bin/node_modules/q/CONTRIBUTING.md
@@ -0,0 +1,40 @@
+
+For pull requests:
+
+-   Be consistent with prevalent style and design decisions.
+-   Add a Jasmine spec to `specs/q-spec.js`.
+-   Use `npm test` to avoid regressions.
+-   Run tests in `q-spec/run.html` in as many supported browsers as you
+    can find the will to deal with.
+-   Do not build minified versions; we do this each release.
+-   If you would be so kind, add a note to `CHANGES.md` in an
+    appropriate section:
+
+    -   `Next Major Version` if it introduces backward incompatibilities
+        to code in the wild using documented features.
+    -   `Next Minor Version` if it adds a new feature.
+    -   `Next Patch Version` if it fixes a bug.
+
+For releases:
+
+-   Run `npm test`.
+-   Run tests in `q-spec/run.html` in a representative sample of every
+    browser under the sun.
+-   Run `npm run cover` and make sure you're happy with the results.
+-   Run `npm run minify` and be sure to commit the resulting `q.min.js`.
+-   Note the Gzipped size output by the previous command, and update
+    `README.md` if it has changed to 1 significant digit.
+-   Stash any local changes.
+-   Update `CHANGES.md` to reflect all changes in the differences
+    between `HEAD` and the previous tagged version.  Give credit where
+    credit is due.
+-   Update `README.md` to address all new, non-experimental features.
+-   Update the API reference on the Wiki to reflect all non-experimental
+    features.
+-   Use `npm version major|minor|patch` to update `package.json`,
+    commit, and tag the new version.
+-   Use `npm publish` to send up a new release.
+-   Send an email to the q-continuum mailing list announcing the new
+    release and the notes from the change log.  This helps folks
+    maintaining other package ecosystems.
+

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/node_modules/q/LICENSE
----------------------------------------------------------------------
diff --git a/bin/node_modules/q/LICENSE b/bin/node_modules/q/LICENSE
new file mode 100644
index 0000000..8a706b5
--- /dev/null
+++ b/bin/node_modules/q/LICENSE
@@ -0,0 +1,18 @@
+Copyright 2009–2014 Kristopher Michael Kowal. All rights reserved.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/node_modules/q/README.md
----------------------------------------------------------------------
diff --git a/bin/node_modules/q/README.md b/bin/node_modules/q/README.md
new file mode 100644
index 0000000..bdd4168
--- /dev/null
+++ b/bin/node_modules/q/README.md
@@ -0,0 +1,820 @@
+[![Build Status](https://secure.travis-ci.org/kriskowal/q.png?branch=master)](http://travis-ci.org/kriskowal/q)
+
+<a href="http://promises-aplus.github.com/promises-spec">
+    <img src="http://promises-aplus.github.com/promises-spec/assets/logo-small.png"
+         align="right" alt="Promises/A+ logo" />
+</a>
+
+*This is Q version 1, from the `v1` branch in Git. This documentation applies to
+the latest of both the version 1 and version 0.9 release trains. These releases
+are stable. There will be no further releases of 0.9 after 0.9.7 which is nearly
+equivalent to version 1.0.0. All further releases of `q@~1.0` will be backward
+compatible. The version 2 release train introduces significant but
+backward-incompatible changes and is experimental at this time.*
+
+If a function cannot return a value or throw an exception without
+blocking, it can return a promise instead.  A promise is an object
+that represents the return value or the thrown exception that the
+function may eventually provide.  A promise can also be used as a
+proxy for a [remote object][Q-Connection] to overcome latency.
+
+[Q-Connection]: https://github.com/kriskowal/q-connection
+
+On the first pass, promises can mitigate the “[Pyramid of
+Doom][POD]”: the situation where code marches to the right faster
+than it marches forward.
+
+[POD]: http://calculist.org/blog/2011/12/14/why-coroutines-wont-work-on-the-web/
+
+```javascript
+step1(function (value1) {
+    step2(value1, function(value2) {
+        step3(value2, function(value3) {
+            step4(value3, function(value4) {
+                // Do something with value4
+            });
+        });
+    });
+});
+```
+
+With a promise library, you can flatten the pyramid.
+
+```javascript
+Q.fcall(promisedStep1)
+.then(promisedStep2)
+.then(promisedStep3)
+.then(promisedStep4)
+.then(function (value4) {
+    // Do something with value4
+})
+.catch(function (error) {
+    // Handle any error from all above steps
+})
+.done();
+```
+
+With this approach, you also get implicit error propagation, just like `try`,
+`catch`, and `finally`.  An error in `promisedStep1` will flow all the way to
+the `catch` function, where it’s caught and handled.  (Here `promisedStepN` is
+a version of `stepN` that returns a promise.)
+
+The callback approach is called an “inversion of control”.
+A function that accepts a callback instead of a return value
+is saying, “Don’t call me, I’ll call you.”.  Promises
+[un-invert][IOC] the inversion, cleanly separating the input
+arguments from control flow arguments.  This simplifies the
+use and creation of API’s, particularly variadic,
+rest and spread arguments.
+
+[IOC]: http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript
+
+
+## Getting Started
+
+The Q module can be loaded as:
+
+-   A ``<script>`` tag (creating a ``Q`` global variable): ~2.5 KB minified and
+    gzipped.
+-   A Node.js and CommonJS module, available in [npm](https://npmjs.org/) as
+    the [q](https://npmjs.org/package/q) package
+-   An AMD module
+-   A [component](https://github.com/component/component) as ``microjs/q``
+-   Using [bower](http://bower.io/) as ``q``
+-   Using [NuGet](http://nuget.org/) as [Q](https://nuget.org/packages/q)
+
+Q can exchange promises with jQuery, Dojo, When.js, WinJS, and more.
+
+## Resources
+
+Our [wiki][] contains a number of useful resources, including:
+
+- A method-by-method [Q API reference][reference].
+- A growing [examples gallery][examples], showing how Q can be used to make
+  everything better. From XHR to database access to accessing the Flickr API,
+  Q is there for you.
+- There are many libraries that produce and consume Q promises for everything
+  from file system/database access or RPC to templating. For a list of some of
+  the more popular ones, see [Libraries][].
+- If you want materials that introduce the promise concept generally, and the
+  below tutorial isn't doing it for you, check out our collection of
+  [presentations, blog posts, and podcasts][resources].
+- A guide for those [coming from jQuery's `$.Deferred`][jquery].
+
+We'd also love to have you join the Q-Continuum [mailing list][].
+
+[wiki]: https://github.com/kriskowal/q/wiki
+[reference]: https://github.com/kriskowal/q/wiki/API-Reference
+[examples]: https://github.com/kriskowal/q/wiki/Examples-Gallery
+[Libraries]: https://github.com/kriskowal/q/wiki/Libraries
+[resources]: https://github.com/kriskowal/q/wiki/General-Promise-Resources
+[jquery]: https://github.com/kriskowal/q/wiki/Coming-from-jQuery
+[mailing list]: https://groups.google.com/forum/#!forum/q-continuum
+
+
+## Tutorial
+
+Promises have a ``then`` method, which you can use to get the eventual
+return value (fulfillment) or thrown exception (rejection).
+
+```javascript
+promiseMeSomething()
+.then(function (value) {
+}, function (reason) {
+});
+```
+
+If ``promiseMeSomething`` returns a promise that gets fulfilled later
+with a return value, the first function (the fulfillment handler) will be
+called with the value.  However, if the ``promiseMeSomething`` function
+gets rejected later by a thrown exception, the second function (the
+rejection handler) will be called with the exception.
+
+Note that resolution of a promise is always asynchronous: that is, the
+fulfillment or rejection handler will always be called in the next turn of the
+event loop (i.e. `process.nextTick` in Node). This gives you a nice
+guarantee when mentally tracing the flow of your code, namely that
+``then`` will always return before either handler is executed.
+
+In this tutorial, we begin with how to consume and work with promises. We'll
+talk about how to create them, and thus create functions like
+`promiseMeSomething` that return promises, [below](#the-beginning).
+
+
+### Propagation
+
+The ``then`` method returns a promise, which in this example, I’m
+assigning to ``outputPromise``.
+
+```javascript
+var outputPromise = getInputPromise()
+.then(function (input) {
+}, function (reason) {
+});
+```
+
+The ``outputPromise`` variable becomes a new promise for the return
+value of either handler.  Since a function can only either return a
+value or throw an exception, only one handler will ever be called and it
+will be responsible for resolving ``outputPromise``.
+
+-   If you return a value in a handler, ``outputPromise`` will get
+    fulfilled.
+
+-   If you throw an exception in a handler, ``outputPromise`` will get
+    rejected.
+
+-   If you return a **promise** in a handler, ``outputPromise`` will
+    “become” that promise.  Being able to become a new promise is useful
+    for managing delays, combining results, or recovering from errors.
+
+If the ``getInputPromise()`` promise gets rejected and you omit the
+rejection handler, the **error** will go to ``outputPromise``:
+
+```javascript
+var outputPromise = getInputPromise()
+.then(function (value) {
+});
+```
+
+If the input promise gets fulfilled and you omit the fulfillment handler, the
+**value** will go to ``outputPromise``:
+
+```javascript
+var outputPromise = getInputPromise()
+.then(null, function (error) {
+});
+```
+
+Q promises provide a ``fail`` shorthand for ``then`` when you are only
+interested in handling the error:
+
+```javascript
+var outputPromise = getInputPromise()
+.fail(function (error) {
+});
+```
+
+If you are writing JavaScript for modern engines only or using
+CoffeeScript, you may use `catch` instead of `fail`.
+
+Promises also have a ``fin`` function that is like a ``finally`` clause.
+The final handler gets called, with no arguments, when the promise
+returned by ``getInputPromise()`` either returns a value or throws an
+error.  The value returned or error thrown by ``getInputPromise()``
+passes directly to ``outputPromise`` unless the final handler fails, and
+may be delayed if the final handler returns a promise.
+
+```javascript
+var outputPromise = getInputPromise()
+.fin(function () {
+    // close files, database connections, stop servers, conclude tests
+});
+```
+
+-   If the handler returns a value, the value is ignored
+-   If the handler throws an error, the error passes to ``outputPromise``
+-   If the handler returns a promise, ``outputPromise`` gets postponed.  The
+    eventual value or error has the same effect as an immediate return
+    value or thrown error: a value would be ignored, an error would be
+    forwarded.
+
+If you are writing JavaScript for modern engines only or using
+CoffeeScript, you may use `finally` instead of `fin`.
+
+### Chaining
+
+There are two ways to chain promises.  You can chain promises either
+inside or outside handlers.  The next two examples are equivalent.
+
+```javascript
+return getUsername()
+.then(function (username) {
+    return getUser(username)
+    .then(function (user) {
+        // if we get here without an error,
+        // the value returned here
+        // or the exception thrown here
+        // resolves the promise returned
+        // by the first line
+    })
+});
+```
+
+```javascript
+return getUsername()
+.then(function (username) {
+    return getUser(username);
+})
+.then(function (user) {
+    // if we get here without an error,
+    // the value returned here
+    // or the exception thrown here
+    // resolves the promise returned
+    // by the first line
+});
+```
+
+The only difference is nesting.  It’s useful to nest handlers if you
+need to capture multiple input values in your closure.
+
+```javascript
+function authenticate() {
+    return getUsername()
+    .then(function (username) {
+        return getUser(username);
+    })
+    // chained because we will not need the user name in the next event
+    .then(function (user) {
+        return getPassword()
+        // nested because we need both user and password next
+        .then(function (password) {
+            if (user.passwordHash !== hash(password)) {
+                throw new Error("Can't authenticate");
+            }
+        });
+    });
+}
+```
+
+
+### Combination
+
+You can turn an array of promises into a promise for the whole,
+fulfilled array using ``all``.
+
+```javascript
+return Q.all([
+    eventualAdd(2, 2),
+    eventualAdd(10, 20)
+]);
+```
+
+If you have a promise for an array, you can use ``spread`` as a
+replacement for ``then``.  The ``spread`` function “spreads” the
+values over the arguments of the fulfillment handler.  The rejection handler
+will get called at the first sign of failure.  That is, whichever of
+the recived promises fails first gets handled by the rejection handler.
+
+```javascript
+function eventualAdd(a, b) {
+    return Q.spread([a, b], function (a, b) {
+        return a + b;
+    })
+}
+```
+
+But ``spread`` calls ``all`` initially, so you can skip it in chains.
+
+```javascript
+return getUsername()
+.then(function (username) {
+    return [username, getUser(username)];
+})
+.spread(function (username, user) {
+});
+```
+
+The ``all`` function returns a promise for an array of values.  When this
+promise is fulfilled, the array contains the fulfillment values of the original
+promises, in the same order as those promises.  If one of the given promises
+is rejected, the returned promise is immediately rejected, not waiting for the
+rest of the batch.  If you want to wait for all of the promises to either be
+fulfilled or rejected, you can use ``allSettled``.
+
+```javascript
+Q.allSettled(promises)
+.then(function (results) {
+    results.forEach(function (result) {
+        if (result.state === "fulfilled") {
+            var value = result.value;
+        } else {
+            var reason = result.reason;
+        }
+    });
+});
+```
+
+
+### Sequences
+
+If you have a number of promise-producing functions that need
+to be run sequentially, you can of course do so manually:
+
+```javascript
+return foo(initialVal).then(bar).then(baz).then(qux);
+```
+
+However, if you want to run a dynamically constructed sequence of
+functions, you'll want something like this:
+
+```javascript
+var funcs = [foo, bar, baz, qux];
+
+var result = Q(initialVal);
+funcs.forEach(function (f) {
+    result = result.then(f);
+});
+return result;
+```
+
+You can make this slightly more compact using `reduce`:
+
+```javascript
+return funcs.reduce(function (soFar, f) {
+    return soFar.then(f);
+}, Q(initialVal));
+```
+
+Or, you could use th ultra-compact version:
+
+```javascript
+return funcs.reduce(Q.when, Q());
+```
+
+### Handling Errors
+
+One sometimes-unintuive aspect of promises is that if you throw an
+exception in the fulfillment handler, it will not be be caught by the error
+handler.
+
+```javascript
+return foo()
+.then(function (value) {
+    throw new Error("Can't bar.");
+}, function (error) {
+    // We only get here if "foo" fails
+});
+```
+
+To see why this is, consider the parallel between promises and
+``try``/``catch``. We are ``try``-ing to execute ``foo()``: the error
+handler represents a ``catch`` for ``foo()``, while the fulfillment handler
+represents code that happens *after* the ``try``/``catch`` block.
+That code then needs its own ``try``/``catch`` block.
+
+In terms of promises, this means chaining your rejection handler:
+
+```javascript
+return foo()
+.then(function (value) {
+    throw new Error("Can't bar.");
+})
+.fail(function (error) {
+    // We get here with either foo's error or bar's error
+});
+```
+
+### Progress Notification
+
+It's possible for promises to report their progress, e.g. for tasks that take a
+long time like a file upload. Not all promises will implement progress
+notifications, but for those that do, you can consume the progress values using
+a third parameter to ``then``:
+
+```javascript
+return uploadFile()
+.then(function () {
+    // Success uploading the file
+}, function (err) {
+    // There was an error, and we get the reason for error
+}, function (progress) {
+    // We get notified of the upload's progress as it is executed
+});
+```
+
+Like `fail`, Q also provides a shorthand for progress callbacks
+called `progress`:
+
+```javascript
+return uploadFile().progress(function (progress) {
+    // We get notified of the upload's progress
+});
+```
+
+### The End
+
+When you get to the end of a chain of promises, you should either
+return the last promise or end the chain.  Since handlers catch
+errors, it’s an unfortunate pattern that the exceptions can go
+unobserved.
+
+So, either return it,
+
+```javascript
+return foo()
+.then(function () {
+    return "bar";
+});
+```
+
+Or, end it.
+
+```javascript
+foo()
+.then(function () {
+    return "bar";
+})
+.done();
+```
+
+Ending a promise chain makes sure that, if an error doesn’t get
+handled before the end, it will get rethrown and reported.
+
+This is a stopgap. We are exploring ways to make unhandled errors
+visible without any explicit handling.
+
+
+### The Beginning
+
+Everything above assumes you get a promise from somewhere else.  This
+is the common case.  Every once in a while, you will need to create a
+promise from scratch.
+
+#### Using ``Q.fcall``
+
+You can create a promise from a value using ``Q.fcall``.  This returns a
+promise for 10.
+
+```javascript
+return Q.fcall(function () {
+    return 10;
+});
+```
+
+You can also use ``fcall`` to get a promise for an exception.
+
+```javascript
+return Q.fcall(function () {
+    throw new Error("Can't do it");
+});
+```
+
+As the name implies, ``fcall`` can call functions, or even promised
+functions.  This uses the ``eventualAdd`` function above to add two
+numbers.
+
+```javascript
+return Q.fcall(eventualAdd, 2, 2);
+```
+
+
+#### Using Deferreds
+
+If you have to interface with asynchronous functions that are callback-based
+instead of promise-based, Q provides a few shortcuts (like ``Q.nfcall`` and
+friends). But much of the time, the solution will be to use *deferreds*.
+
+```javascript
+var deferred = Q.defer();
+FS.readFile("foo.txt", "utf-8", function (error, text) {
+    if (error) {
+        deferred.reject(new Error(error));
+    } else {
+        deferred.resolve(text);
+    }
+});
+return deferred.promise;
+```
+
+Note that a deferred can be resolved with a value or a promise.  The
+``reject`` function is a shorthand for resolving with a rejected
+promise.
+
+```javascript
+// this:
+deferred.reject(new Error("Can't do it"));
+
+// is shorthand for:
+var rejection = Q.fcall(function () {
+    throw new Error("Can't do it");
+});
+deferred.resolve(rejection);
+```
+
+This is a simplified implementation of ``Q.delay``.
+
+```javascript
+function delay(ms) {
+    var deferred = Q.defer();
+    setTimeout(deferred.resolve, ms);
+    return deferred.promise;
+}
+```
+
+This is a simplified implementation of ``Q.timeout``
+
+```javascript
+function timeout(promise, ms) {
+    var deferred = Q.defer();
+    Q.when(promise, deferred.resolve);
+    delay(ms).then(function () {
+        deferred.reject(new Error("Timed out"));
+    });
+    return deferred.promise;
+}
+```
+
+Finally, you can send a progress notification to the promise with
+``deferred.notify``.
+
+For illustration, this is a wrapper for XML HTTP requests in the browser. Note
+that a more [thorough][XHR] implementation would be in order in practice.
+
+[XHR]: https://github.com/montagejs/mr/blob/71e8df99bb4f0584985accd6f2801ef3015b9763/browser.js#L29-L73
+
+```javascript
+function requestOkText(url) {
+    var request = new XMLHttpRequest();
+    var deferred = Q.defer();
+
+    request.open("GET", url, true);
+    request.onload = onload;
+    request.onerror = onerror;
+    request.onprogress = onprogress;
+    request.send();
+
+    function onload() {
+        if (request.status === 200) {
+            deferred.resolve(request.responseText);
+        } else {
+            deferred.reject(new Error("Status code was " + request.status));
+        }
+    }
+
+    function onerror() {
+        deferred.reject(new Error("Can't XHR " + JSON.stringify(url)));
+    }
+
+    function onprogress(event) {
+        deferred.notify(event.loaded / event.total);
+    }
+
+    return deferred.promise;
+}
+```
+
+Below is an example of how to use this ``requestOkText`` function:
+
+```javascript
+requestOkText("http://localhost:3000")
+.then(function (responseText) {
+    // If the HTTP response returns 200 OK, log the response text.
+    console.log(responseText);
+}, function (error) {
+    // If there's an error or a non-200 status code, log the error.
+    console.error(error);
+}, function (progress) {
+    // Log the progress as it comes in.
+    console.log("Request progress: " + Math.round(progress * 100) + "%");
+});
+```
+
+### The Middle
+
+If you are using a function that may return a promise, but just might
+return a value if it doesn’t need to defer, you can use the “static”
+methods of the Q library.
+
+The ``when`` function is the static equivalent for ``then``.
+
+```javascript
+return Q.when(valueOrPromise, function (value) {
+}, function (error) {
+});
+```
+
+All of the other methods on a promise have static analogs with the
+same name.
+
+The following are equivalent:
+
+```javascript
+return Q.all([a, b]);
+```
+
+```javascript
+return Q.fcall(function () {
+    return [a, b];
+})
+.all();
+```
+
+When working with promises provided by other libraries, you should
+convert it to a Q promise.  Not all promise libraries make the same
+guarantees as Q and certainly don’t provide all of the same methods.
+Most libraries only provide a partially functional ``then`` method.
+This thankfully is all we need to turn them into vibrant Q promises.
+
+```javascript
+return Q($.ajax(...))
+.then(function () {
+});
+```
+
+If there is any chance that the promise you receive is not a Q promise
+as provided by your library, you should wrap it using a Q function.
+You can even use ``Q.invoke`` as a shorthand.
+
+```javascript
+return Q.invoke($, 'ajax', ...)
+.then(function () {
+});
+```
+
+
+### Over the Wire
+
+A promise can serve as a proxy for another object, even a remote
+object.  There are methods that allow you to optimistically manipulate
+properties or call functions.  All of these interactions return
+promises, so they can be chained.
+
+```
+direct manipulation         using a promise as a proxy
+--------------------------  -------------------------------
+value.foo                   promise.get("foo")
+value.foo = value           promise.put("foo", value)
+delete value.foo            promise.del("foo")
+value.foo(...args)          promise.post("foo", [args])
+value.foo(...args)          promise.invoke("foo", ...args)
+value(...args)              promise.fapply([args])
+value(...args)              promise.fcall(...args)
+```
+
+If the promise is a proxy for a remote object, you can shave
+round-trips by using these functions instead of ``then``.  To take
+advantage of promises for remote objects, check out [Q-Connection][].
+
+[Q-Connection]: https://github.com/kriskowal/q-connection
+
+Even in the case of non-remote objects, these methods can be used as
+shorthand for particularly-simple fulfillment handlers. For example, you
+can replace
+
+```javascript
+return Q.fcall(function () {
+    return [{ foo: "bar" }, { foo: "baz" }];
+})
+.then(function (value) {
+    return value[0].foo;
+});
+```
+
+with
+
+```javascript
+return Q.fcall(function () {
+    return [{ foo: "bar" }, { foo: "baz" }];
+})
+.get(0)
+.get("foo");
+```
+
+
+### Adapting Node
+
+If you're working with functions that make use of the Node.js callback pattern,
+where callbacks are in the form of `function(err, result)`, Q provides a few
+useful utility functions for converting between them. The most straightforward
+are probably `Q.nfcall` and `Q.nfapply` ("Node function call/apply") for calling
+Node.js-style functions and getting back a promise:
+
+```javascript
+return Q.nfcall(FS.readFile, "foo.txt", "utf-8");
+return Q.nfapply(FS.readFile, ["foo.txt", "utf-8"]);
+```
+
+If you are working with methods, instead of simple functions, you can easily
+run in to the usual problems where passing a method to another function—like
+`Q.nfcall`—"un-binds" the method from its owner. To avoid this, you can either
+use `Function.prototype.bind` or some nice shortcut methods we provide:
+
+```javascript
+return Q.ninvoke(redisClient, "get", "user:1:id");
+return Q.npost(redisClient, "get", ["user:1:id"]);
+```
+
+You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
+
+```javascript
+var readFile = Q.denodeify(FS.readFile);
+return readFile("foo.txt", "utf-8");
+
+var redisClientGet = Q.nbind(redisClient.get, redisClient);
+return redisClientGet("user:1:id");
+```
+
+Finally, if you're working with raw deferred objects, there is a
+`makeNodeResolver` method on deferreds that can be handy:
+
+```javascript
+var deferred = Q.defer();
+FS.readFile("foo.txt", "utf-8", deferred.makeNodeResolver());
+return deferred.promise;
+```
+
+### Long Stack Traces
+
+Q comes with optional support for “long stack traces,” wherein the `stack`
+property of `Error` rejection reasons is rewritten to be traced along
+asynchronous jumps instead of stopping at the most recent one. As an example:
+
+```js
+function theDepthsOfMyProgram() {
+  Q.delay(100).done(function explode() {
+    throw new Error("boo!");
+  });
+}
+
+theDepthsOfMyProgram();
+```
+
+usually would give a rather unhelpful stack trace looking something like
+
+```
+Error: boo!
+    at explode (/path/to/test.js:3:11)
+    at _fulfilled (/path/to/test.js:q:54)
+    at resolvedValue.promiseDispatch.done (/path/to/q.js:823:30)
+    at makePromise.promise.promiseDispatch (/path/to/q.js:496:13)
+    at pending (/path/to/q.js:397:39)
+    at process.startup.processNextTick.process._tickCallback (node.js:244:9)
+```
+
+But, if you turn this feature on by setting
+
+```js
+Q.longStackSupport = true;
+```
+
+then the above code gives a nice stack trace to the tune of
+
+```
+Error: boo!
+    at explode (/path/to/test.js:3:11)
+From previous event:
+    at theDepthsOfMyProgram (/path/to/test.js:2:16)
+    at Object.<anonymous> (/path/to/test.js:7:1)
+```
+
+Note how you can see the the function that triggered the async operation in the
+stack trace! This is very helpful for debugging, as otherwise you end up getting
+only the first line, plus a bunch of Q internals, with no sign of where the
+operation started.
+
+This feature does come with somewhat-serious performance and memory overhead,
+however. If you're working with lots of promises, or trying to scale a server
+to many users, you should probably keep it off. But in development, go for it!
+
+## Tests
+
+You can view the results of the Q test suite [in your browser][tests]!
+
+[tests]: https://rawgithub.com/kriskowal/q/v1/spec/q-spec.html
+
+## License
+
+Copyright 2009–2014 Kristopher Michael Kowal
+MIT License (enclosed)
+

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/node_modules/q/benchmark/compare-with-callbacks.js
----------------------------------------------------------------------
diff --git a/bin/node_modules/q/benchmark/compare-with-callbacks.js b/bin/node_modules/q/benchmark/compare-with-callbacks.js
new file mode 100644
index 0000000..97f1298
--- /dev/null
+++ b/bin/node_modules/q/benchmark/compare-with-callbacks.js
@@ -0,0 +1,71 @@
+"use strict";
+
+var Q = require("../q");
+var fs = require("fs");
+
+suite("A single simple async operation", function () {
+    bench("with an immediately-fulfilled promise", function (done) {
+        Q().then(done);
+    });
+
+    bench("with direct setImmediate usage", function (done) {
+        setImmediate(done);
+    });
+
+    bench("with direct setTimeout(…, 0)", function (done) {
+        setTimeout(done, 0);
+    });
+});
+
+suite("A fs.readFile", function () {
+    var denodeified = Q.denodeify(fs.readFile);
+
+    set("iterations", 1000);
+    set("delay", 1000);
+
+    bench("directly, with callbacks", function (done) {
+        fs.readFile(__filename, done);
+    });
+
+    bench("with Q.nfcall", function (done) {
+        Q.nfcall(fs.readFile, __filename).then(done);
+    });
+
+    bench("with a Q.denodeify'ed version", function (done) {
+        denodeified(__filename).then(done);
+    });
+
+    bench("with manual usage of deferred.makeNodeResolver", function (done) {
+        var deferred = Q.defer();
+        fs.readFile(__filename, deferred.makeNodeResolver());
+        deferred.promise.then(done);
+    });
+});
+
+suite("1000 operations in parallel", function () {
+    function makeCounter(desiredCount, ultimateCallback) {
+        var soFar = 0;
+        return function () {
+            if (++soFar === desiredCount) {
+                ultimateCallback();
+            }
+        };
+    }
+    var numberOfOps = 1000;
+
+    bench("with immediately-fulfilled promises", function (done) {
+        var counter = makeCounter(numberOfOps, done);
+
+        for (var i = 0; i < numberOfOps; ++i) {
+            Q().then(counter);
+        }
+    });
+
+    bench("with direct setImmediate usage", function (done) {
+        var counter = makeCounter(numberOfOps, done);
+
+        for (var i = 0; i < numberOfOps; ++i) {
+            setImmediate(counter);
+        }
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/node_modules/q/benchmark/scenarios.js
----------------------------------------------------------------------
diff --git a/bin/node_modules/q/benchmark/scenarios.js b/bin/node_modules/q/benchmark/scenarios.js
new file mode 100644
index 0000000..7c18564
--- /dev/null
+++ b/bin/node_modules/q/benchmark/scenarios.js
@@ -0,0 +1,36 @@
+"use strict";
+
+var Q = require("../q");
+
+suite("Chaining", function () {
+    var numberToChain = 1000;
+
+    bench("Chaining many already-fulfilled promises together", function (done) {
+        var currentPromise = Q();
+        for (var i = 0; i < numberToChain; ++i) {
+            currentPromise = currentPromise.then(function () {
+                return Q();
+            });
+        }
+
+        currentPromise.then(done);
+    });
+
+    bench("Chaining and then fulfilling the end of the chain", function (done) {
+        var deferred = Q.defer();
+
+        var currentPromise = deferred.promise;
+        for (var i = 0; i < numberToChain; ++i) {
+            (function () {
+                var promiseToReturn = currentPromise;
+                currentPromise = Q().then(function () {
+                    return promiseToReturn;
+                });
+            }());
+        }
+
+        currentPromise.then(done);
+
+        deferred.resolve();
+    });
+});

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/dd54d96b/bin/node_modules/q/package.json
----------------------------------------------------------------------
diff --git a/bin/node_modules/q/package.json b/bin/node_modules/q/package.json
new file mode 100644
index 0000000..7b7f3c6
--- /dev/null
+++ b/bin/node_modules/q/package.json
@@ -0,0 +1,112 @@
+{
+  "name": "q",
+  "version": "1.0.1",
+  "description": "A library for promises (CommonJS/Promises/A,B,D)",
+  "homepage": "https://github.com/kriskowal/q",
+  "author": {
+    "name": "Kris Kowal",
+    "email": "kris@cixar.com",
+    "url": "https://github.com/kriskowal"
+  },
+  "keywords": [
+    "q",
+    "promise",
+    "promises",
+    "promises-a",
+    "promises-aplus",
+    "deferred",
+    "future",
+    "async",
+    "flow control",
+    "fluent",
+    "browser",
+    "node"
+  ],
+  "contributors": [
+    {
+      "name": "Kris Kowal",
+      "email": "kris@cixar.com",
+      "url": "https://github.com/kriskowal"
+    },
+    {
+      "name": "Irakli Gozalishvili",
+      "email": "rfobic@gmail.com",
+      "url": "http://jeditoolkit.com"
+    },
+    {
+      "name": "Domenic Denicola",
+      "email": "domenic@domenicdenicola.com",
+      "url": "http://domenicdenicola.com"
+    }
+  ],
+  "bugs": {
+    "url": "http://github.com/kriskowal/q/issues"
+  },
+  "license": {
+    "type": "MIT",
+    "url": "http://github.com/kriskowal/q/raw/master/LICENSE"
+  },
+  "main": "q.js",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/kriskowal/q.git"
+  },
+  "engines": {
+    "node": ">=0.6.0",
+    "teleport": ">=0.2.0"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "jshint": "~2.1.9",
+    "cover": "*",
+    "jasmine-node": "1.11.0",
+    "opener": "*",
+    "promises-aplus-tests": "1.x",
+    "grunt": "~0.4.1",
+    "grunt-cli": "~0.1.9",
+    "grunt-contrib-uglify": "~0.2.2",
+    "matcha": "~0.2.0"
+  },
+  "scripts": {
+    "test": "jasmine-node spec && promises-aplus-tests spec/aplus-adapter",
+    "test-browser": "opener spec/q-spec.html",
+    "benchmark": "matcha",
+    "lint": "jshint q.js",
+    "cover": "cover run node_modules/jasmine-node/bin/jasmine-node spec && cover report html && opener cover_html/index.html",
+    "minify": "grunt",
+    "prepublish": "grunt"
+  },
+  "overlay": {
+    "teleport": {
+      "dependencies": {
+        "system": ">=0.0.4"
+      }
+    }
+  },
+  "directories": {
+    "test": "./spec"
+  },
+  "_id": "q@1.0.1",
+  "dist": {
+    "shasum": "11872aeedee89268110b10a718448ffb10112a14",
+    "tarball": "http://registry.npmjs.org/q/-/q-1.0.1.tgz"
+  },
+  "_from": "q@",
+  "_npmVersion": "1.4.4",
+  "_npmUser": {
+    "name": "kriskowal",
+    "email": "kris.kowal@cixar.com"
+  },
+  "maintainers": [
+    {
+      "name": "kriskowal",
+      "email": "kris.kowal@cixar.com"
+    },
+    {
+      "name": "domenic",
+      "email": "domenic@domenicdenicola.com"
+    }
+  ],
+  "_shasum": "11872aeedee89268110b10a718448ffb10112a14",
+  "_resolved": "https://registry.npmjs.org/q/-/q-1.0.1.tgz"
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[04/10] ios commit: CB-6637 - Removed - request:isFragmentIdentifierToRequest: deprecated method in CDVWebViewDelegate (closes #121)

Posted by sh...@apache.org.
CB-6637 - Removed - request:isFragmentIdentifierToRequest: deprecated method in CDVWebViewDelegate (closes #121)

Signed-off-by: Shazron Abdullah <sh...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/ea2a9467
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/ea2a9467
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/ea2a9467

Branch: refs/heads/wkwebview
Commit: ea2a9467912ea503360c26a867ede4311fe1a3c1
Parents: 9e53aa9
Author: Ivan Karpan <iv...@gmail.com>
Authored: Mon Dec 8 16:59:21 2014 +0200
Committer: Shazron Abdullah <sh...@apache.org>
Committed: Fri Dec 12 11:14:26 2014 -0800

----------------------------------------------------------------------
 CordovaLib/Classes/CDVWebViewDelegate.h | 1 -
 CordovaLib/Classes/CDVWebViewDelegate.m | 5 -----
 2 files changed, 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ea2a9467/CordovaLib/Classes/CDVWebViewDelegate.h
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWebViewDelegate.h b/CordovaLib/Classes/CDVWebViewDelegate.h
index 4b60bab..f6c419f 100644
--- a/CordovaLib/Classes/CDVWebViewDelegate.h
+++ b/CordovaLib/Classes/CDVWebViewDelegate.h
@@ -35,7 +35,6 @@
 }
 
 - (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate;
-- (BOOL)request:(NSURLRequest*)newRequest isFragmentIdentifierToRequest:(NSURLRequest*)originalRequest CDV_DEPRECATED(3.5, "Use request:isEqualToRequestAfterStrippingFragments: instead.");
 
 - (BOOL)request:(NSURLRequest*)newRequest isEqualToRequestAfterStrippingFragments:(NSURLRequest*)originalRequest;
 

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/ea2a9467/CordovaLib/Classes/CDVWebViewDelegate.m
----------------------------------------------------------------------
diff --git a/CordovaLib/Classes/CDVWebViewDelegate.m b/CordovaLib/Classes/CDVWebViewDelegate.m
index 5a187f4..514827e 100644
--- a/CordovaLib/Classes/CDVWebViewDelegate.m
+++ b/CordovaLib/Classes/CDVWebViewDelegate.m
@@ -114,11 +114,6 @@ static NSString *stripFragment(NSString* url)
     return self;
 }
 
-- (BOOL)request:(NSURLRequest*)newRequest isFragmentIdentifierToRequest:(NSURLRequest*)originalRequest
-{
-    return [self request:newRequest isEqualToRequestAfterStrippingFragments:originalRequest];
-}
-
 - (BOOL)request:(NSURLRequest*)newRequest isEqualToRequestAfterStrippingFragments:(NSURLRequest*)originalRequest
 {
     if (originalRequest.URL && newRequest.URL) {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[03/10] ios commit: CB-8002 CB-7735 Update cordova.js to include bridge fix

Posted by sh...@apache.org.
CB-8002 CB-7735 Update cordova.js to include bridge fix


Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/9e53aa99
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/9e53aa99
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/9e53aa99

Branch: refs/heads/wkwebview
Commit: 9e53aa9976772ea0a6861d6c451fef019d29fc65
Parents: dd54d96
Author: Andrew Grieve <ag...@chromium.org>
Authored: Tue Nov 25 13:42:40 2014 -0500
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Tue Nov 25 13:42:40 2014 -0500

----------------------------------------------------------------------
 CordovaLib/cordova.js | 122 +++++++++++++++++++++++----------------------
 1 file changed, 62 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/9e53aa99/CordovaLib/cordova.js
----------------------------------------------------------------------
diff --git a/CordovaLib/cordova.js b/CordovaLib/cordova.js
index 75729c1..9588ca4 100644
--- a/CordovaLib/cordova.js
+++ b/CordovaLib/cordova.js
@@ -1,5 +1,5 @@
 // Platform: ios
-// 91157c2e1bf3eb098c7e2ab31404e895ccb0df2a
+// 227d83a122733fdf0300ffe75507a221bcef2b06
 /*
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
@@ -464,9 +464,14 @@ function each(objects, func, context) {
 
 function clobber(obj, key, value) {
     exports.replaceHookForTesting(obj, key);
-    obj[key] = value;
+    var needsProperty = false;
+    try {
+        obj[key] = value;
+    } catch (e) {
+        needsProperty = true;
+    }
     // Getters can only be overridden by getters.
-    if (obj[key] !== value) {
+    if (needsProperty || obj[key] !== value) {
         utils.defineGetter(obj, key, function() {
             return value;
         });
@@ -821,14 +826,13 @@ var cordova = require('cordova'),
     // IFRAME_NAV is the fastest.
     // IFRAME_HASH could be made to enable synchronous bridge calls if we wanted this feature.
     jsToNativeModes = {
-        IFRAME_NAV: 0,
-        XHR_NO_PAYLOAD: 1,
-        XHR_WITH_PAYLOAD: 2,
-        XHR_OPTIONAL_PAYLOAD: 3,
-        IFRAME_HASH_NO_PAYLOAD: 4,
-        // Bundling the payload turns out to be slower. Probably since it has to be URI encoded / decoded.
-        IFRAME_HASH_WITH_PAYLOAD: 5,
-        WK_WEBVIEW_BINDING: 6
+        IFRAME_NAV: 0, // Default. Uses a new iframe for each poke.
+        XHR_NO_PAYLOAD: 1, // About the same speed as IFRAME_NAV. Performance not about the same as IFRAME_NAV, but more variable.
+        XHR_WITH_PAYLOAD: 2, // Flakey, and not as performant
+        XHR_OPTIONAL_PAYLOAD: 3, // Flakey, and not as performant
+        IFRAME_HASH_NO_PAYLOAD: 4, // Not fully baked. A bit faster than IFRAME_NAV, but risks jank since poke happens synchronously.
+        IFRAME_HASH_WITH_PAYLOAD: 5, // Slower than no payload. Maybe since it has to be URI encoded / decoded.
+        WK_WEBVIEW_BINDING: 6 // Only way that works for WKWebView :)
     },
     bridgeMode,
     execIframe,
@@ -838,26 +842,8 @@ var cordova = require('cordova'),
     requestCount = 0,
     vcHeaderValue = null,
     commandQueue = [], // Contains pending JS->Native messages.
-    isInContextOfEvalJs = 0;
-
-function createExecIframe(src, unloadListener) {
-    var iframe = document.createElement("iframe");
-    iframe.style.display = 'none';
-    // Both the unload listener and the src must be set before adding the iframe
-    // to the document in order to avoid race conditions. Callbacks from native
-    // can happen within the appendChild() call!
-    iframe.onunload = unloadListener;
-    iframe.src = src;
-    document.body.appendChild(iframe);
-    return iframe;
-}
-
-function createHashIframe() {
-    var ret = createExecIframe('about:blank');
-    // Hash changes don't work on about:blank, so switch it to file:///.
-    ret.contentWindow.history.replaceState(null, null, 'file:///#');
-    return ret;
-}
+    isInContextOfEvalJs = 0,
+    failSafeTimerId = 0;
 
 function shouldBundleCommandJson() {
     if (bridgeMode === jsToNativeModes.XHR_WITH_PAYLOAD) {
@@ -990,19 +976,23 @@ function iOSExec() {
         // Also, if there is already a command in the queue, then we've already
         // poked the native side, so there is no reason to do so again.
         if (!isInContextOfEvalJs && commandQueue.length == 1) {
-            switch (bridgeMode) {
-            case jsToNativeModes.XHR_NO_PAYLOAD:
-            case jsToNativeModes.XHR_WITH_PAYLOAD:
-            case jsToNativeModes.XHR_OPTIONAL_PAYLOAD:
-                pokeNativeViaXhr();
-                break;
-            default: // iframe-based.
-                pokeNativeViaIframe();
-            }
+            pokeNative();
         }
     }
 }
 
+function pokeNative() {
+    switch (bridgeMode) {
+    case jsToNativeModes.XHR_NO_PAYLOAD:
+    case jsToNativeModes.XHR_WITH_PAYLOAD:
+    case jsToNativeModes.XHR_OPTIONAL_PAYLOAD:
+        pokeNativeViaXhr();
+        break;
+    default: // iframe-based.
+        pokeNativeViaIframe();
+    }
+}
+
 function pokeNativeViaXhr() {
     // This prevents sending an XHR when there is already one being sent.
     // This should happen only in rare circumstances (refer to unit tests).
@@ -1026,11 +1016,6 @@ function pokeNativeViaXhr() {
     execXhr.send(null);
 }
 
-function onIframeUnload() {
-    execIframe = null;
-    setTimeout(pokeNativeViaIframe, 0);
-}
-
 function pokeNativeViaIframe() {
     // CB-5488 - Don't attempt to create iframe before document.body is available.
     if (!document.body) {
@@ -1039,10 +1024,12 @@ function pokeNativeViaIframe() {
     }
     if (bridgeMode === jsToNativeModes.IFRAME_HASH_NO_PAYLOAD || bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
         // TODO: This bridge mode doesn't properly support being removed from the DOM (CB-7735)
-        execHashIframe = execHashIframe || createHashIframe();
-        // Check if they've removed it from the DOM, and put it back if so.
-        if (!execHashIframe.contentWindow) {
-            execHashIframe = createHashIframe();
+        if (!execHashIframe) {
+            execHashIframe = document.createElement('iframe');
+            execHashIframe.style.display = 'none';
+            document.body.appendChild(execHashIframe);
+            // Hash changes don't work on about:blank, so switch it to file:///.
+            execHashIframe.contentWindow.history.replaceState(null, null, 'file:///#');
         }
         // The delegate method is called only when the hash changes, so toggle it back and forth.
         hashToggle = hashToggle ^ 3;
@@ -1054,13 +1041,25 @@ function pokeNativeViaIframe() {
     } else {
         // Check if they've removed it from the DOM, and put it back if so.
         if (execIframe && execIframe.contentWindow) {
-            // Listen for unload, since it can happen (CB-7735) that the iframe gets
-            // removed from the DOM before it gets a chance to poke the native side.
-            execIframe.contentWindow.onunload = onIframeUnload;
-            execIframe.src = 'gap://ready';
+            execIframe.contentWindow.location = 'gap://ready';
         } else {
-            execIframe = createExecIframe('gap://ready', onIframeUnload);
+            execIframe = document.createElement('iframe');
+            execIframe.style.display = 'none';
+            execIframe.src = 'gap://ready';
+            document.body.appendChild(execIframe);
         }
+        // Use a timer to protect against iframe being unloaded during the poke (CB-7735).
+        // This makes the bridge ~ 7% slower, but works around the poke getting lost
+        // when the iframe is removed from the DOM.
+        // An onunload listener could be used in the case where the iframe has just been
+        // created, but since unload events fire only once, it doesn't work in the normal
+        // case of iframe reuse (where unload will have already fired due to the attempted
+        // navigation of the page).
+        failSafeTimerId = setTimeout(function() {
+            if (commandQueue.length) {
+                pokeNative();
+            }
+        }, 50); // Making this > 0 improves performance (marginally) in the normal case (where it doesn't fire).
     }
 }
 
@@ -1071,7 +1070,9 @@ iOSExec.setJsToNativeBridgeMode = function(mode) {
     // can trigger browser bugs.
     // https://issues.apache.org/jira/browse/CB-593
     if (execIframe) {
-        execIframe.parentNode.removeChild(execIframe);
+        if (execIframe.parentNode) {
+            execIframe.parentNode.removeChild(execIframe);
+        }
         execIframe = null;
     }
     bridgeMode = mode;
@@ -1079,8 +1080,9 @@ iOSExec.setJsToNativeBridgeMode = function(mode) {
 
 iOSExec.nativeFetchMessages = function() {
     // Stop listing for window detatch once native side confirms poke.
-    if (execIframe && execIframe.contentWindow) {
-        execIframe.contentWindow.onunload = null;
+    if (failSafeTimerId) {
+        clearTimeout(failSafeTimerId);
+        failSafeTimerId = 0;
     }
     // Each entry in commandQueue is a JSON string already.
     if (!commandQueue.length) {
@@ -1184,7 +1186,7 @@ function replaceNavigator(origNavigator) {
         for (var key in origNavigator) {
             if (typeof origNavigator[key] == 'function') {
                 newNavigator[key] = origNavigator[key].bind(origNavigator);
-            } 
+            }
             else {
                 (function(k) {
                     utils.defineGetterSetter(newNavigator,key,function() {
@@ -1312,7 +1314,7 @@ function replaceNavigator(origNavigator) {
         for (var key in origNavigator) {
             if (typeof origNavigator[key] == 'function') {
                 newNavigator[key] = origNavigator[key].bind(origNavigator);
-            } 
+            }
             else {
                 (function(k) {
                     utils.defineGetterSetter(newNavigator,key,function() {
@@ -1367,7 +1369,7 @@ platform.bootstrap && platform.bootstrap();
  * Create all cordova objects once native side is ready.
  */
 channel.join(function() {
-    
+
     platform.initialize && platform.initialize();
 
     // Fire event to notify that all objects are created


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[06/10] ios commit: [CB-8044] support for --nobuild flag in run script

Posted by sh...@apache.org.
[CB-8044] support for --nobuild flag in run script


Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/19e95454
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/19e95454
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/19e95454

Branch: refs/heads/wkwebview
Commit: 19e9545411bb055ddd12fb3754b08cfad564401d
Parents: 9ea4c78
Author: Lorin Beer <lo...@gmail.com>
Authored: Fri Dec 12 11:50:04 2014 -0800
Committer: Lorin Beer <lo...@gmail.com>
Committed: Fri Dec 12 11:50:04 2014 -0800

----------------------------------------------------------------------
 bin/templates/scripts/cordova/run | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/19e95454/bin/templates/scripts/cordova/run
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/run b/bin/templates/scripts/cordova/run
index 12334ac..f66f703 100755
--- a/bin/templates/scripts/cordova/run
+++ b/bin/templates/scripts/cordova/run
@@ -115,7 +115,7 @@ if "$USE_DEVICE"; then
         USE_SIMULATOR=true
     else
         # if we got here, we can deploy the app, then exit success
-        if [ ! $NO_BUILD ] then
+        if [ ! $NO_BUILD ]; then
             "$CORDOVA_PATH/build" --device || exit $?
         fi
         ios-deploy -d -b "$DEVICE_APP_PATH"
@@ -139,7 +139,7 @@ if "$USE_SIMULATOR"; then
     fi
     
     # launch using ios-sim
-    if [ ! $NO_BUILD ] then
+    if [ ! $NO_BUILD ]; then
         "$CORDOVA_PATH/build" --emulator || exit $?
     fi
     ios-sim launch "$SIMULATOR_APP_PATH" --stderr "$CORDOVA_PATH/console.log" --stdout "$CORDOVA_PATH/console.log" --devicetypeid com.apple.CoreSimulator.SimDeviceType.$TARGET --exit


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[10/10] ios commit: Merge branch 'master' into wkwebview

Posted by sh...@apache.org.
Merge branch 'master' into wkwebview


Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/e0dc7443
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/e0dc7443
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/e0dc7443

Branch: refs/heads/wkwebview
Commit: e0dc7443be93978f8bead23fc3c968e95cffe4f7
Parents: 1d4ba97 0a2eac7
Author: Shazron Abdullah <sh...@gmail.com>
Authored: Tue Jan 6 16:44:17 2015 -0800
Committer: Shazron Abdullah <sh...@gmail.com>
Committed: Tue Jan 6 16:44:17 2015 -0800

----------------------------------------------------------------------
 CordovaLib/Classes/CDVUIWebViewDelegate.h       |    1 -
 CordovaLib/Classes/CDVUIWebViewDelegate.m       |    5 -
 CordovaLib/cordova.js                           |  122 +-
 bin/apple_ios_version                           |   47 +-
 bin/apple_ios_version.bat                       |   26 +
 bin/apple_osx_version                           |   47 +-
 bin/apple_osx_version.bat                       |   26 +
 bin/apple_xcode_version                         |   47 +-
 bin/apple_xcode_version.bat                     |   26 +
 bin/create                                      |  205 +-
 bin/create.bat                                  |   26 +
 bin/lib/create.js                               |  255 +++
 bin/lib/update.js                               |   72 +
 bin/lib/versions.js                             |  101 +
 bin/node_modules/q/CONTRIBUTING.md              |   40 +
 bin/node_modules/q/LICENSE                      |   18 +
 bin/node_modules/q/README.md                    |  820 ++++++++
 .../q/benchmark/compare-with-callbacks.js       |   71 +
 bin/node_modules/q/benchmark/scenarios.js       |   36 +
 bin/node_modules/q/package.json                 |  112 ++
 bin/node_modules/q/q.js                         | 1904 ++++++++++++++++++
 bin/node_modules/q/queue.js                     |   35 +
 bin/node_modules/which/LICENSE                  |   23 +
 bin/node_modules/which/README.md                |    5 +
 bin/node_modules/which/bin/which                |   14 +
 bin/node_modules/which/package.json             |   31 +
 bin/node_modules/which/which.js                 |  104 +
 bin/replaces                                    |   28 -
 bin/templates/scripts/cordova/build.xcconfig    |    2 +-
 bin/templates/scripts/cordova/run               |   53 +-
 bin/templates/scripts/cordova/version           |   51 +-
 bin/templates/scripts/cordova/version.bat       |   26 +
 bin/update                                      |   95 +-
 bin/update.bat                                  |   26 +
 bin/update_cordova_subproject                   |  137 +-
 bin/update_cordova_subproject.bat               |   26 +
 tests/spec/create.spec.js                       |   13 +-
 37 files changed, 4145 insertions(+), 531 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/e0dc7443/CordovaLib/Classes/CDVUIWebViewDelegate.h
----------------------------------------------------------------------
diff --cc CordovaLib/Classes/CDVUIWebViewDelegate.h
index 05979ed,0000000..d77f191
mode 100644,000000..100644
--- a/CordovaLib/Classes/CDVUIWebViewDelegate.h
+++ b/CordovaLib/Classes/CDVUIWebViewDelegate.h
@@@ -1,42 -1,0 +1,41 @@@
 +/*
 + Licensed to the Apache Software Foundation (ASF) under one
 + or more contributor license agreements.  See the NOTICE file
 + distributed with this work for additional information
 + regarding copyright ownership.  The ASF licenses this file
 + to you under the Apache License, Version 2.0 (the
 + "License"); you may not use this file except in compliance
 + with the License.  You may obtain a copy of the License at
 +
 + http://www.apache.org/licenses/LICENSE-2.0
 +
 + Unless required by applicable law or agreed to in writing,
 + software distributed under the License is distributed on an
 + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + KIND, either express or implied.  See the License for the
 + specific language governing permissions and limitations
 + under the License.
 + */
 +
 +#import <UIKit/UIKit.h>
 +#import "CDVAvailability.h"
 +
 +/**
 + * Distinguishes top-level navigations from sub-frame navigations.
 + * shouldStartLoadWithRequest is called for every request, but didStartLoad
 + * and didFinishLoad is called only for top-level navigations.
 + * Relevant bug: CB-2389
 + */
 +@interface CDVUIWebViewDelegate : NSObject <UIWebViewDelegate>{
 +    __weak NSObject <UIWebViewDelegate>* _delegate;
 +    NSInteger _loadCount;
 +    NSInteger _state;
 +    NSInteger _curLoadToken;
 +    NSInteger _loadStartPollCount;
 +}
 +
 +- (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate;
- - (BOOL)request:(NSURLRequest*)newRequest isFragmentIdentifierToRequest:(NSURLRequest*)originalRequest CDV_DEPRECATED(3.5, "Use request:isEqualToRequestAfterStrippingFragments: instead.");
 +
 +- (BOOL)request:(NSURLRequest*)newRequest isEqualToRequestAfterStrippingFragments:(NSURLRequest*)originalRequest;
 +
 +@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/e0dc7443/CordovaLib/Classes/CDVUIWebViewDelegate.m
----------------------------------------------------------------------
diff --cc CordovaLib/Classes/CDVUIWebViewDelegate.m
index d880a4b,0000000..929138f
mode 100644,000000..100644
--- a/CordovaLib/Classes/CDVUIWebViewDelegate.m
+++ b/CordovaLib/Classes/CDVUIWebViewDelegate.m
@@@ -1,416 -1,0 +1,411 @@@
 +/*
 + Licensed to the Apache Software Foundation (ASF) under one
 + or more contributor license agreements.  See the NOTICE file
 + distributed with this work for additional information
 + regarding copyright ownership.  The ASF licenses this file
 + to you under the Apache License, Version 2.0 (the
 + "License"); you may not use this file except in compliance
 + with the License.  You may obtain a copy of the License at
 +
 + http://www.apache.org/licenses/LICENSE-2.0
 +
 + Unless required by applicable law or agreed to in writing,
 + software distributed under the License is distributed on an
 + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + KIND, either express or implied.  See the License for the
 + specific language governing permissions and limitations
 + under the License.
 + */
 +
 +//
 +// Testing shows:
 +//
 +// In all cases, webView.request.URL is the previous page's URL (or empty) during the didStartLoad callback.
 +// When loading a page with a redirect:
 +// 1. shouldStartLoading (requestURL is target page)
 +// 2. didStartLoading
 +// 3. shouldStartLoading (requestURL is redirect target)
 +// 4. didFinishLoad (request.URL is redirect target)
 +//
 +// Note the lack of a second didStartLoading **
 +//
 +// When loading a page with iframes:
 +// 1. shouldStartLoading (requestURL is main page)
 +// 2. didStartLoading
 +// 3. shouldStartLoading (requestURL is one of the iframes)
 +// 4. didStartLoading
 +// 5. didFinishLoad
 +// 6. didFinishLoad
 +//
 +// Note there is no way to distinguish which didFinishLoad maps to which didStartLoad **
 +//
 +// Loading a page by calling window.history.go(-1):
 +// 1. didStartLoading
 +// 2. didFinishLoad
 +//
 +// Note the lack of a shouldStartLoading call **
 +// Actually - this is fixed on iOS6. iOS6 has a shouldStart. **
 +//
 +// Loading a page by calling location.reload()
 +// 1. shouldStartLoading
 +// 2. didStartLoading
 +// 3. didFinishLoad
 +//
 +// Loading a page with an iframe that fails to load:
 +// 1. shouldStart (main page)
 +// 2. didStart
 +// 3. shouldStart (iframe)
 +// 4. didStart
 +// 5. didFailWithError
 +// 6. didFinish
 +//
 +// Loading a page with an iframe that fails to load due to an invalid URL:
 +// 1. shouldStart (main page)
 +// 2. didStart
 +// 3. shouldStart (iframe)
 +// 5. didFailWithError
 +// 6. didFinish
 +//
 +// This case breaks our logic since there is a missing didStart. To prevent this,
 +// we check URLs in shouldStart and return NO if they are invalid.
 +//
 +// Loading a page with an invalid URL
 +// 1. shouldStart (main page)
 +// 2. didFailWithError
 +//
 +// TODO: Record order when page is re-navigated before the first navigation finishes.
 +//
 +
 +#import "CDVUIWebViewDelegate.h"
 +
 +// #define VerboseLog NSLog
 +#define VerboseLog(...) do {} while (0)
 +
 +typedef enum {
 +    STATE_IDLE = 0,
 +    STATE_WAITING_FOR_LOAD_START = 1,
 +    STATE_WAITING_FOR_LOAD_FINISH = 2,
 +    STATE_IOS5_POLLING_FOR_LOAD_START = 3,
 +    STATE_IOS5_POLLING_FOR_LOAD_FINISH = 4,
 +    STATE_CANCELLED = 5
 +} State;
 +
 +static NSString *stripFragment(NSString* url)
 +{
 +    NSRange r = [url rangeOfString:@"#"];
 +
 +    if (r.location == NSNotFound) {
 +        return url;
 +    }
 +    return [url substringToIndex:r.location];
 +}
 +
 +@implementation CDVUIWebViewDelegate
 +
 +- (id)initWithDelegate:(NSObject <UIWebViewDelegate>*)delegate
 +{
 +    self = [super init];
 +    if (self != nil) {
 +        _delegate = delegate;
 +        _loadCount = -1;
 +        _state = STATE_IDLE;
 +    }
 +    return self;
 +}
 +
- - (BOOL)request:(NSURLRequest*)newRequest isFragmentIdentifierToRequest:(NSURLRequest*)originalRequest
- {
-     return [self request:newRequest isEqualToRequestAfterStrippingFragments:originalRequest];
- }
- 
 +- (BOOL)request:(NSURLRequest*)newRequest isEqualToRequestAfterStrippingFragments:(NSURLRequest*)originalRequest
 +{
 +    if (originalRequest.URL && newRequest.URL) {
 +        NSString* originalRequestUrl = [originalRequest.URL absoluteString];
 +        NSString* newRequestUrl = [newRequest.URL absoluteString];
 +
 +        NSString* baseOriginalRequestUrl = stripFragment(originalRequestUrl);
 +        NSString* baseNewRequestUrl = stripFragment(newRequestUrl);
 +        return [baseOriginalRequestUrl isEqualToString:baseNewRequestUrl];
 +    }
 +
 +    return NO;
 +}
 +
 +- (BOOL)isPageLoaded:(UIWebView*)webView
 +{
 +    NSString* readyState = [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"];
 +
 +    return [readyState isEqualToString:@"loaded"] || [readyState isEqualToString:@"complete"];
 +}
 +
 +- (BOOL)isJsLoadTokenSet:(UIWebView*)webView
 +{
 +    NSString* loadToken = [webView stringByEvaluatingJavaScriptFromString:@"window.__cordovaLoadToken"];
 +
 +    return [[NSString stringWithFormat:@"%ld", (long)_curLoadToken] isEqualToString:loadToken];
 +}
 +
 +- (void)setLoadToken:(UIWebView*)webView
 +{
 +    _curLoadToken += 1;
 +    [webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.__cordovaLoadToken=%ld", (long)_curLoadToken]];
 +}
 +
 +- (NSString*)evalForCurrentURL:(UIWebView*)webView
 +{
 +    return [webView stringByEvaluatingJavaScriptFromString:@"location.href"];
 +}
 +
 +- (void)pollForPageLoadStart:(UIWebView*)webView
 +{
 +    if (_state != STATE_IOS5_POLLING_FOR_LOAD_START) {
 +        return;
 +    }
 +    if (![self isJsLoadTokenSet:webView]) {
 +        VerboseLog(@"Polled for page load start. result = YES!");
 +        _state = STATE_IOS5_POLLING_FOR_LOAD_FINISH;
 +        [self setLoadToken:webView];
 +        if ([_delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
 +            [_delegate webViewDidStartLoad:webView];
 +        }
 +        [self pollForPageLoadFinish:webView];
 +    } else {
 +        VerboseLog(@"Polled for page load start. result = NO");
 +        // Poll only for 1 second, and then fall back on checking only when delegate methods are called.
 +        ++_loadStartPollCount;
 +        if (_loadStartPollCount < (1000 * .05)) {
 +            [self performSelector:@selector(pollForPageLoadStart:) withObject:webView afterDelay:.05];
 +        }
 +    }
 +}
 +
 +- (void)pollForPageLoadFinish:(UIWebView*)webView
 +{
 +    if (_state != STATE_IOS5_POLLING_FOR_LOAD_FINISH) {
 +        return;
 +    }
 +    if ([self isPageLoaded:webView]) {
 +        VerboseLog(@"Polled for page load finish. result = YES!");
 +        _state = STATE_IDLE;
 +        if ([_delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
 +            [_delegate webViewDidFinishLoad:webView];
 +        }
 +    } else {
 +        VerboseLog(@"Polled for page load finish. result = NO");
 +        [self performSelector:@selector(pollForPageLoadFinish:) withObject:webView afterDelay:.05];
 +    }
 +}
 +
 +- (BOOL)shouldLoadRequest:(NSURLRequest*)request
 +{
 +    NSString* scheme = [[request URL] scheme];
 +
 +    if ([scheme isEqualToString:@"mailto"] || [scheme isEqualToString:@"tel"]) {
 +        return YES;
 +    }
 +
 +    return [NSURLConnection canHandleRequest:request];
 +}
 +
 +- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
 +{
 +    BOOL shouldLoad = YES;
 +
 +    if ([_delegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) {
 +        shouldLoad = [_delegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
 +    }
 +
 +    VerboseLog(@"webView shouldLoad=%d (before) state=%d loadCount=%d URL=%@", shouldLoad, _state, _loadCount, request.URL);
 +
 +    if (shouldLoad) {
 +        // When devtools refresh occurs, it blindly uses the same request object. If a history.replaceState() has occured, then
 +        // mainDocumentURL != URL even though it's a top-level navigation.
 +        BOOL isDevToolsRefresh = (request == webView.request);
 +        BOOL isTopLevelNavigation = isDevToolsRefresh || [request.URL isEqual:[request mainDocumentURL]];
 +        if (isTopLevelNavigation) {
 +            // Ignore hash changes that don't navigate to a different page.
 +            // webView.request does actually update when history.replaceState() gets called.
 +            if ([self request:request isEqualToRequestAfterStrippingFragments:webView.request]) {
 +                NSString* prevURL = [self evalForCurrentURL:webView];
 +                if ([prevURL isEqualToString:[request.URL absoluteString]]) {
 +                    VerboseLog(@"Page reload detected.");
 +                } else {
 +                    VerboseLog(@"Detected hash change shouldLoad");
 +                    return shouldLoad;
 +                }
 +            }
 +
 +            switch (_state) {
 +                case STATE_WAITING_FOR_LOAD_FINISH:
 +                    // Redirect case.
 +                    // We expect loadCount == 1.
 +                    if (_loadCount != 1) {
 +                        NSLog(@"CDVWebViewDelegate: Detected redirect when loadCount=%ld", (long)_loadCount);
 +                    }
 +                    break;
 +
 +                case STATE_IDLE:
 +                case STATE_IOS5_POLLING_FOR_LOAD_START:
 +                case STATE_CANCELLED:
 +                    // Page navigation start.
 +                    _loadCount = 0;
 +                    _state = STATE_WAITING_FOR_LOAD_START;
 +                    break;
 +
 +                default:
 +                    {
 +                        _loadCount = 0;
 +                        _state = STATE_WAITING_FOR_LOAD_START;
 +                        NSString* description = [NSString stringWithFormat:@"CDVWebViewDelegate: Navigation started when state=%ld", (long)_state];
 +                        NSLog(@"%@", description);
 +                        if ([_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
 +                            NSDictionary* errorDictionary = @{NSLocalizedDescriptionKey : description};
 +                            NSError* error = [[NSError alloc] initWithDomain:@"CDVUIWebViewDelegate" code:1 userInfo:errorDictionary];
 +                            [_delegate webView:webView didFailLoadWithError:error];
 +                        }
 +                    }
 +            }
 +        } else {
 +            // Deny invalid URLs so that we don't get the case where we go straight from
 +            // webViewShouldLoad -> webViewDidFailLoad (messes up _loadCount).
 +            shouldLoad = shouldLoad && [self shouldLoadRequest:request];
 +        }
 +        VerboseLog(@"webView shouldLoad=%d (after) isTopLevelNavigation=%d state=%d loadCount=%d", shouldLoad, isTopLevelNavigation, _state, _loadCount);
 +    }
 +    return shouldLoad;
 +}
 +
 +- (void)webViewDidStartLoad:(UIWebView*)webView
 +{
 +    VerboseLog(@"webView didStartLoad (before). state=%d loadCount=%d", _state, _loadCount);
 +    BOOL fireCallback = NO;
 +    switch (_state) {
 +        case STATE_IDLE:
 +            if (IsAtLeastiOSVersion(@"6.0")) {
 +                break;
 +            }
 +            // If history.go(-1) is used pre-iOS6, the shouldStartLoadWithRequest function is not called.
 +            // Without shouldLoad, we can't distinguish an iframe from a top-level navigation.
 +            // We could try to distinguish using [UIWebView canGoForward], but that's too much complexity,
 +            // and would work only on the first time it was used.
 +
 +            // Our work-around is to set a JS variable and poll until it disappears (from a navigation).
 +            _state = STATE_IOS5_POLLING_FOR_LOAD_START;
 +            _loadStartPollCount = 0;
 +            [self setLoadToken:webView];
 +            [self pollForPageLoadStart:webView];
 +            break;
 +
 +        case STATE_CANCELLED:
 +            fireCallback = YES;
 +            _state = STATE_WAITING_FOR_LOAD_FINISH;
 +            _loadCount += 1;
 +            break;
 +
 +        case STATE_WAITING_FOR_LOAD_START:
 +            if (_loadCount != 0) {
 +                NSLog(@"CDVWebViewDelegate: Unexpected loadCount in didStart. count=%ld", (long)_loadCount);
 +            }
 +            fireCallback = YES;
 +            _state = STATE_WAITING_FOR_LOAD_FINISH;
 +            _loadCount = 1;
 +            break;
 +
 +        case STATE_WAITING_FOR_LOAD_FINISH:
 +            _loadCount += 1;
 +            break;
 +
 +        case STATE_IOS5_POLLING_FOR_LOAD_START:
 +            [self pollForPageLoadStart:webView];
 +            break;
 +
 +        case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
 +            [self pollForPageLoadFinish:webView];
 +            break;
 +
 +        default:
 +            NSLog(@"CDVWebViewDelegate: Unexpected didStart with state=%ld loadCount=%ld", (long)_state, (long)_loadCount);
 +    }
 +    VerboseLog(@"webView didStartLoad (after). state=%d loadCount=%d fireCallback=%d", _state, _loadCount, fireCallback);
 +    if (fireCallback && [_delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
 +        [_delegate webViewDidStartLoad:webView];
 +    }
 +}
 +
 +- (void)webViewDidFinishLoad:(UIWebView*)webView
 +{
 +    VerboseLog(@"webView didFinishLoad (before). state=%d loadCount=%d", _state, _loadCount);
 +    BOOL fireCallback = NO;
 +    switch (_state) {
 +        case STATE_IDLE:
 +            break;
 +
 +        case STATE_WAITING_FOR_LOAD_START:
 +            NSLog(@"CDVWebViewDelegate: Unexpected didFinish while waiting for load start.");
 +            break;
 +
 +        case STATE_WAITING_FOR_LOAD_FINISH:
 +            if (_loadCount == 1) {
 +                fireCallback = YES;
 +                _state = STATE_IDLE;
 +            }
 +            _loadCount -= 1;
 +            break;
 +
 +        case STATE_IOS5_POLLING_FOR_LOAD_START:
 +            [self pollForPageLoadStart:webView];
 +            break;
 +
 +        case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
 +            [self pollForPageLoadFinish:webView];
 +            break;
 +    }
 +    VerboseLog(@"webView didFinishLoad (after). state=%d loadCount=%d fireCallback=%d", _state, _loadCount, fireCallback);
 +    if (fireCallback && [_delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
 +        [_delegate webViewDidFinishLoad:webView];
 +    }
 +}
 +
 +- (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error
 +{
 +    VerboseLog(@"webView didFailLoad (before). state=%d loadCount=%d", _state, _loadCount);
 +    BOOL fireCallback = NO;
 +
 +    switch (_state) {
 +        case STATE_IDLE:
 +            break;
 +
 +        case STATE_WAITING_FOR_LOAD_START:
 +            if ([error code] == NSURLErrorCancelled) {
 +                _state = STATE_CANCELLED;
 +            } else {
 +                _state = STATE_IDLE;
 +            }
 +            fireCallback = YES;
 +            break;
 +
 +        case STATE_WAITING_FOR_LOAD_FINISH:
 +            if ([error code] != NSURLErrorCancelled) {
 +                if (_loadCount == 1) {
 +                    _state = STATE_IDLE;
 +                    fireCallback = YES;
 +                }
 +                _loadCount = -1;
 +            } else {
 +                fireCallback = YES;
 +                _state = STATE_CANCELLED;
 +                _loadCount -= 1;
 +            }
 +            break;
 +
 +        case STATE_IOS5_POLLING_FOR_LOAD_START:
 +            [self pollForPageLoadStart:webView];
 +            break;
 +
 +        case STATE_IOS5_POLLING_FOR_LOAD_FINISH:
 +            [self pollForPageLoadFinish:webView];
 +            break;
 +    }
 +    VerboseLog(@"webView didFailLoad (after). state=%d loadCount=%d, fireCallback=%d", _state, _loadCount, fireCallback);
 +    if (fireCallback && [_delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) {
 +        [_delegate webView:webView didFailLoadWithError:error];
 +    }
 +}
 +
 +@end

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/e0dc7443/CordovaLib/cordova.js
----------------------------------------------------------------------


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[08/10] ios commit: CB-8168 `cordova/run --list` support for iOS (closes #122)

Posted by sh...@apache.org.
CB-8168 `cordova/run --list` support for iOS (closes #122)


Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/54420692
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/54420692
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/54420692

Branch: refs/heads/wkwebview
Commit: 54420692ac2d4725e757b93a1771a33d56a4d87d
Parents: b53b305
Author: muratsu <su...@gmail.com>
Authored: Mon Dec 29 15:59:51 2014 -0800
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Sat Jan 3 21:08:43 2015 -0500

----------------------------------------------------------------------
 bin/templates/scripts/cordova/run | 39 ++++++++++++++++++++++++++++++++++
 tests/spec/create.spec.js         | 13 +++++++++++-
 2 files changed, 51 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/54420692/bin/templates/scripts/cordova/run
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/run b/bin/templates/scripts/cordova/run
index 12633bf..2cd0811 100755
--- a/bin/templates/scripts/cordova/run
+++ b/bin/templates/scripts/cordova/run
@@ -40,6 +40,11 @@ USE_SIMULATOR=false
 # options
 NO_BUILD=false
 
+# display list
+DISPLAY_LIST=false
+DISPLAY_DEVICE=false
+DISPLAY_EMULATOR=false
+
 # separates "key=value", sets an array with 0th index as key, 1st index as value
 _parseOption()
 {
@@ -69,10 +74,15 @@ _parseArgs()
     "--device")
       USE_DEVICE=true
       USE_SIMULATOR=false
+      DISPLAY_DEVICE=true
       ;;
     "--emulator")
       USE_DEVICE=false
       USE_SIMULATOR=true
+      DISPLAY_EMULATOR=true
+      ;;
+    "--list")
+      DISPLAY_LIST=true
       ;;
     "--nobuild")
       NO_BUILD=true
@@ -81,6 +91,18 @@ _parseArgs()
   done
 }
 
+_displayDevices()
+{
+    echo "Available iOS Devices:"
+    "$CORDOVA_PATH/lib/list-devices" 2>&1 | sed 's/^/    /'
+}
+
+_displayVirtualDevices()
+{
+    echo "Available iOS Virtual Devices:"
+    "$CORDOVA_PATH/lib/list-emulator-images" 2>&1 | sed 's/^/    /'
+}
+
 _parseArgs "$@"
 
 CORDOVA_PATH=$( cd "$( dirname "$0" )" && pwd -P)
@@ -93,6 +115,23 @@ DEVICE_APP_PATH="$PROJECT_PATH/build/device/$PROJECT_NAME.app"
 
 source "$CORDOVA_PATH/check_reqs"
 
+# check if it's a list command
+if "$DISPLAY_LIST"; then
+    if "$DISPLAY_DEVICE" || "$DISPLAY_EMULATOR"; then
+        if "$DISPLAY_EMULATOR"; then
+            _displayVirtualDevices
+        fi
+        if "$DISPLAY_DEVICE"; then
+            _displayDevices
+        fi
+        exit 0
+    else
+        _displayVirtualDevices
+        _displayDevices
+        exit 0
+    fi
+fi
+
 
 # if device build found, run it first
 if "$USE_DEVICE"; then

http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/54420692/tests/spec/create.spec.js
----------------------------------------------------------------------
diff --git a/tests/spec/create.spec.js b/tests/spec/create.spec.js
index e25440a..48d6073 100644
--- a/tests/spec/create.spec.js
+++ b/tests/spec/create.spec.js
@@ -103,4 +103,15 @@ describe('create', function() {
         shell.rm('-rf', tmp);
     });
 
-});
\ No newline at end of file
+});
+
+describe('end-to-end list validation', function(){
+    it('handles list parameter', function() {
+        shell.cp('-f', path.join(cordova_bin, 'check_reqs'), path.join(cordova_bin, 'templates', 'scripts', 'cordova', 'check_reqs'));
+        var command = '"' + path.join(cordova_bin, 'templates', 'scripts', 'cordova', 'run') + '" --list';
+        var output = shell.exec(command, {silent: true}).output;
+        expect(output).toMatch(/Available iOS Virtual Devices/);
+        expect(output).toMatch(/Available iOS Devices/);
+        shell.rm('-f', path.join(cordova_bin, 'templates', 'scripts', 'cordova', 'check_reqs'));
+    });
+});


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org


[09/10] ios commit: CB-7872 Fix CODE_SIGN_RESOURCE_RULES_PATH being set wrong in xcconfig (closes #120)

Posted by sh...@apache.org.
CB-7872 Fix CODE_SIGN_RESOURCE_RULES_PATH being set wrong in xcconfig (closes #120)


Project: http://git-wip-us.apache.org/repos/asf/cordova-ios/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-ios/commit/0a2eac7c
Tree: http://git-wip-us.apache.org/repos/asf/cordova-ios/tree/0a2eac7c
Diff: http://git-wip-us.apache.org/repos/asf/cordova-ios/diff/0a2eac7c

Branch: refs/heads/wkwebview
Commit: 0a2eac7c112d0dab054fb8288354c9332c27b6c0
Parents: 5442069
Author: Josef Schweiger <js...@oas.de>
Authored: Fri Dec 5 10:30:30 2014 +0100
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Sat Jan 3 21:11:41 2015 -0500

----------------------------------------------------------------------
 bin/templates/scripts/cordova/build.xcconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-ios/blob/0a2eac7c/bin/templates/scripts/cordova/build.xcconfig
----------------------------------------------------------------------
diff --git a/bin/templates/scripts/cordova/build.xcconfig b/bin/templates/scripts/cordova/build.xcconfig
index dca8c6c..0b89ad0 100644
--- a/bin/templates/scripts/cordova/build.xcconfig
+++ b/bin/templates/scripts/cordova/build.xcconfig
@@ -29,4 +29,4 @@ CODE_SIGN_IDENTITY = iPhone Developer
 CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer
 
 // (CB-7872) Solution for XCode 6.1 signing errors related to resource envelope format deprecation 
-CODE_SIGN_RESOURCE_RULES_PATH = "$(SDKROOT)/ResourceRules.plist"
\ No newline at end of file
+CODE_SIGN_RESOURCE_RULES_PATH = $(SDKROOT)/ResourceRules.plist
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org