request-iframe 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/README.CN.md +53 -6
  2. package/README.md +63 -10
  3. package/esm/api/client.js +79 -0
  4. package/esm/api/server.js +59 -0
  5. package/esm/constants/index.js +257 -0
  6. package/esm/constants/messages.js +155 -0
  7. package/esm/core/client-server.js +329 -0
  8. package/esm/core/client.js +873 -0
  9. package/esm/core/request.js +27 -0
  10. package/esm/core/response.js +451 -0
  11. package/esm/core/server.js +767 -0
  12. package/esm/index.js +21 -0
  13. package/esm/interceptors/index.js +122 -0
  14. package/esm/message/channel.js +181 -0
  15. package/esm/message/dispatcher.js +380 -0
  16. package/esm/message/index.js +2 -0
  17. package/esm/stream/file-stream.js +289 -0
  18. package/esm/stream/index.js +44 -0
  19. package/esm/stream/readable-stream.js +500 -0
  20. package/esm/stream/stream-core.js +91 -0
  21. package/esm/stream/types.js +1 -0
  22. package/esm/stream/writable-stream.js +582 -0
  23. package/esm/types/index.js +1 -0
  24. package/esm/utils/ack-meta.js +53 -0
  25. package/esm/utils/cache.js +147 -0
  26. package/esm/utils/cookie.js +352 -0
  27. package/esm/utils/debug.js +521 -0
  28. package/esm/utils/error.js +27 -0
  29. package/esm/utils/index.js +178 -0
  30. package/esm/utils/origin.js +28 -0
  31. package/esm/utils/path-match.js +148 -0
  32. package/esm/utils/protocol.js +157 -0
  33. package/library/api/client.d.ts.map +1 -1
  34. package/library/api/client.js +8 -1
  35. package/library/api/server.d.ts.map +1 -1
  36. package/library/api/server.js +4 -1
  37. package/library/constants/index.d.ts +25 -1
  38. package/library/constants/index.d.ts.map +1 -1
  39. package/library/constants/index.js +30 -5
  40. package/library/constants/messages.d.ts +5 -0
  41. package/library/constants/messages.d.ts.map +1 -1
  42. package/library/constants/messages.js +5 -0
  43. package/library/core/client-server.d.ts +3 -2
  44. package/library/core/client-server.d.ts.map +1 -1
  45. package/library/core/client-server.js +51 -4
  46. package/library/core/client.d.ts +4 -1
  47. package/library/core/client.d.ts.map +1 -1
  48. package/library/core/client.js +74 -31
  49. package/library/core/response.d.ts +21 -3
  50. package/library/core/response.d.ts.map +1 -1
  51. package/library/core/response.js +46 -6
  52. package/library/core/server.d.ts +28 -1
  53. package/library/core/server.d.ts.map +1 -1
  54. package/library/core/server.js +180 -19
  55. package/library/message/channel.d.ts +6 -0
  56. package/library/message/channel.d.ts.map +1 -1
  57. package/library/message/dispatcher.d.ts +22 -0
  58. package/library/message/dispatcher.d.ts.map +1 -1
  59. package/library/message/dispatcher.js +92 -0
  60. package/library/stream/file-stream.d.ts +4 -0
  61. package/library/stream/file-stream.d.ts.map +1 -1
  62. package/library/stream/file-stream.js +61 -33
  63. package/library/stream/index.d.ts.map +1 -1
  64. package/library/stream/index.js +2 -0
  65. package/library/stream/readable-stream.d.ts +30 -11
  66. package/library/stream/readable-stream.d.ts.map +1 -1
  67. package/library/stream/readable-stream.js +329 -73
  68. package/library/stream/stream-core.d.ts +44 -0
  69. package/library/stream/stream-core.d.ts.map +1 -0
  70. package/library/stream/stream-core.js +98 -0
  71. package/library/stream/types.d.ts +90 -3
  72. package/library/stream/types.d.ts.map +1 -1
  73. package/library/stream/writable-stream.d.ts +40 -12
  74. package/library/stream/writable-stream.d.ts.map +1 -1
  75. package/library/stream/writable-stream.js +391 -195
  76. package/library/types/index.d.ts +70 -3
  77. package/library/types/index.d.ts.map +1 -1
  78. package/library/utils/ack-meta.d.ts +2 -0
  79. package/library/utils/ack-meta.d.ts.map +1 -0
  80. package/library/utils/ack-meta.js +59 -0
  81. package/library/utils/index.d.ts +1 -0
  82. package/library/utils/index.d.ts.map +1 -1
  83. package/library/utils/index.js +16 -0
  84. package/library/utils/origin.d.ts +14 -0
  85. package/library/utils/origin.d.ts.map +1 -0
  86. package/library/utils/origin.js +34 -0
  87. package/package.json +30 -7
  88. package/react/README.md +16 -0
  89. package/react/esm/index.js +284 -0
  90. package/react/library/index.d.ts +1 -1
  91. package/react/library/index.d.ts.map +1 -1
  92. package/react/library/index.js +3 -3
  93. package/react/package.json +24 -2
