Skip to content

Commit

Permalink
fix: convert destructured array's props to signal
Browse files Browse the repository at this point in the history
  • Loading branch information
Varixo committed Dec 31, 2024
1 parent c029c32 commit 742d83f
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/unlucky-dodos-grab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@qwik.dev/core': patch
---

fix: convert destructured array's props to signal
3 changes: 2 additions & 1 deletion packages/qwik/src/core/shared/platform/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { QError, qError } from '../error/error';
import { getSymbolHash } from '../qrl/qrl-class';
import { qDynamicPlatform } from '../utils/qdev';
import type { CorePlatform } from './types';
import { QBaseAttr } from '../utils/markers';

export const createPlatform = (): CorePlatform => {
return {
Expand Down Expand Up @@ -65,7 +66,7 @@ export const createPlatform = (): CorePlatform => {
*/
export const toUrl = (doc: Document, containerEl: Element, url: string | URL): URL => {
const baseURI = doc.baseURI;
const base = new URL(containerEl.getAttribute('q:base') ?? baseURI, baseURI);
const base = new URL(containerEl.getAttribute(QBaseAttr) ?? baseURI, baseURI);
return new URL(url, base);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
---
source: packages/qwik/src/optimizer/core/src/test.rs
assertion_line: 4118
expression: output
snapshot_kind: text
---
==INPUT==


import { component$, useStore, useTask$ } from '@qwik.dev/core';

export const Input = component$<{error: string, error2: string, error3: string}>(
(props) => {
useTask$(({ track }) => {
track(() => props.error);
track(() => props.error2);
track(() => props.error3);
});

return (
<>
</>
);
}
);

export default component$(() => {
const [store] = [useStore({errors: {}})];
const [[store2]] = [[useStore({errors: {}})]];
const { store3 } = { store3: useStore({errors: {}}) };

return (
<div>
<button onClick$={() => {
store.errors.test = store.errors.test ? undefined : 'ERROR TEST';
}}>click</button>
<Input error={store.errors.test} error2={store2.errors.test} error3={store3.errors.test} />
</div>
);
});

============================= test.js ==

import { componentQrl } from "@qwik.dev/core";
import { qrl } from "@qwik.dev/core";
export const Input = /*#__PURE__*/ componentQrl(/*#__PURE__*/ qrl(()=>import("./test.tsx_Input_component_9metqqaxlN8"), "Input_component_9metqqaxlN8"));
export default /*#__PURE__*/ componentQrl(/*#__PURE__*/ qrl(()=>import("./test.tsx_test_component_LUXeXe0DQrg"), "test_component_LUXeXe0DQrg"));


Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;AAGE,OAAO,MAAM,sBAAQ,qHAanB;AAEF,6BAAe,mHAaZ\"}")
============================= test.tsx_test_component_LUXeXe0DQrg.js (ENTRY POINT)==

import { Input } from "./test";
import { _fnSignal } from "@qwik.dev/core";
import { _jsxSorted } from "@qwik.dev/core";
import { qrl } from "@qwik.dev/core";
import { useStore } from "@qwik.dev/core";
export const test_component_LUXeXe0DQrg = ()=>{
const [store] = [
useStore({
errors: {}
})
];
const [[store2]] = [
[
useStore({
errors: {}
})
]
];
const { store3 } = {
store3: useStore({
errors: {}
})
};
return /*#__PURE__*/ _jsxSorted("div", null, null, [
/*#__PURE__*/ _jsxSorted("button", null, {
onClick$: /*#__PURE__*/ qrl(()=>import("./test.tsx_test_component_div_button_onClick_TfpwI5Xb2NU"), "test_component_div_button_onClick_TfpwI5Xb2NU", [
store
])
}, "click", 3, null),
/*#__PURE__*/ _jsxSorted(Input, null, {
error: _fnSignal((p0)=>p0.errors.test, [
store
], "p0.errors.test"),
error2: _fnSignal((p0)=>p0.errors.test, [
store2
], "p0.errors.test"),
error3: _fnSignal((p0)=>p0.errors.test, [
store3
], "p0.errors.test")
}, null, 3, "u6_1")
], 1, "u6_2");
};


Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;;0CAkB4B;IACzB,MAAM,CAAC,MAAM,GAAG;QAAC,SAAS;YAAC,QAAQ,CAAC;QAAC;KAAG;IACxC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG;QAAC;YAAC,SAAS;gBAAC,QAAQ,CAAC;YAAC;SAAG;KAAC;IAC7C,MAAM,EAAE,MAAM,EAAE,GAAG;QAAE,QAAQ,SAAS;YAAC,QAAQ,CAAC;QAAC;IAAG;IAEpD,qBACC,WAAC;sBACA,WAAC;YAAO,QAAQ;;;WAEb;sBACH,WAAC;YAAM,KAAK,kBAAE,GAAM,MAAM,CAAC,IAAI;;;YAAE,MAAM,kBAAE,GAAO,MAAM,CAAC,IAAI;;;YAAE,MAAM,kBAAE,GAAO,MAAM,CAAC,IAAI;;;;;AAG1F\"}")
/*
{
"origin": "test.tsx",
"name": "test_component_LUXeXe0DQrg",
"entry": null,
"displayName": "test.tsx_test_component",
"hash": "LUXeXe0DQrg",
"canonicalFilename": "test.tsx_test_component_LUXeXe0DQrg",
"path": "",
"extension": "js",
"parent": null,
"ctxKind": "function",
"ctxName": "component$",
"captures": false,
"loc": [
380,
807
]
}
*/
============================= test.tsx_test_component_div_button_onClick_TfpwI5Xb2NU.js (ENTRY POINT)==

import { useLexicalScope } from "@qwik.dev/core";
export const test_component_div_button_onClick_TfpwI5Xb2NU = ()=>{
const [store] = useLexicalScope();
store.errors.test = store.errors.test ? undefined : 'ERROR TEST';
};


Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";6DAyBuB;;IACjB,MAAM,MAAM,CAAC,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,GAAG,YAAY\"}")
/*
{
"origin": "test.tsx",
"name": "test_component_div_button_onClick_TfpwI5Xb2NU",
"entry": null,
"displayName": "test.tsx_test_component_div_button_onClick",
"hash": "TfpwI5Xb2NU",
"canonicalFilename": "test.tsx_test_component_div_button_onClick_TfpwI5Xb2NU",
"path": "",
"extension": "js",
"parent": "test_component_LUXeXe0DQrg",
"ctxKind": "eventHandler",
"ctxName": "onClick$",
"captures": true,
"loc": [
587,
673
]
}
*/
============================= test.tsx_Input_component_useTask_Sbgs9Wtfkt0.js (ENTRY POINT)==

import { useLexicalScope } from "@qwik.dev/core";
export const Input_component_useTask_Sbgs9Wtfkt0 = ({ track })=>{
const [props] = useLexicalScope();
track(()=>props.error);
track(()=>props.error2);
track(()=>props.error3);
};
export { _hW } from "@qwik.dev/core";


Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";mDAKa,CAAC,EAAE,KAAK,EAAE;;IAClB,MAAM,IAAM,MAAM,KAAK;IACvB,MAAM,IAAM,MAAM,MAAM;IACxB,MAAM,IAAM,MAAM,MAAM\"}")
/*
{
"origin": "test.tsx",
"name": "Input_component_useTask_Sbgs9Wtfkt0",
"entry": null,
"displayName": "test.tsx_Input_component_useTask",
"hash": "Sbgs9Wtfkt0",
"canonicalFilename": "test.tsx_Input_component_useTask_Sbgs9Wtfkt0",
"path": "",
"extension": "js",
"parent": "Input_component_9metqqaxlN8",
"ctxKind": "function",
"ctxName": "useTask$",
"captures": true,
"loc": [
183,
300
]
}
*/
============================= test.tsx_Input_component_9metqqaxlN8.js (ENTRY POINT)==

