diff --git a/.changeset/good-jars-mix.md b/.changeset/good-jars-mix.md new file mode 100644 index 00000000000..6672be7303a --- /dev/null +++ b/.changeset/good-jars-mix.md @@ -0,0 +1,20 @@ +--- +'@builder.io/qwik': minor +--- + +CHORE: Prepare backwards compatibility for V1 libraries in V2. + +We move internal fields `immutableProps` and `flags` out of JSXNode as they are not meant for public use. + +This will allow projects using older V1 libraries to continue to work with the Qwik V2 by adding the following `package.json` changes: + +```json +{ + "dependencies": { + "@builder.io/qwik": "^1.11.0", + "@qwik.dev/core": "^2.0.0" + } +} +``` + +And will prevent typescript errors when using libraries which haven't upgraded to V2 yet. diff --git a/packages/docs/src/routes/api/qwik/api.json b/packages/docs/src/routes/api/qwik/api.json index 7b1503a4698..0fb54f60c90 100644 --- a/packages/docs/src/routes/api/qwik/api.json +++ b/packages/docs/src/routes/api/qwik/api.json @@ -1256,7 +1256,7 @@ } ], "kind": "Interface", - "content": "A JSX Node, an internal structure. You probably want to use `JSXOutput` instead.\n\n\n```typescript\nexport interface JSXNode \n```\n\n\n\n\n\n\n\n\n\n\n
\n\nProperty\n\n\n\n\nModifiers\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\n[children](#)\n\n\n\n\n\n\n\n[JSXChildren](#jsxchildren) \\| null\n\n\n\n\n\n
\n\n[dev?](#)\n\n\n\n\n\n\n\n[DevJSX](#devjsx)\n\n\n\n\n_(Optional)_\n\n\n
\n\n[flags](#)\n\n\n\n\n\n\n\nnumber\n\n\n\n\n\n
\n\n[immutableProps](#)\n\n\n\n\n\n\n\nRecord<any, unknown> \\| null\n\n\n\n\n\n
\n\n[key](#)\n\n\n\n\n\n\n\nstring \\| null\n\n\n\n\n\n
\n\n[props](#)\n\n\n\n\n\n\n\nT extends [FunctionComponent](#functioncomponent)<infer P> ? P : Record<any, unknown>\n\n\n\n\n\n
\n\n[type](#)\n\n\n\n\n\n\n\nT\n\n\n\n\n\n
", + "content": "A JSX Node, an internal structure. You probably want to use `JSXOutput` instead.\n\n\n```typescript\nexport interface JSXNode \n```\n\n\n\n\n\n\n\n\n
\n\nProperty\n\n\n\n\nModifiers\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\n[children](#)\n\n\n\n\n\n\n\n[JSXChildren](#jsxchildren) \\| null\n\n\n\n\n\n
\n\n[dev?](#)\n\n\n\n\n\n\n\n[DevJSX](#devjsx)\n\n\n\n\n_(Optional)_\n\n\n
\n\n[key](#)\n\n\n\n\n\n\n\nstring \\| null\n\n\n\n\n\n
\n\n[props](#)\n\n\n\n\n\n\n\nT extends [FunctionComponent](#functioncomponent)<infer P> ? P : Record<any, unknown>\n\n\n\n\n\n
\n\n[type](#)\n\n\n\n\n\n\n\nT\n\n\n\n\n\n
", "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/render/jsx/types/jsx-node.ts", "mdFile": "qwik.jsxnode.md" }, @@ -1760,7 +1760,7 @@ } ], "kind": "Function", - "content": "> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.\n> \n\nLoad the prefetch graph for the container.\n\nEach Qwik container needs to include its own prefetch graph.\n\n\n```typescript\nPrefetchGraph: (opts?: {\n base?: string;\n manifestHash?: string;\n manifestURL?: string;\n nonce?: string;\n}) => JSXNode<\"script\">\n```\n\n\n\n\n
\n\nParameter\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\nopts\n\n\n\n\n{ base?: string; manifestHash?: string; manifestURL?: string; nonce?: string; }\n\n\n\n\n_(Optional)_ Options for the loading prefetch graph.\n\n- `base` - Base of the graph. For a default installation this will default to the q:base value `/build/`. But if more than one MFE is installed on the page, then each MFE needs to have its own base. - `manifestHash` - Hash of the manifest file to load. If not provided the hash will be extracted from the container attribute `q:manifest-hash` and assume the default build file `${base}/q-bundle-graph-${manifestHash}.json`. - `manifestURL` - URL of the manifest file to load if non-standard bundle graph location name.\n\n\n
\n**Returns:**\n\nJSXNode<\"script\">", + "content": "> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.\n> \n\nLoad the prefetch graph for the container.\n\nEach Qwik container needs to include its own prefetch graph.\n\n\n```typescript\nPrefetchGraph: (opts?: {\n base?: string;\n manifestHash?: string;\n manifestURL?: string;\n nonce?: string;\n}) => JSXOutput\n```\n\n\n\n\n
\n\nParameter\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\nopts\n\n\n\n\n{ base?: string; manifestHash?: string; manifestURL?: string; nonce?: string; }\n\n\n\n\n_(Optional)_ Options for the loading prefetch graph.\n\n- `base` - Base of the graph. For a default installation this will default to the q:base value `/build/`. But if more than one MFE is installed on the page, then each MFE needs to have its own base. - `manifestHash` - Hash of the manifest file to load. If not provided the hash will be extracted from the container attribute `q:manifest-hash` and assume the default build file `${base}/q-bundle-graph-${manifestHash}.json`. - `manifestURL` - URL of the manifest file to load if non-standard bundle graph location name.\n\n\n
\n**Returns:**\n\n[JSXOutput](#jsxoutput)", "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/components/prefetch.ts", "mdFile": "qwik.prefetchgraph.md" }, @@ -1774,7 +1774,7 @@ } ], "kind": "Function", - "content": "> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.\n> \n\nInstall a service worker which will prefetch the bundles.\n\nThere can only be one service worker per page. Because there can be many separate Qwik Containers on the page each container needs to load its prefetch graph using `PrefetchGraph` component.\n\n\n```typescript\nPrefetchServiceWorker: (opts: {\n base?: string;\n scope?: string;\n path?: string;\n verbose?: boolean;\n fetchBundleGraph?: boolean;\n nonce?: string;\n}) => JSXNode<'script'>\n```\n\n\n\n\n
\n\nParameter\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\nopts\n\n\n\n\n{ base?: string; scope?: string; path?: string; verbose?: boolean; fetchBundleGraph?: boolean; nonce?: string; }\n\n\n\n\nOptions for the prefetch service worker.\n\n- `base` - Base URL for the service worker `import.meta.env.BASE_URL` or `/`. Default is `import.meta.env.BASE_URL` - `scope` - Base URL for when the service-worker will activate. Default is `/` - `path` - Path to the service worker. Default is `qwik-prefetch-service-worker.js` unless you pass a path that starts with a `/` then the base is ignored. Default is `qwik-prefetch-service-worker.js` - `verbose` - Verbose logging for the service worker installation. Default is `false` - `nonce` - Optional nonce value for security purposes, defaults to `undefined`.\n\n\n
\n**Returns:**\n\nJSXNode<'script'>", + "content": "> This API is provided as an alpha preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.\n> \n\nInstall a service worker which will prefetch the bundles.\n\nThere can only be one service worker per page. Because there can be many separate Qwik Containers on the page each container needs to load its prefetch graph using `PrefetchGraph` component.\n\n\n```typescript\nPrefetchServiceWorker: (opts: {\n base?: string;\n scope?: string;\n path?: string;\n verbose?: boolean;\n fetchBundleGraph?: boolean;\n nonce?: string;\n}) => JSXNode<'script'>\n```\n\n\n\n\n
\n\nParameter\n\n\n\n\nType\n\n\n\n\nDescription\n\n\n
\n\nopts\n\n\n\n\n{ base?: string; scope?: string; path?: string; verbose?: boolean; fetchBundleGraph?: boolean; nonce?: string; }\n\n\n\n\nOptions for the prefetch service worker.\n\n- `base` - Base URL for the service worker `import.meta.env.BASE_URL` or `/`. Default is `import.meta.env.BASE_URL` - `scope` - Base URL for when the service-worker will activate. Default is `/` - `path` - Path to the service worker. Default is `qwik-prefetch-service-worker.js` unless you pass a path that starts with a `/` then the base is ignored. Default is `qwik-prefetch-service-worker.js` - `verbose` - Verbose logging for the service worker installation. Default is `false` - `nonce` - Optional nonce value for security purposes, defaults to `undefined`.\n\n\n
\n**Returns:**\n\n[JSXNode](#jsxnode)<'script'>", "editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/components/prefetch.ts", "mdFile": "qwik.prefetchserviceworker.md" }, diff --git a/packages/docs/src/routes/api/qwik/index.md b/packages/docs/src/routes/api/qwik/index.md index 7e7b14311f9..805484b0d50 100644 --- a/packages/docs/src/routes/api/qwik/index.md +++ b/packages/docs/src/routes/api/qwik/index.md @@ -3043,32 +3043,6 @@ _(Optional)_ -[flags](#) - - - - - -number - - - - - - -[immutableProps](#) - - - - - -Record<any, unknown> \| null - - - - - - [key](#) @@ -3591,7 +3565,7 @@ PrefetchGraph: (opts?: { manifestHash?: string; manifestURL?: string; nonce?: string; -}) => JSXNode<"script">; +}) => JSXOutput; ```
@@ -3625,7 +3599,7 @@ _(Optional)_ Options for the loading prefetch graph.
**Returns:** -JSXNode<"script"> +[JSXOutput](#jsxoutput) [Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/components/prefetch.ts) @@ -3679,7 +3653,7 @@ Options for the prefetch service worker. **Returns:** -JSXNode<'script'> +[JSXNode](#jsxnode)<'script'> [Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/components/prefetch.ts) diff --git a/packages/qwik/src/core/api.md b/packages/qwik/src/core/api.md index 430b1328f75..b5ea3a3f253 100644 --- a/packages/qwik/src/core/api.md +++ b/packages/qwik/src/core/api.md @@ -413,9 +413,10 @@ export { jsx as jsxs } export const _jsxBranch: (input?: T) => T | undefined; // Warning: (ae-forgotten-export) The symbol "JsxDevOpts" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "JSXNodeInternal" needs to be exported by the entry point index.d.ts // // @internal -export const _jsxC: >>(type: T, mutableProps: (T extends FunctionComponent ? PROPS : Record) | null, flags: number, key: string | number | null, dev?: JsxDevOpts) => JSXNode; +export const _jsxC: >>(type: T, mutableProps: (T extends FunctionComponent ? PROPS : Record) | null, flags: number, key: string | number | null, dev?: JsxDevOpts) => JSXNodeInternal; // @public (undocumented) export type JSXChildren = string | number | boolean | null | undefined | Function | RegExp | JSXChildren[] | Promise | Signal | JSXNode; @@ -430,10 +431,6 @@ export interface JSXNode | null; - // (undocumented) key: string | null; // (undocumented) props: T extends FunctionComponent ? P : Record; @@ -445,10 +442,10 @@ export interface JSXNode(type: T, mutableProps: Record | null, immutableProps: Record | null, children: JSXChildren | null, flags: number, key: string | number | null, dev?: DevJSX) => JSXNode; +export const _jsxQ: (type: T, mutableProps: Record | null, immutableProps: Record | null, children: JSXChildren | null, flags: number, key: string | number | null, dev?: DevJSX) => JSXNodeInternal; // @internal -export const _jsxS: (type: T, mutableProps: Record | null, immutableProps: Record | null, flags: number, key: string | number | null, dev?: DevJSX) => JSXNode; +export const _jsxS: (type: T, mutableProps: Record | null, immutableProps: Record | null, flags: number, key: string | number | null, dev?: DevJSX) => JSXNodeInternal; // @public (undocumented) export type JSXTagName = keyof HTMLElementTagNameMap | Omit; @@ -606,7 +603,7 @@ export const PrefetchGraph: (opts?: { manifestHash?: string; manifestURL?: string; nonce?: string; -}) => JSXNode_2<"script">; +}) => JSXOutput; // @alpha export const PrefetchServiceWorker: (opts: { diff --git a/packages/qwik/src/core/components/prefetch.ts b/packages/qwik/src/core/components/prefetch.ts index cec617bd361..6e7f045a576 100644 --- a/packages/qwik/src/core/components/prefetch.ts +++ b/packages/qwik/src/core/components/prefetch.ts @@ -2,6 +2,7 @@ import { isDev } from '@builder.io/qwik/build'; import { _jsxC } from '../internal'; import type { JSXNode } from '@builder.io/qwik/jsx-runtime'; import { useServerData } from '../use/use-env-data'; +import type { JSXOutput } from '../render/jsx/types/jsx-node'; /** * Install a service worker which will prefetch the bundles. @@ -124,7 +125,7 @@ const PREFETCH_CODE = /*#__PURE__*/ (( */ export const PrefetchGraph = ( opts: { base?: string; manifestHash?: string; manifestURL?: string; nonce?: string } = {} -) => { +): JSXOutput => { const isTest = import.meta.env.TEST; if (isDev && !isTest) { const props = { diff --git a/packages/qwik/src/core/container/serializers.ts b/packages/qwik/src/core/container/serializers.ts index 7ef7afaab35..5b7852b710e 100644 --- a/packages/qwik/src/core/container/serializers.ts +++ b/packages/qwik/src/core/container/serializers.ts @@ -37,8 +37,8 @@ import { serializeDerivedSignalFunc } from '../qrl/inlined-fn'; import type { QwikElement } from '../render/dom/virtual-element'; import { assertString, assertTrue } from '../error/assert'; import { Fragment, JSXNodeImpl, isJSXNode } from '../render/jsx/jsx-runtime'; -import type { JSXNode } from '@builder.io/qwik/jsx-runtime'; import { Slot } from '../render/jsx/slot.public'; +import type { JSXNodeInternal } from '../render/jsx/types/jsx-node'; /** * - 0, 8, 9, A, B, C, D @@ -383,7 +383,7 @@ const FormDataSerializer = /*#__PURE__*/ serializer({ }, }); -const JSXNodeSerializer = /*#__PURE__*/ serializer({ +const JSXNodeSerializer = /*#__PURE__*/ serializer({ $prefix$: '\u0017', $test$: (v) => isJSXNode(v), $collect$: (node, collector, leaks) => { diff --git a/packages/qwik/src/core/render/dom/render-dom.ts b/packages/qwik/src/core/render/dom/render-dom.ts index 14856c2ec53..916469a54aa 100644 --- a/packages/qwik/src/core/render/dom/render-dom.ts +++ b/packages/qwik/src/core/render/dom/render-dom.ts @@ -8,7 +8,7 @@ import { isArray, isFunction, isObject, isString, type ValueOrPromise } from '.. import { domToVnode, smartUpdateChildren } from './visitor'; import { SkipRender } from '../jsx/utils.public'; import { isJSXNode, SKIP_RENDER_TYPE, _jsxC, Virtual } from '../jsx/jsx-runtime'; -import type { DevJSX, JSXNode } from '../jsx/types/jsx-node'; +import type { DevJSX, JSXNodeInternal } from '../jsx/types/jsx-node'; import { executeComponent, shouldWrapFunctional } from '../execute-component'; import type { RenderContext } from '../types'; import { type QwikElement, VIRTUAL, type VirtualElement } from './virtual-element'; @@ -88,7 +88,7 @@ export class ProcessedJSXNodeImpl implements ProcessedJSXNode { } export const processNode = ( - node: JSXNode, + node: JSXNodeInternal, invocationContext?: InvokeContext ): ValueOrPromise => { const { key, type, props, children, flags, immutableProps } = node; diff --git a/packages/qwik/src/core/render/jsx/factory.unit.ts b/packages/qwik/src/core/render/jsx/factory.unit.ts index 167f0758740..17f576dd9ec 100644 --- a/packages/qwik/src/core/render/jsx/factory.unit.ts +++ b/packages/qwik/src/core/render/jsx/factory.unit.ts @@ -1,6 +1,6 @@ import { h } from './factory'; import { isJSXNode, Fragment } from './jsx-runtime'; -import type { FunctionComponent } from './types/jsx-node'; +import type { FunctionComponent, JSXNodeInternal } from './types/jsx-node'; import { type ProcessedJSXNode, processNode } from '../dom/render-dom'; import { test, assert } from 'vitest'; @@ -19,7 +19,7 @@ test('map multiple nodes, flatten', () => { 'a', [1, 2].map((n) => h('child', null, n)), 'b' - ) + ) as JSXNodeInternal ) as ProcessedJSXNode; assert.deepEqual(v.$children$.length, 4); assert.deepEqual(v.$children$[0].$text$, 'a'); @@ -32,7 +32,7 @@ test('map multiple nodes, flatten', () => { test('one child node', () => { // - const v = processNode(h('parent', null, h('child', null))) as ProcessedJSXNode; + const v = processNode(h('parent', null, h('child', null)) as JSXNodeInternal) as ProcessedJSXNode; assert.deepEqual(v.$children$.length, 1); assert.deepEqual(v.$children$[0].$type$, 'child'); assert.deepEqual(v.$children$[0].$props$, {}); @@ -41,7 +41,7 @@ test('one child node', () => { test('text w/ expression', () => { //
1 {2} 3
- const v = processNode(h('div', null, '1 ', 2, ' 3')) as ProcessedJSXNode; + const v = processNode(h('div', null, '1 ', 2, ' 3') as JSXNodeInternal) as ProcessedJSXNode; assert.deepEqual(v.$children$[0].$type$, '#text'); assert.deepEqual(v.$children$[0].$text$, '1 '); assert.deepEqual(v.$children$[0].$key$, null); @@ -57,7 +57,7 @@ test('text w/ expression', () => { test('text child', () => { //
text
- const v = processNode(h('div', null, 'text')) as ProcessedJSXNode; + const v = processNode(h('div', null, 'text') as JSXNodeInternal) as ProcessedJSXNode; assert.deepEqual(v.$children$[0].$type$, '#text'); assert.deepEqual(v.$children$[0].$text$, 'text'); assert.deepEqual(v.$children$[0].$key$, null); @@ -65,7 +65,7 @@ test('text child', () => { test('no children', () => { //
- const v = processNode(h('div', null)) as ProcessedJSXNode; + const v = processNode(h('div', null) as JSXNodeInternal) as ProcessedJSXNode; assert.deepEqual(v.$children$, []); }); diff --git a/packages/qwik/src/core/render/jsx/jsx-runtime.ts b/packages/qwik/src/core/render/jsx/jsx-runtime.ts index 8c52ccea098..12ee43c6461 100644 --- a/packages/qwik/src/core/render/jsx/jsx-runtime.ts +++ b/packages/qwik/src/core/render/jsx/jsx-runtime.ts @@ -1,4 +1,4 @@ -import type { DevJSX, FunctionComponent, JSXNode } from './types/jsx-node'; +import type { DevJSX, FunctionComponent, JSXNode, JSXNodeInternal } from './types/jsx-node'; import type { QwikJSX } from './types/jsx-qwik'; import { qDev, qRuntimeQrl, seal } from '../../util/qdev'; import { logError, logOnceWarn, logWarn } from '../../util/log'; @@ -33,7 +33,7 @@ export const _jsxQ = ( flags: number, key: string | number | null, dev?: DevJSX -): JSXNode => { +): JSXNodeInternal => { assertString(type, 'jsx type must be a string'); const processed = key == null ? null : String(key); const node = new JSXNodeImpl( @@ -67,7 +67,7 @@ export const _jsxS = ( flags: number, key: string | number | null, dev?: DevJSX -): JSXNode => { +): JSXNodeInternal => { let children: JSXChildren = null; if (mutableProps && 'children' in mutableProps) { children = mutableProps.children as JSXChildren; @@ -87,7 +87,7 @@ export const _jsxC = > flags: number, key: string | number | null, dev?: JsxDevOpts -): JSXNode => { +): JSXNodeInternal => { const processed = key == null ? null : String(key); const props = mutableProps ?? ({} as NonNullable); // In dynamic components, type could be a string @@ -195,7 +195,7 @@ export const RenderOnce: FunctionComponent<{ return new JSXNodeImpl(Virtual, EMPTY_OBJ, null, props.children, static_subtree, key); }; -const validateJSXNode = (node: JSXNode) => { +const validateJSXNode = (node: JSXNodeInternal) => { if (qDev) { const { type, props, immutableProps, children } = node; invoke(undefined, () => { @@ -320,7 +320,7 @@ const printObjectLiteral = (obj: Record) => { .join(', ')} }`; }; -export const isJSXNode = (n: unknown): n is JSXNode => { +export const isJSXNode = (n: unknown): n is JSXNodeInternal => { if (qDev) { if (n instanceof JSXNodeImpl) { return true; diff --git a/packages/qwik/src/core/render/jsx/jsx-runtime.unit.ts b/packages/qwik/src/core/render/jsx/jsx-runtime.unit.ts index 717ec3b076c..9c40b0cfdfa 100644 --- a/packages/qwik/src/core/render/jsx/jsx-runtime.unit.ts +++ b/packages/qwik/src/core/render/jsx/jsx-runtime.unit.ts @@ -1,7 +1,7 @@ import { assert, test } from 'vitest'; import { type ProcessedJSXNode, processNode } from '../dom/render-dom'; import { jsx, isJSXNode, Fragment } from './jsx-runtime'; -import type { FunctionComponent } from './types/jsx-node'; +import type { FunctionComponent, JSXNodeInternal } from './types/jsx-node'; test('map multiple nodes', () => { // @@ -10,7 +10,7 @@ test('map multiple nodes', () => { const v = processNode( jsx('parent', { children: [1, 2].map((n) => jsx('child', { children: n })), - }) + }) as JSXNodeInternal ) as ProcessedJSXNode; assert.deepEqual(v.$children$.length, 2); assert.deepEqual(v.$children$[0].$type$, 'child'); @@ -19,7 +19,9 @@ test('map multiple nodes', () => { test('one child node', () => { // - const v = processNode(jsx('parent', { children: jsx('child', {}) })) as ProcessedJSXNode; + const v = processNode( + jsx('parent', { children: jsx('child', {}) }) as JSXNodeInternal + ) as ProcessedJSXNode; assert.deepEqual(v.$children$.length, 1); assert.deepEqual(v.$children$[0].$type$, 'child'); assert.deepEqual(v.$children$[0].$props$, {}); @@ -28,7 +30,9 @@ test('one child node', () => { test('text w/ expression', () => { //
1 {2} 3
- const v = processNode(jsx('div', { children: ['1 ', 2, ' 3'] })) as ProcessedJSXNode; + const v = processNode( + jsx('div', { children: ['1 ', 2, ' 3'] }) as JSXNodeInternal + ) as ProcessedJSXNode; assert.deepEqual(v.$children$[0].$type$, '#text'); assert.deepEqual(v.$children$[0].$text$, '1 '); assert.deepEqual(v.$children$[0].$key$, null); @@ -44,7 +48,7 @@ test('text w/ expression', () => { test('text child', () => { //
text
- const v = processNode(jsx('div', { children: 'text' })) as ProcessedJSXNode; + const v = processNode(jsx('div', { children: 'text' }) as JSXNodeInternal) as ProcessedJSXNode; assert.deepEqual(v.$children$[0].$type$, '#text'); assert.deepEqual(v.$children$[0].$text$, 'text'); assert.deepEqual(v.$children$[0].$key$, null); @@ -52,7 +56,7 @@ test('text child', () => { test('no children', () => { //
- const v = processNode(jsx('div', {})) as ProcessedJSXNode; + const v = processNode(jsx('div', {}) as JSXNodeInternal) as ProcessedJSXNode; assert.deepEqual(v.$children$, []); }); test('key', () => { diff --git a/packages/qwik/src/core/render/jsx/types/jsx-node.ts b/packages/qwik/src/core/render/jsx/types/jsx-node.ts index a3b493d296e..f6733b52a90 100644 --- a/packages/qwik/src/core/render/jsx/types/jsx-node.ts +++ b/packages/qwik/src/core/render/jsx/types/jsx-node.ts @@ -34,9 +34,18 @@ export interface DevJSX { export interface JSXNode { type: T; props: T extends FunctionComponent ? P : Record; - immutableProps: Record | null; children: JSXChildren | null; - flags: number; key: string | null; dev?: DevJSX; } + +/** + * The internal representation of a JSX node. + * + * @internal + */ +export interface JSXNodeInternal + extends JSXNode { + immutableProps: Record | null; + flags: number; +} diff --git a/packages/qwik/src/core/render/ssr/render-ssr.ts b/packages/qwik/src/core/render/ssr/render-ssr.ts index cd970f7757f..06ca202b6a2 100644 --- a/packages/qwik/src/core/render/ssr/render-ssr.ts +++ b/packages/qwik/src/core/render/ssr/render-ssr.ts @@ -48,7 +48,7 @@ import { stringifyStyle, } from '../execute-component'; import { Virtual, _jsxC, _jsxQ, createJSXError, isJSXNode } from '../jsx/jsx-runtime'; -import type { FunctionComponent, JSXNode, JSXOutput } from '../jsx/types/jsx-node'; +import type { FunctionComponent, JSXNode, JSXNodeInternal, JSXOutput } from '../jsx/types/jsx-node'; import type { ClassList, JSXChildren } from '../jsx/types/jsx-qwik-attributes'; import { InternalSSRStream, SSRRaw } from '../jsx/utils.public'; import type { RenderContext } from '../types'; @@ -193,7 +193,7 @@ export const _renderSSR = async (node: JSXOutput, opts: RenderSSROptions) => { const hash = () => Math.random().toString(36).slice(2); const renderRoot = async ( - node: JSXNode, + node: JSXNodeInternal, rCtx: RenderContext, ssrCtx: SSRContext, stream: StreamWriter, @@ -531,7 +531,7 @@ const createMockQContext = (nodeType: 1 | 111) => { }; const renderNode = ( - node: JSXNode, + node: JSXNodeInternal, rCtx: RenderContext, ssrCtx: SSRContext, stream: StreamWriter, @@ -837,11 +837,17 @@ This goes against the HTML spec: https://html.spec.whatwg.org/multipage/dom.html } if (tagName === SSRRaw) { - stream.write((node as JSXNode).props.data); + stream.write((node as JSXNodeInternal).props.data); return; } if (tagName === InternalSSRStream) { - return renderGenerator(node as JSXNode, rCtx, ssrCtx, stream, flags); + return renderGenerator( + node as JSXNodeInternal, + rCtx, + ssrCtx, + stream, + flags + ); } // Inline component const res = invoke(