@@ -11,19 +11,15 @@ exports.IframeWritableStream = void 0;
11
11
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
12
12
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
13
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
14
- require("core-js/modules/es.symbol.description.js");
15
- require("core-js/modules/es.symbol.async-iterator.js");
16
- require("core-js/modules/es.array.iterator.js");
17
14
  require("core-js/modules/es.array.slice.js");
18
15
  require("core-js/modules/es.promise.js");
16
+ require("core-js/modules/es.promise.finally.js");
19
17
  require("core-js/modules/es.regexp.to-string.js");
20
- require("core-js/modules/web.dom-collections.iterator.js");
21
18
  var _utils = require("../utils");
22
19
  var _constants = require("../constants");
20
+ var _streamCore = require("./stream-core");
23
21
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
24
22
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
25
- function _asyncIterator(r) { var n, t, o, e = 2; for ("undefined" != typeof Symbol && (t = Symbol.asyncIterator, o = Symbol.iterator); e--;) { if (t && null != (n = r[t])) return n.call(r); if (o && null != (n = r[o])) return new AsyncFromSyncIterator(n.call(r)); t = "@@asyncIterator", o = "@@iterator"; } throw new TypeError("Object is not async iterable"); }
26
- function AsyncFromSyncIterator(r) { function AsyncFromSyncIteratorContinuation(r) { if (Object(r) !== r) return Promise.reject(new TypeError(r + " is not an object.")); var n = r.done; return Promise.resolve(r.value).then(function (r) { return { value: r, done: n }; }); } return AsyncFromSyncIterator = function AsyncFromSyncIterator(r) { this.s = r, this.n = r.next; }, AsyncFromSyncIterator.prototype = { s: null, n: null, next: function next() { return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments)); }, return: function _return(r) { var n = this.s.return; return void 0 === n ? Promise.resolve({ value: r, done: !0 }) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); }, throw: function _throw(r) { var n = this.s.return; return void 0 === n ? Promise.reject(r) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments)); } }, new AsyncFromSyncIterator(r); }
27
23
  /**
28
24
  * Generate a unique stream ID
29
25
  */