import { Fragment as _Fragment } from "@qwik.dev/core/jsx-runtime";
import { _jsxSorted } from "@qwik.dev/core";
import { qrl } from "@qwik.dev/core";
import { useTaskQrl } from "@qwik.dev/core";
export const Input_component_9metqqaxlN8 = (props)=>{
useTaskQrl(/*#__PURE__*/ qrl(()=>import("./test.tsx_Input_component_useTask_Sbgs9Wtfkt0"), "Input_component_useTask_Sbgs9Wtfkt0", [
props
]));
return /*#__PURE__*/ _jsxSorted(_Fragment, null, null, null, 3, "u6_0");
};


Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;;2CAIG,CAAC;IACA;;;IAMA,qBACC;AAGF\"}")
/*
{
"origin": "test.tsx",
"name": "Input_component_9metqqaxlN8",
"entry": null,
"displayName": "test.tsx_Input_component",
"hash": "9metqqaxlN8",
"canonicalFilename": "test.tsx_Input_component_9metqqaxlN8",
"path": "",
"extension": "js",
"parent": null,
"ctxKind": "function",
"ctxName": "component$",
"captures": false,
"loc": [
157,
345
]
}
*/
== DIAGNOSTICS ==

[]
43 changes: 43 additions & 0 deletions packages/qwik/src/optimizer/core/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3974,6 +3974,49 @@ fn rename_builder_io() {
});
}

