Use native promise implementation if one is available, otherwise
es6-promise polyfill.

Change-Id: I41919aab18e68370d250a77cfba7f53a8f61f8be
diff --git a/package.json b/package.json
index ad5da87..a9421c3 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,6 @@
   "version": "0.1.0",
   "main": "./src/vanadium",
   "dependencies": {
-    "bluebird": "^2.3.2",
     "is-browser": "^2.0.1",
     "ws": "~0.4.31",
     "xtend": "^4.0.0",
@@ -15,7 +14,8 @@
     "inherits": "~2.0.1",
     "format": "~0.2.1",
     "randombytes": "~2.0.1",
-    "domready": "~1.0.7"
+    "domready": "~1.0.7",
+    "es6-promise": "~2.1.1"
   },
   "devDependencies": {
     "node-static": "^0.7.4",
diff --git a/src/lib/deferred.js b/src/lib/deferred.js
index a11171d..68ead13 100644
--- a/src/lib/deferred.js
+++ b/src/lib/deferred.js
@@ -27,17 +27,20 @@
 
 function addCallback(promise, cb) {
   if (cb) {
-    // Note, this must be a .done() and not a .then().  Errors thrown inside of
-    // a .then() callback are wrapped in a try/catch, whereas errors thrown
-    // inside of a .done() callback will be thrown as an error.
-    promise.done(
+    promise.then(
       function success(value) {
         cb(null, value);
       },
       function error(err) {
         cb(err);
       }
-    );
+    ).catch(function catchError(err) {
+      // Re-throw the error in a process.nextTick so that it won't be caught by
+      // the promise implementation.
+      process.nextTick(function() {
+        throw err;
+      });
+    });
   }
 }
 
diff --git a/src/lib/promise.js b/src/lib/promise.js
index fce522d..ccdecd4 100644
--- a/src/lib/promise.js
+++ b/src/lib/promise.js
@@ -5,23 +5,32 @@
 /**
  * @fileoverview Vanadium.js promise implementation.
  *
- * Currently this is just bluebird promises.
+ * This uses the native Promise implementation in browsers, and the es6-promise
+ * polyfill in non-browsers.
  *
- * We'd like our promise implementation to follow the es6/A+ promise spec, but
- * the "es6-promises" module eats errors, so we are using bluebird.
+ * WARNING: es6 promises are notorius for eating errors. Make sure to add
+ * 'catch()' to the end of promise chains so that errors can be caught and
+ * handled.
  *
  * See for reference:
  *   http://blog.soareschen.com/the-problem-with-es6-promises
  *   https://github.com/soareschen/es6-promise-debugging
  *   https://github.com/petkaantonov/bluebird#error-handling
  *
- * TODO(nlacasse): Wrap bluebird promises to only expose es6/A+ promise API.
- * Otherwise users might rely on non-A+ parts of the bluebird API, preventing us
- * from switching in the future.
  * @private
  */
 
-var Promise = require('bluebird');
-Promise.longStackTraces();
+var isBrowser = require('is-browser');
 
-module.exports = Promise;
+if (isBrowser) {
+  // Use native Promise implementation in browsers.
+  if (typeof Promise === 'undefined') {
+    throw new Error('No native promise implementation found.');
+  }
+  module.exports = Promise;
+} else {
+  // Use es6-promise polyfill in non-browsers.
+  // The require string is split so that browserify does not bundle es6-promise
+  // library.
+  module.exports = require('es6' + '-promise').Promise;
+}
diff --git a/test/integration/test-cancellation.js b/test/integration/test-cancellation.js
index 8c36817..a4f40f2 100644
--- a/test/integration/test-cancellation.js
+++ b/test/integration/test-cancellation.js
@@ -43,10 +43,11 @@
       ctx.cancel();
       return collector.waitForStatus(dctx, id, 'cancelled');
     }).then(function(timeout) {
+      dctx.finish();
+      end(assert);
     }).catch(function(err) {
-      assert.error(err);
-    }).finally(function() {
       dctx.cancel();
+      assert.error(err);
       end(assert);
     });
 }
diff --git a/test/integration/test-service-cache.js b/test/integration/test-service-cache.js
index 9dafca6..0ade094 100644
--- a/test/integration/test-service-cache.js
+++ b/test/integration/test-service-cache.js
@@ -7,7 +7,7 @@
 var NoExistError = vanadium.verror.NoExistError;
 var config = require('./default-config');
 var service = require('./get-service');
-var Promise = require('bluebird');
+var Promise = require('../../src/lib/promise');
 
 test('Test set() of Go sample cache service - ' +
   'cache.set(key, value, callback)', function(assert) {