vinext 0.0.29 → 0.0.30

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 (128) hide show
  1. package/dist/check.d.ts.map +1 -1
  2. package/dist/check.js +11 -7
  3. package/dist/check.js.map +1 -1
  4. package/dist/cloudflare/kv-cache-handler.d.ts.map +1 -1
  5. package/dist/cloudflare/kv-cache-handler.js +44 -30
  6. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  7. package/dist/entries/app-rsc-entry.d.ts +1 -1
  8. package/dist/entries/app-rsc-entry.d.ts.map +1 -1
  9. package/dist/entries/app-rsc-entry.js +208 -164
  10. package/dist/entries/app-rsc-entry.js.map +1 -1
  11. package/dist/entries/pages-server-entry.d.ts.map +1 -1
  12. package/dist/entries/pages-server-entry.js +151 -100
  13. package/dist/entries/pages-server-entry.js.map +1 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +10 -2
  16. package/dist/index.js.map +1 -1
  17. package/dist/routing/app-router.d.ts.map +1 -1
  18. package/dist/routing/app-router.js +43 -29
  19. package/dist/routing/app-router.js.map +1 -1
  20. package/dist/server/app-router-entry.js +1 -1
  21. package/dist/server/app-router-entry.js.map +1 -1
  22. package/dist/server/dev-server.d.ts +2 -1
  23. package/dist/server/dev-server.d.ts.map +1 -1
  24. package/dist/server/dev-server.js +163 -163
  25. package/dist/server/dev-server.js.map +1 -1
  26. package/dist/server/image-optimization.d.ts.map +1 -1
  27. package/dist/server/image-optimization.js +23 -11
  28. package/dist/server/image-optimization.js.map +1 -1
  29. package/dist/server/isr-cache.d.ts.map +1 -1
  30. package/dist/server/isr-cache.js +8 -3
  31. package/dist/server/isr-cache.js.map +1 -1
  32. package/dist/server/metadata-routes.d.ts.map +1 -1
  33. package/dist/server/metadata-routes.js +56 -18
  34. package/dist/server/metadata-routes.js.map +1 -1
  35. package/dist/server/middleware-codegen.d.ts.map +1 -1
  36. package/dist/server/middleware-codegen.js +37 -4
  37. package/dist/server/middleware-codegen.js.map +1 -1
  38. package/dist/server/middleware.d.ts.map +1 -1
  39. package/dist/server/middleware.js +50 -6
  40. package/dist/server/middleware.js.map +1 -1
  41. package/dist/server/pages-i18n.d.ts +50 -0
  42. package/dist/server/pages-i18n.d.ts.map +1 -0
  43. package/dist/server/pages-i18n.js +152 -0
  44. package/dist/server/pages-i18n.js.map +1 -0
  45. package/dist/shims/cache-runtime.d.ts +3 -0
  46. package/dist/shims/cache-runtime.d.ts.map +1 -1
  47. package/dist/shims/cache-runtime.js +22 -5
  48. package/dist/shims/cache-runtime.js.map +1 -1
  49. package/dist/shims/cache.d.ts +3 -0
  50. package/dist/shims/cache.d.ts.map +1 -1
  51. package/dist/shims/cache.js +21 -12
  52. package/dist/shims/cache.js.map +1 -1
  53. package/dist/shims/constants.d.ts.map +1 -1
  54. package/dist/shims/constants.js +0 -1
  55. package/dist/shims/constants.js.map +1 -1
  56. package/dist/shims/fetch-cache.d.ts +14 -0
  57. package/dist/shims/fetch-cache.d.ts.map +1 -1
  58. package/dist/shims/fetch-cache.js +102 -37
  59. package/dist/shims/fetch-cache.js.map +1 -1
  60. package/dist/shims/head-state.d.ts +4 -0
  61. package/dist/shims/head-state.d.ts.map +1 -1
  62. package/dist/shims/head-state.js +14 -11
  63. package/dist/shims/head-state.js.map +1 -1
  64. package/dist/shims/head.d.ts +4 -2
  65. package/dist/shims/head.d.ts.map +1 -1
  66. package/dist/shims/head.js +162 -52
  67. package/dist/shims/head.js.map +1 -1
  68. package/dist/shims/headers.d.ts +8 -1
  69. package/dist/shims/headers.d.ts.map +1 -1
  70. package/dist/shims/headers.js +21 -29
  71. package/dist/shims/headers.js.map +1 -1
  72. package/dist/shims/i18n-context.d.ts +27 -0
  73. package/dist/shims/i18n-context.d.ts.map +1 -0
  74. package/dist/shims/i18n-context.js +57 -0
  75. package/dist/shims/i18n-context.js.map +1 -0
  76. package/dist/shims/i18n-state.d.ts +20 -0
  77. package/dist/shims/i18n-state.d.ts.map +1 -0
  78. package/dist/shims/i18n-state.js +53 -0
  79. package/dist/shims/i18n-state.js.map +1 -0
  80. package/dist/shims/image.d.ts +2 -0
  81. package/dist/shims/image.d.ts.map +1 -1
  82. package/dist/shims/image.js +14 -6
  83. package/dist/shims/image.js.map +1 -1
  84. package/dist/shims/internal/utils.d.ts +1 -0
  85. package/dist/shims/internal/utils.d.ts.map +1 -1
  86. package/dist/shims/internal/utils.js.map +1 -1
  87. package/dist/shims/link.d.ts.map +1 -1
  88. package/dist/shims/link.js +27 -11
  89. package/dist/shims/link.js.map +1 -1
  90. package/dist/shims/metadata.d.ts +22 -22
  91. package/dist/shims/metadata.d.ts.map +1 -1
  92. package/dist/shims/metadata.js +34 -32
  93. package/dist/shims/metadata.js.map +1 -1
  94. package/dist/shims/navigation-state.d.ts +14 -0
  95. package/dist/shims/navigation-state.d.ts.map +1 -1
  96. package/dist/shims/navigation-state.js +33 -15
  97. package/dist/shims/navigation-state.js.map +1 -1
  98. package/dist/shims/navigation.d.ts.map +1 -1
  99. package/dist/shims/navigation.js +39 -22
  100. package/dist/shims/navigation.js.map +1 -1
  101. package/dist/shims/request-context.d.ts.map +1 -1
  102. package/dist/shims/request-context.js +9 -0
  103. package/dist/shims/request-context.js.map +1 -1
  104. package/dist/shims/request-state-types.d.ts +11 -0
  105. package/dist/shims/request-state-types.d.ts.map +1 -0
  106. package/dist/shims/request-state-types.js +2 -0
  107. package/dist/shims/request-state-types.js.map +1 -0
  108. package/dist/shims/router-state.d.ts +11 -0
  109. package/dist/shims/router-state.d.ts.map +1 -1
  110. package/dist/shims/router-state.js +10 -8
  111. package/dist/shims/router-state.js.map +1 -1
  112. package/dist/shims/router.d.ts +4 -0
  113. package/dist/shims/router.d.ts.map +1 -1
  114. package/dist/shims/router.js +117 -21
  115. package/dist/shims/router.js.map +1 -1
  116. package/dist/shims/server.d.ts +8 -1
  117. package/dist/shims/server.d.ts.map +1 -1
  118. package/dist/shims/server.js +52 -6
  119. package/dist/shims/server.js.map +1 -1
  120. package/dist/shims/unified-request-context.d.ts +66 -0
  121. package/dist/shims/unified-request-context.d.ts.map +1 -0
  122. package/dist/shims/unified-request-context.js +116 -0
  123. package/dist/shims/unified-request-context.js.map +1 -0
  124. package/dist/utils/domain-locale.d.ts +18 -0
  125. package/dist/utils/domain-locale.d.ts.map +1 -0
  126. package/dist/utils/domain-locale.js +64 -0
  127. package/dist/utils/domain-locale.js.map +1 -0
  128. package/package.json +2 -2
