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,108 @@
|
|
|
1
|
+
import "core-js/modules/es.array.iterator.js";
|
|
2
|
+
import "core-js/modules/es.map.js";
|
|
3
|
+
import "core-js/modules/esnext.global-this.js";
|
|
4
|
+
import "core-js/modules/web.dom-collections.for-each.js";
|
|
5
|
+
import "core-js/modules/web.dom-collections.iterator.js";
|
|
6
|
+
import { MessageChannel, ChannelType } from './channel';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Global cache Symbol (used to store MessageChannel instance cache on window/globalThis).
|
|
10
|
+
*
|
|
11
|
+
* NOTE:
|
|
12
|
+
* - We MUST use Symbol.for() so multiple library copies (different bundles/versions)
|
|
13
|
+
* can share the same cache.
|
|
14
|
+
* - Keep the symbol key stable for backward compatibility with older releases.
|
|
15
|
+
*/
|
|
16
|
+
var MESSAGE_CHANNEL_CACHE_SYMBOL = Symbol.for('__requestIframeMessageChannelCache__');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get the cache host object.
|
|
20
|
+
*
|
|
21
|
+
* We prefer `window` because MessageChannel itself is window-based (postMessage listener),
|
|
22
|
+
* and existing versions store the cache on window as well.
|
|
23
|
+
*/
|
|
24
|
+
function getCacheHost() {
|
|
25
|
+
if (typeof window !== 'undefined') return window;
|
|
26
|
+
// Fallback for non-browser environments; creating MessageChannel will likely fail anyway.
|
|
27
|
+
return globalThis;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get the MessageChannel cache Map from the host.
|
|
32
|
+
*/
|
|
33
|
+
function getChannelCache() {
|
|
34
|
+
var host = getCacheHost();
|
|
35
|
+
if (!(MESSAGE_CHANNEL_CACHE_SYMBOL in host)) {
|
|
36
|
+
host[MESSAGE_CHANNEL_CACHE_SYMBOL] = new Map();
|
|
37
|
+
}
|
|
38
|
+
return host[MESSAGE_CHANNEL_CACHE_SYMBOL];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Generate cache key.
|
|
43
|
+
* Format: "type:secretKey" or "type:" when no secretKey.
|
|
44
|
+
*/
|
|
45
|
+
function getCacheKey(type, secretKey) {
|
|
46
|
+
return `${type}:${secretKey !== null && secretKey !== void 0 ? secretKey : ''}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get or create MessageChannel instance.
|
|
51
|
+
*
|
|
52
|
+
* - Within the same window, only one channel is created per type + secretKey.
|
|
53
|
+
* - Uses reference counting to manage lifecycle.
|
|
54
|
+
*/
|
|
55
|
+
export function getOrCreateMessageChannel(secretKey, type = ChannelType.POST_MESSAGE) {
|
|
56
|
+
var cache = getChannelCache();
|
|
57
|
+
var key = getCacheKey(type, secretKey);
|
|
58
|
+
var channel = cache.get(key);
|
|
59
|
+
if (!channel) {
|
|
60
|
+
channel = new MessageChannel(secretKey, type);
|
|
61
|
+
cache.set(key, channel);
|
|
62
|
+
}
|
|
63
|
+
channel.addRef();
|
|
64
|
+
return channel;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Release MessageChannel reference.
|
|
69
|
+
*
|
|
70
|
+
* - When reference count reaches 0, destroy channel and remove from cache.
|
|
71
|
+
*/
|
|
72
|
+
export function releaseMessageChannel(channel) {
|
|
73
|
+
var refCount = channel.release();
|
|
74
|
+
if (refCount > 0) return;
|
|
75
|
+
var cache = getChannelCache();
|
|
76
|
+
var key = getCacheKey(channel.type, channel.secretKey);
|
|
77
|
+
if (cache.get(key) === channel) {
|
|
78
|
+
cache.delete(key);
|
|
79
|
+
channel.destroy();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Clear MessageChannel cache (mainly for testing).
|
|
85
|
+
*
|
|
86
|
+
* - No args: clear all channels
|
|
87
|
+
* - string arg: treated as secretKey filter
|
|
88
|
+
* - params arg: filter by secretKey/type
|
|
89
|
+
*/
|
|
90
|
+
export function clearMessageChannelCache(arg) {
|
|
91
|
+
var cache = getChannelCache();
|
|
92
|
+
if (!arg) {
|
|
93
|
+
cache.forEach(channel => {
|
|
94
|
+
channel.destroy();
|
|
95
|
+
});
|
|
96
|
+
cache.clear();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
var params = typeof arg === 'string' ? {
|
|
100
|
+
secretKey: arg
|
|
101
|
+
} : arg;
|
|
102
|
+
cache.forEach((channel, key) => {
|
|
103
|
+
if (params.type && channel.type !== params.type) return;
|
|
104
|
+
if (typeof params.secretKey === 'string' && channel.secretKey !== params.secretKey) return;
|
|
105
|
+
cache.delete(key);
|
|
106
|
+
channel.destroy();
|
|
107
|
+
});
|
|
108
|
+
}
|
package/esm/message/channel.js
CHANGED
|
@@ -7,11 +7,25 @@ import "core-js/modules/es.object.get-own-property-descriptors.js";
|
|
|
7
7
|
import "core-js/modules/es.set.js";
|
|
8
8
|
import "core-js/modules/web.dom-collections.for-each.js";
|
|
9
9
|
import "core-js/modules/web.dom-collections.iterator.js";
|
|
10
|
-
import { isValidPostMessage, createPostMessage
|
|
10
|
+
import { isValidPostMessage, createPostMessage } from '../utils/protocol';
|
|
11
|
+
import { isWindowAvailable } from '../utils/window';
|
|
12
|
+
import { OriginConstant } from '../constants';
|
|
13
|
+
import { requestIframeLog } from '../utils/logger';
|
|
14
|
+
import { SyncHook } from '../utils/hooks';
|
|
11
15
|
|
|
12
16
|
/**
|
|
13
17
|
* Message context (extracted from MessageEvent, transport-agnostic)
|
|
14
18
|
*/
|
|
19
|
+
export var MessageContextStage = {
|
|
20
|
+
/** Message is not handled by any instance yet */
|
|
21
|
+
PENDING: 'pending',
|
|
22
|
+
/** Message is claimed/being handled (handledBy is set, but not accepted) */
|
|
23
|
+
HANDLING: 'handling',
|
|
24
|
+
/** Message is accepted for processing (acceptedBy is set) */
|
|
25
|
+
ACCEPTED: 'accepted',
|
|
26
|
+
/** Message handling finished (synchronous dispatch finished) */
|
|
27
|
+
DONE: 'done'
|
|
28
|
+
};
|
|
15
29
|
|
|
16
30
|
/**
|
|
17
31
|
* Message receiver callback
|
|
@@ -98,10 +112,83 @@ export class MessageChannel {
|
|
|
98
112
|
* This encapsulates transport-specific details
|
|
99
113
|
*/
|
|
100
114
|
extractContext(event) {
|
|
101
|
-
|
|
102
|
-
|
|
115
|
+
var _ref;
|
|
116
|
+
var context = {
|
|
117
|
+
source: (_ref = event.source) !== null && _ref !== void 0 ? _ref : undefined,
|
|
103
118
|
origin: event.origin
|
|
104
119
|
};
|
|
120
|
+
var stateChangeHook;
|
|
121
|
+
var ensureStateChangeHook = () => {
|
|
122
|
+
if (!stateChangeHook) {
|
|
123
|
+
stateChangeHook = new SyncHook();
|
|
124
|
+
}
|
|
125
|
+
return stateChangeHook;
|
|
126
|
+
};
|
|
127
|
+
var emitStateChange = (prev, next) => {
|
|
128
|
+
if (!stateChangeHook) return;
|
|
129
|
+
stateChangeHook.call(prev, next, context);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Attach stable internal helper methods.
|
|
134
|
+
*
|
|
135
|
+
* We intentionally make them non-enumerable so typical object inspection won't be polluted.
|
|
136
|
+
*/
|
|
137
|
+
var markHandledBy = handledBy => {
|
|
138
|
+
var prev = getStage();
|
|
139
|
+
if (!context.handledBy) {
|
|
140
|
+
context.handledBy = handledBy;
|
|
141
|
+
}
|
|
142
|
+
var next = getStage();
|
|
143
|
+
if (prev !== next) emitStateChange(prev, next);
|
|
144
|
+
};
|
|
145
|
+
var markAcceptedBy = handledBy => {
|
|
146
|
+
var prev = getStage();
|
|
147
|
+
if (!context.acceptedBy) {
|
|
148
|
+
context.acceptedBy = handledBy;
|
|
149
|
+
}
|
|
150
|
+
markHandledBy(handledBy);
|
|
151
|
+
var next = getStage();
|
|
152
|
+
if (prev !== next) emitStateChange(prev, next);
|
|
153
|
+
};
|
|
154
|
+
var markDoneBy = doneBy => {
|
|
155
|
+
var prev = getStage();
|
|
156
|
+
if (!context.doneBy) {
|
|
157
|
+
context.doneBy = doneBy;
|
|
158
|
+
}
|
|
159
|
+
var next = getStage();
|
|
160
|
+
if (prev !== next) emitStateChange(prev, next);
|
|
161
|
+
};
|
|
162
|
+
var getStage = () => {
|
|
163
|
+
if (context.doneBy) return MessageContextStage.DONE;
|
|
164
|
+
if (context.acceptedBy) return MessageContextStage.ACCEPTED;
|
|
165
|
+
if (context.handledBy) return MessageContextStage.HANDLING;
|
|
166
|
+
return MessageContextStage.PENDING;
|
|
167
|
+
};
|
|
168
|
+
var onStateChange = (name, fn) => {
|
|
169
|
+
return ensureStateChangeHook().tap(name, fn);
|
|
170
|
+
};
|
|
171
|
+
Object.defineProperty(context, 'markHandledBy', {
|
|
172
|
+
value: markHandledBy,
|
|
173
|
+
enumerable: false
|
|
174
|
+
});
|
|
175
|
+
Object.defineProperty(context, 'markAcceptedBy', {
|
|
176
|
+
value: markAcceptedBy,
|
|
177
|
+
enumerable: false
|
|
178
|
+
});
|
|
179
|
+
Object.defineProperty(context, 'markDoneBy', {
|
|
180
|
+
value: markDoneBy,
|
|
181
|
+
enumerable: false
|
|
182
|
+
});
|
|
183
|
+
Object.defineProperty(context, 'getStage', {
|
|
184
|
+
value: getStage,
|
|
185
|
+
enumerable: false
|
|
186
|
+
});
|
|
187
|
+
Object.defineProperty(context, 'onStateChange', {
|
|
188
|
+
value: onStateChange,
|
|
189
|
+
enumerable: false
|
|
190
|
+
});
|
|
191
|
+
return context;
|
|
105
192
|
}
|
|
106
193
|
|
|
107
194
|
/**
|
|
@@ -130,7 +217,7 @@ export class MessageChannel {
|
|
|
130
217
|
try {
|
|
131
218
|
receiver(data, context);
|
|
132
219
|
} catch (e) {
|
|
133
|
-
|
|
220
|
+
requestIframeLog('error', 'Receiver error', e);
|
|
134
221
|
}
|
|
135
222
|
});
|
|
136
223
|
}
|
|
@@ -141,7 +228,7 @@ export class MessageChannel {
|
|
|
141
228
|
* @param message message data (already formatted as PostMessageData)
|
|
142
229
|
* @param targetOrigin target origin (defaults to '*')
|
|
143
230
|
*/
|
|
144
|
-
send(target, message, targetOrigin =
|
|
231
|
+
send(target, message, targetOrigin = OriginConstant.ANY) {
|
|
145
232
|
if (!isWindowAvailable(target)) {
|
|
146
233
|
return false;
|
|
147
234
|
}
|
|
@@ -18,8 +18,12 @@ import "core-js/modules/es.object.get-own-property-descriptors.js";
|
|
|
18
18
|
import "core-js/modules/es.regexp.constructor.js";
|
|
19
19
|
import "core-js/modules/es.regexp.exec.js";
|
|
20
20
|
import "core-js/modules/es.regexp.to-string.js";
|
|
21
|
-
import { MessageRole, MessageType } from '../constants';
|
|
22
|
-
import { getProtocolVersion, createPostMessage } from '../utils';
|
|
21
|
+
import { AutoAckConstant, MessageRole, MessageType, OriginConstant } from '../constants';
|
|
22
|
+
import { getProtocolVersion, createPostMessage } from '../utils/protocol';
|
|
23
|
+
import { isFunction } from '../utils/is';
|
|
24
|
+
import { getAckId, getAckMeta } from '../utils/ack';
|
|
25
|
+
import { SyncHook } from '../utils/hooks';
|
|
26
|
+
import { requestIframeLog } from '../utils/logger';
|
|
23
27
|
|
|
24
28
|
/**
|
|
25
29
|
* Message handler function type
|
|
@@ -60,17 +64,15 @@ import { getProtocolVersion, createPostMessage } from '../utils';
|
|
|
60
64
|
*/
|
|
61
65
|
export class MessageDispatcher {
|
|
62
66
|
constructor(channel, role, instanceId) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
*/
|
|
73
|
-
_defineProperty(this, "fallbackTargetOrigin", '*');
|
|
67
|
+
_defineProperty(this, "hooks", {
|
|
68
|
+
inbound: new SyncHook(),
|
|
69
|
+
beforeSend: new SyncHook(),
|
|
70
|
+
afterSend: new SyncHook(),
|
|
71
|
+
sendError: new SyncHook()
|
|
72
|
+
});
|
|
73
|
+
_defineProperty(this, "autoAckMaxMetaLength", AutoAckConstant.MAX_META_LENGTH);
|
|
74
|
+
_defineProperty(this, "autoAckMaxIdLength", AutoAckConstant.MAX_ID_LENGTH);
|
|
75
|
+
_defineProperty(this, "fallbackTargetOrigin", OriginConstant.ANY);
|
|
74
76
|
/** Message handler list */
|
|
75
77
|
_defineProperty(this, "handlers", []);
|
|
76
78
|
/** Reference count (for determining if can be destroyed when cached) */
|
|
@@ -93,11 +95,26 @@ export class MessageDispatcher {
|
|
|
93
95
|
/**
|
|
94
96
|
* Set fallback target for outgoing auto-ack messages.
|
|
95
97
|
*/
|
|
96
|
-
setFallbackTarget(targetWindow, targetOrigin =
|
|
98
|
+
setFallbackTarget(targetWindow, targetOrigin = OriginConstant.ANY) {
|
|
97
99
|
this.fallbackTargetWindow = targetWindow;
|
|
98
100
|
this.fallbackTargetOrigin = targetOrigin;
|
|
99
101
|
}
|
|
100
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Configure auto-ack echo limits (advanced/internal).
|
|
105
|
+
*
|
|
106
|
+
* @internal
|
|
107
|
+
*/
|
|
108
|
+
setAutoAckLimits(limits) {
|
|
109
|
+
if (!limits || typeof limits !== 'object') return;
|
|
110
|
+
if (typeof limits.maxMetaLength === 'number' && Number.isFinite(limits.maxMetaLength) && limits.maxMetaLength >= 0) {
|
|
111
|
+
this.autoAckMaxMetaLength = limits.maxMetaLength;
|
|
112
|
+
}
|
|
113
|
+
if (typeof limits.maxIdLength === 'number' && Number.isFinite(limits.maxIdLength) && limits.maxIdLength >= 0) {
|
|
114
|
+
this.autoAckMaxIdLength = limits.maxIdLength;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
101
118
|
// ==================== Reference Counting ====================
|
|
102
119
|
|
|
103
120
|
/**
|
|
@@ -183,79 +200,80 @@ export class MessageDispatcher {
|
|
|
183
200
|
return;
|
|
184
201
|
}
|
|
185
202
|
}
|
|
186
|
-
var type = data.type;
|
|
187
|
-
var version = getProtocolVersion(data);
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Auto-ack state for this incoming message.
|
|
191
|
-
* - We intentionally couple this to `context.handledBy` as the "accepted/handled" signal.
|
|
192
|
-
* - For some message types we only ack if they are truly handled (e.g. response requireAck),
|
|
193
|
-
* so we avoid incorrectly acknowledging messages when there is no pending consumer.
|
|
194
|
-
*
|
|
195
|
-
* Implementation note:
|
|
196
|
-
* We avoid using Proxy for compatibility and instead hook the `handledBy` property
|
|
197
|
-
* with a setter so handlers can trigger the ack immediately when they "accept" a message.
|
|
198
|
-
*/
|
|
199
|
-
var autoAckState = {
|
|
200
|
-
sent: false
|
|
201
|
-
};
|
|
202
|
-
var originalHandledBy = context.handledBy;
|
|
203
|
-
var handledByValue = originalHandledBy;
|
|
204
203
|
try {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
return handledByValue;
|
|
210
|
-
},
|
|
211
|
-
set: value => {
|
|
212
|
-
handledByValue = value;
|
|
213
|
-
if (value && !autoAckState.sent) {
|
|
214
|
-
autoAckState.sent = true;
|
|
215
|
-
this.tryAutoAck(data, context);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
});
|
|
219
|
-
} catch (_unused) {
|
|
204
|
+
this.hooks.inbound.call(data, context);
|
|
205
|
+
var _type = data.type;
|
|
206
|
+
var _version = getProtocolVersion(data);
|
|
207
|
+
|
|
220
208
|
/**
|
|
221
|
-
*
|
|
222
|
-
*
|
|
209
|
+
* Auto-ack state for this incoming message.
|
|
210
|
+
*
|
|
211
|
+
* Design notes:
|
|
212
|
+
* - We only auto-ack after the message is truly handled (context.handledBy is set)
|
|
213
|
+
* AND accepted (context.acceptedBy is set).
|
|
214
|
+
* - This prevents incorrectly acknowledging messages when there is no pending consumer.
|
|
223
215
|
*/
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if (
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
216
|
+
var autoAckState = {
|
|
217
|
+
sent: false
|
|
218
|
+
};
|
|
219
|
+
var maybeAutoAck = () => {
|
|
220
|
+
if (autoAckState.sent) return;
|
|
221
|
+
if (!context.handledBy) return;
|
|
222
|
+
if (!context.acceptedBy) return;
|
|
223
|
+
autoAckState.sent = true;
|
|
224
|
+
this.tryAutoAck(data, context);
|
|
225
|
+
};
|
|
226
|
+
var _iterator = _createForOfIteratorHelper(this.handlers),
|
|
227
|
+
_step;
|
|
228
|
+
try {
|
|
229
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
230
|
+
var entry = _step.value;
|
|
231
|
+
if (this.matchType(_type, entry.matcher)) {
|
|
232
|
+
// If message has been handled by a previous handler, stop processing
|
|
233
|
+
if (context.handledBy) {
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
235
236
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
237
|
+
// If handler specified version validation
|
|
238
|
+
if (entry.versionValidator && _version !== undefined) {
|
|
239
|
+
if (!entry.versionValidator(_version)) {
|
|
240
|
+
var _entry$onVersionError;
|
|
241
|
+
// Version incompatible, call error handler (if any)
|
|
242
|
+
(_entry$onVersionError = entry.onVersionError) === null || _entry$onVersionError === void 0 || _entry$onVersionError.call(entry, data, context, _version);
|
|
243
|
+
continue; // Skip this handler, try other handlers
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
entry.handler(data, context);
|
|
248
|
+
// After handler execution, check if it marked the message as handled
|
|
249
|
+
// If context.handledBy is set by the handler, subsequent handlers will be skipped
|
|
250
|
+
} catch (e) {
|
|
251
|
+
// Ignore handler exception, continue executing other handlers
|
|
252
|
+
requestIframeLog('error', 'Handler error', e);
|
|
253
|
+
} finally {
|
|
254
|
+
// Auto-ack once the message is accepted + handled.
|
|
255
|
+
maybeAutoAck();
|
|
243
256
|
}
|
|
244
|
-
}
|
|
245
|
-
try {
|
|
246
|
-
entry.handler(data, context);
|
|
247
|
-
// After handler execution, check if it marked the message as handled
|
|
248
|
-
// If context.handledBy is set by the handler, subsequent handlers will be skipped
|
|
249
|
-
} catch (e) {
|
|
250
|
-
// Ignore handler exception, continue executing other handlers
|
|
251
|
-
console.error('[request-iframe] Handler error:', e);
|
|
252
257
|
}
|
|
253
258
|
}
|
|
259
|
+
|
|
260
|
+
// Fallback: if a handler accepted+handled without throwing, ensure we auto-ack.
|
|
261
|
+
// (This is safe due to autoAckState guard.)
|
|
262
|
+
} catch (err) {
|
|
263
|
+
_iterator.e(err);
|
|
264
|
+
} finally {
|
|
265
|
+
_iterator.f();
|
|
254
266
|
}
|
|
255
|
-
|
|
256
|
-
_iterator.e(err);
|
|
267
|
+
maybeAutoAck();
|
|
257
268
|
} finally {
|
|
258
|
-
|
|
269
|
+
/**
|
|
270
|
+
* Mark as "done" only when this dispatcher actually claimed/handled this message.
|
|
271
|
+
* - If the message was never claimed (handledBy not set), we keep `doneBy` empty so another
|
|
272
|
+
* dispatcher/handler still has a chance to process it.
|
|
273
|
+
*/
|
|
274
|
+
if (context.handledBy) {
|
|
275
|
+
context.markDoneBy(context.handledBy);
|
|
276
|
+
}
|
|
259
277
|
}
|
|
260
278
|
}
|
|
261
279
|
|
|
@@ -277,29 +295,54 @@ export class MessageDispatcher {
|
|
|
277
295
|
var type = data.type;
|
|
278
296
|
|
|
279
297
|
// Don't auto-ack ack messages (avoid loops)
|
|
280
|
-
if (type === MessageType.ACK
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
298
|
+
if (type === MessageType.ACK) return;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* ACK-only requireAck workflow (no compatibility guarantees):
|
|
302
|
+
* - For any message with `requireAck === true`, once the message is accepted/handled
|
|
303
|
+
* (via `context.acceptedBy` + `context.handledBy`),
|
|
304
|
+
* we reply with `ack`.
|
|
305
|
+
*
|
|
306
|
+
* This unifies:
|
|
307
|
+
* - request delivery confirmation
|
|
308
|
+
* - response receipt confirmation
|
|
309
|
+
* - stream frame delivery confirmation (e.g. stream_data per-frame ack)
|
|
310
|
+
*/
|
|
311
|
+
if (data.requireAck === true && !!context.acceptedBy) {
|
|
312
|
+
var ack = this.getAutoAckEchoPayload(data.ack);
|
|
286
313
|
this.sendMessage(targetWindow, targetOrigin, MessageType.ACK, data.requestId, {
|
|
287
314
|
path: data.path,
|
|
288
315
|
targetId: data.creatorId,
|
|
289
|
-
|
|
290
|
-
});
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
if (shouldAckResponse && context.accepted === true) {
|
|
294
|
-
// Receipt acknowledgment for response/error
|
|
295
|
-
this.sendMessage(targetWindow, targetOrigin, MessageType.RECEIVED, data.requestId, {
|
|
296
|
-
path: data.path,
|
|
297
|
-
targetId: data.creatorId,
|
|
298
|
-
ackMeta: data.ackMeta
|
|
316
|
+
ack
|
|
299
317
|
});
|
|
300
318
|
}
|
|
301
319
|
}
|
|
302
320
|
|
|
321
|
+
/**
|
|
322
|
+
* Limit echoed ack payload size for auto-ack replies.
|
|
323
|
+
*
|
|
324
|
+
* We only echo a fixed shape `{ id, meta?: string }`:
|
|
325
|
+
* - If meta is too long, we drop meta and only echo `{ id }`.
|
|
326
|
+
* - If id is missing or too long, omit `ack` field.
|
|
327
|
+
*/
|
|
328
|
+
getAutoAckEchoPayload(rawAck) {
|
|
329
|
+
if (rawAck === undefined) return undefined;
|
|
330
|
+
var id = getAckId(rawAck);
|
|
331
|
+
if (id === undefined) return undefined;
|
|
332
|
+
if (typeof id === 'string' && id.length > this.autoAckMaxIdLength) return undefined;
|
|
333
|
+
var meta = getAckMeta(rawAck);
|
|
334
|
+
if (meta === undefined) return {
|
|
335
|
+
id
|
|
336
|
+
};
|
|
337
|
+
if (meta.length > this.autoAckMaxMetaLength) return {
|
|
338
|
+
id
|
|
339
|
+
};
|
|
340
|
+
return {
|
|
341
|
+
id,
|
|
342
|
+
meta
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
303
346
|
/**
|
|
304
347
|
* Check if message type matches
|
|
305
348
|
*/
|
|
@@ -310,7 +353,7 @@ export class MessageDispatcher {
|
|
|
310
353
|
if (matcher instanceof RegExp) {
|
|
311
354
|
return matcher.test(type);
|
|
312
355
|
}
|
|
313
|
-
if (
|
|
356
|
+
if (isFunction(matcher)) {
|
|
314
357
|
return matcher(type);
|
|
315
358
|
}
|
|
316
359
|
return false;
|
|
@@ -324,7 +367,7 @@ export class MessageDispatcher {
|
|
|
324
367
|
* @param message message data (already formatted as PostMessageData)
|
|
325
368
|
* @param targetOrigin target origin (defaults to '*')
|
|
326
369
|
*/
|
|
327
|
-
send(target, message, targetOrigin =
|
|
370
|
+
send(target, message, targetOrigin = OriginConstant.ANY) {
|
|
328
371
|
// Automatically set role and creatorId if not already set (for backward compatibility)
|
|
329
372
|
if (message.role === undefined) {
|
|
330
373
|
message.role = this.role;
|
|
@@ -332,7 +375,15 @@ export class MessageDispatcher {
|
|
|
332
375
|
if (message.creatorId === undefined && this.instanceId) {
|
|
333
376
|
message.creatorId = this.instanceId;
|
|
334
377
|
}
|
|
335
|
-
|
|
378
|
+
this.hooks.beforeSend.call(target, targetOrigin, message);
|
|
379
|
+
try {
|
|
380
|
+
var _ok = this.channel.send(target, message, targetOrigin);
|
|
381
|
+
this.hooks.afterSend.call(target, targetOrigin, message, _ok);
|
|
382
|
+
return _ok;
|
|
383
|
+
} catch (e) {
|
|
384
|
+
this.hooks.sendError.call(target, targetOrigin, message, e);
|
|
385
|
+
throw e;
|
|
386
|
+
}
|
|
336
387
|
}
|
|
337
388
|
|
|
338
389
|
/**
|
|
@@ -351,7 +402,7 @@ export class MessageDispatcher {
|
|
|
351
402
|
creatorId: this.instanceId,
|
|
352
403
|
secretKey: this.secretKey
|
|
353
404
|
}));
|
|
354
|
-
return this.
|
|
405
|
+
return this.send(target, message, targetOrigin);
|
|
355
406
|
}
|
|
356
407
|
|
|
357
408
|
// ==================== Utilities ====================
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream-specific error type.
|
|
3
|
+
*
|
|
4
|
+
* Notes:
|
|
5
|
+
* - This is for stream lifecycle / protocol / binding errors (not request/response errors).
|
|
6
|
+
* - Use `RequestIframeError` for request/response level failures.
|
|
7
|
+
*/
|
|
8
|
+
export class RequestIframeStreamError extends Error {
|
|
9
|
+
constructor(params) {
|
|
10
|
+
super(params.message);
|
|
11
|
+
this.name = 'RequestIframeStreamError';
|
|
12
|
+
this.code = params.code;
|
|
13
|
+
this.streamId = params.streamId;
|
|
14
|
+
this.requestId = params.requestId;
|
|
15
|
+
this.cause = params.cause;
|
|
16
|
+
|
|
17
|
+
// Maintain proper stack trace for where our error was thrown (only available on V8)
|
|
18
|
+
if (Error.captureStackTrace) {
|
|
19
|
+
Error.captureStackTrace(this, RequestIframeStreamError);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
package/esm/stream/index.js
CHANGED
|
@@ -7,8 +7,10 @@ export * from './types';
|
|
|
7
7
|
export { IframeWritableStream } from './writable-stream';
|
|
8
8
|
export { IframeFileWritableStream } from './file-stream';
|
|
9
9
|
|
|
10
|
+
// Stream error
|
|
11
|
+
export { RequestIframeStreamError } from './error';
|
|
10
12
|
// Readable stream (client-side)
|
|
11
|
-
export { IframeReadableStream
|
|
13
|
+
export { IframeReadableStream } from './readable-stream';
|
|
12
14
|
export { IframeFileReadableStream } from './file-stream';
|
|
13
15
|
|
|
14
16
|
// Type checking utility functions
|