Skip to content

Commit 6539f9d

Browse files
committed
compare with TypeScript compiler
1 parent dfc1e6f commit 6539f9d

File tree

112 files changed

+8190
-1934
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+8190
-1934
lines changed

crates/oxc_angular_compiler/src/ir/enums.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@ pub enum ExpressionKind {
246246
DerivedLiteralArray,
247247
/// Derived literal map for pure function bodies.
248248
DerivedLiteralMap,
249+
/// Literal array with IR expression elements.
250+
LiteralArray,
251+
/// Literal map (object) with IR expression values.
252+
LiteralMap,
249253
}
250254

251255
/// Flags for semantic variables.

crates/oxc_angular_compiler/src/ir/expression.rs

Lines changed: 299 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,12 @@ pub enum IrExpression<'a> {
156156
/// Derived literal map for pure function bodies.
157157
/// Contains IrExpression values that can include PureFunctionParameter references.
158158
DerivedLiteralMap(Box<'a, DerivedLiteralMapExpr<'a>>),
159+
/// Literal array with IR expression elements.
160+
/// Used to preserve pipe bindings inside array literals during ingest.
161+
LiteralArray(Box<'a, IrLiteralArrayExpr<'a>>),
162+
/// Literal map (object) with IR expression values.
163+
/// Used to preserve pipe bindings inside object literals during ingest.
164+
LiteralMap(Box<'a, IrLiteralMapExpr<'a>>),
159165
}
160166

161167
impl<'a> IrExpression<'a> {
@@ -212,6 +218,10 @@ impl<'a> IrExpression<'a> {
212218
IrExpression::DerivedLiteralArray(_) => ExpressionKind::DerivedLiteralArray,
213219
// DerivedLiteralMap is a literal map for pure function bodies
214220
IrExpression::DerivedLiteralMap(_) => ExpressionKind::DerivedLiteralMap,
221+
// LiteralArray is an array literal with IR expression elements
222+
IrExpression::LiteralArray(_) => ExpressionKind::LiteralArray,
223+
// LiteralMap is an object literal with IR expression values
224+
IrExpression::LiteralMap(_) => ExpressionKind::LiteralMap,
215225
}
216226
}
217227
}
@@ -618,6 +628,34 @@ impl<'a> IrExpression<'a> {
618628
allocator,
619629
))
620630
}
631+
IrExpression::LiteralArray(e) => {
632+
let mut elements = Vec::with_capacity_in(e.elements.len(), allocator);
633+
for elem in e.elements.iter() {
634+
elements.push(elem.clone_in(allocator));
635+
}
636+
IrExpression::LiteralArray(Box::new_in(
637+
IrLiteralArrayExpr { elements, source_span: e.source_span },
638+
allocator,
639+
))
640+
}
641+
IrExpression::LiteralMap(e) => {
642+
let mut keys = Vec::with_capacity_in(e.keys.len(), allocator);
643+
for key in e.keys.iter() {
644+
keys.push(key.clone());
645+
}
646+
let mut values = Vec::with_capacity_in(e.values.len(), allocator);
647+
for value in e.values.iter() {
648+
values.push(value.clone_in(allocator));
649+
}
650+
let mut quoted = Vec::with_capacity_in(e.quoted.len(), allocator);
651+
for q in e.quoted.iter() {
652+
quoted.push(*q);
653+
}
654+
IrExpression::LiteralMap(Box::new_in(
655+
IrLiteralMapExpr { keys, values, quoted, source_span: e.source_span },
656+
allocator,
657+
))
658+
}
621659
}
622660
}
623661
}
@@ -829,6 +867,30 @@ pub struct DerivedLiteralMapExpr<'a> {
829867
pub source_span: Option<Span>,
830868
}
831869

870+
/// Literal array with IR expression elements.
871+
/// Used during ingest to preserve pipe bindings inside array literals.
872+
#[derive(Debug)]
873+
pub struct IrLiteralArrayExpr<'a> {
874+
/// Array elements as IR expressions.
875+
pub elements: Vec<'a, IrExpression<'a>>,
876+
/// Source span.
877+
pub source_span: Option<Span>,
878+
}
879+
880+
/// Literal map (object) with IR expression values.
881+
/// Used during ingest to preserve pipe bindings inside object literals.
882+
#[derive(Debug)]
883+
pub struct IrLiteralMapExpr<'a> {
884+
/// Map keys (string keys from the original literal map).
885+
pub keys: Vec<'a, Atom<'a>>,
886+
/// Map values as IR expressions.
887+
pub values: Vec<'a, IrExpression<'a>>,
888+
/// Whether each key is quoted.
889+
pub quoted: Vec<'a, bool>,
890+
/// Source span.
891+
pub source_span: Option<Span>,
892+
}
893+
832894
/// Pure function expression (memoized computation).
833895
#[derive(Debug)]
834896
pub struct PureFunctionExpr<'a> {
@@ -1114,17 +1176,66 @@ pub struct TernaryExpr<'a> {
11141176

