@modern-js/runtime 3.9.2 → 3.9.3

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.
@@ -143,12 +143,14 @@ const createRequestHandler = async (handleRequest, createRequestOptions)=>{
143
143
  status: -1
144
144
  };
145
145
  const activeDeferreds = new Map();
146
+ const deferredScriptKeys = new Map();
146
147
  return node_namespaceObject.storage.run({
147
148
  headers: headersData,
148
149
  request,
149
150
  monitors: options.monitors,
150
151
  responseProxy,
151
152
  activeDeferreds,
153
+ deferredScriptKeys,
152
154
  serverPayload: void 0
153
155
  }, async ()=>{
154
156
  const Root = (0, external_react_index_js_namespaceObject.createRoot)();
@@ -31,6 +31,7 @@ __webpack_require__.d(__webpack_exports__, {
31
31
  createReadableStreamFromElement: ()=>createReadableStreamFromElement
32
32
  });
33
33
  const external_stream_namespaceObject = require("stream");
34
+ const external_string_decoder_namespaceObject = require("string_decoder");
34
35
  const node_namespaceObject = require("@modern-js/runtime-utils/node");
35
36
  const constants_namespaceObject = require("@modern-js/utils/universal/constants");
36
37
  const external_common_js_namespaceObject = require("../../../common.js");
@@ -38,6 +39,7 @@ const external_constants_js_namespaceObject = require("../../constants.js");
38
39
  const index_js_namespaceObject = require("../../context/index.js");
39
40
  const monitors_index_js_namespaceObject = require("../../context/monitors/index.js");
40
41
  const external_deferredScript_js_namespaceObject = require("./deferredScript.js");
42
+ const external_deferredScriptOutputCoordinator_js_namespaceObject = require("./deferredScriptOutputCoordinator.js");
41
43
  const external_shared_js_namespaceObject = require("./shared.js");
42
44
  const external_template_js_namespaceObject = require("./template.js");
43
45
  const defaultExtender = {
@@ -86,7 +88,14 @@ const createReadableStreamFromElement = async (request, rootElement, options)=>{
86
88
  entryName,
87
89
  styledComponentsStyleTags
88
90
  }).then(({ shellAfter, shellBefore })=>{
91
+ const decoder = new external_string_decoder_namespaceObject.StringDecoder('utf8');
89
92
  const pendingScripts = [];
93
+ const outputState = {};
94
+ let deferredResolversComplete = Promise.resolve();
95
+ const writeReact = (content)=>{
96
+ if (!outputState.coordinator) throw new Error("Deferred script coordinator is not ready");
97
+ outputState.coordinator.writeReact(content);
98
+ };
90
99
  const body = new external_stream_namespaceObject.Transform({
91
100
  transform (chunk, _encoding, callback) {
92
101
  try {
@@ -98,17 +107,49 @@ const createReadableStreamFromElement = async (request, rootElement, options)=>{
98
107
  const beforeMark = concatedChunk.slice(0, markerIndex);
99
108
  const afterMark = concatedChunk.slice(markerIndex + external_common_js_namespaceObject.ESCAPED_SHELL_STREAM_END_MARK.length);
100
109
  shellChunkStatus = external_shared_js_namespaceObject.ShellChunkStatus.FINISH;
101
- this.push(`${shellBefore}${beforeMark}${shellAfter}`);
102
- if (afterMark) this.push(afterMark);
103
- if (pendingScripts.length > 0) for (const s of pendingScripts)this.push(s);
110
+ writeReact(`${shellBefore}${beforeMark}${shellAfter}`);
111
+ if (afterMark) writeReact(afterMark);
112
+ if (outputState.coordinator) {
113
+ outputState.coordinator.markShellFinished();
114
+ for (const script of pendingScripts)outputState.coordinator.enqueueResolver(script);
115
+ pendingScripts.length = 0;
116
+ }
104
117
  }
105
- } else this.push(chunk);
118
+ } else {
119
+ const decodedChunk = decoder.write(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
120
+ writeReact(decodedChunk);
121
+ }
106
122
  callback();
107
123
  } catch (e) {
108
124
  e instanceof Error ? callback(e) : callback(new Error('Received unknown error when streaming'));
109
125
  }
126
+ },
127
+ flush (callback) {
128
+ try {
129
+ writeReact(decoder.end());
130
+ } catch (error) {
131
+ callback(error instanceof Error ? error : new Error('Received unknown error when streaming'));
132
+ return;
133
+ }
134
+ deferredResolversComplete.then(()=>{
135
+ try {
136
+ outputState.coordinator?.finish();
137
+ callback();
138
+ } catch (error) {
139
+ callback(error instanceof Error ? error : new Error('Received unknown error when streaming'));
140
+ }
141
+ }, (error)=>{
142
+ callback(error instanceof Error ? error : new Error('Received unknown error when streaming'));
143
+ });
110
144
  }
111
145
  });
146
+ const coordinator = new external_deferredScriptOutputCoordinator_js_namespaceObject.DeferredScriptOutputCoordinator((content)=>{
147
+ body.push(content);
148
+ });
149
+ outputState.coordinator = coordinator;
150
+ body.once('close', ()=>{
151
+ coordinator.abort();
152
+ });
112
153
  const passThrough = new external_stream_namespaceObject.PassThrough();
113
154
  const stream = external_stream_namespaceObject.Readable.toWeb(body);
114
155
  resolve(stream);
@@ -116,23 +157,25 @@ const createReadableStreamFromElement = async (request, rootElement, options)=>{
116
157
  extenders.forEach((extender)=>{
117
158
  if (extender.processStream) processedStream = extender.processStream(processedStream);
118
159
  });
119
- reactStreamingPipe(passThrough);
120
- processedStream.pipe(body);
121
160
  try {
122
161
  const storageContext = node_namespaceObject.storage.useContext?.();
123
162
  const activeDeferreds = storageContext?.activeDeferreds;
163
+ const deferredScriptKeys = storageContext?.deferredScriptKeys;
124
164
  const entries = activeDeferreds instanceof Map ? Array.from(activeDeferreds.entries()) : [];
125
165
  if (entries.length > 0) {
126
166
  const enqueueScript = (s)=>{
127
- if (shellChunkStatus === external_shared_js_namespaceObject.ShellChunkStatus.FINISH) body.write(s);
167
+ if (!outputState.coordinator) throw new Error("Deferred script coordinator is not ready");
168
+ if (shellChunkStatus === external_shared_js_namespaceObject.ShellChunkStatus.FINISH) outputState.coordinator.enqueueResolver(s);
128
169
  else pendingScripts.push(s);
129
170
  };
130
- (0, external_deferredScript_js_namespaceObject.enqueueFromEntries)(entries, config.nonce, (s)=>enqueueScript(s));
171
+ deferredResolversComplete = (0, external_deferredScript_js_namespaceObject.enqueueFromEntries)(entries, deferredScriptKeys, config.nonce, enqueueScript);
131
172
  }
132
173
  } catch (err) {
133
174
  const monitors = (0, monitors_index_js_namespaceObject.getMonitors)();
134
175
  monitors.error("cannot inject router data script", err);
135
176
  }
177
+ reactStreamingPipe(passThrough);
178
+ processedStream.pipe(body);
136
179
  });
137
180
  },
138
181
  onShellError (error) {
@@ -35,6 +35,7 @@ const node_namespaceObject = require("@modern-js/runtime-utils/node");
35
35
  const external_common_js_namespaceObject = require("../../../common.js");
36
36
  const external_constants_js_namespaceObject = require("../../constants.js");
37
37
  const external_deferredScript_js_namespaceObject = require("./deferredScript.js");
38
+ const external_deferredScriptOutputCoordinator_js_namespaceObject = require("./deferredScriptOutputCoordinator.js");
38
39
  const external_shared_js_namespaceObject = require("./shared.js");
39
40
  const external_template_js_namespaceObject = require("./template.js");
40
41
  const createReadableStreamFromElement = async (request, rootElement, options)=>{
@@ -67,10 +68,13 @@ const createReadableStreamFromElement = async (request, rootElement, options)=>{
67
68
  const { waitForAllReady } = (0, external_shared_js_namespaceObject.resolveStreamingMode)(request, forceStreamToString);
68
69
  if (waitForAllReady) await readableOriginal.allReady;
69
70
  const reader = readableOriginal.getReader();
71
+ let coordinator;
70
72
  const stream = new ReadableStream({
71
73
  start (controller) {
74
+ const decoder = new TextDecoder();
72
75
  const pendingScripts = [];
73
76
  let isClosed = false;
77
+ let deferredResolversComplete = Promise.resolve();
74
78
  const safeEnqueue = (chunk)=>{
75
79
  if (isClosed) return;
76
80
  try {
@@ -87,38 +91,55 @@ const createReadableStreamFromElement = async (request, rootElement, options)=>{
87
91
  } catch {}
88
92
  }
89
93
  };
90
- const flushPendingScripts = ()=>{
91
- for (const s of pendingScripts)safeEnqueue((0, external_shared_js_namespaceObject.encodeForWebStream)(s));
92
- pendingScripts.length = 0;
93
- };
94
- const enqueueScript = (script)=>{
95
- if (shellChunkStatus === external_shared_js_namespaceObject.ShellChunkStatus.FINISH) safeEnqueue((0, external_shared_js_namespaceObject.encodeForWebStream)(script));
96
- else pendingScripts.push(script);
97
- };
94
+ coordinator = new external_deferredScriptOutputCoordinator_js_namespaceObject.DeferredScriptOutputCoordinator((content)=>{
95
+ safeEnqueue((0, external_shared_js_namespaceObject.encodeForWebStream)(content));
96
+ });
98
97
  const storageContext = node_namespaceObject.storage.useContext?.();
99
98
  const activeDeferreds = storageContext?.activeDeferreds;
99
+ const deferredScriptKeys = storageContext?.deferredScriptKeys;
100
100
  const entries = activeDeferreds instanceof Map ? Array.from(activeDeferreds.entries()) : [];
101
- if (entries.length > 0) (0, external_deferredScript_js_namespaceObject.enqueueFromEntries)(entries, config.nonce, enqueueScript);
101
+ if (entries.length > 0) deferredResolversComplete = (0, external_deferredScript_js_namespaceObject.enqueueFromEntries)(entries, deferredScriptKeys, config.nonce, (script)=>{
102
+ if (!coordinator) throw new Error("Deferred script coordinator is not ready");
103
+ if (shellChunkStatus === external_shared_js_namespaceObject.ShellChunkStatus.FINISH) coordinator.enqueueResolver(script);
104
+ else pendingScripts.push(script);
105
+ });
102
106
  async function push() {
103
107
  try {
104
108
  const { done, value } = await reader.read();
105
- if (done) return void closeController();
109
+ if (done) {
110
+ const trailingText = decoder.decode();
111
+ if (trailingText) coordinator?.writeReact(trailingText);
112
+ await deferredResolversComplete;
113
+ coordinator?.finish();
114
+ closeController();
115
+ return;
116
+ }
106
117
  if (isClosed) return;
107
118
  if (shellChunkStatus !== external_shared_js_namespaceObject.ShellChunkStatus.FINISH) {
108
- chunkVec.push(new TextDecoder().decode(value));
119
+ chunkVec.push(decoder.decode(value, {
120
+ stream: true
121
+ }));
109
122
  const concatedChunk = chunkVec.join('');
110
123
  const markerIndex = concatedChunk.indexOf(external_common_js_namespaceObject.ESCAPED_SHELL_STREAM_END_MARK);
111
124
  if (-1 !== markerIndex) {
112
125
  const beforeMark = concatedChunk.slice(0, markerIndex);
113
126
  const afterMark = concatedChunk.slice(markerIndex + external_common_js_namespaceObject.ESCAPED_SHELL_STREAM_END_MARK.length);
114
127
  shellChunkStatus = external_shared_js_namespaceObject.ShellChunkStatus.FINISH;
115
- safeEnqueue((0, external_shared_js_namespaceObject.encodeForWebStream)(`${shellBefore}${beforeMark}${shellAfter}`));
116
- if (afterMark) safeEnqueue((0, external_shared_js_namespaceObject.encodeForWebStream)(afterMark));
117
- flushPendingScripts();
128
+ coordinator?.writeReact(`${shellBefore}${beforeMark}${shellAfter}`);
129
+ if (afterMark) coordinator?.writeReact(afterMark);
130
+ coordinator?.markShellFinished();
131
+ for (const script of pendingScripts)coordinator?.enqueueResolver(script);
132
+ pendingScripts.length = 0;
118
133
  }
119
- } else safeEnqueue(value);
134
+ } else {
135
+ const decodedChunk = decoder.decode(value, {
136
+ stream: true
137
+ });
138
+ if (decodedChunk) coordinator?.writeReact(decodedChunk);
139
+ }
120
140
  if (!isClosed) push();
121
141
  } catch (error) {
142
+ coordinator?.abort();
122
143
  if (!isClosed) {
123
144
  isClosed = true;
124
145
  try {
@@ -130,6 +151,7 @@ const createReadableStreamFromElement = async (request, rootElement, options)=>{
130
151
  push();
131
152
  },
132
153
  cancel (reason) {
154
+ coordinator?.abort();
133
155
  reader.cancel(reason).catch(()=>{});
134
156
  }
135
157
  });
@@ -78,24 +78,30 @@ function buildDeferredDataScript(nonce, args) {
78
78
  const nonceAttr = nonce ? ` nonce="${nonce}"` : '';
79
79
  return `<script async${nonceAttr} data-fn-name="r" data-script-src="modern-run-router-data-fn" data-fn-args='${escaped}' suppressHydrationWarning>${constants_js_namespaceObject.runRouterDataFnStr}</script>`;
80
80
  }
81
- function enqueueFromEntries(entries, nonce, emit) {
81
+ function enqueueFromEntries(entries, deferredScriptKeys, nonce, emit) {
82
+ const pendingResolvers = [];
82
83
  entries.forEach(([routeId, value])=>{
83
84
  if (!isDeferredDataLike(value)) return;
84
- const pendingKeys = new Set(value.pendingKeys ?? []);
85
- pendingKeys.forEach((key)=>{
85
+ const serializedKeys = deferredScriptKeys ? deferredScriptKeys.get(routeId) ?? [] : value.pendingKeys ?? [];
86
+ serializedKeys.forEach((key)=>{
86
87
  const tracked = value.data?.[key];
87
- if (isPromiseLike(tracked)) tracked.then((val)=>emit(buildDeferredDataScript(nonce, [
88
+ if (isPromiseLike(tracked)) pendingResolvers.push(Promise.resolve(tracked).then((val)=>{
89
+ emit(buildDeferredDataScript(nonce, [
88
90
  routeId,
89
91
  key,
90
92
  val
91
- ])), (err)=>emit(buildDeferredDataScript(nonce, [
93
+ ]));
94
+ }, (err)=>{
95
+ emit(buildDeferredDataScript(nonce, [
92
96
  routeId,
93
97
  key,
94
98
  void 0,
95
99
  toErrorInfo(err)
96
- ])));
100
+ ]));
101
+ }));
97
102
  });
98
103
  });
104
+ return Promise.all(pendingResolvers).then(()=>void 0);
99
105
  }
100
106
  exports.buildDeferredDataScript = __webpack_exports__.buildDeferredDataScript;
101
107
  exports.enqueueFromEntries = __webpack_exports__.enqueueFromEntries;
@@ -0,0 +1,370 @@
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
+ DeferredScriptOutputCoordinator: ()=>DeferredScriptOutputCoordinator
32
+ });
33
+ const constants_namespaceObject = require("@modern-js/utils/universal/constants");
34
+ const VOID_ELEMENTS = new Set([
35
+ 'area',
36
+ 'base',
37
+ 'br',
38
+ 'col',
39
+ 'embed',
40
+ 'hr',
41
+ 'img',
42
+ 'input',
43
+ 'link',
44
+ 'meta',
45
+ 'param',
46
+ 'source',
47
+ 'track',
48
+ 'wbr'
49
+ ]);
50
+ const RAW_TEXT_ELEMENTS = new Set([
51
+ 'iframe',
52
+ 'noembed',
53
+ 'noframes',
54
+ "script",
55
+ 'style',
56
+ 'textarea',
57
+ 'title',
58
+ 'xmp'
59
+ ]);
60
+ const REACT_SEGMENT_ID_PATTERN = new RegExp(`^${constants_namespaceObject.SSR_HYDRATION_ID_PREFIX}S:[0-9a-f]+$`);
61
+ const TABLE_SEGMENT_CHILDREN = new Set([
62
+ 'tbody',
63
+ 'tr',
64
+ 'colgroup'
65
+ ]);
66
+ function isAsciiAlpha(char) {
67
+ return /[A-Za-z]/.test(char);
68
+ }
69
+ function isWhitespace(char) {
70
+ return /[\t\n\f\r ]/.test(char);
71
+ }
72
+ function getSuffix(value, pattern) {
73
+ const start = Math.max(0, value.length - pattern.length);
74
+ for(let index = start; index < value.length; index++){
75
+ const suffix = value.slice(index);
76
+ if (pattern.startsWith(suffix)) return suffix;
77
+ }
78
+ return '';
79
+ }
80
+ class DeferredScriptOutputCoordinator {
81
+ enqueueResolver(script) {
82
+ if (this.closed) return;
83
+ this.pendingResolvers.push(script);
84
+ this.flushResolvers();
85
+ }
86
+ markShellFinished() {
87
+ if (this.closed) return;
88
+ this.shellFinished = true;
89
+ this.flushResolvers();
90
+ }
91
+ writeReact(chunk) {
92
+ if (this.closed || !chunk) return;
93
+ this.flushResolvers();
94
+ let emittedUntil = 0;
95
+ for(let index = 0; index < chunk.length; index++){
96
+ const wasSafe = this.isSafeBoundary();
97
+ this.consume(chunk[index]);
98
+ if (!wasSafe && this.isSafeBoundary() && this.pendingResolvers.length) {
99
+ this.emit(chunk.slice(emittedUntil, index + 1));
100
+ emittedUntil = index + 1;
101
+ this.flushResolvers();
102
+ }
103
+ }
104
+ if (emittedUntil < chunk.length) this.emit(chunk.slice(emittedUntil));
105
+ }
106
+ finish() {
107
+ if (this.closed) return;
108
+ this.flushResolvers();
109
+ this.closed = true;
110
+ if (this.pendingResolvers.length > 0) throw new Error("Cannot emit deferred resolver scripts because the React stream ended outside a safe HTML boundary.");
111
+ }
112
+ abort() {
113
+ this.closed = true;
114
+ this.pendingResolvers.length = 0;
115
+ }
116
+ isSafeBoundary() {
117
+ return this.shellFinished && 'data' === this.state && 0 === this.openElements.length && !this.awaitingContinuationProtocol;
118
+ }
119
+ flushResolvers() {
120
+ if (!this.isSafeBoundary() || 0 === this.pendingResolvers.length) return;
121
+ while(this.pendingResolvers.length > 0){
122
+ const resolver = this.pendingResolvers.shift();
123
+ if (resolver) this.emit(resolver);
124
+ }
125
+ }
126
+ consume(char) {
127
+ switch(this.state){
128
+ case 'data':
129
+ if ('<' === char) this.state = 'tag-open';
130
+ return;
131
+ case 'tag-open':
132
+ if ('/' === char) {
133
+ this.currentTagName = '';
134
+ this.state = 'end-tag-name';
135
+ } else if ('!' === char) {
136
+ this.declarationPrefix = '';
137
+ this.state = 'markup-declaration';
138
+ } else if ('?' === char) this.state = 'bogus-comment';
139
+ else if (isAsciiAlpha(char)) {
140
+ this.startTag(char);
141
+ this.state = 'start-tag-name';
142
+ } else this.state = 'data';
143
+ return;
144
+ case 'start-tag-name':
145
+ if (isWhitespace(char)) this.state = 'before-attribute-name';
146
+ else if ('/' === char) this.state = 'self-closing-start-tag';
147
+ else if ('>' === char) this.completeStartTag(false);
148
+ else this.currentTagName += char.toLowerCase();
149
+ return;
150
+ case 'before-attribute-name':
151
+ if (isWhitespace(char)) return;
152
+ if ('/' === char) this.state = 'self-closing-start-tag';
153
+ else if ('>' === char) this.completeStartTag(false);
154
+ else {
155
+ this.startAttribute(char);
156
+ this.state = 'attribute-name';
157
+ }
158
+ return;
159
+ case 'attribute-name':
160
+ if (isWhitespace(char)) this.state = 'after-attribute-name';
161
+ else if ('=' === char) {
162
+ this.currentAttributeHasValue = true;
163
+ this.state = 'before-attribute-value';
164
+ } else if ('/' === char) {
165
+ this.completeAttribute();
166
+ this.state = 'self-closing-start-tag';
167
+ } else if ('>' === char) this.completeStartTag(false);
168
+ else this.currentAttributeName += char.toLowerCase();
169
+ return;
170
+ case 'after-attribute-name':
171
+ if (isWhitespace(char)) return;
172
+ if ('=' === char) {
173
+ this.currentAttributeHasValue = true;
174
+ this.state = 'before-attribute-value';
175
+ } else if ('/' === char) {
176
+ this.completeAttribute();
177
+ this.state = 'self-closing-start-tag';
178
+ } else if ('>' === char) this.completeStartTag(false);
179
+ else {
180
+ this.completeAttribute();
181
+ this.startAttribute(char);
182
+ this.state = 'attribute-name';
183
+ }
184
+ return;
185
+ case 'before-attribute-value':
186
+ if (isWhitespace(char)) return;
187
+ if ('"' === char) this.state = 'attribute-value-double-quoted';
188
+ else if ("'" === char) this.state = 'attribute-value-single-quoted';
189
+ else if ('>' === char) this.completeStartTag(false);
190
+ else {
191
+ this.currentAttributeValue += char;
192
+ this.state = 'attribute-value-unquoted';
193
+ }
194
+ return;
195
+ case 'attribute-value-double-quoted':
196
+ if ('"' === char) {
197
+ this.completeAttribute();
198
+ this.state = 'before-attribute-name';
199
+ } else this.currentAttributeValue += char;
200
+ return;
201
+ case 'attribute-value-single-quoted':
202
+ if ("'" === char) {
203
+ this.completeAttribute();
204
+ this.state = 'before-attribute-name';
205
+ } else this.currentAttributeValue += char;
206
+ return;
207
+ case 'attribute-value-unquoted':
208
+ if (isWhitespace(char)) {
209
+ this.completeAttribute();
210
+ this.state = 'before-attribute-name';
211
+ } else if ('>' === char) this.completeStartTag(false);
212
+ else this.currentAttributeValue += char;
213
+ return;
214
+ case 'self-closing-start-tag':
215
+ if ('>' === char) this.completeStartTag(true);
216
+ else if (!isWhitespace(char)) {
217
+ this.startAttribute(char);
218
+ this.state = 'attribute-name';
219
+ }
220
+ return;
221
+ case 'end-tag-name':
222
+ if (isWhitespace(char)) this.state = 'after-end-tag-name';
223
+ else if ('>' === char) this.completeEndTag();
224
+ else this.currentTagName += char.toLowerCase();
225
+ return;
226
+ case 'after-end-tag-name':
227
+ if ('>' === char) this.completeEndTag();
228
+ return;
229
+ case 'markup-declaration':
230
+ if (this.declarationPrefix.length < 2 && '-' === char) {
231
+ this.declarationPrefix += char;
232
+ if ('--' === this.declarationPrefix) {
233
+ this.commentTail = '';
234
+ this.state = 'comment';
235
+ }
236
+ } else this.state = '>' === char ? 'data' : 'declaration';
237
+ return;
238
+ case 'declaration':
239
+ if ('>' === char) this.state = 'data';
240
+ return;
241
+ case 'comment':
242
+ this.commentTail = `${this.commentTail}${char}`.slice(-3);
243
+ if ('-->' === this.commentTail) this.state = 'data';
244
+ return;
245
+ case 'bogus-comment':
246
+ if ('>' === char) this.state = 'data';
247
+ return;
248
+ case 'raw-text':
249
+ this.consumeRawText(char);
250
+ return;
251
+ case 'raw-end-tag':
252
+ if ('>' === char) this.completeRawTextEndTag();
253
+ else if (!isWhitespace(char)) {
254
+ this.state = 'raw-text';
255
+ this.rawTextSearch = getSuffix(`${this.rawTextSearch}${char.toLowerCase()}`, `</${this.rawTextElement}`);
256
+ }
257
+ }
258
+ }
259
+ startTag(char) {
260
+ this.currentTagName = char.toLowerCase();
261
+ this.currentAttributes = new Map();
262
+ this.currentAttributeName = '';
263
+ this.currentAttributeValue = '';
264
+ this.currentAttributeHasValue = false;
265
+ }
266
+ startAttribute(char) {
267
+ this.currentAttributeName = char.toLowerCase();
268
+ this.currentAttributeValue = '';
269
+ this.currentAttributeHasValue = false;
270
+ }
271
+ completeAttribute() {
272
+ if (!this.currentAttributeName) return;
273
+ this.currentAttributes.set(this.currentAttributeName, this.currentAttributeHasValue ? this.currentAttributeValue : true);
274
+ this.currentAttributeName = '';
275
+ this.currentAttributeValue = '';
276
+ this.currentAttributeHasValue = false;
277
+ }
278
+ completeStartTag(selfClosing) {
279
+ this.completeAttribute();
280
+ const tagName = this.currentTagName;
281
+ const id = this.currentAttributes.get('id');
282
+ const hasReactSegmentId = 'string' == typeof id && REACT_SEGMENT_ID_PATTERN.test(id);
283
+ const hasHiddenAttribute = this.currentAttributes.has('hidden');
284
+ const isHiddenSegmentTable = 'table' === tagName && hasHiddenAttribute && !hasReactSegmentId;
285
+ const isTableSegmentChild = hasReactSegmentId && TABLE_SEGMENT_CHILDREN.has(tagName) && this.openElements[this.openElements.length - 1]?.isSegmentTableWrapper === true;
286
+ const isContinuationContainer = hasReactSegmentId && ('div' === tagName && hasHiddenAttribute || ('svg' === tagName || 'math' === tagName) && void 0 !== id && 'true' === this.currentAttributes.get('aria-hidden') && 'display:none' === this.currentAttributes.get('style') || 'table' === tagName && hasHiddenAttribute || isTableSegmentChild);
287
+ this.continuationProtocolScript = "script" === tagName && this.awaitingContinuationProtocol;
288
+ this.continuationProtocolTail = '';
289
+ this.hasContinuationProtocolCall = false;
290
+ if (!selfClosing && !VOID_ELEMENTS.has(tagName)) this.openElements.push({
291
+ tagName,
292
+ isContinuationContainer,
293
+ isSegmentTableWrapper: isHiddenSegmentTable
294
+ });
295
+ this.currentTagName = '';
296
+ this.currentAttributes = new Map();
297
+ this.currentAttributeName = '';
298
+ this.currentAttributeValue = '';
299
+ this.currentAttributeHasValue = false;
300
+ if (!selfClosing && RAW_TEXT_ELEMENTS.has(tagName)) {
301
+ this.rawTextElement = tagName;
302
+ this.rawTextSearch = '';
303
+ this.state = 'raw-text';
304
+ } else this.state = 'data';
305
+ }
306
+ completeEndTag() {
307
+ this.closeOpenElement(this.currentTagName);
308
+ this.currentTagName = '';
309
+ this.state = 'data';
310
+ }
311
+ consumeRawText(char) {
312
+ const rawTextElement = this.rawTextElement;
313
+ if (!rawTextElement) {
314
+ this.state = 'data';
315
+ return;
316
+ }
317
+ const endTagPrefix = `</${rawTextElement}`;
318
+ if (this.continuationProtocolScript) {
319
+ this.continuationProtocolTail = `${this.continuationProtocolTail}${char}`.slice(-4);
320
+ if (/\$(?:RC|RS|RX|RB|RR)\b/.test(this.continuationProtocolTail)) this.hasContinuationProtocolCall = true;
321
+ }
322
+ this.rawTextSearch = getSuffix(`${this.rawTextSearch}${char.toLowerCase()}`, endTagPrefix);
323
+ if (this.rawTextSearch === endTagPrefix) this.state = 'raw-end-tag';
324
+ }
325
+ completeRawTextEndTag() {
326
+ const rawTextElement = this.rawTextElement;
327
+ if (rawTextElement) this.closeOpenElement(rawTextElement);
328
+ if ("script" === rawTextElement && this.continuationProtocolScript && this.hasContinuationProtocolCall) this.awaitingContinuationProtocol = false;
329
+ this.rawTextElement = void 0;
330
+ this.rawTextSearch = '';
331
+ this.continuationProtocolScript = false;
332
+ this.continuationProtocolTail = '';
333
+ this.hasContinuationProtocolCall = false;
334
+ this.state = 'data';
335
+ }
336
+ closeOpenElement(tagName) {
337
+ const matchingIndex = this.openElements.map((element)=>element.tagName).lastIndexOf(tagName);
338
+ if (-1 === matchingIndex) return;
339
+ const closedElements = this.openElements.splice(matchingIndex);
340
+ const closedContinuation = closedElements.some((element)=>element.isContinuationContainer);
341
+ if (closedContinuation) this.awaitingContinuationProtocol = true;
342
+ }
343
+ constructor(emit){
344
+ this.emit = emit;
345
+ this.pendingResolvers = [];
346
+ this.openElements = [];
347
+ this.shellFinished = false;
348
+ this.closed = false;
349
+ this.state = 'data';
350
+ this.currentTagName = '';
351
+ this.currentAttributes = new Map();
352
+ this.currentAttributeName = '';
353
+ this.currentAttributeValue = '';
354
+ this.currentAttributeHasValue = false;
355
+ this.declarationPrefix = '';
356
+ this.commentTail = '';
357
+ this.rawTextSearch = '';
358
+ this.continuationProtocolScript = false;
359
+ this.continuationProtocolTail = '';
360
+ this.hasContinuationProtocolCall = false;
361
+ this.awaitingContinuationProtocol = false;
362
+ }
363
+ }
364
+ exports.DeferredScriptOutputCoordinator = __webpack_exports__.DeferredScriptOutputCoordinator;
365
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
366
+ "DeferredScriptOutputCoordinator"
367
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
368
+ Object.defineProperty(exports, '__esModule', {
369
+ value: true
370
+ });
@@ -45,7 +45,8 @@ const DeferredDataScripts = (props)=>{
45
45
  }, []);
46
46
  const deferredScripts = (0, external_react_namespaceObject.useMemo)(()=>{
47
47
  if (!staticContext) return null;
48
- const activeDeferreds = node_namespaceObject.storage.useContext().activeDeferreds;
48
+ const requestStorage = node_namespaceObject.storage.useContext();
49
+ const activeDeferreds = requestStorage.activeDeferreds;
49
50
  const _ROUTER_DATA = {
50
51
  loaderData: staticContext.loaderData,
51
52
  errors: (0, external_utils_js_namespaceObject.serializeErrors)(staticContext.errors)
@@ -58,6 +59,7 @@ const DeferredDataScripts = (props)=>{
58
59
  const deferredDataScripts = [];
59
60
  const initialScripts = Array.from(activeDeferreds.entries()).map(([routeId, deferredData])=>{
60
61
  const pendingKeys = new Set(deferredData.pendingKeys);
62
+ requestStorage.deferredScriptKeys?.set(routeId, Array.from(pendingKeys));
61
63
  const { deferredKeys } = deferredData;
62
64
  const deferredKeyPromiseManifests = deferredKeys.map((key)=>{
63
65
  if (pendingKeys.has(key)) return {