@kasperpeulen/vitest-plugin-nextjs 0.0.0-alpha.0 → 0.1.0-alpha.0

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 (250) hide show
  1. package/README.md +249 -2
  2. package/dist/_virtual/_rolldown/runtime.js +14 -0
  3. package/dist/action-ids.d.ts +18 -0
  4. package/dist/action-ids.js +44 -0
  5. package/dist/adapter.d.ts +8 -0
  6. package/dist/adapter.js +12 -0
  7. package/dist/app-requests.d.ts +63 -0
  8. package/dist/app-requests.js +253 -0
  9. package/dist/browser-context.d.ts +24 -0
  10. package/dist/browser-context.js +157 -0
  11. package/dist/build-output.d.ts +68 -0
  12. package/dist/build-output.js +216 -0
  13. package/dist/build.d.ts +26 -0
  14. package/dist/build.js +39 -0
  15. package/dist/built-files.d.ts +9 -0
  16. package/dist/built-files.js +22 -0
  17. package/dist/cache.d.ts +44 -0
  18. package/dist/cache.js +99 -0
  19. package/dist/client-components.d.ts +3 -0
  20. package/dist/client-components.js +4 -0
  21. package/dist/client-file-key.d.ts +5 -0
  22. package/dist/client-file-key.js +5 -0
  23. package/dist/client-files.d.ts +83 -0
  24. package/dist/client-files.js +186 -0
  25. package/dist/client-graph.d.ts +94 -0
  26. package/dist/client-graph.js +266 -0
  27. package/dist/client-modules.d.ts +10 -0
  28. package/dist/client-modules.js +43 -0
  29. package/dist/client.d.ts +42 -0
  30. package/dist/client.js +263 -0
  31. package/dist/commonjs.d.ts +44 -0
  32. package/dist/commonjs.js +111 -0
  33. package/dist/compat/browser/client.d.ts +19 -0
  34. package/dist/compat/browser/client.js +13 -0
  35. package/dist/compat/build.d.ts +145 -0
  36. package/dist/compat/build.js +149 -0
  37. package/dist/compat/checks.d.ts +16 -0
  38. package/dist/compat/checks.js +148 -0
  39. package/dist/compat/patches.d.ts +13 -0
  40. package/dist/compat/patches.js +30 -0
  41. package/dist/compat/paths.d.ts +74 -0
  42. package/dist/compat/paths.js +160 -0
  43. package/dist/compat/rsc/handlers.d.ts +2 -0
  44. package/dist/compat/rsc/handlers.js +2 -0
  45. package/dist/compat/rsc/prerender.d.ts +10 -0
  46. package/dist/compat/rsc/prerender.js +9 -0
  47. package/dist/compat/server/headers.d.ts +3 -0
  48. package/dist/compat/server/headers.js +3 -0
  49. package/dist/compat/ssr/build-output.d.ts +4 -0
  50. package/dist/compat/ssr/build-output.js +3 -0
  51. package/dist/compat/ssr/cache.d.ts +6 -0
  52. package/dist/compat/ssr/cache.js +6 -0
  53. package/dist/compat/ssr/handler.d.ts +8 -0
  54. package/dist/compat/ssr/handler.js +8 -0
  55. package/dist/compat/ssr/node-server.d.ts +5 -0
  56. package/dist/compat/ssr/node-server.js +4 -0
  57. package/dist/compat/ssr/render-errors.d.ts +4 -0
  58. package/dist/compat/ssr/render-errors.js +4 -0
  59. package/dist/compat/ssr/senders.d.ts +6 -0
  60. package/dist/compat/ssr/senders.js +6 -0
  61. package/dist/compat/types.d.ts +8 -0
  62. package/dist/compat/types.js +1 -0
  63. package/dist/compile.d.ts +31 -0
  64. package/dist/compile.js +140 -0
  65. package/dist/disk.d.ts +16 -0
  66. package/dist/disk.js +13 -0
  67. package/dist/document-loads.d.ts +15 -0
  68. package/dist/document-loads.js +53 -0
  69. package/dist/document.d.ts +79 -0
  70. package/dist/document.js +328 -0
  71. package/dist/downloads.d.ts +15 -0
  72. package/dist/downloads.js +71 -0
  73. package/dist/esm-require.d.ts +11 -0
  74. package/dist/esm-require.js +32 -0
  75. package/dist/fast-crypto/index.js +1093 -0
  76. package/dist/fast-crypto.d.ts +20 -0
  77. package/dist/fast-crypto.js +151 -0
  78. package/dist/flight.d.ts +19 -0
  79. package/dist/flight.js +42 -0
  80. package/dist/form-submission.d.ts +15 -0
  81. package/dist/form-submission.js +27 -0
  82. package/dist/from-page.d.ts +5 -0
  83. package/dist/from-page.js +44 -0
  84. package/dist/globals.d.ts +1 -0
  85. package/dist/globals.js +197 -0
  86. package/dist/host-document.d.ts +26 -0
  87. package/dist/host-document.js +34 -0
  88. package/dist/index.d.ts +280 -0
  89. package/dist/index.js +281 -0
  90. package/dist/internal.d.ts +2 -0
  91. package/dist/internal.js +3 -0
  92. package/dist/leftovers.d.ts +11 -0
  93. package/dist/leftovers.js +55 -0
  94. package/dist/mode.d.ts +169 -0
  95. package/dist/mode.js +31 -0
  96. package/dist/node/LICENSES.md +3540 -0
  97. package/dist/node/assert/strict.js +29 -0
  98. package/dist/node/assert.js +3044 -0
  99. package/dist/node/buffer.js +1499 -0
  100. package/dist/node/child_process.js +45 -0
  101. package/dist/node/cluster.js +85 -0
  102. package/dist/node/console.js +96 -0
  103. package/dist/node/constants.js +495 -0
  104. package/dist/node/crypto.js +1388 -0
  105. package/dist/node/dgram.js +78 -0
  106. package/dist/node/diagnostics_channel.js +122 -0
  107. package/dist/node/dns/promises.js +129 -0
  108. package/dist/node/dns.js +137 -0
  109. package/dist/node/domain.js +43 -0
  110. package/dist/node/events.js +1155 -0
  111. package/dist/node/fs/promises.js +40 -0
  112. package/dist/node/fs.js +10375 -0
  113. package/dist/node/http.js +326 -0
  114. package/dist/node/http2.js +305 -0
  115. package/dist/node/https.js +57 -0
  116. package/dist/node/inspector/promises.js +66 -0
  117. package/dist/node/inspector.js +76 -0
  118. package/dist/node/module.js +205 -0
  119. package/dist/node/net.js +392 -0
  120. package/dist/node/os.js +259 -0
  121. package/dist/node/path/posix.js +25 -0
  122. package/dist/node/path/win32.js +25 -0
  123. package/dist/node/path.js +384 -0
  124. package/dist/node/perf_hooks.js +313 -0
  125. package/dist/node/process.js +452 -0
  126. package/dist/node/punycode.js +178 -0
  127. package/dist/node/querystring.js +934 -0
  128. package/dist/node/readline/promises.js +71 -0
  129. package/dist/node/readline.js +56 -0
  130. package/dist/node/repl.js +44 -0
  131. package/dist/node/sqlite.js +22 -0
  132. package/dist/node/stream/consumers.js +47 -0
  133. package/dist/node/stream/promises.js +6 -0
  134. package/dist/node/stream/web.js +52 -0
  135. package/dist/node/stream.js +4323 -0
  136. package/dist/node/string_decoder.js +276 -0
  137. package/dist/node/sys.js +6 -0
  138. package/dist/node/timers/promises.js +71 -0
  139. package/dist/node/timers.js +133 -0
  140. package/dist/node/tls.js +122 -0
  141. package/dist/node/trace_events.js +23 -0
  142. package/dist/node/tty.js +69 -0
  143. package/dist/node/url.js +1426 -0
  144. package/dist/node/util/types.js +1456 -0
  145. package/dist/node/util.js +4807 -0
  146. package/dist/node/v8.js +160 -0
  147. package/dist/node/vm.js +88 -0
  148. package/dist/node/wasi.js +16 -0
  149. package/dist/node/worker_threads.js +123 -0
  150. package/dist/node/zlib.js +1396 -0
  151. package/dist/node-builtins.d.ts +40 -0
  152. package/dist/node-builtins.js +74 -0
  153. package/dist/node-on-page.d.ts +46 -0
  154. package/dist/node-on-page.js +101 -0
  155. package/dist/node-platform.d.ts +36 -0
  156. package/dist/node-platform.js +152 -0
  157. package/dist/node-rendered.d.ts +21 -0
  158. package/dist/node-rendered.js +26 -0
  159. package/dist/node-server.d.ts +46 -0
  160. package/dist/node-server.js +193 -0
  161. package/dist/optimizer-cache-key.d.ts +26 -0
  162. package/dist/optimizer-cache-key.js +73 -0
  163. package/dist/own-package.d.ts +1 -0
  164. package/dist/own-package.js +6 -0
  165. package/dist/page-store.d.ts +33 -0
  166. package/dist/page-store.js +80 -0
  167. package/dist/page-timers.d.ts +22 -0
  168. package/dist/page-timers.js +47 -0
  169. package/dist/page.d.ts +112 -0
  170. package/dist/page.js +549 -0
  171. package/dist/paths.d.ts +13 -0
  172. package/dist/paths.js +47 -0
  173. package/dist/plugin.d.ts +22 -0
  174. package/dist/plugin.js +995 -0
  175. package/dist/prerender-verdict.d.ts +8 -0
  176. package/dist/prerender-verdict.js +67 -0
  177. package/dist/project/context.d.ts +546 -0
  178. package/dist/project/context.js +111 -0
  179. package/dist/project/entries.d.ts +42 -0
  180. package/dist/project/entries.js +189 -0
  181. package/dist/project/env-worker.d.ts +1 -0
  182. package/dist/project/env-worker.js +9 -0
  183. package/dist/project/env.d.ts +36 -0
  184. package/dist/project/env.js +82 -0
  185. package/dist/project/layers.d.ts +31 -0
  186. package/dist/project/layers.js +150 -0
  187. package/dist/project/loaders.d.ts +71 -0
  188. package/dist/project/loaders.js +300 -0
  189. package/dist/project/metadata.d.ts +8 -0
  190. package/dist/project/metadata.js +34 -0
  191. package/dist/project/module-exports.d.ts +29 -0
  192. package/dist/project/module-exports.js +77 -0
  193. package/dist/project/routes.d.ts +19 -0
  194. package/dist/project/routes.js +92 -0
  195. package/dist/project/routing.d.ts +46 -0
  196. package/dist/project/routing.js +280 -0
  197. package/dist/project/transform.d.ts +8 -0
  198. package/dist/project/transform.js +110 -0
  199. package/dist/project/webpack.d.ts +46 -0
  200. package/dist/project/webpack.js +160 -0
  201. package/dist/project.d.ts +264 -0
  202. package/dist/project.js +58 -0
  203. package/dist/registry-global.d.ts +5 -0
  204. package/dist/registry-global.js +5 -0
  205. package/dist/registry.d.ts +241 -0
  206. package/dist/registry.js +30 -0
  207. package/dist/route-chunks.d.ts +13 -0
  208. package/dist/route-chunks.js +32 -0
  209. package/dist/route-lookup.d.ts +34 -0
  210. package/dist/route-lookup.js +207 -0
  211. package/dist/routes-ahead-shared.d.ts +17 -0
  212. package/dist/routes-ahead-shared.js +9 -0
  213. package/dist/routes-ahead.d.ts +10 -0
  214. package/dist/routes-ahead.js +54 -0
  215. package/dist/rsc.d.ts +19 -0
  216. package/dist/rsc.js +171 -0
  217. package/dist/server-action.d.ts +9 -0
  218. package/dist/server-action.js +15 -0
  219. package/dist/server-code.d.ts +176 -0
  220. package/dist/server-code.js +357 -0
  221. package/dist/server-in-front.d.ts +37 -0
  222. package/dist/server-in-front.js +90 -0
  223. package/dist/server-layers.d.ts +22 -0
  224. package/dist/server-layers.js +33 -0
  225. package/dist/setup-browser.d.ts +1 -0
  226. package/dist/setup-browser.js +8 -0
  227. package/dist/setup-node.d.ts +1 -0
  228. package/dist/setup-node.js +6 -0
  229. package/dist/setup.d.ts +8 -0
  230. package/dist/setup.js +62 -0
  231. package/dist/speed-features.d.ts +13 -0
  232. package/dist/speed-features.js +95 -0
  233. package/dist/ssr.d.ts +70 -0
  234. package/dist/ssr.js +480 -0
  235. package/dist/static-build.d.ts +36 -0
  236. package/dist/static-build.js +92 -0
  237. package/dist/storage.d.ts +31 -0
  238. package/dist/storage.js +94 -0
  239. package/dist/styles-shared.d.ts +137 -0
  240. package/dist/styles-shared.js +124 -0
  241. package/dist/styles.d.ts +102 -0
  242. package/dist/styles.js +730 -0
  243. package/dist/stylesheet-versions.d.ts +17 -0
  244. package/dist/stylesheet-versions.js +43 -0
  245. package/dist/tester.html +10 -0
  246. package/dist/use-cache.d.ts +15 -0
  247. package/dist/use-cache.js +93 -0
  248. package/dist/vitest-version.d.ts +6 -0
  249. package/dist/vitest-version.js +12 -0
  250. package/package.json +125 -4
