request-iframe 0.0.5 → 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 (142) hide show
  1. package/README.CN.md +54 -7
  2. package/README.md +64 -11
  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 +31 -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 +7 -4
  93. package/react/package.json +24 -2
  94. package/library/__tests__/channel.test.ts +0 -432
  95. package/library/__tests__/coverage-branches.test.ts +0 -356
  96. package/library/__tests__/debug.test.ts +0 -610
  97. package/library/__tests__/dispatcher.test.ts +0 -485
  98. package/library/__tests__/interceptors.test.ts +0 -146
  99. package/library/__tests__/requestIframe.test.ts +0 -5590
  100. package/library/__tests__/server.test.ts +0 -738
  101. package/library/__tests__/stream.test.ts +0 -726
  102. package/library/__tests__/utils.test.ts +0 -473
  103. package/library/api/client.d.js +0 -5
  104. package/library/api/server.d.js +0 -5
  105. package/library/constants/index.d.js +0 -36
  106. package/library/constants/messages.d.js +0 -5
  107. package/library/core/client.d.js +0 -5
  108. package/library/core/message-handler.d.ts +0 -110
  109. package/library/core/message-handler.d.ts.map +0 -1
  110. package/library/core/message-handler.js +0 -320
  111. package/library/core/request-response.d.ts +0 -59
  112. package/library/core/request-response.d.ts.map +0 -1
  113. package/library/core/request-response.js +0 -337
  114. package/library/core/request.d.js +0 -5
  115. package/library/core/response.d.js +0 -5
  116. package/library/core/server-base.d.ts +0 -86
  117. package/library/core/server-base.d.ts.map +0 -1
  118. package/library/core/server-base.js +0 -257
  119. package/library/core/server-client.d.js +0 -5
  120. package/library/core/server-client.d.ts +0 -101
  121. package/library/core/server-client.d.ts.map +0 -1
  122. package/library/core/server-client.js +0 -266
  123. package/library/core/server.d.js +0 -5
  124. package/library/interceptors/index.d.js +0 -5
  125. package/library/message/channel.d.js +0 -5
  126. package/library/message/dispatcher.d.js +0 -5
  127. package/library/message/index.d.js +0 -25
  128. package/library/stream/file-stream.d.js +0 -4
  129. package/library/stream/index.d.js +0 -58
  130. package/library/stream/readable-stream.d.js +0 -5
  131. package/library/stream/types.d.js +0 -5
  132. package/library/stream/writable-stream.d.js +0 -5
  133. package/library/types/index.d.js +0 -5
  134. package/library/utils/cache.d.js +0 -5
  135. package/library/utils/cookie.d.js +0 -5
  136. package/library/utils/debug.d.js +0 -5
  137. package/library/utils/index.d.js +0 -94
  138. package/library/utils/path-match.d.js +0 -5
  139. package/library/utils/protocol.d.js +0 -5
  140. package/react/library/__tests__/index.test.d.ts +0 -2
  141. package/react/library/__tests__/index.test.d.ts.map +0 -1
  142. package/react/library/__tests__/index.test.tsx +0 -792
@@ -1,5 +1,8 @@
1
1
  "use strict";
2
2
 