@@ -4,23 +4,25 @@
4
4
  * In the Pages Router, <Head> manages document <head> elements.
5
5
  * - On the server: collects elements into a module-level array that the
6
6
  * dev-server reads after render and injects into the HTML <head>.
7
- * - On the client: uses useEffect + DOM manipulation.
7
+ * - On the client: reduces all mounted <Head> instances into one deduped
8
+ * document.head projection and applies it with DOM manipulation.
8
9
  */
9
- import { useEffect, Children, isValidElement } from "react";
10
+ import React, { useEffect, useRef, Children, isValidElement } from "react";
10
11
  // --- SSR head collection ---
11
12
  // State uses a registration pattern so this module can be bundled for the
12
13
  // browser. The ALS-backed implementation lives in head-state.ts (server-only).
13
- let _ssrHeadElements = [];
14
- let _getSSRHeadElements = () => _ssrHeadElements;
14
+ let _ssrHeadChildren = [];
15
+ const _clientHeadChildren = new Map();
16
+ let _getSSRHeadChildren = () => _ssrHeadChildren;
15
17
  let _resetSSRHeadImpl = () => {
16
- _ssrHeadElements = [];
18
+ _ssrHeadChildren = [];
17
19
  };
18
20
  /**
19
21
  * Register ALS-backed state accessors. Called by head-state.ts on import.
20
22
  * @internal
21
23
  */
22
24
  export function _registerHeadStateAccessors(accessors) {
23
- _getSSRHeadElements = accessors.getSSRHeadElements;
25
+ _getSSRHeadChildren = accessors.getSSRHeadChildren;
24
26
  _resetSSRHeadImpl = accessors.resetSSRHead;
25
27
  }
26
28
  /** Reset the SSR head collector. Call before render. */
@@ -29,13 +31,126 @@ export function resetSSRHead() {
29
31
  }
30
32
  /** Get collected head HTML. Call after render. */
31
33
  export function getSSRHeadHTML() {
32
- return _getSSRHeadElements().join("\n ");
34
+ return reduceHeadChildren(_getSSRHeadChildren())
35
+ .map(reactElementToHTML)
36
+ .filter(Boolean)
37
+ .join("\n ");
33
38
  }
34
39
  /**
35
40
  * Tags allowed inside <head>. Anything else is silently dropped.
36
41
  * This prevents injection of dangerous elements like <iframe>, <object>, etc.
37
42
  */
