request-iframe 0.2.0 → 0.2.2
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 +33 -11
- package/QUICKSTART.md +33 -11
- package/README.CN.md +157 -44
- package/README.md +159 -41
- package/cdn/request-iframe.umd.js +4814 -4026
- package/cdn/request-iframe.umd.js.map +1 -1
- package/cdn/request-iframe.umd.min.js +2 -2
- package/cdn/request-iframe.umd.min.js.map +1 -1
- package/esm/api/client.js +45 -22
- package/esm/api/endpoint.js +30 -13
- package/esm/api/server.js +22 -13
- package/esm/constants/warn-once.js +7 -1
- package/esm/endpoint/index.js +1 -2
- package/esm/endpoint/infra/inbox.js +5 -4
- package/esm/endpoint/infra/outbox.js +8 -8
- package/esm/endpoint/stream/file-auto-resolve.js +9 -8
- package/esm/impl/client.js +3 -2
- package/esm/impl/response.js +4 -2
- package/esm/impl/server.js +8 -6
- package/esm/message/channel.js +15 -3
- package/esm/message/dispatcher.js +27 -0
- package/esm/stream/file-stream.js +311 -72
- package/esm/stream/writable-stream.js +21 -4
- package/esm/utils/blob.js +17 -0
- package/esm/utils/debug-lazy.js +76 -0
- package/esm/utils/logger.js +33 -1
- package/esm/utils/strict-mode.js +85 -0
- package/esm/utils/warn-once.js +30 -0
- package/esm/utils/warnings.js +47 -0
- package/library/api/client.d.ts.map +1 -1
- package/library/api/client.js +45 -22
- package/library/api/endpoint.d.ts.map +1 -1
- package/library/api/endpoint.js +30 -13
- package/library/api/server.d.ts.map +1 -1
- package/library/api/server.js +22 -13
- package/library/constants/warn-once.d.ts +6 -0
- package/library/constants/warn-once.d.ts.map +1 -1
- package/library/constants/warn-once.js +7 -1
- package/library/endpoint/index.d.ts +0 -1
- package/library/endpoint/index.d.ts.map +1 -1
- package/library/endpoint/index.js +1 -8
- package/library/endpoint/infra/inbox.d.ts.map +1 -1
- package/library/endpoint/infra/inbox.js +4 -3
- package/library/endpoint/infra/outbox.d.ts +2 -0
- package/library/endpoint/infra/outbox.d.ts.map +1 -1
- package/library/endpoint/infra/outbox.js +7 -7
- package/library/endpoint/stream/file-auto-resolve.d.ts +1 -1
- package/library/endpoint/stream/file-auto-resolve.d.ts.map +1 -1
- package/library/endpoint/stream/file-auto-resolve.js +8 -8
- package/library/impl/client.d.ts +2 -0
- package/library/impl/client.d.ts.map +1 -1
- package/library/impl/client.js +3 -2
- package/library/impl/response.d.ts.map +1 -1
- package/library/impl/response.js +4 -2
- package/library/impl/server.d.ts.map +1 -1
- package/library/impl/server.js +7 -5
- package/library/message/channel.d.ts +2 -2
- package/library/message/channel.d.ts.map +1 -1
- package/library/message/channel.js +15 -3
- package/library/message/dispatcher.d.ts.map +1 -1
- package/library/message/dispatcher.js +27 -0
- package/library/stream/file-stream.d.ts +70 -5
- package/library/stream/file-stream.d.ts.map +1 -1
- package/library/stream/file-stream.js +310 -70
- package/library/stream/types.d.ts +2 -0
- package/library/stream/types.d.ts.map +1 -1
- package/library/stream/writable-stream.d.ts.map +1 -1
- package/library/stream/writable-stream.js +21 -4
- package/library/types/index.d.ts +38 -0
- package/library/types/index.d.ts.map +1 -1
- package/library/utils/blob.d.ts +7 -0
- package/library/utils/blob.d.ts.map +1 -1
- package/library/utils/blob.js +18 -0
- package/library/utils/debug-lazy.d.ts +26 -0
- package/library/utils/debug-lazy.d.ts.map +1 -0
- package/library/utils/debug-lazy.js +85 -0
- package/library/utils/logger.d.ts +20 -0
- package/library/utils/logger.d.ts.map +1 -1
- package/library/utils/logger.js +34 -1
- package/library/utils/strict-mode.d.ts +37 -0
- package/library/utils/strict-mode.d.ts.map +1 -0
- package/library/utils/strict-mode.js +94 -0
- package/library/utils/warn-once.d.ts +9 -0
- package/library/utils/warn-once.d.ts.map +1 -0
- package/library/utils/warn-once.js +36 -0
- package/library/utils/warnings.d.ts +48 -0
- package/library/utils/warnings.d.ts.map +1 -0
- package/library/utils/warnings.js +54 -0
- package/package.json +1 -1
- package/esm/endpoint/stream/file-writable.js +0 -105
- package/library/endpoint/stream/file-writable.d.ts +0 -33
- package/library/endpoint/stream/file-writable.d.ts.map +0 -1
- package/library/endpoint/stream/file-writable.js +0 -115
package/esm/api/client.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { getIframeTargetOrigin } from '../utils/iframe';
|
|
2
2
|
import { generateInstanceId } from '../utils/id';
|
|
3
3
|
import { RequestIframeClientImpl } from '../impl/client';
|
|
4
|
-
import { setupClientDebugInterceptors } from '../utils/debug';
|
|
5
4
|
import { setRequestIframeLogLevel } from '../utils/logger';
|
|
6
5
|
import { Messages, ErrorCode, OriginConstant, LogLevel } from '../constants';
|
|
7
6
|
import { clearMessageChannelCache } from '../message/channel-cache';
|
|
7
|
+
import { warnUnsafeTargetOriginForWindow } from '../utils/warnings';
|
|
8
|
+
import { ensureClientDebugInterceptors, loadDebugModule, wrapClientMethodsForDebug } from '../utils/debug-lazy';
|
|
9
|
+
import { applyStrictClientSecurityDefaults } from '../utils/strict-mode';
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* Create a client (for sending requests)
|
|
@@ -15,12 +17,13 @@ import { clearMessageChannelCache } from '../message/channel-cache';
|
|
|
15
17
|
* - This allows different versions of the library to coexist
|
|
16
18
|
*/
|
|
17
19
|
export function requestIframeClient(target, options) {
|
|
20
|
+
var _resolved$options;
|
|
18
21
|
var targetWindow = null;
|
|
19
|
-
var
|
|
22
|
+
var defaultTargetOrigin = OriginConstant.ANY;
|
|
20
23
|
if (target.tagName === 'IFRAME') {
|
|
21
24
|
var iframe = target;
|
|
22
25
|
targetWindow = iframe.contentWindow;
|
|
23
|
-
|
|
26
|
+
defaultTargetOrigin = getIframeTargetOrigin(iframe);
|
|
24
27
|
if (!targetWindow) {
|
|
25
28
|
throw {
|
|
26
29
|
message: Messages.IFRAME_NOT_READY,
|
|
@@ -29,16 +32,26 @@ export function requestIframeClient(target, options) {
|
|
|
29
32
|
}
|
|
30
33
|
} else {
|
|
31
34
|
targetWindow = target;
|
|
32
|
-
|
|
35
|
+
defaultTargetOrigin = OriginConstant.ANY;
|
|
33
36
|
}
|
|
37
|
+
var resolved = applyStrictClientSecurityDefaults(defaultTargetOrigin, options);
|
|
38
|
+
var targetOrigin = resolved.targetOrigin;
|
|
39
|
+
var resolvedOptions = (_resolved$options = resolved.options) !== null && _resolved$options !== void 0 ? _resolved$options : options;
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
/**
|
|
42
|
+
* P1: warn on unsafe default targetOrigin for Window targets.
|
|
43
|
+
* - If targetOrigin is '*' and user did not configure allowedOrigins/validateOrigin,
|
|
44
|
+
* incoming message origin validation is effectively disabled.
|
|
45
|
+
*/
|
|
46
|
+
warnUnsafeTargetOriginForWindow({
|
|
47
|
+
isIframeTarget: target.tagName === 'IFRAME',
|
|
48
|
+
targetOrigin,
|
|
49
|
+
allowedOrigins: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.allowedOrigins,
|
|
50
|
+
validateOrigin: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.validateOrigin
|
|
51
|
+
});
|
|
39
52
|
|
|
40
53
|
// Determine secretKey
|
|
41
|
-
var secretKey =
|
|
54
|
+
var secretKey = resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.secretKey;
|
|
42
55
|
|
|
43
56
|
// Generate instance ID first (will be used by both client and server)
|
|
44
57
|
var instanceId = generateInstanceId();
|
|
@@ -46,16 +59,16 @@ export function requestIframeClient(target, options) {
|
|
|
46
59
|
// Create client instance (internally creates its core message server)
|
|
47
60
|
var client = new RequestIframeClientImpl(targetWindow, targetOrigin, {
|
|
48
61
|
secretKey,
|
|
49
|
-
ackTimeout:
|
|
50
|
-
timeout:
|
|
51
|
-
asyncTimeout:
|
|
52
|
-
returnData:
|
|
53
|
-
headers:
|
|
54
|
-
allowedOrigins:
|
|
55
|
-
validateOrigin:
|
|
56
|
-
autoOpen:
|
|
57
|
-
autoAckMaxMetaLength:
|
|
58
|
-
autoAckMaxIdLength:
|
|
62
|
+
ackTimeout: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.ackTimeout,
|
|
63
|
+
timeout: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.timeout,
|
|
64
|
+
asyncTimeout: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.asyncTimeout,
|
|
65
|
+
returnData: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.returnData,
|
|
66
|
+
headers: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.headers,
|
|
67
|
+
allowedOrigins: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.allowedOrigins,
|
|
68
|
+
validateOrigin: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.validateOrigin,
|
|
69
|
+
autoOpen: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.autoOpen,
|
|
70
|
+
autoAckMaxMetaLength: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.autoAckMaxMetaLength,
|
|
71
|
+
autoAckMaxIdLength: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.autoAckMaxIdLength
|
|
59
72
|
}, instanceId);
|
|
60
73
|
|
|
61
74
|
/**
|
|
@@ -63,11 +76,21 @@ export function requestIframeClient(target, options) {
|
|
|
63
76
|
* - default: only warn/error will be printed (logger default)
|
|
64
77
|
* - if trace enabled: raise log level and (optionally) enable detailed debug interceptors
|
|
65
78
|
*/
|
|
66
|
-
if (
|
|
67
|
-
var level =
|
|
79
|
+
if (resolvedOptions !== null && resolvedOptions !== void 0 && resolvedOptions.trace) {
|
|
80
|
+
var level = resolvedOptions.trace === true ? LogLevel.TRACE : resolvedOptions.trace;
|
|
68
81
|
setRequestIframeLogLevel(level);
|
|
69
82
|
if (level === LogLevel.TRACE || level === LogLevel.INFO) {
|
|
70
|
-
|
|
83
|
+
/**
|
|
84
|
+
* Lazy-load debug hooks to keep main bundle smaller, but still ensure
|
|
85
|
+
* the first request in trace mode won't miss debug interceptors.
|
|
86
|
+
*/
|
|
87
|
+
wrapClientMethodsForDebug(client);
|
|
88
|
+
// Preheat import early (best-effort)
|
|
89
|
+
void loadDebugModule().catch(() => {
|
|
90
|
+
/** ignore */
|
|
91
|
+
});
|
|
92
|
+
// Attach ASAP (best-effort)
|
|
93
|
+
void ensureClientDebugInterceptors(client);
|
|
71
94
|
}
|
|
72
95
|
}
|
|
73
96
|
return client;
|
package/esm/api/endpoint.js
CHANGED
|
@@ -5,9 +5,11 @@ import { generateInstanceId } from '../utils/id';
|
|
|
5
5
|
import { isWindowAvailable } from '../utils/window';
|
|
6
6
|
import { RequestIframeClientImpl } from '../impl/client';
|
|
7
7
|
import { RequestIframeServerImpl } from '../impl/server';
|
|
8
|
-
import { setupClientDebugInterceptors, setupServerDebugListeners } from '../utils/debug';
|
|
9
8
|
import { setRequestIframeLogLevel } from '../utils/logger';
|
|
10
9
|
import { Messages, ErrorCode, OriginConstant, LogLevel } from '../constants';
|
|
10
|
+
import { warnUnsafeTargetOriginForWindow } from '../utils/warnings';
|
|
11
|
+
import { ensureClientDebugInterceptors, loadDebugModule, wrapClientMethodsForDebug } from '../utils/debug-lazy';
|
|
12
|
+
import { applyStrictClientSecurityDefaults, applyStrictServerSecurityDefaults } from '../utils/strict-mode';
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* Endpoint facade type (client + server).
|
|
@@ -71,7 +73,11 @@ class RequestIframeEndpointApiFacade {
|
|
|
71
73
|
var level = options.trace === true ? LogLevel.TRACE : options.trace;
|
|
72
74
|
setRequestIframeLogLevel(level);
|
|
73
75
|
if (level === LogLevel.TRACE || level === LogLevel.INFO) {
|
|
74
|
-
|
|
76
|
+
wrapClientMethodsForDebug(client);
|
|
77
|
+
void loadDebugModule().catch(() => {
|
|
78
|
+
/** ignore */
|
|
79
|
+
});
|
|
80
|
+
void ensureClientDebugInterceptors(client);
|
|
75
81
|
}
|
|
76
82
|
}
|
|
77
83
|
this.client_ = client;
|
|
@@ -106,7 +112,9 @@ class RequestIframeEndpointApiFacade {
|
|
|
106
112
|
var level = options.trace === true ? LogLevel.TRACE : options.trace;
|
|
107
113
|
setRequestIframeLogLevel(level);
|
|
108
114
|
if (level === LogLevel.TRACE || level === LogLevel.INFO) {
|
|
109
|
-
setupServerDebugListeners(server)
|
|
115
|
+
void loadDebugModule().then(m => m.setupServerDebugListeners(server)).catch(() => {
|
|
116
|
+
/** ignore */
|
|
117
|
+
});
|
|
110
118
|
}
|
|
111
119
|
}
|
|
112
120
|
this.server_ = server;
|
|
@@ -192,13 +200,13 @@ class RequestIframeEndpointApiFacade {
|
|
|
192
200
|
* - handle requests from the peer (server)
|
|
193
201
|
*/
|
|
194
202
|
export function requestIframeEndpoint(target, options) {
|
|
195
|
-
var
|
|
203
|
+
var _applyStrictServerSec, _resolvedClient$optio, _resolvedClient$optio2, _resolvedOptions$id;
|
|
196
204
|
var targetWindow = null;
|
|
197
|
-
var
|
|
205
|
+
var defaultTargetOrigin = OriginConstant.ANY;
|
|
198
206
|
if (target.tagName === 'IFRAME') {
|
|
199
207
|
var iframe = target;
|
|
200
208
|
targetWindow = iframe.contentWindow;
|
|
201
|
-
|
|
209
|
+
defaultTargetOrigin = getIframeTargetOrigin(iframe);
|
|
202
210
|
if (!targetWindow) {
|
|
203
211
|
throw {
|
|
204
212
|
message: Messages.IFRAME_NOT_READY,
|
|
@@ -207,23 +215,32 @@ export function requestIframeEndpoint(target, options) {
|
|
|
207
215
|
}
|
|
208
216
|
} else {
|
|
209
217
|
targetWindow = target;
|
|
210
|
-
|
|
218
|
+
defaultTargetOrigin = OriginConstant.ANY;
|
|
211
219
|
}
|
|
220
|
+
var resolvedClient = applyStrictClientSecurityDefaults(defaultTargetOrigin, options);
|
|
221
|
+
var targetOrigin = resolvedClient.targetOrigin;
|
|
222
|
+
var resolvedOptions = (_applyStrictServerSec = applyStrictServerSecurityDefaults((_resolvedClient$optio = resolvedClient.options) !== null && _resolvedClient$optio !== void 0 ? _resolvedClient$optio : options)) !== null && _applyStrictServerSec !== void 0 ? _applyStrictServerSec : (_resolvedClient$optio2 = resolvedClient.options) !== null && _resolvedClient$optio2 !== void 0 ? _resolvedClient$optio2 : options;
|
|
212
223
|
|
|
213
|
-
/**
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
224
|
+
/**
|
|
225
|
+
* P1: warn on unsafe default targetOrigin for Window targets.
|
|
226
|
+
* Endpoint facade is lazy (client/server created later), so warn here.
|
|
227
|
+
*/
|
|
228
|
+
warnUnsafeTargetOriginForWindow({
|
|
229
|
+
isIframeTarget: target.tagName === 'IFRAME',
|
|
230
|
+
targetOrigin,
|
|
231
|
+
allowedOrigins: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.allowedOrigins,
|
|
232
|
+
validateOrigin: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.validateOrigin
|
|
233
|
+
});
|
|
217
234
|
|
|
218
235
|
/**
|
|
219
236
|
* Endpoint uses ONE shared id by default, so it behaves like a single endpoint.
|
|
220
237
|
* If options.id is provided, it becomes the shared id for both client+server.
|
|
221
238
|
*/
|
|
222
|
-
var endpointId = (
|
|
239
|
+
var endpointId = (_resolvedOptions$id = resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.id) !== null && _resolvedOptions$id !== void 0 ? _resolvedOptions$id : generateInstanceId();
|
|
223
240
|
return new RequestIframeEndpointApiFacade({
|
|
224
241
|
targetWindow,
|
|
225
242
|
targetOrigin,
|
|
226
|
-
options,
|
|
243
|
+
options: resolvedOptions,
|
|
227
244
|
endpointId
|
|
228
245
|
});
|
|
229
246
|
}
|
package/esm/api/server.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { RequestIframeServerImpl } from '../impl/server';
|
|
2
|
-
import { setupServerDebugListeners } from '../utils/debug';
|
|
3
2
|
import { setRequestIframeLogLevel } from '../utils/logger';
|
|
4
3
|
import { getCachedServer, cacheServer, clearServerCache } from '../utils/cache';
|
|
5
4
|
import { LogLevel } from '../constants';
|
|
5
|
+
import { loadDebugModule } from '../utils/debug-lazy';
|
|
6
|
+
import { applyStrictServerSecurityDefaults } from '../utils/strict-mode';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Create a server (for receiving and handling requests)
|
|
@@ -14,9 +15,11 @@ import { LogLevel } from '../constants';
|
|
|
14
15
|
* - This allows different versions of the library to coexist
|
|
15
16
|
*/
|
|
16
17
|
export function requestIframeServer(options) {
|
|
18
|
+
var _applyStrictServerSec;
|
|
19
|
+
var resolvedOptions = (_applyStrictServerSec = applyStrictServerSecurityDefaults(options)) !== null && _applyStrictServerSec !== void 0 ? _applyStrictServerSec : options;
|
|
17
20
|
// Determine secretKey and id
|
|
18
|
-
var secretKey =
|
|
19
|
-
var id =
|
|
21
|
+
var secretKey = resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.secretKey;
|
|
22
|
+
var id = resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.id;
|
|
20
23
|
|
|
21
24
|
// If id is specified, check cache first
|
|
22
25
|
if (id) {
|
|
@@ -30,13 +33,13 @@ export function requestIframeServer(options) {
|
|
|
30
33
|
var server = new RequestIframeServerImpl({
|
|
31
34
|
secretKey,
|
|
32
35
|
id,
|
|
33
|
-
ackTimeout:
|
|
34
|
-
autoOpen:
|
|
35
|
-
allowedOrigins:
|
|
36
|
-
validateOrigin:
|
|
37
|
-
maxConcurrentRequestsPerClient:
|
|
38
|
-
autoAckMaxMetaLength:
|
|
39
|
-
autoAckMaxIdLength:
|
|
36
|
+
ackTimeout: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.ackTimeout,
|
|
37
|
+
autoOpen: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.autoOpen,
|
|
38
|
+
allowedOrigins: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.allowedOrigins,
|
|
39
|
+
validateOrigin: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.validateOrigin,
|
|
40
|
+
maxConcurrentRequestsPerClient: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.maxConcurrentRequestsPerClient,
|
|
41
|
+
autoAckMaxMetaLength: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.autoAckMaxMetaLength,
|
|
42
|
+
autoAckMaxIdLength: resolvedOptions === null || resolvedOptions === void 0 ? void 0 : resolvedOptions.autoAckMaxIdLength
|
|
40
43
|
});
|
|
41
44
|
|
|
42
45
|
/**
|
|
@@ -44,11 +47,17 @@ export function requestIframeServer(options) {
|
|
|
44
47
|
* - default: only warn/error will be printed (logger default)
|
|
45
48
|
* - if trace enabled: raise log level and (optionally) enable detailed debug listeners
|
|
46
49
|
*/
|
|
47
|
-
if (
|
|
48
|
-
var level =
|
|
50
|
+
if (resolvedOptions !== null && resolvedOptions !== void 0 && resolvedOptions.trace) {
|
|
51
|
+
var level = resolvedOptions.trace === true ? LogLevel.TRACE : resolvedOptions.trace;
|
|
49
52
|
setRequestIframeLogLevel(level);
|
|
50
53
|
if (level === LogLevel.TRACE || level === LogLevel.INFO) {
|
|
51
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Lazy-load debug hooks to keep main bundle smaller.
|
|
56
|
+
* Best-effort: ignore dynamic import errors.
|
|
57
|
+
*/
|
|
58
|
+
void loadDebugModule().then(m => m.setupServerDebugListeners(server)).catch(() => {
|
|
59
|
+
/** ignore */
|
|
60
|
+
});
|
|
52
61
|
}
|
|
53
62
|
}
|
|
54
63
|
|
|
@@ -7,7 +7,13 @@ import "core-js/modules/es.array.map.js";
|
|
|
7
7
|
|
|
8
8
|
export var WarnOnceKey = {
|
|
9
9
|
INBOX_MISSING_PENDING_WHEN_CLOSED: 'inbox:missingPendingWhenClosed',
|
|
10
|
-
SERVER_MISSING_PENDING_WHEN_CLOSED: 'server:missingPendingWhenClosed'
|
|
10
|
+
SERVER_MISSING_PENDING_WHEN_CLOSED: 'server:missingPendingWhenClosed',
|
|
11
|
+
/**
|
|
12
|
+
* Security warning:
|
|
13
|
+
* - targetOrigin is '*'
|
|
14
|
+
* - and no allowedOrigins/validateOrigin is configured
|
|
15
|
+
*/
|
|
16
|
+
TARGET_ORIGIN_ANY_WITHOUT_ORIGIN_VALIDATION: 'targetOrigin:anyWithoutOriginValidation'
|
|
11
17
|
};
|
|
12
18
|
export function buildWarnOnceKey(prefix, ...parts) {
|
|
13
19
|
if (!parts.length) return prefix;
|
package/esm/endpoint/index.js
CHANGED
|
@@ -9,5 +9,4 @@ export { parseStreamStart, createReadableStreamFromStart } from './stream/factor
|
|
|
9
9
|
export { RequestIframeEndpointFacade } from './facade';
|
|
10
10
|
export { createStreamMessageHandler } from './stream/handler';
|
|
11
11
|
export { buildStreamStartTimeoutErrorPayload } from './stream/errors';
|
|
12
|
-
export { autoResolveIframeFileReadableStream, parseFilenameFromContentDisposition } from './stream/file-auto-resolve';
|
|
13
|
-
export { createIframeFileWritableStreamFromContent } from './stream/file-writable';
|
|
12
|
+
export { autoResolveIframeFileReadableStream, parseFilenameFromContentDisposition } from './stream/file-auto-resolve';
|
|
@@ -2,10 +2,10 @@ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
|
2
2
|
import "core-js/modules/es.array.slice.js";
|
|
3
3
|
import "core-js/modules/es.promise.js";
|
|
4
4
|
import "core-js/modules/es.regexp.to-string.js";
|
|
5
|
-
import { MessageType, ProtocolVersion, Messages, formatMessage, MessageRole
|
|
5
|
+
import { MessageType, ProtocolVersion, Messages, formatMessage, MessageRole } from '../../constants';
|
|
6
6
|
import { createPingResponder } from '../heartbeat/ping';
|
|
7
7
|
import { SyncHook } from '../../utils/hooks';
|
|
8
|
-
import {
|
|
8
|
+
import { warnClientServerIgnoredMessageWhenClosedOnce } from '../../utils/warnings';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Pending request awaiting response
|
|
@@ -162,8 +162,9 @@ export class RequestIframeEndpointInbox {
|
|
|
162
162
|
*/
|
|
163
163
|
if (!this.hub.isOpen) {
|
|
164
164
|
this.hooks.missingPending.call(data, context);
|
|
165
|
-
this.hub
|
|
166
|
-
|
|
165
|
+
warnClientServerIgnoredMessageWhenClosedOnce(this.hub, {
|
|
166
|
+
type: data.type,
|
|
167
|
+
requestId: data.requestId
|
|
167
168
|
});
|
|
168
169
|
}
|
|
169
170
|
return;
|
|
@@ -8,8 +8,7 @@ import "core-js/modules/es.object.get-own-property-descriptors.js";
|
|
|
8
8
|
import "core-js/modules/es.promise.js";
|
|
9
9
|
import "core-js/modules/es.promise.finally.js";
|
|
10
10
|
import "core-js/modules/web.dom-collections.for-each.js";
|
|
11
|
-
import { isIframeWritableStream } from '../../stream';
|
|
12
|
-
import { createIframeFileWritableStreamFromContent } from '../stream/file-writable';
|
|
11
|
+
import { IframeFileWritableStream, isIframeWritableStream } from '../../stream';
|
|
13
12
|
import { SyncHook } from '../../utils/hooks';
|
|
14
13
|
|
|
15
14
|
/**
|
|
@@ -330,31 +329,32 @@ export class RequestIframeEndpointOutbox {
|
|
|
330
329
|
case 0:
|
|
331
330
|
return _context9.abrupt("return", _this5.runWithHooks(params, /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee8() {
|
|
332
331
|
var _params$onFileInfo;
|
|
333
|
-
var
|
|
332
|
+
var stream;
|
|
334
333
|
return _regeneratorRuntime.wrap(function (_context8) {
|
|
335
334
|
while (1) switch (_context8.prev = _context8.next) {
|
|
336
335
|
case 0:
|
|
337
336
|
_context8.next = 1;
|
|
338
|
-
return
|
|
337
|
+
return IframeFileWritableStream.from({
|
|
339
338
|
content: params.content,
|
|
340
339
|
fileName: params.fileName,
|
|
341
340
|
mimeType: params.mimeType,
|
|
342
341
|
chunked: params.chunked,
|
|
342
|
+
chunkSize: params.chunkSize,
|
|
343
343
|
autoResolve: params.autoResolve,
|
|
344
344
|
defaultFileName: params.defaultFileName,
|
|
345
345
|
defaultMimeType: params.defaultMimeType
|
|
346
346
|
});
|
|
347
347
|
case 1:
|
|
348
|
-
|
|
348
|
+
stream = _context8.sent;
|
|
349
349
|
_context8.next = 2;
|
|
350
350
|
return (_params$onFileInfo = params.onFileInfo) === null || _params$onFileInfo === void 0 ? void 0 : _params$onFileInfo.call(params, {
|
|
351
|
-
fileName:
|
|
352
|
-
mimeType:
|
|
351
|
+
fileName: stream.filename,
|
|
352
|
+
mimeType: stream.mimeType
|
|
353
353
|
});
|
|
354
354
|
case 2:
|
|
355
355
|
_context8.next = 3;
|
|
356
356
|
return _this5.runStreamSend(_objectSpread(_objectSpread({}, params.stream), {}, {
|
|
357
|
-
stream:
|
|
357
|
+
stream: stream
|
|
358
358
|
}));
|
|
359
359
|
case 3:
|
|
360
360
|
return _context8.abrupt("return", _context8.sent);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "core-js/modules/es.regexp.exec.js";
|
|
2
|
-
import "core-js/modules/es.string.match.js";
|
|
3
1
|
import { HttpHeader } from '../../constants';
|
|
2
|
+
import { IframeFileReadableStream } from '../../stream';
|
|
3
|
+
|
|
4
4
|
/**
|
|
5
5
|
* Endpoint Stream integration layer (`src/endpoint/stream`)
|
|
6
6
|
*
|
|
@@ -11,11 +11,7 @@ import { HttpHeader } from '../../constants';
|
|
|
11
11
|
* Parse filename from Content-Disposition header.
|
|
12
12
|
*/
|
|
13
13
|
export function parseFilenameFromContentDisposition(value) {
|
|
14
|
-
|
|
15
|
-
var disposition = typeof value === 'string' ? value : value[0];
|
|
16
|
-
if (!disposition) return undefined;
|
|
17
|
-
var match = disposition.match(/filename="?([^"]+)"?/i);
|
|
18
|
-
return match ? match[1] : undefined;
|
|
14
|
+
return IframeFileReadableStream.parseFilenameFromContentDisposition(value);
|
|
19
15
|
}
|
|
20
16
|
|
|
21
17
|
/**
|
|
@@ -30,5 +26,10 @@ export function autoResolveIframeFileReadableStream(params) {
|
|
|
30
26
|
var _params$headers, _params$info;
|
|
31
27
|
var headerFilename = parseFilenameFromContentDisposition((_params$headers = params.headers) === null || _params$headers === void 0 ? void 0 : _params$headers[HttpHeader.CONTENT_DISPOSITION]);
|
|
32
28
|
var fileName = headerFilename || ((_params$info = params.info) === null || _params$info === void 0 || (_params$info = _params$info.metadata) === null || _params$info === void 0 ? void 0 : _params$info.filename) || params.fileStream.filename;
|
|
33
|
-
|
|
29
|
+
var anyStream = params.fileStream;
|
|
30
|
+
if (typeof anyStream.readAsFileOrBlob === 'function') {
|
|
31
|
+
return anyStream.readAsFileOrBlob(fileName);
|
|
32
|
+
}
|
|
33
|
+
// Backward-compatible fallback for mocks/older stream objects
|
|
34
|
+
return fileName ? anyStream.readAsFile(fileName) : anyStream.readAsBlob();
|
|
34
35
|
}
|
package/esm/impl/client.js
CHANGED
|
@@ -296,7 +296,7 @@ export class RequestIframeClientImpl {
|
|
|
296
296
|
sendFile(path, content, options) {
|
|
297
297
|
var _this2 = this;
|
|
298
298
|
return _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
|
|
299
|
-
var _processedConfig$requ2, _processedConfig$targ, _options$autoResolve;
|
|
299
|
+
var _processedConfig$requ2, _processedConfig$targ, _options$chunked, _options$autoResolve;
|
|
300
300
|
var config, processedConfig, requestId, targetId, processedPath, mergedHeaders, pathMatchedCookies, mergedCookies, streamConfig;
|
|
301
301
|
return _regeneratorRuntime.wrap(function (_context2) {
|
|
302
302
|
while (1) switch (_context2.prev = _context2.next) {
|
|
@@ -322,7 +322,8 @@ export class RequestIframeClientImpl {
|
|
|
322
322
|
content,
|
|
323
323
|
fileName: options === null || options === void 0 ? void 0 : options.fileName,
|
|
324
324
|
mimeType: options === null || options === void 0 ? void 0 : options.mimeType,
|
|
325
|
-
chunked: false,
|
|
325
|
+
chunked: (_options$chunked = options === null || options === void 0 ? void 0 : options.chunked) !== null && _options$chunked !== void 0 ? _options$chunked : false,
|
|
326
|
+
chunkSize: options === null || options === void 0 ? void 0 : options.chunkSize,
|
|
326
327
|
autoResolve: (_options$autoResolve = options === null || options === void 0 ? void 0 : options.autoResolve) !== null && _options$autoResolve !== void 0 ? _options$autoResolve : true,
|
|
327
328
|
defaultFileName: typeof File !== 'undefined' && content instanceof File ? content.name : 'file',
|
|
328
329
|
defaultMimeType: 'application/octet-stream',
|
package/esm/impl/response.js
CHANGED
|
@@ -250,6 +250,7 @@ export class ServerResponseImpl {
|
|
|
250
250
|
sendFile(content, options) {
|
|
251
251
|
var _this2 = this;
|
|
252
252
|
return _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
|
|
253
|
+
var _options$chunked, _options$autoResolve;
|
|
253
254
|
return _regeneratorRuntime.wrap(function (_context3) {
|
|
254
255
|
while (1) switch (_context3.prev = _context3.next) {
|
|
255
256
|
case 0:
|
|
@@ -264,8 +265,9 @@ export class ServerResponseImpl {
|
|
|
264
265
|
content,
|
|
265
266
|
fileName: options === null || options === void 0 ? void 0 : options.fileName,
|
|
266
267
|
mimeType: options === null || options === void 0 ? void 0 : options.mimeType,
|
|
267
|
-
chunked: false,
|
|
268
|
-
|
|
268
|
+
chunked: (_options$chunked = options === null || options === void 0 ? void 0 : options.chunked) !== null && _options$chunked !== void 0 ? _options$chunked : false,
|
|
269
|
+
chunkSize: options === null || options === void 0 ? void 0 : options.chunkSize,
|
|
270
|
+
autoResolve: (_options$autoResolve = options === null || options === void 0 ? void 0 : options.autoResolve) !== null && _options$autoResolve !== void 0 ? _options$autoResolve : true,
|
|
269
271
|
defaultFileName: 'file',
|
|
270
272
|
defaultMimeType: 'application/octet-stream',
|
|
271
273
|
onFileInfo: ({
|
package/esm/impl/server.js
CHANGED
|
@@ -22,10 +22,10 @@ import { ServerRequestImpl } from './request';
|
|
|
22
22
|
import { ServerResponseImpl } from './response';
|
|
23
23
|
import { generateInstanceId } from '../utils/id';
|
|
24
24
|
import { RequestIframeEndpointFacade, buildStreamStartTimeoutErrorPayload, autoResolveIframeFileReadableStream } from '../endpoint';
|
|
25
|
-
import { MessageType, ErrorCode, HttpStatus, HttpStatusText, Messages, DefaultTimeout, ProtocolVersion,
|
|
25
|
+
import { MessageType, ErrorCode, HttpStatus, HttpStatusText, Messages, formatMessage, DefaultTimeout, ProtocolVersion, MessageRole, StreamType as StreamTypeConstant } from '../constants';
|
|
26
26
|
import { isPromise } from '../utils/promise';
|
|
27
27
|
import { isFunction } from '../utils/is';
|
|
28
|
-
import {
|
|
28
|
+
import { warnServerIgnoredMessageWhenClosedOnce } from '../utils/warnings';
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Middleware item (contains path matcher and middleware function)
|
|
@@ -61,8 +61,9 @@ export class RequestIframeServerImpl {
|
|
|
61
61
|
handledBy: this.id,
|
|
62
62
|
isOriginAllowed: (d, ctx) => this.isOriginAllowed(d, ctx),
|
|
63
63
|
warnMissingPendingWhenClosed: d => {
|
|
64
|
-
this.hub
|
|
65
|
-
|
|
64
|
+
warnServerIgnoredMessageWhenClosedOnce(this.hub, {
|
|
65
|
+
type: d.type,
|
|
66
|
+
requestId: d.requestId
|
|
66
67
|
});
|
|
67
68
|
}
|
|
68
69
|
},
|
|
@@ -77,8 +78,9 @@ export class RequestIframeServerImpl {
|
|
|
77
78
|
this.ackTimeout = (_options$ackTimeout = options === null || options === void 0 ? void 0 : options.ackTimeout) !== null && _options$ackTimeout !== void 0 ? _options$ackTimeout : DefaultTimeout.ACK;
|
|
78
79
|
this.maxConcurrentRequestsPerClient = (_options$maxConcurren = options === null || options === void 0 ? void 0 : options.maxConcurrentRequestsPerClient) !== null && _options$maxConcurren !== void 0 ? _options$maxConcurren : Number.POSITIVE_INFINITY;
|
|
79
80
|
var warnMissingPendingWhenClosed = d => {
|
|
80
|
-
this.hub
|
|
81
|
-
|
|
81
|
+
warnServerIgnoredMessageWhenClosedOnce(this.hub, {
|
|
82
|
+
type: d.type,
|
|
83
|
+
requestId: d.requestId
|
|
82
84
|
});
|
|
83
85
|
};
|
|
84
86
|
var handlerOptions = this.hub.createHandlerOptions(this.handleVersionError.bind(this));
|
package/esm/message/channel.js
CHANGED
|
@@ -228,10 +228,22 @@ export class MessageChannel {
|
|
|
228
228
|
* @param message message data (already formatted as PostMessageData)
|
|
229
229
|
* @param targetOrigin target origin (defaults to '*')
|
|
230
230
|
*/
|
|
231
|
-
send(target, message, targetOrigin = OriginConstant.ANY) {
|
|
231
|
+
send(target, message, targetOrigin = OriginConstant.ANY, transfer) {
|
|
232
232
|
if (!isWindowAvailable(target)) {
|
|
233
233
|
return false;
|
|
234
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Prefer transferable objects when provided.
|
|
237
|
+
* Use a try/catch fallback for environments that don't support the 3rd arg signature.
|
|
238
|
+
*/
|
|
239
|
+
if (transfer && transfer.length) {
|
|
240
|
+
try {
|
|
241
|
+
target.postMessage(message, targetOrigin, transfer);
|
|
242
|
+
return true;
|
|
243
|
+
} catch (_unused) {
|
|
244
|
+
/** fall through to 2-arg postMessage */
|
|
245
|
+
}
|
|
246
|
+
}
|
|
235
247
|
target.postMessage(message, targetOrigin);
|
|
236
248
|
return true;
|
|
237
249
|
}
|
|
@@ -244,11 +256,11 @@ export class MessageChannel {
|
|
|
244
256
|
* @param requestId request ID
|
|
245
257
|
* @param data additional data
|
|
246
258
|
*/
|
|
247
|
-
sendMessage(target, targetOrigin, type, requestId, data) {
|
|
259
|
+
sendMessage(target, targetOrigin, type, requestId, data, transfer) {
|
|
248
260
|
var message = createPostMessage(type, requestId, _objectSpread(_objectSpread({}, data), {}, {
|
|
249
261
|
secretKey: this.secretKey
|
|
250
262
|
}));
|
|
251
|
-
return this.send(target, message, targetOrigin);
|
|
263
|
+
return this.send(target, message, targetOrigin, transfer);
|
|
252
264
|
}
|
|
253
265
|
|
|
254
266
|
/**
|
|
@@ -24,6 +24,7 @@ import { isFunction } from '../utils/is';
|
|
|
24
24
|
import { getAckId, getAckMeta } from '../utils/ack';
|
|
25
25
|
import { SyncHook } from '../utils/hooks';
|
|
26
26
|
import { requestIframeLog } from '../utils/logger';
|
|
27
|
+
import { MessageContextStage } from './channel';
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* Message handler function type
|
|
@@ -200,6 +201,7 @@ export class MessageDispatcher {
|
|
|
200
201
|
return;
|
|
201
202
|
}
|
|
202
203
|
}
|
|
204
|
+
var offEarlyAutoAck;
|
|
203
205
|
try {
|
|
204
206
|
this.hooks.inbound.call(data, context);
|
|
205
207
|
var _type = data.type;
|
|
@@ -223,6 +225,25 @@ export class MessageDispatcher {
|
|
|
223
225
|
autoAckState.sent = true;
|
|
224
226
|
this.tryAutoAck(data, context);
|
|
225
227
|
};
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Early auto-ack: send ACK as soon as the handler "accepts" the message.
|
|
231
|
+
*
|
|
232
|
+
* Why:
|
|
233
|
+
* - For request delivery confirmation, ACK should represent "accepted/claimed by server"
|
|
234
|
+
* instead of "handler finished".
|
|
235
|
+
* - This keeps client-side ackTimeout meaningful and avoids being delayed by business logic.
|
|
236
|
+
*
|
|
237
|
+
* Notes:
|
|
238
|
+
* - Only contexts created by MessageChannel have onStateChange; tests may provide mocks.
|
|
239
|
+
* - We keep the original end-of-dispatch maybeAutoAck() as a fallback for older/edge contexts.
|
|
240
|
+
*/
|
|
241
|
+
var onStateChangeMaybe = context.onStateChange;
|
|
242
|
+
offEarlyAutoAck = typeof onStateChangeMaybe === 'function' ? onStateChangeMaybe('autoAck:early', (_prev, next) => {
|
|
243
|
+
if (next === MessageContextStage.ACCEPTED) {
|
|
244
|
+
maybeAutoAck();
|
|
245
|
+
}
|
|
246
|
+
}) : undefined;
|
|
226
247
|
var _iterator = _createForOfIteratorHelper(this.handlers),
|
|
227
248
|
_step;
|
|
228
249
|
try {
|
|
@@ -266,6 +287,12 @@ export class MessageDispatcher {
|
|
|
266
287
|
}
|
|
267
288
|
maybeAutoAck();
|
|
268
289
|
} finally {
|
|
290
|
+
try {
|
|
291
|
+
var _offEarlyAutoAck;
|
|
292
|
+
(_offEarlyAutoAck = offEarlyAutoAck) === null || _offEarlyAutoAck === void 0 || _offEarlyAutoAck();
|
|
293
|
+
} catch (_unused) {
|
|
294
|
+
// ignore
|
|
295
|
+
}
|
|
269
296
|
/**
|
|
270
297
|
* Mark as "done" only when this dispatcher actually claimed/handled this message.
|
|
271
298
|
* - If the message was never claimed (handledBy not set), we keep `doneBy` empty so another
|