Merge remote-tracking branch 'connrs/browserify' into develop
Conflicts: js/Gruntfile.js
This commit is contained in:
commit
a5bbe248cc
1
.gitignore
vendored
1
.gitignore
vendored
@ -16,3 +16,4 @@ node_modules/
|
|||||||
nosetests.xml
|
nosetests.xml
|
||||||
*~
|
*~
|
||||||
*.orig
|
*.orig
|
||||||
|
js/test/lib/
|
||||||
|
|||||||
@ -11,6 +11,7 @@ module.exports = function (grunt) {
|
|||||||
" * Licensed under the Apache License, Version 2.0 */\n",
|
" * Licensed under the Apache License, Version 2.0 */\n",
|
||||||
files: {
|
files: {
|
||||||
own: ["Gruntfile.js", "src/**/*.js", "test/**/*-test.js"],
|
own: ["Gruntfile.js", "src/**/*.js", "test/**/*-test.js"],
|
||||||
|
main: "src/mopidy.js",
|
||||||
concat: "../mopidy/http/data/mopidy.js",
|
concat: "../mopidy/http/data/mopidy.js",
|
||||||
minified: "../mopidy/http/data/mopidy.min.js"
|
minified: "../mopidy/http/data/mopidy.min.js"
|
||||||
}
|
}
|
||||||
@ -18,19 +19,35 @@ module.exports = function (grunt) {
|
|||||||
buster: {
|
buster: {
|
||||||
all: {}
|
all: {}
|
||||||
},
|
},
|
||||||
concat: {
|
browserify: {
|
||||||
options: {
|
test_mopidy: {
|
||||||
banner: "<%= meta.banner %>",
|
|
||||||
stripBanners: true
|
|
||||||
},
|
|
||||||
all: {
|
|
||||||
files: {
|
files: {
|
||||||
"<%= meta.files.concat %>": [
|
"test/lib/mopidy.js": "<%= meta.files.main %>"
|
||||||
"lib/bane-*.js",
|
},
|
||||||
"lib/when-define-shim.js",
|
options: {
|
||||||
"lib/when-*.js",
|
postBundleCB: function (err, src, next) {
|
||||||
"src/mopidy.js"
|
next(null, grunt.template.process("<%= meta.banner %>") + src);
|
||||||
]
|
},
|
||||||
|
standalone: "Mopidy"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
test_when: {
|
||||||
|
files: {
|
||||||
|
"test/lib/when.js": "node_modules/when/when.js"
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
standalone: "when"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dist: {
|
||||||
|
files: {
|
||||||
|
"<%= meta.files.concat %>": "<%= meta.files.main %>"
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
postBundleCB: function (err, src, next) {
|
||||||
|
next(null, grunt.template.process("<%= meta.banner %>") + src);
|
||||||
|
},
|
||||||
|
standalone: "Mopidy"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -70,12 +87,13 @@ module.exports = function (grunt) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
grunt.registerTask("test", ["jshint", "buster"]);
|
grunt.registerTask("test_build", ["browserify:test_when", "browserify:test_mopidy"]);
|
||||||
grunt.registerTask("build", ["test", "concat", "uglify"]);
|
grunt.registerTask("test", ["jshint", "test_build", "buster"]);
|
||||||
|
grunt.registerTask("build", ["test", "browserify:dist", "uglify"]);
|
||||||
grunt.registerTask("default", ["build"]);
|
grunt.registerTask("default", ["build"]);
|
||||||
|
|
||||||
grunt.loadNpmTasks("grunt-buster");
|
grunt.loadNpmTasks("grunt-buster");
|
||||||
grunt.loadNpmTasks("grunt-contrib-concat");
|
grunt.loadNpmTasks("grunt-browserify");
|
||||||
grunt.loadNpmTasks("grunt-contrib-jshint");
|
grunt.loadNpmTasks("grunt-contrib-jshint");
|
||||||
grunt.loadNpmTasks("grunt-contrib-uglify");
|
grunt.loadNpmTasks("grunt-contrib-uglify");
|
||||||
grunt.loadNpmTasks("grunt-contrib-watch");
|
grunt.loadNpmTasks("grunt-contrib-watch");
|
||||||
|
|||||||
12
js/buster.js
12
js/buster.js
@ -2,23 +2,13 @@ var config = module.exports;
|
|||||||
|
|
||||||
config.browser_tests = {
|
config.browser_tests = {
|
||||||
environment: "browser",
|
environment: "browser",
|
||||||
libs: [
|
libs: ["test/lib/*.js"],
|
||||||
"lib/bane-*.js",
|
|
||||||
"lib/when-define-shim.js",
|
|
||||||
"lib/when-*.js"
|
|
||||||
],
|
|
||||||
sources: ["src/**/*.js"],
|
|
||||||
testHelpers: ["test/**/*-helper.js"],
|
testHelpers: ["test/**/*-helper.js"],
|
||||||
tests: ["test/**/*-test.js"]
|
tests: ["test/**/*-test.js"]
|
||||||
};
|
};
|
||||||
|
|
||||||
config.node_tests = {
|
config.node_tests = {
|
||||||
environment: "node",
|
environment: "node",
|
||||||
libs: [
|
|
||||||
"lib/bane-*.js",
|
|
||||||
"lib/when-define-shim.js",
|
|
||||||
"lib/when-*.js"
|
|
||||||
],
|
|
||||||
sources: ["src/**/*.js"],
|
sources: ["src/**/*.js"],
|
||||||
testHelpers: ["test/**/*-helper.js"],
|
testHelpers: ["test/**/*-helper.js"],
|
||||||
tests: ["test/**/*-test.js"]
|
tests: ["test/**/*-test.js"]
|
||||||
|
|||||||
@ -1,171 +0,0 @@
|
|||||||
/**
|
|
||||||
* BANE - Browser globals, AMD and Node Events
|
|
||||||
*
|
|
||||||
* https://github.com/busterjs/bane
|
|
||||||
*
|
|
||||||
* @version 1.0.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
((typeof define === "function" && define.amd && function (m) { define("bane", m); }) ||
|
|
||||||
(typeof module === "object" && function (m) { module.exports = m(); }) ||
|
|
||||||
function (m) { this.bane = m(); }
|
|
||||||
)(function () {
|
|
||||||
"use strict";
|
|
||||||
var slice = Array.prototype.slice;
|
|
||||||
|
|
||||||
function handleError(event, error, errbacks) {
|
|
||||||
var i, l = errbacks.length;
|
|
||||||
if (l > 0) {
|
|
||||||
for (i = 0; i < l; ++i) { errbacks[i](event, error); }
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setTimeout(function () {
|
|
||||||
error.message = event + " listener threw error: " + error.message;
|
|
||||||
throw error;
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertFunction(fn) {
|
|
||||||
if (typeof fn !== "function") {
|
|
||||||
throw new TypeError("Listener is not function");
|
|
||||||
}
|
|
||||||
return fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
function supervisors(object) {
|
|
||||||
if (!object.supervisors) { object.supervisors = []; }
|
|
||||||
return object.supervisors;
|
|
||||||
}
|
|
||||||
|
|
||||||
function listeners(object, event) {
|
|
||||||
if (!object.listeners) { object.listeners = {}; }
|
|
||||||
if (event && !object.listeners[event]) { object.listeners[event] = []; }
|
|
||||||
return event ? object.listeners[event] : object.listeners;
|
|
||||||
}
|
|
||||||
|
|
||||||
function errbacks(object) {
|
|
||||||
if (!object.errbacks) { object.errbacks = []; }
|
|
||||||
return object.errbacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @signature var emitter = bane.createEmitter([object]);
|
|
||||||
*
|
|
||||||
* Create a new event emitter. If an object is passed, it will be modified
|
|
||||||
* by adding the event emitter methods (see below).
|
|
||||||
*/
|
|
||||||
function createEventEmitter(object) {
|
|
||||||
object = object || {};
|
|
||||||
|
|
||||||
function notifyListener(event, listener, args) {
|
|
||||||
try {
|
|
||||||
listener.listener.apply(listener.thisp || object, args);
|
|
||||||
} catch (e) {
|
|
||||||
handleError(event, e, errbacks(object));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object.on = function (event, listener, thisp) {
|
|
||||||
if (typeof event === "function") {
|
|
||||||
return supervisors(this).push({
|
|
||||||
listener: event,
|
|
||||||
thisp: listener
|
|
||||||
});
|
|
||||||
}
|
|
||||||
listeners(this, event).push({
|
|
||||||
listener: assertFunction(listener),
|
|
||||||
thisp: thisp
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
object.off = function (event, listener) {
|
|
||||||
var fns, events, i, l;
|
|
||||||
if (!event) {
|
|
||||||
fns = supervisors(this);
|
|
||||||
fns.splice(0, fns.length);
|
|
||||||
|
|
||||||
events = listeners(this);
|
|
||||||
for (i in events) {
|
|
||||||
if (events.hasOwnProperty(i)) {
|
|
||||||
fns = listeners(this, i);
|
|
||||||
fns.splice(0, fns.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fns = errbacks(this);
|
|
||||||
fns.splice(0, fns.length);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeof event === "function") {
|
|
||||||
fns = supervisors(this);
|
|
||||||
listener = event;
|
|
||||||
} else {
|
|
||||||
fns = listeners(this, event);
|
|
||||||
}
|
|
||||||
if (!listener) {
|
|
||||||
fns.splice(0, fns.length);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (i = 0, l = fns.length; i < l; ++i) {
|
|
||||||
if (fns[i].listener === listener) {
|
|
||||||
fns.splice(i, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
object.once = function (event, listener, thisp) {
|
|
||||||
var wrapper = function () {
|
|
||||||
object.off(event, wrapper);
|
|
||||||
listener.apply(this, arguments);
|
|
||||||
};
|
|
||||||
|
|
||||||
object.on(event, wrapper, thisp);
|
|
||||||
};
|
|
||||||
|
|
||||||
object.bind = function (object, events) {
|
|
||||||
var prop, i, l;
|
|
||||||
if (!events) {
|
|
||||||
for (prop in object) {
|
|
||||||
if (typeof object[prop] === "function") {
|
|
||||||
this.on(prop, object[prop], object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (i = 0, l = events.length; i < l; ++i) {
|
|
||||||
if (typeof object[events[i]] === "function") {
|
|
||||||
this.on(events[i], object[events[i]], object);
|
|
||||||
} else {
|
|
||||||
throw new Error("No such method " + events[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return object;
|
|
||||||
};
|
|
||||||
|
|
||||||
object.emit = function (event) {
|
|
||||||
var toNotify = supervisors(this);
|
|
||||||
var args = slice.call(arguments), i, l;
|
|
||||||
|
|
||||||
for (i = 0, l = toNotify.length; i < l; ++i) {
|
|
||||||
notifyListener(event, toNotify[i], args);
|
|
||||||
}
|
|
||||||
|
|
||||||
toNotify = listeners(this, event).slice();
|
|
||||||
args = slice.call(arguments, 1);
|
|
||||||
for (i = 0, l = toNotify.length; i < l; ++i) {
|
|
||||||
notifyListener(event, toNotify[i], args);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
object.errback = function (listener) {
|
|
||||||
if (!this.errbacks) { this.errbacks = []; }
|
|
||||||
this.errbacks.push(assertFunction(listener));
|
|
||||||
};
|
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { createEventEmitter: createEventEmitter };
|
|
||||||
});
|
|
||||||
1
js/lib/websocket/browser.js
Normal file
1
js/lib/websocket/browser.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = { Client: window.WebSocket };
|
||||||
4
js/lib/websocket/package.json
Normal file
4
js/lib/websocket/package.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"browser": "browser.js",
|
||||||
|
"main": "server.js"
|
||||||
|
}
|
||||||
1
js/lib/websocket/server.js
Normal file
1
js/lib/websocket/server.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = require('faye-websocket');
|
||||||
@ -1,922 +0,0 @@
|
|||||||
/** @license MIT License (c) copyright 2011-2013 original author or authors */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A lightweight CommonJS Promises/A and when() implementation
|
|
||||||
* when is part of the cujo.js family of libraries (http://cujojs.com/)
|
|
||||||
*
|
|
||||||
* Licensed under the MIT License at:
|
|
||||||
* http://www.opensource.org/licenses/mit-license.php
|
|
||||||
*
|
|
||||||
* @author Brian Cavalier
|
|
||||||
* @author John Hann
|
|
||||||
* @version 2.4.0
|
|
||||||
*/
|
|
||||||
(function(define, global) { 'use strict';
|
|
||||||
define(function (require) {
|
|
||||||
|
|
||||||
// Public API
|
|
||||||
|
|
||||||
when.promise = promise; // Create a pending promise
|
|
||||||
when.resolve = resolve; // Create a resolved promise
|
|
||||||
when.reject = reject; // Create a rejected promise
|
|
||||||
when.defer = defer; // Create a {promise, resolver} pair
|
|
||||||
|
|
||||||
when.join = join; // Join 2 or more promises
|
|
||||||
|
|
||||||
when.all = all; // Resolve a list of promises
|
|
||||||
when.map = map; // Array.map() for promises
|
|
||||||
when.reduce = reduce; // Array.reduce() for promises
|
|
||||||
when.settle = settle; // Settle a list of promises
|
|
||||||
|
|
||||||
when.any = any; // One-winner race
|
|
||||||
when.some = some; // Multi-winner race
|
|
||||||
|
|
||||||
when.isPromise = isPromiseLike; // DEPRECATED: use isPromiseLike
|
|
||||||
when.isPromiseLike = isPromiseLike; // Is something promise-like, aka thenable
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register an observer for a promise or immediate value.
|
|
||||||
*
|
|
||||||
* @param {*} promiseOrValue
|
|
||||||
* @param {function?} [onFulfilled] callback to be called when promiseOrValue is
|
|
||||||
* successfully fulfilled. If promiseOrValue is an immediate value, callback
|
|
||||||
* will be invoked immediately.
|
|
||||||
* @param {function?} [onRejected] callback to be called when promiseOrValue is
|
|
||||||
* rejected.
|
|
||||||
* @param {function?} [onProgress] callback to be called when progress updates
|
|
||||||
* are issued for promiseOrValue.
|
|
||||||
* @returns {Promise} a new {@link Promise} that will complete with the return
|
|
||||||
* value of callback or errback or the completion value of promiseOrValue if
|
|
||||||
* callback and/or errback is not supplied.
|
|
||||||
*/
|
|
||||||
function when(promiseOrValue, onFulfilled, onRejected, onProgress) {
|
|
||||||
// Get a trusted promise for the input promiseOrValue, and then
|
|
||||||
// register promise handlers
|
|
||||||
return resolve(promiseOrValue).then(onFulfilled, onRejected, onProgress);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trusted Promise constructor. A Promise created from this constructor is
|
|
||||||
* a trusted when.js promise. Any other duck-typed promise is considered
|
|
||||||
* untrusted.
|
|
||||||
* @constructor
|
|
||||||
* @param {function} sendMessage function to deliver messages to the promise's handler
|
|
||||||
* @param {function?} inspect function that reports the promise's state
|
|
||||||
* @name Promise
|
|
||||||
*/
|
|
||||||
function Promise(sendMessage, inspect) {
|
|
||||||
this._message = sendMessage;
|
|
||||||
this.inspect = inspect;
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise.prototype = {
|
|
||||||
/**
|
|
||||||
* Register handlers for this promise.
|
|
||||||
* @param [onFulfilled] {Function} fulfillment handler
|
|
||||||
* @param [onRejected] {Function} rejection handler
|
|
||||||
* @param [onProgress] {Function} progress handler
|
|
||||||
* @return {Promise} new Promise
|
|
||||||
*/
|
|
||||||
then: function(onFulfilled, onRejected, onProgress) {
|
|
||||||
/*jshint unused:false*/
|
|
||||||
var args, sendMessage;
|
|
||||||
|
|
||||||
args = arguments;
|
|
||||||
sendMessage = this._message;
|
|
||||||
|
|
||||||
return _promise(function(resolve, reject, notify) {
|
|
||||||
sendMessage('when', args, resolve, notify);
|
|
||||||
}, this._status && this._status.observed());
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a rejection handler. Shortcut for .then(undefined, onRejected)
|
|
||||||
* @param {function?} onRejected
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
otherwise: function(onRejected) {
|
|
||||||
return this.then(undef, onRejected);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures that onFulfilledOrRejected will be called regardless of whether
|
|
||||||
* this promise is fulfilled or rejected. onFulfilledOrRejected WILL NOT
|
|
||||||
* receive the promises' value or reason. Any returned value will be disregarded.
|
|
||||||
* onFulfilledOrRejected may throw or return a rejected promise to signal
|
|
||||||
* an additional error.
|
|
||||||
* @param {function} onFulfilledOrRejected handler to be called regardless of
|
|
||||||
* fulfillment or rejection
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
ensure: function(onFulfilledOrRejected) {
|
|
||||||
return this.then(injectHandler, injectHandler)['yield'](this);
|
|
||||||
|
|
||||||
function injectHandler() {
|
|
||||||
return resolve(onFulfilledOrRejected());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortcut for .then(function() { return value; })
|
|
||||||
* @param {*} value
|
|
||||||
* @return {Promise} a promise that:
|
|
||||||
* - is fulfilled if value is not a promise, or
|
|
||||||
* - if value is a promise, will fulfill with its value, or reject
|
|
||||||
* with its reason.
|
|
||||||
*/
|
|
||||||
'yield': function(value) {
|
|
||||||
return this.then(function() {
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a side effect when this promise fulfills, without changing the
|
|
||||||
* fulfillment value.
|
|
||||||
* @param {function} onFulfilledSideEffect
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
tap: function(onFulfilledSideEffect) {
|
|
||||||
return this.then(onFulfilledSideEffect)['yield'](this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assumes that this promise will fulfill with an array, and arranges
|
|
||||||
* for the onFulfilled to be called with the array as its argument list
|
|
||||||
* i.e. onFulfilled.apply(undefined, array).
|
|
||||||
* @param {function} onFulfilled function to receive spread arguments
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
spread: function(onFulfilled) {
|
|
||||||
return this.then(function(array) {
|
|
||||||
// array may contain promises, so resolve its contents.
|
|
||||||
return all(array, function(array) {
|
|
||||||
return onFulfilled.apply(undef, array);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortcut for .then(onFulfilledOrRejected, onFulfilledOrRejected)
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
always: function(onFulfilledOrRejected, onProgress) {
|
|
||||||
return this.then(onFulfilledOrRejected, onFulfilledOrRejected, onProgress);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a resolved promise. The returned promise will be
|
|
||||||
* - fulfilled with promiseOrValue if it is a value, or
|
|
||||||
* - if promiseOrValue is a promise
|
|
||||||
* - fulfilled with promiseOrValue's value after it is fulfilled
|
|
||||||
* - rejected with promiseOrValue's reason after it is rejected
|
|
||||||
* @param {*} value
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
function resolve(value) {
|
|
||||||
return promise(function(resolve) {
|
|
||||||
resolve(value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a rejected promise for the supplied promiseOrValue. The returned
|
|
||||||
* promise will be rejected with:
|
|
||||||
* - promiseOrValue, if it is a value, or
|
|
||||||
* - if promiseOrValue is a promise
|
|
||||||
* - promiseOrValue's value after it is fulfilled
|
|
||||||
* - promiseOrValue's reason after it is rejected
|
|
||||||
* @param {*} promiseOrValue the rejected value of the returned {@link Promise}
|
|
||||||
* @return {Promise} rejected {@link Promise}
|
|
||||||
*/
|
|
||||||
function reject(promiseOrValue) {
|
|
||||||
return when(promiseOrValue, rejected);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {promise, resolver} pair, either or both of which
|
|
||||||
* may be given out safely to consumers.
|
|
||||||
* The resolver has resolve, reject, and progress. The promise
|
|
||||||
* has then plus extended promise API.
|
|
||||||
*
|
|
||||||
* @return {{
|
|
||||||
* promise: Promise,
|
|
||||||
* resolve: function:Promise,
|
|
||||||
* reject: function:Promise,
|
|
||||||
* notify: function:Promise
|
|
||||||
* resolver: {
|
|
||||||
* resolve: function:Promise,
|
|
||||||
* reject: function:Promise,
|
|
||||||
* notify: function:Promise
|
|
||||||
* }}}
|
|
||||||
*/
|
|
||||||
function defer() {
|
|
||||||
var deferred, pending, resolved;
|
|
||||||
|
|
||||||
// Optimize object shape
|
|
||||||
deferred = {
|
|
||||||
promise: undef, resolve: undef, reject: undef, notify: undef,
|
|
||||||
resolver: { resolve: undef, reject: undef, notify: undef }
|
|
||||||
};
|
|
||||||
|
|
||||||
deferred.promise = pending = promise(makeDeferred);
|
|
||||||
|
|
||||||
return deferred;
|
|
||||||
|
|
||||||
function makeDeferred(resolvePending, rejectPending, notifyPending) {
|
|
||||||
deferred.resolve = deferred.resolver.resolve = function(value) {
|
|
||||||
if(resolved) {
|
|
||||||
return resolve(value);
|
|
||||||
}
|
|
||||||
resolved = true;
|
|
||||||
resolvePending(value);
|
|
||||||
return pending;
|
|
||||||
};
|
|
||||||
|
|
||||||
deferred.reject = deferred.resolver.reject = function(reason) {
|
|
||||||
if(resolved) {
|
|
||||||
return resolve(rejected(reason));
|
|
||||||
}
|
|
||||||
resolved = true;
|
|
||||||
rejectPending(reason);
|
|
||||||
return pending;
|
|
||||||
};
|
|
||||||
|
|
||||||
deferred.notify = deferred.resolver.notify = function(update) {
|
|
||||||
notifyPending(update);
|
|
||||||
return update;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new promise whose fate is determined by resolver.
|
|
||||||
* @param {function} resolver function(resolve, reject, notify)
|
|
||||||
* @returns {Promise} promise whose fate is determine by resolver
|
|
||||||
*/
|
|
||||||
function promise(resolver) {
|
|
||||||
return _promise(resolver, monitorApi.PromiseStatus && monitorApi.PromiseStatus());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new promise, linked to parent, whose fate is determined
|
|
||||||
* by resolver.
|
|
||||||
* @param {function} resolver function(resolve, reject, notify)
|
|
||||||
* @param {Promise?} status promise from which the new promise is begotten
|
|
||||||
* @returns {Promise} promise whose fate is determine by resolver
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
function _promise(resolver, status) {
|
|
||||||
var self, value, consumers = [];
|
|
||||||
|
|
||||||
self = new Promise(_message, inspect);
|
|
||||||
self._status = status;
|
|
||||||
|
|
||||||
// Call the provider resolver to seal the promise's fate
|
|
||||||
try {
|
|
||||||
resolver(promiseResolve, promiseReject, promiseNotify);
|
|
||||||
} catch(e) {
|
|
||||||
promiseReject(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the promise
|
|
||||||
return self;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private message delivery. Queues and delivers messages to
|
|
||||||
* the promise's ultimate fulfillment value or rejection reason.
|
|
||||||
* @private
|
|
||||||
* @param {String} type
|
|
||||||
* @param {Array} args
|
|
||||||
* @param {Function} resolve
|
|
||||||
* @param {Function} notify
|
|
||||||
*/
|
|
||||||
function _message(type, args, resolve, notify) {
|
|
||||||
consumers ? consumers.push(deliver) : enqueue(function() { deliver(value); });
|
|
||||||
|
|
||||||
function deliver(p) {
|
|
||||||
p._message(type, args, resolve, notify);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a snapshot of the promise's state at the instant inspect()
|
|
||||||
* is called. The returned object is not live and will not update as
|
|
||||||
* the promise's state changes.
|
|
||||||
* @returns {{ state:String, value?:*, reason?:* }} status snapshot
|
|
||||||
* of the promise.
|
|
||||||
*/
|
|
||||||
function inspect() {
|
|
||||||
return value ? value.inspect() : toPendingState();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transition from pre-resolution state to post-resolution state, notifying
|
|
||||||
* all listeners of the ultimate fulfillment or rejection
|
|
||||||
* @param {*|Promise} val resolution value
|
|
||||||
*/
|
|
||||||
function promiseResolve(val) {
|
|
||||||
if(!consumers) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = coerce(val);
|
|
||||||
scheduleConsumers(consumers, value);
|
|
||||||
consumers = undef;
|
|
||||||
|
|
||||||
if(status) {
|
|
||||||
updateStatus(value, status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reject this promise with the supplied reason, which will be used verbatim.
|
|
||||||
* @param {*} reason reason for the rejection
|
|
||||||
*/
|
|
||||||
function promiseReject(reason) {
|
|
||||||
promiseResolve(rejected(reason));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Issue a progress event, notifying all progress listeners
|
|
||||||
* @param {*} update progress event payload to pass to all listeners
|
|
||||||
*/
|
|
||||||
function promiseNotify(update) {
|
|
||||||
if(consumers) {
|
|
||||||
scheduleConsumers(consumers, progressed(update));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a fulfilled, local promise as a proxy for a value
|
|
||||||
* NOTE: must never be exposed
|
|
||||||
* @param {*} value fulfillment value
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
function fulfilled(value) {
|
|
||||||
return near(
|
|
||||||
new NearFulfilledProxy(value),
|
|
||||||
function() { return toFulfilledState(value); }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a rejected, local promise with the supplied reason
|
|
||||||
* NOTE: must never be exposed
|
|
||||||
* @param {*} reason rejection reason
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
function rejected(reason) {
|
|
||||||
return near(
|
|
||||||
new NearRejectedProxy(reason),
|
|
||||||
function() { return toRejectedState(reason); }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a near promise using the provided proxy
|
|
||||||
* NOTE: must never be exposed
|
|
||||||
* @param {object} proxy proxy for the promise's ultimate value or reason
|
|
||||||
* @param {function} inspect function that returns a snapshot of the
|
|
||||||
* returned near promise's state
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
function near(proxy, inspect) {
|
|
||||||
return new Promise(function (type, args, resolve) {
|
|
||||||
try {
|
|
||||||
resolve(proxy[type].apply(proxy, args));
|
|
||||||
} catch(e) {
|
|
||||||
resolve(rejected(e));
|
|
||||||
}
|
|
||||||
}, inspect);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a progress promise with the supplied update.
|
|
||||||
* @private
|
|
||||||
* @param {*} update
|
|
||||||
* @return {Promise} progress promise
|
|
||||||
*/
|
|
||||||
function progressed(update) {
|
|
||||||
return new Promise(function (type, args, _, notify) {
|
|
||||||
var onProgress = args[2];
|
|
||||||
try {
|
|
||||||
notify(typeof onProgress === 'function' ? onProgress(update) : update);
|
|
||||||
} catch(e) {
|
|
||||||
notify(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Coerces x to a trusted Promise
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {*} x thing to coerce
|
|
||||||
* @returns {*} Guaranteed to return a trusted Promise. If x
|
|
||||||
* is trusted, returns x, otherwise, returns a new, trusted, already-resolved
|
|
||||||
* Promise whose resolution value is:
|
|
||||||
* * the resolution value of x if it's a foreign promise, or
|
|
||||||
* * x if it's a value
|
|
||||||
*/
|
|
||||||
function coerce(x) {
|
|
||||||
if (x instanceof Promise) {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(x === Object(x) && 'then' in x)) {
|
|
||||||
return fulfilled(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
return promise(function(resolve, reject, notify) {
|
|
||||||
enqueue(function() {
|
|
||||||
try {
|
|
||||||
// We must check and assimilate in the same tick, but not the
|
|
||||||
// current tick, careful only to access promiseOrValue.then once.
|
|
||||||
var untrustedThen = x.then;
|
|
||||||
|
|
||||||
if(typeof untrustedThen === 'function') {
|
|
||||||
fcall(untrustedThen, x, resolve, reject, notify);
|
|
||||||
} else {
|
|
||||||
// It's a value, create a fulfilled wrapper
|
|
||||||
resolve(fulfilled(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch(e) {
|
|
||||||
// Something went wrong, reject
|
|
||||||
reject(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Proxy for a near, fulfilled value
|
|
||||||
* @param {*} value
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function NearFulfilledProxy(value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
NearFulfilledProxy.prototype.when = function(onResult) {
|
|
||||||
return typeof onResult === 'function' ? onResult(this.value) : this.value;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Proxy for a near rejection
|
|
||||||
* @param {*} reason
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function NearRejectedProxy(reason) {
|
|
||||||
this.reason = reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
NearRejectedProxy.prototype.when = function(_, onError) {
|
|
||||||
if(typeof onError === 'function') {
|
|
||||||
return onError(this.reason);
|
|
||||||
} else {
|
|
||||||
throw this.reason;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedule a task that will process a list of handlers
|
|
||||||
* in the next queue drain run.
|
|
||||||
* @private
|
|
||||||
* @param {Array} handlers queue of handlers to execute
|
|
||||||
* @param {*} value passed as the only arg to each handler
|
|
||||||
*/
|
|
||||||
function scheduleConsumers(handlers, value) {
|
|
||||||
enqueue(function() {
|
|
||||||
var handler, i = 0;
|
|
||||||
while (handler = handlers[i++]) {
|
|
||||||
handler(value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateStatus(value, status) {
|
|
||||||
value.then(statusFulfilled, statusRejected);
|
|
||||||
|
|
||||||
function statusFulfilled() { status.fulfilled(); }
|
|
||||||
function statusRejected(r) { status.rejected(r); }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if x is promise-like, i.e. a thenable object
|
|
||||||
* NOTE: Will return true for *any thenable object*, and isn't truly
|
|
||||||
* safe, since it may attempt to access the `then` property of x (i.e.
|
|
||||||
* clever/malicious getters may do weird things)
|
|
||||||
* @param {*} x anything
|
|
||||||
* @returns {boolean} true if x is promise-like
|
|
||||||
*/
|
|
||||||
function isPromiseLike(x) {
|
|
||||||
return x && typeof x.then === 'function';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initiates a competitive race, returning a promise that will resolve when
|
|
||||||
* howMany of the supplied promisesOrValues have resolved, or will reject when
|
|
||||||
* it becomes impossible for howMany to resolve, for example, when
|
|
||||||
* (promisesOrValues.length - howMany) + 1 input promises reject.
|
|
||||||
*
|
|
||||||
* @param {Array} promisesOrValues array of anything, may contain a mix
|
|
||||||
* of promises and values
|
|
||||||
* @param howMany {number} number of promisesOrValues to resolve
|
|
||||||
* @param {function?} [onFulfilled] DEPRECATED, use returnedPromise.then()
|
|
||||||
* @param {function?} [onRejected] DEPRECATED, use returnedPromise.then()
|
|
||||||
* @param {function?} [onProgress] DEPRECATED, use returnedPromise.then()
|
|
||||||
* @returns {Promise} promise that will resolve to an array of howMany values that
|
|
||||||
* resolved first, or will reject with an array of
|
|
||||||
* (promisesOrValues.length - howMany) + 1 rejection reasons.
|
|
||||||
*/
|
|
||||||
function some(promisesOrValues, howMany, onFulfilled, onRejected, onProgress) {
|
|
||||||
|
|
||||||
return when(promisesOrValues, function(promisesOrValues) {
|
|
||||||
|
|
||||||
return promise(resolveSome).then(onFulfilled, onRejected, onProgress);
|
|
||||||
|
|
||||||
function resolveSome(resolve, reject, notify) {
|
|
||||||
var toResolve, toReject, values, reasons, fulfillOne, rejectOne, len, i;
|
|
||||||
|
|
||||||
len = promisesOrValues.length >>> 0;
|
|
||||||
|
|
||||||
toResolve = Math.max(0, Math.min(howMany, len));
|
|
||||||
values = [];
|
|
||||||
|
|
||||||
toReject = (len - toResolve) + 1;
|
|
||||||
reasons = [];
|
|
||||||
|
|
||||||
// No items in the input, resolve immediately
|
|
||||||
if (!toResolve) {
|
|
||||||
resolve(values);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
rejectOne = function(reason) {
|
|
||||||
reasons.push(reason);
|
|
||||||
if(!--toReject) {
|
|
||||||
fulfillOne = rejectOne = identity;
|
|
||||||
reject(reasons);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fulfillOne = function(val) {
|
|
||||||
// This orders the values based on promise resolution order
|
|
||||||
values.push(val);
|
|
||||||
if (!--toResolve) {
|
|
||||||
fulfillOne = rejectOne = identity;
|
|
||||||
resolve(values);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for(i = 0; i < len; ++i) {
|
|
||||||
if(i in promisesOrValues) {
|
|
||||||
when(promisesOrValues[i], fulfiller, rejecter, notify);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function rejecter(reason) {
|
|
||||||
rejectOne(reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
function fulfiller(val) {
|
|
||||||
fulfillOne(val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initiates a competitive race, returning a promise that will resolve when
|
|
||||||
* any one of the supplied promisesOrValues has resolved or will reject when
|
|
||||||
* *all* promisesOrValues have rejected.
|
|
||||||
*
|
|
||||||
* @param {Array|Promise} promisesOrValues array of anything, may contain a mix
|
|
||||||
* of {@link Promise}s and values
|
|
||||||
* @param {function?} [onFulfilled] DEPRECATED, use returnedPromise.then()
|
|
||||||
* @param {function?} [onRejected] DEPRECATED, use returnedPromise.then()
|
|
||||||
* @param {function?} [onProgress] DEPRECATED, use returnedPromise.then()
|
|
||||||
* @returns {Promise} promise that will resolve to the value that resolved first, or
|
|
||||||
* will reject with an array of all rejected inputs.
|
|
||||||
*/
|
|
||||||
function any(promisesOrValues, onFulfilled, onRejected, onProgress) {
|
|
||||||
|
|
||||||
function unwrapSingleResult(val) {
|
|
||||||
return onFulfilled ? onFulfilled(val[0]) : val[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return some(promisesOrValues, 1, unwrapSingleResult, onRejected, onProgress);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a promise that will resolve only once all the supplied promisesOrValues
|
|
||||||
* have resolved. The resolution value of the returned promise will be an array
|
|
||||||
* containing the resolution values of each of the promisesOrValues.
|
|
||||||
* @memberOf when
|
|
||||||
*
|
|
||||||
* @param {Array|Promise} promisesOrValues array of anything, may contain a mix
|
|
||||||
* of {@link Promise}s and values
|
|
||||||
* @param {function?} [onFulfilled] DEPRECATED, use returnedPromise.then()
|
|
||||||
* @param {function?} [onRejected] DEPRECATED, use returnedPromise.then()
|
|
||||||
* @param {function?} [onProgress] DEPRECATED, use returnedPromise.then()
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
function all(promisesOrValues, onFulfilled, onRejected, onProgress) {
|
|
||||||
return _map(promisesOrValues, identity).then(onFulfilled, onRejected, onProgress);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Joins multiple promises into a single returned promise.
|
|
||||||
* @return {Promise} a promise that will fulfill when *all* the input promises
|
|
||||||
* have fulfilled, or will reject when *any one* of the input promises rejects.
|
|
||||||
*/
|
|
||||||
function join(/* ...promises */) {
|
|
||||||
return _map(arguments, identity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Settles all input promises such that they are guaranteed not to
|
|
||||||
* be pending once the returned promise fulfills. The returned promise
|
|
||||||
* will always fulfill, except in the case where `array` is a promise
|
|
||||||
* that rejects.
|
|
||||||
* @param {Array|Promise} array or promise for array of promises to settle
|
|
||||||
* @returns {Promise} promise that always fulfills with an array of
|
|
||||||
* outcome snapshots for each input promise.
|
|
||||||
*/
|
|
||||||
function settle(array) {
|
|
||||||
return _map(array, toFulfilledState, toRejectedState);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Promise-aware array map function, similar to `Array.prototype.map()`,
|
|
||||||
* but input array may contain promises or values.
|
|
||||||
* @param {Array|Promise} array array of anything, may contain promises and values
|
|
||||||
* @param {function} mapFunc map function which may return a promise or value
|
|
||||||
* @returns {Promise} promise that will fulfill with an array of mapped values
|
|
||||||
* or reject if any input promise rejects.
|
|
||||||
*/
|
|
||||||
function map(array, mapFunc) {
|
|
||||||
return _map(array, mapFunc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal map that allows a fallback to handle rejections
|
|
||||||
* @param {Array|Promise} array array of anything, may contain promises and values
|
|
||||||
* @param {function} mapFunc map function which may return a promise or value
|
|
||||||
* @param {function?} fallback function to handle rejected promises
|
|
||||||
* @returns {Promise} promise that will fulfill with an array of mapped values
|
|
||||||
* or reject if any input promise rejects.
|
|
||||||
*/
|
|
||||||
function _map(array, mapFunc, fallback) {
|
|
||||||
return when(array, function(array) {
|
|
||||||
|
|
||||||
return _promise(resolveMap);
|
|
||||||
|
|
||||||
function resolveMap(resolve, reject, notify) {
|
|
||||||
var results, len, toResolve, i;
|
|
||||||
|
|
||||||
// Since we know the resulting length, we can preallocate the results
|
|
||||||
// array to avoid array expansions.
|
|
||||||
toResolve = len = array.length >>> 0;
|
|
||||||
results = [];
|
|
||||||
|
|
||||||
if(!toResolve) {
|
|
||||||
resolve(results);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since mapFunc may be async, get all invocations of it into flight
|
|
||||||
for(i = 0; i < len; i++) {
|
|
||||||
if(i in array) {
|
|
||||||
resolveOne(array[i], i);
|
|
||||||
} else {
|
|
||||||
--toResolve;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveOne(item, i) {
|
|
||||||
when(item, mapFunc, fallback).then(function(mapped) {
|
|
||||||
results[i] = mapped;
|
|
||||||
notify(mapped);
|
|
||||||
|
|
||||||
if(!--toResolve) {
|
|
||||||
resolve(results);
|
|
||||||
}
|
|
||||||
}, reject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Traditional reduce function, similar to `Array.prototype.reduce()`, but
|
|
||||||
* input may contain promises and/or values, and reduceFunc
|
|
||||||
* may return either a value or a promise, *and* initialValue may
|
|
||||||
* be a promise for the starting value.
|
|
||||||
*
|
|
||||||
* @param {Array|Promise} promise array or promise for an array of anything,
|
|
||||||
* may contain a mix of promises and values.
|
|
||||||
* @param {function} reduceFunc reduce function reduce(currentValue, nextValue, index, total),
|
|
||||||
* where total is the total number of items being reduced, and will be the same
|
|
||||||
* in each call to reduceFunc.
|
|
||||||
* @returns {Promise} that will resolve to the final reduced value
|
|
||||||
*/
|
|
||||||
function reduce(promise, reduceFunc /*, initialValue */) {
|
|
||||||
var args = fcall(slice, arguments, 1);
|
|
||||||
|
|
||||||
return when(promise, function(array) {
|
|
||||||
var total;
|
|
||||||
|
|
||||||
total = array.length;
|
|
||||||
|
|
||||||
// Wrap the supplied reduceFunc with one that handles promises and then
|
|
||||||
// delegates to the supplied.
|
|
||||||
args[0] = function (current, val, i) {
|
|
||||||
return when(current, function (c) {
|
|
||||||
return when(val, function (value) {
|
|
||||||
return reduceFunc(c, value, i, total);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return reduceArray.apply(array, args);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Snapshot states
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a fulfilled state snapshot
|
|
||||||
* @private
|
|
||||||
* @param {*} x any value
|
|
||||||
* @returns {{state:'fulfilled',value:*}}
|
|
||||||
*/
|
|
||||||
function toFulfilledState(x) {
|
|
||||||
return { state: 'fulfilled', value: x };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a rejected state snapshot
|
|
||||||
* @private
|
|
||||||
* @param {*} x any reason
|
|
||||||
* @returns {{state:'rejected',reason:*}}
|
|
||||||
*/
|
|
||||||
function toRejectedState(x) {
|
|
||||||
return { state: 'rejected', reason: x };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a pending state snapshot
|
|
||||||
* @private
|
|
||||||
* @returns {{state:'pending'}}
|
|
||||||
*/
|
|
||||||
function toPendingState() {
|
|
||||||
return { state: 'pending' };
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Internals, utilities, etc.
|
|
||||||
//
|
|
||||||
|
|
||||||
var reduceArray, slice, fcall, nextTick, handlerQueue,
|
|
||||||
setTimeout, funcProto, call, arrayProto, monitorApi,
|
|
||||||
cjsRequire, undef;
|
|
||||||
|
|
||||||
cjsRequire = require;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Shared handler queue processing
|
|
||||||
//
|
|
||||||
// Credit to Twisol (https://github.com/Twisol) for suggesting
|
|
||||||
// this type of extensible queue + trampoline approach for
|
|
||||||
// next-tick conflation.
|
|
||||||
|
|
||||||
handlerQueue = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enqueue a task. If the queue is not currently scheduled to be
|
|
||||||
* drained, schedule it.
|
|
||||||
* @param {function} task
|
|
||||||
*/
|
|
||||||
function enqueue(task) {
|
|
||||||
if(handlerQueue.push(task) === 1) {
|
|
||||||
nextTick(drainQueue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Drain the handler queue entirely, being careful to allow the
|
|
||||||
* queue to be extended while it is being processed, and to continue
|
|
||||||
* processing until it is truly empty.
|
|
||||||
*/
|
|
||||||
function drainQueue() {
|
|
||||||
var task, i = 0;
|
|
||||||
|
|
||||||
while(task = handlerQueue[i++]) {
|
|
||||||
task();
|
|
||||||
}
|
|
||||||
|
|
||||||
handlerQueue = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// capture setTimeout to avoid being caught by fake timers
|
|
||||||
// used in time based tests
|
|
||||||
setTimeout = global.setTimeout;
|
|
||||||
|
|
||||||
// Allow attaching the monitor to when() if env has no console
|
|
||||||
monitorApi = typeof console != 'undefined' ? console : when;
|
|
||||||
|
|
||||||
// Prefer setImmediate or MessageChannel, cascade to node,
|
|
||||||
// vertx and finally setTimeout
|
|
||||||
/*global setImmediate,MessageChannel,process*/
|
|
||||||
if (typeof setImmediate === 'function') {
|
|
||||||
nextTick = setImmediate.bind(global);
|
|
||||||
} else if(typeof MessageChannel !== 'undefined') {
|
|
||||||
var channel = new MessageChannel();
|
|
||||||
channel.port1.onmessage = drainQueue;
|
|
||||||
nextTick = function() { channel.port2.postMessage(0); };
|
|
||||||
} else if (typeof process === 'object' && process.nextTick) {
|
|
||||||
nextTick = process.nextTick;
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
// vert.x 1.x || 2.x
|
|
||||||
nextTick = cjsRequire('vertx').runOnLoop || cjsRequire('vertx').runOnContext;
|
|
||||||
} catch(ignore) {
|
|
||||||
nextTick = function(t) { setTimeout(t, 0); };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Capture/polyfill function and array utils
|
|
||||||
//
|
|
||||||
|
|
||||||
// Safe function calls
|
|
||||||
funcProto = Function.prototype;
|
|
||||||
call = funcProto.call;
|
|
||||||
fcall = funcProto.bind
|
|
||||||
? call.bind(call)
|
|
||||||
: function(f, context) {
|
|
||||||
return f.apply(context, slice.call(arguments, 2));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Safe array ops
|
|
||||||
arrayProto = [];
|
|
||||||
slice = arrayProto.slice;
|
|
||||||
|
|
||||||
// ES5 reduce implementation if native not available
|
|
||||||
// See: http://es5.github.com/#x15.4.4.21 as there are many
|
|
||||||
// specifics and edge cases. ES5 dictates that reduce.length === 1
|
|
||||||
// This implementation deviates from ES5 spec in the following ways:
|
|
||||||
// 1. It does not check if reduceFunc is a Callable
|
|
||||||
reduceArray = arrayProto.reduce ||
|
|
||||||
function(reduceFunc /*, initialValue */) {
|
|
||||||
/*jshint maxcomplexity: 7*/
|
|
||||||
var arr, args, reduced, len, i;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
arr = Object(this);
|
|
||||||
len = arr.length >>> 0;
|
|
||||||
args = arguments;
|
|
||||||
|
|
||||||
// If no initialValue, use first item of array (we know length !== 0 here)
|
|
||||||
// and adjust i to start at second item
|
|
||||||
if(args.length <= 1) {
|
|
||||||
// Skip to the first real element in the array
|
|
||||||
for(;;) {
|
|
||||||
if(i in arr) {
|
|
||||||
reduced = arr[i++];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we reached the end of the array without finding any real
|
|
||||||
// elements, it's a TypeError
|
|
||||||
if(++i >= len) {
|
|
||||||
throw new TypeError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If initialValue provided, use it
|
|
||||||
reduced = args[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do the actual reduce
|
|
||||||
for(;i < len; ++i) {
|
|
||||||
if(i in arr) {
|
|
||||||
reduced = reduceFunc(reduced, arr[i], i, arr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return reduced;
|
|
||||||
};
|
|
||||||
|
|
||||||
function identity(x) {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
return when;
|
|
||||||
});
|
|
||||||
})(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); }, this);
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mopidy",
|
"name": "mopidy",
|
||||||
"version": "0.1.1",
|
"version": "0.2.0",
|
||||||
"description": "Client lib for controlling a Mopidy music server over a WebSocket",
|
"description": "Client lib for controlling a Mopidy music server over a WebSocket",
|
||||||
"homepage": "http://www.mopidy.com/",
|
"homepage": "http://www.mopidy.com/",
|
||||||
"author": {
|
"author": {
|
||||||
@ -16,13 +16,13 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bane": "~1.0.0",
|
"bane": "~1.0.0",
|
||||||
"faye-websocket": "~0.7.0",
|
"faye-websocket": "~0.7.0",
|
||||||
"when": "~2.4.0"
|
"when": "~2.7.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"buster": "~0.6.13",
|
"buster": "~0.6.13",
|
||||||
"grunt": "~0.4.1",
|
"grunt": "~0.4.1",
|
||||||
"grunt-buster": "~0.2.1",
|
"grunt-buster": "~0.2.1",
|
||||||
"grunt-contrib-concat": "~0.3.0",
|
"grunt-browserify": "~1.3.0",
|
||||||
"grunt-contrib-jshint": "~0.6.4",
|
"grunt-contrib-jshint": "~0.6.4",
|
||||||
"grunt-contrib-uglify": "~0.2.4",
|
"grunt-contrib-uglify": "~0.2.4",
|
||||||
"grunt-contrib-watch": "~0.5.3",
|
"grunt-contrib-watch": "~0.5.3",
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
/*global exports:false, require:false*/
|
/*global module:true, require:false*/
|
||||||
|
|
||||||
if (typeof module === "object" && typeof require === "function") {
|
var bane = require("bane");
|
||||||
var bane = require("bane");
|
var websocket = require("../lib/websocket/");
|
||||||
var websocket = require("faye-websocket");
|
var when = require("when");
|
||||||
var when = require("when");
|
|
||||||
}
|
|
||||||
|
|
||||||
function Mopidy(settings) {
|
function Mopidy(settings) {
|
||||||
if (!(this instanceof Mopidy)) {
|
if (!(this instanceof Mopidy)) {
|
||||||
@ -26,11 +24,7 @@ function Mopidy(settings) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof module === "object" && typeof require === "function") {
|
Mopidy.WebSocket = websocket.Client;
|
||||||
Mopidy.WebSocket = websocket.Client;
|
|
||||||
} else {
|
|
||||||
Mopidy.WebSocket = window.WebSocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mopidy.prototype._configure = function (settings) {
|
Mopidy.prototype._configure = function (settings) {
|
||||||
var currentHost = (typeof document !== "undefined" &&
|
var currentHost = (typeof document !== "undefined" &&
|
||||||
@ -295,6 +289,4 @@ Mopidy.prototype._snakeToCamel = function (name) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof exports === "object") {
|
module.exports = Mopidy;
|
||||||
exports.Mopidy = Mopidy;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
if (typeof module === "object" && typeof require === "function") {
|
if (typeof module === "object" && typeof require === "function") {
|
||||||
var buster = require("buster");
|
var buster = require("buster");
|
||||||
var Mopidy = require("../src/mopidy").Mopidy;
|
var Mopidy = require("../src/mopidy");
|
||||||
var when = require("when");
|
var when = require("when");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
/*! Mopidy.js - built 2013-09-17
|
/*! Mopidy.js - built 2013-12-15
|
||||||
* http://www.mopidy.com/
|
* http://www.mopidy.com/
|
||||||
* Copyright (c) 2013 Stein Magnus Jodal and contributors
|
* Copyright (c) 2013 Stein Magnus Jodal and contributors
|
||||||
* Licensed under the Apache License, Version 2.0 */
|
* Licensed under the Apache License, Version 2.0 */
|
||||||
|
!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.Mopidy=e():"undefined"!=typeof global?global.Mopidy=e():"undefined"!=typeof self&&(self.Mopidy=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||||
|
module.exports = { Client: window.WebSocket };
|
||||||
|
|
||||||
|
},{}],2:[function(require,module,exports){
|
||||||
((typeof define === "function" && define.amd && function (m) { define("bane", m); }) ||
|
((typeof define === "function" && define.amd && function (m) { define("bane", m); }) ||
|
||||||
(typeof module === "object" && function (m) { module.exports = m(); }) ||
|
(typeof module === "object" && function (m) { module.exports = m(); }) ||
|
||||||
function (m) { this.bane = m(); }
|
function (m) { this.bane = m(); }
|
||||||
@ -166,18 +170,63 @@
|
|||||||
return { createEventEmitter: createEventEmitter };
|
return { createEventEmitter: createEventEmitter };
|
||||||
});
|
});
|
||||||
|
|
||||||
if (typeof window !== "undefined") {
|
},{}],3:[function(require,module,exports){
|
||||||
window.define = function (factory) {
|
// shim for using process in browser
|
||||||
try {
|
|
||||||
delete window.define;
|
var process = module.exports = {};
|
||||||
} catch (e) {
|
|
||||||
window.define = void 0; // IE
|
process.nextTick = (function () {
|
||||||
}
|
var canSetImmediate = typeof window !== 'undefined'
|
||||||
window.when = factory();
|
&& window.setImmediate;
|
||||||
|
var canPost = typeof window !== 'undefined'
|
||||||
|
&& window.postMessage && window.addEventListener
|
||||||
|
;
|
||||||
|
|
||||||
|
if (canSetImmediate) {
|
||||||
|
return function (f) { return window.setImmediate(f) };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canPost) {
|
||||||
|
var queue = [];
|
||||||
|
window.addEventListener('message', function (ev) {
|
||||||
|
if (ev.source === window && ev.data === 'process-tick') {
|
||||||
|
ev.stopPropagation();
|
||||||
|
if (queue.length > 0) {
|
||||||
|
var fn = queue.shift();
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
return function nextTick(fn) {
|
||||||
|
queue.push(fn);
|
||||||
|
window.postMessage('process-tick', '*');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return function nextTick(fn) {
|
||||||
|
setTimeout(fn, 0);
|
||||||
};
|
};
|
||||||
window.define.amd = {};
|
})();
|
||||||
|
|
||||||
|
process.title = 'browser';
|
||||||
|
process.browser = true;
|
||||||
|
process.env = {};
|
||||||
|
process.argv = [];
|
||||||
|
|
||||||
|
process.binding = function (name) {
|
||||||
|
throw new Error('process.binding is not supported');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(shtylman)
|
||||||
|
process.cwd = function () { return '/' };
|
||||||
|
process.chdir = function (dir) {
|
||||||
|
throw new Error('process.chdir is not supported');
|
||||||
|
};
|
||||||
|
|
||||||
|
},{}],4:[function(require,module,exports){
|
||||||
|
var process=require("__browserify_process");/** @license MIT License (c) copyright 2011-2013 original author or authors */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A lightweight CommonJS Promises/A and when() implementation
|
* A lightweight CommonJS Promises/A and when() implementation
|
||||||
* when is part of the cujo.js family of libraries (http://cujojs.com/)
|
* when is part of the cujo.js family of libraries (http://cujojs.com/)
|
||||||
@ -187,9 +236,9 @@ if (typeof window !== "undefined") {
|
|||||||
*
|
*
|
||||||
* @author Brian Cavalier
|
* @author Brian Cavalier
|
||||||
* @author John Hann
|
* @author John Hann
|
||||||
* @version 2.4.0
|
* @version 2.7.0
|
||||||
*/
|
*/
|
||||||
(function(define, global) { 'use strict';
|
(function(define) { 'use strict';
|
||||||
define(function (require) {
|
define(function (require) {
|
||||||
|
|
||||||
// Public API
|
// Public API
|
||||||
@ -230,7 +279,11 @@ define(function (require) {
|
|||||||
function when(promiseOrValue, onFulfilled, onRejected, onProgress) {
|
function when(promiseOrValue, onFulfilled, onRejected, onProgress) {
|
||||||
// Get a trusted promise for the input promiseOrValue, and then
|
// Get a trusted promise for the input promiseOrValue, and then
|
||||||
// register promise handlers
|
// register promise handlers
|
||||||
return resolve(promiseOrValue).then(onFulfilled, onRejected, onProgress);
|
return cast(promiseOrValue).then(onFulfilled, onRejected, onProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cast(x) {
|
||||||
|
return x instanceof Promise ? x : resolve(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -247,102 +300,118 @@ define(function (require) {
|
|||||||
this.inspect = inspect;
|
this.inspect = inspect;
|
||||||
}
|
}
|
||||||
|
|
||||||
Promise.prototype = {
|
var promisePrototype = Promise.prototype;
|
||||||
/**
|
|
||||||
* Register handlers for this promise.
|
|
||||||
* @param [onFulfilled] {Function} fulfillment handler
|
|
||||||
* @param [onRejected] {Function} rejection handler
|
|
||||||
* @param [onProgress] {Function} progress handler
|
|
||||||
* @return {Promise} new Promise
|
|
||||||
*/
|
|
||||||
then: function(onFulfilled, onRejected, onProgress) {
|
|
||||||
/*jshint unused:false*/
|
|
||||||
var args, sendMessage;
|
|
||||||
|
|
||||||
args = arguments;
|
/**
|
||||||
sendMessage = this._message;
|
* Register handlers for this promise.
|
||||||
|
* @param [onFulfilled] {Function} fulfillment handler
|
||||||
|
* @param [onRejected] {Function} rejection handler
|
||||||
|
* @param [onProgress] {Function} progress handler
|
||||||
|
* @return {Promise} new Promise
|
||||||
|
*/
|
||||||
|
promisePrototype.then = function(onFulfilled, onRejected, onProgress) {
|
||||||
|
/*jshint unused:false*/
|
||||||
|
var args, sendMessage;
|
||||||
|
|
||||||
return _promise(function(resolve, reject, notify) {
|
args = arguments;
|
||||||
sendMessage('when', args, resolve, notify);
|
sendMessage = this._message;
|
||||||
}, this._status && this._status.observed());
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
return _promise(function(resolve, reject, notify) {
|
||||||
* Register a rejection handler. Shortcut for .then(undefined, onRejected)
|
sendMessage('when', args, resolve, notify);
|
||||||
* @param {function?} onRejected
|
}, this._status && this._status.observed());
|
||||||
* @return {Promise}
|
};
|
||||||
*/
|
|
||||||
otherwise: function(onRejected) {
|
|
||||||
return this.then(undef, onRejected);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that onFulfilledOrRejected will be called regardless of whether
|
* Register a rejection handler. Shortcut for .then(undefined, onRejected)
|
||||||
* this promise is fulfilled or rejected. onFulfilledOrRejected WILL NOT
|
* @param {function?} onRejected
|
||||||
* receive the promises' value or reason. Any returned value will be disregarded.
|
* @return {Promise}
|
||||||
* onFulfilledOrRejected may throw or return a rejected promise to signal
|
*/
|
||||||
* an additional error.
|
promisePrototype['catch'] = promisePrototype.otherwise = function(onRejected) {
|
||||||
* @param {function} onFulfilledOrRejected handler to be called regardless of
|
return this.then(undef, onRejected);
|
||||||
* fulfillment or rejection
|
};
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
ensure: function(onFulfilledOrRejected) {
|
|
||||||
return this.then(injectHandler, injectHandler)['yield'](this);
|
|
||||||
|
|
||||||
function injectHandler() {
|
/**
|
||||||
return resolve(onFulfilledOrRejected());
|
* Ensures that onFulfilledOrRejected will be called regardless of whether
|
||||||
}
|
* this promise is fulfilled or rejected. onFulfilledOrRejected WILL NOT
|
||||||
},
|
* receive the promises' value or reason. Any returned value will be disregarded.
|
||||||
|
* onFulfilledOrRejected may throw or return a rejected promise to signal
|
||||||
|
* an additional error.
|
||||||
|
* @param {function} onFulfilledOrRejected handler to be called regardless of
|
||||||
|
* fulfillment or rejection
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
promisePrototype['finally'] = promisePrototype.ensure = function(onFulfilledOrRejected) {
|
||||||
|
return typeof onFulfilledOrRejected === 'function'
|
||||||
|
? this.then(injectHandler, injectHandler)['yield'](this)
|
||||||
|
: this;
|
||||||
|
|
||||||
/**
|
function injectHandler() {
|
||||||
* Shortcut for .then(function() { return value; })
|
return resolve(onFulfilledOrRejected());
|
||||||
* @param {*} value
|
|
||||||
* @return {Promise} a promise that:
|
|
||||||
* - is fulfilled if value is not a promise, or
|
|
||||||
* - if value is a promise, will fulfill with its value, or reject
|
|
||||||
* with its reason.
|
|
||||||
*/
|
|
||||||
'yield': function(value) {
|
|
||||||
return this.then(function() {
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a side effect when this promise fulfills, without changing the
|
|
||||||
* fulfillment value.
|
|
||||||
* @param {function} onFulfilledSideEffect
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
tap: function(onFulfilledSideEffect) {
|
|
||||||
return this.then(onFulfilledSideEffect)['yield'](this);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Assumes that this promise will fulfill with an array, and arranges
|
|
||||||
* for the onFulfilled to be called with the array as its argument list
|
|
||||||
* i.e. onFulfilled.apply(undefined, array).
|
|
||||||
* @param {function} onFulfilled function to receive spread arguments
|
|
||||||
* @return {Promise}
|
|
||||||
*/
|
|
||||||
spread: function(onFulfilled) {
|
|
||||||
return this.then(function(array) {
|
|
||||||
// array may contain promises, so resolve its contents.
|
|
||||||
return all(array, function(array) {
|
|
||||||
return onFulfilled.apply(undef, array);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortcut for .then(onFulfilledOrRejected, onFulfilledOrRejected)
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
always: function(onFulfilledOrRejected, onProgress) {
|
|
||||||
return this.then(onFulfilledOrRejected, onFulfilledOrRejected, onProgress);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminate a promise chain by handling the ultimate fulfillment value or
|
||||||
|
* rejection reason, and assuming responsibility for all errors. if an
|
||||||
|
* error propagates out of handleResult or handleFatalError, it will be
|
||||||
|
* rethrown to the host, resulting in a loud stack track on most platforms
|
||||||
|
* and a crash on some.
|
||||||
|
* @param {function?} handleResult
|
||||||
|
* @param {function?} handleError
|
||||||
|
* @returns {undefined}
|
||||||
|
*/
|
||||||
|
promisePrototype.done = function(handleResult, handleError) {
|
||||||
|
this.then(handleResult, handleError).otherwise(crash);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut for .then(function() { return value; })
|
||||||
|
* @param {*} value
|
||||||
|
* @return {Promise} a promise that:
|
||||||
|
* - is fulfilled if value is not a promise, or
|
||||||
|
* - if value is a promise, will fulfill with its value, or reject
|
||||||
|
* with its reason.
|
||||||
|
*/
|
||||||
|
promisePrototype['yield'] = function(value) {
|
||||||
|
return this.then(function() {
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs a side effect when this promise fulfills, without changing the
|
||||||
|
* fulfillment value.
|
||||||
|
* @param {function} onFulfilledSideEffect
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
promisePrototype.tap = function(onFulfilledSideEffect) {
|
||||||
|
return this.then(onFulfilledSideEffect)['yield'](this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assumes that this promise will fulfill with an array, and arranges
|
||||||
|
* for the onFulfilled to be called with the array as its argument list
|
||||||
|
* i.e. onFulfilled.apply(undefined, array).
|
||||||
|
* @param {function} onFulfilled function to receive spread arguments
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
promisePrototype.spread = function(onFulfilled) {
|
||||||
|
return this.then(function(array) {
|
||||||
|
// array may contain promises, so resolve its contents.
|
||||||
|
return all(array, function(array) {
|
||||||
|
return onFulfilled.apply(undef, array);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut for .then(onFulfilledOrRejected, onFulfilledOrRejected)
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
promisePrototype.always = function(onFulfilledOrRejected, onProgress) {
|
||||||
|
return this.then(onFulfilledOrRejected, onFulfilledOrRejected, onProgress);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a resolved promise. The returned promise will be
|
* Returns a resolved promise. The returned promise will be
|
||||||
* - fulfilled with promiseOrValue if it is a value, or
|
* - fulfilled with promiseOrValue if it is a value, or
|
||||||
@ -499,13 +568,17 @@ define(function (require) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = coerce(val);
|
var queue = consumers;
|
||||||
scheduleConsumers(consumers, value);
|
|
||||||
consumers = undef;
|
consumers = undef;
|
||||||
|
|
||||||
if(status) {
|
enqueue(function () {
|
||||||
updateStatus(value, status);
|
value = coerce(self, val);
|
||||||
}
|
if(status) {
|
||||||
|
updateStatus(value, status);
|
||||||
|
}
|
||||||
|
runHandlers(queue, value);
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -522,11 +595,24 @@ define(function (require) {
|
|||||||
*/
|
*/
|
||||||
function promiseNotify(update) {
|
function promiseNotify(update) {
|
||||||
if(consumers) {
|
if(consumers) {
|
||||||
scheduleConsumers(consumers, progressed(update));
|
var queue = consumers;
|
||||||
|
enqueue(function () {
|
||||||
|
runHandlers(queue, progressed(update));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a queue of functions as quickly as possible, passing
|
||||||
|
* value to each.
|
||||||
|
*/
|
||||||
|
function runHandlers(queue, value) {
|
||||||
|
for (var i = 0; i < queue.length; i++) {
|
||||||
|
queue[i](value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a fulfilled, local promise as a proxy for a value
|
* Creates a fulfilled, local promise as a proxy for a value
|
||||||
* NOTE: must never be exposed
|
* NOTE: must never be exposed
|
||||||
@ -590,8 +676,6 @@ define(function (require) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Coerces x to a trusted Promise
|
* Coerces x to a trusted Promise
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {*} x thing to coerce
|
* @param {*} x thing to coerce
|
||||||
* @returns {*} Guaranteed to return a trusted Promise. If x
|
* @returns {*} Guaranteed to return a trusted Promise. If x
|
||||||
* is trusted, returns x, otherwise, returns a new, trusted, already-resolved
|
* is trusted, returns x, otherwise, returns a new, trusted, already-resolved
|
||||||
@ -599,34 +683,35 @@ define(function (require) {
|
|||||||
* * the resolution value of x if it's a foreign promise, or
|
* * the resolution value of x if it's a foreign promise, or
|
||||||
* * x if it's a value
|
* * x if it's a value
|
||||||
*/
|
*/
|
||||||
function coerce(x) {
|
function coerce(self, x) {
|
||||||
|
if (x === self) {
|
||||||
|
return rejected(new TypeError());
|
||||||
|
}
|
||||||
|
|
||||||
if (x instanceof Promise) {
|
if (x instanceof Promise) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(x === Object(x) && 'then' in x)) {
|
try {
|
||||||
return fulfilled(x);
|
var untrustedThen = x === Object(x) && x.then;
|
||||||
|
|
||||||
|
return typeof untrustedThen === 'function'
|
||||||
|
? assimilate(untrustedThen, x)
|
||||||
|
: fulfilled(x);
|
||||||
|
} catch(e) {
|
||||||
|
return rejected(e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return promise(function(resolve, reject, notify) {
|
/**
|
||||||
enqueue(function() {
|
* Safely assimilates a foreign thenable by wrapping it in a trusted promise
|
||||||
try {
|
* @param {function} untrustedThen x's then() method
|
||||||
// We must check and assimilate in the same tick, but not the
|
* @param {object|function} x thenable
|
||||||
// current tick, careful only to access promiseOrValue.then once.
|
* @returns {Promise}
|
||||||
var untrustedThen = x.then;
|
*/
|
||||||
|
function assimilate(untrustedThen, x) {
|
||||||
if(typeof untrustedThen === 'function') {
|
return promise(function (resolve, reject) {
|
||||||
fcall(untrustedThen, x, resolve, reject, notify);
|
fcall(untrustedThen, x, resolve, reject);
|
||||||
} else {
|
|
||||||
// It's a value, create a fulfilled wrapper
|
|
||||||
resolve(fulfilled(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch(e) {
|
|
||||||
// Something went wrong, reject
|
|
||||||
reject(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,22 +745,6 @@ define(function (require) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedule a task that will process a list of handlers
|
|
||||||
* in the next queue drain run.
|
|
||||||
* @private
|
|
||||||
* @param {Array} handlers queue of handlers to execute
|
|
||||||
* @param {*} value passed as the only arg to each handler
|
|
||||||
*/
|
|
||||||
function scheduleConsumers(handlers, value) {
|
|
||||||
enqueue(function() {
|
|
||||||
var handler, i = 0;
|
|
||||||
while (handler = handlers[i++]) {
|
|
||||||
handler(value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateStatus(value, status) {
|
function updateStatus(value, status) {
|
||||||
value.then(statusFulfilled, statusRejected);
|
value.then(statusFulfilled, statusRejected);
|
||||||
|
|
||||||
@ -879,12 +948,11 @@ define(function (require) {
|
|||||||
function resolveOne(item, i) {
|
function resolveOne(item, i) {
|
||||||
when(item, mapFunc, fallback).then(function(mapped) {
|
when(item, mapFunc, fallback).then(function(mapped) {
|
||||||
results[i] = mapped;
|
results[i] = mapped;
|
||||||
notify(mapped);
|
|
||||||
|
|
||||||
if(!--toResolve) {
|
if(!--toResolve) {
|
||||||
resolve(results);
|
resolve(results);
|
||||||
}
|
}
|
||||||
}, reject);
|
}, reject, notify);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -961,8 +1029,8 @@ define(function (require) {
|
|||||||
//
|
//
|
||||||
|
|
||||||
var reduceArray, slice, fcall, nextTick, handlerQueue,
|
var reduceArray, slice, fcall, nextTick, handlerQueue,
|
||||||
setTimeout, funcProto, call, arrayProto, monitorApi,
|
funcProto, call, arrayProto, monitorApi,
|
||||||
cjsRequire, undef;
|
capturedSetTimeout, cjsRequire, MutationObs, undef;
|
||||||
|
|
||||||
cjsRequire = require;
|
cjsRequire = require;
|
||||||
|
|
||||||
@ -992,39 +1060,39 @@ define(function (require) {
|
|||||||
* processing until it is truly empty.
|
* processing until it is truly empty.
|
||||||
*/
|
*/
|
||||||
function drainQueue() {
|
function drainQueue() {
|
||||||
var task, i = 0;
|
runHandlers(handlerQueue);
|
||||||
|
|
||||||
while(task = handlerQueue[i++]) {
|
|
||||||
task();
|
|
||||||
}
|
|
||||||
|
|
||||||
handlerQueue = [];
|
handlerQueue = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// capture setTimeout to avoid being caught by fake timers
|
|
||||||
// used in time based tests
|
|
||||||
setTimeout = global.setTimeout;
|
|
||||||
|
|
||||||
// Allow attaching the monitor to when() if env has no console
|
// Allow attaching the monitor to when() if env has no console
|
||||||
monitorApi = typeof console != 'undefined' ? console : when;
|
monitorApi = typeof console !== 'undefined' ? console : when;
|
||||||
|
|
||||||
// Prefer setImmediate or MessageChannel, cascade to node,
|
// Sniff "best" async scheduling option
|
||||||
// vertx and finally setTimeout
|
// Prefer process.nextTick or MutationObserver, then check for
|
||||||
/*global setImmediate,MessageChannel,process*/
|
// vertx and finally fall back to setTimeout
|
||||||
if (typeof setImmediate === 'function') {
|
/*global process,document,setTimeout,MutationObserver,WebKitMutationObserver*/
|
||||||
nextTick = setImmediate.bind(global);
|
if (typeof process === 'object' && process.nextTick) {
|
||||||
} else if(typeof MessageChannel !== 'undefined') {
|
|
||||||
var channel = new MessageChannel();
|
|
||||||
channel.port1.onmessage = drainQueue;
|
|
||||||
nextTick = function() { channel.port2.postMessage(0); };
|
|
||||||
} else if (typeof process === 'object' && process.nextTick) {
|
|
||||||
nextTick = process.nextTick;
|
nextTick = process.nextTick;
|
||||||
|
} else if(MutationObs =
|
||||||
|
(typeof MutationObserver === 'function' && MutationObserver) ||
|
||||||
|
(typeof WebKitMutationObserver === 'function' && WebKitMutationObserver)) {
|
||||||
|
nextTick = (function(document, MutationObserver, drainQueue) {
|
||||||
|
var el = document.createElement('div');
|
||||||
|
new MutationObserver(drainQueue).observe(el, { attributes: true });
|
||||||
|
|
||||||
|
return function() {
|
||||||
|
el.setAttribute('x', 'x');
|
||||||
|
};
|
||||||
|
}(document, MutationObs, drainQueue));
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
// vert.x 1.x || 2.x
|
// vert.x 1.x || 2.x
|
||||||
nextTick = cjsRequire('vertx').runOnLoop || cjsRequire('vertx').runOnContext;
|
nextTick = cjsRequire('vertx').runOnLoop || cjsRequire('vertx').runOnContext;
|
||||||
} catch(ignore) {
|
} catch(ignore) {
|
||||||
nextTick = function(t) { setTimeout(t, 0); };
|
// capture setTimeout to avoid being caught by fake timers
|
||||||
|
// used in time based tests
|
||||||
|
capturedSetTimeout = setTimeout;
|
||||||
|
nextTick = function(t) { capturedSetTimeout(t, 0); };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1095,15 +1163,28 @@ define(function (require) {
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function crash(fatalError) {
|
||||||
|
if(typeof monitorApi.reportUnhandled === 'function') {
|
||||||
|
monitorApi.reportUnhandled();
|
||||||
|
} else {
|
||||||
|
enqueue(function() {
|
||||||
|
throw fatalError;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
throw fatalError;
|
||||||
|
}
|
||||||
|
|
||||||
return when;
|
return when;
|
||||||
});
|
});
|
||||||
})(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); }, this);
|
})(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });
|
||||||
|
|
||||||
if (typeof module === "object" && typeof require === "function") {
|
},{"__browserify_process":3}],5:[function(require,module,exports){
|
||||||
var bane = require("bane");
|
/*global module:true, require:false*/
|
||||||
var websocket = require("faye-websocket");
|
|
||||||
var when = require("when");
|
var bane = require("bane");
|
||||||
}
|
var websocket = require("../lib/websocket/");
|
||||||
|
var when = require("when");
|
||||||
|
|
||||||
function Mopidy(settings) {
|
function Mopidy(settings) {
|
||||||
if (!(this instanceof Mopidy)) {
|
if (!(this instanceof Mopidy)) {
|
||||||
@ -1125,11 +1206,7 @@ function Mopidy(settings) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof module === "object" && typeof require === "function") {
|
Mopidy.WebSocket = websocket.Client;
|
||||||
Mopidy.WebSocket = websocket.Client;
|
|
||||||
} else {
|
|
||||||
Mopidy.WebSocket = window.WebSocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mopidy.prototype._configure = function (settings) {
|
Mopidy.prototype._configure = function (settings) {
|
||||||
var currentHost = (typeof document !== "undefined" &&
|
var currentHost = (typeof document !== "undefined" &&
|
||||||
@ -1394,6 +1471,9 @@ Mopidy.prototype._snakeToCamel = function (name) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof exports === "object") {
|
module.exports = Mopidy;
|
||||||
exports.Mopidy = Mopidy;
|
|
||||||
}
|
},{"../lib/websocket/":1,"bane":2,"when":4}]},{},[5])
|
||||||
|
(5)
|
||||||
|
});
|
||||||
|
;
|
||||||
4
mopidy/http/data/mopidy.min.js
vendored
4
mopidy/http/data/mopidy.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user