vinext 0.0.20 → 0.0.21

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.
@@ -1 +1 @@
1
- {"version":3,"file":"app-dev-server.d.ts","sourceRoot":"","sources":["../../src/server/app-dev-server.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAKtF;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,WAAW,EAAE,WAAW,EAAE,CAAC;QAC3B,UAAU,EAAE,WAAW,EAAE,CAAC;QAC1B,QAAQ,EAAE,WAAW,EAAE,CAAC;KACzB,CAAC;IACF,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,4GAA4G;IAC5G,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,uGAAuG;IACvG,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,QAAQ,EAAE,EAClB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,EAC9B,cAAc,CAAC,EAAE,iBAAiB,EAAE,EACpC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,EAC/B,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,OAAO,EACvB,MAAM,CAAC,EAAE,eAAe,GACvB,MAAM,CA6oER;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAwZzC;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CA4S7C"}
1
+ {"version":3,"file":"app-dev-server.d.ts","sourceRoot":"","sources":["../../src/server/app-dev-server.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAKtF;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,WAAW,EAAE,WAAW,EAAE,CAAC;QAC3B,UAAU,EAAE,WAAW,EAAE,CAAC;QAC1B,QAAQ,EAAE,WAAW,EAAE,CAAC;KACzB,CAAC;IACF,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,4GAA4G;IAC5G,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,uGAAuG;IACvG,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,QAAQ,EAAE,EAClB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,EAC9B,cAAc,CAAC,EAAE,iBAAiB,EAAE,EACpC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,EAC/B,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,OAAO,EACvB,MAAM,CAAC,EAAE,eAAe,GACvB,MAAM,CAurER;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAibzC;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CA4S7C"}
@@ -294,6 +294,48 @@ function rscOnError(error) {
294
294
  if (error && typeof error === "object" && "digest" in error) {
295
295
  return String(error.digest);
296
296
  }
297
+
298
+ // In dev, detect the "Only plain objects" RSC serialization error and emit
299
+ // an actionable hint. This error occurs when a Server Component passes a
300
+ // class instance, ES module namespace object, or null-prototype object as a
301
+ // prop to a Client Component.
302
+ //
303
+ // Root cause: Vite bundles modules as true ESM (module namespace objects
304
+ // have a null-like internal slot), while Next.js's webpack build produces
305
+ // plain CJS-wrapped objects with __esModule:true. React's RSC serializer
306
+ // accepts the latter as plain objects but rejects the former — which means
307
+ // code that accidentally passes "import * as X" works in webpack/Next.js
308
+ // but correctly fails in vinext.
309
+ //
310
+ // Common triggers:
311
+ // - "import * as utils from './utils'" passed as a prop
312
+ // - class instances (new Foo()) passed as props
313
+ // - Date / Map / Set instances passed as props
314
+ // - Objects with Object.create(null) (null prototype)
315
+ if (
316
+ process.env.NODE_ENV !== "production" &&
317
+ error instanceof Error &&
318
+ error.message.includes("Only plain objects, and a few built-ins, can be passed to Client Components")
319
+ ) {
320
+ console.error(
321
+ "[vinext] RSC serialization error: a non-plain object was passed from a Server Component to a Client Component.\\n" +
322
+ "\\n" +
323
+ "Common causes:\\n" +
324
+ " * Passing a module namespace (import * as X) directly as a prop.\\n" +
325
+ " Unlike Next.js (webpack), Vite produces real ESM module namespace objects\\n" +
326
+ " which are not serializable. Fix: pass individual values instead,\\n" +
327
+ " e.g. <Comp value={module.value} />\\n" +
328
+ " * Passing a class instance (new Foo()) as a prop.\\n" +
329
+ " Fix: convert to a plain object, e.g. { id: foo.id, name: foo.name }\\n" +
330
+ " * Passing a Date, Map, or Set. Use .toISOString(), [...map.entries()], etc.\\n" +
331
+ " * Passing Object.create(null). Use { ...obj } to restore a prototype.\\n" +
332
+ "\\n" +
333
+ "Original error:",
334
+ error.message,
335
+ );
336
+ return undefined;
337
+ }
338
+
297
339
  // In production, generate a digest hash for non-navigation errors
298
340
  if (process.env.NODE_ENV === "production" && error) {
299
341
  const msg = error instanceof Error ? error.message : String(error);
@@ -2257,6 +2299,20 @@ async function collectStreamChunks(stream) {
2257
2299
  return chunks;
2258
2300
  }
2259
2301
 
2302
+ // React 19 dev-mode workaround (see VinextFlightRoot in handleSsr):
2303
+ //
2304
+ // In dev, Flight error decoding in react-server-dom-webpack/client.edge
2305
+ // can hit resolveErrorDev() which (via React's dev error stack capture)
2306
+ // expects a non-null hooks dispatcher.
2307
+ //
2308
+ // Vinext previously called createFromReadableStream() outside of any React render.
2309
+ // When an RSC stream contains an error, dev-mode decoding could crash with:
2310
+ // - "Invalid hook call"
2311
+ // - "Cannot read properties of null (reading 'useContext')"
2312
+ //
2313
+ // Fix: call createFromReadableStream() lazily inside a React component render.
2314
+ // This mirrors Next.js behavior and ensures the dispatcher is set.
2315
+
2260
2316
  /**
2261
2317
  * Create a TransformStream that appends RSC chunks as inline <script> tags
2262
2318
  * to the HTML stream. This allows progressive hydration — the browser receives
@@ -2391,7 +2447,18 @@ export async function handleSsr(rscStream, navContext, fontData) {
2391
2447
  // immediately in the HTML shell, then stream in resolved content as RSC
2392
2448
  // chunks arrive. Awaiting here would block until all async server components
2393
2449
  // complete, collapsing the streaming behavior.
2394
- const root = createFromReadableStream(ssrStream);
2450
+ // Lazily create the Flight root inside render so React's hook dispatcher is set
2451
+ // (avoids React 19 dev-mode resolveErrorDev() crash). VinextFlightRoot returns
2452
+ // a thenable (not a ReactNode), which React 19 consumes via its internal
2453
+ // thenable-as-child suspend/resume behavior. This matches Next.js's approach.
2454
+ let flightRoot;
2455
+ function VinextFlightRoot() {
2456
+ if (!flightRoot) {
2457
+ flightRoot = createFromReadableStream(ssrStream);
2458
+ }
2459
+ return flightRoot;
2460
+ }
2461
+ const root = _ssrCE(VinextFlightRoot);
2395
2462
 
2396
2463
  // Wrap with ServerInsertedHTMLContext.Provider so libraries that use
2397
2464
  // useContext(ServerInsertedHTMLContext) (Apollo Client, styled-components,
@@ -2446,11 +2513,11 @@ export async function handleSsr(rscStream, navContext, fontData) {
2446
2513
  const insertedElements = flushServerInsertedHTML();
2447
2514
 
2448
2515
  // Render the inserted elements to HTML strings
2449
- const { createElement, Fragment } = await import("react");
2516
+ const { Fragment } = await import("react");
2450
2517
  let insertedHTML = "";
2451
2518
  for (const el of insertedElements) {
2452
2519
  try {
2453
- insertedHTML += renderToStaticMarkup(createElement(Fragment, null, el));
2520
+ insertedHTML += renderToStaticMarkup(_ssrCE(Fragment, null, el));
2454
2521
  } catch {
2455
2522
  // Skip elements that can't be rendered
2456
2523
  }