@@ -35,23 +31,38 @@ function generateStreamId() {
35
31
  * IframeWritableStream - Server-side writable stream
36
32
  * Used to send stream data to the client
37
33
  */
38
- class IframeWritableStream {
34
+ class IframeWritableStream extends _streamCore.IframeStreamCore {
39
35
  constructor(options = {}) {
40
- var _options$type, _options$chunked;
41
- (0, _defineProperty2.default)(this, "_state", _constants.StreamState.PENDING);
36
+ var _options$type, _options$chunked, _options$mode, _options$expireTimeou;
37
+ var streamId = generateStreamId();
38
+ var streamType = (_options$type = options.type) !== null && _options$type !== void 0 ? _options$type : _constants.StreamType.DATA;
39
+ var chunked = (_options$chunked = options.chunked) !== null && _options$chunked !== void 0 ? _options$chunked : true;
40
+ super(streamId, streamType, chunked, options.metadata, false, options.mode);
42
41
  (0, _defineProperty2.default)(this, "context", null);
43
- this.streamId = generateStreamId();
44
- this.type = (_options$type = options.type) !== null && _options$type !== void 0 ? _options$type : _constants.StreamType.DATA;
45
- this.chunked = (_options$chunked = options.chunked) !== null && _options$chunked !== void 0 ? _options$chunked : true;
42
+ (0, _defineProperty2.default)(this, "expireTimer", null);
43
+ (0, _defineProperty2.default)(this, "idleTimer", null);
44
+ (0, _defineProperty2.default)(this, "lastRemoteActivityAt", Date.now());
45
+ (0, _defineProperty2.default)(this, "heartbeatInFlight", null);
46
+ /** pull/ack protocol */
47
+ (0, _defineProperty2.default)(this, "pullCredit", 0);
48
+ (0, _defineProperty2.default)(this, "seq", 0);
49
+ (0, _defineProperty2.default)(this, "pendingQueue", []);
50
+ (0, _defineProperty2.default)(this, "pumping", false);
51
+ (0, _defineProperty2.default)(this, "completionPromise", null);
52
+ (0, _defineProperty2.default)(this, "resolveCompletion", null);
53
+ (0, _defineProperty2.default)(this, "rejectCompletion", null);
54
+ this.mode = (_options$mode = options.mode) !== null && _options$mode !== void 0 ? _options$mode : _constants.StreamMode.PULL;
46
55
  this.iterator = options.iterator;
47
56
  this.nextFn = options.next;
48
- this.metadata = options.metadata;
49
57
  this.autoResolve = options.autoResolve;
58
+ // Default to async-timeout length to avoid leaking long-lived streams
59
+ this.expireTimeout = (_options$expireTimeou = options.expireTimeout) !== null && _options$expireTimeou !== void 0 ? _options$expireTimeou : _constants.DefaultTimeout.ASYNC;
60
+ this.streamTimeout = options.streamTimeout;
50
61
  }
51
62
 
52
63
  /** Get stream state */
53
64
  get state() {
54
- return this._state;
65
+ return super.state;
55
66
  }
56
67
 
57
68
  /**
@@ -61,6 +72,117 @@ class IframeWritableStream {
61
72
  _bind(context) {
62
73
  this.context = context;
63
74
  }
75
+ registerControlHandler() {
76
+ var _this$context;
77
+ if (!((_this$context = this.context) !== null && _this$context !== void 0 && _this$context.registerStreamHandler)) return;
78
+ this.context.registerStreamHandler(this.streamId, this.handleControlMessage.bind(this));
79
+ }
80
+ unregisterControlHandler() {
81
+ var _this$context2;
82
+ if (!((_this$context2 = this.context) !== null && _this$context2 !== void 0 && _this$context2.unregisterStreamHandler)) return;
83
+ this.context.unregisterStreamHandler(this.streamId);
84
+ }
85
+ handleControlMessage(data) {
86
+ // Update remote activity timestamp on any control message
87
+ this.lastRemoteActivityAt = Date.now();
88
+ switch (data.type) {
89
+ case _constants.StreamInternalMessageType.PULL:
90
+ {
91
+ var credit = typeof data.credit === 'number' && data.credit > 0 ? data.credit : 1;
92
+ this.pullCredit += credit;
93
+ // Try flushing buffered chunks or pumping generator
94
+ this.flush();
95
+ break;
96
+ }
97
+ case _constants.StreamInternalMessageType.ACK:
98
+ // Ack is treated as heartbeat; no further action required
99
+ break;
100
+ case _constants.StreamInternalMessageType.CANCEL:
101
+ this.cancel(data.reason);
102
+ break;
103
+ default:
104
+ break;
105
+ }
106
+ }
107
+ clearIdleTimer() {
108
+ if (this.idleTimer) {
109
+ clearTimeout(this.idleTimer);
110
+ this.idleTimer = null;
111
+ }
112
+ }
113
+ performHeartbeat() {
114
+ var _this = this;
115
+ return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee() {
116
+ var _this$context3;
117
+ return _regenerator.default.wrap(function (_context) {
118
+ while (1) switch (_context.prev = _context.next) {
119
+ case 0:
120
+ if ((_this$context3 = _this.context) !== null && _this$context3 !== void 0 && _this$context3.heartbeat) {
121
+ _context.next = 1;
122
+ break;
123
+ }
124
+ return _context.abrupt("return", false);
125
+ case 1:
126
+ if (!_this.heartbeatInFlight) {
127
+ _this.heartbeatInFlight = Promise.resolve().then(() => _this.context.heartbeat()).catch(() => false).finally(() => {
128
+ _this.heartbeatInFlight = null;
129
+ });
130
+ }
131
+ return _context.abrupt("return", _this.heartbeatInFlight);
132
+ case 2:
133
+ case "end":
134
+ return _context.stop();
135
+ }
136
+ }, _callee);
137
+ }))();
138
+ }
139
+ startIdleTimer() {
140
+ var _this2 = this;
141
+ if (!this.streamTimeout || this.streamTimeout <= 0) return;
142
+ this.clearIdleTimer();
143
+ var timeout = this.streamTimeout;
144
+ this.idleTimer = setTimeout(/*#__PURE__*/(0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2() {
145
+ var ok;
146
+ return _regenerator.default.wrap(function (_context2) {
147
+ while (1) switch (_context2.prev = _context2.next) {
148
+ case 0:
149
+ if (!(_this2._state !== _constants.StreamState.STREAMING)) {
150
+ _context2.next = 1;
151
+ break;
152
+ }
153
+ return _context2.abrupt("return");
154
+ case 1:
155
+ if (!(Date.now() - _this2.lastRemoteActivityAt < timeout)) {
156
+ _context2.next = 2;
157
+ break;
158
+ }
159
+ _this2.startIdleTimer();
160
+ return _context2.abrupt("return");
161
+ case 2:
162
+ _context2.next = 3;
163
+ return _this2.performHeartbeat();
164
+ case 3:
165
+ ok = _context2.sent;
166
+ if (!ok) {
167
+ _context2.next = 4;
168
+ break;
169
+ }
170
+ _this2.lastRemoteActivityAt = Date.now();
171
+ _this2.startIdleTimer();
172
+ return _context2.abrupt("return");
173
+ case 4:
174
+ try {
175
+ _this2.error((0, _constants.formatMessage)(_constants.Messages.STREAM_TIMEOUT, timeout));
176
+ } catch (_unused) {
177
+ /** ignore */
178
+ }
179
+ case 5:
180
+ case "end":
181
+ return _context2.stop();
182
+ }
183
+ }, _callee2);
184
+ })), timeout);
185
+ }
64
186
 
