[Pkg-javascript-commits] [node-es6-promise] 01/04: Imported Upstream version 3.0.2+ds
Julien Puydt
julien.puydt at laposte.net
Tue Oct 20 08:30:31 UTC 2015
This is an automated email from the git hooks/post-receive script.
jpuydt-guest pushed a commit to branch master
in repository node-es6-promise.
commit 7aae857a60f8196c78396e44ad35d7b9ca789f3d
Author: Julien Puydt <julien.puydt at laposte.net>
Date: Mon Oct 19 19:50:31 2015 +0200
Imported Upstream version 3.0.2+ds
---
.DS_Store | Bin 0 -> 6148 bytes
.gitignore | 6 +
.jshintrc | 46 ++
.release.json | 17 +
.spmignore | 11 +
.travis.yml | 17 +
Brocfile.js | 65 +++
CHANGELOG.md | 29 ++
LICENSE | 19 +
README.md | 61 +++
bin/publish_to_s3.js | 28 ++
bower.json | 29 ++
config/s3ProjectConfig.js | 26 +
config/versionTemplate.txt | 7 +
lib/es6-promise.umd.js | 18 +
lib/es6-promise/-internal.js | 252 ++++++++++
lib/es6-promise/asap.js | 120 +++++
lib/es6-promise/enumerator.js | 113 +++++
lib/es6-promise/polyfill.js | 26 +
lib/es6-promise/promise.js | 415 ++++++++++++++++
lib/es6-promise/promise/all.js | 52 ++
lib/es6-promise/promise/race.js | 104 ++++
lib/es6-promise/promise/reject.js | 46 ++
lib/es6-promise/promise/resolve.js | 48 ++
lib/es6-promise/utils.js | 22 +
package.json | 64 +++
server/.jshintrc | 3 +
server/index.js | 5 +
test/extension-test.js | 986 +++++++++++++++++++++++++++++++++++++
test/index.html | 25 +
test/index.js | 4 +
test/scheduler-test.js | 76 +++
test/test-adapter.js | 26 +
test/worker.js | 16 +
testem.json | 14 +
vendor/loader.js | 53 ++
36 files changed, 2849 insertions(+)
diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..0e1992e
Binary files /dev/null and b/.DS_Store differ
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8b81193
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/promises_tests
+/main.js
+/tmp
+/docs
+/dist/test
\ No newline at end of file
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..be502a3
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,46 @@
+{
+ "predef": [
+ "console",
+ "require",
+ "equal",
+ "test",
+ "testBoth",
+ "testWithDefault",
+ "raises",
+ "deepEqual",
+ "start",
+ "stop",
+ "ok",
+ "strictEqual",
+ "module",
+ "expect"
+ ],
+
+ "esnext": true,
+ "proto": true,
+ "node" : true,
+ "browser" : true,
+
+ "boss" : true,
+ "curly": false,
+ "debug": false,
+ "devel": false,
+ "eqeqeq": true,
+ "evil": true,
+ "forin": false,
+ "immed": false,
+ "laxbreak": false,
+ "newcap": true,
+ "noarg": true,
+ "noempty": false,
+ "nonew": false,
+ "nomen": false,
+ "onevar": false,
+ "plusplus": false,
+ "regexp": false,
+ "undef": true,
+ "sub": true,
+ "strict": false,
+ "white": false,
+ "eqnull": true
+}
diff --git a/.release.json b/.release.json
new file mode 100644
index 0000000..dee8cbc
--- /dev/null
+++ b/.release.json
@@ -0,0 +1,17 @@
+{
+ "non-interactive": true,
+ "dry-run": false,
+ "verbose": false,
+ "force": false,
+ "pkgFiles": ["package.json", "bower.json"],
+ "increment": "patch",
+ "commitMessage": "Release %s",
+ "tagName": "%s",
+ "tagAnnotation": "Release %s",
+ "buildCommand": "npm run-script build-all",
+ "distRepo": "git at github.com:components/rsvp.js.git",
+ "distStageDir": "tmp/stage",
+ "distBase": "dist",
+ "distFiles": ["**/*", "../package.json", "../bower.json"],
+ "publish": false
+}
diff --git a/.spmignore b/.spmignore
new file mode 100644
index 0000000..7a75811
--- /dev/null
+++ b/.spmignore
@@ -0,0 +1,11 @@
+/node_modules/
+/tmp
+/tasks
+/test
+/vendor
+/.jshintrc
+/.npmignore
+/.travis.yml
+/Gruntfile.js
+/component.json
+/index.html
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..9e9d1e9
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,17 @@
+---
+language: node_js
+node_js:
+- '0.10'
+after_success:
+- "./bin/publish_to_s3.js"
+env:
+ global:
+ - secure: |-
+ d59CLXVX6GiFNo9z2vzCt/l/3p2/RjvjgYvrE3Tx7Ose6H7BBOuV6fSGOQ2n
+ MK4RHcA+2TIhNshldeX6ZCXNaRIMY3dixfJBF7eb2N7wDBj2hA17oxvE0MzE
+ rOWXzvAmxA53/xvr4bShoCbsa06WDGScEkcdJRCnFG+ReAyG/WU=
+ - secure: |-
+ mrNGoG5AycW+d5jlghF9PJHQW1ETT9jWI7bGe9QX1QRpoSLkGAvxavrujmhu
+ UNRP/pe5AJBh3zDED38nD/ZGtrcSYQ5CC6QbFLx5mLtqn7mNTo1m3C5lr+55
+ Sb6mnyLLz2eoPBUMcXwY1i9Qisy40uhfV9VuD5B/gvVud2+oJWI=
+ - EMBER_ENV=production
diff --git a/Brocfile.js b/Brocfile.js
new file mode 100644
index 0000000..89a3903
--- /dev/null
+++ b/Brocfile.js
@@ -0,0 +1,65 @@
+/* jshint node:true, undef:true, unused:true */
+var compileModules = require('broccoli-es6-module-transpiler');
+var merge = require('broccoli-merge-trees');
+var uglify = require('broccoli-uglify-js');
+var version = require('git-repo-version');
+var browserify = require('broccoli-watchify');
+var fs = require('fs');
+
+var stew = require('broccoli-stew');
+
+var find = stew.find;
+var mv = stew.mv;
+var rename = stew.rename;
+var env = stew.env;
+var map = stew.map;
+
+var lib = find('lib');
+var testDir = find('test');
+var testFiles = find('test/{index.html,worker.js}');
+
+var json3 = mv(find('node_modules/json3/lib/{json3.js}'), 'node_modules/json3/lib/', 'test/');
+var mocha = mv(find('node_modules/mocha/mocha.{js,css}'), 'node_modules/mocha/', 'test/');
+
+var testVendor = merge([ json3, mocha ]);
+
+var es6Promise = compileModules(lib, {
+ format: 'bundle',
+ entry: 'es6-promise.umd.js',
+ output: 'es6-promise.js'
+});
+
+var testBundle = browserify(merge([
+ mv(es6Promise, 'test'),
+ testDir
+]), {
+ browserify: { entries: ['./test/index.js'] },
+ init: function (b) { b.external('vertx'); }
+});
+
+var dist = es6Promise;
+
+env('production', function() {
+ dist = merge([
+ rename(uglify(dist), '.js', '.min.js'),
+ dist
+ ]);
+});
+
+function prependLicense(content) {
+ var license = fs.readFileSync('./config/versionTemplate.txt').toString().replace(/VERSION_PLACEHOLDER_STRING/, version());
+ // strip source maps for now...
+ var content = content.replace(/\/\/# sourceMappingURL=es6-promise.*/,'');
+ return license + '\n' + content;
+}
+
+// exclude source maps for now, until map/cat supports source maps
+dist = find(dist, '!*.map');
+
+module.exports = merge([
+ map(dist, prependLicense),
+ testFiles,
+ testVendor,
+ mv(dist, 'test'),
+ mv(testBundle, 'test')
+]);
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..fbe4053
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,29 @@
+# Master
+
+# 3.0.2
+
+* correctly bump both bower and package.json versions
+
+# 3.0.1
+
+* no longer include dist/test in npm releases
+
+# 3.0.0
+
+* use nextTick() instead of setImmediate() to schedule microtasks with node 0.10. Later versions of
+ nodes are not affected as they were already using nextTick(). Note that using nextTick() might
+ trigger a depreciation warning on 0.10 as described at https://github.com/cujojs/when/issues/410.
+ The reason why nextTick() is preferred is that is setImmediate() would schedule a macrotask
+ instead of a microtask and might result in a different scheduling.
+ If needed you can revert to the former behavior as follow:
+
+ var Promise = require('es6-promise').Promise;
+ Promise._setScheduler(setImmediate);
+
+# 2.0.0
+
+* re-sync with RSVP. Many large performance improvements and bugfixes.
+
+# 1.0.0
+
+* first subset of RSVP
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..954ec59
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d952fa7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,61 @@
+# ES6-Promise (subset of [rsvp.js](https://github.com/tildeio/rsvp.js))
+
+This is a polyfill of the [ES6 Promise](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-promise-constructor). The implementation is a subset of [rsvp.js](https://github.com/tildeio/rsvp.js), if you're wanting extra features and more debugging options, check out the [full library](https://github.com/tildeio/rsvp.js).
+
+For API details and how to use promises, see the <a href="http://www.html5rocks.com/en/tutorials/es6/promises/">JavaScript Promises HTML5Rocks article</a>.
+
+## Downloads
+
+* [es6-promise](https://raw.githubusercontent.com/jakearchibald/es6-promise/master/dist/es6-promise.js)
+* [es6-promise-min](https://raw.githubusercontent.com/jakearchibald/es6-promise/master/dist/es6-promise.min.js)
+
+## Node.js
+
+To install:
+
+```sh
+npm install es6-promise
+```
+
+To use:
+
+```js
+var Promise = require('es6-promise').Promise;
+```
+
+## Usage in IE<9
+
+`catch` is a reserved word in IE<9, meaning `promise.catch(func)` throws a syntax error. To work around this, you can use a string to access the property as shown in the following example.
+
+However, please remember that such technique is already provided by most common minifiers, making the resulting code safe for old browsers and production:
+
+```js
+promise['catch'](function(err) {
+ // ...
+});
+```
+
+Or use `.then` instead:
+
+```js
+promise.then(undefined, function(err) {
+ // ...
+});
+```
+
+## Auto-polyfill
+
+To polyfill the global environment (either in Node or in the browser via CommonJS) use the following code snippet:
+
+```js
+require('es6-promise').polyfill();
+```
+
+Notice that we don't assign the result of `polyfill()` to any variable. The `polyfill()` method will patch the global environment (in this case to the `Promise` name) when called.
+
+## Building & Testing
+
+* `npm run build` to build
+* `npm test` to run tests
+* `npm start` to run a build watcher, and webserver to test
+* `npm run test:server` for a testem test runner and watching builder
diff --git a/bin/publish_to_s3.js b/bin/publish_to_s3.js
new file mode 100755
index 0000000..7daf49a
--- /dev/null
+++ b/bin/publish_to_s3.js
@@ -0,0 +1,28 @@
+#!/usr/bin/env node
+
+// To invoke this from the commandline you need the following to env vars to exist:
+//
+// S3_BUCKET_NAME
+// TRAVIS_BRANCH
+// TRAVIS_TAG
+// TRAVIS_COMMIT
+// S3_SECRET_ACCESS_KEY
+// S3_ACCESS_KEY_ID
+//
+// Once you have those you execute with the following:
+//
+// ```sh
+// ./bin/publish_to_s3.js
+// ```
+var S3Publisher = require('ember-publisher');
+var configPath = require('path').join(__dirname, '../config/s3ProjectConfig.js');
+publisher = new S3Publisher({ projectConfigPath: configPath });
+
+// Always use wildcard section of project config.
+// This is useful when the including library does not
+// require channels (like in ember.js / ember-data).
+publisher.currentBranch = function() {
+ return (process.env.TRAVIS_BRANCH === 'master') ? 'wildcard' : 'no-op';
+};
+publisher.publish();
+
diff --git a/bower.json b/bower.json
new file mode 100644
index 0000000..c699782
--- /dev/null
+++ b/bower.json
@@ -0,0 +1,29 @@
+{
+ "name": "es6-promise",
+ "namespace": "Promise",
+ "version": "3.0.2",
+ "description": "A polyfill for ES6-style Promises, tracking rsvp",
+ "authors": [
+ "Stefan Penner <stefan.penner at gmail.com>"
+ ],
+ "main": "dist/es6-promise.js",
+ "keywords": [
+ "promise"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/jakearchibald/ES6-Promises.git"
+ },
+ "bugs": {
+ "url": "https://github.com/jakearchibald/ES6-Promises/issues"
+ },
+ "license": "MIT",
+ "ignore": [
+ "node_modules",
+ "bower_components",
+ "test",
+ "tests",
+ "vendor",
+ "tasks"
+ ]
+}
diff --git a/config/s3ProjectConfig.js b/config/s3ProjectConfig.js
new file mode 100644
index 0000000..5f3349a
--- /dev/null
+++ b/config/s3ProjectConfig.js
@@ -0,0 +1,26 @@
+/*
+ * Using wildcard because es6-promise does not currently have a
+ * channel system in place.
+ */
+module.exports = function(revision,tag,date){
+ return {
+ 'es6-promise.js':
+ { contentType: 'text/javascript',
+ destinations: {
+ wildcard: [
+ 'es6-promise-latest.js',
+ 'es6-promise-' + revision + '.js'
+ ]
+ }
+ },
+ 'es6-promise.min.js':
+ { contentType: 'text/javascript',
+ destinations: {
+ wildcard: [
+ 'es6-promise-latest.min.js',
+ 'es6-promise-' + revision + '.min.js'
+ ]
+ }
+ }
+ }
+}
diff --git a/config/versionTemplate.txt b/config/versionTemplate.txt
new file mode 100644
index 0000000..999a5fc
--- /dev/null
+++ b/config/versionTemplate.txt
@@ -0,0 +1,7 @@
+/*!
+ * @overview es6-promise - a tiny implementation of Promises/A+.
+ * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
+ * @license Licensed under MIT license
+ * See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE
+ * @version VERSION_PLACEHOLDER_STRING
+ */
diff --git a/lib/es6-promise.umd.js b/lib/es6-promise.umd.js
new file mode 100644
index 0000000..5984f70
--- /dev/null
+++ b/lib/es6-promise.umd.js
@@ -0,0 +1,18 @@
+import Promise from './es6-promise/promise';
+import polyfill from './es6-promise/polyfill';
+
+var ES6Promise = {
+ 'Promise': Promise,
+ 'polyfill': polyfill
+};
+
+/* global define:true module:true window: true */
+if (typeof define === 'function' && define['amd']) {
+ define(function() { return ES6Promise; });
+} else if (typeof module !== 'undefined' && module['exports']) {
+ module['exports'] = ES6Promise;
+} else if (typeof this !== 'undefined') {
+ this['ES6Promise'] = ES6Promise;
+}
+
+polyfill();
diff --git a/lib/es6-promise/-internal.js b/lib/es6-promise/-internal.js
new file mode 100644
index 0000000..720448f
--- /dev/null
+++ b/lib/es6-promise/-internal.js
@@ -0,0 +1,252 @@
+import {
+ objectOrFunction,
+ isFunction
+} from './utils';
+
+import {
+ asap
+} from './asap';
+
+function noop() {}
+
+var PENDING = void 0;
+var FULFILLED = 1;
+var REJECTED = 2;
+
+var GET_THEN_ERROR = new ErrorObject();
+
+function selfFulfillment() {
+ return new TypeError("You cannot resolve a promise with itself");
+}
+
+function cannotReturnOwn() {
+ return new TypeError('A promises callback cannot return that same promise.');
+}
+
+function getThen(promise) {
+ try {
+ return promise.then;
+ } catch(error) {
+ GET_THEN_ERROR.error = error;
+ return GET_THEN_ERROR;
+ }
+}
+
+function tryThen(then, value, fulfillmentHandler, rejectionHandler) {
+ try {
+ then.call(value, fulfillmentHandler, rejectionHandler);
+ } catch(e) {
+ return e;
+ }
+}
+
+function handleForeignThenable(promise, thenable, then) {
+ asap(function(promise) {
+ var sealed = false;
+ var error = tryThen(then, thenable, function(value) {
+ if (sealed) { return; }
+ sealed = true;
+ if (thenable !== value) {
+ resolve(promise, value);
+ } else {
+ fulfill(promise, value);
+ }
+ }, function(reason) {
+ if (sealed) { return; }
+ sealed = true;
+
+ reject(promise, reason);
+ }, 'Settle: ' + (promise._label || ' unknown promise'));
+
+ if (!sealed && error) {
+ sealed = true;
+ reject(promise, error);
+ }
+ }, promise);
+}
+
+function handleOwnThenable(promise, thenable) {
+ if (thenable._state === FULFILLED) {
+ fulfill(promise, thenable._result);
+ } else if (thenable._state === REJECTED) {
+ reject(promise, thenable._result);
+ } else {
+ subscribe(thenable, undefined, function(value) {
+ resolve(promise, value);
+ }, function(reason) {
+ reject(promise, reason);
+ });
+ }
+}
+
+function handleMaybeThenable(promise, maybeThenable) {
+ if (maybeThenable.constructor === promise.constructor) {
+ handleOwnThenable(promise, maybeThenable);
+ } else {
+ var then = getThen(maybeThenable);
+
+ if (then === GET_THEN_ERROR) {
+ reject(promise, GET_THEN_ERROR.error);
+ } else if (then === undefined) {
+ fulfill(promise, maybeThenable);
+ } else if (isFunction(then)) {
+ handleForeignThenable(promise, maybeThenable, then);
+ } else {
+ fulfill(promise, maybeThenable);
+ }
+ }
+}
+
+function resolve(promise, value) {
+ if (promise === value) {
+ reject(promise, selfFulfillment());
+ } else if (objectOrFunction(value)) {
+ handleMaybeThenable(promise, value);
+ } else {
+ fulfill(promise, value);
+ }
+}
+
+function publishRejection(promise) {
+ if (promise._onerror) {
+ promise._onerror(promise._result);
+ }
+
+ publish(promise);
+}
+
+function fulfill(promise, value) {
+ if (promise._state !== PENDING) { return; }
+
+ promise._result = value;
+ promise._state = FULFILLED;
+
+ if (promise._subscribers.length !== 0) {
+ asap(publish, promise);
+ }
+}
+
+function reject(promise, reason) {
+ if (promise._state !== PENDING) { return; }
+ promise._state = REJECTED;
+ promise._result = reason;
+
+ asap(publishRejection, promise);
+}
+
+function subscribe(parent, child, onFulfillment, onRejection) {
+ var subscribers = parent._subscribers;
+ var length = subscribers.length;
+
+ parent._onerror = null;
+
+ subscribers[length] = child;
+ subscribers[length + FULFILLED] = onFulfillment;
+ subscribers[length + REJECTED] = onRejection;
+
+ if (length === 0 && parent._state) {
+ asap(publish, parent);
+ }
+}
+
+function publish(promise) {
+ var subscribers = promise._subscribers;
+ var settled = promise._state;
+
+ if (subscribers.length === 0) { return; }
+
+ var child, callback, detail = promise._result;
+
+ for (var i = 0; i < subscribers.length; i += 3) {
+ child = subscribers[i];
+ callback = subscribers[i + settled];
+
+ if (child) {
+ invokeCallback(settled, child, callback, detail);
+ } else {
+ callback(detail);
+ }
+ }
+
+ promise._subscribers.length = 0;
+}
+
+function ErrorObject() {
+ this.error = null;
+}
+
+var TRY_CATCH_ERROR = new ErrorObject();
+
+function tryCatch(callback, detail) {
+ try {
+ return callback(detail);
+ } catch(e) {
+ TRY_CATCH_ERROR.error = e;
+ return TRY_CATCH_ERROR;
+ }
+}
+
+function invokeCallback(settled, promise, callback, detail) {
+ var hasCallback = isFunction(callback),
+ value, error, succeeded, failed;
+
+ if (hasCallback) {
+ value = tryCatch(callback, detail);
+
+ if (value === TRY_CATCH_ERROR) {
+ failed = true;
+ error = value.error;
+ value = null;
+ } else {
+ succeeded = true;
+ }
+
+ if (promise === value) {
+ reject(promise, cannotReturnOwn());
+ return;
+ }
+
+ } else {
+ value = detail;
+ succeeded = true;
+ }
+
+ if (promise._state !== PENDING) {
+ // noop
+ } else if (hasCallback && succeeded) {
+ resolve(promise, value);
+ } else if (failed) {
+ reject(promise, error);
+ } else if (settled === FULFILLED) {
+ fulfill(promise, value);
+ } else if (settled === REJECTED) {
+ reject(promise, value);
+ }
+}
+
+function initializePromise(promise, resolver) {
+ try {
+ resolver(function resolvePromise(value){
+ resolve(promise, value);
+ }, function rejectPromise(reason) {
+ reject(promise, reason);
+ });
+ } catch(e) {
+ reject(promise, e);
+ }
+}
+
+export {
+ noop,
+ resolve,
+ reject,
+ fulfill,
+ subscribe,
+ publish,
+ publishRejection,
+ initializePromise,
+ invokeCallback,
+ FULFILLED,
+ REJECTED,
+ PENDING
+};
diff --git a/lib/es6-promise/asap.js b/lib/es6-promise/asap.js
new file mode 100644
index 0000000..56a65a5
--- /dev/null
+++ b/lib/es6-promise/asap.js
@@ -0,0 +1,120 @@
+var len = 0;
+var toString = {}.toString;
+var vertxNext;
+var customSchedulerFn;
+
+export var asap = function asap(callback, arg) {
+ queue[len] = callback;
+ queue[len + 1] = arg;
+ len += 2;
+ if (len === 2) {
+ // If len is 2, that means that we need to schedule an async flush.
+ // If additional callbacks are queued before the queue is flushed, they
+ // will be processed by this flush that we are scheduling.
+ if (customSchedulerFn) {
+ customSchedulerFn(flush);
+ } else {
+ scheduleFlush();
+ }
+ }
+}
+
+export function setScheduler(scheduleFn) {
+ customSchedulerFn = scheduleFn;
+}
+
+export function setAsap(asapFn) {
+ asap = asapFn;
+}
+
+var browserWindow = (typeof window !== 'undefined') ? window : undefined;
+var browserGlobal = browserWindow || {};
+var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
+var isNode = typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';
+
+// test for web worker but not in IE10
+var isWorker = typeof Uint8ClampedArray !== 'undefined' &&
+ typeof importScripts !== 'undefined' &&
+ typeof MessageChannel !== 'undefined';
+
+// node
+function useNextTick() {
+ // node version 0.10.x displays a deprecation warning when nextTick is used recursively
+ // see https://github.com/cujojs/when/issues/410 for details
+ return function() {
+ process.nextTick(flush);
+ };
+}
+
+// vertx
+function useVertxTimer() {
+ return function() {
+ vertxNext(flush);
+ };
+}
+
+function useMutationObserver() {
+ var iterations = 0;
+ var observer = new BrowserMutationObserver(flush);
+ var node = document.createTextNode('');
+ observer.observe(node, { characterData: true });
+
+ return function() {
+ node.data = (iterations = ++iterations % 2);
+ };
+}
+
+// web worker
+function useMessageChannel() {
+ var channel = new MessageChannel();
+ channel.port1.onmessage = flush;
+ return function () {
+ channel.port2.postMessage(0);
+ };
+}
+
+function useSetTimeout() {
+ return function() {
+ setTimeout(flush, 1);
+ };
+}
+
+var queue = new Array(1000);
+function flush() {
+ for (var i = 0; i < len; i+=2) {
+ var callback = queue[i];
+ var arg = queue[i+1];
+
+ callback(arg);
+
+ queue[i] = undefined;
+ queue[i+1] = undefined;
+ }
+
+ len = 0;
+}
+
+function attemptVertx() {
+ try {
+ var r = require;
+ var vertx = r('vertx');
+ vertxNext = vertx.runOnLoop || vertx.runOnContext;
+ return useVertxTimer();
+ } catch(e) {
+ return useSetTimeout();
+ }
+}
+
+var scheduleFlush;
+// Decide what async method to use to triggering processing of queued callbacks:
+if (isNode) {
+ scheduleFlush = useNextTick();
+} else if (BrowserMutationObserver) {
+ scheduleFlush = useMutationObserver();
+} else if (isWorker) {
+ scheduleFlush = useMessageChannel();
+} else if (browserWindow === undefined && typeof require === 'function') {
+ scheduleFlush = attemptVertx();
+} else {
+ scheduleFlush = useSetTimeout();
+}
diff --git a/lib/es6-promise/enumerator.js b/lib/es6-promise/enumerator.js
new file mode 100644
index 0000000..03fdf8c
--- /dev/null
+++ b/lib/es6-promise/enumerator.js
@@ -0,0 +1,113 @@
+import {
+ isArray,
+ isMaybeThenable
+} from './utils';
+
+import {
+ noop,
+ reject,
+ fulfill,
+ subscribe,
+ FULFILLED,
+ REJECTED,
+ PENDING
+} from './-internal';
+
+function Enumerator(Constructor, input) {
+ var enumerator = this;
+
+ enumerator._instanceConstructor = Constructor;
+ enumerator.promise = new Constructor(noop);
+
+ if (enumerator._validateInput(input)) {
+ enumerator._input = input;
+ enumerator.length = input.length;
+ enumerator._remaining = input.length;
+
+ enumerator._init();
+
+ if (enumerator.length === 0) {
+ fulfill(enumerator.promise, enumerator._result);
+ } else {
+ enumerator.length = enumerator.length || 0;
+ enumerator._enumerate();
+ if (enumerator._remaining === 0) {
+ fulfill(enumerator.promise, enumerator._result);
+ }
+ }
+ } else {
+ reject(enumerator.promise, enumerator._validationError());
+ }
+}
+
+Enumerator.prototype._validateInput = function(input) {
+ return isArray(input);
+};
+
+Enumerator.prototype._validationError = function() {
+ return new Error('Array Methods must be provided an Array');
+};
+
+Enumerator.prototype._init = function() {
+ this._result = new Array(this.length);
+};
+
+export default Enumerator;
+
+Enumerator.prototype._enumerate = function() {
+ var enumerator = this;
+
+ var length = enumerator.length;
+ var promise = enumerator.promise;
+ var input = enumerator._input;
+
+ for (var i = 0; promise._state === PENDING && i < length; i++) {
+ enumerator._eachEntry(input[i], i);
+ }
+};
+
+Enumerator.prototype._eachEntry = function(entry, i) {
+ var enumerator = this;
+ var c = enumerator._instanceConstructor;
+
+ if (isMaybeThenable(entry)) {
+ if (entry.constructor === c && entry._state !== PENDING) {
+ entry._onerror = null;
+ enumerator._settledAt(entry._state, i, entry._result);
+ } else {
+ enumerator._willSettleAt(c.resolve(entry), i);
+ }
+ } else {
+ enumerator._remaining--;
+ enumerator._result[i] = entry;
+ }
+};
+
+Enumerator.prototype._settledAt = function(state, i, value) {
+ var enumerator = this;
+ var promise = enumerator.promise;
+
+ if (promise._state === PENDING) {
+ enumerator._remaining--;
+
+ if (state === REJECTED) {
+ reject(promise, value);
+ } else {
+ enumerator._result[i] = value;
+ }
+ }
+
+ if (enumerator._remaining === 0) {
+ fulfill(promise, enumerator._result);
+ }
+};
+
+Enumerator.prototype._willSettleAt = function(promise, i) {
+ var enumerator = this;
+
+ subscribe(promise, undefined, function(value) {
+ enumerator._settledAt(FULFILLED, i, value);
+ }, function(reason) {
+ enumerator._settledAt(REJECTED, i, reason);
+ });
+};
diff --git a/lib/es6-promise/polyfill.js b/lib/es6-promise/polyfill.js
new file mode 100644
index 0000000..6696dfc
--- /dev/null
+++ b/lib/es6-promise/polyfill.js
@@ -0,0 +1,26 @@
+/*global self*/
+import Promise from './promise';
+
+export default function polyfill() {
+ var local;
+
+ if (typeof global !== 'undefined') {
+ local = global;
+ } else if (typeof self !== 'undefined') {
+ local = self;
+ } else {
+ try {
+ local = Function('return this')();
+ } catch (e) {
+ throw new Error('polyfill failed because global object is unavailable in this environment');
+ }
+ }
+
+ var P = local.Promise;
+
+ if (P && Object.prototype.toString.call(P.resolve()) === '[object Promise]' && !P.cast) {
+ return;
+ }
+
+ local.Promise = Promise;
+}
diff --git a/lib/es6-promise/promise.js b/lib/es6-promise/promise.js
new file mode 100644
index 0000000..8b1688b
--- /dev/null
+++ b/lib/es6-promise/promise.js
@@ -0,0 +1,415 @@
+import {
+ isFunction
+} from './utils';
+
+import {
+ noop,
+ subscribe,
+ initializePromise,
+ invokeCallback,
+ FULFILLED,
+ REJECTED
+} from './-internal';
+
+import {
+ asap,
+ setAsap,
+ setScheduler
+} from './asap';
+
+import all from './promise/all';
+import race from './promise/race';
+import Resolve from './promise/resolve';
+import Reject from './promise/reject';
+
+var counter = 0;
+
+function needsResolver() {
+ throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
+}
+
+function needsNew() {
+ throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
+}
+
+export default Promise;
+/**
+ Promise objects represent the eventual result of an asynchronous operation. The
+ primary way of interacting with a promise is through its `then` method, which
+ registers callbacks to receive either a promise's eventual value or the reason
+ why the promise cannot be fulfilled.
+
+ Terminology
+ -----------
+
+ - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
+ - `thenable` is an object or function that defines a `then` method.
+ - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
+ - `exception` is a value that is thrown using the throw statement.
+ - `reason` is a value that indicates why a promise was rejected.
+ - `settled` the final resting state of a promise, fulfilled or rejected.
+
+ A promise can be in one of three states: pending, fulfilled, or rejected.
+
+ Promises that are fulfilled have a fulfillment value and are in the fulfilled
+ state. Promises that are rejected have a rejection reason and are in the
+ rejected state. A fulfillment value is never a thenable.
+
+ Promises can also be said to *resolve* a value. If this value is also a
+ promise, then the original promise's settled state will match the value's
+ settled state. So a promise that *resolves* a promise that rejects will
+ itself reject, and a promise that *resolves* a promise that fulfills will
+ itself fulfill.
+
+
+ Basic Usage:
+ ------------
+
+ ```js
+ var promise = new Promise(function(resolve, reject) {
+ // on success
+ resolve(value);
+
+ // on failure
+ reject(reason);
+ });
+
+ promise.then(function(value) {
+ // on fulfillment
+ }, function(reason) {
+ // on rejection
+ });
+ ```
+
+ Advanced Usage:
+ ---------------
+
+ Promises shine when abstracting away asynchronous interactions such as
+ `XMLHttpRequest`s.
+
+ ```js
+ function getJSON(url) {
+ return new Promise(function(resolve, reject){
+ var xhr = new XMLHttpRequest();
+
+ xhr.open('GET', url);
+ xhr.onreadystatechange = handler;
+ xhr.responseType = 'json';
+ xhr.setRequestHeader('Accept', 'application/json');
+ xhr.send();
+
+ function handler() {
+ if (this.readyState === this.DONE) {
+ if (this.status === 200) {
+ resolve(this.response);
+ } else {
+ reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
+ }
+ }
+ };
+ });
+ }
+
+ getJSON('/posts.json').then(function(json) {
+ // on fulfillment
+ }, function(reason) {
+ // on rejection
+ });
+ ```
+
+ Unlike callbacks, promises are great composable primitives.
+
+ ```js
+ Promise.all([
+ getJSON('/posts'),
+ getJSON('/comments')
+ ]).then(function(values){
+ values[0] // => postsJSON
+ values[1] // => commentsJSON
+
+ return values;
+ });
+ ```
+
+ @class Promise
+ @param {function} resolver
+ Useful for tooling.
+ @constructor
+*/
+function Promise(resolver) {
+ this._id = counter++;
+ this._state = undefined;
+ this._result = undefined;
+ this._subscribers = [];
+
+ if (noop !== resolver) {
+ if (!isFunction(resolver)) {
+ needsResolver();
+ }
+
+ if (!(this instanceof Promise)) {
+ needsNew();
+ }
+
+ initializePromise(this, resolver);
+ }
+}
+
+Promise.all = all;
+Promise.race = race;
+Promise.resolve = Resolve;
+Promise.reject = Reject;
+Promise._setScheduler = setScheduler;
+Promise._setAsap = setAsap;
+Promise._asap = asap;
+
+Promise.prototype = {
+ constructor: Promise,
+
+/**
+ The primary way of interacting with a promise is through its `then` method,
+ which registers callbacks to receive either a promise's eventual value or the
+ reason why the promise cannot be fulfilled.
+
+ ```js
+ findUser().then(function(user){
+ // user is available
+ }, function(reason){
+ // user is unavailable, and you are given the reason why
+ });
+ ```
+
+ Chaining
+ --------
+
+ The return value of `then` is itself a promise. This second, 'downstream'
+ promise is resolved with the return value of the first promise's fulfillment
+ or rejection handler, or rejected if the handler throws an exception.
+
+ ```js
+ findUser().then(function (user) {
+ return user.name;
+ }, function (reason) {
+ return 'default name';
+ }).then(function (userName) {
+ // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
+ // will be `'default name'`
+ });
+
+ findUser().then(function (user) {
+ throw new Error('Found user, but still unhappy');
+ }, function (reason) {
+ throw new Error('`findUser` rejected and we're unhappy');
+ }).then(function (value) {
+ // never reached
+ }, function (reason) {
+ // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
+ // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
+ });
+ ```
+ If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
+
+ ```js
+ findUser().then(function (user) {
+ throw new PedagogicalException('Upstream error');
+ }).then(function (value) {
+ // never reached
+ }).then(function (value) {
+ // never reached
+ }, function (reason) {
+ // The `PedgagocialException` is propagated all the way down to here
+ });
+ ```
+
+ Assimilation
+ ------------
+
+ Sometimes the value you want to propagate to a downstream promise can only be
+ retrieved asynchronously. This can be achieved by returning a promise in the
+ fulfillment or rejection handler. The downstream promise will then be pending
+ until the returned promise is settled. This is called *assimilation*.
+
+ ```js
+ findUser().then(function (user) {
+ return findCommentsByAuthor(user);
+ }).then(function (comments) {
+ // The user's comments are now available
+ });
+ ```
+
+ If the assimliated promise rejects, then the downstream promise will also reject.
+
+ ```js
+ findUser().then(function (user) {
+ return findCommentsByAuthor(user);
+ }).then(function (comments) {
+ // If `findCommentsByAuthor` fulfills, we'll have the value here
+ }, function (reason) {
+ // If `findCommentsByAuthor` rejects, we'll have the reason here
+ });
+ ```
+
+ Simple Example
+ --------------
+
+ Synchronous Example
+
+ ```javascript
+ var result;
+
+ try {
+ result = findResult();
+ // success
+ } catch(reason) {
+ // failure
+ }
+ ```
+
+ Errback Example
+
+ ```js
+ findResult(function(result, err){
+ if (err) {
+ // failure
+ } else {
+ // success
+ }
+ });
+ ```
+
+ Promise Example;
+
+ ```javascript
+ findResult().then(function(result){
+ // success
+ }, function(reason){
+ // failure
+ });
+ ```
+
+ Advanced Example
+ --------------
+
+ Synchronous Example
+
+ ```javascript
+ var author, books;
+
+ try {
+ author = findAuthor();
+ books = findBooksByAuthor(author);
+ // success
+ } catch(reason) {
+ // failure
+ }
+ ```
+
+ Errback Example
+
+ ```js
+
+ function foundBooks(books) {
+
+ }
+
+ function failure(reason) {
+
+ }
+
+ findAuthor(function(author, err){
+ if (err) {
+ failure(err);
+ // failure
+ } else {
+ try {
+ findBoooksByAuthor(author, function(books, err) {
+ if (err) {
+ failure(err);
+ } else {
+ try {
+ foundBooks(books);
+ } catch(reason) {
+ failure(reason);
+ }
+ }
+ });
+ } catch(error) {
+ failure(err);
+ }
+ // success
+ }
+ });
+ ```
+
+ Promise Example;
+
+ ```javascript
+ findAuthor().
+ then(findBooksByAuthor).
+ then(function(books){
+ // found books
+ }).catch(function(reason){
+ // something went wrong
+ });
+ ```
+
+ @method then
+ @param {Function} onFulfilled
+ @param {Function} onRejected
+ Useful for tooling.
+ @return {Promise}
+*/
+ then: function(onFulfillment, onRejection) {
+ var parent = this;
+ var state = parent._state;
+
+ if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) {
+ return this;
+ }
+
+ var child = new this.constructor(noop);
+ var result = parent._result;
+
+ if (state) {
+ var callback = arguments[state - 1];
+ asap(function(){
+ invokeCallback(state, child, callback, result);
+ });
+ } else {
+ subscribe(parent, child, onFulfillment, onRejection);
+ }
+
+ return child;
+ },
+
+/**
+ `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
+ as the catch block of a try/catch statement.
+
+ ```js
+ function findAuthor(){
+ throw new Error('couldn't find that author');
+ }
+
+ // synchronous
+ try {
+ findAuthor();
+ } catch(reason) {
+ // something went wrong
+ }
+
+ // async with promises
+ findAuthor().catch(function(reason){
+ // something went wrong
+ });
+ ```
+
+ @method catch
+ @param {Function} onRejection
+ Useful for tooling.
+ @return {Promise}
+*/
+ 'catch': function(onRejection) {
+ return this.then(null, onRejection);
+ }
+};
diff --git a/lib/es6-promise/promise/all.js b/lib/es6-promise/promise/all.js
new file mode 100644
index 0000000..03033f0
--- /dev/null
+++ b/lib/es6-promise/promise/all.js
@@ -0,0 +1,52 @@
+import Enumerator from '../enumerator';
+
+/**
+ `Promise.all` accepts an array of promises, and returns a new promise which
+ is fulfilled with an array of fulfillment values for the passed promises, or
+ rejected with the reason of the first passed promise to be rejected. It casts all
+ elements of the passed iterable to promises as it runs this algorithm.
+
+ Example:
+
+ ```javascript
+ var promise1 = resolve(1);
+ var promise2 = resolve(2);
+ var promise3 = resolve(3);
+ var promises = [ promise1, promise2, promise3 ];
+
+ Promise.all(promises).then(function(array){
+ // The array here would be [ 1, 2, 3 ];
+ });
+ ```
+
+ If any of the `promises` given to `all` are rejected, the first promise
+ that is rejected will be given as an argument to the returned promises's
+ rejection handler. For example:
+
+ Example:
+
+ ```javascript
+ var promise1 = resolve(1);
+ var promise2 = reject(new Error("2"));
+ var promise3 = reject(new Error("3"));
+ var promises = [ promise1, promise2, promise3 ];
+
+ Promise.all(promises).then(function(array){
+ // Code here never runs because there are rejected promises!
+ }, function(error) {
+ // error.message === "2"
+ });
+ ```
+
+ @method all
+ @static
+ @param {Array} entries array of promises
+ @param {String} label optional string for labeling the promise.
+ Useful for tooling.
+ @return {Promise} promise that is fulfilled when all `promises` have been
+ fulfilled, or rejected if any of them become rejected.
+ @static
+*/
+export default function all(entries) {
+ return new Enumerator(this, entries).promise;
+}
diff --git a/lib/es6-promise/promise/race.js b/lib/es6-promise/promise/race.js
new file mode 100644
index 0000000..0d7ff13
--- /dev/null
+++ b/lib/es6-promise/promise/race.js
@@ -0,0 +1,104 @@
+import {
+ isArray
+} from "../utils";
+
+import {
+ noop,
+ resolve,
+ reject,
+ subscribe,
+ PENDING
+} from '../-internal';
+
+/**
+ `Promise.race` returns a new promise which is settled in the same way as the
+ first passed promise to settle.
+
+ Example:
+
+ ```javascript
+ var promise1 = new Promise(function(resolve, reject){
+ setTimeout(function(){
+ resolve('promise 1');
+ }, 200);
+ });
+
+ var promise2 = new Promise(function(resolve, reject){
+ setTimeout(function(){
+ resolve('promise 2');
+ }, 100);
+ });
+
+ Promise.race([promise1, promise2]).then(function(result){
+ // result === 'promise 2' because it was resolved before promise1
+ // was resolved.
+ });
+ ```
+
+ `Promise.race` is deterministic in that only the state of the first
+ settled promise matters. For example, even if other promises given to the
+ `promises` array argument are resolved, but the first settled promise has
+ become rejected before the other promises became fulfilled, the returned
+ promise will become rejected:
+
+ ```javascript
+ var promise1 = new Promise(function(resolve, reject){
+ setTimeout(function(){
+ resolve('promise 1');
+ }, 200);
+ });
+
+ var promise2 = new Promise(function(resolve, reject){
+ setTimeout(function(){
+ reject(new Error('promise 2'));
+ }, 100);
+ });
+
+ Promise.race([promise1, promise2]).then(function(result){
+ // Code here never runs
+ }, function(reason){
+ // reason.message === 'promise 2' because promise 2 became rejected before
+ // promise 1 became fulfilled
+ });
+ ```
+
+ An example real-world use case is implementing timeouts:
+
+ ```javascript
+ Promise.race([ajax('foo.json'), timeout(5000)])
+ ```
+
+ @method race
+ @static
+ @param {Array} promises array of promises to observe
+ Useful for tooling.
+ @return {Promise} a promise which settles in the same way as the first passed
+ promise to settle.
+*/
+export default function race(entries) {
+ /*jshint validthis:true */
+ var Constructor = this;
+
+ var promise = new Constructor(noop);
+
+ if (!isArray(entries)) {
+ reject(promise, new TypeError('You must pass an array to race.'));
+ return promise;
+ }
+
+ var length = entries.length;
+
+ function onFulfillment(value) {
+ resolve(promise, value);
+ }
+
+ function onRejection(reason) {
+ reject(promise, reason);
+ }
+
+ for (var i = 0; promise._state === PENDING && i < length; i++) {
+ subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection);
+ }
+
+ return promise;
+}
diff --git a/lib/es6-promise/promise/reject.js b/lib/es6-promise/promise/reject.js
new file mode 100644
index 0000000..63b86cb
--- /dev/null
+++ b/lib/es6-promise/promise/reject.js
@@ -0,0 +1,46 @@
+import {
+ noop,
+ reject as _reject
+} from '../-internal';
+
+/**
+ `Promise.reject` returns a promise rejected with the passed `reason`.
+ It is shorthand for the following:
+
+ ```javascript
+ var promise = new Promise(function(resolve, reject){
+ reject(new Error('WHOOPS'));
+ });
+
+ promise.then(function(value){
+ // Code here doesn't run because the promise is rejected!
+ }, function(reason){
+ // reason.message === 'WHOOPS'
+ });
+ ```
+
+ Instead of writing the above, your code now simply becomes the following:
+
+ ```javascript
+ var promise = Promise.reject(new Error('WHOOPS'));
+
+ promise.then(function(value){
+ // Code here doesn't run because the promise is rejected!
+ }, function(reason){
+ // reason.message === 'WHOOPS'
+ });
+ ```
+
+ @method reject
+ @static
+ @param {Any} reason value that the returned promise will be rejected with.
+ Useful for tooling.
+ @return {Promise} a promise rejected with the given `reason`.
+*/
+export default function reject(reason) {
+ /*jshint validthis:true */
+ var Constructor = this;
+ var promise = new Constructor(noop);
+ _reject(promise, reason);
+ return promise;
+}
diff --git a/lib/es6-promise/promise/resolve.js b/lib/es6-promise/promise/resolve.js
new file mode 100644
index 0000000..201a545
--- /dev/null
+++ b/lib/es6-promise/promise/resolve.js
@@ -0,0 +1,48 @@
+import {
+ noop,
+ resolve as _resolve
+} from '../-internal';
+
+/**
+ `Promise.resolve` returns a promise that will become resolved with the
+ passed `value`. It is shorthand for the following:
+
+ ```javascript
+ var promise = new Promise(function(resolve, reject){
+ resolve(1);
+ });
+
+ promise.then(function(value){
+ // value === 1
+ });
+ ```
+
+ Instead of writing the above, your code now simply becomes the following:
+
+ ```javascript
+ var promise = Promise.resolve(1);
+
+ promise.then(function(value){
+ // value === 1
+ });
+ ```
+
+ @method resolve
+ @static
+ @param {Any} value value that the returned promise will be resolved with
+ Useful for tooling.
+ @return {Promise} a promise that will become fulfilled with the given
+ `value`
+*/
+export default function resolve(object) {
+ /*jshint validthis:true */
+ var Constructor = this;
+
+ if (object && typeof object === 'object' && object.constructor === Constructor) {
+ return object;
+ }
+
+ var promise = new Constructor(noop);
+ _resolve(promise, object);
+ return promise;
+}
diff --git a/lib/es6-promise/utils.js b/lib/es6-promise/utils.js
new file mode 100644
index 0000000..31ec6f9
--- /dev/null
+++ b/lib/es6-promise/utils.js
@@ -0,0 +1,22 @@
+export function objectOrFunction(x) {
+ return typeof x === 'function' || (typeof x === 'object' && x !== null);
+}
+
+export function isFunction(x) {
+ return typeof x === 'function';
+}
+
+export function isMaybeThenable(x) {
+ return typeof x === 'object' && x !== null;
+}
+
+var _isArray;
+if (!Array.isArray) {
+ _isArray = function (x) {
+ return Object.prototype.toString.call(x) === '[object Array]';
+ };
+} else {
+ _isArray = Array.isArray;
+}
+
+export var isArray = _isArray;
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..920d501
--- /dev/null
+++ b/package.json
@@ -0,0 +1,64 @@
+{
+ "name": "es6-promise",
+ "namespace": "es6-promise",
+ "version": "3.0.2",
+ "description": "A lightweight library that provides tools for organizing asynchronous code",
+ "main": "dist/es6-promise.js",
+ "directories": {
+ "lib": "lib"
+ },
+ "files": [
+ "dist",
+ "lib",
+ "!dist/test"
+ ],
+ "devDependencies": {
+ "bower": "^1.3.9",
+ "brfs": "0.0.8",
+ "broccoli-es3-safe-recast": "0.0.8",
+ "broccoli-es6-module-transpiler": "^0.5.0",
+ "broccoli-jshint": "^0.5.1",
+ "broccoli-merge-trees": "^0.1.4",
+ "broccoli-replace": "^0.2.0",
+ "broccoli-stew": "0.0.6",
+ "broccoli-uglify-js": "^0.1.3",
+ "broccoli-watchify": "^0.2.0",
+ "ember-cli": "0.2.3",
+ "ember-publisher": "0.0.7",
+ "git-repo-version": "0.0.2",
+ "json3": "^3.3.2",
+ "minimatch": "^2.0.1",
+ "mocha": "^1.20.1",
+ "promises-aplus-tests-phantom": "^2.1.0-revise",
+ "release-it": "0.0.10"
+ },
+ "scripts": {
+ "build": "ember build",
+ "start": "ember s",
+ "test": "ember test",
+ "test:server": "ember test --server",
+ "test:node": "ember build && mocha ./dist/test/browserify",
+ "lint": "jshint lib",
+ "prepublish": "ember build --environment production",
+ "dry-run-release": "ember build --environment production && release-it --dry-run --non-interactive"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/jakearchibald/ES6-Promises.git"
+ },
+ "bugs": {
+ "url": "https://github.com/jakearchibald/ES6-Promises/issues"
+ },
+ "browser": {
+ "vertx": false
+ },
+ "keywords": [
+ "promises",
+ "futures"
+ ],
+ "author": "Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)",
+ "license": "MIT",
+ "spm": {
+ "main": "dist/es6-promise.js"
+ }
+}
diff --git a/server/.jshintrc b/server/.jshintrc
new file mode 100644
index 0000000..c1f2978
--- /dev/null
+++ b/server/.jshintrc
@@ -0,0 +1,3 @@
+{
+ "node": true
+}
diff --git a/server/index.js b/server/index.js
new file mode 100644
index 0000000..8681f28
--- /dev/null
+++ b/server/index.js
@@ -0,0 +1,5 @@
+module.exports = function(app) {
+ app.get('/', function(req, res) {
+ res.redirect('/test/');
+ })
+};
diff --git a/test/extension-test.js b/test/extension-test.js
new file mode 100644
index 0000000..51bd242
--- /dev/null
+++ b/test/extension-test.js
@@ -0,0 +1,986 @@
+/*global describe, specify, it, assert */
+
+if (typeof Object.getPrototypeOf !== "function") {
+ Object.getPrototypeOf = "".__proto__ === String.prototype
+ ? function (object) {
+ return object.__proto__;
+ }
+ : function (object) {
+ // May break if the constructor has been tampered with
+ return object.constructor.prototype;
+ };
+}
+
+function keysOf(object) {
+ var results = [];
+
+ for (var key in object) {
+ if (object.hasOwnProperty(key)) {
+ results.push(key);
+ }
+ }
+
+ return results;
+}
+
+var g = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : this;
+var Promise = g.adapter.Promise;
+var assert = require('assert');
+
+function objectEquals(obj1, obj2) {
+ for (var i in obj1) {
+ if (obj1.hasOwnProperty(i)) {
+ if (!obj2.hasOwnProperty(i)) return false;
+ if (obj1[i] != obj2[i]) return false;
+ }
+ }
+ for (var i in obj2) {
+ if (obj2.hasOwnProperty(i)) {
+ if (!obj1.hasOwnProperty(i)) return false;
+ if (obj1[i] != obj2[i]) return false;
+ }
+ }
+ return true;
+}
+
+describe("extensions", function() {
+ describe("Promise constructor", function() {
+ it('should exist and have length 1', function() {
+ assert(Promise);
+ assert.equal(Promise.length, 1);
+ });
+
+ it('should fulfill if `resolve` is called with a value', function(done) {
+ var promise = new Promise(function(resolve) { resolve('value'); });
+
+ promise.then(function(value) {
+ assert.equal(value, 'value');
+ done();
+ });
+ });
+
+ it('should reject if `reject` is called with a reason', function(done) {
+ var promise = new Promise(function(resolve, reject) { reject('reason'); });
+
+ promise.then(function() {
+ assert(false);
+ done();
+ }, function(reason) {
+ assert.equal(reason, 'reason');
+ done();
+ });
+ });
+
+ it('should be a constructor', function() {
+ var promise = new Promise(function() {});
+
+ assert.equal(Object.getPrototypeOf(promise), Promise.prototype, '[[Prototype]] equals Promise.prototype');
+ assert.equal(promise.constructor, Promise, 'constructor property of instances is set correctly');
+ assert.equal(Promise.prototype.constructor, Promise, 'constructor property of prototype is set correctly');
+ });
+
+ it('should NOT work without `new`', function() {
+ assert.throws(function(){
+ Promise(function(resolve) { resolve('value'); });
+ }, TypeError)
+ });
+
+ it('should throw a `TypeError` if not given a function', function() {
+ assert.throws(function () {
+ new Promise();
+ }, TypeError);
+
+ assert.throws(function () {
+ new Promise({});
+ }, TypeError);
+
+ assert.throws(function () {
+ new Promise('boo!');
+ }, TypeError);
+ });
+
+ it('should reject on resolver exception', function(done) {
+ new Promise(function() {
+ throw 'error';
+ }).then(null, function(e) {
+ assert.equal(e, 'error');
+ done();
+ });
+ });
+
+ it('should not resolve multiple times', function(done) {
+ var resolver, rejector, fulfilled = 0, rejected = 0;
+ var thenable = {
+ then: function(resolve, reject) {
+ resolver = resolve;
+ rejector = reject;
+ }
+ };
+
+ var promise = new Promise(function(resolve) {
+ resolve(1);
+ });
+
+ promise.then(function(value){
+ return thenable;
+ }).then(function(value){
+ fulfilled++;
+ }, function(reason) {
+ rejected++;
+ });
+
+ setTimeout(function() {
+ resolver(1);
+ resolver(1);
+ rejector(1);
+ rejector(1);
+
+ setTimeout(function() {
+ assert.equal(fulfilled, 1);
+ assert.equal(rejected, 0);
+ done();
+ }, 20);
+ }, 20);
+
+ });
+
+ describe('assimilation', function() {
+ it('should assimilate if `resolve` is called with a fulfilled promise', function(done) {
+ var originalPromise = new Promise(function(resolve) { resolve('original value'); });
+ var promise = new Promise(function(resolve) { resolve(originalPromise); });
+
+ promise.then(function(value) {
+ assert.equal(value, 'original value');
+ done();
+ });
+ });
+
+ it('should assimilate if `resolve` is called with a rejected promise', function(done) {
+ var originalPromise = new Promise(function(resolve, reject) { reject('original reason'); });
+ var promise = new Promise(function(resolve) { resolve(originalPromise); });
+
+ promise.then(function() {
+ assert(false);
+ done();
+ }, function(reason) {
+ assert.equal(reason, 'original reason');
+ done();
+ });
+ });
+
+ it('should assimilate if `resolve` is called with a fulfilled thenable', function(done) {
+ var originalThenable = {
+ then: function (onFulfilled) {
+ setTimeout(function() { onFulfilled('original value'); }, 0);
+ }
+ };
+ var promise = new Promise(function(resolve) { resolve(originalThenable); });
+
+ promise.then(function(value) {
+ assert.equal(value, 'original value');
+ done();
+ });
+ });
+
+ it('should assimilate if `resolve` is called with a rejected thenable', function(done) {
+ var originalThenable = {
+ then: function (onFulfilled, onRejected) {
+ setTimeout(function() { onRejected('original reason'); }, 0);
+ }
+ };
+ var promise = new Promise(function(resolve) { resolve(originalThenable); });
+
+ promise.then(function() {
+ assert(false);
+ done();
+ }, function(reason) {
+ assert.equal(reason, 'original reason');
+ done();
+ });
+ });
+
+
+ it('should assimilate two levels deep, for fulfillment of self fulfilling promises', function(done) {
+ var originalPromise, promise;
+ originalPromise = new Promise(function(resolve) {
+ setTimeout(function() {
+ resolve(originalPromise);
+ }, 0)
+ });
+
+ promise = new Promise(function(resolve) {
+ setTimeout(function() {
+ resolve(originalPromise);
+ }, 0);
+ });
+
+ promise.then(function(value) {
+ assert(false);
+ done();
+ })['catch'](function(reason) {
+ assert.equal(reason.message, "You cannot resolve a promise with itself");
+ assert(reason instanceof TypeError);
+ done();
+ });
+ });
+
+ it('should assimilate two levels deep, for fulfillment', function(done) {
+ var originalPromise = new Promise(function(resolve) { resolve('original value'); });
+ var nextPromise = new Promise(function(resolve) { resolve(originalPromise); });
+ var promise = new Promise(function(resolve) { resolve(nextPromise); });
+
+ promise.then(function(value) {
+ assert.equal(value, 'original value');
+ done();
+ });
+ });
+
+ it('should assimilate two levels deep, for rejection', function(done) {
+ var originalPromise = new Promise(function(resolve, reject) { reject('original reason'); });
+ var nextPromise = new Promise(function(resolve) { resolve(originalPromise); });
+ var promise = new Promise(function(resolve) { resolve(nextPromise); });
+
+ promise.then(function() {
+ assert(false);
+ done();
+ }, function(reason) {
+ assert.equal(reason, 'original reason');
+ done();
+ });
+ });
+
+ it('should assimilate three levels deep, mixing thenables and promises (fulfilled case)', function(done) {
+ var originalPromise = new Promise(function(resolve) { resolve('original value'); });
+ var intermediateThenable = {
+ then: function (onFulfilled) {
+ setTimeout(function() { onFulfilled(originalPromise); }, 0);
+ }
+ };
+ var promise = new Promise(function(resolve) { resolve(intermediateThenable); });
+
+ promise.then(function(value) {
+ assert.equal(value, 'original value');
+ done();
+ });
+ });
+
+ it('should assimilate three levels deep, mixing thenables and promises (rejected case)', function(done) {
+ var originalPromise = new Promise(function(resolve, reject) { reject('original reason'); });
+ var intermediateThenable = {
+ then: function (onFulfilled) {
+ setTimeout(function() { onFulfilled(originalPromise); }, 0);
+ }
+ };
+ var promise = new Promise(function(resolve) { resolve(intermediateThenable); });
+
+ promise.then(function() {
+ assert(false);
+ done();
+ }, function(reason) {
+ assert.equal(reason, 'original reason');
+ done();
+ });
+ });
+ });
+ });
+
+ describe("Promise.all", function() {
+ testAll(function(){
+ return Promise.all.apply(Promise, arguments);
+ });
+ });
+
+ function testAll(all) {
+ it('should exist', function() {
+ assert(all);
+ });
+
+ it('throws when not passed an array', function(done) {
+ var nothing = assertRejection(all());
+ var string = assertRejection(all(''));
+ var object = assertRejection(all({}));
+
+ Promise.all([
+ nothing,
+ string,
+ object
+ ]).then(function(){ done(); });
+ });
+
+ specify('fulfilled only after all of the other promises are fulfilled', function(done) {
+ var firstResolved, secondResolved, firstResolver, secondResolver;
+
+ var first = new Promise(function(resolve) {
+ firstResolver = resolve;
+ });
+ first.then(function() {
+ firstResolved = true;
+ });
+
+ var second = new Promise(function(resolve) {
+ secondResolver = resolve;
+ });
+ second.then(function() {
+ secondResolved = true;
+ });
+
+ setTimeout(function() {
+ firstResolver(true);
+ }, 0);
+
+ setTimeout(function() {
+ secondResolver(true);
+ }, 0);
+
+ all([first, second]).then(function() {
+ assert(firstResolved);
+ assert(secondResolved);
+ done();
+ });
+ });
+
+ specify('rejected as soon as a promise is rejected', function(done) {
+ var firstResolver, secondResolver;
+
+ var first = new Promise(function(resolve, reject) {
+ firstResolver = { resolve: resolve, reject: reject };
+ });
+
+ var second = new Promise(function(resolve, reject) {
+ secondResolver = { resolve: resolve, reject: reject };
+ });
+
+ setTimeout(function() {
+ firstResolver.reject({});
+ }, 0);
+
+ var firstWasRejected, secondCompleted;
+
+ first['catch'](function(){
+ firstWasRejected = true;
+ });
+
+ second.then(function(){
+ secondCompleted = true;
+ }, function() {
+ secondCompleted = true;
+ });
+
+ all([first, second]).then(function() {
+ assert(false);
+ }, function() {
+ assert(firstWasRejected);
+ assert(!secondCompleted);
+ done();
+ });
+ });
+
+ specify('passes the resolved values of each promise to the callback in the correct order', function(done) {
+ var firstResolver, secondResolver, thirdResolver;
+
+ var first = new Promise(function(resolve, reject) {
+ firstResolver = { resolve: resolve, reject: reject };
+ });
+
+ var second = new Promise(function(resolve, reject) {
+ secondResolver = { resolve: resolve, reject: reject };
+ });
+
+ var third = new Promise(function(resolve, reject) {
+ thirdResolver = { resolve: resolve, reject: reject };
+ });
+
+ thirdResolver.resolve(3);
+ firstResolver.resolve(1);
+ secondResolver.resolve(2);
+
+ all([first, second, third]).then(function(results) {
+ assert(results.length === 3);
+ assert(results[0] === 1);
+ assert(results[1] === 2);
+ assert(results[2] === 3);
+ done();
+ });
+ });
+
+ specify('resolves an empty array passed to all()', function(done) {
+ all([]).then(function(results) {
+ assert(results.length === 0);
+ done();
+ });
+ });
+
+ specify('works with null', function(done) {
+ all([null]).then(function(results) {
+ assert.equal(results[0], null);
+ done();
+ });
+ });
+
+ specify('works with a mix of promises and thenables and non-promises', function(done) {
+ var promise = new Promise(function(resolve) { resolve(1); });
+ var syncThenable = { then: function (onFulfilled) { onFulfilled(2); } };
+ var asyncThenable = { then: function (onFulfilled) { setTimeout(function() { onFulfilled(3); }, 0); } };
+ var nonPromise = 4;
+
+ all([promise, syncThenable, asyncThenable, nonPromise]).then(function(results) {
+ assert(objectEquals(results, [1, 2, 3, 4]));
+ done();
+ })['catch'](done);
+ });
+ }
+
+ describe("reject", function(){
+ specify("it should exist", function(){
+ assert(Promise.reject);
+ });
+
+ describe('it rejects', function(){
+ var reason = 'the reason',
+ promise = Promise.reject(reason);
+
+ promise.then(function(){
+ assert(false, 'should not fulfill');
+ }, function(actualReason){
+ assert.equal(reason, actualReason);
+ });
+ });
+ });
+
+ function assertRejection(promise) {
+ return promise.then(function(){
+ assert(false, 'expected rejection, but got fulfillment');
+ }, function(reason){
+ assert(reason instanceof Error);
+ });
+ }
+
+ describe('race', function() {
+ it("should exist", function() {
+ assert(Promise.race);
+ });
+
+ it("throws when not passed an array", function(done) {
+ var nothing = assertRejection(Promise.race());
+ var string = assertRejection(Promise.race(''));
+ var object = assertRejection(Promise.race({}));
+
+ Promise.all([
+ nothing,
+ string,
+ object
+ ]).then(function(){ done(); });
+ });
+
+ specify('fulfilled after one of the other promises are fulfilled', function(done) {
+ var firstResolved, secondResolved, firstResolver, secondResolver;
+
+ var first = new Promise(function(resolve) {
+ firstResolver = resolve;
+ });
+ first.then(function() {
+ firstResolved = true;
+ });
+
+ var second = new Promise(function(resolve) {
+ secondResolver = resolve;
+ });
+ second.then(function() {
+ secondResolved = true;
+ });
+
+ setTimeout(function() {
+ firstResolver(true);
+ }, 100);
+
+ setTimeout(function() {
+ secondResolver(true);
+ }, 0);
+
+ Promise.race([first, second]).then(function() {
+ assert(secondResolved);
+ assert.equal(firstResolved, undefined);
+ done();
+ });
+ });
+
+ specify('the race begins on nextTurn and prioritized by array entry', function(done) {
+ var firstResolver, secondResolver, nonPromise = 5;
+
+ var first = new Promise(function(resolve, reject) {
+ resolve(true);
+ });
+
+ var second = new Promise(function(resolve, reject) {
+ resolve(false);
+ });
+
+ Promise.race([first, second, nonPromise]).then(function(value) {
+ assert.equal(value, true);
+ done();
+ });
+ });
+
+ specify('rejected as soon as a promise is rejected', function(done) {
+ var firstResolver, secondResolver;
+
+ var first = new Promise(function(resolve, reject) {
+ firstResolver = { resolve: resolve, reject: reject };
+ });
+
+ var second = new Promise(function(resolve, reject) {
+ secondResolver = { resolve: resolve, reject: reject };
+ });
+
+ setTimeout(function() {
+ firstResolver.reject({});
+ }, 0);
+
+ var firstWasRejected, secondCompleted;
+
+ first['catch'](function(){
+ firstWasRejected = true;
+ });
+
+ second.then(function(){
+ secondCompleted = true;
+ }, function() {
+ secondCompleted = true;
+ });
+
+ Promise.race([first, second]).then(function() {
+ assert(false);
+ }, function() {
+ assert(firstWasRejected);
+ assert(!secondCompleted);
+ done();
+ });
+ });
+
+ specify('resolves an empty array to forever pending Promise', function(done) {
+ var foreverPendingPromise = Promise.race([]),
+ wasSettled = false;
+
+ foreverPendingPromise.then(function() {
+ wasSettled = true;
+ }, function() {
+ wasSettled = true;
+ });
+
+ setTimeout(function() {
+ assert(!wasSettled);
+ done();
+ }, 50);
+ });
+
+ specify('works with a mix of promises and thenables', function(done) {
+ var promise = new Promise(function(resolve) { setTimeout(function() { resolve(1); }, 10); }),
+ syncThenable = { then: function (onFulfilled) { onFulfilled(2); } };
+
+ Promise.race([promise, syncThenable]).then(function(result) {
+ assert(result, 2);
+ done();
+ });
+ });
+
+ specify('works with a mix of thenables and non-promises', function (done) {
+ var asyncThenable = { then: function (onFulfilled) { setTimeout(function() { onFulfilled(3); }, 0); } },
+ nonPromise = 4;
+
+ Promise.race([asyncThenable, nonPromise]).then(function(result) {
+ assert(result, 4);
+ done();
+ });
+ });
+ });
+
+ describe("resolve", function(){
+ specify("it should exist", function(){
+ assert(Promise.resolve);
+ });
+
+ describe("1. If x is a promise, adopt its state ", function(){
+ specify("1.1 If x is pending, promise must remain pending until x is fulfilled or rejected.", function(done){
+ var expectedValue, resolver, thenable, wrapped;
+
+ expectedValue = 'the value';
+ thenable = {
+ then: function(resolve, reject){
+ resolver = resolve;
+ }
+ };
+
+ wrapped = Promise.resolve(thenable);
+
+ wrapped.then(function(value){
+ assert(value === expectedValue);
+ done();
+ });
+
+ setTimeout(function(){
+ resolver(expectedValue);
+ }, 10);
+ });
+
+ specify("1.2 If/when x is fulfilled, fulfill promise with the same value.", function(done){
+ var expectedValue, thenable, wrapped;
+
+ expectedValue = 'the value';
+ thenable = {
+ then: function(resolve, reject){
+ resolve(expectedValue);
+ }
+ };
+
+ wrapped = Promise.resolve(thenable);
+
+ wrapped.then(function(value){
+ assert(value === expectedValue);
+ done();
+ })
+ });
+
+ specify("1.3 If/when x is rejected, reject promise with the same reason.", function(done){
+ var expectedError, thenable, wrapped;
+
+ expectedError = new Error();
+ thenable = {
+ then: function(resolve, reject){
+ reject(expectedError);
+ }
+ };
+
+ wrapped = Promise.resolve(thenable);
+
+ wrapped.then(null, function(error){
+ assert(error === expectedError);
+ done();
+ });
+ });
+ });
+
+ describe("2. Otherwise, if x is an object or function,", function(){
+ specify("2.1 Let then x.then", function(done){
+ var accessCount, resolver, wrapped, thenable;
+
+ accessCount = 0;
+ thenable = { };
+
+ // we likely don't need to test this, if the browser doesn't support it
+ if (typeof Object.defineProperty !== "function") { done(); return; }
+
+ Object.defineProperty(thenable, 'then', {
+ get: function(){
+ accessCount++;
+
+ if (accessCount > 1) {
+ throw new Error();
+ }
+
+ return function(){ };
+ }
+ });
+
+ assert(accessCount === 0);
+
+ wrapped = Promise.resolve(thenable);
+
+ assert(accessCount === 1);
+
+ done();
+ });
+
+ specify("2.2 If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason.", function(done){
+ var wrapped, thenable, expectedError;
+
+ expectedError = new Error();
+ thenable = { };
+
+ // we likely don't need to test this, if the browser doesn't support it
+ if (typeof Object.defineProperty !== "function") { done(); return; }
+
+ Object.defineProperty(thenable, 'then', {
+ get: function(){
+ throw expectedError;
+ }
+ });
+
+ wrapped = Promise.resolve(thenable);
+
+ wrapped.then(null, function(error){
+ assert(error === expectedError, 'incorrect exception was thrown');
+ done();
+ });
+ });
+
+ describe('2.3. If then is a function, call it with x as this, first argument resolvePromise, and second argument rejectPromise, where', function(){
+ specify('2.3.1 If/when resolvePromise is called with a value y, run Resolve(promise, y)', function(done){
+ var expectedSuccess, resolver, rejector, thenable, wrapped, calledThis;
+
+ thenable = {
+ then: function(resolve, reject){
+ calledThis = this;
+ resolver = resolve;
+ rejector = reject;
+ }
+ };
+
+ expectedSuccess = 'success';
+ wrapped = Promise.resolve(thenable);
+
+ wrapped.then(function(success){
+ assert(calledThis === thenable, 'this must be the thenable');
+ assert(success === expectedSuccess, 'rejected promise with x');
+ done();
+ });
+
+ setTimeout(function() {
+ resolver(expectedSuccess);
+ }, 20);
+ });
+
+ specify('2.3.2 If/when rejectPromise is called with a reason r, reject promise with r.', function(done){
+ var expectedError, resolver, rejector, thenable, wrapped, calledThis;
+
+ thenable = {
+ then: function(resolve, reject){
+ calledThis = this;
+ resolver = resolve;
+ rejector = reject;
+ }
+ };
+
+ expectedError = new Error();
+
+ wrapped = Promise.resolve(thenable);
+
+ wrapped.then(null, function(error){
+ assert(error === expectedError, 'rejected promise with x');
+ done();
+ });
+
+ setTimeout(function() {
+ rejector(expectedError);
+ }, 20);
+ });
+
+ specify("2.3.3 If both resolvePromise and rejectPromise are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored", function(done){
+ var expectedError, expectedSuccess, resolver, rejector, thenable, wrapped, calledThis,
+ calledRejected, calledResolved;
+
+ calledRejected = 0;
+ calledResolved = 0;
+
+ thenable = {
+ then: function(resolve, reject){
+ calledThis = this;
+ resolver = resolve;
+ rejector = reject;
+ }
+ };
+
+ expectedError = new Error();
+
+ wrapped = Promise.resolve(thenable);
+
+ wrapped.then(function(){
+ calledResolved++;
+ }, function(error){
+ calledRejected++;
+ assert(calledResolved === 0, 'never resolved');
+ assert(calledRejected === 1, 'rejected only once');
+ assert(error === expectedError, 'rejected promise with x');
+ });
+
+ setTimeout(function() {
+ rejector(expectedError);
+ rejector(expectedError);
+
+ rejector('foo');
+
+ resolver('bar');
+ resolver('baz');
+ }, 20);
+
+ setTimeout(function(){
+ assert(calledRejected === 1, 'only rejected once');
+ assert(calledResolved === 0, 'never resolved');
+ done();
+ }, 50);
+ });
+
+ describe("2.3.4 If calling then throws an exception e", function(){
+ specify("2.3.4.1 If resolvePromise or rejectPromise have been called, ignore it.", function(done){
+ var expectedSuccess, resolver, rejector, thenable, wrapped, calledThis,
+ calledRejected, calledResolved;
+
+ expectedSuccess = 'success';
+
+ thenable = {
+ then: function(resolve, reject){
+ resolve(expectedSuccess);
+ throw expectedError;
+ }
+ };
+
+ wrapped = Promise.resolve(thenable);
+
+ wrapped.then(function(success){
+ assert(success === expectedSuccess, 'resolved not errored');
+ done();
+ });
+ });
+
+ specify("2.3.4.2 Otherwise, reject promise with e as the reason.", function(done) {
+ var expectedError, resolver, rejector, thenable, wrapped, calledThis, callCount;
+
+ expectedError = new Error();
+ callCount = 0;
+
+ thenable = { then: function() { throw expectedError; } };
+
+ wrapped = Promise.resolve(thenable);
+
+ wrapped.then(null, function(error){
+ callCount++;
+ assert(expectedError === error, 'expected the correct error to be rejected');
+ done();
+ });
+
+ assert(callCount === 0, 'expected async, was sync');
+ });
+ });
+ });
+
+ specify("2.4 If then is not a function, fulfill promise with x", function(done){
+ var expectedError, resolver, rejector, thenable, wrapped, calledThis, callCount;
+
+ thenable = { then: 3 };
+ callCount = 0;
+ wrapped = Promise.resolve(thenable);
+
+ wrapped.then(function(success){
+ callCount++;
+ assert(thenable === success, 'fulfilled promise with x');
+ done();
+ });
+
+ assert(callCount === 0, 'expected async, was sync');
+ });
+ });
+
+ describe("3. If x is not an object or function, ", function(){
+ specify("fulfill promise with x.", function(done){
+ var thenable, callCount, wrapped;
+
+ thenable = null;
+ callCount = 0;
+ wrapped = Promise.resolve(thenable);
+
+ wrapped.then(function(success){
+ callCount++;
+ assert(success === thenable, 'fulfilled promise with x');
+ done();
+ }, function(a){
+ assert(false, 'should not also reject');
+ });
+
+ assert(callCount === 0, 'expected async, was sync');
+ });
+ });
+ });
+
+ if (typeof Worker !== 'undefined') {
+ describe('web worker', function () {
+ it('should work', function (done) {
+ this.timeout(2000);
+ var worker = new Worker('worker.js');
+ worker.addEventListener('error', function(reason) {
+ done(new Error("Test failed:" + reason));
+ });
+ worker.addEventListener('message', function (e) {
+ worker.terminate();
+ assert.equal(e.data, 'pong');
+ done();
+ });
+ worker.postMessage('ping');
+ });
+ });
+ }
+});
+
+// thanks to @wizardwerdna for the test case -> https://github.com/tildeio/rsvp.js/issues/66
+// Only run these tests in node (phantomjs cannot handle them)
+if (typeof module !== 'undefined' && module.exports) {
+
+ describe("using reduce to sum integers using promises", function(){
+ it("should build the promise pipeline without error", function(){
+ var array, iters, pZero, i;
+
+ array = [];
+ iters = 1000;
+
+ for (i=1; i<=iters; i++) {
+ array.push(i);
+ }
+
+ pZero = Promise.resolve(0);
+
+ array.reduce(function(promise, nextVal) {
+ return promise.then(function(currentVal) {
+ return Promise.resolve(currentVal + nextVal);
+ });
+ }, pZero);
+ });
+
+ it("should get correct answer without blowing the nextTick stack", function(done){
+ var pZero, array, iters, result, i;
+
+ pZero = Promise.resolve(0);
+
+ array = [];
+ iters = 1000;
+
+ for (i=1; i<=iters; i++) {
+ array.push(i);
+ }
+
+ result = array.reduce(function(promise, nextVal) {
+ return promise.then(function(currentVal) {
+ return Promise.resolve(currentVal + nextVal);
+ });
+ }, pZero);
+
+ result.then(function(value){
+ assert.equal(value, (iters*(iters+1)/2));
+ done();
+ });
+ });
+ });
+}
+
+// Kudos to @Octane at https://github.com/getify/native-promise-only/issues/5 for this, and @getify for pinging me.
+describe("Thenables should not be able to run code during assimilation", function () {
+ specify("resolving to a thenable", function () {
+ var thenCalled = false;
+ var thenable = {
+ then: function () {
+ thenCalled = true;
+ }
+ };
+
+ Promise.resolve(thenable);
+ assert.strictEqual(thenCalled, false);
+ });
+
+ specify("resolving to an evil promise", function () {
+ var thenCalled = false;
+ var evilPromise = Promise.resolve();
+ evilPromise.then = function () {
+ thenCalled = true;
+ };
+
+ Promise.resolve(evilPromise);
+ assert.strictEqual(thenCalled, false);
+ });
+});
diff --git a/test/index.html b/test/index.html
new file mode 100644
index 0000000..de6bf1b
--- /dev/null
+++ b/test/index.html
@@ -0,0 +1,25 @@
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>rsvp.js Tests</title>
+ <link rel="stylesheet" href="mocha.css" />
+</head>
+<body>
+ <div id="mocha"></div>
+ <script src="json3.js"></script>
+ <script src="mocha.js"></script>
+ <script src="/testem.js"></script>
+ <script>
+ mocha.setup({
+ ui: 'bdd',
+ timeout: 200,
+ ignoreLeaks: true
+ });
+ </script>
+ <script src="browserify.js"></script>
+ <script>
+ if (window.mochaPhantomJS) { mochaPhantomJS.run(); }
+ else { mocha.run(); }
+ </script>
+</body>
+</html>
diff --git a/test/index.js b/test/index.js
new file mode 100644
index 0000000..b2c0152
--- /dev/null
+++ b/test/index.js
@@ -0,0 +1,4 @@
+require('./test-adapter.js');
+require('./scheduler-test.js');
+require('./extension-test.js');
+require('promises-aplus-tests-phantom/lib/testFiles');
diff --git a/test/scheduler-test.js b/test/scheduler-test.js
new file mode 100644
index 0000000..59bf586
--- /dev/null
+++ b/test/scheduler-test.js
@@ -0,0 +1,76 @@
+/*global describe, it, assert */
+
+var g = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : this;
+var Promise = g.adapter.Promise;
+var assert = require('assert');
+
+describe('scheduler', function() {
+ afterEach(function() {
+ // make sure the es6-promise scheduler is restored after each test
+ Promise._setScheduler(void 0);
+ });
+
+ describe('Promise._setScheduler', function() {
+ it('should allow overriding the default scheduling mechanism', function(done) {
+ // Wrapped in a setTimeout() to make sure that the microtask queue is empty
+ // Otherwise we would have len > 2 and the overriden scheduling mechanism would not
+ // be used.
+ // This is required because the test library uses Promise.
+ setTimeout(function() {
+ var microtasks = [];
+ var resolvedWith = null;
+
+ Promise._setScheduler(function(fn) {
+ microtasks.push(fn);
+ });
+
+ Promise.resolve('value').then(function(v) {
+ resolvedWith = v;
+ });
+
+ assert.equal(resolvedWith, null);
+ assert.equal(microtasks.length, 1);
+
+ while (microtasks.length) {
+ microtasks.shift()();
+ }
+
+ assert.equal(resolvedWith, 'value');
+
+ // restore the original scheduler
+ Promise._setScheduler(void 0);
+ done();
+ });
+ });
+ });
+
+ describe('Promise._asap', function() {
+ it('should allow enqueuing microtasks', function(done) {
+ Promise._asap(function(arg) {
+ assert.equal(arg, 'arg');
+ done();
+ }, 'arg');
+ });
+ });
+
+ describe('Promise._setAsap', function() {
+ it('should allow overriding asap', function(done) {
+ var called = false;
+
+ Promise._setAsap(function(fn, arg) {
+ called = true;
+ // call the original implementation
+ Promise._asap(fn, arg);
+ // restore the original implementation
+ Promise._setAsap(Promise._asap);
+ });
+
+ Promise.resolve('value').then(function(v) {
+ resolvedWith = v;
+ assert.equal(v, 'value');
+ assert.equal(called, true);
+ done();
+ });
+ });
+ });
+});
diff --git a/test/test-adapter.js b/test/test-adapter.js
new file mode 100644
index 0000000..9fe3f45
--- /dev/null
+++ b/test/test-adapter.js
@@ -0,0 +1,26 @@
+var assert = require('assert');
+var g = typeof window !== 'undefined' ?
+ window : typeof global !== 'undefined' ? global : this;
+
+var Promise = g.ES6Promise || require('./es6-promise').Promise;
+
+function defer() {
+ var deferred = {};
+
+ deferred.promise = new Promise(function(resolve, reject) {
+ deferred.resolve = resolve;
+ deferred.reject = reject;
+ });
+
+ return deferred;
+}
+var resolve = Promise.resolve;
+var reject = Promise.reject;
+
+
+module.exports = g.adapter = {
+ resolved: function(a) { return Promise.resolve(a); },
+ rejected: function(a) { return Promise.reject(a); },
+ deferred: defer,
+ Promise: Promise
+};
diff --git a/test/worker.js b/test/worker.js
new file mode 100644
index 0000000..7ad9f8a
--- /dev/null
+++ b/test/worker.js
@@ -0,0 +1,16 @@
+importScripts('es6-promise.js');
+new ES6Promise.Promise(function(resolve, reject) {
+ self.onmessage = function (e) {
+ if (e.data === 'ping') {
+ resolve('pong');
+ } else {
+ reject(new Error('wrong message'));
+ }
+ };
+}).then(function (result) {
+ self.postMessage(result);
+}, function (err){
+ setTimeout(function () {
+ throw err;
+ });
+});
diff --git a/testem.json b/testem.json
new file mode 100644
index 0000000..89d25be
--- /dev/null
+++ b/testem.json
@@ -0,0 +1,14 @@
+{
+ "test_page": "test/index.html",
+ "parallel": 5,
+ "frameworks": "mocha",
+ "launchers": {
+ "Mocha": {
+ "command": "./node_modules/.bin/mocha dist/test/browserify.js"
+ }
+ },
+ "launch_in_ci": [
+ "PhantomJS",
+ "Mocha"
+ ]
+}
diff --git a/vendor/loader.js b/vendor/loader.js
new file mode 100644
index 0000000..54d178b
--- /dev/null
+++ b/vendor/loader.js
@@ -0,0 +1,53 @@
+var define, requireModule, require, requirejs;
+
+(function() {
+ var registry = {}, seen = {};
+
+ define = function(name, deps, callback) {
+ registry[name] = { deps: deps, callback: callback };
+ };
+
+ requirejs = require = requireModule = function(name) {
+ requirejs._eak_seen = registry;
+
+ if (seen[name]) { return seen[name]; }
+ seen[name] = {};
+
+ if (!registry[name]) {
+ throw new Error("Could not find module " + name);
+ }
+
+ var mod = registry[name],
+ deps = mod.deps,
+ callback = mod.callback,
+ reified = [],
+ exports;
+
+ for (var i=0, l=deps.length; i<l; i++) {
+ if (deps[i] === 'exports') {
+ reified.push(exports = {});
+ } else {
+ reified.push(requireModule(resolve(deps[i])));
+ }
+ }
+
+ var value = callback.apply(this, reified);
+ return seen[name] = exports || value;
+
+ function resolve(child) {
+ if (child.charAt(0) !== '.') { return child; }
+ var parts = child.split("/");
+ var parentBase = name.split("/").slice(0, -1);
+
+ for (var i=0, l=parts.length; i<l; i++) {
+ var part = parts[i];
+
+ if (part === '..') { parentBase.pop(); }
+ else if (part === '.') { continue; }
+ else { parentBase.push(part); }
+ }
+
+ return parentBase.join("/");
+ }
+ };
+})();
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-es6-promise.git
More information about the Pkg-javascript-commits
mailing list