38
43
  const ALLOWED_HEAD_TAGS = new Set(["title", "meta", "link", "style", "script", "base", "noscript"]);
44
+ const META_TYPES = ["name", "httpEquiv", "charSet", "itemProp"];
45
+ function warnDisallowedHeadTag(tag) {
46
+ if (process.env.NODE_ENV !== "production") {
47
+ console.warn(`[vinext] <Head> ignoring disallowed tag <${tag}>. ` +
48
+ `Only ${[...ALLOWED_HEAD_TAGS].join(", ")} are allowed.`);
49
+ }
50
+ }
51
+ function collectHeadElements(list, child) {
52
+ if (child == null ||
53
+ typeof child === "boolean" ||
54
+ typeof child === "string" ||
55
+ typeof child === "number") {
56
+ return list;
57
+ }
58
+ if (!isValidElement(child)) {
59
+ return list;
60
+ }
61
+ if (child.type === React.Fragment) {
62
+ return Children.toArray(child.props.children).reduce(collectHeadElements, list);
63
+ }
64
+ if (typeof child.type !== "string") {
65
+ return list;
66
+ }
67
+ if (!ALLOWED_HEAD_TAGS.has(child.type)) {
68
+ warnDisallowedHeadTag(child.type);
69
+ return list;
70
+ }
71
+ return list.concat(child);
72
+ }
73
+ function normalizeHeadKey(key) {
74
+ if (key == null || typeof key === "number")
75
+ return null;
76
+ const normalizedKey = String(key);
77
+ const separatorIndex = normalizedKey.indexOf("$");
78
+ return separatorIndex > 0 ? normalizedKey.slice(separatorIndex + 1) : null;
79
+ }
80
+ function createUniqueHeadFilter() {
81
+ const keys = new Set();
82
+ const tags = new Set();
83
+ const metaTypes = new Set();
84
+ const metaCategories = new Map();
85
+ return (child) => {
86
+ let isUnique = true;
87
+ const normalizedKey = normalizeHeadKey(child.key);
88
+ const hasKey = normalizedKey !== null;
89
+ if (normalizedKey) {
90
+ if (keys.has(normalizedKey)) {
91
+ isUnique = false;
92
+ }
93
+ else {
94
+ keys.add(normalizedKey);
95
+ }
96
+ }
97
+ switch (child.type) {
98
+ case "title":
99
+ case "base":
100
+ if (tags.has(child.type)) {
101
+ isUnique = false;
102
+ }
103
+ else {
104
+ tags.add(child.type);
105
+ }
106
+ break;
107
+ case "meta": {
108
+ const props = child.props;
109
+ for (const metaType of META_TYPES) {
110
+ if (!Object.prototype.hasOwnProperty.call(props, metaType))
111
+ continue;
112
+ if (metaType === "charSet") {
113
+ if (metaTypes.has(metaType)) {
114
+ isUnique = false;
115
+ }
116
+ else {
117
+ metaTypes.add(metaType);
118
+ }
119
+ continue;
120
+ }
121
+ const category = props[metaType];
122
+ if (typeof category !== "string")
123
+ continue;
124
+ let categories = metaCategories.get(metaType);
125
+ if (!categories) {
126
+ categories = new Set();
127
+ metaCategories.set(metaType, categories);
128
+ }
129
+ if ((metaType !== "name" || !hasKey) && categories.has(category)) {
130
+ isUnique = false;
131
+ }
132
+ else {
133
+ categories.add(category);
134
+ }
135
+ }
136
+ break;
137
+ }
138
+ default:
139
+ break;
140
+ }
141
+ return isUnique;
142
+ };
143
+ }
144
+ export function reduceHeadChildren(headChildren) {
145
+ return headChildren
146
+ .reduce((flattenedChildren, child) => {
147
+ return flattenedChildren.concat(Children.toArray(child));
148
+ }, [])
149
+ .reduce(collectHeadElements, [])
150
+ .reverse()
151
+ .filter(createUniqueHeadFilter())
152
+ .reverse();
153
+ }
39
154
  /**
40
155
  * Convert a React element to an HTML string for SSR head injection.
41
156
  * Returns an empty string for disallowed tag types.
@@ -43,10 +158,7 @@ const ALLOWED_HEAD_TAGS = new Set(["title", "meta", "link", "style", "script", "
43
158
  function reactElementToHTML(child) {
44
159
  const tag = child.type;
45
160
  if (!ALLOWED_HEAD_TAGS.has(tag)) {
46
- if (process.env.NODE_ENV !== "production") {
47
- console.warn(`[vinext] <Head> ignoring disallowed tag <${tag}>. ` +
48
- `Only ${[...ALLOWED_HEAD_TAGS].join(", ")} are allowed.`);
49
- }
161
+ warnDisallowedHeadTag(tag);
50
162
  return "";
51
163
  }
52
164
  const props = child.props;
@@ -116,56 +228,54 @@ export function escapeInlineContent(content, tag) {
116
228
  const pattern = new RegExp(`<\\/(${tag})`, "gi");
117
229
  return content.replace(pattern, "<\\/$1");
118
230
  }
231
+ function syncClientHead() {
232
+ document.querySelectorAll("[data-vinext-head]").forEach((el) => el.remove());
233
+ for (const child of reduceHeadChildren([..._clientHeadChildren.values()])) {
234
+ if (typeof child.type !== "string")
235
+ continue;
236
+ const domEl = document.createElement(child.type);
237
+ const props = child.props;
238
+ for (const [key, value] of Object.entries(props)) {
239
+ if (key === "children" && typeof value === "string") {
240
+ domEl.textContent = value;
241
+ }
242
+ else if (key === "dangerouslySetInnerHTML") {
243
+ // skip for safety
244
+ }
245
+ else if (key === "className") {
246
+ domEl.setAttribute("class", String(value));
247
+ }
248
+ else if (typeof value === "boolean" && value) {
249
+ domEl.setAttribute(key, "");
250
+ }
251
+ else if (key !== "children" && typeof value === "string") {
252
+ domEl.setAttribute(key, value);
253
+ }
254
+ }
255
+ domEl.setAttribute("data-vinext-head", "true");
256
+ document.head.appendChild(domEl);
257
+ }
258
+ }
119
259
  // --- Component ---
120
260
  function Head({ children }) {
261
+ const headInstanceIdRef = useRef(null);
262
+ if (headInstanceIdRef.current === null) {
263
+ headInstanceIdRef.current = Symbol("vinext-head");
264
+ }
121
265
  // SSR path: collect elements for later injection
122
266
  if (typeof window === "undefined") {
123
- Children.forEach(children, (child) => {
124
- if (!isValidElement(child))
125
- return;
126
- if (typeof child.type !== "string")
127
- return;
128
- const html = reactElementToHTML(child);
129
- if (html)
130
- _getSSRHeadElements().push(html);
131
- });
267
+ _getSSRHeadChildren().push(children);
132
268
  return null;
133
269
  }
134
- // Client path: useEffect DOM manipulation (runs after hydration)
270
+ // Client path: update the shared head projection after hydration.
135
271
  // eslint-disable-next-line react-hooks/rules-of-hooks
136
272
  useEffect(() => {
137
- const elements = [];
138
- // Remove previous vinext-managed head elements
139
- document.querySelectorAll("[data-vinext-head]").forEach((el) => el.remove());
140
- Children.forEach(children, (child) => {
141
- if (!isValidElement(child))
142
- return;
143
- if (typeof child.type !== "string")
144
- return;
145
- if (!ALLOWED_HEAD_TAGS.has(child.type))
146
- return;
147
- const domEl = document.createElement(child.type);
148
- const props = child.props;
149
- for (const [key, value] of Object.entries(props)) {
150
- if (key === "children" && typeof value === "string") {
151
- domEl.textContent = value;
152
- }
153
- else if (key === "dangerouslySetInnerHTML") {
154
- // skip for safety
155
- }
156
- else if (key === "className") {
157
- domEl.setAttribute("class", String(value));
158
- }
159
- else if (key !== "children" && typeof value === "string") {
160
- domEl.setAttribute(key, value);
161
- }
162
- }
163
- domEl.setAttribute("data-vinext-head", "true");
164
- document.head.appendChild(domEl);
165
- elements.push(domEl);
166
- });
273
+ const instanceId = headInstanceIdRef.current;
274
+ _clientHeadChildren.set(instanceId, children);
275
+ syncClientHead();
167
276
  return () => {
168
- elements.forEach((el) => el.remove());
277
+ _clientHeadChildren.delete(instanceId);
278
+ syncClientHead();
169
279
  };
170
280
  }, [children]);
171
281
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"head.js","sourceRoot":"","sources":["../../src/shims/head.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * next/head shim\n *\n * In the Pages Router, <Head> manages document <head> elements.\n * - On the server: collects elements into a module-level array that the\n * dev-server reads after render and injects into the HTML <head>.\n * - On the client: uses useEffect + DOM manipulation.\n */\nimport React, { useEffect, Children, isValidElement } from \"react\";\n\ninterface HeadProps {\n children?: React.ReactNode;\n}\n\n// --- SSR head collection ---\n// State uses a registration pattern so this module can be bundled for the\n// browser. The ALS-backed implementation lives in head-state.ts (server-only).\n\nlet _ssrHeadElements: string[] = [];\n\nlet _getSSRHeadElements = (): string[] => _ssrHeadElements;\nlet _resetSSRHeadImpl = (): void => {\n _ssrHeadElements = [];\n};\n\n/**\n * Register ALS-backed state accessors. Called by head-state.ts on import.\n * @internal\n */\nexport function _registerHeadStateAccessors(accessors: {\n getSSRHeadElements: () => string[];\n resetSSRHead: () => void;\n}): void {\n _getSSRHeadElements = accessors.getSSRHeadElements;\n _resetSSRHeadImpl = accessors.resetSSRHead;\n}\n\n/** Reset the SSR head collector. Call before render. */\nexport function resetSSRHead(): void {\n _resetSSRHeadImpl();\n}\n\n/** Get collected head HTML. Call after render. */\nexport function getSSRHeadHTML(): string {\n return _getSSRHeadElements().join(\"\\n \");\n}\n\n/**\n * Tags allowed inside <head>. Anything else is silently dropped.\n * This prevents injection of dangerous elements like <iframe>, <object>, etc.\n */\nconst ALLOWED_HEAD_TAGS = new Set([\"title\", \"meta\", \"link\", \"style\", \"script\", \"base\", \"noscript\"]);\n\n/**\n * Convert a React element to an HTML string for SSR head injection.\n * Returns an empty string for disallowed tag types.\n */\nfunction reactElementToHTML(child: React.ReactElement): string {\n const tag = child.type as string;\n\n if (!ALLOWED_HEAD_TAGS.has(tag)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `[vinext] <Head> ignoring disallowed tag <${tag}>. ` +\n `Only ${[...ALLOWED_HEAD_TAGS].join(\", \")} are allowed.`,\n );\n }\n return \"\";\n }\n\n const props = child.props as Record<string, unknown>;\n const attrs: string[] = [];\n let innerHTML = \"\";\n\n for (const [key, value] of Object.entries(props)) {\n if (key === \"children\") {\n if (typeof value === \"string\") {\n innerHTML = escapeHTML(value);\n }\n } else if (key === \"dangerouslySetInnerHTML\") {\n // Intentionally raw — developer explicitly opted in.\n // SECURITY NOTE: This injects raw HTML during SSR. The client-side\n // path (line ~148) skips dangerouslySetInnerHTML for safety. Developers\n // must never pass unsanitized user input here — it is a stored XSS vector.\n const html = value as { __html: string };\n if (html?.__html) innerHTML = html.__html;\n } else if (key === \"className\") {\n attrs.push(`class=\"${escapeAttr(String(value))}\"`);\n } else if (typeof value === \"string\") {\n attrs.push(`${key}=\"${escapeAttr(value)}\"`);\n } else if (typeof value === \"boolean\" && value) {\n attrs.push(key);\n }\n }\n\n const attrStr = attrs.length ? \" \" + attrs.join(\" \") : \"\";\n\n // Self-closing tags\n const selfClosing = [\"meta\", \"link\", \"base\"];\n if (selfClosing.includes(tag)) {\n return `<${tag}${attrStr} data-vinext-head=\"true\" />`;\n }\n\n // For raw-content tags (script, style), escape closing-tag sequences so the\n // HTML parser doesn't prematurely terminate the element.\n const rawContentTags = [\"script\", \"style\"];\n if (rawContentTags.includes(tag) && innerHTML) {\n innerHTML = escapeInlineContent(innerHTML, tag);\n }\n\n return `<${tag}${attrStr} data-vinext-head=\"true\">${innerHTML}</${tag}>`;\n}\n\nfunction escapeHTML(s: string): string {\n return s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n\nexport function escapeAttr(s: string): string {\n return s\n .replace(/&/g, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n\n/**\n * Escape content that will be placed inside a raw <script> or <style> tag\n * during SSR. The HTML parser treats `</script>` (or `</style>`) as the end\n * of the block regardless of JavaScript string context, so any occurrence\n * of `</` followed by the tag name must be escaped.\n *\n * We replace `</script` and `</style` (case-insensitive) with `<\\/script`\n * and `<\\/style` respectively. The `<\\/` form is harmless in JS/CSS string\n * context but prevents the HTML parser from seeing a closing tag.\n */\nexport function escapeInlineContent(content: string, tag: string): string {\n // Build a pattern like `<\\/script` or `<\\/style`, case-insensitive\n const pattern = new RegExp(`<\\\\/(${tag})`, \"gi\");\n return content.replace(pattern, \"<\\\\/$1\");\n}\n\n// --- Component ---\n\nfunction Head({ children }: HeadProps): null {\n // SSR path: collect elements for later injection\n if (typeof window === \"undefined\") {\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) return;\n if (typeof child.type !== \"string\") return;\n const html = reactElementToHTML(child);\n if (html) _getSSRHeadElements().push(html);\n });\n return null;\n }\n\n // Client path: useEffect DOM manipulation (runs after hydration)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useEffect(() => {\n const elements: Element[] = [];\n\n // Remove previous vinext-managed head elements\n document.querySelectorAll(\"[data-vinext-head]\").forEach((el) => el.remove());\n\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) return;\n if (typeof child.type !== \"string\") return;\n if (!ALLOWED_HEAD_TAGS.has(child.type)) return;\n\n const domEl = document.createElement(child.type);\n const props = child.props as Record<string, unknown>;\n\n for (const [key, value] of Object.entries(props)) {\n if (key === \"children\" && typeof value === \"string\") {\n domEl.textContent = value;\n } else if (key === \"dangerouslySetInnerHTML\") {\n // skip for safety\n } else if (key === \"className\") {\n domEl.setAttribute(\"class\", String(value));\n } else if (key !== \"children\" && typeof value === \"string\") {\n domEl.setAttribute(key, value);\n }\n }\n\n domEl.setAttribute(\"data-vinext-head\", \"true\");\n document.head.appendChild(domEl);\n elements.push(domEl);\n });\n\n return () => {\n elements.forEach((el) => el.remove());\n };\n }, [children]);\n\n return null;\n}\n\nexport default Head;\n"]}
1
+ {"version":3,"file":"head.js","sourceRoot":"","sources":["../../src/shims/head.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * next/head shim\n *\n * In the Pages Router, <Head> manages document <head> elements.\n * - On the server: collects elements into a module-level array that the\n * dev-server reads after render and injects into the HTML <head>.\n * - On the client: reduces all mounted <Head> instances into one deduped\n * document.head projection and applies it with DOM manipulation.\n */\nimport React, { useEffect, useRef, Children, isValidElement } from \"react\";\n\ninterface HeadProps {\n children?: React.ReactNode;\n}\n\n// --- SSR head collection ---\n// State uses a registration pattern so this module can be bundled for the\n// browser. The ALS-backed implementation lives in head-state.ts (server-only).\n\nlet _ssrHeadChildren: React.ReactNode[] = [];\nconst _clientHeadChildren = new Map<symbol, React.ReactNode>();\n\nlet _getSSRHeadChildren = (): React.ReactNode[] => _ssrHeadChildren;\nlet _resetSSRHeadImpl = (): void => {\n _ssrHeadChildren = [];\n};\n\n/**\n * Register ALS-backed state accessors. Called by head-state.ts on import.\n * @internal\n */\nexport function _registerHeadStateAccessors(accessors: {\n getSSRHeadChildren: () => React.ReactNode[];\n resetSSRHead: () => void;\n}): void {\n _getSSRHeadChildren = accessors.getSSRHeadChildren;\n _resetSSRHeadImpl = accessors.resetSSRHead;\n}\n\n/** Reset the SSR head collector. Call before render. */\nexport function resetSSRHead(): void {\n _resetSSRHeadImpl();\n}\n\n/** Get collected head HTML. Call after render. */\nexport function getSSRHeadHTML(): string {\n return reduceHeadChildren(_getSSRHeadChildren())\n .map(reactElementToHTML)\n .filter(Boolean)\n .join(\"\\n \");\n}\n\n/**\n * Tags allowed inside <head>. Anything else is silently dropped.\n * This prevents injection of dangerous elements like <iframe>, <object>, etc.\n */\nconst ALLOWED_HEAD_TAGS = new Set([\"title\", \"meta\", \"link\", \"style\", \"script\", \"base\", \"noscript\"]);\nconst META_TYPES = [\"name\", \"httpEquiv\", \"charSet\", \"itemProp\"] as const;\n\nfunction warnDisallowedHeadTag(tag: string): void {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `[vinext] <Head> ignoring disallowed tag <${tag}>. ` +\n `Only ${[...ALLOWED_HEAD_TAGS].join(\", \")} are allowed.`,\n );\n }\n}\n\nfunction collectHeadElements(\n list: React.ReactElement[],\n child: React.ReactNode,\n): React.ReactElement[] {\n if (\n child == null ||\n typeof child === \"boolean\" ||\n typeof child === \"string\" ||\n typeof child === \"number\"\n ) {\n return list;\n }\n if (!isValidElement(child)) {\n return list;\n }\n if (child.type === React.Fragment) {\n return Children.toArray((child.props as { children?: React.ReactNode }).children).reduce(\n collectHeadElements,\n list,\n );\n }\n if (typeof child.type !== \"string\") {\n return list;\n }\n if (!ALLOWED_HEAD_TAGS.has(child.type)) {\n warnDisallowedHeadTag(child.type);\n return list;\n }\n return list.concat(child);\n}\n\nfunction normalizeHeadKey(key: React.Key | null): string | null {\n if (key == null || typeof key === \"number\") return null;\n const normalizedKey = String(key);\n const separatorIndex = normalizedKey.indexOf(\"$\");\n return separatorIndex > 0 ? normalizedKey.slice(separatorIndex + 1) : null;\n}\n\nfunction createUniqueHeadFilter(): (child: React.ReactElement) => boolean {\n const keys = new Set<string>();\n const tags = new Set<string>();\n const metaTypes = new Set<string>();\n const metaCategories = new Map<string, Set<string>>();\n\n return (child) => {\n let isUnique = true;\n const normalizedKey = normalizeHeadKey(child.key);\n const hasKey = normalizedKey !== null;\n if (normalizedKey) {\n if (keys.has(normalizedKey)) {\n isUnique = false;\n } else {\n keys.add(normalizedKey);\n }\n }\n\n switch (child.type) {\n case \"title\":\n case \"base\":\n if (tags.has(child.type)) {\n isUnique = false;\n } else {\n tags.add(child.type);\n }\n break;\n case \"meta\": {\n const props = child.props as Record<string, unknown>;\n for (const metaType of META_TYPES) {\n if (!Object.prototype.hasOwnProperty.call(props, metaType)) continue;\n if (metaType === \"charSet\") {\n if (metaTypes.has(metaType)) {\n isUnique = false;\n } else {\n metaTypes.add(metaType);\n }\n continue;\n }\n\n const category = props[metaType];\n if (typeof category !== \"string\") continue;\n\n let categories = metaCategories.get(metaType);\n if (!categories) {\n categories = new Set<string>();\n metaCategories.set(metaType, categories);\n }\n\n if ((metaType !== \"name\" || !hasKey) && categories.has(category)) {\n isUnique = false;\n } else {\n categories.add(category);\n }\n }\n break;\n }\n default:\n break;\n }\n\n return isUnique;\n };\n}\n\nexport function reduceHeadChildren(headChildren: React.ReactNode[]): React.ReactElement[] {\n return headChildren\n .reduce<React.ReactNode[]>((flattenedChildren, child) => {\n return flattenedChildren.concat(Children.toArray(child));\n }, [])\n .reduce(collectHeadElements, [])\n .reverse()\n .filter(createUniqueHeadFilter())\n .reverse();\n}\n\n/**\n * Convert a React element to an HTML string for SSR head injection.\n * Returns an empty string for disallowed tag types.\n */\nfunction reactElementToHTML(child: React.ReactElement): string {\n const tag = child.type as string;\n\n if (!ALLOWED_HEAD_TAGS.has(tag)) {\n warnDisallowedHeadTag(tag);\n return \"\";\n }\n\n const props = child.props as Record<string, unknown>;\n const attrs: string[] = [];\n let innerHTML = \"\";\n\n for (const [key, value] of Object.entries(props)) {\n if (key === \"children\") {\n if (typeof value === \"string\") {\n innerHTML = escapeHTML(value);\n }\n } else if (key === \"dangerouslySetInnerHTML\") {\n // Intentionally raw — developer explicitly opted in.\n // SECURITY NOTE: This injects raw HTML during SSR. The client-side\n // path (line ~148) skips dangerouslySetInnerHTML for safety. Developers\n // must never pass unsanitized user input here — it is a stored XSS vector.\n const html = value as { __html: string };\n if (html?.__html) innerHTML = html.__html;\n } else if (key === \"className\") {\n attrs.push(`class=\"${escapeAttr(String(value))}\"`);\n } else if (typeof value === \"string\") {\n attrs.push(`${key}=\"${escapeAttr(value)}\"`);\n } else if (typeof value === \"boolean\" && value) {\n attrs.push(key);\n }\n }\n\n const attrStr = attrs.length ? \" \" + attrs.join(\" \") : \"\";\n\n // Self-closing tags\n const selfClosing = [\"meta\", \"link\", \"base\"];\n if (selfClosing.includes(tag)) {\n return `<${tag}${attrStr} data-vinext-head=\"true\" />`;\n }\n\n // For raw-content tags (script, style), escape closing-tag sequences so the\n // HTML parser doesn't prematurely terminate the element.\n const rawContentTags = [\"script\", \"style\"];\n if (rawContentTags.includes(tag) && innerHTML) {\n innerHTML = escapeInlineContent(innerHTML, tag);\n }\n\n return `<${tag}${attrStr} data-vinext-head=\"true\">${innerHTML}</${tag}>`;\n}\n\nfunction escapeHTML(s: string): string {\n return s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n\nexport function escapeAttr(s: string): string {\n return s\n .replace(/&/g, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n\n/**\n * Escape content that will be placed inside a raw <script> or <style> tag\n * during SSR. The HTML parser treats `</script>` (or `</style>`) as the end\n * of the block regardless of JavaScript string context, so any occurrence\n * of `</` followed by the tag name must be escaped.\n *\n * We replace `</script` and `</style` (case-insensitive) with `<\\/script`\n * and `<\\/style` respectively. The `<\\/` form is harmless in JS/CSS string\n * context but prevents the HTML parser from seeing a closing tag.\n */\nexport function escapeInlineContent(content: string, tag: string): string {\n // Build a pattern like `<\\/script` or `<\\/style`, case-insensitive\n const pattern = new RegExp(`<\\\\/(${tag})`, \"gi\");\n return content.replace(pattern, \"<\\\\/$1\");\n}\n\nfunction syncClientHead(): void {\n document.querySelectorAll(\"[data-vinext-head]\").forEach((el) => el.remove());\n\n for (const child of reduceHeadChildren([..._clientHeadChildren.values()])) {\n if (typeof child.type !== \"string\") continue;\n\n const domEl = document.createElement(child.type);\n const props = child.props as Record<string, unknown>;\n\n for (const [key, value] of Object.entries(props)) {\n if (key === \"children\" && typeof value === \"string\") {\n domEl.textContent = value;\n } else if (key === \"dangerouslySetInnerHTML\") {\n // skip for safety\n } else if (key === \"className\") {\n domEl.setAttribute(\"class\", String(value));\n } else if (typeof value === \"boolean\" && value) {\n domEl.setAttribute(key, \"\");\n } else if (key !== \"children\" && typeof value === \"string\") {\n domEl.setAttribute(key, value);\n }\n }\n\n domEl.setAttribute(\"data-vinext-head\", \"true\");\n document.head.appendChild(domEl);\n }\n}\n\n// --- Component ---\n\nfunction Head({ children }: HeadProps): null {\n const headInstanceIdRef = useRef<symbol | null>(null);\n if (headInstanceIdRef.current === null) {\n headInstanceIdRef.current = Symbol(\"vinext-head\");\n }\n\n // SSR path: collect elements for later injection\n if (typeof window === \"undefined\") {\n _getSSRHeadChildren().push(children);\n return null;\n }\n\n // Client path: update the shared head projection after hydration.\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useEffect(() => {\n const instanceId = headInstanceIdRef.current!;\n _clientHeadChildren.set(instanceId, children);\n syncClientHead();\n\n return () => {\n _clientHeadChildren.delete(instanceId);\n syncClientHead();\n };\n }, [children]);\n\n return null;\n}\n\nexport default Head;\n"]}
@@ -7,7 +7,7 @@
7
7
  * In Next.js 15+, cookies() and headers() return Promises (async).