65
187
  /**
66
188
  * Send message (to client when server-side stream, to server when client-side stream)
@@ -85,254 +207,277 @@ class IframeWritableStream {
85
207
  var ok = this.context.channel.send(this.context.targetWindow, message, this.context.targetOrigin);
86
208
  if (!ok) {
87
209
  this._state = _constants.StreamState.CANCELLED;
210
+ this.clearExpireTimer();
88
211
  // For most stream messages, if we cannot send, treat as a hard cancellation signal
89
212
  // so callers can stop further processing immediately.
90
213
  throw new Error((0, _constants.formatMessage)(_constants.Messages.STREAM_CANCELLED, 'Target window closed'));
91
214
  }
92
215
  return true;
93
216
  }
217
+ clearExpireTimer() {
218
+ if (this.expireTimer) {
219
+ clearTimeout(this.expireTimer);
220
+ this.expireTimer = null;
221
+ }
222
+ }
223
+ startExpireTimer() {
224
+ if (!this.expireTimeout || this.expireTimeout <= 0) return;
225
+ var expireTimeout = this.expireTimeout;
226
+ this.clearExpireTimer();
227
+ this.expireTimer = setTimeout(() => {
228
+ if (this._state !== _constants.StreamState.STREAMING) return;
229
+ try {
230
+ this.error((0, _constants.formatMessage)(_constants.Messages.STREAM_EXPIRED, expireTimeout));
231
+ } catch (_unused2) {
232
+ /** ignore timer-triggered send failures */
233
+ }
234
+ }, expireTimeout);
235
+ }
94
236
 
95
237
  /**
96
238
  * Start stream transfer
97
239
  */
