@bleedingdev/modern-js-renderer-core 3.9.3-ultramodern.7 → 3.9.3-ultramodern.9

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 (53) hide show
  1. package/dist/cjs/adapter.js +1 -1
  2. package/dist/cjs/data/codec.js +1 -1
  3. package/dist/cjs/entry-client.js +5 -0
  4. package/dist/cjs/federation.js +14 -5
  5. package/dist/cjs/server/worker.js +2 -1
  6. package/dist/cjs/worker-federation/contract.js +298 -0
  7. package/dist/cjs/worker-federation/handler.js +197 -0
  8. package/dist/cjs/worker-federation/index.js +63 -0
  9. package/dist/cjs/worker-federation/lease.js +167 -0
  10. package/dist/cjs/worker-federation/transport.js +272 -0
  11. package/dist/esm/adapter.mjs +1 -1
  12. package/dist/esm/data/codec.mjs +1 -1
  13. package/dist/esm/entry-client.mjs +5 -0
  14. package/dist/esm/federation.mjs +14 -5
  15. package/dist/esm/server/worker.mjs +2 -1
  16. package/dist/esm/worker-federation/contract.mjs +227 -0
  17. package/dist/esm/worker-federation/handler.mjs +159 -0
  18. package/dist/esm/worker-federation/index.mjs +3 -0
  19. package/dist/esm/worker-federation/lease.mjs +107 -0
  20. package/dist/esm/worker-federation/transport.mjs +234 -0
  21. package/dist/esm-node/adapter.mjs +1 -1
  22. package/dist/esm-node/data/codec.mjs +1 -1
  23. package/dist/esm-node/entry-client.mjs +5 -0
  24. package/dist/esm-node/federation.mjs +14 -5
  25. package/dist/esm-node/server/worker.mjs +2 -1
  26. package/dist/esm-node/worker-federation/contract.mjs +228 -0
  27. package/dist/esm-node/worker-federation/handler.mjs +160 -0
  28. package/dist/esm-node/worker-federation/index.mjs +4 -0
  29. package/dist/esm-node/worker-federation/lease.mjs +108 -0
  30. package/dist/esm-node/worker-federation/transport.mjs +235 -0
  31. package/dist/types/adapter.d.ts +1 -1
  32. package/dist/types/data/codec.d.ts +1 -1
  33. package/dist/types/entry-client.d.ts +2 -0
  34. package/dist/types/federation.d.ts +15 -2
  35. package/dist/types/server/types.d.ts +3 -0
  36. package/dist/types/server/worker.d.ts +19 -0
  37. package/dist/types/worker-federation/contract.d.ts +70 -0
  38. package/dist/types/worker-federation/handler.d.ts +21 -0
  39. package/dist/types/worker-federation/index.d.ts +6 -0
  40. package/dist/types/worker-federation/lease.d.ts +11 -0
  41. package/dist/types/worker-federation/transport.d.ts +47 -0
  42. package/package.json +17 -7
  43. package/src/adapter.ts +4 -2
  44. package/src/data/codec.ts +1 -1
  45. package/src/entry-client.ts +5 -0
  46. package/src/federation.ts +36 -8
  47. package/src/server/types.ts +3 -0
  48. package/src/server/worker.ts +23 -0
  49. package/src/worker-federation/contract.ts +449 -0
  50. package/src/worker-federation/handler.ts +274 -0
  51. package/src/worker-federation/index.ts +23 -0
  52. package/src/worker-federation/lease.ts +143 -0
  53. package/src/worker-federation/transport.ts +430 -0
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, getters, values)=>{
5
+ var define = (defs, kind)=>{
6
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
+ enumerable: true,
8
+ [kind]: defs[key]
9
+ });
10
+ };
11
+ define(getters, "get");
12
+ define(values, "value");
13
+ };
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
+ })();
18
+ (()=>{
19
+ __webpack_require__.r = (exports1)=>{
20
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
+ value: 'Module'
22
+ });
23
+ Object.defineProperty(exports1, '__esModule', {
24
+ value: true
25
+ });
26
+ };
27
+ })();
28
+ var __webpack_exports__ = {};
29
+ __webpack_require__.r(__webpack_exports__);
30
+ function checkWorkerFederationDeadline(deadlineAt, signal, controller) {
31
+ if (signal?.aborted) throw workerAbortReason(signal);
32
+ if (performance.now() >= deadlineAt) {
33
+ const error = new Error('Worker federation request deadline exceeded.');
34
+ controller?.abort(error);
35
+ throw error;
36
+ }
37
+ }
38
+ function workerFederationErrorMessage(error, fallback, maxLength = 1024) {
39
+ return error instanceof Error && error.message.length <= maxLength ? error.message : fallback;
40
+ }
41
+ function workerAbortReason(signal) {
42
+ return signal.reason ?? new DOMException('Worker federation request aborted.', 'AbortError');
43
+ }
44
+ function workerAbortable(operation, signal) {
45
+ if (signal.aborted) {
46
+ operation.catch(()=>void 0);
47
+ return Promise.reject(workerAbortReason(signal));
48
+ }
49
+ return new Promise((resolve, reject)=>{
50
+ const onAbort = ()=>reject(workerAbortReason(signal));
51
+ signal.addEventListener('abort', onAbort, {
52
+ once: true
53
+ });
54
+ operation.then(resolve, reject).finally(()=>signal.removeEventListener('abort', onAbort));
55
+ });
56
+ }
57
+ async function readWorkerFederationJsonBody(body, signal, contentLength, checkDeadline) {
58
+ if (signal.aborted) {
59
+ body.cancel().catch(()=>void 0);
60
+ throw workerAbortReason(signal);
61
+ }
62
+ try {
63
+ checkDeadline?.();
64
+ if (null != contentLength) {
65
+ if (!/^\d+$/u.test(contentLength)) throw new Error('Worker federation body has an invalid Content-Length.');
66
+ if (Number(contentLength) > WORKER_FEDERATION_MAX_BODY_BYTES) throw new WorkerFederationBodyTooLargeError();
67
+ }
68
+ } catch (error) {
69
+ body.cancel(error).catch(()=>void 0);
70
+ throw error;
71
+ }
72
+ const reader = body.getReader();
73
+ const onAbort = ()=>{
74
+ reader.cancel(workerAbortReason(signal)).catch(()=>void 0);
75
+ };
76
+ signal.addEventListener('abort', onAbort, {
77
+ once: true
78
+ });
79
+ try {
80
+ const chunks = [];
81
+ let length = 0;
82
+ while(true){
83
+ checkDeadline?.();
84
+ const chunk = await workerAbortable(reader.read(), signal);
85
+ checkDeadline?.();
86
+ if (chunk.done) break;
87
+ if (chunk.value.byteLength > WORKER_FEDERATION_MAX_BODY_BYTES - length) throw new WorkerFederationBodyTooLargeError();
88
+ chunks.push(new Uint8Array(chunk.value));
89
+ length += chunk.value.byteLength;
90
+ }
91
+ checkDeadline?.();
92
+ const bytes = new Uint8Array(length);
93
+ let offset = 0;
94
+ for (const chunk of chunks){
95
+ bytes.set(chunk, offset);
96
+ offset += chunk.byteLength;
97
+ }
98
+ if (signal.aborted) throw workerAbortReason(signal);
99
+ const decoded = new TextDecoder('utf-8', {
100
+ fatal: true
101
+ }).decode(bytes);
102
+ checkDeadline?.();
103
+ const result = JSON.parse(decoded);
104
+ checkDeadline?.();
105
+ return result;
106
+ } catch (error) {
107
+ reader.cancel(error).catch(()=>void 0);
108
+ throw error;
109
+ } finally{
110
+ signal.removeEventListener('abort', onAbort);
111
+ reader.releaseLock();
112
+ }
113
+ }
114
+ const WORKER_FEDERATION_MAX_BODY_BYTES = 8388608;
115
+ class WorkerFederationBodyTooLargeError extends Error {
116
+ constructor(){
117
+ super('Worker federation body exceeds 8 MiB.');
118
+ this.name = 'WorkerFederationBodyTooLargeError';
119
+ }
120
+ }
121
+ function assertWorkerFederationBodySize(value) {
122
+ if (value.length > WORKER_FEDERATION_MAX_BODY_BYTES) throw new WorkerFederationBodyTooLargeError();
123
+ let bytes = 0;
124
+ for(let index = 0; index < value.length; index++){
125
+ const code = value.charCodeAt(index);
126
+ if (code <= 0x7f) bytes++;
127
+ else if (code <= 0x7ff) bytes += 2;
128
+ else if (code >= 0xd800 && code <= 0xdbff && value.charCodeAt(index + 1) >= 0xdc00 && value.charCodeAt(index + 1) <= 0xdfff) {
129
+ bytes += 4;
130
+ index++;
131
+ } else bytes += 3;
132
+ if (bytes > WORKER_FEDERATION_MAX_BODY_BYTES) throw new WorkerFederationBodyTooLargeError();
133
+ }
134
+ return value;
135
+ }
136
+ __webpack_require__.d(__webpack_exports__, {
137
+ WorkerFederationBodyTooLargeError: ()=>WorkerFederationBodyTooLargeError,
138
+ assertWorkerFederationBodySize: ()=>assertWorkerFederationBodySize,
139
+ checkWorkerFederationDeadline: ()=>checkWorkerFederationDeadline,
140
+ readWorkerFederationJsonBody: ()=>readWorkerFederationJsonBody,
141
+ workerAbortReason: ()=>workerAbortReason,
142
+ workerAbortable: ()=>workerAbortable,
143
+ workerFederationErrorMessage: ()=>workerFederationErrorMessage
144
+ }, {
145
+ WORKER_FEDERATION_MAX_BODY_BYTES: WORKER_FEDERATION_MAX_BODY_BYTES
146
+ });
147
+ exports.WORKER_FEDERATION_MAX_BODY_BYTES = __webpack_exports__.WORKER_FEDERATION_MAX_BODY_BYTES;
148
+ exports.WorkerFederationBodyTooLargeError = __webpack_exports__.WorkerFederationBodyTooLargeError;
149
+ exports.assertWorkerFederationBodySize = __webpack_exports__.assertWorkerFederationBodySize;
150
+ exports.checkWorkerFederationDeadline = __webpack_exports__.checkWorkerFederationDeadline;
151
+ exports.readWorkerFederationJsonBody = __webpack_exports__.readWorkerFederationJsonBody;
152
+ exports.workerAbortReason = __webpack_exports__.workerAbortReason;
153
+ exports.workerAbortable = __webpack_exports__.workerAbortable;
154
+ exports.workerFederationErrorMessage = __webpack_exports__.workerFederationErrorMessage;
155
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
156
+ "WORKER_FEDERATION_MAX_BODY_BYTES",
157
+ "WorkerFederationBodyTooLargeError",
158
+ "assertWorkerFederationBodySize",
159
+ "checkWorkerFederationDeadline",
160
+ "readWorkerFederationJsonBody",
161
+ "workerAbortReason",
162
+ "workerAbortable",
163
+ "workerFederationErrorMessage"
164
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
165
+ Object.defineProperty(exports, '__esModule', {
166
+ value: true
167
+ });
@@ -0,0 +1,272 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, getters, values)=>{
5
+ var define = (defs, kind)=>{
6
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
+ enumerable: true,
8
+ [kind]: defs[key]
9
+ });
10
+ };
11
+ define(getters, "get");
12
+ define(values, "value");
13
+ };
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
+ })();
18
+ (()=>{
19
+ __webpack_require__.r = (exports1)=>{
20
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
+ value: 'Module'
22
+ });
23
+ Object.defineProperty(exports1, '__esModule', {
24
+ value: true
25
+ });
26
+ };
27
+ })();
28
+ var __webpack_exports__ = {};
29
+ __webpack_require__.r(__webpack_exports__);
30
+ __webpack_require__.d(__webpack_exports__, {
31
+ createWorkerFederationTransport: ()=>createWorkerFederationTransport
32
+ });
33
+ const external_contract_js_namespaceObject = require("./contract.js");
34
+ const external_lease_js_namespaceObject = require("./lease.js");
35
+ async function readResponseJson(response, expectedUrl, signal, checkDeadline) {
36
+ const cancelBody = ()=>{
37
+ response.body?.cancel().catch(()=>void 0);
38
+ };
39
+ if (signal.aborted) {
40
+ cancelBody();
41
+ throw (0, external_lease_js_namespaceObject.workerAbortReason)(signal);
42
+ }
43
+ try {
44
+ checkDeadline();
45
+ } catch (error) {
46
+ cancelBody();
47
+ throw error;
48
+ }
49
+ if (!response.ok || response.redirected || response.url && response.url !== expectedUrl) {
50
+ cancelBody();
51
+ throw new Error(`Worker federation publication request failed (${response.status}).`);
52
+ }
53
+ if (!response.body) throw new Error('Worker federation response has no body.');
54
+ return (0, external_lease_js_namespaceObject.readWorkerFederationJsonBody)(response.body, signal, response.headers.get('content-length'), checkDeadline);
55
+ }
56
+ async function fetchJson(fetchResponse, request, signal, checkDeadline) {
57
+ checkDeadline();
58
+ if (signal.aborted) throw (0, external_lease_js_namespaceObject.workerAbortReason)(signal);
59
+ const pending = fetchResponse(request);
60
+ pending.then((response)=>{
61
+ if (signal.aborted) response.body?.cancel().catch(()=>void 0);
62
+ }, ()=>void 0);
63
+ return readResponseJson(await (0, external_lease_js_namespaceObject.workerAbortable)(pending, signal), request.url, signal, checkDeadline);
64
+ }
65
+ function createWorkerFederationTransport(options) {
66
+ const timeout = options.requestTimeout ?? 3000;
67
+ const admitRendererContract = options.admitRendererContract;
68
+ if ('function' != typeof admitRendererContract) throw new Error('Worker federation requires canonical renderer admission.');
69
+ if (!Number.isFinite(timeout) || timeout <= 0) throw new Error('Worker federation requires a positive request deadline.');
70
+ const services = new Map();
71
+ for (const service of options.services){
72
+ if (!service.remote || services.has(service.remote)) throw new Error('Worker federation service remotes must be unique.');
73
+ const exposes = new Set();
74
+ for (const fragment of service.fragments){
75
+ Object.values(fragment.paths).forEach(external_contract_js_namespaceObject.readWorkerFederationPath);
76
+ if (!fragment.boundaryId || exposes.has(fragment.expose)) throw new Error('Worker federation service exposes must be explicit and unique.');
77
+ exposes.add(fragment.expose);
78
+ }
79
+ const captured = {
80
+ ...service,
81
+ manifestUrl: (0, external_contract_js_namespaceObject.readWorkerFederationManifestUrl)(service.manifestUrl).href,
82
+ fetch: service.fetch.bind(service),
83
+ fragments: service.fragments.map((fragment)=>Object.freeze({
84
+ ...fragment,
85
+ paths: Object.freeze({
86
+ ...fragment.paths
87
+ })
88
+ }))
89
+ };
90
+ services.set(service.remote, captured);
91
+ if (service.alias && service.alias !== service.remote) {
92
+ if (services.has(service.alias)) throw new Error('Worker federation service aliases must be unique.');
93
+ services.set(service.alias, captured);
94
+ }
95
+ }
96
+ const snapshots = new Map();
97
+ const admissions = new Map();
98
+ const fetchManifest = options.fetchManifest;
99
+ let retired;
100
+ const onOwnerAbort = ()=>dispose((0, external_lease_js_namespaceObject.workerAbortReason)(options.signal));
101
+ function checkDocumentLiveness() {
102
+ if (retired) throw retired.reason;
103
+ }
104
+ function dispose(reason = new DOMException('The Worker federation document was disposed', 'AbortError')) {
105
+ if (retired) return;
106
+ retired = {
107
+ reason
108
+ };
109
+ options.signal?.removeEventListener('abort', onOwnerAbort);
110
+ for (const pending of [
111
+ ...snapshots.values(),
112
+ ...admissions.values()
113
+ ])pending.controller.abort(reason);
114
+ snapshots.clear();
115
+ admissions.clear();
116
+ }
117
+ if (options.signal?.aborted) onOwnerAbort();
118
+ else options.signal?.addEventListener('abort', onOwnerAbort, {
119
+ once: true
120
+ });
121
+ function serviceCoordinate(remote, expose, locale) {
122
+ const service = services.get(remote);
123
+ const fragment = service?.fragments.find((value)=>value.expose === expose);
124
+ if (!service || !fragment || !Object.hasOwn(fragment.paths, locale)) throw new Error('Worker federation remote/expose has no configured service binding.');
125
+ return {
126
+ service,
127
+ fragment
128
+ };
129
+ }
130
+ async function shared(cache, key, operation, signal, deadlineAt = performance.now() + timeout, retainFulfilled = true) {
131
+ checkDocumentLiveness();
132
+ if (signal?.aborted) throw (0, external_lease_js_namespaceObject.workerAbortReason)(signal);
133
+ let pending = cache.get(key);
134
+ if (!pending) {
135
+ const controller = new AbortController();
136
+ const checkDeadline = ()=>(0, external_lease_js_namespaceObject.checkWorkerFederationDeadline)(deadlineAt, controller.signal, controller);
137
+ const deadline = setTimeout(()=>controller.abort(new Error('Worker federation request deadline exceeded.')), Math.max(0, deadlineAt - performance.now()));
138
+ const promise = operation(controller.signal, checkDeadline);
139
+ pending = {
140
+ controller,
141
+ promise,
142
+ waiters: 0,
143
+ settled: false
144
+ };
145
+ const captured = pending;
146
+ cache.set(key, captured);
147
+ promise.then(()=>{
148
+ captured.settled = true;
149
+ clearTimeout(deadline);
150
+ if (!retainFulfilled && cache.get(key) === captured) cache.delete(key);
151
+ }, ()=>{
152
+ captured.settled = true;
153
+ clearTimeout(deadline);
154
+ if (cache.get(key) === captured) cache.delete(key);
155
+ });
156
+ }
157
+ const captured = pending;
158
+ captured.waiters++;
159
+ try {
160
+ const value = await (signal ? (0, external_lease_js_namespaceObject.workerAbortable)(captured.promise, signal) : captured.promise);
161
+ checkDocumentLiveness();
162
+ (0, external_lease_js_namespaceObject.checkWorkerFederationDeadline)(deadlineAt, signal);
163
+ return value;
164
+ } finally{
165
+ captured.waiters--;
166
+ if (!captured.settled && 0 === captured.waiters) {
167
+ captured.controller.abort(new Error('Worker federation request has no active consumers.'));
168
+ if (cache.get(key) === captured) cache.delete(key);
169
+ }
170
+ }
171
+ }
172
+ function admitWithin({ remote, expose, locale, signal }, deadlineAt = performance.now() + timeout) {
173
+ const { service, fragment } = serviceCoordinate(remote, expose, locale);
174
+ const key = (0, external_contract_js_namespaceObject.workerFederationWireJson)([
175
+ service.remote,
176
+ expose,
177
+ locale
178
+ ]);
179
+ const promise = shared(admissions, key, async (signal, checkDeadline)=>{
180
+ checkDeadline();
181
+ const request = new Request(service.manifestUrl, {
182
+ redirect: 'manual',
183
+ signal
184
+ });
185
+ const manifest = await fetchJson(fetchManifest ?? service.fetch, request, signal, checkDeadline);
186
+ const styles = (0, external_contract_js_namespaceObject.readWorkerFederationStyles)({
187
+ manifest,
188
+ manifestUrl: request.url,
189
+ expose
190
+ });
191
+ const admitted = (0, external_contract_js_namespaceObject.admitWorkerFederationExpose)({
192
+ manifest,
193
+ manifestUrl: request.url,
194
+ remote: service.remote,
195
+ expose,
196
+ locale,
197
+ admitRendererContract
198
+ });
199
+ checkDeadline();
200
+ if (admitted.coordinate.boundaryId !== fragment.boundaryId || admitted.path !== fragment.paths[locale]) throw new Error('Worker federation publication conflicts with its service coordinate.');
201
+ return Object.freeze({
202
+ ...admitted,
203
+ styles
204
+ });
205
+ }, signal, deadlineAt);
206
+ return {
207
+ promise,
208
+ key,
209
+ pending: admissions.get(key)
210
+ };
211
+ }
212
+ return {
213
+ dispose,
214
+ admit: (options)=>admitWithin(options).promise,
215
+ async request ({ remote, expose, locale, payload, signal }) {
216
+ const deadlineAt = performance.now() + timeout;
217
+ checkDocumentLiveness();
218
+ if (signal?.aborted) throw (0, external_lease_js_namespaceObject.workerAbortReason)(signal);
219
+ const { service } = serviceCoordinate(remote, expose, locale);
220
+ if ('string' == typeof payload) (0, external_lease_js_namespaceObject.assertWorkerFederationBodySize)(payload);
221
+ const encodedPayload = (0, external_lease_js_namespaceObject.assertWorkerFederationBodySize)((0, external_contract_js_namespaceObject.workerFederationWireJson)(payload));
222
+ const key = (0, external_contract_js_namespaceObject.workerFederationWireJson)([
223
+ service.remote,
224
+ expose,
225
+ locale,
226
+ encodedPayload
227
+ ]);
228
+ (0, external_lease_js_namespaceObject.checkWorkerFederationDeadline)(deadlineAt, signal);
229
+ return shared(snapshots, key, async (signal, checkDeadline)=>{
230
+ checkDeadline();
231
+ const admission = admitWithin({
232
+ remote,
233
+ expose,
234
+ locale,
235
+ signal
236
+ }, deadlineAt);
237
+ const admitted = await admission.promise;
238
+ checkDeadline();
239
+ try {
240
+ const body = (0, external_lease_js_namespaceObject.assertWorkerFederationBodySize)((0, external_contract_js_namespaceObject.workerFederationWireJson)((0, external_contract_js_namespaceObject.workerFederationEnvelope)('request', admitted, JSON.parse(encodedPayload))));
241
+ checkDeadline();
242
+ const response = await fetchJson(service.fetch, new Request(admitted.endpoint, {
243
+ method: 'POST',
244
+ headers: {
245
+ 'content-type': 'application/json'
246
+ },
247
+ body,
248
+ redirect: 'manual',
249
+ signal
250
+ }), signal, checkDeadline);
251
+ checkDeadline();
252
+ const decodedPayload = (0, external_contract_js_namespaceObject.readWorkerFederationEnvelope)(response, 'response', admitted);
253
+ checkDeadline();
254
+ return {
255
+ admitted,
256
+ payload: decodedPayload
257
+ };
258
+ } catch (error) {
259
+ if (!signal.aborted && admissions.get(admission.key) === admission.pending) admissions.delete(admission.key);
260
+ throw error;
261
+ }
262
+ }, signal, deadlineAt, false);
263
+ }
264
+ };
265
+ }
266
+ exports.createWorkerFederationTransport = __webpack_exports__.createWorkerFederationTransport;
267
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
268
+ "createWorkerFederationTransport"
269
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
270
+ Object.defineProperty(exports, '__esModule', {
271
+ value: true
272
+ });
@@ -15,7 +15,7 @@ function defineRendererAdapter(adapter) {
15
15
  function nativeRendererDependencies(profile) {
16
16
  return {
17
17
  ...Object.fromEntries(Object.entries(profile.dependencies).filter(([name])=>!name.startsWith('@modern-js/'))),
18
- [profile.router.coreName]: profile.router.coreVersion
18
+ [profile.router.coreName]: profile.dependencies[profile.router.coreName] ?? profile.router.coreVersion
19
19
  };
20
20
  }
21
21
  export { defineRendererAdapter, nativeRendererDependencies };
@@ -1,6 +1,6 @@
1
1
  import { fromJSON, toJSON } from "seroval";
2
2
  import { validateSerializedData } from "./tree.mjs";
3
- const DATA_CODEC = 'seroval-json@1.6.8';
3
+ const DATA_CODEC = 'seroval-json@1.6.9';
4
4
  const MAX_DATA_BYTES = 1048576;
5
5
  const MAX_DEPTH = 100;
6
6
  const MAX_NODES = 20000;
@@ -69,6 +69,11 @@ function startNativeClientEntry(options, adapter) {
69
69
  rewrite: i18n.rewrite(()=>current.language)
70
70
  } : {}
71
71
  });
