request-iframe 0.1.0 → 0.2.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/QUICKSTART.CN.md +4 -2
- package/QUICKSTART.md +4 -2
- package/README.CN.md +302 -54
- package/README.md +281 -36
- package/cdn/request-iframe-react.umd.js +3354 -0
- package/cdn/request-iframe-react.umd.js.map +1 -0
- package/cdn/request-iframe-react.umd.min.js +2 -0
- package/cdn/request-iframe-react.umd.min.js.map +1 -0
- package/cdn/request-iframe.umd.js +19735 -0
- package/cdn/request-iframe.umd.js.map +1 -0
- package/cdn/request-iframe.umd.min.js +4 -0
- package/cdn/request-iframe.umd.min.js.map +1 -0
- package/esm/api/client.js +31 -22
- package/esm/api/endpoint.js +229 -0
- package/esm/api/server.js +19 -9
- package/esm/constants/debug.js +17 -0
- package/esm/constants/index.js +115 -66
- package/esm/constants/log.js +11 -0
- package/esm/constants/messages.js +6 -1
- package/esm/constants/warn-once.js +15 -0
- package/esm/endpoint/facade.js +390 -0
- package/esm/endpoint/heartbeat/heartbeat.js +60 -0
- package/esm/endpoint/heartbeat/ping.js +20 -0
- package/esm/endpoint/index.js +13 -0
- package/esm/endpoint/infra/hub.js +316 -0
- package/esm/endpoint/infra/inbox.js +232 -0
- package/esm/endpoint/infra/outbox.js +408 -0
- package/esm/endpoint/stream/dispatcher.js +58 -0
- package/esm/endpoint/stream/errors.js +27 -0
- package/esm/endpoint/stream/factory.js +76 -0
- package/esm/endpoint/stream/file-auto-resolve.js +34 -0
- package/esm/endpoint/stream/file-writable.js +105 -0
- package/esm/endpoint/stream/handler.js +26 -0
- package/esm/{core → impl}/client.js +243 -320
- package/esm/{core → impl}/response.js +120 -154
- package/esm/impl/server.js +568 -0
- package/esm/index.js +13 -6
- package/esm/message/ack.js +27 -0
- package/esm/message/channel-cache.js +108 -0
- package/esm/message/channel.js +92 -5
- package/esm/message/dispatcher.js +149 -98
- package/esm/stream/error.js +22 -0
- package/esm/stream/index.js +3 -1
- package/esm/stream/readable-stream.js +101 -26
- package/esm/stream/stream-core.js +121 -3
- package/esm/stream/writable-stream.js +368 -43
- package/esm/utils/ack.js +36 -0
- package/esm/utils/blob.js +16 -0
- package/esm/utils/cache.js +25 -76
- package/esm/utils/content-type.js +81 -0
- package/esm/utils/debug.js +157 -180
- package/esm/utils/hooks.js +130 -0
- package/esm/utils/id.js +14 -0
- package/esm/utils/iframe.js +20 -0
- package/esm/utils/index.js +12 -162
- package/esm/utils/is.js +3 -0
- package/esm/utils/logger.js +55 -0
- package/esm/utils/origin.js +3 -1
- package/esm/utils/promise.js +3 -0
- package/esm/utils/window.js +31 -0
- package/library/api/client.d.ts.map +1 -1
- package/library/api/client.js +32 -23
- package/library/api/endpoint.d.ts +23 -0
- package/library/api/endpoint.d.ts.map +1 -0
- package/library/api/endpoint.js +235 -0
- package/library/api/server.d.ts +4 -1
- package/library/api/server.d.ts.map +1 -1
- package/library/api/server.js +19 -9
- package/library/constants/debug.d.ts +18 -0
- package/library/constants/debug.d.ts.map +1 -0
- package/library/constants/debug.js +23 -0
- package/library/constants/index.d.ts +58 -7
- package/library/constants/index.d.ts.map +1 -1
- package/library/constants/index.js +143 -67
- package/library/constants/log.d.ts +12 -0
- package/library/constants/log.d.ts.map +1 -0
- package/library/constants/log.js +17 -0
- package/library/constants/messages.d.ts +6 -1
- package/library/constants/messages.d.ts.map +1 -1
- package/library/constants/messages.js +6 -1
- package/library/constants/warn-once.d.ts +12 -0
- package/library/constants/warn-once.d.ts.map +1 -0
- package/library/constants/warn-once.js +22 -0
- package/library/endpoint/facade.d.ts +238 -0
- package/library/endpoint/facade.d.ts.map +1 -0
- package/library/endpoint/facade.js +398 -0
- package/library/endpoint/heartbeat/heartbeat.d.ts +34 -0
- package/library/endpoint/heartbeat/heartbeat.d.ts.map +1 -0
- package/library/endpoint/heartbeat/heartbeat.js +67 -0
- package/library/endpoint/heartbeat/ping.d.ts +18 -0
- package/library/endpoint/heartbeat/ping.d.ts.map +1 -0
- package/library/endpoint/heartbeat/ping.js +26 -0
- package/library/endpoint/index.d.ts +16 -0
- package/library/endpoint/index.d.ts.map +1 -0
- package/library/endpoint/index.js +114 -0
- package/library/endpoint/infra/hub.d.ts +170 -0
- package/library/endpoint/infra/hub.d.ts.map +1 -0
- package/library/endpoint/infra/hub.js +323 -0
- package/library/endpoint/infra/inbox.d.ts +73 -0
- package/library/endpoint/infra/inbox.d.ts.map +1 -0
- package/library/endpoint/infra/inbox.js +239 -0
- package/library/endpoint/infra/outbox.d.ts +149 -0
- package/library/endpoint/infra/outbox.d.ts.map +1 -0
- package/library/endpoint/infra/outbox.js +415 -0
- package/library/endpoint/stream/dispatcher.d.ts +33 -0
- package/library/endpoint/stream/dispatcher.d.ts.map +1 -0
- package/library/endpoint/stream/dispatcher.js +66 -0
- package/library/endpoint/stream/errors.d.ts +20 -0
- package/library/endpoint/stream/errors.d.ts.map +1 -0
- package/library/endpoint/stream/errors.js +32 -0
- package/library/endpoint/stream/factory.d.ts +44 -0
- package/library/endpoint/stream/factory.d.ts.map +1 -0
- package/library/endpoint/stream/factory.js +82 -0
- package/library/endpoint/stream/file-auto-resolve.d.ts +26 -0
- package/library/endpoint/stream/file-auto-resolve.d.ts.map +1 -0
- package/library/endpoint/stream/file-auto-resolve.js +41 -0
- package/library/endpoint/stream/file-writable.d.ts +33 -0
- package/library/endpoint/stream/file-writable.d.ts.map +1 -0
- package/library/endpoint/stream/file-writable.js +115 -0
- package/library/endpoint/stream/handler.d.ts +20 -0
- package/library/endpoint/stream/handler.d.ts.map +1 -0
- package/library/endpoint/stream/handler.js +32 -0
- package/library/{core → impl}/client.d.ts +16 -13
- package/library/impl/client.d.ts.map +1 -0
- package/library/{core → impl}/client.js +254 -333
- package/library/{core → impl}/request.d.ts.map +1 -1
- package/library/{core → impl}/response.d.ts +7 -12
- package/library/impl/response.d.ts.map +1 -0
- package/library/{core → impl}/response.js +120 -154
- package/library/{core → impl}/server.d.ts +26 -55
- package/library/impl/server.d.ts.map +1 -0
- package/library/impl/server.js +575 -0
- package/library/index.d.ts +13 -6
- package/library/index.d.ts.map +1 -1
- package/library/index.js +16 -16
- package/library/message/ack.d.ts +15 -0
- package/library/message/ack.d.ts.map +1 -0
- package/library/message/ack.js +33 -0
- package/library/message/channel-cache.d.ts +26 -0
- package/library/message/channel-cache.d.ts.map +1 -0
- package/library/message/channel-cache.js +115 -0
- package/library/message/channel.d.ts +53 -6
- package/library/message/channel.d.ts.map +1 -1
- package/library/message/channel.js +96 -9
- package/library/message/dispatcher.d.ts +17 -0
- package/library/message/dispatcher.d.ts.map +1 -1
- package/library/message/dispatcher.js +149 -98
- package/library/stream/error.d.ts +24 -0
- package/library/stream/error.d.ts.map +1 -0
- package/library/stream/error.js +29 -0
- package/library/stream/index.d.ts +4 -1
- package/library/stream/index.d.ts.map +1 -1
- package/library/stream/index.js +7 -4
- package/library/stream/readable-stream.d.ts.map +1 -1
- package/library/stream/readable-stream.js +102 -27
- package/library/stream/stream-core.d.ts +22 -1
- package/library/stream/stream-core.d.ts.map +1 -1
- package/library/stream/stream-core.js +120 -2
- package/library/stream/types.d.ts +115 -2
- package/library/stream/types.d.ts.map +1 -1
- package/library/stream/writable-stream.d.ts +20 -2
- package/library/stream/writable-stream.d.ts.map +1 -1
- package/library/stream/writable-stream.js +366 -41
- package/library/types/index.d.ts +17 -22
- package/library/types/index.d.ts.map +1 -1
- package/library/utils/ack.d.ts +2 -0
- package/library/utils/ack.d.ts.map +1 -0
- package/library/utils/ack.js +44 -0
- package/library/utils/blob.d.ts +3 -0
- package/library/utils/blob.d.ts.map +1 -0
- package/library/utils/blob.js +22 -0
- package/library/utils/cache.d.ts +10 -20
- package/library/utils/cache.d.ts.map +1 -1
- package/library/utils/cache.js +25 -79
- package/library/utils/content-type.d.ts +13 -0
- package/library/utils/content-type.d.ts.map +1 -0
- package/library/utils/content-type.js +87 -0
- package/library/utils/debug.d.ts.map +1 -1
- package/library/utils/debug.js +156 -178
- package/library/utils/hooks.d.ts +30 -0
- package/library/utils/hooks.d.ts.map +1 -0
- package/library/utils/hooks.js +139 -0
- package/library/utils/id.d.ts +9 -0
- package/library/utils/id.d.ts.map +1 -0
- package/library/utils/id.js +21 -0
- package/library/utils/iframe.d.ts +5 -0
- package/library/utils/iframe.d.ts.map +1 -0
- package/library/utils/iframe.js +25 -0
- package/library/utils/index.d.ts +7 -34
- package/library/utils/index.d.ts.map +1 -1
- package/library/utils/index.js +58 -193
- package/library/utils/is.d.ts +2 -0
- package/library/utils/is.d.ts.map +1 -0
- package/library/utils/is.js +9 -0
- package/library/utils/logger.d.ts +13 -0
- package/library/utils/logger.d.ts.map +1 -0
- package/library/utils/logger.js +63 -0
- package/library/utils/origin.d.ts.map +1 -1
- package/library/utils/origin.js +2 -1
- package/library/utils/promise.d.ts +2 -0
- package/library/utils/promise.d.ts.map +1 -0
- package/library/utils/promise.js +9 -0
- package/library/utils/window.d.ts +2 -0
- package/library/utils/window.d.ts.map +1 -0
- package/library/utils/window.js +38 -0
- package/package.json +49 -2
- package/react/package.json +2 -1
- package/esm/core/client-server.js +0 -329
- package/esm/core/server.js +0 -767
- package/esm/utils/ack-meta.js +0 -53
- package/library/core/client-server.d.ts +0 -106
- package/library/core/client-server.d.ts.map +0 -1
- package/library/core/client-server.js +0 -336
- package/library/core/client.d.ts.map +0 -1
- package/library/core/response.d.ts.map +0 -1
- package/library/core/server.d.ts.map +0 -1
- package/library/core/server.js +0 -772
- package/library/utils/ack-meta.d.ts +0 -2
- package/library/utils/ack-meta.d.ts.map +0 -1
- package/library/utils/ack-meta.js +0 -59
- /package/esm/{core → impl}/request.js +0 -0
- /package/library/{core → impl}/request.d.ts +0 -0
- /package/library/{core → impl}/request.js +0 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
2
|
+
import "core-js/modules/es.array.iterator.js";
|
|
3
|
+
import "core-js/modules/es.array.map.js";
|
|
4
|
+
import "core-js/modules/es.map.js";
|
|
5
|
+
import "core-js/modules/es.set.js";
|
|
6
|
+
import "core-js/modules/web.dom-collections.for-each.js";
|
|
7
|
+
import "core-js/modules/web.dom-collections.iterator.js";
|
|
8
|
+
import { MessageDispatcher } from '../../message';
|
|
9
|
+
import { isCompatibleVersion } from '../../utils/protocol';
|
|
10
|
+
import { OriginConstant, Messages } from '../../constants';
|
|
11
|
+
import { getOrCreateMessageChannel, releaseMessageChannel } from '../../message/channel-cache';
|
|
12
|
+
import { RequestIframeEndpointOutbox } from './outbox';
|
|
13
|
+
import { SyncHook } from '../../utils/hooks';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Pending manager for maps and timers.
|
|
17
|
+
*
|
|
18
|
+
* - Track all pending maps created by hub
|
|
19
|
+
* - Track all timeouts created by hub
|
|
20
|
+
* - Provide a unified cleanup when destroying
|
|
21
|
+
*/
|
|
22
|
+
class RequestIframePendingManager {
|
|
23
|
+
constructor() {
|
|
24
|
+
_defineProperty(this, "maps", new Map());
|
|
25
|
+
_defineProperty(this, "timeouts", new Set());
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get or create a named pending map that will be auto-cleared on destroy.
|
|
29
|
+
*/
|
|
30
|
+
map(name) {
|
|
31
|
+
var existing = this.maps.get(name);
|
|
32
|
+
if (existing) return existing;
|
|
33
|
+
var m = new Map();
|
|
34
|
+
this.maps.set(name, m);
|
|
35
|
+
return m;
|
|
36
|
+
}
|
|
37
|
+
get(name, key) {
|
|
38
|
+
return this.map(name).get(key);
|
|
39
|
+
}
|
|
40
|
+
set(name, key, value) {
|
|
41
|
+
this.map(name).set(key, value);
|
|
42
|
+
}
|
|
43
|
+
has(name, key) {
|
|
44
|
+
return this.map(name).has(key);
|
|
45
|
+
}
|
|
46
|
+
delete(name, key) {
|
|
47
|
+
return this.map(name).delete(key);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Create a timeout that will be auto-cleared on destroy.
|
|
52
|
+
*/
|
|
53
|
+
setTimeout(fn, ms) {
|
|
54
|
+
var id = setTimeout(() => {
|
|
55
|
+
this.timeouts.delete(id);
|
|
56
|
+
fn();
|
|
57
|
+
}, ms);
|
|
58
|
+
this.timeouts.add(id);
|
|
59
|
+
return id;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Clear a tracked timeout.
|
|
64
|
+
*/
|
|
65
|
+
clearTimeout(id) {
|
|
66
|
+
clearTimeout(id);
|
|
67
|
+
this.timeouts.delete(id);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Clear all tracked pending maps and timeouts.
|
|
72
|
+
*/
|
|
73
|
+
clearAll() {
|
|
74
|
+
this.timeouts.forEach(id => clearTimeout(id));
|
|
75
|
+
this.timeouts.clear();
|
|
76
|
+
this.maps.forEach(m => m.clear());
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Generic counter/limiter utilities (built on hub.pending maps).
|
|
82
|
+
*
|
|
83
|
+
* This is intended as a shared infrastructure for both client/server:
|
|
84
|
+
* - server can limit max concurrent in-flight requests per client
|
|
85
|
+
* - client can limit max concurrent streams / in-flight sends in future
|
|
86
|
+
*/
|
|
87
|
+
class RequestIframeLimiter {
|
|
88
|
+
constructor(pending) {
|
|
89
|
+
this.pending = pending;
|
|
90
|
+
}
|
|
91
|
+
get(bucket, key) {
|
|
92
|
+
var _this$pending$get;
|
|
93
|
+
return (_this$pending$get = this.pending.get(bucket, key)) !== null && _this$pending$get !== void 0 ? _this$pending$get : 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Try acquire one permit for the given key.
|
|
98
|
+
* Returns true if acquired, false if limit reached.
|
|
99
|
+
*/
|
|
100
|
+
tryAcquire(bucket, key, limit) {
|
|
101
|
+
if (!Number.isFinite(limit)) {
|
|
102
|
+
/** Treat Infinity as always allowed but still count for symmetry */
|
|
103
|
+
var next = this.get(bucket, key) + 1;
|
|
104
|
+
this.pending.set(bucket, key, next);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
var current = this.get(bucket, key);
|
|
108
|
+
if (current >= limit) return false;
|
|
109
|
+
this.pending.set(bucket, key, current + 1);
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Release one permit for the given key.
|
|
115
|
+
*/
|
|
116
|
+
release(bucket, key) {
|
|
117
|
+
var current = this.get(bucket, key);
|
|
118
|
+
var next = current - 1;
|
|
119
|
+
if (next <= 0) {
|
|
120
|
+
this.pending.delete(bucket, key);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
this.pending.set(bucket, key, next);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Shared options for endpoint hub.
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* RequestIframeEndpointHub
|
|
133
|
+
*
|
|
134
|
+
* Endpoint "hub" responsible for:
|
|
135
|
+
* - MessageDispatcher lifecycle
|
|
136
|
+
* - handler registration/unregistration
|
|
137
|
+
* - pending + timeout management
|
|
138
|
+
* - limiter counters
|
|
139
|
+
*/
|
|
140
|
+
export class RequestIframeEndpointHub {
|
|
141
|
+
constructor(role, instanceId, options) {
|
|
142
|
+
var _options$versionValid;
|
|
143
|
+
_defineProperty(this, "hooks", {
|
|
144
|
+
beforeOpen: new SyncHook(),
|
|
145
|
+
afterOpen: new SyncHook(),
|
|
146
|
+
beforeClose: new SyncHook(),
|
|
147
|
+
afterClose: new SyncHook(),
|
|
148
|
+
beforeDestroy: new SyncHook(),
|
|
149
|
+
afterDestroy: new SyncHook(),
|
|
150
|
+
registerHandler: new SyncHook(),
|
|
151
|
+
unregisterHandler: new SyncHook()
|
|
152
|
+
});
|
|
153
|
+
_defineProperty(this, "pending", new RequestIframePendingManager());
|
|
154
|
+
_defineProperty(this, "limiter", new RequestIframeLimiter(this.pending));
|
|
155
|
+
_defineProperty(this, "unregisterFns", []);
|
|
156
|
+
_defineProperty(this, "warnOnceKeys", new Set());
|
|
157
|
+
/** Whether it is open */
|
|
158
|
+
_defineProperty(this, "_isOpen", false);
|
|
159
|
+
this.instanceId = instanceId;
|
|
160
|
+
this.versionValidator = (_options$versionValid = options === null || options === void 0 ? void 0 : options.versionValidator) !== null && _options$versionValid !== void 0 ? _options$versionValid : isCompatibleVersion;
|
|
161
|
+
|
|
162
|
+
/** Get or create shared channel and create dispatcher */
|
|
163
|
+
var channel = getOrCreateMessageChannel(options === null || options === void 0 ? void 0 : options.secretKey);
|
|
164
|
+
this.messageDispatcher = new MessageDispatcher(channel, role, instanceId);
|
|
165
|
+
this.messageDispatcher.setAutoAckLimits({
|
|
166
|
+
maxMetaLength: options === null || options === void 0 ? void 0 : options.autoAckMaxMetaLength,
|
|
167
|
+
maxIdLength: options === null || options === void 0 ? void 0 : options.autoAckMaxIdLength
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Set registerHandlers callback.
|
|
173
|
+
*
|
|
174
|
+
* This is used by composition-based implementations to define handler bindings.
|
|
175
|
+
*/
|
|
176
|
+
setRegisterHandlers(fn) {
|
|
177
|
+
this.registerHandlersFn = fn;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Register a dispatcher handler and track its unregister function.
|
|
182
|
+
*/
|
|
183
|
+
registerHandler(matcher, handler, options) {
|
|
184
|
+
this.hooks.registerHandler.call(matcher);
|
|
185
|
+
var unreg = this.messageDispatcher.registerHandler(matcher, handler, options);
|
|
186
|
+
this.unregisterFns.push(unreg);
|
|
187
|
+
return unreg;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Create common handler options object.
|
|
192
|
+
*/
|
|
193
|
+
createHandlerOptions(onVersionError) {
|
|
194
|
+
return {
|
|
195
|
+
versionValidator: this.versionValidator,
|
|
196
|
+
onVersionError
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Warn once per key.
|
|
202
|
+
*/
|
|
203
|
+
warnOnce(key, fn) {
|
|
204
|
+
if (this.warnOnceKeys.has(key)) return;
|
|
205
|
+
this.warnOnceKeys.add(key);
|
|
206
|
+
fn();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Set stream callback (used by client-side stream routing).
|
|
211
|
+
*/
|
|
212
|
+
setStreamCallback(callback) {
|
|
213
|
+
this.streamCallback = callback;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Get stream callback (used by handler registration side).
|
|
218
|
+
*/
|
|
219
|
+
getStreamCallback() {
|
|
220
|
+
return this.streamCallback;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Validate origin safely (originValidator wins over origin string).
|
|
225
|
+
*/
|
|
226
|
+
isOriginAllowedBy(contextOrigin, data, context, origin, originValidator) {
|
|
227
|
+
if (originValidator) {
|
|
228
|
+
try {
|
|
229
|
+
return originValidator(contextOrigin, data, context);
|
|
230
|
+
} catch (_unused) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (!origin || origin === OriginConstant.ANY) return true;
|
|
235
|
+
return contextOrigin === origin;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Set a fixed peer (fallback target) for cases where MessageEvent.source is missing.
|
|
240
|
+
*
|
|
241
|
+
* This is useful for "response endpoint" style usage where the peer is already known
|
|
242
|
+
* (e.g. a client bound to an iframe window).
|
|
243
|
+
*/
|
|
244
|
+
setFallbackTarget(targetWindow, targetOrigin) {
|
|
245
|
+
this.messageDispatcher.setFallbackTarget(targetWindow, targetOrigin);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Create a peer-bound outbox using this hub's dispatcher.
|
|
250
|
+
*/
|
|
251
|
+
createOutbox(targetWindow, targetOrigin, defaultTargetId) {
|
|
252
|
+
return new RequestIframeEndpointOutbox(this.messageDispatcher, targetWindow, targetOrigin, defaultTargetId);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Open message processing (register message handlers)
|
|
257
|
+
*/
|
|
258
|
+
open() {
|
|
259
|
+
if (this._isOpen) return;
|
|
260
|
+
this.hooks.beforeOpen.call();
|
|
261
|
+
this._isOpen = true;
|
|
262
|
+
if (!this.registerHandlersFn) {
|
|
263
|
+
throw new Error(Messages.HUB_REGISTER_HANDLERS_NOT_SET);
|
|
264
|
+
}
|
|
265
|
+
this.registerHandlersFn();
|
|
266
|
+
this.hooks.afterOpen.call();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Close message processing (unregister message handlers, but don't release channel)
|
|
271
|
+
*/
|
|
272
|
+
close() {
|
|
273
|
+
if (!this._isOpen) return;
|
|
274
|
+
this.hooks.beforeClose.call();
|
|
275
|
+
this._isOpen = false;
|
|
276
|
+
|
|
277
|
+
/** Unregister all handlers */
|
|
278
|
+
this.unregisterFns.forEach(fn => fn());
|
|
279
|
+
this.unregisterFns.length = 0;
|
|
280
|
+
this.hooks.unregisterHandler.call();
|
|
281
|
+
this.hooks.afterClose.call();
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Whether it is open
|
|
286
|
+
*/
|
|
287
|
+
get isOpen() {
|
|
288
|
+
return this._isOpen;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Get secretKey
|
|
293
|
+
*/
|
|
294
|
+
get secretKey() {
|
|
295
|
+
return this.messageDispatcher.secretKey;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Destroy (close and release channel reference)
|
|
300
|
+
*/
|
|
301
|
+
destroy() {
|
|
302
|
+
this.hooks.beforeDestroy.call();
|
|
303
|
+
/** Close first */
|
|
304
|
+
this.close();
|
|
305
|
+
|
|
306
|
+
/** Clear all pending maps and timeouts */
|
|
307
|
+
this.pending.clearAll();
|
|
308
|
+
this.warnOnceKeys.clear();
|
|
309
|
+
this.streamCallback = undefined;
|
|
310
|
+
|
|
311
|
+
/** Destroy dispatcher and release channel reference */
|
|
312
|
+
this.messageDispatcher.destroy();
|
|
313
|
+
releaseMessageChannel(this.messageDispatcher.getChannel());
|
|
314
|
+
this.hooks.afterDestroy.call();
|
|
315
|
+
}
|
|
316
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
2
|
+
import "core-js/modules/es.array.slice.js";
|
|
3
|
+
import "core-js/modules/es.promise.js";
|
|
4
|
+
import "core-js/modules/es.regexp.to-string.js";
|
|
5
|
+
import { MessageType, ProtocolVersion, Messages, formatMessage, MessageRole, WarnOnceKey, buildWarnOnceKey } from '../../constants';
|
|
6
|
+
import { createPingResponder } from '../heartbeat/ping';
|
|
7
|
+
import { SyncHook } from '../../utils/hooks';
|
|
8
|
+
import { requestIframeLog } from '../../utils/logger';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Pending request awaiting response
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* RequestIframeEndpointInbox
|
|
16
|
+
*
|
|
17
|
+
* The endpoint "inbox" is responsible for handling inbound framework messages and
|
|
18
|
+
* driving pending request resolution by requestId.
|
|
19
|
+
*
|
|
20
|
+
* - Registers dispatcher handlers for ACK/ASYNC/RESPONSE/ERROR/STREAM_START + PING/PONG
|
|
21
|
+
* - Manages pending requests via hub.pending
|
|
22
|
+
*/
|
|
23
|
+
export class RequestIframeEndpointInbox {
|
|
24
|
+
constructor(hub, versionValidator) {
|
|
25
|
+
_defineProperty(this, "hooks", {
|
|
26
|
+
inbound: new SyncHook(),
|
|
27
|
+
pendingRegistered: new SyncHook(),
|
|
28
|
+
pendingUnregistered: new SyncHook(),
|
|
29
|
+
pendingResolved: new SyncHook(),
|
|
30
|
+
missingPending: new SyncHook()
|
|
31
|
+
});
|
|
32
|
+
this.hub = hub;
|
|
33
|
+
this.versionValidator = versionValidator !== null && versionValidator !== void 0 ? versionValidator : hub.versionValidator;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Register message handlers on hub.
|
|
38
|
+
*/
|
|
39
|
+
registerHandlers() {
|
|
40
|
+
var handlerOptions = this.hub.createHandlerOptions(this.handleVersionError.bind(this));
|
|
41
|
+
handlerOptions.versionValidator = this.versionValidator;
|
|
42
|
+
var boundHandleClientResponse = this.handleClientResponse.bind(this);
|
|
43
|
+
this.hub.registerHandler(MessageType.ACK, boundHandleClientResponse, handlerOptions);
|
|
44
|
+
this.hub.registerHandler(MessageType.ASYNC, boundHandleClientResponse, handlerOptions);
|
|
45
|
+
this.hub.registerHandler(MessageType.RESPONSE, boundHandleClientResponse, handlerOptions);
|
|
46
|
+
this.hub.registerHandler(MessageType.ERROR, boundHandleClientResponse, handlerOptions);
|
|
47
|
+
this.hub.registerHandler(MessageType.PONG, this.handlePong.bind(this), handlerOptions);
|
|
48
|
+
this.hub.registerHandler(MessageType.PING, this.handlePing.bind(this), handlerOptions);
|
|
49
|
+
this.hub.registerHandler(MessageType.STREAM_START, boundHandleClientResponse, handlerOptions);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Client-side "isConnect" ping helper.
|
|
54
|
+
*
|
|
55
|
+
* - Sends PING(requireAck=true)
|
|
56
|
+
* - Resolves true when ACK or PONG arrives, false on timeout
|
|
57
|
+
*/
|
|
58
|
+
pingIsConnect(params) {
|
|
59
|
+
var requestId = `ping_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
60
|
+
return new Promise(resolve => {
|
|
61
|
+
var timeoutId = this.hub.pending.setTimeout(() => {
|
|
62
|
+
this.hub.pending.delete(RequestIframeEndpointInbox.PENDING_IS_CONNECT, requestId);
|
|
63
|
+
resolve(false);
|
|
64
|
+
}, params.timeoutMs);
|
|
65
|
+
this.hub.pending.set(RequestIframeEndpointInbox.PENDING_IS_CONNECT, requestId, {
|
|
66
|
+
resolve,
|
|
67
|
+
timeoutId,
|
|
68
|
+
targetOrigin: params.targetOrigin,
|
|
69
|
+
originValidator: params.originValidator,
|
|
70
|
+
onPeerId: params.onPeerId
|
|
71
|
+
});
|
|
72
|
+
params.peer.sendMessage(MessageType.PING, requestId, {
|
|
73
|
+
requireAck: true,
|
|
74
|
+
targetId: params.targetId
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Register pending request awaiting response
|
|
81
|
+
*/
|
|
82
|
+
registerPendingRequest(requestId, resolve, reject, origin, originValidator) {
|
|
83
|
+
this.hub.pending.set(RequestIframeEndpointInbox.PENDING_REQUESTS, requestId, {
|
|
84
|
+
resolve,
|
|
85
|
+
reject,
|
|
86
|
+
origin,
|
|
87
|
+
originValidator
|
|
88
|
+
});
|
|
89
|
+
this.hooks.pendingRegistered.call(requestId, {
|
|
90
|
+
origin
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Cancel pending response
|
|
96
|
+
*/
|
|
97
|
+
unregisterPendingRequest(requestId) {
|
|
98
|
+
this.hub.pending.delete(RequestIframeEndpointInbox.PENDING_REQUESTS, requestId);
|
|
99
|
+
this.hooks.pendingUnregistered.call(requestId);
|
|
100
|
+
}
|
|
101
|
+
handlePing(data, context) {
|
|
102
|
+
var _this$hub$instanceId;
|
|
103
|
+
this.hooks.inbound.call(data, context);
|
|
104
|
+
var responder = createPingResponder({
|
|
105
|
+
hub: this.hub,
|
|
106
|
+
handledBy: (_this$hub$instanceId = this.hub.instanceId) !== null && _this$hub$instanceId !== void 0 ? _this$hub$instanceId : MessageRole.CLIENT,
|
|
107
|
+
includeTargetId: true
|
|
108
|
+
});
|
|
109
|
+
responder(data, context);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Handle protocol version error
|
|
114
|
+
*/
|
|
115
|
+
handleVersionError(data, context, version) {
|
|
116
|
+
void context;
|
|
117
|
+
var pending = this.hub.pending.get(RequestIframeEndpointInbox.PENDING_REQUESTS, data.requestId);
|
|
118
|
+
if (pending) {
|
|
119
|
+
this.hub.pending.delete(RequestIframeEndpointInbox.PENDING_REQUESTS, data.requestId);
|
|
120
|
+
pending.reject(new Error(formatMessage(Messages.PROTOCOL_VERSION_TOO_LOW, version, ProtocolVersion.MIN_SUPPORTED)));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Handle client response
|
|
126
|
+
*/
|
|
127
|
+
handleClientResponse(data, context) {
|
|
128
|
+
var _this$hub$instanceId4;
|
|
129
|
+
this.hooks.inbound.call(data, context);
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* isConnect waiter:
|
|
133
|
+
* - ACK is sent by the peer when it accepted the PING (auto-ack workflow)
|
|
134
|
+
* - We treat either ACK or PONG as a successful connectivity signal
|
|
135
|
+
*/
|
|
136
|
+
if (data.type === MessageType.ACK) {
|
|
137
|
+
var pendingIsConnect = this.hub.pending.get(RequestIframeEndpointInbox.PENDING_IS_CONNECT, data.requestId);
|
|
138
|
+
if (pendingIsConnect) {
|
|
139
|
+
var _this$hub$instanceId3, _pendingIsConnect$onP;
|
|
140
|
+
// Must match the pending target origin (and originValidator if configured)
|
|
141
|
+
if (!this.hub.isOriginAllowedBy(context.origin, data, context, pendingIsConnect.targetOrigin, pendingIsConnect.originValidator)) {
|
|
142
|
+
var _this$hub$instanceId2;
|
|
143
|
+
// Mark handled (and auto-ack if requireAck) but ignore the signal
|
|
144
|
+
context.markAcceptedBy((_this$hub$instanceId2 = this.hub.instanceId) !== null && _this$hub$instanceId2 !== void 0 ? _this$hub$instanceId2 : MessageRole.CLIENT);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
context.markAcceptedBy((_this$hub$instanceId3 = this.hub.instanceId) !== null && _this$hub$instanceId3 !== void 0 ? _this$hub$instanceId3 : MessageRole.CLIENT);
|
|
148
|
+
this.hub.pending.clearTimeout(pendingIsConnect.timeoutId);
|
|
149
|
+
this.hub.pending.delete(RequestIframeEndpointInbox.PENDING_IS_CONNECT, data.requestId);
|
|
150
|
+
(_pendingIsConnect$onP = pendingIsConnect.onPeerId) === null || _pendingIsConnect$onP === void 0 || _pendingIsConnect$onP.call(pendingIsConnect, data.creatorId);
|
|
151
|
+
pendingIsConnect.resolve(true);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
var pending = this.hub.pending.get(RequestIframeEndpointInbox.PENDING_REQUESTS, data.requestId);
|
|
156
|
+
if (!pending) {
|
|
157
|
+
/**
|
|
158
|
+
* Pending request not found - ignore by default.
|
|
159
|
+
*
|
|
160
|
+
* If endpoint is already closed/destroyed, emit a warning to help debugging:
|
|
161
|
+
* this usually means the client was recreated/unmounted before the response arrived.
|
|
162
|
+
*/
|
|
163
|
+
if (!this.hub.isOpen) {
|
|
164
|
+
this.hooks.missingPending.call(data, context);
|
|
165
|
+
this.hub.warnOnce(buildWarnOnceKey(WarnOnceKey.INBOX_MISSING_PENDING_WHEN_CLOSED, data.requestId), () => {
|
|
166
|
+
requestIframeLog('warn', formatMessage(Messages.CLIENT_SERVER_IGNORED_MESSAGE_WHEN_CLOSED, data.type, data.requestId));
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Validate origin */
|
|
173
|
+
if (!this.hub.isOriginAllowedBy(context.origin, data, context, pending.origin, pending.originValidator)) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Mark as handled so:
|
|
179
|
+
* - other client instances sharing the same channel won't also process it
|
|
180
|
+
* - MessageDispatcher can run its generalized requireAck auto-ack logic
|
|
181
|
+
*/
|
|
182
|
+
context.markAcceptedBy((_this$hub$instanceId4 = this.hub.instanceId) !== null && _this$hub$instanceId4 !== void 0 ? _this$hub$instanceId4 : MessageRole.CLIENT);
|
|
183
|
+
|
|
184
|
+
/** ack, async, and stream_start don't delete pending (stream_start needs to keep pending for stream_data/stream_end) */
|
|
185
|
+
if (data.type === MessageType.ACK || data.type === MessageType.ASYNC || data.type === MessageType.STREAM_START) {
|
|
186
|
+
this.hooks.pendingResolved.call(data.requestId, data);
|
|
187
|
+
pending.resolve(data);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** response and error delete pending */
|
|
192
|
+
this.hub.pending.delete(RequestIframeEndpointInbox.PENDING_REQUESTS, data.requestId);
|
|
193
|
+
this.hooks.pendingResolved.call(data.requestId, data);
|
|
194
|
+
pending.resolve(data);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Handle PONG:
|
|
199
|
+
* - If it matches an existing pending request, resolve it.
|
|
200
|
+
* - Otherwise, ignore (facade may still use PONG for isConnect waiter).
|
|
201
|
+
*/
|
|
202
|
+
handlePong(data, context) {
|
|
203
|
+
var _this$hub$instanceId7;
|
|
204
|
+
this.hooks.inbound.call(data, context);
|
|
205
|
+
var pendingIsConnect = this.hub.pending.get(RequestIframeEndpointInbox.PENDING_IS_CONNECT, data.requestId);
|
|
206
|
+
if (pendingIsConnect) {
|
|
207
|
+
var _this$hub$instanceId6, _pendingIsConnect$onP2;
|
|
208
|
+
if (!this.hub.isOriginAllowedBy(context.origin, data, context, pendingIsConnect.targetOrigin, pendingIsConnect.originValidator)) {
|
|
209
|
+
var _this$hub$instanceId5;
|
|
210
|
+
context.markAcceptedBy((_this$hub$instanceId5 = this.hub.instanceId) !== null && _this$hub$instanceId5 !== void 0 ? _this$hub$instanceId5 : MessageRole.CLIENT);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
context.markAcceptedBy((_this$hub$instanceId6 = this.hub.instanceId) !== null && _this$hub$instanceId6 !== void 0 ? _this$hub$instanceId6 : MessageRole.CLIENT);
|
|
214
|
+
this.hub.pending.clearTimeout(pendingIsConnect.timeoutId);
|
|
215
|
+
this.hub.pending.delete(RequestIframeEndpointInbox.PENDING_IS_CONNECT, data.requestId);
|
|
216
|
+
(_pendingIsConnect$onP2 = pendingIsConnect.onPeerId) === null || _pendingIsConnect$onP2 === void 0 || _pendingIsConnect$onP2.call(pendingIsConnect, data.creatorId);
|
|
217
|
+
pendingIsConnect.resolve(true);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
var pending = this.hub.pending.get(RequestIframeEndpointInbox.PENDING_REQUESTS, data.requestId);
|
|
221
|
+
if (!pending) return;
|
|
222
|
+
if (!this.hub.isOriginAllowedBy(context.origin, data, context, pending.origin, pending.originValidator)) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
context.markAcceptedBy((_this$hub$instanceId7 = this.hub.instanceId) !== null && _this$hub$instanceId7 !== void 0 ? _this$hub$instanceId7 : MessageRole.CLIENT);
|
|
226
|
+
this.hub.pending.delete(RequestIframeEndpointInbox.PENDING_REQUESTS, data.requestId);
|
|
227
|
+
this.hooks.pendingResolved.call(data.requestId, data);
|
|
228
|
+
pending.resolve(data);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
_defineProperty(RequestIframeEndpointInbox, "PENDING_REQUESTS", 'inbox:pendingRequests');
|
|
232
|
+
_defineProperty(RequestIframeEndpointInbox, "PENDING_IS_CONNECT", 'inbox:pendingIsConnect');
|