98
240
  start() {
99
- var _this = this;
100
- return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee() {
241
+ var _this3 = this;
242
+ return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3() {
101
243
  var _t;
102
- return _regenerator.default.wrap(function (_context) {
103
- while (1) switch (_context.prev = _context.next) {
244
+ return _regenerator.default.wrap(function (_context3) {
245
+ while (1) switch (_context3.prev = _context3.next) {
104
246
  case 0:
105
- if (_this.context) {
106
- _context.next = 1;
247
+ if (_this3.context) {
248
+ _context3.next = 1;
107
249
  break;
108
250
  }
109
251
  throw new Error(_constants.Messages.STREAM_NOT_BOUND);
110
252
  case 1:
111
- if (!(_this._state !== _constants.StreamState.PENDING)) {
112
- _context.next = 2;
253
+ if (!(_this3._state !== _constants.StreamState.PENDING)) {
254
+ _context3.next = 2;
113
255
  break;
114
256
  }
115
257
  throw new Error(_constants.Messages.STREAM_ALREADY_STARTED);
116
258
  case 2:
117
- _this._state = _constants.StreamState.STREAMING;
259
+ _this3.completionPromise = new Promise((resolve, reject) => {
260
+ _this3.resolveCompletion = resolve;
261
+ _this3.rejectCompletion = reject;
262
+ });
263
+ _this3._state = _constants.StreamState.STREAMING;
264
+ _this3.startExpireTimer();
265
+ _this3.startIdleTimer();
266
+ _this3.lastRemoteActivityAt = Date.now();
267
+ _this3.registerControlHandler();
118
268
 
119
269
  // Send stream start message
120
- _this.sendMessage(_constants.MessageType.STREAM_START, {
121
- type: _this.type,
122
- chunked: _this.chunked,
123
- metadata: _this.metadata,
124
- autoResolve: _this.autoResolve
270
+ _this3.sendMessage(_constants.MessageType.STREAM_START, {
271
+ type: _this3.type,
272
+ mode: _this3.mode,
273
+ chunked: _this3.chunked,
274
+ metadata: _this3.metadata,
275
+ autoResolve: _this3.autoResolve
125
276
  });
126
- _context.prev = 3;
127
- if (!_this.iterator) {
128
- _context.next = 5;
277
+ _context3.prev = 3;
278
+ if (!(_this3.mode === _constants.StreamMode.PUSH)) {
279
+ _context3.next = 5;
129
280
  break;
130
281
  }
131
- _context.next = 4;
132
- return _this.streamFromIterator();
282
+ _context3.next = 4;
283
+ return _this3.completionPromise;
133
284
  case 4:
134
- _context.next = 8;
135
- break;
285
+ return _context3.abrupt("return", _context3.sent);
136
286
  case 5:
137
- if (!_this.nextFn) {
138
- _context.next = 7;
139
- break;
140
- }
141
- _context.next = 6;
142
- return _this.streamFromNext();
287
+ // pull protocol: produce only when receiver grants credit
288
+ _this3.flush();
289
+ _context3.next = 6;
290
+ return _this3.completionPromise;
143
291
  case 6:
144
- _context.next = 8;
145
- break;
292
+ return _context3.abrupt("return", _context3.sent);
146
293
  case 7:
147
- // No data source, end directly
148
- _this.end();
149
- case 8:
150
- _context.next = 11;
151
- break;
152
- case 9:
153
- _context.prev = 9;
154
- _t = _context["catch"](3);
155
- if (!(_this._state === _constants.StreamState.CANCELLED)) {
156
- _context.next = 10;
294
+ _context3.prev = 7;
295
+ _t = _context3["catch"](3);
296
+ if (!(_this3._state === _constants.StreamState.CANCELLED)) {
297
+ _context3.next = 8;
157
298
  break;
158
299
  }
300
+ _this3.clearExpireTimer();
159
301
  throw _t;
302
+ case 8:
303
+ _this3.error(_t.message || String(_t));
304
+ _context3.next = 9;
305
+ return _this3.completionPromise;
306
+ case 9:
307
+ return _context3.abrupt("return", _context3.sent);
160
308
  case 10:
161
- _this.error(_t.message || String(_t));
162
- case 11:
163
309
  case "end":
164
- return _context.stop();
310
+ return _context3.stop();
165
311
  }
166
- }, _callee, null, [[3, 9]]);
312
+ }, _callee3, null, [[3, 7]]);
167
313
  }))();
168
314
  }
169
315
 
316
+ /**
317
+ * Push a chunk manually (mode === 'push').
318
+ */
319
+ write(data, done = false) {
320
+ if (this.mode !== _constants.StreamMode.PUSH) {
321
+ throw new Error(_constants.Messages.STREAM_WRITE_ONLY_IN_PUSH_MODE);
322
+ }
323
+ if (this._state === _constants.StreamState.PENDING) {
324
+ /**
325
+ * In push mode, users must call start() first so STREAM_START is sent and binding is complete.
326
+ */
327
+ throw new Error(_constants.Messages.STREAM_NOT_BOUND);
328
+ }
329
+ if (this._state !== _constants.StreamState.STREAMING) {
330
+ throw new Error(_constants.Messages.STREAM_ENDED);
331
+ }
332
+ // push mode now buffers and sends based on pull credit
333
+ this.pendingQueue.push({
334
+ data,
335
+ done
336
+ });
337
+ this.flush();
338
+ }
339
+
340
+ /**
341
+ * End the stream (mode === 'push').
342
+ */
343
+ end() {
344
+ if (this.mode !== _constants.StreamMode.PUSH) {
345
+ // For pull mode, end is controlled internally
346
+ this.endInternal();
347
+ return;
348
+ }
349
+ // In push mode, end means enqueue a terminal marker if nothing queued
350
+ if (this.mode === _constants.StreamMode.PUSH) {
351
+ if (this.pendingQueue.length === 0) {
352
+ this.pendingQueue.push({
353
+ data: undefined,
354
+ done: true
355
+ });
356
+ } else {
357
+ // Ensure the last queued chunk marks done
358
+ this.pendingQueue[this.pendingQueue.length - 1].done = true;
359
+ }
360
+ this.flush();
361
+ return;
362
+ }
363
+ this.endInternal();
364
+ }
365
+
170
366
  /**
171
367
  * Generate data from iterator
172
368
  */
173
- streamFromIterator() {
174
- var _this2 = this;
175
- return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2() {
176
- var gen, _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, chunk, _t2, _t3, _t4;
177
- return _regenerator.default.wrap(function (_context2) {
178
- while (1) switch (_context2.prev = _context2.next) {
369
+ pumpFromGenerator() {
370
+ var _this4 = this;
371
+ return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee4() {
372
+ var gen, r, result, _t2;
373
+ return _regenerator.default.wrap(function (_context4) {
374
+ while (1) switch (_context4.prev = _context4.next) {
179
375
  case 0:
180
- if (_this2.iterator) {
181
- _context2.next = 1;
376
+ if (!_this4.pumping) {
377
+ _context4.next = 1;
182
378
  break;
183
379
  }
184
- return _context2.abrupt("return");
380
+ return _context4.abrupt("return");
185
381
  case 1:
186
- gen = _this2.iterator();
187
- _context2.prev = 2;
188
- _iteratorAbruptCompletion = false;
189
- _didIteratorError = false;
190
- _context2.prev = 3;
191
- _iterator = _asyncIterator(gen);
192
- case 4:
193
- _context2.next = 5;
194
- return _iterator.next();
195
- case 5:
196
- if (!(_iteratorAbruptCompletion = !(_step = _context2.sent).done)) {
197
- _context2.next = 10;
382
+ _this4.pumping = true;
383
+ _context4.prev = 2;
384
+ if (!_this4.iterator) {
385
+ _context4.next = 8;
198
386
  break;
199
387
  }
200
- chunk = _step.value;
201
- if (!(_this2._state !== _constants.StreamState.STREAMING)) {
202
- _context2.next = 6;
203
- break;
204
- }
205
- return _context2.abrupt("continue", 10);
206
- case 6:
207
- _context2.prev = 6;
208
- _this2.sendData(chunk);
209
- _context2.next = 9;
210
- break;
211
- case 7:
212
- _context2.prev = 7;
213
- _t2 = _context2["catch"](6);
214
- if (!(_this2._state === _constants.StreamState.CANCELLED)) {
215
- _context2.next = 8;
388
+ gen = _this4.iterator();
389
+ case 3:
390
+ if (!(_this4._state === _constants.StreamState.STREAMING)) {
391
+ _context4.next = 7;
216
392
  break;
217
393
  }
218
- throw _t2;
219
- case 8:
220
- throw _t2;
221
- case 9:
222
- _iteratorAbruptCompletion = false;
223
- _context2.next = 4;
224
- break;
225
- case 10:
226
- _context2.next = 12;
227
- break;
228
- case 11:
229
- _context2.prev = 11;
230
- _t3 = _context2["catch"](3);
231
- _didIteratorError = true;
232
- _iteratorError = _t3;
233
- case 12:
234
- _context2.prev = 12;
235
- _context2.prev = 13;
236
- if (!(_iteratorAbruptCompletion && _iterator.return != null)) {
237
- _context2.next = 14;
394
+ if (!(_this4.pullCredit <= 0)) {
395
+ _context4.next = 4;
238
396
  break;
239
397
  }
240
- _context2.next = 14;
241
- return _iterator.return();
242
- case 14:
243
- _context2.prev = 14;
244
- if (!_didIteratorError) {
245
- _context2.next = 15;
398
+ return _context4.abrupt("continue", 7);
399
+ case 4:
400
+ _context4.next = 5;
401
+ return gen.next();
402
+ case 5:
403
+ r = _context4.sent;
404
+ if (!r.done) {
405
+ _context4.next = 6;
246
406
  break;
247
407
  }
248
- throw _iteratorError;
249
- case 15:
250
- return _context2.finish(14);
251
- case 16:
252
- return _context2.finish(12);
253
- case 17:
254
- if (_this2._state === _constants.StreamState.STREAMING) {
255
- _this2.end();
256
- }
257
- _context2.next = 20;
408
+ // no more data: send end
409
+ _this4.endInternal();
410
+ return _context4.abrupt("continue", 7);
411
+ case 6:
412
+ _this4.pendingQueue.push({
413
+ data: r.value,
414
+ done: false
415
+ });
416
+ _this4.flush();
417
+ _context4.next = 3;
258
418
  break;
259
- case 18:
260
- _context2.prev = 18;
261
- _t4 = _context2["catch"](2);
262
- if (!(_this2._state === _constants.StreamState.CANCELLED)) {
263
- _context2.next = 19;
419
+ case 7:
420
+ _context4.next = 15;
421
+ break;
422
+ case 8:
423
+ if (!_this4.nextFn) {
424
+ _context4.next = 14;
264
425
  break;
265
426
  }
266
- throw _t4;
267
- case 19:
268
- if (_this2._state === _constants.StreamState.STREAMING) {
269
- _this2.error(_t4.message || String(_t4));
270
- }
271
- case 20:
272
- case "end":
273
- return _context2.stop();
274
- }
275
- }, _callee2, null, [[2, 18], [3, 11, 12, 17], [6, 7], [13,, 14, 16]]);
276
- }))();
277
- }
278
-
279
- /**
280
- * Generate data from next function
281
- */
282
- streamFromNext() {
283
- var _this3 = this;
284
- return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3() {
285
- var result, _t5;
286
- return _regenerator.default.wrap(function (_context3) {
287
- while (1) switch (_context3.prev = _context3.next) {
288
- case 0:
289
- if (_this3.nextFn) {
290
- _context3.next = 1;
427
+ case 9:
428
+ if (!(_this4._state === _constants.StreamState.STREAMING)) {
429
+ _context4.next = 13;
291
430
  break;
292
431
  }
293
- return _context3.abrupt("return");
294
- case 1:
295
- _context3.prev = 1;
296
- case 2:
297
- if (!(_this3._state === _constants.StreamState.STREAMING)) {
298
- _context3.next = 5;
432
+ if (!(_this4.pullCredit <= 0)) {
433
+ _context4.next = 10;
299
434
  break;
300
435
  }
301
- _context3.next = 3;
302
- return Promise.resolve(_this3.nextFn());
303
- case 3:
304
- result = _context3.sent;
436
+ return _context4.abrupt("continue", 13);
437
+ case 10:
438
+ _context4.next = 11;
439
+ return Promise.resolve(_this4.nextFn());
440
+ case 11:
441
+ result = _context4.sent;
442
+ _this4.pendingQueue.push({
443
+ data: result.data,
444
+ done: result.done
445
+ });
446
+ _this4.flush();
305
447
  if (!result.done) {
306
- _context3.next = 4;
448
+ _context4.next = 12;
307
449
  break;
308
450
  }
309
- _this3.sendData(result.data, true);
310
- _this3.end();
311
- return _context3.abrupt("continue", 5);
312
- case 4:
313
- _this3.sendData(result.data);
314
- _context3.next = 2;
451
+ return _context4.abrupt("continue", 13);
452
+ case 12:
453
+ _context4.next = 9;
315
454
  break;
316
- case 5:
317
- _context3.next = 8;
455
+ case 13:
456
+ _context4.next = 15;
318
457
  break;
319
- case 6:
320
- _context3.prev = 6;
321
- _t5 = _context3["catch"](1);
322
- if (!(_this3._state === _constants.StreamState.CANCELLED)) {
323
- _context3.next = 7;
324
- break;
458
+ case 14:
459
+ // No producer, just end when pulled
460
+ if (_this4.pullCredit > 0) {
461
+ _this4.endInternal();
325
462
  }
326
- throw _t5;
327
- case 7:
328
- if (_this3._state === _constants.StreamState.STREAMING) {
329
- _this3.error(_t5.message || String(_t5));
463
+ case 15:
464
+ _context4.next = 17;
465
+ break;
466
+ case 16:
467
+ _context4.prev = 16;
468
+ _t2 = _context4["catch"](2);
469
+ if (_this4._state === _constants.StreamState.STREAMING) {
470
+ _this4.error((_t2 === null || _t2 === void 0 ? void 0 : _t2.message) || String(_t2));
330
471
  }
331
- case 8:
472
+ case 17:
473
+ _context4.prev = 17;
474
+ _this4.pumping = false;
475
+ return _context4.finish(17);
476
+ case 18:
332
477
  case "end":
333
- return _context3.stop();
478
+ return _context4.stop();
334
479
  }
335
- }, _callee3, null, [[1, 6]]);
480
+ }, _callee4, null, [[2, 16, 17, 18]]);
336
481
  }))();
337
482
  }
338
483
 
@@ -342,9 +487,38 @@ class IframeWritableStream {
342
487
  sendData(data, done = false) {
343
488
  this.sendMessage(_constants.MessageType.STREAM_DATA, {
344
489
  data: this.encodeData(data),
345
- done
490
+ done,
491
+ seq: this.seq++
346
492
  });
347
493
  }
494
+ flush() {
495
+ if (this._state !== _constants.StreamState.STREAMING) return;
496
+
497
+ // First try to pump from generator if needed
498
+ if (this.mode === _constants.StreamMode.PULL && this.pendingQueue.length === 0) {
499
+ void this.pumpFromGenerator();
500
+ }
501
+ while (this.pullCredit > 0 && this.pendingQueue.length > 0 && this._state === _constants.StreamState.STREAMING) {
502
+ var item = this.pendingQueue.shift();
503
+ this.pullCredit--;
504
+ try {
505
+ this.sendData(item.data, item.done);
506
+ } catch (e) {
507
+ var _this$rejectCompletio;
508
+ // send failure treated as cancellation
509
+ this._state = _constants.StreamState.CANCELLED;
510
+ this.clearExpireTimer();
511
+ this.clearIdleTimer();
512
+ this.unregisterControlHandler();
513
+ (_this$rejectCompletio = this.rejectCompletion) === null || _this$rejectCompletio === void 0 || _this$rejectCompletio.call(this, e instanceof Error ? e : new Error(String(e)));
514
+ throw e;
515
+ }
516
+ if (item.done) {
517
+ this.endInternal();
518
+ break;
519
+ }
520
+ }
521
+ }
348
522
 
349
523
  /**
350
524
  * Encode data (subclasses can override, e.g., FileStream needs Base64 encoding)
@@ -356,38 +530,60 @@ class IframeWritableStream {
356
530
  /**
357
531
  * End stream
358
532
  */
359
- end() {
533
+ endInternal() {
534
+ var _this$resolveCompleti;
360
535
  if (this._state !== _constants.StreamState.STREAMING) return;
361
536
  this._state = _constants.StreamState.ENDED;
537
+ this.clearExpireTimer();
538
+ this.clearIdleTimer();
539
+ this.unregisterControlHandler();
362
540
  this.sendMessage(_constants.MessageType.STREAM_END);
541
+ (_this$resolveCompleti = this.resolveCompletion) === null || _this$resolveCompleti === void 0 || _this$resolveCompleti.call(this);
363
542
  }
364
543
 
365
544
  /**
366
545
  * Send error
367
546
  */
368
547
  error(message) {
548
+ var _this$resolveCompleti2;
369
549
  if (this._state !== _constants.StreamState.STREAMING) return;
370
550
  this._state = _constants.StreamState.ERROR;
551
+ this.clearExpireTimer();
552
+ this.clearIdleTimer();
553
+ this.unregisterControlHandler();
371
554
  this.sendMessage(_constants.MessageType.STREAM_ERROR, {
372
555
  error: message
373
556
  });
557
+ (_this$resolveCompleti2 = this.resolveCompletion) === null || _this$resolveCompleti2 === void 0 || _this$resolveCompleti2.call(this);
558
+ }
559
+
560
+ /**
561
+ * Abort stream transfer (is alias of cancel method)
562
+ */
563
+ abort(reason) {
564
+ this.cancel(reason);
374
565
  }
375
566
 
376
567
  /**
377
568
  * Cancel stream transfer
378
569
  */
379
570
  cancel(reason) {
571
+ var _this$resolveCompleti3;
380
572
  if (this._state !== _constants.StreamState.PENDING && this._state !== _constants.StreamState.STREAMING) return;
381
573
  this._state = _constants.StreamState.CANCELLED;
574
+ this.clearExpireTimer();
575
+ this.clearIdleTimer();
576
+ this.unregisterControlHandler();
382
577
  if (this.context) {
383
578
  try {
384
579
  this.sendMessage(_constants.MessageType.STREAM_CANCEL, {
385
580
  reason
386
581
  });
387
- } catch (_unused) {
582
+ } catch (_unused3) {
388
583
  // ignore send failures on cancel
389
584
  }
390
585
  }
586
+ (_this$resolveCompleti3 = this.resolveCompletion) === null || _this$resolveCompleti3 === void 0 || _this$resolveCompleti3.call(this);
391
587
  }
392
588
  }
393
589
  exports.IframeWritableStream = IframeWritableStream;