97 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| import AwaitValue from "./AwaitValue";
 | |
| export default function AsyncGenerator(gen) {
 | |
|   var front, back;
 | |
| 
 | |
|   function send(key, arg) {
 | |
|     return new Promise(function (resolve, reject) {
 | |
|       var request = {
 | |
|         key: key,
 | |
|         arg: arg,
 | |
|         resolve: resolve,
 | |
|         reject: reject,
 | |
|         next: null
 | |
|       };
 | |
| 
 | |
|       if (back) {
 | |
|         back = back.next = request;
 | |
|       } else {
 | |
|         front = back = request;
 | |
|         resume(key, arg);
 | |
|       }
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   function resume(key, arg) {
 | |
|     try {
 | |
|       var result = gen[key](arg);
 | |
|       var value = result.value;
 | |
|       var wrappedAwait = value instanceof AwaitValue;
 | |
|       Promise.resolve(wrappedAwait ? value.wrapped : value).then(function (arg) {
 | |
|         if (wrappedAwait) {
 | |
|           resume(key === "return" ? "return" : "next", arg);
 | |
|           return;
 | |
|         }
 | |
| 
 | |
|         settle(result.done ? "return" : "normal", arg);
 | |
|       }, function (err) {
 | |
|         resume("throw", err);
 | |
|       });
 | |
|     } catch (err) {
 | |
|       settle("throw", err);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   function settle(type, value) {
 | |
|     switch (type) {
 | |
|       case "return":
 | |
|         front.resolve({
 | |
|           value: value,
 | |
|           done: true
 | |
|         });
 | |
|         break;
 | |
| 
 | |
|       case "throw":
 | |
|         front.reject(value);
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         front.resolve({
 | |
|           value: value,
 | |
|           done: false
 | |
|         });
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     front = front.next;
 | |
| 
 | |
|     if (front) {
 | |
|       resume(front.key, front.arg);
 | |
|     } else {
 | |
|       back = null;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   this._invoke = send;
 | |
| 
 | |
|   if (typeof gen["return"] !== "function") {
 | |
|     this["return"] = undefined;
 | |
|   }
 | |
| }
 | |
| 
 | |
| if (typeof Symbol === "function" && Symbol.asyncIterator) {
 | |
|   AsyncGenerator.prototype[Symbol.asyncIterator] = function () {
 | |
|     return this;
 | |
|   };
 | |
| }
 | |
| 
 | |
| AsyncGenerator.prototype.next = function (arg) {
 | |
|   return this._invoke("next", arg);
 | |
| };
 | |
| 
 | |
| AsyncGenerator.prototype["throw"] = function (arg) {
 | |
|   return this._invoke("throw", arg);
 | |
| };
 | |
| 
 | |
| AsyncGenerator.prototype["return"] = function (arg) {
 | |
|   return this._invoke("return", arg);
 | |
| }; |