11151177
/// Binary operators for IR expressions.
11161178
///
1117-
/// These are used for computed expressions in @for loops.
1179+
/// These are used for computed expressions in @for loops and for preserving
1180+
/// pipes nested in binary expressions like `a ?? (b | pipe)`.
11181181
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11191182
pub enum IrBinaryOperator {
1120-
/// Strict equality (===)
1121-
Identical,
1122-
/// Strict inequality (!==)
1123-
NotIdentical,
1183+
/// Addition (+)
1184+
Plus,
11241185
/// Subtraction (-)
11251186
Minus,
1187+
/// Multiplication (*)
1188+
Multiply,
1189+
/// Division (/)
1190+
Divide,
11261191
/// Modulo (%)
11271192
Modulo,
1193+
/// Exponentiation (**)
1194+
Exponentiation,
1195+
/// Loose equality (==)
1196+
Equals,
1197+
/// Loose inequality (!=)
1198+
NotEquals,
1199+
/// Strict equality (===)
1200+
Identical,
1201+
/// Strict inequality (!==)
1202+
NotIdentical,
1203+
/// Less than (<)
1204+
Lower,
1205+
/// Less than or equal (<=)
1206+
LowerEquals,
1207+
/// Greater than (>)
1208+
Bigger,
1209+
/// Greater than or equal (>=)
1210+
BiggerEquals,
1211+
/// Logical and (&&)
1212+
And,
1213+
/// Logical or (||)
1214+
Or,
1215+
/// Nullish coalescing (??)
1216+
NullishCoalesce,
1217+
/// In operator (in)
1218+
In,
1219+
/// Assignment (=)
1220+
Assign,
1221+
/// Addition assignment (+=)
1222+
AdditionAssignment,
1223+
/// Subtraction assignment (-=)
1224+
SubtractionAssignment,
1225+
/// Multiplication assignment (*=)
1226+
MultiplicationAssignment,
1227+
/// Division assignment (/=)
1228+
DivisionAssignment,
1229+
/// Remainder assignment (%=)
1230+
RemainderAssignment,
1231+
/// Exponentiation assignment (**=)
1232+
ExponentiationAssignment,
1233+
/// And assignment (&&=)
1234+
AndAssignment,
1235+
/// Or assignment (||=)
1236+
OrAssignment,
1237+
/// Nullish coalescing assignment (??=)
1238+
NullishCoalesceAssignment,
11281239
}
11291240

