diff --git a/.changeset/gentle-melons-pretend.md b/.changeset/gentle-melons-pretend.md new file mode 100644 index 00000000000..9d490c6017c --- /dev/null +++ b/.changeset/gentle-melons-pretend.md @@ -0,0 +1,5 @@ +--- +'@qwik.dev/core': patch +--- + +fix: convert destructured string prop to props variable diff --git a/packages/qwik/src/optimizer/core/src/props_destructuring.rs b/packages/qwik/src/optimizer/core/src/props_destructuring.rs index d316cf99356..2bd05211a29 100644 --- a/packages/qwik/src/optimizer/core/src/props_destructuring.rs +++ b/packages/qwik/src/optimizer/core/src/props_destructuring.rs @@ -4,6 +4,7 @@ use crate::code_move::create_return_stmt; use crate::collector::{new_ident_from_id, GlobalCollect, Id}; use crate::is_const::is_const_expr; use crate::words::*; +use swc_atoms::Atom; use swc_atoms::JsWord; use swc_common::DUMMY_SP; use swc_ecmascript::ast; @@ -315,15 +316,30 @@ fn transform_pat( } } ast::ObjectPatProp::KeyValue(ref v) => { - if let ast::PropName::Ident(ref key) = v.key { + if matches!(v.key, ast::PropName::Ident(_) | ast::PropName::Str(_)) { + let (key_atom, key_ident) = match &v.key { + ast::PropName::Str(ref key) => { + let key_str: &str = &key.value; + let key_atom = Atom::from(key_str); + ( + key_atom.clone(), + ast::IdentName::new(key_atom.clone(), DUMMY_SP), + ) + } + ast::PropName::Ident(ref key) => (key.sym.clone(), key.clone()), + _ => { + continue; + } + }; match &v.value { box ast::Pat::Ident(ref ident) => { let access = ast::Expr::Member(ast::MemberExpr { obj: Box::new(new_ident.clone()), - prop: ast::MemberProp::Ident(key.clone()), + prop: ast::MemberProp::Ident(key_ident), span: DUMMY_SP, }); - local.push((id!(ident), key.sym.clone(), access)); + + local.push((id!(ident), key_atom.clone(), access)); } box ast::Pat::Assign(ast::AssignPat { left: box ast::Pat::Ident(ident), @@ -333,12 +349,12 @@ fn transform_pat( if is_const_expr(value.as_ref(), props_transform.global_collect, None) { let access = ast::Expr::Member(ast::MemberExpr { obj: Box::new(new_ident.clone()), - prop: ast::MemberProp::Ident(key.clone()), + prop: ast::MemberProp::Ident(key_ident), span: DUMMY_SP, }); local.push(( id!(ident.id), - key.sym.clone(), + key_atom.clone(), ast::Expr::Bin(ast::BinExpr { span: DUMMY_SP, op: ast::BinaryOp::NullishCoalescing, diff --git a/packages/qwik/src/optimizer/core/src/snapshots/qwik_core__test__destructure_args_colon_props.snap b/packages/qwik/src/optimizer/core/src/snapshots/qwik_core__test__destructure_args_colon_props.snap new file mode 100644 index 00000000000..652a56709b5 --- /dev/null +++ b/packages/qwik/src/optimizer/core/src/snapshots/qwik_core__test__destructure_args_colon_props.snap @@ -0,0 +1,61 @@ +--- +source: packages/qwik/src/optimizer/core/src/test.rs +assertion_line: 3651 +expression: output +snapshot_kind: text +--- +==INPUT== + + + import { component$ } from "@qwik.dev/core"; + export default component$((props) => { + const { 'bind:value': bindValue } = props; + return ( + <> + {bindValue} + + ); + }); + +============================= test.js == + +import { componentQrl } from "@qwik.dev/core"; +import { qrl } from "@qwik.dev/core"; +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\":\";;AAEE,6BAAe,mHAOZ\"}") +============================= test.tsx_test_component_LUXeXe0DQrg.js (ENTRY POINT)== + +import { Fragment as _Fragment } from "@qwik.dev/core/jsx-runtime"; +import { _jsxSorted } from "@qwik.dev/core"; +import { _wrapProp } from "@qwik.dev/core"; +export const test_component_LUXeXe0DQrg = (props)=>{ + return /*#__PURE__*/ _jsxSorted(_Fragment, null, null, _wrapProp(props, "bind:value"), 3, "u6_0"); +}; + + +Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;0CAE4B,CAAC;IAE1B,qBACC,4CAFmC;AAMrC\"}") +/* +{ + "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": [ + 77, + 188 + ] +} +*/ +== DIAGNOSTICS == + +[] diff --git a/packages/qwik/src/optimizer/core/src/test.rs b/packages/qwik/src/optimizer/core/src/test.rs index 7401c13cba3..d82f5b86e43 100644 --- a/packages/qwik/src/optimizer/core/src/test.rs +++ b/packages/qwik/src/optimizer/core/src/test.rs @@ -3646,6 +3646,27 @@ fn should_destructure_args() { }); } +#[test] +fn destructure_args_colon_props() { + test_input!(TestInput { + code: r#" + import { component$ } from "@qwik.dev/core"; + export default component$((props) => { + const { 'bind:value': bindValue } = props; + return ( + <> + {bindValue} + + ); + }); + "# + .to_string(), + transpile_ts: true, + transpile_jsx: true, + ..TestInput::default() + }); +} + #[test] fn should_handle_dangerously_set_inner_html() { test_input!(TestInput {