[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