// Asynchronous functions
// ======================

var {assign, defineProperty} = Object;

// Run values from a generator through promises.
// Return a promise for when everything is done.
function spawn(generator) {
  var iterator = generator();
  
  return new Promise(
    resolve =>
      (function iterate(val) {
        var {value, done} = iterator.next(val);
        if (done) { resolve(val); }
        else { Promise.resolve(value).then(iterate); }
      }())
  );
  
}

// Return a promise for some time in the future,
// passing through the invoking promise's value:
// ```
// Promise.resolve(99).then(timeout(250)) // promise value is 99
// ```
function timeout(ms = 0) {
  return function(val) {
    return new Promise(resolve => setTimeout(_ => resolve(val), ms));
  };
}

// Implement Promise.done.
// Set Promise.onDoneError to trap errors.
function _throw(e) { throw e; }
if (!Promise.prototype.done) {
  defineProperty(Promise.prototype, 'done', {
    value: function(fulfill, reject) {
      return this
        .then(fulfill, reject)
        .catch(e => setTimeout(Promise.onDoneError || _throw, 1, e));
    }
  });
}

// Implement `get` on promises.
if (!Promise.prototype.get) {
  defineProperty(Promise.prototype, 'get', {
    value: function(prop) { return this.then(o => o[prop]); }
  });
}

// Implement `defer`, which returns an object with the promise and resolve and reject methods.
if (!Promise.defer) {
  defineProperty(Promise, 'defer', {
    value() {
      var ret = {};
      ret.promise = new Promise((resolve, reject) => assign(ret, {resolve, reject}) );
      return ret;
    }
  });
}

// Promise queues.
// See https://github.com/kriskowal/gtor.
function PromiseQueue() {
  var ends = Promise.defer();    // not in spec, but in Chrome
  this.put = function (value) {
    var next = Promise.defer();
    ends.resolve({head: value, tail: next.promise});
    ends.resolve = next.resolve;
  };
  this.get = function () {
    var result = ends.promise.get('head');
    ends.promise = ends.promise.get('tail');
    return result;
  };
}

export {
  spawn,
  timeout,
  PromiseQueue
};

@@ -73,16 +73,36 @@
 Property
+, observe, unobserve
 %7D = Obje
@@ -2090,51 +2090,912 @@
 %0A%7D%0A%0A
-export %7B%0A  spawn,%0A  timeout,%0A  PromiseQueue
+// Promise from one-time Object.observe.%0A// Usage: %60%60%60promiseChanges(obj, %5B'update'%5D).then(function(changes) %7B...%60%0Afunction promiseChanges(object, types) %7B%0A  return new Promise(function(resolve) %7B%0A    function observer(changes) %7B%0A      resolve(changes);%0A      unobserve(object, observer);%0A    %7D%0A    observe(object, observer, types);%0A  %7D;%0A%7D%0A%0Afunction castPromise(p) %7B%0A  return p && typeof p === 'object' && p.then ? p : Promise.resolve(p);%0A%7D%0A%0A// Create a %60Deferred%60 object, a combination of a promise and its%0A// resolver and rejector.%0Afunction Deferred() %7B%0A  var deferred = %7B%7D;%0A  deferred.promise = new Promise(function(resolve, reject) %7B%0A    deferred.resolve = resolve;%0A    deferred.reject  = reject;%0A  %7D);%0A  return deferred;%0A%7D%0A%0Afunction *generateForever(x) %7B%0A  while (true) %5B%0A    yield x;%0A  %7D%0A%7D%0A%0Aexport %7B%0A  spawn,%0A  timeout,%0A  PromiseQueue,%0A  promiseChanges,%0A  castPromise,%0A  Deferred,%0A  generateForever
 %0A%7D;%0A

Add a couple methods to Asy.