#[test]
fn should_wrap_prop_from_destructured_array() {
test_input!(TestInput {
code: r#"
import { component$, useStore, useTask$ } from '@qwik.dev/core';
export const Input = component$<{error: string, error2: string, error3: string}>(
(props) => {
useTask$(({ track }) => {
track(() => props.error);
track(() => props.error2);
track(() => props.error3);
});
return (
<>
</>
);
}
);
export default component$(() => {
const [store] = [useStore({errors: {}})];
const [[store2]] = [[useStore({errors: {}})]];
const { store3 } = { store3: useStore({errors: {}}) };
return (
<div>
<button onClick$={() => {
store.errors.test = store.errors.test ? undefined : 'ERROR TEST';
}}>click</button>
<Input error={store.errors.test} error2={store2.errors.test} error3={store3.errors.test} />
</div>
);
});
"#
.to_string(),
transpile_jsx: true,
transpile_ts: true,
..TestInput::default()
});
}

// TODO(misko): Make this test work by implementing strict serialization.
// #[test]
// fn example_of_synchronous_qrl_that_cant_be_serialized() {
Expand Down
17 changes: 7 additions & 10 deletions packages/qwik/src/optimizer/core/src/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1734,17 +1734,13 @@ impl<'a> Fold for QwikTransform<'a> {
fn fold_var_decl(&mut self, node: ast::VarDecl) -> ast::VarDecl {
if let Some(current_scope) = self.decl_stack.last_mut() {
for decl in &node.decls {
let mut identifiers = Vec::with_capacity(node.decls.len() + 2);
let mut identifiers: Vec<(Id, Span)> = Vec::with_capacity(node.decls.len() + 2);
collect_from_pat(&decl.name, &mut identifiers);
let ident_type = if node.kind == ast::VarDeclKind::Const
&& matches!(decl.name, ast::Pat::Ident(_))
&& is_return_static(&decl.init)
{
IdentType::Var(true)
} else {
IdentType::Var(false)
};
current_scope.extend(identifiers.into_iter().map(|(id, _)| (id, ident_type)));
let is_const = node.kind == ast::VarDeclKind::Const && is_return_static(&decl.init);

for ident in identifiers {
current_scope.push((ident.0, IdentType::Var(is_const)));
}
}
}
node.fold_children_with(self)
Expand Down Expand Up @@ -2318,6 +2314,7 @@ fn is_return_static(expr: &Option<Box<ast::Expr>>) -> bool {
callee: ast::Callee::Expr(box ast::Expr::Ident(ident)),
..
})) => ident.sym.ends_with('$') || ident.sym.ends_with("Qrl") || ident.sym.starts_with("use"),
Some(box (ast::Expr::Array(_) | ast::Expr::Object(_))) => true,
Some(_) => false,
None => true,
}
Expand Down

0 comments on commit 742d83f

Please sign in to comment.