3
+ require("core-js/modules/es.array.filter.js");
4
+ require("core-js/modules/es.object.get-own-property-descriptors.js");
5
+ require("core-js/modules/web.dom-collections.for-each.js");
3
6
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
7
  Object.defineProperty(exports, "__esModule", {
5
8
  value: true
@@ -7,11 +10,18 @@ Object.defineProperty(exports, "__esModule", {
7
10
  exports.IframeReadableStream = void 0;
8
11
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
12
  require("core-js/modules/es.symbol.async-iterator.js");
13
+ require("core-js/modules/es.array.iterator.js");
14
+ require("core-js/modules/es.array.slice.js");
10
15
  require("core-js/modules/es.promise.js");
16
+ require("core-js/modules/es.promise.finally.js");
17
+ require("core-js/modules/web.dom-collections.iterator.js");
11
18
  var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
12
19
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
20
  var _utils = require("../utils");
14
21
  var _constants = require("../constants");
22
+ var _streamCore = require("./stream-core");
23
+ 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
+ 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; }
15
25
  /**
16
26
  * Stream message handler interface
17
27
  */
@@ -20,35 +30,73 @@ var _constants = require("../constants");
20
30
  * IframeReadableStream - Client-side readable stream
21
31
  * Used to receive stream data sent from the server
22
32
  */
23
- class IframeReadableStream {
33
+ class IframeReadableStream extends _streamCore.IframeStreamCore {
24
34
  constructor(streamId, requestId, messageHandler, options = {}) {
25
- var _options$type, _options$chunked;
26
- (0, _defineProperty2.default)(this, "_state", _constants.StreamState.PENDING);
27
- (0, _defineProperty2.default)(this, "chunks", []);
28
- this.streamId = streamId;
35
+ var _options$type, _options$chunked, _options$consume;
36
+ super(streamId, (_options$type = options.type) !== null && _options$type !== void 0 ? _options$type : _constants.StreamType.DATA, (_options$chunked = options.chunked) !== null && _options$chunked !== void 0 ? _options$chunked : true, options.metadata, (_options$consume = options.consume) !== null && _options$consume !== void 0 ? _options$consume : true, options.mode);
37
+ (0, _defineProperty2.default)(this, "heartbeatInFlight", null);
38
+ (0, _defineProperty2.default)(this, "lastActivityAt", Date.now());
39
+ /** pull/ack protocol */
40
+ (0, _defineProperty2.default)(this, "pullScheduled", false);
41
+ (0, _defineProperty2.default)(this, "highWaterMark", 16);
29
42
  this.requestId = requestId;
30
43
  this.messageHandler = messageHandler;
31
- this.type = (_options$type = options.type) !== null && _options$type !== void 0 ? _options$type : _constants.StreamType.DATA;
32
- this.chunked = (_options$chunked = options.chunked) !== null && _options$chunked !== void 0 ? _options$chunked : true;
33
- this.metadata = options.metadata;
34
44
  this.secretKey = options.secretKey;
45
+ this.idleTimeout = options.idleTimeout;
46
+ this.heartbeat = options.heartbeat;
35
47
 
36
48
  // Register stream message handler
37
49
  this.messageHandler.registerStreamHandler(streamId, this.handleStreamMessage.bind(this));
50
+ // Initial pull to start the stream (pull protocol)
51
+ this.requestMore(1);
52
+ }
53
+ postControl(type, body) {
54
+ var message = (0, _utils.createPostMessage)(type, this.requestId, {
55
+ secretKey: this.secretKey,
56
+ body: _objectSpread({
57
+ streamId: this.streamId
58
+ }, body)
59
+ });
60
+ this.messageHandler.postMessage(message);
61
+ }
62
+ requestMore(credit) {
63
+ if (!credit || credit <= 0) return;
64
+ if (this._state !== _constants.StreamState.PENDING && this._state !== _constants.StreamState.STREAMING) return;
65
+ try {
66
+ this.postControl(_constants.MessageType.STREAM_PULL, {
67
+ credit
68
+ });
69
+ } catch (_unused) {
70
+ /** ignore */
71
+ }
72
+ }
73
+ schedulePullIfNeeded() {
74
+ if (this.pullScheduled) return;
75
+ this.pullScheduled = true;
76
+ Promise.resolve().then(() => {
77
+ this.pullScheduled = false;
78
+ if (this._state !== _constants.StreamState.PENDING && this._state !== _constants.StreamState.STREAMING) return;
79
+ var need = Math.max(0, this.highWaterMark - this.chunks.length);
80
+ if (need > 0) {
81
+ this.requestMore(need);
82
+ }
83
+ });
38
84
  }
39
85
 
40
86
  /** Get stream state */
41
87
  get state() {
42
- return this._state;
88
+ return super.state;
43
89
  }
44
90
 
45
91
  /**
46
92
  * Handle stream message
47
93
  */
48
94
  handleStreamMessage(data) {
95
+ // Mark activity on any incoming stream message
96
+ this.lastActivityAt = Date.now();
49
97
  switch (data.type) {
50
98
  case _constants.StreamInternalMessageType.DATA:
51
- this.handleData(data.data, data.done);
99
+ this.handleData(data.data, data.done, data.seq);
52
100
  break;
53
101
  case _constants.StreamInternalMessageType.END:
54
102
  this.handleEnd();
@@ -59,17 +107,34 @@ class IframeReadableStream {
59
107
  case _constants.StreamInternalMessageType.CANCEL:
60
108
  this.handleCancel(data.reason);
61
109
  break;
110
+ case _constants.StreamInternalMessageType.PULL:
111
+ case _constants.StreamInternalMessageType.ACK:
112
+ // Control messages for writer side; ignore in readable stream
113
+ break;
62
114
  }
63
115
  }
64
116
 
65
117
  /**
66
118
  * Handle data chunk (internal method)
67
119
  */
68
- handleData(data, done) {
120
+ handleData(data, done, seq) {
69
121
  if (this._state !== _constants.StreamState.PENDING && this._state !== _constants.StreamState.STREAMING) return;
70
122
  this._state = _constants.StreamState.STREAMING;
71
123
  var decoded = this.decodeData(data);
72
124
  this.chunks.push(decoded);
125
+
126
+ // Ack this chunk (if seq provided)
127
+ if (typeof seq === 'number' && seq >= 0) {
128
+ try {
129
+ this.postControl(_constants.MessageType.STREAM_ACK, {
130
+ seq
131
+ });
132
+ } catch (_unused2) {
133
+ /** ignore */
134
+ }
135
+ }
136
+ this.notifyWaiters();
137
+ this.schedulePullIfNeeded();
73
138
  if (done) {
74
139
  this.handleEnd();
75
140
  }
@@ -88,15 +153,9 @@ class IframeReadableStream {
88
153
  handleEnd() {
89
154
  var _this$onEndCallback;
90
155
  if (this._state === _constants.StreamState.ENDED) return;
91
- this._state = _constants.StreamState.ENDED;
156
+ super.end();
92
157
  this.messageHandler.unregisterStreamHandler(this.streamId);
93
- if (this.resolveRead) {
94
- // Merge all data chunks
95
- var result = this.mergeChunks();
96
- this.resolveRead(result);
97
- this.resolveRead = undefined;
98
- this.rejectRead = undefined;
99
- }
158
+ this.notifyWaiters();
100
159
  (_this$onEndCallback = this.onEndCallback) === null || _this$onEndCallback === void 0 || _this$onEndCallback.call(this);
101
160
  }
102
161
 
@@ -120,13 +179,9 @@ class IframeReadableStream {
120
179
  handleError(error) {
121
180
  var _this$onErrorCallback;
122
181
  if (this._state === _constants.StreamState.ENDED || this._state === _constants.StreamState.ERROR) return;
123
- this._state = _constants.StreamState.ERROR;
182
+ super.fail(error);
124
183
  this.messageHandler.unregisterStreamHandler(this.streamId);
125
- if (this.rejectRead) {
126
- this.rejectRead(error);
127
- this.resolveRead = undefined;
128
- this.rejectRead = undefined;
129
- }
184
+ this.notifyWaiters();
130
185
  (_this$onErrorCallback = this.onErrorCallback) === null || _this$onErrorCallback === void 0 || _this$onErrorCallback.call(this, error);
131
186
  }
132
187
 
@@ -134,35 +189,229 @@ class IframeReadableStream {
134
189
  * Stream cancelled (internal method)
135
190
  */
136
191
  handleCancel(reason) {
137
- var _this$onErrorCallback2;
192
+ this.cancelInternal(reason, false);
193
+ }
194
+
195
+ /**
196
+ * Cancel/abort core logic
197
+ * @param reason cancel reason
198
+ * @param notifyRemote whether to notify remote side (send stream_cancel)
199
+ */
200
+ cancelInternal(reason, notifyRemote = false) {
138
201
  if (this._state === _constants.StreamState.ENDED || this._state === _constants.StreamState.ERROR || this._state === _constants.StreamState.CANCELLED) return;
139
- this._state = _constants.StreamState.CANCELLED;
202
+ super.cancel((0, _constants.formatMessage)(_constants.Messages.STREAM_CANCELLED, reason || ''));
203
+ this.notifyWaiters();
204
+ if (notifyRemote) {
205
+ try {
206
+ /** Notify server to cancel */
207
+ var _message = (0, _utils.createPostMessage)(_constants.MessageType.STREAM_CANCEL, this.requestId, {
208
+ secretKey: this.secretKey,
209
+ body: {
210
+ streamId: this.streamId,
211
+ reason
212
+ }
213
+ });
214
+ this.messageHandler.postMessage(_message);
215
+ } catch (_unused3) {
216
+ /** ignore send failures on cancel/abort */
217
+ }
218
+ }
140
219
  this.messageHandler.unregisterStreamHandler(this.streamId);
141
- var error = new Error(reason || _constants.Messages.STREAM_CANCELLED);
142
- if (this.rejectRead) {
143
- this.rejectRead(error);
144
- this.resolveRead = undefined;
145
- this.rejectRead = undefined;
220
+ if (this.terminalError) {
221
+ var _this$onErrorCallback2;
222
+ (_this$onErrorCallback2 = this.onErrorCallback) === null || _this$onErrorCallback2 === void 0 || _this$onErrorCallback2.call(this, this.terminalError);
223
+ } else {
224
+ var _this$onErrorCallback3;
225
+ (_this$onErrorCallback3 = this.onErrorCallback) === null || _this$onErrorCallback3 === void 0 || _this$onErrorCallback3.call(this, new Error(_constants.Messages.STREAM_CANCELLED));
146
226
  }
147
- (_this$onErrorCallback2 = this.onErrorCallback) === null || _this$onErrorCallback2 === void 0 || _this$onErrorCallback2.call(this, error);
227
+ }
228
+ performHeartbeat() {
229
+ var _this = this;
230
+ return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee() {
231
+ return _regenerator.default.wrap(function (_context) {
232
+ while (1) switch (_context.prev = _context.next) {
233
+ case 0:
234
+ if (_this.heartbeat) {
235
+ _context.next = 1;
236
+ break;
237
+ }
238
+ return _context.abrupt("return", false);
239
+ case 1:
240
+ if (!_this.heartbeatInFlight) {
241
+ _this.heartbeatInFlight = Promise.resolve().then(() => _this.heartbeat()).catch(() => false).finally(() => {
242
+ _this.heartbeatInFlight = null;
243
+ });
244
+ }
245
+ return _context.abrupt("return", _this.heartbeatInFlight);
246
+ case 2:
247
+ case "end":
248
+ return _context.stop();
249
+ }
250
+ }, _callee);
251
+ }))();
252
+ }
253
+ waitForChangeWithIdleTimeout() {
254
+ var _this2 = this;
255
+ return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee2() {
256
+ var state0, snapshot, timerId, stateAfter, ok;
257
+ return _regenerator.default.wrap(function (_context2) {
258
+ while (1) switch (_context2.prev = _context2.next) {
259
+ case 0:
260
+ state0 = _this2._state;
261
+ if (!(state0 === _constants.StreamState.ENDED || state0 === _constants.StreamState.ERROR || state0 === _constants.StreamState.CANCELLED)) {
262
+ _context2.next = 1;
263
+ break;
264
+ }
265
+ return _context2.abrupt("return");
266
+ case 1:
267
+ if (!(!_this2.idleTimeout || _this2.idleTimeout <= 0)) {
268
+ _context2.next = 3;
269
+ break;
270
+ }
271
+ _context2.next = 2;
272
+ return _this2.waitForChange();
273
+ case 2:
274
+ return _context2.abrupt("return");
275
+ case 3:
276
+ snapshot = _this2.lastActivityAt;
277
+ timerId = null;
278
+ _context2.next = 4;
279
+ return Promise.race([_this2.waitForChange(), new Promise(resolve => {
280
+ timerId = setTimeout(resolve, _this2.idleTimeout);
281
+ })]);
282
+ case 4:
283
+ if (timerId) clearTimeout(timerId);
284
+
285
+ // If stream already moved to a terminal state, just return
286
+ stateAfter = _this2._state;
287
+ if (!(stateAfter === _constants.StreamState.ENDED || stateAfter === _constants.StreamState.ERROR || stateAfter === _constants.StreamState.CANCELLED)) {
288
+ _context2.next = 5;
289
+ break;
290
+ }
291
+ return _context2.abrupt("return");
292
+ case 5:
293
+ if (!(_this2.lastActivityAt !== snapshot)) {
294
+ _context2.next = 6;
295
+ break;
296
+ }
297
+ return _context2.abrupt("return");
298
+ case 6:
299
+ _context2.next = 7;
300
+ return _this2.performHeartbeat();
301
+ case 7:
302
+ ok = _context2.sent;
303
+ if (!ok) {
304
+ _context2.next = 8;
305
+ break;
306
+ }
307
+ // Treat heartbeat as activity to prevent immediate re-trigger
308
+ _this2.lastActivityAt = Date.now();
309
+ return _context2.abrupt("return");
310
+ case 8:
311
+ // Connection likely dead: fail the stream
312
+ _this2.handleError(new Error((0, _constants.formatMessage)(_constants.Messages.STREAM_TIMEOUT, _this2.idleTimeout)));
313
+ case 9:
314
+ case "end":
315
+ return _context2.stop();
316
+ }
317
+ }, _callee2);
318
+ }))();
148
319
  }
149
320
 
150
321
  /**
151
322
  * Read all data
152
323
  */
153
324
  read() {
154
- return new Promise((resolve, reject) => {
155
- if (this._state === _constants.StreamState.ENDED) {
156
- resolve(this.mergeChunks());
157
- return;
158
- }
159
- if (this._state === _constants.StreamState.ERROR || this._state === _constants.StreamState.CANCELLED) {
160
- reject(new Error(_constants.Messages.STREAM_READ_ERROR));
161
- return;
162
- }
163
- this.resolveRead = resolve;
164
- this.rejectRead = reject;
165
- });
325
+ var _this3 = this;
326
+ return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3() {
327
+ return _regenerator.default.wrap(function (_context3) {
328
+ while (1) switch (_context3.prev = _context3.next) {
329
+ case 0:
330
+ if (!(_this3._state === _constants.StreamState.ENDED)) {
331
+ _context3.next = 1;
332
+ break;
333
+ }
334
+ return _context3.abrupt("return", _this3.mergeChunks());
335
+ case 1:
336
+ if (!(_this3._state === _constants.StreamState.ERROR || _this3._state === _constants.StreamState.CANCELLED)) {
337
+ _context3.next = 2;
338
+ break;
339
+ }
340
+ throw _this3.terminalError || new Error(_constants.Messages.STREAM_READ_ERROR);
341
+ case 2:
342
+ if (!(_this3._state === _constants.StreamState.PENDING || _this3._state === _constants.StreamState.STREAMING)) {
343
+ _context3.next = 4;
344
+ break;
345
+ }
346
+ if (_this3.chunks.length === 0) {
347
+ _this3.requestMore(1);
348
+ }
349
+ _context3.next = 3;
350
+ return _this3.waitForChangeWithIdleTimeout();
351
+ case 3:
352
+ _context3.next = 2;
353
+ break;
354
+ case 4:
355
+ if (!(_this3._state === _constants.StreamState.ENDED)) {
356
+ _context3.next = 5;
357
+ break;
358
+ }
359
+ return _context3.abrupt("return", _this3.mergeChunks());
360
+ case 5:
361
+ throw _this3.terminalError || new Error(_constants.Messages.STREAM_READ_ERROR);
362
+ case 6:
363
+ case "end":
364
+ return _context3.stop();
365
+ }
366
+ }, _callee3);
367
+ }))();
368
+ }
369
+
370
+ /**
371
+ * Read all chunks as an array
372
+ */
373
+ readAll() {
374
+ var _this4 = this;
375
+ return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee4() {
376
+ return _regenerator.default.wrap(function (_context4) {
377
+ while (1) switch (_context4.prev = _context4.next) {
378
+ case 0:
379
+ if (!(_this4._state === _constants.StreamState.ENDED)) {
380
+ _context4.next = 1;
381
+ break;
382
+ }
383
+ return _context4.abrupt("return", _this4.chunks.slice());
384
+ case 1:
385
+ if (!(_this4._state === _constants.StreamState.ERROR || _this4._state === _constants.StreamState.CANCELLED)) {
386
+ _context4.next = 2;
387
+ break;
388
+ }
389
+ throw _this4.terminalError || new Error(_constants.Messages.STREAM_READ_ERROR);
390
+ case 2:
391
+ if (!(_this4._state === _constants.StreamState.PENDING || _this4._state === _constants.StreamState.STREAMING)) {
392
+ _context4.next = 4;
393
+ break;
394
+ }
395
+ _this4.schedulePullIfNeeded();
396
+ _context4.next = 3;
397
+ return _this4.waitForChangeWithIdleTimeout();
398
+ case 3:
399
+ _context4.next = 2;
400
+ break;
401
+ case 4:
402
+ if (!(_this4._state === _constants.StreamState.ENDED)) {
403
+ _context4.next = 5;
404
+ break;
405
+ }
406
+ return _context4.abrupt("return", _this4.chunks.slice());
407
+ case 5:
408
+ throw _this4.terminalError || new Error(_constants.Messages.STREAM_READ_ERROR);
409
+ case 6:
410
+ case "end":
411
+ return _context4.stop();
412
+ }
413
+ }, _callee4);
414
+ }))();
166
415
  }
167
416
 
168
417
  /**
@@ -173,62 +422,69 @@ class IframeReadableStream {
173
422
  var stream = this;
174
423
  return {
175
424
  next() {
176
- return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee() {
177
- return _regenerator.default.wrap(function (_context) {
178
- while (1) switch (_context.prev = _context.next) {
425
+ return (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee5() {
426
+ var value;
427
+ return _regenerator.default.wrap(function (_context5) {
428
+ while (1) switch (_context5.prev = _context5.next) {
179
429
  case 0:
180
430
  if (!(index >= stream.chunks.length)) {
181
- _context.next = 3;
431
+ _context5.next = 3;
182
432
  break;
183
433
  }
184
434
  if (!(stream._state === _constants.StreamState.ENDED || stream._state === _constants.StreamState.ERROR || stream._state === _constants.StreamState.CANCELLED)) {
185
- _context.next = 1;
435
+ _context5.next = 1;
186
436
  break;
187
437
  }
188
- return _context.abrupt("return", {
438
+ return _context5.abrupt("return", {
189
439
  done: true,
190
440
  value: undefined
191
441
  });
192
442
  case 1:
193
- _context.next = 2;
194
- return new Promise(resolve => setTimeout(resolve, 10));
443
+ // Consumer is ready: request at least 1 chunk
444
+ stream.requestMore(1);
445
+ _context5.next = 2;
446
+ return stream.waitForChangeWithIdleTimeout();
195
447
  case 2:
196
- _context.next = 0;
448
+ _context5.next = 0;
197
449
  break;
198
450
  case 3:
199
- return _context.abrupt("return", {
451
+ value = stream.chunks[index++];
452
+ if (stream.consume) {
453
+ /**
454
+ * Drop already-consumed chunks to reduce memory usage.
455
+ * Use compaction (slice) to avoid O(n) shift per chunk.
456
+ */
457
+ if (index > 128) {
458
+ stream.chunks = stream.chunks.slice(index);
459
+ index = 0;
460
+ }
461
+ }
462
+ return _context5.abrupt("return", {
200
463
  done: false,
201
- value: stream.chunks[index++]
464
+ value
202
465
  });
203
466
  case 4:
204
467
  case "end":
205
- return _context.stop();
468
+ return _context5.stop();
206
469
  }
207
- }, _callee);
470
+ }, _callee5);
208
471
  }))();
