commit a35461e2fc6847d09e01467bddd3fc27a8b51131
parent 06825c4767fe5c16f52c2cfcebef7c92749933b2
Author: Simon Kornblith <simon@simonster.com>
Date: Tue, 10 Jul 2012 15:27:38 -0400
Rename q.jsm to q.js, and use a version of q that's closer to the original and allows use in script tags as well
Diffstat:
5 files changed, 1514 insertions(+), 1502 deletions(-)
diff --git a/chrome/content/zotero/xpcom/file.js b/chrome/content/zotero/xpcom/file.js
@@ -28,7 +28,7 @@
* @namespace
*/
Zotero.File = new function(){
- Components.utils.import("resource://zotero/q.jsm");
+ Components.utils.import("resource://zotero/q.js");
Components.utils.import("resource://gre/modules/NetUtil.jsm");
Components.utils.import("resource://gre/modules/FileUtils.jsm");
diff --git a/chrome/content/zotero/xpcom/http.js b/chrome/content/zotero/xpcom/http.js
@@ -3,7 +3,7 @@
* @namespace
*/
Zotero.HTTP = new function() {
- Components.utils.import("resource://zotero/q.jsm");
+ Components.utils.import("resource://zotero/q.js");
/**
* Exception returned for unexpected status when promise* is used
diff --git a/chrome/content/zotero/xpcom/style.js b/chrome/content/zotero/xpcom/style.js
@@ -32,7 +32,7 @@ Zotero.Styles = new function() {
var _initialized = false;
var _styles, _visibleStyles, _cacheTranslatorData;
- Components.utils.import("resource://zotero/q.jsm");
+ Components.utils.import("resource://zotero/q.js");
Components.utils.import("resource://gre/modules/Services.jsm");
this.xsltProcessor = null;
diff --git a/resource/q.js b/resource/q.js
@@ -0,0 +1,1511 @@
+// vim:ts=4:sts=4:sw=4:
+/*jshint browser: true, node: true,
+ curly: true, eqeqeq: true, noarg: true, nonew: true, trailing: true,
+ undef: true */
+/*global define: false, Q: true, msSetImmediate: false, setImmediate: false,
+ ReturnValue: false, cajaVM: false, ses: false */
+/*!
+ *
+ * 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.
+ *
+ * With formatStackTrace and formatSourcePosition functions
+ * Copyright 2006-2008 the V8 project authors. All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+(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.
+
+ // RequireJS
+ if (typeof define === "function") {
+ define(definition);
+
+ // CommonJS
+ } else if (typeof exports === "object") {
+ definition(void 0, exports);
+
+ // SES (Secure EcmaScript)
+ } else if (typeof ses !== "undefined") {
+ if (!ses.ok()) {
+ return;
+ } else {
+ ses.makeQ = function () {
+ var Q = {};
+ return definition(void 0, Q);
+ };
+ }
+
+ // Mozilla JSM
+ } else if (~String(this).indexOf('BackstagePass')) {
+ EXPORTED_SYMBOLS = ["Q"];
+
+ // Q expects an implementation of setTimeout
+ setTimeout = new function() {
+ // We need to maintain references to running nsITimers. Otherwise, they can
+ // get garbage collected before they fire.
+ var _runningTimers = [];
+
+ return function setTimeout(func, ms) {
+ var timer = Components.classes["@mozilla.org/timer;1"].
+ createInstance(Components.interfaces.nsITimer);
+ timer.initWithCallback({"notify":function() {
+ // Remove timer from array so it can be garbage collected
+ _runningTimers.splice(_runningTimers.indexOf(timer), 1);
+
+ // Execute callback function
+ try {
+ func();
+ } catch(err) {
+ // Rethrow errors that occur so that they appear in the error
+ // console with the appropriate name and line numbers. While the
+ // the errors appear without this, the line numbers get eaten.
+ var scriptError = Components.classes["@mozilla.org/scripterror;1"]
+ .createInstance(Components.interfaces.nsIScriptError);
+ scriptError.init(
+ err.message || err.toString(),
+ err.fileName || err.filename || null,
+ null,
+ err.lineNumber || null,
+ null,
+ scriptError.errorFlag,
+ 'component javascript'
+ );
+ Components.classes["@mozilla.org/consoleservice;1"]
+ .getService(Components.interfaces.nsIConsoleService)
+ .logMessage(scriptError);
+ }
+ }}, ms, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
+ _runningTimers.push(timer);
+ }
+ };
+ definition(void 0, Q = {});
+
+ // <script>
+ } else {
+ definition(void 0, Q = {});
+ }
+
+})(function (require, exports) {
+"use strict";
+
+// shims
+
+// used for fallback "defend" and in "allResolved"
+var noop = function () {};
+
+// for the security conscious, defend may be a deep freeze as provided
+// by cajaVM. Otherwise we try to provide a shallow freeze just to
+// discourage promise changes that are not compatible with secure
+// usage. If Object.freeze does not exist, fall back to doing nothing
+// (no op).
+var defend = Object.freeze || noop;
+if (typeof cajaVM !== "undefined") {
+ defend = cajaVM.def;
+}
+
+// use the fastest possible means to execute a task in a future turn
+// of the event loop.
+var nextTick;
+if (typeof process !== "undefined") {
+ // node
+ nextTick = process.nextTick;
+} else if (typeof msSetImmediate === "function") {
+ // IE 10 only, at the moment
+ // And yes, ``bind``ing to ``window`` is necessary O_o.
+ nextTick = msSetImmediate.bind(window);
+} else if (typeof setImmediate === "function") {
+ // https://github.com/NobleJS/setImmediate
+ nextTick = setImmediate;
+} else if (typeof MessageChannel !== "undefined") {
+ // modern browsers
+ // http://www.nonblocking.io/2011/06/windownexttick.html
+ var channel = new MessageChannel();
+ // linked list of tasks (single, with head node)
+ var head = {}, tail = head;
+ channel.port1.onmessage = function () {
+ head = head.next;
+ var task = head.task;
+ delete head.task;
+ task();
+ };
+ nextTick = function (task) {
+ tail = tail.next = {task: task};
+ channel.port2.postMessage(0);
+ };
+} else {
+ // old browsers
+ nextTick = function (task) {
+ setTimeout(task, 0);
+ };
+}
+
+// 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 does have the nice side-effect of reducing the size
+// of the code by reducing x.call() to merely x(), eliminating many
+// hard-to-minify characters.
+// See Mark Miller’s explanation of what this does.
+// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
+var uncurryThis;
+// I have kept both variations because the first is theoretically
+// faster, if bind is available.
+if (Function.prototype.bind) {
+ var Function_bind = Function.prototype.bind;
+ uncurryThis = Function_bind.bind(Function_bind.call);
+} else {
+ uncurryThis = function (f) {
+ return function (thisp) {
+ return f.call.apply(f, arguments);
+ };
+ };
+}
+
+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_keys = Object.keys || function (object) {
+ var keys = [];
+ for (var key in object) {
+ keys.push(key);
+ }
+ return keys;
+};
+
+var object_toString = Object.prototype.toString;
+
+// generator related shims
+
+function isStopIteration(exception) {
+ return (
+ object_toString(exception) === "[object StopIteration]" ||
+ exception instanceof QReturnValue
+ );
+}
+
+var QReturnValue;
+if (typeof ReturnValue !== "undefined") {
+ QReturnValue = ReturnValue;
+} else {
+ QReturnValue = function (value) {
+ this.value = value;
+ };
+}
+
+// long stack traces
+
+function formatStackTrace(error, frames) {
+ var lines = [];
+ try {
+ lines.push(error.toString());
+ } catch (e) {
+ try {
+ lines.push("<error: " + e + ">");
+ } catch (ee) {
+ lines.push("<error>");
+ }
+ }
+ for (var i = 0; i < frames.length; i++) {
+ var frame = frames[i];
+ var line;
+
+ // <Inserted by @domenic>
+ if (typeof frame === "string") {
+ lines.push(frame);
+ // </Inserted by @domenic>
+ } else {
+ try {
+ line = formatSourcePosition(frame);
+ } catch (e) {
+ try {
+ line = "<error: " + e + ">";
+ } catch (ee) {
+ // Any code that reaches this point is seriously nasty!
+ line = "<error>";
+ }
+ }
+ lines.push(" at " + line);
+ }
+ }
+ return lines.join("\n");
+}
+
+function formatSourcePosition(frame) {
+ var fileLocation = "";
+ if (frame.isNative()) {
+ fileLocation = "native";
+ } else if (frame.isEval()) {
+ fileLocation = "eval at " + frame.getEvalOrigin();
+ } else {
+ var fileName = frame.getFileName();
+ if (fileName) {
+ fileLocation += fileName;
+ var lineNumber = frame.getLineNumber();
+ if (lineNumber !== null) {
+ fileLocation += ":" + lineNumber;
+ var columnNumber = frame.getColumnNumber();
+ if (columnNumber) {
+ fileLocation += ":" + columnNumber;
+ }
+ }
+ }
+ }
+ if (!fileLocation) {
+ fileLocation = "unknown source";
+ }
+ var line = "";
+ var functionName = frame.getFunction().name;
+ var addPrefix = true;
+ var isConstructor = frame.isConstructor();
+ var isMethodCall = !(frame.isToplevel() || isConstructor);
+ if (isMethodCall) {
+ var methodName = frame.getMethodName();
+ line += frame.getTypeName() + ".";
+ if (functionName) {
+ line += functionName;
+ if (methodName && (methodName !== functionName)) {
+ line += " [as " + methodName + "]";
+ }
+ } else {
+ line += methodName || "<anonymous>";
+ }
+ } else if (isConstructor) {
+ line += "new " + (functionName || "<anonymous>");
+ } else if (functionName) {
+ line += functionName;
+ } else {
+ line += fileLocation;
+ addPrefix = false;
+ }
+ if (addPrefix) {
+ line += " (" + fileLocation + ")";
+ }
+ return line;
+}
+
+/*
+ * Retrieves an array of structured stack frames parsed from the ``stack``
+ * property of a given object.
+ *
+ * @param objectWithStack {Object} an object with a ``stack`` property: usually
+ * an error or promise.
+ *
+ * @returns an array of stack frame objects. For more information, see
+ * [V8's JavaScript stack trace API documentation](http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi).
+ */
+function getStackFrames(objectWithStack) {
+ var oldPrepareStackTrace = Error.prepareStackTrace;
+
+ Error.prepareStackTrace = function (error, frames) {
+ // Filter out frames from the innards of Node and Q.
+ return frames.filter(function (frame) {
+ var fileName = frame.getFileName();
+ return (
+ fileName !== "module.js" &&
+ fileName !== "node.js" &&
+ fileName !== qFileName
+ );
+ });
+ };
+
+ var stack = objectWithStack.stack;
+
+ Error.prepareStackTrace = oldPrepareStackTrace;
+
+ return stack;
+}
+
+// discover own file name for filtering stack traces
+var qFileName;
+if (Error.captureStackTrace) {
+ qFileName = (function () {
+ var fileName;
+
+ var oldPrepareStackTrace = Error.prepareStackTrace;
+
+ Error.prepareStackTrace = function (error, frames) {
+ fileName = frames[0].getFileName();
+ };
+
+ // teases call of temporary prepareStackTrace
+ // JSHint and Closure Compiler generate known warnings here
+ /*jshint expr: true */
+ new Error().stack;
+
+ Error.prepareStackTrace = oldPrepareStackTrace;
+
+ return fileName;
+ })();
+}
+
+function deprecate(fn, name, alternative){
+ return function () {
+ if (typeof console !== "undefined" && typeof console.warn === "function"){
+ console.warn(name + " is deprecated, use " + alternative + " instead.");
+ }
+ return fn.apply(fn,arguments);
+ };
+}
+
+// end of shims
+// beginning of real work
+
+/**
+ * Performs a task in a future turn of the event loop.
+ * @param {Function} task
+ */
+exports.nextTick = nextTick;
+
+/**
+ * Constructs a {promise, resolve} object.
+ *
+ * The resolver is a callback to invoke with a more resolved value for the
+ * promise. To fulfill the promise, invoke the resolver with any value that is
+ * not a function. To reject the promise, invoke the resolver with a rejection
+ * object. To put the promise in the same state as another promise, invoke the
+ * resolver with that other promise.
+ */
+exports.defer = defer;
+function defer() {
+ // if "pending" 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 pending array is itself an array of complete arguments to
+ // forward to the resolved promise. We coerce the resolution value to a
+ // promise using the ref promise because it handles both fully
+ // resolved values and other promises gracefully.
+ var pending = [], value;
+
+ var deferred = object_create(defer.prototype);
+ var promise = object_create(makePromise.prototype);
+
+ promise.promiseSend = function () {
+ var args = array_slice(arguments);
+ if (pending) {
+ pending.push(args);
+ } else {
+ nextTick(function () {
+ value.promiseSend.apply(value, args);
+ });
+ }
+ };
+
+ promise.valueOf = function () {
+ if (pending) {
+ return promise;
+ }
+ return value.valueOf();
+ };
+
+ if (Error.captureStackTrace) {
+ Error.captureStackTrace(promise, defer);
+ }
+
+ function become(resolvedValue) {
+ if (!pending) {
+ return;
+ }
+ value = resolve(resolvedValue);
+ array_reduce(pending, function (undefined, pending) {
+ nextTick(function () {
+ value.promiseSend.apply(value, pending);
+ });
+ }, void 0);
+ pending = void 0;
+ return value;
+ }
+
+ defend(promise);
+
+ deferred.promise = promise;
+ deferred.resolve = become;
+ deferred.reject = function (exception) {
+ return become(reject(exception));
+ };
+
+ 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);
+ }
+ };
+};
+// XXX deprecated
+defer.prototype.node = deprecate(defer.prototype.makeNodeResolver, "node", "makeNodeResolver");
+
+/**
+ * @param makePromise {Function} a function that returns nothing and accepts
+ * the resolve and reject 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 makePromise
+ */
+exports.promise = promise;
+function promise(makePromise) {
+ var deferred = defer();
+ call(
+ makePromise,
+ void 0,
+ deferred.resolve,
+ deferred.reject
+ ).fail(deferred.reject);
+ return deferred.promise;
+}
+
+/**
+ * Constructs a Promise with a promise descriptor object and optional fallback
+ * function. The descriptor contains methods like when(rejected), get(name),
+ * put(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.
+ */
+exports.makePromise = makePromise;
+function makePromise(descriptor, fallback, valueOf, exception) {
+ if (fallback === void 0) {
+ fallback = function (op) {
+ return reject(new Error("Promise does not support operation: " + op));
+ };
+ }
+
+ var promise = object_create(makePromise.prototype);
+
+ promise.promiseSend = function (op, resolved /* ...args */) {
+ var args = array_slice(arguments, 2);
+ var result;
+ try {
+ if (descriptor[op]) {
+ result = descriptor[op].apply(promise, args);
+ } else {
+ result = fallback.apply(promise, [op].concat(args));
+ }
+ } catch (exception) {
+ result = reject(exception);
+ }
+ resolved(result);
+ };
+
+ if (valueOf) {
+ promise.valueOf = valueOf;
+ }
+
+ if (exception) {
+ promise.exception = exception;
+ }
+
+ defend(promise);
+
+ return promise;
+}
+
+// provide thenables, CommonJS/Promises/A
+makePromise.prototype.then = function (fulfilled, rejected) {
+ return when(this, fulfilled, rejected);
+};
+
+// Chainable methods
+array_reduce(
+ [
+ "isResolved", "isFulfilled", "isRejected",
+ "when", "spread", "send",
+ "get", "put", "del",
+ "post", "invoke",
+ "keys",
+ "apply", "call", "bind",
+ "fapply", "fcall", "fbind",
+ "all", "allResolved",
+ "view", "viewInfo",
+ "timeout", "delay",
+ "catch", "finally", "fail", "fin", "end"
+ ],
+ function (prev, name) {
+ makePromise.prototype[name] = function () {
+ return exports[name].apply(
+ exports,
+ [this].concat(array_slice(arguments))
+ );
+ };
+ },
+ void 0
+);
+
+makePromise.prototype.toSource = function () {
+ return this.toString();
+};
+
+makePromise.prototype.toString = function () {
+ return "[object Promise]";
+};
+
+defend(makePromise.prototype);
+
+/**
+ * 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
+ */
+exports.nearer = valueOf;
+function valueOf(value) {
+ // if !Object.isObject(value)
+ // generates a known JSHint "constructor invocation without new" warning
+ // supposed to be fixed, but isn't? https://github.com/jshint/jshint/issues/392
+ /*jshint newcap: false */
+ if (Object(value) !== value) {
+ return value;
+ } else {
+ return value.valueOf();
+ }
+}
+
+/**
+ * @returns whether the given object is a promise.
+ * Otherwise it is a fulfilled value.
+ */
+exports.isPromise = isPromise;
+function isPromise(object) {
+ return object && typeof object.promiseSend === "function";
+}
+
+/**
+ * @returns whether the given object is a resolved promise.
+ */
+exports.isResolved = isResolved;
+function isResolved(object) {
+ return isFulfilled(object) || isRejected(object);
+}
+
+/**
+ * @returns whether the given object is a value or fulfilled
+ * promise.
+ */
+exports.isFulfilled = isFulfilled;
+function isFulfilled(object) {
+ return !isPromise(valueOf(object));
+}
+
+/**
+ * @returns whether the given object is a rejected promise.
+ */
+exports.isRejected = isRejected;
+function isRejected(object) {
+ object = valueOf(object);
+ return isPromise(object) && 'exception' in object;
+}
+
+var rejections = [];
+var errors = [];
+if (typeof window !== "undefined" && window.console) {
+ // This promise library consumes exceptions thrown in handlers so
+ // they can be handled by a subsequent promise. The rejected
+ // promises get added to this array when they are created, and
+ // removed when they are handled.
+ console.log("Should be empty:", errors);
+}
+
+/**
+ * Constructs a rejected promise.
+ * @param exception value describing the failure
+ */
+exports.reject = reject;
+function reject(exception) {
+ exception = exception || new Error();
+ var rejection = makePromise({
+ "when": function (rejected) {
+ // note that the error has been handled
+ if (rejected) {
+ var at = array_indexOf(rejections, this);
+ if (at !== -1) {
+ errors.splice(at, 1);
+ rejections.splice(at, 1);
+ }
+ }
+ return rejected ? rejected(exception) : reject(exception);
+ }
+ }, function fallback(op) {
+ return reject(exception);
+ }, function valueOf() {
+ return this;
+ }, exception);
+ // note that the error has not been handled
+ rejections.push(rejection);
+ errors.push(exception);
+ return rejection;
+}
+
+/**
+ * Constructs a promise for an immediate reference.
+ * @param value immediate reference
+ */
+exports.begin = resolve; // XXX experimental
+exports.resolve = resolve;
+exports.ref = deprecate(resolve, "ref", "resolve"); // XXX deprecated, use resolve
+function resolve(object) {
+ // 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(object)) {
+ return object;
+ }
+ // assimilate thenables, CommonJS/Promises/A
+ if (object && typeof object.then === "function") {
+ var result = defer();
+ object.then(result.resolve, result.reject);
+ return result.promise;
+ }
+ return makePromise({
+ "when": function (rejected) {
+ return object;
+ },
+ "get": function (name) {
+ return object[name];
+ },
+ "put": function (name, value) {
+ return object[name] = value;
+ },
+ "del": function (name) {
+ return delete object[name];
+ },
+ "post": function (name, value) {
+ return object[name].apply(object, value);
+ },
+ "apply": function (self, args) {
+ return object.apply(self, args);
+ },
+ "fapply": function (args) {
+ return object.apply(void 0, args);
+ },
+ "viewInfo": function () {
+ var on = object;
+ var properties = {};
+
+ function fixFalsyProperty(name) {
+ if (!properties[name]) {
+ properties[name] = typeof on[name];
+ }
+ }
+
+ while (on) {
+ Object.getOwnPropertyNames(on).forEach(fixFalsyProperty);
+ on = Object.getPrototypeOf(on);
+ }
+ return {
+ "type": typeof object,
+ "properties": properties
+ };
+ },
+ "keys": function () {
+ return object_keys(object);
+ }
+ }, void 0, function valueOf() {
+ return object;
+ });
+}
+
+/**
+ * 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.
+ */
+exports.master = master;
+function master(object) {
+ return makePromise({
+ "isDef": function () {}
+ }, function fallback(op) {
+ var args = array_slice(arguments);
+ return send.apply(void 0, [object].concat(args));
+ }, function () {
+ return valueOf(object);
+ });
+}
+
+exports.viewInfo = viewInfo;
+function viewInfo(object, info) {
+ object = resolve(object);
+ if (info) {
+ return makePromise({
+ "viewInfo": function () {
+ return info;
+ }
+ }, function fallback(op) {
+ var args = array_slice(arguments);
+ return send.apply(void 0, [object].concat(args));
+ }, function () {
+ return valueOf(object);
+ });
+ } else {
+ return send(object, "viewInfo");
+ }
+}
+
+exports.view = view;
+function view(object) {
+ return viewInfo(object).when(function (info) {
+ var view;
+ if (info.type === "function") {
+ view = function () {
+ return apply(object, void 0, arguments);
+ };
+ } else {
+ view = {};
+ }
+ var properties = info.properties || {};
+ object_keys(properties).forEach(function (name) {
+ if (properties[name] === "function") {
+ view[name] = function () {
+ return post(object, name, arguments);
+ };
+ }
+ });
+ return resolve(view);
+ });
+}
+
+/**
+ * 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
+ * @return promise for the return value from the invoked callback
+ */
+exports.when = when;
+function when(value, fulfilled, rejected) {
+ 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 fulfilled ? fulfilled(value) : value;
+ } catch (exception) {
+ return reject(exception);
+ }
+ }
+
+ function _rejected(exception) {
+ try {
+ return rejected ? rejected(exception) : reject(exception);
+ } catch (newException) {
+ return reject(newException);
+ }
+ }
+
+ nextTick(function () {
+ resolve(value).promiseSend("when", function (value) {
+ if (done) {
+ return;
+ }
+ done = true;
+ resolve(value).promiseSend("when", function (value) {
+ deferred.resolve(_fulfilled(value));
+ }, function (exception) {
+ deferred.resolve(_rejected(exception));
+ });
+ }, function (exception) {
+ if (done) {
+ return;
+ }
+ done = true;
+ deferred.resolve(_rejected(exception));
+ });
+ });
+
+ return deferred.promise;
+}
+
+/**
+ * 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.
+ */
+exports.spread = spread;
+function spread(promise, fulfilled, rejected) {
+ return when(promise, function (values) {
+ return fulfilled.apply(void 0, values);
+ }, rejected);
+}
+
+/**
+ * The async function is a decorator for generator functions, turning
+ * them into asynchronous generators. This presently only works in
+ * Firefox/Spidermonkey, however, 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.
+ *
+ * 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.
+ * - in present implementations of generators, when a generator
+ * function is complete, it throws ``StopIteration``, ``return`` is
+ * a syntax error in the presence of ``yield``, so there is no
+ * observable return value. There is a proposal[1] to add support
+ * for ``return``, which would permit the value to be carried by a
+ * ``StopIteration`` instance, in which case it would fulfill the
+ * promise returned by the asynchronous generator. This can be
+ * emulated today by throwing StopIteration explicitly with a value
+ * property.
+ *
+ * [1]: http://wiki.ecmascript.org/doku.php?id=strawman:async_functions#reference_implementation
+ *
+ */
+exports.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;
+ 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, "send");
+ var errback = continuer.bind(continuer, "throw");
+ return callback();
+ };
+}
+
+/**
+ * Throws a ReturnValue exception to stop an asynchronous generator.
+ * Only useful presently in Firefox/SpiderMonkey since generators are
+ * implemented.
+ * @param value the return value for the surrounding generator
+ * @throws ReturnValue exception with the value.
+ * @example
+ * Q.async(function () {
+ * var foo = yield getFooPromise();
+ * var bar = yield getBarPromise();
+ * Q.return(foo + bar);
+ * })
+ */
+exports['return'] = _return;
+function _return(value) {
+ throw new QReturnValue(value);
+}
+
+/**
+ * Constructs a promise method that can be used to safely observe resolution of
+ * a promise for an arbitrarily named method like "propfind" in a future turn.
+ */
+exports.sender = deprecate(sender, "sender", "dispatcher"); // XXX deprecated, use dispatcher
+exports.Method = deprecate(sender, "Method", "dispatcher"); // XXX deprecated, use dispatcher
+function sender(op) {
+ return function (object) {
+ var args = array_slice(arguments, 1);
+ return send.apply(void 0, [object, op].concat(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
+ */
+exports.send = deprecate(send, "send", "dispatch"); // XXX deprecated, use dispatch
+function send(object, op) {
+ var deferred = defer();
+ var args = array_slice(arguments, 2);
+ object = resolve(object);
+ nextTick(function () {
+ object.promiseSend.apply(
+ object,
+ [op, deferred.resolve].concat(args)
+ );
+ });
+ return deferred.promise;
+}
+
+/**
+ * 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
+ */
+exports.dispatch = dispatch;
+function dispatch(object, op, args) {
+ var deferred = defer();
+ object = resolve(object);
+ nextTick(function () {
+ object.promiseSend.apply(
+ object,
+ [op, deferred.resolve].concat(args)
+ );
+ });
+ return deferred.promise;
+}
+
+/**
+ * Constructs a promise method that can be used to safely observe resolution of
+ * a promise for an arbitrarily named method like "propfind" in a future turn.
+ *
+ * "dispatcher" constructs methods like "get(promise, name)" and "put(promise)".
+ */
+exports.dispatcher = dispatcher;
+function dispatcher(op) {
+ return function (object) {
+ var args = array_slice(arguments, 1);
+ return dispatch(object, op, args);
+ };
+}
+
+/**
+ * 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
+ */
+exports.get = dispatcher("get");
+
+/**
+ * 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
+ */
+exports.put = dispatcher("put");
+
+/**
+ * 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
+ */
+exports["delete"] = // XXX experimental
+exports.del = dispatcher("del");
+
+/**
+ * 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
+var post = exports.post = dispatcher("post");
+
+/**
+ * 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
+ */
+exports.invoke = function (value, name) {
+ var args = array_slice(arguments, 2);
+ return post(value, name, args);
+};
+
+/**
+ * Applies the promised function in a future turn.
+ * @param object promise or immediate reference for target function
+ * @param thisp the `this` object for the call
+ * @param args array of application arguments
+ */
+// XXX deprecated, use fapply
+var apply = exports.apply = deprecate(dispatcher("apply"), "apply", "fapply");
+
+/**
+ * Applies the promised function in a future turn.
+ * @param object promise or immediate reference for target function
+ * @param args array of application arguments
+ */
+var fapply = exports.fapply = dispatcher("fapply");
+
+/**
+ * Calls the promised function in a future turn.
+ * @param object promise or immediate reference for target function
+ * @param thisp the `this` object for the call
+ * @param ...args array of application arguments
+ */
+// XXX deprecated, use fcall
+exports.call = deprecate(call, "call", "fcall");
+function call(value, thisp) {
+ var args = array_slice(arguments, 2);
+ return apply(value, thisp, args);
+}
+
+/**
+ * Calls the promised function in a future turn.
+ * @param object promise or immediate reference for target function
+ * @param ...args array of application arguments
+ */
+exports["try"] = fcall; // XXX experimental
+exports.fcall = fcall;
+function fcall(value) {
+ var args = array_slice(arguments, 1);
+ return fapply(value, args);
+}
+
+/**
+ * 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 thisp the `this` object for the call
+ * @param ...args array of application arguments
+ */
+exports.bind = deprecate(bind, "bind", "fbind"); // XXX deprecated, use fbind
+function bind(value, thisp) {
+ var args = array_slice(arguments, 2);
+ return function bound() {
+ var allArgs = args.concat(array_slice(arguments));
+ return apply(value, thisp, allArgs);
+ };
+}
+
+/**
+ * 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
+ */
+exports.fbind = fbind;
+function fbind(value) {
+ var args = array_slice(arguments, 1);
+ return function fbound() {
+ var allArgs = args.concat(array_slice(arguments));
+ return fapply(value, allArgs);
+ };
+}
+
+/**
+ * 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 resolved object
+ */
+exports.keys = dispatcher("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
+exports.all = all;
+function all(promises) {
+ return when(promises, function (promises) {
+ var countDown = promises.length;
+ if (countDown === 0) {
+ return resolve(promises);
+ }
+ var deferred = defer();
+ array_reduce(promises, function (undefined, promise, index) {
+ when(promise, function (value) {
+ promises[index] = value;
+ if (--countDown === 0) {
+ deferred.resolve(promises);
+ }
+ })
+ .fail(deferred.reject);
+ }, void 0);
+ return deferred.promise;
+ });
+}
+
+/**
+ * Waits for all promises to be resolved, 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
+ */
+exports.allResolved = allResolved;
+function allResolved(promises) {
+ return when(promises, function (promises) {
+ return when(all(array_map(promises, function (promise) {
+ return when(promise, noop, noop);
+ })), function () {
+ return array_map(promises, resolve);
+ });
+ });
+}
+
+/**
+ * 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
+ */
+exports["catch"] = // XXX experimental
+exports.fail = fail;
+function fail(promise, rejected) {
+ return when(promise, void 0, rejected);
+}
+
+/**
+ * Provides an opportunity to observe the rejection 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.
+ */
+exports["finally"] = // XXX experimental
+exports.fin = fin;
+function fin(promise, callback) {
+ return when(promise, function (value) {
+ return when(callback(), function () {
+ return value;
+ });
+ }, function (exception) {
+ return when(callback(), function () {
+ return reject(exception);
+ });
+ });
+}
+
+/**
+ * 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
+ */
+exports.end = end; // XXX stopgap
+function end(promise) {
+ when(promise, void 0, function (error) {
+ // forward to a future turn so that ``when``
+ // does not catch it and turn it into a rejection.
+ nextTick(function () {
+ // If possible (that is, if in V8), transform the error stack
+ // trace by removing Node and Q cruft, then concatenating with
+ // the stack trace of the promise we are ``end``ing. See #57.
+ if (Error.captureStackTrace && typeof error === "object" &&
+ "stack" in error) {
+ var errorStackFrames = getStackFrames(error);
+ var promiseStackFrames = getStackFrames(promise);
+
+ var combinedStackFrames = errorStackFrames.concat(
+ "From previous event:",
+ promiseStackFrames
+ );
+ error.stack = formatStackTrace(error, combinedStackFrames);
+ }
+
+ throw error;
+ });
+ });
+}
+
+/**
+ * Causes a promise to be rejected if it does not get fulfilled before
+ * some milliseconds time out.
+ * @param {Any*} promise
+ * @param {Number} milliseconds timeout
+ * @returns a promise for the resolution of the given promise if it is
+ * fulfilled before the timeout, otherwise rejected.
+ */
+exports.timeout = timeout;
+function timeout(promise, ms) {
+ var deferred = defer();
+ var timeoutId = setTimeout(function () {
+ deferred.reject(new Error("Timed out after " + ms + " ms"));
+ }, ms);
+
+ when(promise, function (value) {
+ clearTimeout(timeoutId);
+ deferred.resolve(value);
+ }, deferred.reject);
+ return deferred.promise;
+}
+
+/**
+ * Returns a promise for the given value (or promised value) after some
+ * milliseconds.
+ * @param {Any*} promise
+ * @param {Number} milliseconds
+ * @returns a promise for the resolution of the given promise after some
+ * time has elapsed.
+ */
+exports.delay = delay;
+function delay(promise, timeout) {
+ if (timeout === void 0) {
+ timeout = promise;
+ promise = void 0;
+ }
+ var deferred = defer();
+ setTimeout(function () {
+ deferred.resolve(promise);
+ }, timeout);
+ return deferred.promise;
+}
+
+/**
+ * Passes a continuation to a Node function, which is called with a given
+ * `this` value and arguments provided as an array, and returns a promise.
+ *
+ * var FS = require("fs");
+ * Q.napply(FS.readFile, FS, [__filename])
+ * .then(function (content) {
+ * })
+ *
+ */
+exports.napply = napply;
+function napply(callback, thisp, args) {
+ return nbind(callback, thisp).apply(void 0, args);
+}
+
+/**
+ * Passes a continuation to a Node function, which is called with a given
+ * `this` value and arguments provided individually, and returns a promise.
+ *
+ * var FS = require("fs");
+ * Q.ncall(FS.readFile, FS, __filename)
+ * .then(function (content) {
+ * })
+ *
+ */
+exports.ncall = ncall;
+function ncall(callback, thisp /*, ...args*/) {
+ var args = array_slice(arguments, 2);
+ return napply(callback, thisp, args);
+}
+
+/**
+ * Wraps a NodeJS continuation passing function and returns an equivalent
+ * version that returns a promise.
+ *
+ * Q.nbind(FS.readFile, FS)(__filename)
+ * .then(console.log)
+ * .end()
+ *
+ */
+exports.nbind = nbind;
+function nbind(callback /* thisp, ...args*/) {
+ if (arguments.length > 1) {
+ var thisp = arguments[1];
+ var args = array_slice(arguments, 2);
+
+ var originalCallback = callback;
+ callback = function () {
+ var combinedArgs = args.concat(array_slice(arguments));
+ return originalCallback.apply(thisp, combinedArgs);
+ };
+ }
+ return function () {
+ var deferred = defer();
+ var args = array_slice(arguments);
+ // add a continuation that resolves the promise
+ args.push(deferred.makeNodeResolver());
+ // trap exceptions thrown by the callback
+ fapply(callback, args)
+ .fail(deferred.reject);
+ return deferred.promise;
+ };
+}
+
+/**
+ * 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
+ */
+exports.npost = npost;
+function npost(object, name, args) {
+ return napply(object[name], object, args);
+}
+
+/**
+ * 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
+ */
+exports.ninvoke = ninvoke;
+function ninvoke(object, name /*, ...args*/) {
+ var args = array_slice(arguments, 2);
+ return napply(object[name], object, args);
+}
+
+defend(exports);
+
+});
diff --git a/resource/q.jsm b/resource/q.jsm
@@ -1,1499 +0,0 @@
-// vim:ts=4:sts=4:sw=4:
-/*jshint browser: true, node: true,
- curly: true, eqeqeq: true, noarg: true, nonew: true, trailing: true,
- undef: true */
-/*global define: false, Q: true, msSetImmediate: false, setImmediate: false,
- ReturnValue: false, cajaVM: false, ses: false */
-/*!
- *
- * 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.
- *
- * With formatStackTrace and formatSourcePosition functions
- * Copyright 2006-2008 the V8 project authors. All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-var EXPORTED_SYMBOLS = ["Q"];
-var setTimeout = new function() {
- var _runningTimers = [];
- return function setTimeout(func, ms) {
- var timer = Components.classes["@mozilla.org/timer;1"].
- createInstance(Components.interfaces.nsITimer);
- var timerCallback = {"notify":function() {
- // remove timer from global scope, so it can be garbage collected
- _runningTimers.splice(_runningTimers.indexOf(timer), 1);
- // execute callback function
- try {
- func();
- } catch(err) {
- var scriptError = Components.classes["@mozilla.org/scripterror;1"]
- .createInstance(Components.interfaces.nsIScriptError);
- scriptError.init(
- err.message ? err.message : err.toString(),
- err.fileName ? err.fileName : (err.filename ? err.filename : null),
- null,
- err.lineNumber ? err.lineNumber : null,
- null,
- scriptError['errorFlag'],
- 'component javascript'
- );
- Components.classes["@mozilla.org/consoleservice;1"]
- .getService(Components.interfaces.nsIConsoleService)
- .logMessage(scriptError);
- }
- }};
- timer.initWithCallback(timerCallback, ms, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
- }
-};
-
-(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.
-
- // RequireJS
- if (typeof define === "function") {
- define(definition);
-
- // CommonJS
- } else if (typeof exports === "object") {
- definition(void 0, exports);
-
- // SES (Secure EcmaScript)
- } else if (typeof ses !== "undefined") {
- if (!ses.ok()) {
- return;
- } else {
- ses.makeQ = function () {
- var Q = {};
- return definition(void 0, Q);
- };
- }
-
- // <script>
- } else {
- definition(void 0, Q = {});
- }
-
-})(function (require, exports) {
-"use strict";
-
-// shims
-
-// used for fallback "defend" and in "allResolved"
-var noop = function () {};
-
-// for the security conscious, defend may be a deep freeze as provided
-// by cajaVM. Otherwise we try to provide a shallow freeze just to
-// discourage promise changes that are not compatible with secure
-// usage. If Object.freeze does not exist, fall back to doing nothing
-// (no op).
-var defend = Object.freeze || noop;
-if (typeof cajaVM !== "undefined") {
- defend = cajaVM.def;
-}
-
-// use the fastest possible means to execute a task in a future turn
-// of the event loop.
-var nextTick;
-if (typeof process !== "undefined") {
- // node
- nextTick = process.nextTick;
-} else if (typeof msSetImmediate === "function") {
- // IE 10 only, at the moment
- // And yes, ``bind``ing to ``window`` is necessary O_o.
- nextTick = msSetImmediate.bind(window);
-} else if (typeof setImmediate === "function") {
- // https://github.com/NobleJS/setImmediate
- nextTick = setImmediate;
-} else if (typeof MessageChannel !== "undefined") {
- // modern browsers
- // http://www.nonblocking.io/2011/06/windownexttick.html
- var channel = new MessageChannel();
- // linked list of tasks (single, with head node)
- var head = {}, tail = head;
- channel.port1.onmessage = function () {
- head = head.next;
- var task = head.task;
- delete head.task;
- task();
- };
- nextTick = function (task) {
- tail = tail.next = {task: task};
- channel.port2.postMessage(0);
- };
-} else {
- // old browsers
- nextTick = function (task) {
- setTimeout(task, 0);
- };
-}
-
-// 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 does have the nice side-effect of reducing the size
-// of the code by reducing x.call() to merely x(), eliminating many
-// hard-to-minify characters.
-// See Mark Miller’s explanation of what this does.
-// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
-var uncurryThis;
-// I have kept both variations because the first is theoretically
-// faster, if bind is available.
-if (Function.prototype.bind) {
- var Function_bind = Function.prototype.bind;
- uncurryThis = Function_bind.bind(Function_bind.call);
-} else {
- uncurryThis = function (f) {
- return function (thisp) {
- return f.call.apply(f, arguments);
- };
- };
-}
-
-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_keys = Object.keys || function (object) {
- var keys = [];
- for (var key in object) {
- keys.push(key);
- }
- return keys;
-};
-
-var object_toString = Object.prototype.toString;
-
-// generator related shims
-
-function isStopIteration(exception) {
- return (
- object_toString(exception) === "[object StopIteration]" ||
- exception instanceof QReturnValue
- );
-}
-
-var QReturnValue;
-if (typeof ReturnValue !== "undefined") {
- QReturnValue = ReturnValue;
-} else {
- QReturnValue = function (value) {
- this.value = value;
- };
-}
-
-// long stack traces
-
-function formatStackTrace(error, frames) {
- var lines = [];
- try {
- lines.push(error.toString());
- } catch (e) {
- try {
- lines.push("<error: " + e + ">");
- } catch (ee) {
- lines.push("<error>");
- }
- }
- for (var i = 0; i < frames.length; i++) {
- var frame = frames[i];
- var line;
-
- // <Inserted by @domenic>
- if (typeof frame === "string") {
- lines.push(frame);
- // </Inserted by @domenic>
- } else {
- try {
- line = formatSourcePosition(frame);
- } catch (e) {
- try {
- line = "<error: " + e + ">";
- } catch (ee) {
- // Any code that reaches this point is seriously nasty!
- line = "<error>";
- }
- }
- lines.push(" at " + line);
- }
- }
- return lines.join("\n");
-}
-
-function formatSourcePosition(frame) {
- var fileLocation = "";
- if (frame.isNative()) {
- fileLocation = "native";
- } else if (frame.isEval()) {
- fileLocation = "eval at " + frame.getEvalOrigin();
- } else {
- var fileName = frame.getFileName();
- if (fileName) {
- fileLocation += fileName;
- var lineNumber = frame.getLineNumber();
- if (lineNumber !== null) {
- fileLocation += ":" + lineNumber;
- var columnNumber = frame.getColumnNumber();
- if (columnNumber) {
- fileLocation += ":" + columnNumber;
- }
- }
- }
- }
- if (!fileLocation) {
- fileLocation = "unknown source";
- }
- var line = "";
- var functionName = frame.getFunction().name;
- var addPrefix = true;
- var isConstructor = frame.isConstructor();
- var isMethodCall = !(frame.isToplevel() || isConstructor);
- if (isMethodCall) {
- var methodName = frame.getMethodName();
- line += frame.getTypeName() + ".";
- if (functionName) {
- line += functionName;
- if (methodName && (methodName !== functionName)) {
- line += " [as " + methodName + "]";
- }
- } else {
- line += methodName || "<anonymous>";
- }
- } else if (isConstructor) {
- line += "new " + (functionName || "<anonymous>");
- } else if (functionName) {
- line += functionName;
- } else {
- line += fileLocation;
- addPrefix = false;
- }
- if (addPrefix) {
- line += " (" + fileLocation + ")";
- }
- return line;
-}
-
-/*
- * Retrieves an array of structured stack frames parsed from the ``stack``
- * property of a given object.
- *
- * @param objectWithStack {Object} an object with a ``stack`` property: usually
- * an error or promise.
- *
- * @returns an array of stack frame objects. For more information, see
- * [V8's JavaScript stack trace API documentation](http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi).
- */
-function getStackFrames(objectWithStack) {
- var oldPrepareStackTrace = Error.prepareStackTrace;
-
- Error.prepareStackTrace = function (error, frames) {
- // Filter out frames from the innards of Node and Q.
- return frames.filter(function (frame) {
- var fileName = frame.getFileName();
- return (
- fileName !== "module.js" &&
- fileName !== "node.js" &&
- fileName !== qFileName
- );
- });
- };
-
- var stack = objectWithStack.stack;
-
- Error.prepareStackTrace = oldPrepareStackTrace;
-
- return stack;
-}
-
-// discover own file name for filtering stack traces
-var qFileName;
-if (Error.captureStackTrace) {
- qFileName = (function () {
- var fileName;
-
- var oldPrepareStackTrace = Error.prepareStackTrace;
-
- Error.prepareStackTrace = function (error, frames) {
- fileName = frames[0].getFileName();
- };
-
- // teases call of temporary prepareStackTrace
- // JSHint and Closure Compiler generate known warnings here
- /*jshint expr: true */
- new Error().stack;
-
- Error.prepareStackTrace = oldPrepareStackTrace;
-
- return fileName;
- })();
-}
-
-function deprecate(fn, name, alternative){
- return function () {
- if (typeof console !== "undefined" && typeof console.warn === "function"){
- console.warn(name + " is deprecated, use " + alternative + " instead.");
- }
- return fn.apply(fn,arguments);
- };
-}
-
-// end of shims
-// beginning of real work
-
-/**
- * Performs a task in a future turn of the event loop.
- * @param {Function} task
- */
-exports.nextTick = nextTick;
-
-/**
- * Constructs a {promise, resolve} object.
- *
- * The resolver is a callback to invoke with a more resolved value for the
- * promise. To fulfill the promise, invoke the resolver with any value that is
- * not a function. To reject the promise, invoke the resolver with a rejection
- * object. To put the promise in the same state as another promise, invoke the
- * resolver with that other promise.
- */
-exports.defer = defer;
-function defer() {
- // if "pending" 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 pending array is itself an array of complete arguments to
- // forward to the resolved promise. We coerce the resolution value to a
- // promise using the ref promise because it handles both fully
- // resolved values and other promises gracefully.
- var pending = [], value;
-
- var deferred = object_create(defer.prototype);
- var promise = object_create(makePromise.prototype);
-
- promise.promiseSend = function () {
- var args = array_slice(arguments);
- if (pending) {
- pending.push(args);
- } else {
- nextTick(function () {
- value.promiseSend.apply(value, args);
- });
- }
- };
-
- promise.valueOf = function () {
- if (pending) {
- return promise;
- }
- return value.valueOf();
- };
-
- if (Error.captureStackTrace) {
- Error.captureStackTrace(promise, defer);
- }
-
- function become(resolvedValue) {
- if (!pending) {
- return;
- }
- value = resolve(resolvedValue);
- array_reduce(pending, function (undefined, pending) {
- nextTick(function () {
- value.promiseSend.apply(value, pending);
- });
- }, void 0);
- pending = void 0;
- return value;
- }
-
- defend(promise);
-
- deferred.promise = promise;
- deferred.resolve = become;
- deferred.reject = function (exception) {
- return become(reject(exception));
- };
-
- 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);
- }
- };
-};
-// XXX deprecated
-defer.prototype.node = deprecate(defer.prototype.makeNodeResolver, "node", "makeNodeResolver");
-
-/**
- * @param makePromise {Function} a function that returns nothing and accepts
- * the resolve and reject 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 makePromise
- */
-exports.promise = promise;
-function promise(makePromise) {
- var deferred = defer();
- call(
- makePromise,
- void 0,
- deferred.resolve,
- deferred.reject
- ).fail(deferred.reject);
- return deferred.promise;
-}
-
-/**
- * Constructs a Promise with a promise descriptor object and optional fallback
- * function. The descriptor contains methods like when(rejected), get(name),
- * put(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.
- */
-exports.makePromise = makePromise;
-function makePromise(descriptor, fallback, valueOf, exception) {
- if (fallback === void 0) {
- fallback = function (op) {
- return reject(new Error("Promise does not support operation: " + op));
- };
- }
-
- var promise = object_create(makePromise.prototype);
-
- promise.promiseSend = function (op, resolved /* ...args */) {
- var args = array_slice(arguments, 2);
- var result;
- try {
- if (descriptor[op]) {
- result = descriptor[op].apply(promise, args);
- } else {
- result = fallback.apply(promise, [op].concat(args));
- }
- } catch (exception) {
- result = reject(exception);
- }
- resolved(result);
- };
-
- if (valueOf) {
- promise.valueOf = valueOf;
- }
-
- if (exception) {
- promise.exception = exception;
- }
-
- defend(promise);
-
- return promise;
-}
-
-// provide thenables, CommonJS/Promises/A
-makePromise.prototype.then = function (fulfilled, rejected) {
- return when(this, fulfilled, rejected);
-};
-
-// Chainable methods
-array_reduce(
- [
- "isResolved", "isFulfilled", "isRejected",
- "when", "spread", "send",
- "get", "put", "del",
- "post", "invoke",
- "keys",
- "apply", "call", "bind",
- "fapply", "fcall", "fbind",
- "all", "allResolved",
- "view", "viewInfo",
- "timeout", "delay",
- "catch", "finally", "fail", "fin", "end"
- ],
- function (prev, name) {
- makePromise.prototype[name] = function () {
- return exports[name].apply(
- exports,
- [this].concat(array_slice(arguments))
- );
- };
- },
- void 0
-);
-
-makePromise.prototype.toSource = function () {
- return this.toString();
-};
-
-makePromise.prototype.toString = function () {
- return "[object Promise]";
-};
-
-defend(makePromise.prototype);
-
-/**
- * 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
- */
-exports.nearer = valueOf;
-function valueOf(value) {
- // if !Object.isObject(value)
- // generates a known JSHint "constructor invocation without new" warning
- // supposed to be fixed, but isn't? https://github.com/jshint/jshint/issues/392
- /*jshint newcap: false */
- if (Object(value) !== value) {
- return value;
- } else {
- return value.valueOf();
- }
-}
-
-/**
- * @returns whether the given object is a promise.
- * Otherwise it is a fulfilled value.
- */
-exports.isPromise = isPromise;
-function isPromise(object) {
- return object && typeof object.promiseSend === "function";
-}
-
-/**
- * @returns whether the given object is a resolved promise.
- */
-exports.isResolved = isResolved;
-function isResolved(object) {
- return isFulfilled(object) || isRejected(object);
-}
-
-/**
- * @returns whether the given object is a value or fulfilled
- * promise.
- */
-exports.isFulfilled = isFulfilled;
-function isFulfilled(object) {
- return !isPromise(valueOf(object));
-}
-
-/**
- * @returns whether the given object is a rejected promise.
- */
-exports.isRejected = isRejected;
-function isRejected(object) {
- object = valueOf(object);
- return isPromise(object) && 'exception' in object;
-}
-
-var rejections = [];
-var errors = [];
-if (typeof window !== "undefined" && window.console) {
- // This promise library consumes exceptions thrown in handlers so
- // they can be handled by a subsequent promise. The rejected
- // promises get added to this array when they are created, and
- // removed when they are handled.
- console.log("Should be empty:", errors);
-}
-
-/**
- * Constructs a rejected promise.
- * @param exception value describing the failure
- */
-exports.reject = reject;
-function reject(exception) {
- exception = exception || new Error();
- var rejection = makePromise({
- "when": function (rejected) {
- // note that the error has been handled
- if (rejected) {
- var at = array_indexOf(rejections, this);
- if (at !== -1) {
- errors.splice(at, 1);
- rejections.splice(at, 1);
- }
- }
- return rejected ? rejected(exception) : reject(exception);
- }
- }, function fallback(op) {
- return reject(exception);
- }, function valueOf() {
- return this;
- }, exception);
- // note that the error has not been handled
- rejections.push(rejection);
- errors.push(exception);
- return rejection;
-}
-
-/**
- * Constructs a promise for an immediate reference.
- * @param value immediate reference
- */
-exports.begin = resolve; // XXX experimental
-exports.resolve = resolve;
-exports.ref = deprecate(resolve, "ref", "resolve"); // XXX deprecated, use resolve
-function resolve(object) {
- // 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(object)) {
- return object;
- }
- // assimilate thenables, CommonJS/Promises/A
- if (object && typeof object.then === "function") {
- var result = defer();
- object.then(result.resolve, result.reject);
- return result.promise;
- }
- return makePromise({
- "when": function (rejected) {
- return object;
- },
- "get": function (name) {
- return object[name];
- },
- "put": function (name, value) {
- return object[name] = value;
- },
- "del": function (name) {
- return delete object[name];
- },
- "post": function (name, value) {
- return object[name].apply(object, value);
- },
- "apply": function (self, args) {
- return object.apply(self, args);
- },
- "fapply": function (args) {
- return object.apply(void 0, args);
- },
- "viewInfo": function () {
- var on = object;
- var properties = {};
-
- function fixFalsyProperty(name) {
- if (!properties[name]) {
- properties[name] = typeof on[name];
- }
- }
-
- while (on) {
- Object.getOwnPropertyNames(on).forEach(fixFalsyProperty);
- on = Object.getPrototypeOf(on);
- }
- return {
- "type": typeof object,
- "properties": properties
- };
- },
- "keys": function () {
- return object_keys(object);
- }
- }, void 0, function valueOf() {
- return object;
- });
-}
-
-/**
- * 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.
- */
-exports.master = master;
-function master(object) {
- return makePromise({
- "isDef": function () {}
- }, function fallback(op) {
- var args = array_slice(arguments);
- return send.apply(void 0, [object].concat(args));
- }, function () {
- return valueOf(object);
- });
-}
-
-exports.viewInfo = viewInfo;
-function viewInfo(object, info) {
- object = resolve(object);
- if (info) {
- return makePromise({
- "viewInfo": function () {
- return info;
- }
- }, function fallback(op) {
- var args = array_slice(arguments);
- return send.apply(void 0, [object].concat(args));
- }, function () {
- return valueOf(object);
- });
- } else {
- return send(object, "viewInfo");
- }
-}
-
-exports.view = view;
-function view(object) {
- return viewInfo(object).when(function (info) {
- var view;
- if (info.type === "function") {
- view = function () {
- return apply(object, void 0, arguments);
- };
- } else {
- view = {};
- }
- var properties = info.properties || {};
- object_keys(properties).forEach(function (name) {
- if (properties[name] === "function") {
- view[name] = function () {
- return post(object, name, arguments);
- };
- }
- });
- return resolve(view);
- });
-}
-
-/**
- * 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
- * @return promise for the return value from the invoked callback
- */
-exports.when = when;
-function when(value, fulfilled, rejected) {
- 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 fulfilled ? fulfilled(value) : value;
- } catch (exception) {
- return reject(exception);
- }
- }
-
- function _rejected(exception) {
- try {
- return rejected ? rejected(exception) : reject(exception);
- } catch (newException) {
- return reject(newException);
- }
- }
-
- nextTick(function () {
- resolve(value).promiseSend("when", function (value) {
- if (done) {
- return;
- }
- done = true;
- resolve(value).promiseSend("when", function (value) {
- deferred.resolve(_fulfilled(value));
- }, function (exception) {
- deferred.resolve(_rejected(exception));
- });
- }, function (exception) {
- if (done) {
- return;
- }
- done = true;
- deferred.resolve(_rejected(exception));
- });
- });
-
- return deferred.promise;
-}
-
-/**
- * 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.
- */
-exports.spread = spread;
-function spread(promise, fulfilled, rejected) {
- return when(promise, function (values) {
- return fulfilled.apply(void 0, values);
- }, rejected);
-}
-
-/**
- * The async function is a decorator for generator functions, turning
- * them into asynchronous generators. This presently only works in
- * Firefox/Spidermonkey, however, 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.
- *
- * 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.
- * - in present implementations of generators, when a generator
- * function is complete, it throws ``StopIteration``, ``return`` is
- * a syntax error in the presence of ``yield``, so there is no
- * observable return value. There is a proposal[1] to add support
- * for ``return``, which would permit the value to be carried by a
- * ``StopIteration`` instance, in which case it would fulfill the
- * promise returned by the asynchronous generator. This can be
- * emulated today by throwing StopIteration explicitly with a value
- * property.
- *
- * [1]: http://wiki.ecmascript.org/doku.php?id=strawman:async_functions#reference_implementation
- *
- */
-exports.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;
- 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, "send");
- var errback = continuer.bind(continuer, "throw");
- return callback();
- };
-}
-
-/**
- * Throws a ReturnValue exception to stop an asynchronous generator.
- * Only useful presently in Firefox/SpiderMonkey since generators are
- * implemented.
- * @param value the return value for the surrounding generator
- * @throws ReturnValue exception with the value.
- * @example
- * Q.async(function () {
- * var foo = yield getFooPromise();
- * var bar = yield getBarPromise();
- * Q.return(foo + bar);
- * })
- */
-exports['return'] = _return;
-function _return(value) {
- throw new QReturnValue(value);
-}
-
-/**
- * Constructs a promise method that can be used to safely observe resolution of
- * a promise for an arbitrarily named method like "propfind" in a future turn.
- */
-exports.sender = deprecate(sender, "sender", "dispatcher"); // XXX deprecated, use dispatcher
-exports.Method = deprecate(sender, "Method", "dispatcher"); // XXX deprecated, use dispatcher
-function sender(op) {
- return function (object) {
- var args = array_slice(arguments, 1);
- return send.apply(void 0, [object, op].concat(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
- */
-exports.send = deprecate(send, "send", "dispatch"); // XXX deprecated, use dispatch
-function send(object, op) {
- var deferred = defer();
- var args = array_slice(arguments, 2);
- object = resolve(object);
- nextTick(function () {
- object.promiseSend.apply(
- object,
- [op, deferred.resolve].concat(args)
- );
- });
- return deferred.promise;
-}
-
-/**
- * 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
- */
-exports.dispatch = dispatch;
-function dispatch(object, op, args) {
- var deferred = defer();
- object = resolve(object);
- nextTick(function () {
- object.promiseSend.apply(
- object,
- [op, deferred.resolve].concat(args)
- );
- });
- return deferred.promise;
-}
-
-/**
- * Constructs a promise method that can be used to safely observe resolution of
- * a promise for an arbitrarily named method like "propfind" in a future turn.
- *
- * "dispatcher" constructs methods like "get(promise, name)" and "put(promise)".
- */
-exports.dispatcher = dispatcher;
-function dispatcher(op) {
- return function (object) {
- var args = array_slice(arguments, 1);
- return dispatch(object, op, args);
- };
-}
-
-/**
- * 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
- */
-exports.get = dispatcher("get");
-
-/**
- * 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
- */
-exports.put = dispatcher("put");
-
-/**
- * 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
- */
-exports["delete"] = // XXX experimental
-exports.del = dispatcher("del");
-
-/**
- * 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
-var post = exports.post = dispatcher("post");
-
-/**
- * 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
- */
-exports.invoke = function (value, name) {
- var args = array_slice(arguments, 2);
- return post(value, name, args);
-};
-
-/**
- * Applies the promised function in a future turn.
- * @param object promise or immediate reference for target function
- * @param thisp the `this` object for the call
- * @param args array of application arguments
- */
-// XXX deprecated, use fapply
-var apply = exports.apply = deprecate(dispatcher("apply"), "apply", "fapply");
-
-/**
- * Applies the promised function in a future turn.
- * @param object promise or immediate reference for target function
- * @param args array of application arguments
- */
-var fapply = exports.fapply = dispatcher("fapply");
-
-/**
- * Calls the promised function in a future turn.
- * @param object promise or immediate reference for target function
- * @param thisp the `this` object for the call
- * @param ...args array of application arguments
- */
-// XXX deprecated, use fcall
-exports.call = deprecate(call, "call", "fcall");
-function call(value, thisp) {
- var args = array_slice(arguments, 2);
- return apply(value, thisp, args);
-}
-
-/**
- * Calls the promised function in a future turn.
- * @param object promise or immediate reference for target function
- * @param ...args array of application arguments
- */
-exports["try"] = fcall; // XXX experimental
-exports.fcall = fcall;
-function fcall(value) {
- var args = array_slice(arguments, 1);
- return fapply(value, args);
-}
-
-/**
- * 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 thisp the `this` object for the call
- * @param ...args array of application arguments
- */
-exports.bind = deprecate(bind, "bind", "fbind"); // XXX deprecated, use fbind
-function bind(value, thisp) {
- var args = array_slice(arguments, 2);
- return function bound() {
- var allArgs = args.concat(array_slice(arguments));
- return apply(value, thisp, allArgs);
- };
-}
-
-/**
- * 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
- */
-exports.fbind = fbind;
-function fbind(value) {
- var args = array_slice(arguments, 1);
- return function fbound() {
- var allArgs = args.concat(array_slice(arguments));
- return fapply(value, allArgs);
- };
-}
-
-/**
- * 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 resolved object
- */
-exports.keys = dispatcher("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
-exports.all = all;
-function all(promises) {
- return when(promises, function (promises) {
- var countDown = promises.length;
- if (countDown === 0) {
- return resolve(promises);
- }
- var deferred = defer();
- array_reduce(promises, function (undefined, promise, index) {
- when(promise, function (value) {
- promises[index] = value;
- if (--countDown === 0) {
- deferred.resolve(promises);
- }
- })
- .fail(deferred.reject);
- }, void 0);
- return deferred.promise;
- });
-}
-
-/**
- * Waits for all promises to be resolved, 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
- */
-exports.allResolved = allResolved;
-function allResolved(promises) {
- return when(promises, function (promises) {
- return when(all(array_map(promises, function (promise) {
- return when(promise, noop, noop);
- })), function () {
- return array_map(promises, resolve);
- });
- });
-}
-
-/**
- * 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
- */
-exports["catch"] = // XXX experimental
-exports.fail = fail;
-function fail(promise, rejected) {
- return when(promise, void 0, rejected);
-}
-
-/**
- * Provides an opportunity to observe the rejection 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.
- */
-exports["finally"] = // XXX experimental
-exports.fin = fin;
-function fin(promise, callback) {
- return when(promise, function (value) {
- return when(callback(), function () {
- return value;
- });
- }, function (exception) {
- return when(callback(), function () {
- return reject(exception);
- });
- });
-}
-
-/**
- * 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
- */
-exports.end = end; // XXX stopgap
-function end(promise) {
- when(promise, void 0, function (error) {
- // forward to a future turn so that ``when``
- // does not catch it and turn it into a rejection.
- nextTick(function () {
- // If possible (that is, if in V8), transform the error stack
- // trace by removing Node and Q cruft, then concatenating with
- // the stack trace of the promise we are ``end``ing. See #57.
- if (Error.captureStackTrace && typeof error === "object" &&
- "stack" in error) {
- var errorStackFrames = getStackFrames(error);
- var promiseStackFrames = getStackFrames(promise);
-
- var combinedStackFrames = errorStackFrames.concat(
- "From previous event:",
- promiseStackFrames
- );
- error.stack = formatStackTrace(error, combinedStackFrames);
- }
-
- throw error;
- });
- });
-}
-
-/**
- * Causes a promise to be rejected if it does not get fulfilled before
- * some milliseconds time out.
- * @param {Any*} promise
- * @param {Number} milliseconds timeout
- * @returns a promise for the resolution of the given promise if it is
- * fulfilled before the timeout, otherwise rejected.
- */
-exports.timeout = timeout;
-function timeout(promise, ms) {
- var deferred = defer();
- var timeoutId = setTimeout(function () {
- deferred.reject(new Error("Timed out after " + ms + " ms"));
- }, ms);
-
- when(promise, function (value) {
- clearTimeout(timeoutId);
- deferred.resolve(value);
- }, deferred.reject);
- return deferred.promise;
-}
-
-/**
- * Returns a promise for the given value (or promised value) after some
- * milliseconds.
- * @param {Any*} promise
- * @param {Number} milliseconds
- * @returns a promise for the resolution of the given promise after some
- * time has elapsed.
- */
-exports.delay = delay;
-function delay(promise, timeout) {
- if (timeout === void 0) {
- timeout = promise;
- promise = void 0;
- }
- var deferred = defer();
- setTimeout(function () {
- deferred.resolve(promise);
- }, timeout);
- return deferred.promise;
-}
-
-/**
- * Passes a continuation to a Node function, which is called with a given
- * `this` value and arguments provided as an array, and returns a promise.
- *
- * var FS = require("fs");
- * Q.napply(FS.readFile, FS, [__filename])
- * .then(function (content) {
- * })
- *
- */
-exports.napply = napply;
-function napply(callback, thisp, args) {
- return nbind(callback, thisp).apply(void 0, args);
-}
-
-/**
- * Passes a continuation to a Node function, which is called with a given
- * `this` value and arguments provided individually, and returns a promise.
- *
- * var FS = require("fs");
- * Q.ncall(FS.readFile, FS, __filename)
- * .then(function (content) {
- * })
- *
- */
-exports.ncall = ncall;
-function ncall(callback, thisp /*, ...args*/) {
- var args = array_slice(arguments, 2);
- return napply(callback, thisp, args);
-}
-
-/**
- * Wraps a NodeJS continuation passing function and returns an equivalent
- * version that returns a promise.
- *
- * Q.nbind(FS.readFile, FS)(__filename)
- * .then(console.log)
- * .end()
- *
- */
-exports.nbind = nbind;
-function nbind(callback /* thisp, ...args*/) {
- if (arguments.length > 1) {
- var thisp = arguments[1];
- var args = array_slice(arguments, 2);
-
- var originalCallback = callback;
- callback = function () {
- var combinedArgs = args.concat(array_slice(arguments));
- return originalCallback.apply(thisp, combinedArgs);
- };
- }
- return function () {
- var deferred = defer();
- var args = array_slice(arguments);
- // add a continuation that resolves the promise
- args.push(deferred.makeNodeResolver());
- // trap exceptions thrown by the callback
- fapply(callback, args)
- .fail(deferred.reject);
- return deferred.promise;
- };
-}
-
-/**
- * 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
- */
-exports.npost = npost;
-function npost(object, name, args) {
- return napply(object[name], object, args);
-}
-
-/**
- * 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
- */
-exports.ninvoke = ninvoke;
-function ninvoke(object, name /*, ...args*/) {
- var args = array_slice(arguments, 2);
- return napply(object[name], object, args);
-}
-
-defend(exports);
-
-});