simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

AsyncGenerator.js (2010B)


      1 import AwaitValue from "./AwaitValue.js";
      2 export default function AsyncGenerator(gen) {
      3   var front, back;
      4 
      5   function send(key, arg) {
      6     return new Promise(function (resolve, reject) {
      7       var request = {
      8         key: key,
      9         arg: arg,
     10         resolve: resolve,
     11         reject: reject,
     12         next: null
     13       };
     14 
     15       if (back) {
     16         back = back.next = request;
     17       } else {
     18         front = back = request;
     19         resume(key, arg);
     20       }
     21     });
     22   }
     23 
     24   function resume(key, arg) {
     25     try {
     26       var result = gen[key](arg);
     27       var value = result.value;
     28       var wrappedAwait = value instanceof AwaitValue;
     29       Promise.resolve(wrappedAwait ? value.wrapped : value).then(function (arg) {
     30         if (wrappedAwait) {
     31           resume(key === "return" ? "return" : "next", arg);
     32           return;
     33         }
     34 
     35         settle(result.done ? "return" : "normal", arg);
     36       }, function (err) {
     37         resume("throw", err);
     38       });
     39     } catch (err) {
     40       settle("throw", err);
     41     }
     42   }
     43 
     44   function settle(type, value) {
     45     switch (type) {
     46       case "return":
     47         front.resolve({
     48           value: value,
     49           done: true
     50         });
     51         break;
     52 
     53       case "throw":
     54         front.reject(value);
     55         break;
     56 
     57       default:
     58         front.resolve({
     59           value: value,
     60           done: false
     61         });
     62         break;
     63     }
     64 
     65     front = front.next;
     66 
     67     if (front) {
     68       resume(front.key, front.arg);
     69     } else {
     70       back = null;
     71     }
     72   }
     73 
     74   this._invoke = send;
     75 
     76   if (typeof gen["return"] !== "function") {
     77     this["return"] = undefined;
     78   }
     79 }
     80 
     81 AsyncGenerator.prototype[typeof Symbol === "function" && Symbol.asyncIterator || "@@asyncIterator"] = function () {
     82   return this;
     83 };
     84 
     85 AsyncGenerator.prototype.next = function (arg) {
     86   return this._invoke("next", arg);
     87 };
     88 
     89 AsyncGenerator.prototype["throw"] = function (arg) {
     90   return this._invoke("throw", arg);
     91 };
     92 
     93 AsyncGenerator.prototype["return"] = function (arg) {
     94   return this._invoke("return", arg);
     95 };