209
472
  }
210
473
  };
211
474
  }
212
475
 
476
+ /**
477
+ * Abort stream (is alias of cancel method)
478
+ */
479
+ abort(reason) {
480
+ this.cancelInternal(reason, true);
481
+ }
482
+
213
483
  /**
214
484
  * Cancel stream
215
485
  */
216
486
  cancel(reason) {
217
- if (this._state !== _constants.StreamState.PENDING && this._state !== _constants.StreamState.STREAMING) return;
218
- this._state = _constants.StreamState.CANCELLED;
219
-
220
- // Notify server to cancel
221
- var message = (0, _utils.createPostMessage)(_constants.MessageType.STREAM_CANCEL, this.requestId, {
222
- secretKey: this.secretKey,
223
- body: {
224
- streamId: this.streamId,
225
- reason
226
- },
227
- role: _constants.MessageRole.CLIENT,
228
- creatorId: this.messageHandler.id
229
- });
230
- this.messageHandler.postMessage(message);
231
- this.messageHandler.unregisterStreamHandler(this.streamId);
487
+ this.cancelInternal(reason, true);
232
488
  }
233
489
 
234
490
  /**
@@ -0,0 +1,44 @@
1
+ import type { StreamState, StreamType, StreamMessageData, WritableStreamMode } from './types';
2
+ /**
3
+ * Shared stream core (internal).
4
+ *
5
+ * - Read side: buffer + waiters + consume compaction
6
+ * - Common: state + terminal error + basic waiter mechanics
7
+ *
8
+ * NOTE:
9
+ * This is an internal abstraction to share logic between Readable/Writable streams.
10
+ * Public API remains `IframeReadableStream` / `IframeWritableStream`.
11
+ */
12
+ export declare class IframeStreamCore<T = any> {
13
+ readonly streamId: string;
14
+ readonly type: StreamType;
15
+ readonly chunked: boolean;
16
+ readonly metadata?: Record<string, any>;
17
+ readonly mode?: WritableStreamMode;
18
+ protected _state: StreamState;
19
+ protected terminalError?: Error;
20
+ protected chunks: T[];
21
+ protected waiters: Array<() => void>;
22
+ protected consume: boolean;
23
+ constructor(streamId: string, type: StreamType, chunked: boolean, metadata: Record<string, any> | undefined, consume: boolean, mode?: WritableStreamMode);
24
+ get state(): StreamState;
25
+ protected notifyWaiters(): void;
26
+ protected waitForChange(): Promise<void>;
27
+ protected fail(error: Error): void;
28
+ protected cancel(reason?: string): void;
29
+ /**
30
+ * Read-side: enqueue a decoded chunk
31
+ */
32
+ protected pushChunk(chunk: T): void;
33
+ /**
34
+ * Read-side: mark end
35
+ */
36
+ protected end(): void;
37
+ /**
38
+ * Handle inbound message (shared).
39
+ * - ReadableStream will use DATA/END/ERROR/CANCEL
40
+ * - WritableStream may use PULL/ACK/CANCEL separately, so this is intentionally minimal.
41
+ */
42
+ handleInboundMessage(_data: StreamMessageData): void;
43
+ }
44
+ //# sourceMappingURL=stream-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-core.d.ts","sourceRoot":"","sources":["../../src/stream/stream-core.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAG9F;;;;;;;;;GASG;AACH,qBAAa,gBAAgB,CAAC,CAAC,GAAG,GAAG;IACnC,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,IAAI,EAAE,UAAU,CAAC;IACjC,SAAgB,OAAO,EAAE,OAAO,CAAC;IACjC,SAAgB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC/C,SAAgB,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAE1C,SAAS,CAAC,MAAM,EAAE,WAAW,CAA+B;IAC5D,SAAS,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC;IAEhC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,CAAM;IAC3B,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IAE1C,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;gBAGzB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EACzC,OAAO,EAAE,OAAO,EAChB,IAAI,CAAC,EAAE,kBAAkB;IAU3B,IAAW,KAAK,IAAI,WAAW,CAE9B;IAED,SAAS,CAAC,aAAa,IAAI,IAAI;IAa/B,SAAS,CAAC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAaxC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAOlC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAWvC;;OAEG;IACH,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IAOnC;;OAEG;IACH,SAAS,CAAC,GAAG,IAAI,IAAI;IAMrB;;;;OAIG;IACI,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;CAG5D"}
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.IframeStreamCore = void 0;
8
+ require("core-js/modules/es.promise.js");
9
+ require("core-js/modules/web.dom-collections.for-each.js");
10
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
+ var _constants = require("../constants");
12
+ /**
13
+ * Shared stream core (internal).
14
+ *
15
+ * - Read side: buffer + waiters + consume compaction
16
+ * - Common: state + terminal error + basic waiter mechanics
17
+ *
18
+ * NOTE:
19
+ * This is an internal abstraction to share logic between Readable/Writable streams.
20
+ * Public API remains `IframeReadableStream` / `IframeWritableStream`.
21
+ */
22
+ class IframeStreamCore {
23
+ constructor(streamId, type, chunked, metadata, consume, mode) {
24
+ (0, _defineProperty2.default)(this, "_state", _constants.StreamState.PENDING);
25
+ (0, _defineProperty2.default)(this, "chunks", []);
26
+ (0, _defineProperty2.default)(this, "waiters", []);
27
+ this.streamId = streamId;
28
+ this.type = type;
29
+ this.chunked = chunked;
30
+ this.metadata = metadata;
31
+ this.consume = consume;
32
+ this.mode = mode;
33
+ }
34
+ get state() {
35
+ return this._state;
36
+ }
37
+ notifyWaiters() {
38
+ if (this.waiters.length === 0) return;
39
+ var list = this.waiters;
40
+ this.waiters = [];
41
+ list.forEach(fn => {
42
+ try {
43
+ fn();
44
+ } catch (_unused) {
45
+ /** ignore */
46
+ }
47
+ });
48
+ }
49
+ waitForChange() {
50
+ if (this._state === _constants.StreamState.ENDED || this._state === _constants.StreamState.ERROR || this._state === _constants.StreamState.CANCELLED) {
51
+ return Promise.resolve();
52
+ }
53
+ return new Promise(resolve => {
54
+ this.waiters.push(resolve);
55
+ });
56
+ }
57
+ fail(error) {
58
+ if (this._state === _constants.StreamState.ENDED || this._state === _constants.StreamState.ERROR) return;
59
+ this._state = _constants.StreamState.ERROR;
60
+ this.terminalError = error;
61
+ this.notifyWaiters();
62
+ }
63
+ cancel(reason) {
64
+ if (this._state === _constants.StreamState.ENDED || this._state === _constants.StreamState.ERROR || this._state === _constants.StreamState.CANCELLED) return;
65
+ this._state = _constants.StreamState.CANCELLED;
66
+ this.terminalError = new Error(reason || _constants.Messages.STREAM_CANCELLED);
67
+ this.notifyWaiters();
68
+ }
69
+
70
+ /**
71
+ * Read-side: enqueue a decoded chunk
72
+ */
73
+ pushChunk(chunk) {
74
+ if (this._state !== _constants.StreamState.PENDING && this._state !== _constants.StreamState.STREAMING) return;
75
+ this._state = _constants.StreamState.STREAMING;
76
+ this.chunks.push(chunk);
77
+ this.notifyWaiters();
78
+ }
79
+
80
+ /**
81
+ * Read-side: mark end
82
+ */
83
+ end() {
84
+ if (this._state === _constants.StreamState.ENDED) return;
85
+ this._state = _constants.StreamState.ENDED;
86
+ this.notifyWaiters();
87
+ }
88
+
89
+ /**
90
+ * Handle inbound message (shared).
91
+ * - ReadableStream will use DATA/END/ERROR/CANCEL
92
+ * - WritableStream may use PULL/ACK/CANCEL separately, so this is intentionally minimal.
93
+ */
94
+ handleInboundMessage(_data) {
95
+ // Intentionally left blank in core.
96
+ }
97
+ }
98
+ exports.IframeStreamCore = IframeStreamCore;