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.
- package/README.CN.md +54 -7
- package/README.md +64 -11
- package/esm/api/client.js +79 -0
- package/esm/api/server.js +59 -0
- package/esm/constants/index.js +257 -0
- package/esm/constants/messages.js +155 -0
- package/esm/core/client-server.js +329 -0
- package/esm/core/client.js +873 -0
- package/esm/core/request.js +27 -0
- package/esm/core/response.js +451 -0
- package/esm/core/server.js +767 -0
- package/esm/index.js +21 -0
- package/esm/interceptors/index.js +122 -0
- package/esm/message/channel.js +181 -0
- package/esm/message/dispatcher.js +380 -0
- package/esm/message/index.js +2 -0
- package/esm/stream/file-stream.js +289 -0
- package/esm/stream/index.js +44 -0
- package/esm/stream/readable-stream.js +500 -0
- package/esm/stream/stream-core.js +91 -0
- package/esm/stream/types.js +1 -0
- package/esm/stream/writable-stream.js +582 -0
- package/esm/types/index.js +1 -0
- package/esm/utils/ack-meta.js +53 -0
- package/esm/utils/cache.js +147 -0
- package/esm/utils/cookie.js +352 -0
- package/esm/utils/debug.js +521 -0
- package/esm/utils/error.js +27 -0
- package/esm/utils/index.js +178 -0
- package/esm/utils/origin.js +28 -0
- package/esm/utils/path-match.js +148 -0
- package/esm/utils/protocol.js +157 -0
- package/library/api/client.d.ts.map +1 -1
- package/library/api/client.js +8 -1
- package/library/api/server.d.ts.map +1 -1
- package/library/api/server.js +4 -1
- package/library/constants/index.d.ts +25 -1
- package/library/constants/index.d.ts.map +1 -1
- package/library/constants/index.js +30 -5
- package/library/constants/messages.d.ts +5 -0
- package/library/constants/messages.d.ts.map +1 -1
- package/library/constants/messages.js +5 -0
- package/library/core/client-server.d.ts +3 -2
- package/library/core/client-server.d.ts.map +1 -1
- package/library/core/client-server.js +51 -4
- package/library/core/client.d.ts +4 -1
- package/library/core/client.d.ts.map +1 -1
- package/library/core/client.js +74 -31
- package/library/core/response.d.ts +21 -3
- package/library/core/response.d.ts.map +1 -1
- package/library/core/response.js +46 -6
- package/library/core/server.d.ts +28 -1
- package/library/core/server.d.ts.map +1 -1
- package/library/core/server.js +180 -19
- package/library/message/channel.d.ts +6 -0
- package/library/message/channel.d.ts.map +1 -1
- package/library/message/dispatcher.d.ts +22 -0
- package/library/message/dispatcher.d.ts.map +1 -1
- package/library/message/dispatcher.js +92 -0
- package/library/stream/file-stream.d.ts +4 -0
- package/library/stream/file-stream.d.ts.map +1 -1
- package/library/stream/file-stream.js +61 -33
- package/library/stream/index.d.ts.map +1 -1
- package/library/stream/index.js +2 -0
- package/library/stream/readable-stream.d.ts +30 -11
- package/library/stream/readable-stream.d.ts.map +1 -1
- package/library/stream/readable-stream.js +329 -73
- package/library/stream/stream-core.d.ts +44 -0
- package/library/stream/stream-core.d.ts.map +1 -0
- package/library/stream/stream-core.js +98 -0
- package/library/stream/types.d.ts +90 -3
- package/library/stream/types.d.ts.map +1 -1
- package/library/stream/writable-stream.d.ts +40 -12
- package/library/stream/writable-stream.d.ts.map +1 -1
- package/library/stream/writable-stream.js +391 -195
- package/library/types/index.d.ts +70 -3
- package/library/types/index.d.ts.map +1 -1
- package/library/utils/ack-meta.d.ts +2 -0
- package/library/utils/ack-meta.d.ts.map +1 -0
- package/library/utils/ack-meta.js +59 -0
- package/library/utils/index.d.ts +1 -0
- package/library/utils/index.d.ts.map +1 -1
- package/library/utils/index.js +16 -0
- package/library/utils/origin.d.ts +14 -0
- package/library/utils/origin.d.ts.map +1 -0
- package/library/utils/origin.js +34 -0
- package/package.json +31 -7
- package/react/README.md +16 -0
- package/react/esm/index.js +284 -0
- package/react/library/index.d.ts +1 -1
- package/react/library/index.d.ts.map +1 -1
- package/react/library/index.js +7 -4
- package/react/package.json +24 -2
- package/library/__tests__/channel.test.ts +0 -432
- package/library/__tests__/coverage-branches.test.ts +0 -356
- package/library/__tests__/debug.test.ts +0 -610
- package/library/__tests__/dispatcher.test.ts +0 -485
- package/library/__tests__/interceptors.test.ts +0 -146
- package/library/__tests__/requestIframe.test.ts +0 -5590
- package/library/__tests__/server.test.ts +0 -738
- package/library/__tests__/stream.test.ts +0 -726
- package/library/__tests__/utils.test.ts +0 -473
- package/library/api/client.d.js +0 -5
- package/library/api/server.d.js +0 -5
- package/library/constants/index.d.js +0 -36
- package/library/constants/messages.d.js +0 -5
- package/library/core/client.d.js +0 -5
- package/library/core/message-handler.d.ts +0 -110
- package/library/core/message-handler.d.ts.map +0 -1
- package/library/core/message-handler.js +0 -320
- package/library/core/request-response.d.ts +0 -59
- package/library/core/request-response.d.ts.map +0 -1
- package/library/core/request-response.js +0 -337
- package/library/core/request.d.js +0 -5
- package/library/core/response.d.js +0 -5
- package/library/core/server-base.d.ts +0 -86
- package/library/core/server-base.d.ts.map +0 -1
- package/library/core/server-base.js +0 -257
- package/library/core/server-client.d.js +0 -5
- package/library/core/server-client.d.ts +0 -101
- package/library/core/server-client.d.ts.map +0 -1
- package/library/core/server-client.js +0 -266
- package/library/core/server.d.js +0 -5
- package/library/interceptors/index.d.js +0 -5
- package/library/message/channel.d.js +0 -5
- package/library/message/dispatcher.d.js +0 -5
- package/library/message/index.d.js +0 -25
- package/library/stream/file-stream.d.js +0 -4
- package/library/stream/index.d.js +0 -58
- package/library/stream/readable-stream.d.js +0 -5
- package/library/stream/types.d.js +0 -5
- package/library/stream/writable-stream.d.js +0 -5
- package/library/types/index.d.js +0 -5
- package/library/utils/cache.d.js +0 -5
- package/library/utils/cookie.d.js +0 -5
- package/library/utils/debug.d.js +0 -5
- package/library/utils/index.d.js +0 -94
- package/library/utils/path-match.d.js +0 -5
- package/library/utils/protocol.d.js +0 -5
- package/react/library/__tests__/index.test.d.ts +0 -2
- package/react/library/__tests__/index.test.d.ts.map +0 -1
- 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,
|
|
27
|
-
(0, _defineProperty2.default)(this, "
|
|
28
|
-
this
|
|
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
|
|
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
|
-
|
|
156
|
+
super.end();
|
|
92
157
|
this.messageHandler.unregisterStreamHandler(this.streamId);
|
|
93
|
-
|
|
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
|
-
|
|
182
|
+
super.fail(error);
|
|
124
183
|
this.messageHandler.unregisterStreamHandler(this.streamId);
|
|
125
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
this.
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
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
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
|
177
|
-
|
|
178
|
-
|
|
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
|
-
|
|
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
|
-
|
|
435
|
+
_context5.next = 1;
|
|
186
436
|
break;
|
|
187
437
|
}
|
|
188
|
-
return
|
|
438
|
+
return _context5.abrupt("return", {
|
|
189
439
|
done: true,
|
|
190
440
|
value: undefined
|
|
191
441
|
});
|
|
192
442
|
case 1:
|
|
193
|
-
|
|
194
|
-
|
|
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
|
-
|
|
448
|
+
_context5.next = 0;
|
|
197
449
|
break;
|
|
198
450
|
case 3:
|
|
199
|
-
|
|
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
|
|
464
|
+
value
|
|
202
465
|
});
|
|
203
466
|
case 4:
|
|
204
467
|
case "end":
|
|
205
|
-
return
|
|
468
|
+
return _context5.stop();
|
|
206
469
|
}
|
|
207
|
-
},
|
|
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
|
-
|
|
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;
|