11// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
22
33use crate :: swc:: atoms:: Atom ;
4+ use swc_atoms:: Wtf8Atom ;
45use swc_common:: DUMMY_SP ;
56use swc_common:: SyntaxContext ;
67use swc_ecma_ast:: * ;
@@ -325,27 +326,22 @@ fn get_attr_name(jsx_attr: &JSXAttr, normalize: bool) -> String {
325326 }
326327}
327328
328- fn normalize_lit_str ( lit : & Lit ) -> Lit {
329- match lit {
330- Lit :: Str ( lit_str) => {
331- let value: & str = & lit_str. value ;
332- let mut replaced = "" . to_string ( ) ;
329+ fn normalize_lit_str ( lit_str : & Str ) -> Lit {
330+ let value = lit_str. value . to_string_lossy ( ) ;
331+ let mut replaced = "" . to_string ( ) ;
333332
334- for ( i, line) in value. lines ( ) . enumerate ( ) {
335- if i > 0 {
336- replaced. push ( ' ' ) ;
337- }
338- replaced. push_str ( line. trim_start ( ) ) ;
339- }
340-
341- Lit :: Str ( Str {
342- span : lit_str. span ,
343- value : replaced. into ( ) ,
344- raw : None ,
345- } )
333+ for ( i, line) in value. lines ( ) . enumerate ( ) {
334+ if i > 0 {
335+ replaced. push ( ' ' ) ;
346336 }
347- _ => lit . clone ( ) ,
337+ replaced . push_str ( line . trim_start ( ) ) ;
348338 }
339+
340+ Lit :: Str ( Str {
341+ span : lit_str. span ,
342+ value : replaced. into ( ) ,
343+ raw : None ,
344+ } )
349345}
350346
351347fn jsx_text_to_str (
@@ -451,7 +447,7 @@ fn is_text_valid_identifier(string_value: &str) -> bool {
451447 true
452448}
453449
454- fn string_lit_expr ( value : Atom ) -> Expr {
450+ fn string_lit_expr ( value : Wtf8Atom ) -> Expr {
455451 Expr :: Lit ( Lit :: Str ( Str {
456452 span : DUMMY_SP ,
457453 value,
@@ -524,7 +520,7 @@ fn merge_serializable_children(
524520 }
525521 // Can be flattened
526522 Lit :: Str ( str_lit) => {
527- buf. push_str ( & escape_html ( str_lit. value . as_ref ( ) ) ) ;
523+ buf. push_str ( & escape_html ( & str_lit. value . to_string_lossy ( ) ) ) ;
528524 continue ;
529525 }
530526 _ => { }
@@ -673,8 +669,8 @@ impl JsxPrecompile {
673669 Lit :: Bool ( _) => expr,
674670 Lit :: Null ( _) => expr,
675671 Lit :: Str ( string_lit) => {
676- let escaped_value = escape_html ( string_lit. value . as_ref ( ) ) ;
677- if string_lit. value != escaped_value {
672+ let escaped_value = escape_html ( & string_lit. value . to_string_lossy ( ) ) ;
673+ if string_lit. value . to_string_lossy ( ) != escaped_value {
678674 self . wrap_with_jsx_escape_call ( expr)
679675 } else {
680676 expr
@@ -771,7 +767,7 @@ impl JsxPrecompile {
771767 JSXElementChild :: JSXText ( jsx_text) => {
772768 elems. push ( Some ( ExprOrSpread {
773769 spread : None ,
774- expr : Box :: new ( string_lit_expr ( jsx_text. value ) ) ,
770+ expr : Box :: new ( string_lit_expr ( jsx_text. value . into ( ) ) ) ,
775771 } ) ) ;
776772 }
777773 // Case: <div>{2 + 2}</div>
@@ -856,7 +852,7 @@ impl JsxPrecompile {
856852 is_component = true ;
857853 Expr :: Ident ( ident. clone ( ) )
858854 } else {
859- string_lit_expr ( name. clone ( ) )
855+ string_lit_expr ( name. clone ( ) . into ( ) )
860856 }
861857 }
862858 // Case: <ctx.Provider />
@@ -920,8 +916,8 @@ impl JsxPrecompile {
920916
921917 if attr_name == "key" {
922918 key_value = match attr_value {
923- JSXAttrValue :: Lit ( lit ) => {
924- let normalized_lit = normalize_lit_str ( lit ) ;
919+ JSXAttrValue :: Str ( str ) => {
920+ let normalized_lit = normalize_lit_str ( str ) ;
925921 Some ( Expr :: Lit ( normalized_lit) )
926922 }
927923 JSXAttrValue :: JSXExprContainer ( jsx_expr_container) => {
@@ -944,8 +940,8 @@ impl JsxPrecompile {
944940 // Case: <Foo class={true}>
945941 // Case: <Foo class={null}>
946942 match attr_value {
947- JSXAttrValue :: Lit ( lit ) => {
948- let normalized_lit = normalize_lit_str ( lit ) ;
943+ JSXAttrValue :: Str ( str ) => {
944+ let normalized_lit = normalize_lit_str ( str ) ;
949945
950946 props. push ( PropOrSpread :: Prop ( Box :: new ( Prop :: KeyValue (
951947 KeyValueProp {
@@ -1023,7 +1019,11 @@ impl JsxPrecompile {
10231019 }
10241020 }
10251021
1026- fn convert_to_jsx_attr_call ( & mut self , name : Atom , expr : Expr ) -> CallExpr {
1022+ fn convert_to_jsx_attr_call (
1023+ & mut self ,
1024+ name : Wtf8Atom ,
1025+ expr : Expr ,
1026+ ) -> CallExpr {
10271027 let args = vec ! [
10281028 ExprOrSpread {
10291029 spread: None ,
@@ -1157,7 +1157,7 @@ impl JsxPrecompile {
11571157
11581158 let value = match & jsx_attr. value {
11591159 Some ( attr_value) => match attr_value. clone ( ) {
1160- JSXAttrValue :: Lit ( lit) => Expr :: Lit ( lit) ,
1160+ JSXAttrValue :: Str ( lit) => Expr :: Lit ( Lit :: Str ( lit) ) ,
11611161 JSXAttrValue :: JSXExprContainer ( _) => todo ! ( ) ,
11621162 JSXAttrValue :: JSXElement ( jsx_element) => {
11631163 Expr :: JSXElement ( jsx_element)
@@ -1210,44 +1210,34 @@ impl JsxPrecompile {
12101210 // Case: <div class={true}>
12111211 // Case: <div class={null}>
12121212 match attr_value {
1213- JSXAttrValue :: Lit ( lit) => match lit {
1214- Lit :: Str ( string_lit) => {
1215- // Edge Case: Both "key" and "ref" attributes are
1216- // special attributes in most frameworks. Some
1217- // frameworks may want to serialize it, other's don't.
1218- // To support both use cases we'll always pass them to
1219- // `jsxAttr()` so that frameowrks can decide for
1220- // themselves what to do with it.
1221- // Case: <div key="123" />
1222- // Case: <div ref="123" />
1223- if attr_name == "key" || attr_name == "ref" {
1224- strings. last_mut ( ) . unwrap ( ) . push ( ' ' ) ;
1225- strings. push ( "" . to_string ( ) ) ;
1226- let expr = self . convert_to_jsx_attr_call (
1227- attr_name. into ( ) ,
1228- string_lit_expr ( string_lit. value . clone ( ) ) ,
1229- ) ;
1230- dynamic_exprs. push ( Expr :: Call ( expr) ) ;
1231- continue ;
1232- }
1213+ JSXAttrValue :: Str ( string_lit) => {
1214+ // Edge Case: Both "key" and "ref" attributes are
1215+ // special attributes in most frameworks. Some
1216+ // frameworks may want to serialize it, other's don't.
1217+ // To support both use cases we'll always pass them to
1218+ // `jsxAttr()` so that frameowrks can decide for
1219+ // themselves what to do with it.
1220+ // Case: <div key="123" />
1221+ // Case: <div ref="123" />
1222+ if attr_name == "key" || attr_name == "ref" {
1223+ strings. last_mut ( ) . unwrap ( ) . push ( ' ' ) ;
1224+ strings. push ( "" . to_string ( ) ) ;
1225+ let expr = self . convert_to_jsx_attr_call (
1226+ attr_name. into ( ) ,
1227+ string_lit_expr ( string_lit. value . clone ( ) ) ,
1228+ ) ;
1229+ dynamic_exprs. push ( Expr :: Call ( expr) ) ;
1230+ continue ;
1231+ }
12331232
1234- let serialized_attr =
1235- serialize_attr ( & attr_name, & string_lit. value ) ;
1233+ let serialized_attr =
1234+ serialize_attr ( & attr_name, & string_lit. value . to_string_lossy ( ) ) ;
12361235
1237- strings
1238- . last_mut ( )
1239- . unwrap ( )
1240- . push_str ( serialized_attr. as_str ( ) ) ;
1241- }
1242- // I've never seen this being possible as it would
1243- // always be treated as an expression.
1244- Lit :: Bool ( _) => { }
1245- Lit :: Null ( _) => { }
1246- Lit :: Num ( _) => { }
1247- Lit :: BigInt ( _) => { }
1248- Lit :: Regex ( _) => { }
1249- Lit :: JSXText ( _) => { }
1250- } ,
1236+ strings
1237+ . last_mut ( )
1238+ . unwrap ( )
1239+ . push_str ( serialized_attr. as_str ( ) ) ;
1240+ }
12511241 JSXAttrValue :: JSXExprContainer ( jsx_expr_container) => {
12521242 match & jsx_expr_container. expr {
12531243 // This is treated as a syntax error in attributes
@@ -1281,8 +1271,10 @@ impl JsxPrecompile {
12811271 continue ;
12821272 }
12831273 Lit :: Str ( str_lit) => {
1284- let serialized_attr =
1285- serialize_attr ( & attr_name, & str_lit. value ) ;
1274+ let serialized_attr = serialize_attr (
1275+ & attr_name,
1276+ & str_lit. value . to_string_lossy ( ) ,
1277+ ) ;
12861278
12871279 strings
12881280 . last_mut ( )
0 commit comments