8
8
  * We support both the sync (legacy) and async patterns.
9
9
  */
10
- interface HeadersContext {
10
+ export interface HeadersContext {
11
11
  headers: Headers;
12
12
  cookies: Map<string, string>;
13
13
  accessError?: Error;
@@ -16,6 +16,13 @@ interface HeadersContext {
16
16
  readonlyHeaders?: Headers;
17
17
  }
18
18
  export type HeadersAccessPhase = "render" | "action" | "route-handler";
19
+ export type VinextHeadersShimState = {
20
+ headersContext: HeadersContext | null;
21
+ dynamicUsageDetected: boolean;
22
+ pendingSetCookies: string[];
23
+ draftModeCookieHeader: string | null;
24
+ phase: HeadersAccessPhase;
25
+ };
19
26
  /**
20
27
  * Dynamic usage flag — set when a component calls connection(), cookies(),
21
28
  * headers(), or noStore() during rendering. When true, ISR caching is
@@ -1 +1 @@
1
- {"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/shims/headers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/shims/headers.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@
10
10
  import { AsyncLocalStorage } from "node:async_hooks";
11
11
  import { buildRequestHeadersFromMiddlewareResponse } from "../server/middleware-request-headers.js";
12
12
  import { parseCookieHeader } from "./internal/parse-cookie-header.js";
13
+ import { isInsideUnifiedScope, getRequestContext, runWithUnifiedStateMutation, } from "./unified-request-context.js";
13
14
  // NOTE:
14
15
  // - This shim can be loaded under multiple module specifiers in Vite's
15
16
  // multi-environment setup (RSC/SSR). Store the AsyncLocalStorage on
@@ -30,8 +31,10 @@ const _fallbackState = (_g[_FALLBACK_KEY] ??= {
30
31
  phase: "render",
31
32
  });
32
33
  function _getState() {
33
- const state = _als.getStore();
34
- return state ?? _fallbackState;
34
+ if (isInsideUnifiedScope()) {
35
+ return getRequestContext();
36
+ }
37
+ return _als.getStore() ?? _fallbackState;
35
38
  }
36
39
  /**
37
40
  * Dynamic usage flag — set when a component calls connection(), cookies(),
@@ -124,37 +127,17 @@ export function getHeadersContext() {
124
127
  return _getState().headersContext;
125
128
  }
126
129
  export function setHeadersContext(ctx) {
130
+ const state = _getState();
127
131
  if (ctx !== null) {
128
- // For backward compatibility, set context on the current ALS store
129
- // if one exists, otherwise update the fallback. Callers should
130
- // migrate to runWithHeadersContext() for new-request setup.
131
- const existing = _als.getStore();
132
- if (existing) {
133
- existing.headersContext = ctx;
134
- existing.dynamicUsageDetected = false;
135
- existing.pendingSetCookies = [];
136
- existing.draftModeCookieHeader = null;
137
- existing.phase = "render";
138
- }
139
- else {
140
- _fallbackState.headersContext = ctx;
141
- _fallbackState.dynamicUsageDetected = false;
142
- _fallbackState.pendingSetCookies = [];
143
- _fallbackState.draftModeCookieHeader = null;
144
- _fallbackState.phase = "render";
145
- }
146
- return;
147
- }
148
- // End of request cleanup: keep the store (so consumeDynamicUsage and
149
- // cookie flushing can still run), but clear the request headers/cookies.
150
- const state = _als.getStore();
151
- if (state) {
152
- state.headersContext = null;
132
+ state.headersContext = ctx;
133
+ state.dynamicUsageDetected = false;
134
+ state.pendingSetCookies = [];
135
+ state.draftModeCookieHeader = null;
153
136
  state.phase = "render";
154
137
  }
155
138
  else {
156
- _fallbackState.headersContext = null;
157
- _fallbackState.phase = "render";
139
+ state.headersContext = null;
140
+ state.phase = "render";
158
141
  }
159
142
  }
160
143
  /**
@@ -168,6 +151,15 @@ export function setHeadersContext(ctx) {
168
151
  * stream is consumed still see the correct request's context.
169
152
  */
170
153
  export function runWithHeadersContext(ctx, fn) {
154
+ if (isInsideUnifiedScope()) {
155
+ return runWithUnifiedStateMutation((uCtx) => {
156
+ uCtx.headersContext = ctx;
157
+ uCtx.dynamicUsageDetected = false;
158
+ uCtx.pendingSetCookies = [];
159
+ uCtx.draftModeCookieHeader = null;
160
+ uCtx.phase = "render";
161
+ }, fn);
162
+ }
171
163
  const state = {
172
164
  headersContext: ctx,
173
165
  dynamicUsageDetected: false,