Skip to content

Commit 18f0aee

Browse files
committed
Merge remote-tracking branch 'origin/build/v2' into v2-merge-main
2 parents bfc05c7 + 95e34f8 commit 18f0aee

23 files changed

+850
-72
lines changed

.changeset/solid-olives-know.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': patch
3+
---
4+
5+
fix: reactivity after spreading props

packages/qwik/src/core/internal.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ export {
4848
_jsxS,
4949
_jsxSorted,
5050
_jsxSplit,
51+
_getVarProps,
52+
_getConstProps,
5153
} from './shared/jsx/jsx-runtime';
5254
export { _fnSignal } from './shared/qrl/inlined-fn';
5355
export { _SharedContainer } from './shared/shared-container';

packages/qwik/src/core/qwik.core.api.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,12 @@ export type FunctionComponent<P = unknown> = {
341341
renderFn(props: P, key: string | null, flags: number, dev?: DevJSX): JSXOutput;
342342
}['renderFn'];
343343

344+
// Warning: (ae-forgotten-export) The symbol "PropsProxy" needs to be exported by the entry point index.d.ts
345+
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
346+
//
347+
// @internal (undocumented)
348+
export const _getConstProps: <T, JSX>(props: PropsProxy | Record<string, unknown> | null | undefined) => Props | null;
349+
344350
// @internal (undocumented)
345351
export const _getContextContainer: () => ClientContainer | undefined;
346352

@@ -367,6 +373,9 @@ export const getPlatform: () => CorePlatform;
367373
// @internal (undocumented)
368374
export function _getQContainerElement(element: Element | _VNode): Element | null;
369375

376+
// @internal (undocumented)
377+
export const _getVarProps: <T, JSX>(props: PropsProxy | Record<string, unknown> | null | undefined) => Props | null;
378+
370379
// @public
371380
function h<TYPE extends string | FunctionComponent<PROPS>, PROPS extends {} = {}>(type: TYPE, props?: PROPS | null, ...children: any[]): JSXNode<TYPE>;
372381
export { h as createElement }
@@ -447,8 +456,6 @@ export function _isStringifiable(value: unknown): value is _Stringifiable;
447456
// @internal (undocumented)
448457
export const _isTask: (value: any) => value is Task;
449458

450-
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
451-
//
452459
// @public
453460
const jsx: <T extends string | FunctionComponent<any>>(type: T, props: T extends FunctionComponent<infer PROPS> ? PROPS : Props, key?: string | number | null) => JSXNode<T>;
454461
export { jsx }
@@ -892,8 +899,6 @@ export interface ResourceResolved<T> {
892899
// @public (undocumented)
893900
export type ResourceReturn<T> = ResourcePending<T> | ResourceResolved<T> | ResourceRejected<T>;
894901

895-
// Warning: (ae-forgotten-export) The symbol "PropsProxy" needs to be exported by the entry point index.d.ts
896-
//
897902
// @internal (undocumented)
898903
export const _restProps: (props: PropsProxy, omit: string[], target?: Props) => Props;
899904

packages/qwik/src/core/shared/jsx/jsx-runtime.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,4 +427,28 @@ export const directGetPropsProxyProp = <T, JSX>(jsx: JSXNodeInternal<JSX>, prop:
427427
) as T;
428428
};
429429

430+
/** @internal */
431+
export const _getVarProps = <T, JSX>(
432+
props: PropsProxy | Record<string, unknown> | null | undefined
433+
): Props | null => {
434+
if (!props) {
435+
return null;
436+
}
437+
return _VAR_PROPS in props
438+
? 'children' in props
439+
? { ...props[_VAR_PROPS], children: props.children }
440+
: props[_VAR_PROPS]
441+
: props;
442+
};
443+
444+
/** @internal */
445+
export const _getConstProps = <T, JSX>(
446+
props: PropsProxy | Record<string, unknown> | null | undefined
447+
): Props | null => {
448+
if (!props) {
449+
return null;
450+
}
451+
return _CONST_PROPS in props ? props[_CONST_PROPS] : null;
452+
};
453+
430454
export { jsx as jsxs };

