11use rustc_hash:: FxHashMap ;
2- use swc_atoms:: { atom , Atom , Wtf8Atom } ;
2+ use swc_atoms:: { Atom , Wtf8Atom } ;
33use swc_common:: { SyntaxContext , DUMMY_SP } ;
44use swc_ecma_ast:: * ;
55use swc_ecma_utils:: {
@@ -26,15 +26,34 @@ pub(crate) type TsEnumRecord = FxHashMap<TsEnumRecordKey, TsEnumRecordValue>;
2626#[ derive( Debug , Clone ) ]
2727pub ( crate ) enum TsEnumRecordValue {
2828 String ( Atom ) ,
29- Number ( JsNumber ) ,
29+ Number ( Number ) ,
3030 Opaque ( Box < Expr > ) ,
3131 Void ,
3232}
3333
3434impl TsEnumRecordValue {
35+ /// Creates a computed number. Computations intentionally discard source
36+ /// spelling so code generation can choose the canonical representation.
37+ fn number ( value : impl Into < f64 > ) -> Self {
38+ Self :: Number ( Number {
39+ span : DUMMY_SP ,
40+ value : value. into ( ) ,
41+ raw : None ,
42+ } )
43+ }
44+
45+ /// Creates a number converted directly from an AST value.
46+ fn converted_number ( value : impl Into < f64 > , raw : Option < Atom > ) -> Self {
47+ Self :: Number ( Number {
48+ span : DUMMY_SP ,
49+ value : value. into ( ) ,
50+ raw,
51+ } )
52+ }
53+
3554 pub fn inc ( & self ) -> Self {
3655 match self {
37- Self :: Number ( num) => Self :: Number ( ( * * num + 1.0 ) . into ( ) ) ,
56+ Self :: Number ( num) => Self :: number ( num. value + 1.0 ) ,
3857 _ => Self :: Void ,
3958 }
4059 }
@@ -59,37 +78,7 @@ impl From<TsEnumRecordValue> for Expr {
5978 fn from ( value : TsEnumRecordValue ) -> Self {
6079 match value {
6180 TsEnumRecordValue :: String ( string) => Lit :: Str ( string. into ( ) ) . into ( ) ,
62- TsEnumRecordValue :: Number ( num) if num. is_nan ( ) => Ident {
63- span : DUMMY_SP ,
64- sym : atom ! ( "NaN" ) ,
65- ..Default :: default ( )
66- }
67- . into ( ) ,
68- TsEnumRecordValue :: Number ( num) if num. is_infinite ( ) => {
69- let value: Expr = Ident {
70- span : DUMMY_SP ,
71- sym : atom ! ( "Infinity" ) ,
72- ..Default :: default ( )
73- }
74- . into ( ) ;
75-
76- if num. is_sign_negative ( ) {
77- UnaryExpr {
78- span : DUMMY_SP ,
79- op : op ! ( unary, "-" ) ,
80- arg : value. into ( ) ,
81- }
82- . into ( )
83- } else {
84- value
85- }
86- }
87- TsEnumRecordValue :: Number ( num) => Lit :: Num ( Number {
88- span : DUMMY_SP ,
89- value : * num,
90- raw : None ,
91- } )
92- . into ( ) ,
81+ TsEnumRecordValue :: Number ( num) => Lit :: Num ( num) . into ( ) ,
9382 TsEnumRecordValue :: Void => * Expr :: undefined ( DUMMY_SP ) ,
9483 TsEnumRecordValue :: Opaque ( expr) => * expr,
9584 }
@@ -98,7 +87,7 @@ impl From<TsEnumRecordValue> for Expr {
9887
9988impl From < f64 > for TsEnumRecordValue {
10089 fn from ( value : f64 ) -> Self {
101- Self :: Number ( value. into ( ) )
90+ Self :: number ( value)
10291 }
10392}
10493
@@ -117,7 +106,7 @@ impl EnumValueComputer<'_> {
117106 fn compute_rec ( & self , expr : Box < Expr > ) -> TsEnumRecordValue {
118107 match * expr {
119108 Expr :: Lit ( Lit :: Str ( s) ) => TsEnumRecordValue :: String ( atom_from_wtf8_atom ( & s. value ) ) ,
120- Expr :: Lit ( Lit :: Num ( n) ) => TsEnumRecordValue :: Number ( n. value . into ( ) ) ,
109+ Expr :: Lit ( Lit :: Num ( n) ) => TsEnumRecordValue :: Number ( n) ,
121110 Expr :: Ident ( ref ident) if ident. ctxt == self . unresolved_ctxt => {
122111 if let Some ( value) = self . record . get ( & TsEnumRecordKey {
123112 enum_id : self . enum_id . clone ( ) ,
@@ -135,8 +124,13 @@ impl EnumValueComputer<'_> {
135124 }
136125 } else {
137126 match ident. sym . as_ref ( ) {
138- "Infinity" => TsEnumRecordValue :: Number ( f64:: INFINITY . into ( ) ) ,
139- "NaN" => TsEnumRecordValue :: Number ( f64:: NAN . into ( ) ) ,
127+ "Infinity" => TsEnumRecordValue :: converted_number (
128+ f64:: INFINITY ,
129+ Some ( ident. sym . clone ( ) ) ,
130+ ) ,
131+ "NaN" => {
132+ TsEnumRecordValue :: converted_number ( f64:: NAN , Some ( ident. sym . clone ( ) ) )
133+ }
140134 _ => TsEnumRecordValue :: Opaque ( expr) ,
141135 }
142136 }
@@ -177,9 +171,9 @@ impl EnumValueComputer<'_> {
177171 } ;
178172
179173 match expr. op {
180- op ! ( unary, "+" ) => TsEnumRecordValue :: Number ( num) ,
181- op ! ( unary, "-" ) => TsEnumRecordValue :: Number ( -num) ,
182- op ! ( "~" ) => TsEnumRecordValue :: Number ( ! num) ,
174+ op ! ( unary, "+" ) => TsEnumRecordValue :: number ( num. value ) ,
175+ op ! ( unary, "-" ) => TsEnumRecordValue :: number ( -num. value ) ,
176+ op ! ( "~" ) => TsEnumRecordValue :: number ( ! JsNumber :: from ( num. value ) ) ,
183177 _ => unreachable ! ( ) ,
184178 }
185179 }
@@ -209,6 +203,8 @@ impl EnumValueComputer<'_> {
209203
210204 match ( left, right, expr. op ) {
211205 ( TsEnumRecordValue :: Number ( left) , TsEnumRecordValue :: Number ( right) , op) => {
206+ let left = JsNumber :: from ( left. value ) ;
207+ let right = JsNumber :: from ( right. value ) ;
212208 let value = match op {
213209 op ! ( bin, "+" ) => left + right,
214210 op ! ( bin, "-" ) => left - right,
@@ -225,18 +221,18 @@ impl EnumValueComputer<'_> {
225221 _ => unreachable ! ( ) ,
226222 } ;
227223
228- TsEnumRecordValue :: Number ( value)
224+ TsEnumRecordValue :: number ( value)
229225 }
230226 ( TsEnumRecordValue :: String ( left) , TsEnumRecordValue :: String ( right) , op ! ( bin, "+" ) ) => {
231227 TsEnumRecordValue :: String ( format ! ( "{left}{right}" ) . into ( ) )
232228 }
233229 ( TsEnumRecordValue :: Number ( left) , TsEnumRecordValue :: String ( right) , op ! ( bin, "+" ) ) => {
234- let left = left. to_js_string ( ) ;
230+ let left = left. value . to_js_string ( ) ;
235231
236232 TsEnumRecordValue :: String ( format ! ( "{left}{right}" ) . into ( ) )
237233 }
238234 ( TsEnumRecordValue :: String ( left) , TsEnumRecordValue :: Number ( right) , op ! ( bin, "+" ) ) => {
239- let right = right. to_js_string ( ) ;
235+ let right = right. value . to_js_string ( ) ;
240236
241237 TsEnumRecordValue :: String ( format ! ( "{left}{right}" ) . into ( ) )
242238 }
@@ -305,7 +301,7 @@ impl EnumValueComputer<'_> {
305301
306302 let expr = match expr {
307303 TsEnumRecordValue :: String ( s) => s. to_string ( ) ,
308- TsEnumRecordValue :: Number ( n) => n. to_js_string ( ) ,
304+ TsEnumRecordValue :: Number ( n) => n. value . to_js_string ( ) ,
309305 _ => return opaque_expr,
310306 } ;
311307
0 commit comments