You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.0 KiB

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