72
+ const releaseRouter = ()=>adapter.disposeRouter(router);
73
+ if (signal.aborted) releaseRouter();
74
+ else signal.addEventListener('abort', releaseRouter, {
75
+ once: true
76
+ });
72
77
  const stopSync = i18n && current ? i18n.syncWithRouter(router, current) : void 0;
73
78
  if (stopSync) signal.addEventListener('abort', stopSync, {
74
79
  once: true
@@ -1,3 +1,4 @@
1
+ const LOAD_WITH_CAPTURE = Symbol.for('ultramodern.federation.load-with-capture');
1
2
  function getFederationHost(binding) {
2
3
  if (void 0 === binding) return;
3
4
  if ('function' != typeof binding?.instance) throw new TypeError('The native federation host binding is invalid.');
@@ -7,16 +8,24 @@ function getFederationHost(binding) {
7
8
  }
8
9
  async function loadFederatedModule(instance, id) {
9
10
  if (!instance) throw new Error(`Cannot load ${id}: this application has no Module Federation runtime. Add module-federation.config.ts with its remotes.`);
10
- const module = await instance.loadRemote(id);
11
+ const coupledLoad = instance[LOAD_WITH_CAPTURE];
12
+ const result = coupledLoad ? await coupledLoad(id, (_module, resolution)=>remoteBrowserAssets(instance, id, resolution)) : {
13
+ module: await instance.loadRemote(id),
14
+ captured: remoteBrowserAssets(instance, id)
15
+ };
16
+ const module = result.module;
11
17
  if (!module) throw new Error(`Remote module ${id} is unavailable`);
12
- return module;
18
+ return {
19
+ module,
20
+ assets: result.captured
21
+ };
13
22
  }
14
- function remoteBrowserAssets(instance, id) {
23
+ function remoteBrowserAssets(instance, id, resolution) {
15
24
  const target = instance.remoteHandler?.idToRemoteMap?.[id];
16
25
  const loaded = target && instance.moduleCache?.get(target.name);
17
- const snapshot = loaded && instance.snapshotHandler?.getGlobalRemoteInfo(loaded.remoteInfo).remoteSnapshot;
26
+ const snapshot = resolution ? resolution.remoteSnapshot : loaded && instance.snapshotHandler?.getGlobalRemoteInfo(loaded.remoteInfo).remoteSnapshot;
18
27
  if (!snapshot || 'string' != typeof snapshot.publicPath || !snapshot.publicPath || 'string' != typeof snapshot.remoteEntry || !snapshot.remoteEntry) return;
19
- const expose = snapshot.modules?.find((module)=>module.modulePath === target.expose);
28
+ const expose = snapshot.modules?.find((module)=>module.modulePath === (resolution?.expose ?? target?.expose));
20
29
  if (!expose?.assets) return;
21
30
  const publicPath = snapshot.publicPath;
22
31
  const url = (file)=>/^(?:https?:)?\/\//iu.test(file) ? file : `${publicPath.replace(/\/$/u, '')}/${file.replace(/^\//u, '')}`;
@@ -28,7 +28,8 @@ function dispatchNativeWorkerRequest(request, options) {
28
28
  ...resources.serverConfig,
29
29
  forceCSR
30
30
  },
31
- nonce: resources.nonce
31
+ nonce: resources.nonce,
32
+ workerFederation: options.workerFederation
32
33
  }
33
34
  });
34
35
  }