@@ -0,0 +1,328 @@
1
+ import "./styles-shared.js";
2
+ import pageHost from "virtual:vitest-plugin-rsc/page-host";
3
+ import { releaseTimers, runnerTimers } from "@kasperpeulen/vitest-plugin-rsc/internal/timers";
4
+ //#region src/document.ts
5
+ const elements = (of) => [
6
+ of.documentElement,
7
+ of.head,
8
+ of.body
9
+ ];
10
+ const attributesOf = (element) => Array.from(element.attributes, ({ name, value }) => [name, value]);
11
+ let unload;
12
+ const keptProperties = /* @__PURE__ */ new WeakMap();
13
+ /**
14
+ * Keeps the properties `keys` of `target`, the document or one of its
15
+ * elements, as the pages are left, until it is called again: the marks of
16
+ * React DOM on the root of an app that renders the pages after its first
17
+ * (`renderAgain()` in client.tsx). Without `keys` they are no longer kept,
18
+ * and the app that kept them removes them.
19
+ */
20
+ function keepProperties(target, keys) {
21
+ if (keys) keptProperties.set(target, new Set(keys));
22
+ else keptProperties.delete(target);
23
+ }
24
+ const keptNodes = /* @__PURE__ */ new Set();
25
+ let preloads = [];
26
+ let runnerHref;
27
+ /**
28
+ * The URL of the document without the page that is open: the runner's, which
29
+ * the page shows as its own while it is open.
30
+ */
31
+ function documentUrl() {
32
+ return runnerHref ?? window.location.href;
33
+ }
34
+ const navigation = window.navigation;
35
+ function activate() {
36
+ if (!navigation || !("activation" in navigation)) return () => {};
37
+ const activation = {
38
+ entry: navigation.currentEntry,
39
+ from: null,
40
+ navigationType: "push"
41
+ };
42
+ Object.defineProperty(navigation, "activation", {
43
+ configurable: true,
44
+ enumerable: true,
45
+ get: () => activation
46
+ });
47
+ return () => Reflect.deleteProperty(navigation, "activation");
48
+ }
49
+ function staysDuringPage(node) {
50
+ return node instanceof HTMLScriptElement || node instanceof HTMLStyleElement || isPreload(node);
51
+ }
52
+ function isPreload(node) {
53
+ return node instanceof HTMLLinkElement && (node.relList.contains("modulepreload") || node.relList.contains("preload") && node.as !== "style");
54
+ }
55
+ function isViteStyle(node) {
56
+ return node instanceof HTMLStyleElement && node.hasAttribute("data-vite-dev-id");
57
+ }
58
+ function isGraphStylesheet(node) {
59
+ return node instanceof HTMLLinkElement && node.hasAttribute("data-vitest-plugin-rsc-graph");
60
+ }
61
+ function elementsOf(parent, tag) {
62
+ return Array.from(parent.getElementsByTagName(tag));
63
+ }
64
+ const hasRel = (link, keyword) => link.rel.toLowerCase().split(/[\t\n\f\r ]+/).includes(keyword);
65
+ function stylesheetsOf(parent, url) {
66
+ return elementsOf(parent, "link").filter((link) => hasRel(link, "stylesheet") && !link.relList.contains("alternate") && link.getAttribute("href") && (!link.type || link.type === "text/css") && URL.canParse(link.getAttribute("href"), url) && new URL(link.getAttribute("href"), url).origin === window.location.origin);
67
+ }
68
+ function stylesheetLoaded(link) {
69
+ return new Promise((resolve) => {
70
+ link.addEventListener("load", () => resolve(), { once: true });
71
+ link.addEventListener("error", () => resolve(), { once: true });
72
+ });
73
+ }
74
+ const globalsOfThePage = [
75
+ "next",
76
+ "nd",
77
+ "_N_E_STYLE_LOAD",
78
+ "__next_set_public_path__",
79
+ "__NEXT_HMR_CB",
80
+ "$RB",
81
+ "$RM",
82
+ "$RR",
83
+ "$RS",
84
+ "$RT",
85
+ "$RV",
86
+ "$RX"
87
+ ];
88
+ const deleteGlobalsOfThePage = () => {
89
+ for (const name of globalsOfThePage) Reflect.deleteProperty(window, name);
90
+ };
91
+ const reactScript = /\$R[A-Z]\b/;
92
+ function runInlineScript(code, timers) {
93
+ if (!reactScript.test(code)) {
94
+ (0, eval)(code);
95
+ return;
96
+ }
97
+ new Function("setTimeout", "clearTimeout", "requestAnimationFrame", "cancelAnimationFrame", code)(timers.setTimeout, timers.clearTimeout, timers.requestAnimationFrame, timers.cancelAnimationFrame);
98
+ }
99
+ const reactProperty = /^_+react/;
100
+ function forgetReact(root) {
101
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT);
102
+ for (let node = root; node; node = walker.nextNode()) for (const key of Object.keys(node)) if (reactProperty.test(key)) Reflect.deleteProperty(node, key);
103
+ }
104
+ function setAttributes(element, attributes) {
105
+ for (const { name } of Array.from(element.attributes)) element.removeAttribute(name);
106
+ for (const [name, value] of attributes) element.setAttribute(name, value);
107
+ }
108
+ /**
109
+ * Starts the files of the route of the page that loads next, as the server
110
+ * renders it: `stylesheets` as Next links them, in the CORS mode of
111
+ * `crossOrigin`, and `modules`. By their URLs. They go with that page.
112
+ */
113
+ function preloadPage({ stylesheets, crossOrigin, modules }) {
114
+ const links = [...stylesheets.map((href) => ({
115
+ href,
116
+ rel: "preload",
117
+ as: "style",
118
+ crossOrigin
119
+ })), ...modules.map((href) => ({
120
+ href,
121
+ rel: "modulepreload",
122
+ as: "",
123
+ crossOrigin: ""
124
+ }))];
125
+ for (const { href, rel, as, crossOrigin } of links) {
126
+ if (preloads.some((link) => link.href === href)) continue;
127
+ const link = document.createElement("link");
128
+ link.rel = rel;
129
+ if (as) link.as = as;
130
+ if (crossOrigin !== void 0) link.crossOrigin = crossOrigin;
131
+ link.href = href;
132
+ document.head.append(link);
133
+ preloads.push(link);
134
+ }
135
+ }
136
+ /**
137
+ * Replaces the page in this document with the one the server sent as `html`:
138
+ * its `<head>` first, the rest once the stylesheets of the `<head>` have
139
+ * loaded, and runs its inline scripts in document order once the stylesheets
140
+ * of the rest have too. Resolves then, and without running them for a page
141
+ * that was left in the meantime.
142
+ *
143
+ * The page is there in full before the app starts, so the document has loaded
144
+ * by the time Next's client looks: it reads the Flight payload that Next's
145
+ * inline scripts left in `self.__next_f`, and hydrates.
146
+ *
147
+ * With a `container`, the page is the one of a node, which renders no
148
+ * `<html>` or `<body>`, and what is in the document stays the test's. What
149
+ * the HTML parser puts in `<body>` goes in the container: the node, with the
150
+ * scripts it renders, and after it the scripts of Next and React.
151
+ *
152
+ * The page takes the entry of the history that the document is at, or with
153
+ * `after` gets one of its own, after that entry. With `inKeptApp`, leaving
154
+ * the page leaves what the app added to the `<head>`: see `unloadKeptApp()`.
155
+ * React's inline scripts get timers of the page's own, which leaving the
156
+ * page clears.
157
+ *
158
+ * Returns what takes React DOM's properties off the nodes of this page,
159
+ * before its root unmounts: React takes the nodes out of the document as it
160
+ * does, and leaves its fiber on a text node. A node that outlives the page
161
+ * then keeps no fiber of it: the one that an assertion of the test holds
162
+ * until it ends, or the one under the pointer. Once the page is left, it
163
+ * does nothing: leaving took them off already. Nothing for a page of a kept
164
+ * app, whose root outlives the page.
165
+ */
166
+ async function loadDocument(html, url, container, after, inKeptApp = false) {
167
+ leaveDocument();
168
+ const ownPreloads = new Set(preloads);
169
+ preloads = [];
170
+ const runnerUrl = window.location.href;
171
+ runnerHref = runnerUrl;
172
+ const runnerBody = document.body;
173
+ const runnerAttributes = elements(document).map(attributesOf);
174
+ const reactTargets = [
175
+ document,
176
+ document.documentElement,
177
+ document.head
178
+ ];
179
+ if (container) reactTargets.push(container);
180
+ const runnerProperties = reactTargets.map((target) => new Set(Reflect.ownKeys(target)));
181
+ const runnerAdopted = Array.from(document.adoptedStyleSheets);
182
+ const runnerScripts = new Set(document.querySelectorAll("script"));
183
+ const before = new Set([...document.head.childNodes, ...runnerBody.childNodes].filter((node) => !ownPreloads.has(node) && !keptNodes.has(node)));
184
+ const brought = new Set(ownPreloads);
185
+ const parked = [];
186
+ const graphParked = /* @__PURE__ */ new Set();
187
+ const switchedOff = [];
188
+ const pageBody = document.createElement("body");
189
+ let leaveNow;
190
+ const left = new Promise((resolve) => leaveNow = resolve);
191
+ let deactivate = () => {};
192
+ const pageNodes = () => [...container ? Array.from(container.childNodes) : [], ...[document.head, pageBody].flatMap((parent) => Array.from(parent.childNodes).filter((node) => !before.has(node) && !isViteStyle(node) && !isGraphStylesheet(node)))];
193
+ const scriptTimers = runnerTimers(() => unload !== leave);
194
+ const leave = () => {
195
+ try {
196
+ leaveNow();
197
+ if (!inKeptApp) pageNodes().forEach(forgetReact);
198
+ container?.replaceChildren();
199
+ for (const parent of [document.head, pageBody]) for (const node of Array.from(parent.childNodes)) {
200
+ if (before.has(node) || isViteStyle(node) || isGraphStylesheet(node)) continue;
201
+ if (inKeptApp && parent === document.head && !brought.has(node)) keptNodes.add(node);
202
+ else node.remove();
203
+ }
204
+ } finally {
205
+ runnerHref = void 0;
206
+ deactivate();
207
+ if (window.location.href !== runnerUrl) window.history.replaceState(null, "", runnerUrl);
208
+ }
209
+ document.head.append(...parked.filter((node) => !graphParked.has(node) || isGraphStylesheet(node)));
210
+ for (const [style, media] of switchedOff) if (media === null) style.removeAttribute("media");
211
+ else style.media = media;
212
+ runnerBody.append(...pageBody.childNodes);
213
+ pageBody.replaceWith(runnerBody);
214
+ elements(document).forEach((element, index) => setAttributes(element, runnerAttributes[index]));
215
+ document.adoptedStyleSheets = runnerAdopted;
216
+ reactTargets.forEach((target, index) => {
217
+ for (const key of Reflect.ownKeys(target)) {
218
+ if (runnerProperties[index].has(key) || keptProperties.get(target)?.has(key)) continue;
219
+ Reflect.deleteProperty(target, key);
220
+ }
221
+ });
222
+ delete self.__next_f;
223
+ delete self.__next_s;
224
+ if (!inKeptApp) deleteGlobalsOfThePage();
225
+ releaseTimers(scriptTimers);
226
+ };
227
+ unload = leave;
228
+ const forget = () => {
229
+ if (!inKeptApp && unload === leave) pageNodes().forEach(forgetReact);
230
+ };
231
+ const page = new DOMParser().parseFromString(html, "text/html");
232
+ for (const redirect of elementsOf(page, "meta")) if (redirect.id === "__next-page-redirect") redirect.removeAttribute("http-equiv");
233
+ const urlOf = (element, name) => {
234
+ const value = element.getAttribute(name);
235
+ return value !== null && URL.canParse(value, url) ? new URL(value, url).href : void 0;
236
+ };
237
+ const sources = new Set(elementsOf(page, "script").map((script) => urlOf(script, "src")));
238
+ sources.delete(void 0);
239
+ for (const link of elementsOf(page, "link")) if (link.rel.toLowerCase() === "preload" && link.getAttribute("as") === "script") {
240
+ if (sources.has(urlOf(link, "href"))) link.remove();
241
+ }
242
+ const stylesheetsOfHead = stylesheetsOf(page.head, url);
243
+ const stylesheetsOfBody = stylesheetsOf(page.body, url);
244
+ const loaded = (stylesheets) => Promise.race([pageHost.loadsStylesheets ? Promise.all(stylesheets.filter((link) => !link.disabled).map(stylesheetLoaded)) : void 0, left]);
245
+ if (after) {
246
+ window.history.replaceState(after.state, "", after.url);
247
+ window.history.pushState(null, "", url);
248
+ } else window.history.replaceState(null, "", url);
249
+ deactivate = activate();
250
+ const head = Array.from(page.head.childNodes);
251
+ for (const node of head) brought.add(node);
252
+ document.head.append(...head);
253
+ await loaded(stylesheetsOfHead);
254
+ if (unload !== leave) return forget;
255
+ for (const node of runnerBody.childNodes) before.add(node);
256
+ for (const node of container ? [] : document.head.childNodes) {
257
+ if (!before.has(node)) continue;
258
+ if (isViteStyle(node)) switchedOff.push([node, node.getAttribute("media")]);
259
+ else if (!staysDuringPage(node)) parked.push(node);
260
+ if (isGraphStylesheet(node)) graphParked.add(node);
261
+ }
262
+ for (const node of parked) document.head.removeChild(node);
263
+ for (const [style] of switchedOff) style.media = "not all";
264
+ const staying = Array.from(runnerBody.childNodes).filter((node) => container || staysDuringPage(node));
265
+ setAttributes(pageBody, attributesOf(runnerBody));
266
+ document.documentElement.replaceChild(pageBody, runnerBody);
267
+ pageBody.append(...staying);
268
+ if (container) container.append(...page.body.childNodes);
269
+ else {
270
+ elements(page).forEach((element, index) => setAttributes(elements(document)[index], attributesOf(element)));
271
+ pageBody.append(...page.body.childNodes);
272
+ }
273
+ await loaded(stylesheetsOfBody);
274
+ if (unload !== leave) return forget;
275
+ for (const script of document.querySelectorAll("script")) {
276
+ if (runnerScripts.has(script) || script.src) continue;
277
+ if (!script.type || script.type === "text/javascript" || script.type === "module") try {
278
+ runInlineScript(script.textContent ?? "", scriptTimers);
279
+ } catch (error) {
280
+ reportError(error);
281
+ }
282
+ }
283
+ return forget;
284
+ }
285
+ let queueStreamedContent;
286
+ /** `self.$RC` of a page. */
287
+ const streamedContentQueue = {
288
+ configurable: true,
289
+ set: (queue) => queueStreamedContent = queue,
290
+ get: () => queueStreamedContent && ((...args) => {
291
+ queueStreamedContent(...args);
292
+ const { $RB: queued, $RV: reveal } = self;
293
+ try {
294
+ if (queued?.length && reveal) reveal(queued);
295
+ } catch (error) {
296
+ reportError(error);
297
+ }
298
+ })
299
+ };
300
+ function leaveDocument() {
301
+ const leave = unload;
302
+ unload = void 0;
303
+ leave?.();
304
+ }
305
+ /**
306
+ * Takes back what the code of the kept app added to the `<head>` as its pages
307
+ * were open, once the app is left: see `loadDocument()`. With `withGlobals`,
308
+ * also the globals of Next and React on `window` that point into it.
309
+ */
310
+ function unloadKeptApp(withGlobals = true) {
311
+ for (const node of keptNodes) if (node.parentNode === document.head) node.remove();
312
+ keptNodes.clear();
313
+ if (withGlobals) deleteGlobalsOfThePage();
314
+ }
315
+ /**
316
+ * Leaves the page, and the one that was loading: the document is as it was
317
+ * before the page, but for what a kept app keeps (`unloadKeptApp()`).
318
+ */
319
+ function unloadDocument() {
320
+ try {
321
+ leaveDocument();
322
+ } finally {
323
+ for (const link of preloads) link.remove();
324
+ preloads = [];
325
+ }
326
+ }
327
+ //#endregion
328
+ export { documentUrl, keepProperties, loadDocument, preloadPage, streamedContentQueue, unloadDocument, unloadKeptApp };
@@ -0,0 +1,15 @@
1
+ //#region src/downloads.d.ts
2
+ /**
3
+ * The name a browser saves the answer to a navigation as, or none when it
4
+ * shows the answer. `requested` is the navigation's `downloadRequest`: the
5
+ * `download` attribute of a link, `""` without a value.
6
+ */
7
+ declare function downloadName(response: Response, requested: string | null): string | undefined;
8
+ /**
9
+ * Hands the answer to the browser as a download, as `name`: the browser
10
+ * saves the body of a Blob URL that an `<a download>` links, and the URL goes
11
+ * once it has. An answer that is not ok is no file, as in a browser.
12
+ */
13
+ declare function download(response: Response, name: string, signal: AbortSignal): Promise<void>;
14
+ //#endregion
15
+ export { download, downloadName };
@@ -0,0 +1,71 @@
1
+ //#region src/downloads.ts
2
+ /**
3
+ * The name a browser saves the answer to a navigation as, or none when it
4
+ * shows the answer. `requested` is the navigation's `downloadRequest`: the
5
+ * `download` attribute of a link, `""` without a value.
6
+ */
7
+ function downloadName(response, requested) {
8
+ const disposition = response.headers.get("content-disposition") ?? "";
9
+ const type = /^\s*([^\s;=]*)\s*(?:;|$)/.exec(disposition)?.[1]?.toLowerCase();
10
+ if (requested === null && (!type || type === "inline")) return void 0;
11
+ const fromUrl = decode(percentDecoded(new URL(response.url).pathname.split("/").pop()), "utf-8");
12
+ return filenameOf(disposition) || requested || fromUrl || "download";
13
+ }
14
+ function filenameOf(disposition) {
15
+ const parameters = /* @__PURE__ */ new Map();
16
+ for (const [, name, value] of disposition.matchAll(/;\s*([^\s=;]+)\s*=\s*("(?:[^"\\]|\\.)*"|[^;]*)/g)) {
17
+ const unquoted = value.startsWith("\"") ? value.slice(1, -1).replace(/\\(.)/g, "$1") : value;
18
+ if (!parameters.has(name.toLowerCase())) parameters.set(name.toLowerCase(), unquoted.trim());
19
+ }
20
+ const extended = /^([\w!#$%&+^`{}~-]+)'[^']*'(.*)$/.exec(parameters.get("filename*") ?? "");
21
+ if (extended) {
22
+ const decoded = decode(percentDecoded(extended[2]), extended[1]);
23
+ if (decoded) return decoded;
24
+ }
25
+ const plain = parameters.get("filename");
26
+ if (!plain) return void 0;
27
+ const text = decode(Uint8Array.from(plain, (char) => char.charCodeAt(0) & 255), "utf-8") ?? plain;
28
+ return /^[\x20-\x7e]*%[\da-f]{2}[\x20-\x7e]*$/i.test(text) ? decode(percentDecoded(text), "utf-8") ?? text : text;
29
+ }
30
+ function percentDecoded(text) {
31
+ const bytes = [];
32
+ for (let at = 0; at < text.length; at++) {
33
+ const escaped = /^%([\da-f]{2})/i.exec(text.slice(at, at + 3));
34
+ if (escaped) {
35
+ bytes.push(parseInt(escaped[1], 16));
36
+ at += 2;
37
+ } else bytes.push(text.charCodeAt(at) & 255);
38
+ }
39
+ return Uint8Array.from(bytes);
40
+ }
41
+ function decode(bytes, charset) {
42
+ try {
43
+ return new TextDecoder(charset, { fatal: true }).decode(bytes);
44
+ } catch {
45
+ return;
46
+ }
47
+ }
48
+ /**
49
+ * Hands the answer to the browser as a download, as `name`: the browser
50
+ * saves the body of a Blob URL that an `<a download>` links, and the URL goes
51
+ * once it has. An answer that is not ok is no file, as in a browser.
52
+ */
53
+ async function download(response, name, signal) {
54
+ if (!response.ok) {
55
+ await response.body?.cancel();
56
+ throw new Error(`vitest-plugin-rsc: the download of ${response.url} failed: it responded with ${response.status}. A browser saves no file for it.`);
57
+ }
58
+ const blob = await response.blob();
59
+ signal.throwIfAborted();
60
+ const url = URL.createObjectURL(blob);
61
+ try {
62
+ const link = document.createElement("a");
63
+ link.href = url;
64
+ link.download = name;
65
+ link.click();
66
+ } finally {
67
+ URL.revokeObjectURL(url);
68
+ }
69
+ }
70
+ //#endregion
71
+ export { download, downloadName };
@@ -0,0 +1,11 @@
1
+ import { Plugin } from "vite";
2
+
3
+ //#region src/esm-require.d.ts
4
+ /**
5
+ * The plugin of the optimizer that makes `__toCommonJS` of Rolldown's runtime
6
+ * return one object per module. A runtime that does not have it as above is
7
+ * left as it is.
8
+ */
9
+ declare function esmRequirePlugin(): Plugin;
10
+ //#endregion
11
+ export { esmRequirePlugin };
@@ -0,0 +1,32 @@
1
+ //#region src/esm-require.ts
2
+ const declaration = /^(?:export )?var __toCommonJS = /m;
3
+ const copy = /__copyProps\(\s*__defProp\(\s*\{\s*\}\s*,\s*(["'])__esModule\1\s*,\s*\{\s*value:\s*true\s*\}\s*\)\s*,\s*mod\s*\)/y;
4
+ /**
5
+ * The plugin of the optimizer that makes `__toCommonJS` of Rolldown's runtime
6
+ * return one object per module. A runtime that does not have it as above is
7
+ * left as it is.
8
+ */
9
+ function esmRequirePlugin() {
10
+ return {
11
+ name: "vitest-plugin-rsc:esm-require",
12
+ transform: {
13
+ filter: { id: /rolldown\/runtime\.js$/ },
14
+ handler(code) {
15
+ const start = code.search(declaration);
16
+ if (start === -1) return;
17
+ const end = code.indexOf(";", start);
18
+ const at = code.indexOf("__copyProps(", start);
19
+ copy.lastIndex = at;
20
+ const copied = at !== -1 && at < end ? copy.exec(code)?.[0] : void 0;
21
+ if (!copied) return;
22
+ const cached = `(__toCommonJSOf.get(mod) ?? __toCommonJSOf.set(mod, ${copied}).get(mod))`;
23
+ return {
24
+ code: `${code.slice(0, start)}var __toCommonJSOf = new WeakMap();\n${code.slice(start, at)}${cached}${code.slice(at + copied.length)}`,
25
+ map: null
26
+ };
27
+ }
28
+ }
29
+ };
30
+ }
31
+ //#endregion
32
+ export { esmRequirePlugin };