request-iframe 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/README.CN.md +53 -6
  2. package/README.md +63 -10
  3. package/esm/api/client.js +79 -0
  4. package/esm/api/server.js +59 -0
  5. package/esm/constants/index.js +257 -0
  6. package/esm/constants/messages.js +155 -0
  7. package/esm/core/client-server.js +329 -0
  8. package/esm/core/client.js +873 -0
  9. package/esm/core/request.js +27 -0
  10. package/esm/core/response.js +451 -0
  11. package/esm/core/server.js +767 -0
  12. package/esm/index.js +21 -0
  13. package/esm/interceptors/index.js +122 -0
  14. package/esm/message/channel.js +181 -0
  15. package/esm/message/dispatcher.js +380 -0
  16. package/esm/message/index.js +2 -0
  17. package/esm/stream/file-stream.js +289 -0
  18. package/esm/stream/index.js +44 -0
  19. package/esm/stream/readable-stream.js +500 -0
  20. package/esm/stream/stream-core.js +91 -0
  21. package/esm/stream/types.js +1 -0
  22. package/esm/stream/writable-stream.js +582 -0
  23. package/esm/types/index.js +1 -0
  24. package/esm/utils/ack-meta.js +53 -0
  25. package/esm/utils/cache.js +147 -0
  26. package/esm/utils/cookie.js +352 -0
  27. package/esm/utils/debug.js +521 -0
  28. package/esm/utils/error.js +27 -0
  29. package/esm/utils/index.js +178 -0
  30. package/esm/utils/origin.js +28 -0
  31. package/esm/utils/path-match.js +148 -0
  32. package/esm/utils/protocol.js +157 -0
  33. package/library/api/client.d.ts.map +1 -1
  34. package/library/api/client.js +8 -1
  35. package/library/api/server.d.ts.map +1 -1
  36. package/library/api/server.js +4 -1
  37. package/library/constants/index.d.ts +25 -1
  38. package/library/constants/index.d.ts.map +1 -1
  39. package/library/constants/index.js +30 -5
  40. package/library/constants/messages.d.ts +5 -0
  41. package/library/constants/messages.d.ts.map +1 -1
  42. package/library/constants/messages.js +5 -0
  43. package/library/core/client-server.d.ts +3 -2
  44. package/library/core/client-server.d.ts.map +1 -1
  45. package/library/core/client-server.js +51 -4
  46. package/library/core/client.d.ts +4 -1
  47. package/library/core/client.d.ts.map +1 -1
  48. package/library/core/client.js +74 -31
  49. package/library/core/response.d.ts +21 -3
  50. package/library/core/response.d.ts.map +1 -1
  51. package/library/core/response.js +46 -6
  52. package/library/core/server.d.ts +28 -1
  53. package/library/core/server.d.ts.map +1 -1
  54. package/library/core/server.js +180 -19
  55. package/library/message/channel.d.ts +6 -0
  56. package/library/message/channel.d.ts.map +1 -1
  57. package/library/message/dispatcher.d.ts +22 -0
  58. package/library/message/dispatcher.d.ts.map +1 -1
  59. package/library/message/dispatcher.js +92 -0
  60. package/library/stream/file-stream.d.ts +4 -0
  61. package/library/stream/file-stream.d.ts.map +1 -1
  62. package/library/stream/file-stream.js +61 -33
  63. package/library/stream/index.d.ts.map +1 -1
  64. package/library/stream/index.js +2 -0
  65. package/library/stream/readable-stream.d.ts +30 -11
  66. package/library/stream/readable-stream.d.ts.map +1 -1
  67. package/library/stream/readable-stream.js +329 -73
  68. package/library/stream/stream-core.d.ts +44 -0
  69. package/library/stream/stream-core.d.ts.map +1 -0
  70. package/library/stream/stream-core.js +98 -0
  71. package/library/stream/types.d.ts +90 -3
  72. package/library/stream/types.d.ts.map +1 -1
  73. package/library/stream/writable-stream.d.ts +40 -12
  74. package/library/stream/writable-stream.d.ts.map +1 -1
  75. package/library/stream/writable-stream.js +391 -195
  76. package/library/types/index.d.ts +70 -3
  77. package/library/types/index.d.ts.map +1 -1
  78. package/library/utils/ack-meta.d.ts +2 -0
  79. package/library/utils/ack-meta.d.ts.map +1 -0
  80. package/library/utils/ack-meta.js +59 -0
  81. package/library/utils/index.d.ts +1 -0
  82. package/library/utils/index.d.ts.map +1 -1
  83. package/library/utils/index.js +16 -0
  84. package/library/utils/origin.d.ts +14 -0
  85. package/library/utils/origin.d.ts.map +1 -0
  86. package/library/utils/origin.js +34 -0
  87. package/package.json +30 -7
  88. package/react/README.md +16 -0
  89. package/react/esm/index.js +284 -0
  90. package/react/library/index.d.ts +1 -1
  91. package/react/library/index.d.ts.map +1 -1
  92. package/react/library/index.js +3 -3
  93. package/react/package.json +24 -2
