-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
fix(es/typescript): Handle TypeScript expressions in enum transformation #11769
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 15 commits
af91f1a
c9ea557
891439e
96965d9
6433532
fd25b41
d3b6400
fd53909
977d1f7
fa963a6
d2c98c1
9303595
3d75291
1062344
00d0558
c7f2b8b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| { | ||
| "jsc": { | ||
| "parser": { | ||
| "syntax": "typescript", | ||
| "tsx": false | ||
| }, | ||
| "target": "es2024" | ||
| }, | ||
| "module": { | ||
| "type": "es6" | ||
| }, | ||
| "isModule": true | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| export enum RefType { | ||
| property = "11" as any, | ||
| event = "22" as any, | ||
| } | ||
|
|
||
| console.log(RefType.property, RefType.event); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| enum E { | ||
| A = ((B: number) => B)(2), | ||
| B = 1, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| enum E { | ||
| A, | ||
| B, | ||
| C, | ||
| D = ((C) => { | ||
| console.log(A, B, C, F); | ||
| return 2; | ||
| })(), | ||
| F = "F", | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| const A = 100; | ||
| enum E { | ||
| A = foo(), | ||
| B = A, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| enum E { | ||
| Infinity = 1, | ||
| B = Infinity, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| enum E { | ||
| Infinity = foo(), | ||
| B = Infinity, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| export var RefType = /*#__PURE__*/ function(RefType) { | ||
| RefType["property"] = "11"; | ||
| RefType["event"] = "22"; | ||
| return RefType; | ||
| }({}); | ||
| console.log("11", "22"); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| var E = function(E) { | ||
| E[E["A"] = ((B)=>B)(2)] = "A"; | ||
| E[E["B"] = 1] = "B"; | ||
| return E; | ||
| }(E || {}); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| var E = function(E) { | ||
| E[E["A"] = 0] = "A"; | ||
| E[E["B"] = 1] = "B"; | ||
| E[E["C"] = 2] = "C"; | ||
| E[E["D"] = ((C)=>{ | ||
| console.log(E.A, E.B, C, E.F); | ||
| return 2; | ||
| })()] = "D"; | ||
| E["F"] = "F"; | ||
| return E; | ||
| }(E || {}); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| const A = 100; | ||
| var E = function(E) { | ||
| E[E["A"] = foo()] = "A"; | ||
| E[E["B"] = E.A] = "B"; | ||
| return E; | ||
| }(E || {}); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| var E = /*#__PURE__*/ function(E) { | ||
| E[E["Infinity"] = 1] = "Infinity"; | ||
| E[E["B"] = 1] = "B"; | ||
| return E; | ||
| }(E || {}); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| var E = function(E) { | ||
| E[E["Infinity"] = foo()] = "Infinity"; | ||
| E[E["B"] = E.Infinity] = "B"; | ||
| return E; | ||
| }(E || {}); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,7 +22,7 @@ use crate::{ | |
| retain::{should_retain_module_item, should_retain_stmt}, | ||
| semantic::SemanticInfo, | ||
| shared::enum_member_id_atom, | ||
| ts_enum::{TsEnumRecordKey, TsEnumRecordValue}, | ||
| ts_enum::{EnumValueComputer, TsEnumRecordKey, TsEnumRecordValue}, | ||
| utils::{assign_value_to_this_private_prop, assign_value_to_this_prop, Factory}, | ||
| }; | ||
|
|
||
|
|
@@ -1052,6 +1052,20 @@ impl Transform { | |
| && !is_export | ||
| && !self.semantic.exported_binding.contains_key(&id.to_id()); | ||
|
|
||
| let member_names = self | ||
| .semantic | ||
| .enum_record | ||
| .keys() | ||
| .filter(|k| k.enum_id == id.to_id()) | ||
| .map(|k| k.member_name.clone()) | ||
| .collect(); | ||
|
|
||
magic-akari marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| let enum_computer = EnumValueComputer { | ||
| enum_id: &id.to_id(), | ||
| unresolved_ctxt: self.unresolved_ctxt, | ||
| record: &self.semantic.enum_record, | ||
| }; | ||
|
Comment on lines
+1055
to
+1067
|
||
|
|
||
| let member_list: Vec<_> = members | ||
| .into_iter() | ||
| .map(|m| { | ||
|
|
@@ -1063,7 +1077,24 @@ impl Transform { | |
| member_name: name.clone(), | ||
| }; | ||
|
|
||
| let value = self.semantic.enum_record.get(&key).unwrap().clone(); | ||
| let mut value = self.semantic.enum_record.get(&key).unwrap().clone(); | ||
|
|
||
| if let TsEnumRecordValue::Opaque(expr) = &mut value { | ||
| let e = m.init.unwrap(); | ||
| // [TODO]: We have computed twice for TsEnumRecordValue::Opaque case. | ||
| // Try to avoid this if it causes performance issue. | ||
| let TsEnumRecordValue::Opaque(mut e) = enum_computer.compute(e) else { | ||
| unreachable!(); | ||
|
Comment on lines
+1086
to
+1087
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This Useful? React with 👍 / 👎. |
||
| }; | ||
| e.visit_mut_with(&mut RefRewriter { | ||
| query: EnumMemberRefQuery { | ||
| enum_id: &id.to_id(), | ||
| member_names: &member_names, | ||
| unresolved_ctxt: self.unresolved_ctxt, | ||
| }, | ||
| }); | ||
|
Comment on lines
+1088
to
+1095
|
||
| *expr = e; | ||
| } | ||
|
|
||
| EnumMemberItem { span, name, value } | ||
| }) | ||
|
|
@@ -1817,6 +1848,46 @@ impl QueryRef for ExportQuery { | |
| } | ||
| } | ||
|
|
||
| struct EnumMemberRefQuery<'a> { | ||
| enum_id: &'a Id, | ||
| member_names: &'a FxHashSet<Atom>, | ||
| unresolved_ctxt: SyntaxContext, | ||
| } | ||
|
|
||
| impl QueryRef for EnumMemberRefQuery<'_> { | ||
| fn query_ref(&self, ident: &Ident) -> Option<Box<Expr>> { | ||
| if ident.ctxt == self.unresolved_ctxt && self.member_names.contains(&ident.sym) { | ||
| Some( | ||
| self.enum_id | ||
| .clone() | ||
| .make_member(ident.clone().into()) | ||
| .into(), | ||
| ) | ||
| } else { | ||
| None | ||
| } | ||
| } | ||
|
|
||
| fn query_lhs(&self, ident: &Ident) -> Option<Box<Expr>> { | ||
| self.query_ref(ident) | ||
| } | ||
|
|
||
| fn query_jsx(&self, ident: &Ident) -> Option<JSXElementName> { | ||
| if ident.ctxt == self.unresolved_ctxt && self.member_names.contains(&ident.sym) { | ||
| Some( | ||
| JSXMemberExpr { | ||
| span: DUMMY_SP, | ||
| obj: JSXObject::Ident(self.enum_id.clone().into()), | ||
| prop: ident.clone().into(), | ||
| } | ||
| .into(), | ||
| ) | ||
| } else { | ||
| None | ||
| } | ||
| } | ||
| } | ||
|
|
||
| struct EnumMemberItem { | ||
| span: Span, | ||
| name: Atom, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| var A = function(A) { | ||
| A[A["a"] = a] = "a"; | ||
| A[A["a"] = A.a] = "a"; | ||
| return A; | ||
| }(A || {}); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| var Foo = function(Foo) { | ||
| Foo[Foo["a"] = (class { | ||
| constructor(b){ | ||
| this.b = b; | ||
| } | ||
| }, 0)] = "a"; | ||
| return Foo; | ||
| }(Foo || {}); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| var Foo = function(Foo) { | ||
| Foo[Foo["a"] = (()=>{ | ||
| let Bar = /*#__PURE__*/ function(Bar) { | ||
| Bar["a"] = "a"; | ||
| Bar["b"] = "b"; | ||
| return Bar; | ||
| }({}); | ||
| return 0; | ||
| })()] = "a"; | ||
| return Foo; | ||
| }(Foo || {}); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| var Foo = function(Foo) { | ||
| Foo[Foo["a"] = foo('x')] = "a"; | ||
| return Foo; | ||
| }(Foo || {}); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| var RefType = /*#__PURE__*/ function(RefType) { | ||
| RefType["property"] = "11"; | ||
| RefType["event"] = "22"; | ||
| return RefType; | ||
| }(RefType || {}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please review this part carefully.
I am unsure if this implementation represents the correct direction for the fix.
@swc-project/core