Skip to content

Commit 8131529

Browse files
committed
feat(transformer): finish exponentiation operator
1 parent 6c18b3e commit 8131529

File tree

17 files changed

+376
-82
lines changed

17 files changed

+376
-82
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/oxc_ast/src/ast/js.rs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -92,29 +92,18 @@ pub enum Expression<'a> {
9292
impl<'a> Expression<'a> {
9393
/// `PrimaryExpression`
9494
/// [tc39/ecma262#prod-PrimaryExpression](https://tc39.es/ecma262/#prod-PrimaryExpression)
95+
#[rustfmt::skip]
9596
pub fn is_primary_expression(&self) -> bool {
96-
self.is_literal_expression()
97-
|| matches!(
98-
self,
99-
Self::Identifier(_)
100-
| Self::ThisExpression(_)
101-
| Self::FunctionExpression(_)
102-
| Self::ClassExpression(_)
103-
| Self::ParenthesizedExpression(_)
104-
| Self::ArrayExpression(_)
105-
| Self::ObjectExpression(_)
106-
)
107-
}
108-
109-
pub fn is_literal_expression(&self) -> bool {
110-
matches!(
111-
self,
112-
Self::BooleanLiteral(_)
113-
| Self::NullLiteral(_)
114-
| Self::NumberLiteral(_)
115-
| Self::BigintLiteral(_)
116-
| Self::RegExpLiteral(_)
117-
| Self::StringLiteral(_) // TemplateLiteral is not `Literal` type per oxc_ast
97+
self.is_literal() || matches!(self, Self::Identifier(_) | Self::ThisExpression(_) | Self::FunctionExpression(_)
98+
| Self::ClassExpression(_) | Self::ParenthesizedExpression(_)
99+
| Self::ArrayExpression(_) | Self::ObjectExpression(_))
100+
}
101+
102+
#[rustfmt::skip]
103+
pub fn is_literal(&self) -> bool {
104+
// Note: TemplateLiteral is not `Literal`
105+
matches!(self, Self::BooleanLiteral(_) | Self::NullLiteral(_) | Self::NumberLiteral(_)
106+
| Self::BigintLiteral(_) | Self::RegExpLiteral(_) | Self::StringLiteral(_)
118107
)
119108
}
120109

@@ -540,6 +529,10 @@ pub enum MemberExpression<'a> {
540529
}
541530

542531
impl<'a> MemberExpression<'a> {
532+
pub fn is_computed(&self) -> bool {
533+
matches!(self, MemberExpression::ComputedMemberExpression(_))
534+
}
535+
543536
pub fn optional(&self) -> bool {
544537
match self {
545538
MemberExpression::ComputedMemberExpression(expr) => expr.optional,
@@ -814,6 +807,13 @@ impl<'a> AssignmentTarget<'a> {
814807
pub fn is_destructuring_pattern(&self) -> bool {
815808
matches!(self, Self::AssignmentTargetPattern(_))
816809
}
810+
811+
pub fn is_identifier(&self) -> bool {
812+
matches!(
813+
self,
814+
Self::SimpleAssignmentTarget(SimpleAssignmentTarget::AssignmentTargetIdentifier(_))
815+
)
816+
}
817817
}
818818

819819
#[derive(Debug, Hash)]

crates/oxc_ast/src/ast/literal.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ pub struct StringLiteral {
211211
}
212212

213213
impl StringLiteral {
214+
pub fn new(span: Span, value: Atom) -> Self {
215+
Self { span, value }
216+
}
217+
214218
/// Static Semantics: `IsStringWellFormedUnicode`
215219
/// test for \uD800-\uDFFF
216220
pub fn is_string_well_formed_unicode(&self) -> bool {

crates/oxc_ast/src/ast_builder.rs

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ impl<'a> AstBuilder<'a> {
7777
mem::replace(stmts, self.new_vec())
7878
}
7979

80+
pub fn move_assignment_target(
81+
&self,
82+
target: &mut AssignmentTarget<'a>,
83+
) -> AssignmentTarget<'a> {
84+
let ident = IdentifierReference::new(Span::default(), "".into());
85+
let dummy = self.simple_assignment_target_identifier(ident);
86+
let dummy = AssignmentTarget::SimpleAssignmentTarget(dummy);
87+
mem::replace(target, dummy)
88+
}
89+
8090
pub fn program(
8191
&self,
8292
span: Span,
@@ -90,10 +100,6 @@ impl<'a> AstBuilder<'a> {
90100

91101
/* ---------- Literals ---------- */
92102

93-
pub fn string_literal(&self, span: Span, value: Atom) -> StringLiteral {
94-
StringLiteral { span, value }
95-
}
96-
97103
pub fn number_literal(
98104
&self,
99105
span: Span,
@@ -415,6 +421,13 @@ impl<'a> AstBuilder<'a> {
415421
SimpleAssignmentTarget::AssignmentTargetIdentifier(self.alloc(ident))
416422
}
417423

424+
pub fn simple_assignment_target_member_expression(
425+
&self,
426+
expr: MemberExpression<'a>,
427+
) -> SimpleAssignmentTarget<'a> {
428+
SimpleAssignmentTarget::MemberAssignmentTarget(self.alloc(expr))
429+
}
430+
418431
pub fn await_expression(&self, span: Span, argument: Expression<'a>) -> Expression<'a> {
419432
Expression::AwaitExpression(self.alloc(AwaitExpression { span, argument }))
420433
}
@@ -496,31 +509,54 @@ impl<'a> AstBuilder<'a> {
496509
Expression::MemberExpression(self.alloc(expr))
497510
}
498511

512+
pub fn computed_member(
513+
&self,
514+
span: Span,
515+
object: Expression<'a>,
516+
expression: Expression<'a>,
517+
optional: bool, // for optional chaining
518+
) -> MemberExpression<'a> {
519+
MemberExpression::ComputedMemberExpression(ComputedMemberExpression {
520+
span,
521+
object,
522+
expression,
523+
optional,
524+
})
525+
}
526+
499527
pub fn computed_member_expression(
500528
&self,
501529
span: Span,
502530
object: Expression<'a>,
503531
expression: Expression<'a>,
504532
optional: bool, // for optional chaining
505533
) -> Expression<'a> {
506-
self.member_expression(MemberExpression::ComputedMemberExpression(
507-
ComputedMemberExpression { span, object, expression, optional },
508-
))
534+
self.member_expression(self.computed_member(span, object, expression, optional))
509535
}
510536

511-
pub fn static_member_expression(
537+
pub fn static_member(
512538
&self,
513539
span: Span,
514540
object: Expression<'a>,
515541
property: IdentifierName,
516542
optional: bool, // for optional chaining
517-
) -> Expression<'a> {
518-
self.member_expression(MemberExpression::StaticMemberExpression(StaticMemberExpression {
543+
) -> MemberExpression<'a> {
544+
MemberExpression::StaticMemberExpression(StaticMemberExpression {
519545
span,
520546
object,
521547
property,
522548
optional,
523-
}))
549+
})
550+
}
551+
552+
pub fn static_member_expression(
553+
&self,
554+
span: Span,
555+
object: Expression<'a>,
556+
property: IdentifierName,
557+
optional: bool, // for optional chaining
558+
) -> Expression<'a> {
559+
self.member_expression(self.static_member(span, object, property, optional))
524560
}
525561

526562
pub fn private_field_expression(

crates/oxc_linter/src/ast_util.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub fn is_static_boolean<'a>(expr: &Expression<'a>, ctx: &LintContext<'a>) -> bo
3636
/// Checks if a branch node of `LogicalExpression` short circuits the whole condition
3737
fn is_logical_identity(op: LogicalOperator, expr: &Expression) -> bool {
3838
match expr {
39-
expr if expr.is_literal_expression() => {
39+
expr if expr.is_literal() => {
4040
let boolean_value = expr.get_boolean_value();
4141
(op == LogicalOperator::Or && boolean_value == Some(true))
4242
|| (op == LogicalOperator::And && boolean_value == Some(false))
@@ -142,7 +142,7 @@ impl<'a, 'b> IsConstant<'a, 'b> for Expression<'a> {
142142
Self::Identifier(ident) => {
143143
ident.name == "undefined" && ctx.semantic().is_reference_to_global_variable(ident)
144144
}
145-
_ if self.is_literal_expression() => true,
145+
_ if self.is_literal() => true,
146146
_ => false,
147147
}
148148
}

crates/oxc_linter/src/rules/eslint/no_constant_binary_expression.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ impl NoConstantBinaryExpression {
167167
| Expression::UpdateExpression(_)
168168
| Expression::BinaryExpression(_)
169169
| Expression::UnaryExpression(_) => true,
170-
expr if expr.is_literal_expression() => true,
170+
expr if expr.is_literal() => true,
171171
Expression::CallExpression(call_expr) => {
172172
if let Expression::Identifier(ident) = &call_expr.callee {
173173
return ["Boolean", "String", "Number"].contains(&ident.name.as_str())
@@ -267,7 +267,7 @@ impl NoConstantBinaryExpression {
267267
Expression::ParenthesizedExpression(paren_expr) => {
268268
Self::has_constant_loose_boolean_comparison(&paren_expr.expression, ctx)
269269
}
270-
expr if expr.is_literal_expression() => true,
270+
expr if expr.is_literal() => true,
271271
expr if expr.evaluate_to_undefined() => true,
272272
_ => false,
273273
}
@@ -288,7 +288,7 @@ impl NoConstantBinaryExpression {
288288
| Expression::NewExpression(_)
289289
| Expression::TemplateLiteral(_)
290290
| Expression::UpdateExpression(_) => true,
291-
expr if expr.is_literal_expression() => true,
291+
expr if expr.is_literal() => true,
292292
Expression::BinaryExpression(binary_expr) => {
293293
binary_expr.operator.is_numeric_or_string_binary_operator()
294294
}

crates/oxc_minifier/src/compressor/fold.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ impl<'a> Compressor<'a> {
264264
let right_string = get_string_value(right)?;
265265
// let value = left_string.to_owned().
266266
let value = left_string + right_string;
267-
let string_literal = self.ast.string_literal(span, Atom::from(value));
267+
let string_literal = StringLiteral::new(span, Atom::from(value));
268268
Some(self.ast.literal_string_expression(string_literal))
269269
},
270270

@@ -587,7 +587,7 @@ impl<'a> Compressor<'a> {
587587
};
588588

589589
if let Some(type_name) = type_name {
590-
let string_literal = self.ast.string_literal(span, Atom::from(type_name));
590+
let string_literal = StringLiteral::new(span, Atom::from(type_name));
591591
return Some(self.ast.literal_string_expression(string_literal));
592592
}
593593
}

crates/oxc_semantic/src/symbol.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ impl SymbolTable {
9292
&self.references[reference_id]
9393
}
9494

95+
pub fn has_binding(&self, reference_id: ReferenceId) -> bool {
96+
self.references[reference_id].symbol_id().is_some()
97+
}
98+
9599
pub fn is_global_reference(&self, reference_id: ReferenceId) -> bool {
96100
self.references[reference_id].symbol_id().is_none()
97101
}

crates/oxc_transformer/examples/transformer.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{env, path::Path};
1+
use std::{cell::RefCell, env, path::Path, rc::Rc};
22

33
use oxc_allocator::Allocator;
44
use oxc_codegen::{Codegen, CodegenOptions};
@@ -34,12 +34,16 @@ fn main() {
3434
println!("{printed}");
3535

3636
let program = allocator.alloc(ret.program);
37-
let _ = SemanticBuilder::new(&source_text, source_type).build(program);
37+
38+
let semantic = SemanticBuilder::new(&source_text, source_type).build(program).semantic;
39+
let (symbols, _scope_tree) = semantic.into_symbol_table_and_scope_tree();
40+
let symbols = Rc::new(RefCell::new(symbols));
41+
3842
let transform_options = TransformOptions {
3943
target: TransformTarget::ES2015,
4044
react: Some(TransformReactOptions::default()),
4145
};
42-
Transformer::new(&allocator, source_type, transform_options).build(program);
46+
Transformer::new(&allocator, source_type, &symbols, transform_options).build(program);
4347
let printed = Codegen::<false>::new(source_text.len(), codegen_options).build(program);
4448
println!("Transformed:\n");
4549
println!("{printed}");

0 commit comments

Comments
 (0)