packages/qwik/src/core/tests/attributes.spec.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -423,11 +423,11 @@ describe.each([
423423

424424
expect(vNode).toMatchVDOM(
425425
<Component ssr-required>
426-
<Fragment ssr-required>
427-
<Component ssr-required>
426+
<Fragment>
427+
<Component>
428428
<button data-selected id="button-0"></button>
429429
</Component>
430-
<Component ssr-required>
430+
<Component>
431431
<button id="button-1"></button>
432432
</Component>
433433
</Fragment>
@@ -438,11 +438,11 @@ describe.each([
438438

439439
expect(vNode).toMatchVDOM(
440440
<Component ssr-required>
441-
<Fragment ssr-required>
442-
<Component ssr-required>
441+
<Fragment>
442+
<Component>
443443
<button id="button-0"></button>
444444
</Component>
445-
<Component ssr-required>
445+
<Component>
446446
<button data-selected id="button-1"></button>
447447
</Component>
448448
</Fragment>

packages/qwik/src/core/tests/component.spec.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2386,6 +2386,18 @@ describe.each([
23862386
expect(document.body.innerHTML).toContain('I am the innerHTML content!');
23872387
});
23882388

2389+
it('should not throw when props are null', async () => {
2390+
const Child = component$((props: any) => {
2391+
props = (globalThis as any).stuff ? (globalThis as any).foo : (globalThis as any).bar;
2392+
return <div {...props} />;
2393+
});
2394+
const Cmp = component$(() => {
2395+
return <Child />;
2396+
});
2397+
const { document } = await render(<Cmp />, { debug });
2398+
await expect(document.querySelector('div')).toMatchDOM(<div />);
2399+
});
2400+
23892401
describe('regression', () => {
23902402
it('#3643', async () => {
23912403
const Issue3643 = component$(() => {

packages/qwik/src/core/tests/use-task.spec.tsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
Fragment as Component,
33
Fragment,
44
Fragment as Signal,
5+
Slot,
56
component$,
67
isServer,
78
useSignal,
@@ -323,6 +324,47 @@ describe.each([
323324
'Child of "A" (2)', // toggle
324325
]);
325326
});
327+
328+
it('should not rerun on track if the value is not a signal', async () => {
329+
(globalThis as any).counter = 0;
330+
const OtpBase = component$((props: any) => {
331+
useTask$(({ track }) => {
332+
track(() => props.disabled);
333+
(globalThis as any).counter++;
334+
});
335+
336+
return (
337+
<div>
338+
<Slot />
339+
</div>
340+
);
341+
});
342+
343+
const Cmp = component$(() => {
344+
const isDisabled = useSignal(false);
345+
346+
const OtpRoot = (props: any) => {
347+
return <OtpBase {...props}>{props.children}</OtpBase>;
348+
};
349+
return (
350+
<>
351+
<OtpRoot disabled={isDisabled.value} />
352+
353+
<button type="button" onClick$={() => (isDisabled.value = !isDisabled.value)}>
354+
Disable OTP
355+
</button>
356+
</>
357+
);
358+
});
359+
360+
const { document } = await render(<Cmp />, { debug });
361+
await trigger(document.body, 'button', 'click');
362+
await trigger(document.body, 'button', 'click');
363+
await trigger(document.body, 'button', 'click');
364+
await trigger(document.body, 'button', 'click');
365+
expect((globalThis as any).counter).toBe(5);
366+
(globalThis as any).counter = undefined;
367+
});
326368
});
327369
describe('queue', () => {
328370
it('should execute dependant tasks', async () => {

packages/qwik/src/optimizer/core/src/snapshots/qwik_core__test__example_jsx.snap

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ export const Foo = component$((props) => {
5050
============================= test.js ==
5151

5252
import { _jsxSorted } from "@qwik.dev/core";
53+
import { _getVarProps } from "@qwik.dev/core";
54+
import { _getConstProps } from "@qwik.dev/core";
5355
import { _jsxSplit } from "@qwik.dev/core";
5456
import { componentQrl } from "@qwik.dev/core";
5557
import { qrl } from "@qwik.dev/core";
@@ -59,16 +61,16 @@ export const Lightweight = (props)=>{
5961
return /*#__PURE__*/ _jsxSorted("div", null, null, /*#__PURE__*/ _jsxSorted(_Fragment, null, null, [
6062
/*#__PURE__*/ _jsxSorted("div", null, null, null, 3, null),
6163
/*#__PURE__*/ _jsxSplit("button", {
62-
...props
63-
}, null, null, 0, null)
64+
..._getVarProps(props)
65+
}, _getConstProps(props), null, 0, null)
6466
], 1, "u6_0"), 1, "u6_1");
6567
};
6668
export const Foo = /*#__PURE__*/ componentQrl(/*#__PURE__*/ qrl(i_HTDRsvUbLiE, "Foo_component_HTDRsvUbLiE"), {
6769
tagName: "my-foo"
6870
});
6971

7072

71-
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;;AAGA,OAAO,MAAM,cAAc,CAAC;IAC3B,qBACC,WAAC,iCACA;sBACC,WAAC;sBACD,UAAC;YAAQ,GAAG,KAAK;;;AAIrB,EAAE;AAEF,OAAO,MAAM,oBAAM,4EAuBhB;IACF,SAAS;AACV,GAAG\"}")
73+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;;;;AAGA,OAAO,MAAM,cAAc,CAAC;IAC3B,qBACC,WAAC,iCACA;sBACC,WAAC;sBACD,UAAC;4BAAW;0BAAA;;AAIhB,EAAE;AAEF,OAAO,MAAM,oBAAM,4EAuBhB;IACF,SAAS;AACV,GAAG\"}")
7274
============================= test.tsx_Foo_component_HTDRsvUbLiE.js (ENTRY POINT)==
7375

7476
import { qrl } from "@qwik.dev/core";
@@ -109,6 +111,8 @@ Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"ma
109111
import { useLexicalScope } from "@qwik.dev/core";
110112
import { Lightweight } from "./test";
111113
import { Fragment as _Fragment } from "@qwik.dev/core/jsx-runtime";
114+
import { _getConstProps } from "@qwik.dev/core";
115+
import { _getVarProps } from "@qwik.dev/core";
112116
import { _jsxSorted } from "@qwik.dev/core";
113117
import { _jsxSplit } from "@qwik.dev/core";
114118
export const Foo_component_1_DvU6FitWglY = ()=>{
@@ -128,8 +132,8 @@ export const Foo_component_1_DvU6FitWglY = ()=>{
128132
/*#__PURE__*/ _jsxSorted("div", null, {
129133
class: "class"
130134
}, /*#__PURE__*/ _jsxSplit(Lightweight, {
131-
...props
132-
}, null, null, 0, "u6_3"), 1, null),
135+
..._getVarProps(props)
136+
}, _getConstProps(props), null, 0, "u6_3"), 1, null),
133137
/*#__PURE__*/ _jsxSorted("div", null, {
134138
class: "class"
135139
}, [
@@ -144,7 +148,7 @@ export const Foo_component_1_DvU6FitWglY = ()=>{
144148
};
145149

146150

147-
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;2CAeU;;IACR,qBACC,WAAC;sBACA;0BACC,WAAC;gBAAI,OAAM;;0BACX,WAAC;gBAAI,OAAM;;0BACX,WAAC;gBAAI,OAAM;eAAQ;;sBAEpB,WAAC;YAAI,OAAM;yBACV,UAAC;YAAa,GAAG,KAAK;;sBAEvB,WAAC;YAAI,OAAM;;0BACV,WAAC;0BACD,WAAC;0BACD,WAAC;;sBAEF,WAAC;YAAI,OAAM;WACT\"}")
151+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;;;2CAeU;;IACR,qBACC,WAAC;sBACA;0BACC,WAAC;gBAAI,OAAM;;0BACX,WAAC;gBAAI,OAAM;;0BACX,WAAC;gBAAI,OAAM;eAAQ;;sBAEpB,WAAC;YAAI,OAAM;yBACV,UAAC;4BAAgB;0BAAA;sBAElB,WAAC;YAAI,OAAM;;0BACV,WAAC;0BACD,WAAC;0BACD,WAAC;;sBAEF,WAAC;YAAI,OAAM;WACT\"}")
148152
/*
149153
{
150154
"origin": "test.tsx",

packages/qwik/src/optimizer/core/src/snapshots/qwik_core__test__example_props_optimization.snap

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ import { useLexicalScope } from "@qwik.dev/core";
5757
import { inlinedQrl } from "@qwik.dev/core";
5858
import { _fnSignal } from "@qwik.dev/core";
5959
import { _wrapProp } from "@qwik.dev/core";
60+
import { _getVarProps } from "@qwik.dev/core";
61+
import { _getConstProps } from "@qwik.dev/core";
6062
import { _jsxSplit } from "@qwik.dev/core";
6163
import { _jsxSorted } from "@qwik.dev/core";
6264
export const Works = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props)=>{
@@ -86,8 +88,9 @@ export const Works = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl((props)
8688
props
8789
], "{some:p0.some??1+2}"),
8890
class: _wrapProp(props, "count"),
89-
...rest
91+
..._getVarProps(rest)
9092
}, {
93+
..._getConstProps(rest),
9194
override: true
9295
}, _wrapProp(props, "count"), 0, "u6_0");
9396
}, "Works_component_t45qL4vNGv0"));
@@ -119,7 +122,7 @@ export const NoWorks3 = /*#__PURE__*/ componentQrl(/*#__PURE__*/ inlinedQrl(({ c
119122
}, "NoWorks3_component_fc13h5yYn14"));
120123

121124

122-
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;;;;;AAGA,OAAO,MAAM,sBAAQ,sCAAW;;;;;;;;IAO/B,QAAQ,GAAG,OAHX,aAFA,QAAO;IAMP,oCAAS,CAAC,EAAC,KAAK,EAAC;;QAChB,MAAM,UARP;QASC,QAAQ,GAAG,OATZ,OASoB,YANpB,aAFA,QAAO,SAGP,gBAAqB;;;;;IAOrB,qBACC,UAAC;QAAI,IAAI,qBAXV,QAAO;;;QAWW,MAAM,kBAAE,CAAA;gBAAE,IAAI,KAXhC,QAAO;YAW0B,CAAA;;;QAAG,KAAK;QAAU,GAAG,IAAI;;QAAE,QAAQ;;AAErE,mCAAG;AAEH,OAAO,MAAM,yBAAW,sCAAW,CAAC,EAAC,KAAK,EAAE,OAAO,EAAC,GAAG,EAAC,EAAC;IACxD,QAAQ,GAAG,CAAC;IACZ,oCAAS,CAAC,EAAC,KAAK,EAAC;;QAChB,MAAM,IAAM;QACZ,QAAQ,GAAG,CAAC;;;;IAEb,qBACC,WAAC;QAAI,OAAO;aAAQ;AAEtB,sCAAG;AAEH,OAAO,MAAM,yBAAW,sCAAW,CAAC,EAAC,KAAK,EAAE,QAAQ,MAAM,EAAC;IAC1D,QAAQ,GAAG,CAAC;IACZ,oCAAS,CAAC,EAAC,KAAK,EAAC;;QAChB,MAAM,IAAM;QACZ,QAAQ,GAAG,CAAC;;;;IAEb,qBACC,WAAC;QAAI,OAAO;aAAQ;AAEtB,sCAAG\"}")
125+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;;;;;;;AAGA,OAAO,MAAM,sBAAQ,sCAAW;;;;;;;;IAO/B,QAAQ,GAAG,OAHX,aAFA,QAAO;IAMP,oCAAS,CAAC,EAAC,KAAK,EAAC;;QAChB,MAAM,UARP;QASC,QAAQ,GAAG,OATZ,OASoB,YANpB,aAFA,QAAO,SAGP,gBAAqB;;;;;IAOrB,qBACC,UAAC;QAAI,IAAI,qBAXV,QAAO;;;QAWW,MAAM,kBAAE,CAAA;gBAAE,IAAI,KAXhC,QAAO;YAW0B,CAAA;;;QAAG,KAAK;wBAAa;;0BAAA;QAAM,QAAQ;;AAErE,mCAAG;AAEH,OAAO,MAAM,yBAAW,sCAAW,CAAC,EAAC,KAAK,EAAE,OAAO,EAAC,GAAG,EAAC,EAAC;IACxD,QAAQ,GAAG,CAAC;IACZ,oCAAS,CAAC,EAAC,KAAK,EAAC;;QAChB,MAAM,IAAM;QACZ,QAAQ,GAAG,CAAC;;;;IAEb,qBACC,WAAC;QAAI,OAAO;aAAQ;AAEtB,sCAAG;AAEH,OAAO,MAAM,yBAAW,sCAAW,CAAC,EAAC,KAAK,EAAE,QAAQ,MAAM,EAAC;IAC1D,QAAQ,GAAG,CAAC;IACZ,oCAAS,CAAC,EAAC,KAAK,EAAC;;QAChB,MAAM,IAAM;QACZ,QAAQ,GAAG,CAAC;;;;IAEb,qBACC,WAAC;QAAI,OAAO;aAAQ;AAEtB,sCAAG\"}")
123126
== DIAGNOSTICS ==
124127

125128
[]

packages/qwik/src/optimizer/core/src/snapshots/qwik_core__test__example_spread_jsx.snap

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"ma
5454

5555
import { Fragment as _Fragment } from "@qwik.dev/core/jsx-runtime";
5656
import { createElement as _createElement } from "@qwik.dev/core";
57+
import { _getConstProps } from "@qwik.dev/core";
58+
import { _getVarProps } from "@qwik.dev/core";
5759
import { _jsxSorted } from "@qwik.dev/core";
5860
import { _jsxSplit } from "@qwik.dev/core";
5961
import { _wrapProp } from "@qwik.dev/core";
@@ -78,8 +80,8 @@ export const RouterHead_component_DPA76mgIou0 = ()=>{
7880
href: "/favicon.svg"
7981
}, null, 3, null),
8082
head.meta.map((m)=>/*#__PURE__*/ _jsxSplit("meta", {
81-
...m
82-
}, null, null, 0, "u6_0")),
83+
..._getVarProps(m)
84+
}, _getConstProps(m), null, 0, "u6_0")),
8385
head.links.map((l)=>/*#__PURE__*/ _createElement("link", {
8486
...l,
8587
key: l.key
@@ -93,7 +95,7 @@ export const RouterHead_component_DPA76mgIou0 = ()=>{
9395
};
9496

9597

96-
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;;;gDAOqC;IACpC,MAAM,OAAO;IACb,MAAM,MAAM;IAEZ,qBACA;sBACC,WAAC,qBAAO,KAAK,KAAK;sBAElB,WAAC;YAAK,KAAI;YAAY,IAAI,YAAE;;sBAC5B,WAAC;YAAK,MAAK;YAAW,SAAQ;;sBAC9B,WAAC;YAAK,KAAI;YAAO,MAAK;YAAgB,MAAK;;QAE1C,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,kBACf,UAAC;gBAAM,GAAG,CAAC;;QAGX,KAAK,KAAK,CAAC,GAAG,CAAC,CAAC,kBAChB,eAAC;gBAAM,GAAG,CAAC;gBAAE,KAAK,EAAE,GAAG;;QAGvB,KAAK,MAAM,CAAC,GAAG,CAAC,CAAC,kBACjB,eAAC;gBAAO,GAAG,EAAE,KAAK;gBAAE,yBAAyB,EAAE,KAAK;gBAAE,KAAK,EAAE,GAAG;;;AAInE\"}")
98+
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;;;;;gDAOqC;IACpC,MAAM,OAAO;IACb,MAAM,MAAM;IAEZ,qBACA;sBACC,WAAC,qBAAO,KAAK,KAAK;sBAElB,WAAC;YAAK,KAAI;YAAY,IAAI,YAAE;;sBAC5B,WAAC;YAAK,MAAK;YAAW,SAAQ;;sBAC9B,WAAC;YAAK,KAAI;YAAO,MAAK;YAAgB,MAAK;;QAE1C,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,kBACf,UAAC;gCAAS;8BAAA;QAGV,KAAK,KAAK,CAAC,GAAG,CAAC,CAAC,kBAChB,eAAC;gBAAM,GAAG,CAAC;gBAAE,KAAK,EAAE,GAAG;;QAGvB,KAAK,MAAM,CAAC,GAAG,CAAC,CAAC,kBACjB,eAAC;gBAAO,GAAG,EAAE,KAAK;gBAAE,yBAAyB,EAAE,KAAK;gBAAE,KAAK,EAAE,GAAG;;;AAInE\"}")
9799
/*
98100
{
99101
"origin": "test.tsx",

0 commit comments

Comments
 (0)