package/esm/index.js ADDED
@@ -0,0 +1,21 @@
1
+ // API
2
+ export { requestIframeClient, clearRequestIframeClientCache } from './api/client';
3
+ export { requestIframeServer, clearRequestIframeServerCache } from './api/server';
4
+ // Implementation classes
5
+ export { RequestIframeClientImpl } from './core/client';
6
+ export { RequestIframeServerImpl } from './core/server';
7
+ export { RequestIframeClientServer } from './core/client-server';
8
+ // MessageChannel and MessageDispatcher
9
+ export { MessageChannel, ChannelType, MessageDispatcher } from './message';
10
+ // Cache utilities
11
+ export { getOrCreateMessageChannel, releaseMessageChannel, clearMessageChannelCache } from './utils/cache';
12
+ export { ServerRequestImpl } from './core/request';
13
+ export { ServerResponseImpl } from './core/response';
14
+ // Stream
15
+ export { IframeWritableStream, IframeReadableStream, IframeFileWritableStream, IframeFileReadableStream, isIframeReadableStream, isIframeFileReadableStream, isIframeFileWritableStream, isIframeWritableStream } from './stream';
16
+ // Types and utilities
17
+ export * from './types';
18
+ export { detectContentType, blobToBase64, RequestIframeError } from './utils';
19
+ export { InterceptorManager, RequestInterceptorManager, ResponseInterceptorManager } from './interceptors';
20
+ // Constants
21
+ export * from './constants';
@@ -0,0 +1,122 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
2
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
3
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
4
+ import "core-js/modules/es.promise.js";
5
+ import "core-js/modules/web.dom-collections.for-each.js";
6
+ /**
7
+ * Interceptor manager
8
+ */
9
+ export class InterceptorManager {
10
+ constructor() {
11
+ _defineProperty(this, "handlers", []);
12
+ }
13
+ /**
14
+ * Add interceptor
15
+ */
16
+ use(fulfilled, rejected) {
17
+ this.handlers.push({
18
+ fulfilled,
19
+ rejected
20
+ });
21
+ return this.handlers.length - 1;
22
+ }
23
+
24
+ /**
25
+ * Remove interceptor
26
+ */
27
+ eject(id) {
28
+ if (this.handlers[id]) {
29
+ this.handlers[id] = null;
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Clear all interceptors
35
+ */
36
+ clear() {
37
+ this.handlers.length = 0;
38
+ }
39
+
40
+ /**
41
+ * Iterate over all interceptors
42
+ */
43
+ forEach(fn) {
44
+ this.handlers.forEach(h => {
45
+ if (h !== null) {
46
+ fn(h);
47
+ }
48
+ });
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Request interceptor manager
54
+ */
55
+ export class RequestInterceptorManager extends InterceptorManager {}
56
+
57
+ /**
58
+ * Response interceptor manager
59
+ */
60
+ export class ResponseInterceptorManager extends InterceptorManager {}
61
+
62
+ /**
63
+ * Execute request interceptor chain
64
+ */
65
+ export function runRequestInterceptors(_x, _x2) {
66
+ return _runRequestInterceptors.apply(this, arguments);
67
+ }
68
+
69
+ /**
70
+ * Execute response interceptor chain
71
+ */
72
+ function _runRequestInterceptors() {
73
+ _runRequestInterceptors = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(interceptors, config) {
74
+ var promise;
75
+ return _regeneratorRuntime.wrap(function (_context) {
76
+ while (1) switch (_context.prev = _context.next) {
77
+ case 0:
78
+ promise = Promise.resolve(config);
79
+ interceptors.forEach(interceptor => {
80
+ promise = promise.then(config => interceptor.fulfilled(config), error => {
81
+ if (interceptor.rejected) {
82
+ return interceptor.rejected(error);
83
+ }
84
+ return Promise.reject(error);
85
+ });
86
+ });
87
+ return _context.abrupt("return", promise);
88
+ case 1:
89
+ case "end":
90
+ return _context.stop();
91
+ }
92
+ }, _callee);
93
+ }));
94
+ return _runRequestInterceptors.apply(this, arguments);
95
+ }
96
+ export function runResponseInterceptors(_x3, _x4) {
97
+ return _runResponseInterceptors.apply(this, arguments);
98
+ }
99
+ function _runResponseInterceptors() {
100
+ _runResponseInterceptors = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(interceptors, response) {
101
+ var promise;
102
+ return _regeneratorRuntime.wrap(function (_context2) {
103
+ while (1) switch (_context2.prev = _context2.next) {
104
+ case 0:
105
+ promise = Promise.resolve(response);
106
+ interceptors.forEach(interceptor => {
107
+ promise = promise.then(response => interceptor.fulfilled(response), error => {
108
+ if (interceptor.rejected) {
109
+ return interceptor.rejected(error);
110
+ }
111
+ return Promise.reject(error);
112
+ });
113
+ });
114
+ return _context2.abrupt("return", promise);
115
+ case 1:
116
+ case "end":
117
+ return _context2.stop();
118
+ }
119
+ }, _callee2);
120
+ }));
121
+ return _runResponseInterceptors.apply(this, arguments);
122
+ }
@@ -0,0 +1,181 @@
1
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
+ 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; }
3
+ 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) { _defineProperty(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; }
4
+ import "core-js/modules/es.array.filter.js";
5
+ import "core-js/modules/es.array.iterator.js";
6
+ import "core-js/modules/es.object.get-own-property-descriptors.js";
7
+ import "core-js/modules/es.set.js";
8
+ import "core-js/modules/web.dom-collections.for-each.js";
9
+ import "core-js/modules/web.dom-collections.iterator.js";
10
+ import { isValidPostMessage, createPostMessage, isWindowAvailable } from '../utils';
11
+
12
+ /**
13
+ * Message context (extracted from MessageEvent, transport-agnostic)
14
+ */
15
+
16
+ /**
17
+ * Message receiver callback
18
+ */
19
+
20
+ /**
21
+ * Channel type constants
22
+ */
23
+ export var ChannelType = {
24
+ /** postMessage channel type */
25
+ POST_MESSAGE: 'postMessage'
26
+ };
27
+
28
+ /**
29
+ * Channel type
30
+ */
31
+
32
+ /**
33
+ * MessageChannel - Low-level communication channel for postMessage
34
+ *
35
+ * Responsibilities:
36
+ * - Listening to window.postMessage events
37
+ * - Filtering messages by secretKey
38
+ * - Extracting transport-specific information (MessageEvent) into generic MessageContext
39
+ * - Forwarding received messages to registered receivers
40
+ * - Sending messages to target windows
41
+ *
42
+ * This is the low-level communication layer that handles postMessage directly.
43
+ * All transport-specific details (like MessageEvent) are encapsulated here.
44
+ */
45
+ export class MessageChannel {
46
+ constructor(secretKey, type = ChannelType.POST_MESSAGE) {
47
+ /** Channel type (used for cache isolation) */
48
+ /** Secret key for message isolation */
49
+ /** Message receiver callbacks (support multiple receivers) */
50
+ _defineProperty(this, "receivers", new Set());
51
+ /** Reference count (for cache management) */
52
+ _defineProperty(this, "refCount", 0);
53
+ this.type = type;
54
+ this.secretKey = secretKey;
55
+ this.boundOnMessage = this.onMessage.bind(this);
56
+ window.addEventListener('message', this.boundOnMessage);
57
+ }
58
+
59
+ /**
60
+ * Add message receiver callback
61
+ * When a message is received, it will be forwarded to all registered receivers
62
+ */
63
+ addReceiver(receiver) {
64
+ this.receivers.add(receiver);
65
+ }
66
+
67
+ /**
68
+ * Remove message receiver callback
69
+ */
70
+ removeReceiver(receiver) {
71
+ this.receivers.delete(receiver);
72
+ }
73
+
74
+ /**
75
+ * Increment reference count (for cache management)
76
+ */
77
+ addRef() {
78
+ this.refCount++;
79
+ }
80
+
81
+ /**
82
+ * Decrement reference count (for cache management)
83
+ * @returns current reference count
84
+ */
85
+ release() {
86
+ return --this.refCount;
87
+ }
88
+
89
+ /**
90
+ * Get reference count (for cache management)
91
+ */
92
+ getRefCount() {
93
+ return this.refCount;
94
+ }
95
+
96
+ /**
97
+ * Extract MessageContext from MessageEvent
98
+ * This encapsulates transport-specific details
99
+ */
100
+ extractContext(event) {
101
+ return {
102
+ source: event.source,
103
+ origin: event.origin
104
+ };
105
+ }
106
+
107
+ /**
108
+ * Message handling entry point
109
+ */
110
+ onMessage(event) {
111
+ var data = event.data;
112
+
113
+ // Check if this is a request-iframe framework message (basic format validation)
114
+ if (!isValidPostMessage(data)) {
115
+ return;
116
+ }
117
+
118
+ // secretKey isolation
119
+ if (this.secretKey) {
120
+ if (data.secretKey !== this.secretKey) return;
121
+ } else {
122
+ if (data.secretKey) return;
123
+ }
124
+
125
+ // Extract context from transport-specific event
126
+ var context = this.extractContext(event);
127
+
128
+ // Forward to all registered receivers
129
+ this.receivers.forEach(receiver => {
130
+ try {
131
+ receiver(data, context);
132
+ } catch (e) {
133
+ console.error('[request-iframe] Receiver error:', e);
134
+ }
135
+ });
136
+ }
137
+
138
+ /**
139
+ * Send raw message to target window
140
+ * @param target target window
141
+ * @param message message data (already formatted as PostMessageData)
142
+ * @param targetOrigin target origin (defaults to '*')
143
+ */
144
+ send(target, message, targetOrigin = '*') {
145
+ if (!isWindowAvailable(target)) {
146
+ return false;
147
+ }
148
+ target.postMessage(message, targetOrigin);
149
+ return true;
150
+ }
151
+
152
+ /**
153
+ * Send typed message to target window (creates PostMessageData automatically)
154
+ * @param target target window
155
+ * @param targetOrigin target origin
156
+ * @param type message type
157
+ * @param requestId request ID
158
+ * @param data additional data
159
+ */
160
+ sendMessage(target, targetOrigin, type, requestId, data) {
161
+ var message = createPostMessage(type, requestId, _objectSpread(_objectSpread({}, data), {}, {
162
+ secretKey: this.secretKey
163
+ }));
164
+ return this.send(target, message, targetOrigin);
165
+ }
166
+
167
+ /**
168
+ * Add path prefix (for secretKey isolation)
169
+ */
170
+ prefixPath(path) {
171
+ return this.secretKey ? `${this.secretKey}:${path}` : path;
172
+ }
173
+
174
+ /**
175
+ * Destroy channel (remove event listener)
176
+ */
177
+ destroy() {
178
+ window.removeEventListener('message', this.boundOnMessage);
179
+ this.receivers.clear();
180
+ }
181
+ }
@@ -0,0 +1,380 @@
1
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
+ 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; }
3
+ 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) { _defineProperty(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; }
4
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
5
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
6
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
7
+ import "core-js/modules/es.symbol.description.js";
8
+ import "core-js/modules/es.array.filter.js";
9
+ import "core-js/modules/es.array.from.js";
10
+ import "core-js/modules/es.array.index-of.js";
11
+ import "core-js/modules/es.array.iterator.js";
12
+ import "core-js/modules/es.array.slice.js";
13
+ import "core-js/modules/es.array.sort.js";
14
+ import "core-js/modules/es.array.splice.js";
15
+ import "core-js/modules/web.dom-collections.for-each.js";
16
+ import "core-js/modules/web.dom-collections.iterator.js";
17
+ import "core-js/modules/es.object.get-own-property-descriptors.js";
18
+ import "core-js/modules/es.regexp.constructor.js";
19
+ import "core-js/modules/es.regexp.exec.js";
20
+ import "core-js/modules/es.regexp.to-string.js";
21
+ import { MessageRole, MessageType } from '../constants';
22
+ import { getProtocolVersion, createPostMessage } from '../utils';
23
+
24
+ /**
25
+ * Message handler function type
26
+ */
27
+
28
+ /**
29
+ * Message type matcher
30
+ * - string: exact match message type
31
+ * - RegExp: regex match message type
32
+ * - function: custom match function
33
+ */
34
+
35
+ /**
36
+ * Protocol version validator function
37
+ * @param version protocol version in message
38
+ * @returns true if version is compatible, false otherwise
39
+ */
40
+
41
+ /**
42
+ * Message handler registration options
43
+ */
44
+
45
+ /**
46
+ * Message handler entry
47
+ */
48
+
49
+ /**
50
+ * MessageDispatcher - Message dispatcher for client/server interaction
51
+ *
52
+ * Responsibilities:
53
+ * - Using MessageChannel for receiving and sending messages
54
+ * - Dispatching received messages to registered handlers
55
+ * - Managing handler registration/unregistration
56
+ * - Protocol version validation
57
+ *
58
+ * This is the high-level interface used by client and server implementations.
59
+ * It works with transport-agnostic MessageContext instead of transport-specific MessageEvent.
60
+ */
61
+ export class MessageDispatcher {
62
+ constructor(channel, role, instanceId) {
63
+ /** Secret key for message isolation */
64
+ /** Channel type */
65
+ /** Role of this dispatcher ('client' or 'server') */
66
+ /** Instance ID of the client/server that owns this dispatcher */
67
+ /** Underlying message channel */
68
+ /**
69
+ * Fallback target for sending auto-ack messages when MessageEvent.source is unavailable.
70
+ * - In real browser postMessage events, `source` should normally exist.
71
+ * - This is primarily used for unit tests or edge environments that synthesize MessageEvent without `source`.
72
+ */
73
+ _defineProperty(this, "fallbackTargetOrigin", '*');
74
+ /** Message handler list */
75
+ _defineProperty(this, "handlers", []);
76
+ /** Reference count (for determining if can be destroyed when cached) */
77
+ _defineProperty(this, "refCount", 0);
78
+ this.channel = channel;
79
+ this.secretKey = channel.secretKey;
80
+ this.type = channel.type;
81
+ this.role = role;
82
+ this.instanceId = instanceId;
83
+
84
+ // Create bound receiver callback
85
+ this.boundReceiver = (data, context) => {
86
+ this.dispatchMessage(data, context);
87
+ };
88
+
89
+ // Add receiver callback to handle incoming messages
90
+ this.channel.addReceiver(this.boundReceiver);
91
+ }
92
+
93
+ /**
94
+ * Set fallback target for outgoing auto-ack messages.
95
+ */
96
+ setFallbackTarget(targetWindow, targetOrigin = '*') {
97
+ this.fallbackTargetWindow = targetWindow;
98
+ this.fallbackTargetOrigin = targetOrigin;
99
+ }
100
+
101
+ // ==================== Reference Counting ====================
102
+
103
+ /**
104
+ * Increment reference count
105
+ */
106
+ addRef() {
107
+ this.refCount++;
108
+ }
109
+
110
+ /**
111
+ * Decrement reference count
112
+ * @returns current reference count
113
+ */
114
+ release() {
115
+ return --this.refCount;
116
+ }
117
+
118
+ /**
119
+ * Get reference count
120
+ */
121
+ getRefCount() {
122
+ return this.refCount;
123
+ }
124
+
125
+ // ==================== Message Handling ====================
126
+
127
+ /**
128
+ * Register message handler
129
+ * @param matcher message type matcher
130
+ * @param handler handler function
131
+ * @param options registration options (priority, version validation, etc.)
132
+ * @returns function to unregister
133
+ */
134
+ registerHandler(matcher, handler, options) {
135
+ var _opts$priority;
136
+ var opts = typeof options === 'number' ? {
137
+ priority: options
138
+ } : options || {};
139
+ var entry = {
140
+ matcher,
141
+ handler,
142
+ priority: (_opts$priority = opts.priority) !== null && _opts$priority !== void 0 ? _opts$priority : 0,
143
+ versionValidator: opts.versionValidator,
144
+ onVersionError: opts.onVersionError
145
+ };
146
+ this.handlers.push(entry);
147
+ // Sort by priority in descending order
148
+ this.handlers.sort((a, b) => b.priority - a.priority);
149
+ return () => {
150
+ var index = this.handlers.indexOf(entry);
151
+ if (index >= 0) {
152
+ this.handlers.splice(index, 1);
153
+ }
154
+ };
155
+ }
156
+
157
+ /**
158
+ * Unregister message handler
159
+ */
160
+ unregisterHandler(handler) {
161
+ var index = this.handlers.findIndex(entry => entry.handler === handler);
162
+ if (index >= 0) {
163
+ this.handlers.splice(index, 1);
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Dispatch message to matching handlers
169
+ */
170
+ dispatchMessage(data, context) {
171
+ // If message has already been handled by another dispatcher, skip processing
172
+ if (context.handledBy) {
173
+ return;
174
+ }
175
+
176
+ // Role-based message filtering: only process messages from the opposite role
177
+ // - Server only processes messages from client (role === 'client')
178
+ // - Client only processes messages from server (role === 'server')
179
+ if (data.role !== undefined) {
180
+ var expectedRole = this.role === MessageRole.CLIENT ? MessageRole.SERVER : MessageRole.CLIENT;
181
+ if (data.role !== expectedRole) {
182
+ // Message is from the same role, ignore it to prevent routing confusion
183
+ return;
184
+ }
185
+ }
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
+ try {
205
+ Object.defineProperty(context, 'handledBy', {
206
+ configurable: true,
207
+ enumerable: true,
208
+ get() {
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) {
220
+ /**
221
+ * In very rare cases `defineProperty` may fail (frozen object).
222
+ * We still proceed without auto-ack; handlers will continue to work as before.
223
+ */
224
+ }
225
+ var _iterator = _createForOfIteratorHelper(this.handlers),
226
+ _step;
227
+ try {
228
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
229
+ var entry = _step.value;
230
+ if (this.matchType(type, entry.matcher)) {
231
+ // If message has been handled by a previous handler, stop processing
232
+ if (context.handledBy) {
233
+ break;
234
+ }
235
+
236
+ // If handler specified version validation
237
+ if (entry.versionValidator && version !== undefined) {
238
+ if (!entry.versionValidator(version)) {
239
+ var _entry$onVersionError;
240
+ // Version incompatible, call error handler (if any)
241
+ (_entry$onVersionError = entry.onVersionError) === null || _entry$onVersionError === void 0 || _entry$onVersionError.call(entry, data, context, version);
242
+ continue; // Skip this handler, try other handlers
243
+ }
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
+ }
253
+ }
254
+ }
255
+ } catch (err) {
256
+ _iterator.e(err);
257
+ } finally {
258
+ _iterator.f();
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Auto-ack logic (generalized requireAck workflow)
264
+ *
265
+ * Notes:
266
+ * - This is intentionally conservative: it only runs after the message is marked as handled
267
+ * (via `context.handledBy`) to avoid acknowledging messages that no consumer will process.
268
+ * - For backward compatibility:
269
+ * - REQUEST defaults to requiring ACK unless `requireAck === false`
270
+ * - Other message types only ack when `requireAck === true`
271
+ */
272
+ tryAutoAck(data, context) {
273
+ var _context$source;
274
+ var targetWindow = (_context$source = context.source) !== null && _context$source !== void 0 ? _context$source : this.fallbackTargetWindow;
275
+ if (!targetWindow) return;
276
+ var targetOrigin = context.source ? context.origin : this.fallbackTargetOrigin || context.origin;
277
+ var type = data.type;
278
+
279
+ // Don't auto-ack ack messages (avoid loops)
280
+ if (type === MessageType.ACK || type === MessageType.RECEIVED) return;
281
+ var shouldAckRequest = type === MessageType.REQUEST && data.requireAck !== false;
282
+ var shouldAckPing = type === MessageType.PING && data.requireAck === true;
283
+ var shouldAckResponse = (type === MessageType.RESPONSE || type === MessageType.ERROR) && data.requireAck === true;
284
+ if ((shouldAckRequest || shouldAckPing) && context.accepted === true) {
285
+ // Delivery acknowledgment for request/ping
286
+ this.sendMessage(targetWindow, targetOrigin, MessageType.ACK, data.requestId, {
287
+ path: data.path,
288
+ targetId: data.creatorId,
289
+ ackMeta: data.ackMeta
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
299
+ });
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Check if message type matches
305
+ */
306
+ matchType(type, matcher) {
307
+ if (typeof matcher === 'string') {
308
+ return type === matcher;
309
+ }
310
+ if (matcher instanceof RegExp) {
311
+ return matcher.test(type);
312
+ }
313
+ if (typeof matcher === 'function') {
314
+ return matcher(type);
315
+ }
316
+ return false;
317
+ }
318
+
319
+ // ==================== Sending (Delegated to Channel) ====================
320
+
321
+ /**
322
+ * Send raw message to target window
323
+ * @param target target window
324
+ * @param message message data (already formatted as PostMessageData)
325
+ * @param targetOrigin target origin (defaults to '*')
326
+ */
327
+ send(target, message, targetOrigin = '*') {
328
+ // Automatically set role and creatorId if not already set (for backward compatibility)
329
+ if (message.role === undefined) {
330
+ message.role = this.role;
331
+ }
332
+ if (message.creatorId === undefined && this.instanceId) {
333
+ message.creatorId = this.instanceId;
334
+ }
335
+ return this.channel.send(target, message, targetOrigin);
336
+ }
337
+
338
+ /**
339
+ * Send typed message to target window (creates PostMessageData automatically)
340
+ * @param target target window
341
+ * @param targetOrigin target origin
342
+ * @param type message type
343
+ * @param requestId request ID
344
+ * @param data additional data
345
+ */
346
+ sendMessage(target, targetOrigin, type, requestId, data) {
347
+ // Automatically set role, creatorId, and secretKey based on dispatcher's properties
348
+ // Create message with role, creatorId, and secretKey using createPostMessage directly
349
+ var message = createPostMessage(type, requestId, _objectSpread(_objectSpread({}, data), {}, {
350
+ role: this.role,
351
+ creatorId: this.instanceId,
352
+ secretKey: this.secretKey
353
+ }));
354
+ return this.channel.send(target, message, targetOrigin);
355
+ }
356
+
357
+ // ==================== Utilities ====================
358
+
359
+ /**
360
+ * Add path prefix
361
+ */
362
+ prefixPath(path) {
363
+ return this.channel.prefixPath(path);
364
+ }
365
+
366
+ /**
367
+ * Get the underlying message channel
368
+ */
369
+ getChannel() {
370
+ return this.channel;
371
+ }
372
+
373
+ /**
374
+ * Destroy dispatcher (clear handlers, but don't destroy channel as it may be shared)
375
+ */
376
+ destroy() {
377
+ this.handlers.length = 0;
378
+ this.channel.removeReceiver(this.boundReceiver);
379
+ }
380
+ }