11301241
// ============================================================================
@@ -1246,6 +1357,16 @@ pub fn transform_expressions_in_expression<'a, F>(
12461357
transform_expressions_in_expression(value, transform, flags);
12471358
}
12481359
}
1360+
IrExpression::LiteralArray(e) => {
1361+
for elem in e.elements.iter_mut() {
1362+
transform_expressions_in_expression(elem, transform, flags);
1363+
}
1364+
}
1365+
IrExpression::LiteralMap(e) => {
1366+
for value in e.values.iter_mut() {
1367+
transform_expressions_in_expression(value, transform, flags);
1368+
}
1369+
}
12491370
IrExpression::Ternary(e) => {
12501371
transform_expressions_in_expression(&mut e.condition, transform, flags);
12511372
transform_expressions_in_expression(&mut e.true_expr, transform, flags);
@@ -1389,6 +1510,16 @@ pub fn visit_expressions_in_expression<'a, F>(
13891510
visit_expressions_in_expression(value, visitor, flags);
13901511
}
13911512
}
1513+
IrExpression::LiteralArray(e) => {
1514+
for elem in e.elements.iter() {
1515+
visit_expressions_in_expression(elem, visitor, flags);
1516+
}
1517+
}
1518+
IrExpression::LiteralMap(e) => {
1519+
for value in e.values.iter() {
1520+
visit_expressions_in_expression(value, visitor, flags);
1521+
}
1522+
}
13921523
IrExpression::Ternary(e) => {
13931524
visit_expressions_in_expression(&e.condition, visitor, flags);
13941525
visit_expressions_in_expression(&e.true_expr, visitor, flags);
@@ -1497,19 +1628,169 @@ pub fn transform_expressions_in_update_op<'a, F>(
14971628
UpdateOp::DeferWhen(op) => {
14981629
transform_expressions_in_expression(&mut op.condition, transform, flags);
14991630
}
1631+
UpdateOp::Statement(op) => {
1632+
// Statement ops may contain WrappedIrNode which wraps IR expressions.
1633+
// We need to transform these expressions so that phases like naming
1634+
// can propagate variable names to ReadVariableExpr inside.
1635+
transform_expressions_in_output_statement(&mut op.statement, transform, flags);
1636+
}
15001637
// Operations without expressions
15011638
UpdateOp::ListEnd(_)
15021639
| UpdateOp::Advance(_)
15031640
| UpdateOp::I18nApply(_)
1504-
| UpdateOp::Animation(_)
1505-
| UpdateOp::Statement(_) => {
1506-
// Statement ops contain OutputStatement with WrappedNodeExpr which
1507-
// wraps IR expressions. These are handled during the reify phase,
1508-
// not during the expression transformation phase.
1641+
| UpdateOp::Animation(_) => {}
1642+
}
1643+
}
1644+
1645+
/// Transform expressions inside an OutputStatement.
1646+
/// This handles WrappedIrNode expressions that contain IR expressions.
1647+
fn transform_expressions_in_output_statement<'a, F>(
1648+
stmt: &mut crate::output::ast::OutputStatement<'a>,
1649+
transform: &F,
1650+
flags: VisitorContextFlag,
1651+
) where
1652+
F: Fn(&mut IrExpression<'a>, VisitorContextFlag),
1653+
{
1654+
use crate::output::ast::OutputStatement;
1655+
1656+
match stmt {
1657+
OutputStatement::Expression(expr_stmt) => {
1658+
transform_expressions_in_output_expression(&mut expr_stmt.expr, transform, flags);
1659+
}
1660+
OutputStatement::Return(ret_stmt) => {
1661+
transform_expressions_in_output_expression(&mut ret_stmt.value, transform, flags);
1662+
}
1663+
OutputStatement::DeclareVar(decl) => {
1664+
if let Some(ref mut value) = decl.value {
1665+
transform_expressions_in_output_expression(value, transform, flags);
1666+
}
1667+
}
1668+
OutputStatement::If(if_stmt) => {
1669+
transform_expressions_in_output_expression(&mut if_stmt.condition, transform, flags);
1670+
for stmt in if_stmt.true_case.iter_mut() {
1671+
transform_expressions_in_output_statement(stmt, transform, flags);
1672+
}
1673+
for stmt in if_stmt.false_case.iter_mut() {
1674+
transform_expressions_in_output_statement(stmt, transform, flags);
1675+
}
1676+
}
1677+
OutputStatement::DeclareFunction(_) => {
1678+
// Function declarations don't contain IrExpressions to transform
15091679
}
15101680
}
15111681
}
15121682

1683+
/// Transform expressions inside an OutputExpression.
1684+
/// This handles WrappedIrNode which contains IR expressions.
1685+
fn transform_expressions_in_output_expression<'a, F>(
1686+
expr: &mut crate::output::ast::OutputExpression<'a>,
1687+
transform: &F,
1688+
flags: VisitorContextFlag,
1689+
) where
1690+
F: Fn(&mut IrExpression<'a>, VisitorContextFlag),
1691+
{
1692+
use crate::output::ast::OutputExpression;
1693+
1694+
match expr {
1695+
OutputExpression::WrappedIrNode(wrapped) => {
1696+
transform_expressions_in_expression(&mut wrapped.node, transform, flags);
1697+
}
1698+
OutputExpression::Conditional(cond) => {
1699+
transform_expressions_in_output_expression(&mut cond.condition, transform, flags);
1700+
transform_expressions_in_output_expression(&mut cond.true_case, transform, flags);
1701+
if let Some(false_case) = &mut cond.false_case {
1702+
transform_expressions_in_output_expression(false_case, transform, flags);
1703+
}
1704+
}
1705+
OutputExpression::BinaryOperator(bin) => {
1706+
transform_expressions_in_output_expression(&mut bin.lhs, transform, flags);
1707+
transform_expressions_in_output_expression(&mut bin.rhs, transform, flags);
1708+
}
1709+
OutputExpression::UnaryOperator(un) => {
1710+
transform_expressions_in_output_expression(&mut un.expr, transform, flags);
1711+
}
1712+
OutputExpression::Not(not) => {
1713+
transform_expressions_in_output_expression(&mut not.condition, transform, flags);
1714+
}
1715+
OutputExpression::ReadProp(member) => {
1716+
transform_expressions_in_output_expression(&mut member.receiver, transform, flags);
1717+
}
1718+
OutputExpression::ReadKey(idx) => {
1719+
transform_expressions_in_output_expression(&mut idx.receiver, transform, flags);
1720+
transform_expressions_in_output_expression(&mut idx.index, transform, flags);
1721+
}
1722+
OutputExpression::TaggedTemplateLiteral(tagged) => {
1723+
transform_expressions_in_output_expression(&mut tagged.tag, transform, flags);
1724+
for expr in tagged.template.expressions.iter_mut() {
1725+
transform_expressions_in_output_expression(expr, transform, flags);
1726+
}
1727+
}
1728+
OutputExpression::ArrowFunction(arrow) => match &mut arrow.body {
1729+
crate::output::ast::ArrowFunctionBody::Expression(expr) => {
1730+
transform_expressions_in_output_expression(expr, transform, flags);
1731+
}
1732+
crate::output::ast::ArrowFunctionBody::Statements(stmts) => {
1733+
for stmt in stmts.iter_mut() {
1734+
transform_expressions_in_output_statement(stmt, transform, flags);
1735+
}
1736+
}
1737+
},
1738+
OutputExpression::LiteralArray(arr) => {
1739+
for elem in arr.entries.iter_mut() {
1740+
transform_expressions_in_output_expression(elem, transform, flags);
1741+
}
1742+
}
1743+
OutputExpression::LiteralMap(obj) => {
1744+
for entry in obj.entries.iter_mut() {
1745+
transform_expressions_in_output_expression(&mut entry.value, transform, flags);
1746+
if entry.quoted {
1747+
// Key is always a string, no sub-expressions
1748+
}
1749+
}
1750+
}
1751+
OutputExpression::InvokeFunction(inv) => {
1752+
transform_expressions_in_output_expression(&mut inv.fn_expr, transform, flags);
1753+
for arg in inv.args.iter_mut() {
1754+
transform_expressions_in_output_expression(arg, transform, flags);
1755+
}
1756+
}
1757+
OutputExpression::Function(func) => {
1758+
for stmt in func.statements.iter_mut() {
1759+
transform_expressions_in_output_statement(stmt, transform, flags);
1760+
}
1761+
}
1762+
OutputExpression::Instantiate(inst) => {
1763+
transform_expressions_in_output_expression(&mut inst.class_expr, transform, flags);
1764+
for arg in inst.args.iter_mut() {
1765+
transform_expressions_in_output_expression(arg, transform, flags);
1766+
}
1767+
}
1768+
OutputExpression::Parenthesized(paren) => {
1769+
transform_expressions_in_output_expression(&mut paren.expr, transform, flags);
1770+
}
1771+
OutputExpression::Comma(comma) => {
1772+
for part in comma.parts.iter_mut() {
1773+
transform_expressions_in_output_expression(part, transform, flags);
1774+
}
1775+
}
1776+
OutputExpression::Typeof(typeof_expr) => {
1777+
transform_expressions_in_output_expression(&mut typeof_expr.expr, transform, flags);
1778+
}
1779+
OutputExpression::Void(void_expr) => {
1780+
transform_expressions_in_output_expression(&mut void_expr.expr, transform, flags);
1781+
}
1782+
// Leaf expressions without sub-expressions
1783+
OutputExpression::Literal(_)
1784+
| OutputExpression::TemplateLiteral(_)
1785+
| OutputExpression::RegularExpressionLiteral(_)
1786+
| OutputExpression::ReadVar(_)
1787+
| OutputExpression::External(_)
1788+
| OutputExpression::LocalizedString(_)
1789+
| OutputExpression::WrappedNode(_)
1790+
| OutputExpression::DynamicImport(_) => {}
1791+
}
1792+
}
1793+
15131794
/// Transform all expressions in a create operation.
15141795
pub fn transform_expressions_in_create_op<'a, F>(
15151796
op: &mut CreateOp<'a>,
@@ -2208,6 +2489,14 @@ pub fn vars_used_by_ir_expression(expr: &IrExpression<'_>) -> u32 {
22082489
map.values.iter().map(vars_used_by_ir_expression).sum()
22092490
}
22102491

2492+
// LiteralArray: sum of vars used by all elements
2493+
IrExpression::LiteralArray(arr) => {
2494+
arr.elements.iter().map(vars_used_by_ir_expression).sum()
2495+
}
2496+
2497+
// LiteralMap: sum of vars used by all values
2498+
IrExpression::LiteralMap(map) => map.values.iter().map(vars_used_by_ir_expression).sum(),
2499+
22112500
// Ternary: sum of vars used by all branches
22122501
IrExpression::Ternary(ternary) => {
22132502
vars_used_by_ir_expression(&ternary.condition)

0 commit comments

Comments
 (0)