@bleedingdev/modern-js-app-tools-extensions 3.9.0-ultramodern.9 → 3.9.3-ultramodern.1
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/README.md +23 -0
- package/dist/cjs/backend-federation-build/codegen.js +29 -18
- package/dist/cjs/backend-federation-build/config.js +84 -45
- package/dist/cjs/backend-federation-build/emit.js +63 -22
- package/dist/cjs/build-config/build-environment.js +25 -162
- package/dist/cjs/build-config/internal-effect-discovery.js +143 -0
- package/dist/cjs/build-config/public.js +2 -5
- package/dist/cjs/build-config/remote-address.js +58 -0
- package/dist/cjs/cloudflare/artifacts.js +8 -19
- package/dist/cjs/cloudflare/delivery-unit.js +125 -43
- package/dist/cjs/cloudflare/index.js +14 -4
- package/dist/cjs/cloudflare/native-renderer.js +100 -0
- package/dist/cjs/cloudflare/renderer-identity.js +106 -0
- package/dist/cjs/cloudflare/worker-manifest.js +54 -13
- package/dist/cjs/cloudflare/worker-options.js +48 -0
- package/dist/cjs/cloudflare/wrangler-config.js +210 -13
- package/dist/cjs/cloudflare-builder.js +307 -89
- package/dist/cjs/cloudflare-output-contract.js +36 -4
- package/dist/cjs/cloudflare-output-verifier/identity.js +112 -23
- package/dist/cjs/cloudflare-output-verifier/index.js +10 -0
- package/dist/cjs/cloudflare-output-verifier/manifest.js +46 -0
- package/dist/cjs/cloudflare-output-verifier/mutation-policy.js +7 -1
- package/dist/cjs/cloudflare-output-verifier/worker-bundles.js +10 -5
- package/dist/cjs/config.js +10 -5
- package/dist/cjs/deploy-output/npmAliases.js +92 -6
- package/dist/cjs/deploy-output/plugin.js +27 -6
- package/dist/cjs/deploy-output/public-assets.js +146 -0
- package/dist/cjs/deploy-output/target.js +57 -1
- package/dist/cjs/deploy-output/trace-files.js +99 -0
- package/dist/cjs/module-federation-config/exposes.js +70 -0
- package/dist/cjs/module-federation-config/index.js +73 -0
- package/dist/cjs/module-federation-config/inspect.js +103 -0
- package/dist/cjs/module-federation-config/object-literal.js +87 -0
- package/dist/cjs/module-federation-config/syntax.js +151 -0
- package/dist/cjs/module-federation-config/types.js +18 -0
- package/dist/cjs/native-type-checker.js +130 -13
- package/dist/cjs/policy-defaults.js +38 -29
- package/dist/cjs/release-envelope/canonical.js +2 -9
- package/dist/cjs/release-envelope/contract.js +68 -0
- package/dist/cjs/release-envelope/framework-output.js +296 -105
- package/dist/cjs/release-envelope/index.js +150 -36
- package/dist/cjs/release-envelope/plugin.js +24 -15
- package/dist/cjs/release-envelope/renderer-output-stamp.js +170 -0
- package/dist/cjs/release-envelope/types.js +10 -8
- package/dist/cjs/release-identity.js +8 -5
- package/dist/cjs/renderer-build-identity.js +134 -0
- package/dist/cjs/templates/cloudflare-entry.001-bootstrap-security.mjs +14 -6
- package/dist/cjs/templates/cloudflare-entry.002-assets-routes.mjs +10 -2
- package/dist/cjs/templates/cloudflare-entry.004-rendering-css.mjs +403 -96
- package/dist/cjs/templates/cloudflare-entry.005-worker-dispatch.mjs +530 -103
- package/dist/cjs/templates/cloudflare-entry.006-fetch-handler.mjs +26 -7
- package/dist/cjs/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/cjs/workspace-topology.js +84 -0
- package/dist/esm/backend-federation-build/codegen.mjs +29 -18
- package/dist/esm/backend-federation-build/config.mjs +74 -38
- package/dist/esm/backend-federation-build/emit.mjs +64 -23
- package/dist/esm/build-config/build-environment.mjs +26 -160
- package/dist/esm/build-config/internal-effect-discovery.mjs +102 -0
- package/dist/esm/build-config/public.mjs +1 -1
- package/dist/esm/build-config/remote-address.mjs +20 -0
- package/dist/esm/cloudflare/artifacts.mjs +8 -19
- package/dist/esm/cloudflare/delivery-unit.mjs +124 -45
- package/dist/esm/cloudflare/index.mjs +15 -5
- package/dist/esm/cloudflare/native-renderer.mjs +48 -0
- package/dist/esm/cloudflare/renderer-identity.mjs +57 -0
- package/dist/esm/cloudflare/worker-manifest.mjs +55 -14
- package/dist/esm/cloudflare/worker-options.mjs +10 -0
- package/dist/esm/cloudflare/wrangler-config.mjs +203 -12
- package/dist/esm/cloudflare-builder.mjs +301 -89
- package/dist/esm/cloudflare-output-contract.mjs +29 -3
- package/dist/esm/cloudflare-output-verifier/identity.mjs +113 -24
- package/dist/esm/cloudflare-output-verifier/index.mjs +10 -0
- package/dist/esm/cloudflare-output-verifier/manifest.mjs +46 -0
- package/dist/esm/cloudflare-output-verifier/mutation-policy.mjs +7 -1
- package/dist/esm/cloudflare-output-verifier/worker-bundles.mjs +11 -6
- package/dist/esm/config.mjs +3 -1
- package/dist/esm/deploy-output/npmAliases.mjs +92 -6
- package/dist/esm/deploy-output/plugin.mjs +24 -6
- package/dist/esm/deploy-output/public-assets.mjs +82 -0
- package/dist/esm/deploy-output/target.mjs +50 -3
- package/dist/esm/deploy-output/trace-files.mjs +47 -0
- package/dist/esm/module-federation-config/exposes.mjs +18 -0
- package/dist/esm/module-federation-config/index.mjs +4 -0
- package/dist/esm/module-federation-config/inspect.mjs +65 -0
- package/dist/esm/module-federation-config/object-literal.mjs +43 -0
- package/dist/esm/module-federation-config/syntax.mjs +101 -0
- package/dist/esm/module-federation-config/types.mjs +0 -0
- package/dist/esm/native-type-checker.mjs +124 -13
- package/dist/esm/policy-defaults.mjs +36 -30
- package/dist/esm/release-envelope/canonical.mjs +2 -9
- package/dist/esm/release-envelope/contract.mjs +21 -0
- package/dist/esm/release-envelope/framework-output.mjs +297 -106
- package/dist/esm/release-envelope/index.mjs +149 -38
- package/dist/esm/release-envelope/plugin.mjs +24 -15
- package/dist/esm/release-envelope/renderer-output-stamp.mjs +112 -0
- package/dist/esm/release-envelope/types.mjs +2 -3
- package/dist/esm/release-identity.mjs +8 -5
- package/dist/esm/renderer-build-identity.mjs +82 -0
- package/dist/esm/templates/cloudflare-entry.001-bootstrap-security.mjs +14 -6
- package/dist/esm/templates/cloudflare-entry.002-assets-routes.mjs +10 -2
- package/dist/esm/templates/cloudflare-entry.004-rendering-css.mjs +403 -96
- package/dist/esm/templates/cloudflare-entry.005-worker-dispatch.mjs +530 -103
- package/dist/esm/templates/cloudflare-entry.006-fetch-handler.mjs +26 -7
- package/dist/esm/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/esm/workspace-topology.mjs +21 -0
- package/dist/esm-node/backend-federation-build/codegen.mjs +29 -18
- package/dist/esm-node/backend-federation-build/config.mjs +74 -38
- package/dist/esm-node/backend-federation-build/emit.mjs +64 -23
- package/dist/esm-node/build-config/build-environment.mjs +26 -160
- package/dist/esm-node/build-config/internal-effect-discovery.mjs +103 -0
- package/dist/esm-node/build-config/public.mjs +1 -1
- package/dist/esm-node/build-config/remote-address.mjs +21 -0
- package/dist/esm-node/cloudflare/artifacts.mjs +8 -19
- package/dist/esm-node/cloudflare/delivery-unit.mjs +124 -45
- package/dist/esm-node/cloudflare/index.mjs +15 -5
- package/dist/esm-node/cloudflare/native-renderer.mjs +49 -0
- package/dist/esm-node/cloudflare/renderer-identity.mjs +58 -0
- package/dist/esm-node/cloudflare/worker-manifest.mjs +55 -14
- package/dist/esm-node/cloudflare/worker-options.mjs +11 -0
- package/dist/esm-node/cloudflare/wrangler-config.mjs +203 -12
- package/dist/esm-node/cloudflare-builder.mjs +301 -89
- package/dist/esm-node/cloudflare-output-contract.mjs +29 -3
- package/dist/esm-node/cloudflare-output-verifier/identity.mjs +113 -24
- package/dist/esm-node/cloudflare-output-verifier/index.mjs +10 -0
- package/dist/esm-node/cloudflare-output-verifier/manifest.mjs +46 -0
- package/dist/esm-node/cloudflare-output-verifier/mutation-policy.mjs +7 -1
- package/dist/esm-node/cloudflare-output-verifier/worker-bundles.mjs +11 -6
- package/dist/esm-node/config.mjs +3 -1
- package/dist/esm-node/deploy-output/npmAliases.mjs +92 -6
- package/dist/esm-node/deploy-output/plugin.mjs +24 -6
- package/dist/esm-node/deploy-output/public-assets.mjs +83 -0
- package/dist/esm-node/deploy-output/target.mjs +50 -3
- package/dist/esm-node/deploy-output/trace-files.mjs +48 -0
- package/dist/esm-node/module-federation-config/exposes.mjs +19 -0
- package/dist/esm-node/module-federation-config/index.mjs +5 -0
- package/dist/esm-node/module-federation-config/inspect.mjs +66 -0
- package/dist/esm-node/module-federation-config/object-literal.mjs +44 -0
- package/dist/esm-node/module-federation-config/syntax.mjs +102 -0
- package/dist/esm-node/module-federation-config/types.mjs +1 -0
- package/dist/esm-node/native-type-checker.mjs +124 -13
- package/dist/esm-node/policy-defaults.mjs +36 -30
- package/dist/esm-node/release-envelope/canonical.mjs +2 -9
- package/dist/esm-node/release-envelope/contract.mjs +22 -0
- package/dist/esm-node/release-envelope/framework-output.mjs +297 -106
- package/dist/esm-node/release-envelope/index.mjs +149 -38
- package/dist/esm-node/release-envelope/plugin.mjs +24 -15
- package/dist/esm-node/release-envelope/renderer-output-stamp.mjs +113 -0
- package/dist/esm-node/release-envelope/types.mjs +2 -3
- package/dist/esm-node/release-identity.mjs +8 -5
- package/dist/esm-node/renderer-build-identity.mjs +83 -0
- package/dist/esm-node/templates/cloudflare-entry.001-bootstrap-security.mjs +14 -6
- package/dist/esm-node/templates/cloudflare-entry.002-assets-routes.mjs +10 -2
- package/dist/esm-node/templates/cloudflare-entry.004-rendering-css.mjs +403 -96
- package/dist/esm-node/templates/cloudflare-entry.005-worker-dispatch.mjs +530 -103
- package/dist/esm-node/templates/cloudflare-entry.006-fetch-handler.mjs +26 -7
- package/dist/esm-node/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/esm-node/workspace-topology.mjs +22 -0
- package/dist/types/backend-federation-build/codegen.d.ts +30 -0
- package/dist/types/backend-federation-build/config.d.ts +10 -57
- package/dist/types/backend-federation-build/emit.d.ts +12 -2
- package/dist/types/backend-federation-build/index.d.ts +1 -1
- package/dist/types/build-config/build-environment.d.ts +1 -9
- package/dist/types/build-config/internal-effect-discovery.d.ts +4 -0
- package/dist/types/build-config/public.d.ts +1 -1
- package/dist/types/build-config/remote-address.d.ts +3 -0
- package/dist/types/cloudflare/artifacts.d.ts +7 -6
- package/dist/types/cloudflare/constants.d.ts +1 -1
- package/dist/types/cloudflare/delivery-unit.d.ts +38 -7
- package/dist/types/cloudflare/native-renderer.d.ts +30 -0
- package/dist/types/cloudflare/renderer-identity.d.ts +25 -0
- package/dist/types/cloudflare/worker-manifest.d.ts +17 -2
- package/dist/types/cloudflare/worker-options.d.ts +20 -0
- package/dist/types/cloudflare/wrangler-config.d.ts +55 -2
- package/dist/types/cloudflare-builder.d.ts +51 -8
- package/dist/types/cloudflare-output-contract.d.ts +5 -3
- package/dist/types/cloudflare-output-verifier/identity.d.ts +7 -3
- package/dist/types/cloudflare-output-verifier/worker-bundles.d.ts +2 -2
- package/dist/types/config.d.ts +98 -13
- package/dist/types/deploy-output/plugin.d.ts +29 -9
- package/dist/types/deploy-output/public-assets.d.ts +51 -0
- package/dist/types/deploy-output/target.d.ts +28 -5
- package/dist/types/deploy-output/trace-files.d.ts +17 -0
- package/dist/types/module-federation-config/exposes.d.ts +11 -0
- package/dist/types/module-federation-config/index.d.ts +5 -0
- package/dist/types/module-federation-config/inspect.d.ts +2 -0
- package/dist/types/module-federation-config/object-literal.d.ts +4 -0
- package/dist/types/module-federation-config/syntax.d.ts +7 -0
- package/dist/types/module-federation-config/types.d.ts +20 -0
- package/dist/types/native-type-checker.d.ts +26 -3
- package/dist/types/policy-defaults.d.ts +12 -2
- package/dist/types/release-envelope/canonical.d.ts +5 -5
- package/dist/types/release-envelope/contract.d.mts +8 -0
- package/dist/types/release-envelope/framework-output.d.ts +23 -13
- package/dist/types/release-envelope/index.d.ts +17 -5
- package/dist/types/release-envelope/plugin.d.ts +10 -6
- package/dist/types/release-envelope/renderer-output-stamp.d.ts +34 -0
- package/dist/types/release-envelope/types.d.ts +42 -4
- package/dist/types/release-identity.d.ts +3 -2
- package/dist/types/renderer-build-identity.d.ts +30 -0
- package/dist/types/templates/cloudflare-worker-route-data.d.mts +14 -0
- package/dist/types/workspace-topology.d.ts +91 -0
- package/package.json +87 -27
- package/src/backend-federation-build/codegen.ts +28 -19
- package/src/backend-federation-build/config.ts +189 -123
- package/src/backend-federation-build/emit.ts +119 -38
- package/src/backend-federation-build/index.ts +4 -1
- package/src/build-config/build-environment.ts +59 -285
- package/src/build-config/internal-effect-discovery.ts +239 -0
- package/src/build-config/public.ts +0 -1
- package/src/build-config/remote-address.ts +33 -0
- package/src/cloudflare/artifacts.ts +22 -43
- package/src/cloudflare/delivery-unit.ts +283 -60
- package/src/cloudflare/index.ts +35 -19
- package/src/cloudflare/native-renderer.ts +117 -0
- package/src/cloudflare/renderer-identity.ts +171 -0
- package/src/cloudflare/worker-manifest.ts +108 -10
- package/src/cloudflare/worker-options.ts +60 -0
- package/src/cloudflare/wrangler-config.ts +390 -14
- package/src/cloudflare-builder.ts +543 -170
- package/src/cloudflare-output-contract.ts +45 -2
- package/src/cloudflare-output-verifier/identity.ts +138 -7
- package/src/cloudflare-output-verifier/index.ts +20 -0
- package/src/cloudflare-output-verifier/manifest.ts +77 -0
- package/src/cloudflare-output-verifier/mutation-policy.ts +11 -1
- package/src/cloudflare-output-verifier/worker-bundles.ts +27 -11
- package/src/config.ts +101 -19
- package/src/deploy-output/npmAliases.ts +141 -4
- package/src/deploy-output/plugin.ts +55 -18
- package/src/deploy-output/public-assets.ts +224 -0
- package/src/deploy-output/target.ts +97 -14
- package/src/deploy-output/trace-files.ts +80 -0
- package/src/module-federation-config/exposes.ts +46 -0
- package/src/module-federation-config/index.ts +22 -0
- package/src/module-federation-config/inspect.ts +157 -0
- package/src/module-federation-config/object-literal.ts +76 -0
- package/src/module-federation-config/syntax.ts +212 -0
- package/src/module-federation-config/types.ts +22 -0
- package/src/native-type-checker.ts +233 -20
- package/src/policy-defaults.ts +47 -17
- package/src/release-envelope/canonical.ts +6 -18
- package/src/release-envelope/contract.mjs +28 -0
- package/src/release-envelope/framework-output.ts +681 -156
- package/src/release-envelope/index.ts +315 -60
- package/src/release-envelope/plugin.ts +54 -38
- package/src/release-envelope/renderer-output-stamp.ts +210 -0
- package/src/release-envelope/types.ts +75 -6
- package/src/release-identity.ts +19 -2
- package/src/renderer-build-identity.ts +168 -0
- package/src/templates/cloudflare-entry.001-bootstrap-security.mjs +14 -6
- package/src/templates/cloudflare-entry.002-assets-routes.mjs +10 -2
- package/src/templates/cloudflare-entry.004-rendering-css.mjs +403 -96
- package/src/templates/cloudflare-entry.005-worker-dispatch.mjs +530 -103
- package/src/templates/cloudflare-entry.006-fetch-handler.mjs +26 -7
- package/src/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/src/workspace-topology.ts +125 -0
- package/dist/cjs/templates/cloudflare-worker-fs-promises.mjs +0 -11
- package/dist/cjs/templates/cloudflare-worker-loadable-server.mjs +0 -281
- package/dist/cjs/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
- package/dist/cjs/templates/cloudflare-worker-path.mjs +0 -98
- package/dist/esm/templates/cloudflare-worker-fs-promises.mjs +0 -11
- package/dist/esm/templates/cloudflare-worker-loadable-server.mjs +0 -281
- package/dist/esm/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
- package/dist/esm/templates/cloudflare-worker-path.mjs +0 -98
- package/dist/esm-node/templates/cloudflare-worker-fs-promises.mjs +0 -11
- package/dist/esm-node/templates/cloudflare-worker-loadable-server.mjs +0 -281
- package/dist/esm-node/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
- package/dist/esm-node/templates/cloudflare-worker-path.mjs +0 -98
- package/dist/types/templates/cloudflare-worker-fs-promises.d.mts +0 -5
- package/dist/types/templates/cloudflare-worker-loadable-server.d.mts +0 -48
- package/dist/types/templates/cloudflare-worker-mf-ssr-runtime-plugin.d.mts +0 -13
- package/dist/types/templates/cloudflare-worker-path.d.mts +0 -21
- package/src/templates/cloudflare-worker-fs-promises.mjs +0 -11
- package/src/templates/cloudflare-worker-loadable-server.mjs +0 -281
- package/src/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
- package/src/templates/cloudflare-worker-path.mjs +0 -98
|
@@ -2,9 +2,13 @@ function createNoopMonitors() {
|
|
|
2
2
|
const noop = () => {};
|
|
3
3
|
|
|
4
4
|
return {
|
|
5
|
+
counter: noop,
|
|
5
6
|
debug: noop,
|
|
6
7
|
error: noop,
|
|
7
8
|
info: noop,
|
|
9
|
+
push: noop,
|
|
10
|
+
timing: noop,
|
|
11
|
+
trace: noop,
|
|
8
12
|
warn: noop,
|
|
9
13
|
};
|
|
10
14
|
}
|
|
@@ -124,6 +128,24 @@ function extractRenderedFragmentHtml(html, boundaryId, expose) {
|
|
|
124
128
|
return extractRenderedBoundaryElement(html, boundaryId, expose);
|
|
125
129
|
}
|
|
126
130
|
|
|
131
|
+
function readOpeningTagAttributes(openingTag) {
|
|
132
|
+
const attributes = {};
|
|
133
|
+
const opening = /^<\/?[A-Za-z][\w:-]*/u.exec(openingTag);
|
|
134
|
+
if (!opening) return attributes;
|
|
135
|
+
let remaining = openingTag.slice(opening[0].length);
|
|
136
|
+
const attribute =
|
|
137
|
+
/^\s+([^\s=/>]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/u;
|
|
138
|
+
while (remaining) {
|
|
139
|
+
const match = attribute.exec(remaining);
|
|
140
|
+
if (!match) break;
|
|
141
|
+
const name = match[1].toLowerCase();
|
|
142
|
+
if (!Object.hasOwn(attributes, name))
|
|
143
|
+
attributes[name] = match[2] ?? match[3] ?? match[4] ?? '';
|
|
144
|
+
remaining = remaining.slice(match[0].length);
|
|
145
|
+
}
|
|
146
|
+
return attributes;
|
|
147
|
+
}
|
|
148
|
+
|
|
127
149
|
function readOpeningTagAttribute(openingTag, name) {
|
|
128
150
|
const pattern = new RegExp(
|
|
129
151
|
`\\s${escapeFragmentRegExp(name)}=(?:"([^"]*)"|'([^']*)')`,
|
|
@@ -142,7 +164,7 @@ function collectStylesheetHrefs(html) {
|
|
|
142
164
|
const rel = readOpeningTagAttribute(link, 'rel');
|
|
143
165
|
const href = readOpeningTagAttribute(link, 'href');
|
|
144
166
|
|
|
145
|
-
if (href && rel?.split(/\s+/u).includes('stylesheet')) {
|
|
167
|
+
if (href && rel?.toLowerCase().split(/\s+/u).includes('stylesheet')) {
|
|
146
168
|
hrefs.push(href);
|
|
147
169
|
}
|
|
148
170
|
}
|
|
@@ -163,7 +185,7 @@ function dedupeStylesheetLinks(html, seenHrefs = new Set(), requestUrl) {
|
|
|
163
185
|
const rel = readOpeningTagAttribute(link, 'rel');
|
|
164
186
|
const href = readOpeningTagAttribute(link, 'href');
|
|
165
187
|
|
|
166
|
-
if (!href || !rel?.split(/\s+/u).includes('stylesheet')) {
|
|
188
|
+
if (!href || !rel?.toLowerCase().split(/\s+/u).includes('stylesheet')) {
|
|
167
189
|
return link;
|
|
168
190
|
}
|
|
169
191
|
|
|
@@ -180,7 +202,7 @@ function dedupeStylesheetLinks(html, seenHrefs = new Set(), requestUrl) {
|
|
|
180
202
|
function stripStylesheetLinks(html) {
|
|
181
203
|
return html.replace(/<link\b[^>]*>/giu, link => {
|
|
182
204
|
const rel = readOpeningTagAttribute(link, 'rel');
|
|
183
|
-
return rel?.split(/\s+/u).includes('stylesheet') ? '' : link;
|
|
205
|
+
return rel?.toLowerCase().split(/\s+/u).includes('stylesheet') ? '' : link;
|
|
184
206
|
});
|
|
185
207
|
}
|
|
186
208
|
|
|
@@ -194,61 +216,231 @@ function createStylesheetLinksHtml(stylesheetEntries) {
|
|
|
194
216
|
.join('');
|
|
195
217
|
}
|
|
196
218
|
|
|
197
|
-
function createStylesheetLinkStream(
|
|
219
|
+
function createStylesheetLinkStream(
|
|
220
|
+
body,
|
|
221
|
+
stylesheetEntries,
|
|
222
|
+
requestUrl,
|
|
223
|
+
resolveRemoteCss = async () => [],
|
|
224
|
+
) {
|
|
198
225
|
const decoder = new TextDecoder();
|
|
199
226
|
const encoder = new TextEncoder();
|
|
200
|
-
|
|
227
|
+
const seenHrefs = new Set();
|
|
228
|
+
const pendingEntries = [...stylesheetEntries];
|
|
229
|
+
const maxTagLength = 64 * 1024;
|
|
230
|
+
const maxHeadLength = 256 * 1024;
|
|
231
|
+
let reader;
|
|
232
|
+
let cancelled = false;
|
|
233
|
+
let finished = false;
|
|
234
|
+
let headParts;
|
|
235
|
+
let headLength = 0;
|
|
236
|
+
let headSlot;
|
|
237
|
+
let rawText;
|
|
201
238
|
let pending = '';
|
|
202
239
|
|
|
203
|
-
const
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
);
|
|
223
|
-
injected = true;
|
|
224
|
-
pending = '';
|
|
225
|
-
controller.enqueue(encoder.encode(output));
|
|
226
|
-
return;
|
|
240
|
+
const linksFor = entries => {
|
|
241
|
+
const missing = entries.filter(({ preloadHref }) => {
|
|
242
|
+
if (seenHrefs.has(preloadHref)) return false;
|
|
243
|
+
seenHrefs.add(preloadHref);
|
|
244
|
+
return true;
|
|
245
|
+
});
|
|
246
|
+
return createStylesheetLinksHtml(missing);
|
|
247
|
+
};
|
|
248
|
+
const tagEnd = value => {
|
|
249
|
+
let quote;
|
|
250
|
+
for (let index = 1; index < value.length; index += 1) {
|
|
251
|
+
const character = value[index];
|
|
252
|
+
if (quote) {
|
|
253
|
+
if (character === quote) quote = undefined;
|
|
254
|
+
} else if (character === '"' || character === "'") {
|
|
255
|
+
quote = character;
|
|
256
|
+
} else if (character === '>') {
|
|
257
|
+
return index;
|
|
258
|
+
}
|
|
227
259
|
}
|
|
260
|
+
return -1;
|
|
261
|
+
};
|
|
228
262
|
|
|
229
|
-
|
|
230
|
-
|
|
263
|
+
const consume = async final => {
|
|
264
|
+
let output = '';
|
|
265
|
+
const append = value => {
|
|
266
|
+
if (headParts === undefined) {
|
|
267
|
+
output += value;
|
|
268
|
+
} else {
|
|
269
|
+
headLength += encoder.encode(value).byteLength;
|
|
270
|
+
if (headLength > maxHeadLength)
|
|
271
|
+
throw new RangeError('Cloudflare HTML stream head exceeds 256 KiB');
|
|
272
|
+
headParts.push(value);
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
while (pending && !cancelled) {
|
|
276
|
+
if (rawText) {
|
|
277
|
+
const match = rawText.comment
|
|
278
|
+
? /-->/u.exec(pending)
|
|
279
|
+
: new RegExp(`</${rawText.tag}(?=[\\s/>])`, 'iu').exec(pending);
|
|
280
|
+
if (!match) {
|
|
281
|
+
const keep = final ? 0 : rawText.comment ? 2 : rawText.tag.length + 2;
|
|
282
|
+
const available = Math.max(0, pending.length - keep);
|
|
283
|
+
append(pending.slice(0, available));
|
|
284
|
+
pending = pending.slice(available);
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
const end = match.index + (rawText.comment ? match[0].length : 0);
|
|
288
|
+
append(pending.slice(0, end));
|
|
289
|
+
pending = pending.slice(end);
|
|
290
|
+
rawText = undefined;
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
const opening = pending.indexOf('<');
|
|
294
|
+
if (opening < 0) {
|
|
295
|
+
append(pending);
|
|
296
|
+
pending = '';
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
if (opening > 0) {
|
|
300
|
+
append(pending.slice(0, opening));
|
|
301
|
+
pending = pending.slice(opening);
|
|
302
|
+
}
|
|
303
|
+
if (!final && pending.length < 4 && '<!--'.startsWith(pending)) break;
|
|
304
|
+
if (pending.startsWith('<!--')) {
|
|
305
|
+
append('<!--');
|
|
306
|
+
pending = pending.slice(4);
|
|
307
|
+
rawText = { comment: true };
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
const closing = tagEnd(pending);
|
|
311
|
+
if (closing < 0) {
|
|
312
|
+
if (encoder.encode(pending).byteLength > maxTagLength)
|
|
313
|
+
throw new RangeError(
|
|
314
|
+
'Cloudflare HTML stream has an unterminated tag larger than 64 KiB',
|
|
315
|
+
);
|
|
316
|
+
if (final) {
|
|
317
|
+
append(pending);
|
|
318
|
+
pending = '';
|
|
319
|
+
}
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
if (
|
|
323
|
+
encoder.encode(pending.slice(0, closing + 1)).byteLength > maxTagLength
|
|
324
|
+
)
|
|
325
|
+
throw new RangeError('Cloudflare HTML stream tag exceeds 64 KiB');
|
|
326
|
+
const tag = pending.slice(0, closing + 1);
|
|
327
|
+
pending = pending.slice(closing + 1);
|
|
328
|
+
if (/^<head(?:\s|>)/iu.test(tag)) {
|
|
329
|
+
headParts = [];
|
|
330
|
+
headLength = 0;
|
|
331
|
+
headSlot = undefined;
|
|
332
|
+
}
|
|
333
|
+
if (tag === CLOUDFLARE_STYLESHEET_LINKS_SENTINEL && headParts) {
|
|
334
|
+
if (headSlot === undefined) {
|
|
335
|
+
headSlot = headParts.length;
|
|
336
|
+
append('');
|
|
337
|
+
}
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
const attributes = readOpeningTagAttributes(tag);
|
|
341
|
+
if (
|
|
342
|
+
output &&
|
|
343
|
+
headParts === undefined &&
|
|
344
|
+
attributes['data-modern-boundary-id'] &&
|
|
345
|
+
attributes['data-modern-mf-expose']
|
|
346
|
+
) {
|
|
347
|
+
pending = tag + pending;
|
|
348
|
+
return output;
|
|
349
|
+
}
|
|
350
|
+
if (/^<link(?=[\s/>])/iu.test(tag)) {
|
|
351
|
+
const rel = attributes.rel;
|
|
352
|
+
const href = attributes.href;
|
|
353
|
+
if (href && rel?.toLowerCase().split(/\s+/u).includes('stylesheet')) {
|
|
354
|
+
const normalized = normalizeStylesheetHref(href, requestUrl);
|
|
355
|
+
if (seenHrefs.has(normalized)) continue;
|
|
356
|
+
seenHrefs.add(normalized);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const remoteHrefs = await resolveRemoteCss(attributes);
|
|
360
|
+
const remoteEntries = remoteHrefs.map(href => ({
|
|
361
|
+
href,
|
|
362
|
+
preloadHref: normalizeStylesheetHref(href, requestUrl),
|
|
363
|
+
reactResource: true,
|
|
364
|
+
}));
|
|
365
|
+
if (headParts) pendingEntries.push(...remoteEntries);
|
|
366
|
+
else append(linksFor(remoteEntries));
|
|
367
|
+
if (/^<\/head\s*>$/iu.test(tag) && headParts) {
|
|
368
|
+
const links = linksFor(pendingEntries);
|
|
369
|
+
if (headSlot === undefined) append(links);
|
|
370
|
+
else {
|
|
371
|
+
headLength += encoder.encode(links).byteLength;
|
|
372
|
+
if (headLength > maxHeadLength)
|
|
373
|
+
throw new RangeError('Cloudflare HTML stream head exceeds 256 KiB');
|
|
374
|
+
headParts[headSlot] = links;
|
|
375
|
+
}
|
|
376
|
+
append(tag);
|
|
377
|
+
output += headParts.join('');
|
|
378
|
+
headParts = undefined;
|
|
379
|
+
} else {
|
|
380
|
+
append(tag);
|
|
381
|
+
}
|
|
382
|
+
const rawOpening = /^<(script|style|title|textarea)(?=[\s/>])/iu.exec(
|
|
383
|
+
tag,
|
|
384
|
+
);
|
|
385
|
+
if (rawOpening) rawText = { tag: rawOpening[1].toLowerCase() };
|
|
231
386
|
}
|
|
232
|
-
if (
|
|
233
|
-
|
|
234
|
-
|
|
387
|
+
if (final && headParts) {
|
|
388
|
+
if (headSlot !== undefined) {
|
|
389
|
+
const links = linksFor(pendingEntries);
|
|
390
|
+
headLength += encoder.encode(links).byteLength;
|
|
391
|
+
if (headLength > maxHeadLength)
|
|
392
|
+
throw new RangeError('Cloudflare HTML stream head exceeds 256 KiB');
|
|
393
|
+
headParts[headSlot] = links;
|
|
394
|
+
}
|
|
395
|
+
output += headParts.join('');
|
|
396
|
+
headParts = undefined;
|
|
235
397
|
}
|
|
398
|
+
return output;
|
|
236
399
|
};
|
|
237
400
|
|
|
238
|
-
return
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
401
|
+
return new ReadableStream(
|
|
402
|
+
{
|
|
403
|
+
async pull(controller) {
|
|
404
|
+
try {
|
|
405
|
+
reader ??= body.getReader();
|
|
406
|
+
while (!cancelled) {
|
|
407
|
+
const output = await consume(finished);
|
|
408
|
+
if (cancelled) return;
|
|
409
|
+
if (output) controller.enqueue(encoder.encode(output));
|
|
410
|
+
if (finished && pending.length === 0) {
|
|
411
|
+
reader.releaseLock();
|
|
412
|
+
controller.close();
|
|
413
|
+
}
|
|
414
|
+
if (output || finished) return;
|
|
415
|
+
const result = await reader.read();
|
|
416
|
+
finished = result.done;
|
|
417
|
+
pending += result.done
|
|
418
|
+
? decoder.decode()
|
|
419
|
+
: typeof result.value === 'string'
|
|
420
|
+
? result.value
|
|
421
|
+
: decoder.decode(result.value, { stream: true });
|
|
422
|
+
}
|
|
423
|
+
} catch (error) {
|
|
424
|
+
if (cancelled) return;
|
|
425
|
+
cancelled = true;
|
|
426
|
+
// The error reaches the client without waiting on the source's
|
|
427
|
+
// cancel hook, which may never settle.
|
|
428
|
+
reader?.cancel(error).catch(() => {});
|
|
429
|
+
reader?.releaseLock();
|
|
430
|
+
controller.error(error);
|
|
431
|
+
}
|
|
243
432
|
},
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
433
|
+
cancel(reason) {
|
|
434
|
+
cancelled = true;
|
|
435
|
+
if (reader) {
|
|
436
|
+
reader.cancel(reason).catch(() => {});
|
|
437
|
+
reader.releaseLock();
|
|
438
|
+
} else {
|
|
439
|
+
body.cancel(reason).catch(() => {});
|
|
440
|
+
}
|
|
250
441
|
},
|
|
251
|
-
}
|
|
442
|
+
},
|
|
443
|
+
{ highWaterMark: 0 },
|
|
252
444
|
);
|
|
253
445
|
}
|
|
254
446
|
|
|
@@ -511,21 +703,31 @@ function createDistributedSsrFragmentContext(request, env) {
|
|
|
511
703
|
const pendingResolutions = new Set();
|
|
512
704
|
const stylesheetHrefsByFragment = configuredFragments.map(() => new Set());
|
|
513
705
|
|
|
706
|
+
const getCurrentStylesheetHrefs = (boundaryId, expose) => {
|
|
707
|
+
const hrefs = new Set();
|
|
708
|
+
let configured = false;
|
|
709
|
+
for (const [index, { fragment }] of configuredFragments.entries()) {
|
|
710
|
+
if (
|
|
711
|
+
(boundaryId !== undefined && fragment.boundaryId !== boundaryId) ||
|
|
712
|
+
(expose !== undefined && fragment.expose !== expose)
|
|
713
|
+
) {
|
|
714
|
+
continue;
|
|
715
|
+
}
|
|
716
|
+
configured = true;
|
|
717
|
+
for (const href of stylesheetHrefsByFragment[index]) hrefs.add(href);
|
|
718
|
+
}
|
|
719
|
+
if (boundaryId !== undefined && !configured) return undefined;
|
|
720
|
+
return [...hrefs];
|
|
721
|
+
};
|
|
722
|
+
|
|
514
723
|
return {
|
|
515
724
|
required: true,
|
|
725
|
+
getCurrentStylesheetHrefs,
|
|
516
726
|
async getStylesheetHrefs() {
|
|
517
727
|
while (pendingResolutions.size > 0) {
|
|
518
728
|
await Promise.all([...pendingResolutions]);
|
|
519
729
|
}
|
|
520
|
-
|
|
521
|
-
const hrefs = new Set();
|
|
522
|
-
for (const fragmentHrefs of stylesheetHrefsByFragment) {
|
|
523
|
-
for (const href of fragmentHrefs) {
|
|
524
|
-
hrefs.add(href);
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
return [...hrefs];
|
|
730
|
+
return getCurrentStylesheetHrefs();
|
|
529
731
|
},
|
|
530
732
|
resolve(remote, expose, props) {
|
|
531
733
|
const configuredIndex = configuredFragments.findIndex(
|
|
@@ -643,6 +845,8 @@ function createRequestHandlerOptions({
|
|
|
643
845
|
htmlTemplate,
|
|
644
846
|
routeManifest,
|
|
645
847
|
loadableStats,
|
|
848
|
+
env,
|
|
849
|
+
executionContext,
|
|
646
850
|
distributedSsrFragments,
|
|
647
851
|
distributedSsrFragmentRequest,
|
|
648
852
|
}) {
|
|
@@ -657,8 +861,10 @@ function createRequestHandlerOptions({
|
|
|
657
861
|
entryName: route.entryName,
|
|
658
862
|
},
|
|
659
863
|
params: {},
|
|
660
|
-
loaderContext:
|
|
864
|
+
loaderContext: new Map(),
|
|
661
865
|
config: {},
|
|
866
|
+
platform: { kind: 'worker', bindings: env },
|
|
867
|
+
executionContext,
|
|
662
868
|
locals: {
|
|
663
869
|
...(distributedSsrFragments === undefined
|
|
664
870
|
? {}
|
|
@@ -771,33 +977,54 @@ function getRemoteAssetBase(remoteManifest, manifestUrl) {
|
|
|
771
977
|
}
|
|
772
978
|
}
|
|
773
979
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
980
|
+
// Per-request scope for in-flight remote JSON fetches. A fetch Promise is
|
|
981
|
+
// request-bound I/O in workerd: it must never be stored on a module-level
|
|
982
|
+
// map and awaited by a later, unrelated request (that throws "Cannot
|
|
983
|
+
// perform I/O on behalf of a different request"). This scope only dedupes
|
|
984
|
+
// concurrent lookups for the same URL made while handling one request; it is
|
|
985
|
+
// created fresh per request and discarded once that request completes.
|
|
986
|
+
function createRemoteJsonFetchScope() {
|
|
987
|
+
return new Map();
|
|
988
|
+
}
|
|
782
989
|
|
|
783
|
-
|
|
784
|
-
|
|
990
|
+
async function fetchRemoteJson(jsonUrl, pendingFetches) {
|
|
991
|
+
if (remoteJsonCache.has(jsonUrl)) {
|
|
992
|
+
return remoteJsonCache.get(jsonUrl);
|
|
993
|
+
}
|
|
785
994
|
|
|
786
|
-
|
|
787
|
-
|
|
995
|
+
if (pendingFetches.has(jsonUrl)) {
|
|
996
|
+
return pendingFetches.get(jsonUrl);
|
|
997
|
+
}
|
|
788
998
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
999
|
+
const pending = (async () => {
|
|
1000
|
+
let response;
|
|
1001
|
+
try {
|
|
1002
|
+
response = await fetch(jsonUrl);
|
|
1003
|
+
} catch {
|
|
1004
|
+
return {};
|
|
1005
|
+
}
|
|
794
1006
|
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
1007
|
+
if (!response.ok) {
|
|
1008
|
+
return {};
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
const value = await response.json().catch(() => undefined);
|
|
1012
|
+
if (value === undefined) {
|
|
1013
|
+
return {};
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
// Only a settled, plain value is safe to share across requests.
|
|
1017
|
+
remoteJsonCache.set(jsonUrl, value);
|
|
1018
|
+
return value;
|
|
1019
|
+
})();
|
|
1020
|
+
|
|
1021
|
+
pendingFetches.set(jsonUrl, pending);
|
|
799
1022
|
|
|
800
|
-
|
|
1023
|
+
try {
|
|
1024
|
+
return await pending;
|
|
1025
|
+
} finally {
|
|
1026
|
+
pendingFetches.delete(jsonUrl);
|
|
1027
|
+
}
|
|
801
1028
|
}
|
|
802
1029
|
|
|
803
1030
|
function findRemoteExpose(remoteManifest, exposePath) {
|
|
@@ -855,6 +1082,24 @@ function collectLocalFragmentCssAssets(html, request) {
|
|
|
855
1082
|
}
|
|
856
1083
|
}
|
|
857
1084
|
|
|
1085
|
+
// This app's own route rendered the fragment, so the fragment depends on
|
|
1086
|
+
// that route's stylesheets too (for example a global Tailwind sheet the
|
|
1087
|
+
// exposed component never imports). Report the deploy-time route CSS so
|
|
1088
|
+
// the composing shell links it without fetching this app's manifests, as
|
|
1089
|
+
// the Node composition does.
|
|
1090
|
+
const fragmentRequest = readDistributedSsrFragmentRequest(request);
|
|
1091
|
+
if (
|
|
1092
|
+
fragmentRequest &&
|
|
1093
|
+
(!containerName || fragmentRequest.boundaryId === containerName) &&
|
|
1094
|
+
findRemoteExpose(localManifest, fragmentRequest.expose)
|
|
1095
|
+
) {
|
|
1096
|
+
for (const asset of Array.isArray(localManifest.routeCss)
|
|
1097
|
+
? localManifest.routeCss
|
|
1098
|
+
: []) {
|
|
1099
|
+
assets.add(asset);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
|
|
858
1103
|
return [...assets];
|
|
859
1104
|
}
|
|
860
1105
|
|
|
@@ -917,7 +1162,13 @@ function collectRouteManifestCssAssets(routeManifest) {
|
|
|
917
1162
|
return [...assets];
|
|
918
1163
|
}
|
|
919
1164
|
|
|
920
|
-
async function collectRenderedRemoteCssHrefs(
|
|
1165
|
+
async function collectRenderedRemoteCssHrefs(
|
|
1166
|
+
html,
|
|
1167
|
+
request,
|
|
1168
|
+
env,
|
|
1169
|
+
exposes,
|
|
1170
|
+
pendingRemoteJsonFetches,
|
|
1171
|
+
) {
|
|
921
1172
|
const bodyStart = html.indexOf('</head>');
|
|
922
1173
|
const composedFragmentHrefs = collectStylesheetHrefs(
|
|
923
1174
|
bodyStart >= 0 ? html.slice(bodyStart + '</head>'.length) : html,
|
|
@@ -927,7 +1178,7 @@ async function collectRenderedRemoteCssHrefs(html, request, env) {
|
|
|
927
1178
|
return [...new Set(composedFragmentHrefs)];
|
|
928
1179
|
}
|
|
929
1180
|
|
|
930
|
-
const renderedExposes = collectRenderedFederatedExposes(html);
|
|
1181
|
+
const renderedExposes = exposes ?? collectRenderedFederatedExposes(html);
|
|
931
1182
|
|
|
932
1183
|
if (renderedExposes.length === 0) {
|
|
933
1184
|
return [];
|
|
@@ -961,11 +1212,15 @@ async function collectRenderedRemoteCssHrefs(html, request, env) {
|
|
|
961
1212
|
return;
|
|
962
1213
|
}
|
|
963
1214
|
|
|
964
|
-
const remoteManifest = await fetchRemoteJson(
|
|
1215
|
+
const remoteManifest = await fetchRemoteJson(
|
|
1216
|
+
manifestUrl,
|
|
1217
|
+
pendingRemoteJsonFetches,
|
|
1218
|
+
);
|
|
965
1219
|
const remoteExpose = findRemoteExpose(remoteManifest, expose);
|
|
966
1220
|
const publicPath = getRemoteAssetBase(remoteManifest, manifestUrl);
|
|
967
1221
|
const remoteRouteManifest = await fetchRemoteJson(
|
|
968
1222
|
new URL('routes-manifest.json', publicPath).toString(),
|
|
1223
|
+
pendingRemoteJsonFetches,
|
|
969
1224
|
);
|
|
970
1225
|
|
|
971
1226
|
for (const asset of collectCssAssetEntries(remoteExpose?.assets)) {
|
|
@@ -1008,21 +1263,21 @@ async function withRouteCssLinks(
|
|
|
1008
1263
|
request,
|
|
1009
1264
|
env,
|
|
1010
1265
|
distributedSsrFragmentCssHrefs,
|
|
1266
|
+
distributedSsrFragments,
|
|
1011
1267
|
) {
|
|
1012
1268
|
const contentType = response.headers.get('content-type') || '';
|
|
1013
1269
|
|
|
1014
|
-
if (!contentType.includes('text/html')) {
|
|
1270
|
+
if (!contentType.includes('text/html') || response.body === null) {
|
|
1015
1271
|
return response;
|
|
1016
1272
|
}
|
|
1017
1273
|
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
if (
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
) {
|
|
1274
|
+
// Scoped to this one request/response cycle; never stored on a module map.
|
|
1275
|
+
const pendingRemoteJsonFetches = createRemoteJsonFetchScope();
|
|
1276
|
+
|
|
1277
|
+
if (readDistributedSsrFragmentRequest(request) === undefined) {
|
|
1278
|
+
const resolvedDistributedSsrFragmentCssHrefs =
|
|
1279
|
+
distributedSsrFragments?.getCurrentStylesheetHrefs() ??
|
|
1280
|
+
(await Promise.resolve(distributedSsrFragmentCssHrefs ?? []));
|
|
1026
1281
|
const headers = new Headers(response.headers);
|
|
1027
1282
|
const cssEntries = [
|
|
1028
1283
|
...collectRouteCssAssets(route, routeManifest).map(asset => {
|
|
@@ -1061,8 +1316,34 @@ async function withRouteCssLinks(
|
|
|
1061
1316
|
}
|
|
1062
1317
|
headers.delete('content-length');
|
|
1063
1318
|
|
|
1319
|
+
const seenExposes = new Set();
|
|
1320
|
+
const resolveRemoteCss = async attributes => {
|
|
1321
|
+
const boundaryId = attributes['data-modern-boundary-id'];
|
|
1322
|
+
const expose = attributes['data-modern-mf-expose'];
|
|
1323
|
+
if (!boundaryId || !expose) return [];
|
|
1324
|
+
const verifiedHrefs = distributedSsrFragments?.getCurrentStylesheetHrefs(
|
|
1325
|
+
boundaryId,
|
|
1326
|
+
expose,
|
|
1327
|
+
);
|
|
1328
|
+
if (verifiedHrefs !== undefined) return verifiedHrefs;
|
|
1329
|
+
const key = JSON.stringify([boundaryId, expose]);
|
|
1330
|
+
if (seenExposes.has(key)) return [];
|
|
1331
|
+
seenExposes.add(key);
|
|
1332
|
+
return collectRenderedRemoteCssHrefs(
|
|
1333
|
+
'',
|
|
1334
|
+
request,
|
|
1335
|
+
env,
|
|
1336
|
+
[{ boundaryId, expose }],
|
|
1337
|
+
pendingRemoteJsonFetches,
|
|
1338
|
+
);
|
|
1339
|
+
};
|
|
1064
1340
|
return new Response(
|
|
1065
|
-
createStylesheetLinkStream(
|
|
1341
|
+
createStylesheetLinkStream(
|
|
1342
|
+
response.body,
|
|
1343
|
+
uniqueCssEntries,
|
|
1344
|
+
request.url,
|
|
1345
|
+
resolveRemoteCss,
|
|
1346
|
+
),
|
|
1066
1347
|
{
|
|
1067
1348
|
headers,
|
|
1068
1349
|
status: response.status,
|
|
@@ -1071,12 +1352,18 @@ async function withRouteCssLinks(
|
|
|
1071
1352
|
);
|
|
1072
1353
|
}
|
|
1073
1354
|
|
|
1355
|
+
const resolvedDistributedSsrFragmentCssHrefs = await Promise.resolve(
|
|
1356
|
+
distributedSsrFragments?.getStylesheetHrefs() ??
|
|
1357
|
+
distributedSsrFragmentCssHrefs ??
|
|
1358
|
+
[],
|
|
1359
|
+
);
|
|
1074
1360
|
const html = dedupeStylesheetLinks(
|
|
1075
1361
|
await response.text(),
|
|
1076
1362
|
undefined,
|
|
1077
1363
|
request.url,
|
|
1078
1364
|
);
|
|
1079
1365
|
const headers = new Headers(response.headers);
|
|
1366
|
+
headers.delete('content-length');
|
|
1080
1367
|
const localFragmentCssAssets = collectLocalFragmentCssAssets(html, request);
|
|
1081
1368
|
const localFragmentProvenance = await createLocalFragmentProvenance(
|
|
1082
1369
|
html,
|
|
@@ -1108,7 +1395,13 @@ async function withRouteCssLinks(
|
|
|
1108
1395
|
}),
|
|
1109
1396
|
...(resolvedDistributedSsrFragmentCssHrefs.length > 0
|
|
1110
1397
|
? resolvedDistributedSsrFragmentCssHrefs
|
|
1111
|
-
: await collectRenderedRemoteCssHrefs(
|
|
1398
|
+
: await collectRenderedRemoteCssHrefs(
|
|
1399
|
+
html,
|
|
1400
|
+
request,
|
|
1401
|
+
env,
|
|
1402
|
+
undefined,
|
|
1403
|
+
pendingRemoteJsonFetches,
|
|
1404
|
+
)
|
|
1112
1405
|
).map(href => ({
|
|
1113
1406
|
href,
|
|
1114
1407
|
preloadHref: new URL(href, request.url).toString(),
|
|
@@ -1134,7 +1427,7 @@ async function withRouteCssLinks(
|
|
|
1134
1427
|
seenCssHrefs.add(entry.preloadHref);
|
|
1135
1428
|
return true;
|
|
1136
1429
|
});
|
|
1137
|
-
for (const {
|
|
1430
|
+
for (const { preloadHref } of uniqueCssEntries) {
|
|
1138
1431
|
const preloadUrl = new URL(preloadHref);
|
|
1139
1432
|
const preloadReference =
|
|
1140
1433
|
preloadUrl.origin === requestOrigin
|
|
@@ -1170,9 +1463,17 @@ async function withRouteCssLinks(
|
|
|
1170
1463
|
});
|
|
1171
1464
|
}
|
|
1172
1465
|
|
|
1173
|
-
async function getRequestHandlerOptions(
|
|
1466
|
+
async function getRequestHandlerOptions(
|
|
1467
|
+
route,
|
|
1468
|
+
request,
|
|
1469
|
+
env,
|
|
1470
|
+
executionContext,
|
|
1471
|
+
includeHtmlTemplate = true,
|
|
1472
|
+
) {
|
|
1174
1473
|
const [htmlTemplate, routeManifest, loadableStats] = await Promise.all([
|
|
1175
|
-
|
|
1474
|
+
includeHtmlTemplate
|
|
1475
|
+
? readAssetText(route.entryPath, request, env)
|
|
1476
|
+
: undefined,
|
|
1176
1477
|
readAssetJson(MODERN_WORKER_MANIFEST.resources.routeManifest, request, env),
|
|
1177
1478
|
readAssetJson(MODERN_WORKER_MANIFEST.resources.loadableStats, request, env),
|
|
1178
1479
|
]);
|
|
@@ -1183,12 +1484,18 @@ async function getRequestHandlerOptions(route, request, env) {
|
|
|
1183
1484
|
const distributedSsrFragmentRequest =
|
|
1184
1485
|
readDistributedSsrFragmentRequest(request);
|
|
1185
1486
|
|
|
1186
|
-
|
|
1487
|
+
const options = createRequestHandlerOptions({
|
|
1187
1488
|
route,
|
|
1188
1489
|
htmlTemplate: htmlTemplate || '',
|
|
1189
1490
|
routeManifest,
|
|
1190
1491
|
loadableStats,
|
|
1492
|
+
env,
|
|
1493
|
+
executionContext,
|
|
1191
1494
|
distributedSsrFragments,
|
|
1192
1495
|
distributedSsrFragmentRequest,
|
|
1193
1496
|
});
|
|
1497
|
+
if (!includeHtmlTemplate) {
|
|
1498
|
+
delete options.resource.htmlTemplate;
|
|
1499
|
+
}
|
|
1500
|
+
return options;
|
|
1194
1501
|
}
|