From 885e37f8eb2dba6a245cbf0a23a084534d0e9f81 Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Thu, 21 Nov 2024 03:12:17 +0000 Subject: [PATCH] feat(transformer): Optional Chaining (#6990) close: #6958 --- crates/oxc_ast/src/ast_impl/js.rs | 9 + .../src/compiler_assumptions.rs | 2 - crates/oxc_transformer/src/context.rs | 1 - crates/oxc_transformer/src/es2020/mod.rs | 45 +- .../src/es2020/optional_chaining.rs | 664 ++++++++++++++++++ crates/oxc_transformer/src/es2020/options.rs | 3 + crates/oxc_transformer/src/lib.rs | 16 + .../src/options/babel/plugins.rs | 2 + crates/oxc_transformer/src/options/env.rs | 2 + .../src/options/es_features.rs | 17 + crates/oxc_transformer/src/options/mod.rs | 1 + tasks/coverage/snapshots/semantic_misc.snap | 27 +- .../coverage/snapshots/semantic_test262.snap | 39 +- .../snapshots/semantic_typescript.snap | 525 +++++++++++++- .../assignment/output.js | 8 + .../cast-to-boolean/output.js | 85 +++ .../in-function-params/output.js | 19 + .../memoize/output.js | 18 + .../optional-eval-call/output.js | 10 + .../super-method-call/output.js | 12 + .../function-call/output.js | 11 + .../assumption-pureGetters/memoize/output.js | 18 + .../super-method-call/output.js | 12 + .../fixtures/general/assignment/output.js | 8 + .../general/cast-to-boolean/output.js | 85 +++ .../fixtures/general/containers/output.js | 6 + .../delete-in-function-params/output.js | 4 + .../test/fixtures/general/delete/output.js | 7 + .../general/function-call-loose/output.js | 5 + .../general/function-call-spread/output.js | 5 + .../fixtures/general/function-call/output.js | 11 + .../in-function-params-loose/output.js | 19 + .../general/in-function-params/output.js | 19 + .../general/in-method-key-loose/output.js | 3 + .../fixtures/general/in-method-key/output.js | 3 + .../general/in-var-destructuring/output.js | 2 + .../fixtures/general/member-access/output.js | 11 + .../fixtures/general/memoize-loose/output.js | 18 + .../test/fixtures/general/memoize/output.js | 13 + .../optional-eval-call-loose/output.js | 10 + .../general/optional-eval-call/output.js | 10 + .../output.js | 6 + .../parenthesized-member-call-loose/output.js | 31 + .../parenthesized-member-call/output.js | 31 + .../general/super-method-call-loose/output.js | 12 + .../general/super-method-call/output.js | 12 + .../test/fixtures/general/unary/output.js | 7 + .../fixtures/loose/cast-to-boolean/output.js | 85 +++ .../output.js | 9 + .../output.js | 9 + .../regression/10959-transform-ts/output.js | 8 + .../test/fixtures/regression/15887/output.js | 3 + .../test/fixtures/regression/7642/output.js | 7 + .../ts-as-call-context-in-if/output.js | 4 + .../ts-as-call-context/output.js | 2 + .../ts-as-function-call-loose/output.js | 2 + .../ts-as-in-conditional/output.js | 4 + .../ts-as-member-expression/output.js | 2 + .../output.js | 2 + .../snapshots/babel.snap.md | 4 +- .../snapshots/babel_exec.snap.md | 54 +- tasks/transform_conformance/src/constants.rs | 3 +- tasks/transform_conformance/src/test_case.rs | 7 +- 63 files changed, 2028 insertions(+), 61 deletions(-) create mode 100644 crates/oxc_transformer/src/es2020/optional_chaining.rs create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/assignment/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/in-function-params/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/optional-eval-call/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/super-method-call/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-pureGetters/function-call/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-pureGetters/memoize/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-pureGetters/super-method-call/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/assignment/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/cast-to-boolean/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/containers/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/delete-in-function-params/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/delete/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/function-call-loose/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/function-call-spread/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/function-call/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-function-params-loose/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-function-params/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-method-key-loose/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-method-key/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-var-destructuring/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/member-access/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/memoize-loose/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/memoize/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/optional-eval-call-loose/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/optional-eval-call/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/parenthesized-expression-containers/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/parenthesized-member-call-loose/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/parenthesized-member-call/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/super-method-call-loose/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/super-method-call/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/unary/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/loose/cast-to-boolean/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/10959-transform-optional-chaining/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/10959-transform-ts-and-optional-chaining/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/10959-transform-ts/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/15887/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/7642/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-call-context-in-if/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-call-context/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-function-call-loose/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-in-conditional/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-member-expression/output.js create mode 100644 tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-parenthesized-expression-member-call/output.js diff --git a/crates/oxc_ast/src/ast_impl/js.rs b/crates/oxc_ast/src/ast_impl/js.rs index 7710022fadf27..9c3309b37a82c 100644 --- a/crates/oxc_ast/src/ast_impl/js.rs +++ b/crates/oxc_ast/src/ast_impl/js.rs @@ -427,6 +427,15 @@ impl<'a> MemberExpression<'a> { } } + #[allow(missing_docs)] + pub fn object_mut(&mut self) -> &mut Expression<'a> { + match self { + MemberExpression::ComputedMemberExpression(expr) => &mut expr.object, + MemberExpression::StaticMemberExpression(expr) => &mut expr.object, + MemberExpression::PrivateFieldExpression(expr) => &mut expr.object, + } + } + #[allow(missing_docs)] pub fn static_property_name(&self) -> Option<&'a str> { match self { diff --git a/crates/oxc_transformer/src/compiler_assumptions.rs b/crates/oxc_transformer/src/compiler_assumptions.rs index f37995fa930cd..95ceb3e011797 100644 --- a/crates/oxc_transformer/src/compiler_assumptions.rs +++ b/crates/oxc_transformer/src/compiler_assumptions.rs @@ -45,7 +45,6 @@ pub struct CompilerAssumptions { pub no_class_calls: bool, #[serde(default)] - #[deprecated = "Not Implemented"] pub no_document_all: bool, #[serde(default)] @@ -73,7 +72,6 @@ pub struct CompilerAssumptions { pub private_fields_as_properties: bool, #[serde(default)] - #[deprecated = "Not Implemented"] pub pure_getters: bool, #[serde(default)] diff --git a/crates/oxc_transformer/src/context.rs b/crates/oxc_transformer/src/context.rs index 693cff88cd070..03de53e06327a 100644 --- a/crates/oxc_transformer/src/context.rs +++ b/crates/oxc_transformer/src/context.rs @@ -31,7 +31,6 @@ pub struct TransformCtx<'a> { pub module: Module, - #[expect(dead_code)] pub assumptions: CompilerAssumptions, // Helpers diff --git a/crates/oxc_transformer/src/es2020/mod.rs b/crates/oxc_transformer/src/es2020/mod.rs index e00599093ee0b..92cfe88e840f7 100644 --- a/crates/oxc_transformer/src/es2020/mod.rs +++ b/crates/oxc_transformer/src/es2020/mod.rs @@ -1,27 +1,34 @@ +mod nullish_coalescing_operator; +mod optional_chaining; +mod options; + use oxc_ast::ast::*; use oxc_diagnostics::OxcDiagnostic; use oxc_traverse::{Traverse, TraverseCtx}; -use crate::TransformCtx; - -mod nullish_coalescing_operator; -mod options; - pub use nullish_coalescing_operator::NullishCoalescingOperator; +pub use optional_chaining::OptionalChaining; pub use options::ES2020Options; +use crate::TransformCtx; + pub struct ES2020<'a, 'ctx> { ctx: &'ctx TransformCtx<'a>, - options: ES2020Options, // Plugins nullish_coalescing_operator: NullishCoalescingOperator<'a, 'ctx>, + optional_chaining: OptionalChaining<'a, 'ctx>, } impl<'a, 'ctx> ES2020<'a, 'ctx> { pub fn new(options: ES2020Options, ctx: &'ctx TransformCtx<'a>) -> Self { - Self { ctx, nullish_coalescing_operator: NullishCoalescingOperator::new(ctx), options } + Self { + ctx, + options, + nullish_coalescing_operator: NullishCoalescingOperator::new(ctx), + optional_chaining: OptionalChaining::new(ctx), + } } } @@ -30,6 +37,30 @@ impl<'a, 'ctx> Traverse<'a> for ES2020<'a, 'ctx> { if self.options.nullish_coalescing_operator { self.nullish_coalescing_operator.enter_expression(expr, ctx); } + + if self.options.optional_chaining { + self.optional_chaining.enter_expression(expr, ctx); + } + } + + fn enter_formal_parameters( + &mut self, + node: &mut FormalParameters<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + if self.options.optional_chaining { + self.optional_chaining.enter_formal_parameters(node, ctx); + } + } + + fn exit_formal_parameters( + &mut self, + node: &mut FormalParameters<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + if self.options.optional_chaining { + self.optional_chaining.exit_formal_parameters(node, ctx); + } } fn enter_big_int_literal(&mut self, node: &mut BigIntLiteral<'a>, _ctx: &mut TraverseCtx<'a>) { diff --git a/crates/oxc_transformer/src/es2020/optional_chaining.rs b/crates/oxc_transformer/src/es2020/optional_chaining.rs new file mode 100644 index 0000000000000..a26117af80127 --- /dev/null +++ b/crates/oxc_transformer/src/es2020/optional_chaining.rs @@ -0,0 +1,664 @@ +//! ES2020: Optional Chaining +//! +//! This plugin transforms [`ChainExpression`] into a series of `null` and `void 0` checks, +//! resulting in a conditional expression. +//! +//! > This plugin is included in `preset-env`, in ES2020. +//! +//! ## Example +//! +//! Input: +//! ```js +//! const foo = {}; +//! // Read +//! foo?.bar?.bar; +//! // Call +//! foo?.bar?.baz?.(); +//! // Delete +//! delete foo?.bar?.baz; +//! ``` +//! +//! Output: +//! ```js +//! var _foo$bar, _foo$bar2, _foo$bar2$baz, _foo$bar3; +//! const foo = {}; +//! // Read +//! foo === null || foo === void 0 || (_foo$bar = foo.bar) === null || +//! _foo$bar === void 0 ? void 0 : _foo$bar.bar; +//! // Call +//! foo === null || foo === void 0 || (_foo$bar2 = foo.bar) === null || +//! _foo$bar2 === void 0 || (_foo$bar2$baz = _foo$bar2.baz) === null || +//! _foo$bar2$baz === void 0 ? void 0 : _foo$bar2$baz.call(_foo$bar2); +//! // Delete +//! foo === null || foo === void 0 || (_foo$bar3 = foo.bar) === null || +//! _foo$bar3 === void 0 ? true : delete _foo$bar3.baz; +//! ``` +//! +//! ## Implementation +//! +//! Due to the different architecture, we found it hard to port the implementation from Babel directly; +//! however, our implementation is written based on Babel’s transformed output. +//! +//! Nevertheless, our outputs still have some differences from Babel’s output. +//! +//! ## References +//! +//! * Babel docs: +//! * Babel implementation: +//! * Optional chaining TC39 proposal: + +use std::mem; + +use oxc_allocator::CloneIn; +use oxc_ast::{ast::*, NONE}; +use oxc_semantic::{IsGlobalReference, SymbolFlags}; +use oxc_span::SPAN; +use oxc_traverse::{Ancestor, BoundIdentifier, MaybeBoundIdentifier, Traverse, TraverseCtx}; + +use crate::TransformCtx; + +#[derive(Debug)] +enum CallContext<'a> { + /// `new.target?.()` + None, + /// `super.method?.()` + This, + /// All other cases + Binding(MaybeBoundIdentifier<'a>), +} + +pub struct OptionalChaining<'a, 'ctx> { + ctx: &'ctx TransformCtx<'a>, + + // states + is_inside_function_parameter: bool, + temp_binding: Option>, + /// .call(context) + /// ^^^^^^^ + call_context: CallContext<'a>, +} + +impl<'a, 'ctx> OptionalChaining<'a, 'ctx> { + pub fn new(ctx: &'ctx TransformCtx<'a>) -> Self { + Self { + ctx, + is_inside_function_parameter: false, + temp_binding: None, + call_context: CallContext::None, + } + } +} + +impl<'a, 'ctx> Traverse<'a> for OptionalChaining<'a, 'ctx> { + fn enter_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { + *expr = match expr { + Expression::ChainExpression(_) => { + if self.is_inside_function_parameter { + // To insert the temp binding in the correct scope, we wrap the expression with + // an arrow function. During the chain expression transformation, the temp binding + // will be inserted into the arrow function's body. + Self::wrap_arrow_function(expr, ctx) + } else { + self.transform_chain_expression(false, expr, ctx) + } + } + Expression::UnaryExpression(unary_expr) + if unary_expr.operator == UnaryOperator::Delete => + { + let Expression::ChainExpression(_) = unary_expr.argument else { + return; + }; + if self.is_inside_function_parameter { + // Same as the above explanation + Self::wrap_arrow_function(expr, ctx) + } else { + self.transform_chain_expression(true, &mut unary_expr.argument, ctx) + } + } + _ => return, + }; + } + + // `#[inline]` because this is a hot path + #[inline] + fn enter_formal_parameters(&mut self, _: &mut FormalParameters<'a>, _: &mut TraverseCtx<'a>) { + self.is_inside_function_parameter = true; + } + + // `#[inline]` because this is a hot path + #[inline] + fn exit_formal_parameters( + &mut self, + _node: &mut FormalParameters<'a>, + _ctx: &mut TraverseCtx<'a>, + ) { + self.is_inside_function_parameter = false; + } +} + +impl<'a, 'ctx> OptionalChaining<'a, 'ctx> { + fn set_temp_binding(&mut self, binding: BoundIdentifier<'a>) { + self.temp_binding.replace(binding); + } + + fn set_binding_context(&mut self, binding: MaybeBoundIdentifier<'a>) { + self.call_context = CallContext::Binding(binding); + } + + fn set_this_context(&mut self) { + self.call_context = CallContext::This; + } + + /// Get the call context from [`Self::call_context`] + fn get_call_context(&mut self, ctx: &mut TraverseCtx<'a>) -> Argument<'a> { + debug_assert!(!matches!(self.call_context, CallContext::None)); + Argument::from(if let CallContext::Binding(binding) = &self.call_context { + binding.create_read_expression(ctx) + } else { + ctx.ast.expression_this(SPAN) + }) + } + + /// Given an IdentifierReference which is [`CallExpression::callee`] to compare with the collected context + fn should_specify_context( + &self, + ident: &IdentifierReference<'a>, + ctx: &mut TraverseCtx<'a>, + ) -> bool { + match &self.call_context { + CallContext::None => false, + CallContext::This => true, + CallContext::Binding(binding) => { + binding.name != ident.name + || binding.symbol_id.is_some_and(|symbol_id| { + ctx.symbols() + .get_reference(ident.reference_id()) + .symbol_id() + .is_some_and(|id| id != symbol_id) + }) + } + } + } + + /// Check if we should create a temp variable for the identifier + /// + /// Except for `eval`, we should create a temp variable for all global references + fn should_create_temp_variable_for_identifier( + &self, + ident: &IdentifierReference<'a>, + ctx: &TraverseCtx<'a>, + ) -> bool { + !self.ctx.assumptions.pure_getters + && ident.is_global_reference(ctx.symbols()) + && ident.name != "eval" + } + + /// Return `left === null` + fn wrap_null_check(&self, left: Expression<'a>, ctx: &TraverseCtx<'a>) -> Expression<'a> { + let operator = if self.ctx.assumptions.no_document_all { + BinaryOperator::Equality + } else { + BinaryOperator::StrictEquality + }; + ctx.ast.expression_binary(SPAN, left, operator, ctx.ast.expression_null_literal(SPAN)) + } + + /// Return `left === void 0` + fn wrap_void0_check(left: Expression<'a>, ctx: &TraverseCtx<'a>) -> Expression<'a> { + let operator = BinaryOperator::StrictEquality; + ctx.ast.expression_binary(SPAN, left, operator, ctx.ast.void_0(SPAN)) + } + + /// Return `left1 === null || left2 === void 0` + fn wrap_optional_check( + &self, + left1: Expression<'a>, + left2: Expression<'a>, + ctx: &TraverseCtx<'a>, + ) -> Expression<'a> { + let null_check = self.wrap_null_check(left1, ctx); + if self.ctx.assumptions.no_document_all { + null_check + } else { + let void0_check = Self::wrap_void0_check(left2, ctx); + Self::create_logical_expression(null_check, void0_check, ctx) + } + } + + /// Return `left || right` + fn create_logical_expression( + left: Expression<'a>, + right: Expression<'a>, + ctx: &TraverseCtx<'a>, + ) -> Expression<'a> { + ctx.ast.expression_logical(SPAN, left, LogicalOperator::Or, right) + } + + /// Return `left ? void 0 : alternative` + /// + /// The [`ConditionalExpression::consequent`] depends on whether + /// `is_delete` is true or false. + fn create_conditional_expression( + is_delete: bool, + test: Expression<'a>, + alternate: Expression<'a>, + ctx: &TraverseCtx<'a>, + ) -> Expression<'a> { + let consequent = if is_delete { + ctx.ast.expression_boolean_literal(SPAN, true) + } else { + ctx.ast.void_0(SPAN) + }; + ctx.ast.expression_conditional(SPAN, test, consequent, alternate) + } + + /// Wrap the expression with an arrow function + /// + /// `expr` -> `() => { return expr; }` + fn wrap_arrow_function(expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) -> Expression<'a> { + let kind = FormalParameterKind::ArrowFormalParameters; + let params = ctx.ast.formal_parameters(SPAN, kind, ctx.ast.vec(), NONE); + let statements = + ctx.ast.vec1(ctx.ast.statement_return(SPAN, Some(ctx.ast.move_expression(expr)))); + let body = ctx.ast.function_body(SPAN, ctx.ast.vec(), statements); + let scope_id = ctx.current_scope_id(); + let arrow = ctx.ast.alloc_arrow_function_expression_with_scope_id( + SPAN, false, false, NONE, params, NONE, body, scope_id, + ); + // IIFE + ctx.ast.expression_call( + SPAN, + Expression::ArrowFunctionExpression(arrow), + NONE, + ctx.ast.vec(), + false, + ) + } + + /// Convert chain expression to expression + /// + /// - [ChainElement::CallExpression] -> [Expression::CallExpression] + /// - [ChainElement::StaticMemberExpression] -> [Expression::StaticMemberExpression] + /// - [ChainElement::ComputedMemberExpression] -> [Expression::ComputedMemberExpression] + /// - [ChainElement::PrivateFieldExpression] -> [Expression::PrivateFieldExpression] + /// - [ChainElement::TSNonNullExpression] -> [TSNonNullExpression::expression] + /// + /// `#[inline]` so that compiler sees that `expr` is an [`Expression::ChainExpression`]. + #[inline] + fn convert_chain_expression_to_expression( + expr: &mut Expression<'a>, + ctx: &mut TraverseCtx<'a>, + ) -> Expression<'a> { + let Expression::ChainExpression(chain_expr) = ctx.ast.move_expression(expr) else { + unreachable!() + }; + match chain_expr.unbox().expression { + element @ match_member_expression!(ChainElement) => { + Expression::from(element.into_member_expression()) + } + ChainElement::CallExpression(call) => Expression::CallExpression(call), + ChainElement::TSNonNullExpression(non_null) => non_null.unbox().expression, + } + } + + /// Generate a binding based on the node and insert the binding at the top of the current block + fn generate_binding( + &mut self, + expr: &Expression<'a>, + ctx: &mut TraverseCtx<'a>, + ) -> BoundIdentifier<'a> { + let binding = ctx + .generate_uid_in_current_scope_based_on_node(expr, SymbolFlags::FunctionScopedVariable); + self.ctx.var_declarations.insert_var(&binding, None, ctx); + binding + } + + /// Return `left = right` + fn create_assignment_expression( + left: AssignmentTarget<'a>, + right: Expression<'a>, + ctx: &TraverseCtx<'a>, + ) -> Expression<'a> { + ctx.ast.expression_assignment(SPAN, AssignmentOperator::Assign, left, right) + } + + /// Transform chain expression to conditional expression which contains a lot of checks + /// + /// This is the root transform function for chain expressions. It calls + /// [`Self::transform_chain_element_recursion`] to transform the chain expression elements, + /// and then joins the transformed elements with the conditional expression. + fn transform_chain_expression( + &mut self, + is_delete: bool, + chain_expr: &mut Expression<'a>, + ctx: &mut TraverseCtx<'a>, + ) -> Expression<'a> { + let mut chain_expr = Self::convert_chain_expression_to_expression(chain_expr, ctx); + // ^^^^^^^^^^ After the recursive transformation, the chain_expr will be transformed into + // a pure non-optional expression and it's the last part of the chain expression. + + let left = + self.transform_chain_element_recursion(&mut chain_expr, ctx).unwrap_or_else(|| { + unreachable!( + "Given chain expression certainly contains at least one optional expression, + so it must return a transformed expression" + ) + }); + + // If the chain expression is an argument of a UnaryExpression and its operator is `delete`, + // we need to wrap the last part with a `delete` unary expression + // `delete foo?.bar` -> `... || delete _Foo.bar;` + // ^^^^^^ ^^^^^^^^ Here we will wrap the right part with a `delete` unary expression + if is_delete { + chain_expr = ctx.ast.expression_unary(SPAN, UnaryOperator::Delete, chain_expr); + }; + + // If this chain expression is a callee of a CallExpression, we need to transform it to accept a proper context + // `(Foo?.["m"])();` -> `(... _Foo["m"].bind(_Foo))();` + // ^^^^^^^^^^^ Here we will handle the `right` part to bind a proper context + if matches!(ctx.ancestor(1), Ancestor::CallExpressionCallee(_)) { + chain_expr = self.transform_expression_to_bind_context(chain_expr, ctx); + }; + // Clear states + self.temp_binding = None; + self.call_context = CallContext::None; + + Self::create_conditional_expression(is_delete, left, chain_expr, ctx) + } + + /// Transform an expression to bind a proper context + /// + /// `Foo.bar` -> `Foo.bar.bind(context)` + fn transform_expression_to_bind_context( + &mut self, + mut expr: Expression<'a>, + ctx: &mut TraverseCtx<'a>, + ) -> Expression<'a> { + // Find proper context + let context = if let Some(member) = expr.as_member_expression_mut() { + let object = member.object_mut().get_inner_expression_mut(); + let context = if self.ctx.assumptions.pure_getters { + // TODO: `clone_in` causes reference loss of reference id + object.clone_in(ctx.ast.allocator) + } else if let Expression::Identifier(ident) = object { + MaybeBoundIdentifier::from_identifier_reference(ident, ctx) + .create_read_expression(ctx) + } else { + // `foo.bar` -> `_foo$bar = foo.bar` + let binding = self.generate_binding(object, ctx); + *object = Self::create_assignment_expression( + binding.create_read_write_target(ctx), + ctx.ast.move_expression(object), + ctx, + ); + binding.create_read_expression(ctx) + }; + Argument::from(context) + } else { + self.get_call_context(ctx) + }; + + // `expr.bind(context)` + let arguments = ctx.ast.vec1(context); + let property = ctx.ast.identifier_name(SPAN, "bind"); + let callee = ctx.ast.member_expression_static(SPAN, expr, property, false); + let callee = Expression::from(callee); + ctx.ast.expression_call(SPAN, callee, NONE, arguments, false) + } + + /// Recursively transform chain expression elements + /// + /// ## Depth-first transformation + /// + /// Start from the given [`Expression`] which is converted from [`ChainExpression::expression`] + /// by [`Self::convert_chain_expression_to_expression`], and dive into the deepest + /// expression, until it reaches the end of the chain expression and starts to transform. + /// + /// ### Demonstration + /// + /// For the given expression `foo?.bar?.baz?.()` + /// + /// > NOTE: Here assume that `foo` is defined somewhere. + /// + /// 1. Start from the root expression `foo?.bar?.baz?.()` + /// + /// 2. Recurse and go into the deepest optional expression `foo?.bar` + /// + /// 3. The `foo?.bar` is an optional [`StaticMemberExpression`], so transform `foo` to + /// `foo === null || foo === void 0` and return the transformed expression back to the parent + /// + /// 4. Got to here, we now have a left expression as the above transformed expression, and the current expression + /// is `foo.bar?.baz`, and it's also an optional [`StaticMemberExpression`], so transform `foo.bar` to + /// `(_foo$bar = foo.bar) === null || _foo$bar === void 0` and join it with the left expression, and return + /// the joined expression back to the parent. + /// + /// > NOTE: The callee(`foo.bar`) is assigned to a temp binding(`_foo$bar`), so the original callee is also replaced with + /// the temp binding(`_foo$bar`) + /// + /// 5. Repeat the above steps until back to the root expression, and the final expression will be + /// + /// ```js + /// foo === null || foo === void 0 || (_foo$bar = foo.bar) === null || _foo$bar === void 0 || + /// (_foo$bar$baz = _foo$bar.baz) === null || _foo$bar$baz === void 0; + /// ``` + /// + /// After transformation, the passed-in expression will be replaced with `_foo$bar$baz.call(_foo$bar)`, + /// and it will be used to construct the final conditional expression in [`Self::transform_chain_expression`] + fn transform_chain_element_recursion( + &mut self, + expr: &mut Expression<'a>, + ctx: &mut TraverseCtx<'a>, + ) -> Option> { + // Skip parenthesized expression or other TS-syntax expressions + let expr = expr.get_inner_expression_mut(); + match expr { + // `(foo?.bar)?.baz` + // ^^^^^^^^^^ The nested chain expression is always under the ParenthesizedExpression + Expression::ChainExpression(_) => { + *expr = Self::convert_chain_expression_to_expression(expr, ctx); + self.transform_chain_element_recursion(expr, ctx) + } + // `foo?.bar?.baz` + Expression::StaticMemberExpression(member) => { + let left = self.transform_chain_element_recursion(&mut member.object, ctx); + if member.optional { + member.optional = false; + Some(self.transform_optional_expression(false, left, &mut member.object, ctx)) + } else { + left + } + } + // `foo?.[bar]?.[baz]` + Expression::ComputedMemberExpression(member) => { + let left = self.transform_chain_element_recursion(&mut member.object, ctx); + if member.optional { + member.optional = false; + Some(self.transform_optional_expression(false, left, &mut member.object, ctx)) + } else { + left + } + } + // `this?.#foo?.bar` + Expression::PrivateFieldExpression(member) => { + let left = self.transform_chain_element_recursion(&mut member.object, ctx); + if member.optional { + member.optional = false; + Some(self.transform_optional_expression(false, left, &mut member.object, ctx)) + } else { + left + } + } + // `foo?.bar?.bar?.()` + Expression::CallExpression(call) => { + let left = self.transform_chain_element_recursion(&mut call.callee, ctx); + if call.optional { + call.optional = false; + let callee = call.callee.get_inner_expression_mut(); + let left = Some(self.transform_optional_expression(true, left, callee, ctx)); + + if !self.ctx.assumptions.pure_getters { + // After transformation of the callee, this call expression may lose the original context, + // so we need to check if we need to specify the context. + if let Expression::Identifier(ident) = callee { + if self.should_specify_context(ident, ctx) { + // `foo$bar(...)` -> `foo$bar.call(context, ...)` + let callee = ctx.ast.move_expression(callee); + let property = ctx.ast.identifier_name(SPAN, "call"); + let member = + ctx.ast.member_expression_static(SPAN, callee, property, false); + call.callee = Expression::from(member); + call.arguments.insert(0, self.get_call_context(ctx)); + } + } + } + + left + } else { + left + } + } + _ => None, + } + } + + /// Transform optional expressions + /// + /// - `foo` -> `foo === null || foo === void 0` + /// - `foo.bar` -> `(foo$bar = foo.bar) === null || foo$bar === void 0` + /// + /// NOTE: After transformation, the original expression will be replaced with the temp binding + fn transform_optional_expression( + &mut self, + is_call: bool, + left: Option>, + expr: &mut Expression<'a>, + ctx: &mut TraverseCtx<'a>, + ) -> Expression<'a> { + if let Some(left) = left { + return self.transform_and_join_expression(is_call, left, expr, ctx); + } + + // Skip parenthesized expression or other TS-syntax expressions + let expr = expr.get_inner_expression_mut(); + + // If the expression is an identifier and it's not a global reference, we just wrap it with checks + // `foo` -> `foo === null || foo === void 0` + if let Expression::Identifier(ident) = expr { + if !self.should_create_temp_variable_for_identifier(ident, ctx) { + let binding = MaybeBoundIdentifier::from_identifier_reference(ident, ctx); + let left1 = binding.create_read_expression(ctx); + let left2 = binding.create_read_expression(ctx); + if ident.name == "eval" { + // `eval?.()` is an indirect eval call transformed to `(0,eval)()` + let zero = ctx.ast.number_0(); + let original_callee = ctx.ast.move_expression(expr); + let expressions = ctx.ast.vec_from_array([zero, original_callee]); + *expr = ctx.ast.expression_sequence(SPAN, expressions); + } + self.set_binding_context(binding); + return self.wrap_optional_check(left1, left2, ctx); + } + } + + // We should generate a temp binding for the expression first to avoid the next step changing the expression. + let temp_binding = self.generate_binding(expr, ctx); + if is_call && !self.ctx.assumptions.pure_getters { + if let Some(member) = expr.as_member_expression_mut() { + let object = member.object_mut(); + // If the [`MemberExpression::object`] is a global reference, we need to assign it to a temp binding. + // i.e `foo` -> `(_foo = foo)` + if let Expression::Identifier(ident) = object { + let binding = if self.should_create_temp_variable_for_identifier(ident, ctx) { + let binding = self.generate_binding(object, ctx); + // `(_foo = foo)` + *object = Self::create_assignment_expression( + binding.create_read_write_target(ctx), + ctx.ast.move_expression(object), + ctx, + ); + binding.to_maybe_bound_identifier() + } else { + MaybeBoundIdentifier::from_identifier_reference(ident, ctx) + }; + self.set_binding_context(binding); + } else if matches!(object, Expression::Super(_)) { + self.set_this_context(); + } + } + } + + // Replace the expression with the temp binding and assign the original expression to the temp binding + let expr = mem::replace(expr, temp_binding.create_read_expression(ctx)); + // `(binding = expr)` + let assignment_expression = Self::create_assignment_expression( + temp_binding.create_read_write_target(ctx), + expr, + ctx, + ); + // `(binding = expr) === null || binding === void 0` + let expr = self.wrap_optional_check( + assignment_expression, + temp_binding.create_read_expression(ctx), + ctx, + ); + + self.set_temp_binding(temp_binding); + expr + } + + /// Transform the expression and join it with the `left` expression + /// + /// - `left || (binding = expr) === null || binding === void 0` + /// + /// NOTE: After transformation, the original expression will be replaced with the temp binding + fn transform_and_join_expression( + &mut self, + is_call: bool, + left: Expression<'a>, + expr: &mut Expression<'a>, + ctx: &mut TraverseCtx<'a>, + ) -> Expression<'a> { + if is_call { + // We cannot reuse the temp binding for calls because we need to + // store both the method and the receiver. + // And because we will create a new temp binding for the callee and the original temp binding + // will become the call context, we take the current temp binding and set it + // as the call context. + if let Some(temp_binding) = self.temp_binding.take() { + self.set_binding_context(temp_binding.to_maybe_bound_identifier()); + } + } + + let temp_binding = { + if self.temp_binding.is_none() { + let binding = self.generate_binding(expr, ctx); + self.set_temp_binding(binding); + } + self.temp_binding.as_ref().unwrap() + }; + + // Replace the expression with the temp binding and assign the original expression to the temp binding + let expr = mem::replace(expr, temp_binding.create_read_expression(ctx)); + // `(binding = expr)` + let assignment_expression = Self::create_assignment_expression( + temp_binding.create_read_write_target(ctx), + expr, + ctx, + ); + + let reference = temp_binding.create_read_expression(ctx); + // `left || (binding = expr) === null` + let left = Self::create_logical_expression( + left, + self.wrap_null_check(assignment_expression, ctx), + ctx, + ); + + if self.ctx.assumptions.no_document_all { + left + } else { + // `left || (binding = expr) === null || binding === void 0` + Self::create_logical_expression(left, Self::wrap_void0_check(reference, ctx), ctx) + } + } +} diff --git a/crates/oxc_transformer/src/es2020/options.rs b/crates/oxc_transformer/src/es2020/options.rs index cd76e6acd5f1f..c452ef1584d2e 100644 --- a/crates/oxc_transformer/src/es2020/options.rs +++ b/crates/oxc_transformer/src/es2020/options.rs @@ -8,4 +8,7 @@ pub struct ES2020Options { #[serde(skip)] pub big_int: bool, + + #[serde(skip)] + pub optional_chaining: bool, } diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index bba7dcb19c544..c665408c16e6b 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -297,6 +297,22 @@ impl<'a, 'ctx> Traverse<'a> for TransformerImpl<'a, 'ctx> { } } + fn enter_formal_parameters( + &mut self, + node: &mut FormalParameters<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + self.x2_es2020.enter_formal_parameters(node, ctx); + } + + fn exit_formal_parameters( + &mut self, + node: &mut FormalParameters<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + self.x2_es2020.exit_formal_parameters(node, ctx); + } + fn enter_formal_parameter( &mut self, param: &mut FormalParameter<'a>, diff --git a/crates/oxc_transformer/src/options/babel/plugins.rs b/crates/oxc_transformer/src/options/babel/plugins.rs index 79a70100012e2..ffd4bffc95d48 100644 --- a/crates/oxc_transformer/src/options/babel/plugins.rs +++ b/crates/oxc_transformer/src/options/babel/plugins.rs @@ -62,6 +62,7 @@ pub struct BabelPlugins { // ES2019 pub optional_catch_binding: bool, // ES2020 + pub optional_chaining: bool, pub nullish_coalescing_operator: bool, // ES2021 pub logical_assignment_operators: bool, @@ -127,6 +128,7 @@ impl TryFrom for BabelPlugins { } "transform-async-generator-functions" => p.async_generator_functions = true, "transform-optional-catch-binding" => p.optional_catch_binding = true, + "transform-optional-chaining" => p.optional_chaining = true, "transform-nullish-coalescing-operator" => p.nullish_coalescing_operator = true, "transform-logical-assignment-operators" => p.logical_assignment_operators = true, "transform-class-static-block" => p.class_static_block = true, diff --git a/crates/oxc_transformer/src/options/env.rs b/crates/oxc_transformer/src/options/env.rs index fc55a04c268cd..1e384b8a38afa 100644 --- a/crates/oxc_transformer/src/options/env.rs +++ b/crates/oxc_transformer/src/options/env.rs @@ -77,6 +77,7 @@ impl EnvOptions { nullish_coalescing_operator: true, // Turn this on would throw error for all bigints. big_int: false, + optional_chaining: true, }, es2021: ES2021Options { logical_assignment_operators: true }, es2022: ES2022Options { @@ -173,6 +174,7 @@ impl From for EnvOptions { es2020: ES2020Options { nullish_coalescing_operator: o.has_feature(ES2020NullishCoalescingOperator), big_int: o.has_feature(ES2020BigInt), + optional_chaining: o.has_feature(ES2020OptionalChaining), }, es2021: ES2021Options { logical_assignment_operators: o.has_feature(ES2021LogicalAssignmentOperators), diff --git a/crates/oxc_transformer/src/options/es_features.rs b/crates/oxc_transformer/src/options/es_features.rs index b0ef10a550515..cabac4aaca09a 100644 --- a/crates/oxc_transformer/src/options/es_features.rs +++ b/crates/oxc_transformer/src/options/es_features.rs @@ -657,6 +657,23 @@ pub fn features() -> &'static FxHashMap { (Es, Version(2019u32, 0, 0)), ])), ), + ( + ES2020OptionalChaining, + EngineTargets::new(FxHashMap::from_iter([ + (Chrome, Version(91u32, 0u32, 0u32)), + (Safari, Version(13u32, 1u32, 0u32)), + (OperaMobile, Version(64u32, 0u32, 0u32)), + (Samsung, Version(16u32, 0u32, 0u32)), + (Node, Version(16u32, 9u32, 0u32)), + (Firefox, Version(74u32, 0u32, 0u32)), + (Deno, Version(1u32, 9u32, 0u32)), + (Electron, Version(13u32, 0u32, 0u32)), + (Opera, Version(77u32, 0u32, 0u32)), + (Ios, Version(13u32, 4u32, 0u32)), + (Edge, Version(91u32, 0u32, 0u32)), + (Es, Version(2019u32, 0, 0)), + ])), + ), ( ES2020NullishCoalescingOperator, EngineTargets::new(FxHashMap::from_iter([ diff --git a/crates/oxc_transformer/src/options/mod.rs b/crates/oxc_transformer/src/options/mod.rs index ba9d44a097e19..04085fb6eb9d6 100644 --- a/crates/oxc_transformer/src/options/mod.rs +++ b/crates/oxc_transformer/src/options/mod.rs @@ -210,6 +210,7 @@ impl TryFrom<&BabelOptions> for TransformOptions { }; let es2020 = ES2020Options { + optional_chaining: options.plugins.optional_chaining || env.es2020.optional_chaining, nullish_coalescing_operator: options.plugins.nullish_coalescing_operator || env.es2020.nullish_coalescing_operator, big_int: env.es2020.big_int, diff --git a/tasks/coverage/snapshots/semantic_misc.snap b/tasks/coverage/snapshots/semantic_misc.snap index c33b7e2790fa7..96c9c8a09cb05 100644 --- a/tasks/coverage/snapshots/semantic_misc.snap +++ b/tasks/coverage/snapshots/semantic_misc.snap @@ -55,21 +55,27 @@ tasks/coverage/misc/pass/oxc-3948-1.ts semantic error: Bindings mismatch: after transform: ScopeId(0): ["BrowserWorkingCopyBackupTracker", "CancellationToken", "DisposableStore", "EditorPart", "EditorService", "IEditorGroupsService", "IEditorService", "IFilesConfigurationService", "IInstantiationService", "ILifecycleService", "ILogService", "IUntitledTextResourceEditorInput", "IWorkingCopyBackup", "IWorkingCopyBackupService", "IWorkingCopyEditorHandler", "IWorkingCopyEditorService", "IWorkingCopyService", "InMemoryTestWorkingCopyBackupService", "LifecyclePhase", "Schemas", "TestServiceAccessor", "TestWorkingCopy", "URI", "UntitledTextEditorInput", "VSBuffer", "_asyncToGenerator", "assert", "bufferToReadable", "createEditorPart", "ensureNoDisposablesAreLeakedInTestSuite", "isWindows", "registerTestResourceEditor", "timeout", "toResource", "toTypedWorkingCopyId", "toUntypedWorkingCopyId", "workbenchInstantiationService", "workbenchTeardown"] rebuilt : ScopeId(0): ["BrowserWorkingCopyBackupTracker", "DisposableStore", "EditorService", "IEditorGroupsService", "IEditorService", "IFilesConfigurationService", "ILifecycleService", "ILogService", "IWorkingCopyBackupService", "IWorkingCopyEditorService", "IWorkingCopyService", "InMemoryTestWorkingCopyBackupService", "LifecyclePhase", "Schemas", "TestServiceAccessor", "TestWorkingCopy", "URI", "UntitledTextEditorInput", "VSBuffer", "_asyncToGenerator", "assert", "bufferToReadable", "createEditorPart", "ensureNoDisposablesAreLeakedInTestSuite", "isWindows", "registerTestResourceEditor", "timeout", "toResource", "toTypedWorkingCopyId", "toUntypedWorkingCopyId", "workbenchInstantiationService", "workbenchTeardown"] +Bindings mismatch: +after transform: ScopeId(13): ["_await$accessor$edito", "accessor", "untitled", "untitledTextEditor", "untitledTextModel", "workingCopyBackupService"] +rebuilt : ScopeId(20): ["_await$accessor$edito", "_untitledTextModel$te", "accessor", "untitled", "untitledTextEditor", "untitledTextModel", "workingCopyBackupService"] +Bindings mismatch: +after transform: ScopeId(14): ["_untitledTextModel$te"] +rebuilt : ScopeId(21): [] Symbol reference IDs mismatch for "URI": after transform: SymbolId(1): [ReferenceId(109), ReferenceId(117), ReferenceId(156), ReferenceId(158), ReferenceId(160), ReferenceId(162)] -rebuilt : SymbolId(1): [ReferenceId(150), ReferenceId(152), ReferenceId(154), ReferenceId(156)] +rebuilt : SymbolId(1): [ReferenceId(158), ReferenceId(160), ReferenceId(162), ReferenceId(164)] Symbol reference IDs mismatch for "IEditorService": after transform: SymbolId(2): [ReferenceId(23), ReferenceId(24), ReferenceId(67), ReferenceId(184)] -rebuilt : SymbolId(2): [ReferenceId(17), ReferenceId(58), ReferenceId(177)] +rebuilt : SymbolId(2): [ReferenceId(17), ReferenceId(58), ReferenceId(185)] Symbol reference IDs mismatch for "IEditorGroupsService": after transform: SymbolId(4): [ReferenceId(25), ReferenceId(26), ReferenceId(57), ReferenceId(176)] -rebuilt : SymbolId(3): [ReferenceId(18), ReferenceId(49), ReferenceId(170)] +rebuilt : SymbolId(3): [ReferenceId(18), ReferenceId(49), ReferenceId(178)] Symbol reference IDs mismatch for "EditorService": after transform: SymbolId(5): [ReferenceId(61), ReferenceId(64), ReferenceId(178), ReferenceId(181)] -rebuilt : SymbolId(4): [ReferenceId(55), ReferenceId(174)] +rebuilt : SymbolId(4): [ReferenceId(55), ReferenceId(182)] Symbol reference IDs mismatch for "IWorkingCopyBackupService": after transform: SymbolId(7): [ReferenceId(11), ReferenceId(12), ReferenceId(51), ReferenceId(170)] -rebuilt : SymbolId(5): [ReferenceId(11), ReferenceId(43), ReferenceId(164)] +rebuilt : SymbolId(5): [ReferenceId(11), ReferenceId(43), ReferenceId(172)] Symbol reference IDs mismatch for "IFilesConfigurationService": after transform: SymbolId(10): [ReferenceId(13), ReferenceId(14)] rebuilt : SymbolId(8): [ReferenceId(12)] @@ -87,19 +93,22 @@ after transform: SymbolId(17): [ReferenceId(38), ReferenceId(87)] rebuilt : SymbolId(13): [ReferenceId(31)] Symbol reference IDs mismatch for "InMemoryTestWorkingCopyBackupService": after transform: SymbolId(19): [ReferenceId(43), ReferenceId(46), ReferenceId(165)] -rebuilt : SymbolId(15): [ReferenceId(38), ReferenceId(159)] +rebuilt : SymbolId(15): [ReferenceId(38), ReferenceId(167)] Symbol reference IDs mismatch for "TestServiceAccessor": after transform: SymbolId(21): [ReferenceId(1), ReferenceId(40), ReferenceId(71), ReferenceId(155), ReferenceId(188)] -rebuilt : SymbolId(17): [ReferenceId(62), ReferenceId(181)] +rebuilt : SymbolId(17): [ReferenceId(62), ReferenceId(189)] Symbol reference IDs mismatch for "IWorkingCopyEditorService": after transform: SymbolId(32): [ReferenceId(21), ReferenceId(22)] rebuilt : SymbolId(26): [ReferenceId(16)] Symbol reference IDs mismatch for "TestWorkingCopyBackupTracker": after transform: SymbolId(39): [ReferenceId(42), ReferenceId(74), ReferenceId(154), ReferenceId(215)] -rebuilt : SymbolId(34): [ReferenceId(65), ReferenceId(208)] +rebuilt : SymbolId(34): [ReferenceId(65), ReferenceId(216)] +Symbol scope ID mismatch for "_untitledTextModel$te": +after transform: SymbolId(138): ScopeId(14) +rebuilt : SymbolId(63): ScopeId(20) Unresolved reference IDs mismatch for "Promise": after transform: [ReferenceId(36), ReferenceId(39), ReferenceId(82), ReferenceId(114), ReferenceId(153), ReferenceId(282)] -rebuilt : [ReferenceId(281)] +rebuilt : [ReferenceId(289)] tasks/coverage/misc/pass/oxc-4449.ts semantic error: Bindings mismatch: diff --git a/tasks/coverage/snapshots/semantic_test262.snap b/tasks/coverage/snapshots/semantic_test262.snap index 756fc9e92226e..5d9e10c8bb08d 100644 --- a/tasks/coverage/snapshots/semantic_test262.snap +++ b/tasks/coverage/snapshots/semantic_test262.snap @@ -2,7 +2,7 @@ commit: 06454619 semantic_test262 Summary: AST Parsed : 43851/43851 (100.00%) -Positive Passed: 43040/43851 (98.15%) +Positive Passed: 43038/43851 (98.15%) tasks/coverage/test262/test/annexB/language/function-code/if-decl-else-decl-a-func-block-scoping.js semantic error: Symbol scope ID mismatch for "f": after transform: SymbolId(3): ScopeId(4294967294) @@ -3786,6 +3786,43 @@ Unresolved references mismatch: after transform: ["$DONE", "Object", "assert", "require"] rebuilt : ["$DONE", "Object", "_superprop_getMethod", "assert", "require"] +tasks/coverage/test262/test/language/expressions/optional-chaining/iteration-statement-for-of-type-error.js +semantic error: Bindings mismatch: +after transform: ScopeId(1): [] +rebuilt : ScopeId(1): ["_ref"] +Bindings mismatch: +after transform: ScopeId(2): ["_ref", "key"] +rebuilt : ScopeId(2): ["key"] +Bindings mismatch: +after transform: ScopeId(3): [] +rebuilt : ScopeId(3): ["_ref2"] +Bindings mismatch: +after transform: ScopeId(4): ["_ref2", "key"] +rebuilt : ScopeId(4): ["key"] +Symbol scope ID mismatch for "_ref": +after transform: SymbolId(5): ScopeId(2) +rebuilt : SymbolId(0): ScopeId(1) +Symbol scope ID mismatch for "_ref2": +after transform: SymbolId(6): ScopeId(4) +rebuilt : SymbolId(2): ScopeId(3) + +tasks/coverage/test262/test/language/expressions/optional-chaining/iteration-statement-for.js +semantic error: Bindings mismatch: +after transform: ScopeId(0): ["count", "count2", "obj", "obj2", "obj3", "touched"] +rebuilt : ScopeId(0): ["_obj3$a", "_undefined", "count", "count2", "obj", "obj2", "obj3", "touched"] +Bindings mismatch: +after transform: ScopeId(5): ["_undefined"] +rebuilt : ScopeId(5): [] +Bindings mismatch: +after transform: ScopeId(8): ["_obj3$a"] +rebuilt : ScopeId(8): [] +Symbol scope ID mismatch for "_undefined": +after transform: SymbolId(6): ScopeId(5) +rebuilt : SymbolId(0): ScopeId(0) +Symbol scope ID mismatch for "_obj3$a": +after transform: SymbolId(7): ScopeId(8) +rebuilt : SymbolId(1): ScopeId(0) + tasks/coverage/test262/test/language/module-code/export-default-asyncfunction-declaration-binding.js semantic error: Symbol flags mismatch for "_A": after transform: SymbolId(1): SymbolFlags(FunctionScopedVariable) diff --git a/tasks/coverage/snapshots/semantic_typescript.snap b/tasks/coverage/snapshots/semantic_typescript.snap index 6a630dc206491..89f7499e0700a 100644 --- a/tasks/coverage/snapshots/semantic_typescript.snap +++ b/tasks/coverage/snapshots/semantic_typescript.snap @@ -2,7 +2,7 @@ commit: df9d1650 semantic_typescript Summary: AST Parsed : 6490/6490 (100.00%) -Positive Passed: 2666/6490 (41.08%) +Positive Passed: 2663/6490 (41.03%) tasks/coverage/typescript/tests/cases/compiler/2dArrays.ts semantic error: Symbol reference IDs mismatch for "Cell": after transform: SymbolId(0): [ReferenceId(1)] @@ -14527,7 +14527,7 @@ after transform: [ReferenceId(1), ReferenceId(14)] rebuilt : [ReferenceId(3)] Unresolved reference IDs mismatch for "Symbol": after transform: [ReferenceId(8), ReferenceId(55), ReferenceId(69), ReferenceId(72)] -rebuilt : [ReferenceId(43), ReferenceId(46)] +rebuilt : [ReferenceId(46), ReferenceId(49)] Unresolved reference IDs mismatch for "WeakMap": after transform: [ReferenceId(5), ReferenceId(9)] rebuilt : [ReferenceId(2)] @@ -22667,11 +22667,11 @@ Scope children mismatch: after transform: ScopeId(2): [ScopeId(3), ScopeId(4), ScopeId(5)] rebuilt : ScopeId(1): [ScopeId(2), ScopeId(3)] Bindings mismatch: -after transform: ScopeId(5): ["T", "entry", "name"] -rebuilt : ScopeId(3): ["entry", "name"] +after transform: ScopeId(5): ["T", "_this$entries$name", "entry", "name"] +rebuilt : ScopeId(3): ["_this$entries$name", "entry", "name"] Bindings mismatch: -after transform: ScopeId(13): ["T", "p"] -rebuilt : ScopeId(7): ["p"] +after transform: ScopeId(13): ["T", "_typeHandlers$p$t", "p"] +rebuilt : ScopeId(7): ["_typeHandlers$p$t", "p"] Unresolved references mismatch: after transform: ["console", "true"] rebuilt : ["console"] @@ -25597,8 +25597,8 @@ rebuilt : ["assert", "broken", "isA", "isEmptyArray", "isEmptyStrOrUndefi tasks/coverage/typescript/tests/cases/compiler/narrowingUnionWithBang.ts semantic error: Bindings mismatch: -after transform: ScopeId(0): ["BorkedType", "FixedType", "WorkingType", "borked", "fixed", "working"] -rebuilt : ScopeId(0): ["borked", "fixed", "working"] +after transform: ScopeId(0): ["BorkedType", "FixedType", "WorkingType", "_fixed$thing", "borked", "fixed", "working"] +rebuilt : ScopeId(0): ["_fixed$thing", "borked", "fixed", "working"] Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3), ScopeId(4), ScopeId(5), ScopeId(6), ScopeId(7), ScopeId(8), ScopeId(9)] rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3), ScopeId(4), ScopeId(5), ScopeId(6)] @@ -26612,6 +26612,18 @@ rebuilt : Reference symbol mismatch for "a": after transform: SymbolId(3) "a" rebuilt : +Reference symbol mismatch for "a": +after transform: SymbolId(3) "a" +rebuilt : +Reference symbol mismatch for "a": +after transform: SymbolId(3) "a" +rebuilt : +Reference symbol mismatch for "a": +after transform: SymbolId(3) "a" +rebuilt : +Reference symbol mismatch for "a": +after transform: SymbolId(3) "a" +rebuilt : Unresolved references mismatch: after transform: [] rebuilt : ["a"] @@ -37255,8 +37267,8 @@ rebuilt : ScopeId(1): [] tasks/coverage/typescript/tests/cases/compiler/typeParameterLeak.ts semantic error: Bindings mismatch: -after transform: ScopeId(0): ["Box", "BoxFactory", "BoxFactoryFactory", "BoxTypes", "b", "f"] -rebuilt : ScopeId(0): ["b"] +after transform: ScopeId(0): ["Box", "BoxFactory", "BoxFactoryFactory", "BoxTypes", "_f", "b", "f"] +rebuilt : ScopeId(0): ["_f", "b"] Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3), ScopeId(5), ScopeId(7)] rebuilt : ScopeId(0): [ScopeId(1)] @@ -37431,8 +37443,8 @@ rebuilt : ScopeId(0): [ScopeId(1)] tasks/coverage/typescript/tests/cases/compiler/typePredicatesOptionalChaining1.ts semantic error: Bindings mismatch: -after transform: ScopeId(0): ["X", "isNotNull", "title", "x"] -rebuilt : ScopeId(0): ["isNotNull", "title", "x"] +after transform: ScopeId(0): ["X", "_x$y", "isNotNull", "title", "x"] +rebuilt : ScopeId(0): ["_x$y", "isNotNull", "title", "x"] Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3)] rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)] @@ -40991,24 +41003,72 @@ after transform: ["Object"] rebuilt : [] tasks/coverage/typescript/tests/cases/conformance/classes/members/instanceAndStaticMembers/thisAndSuperInStaticMembers1.ts -semantic error: Scope children mismatch: +semantic error: Bindings mismatch: +after transform: ScopeId(0): ["C"] +rebuilt : ScopeId(0): ["C", "_this", "_this2"] +Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(4)] rebuilt : ScopeId(0): [ScopeId(1)] +Bindings mismatch: +after transform: ScopeId(4): ["_this", "_this2"] +rebuilt : ScopeId(1): [] +Symbol scope ID mismatch for "_this": +after transform: SymbolId(1): ScopeId(4) +rebuilt : SymbolId(0): ScopeId(0) +Symbol scope ID mismatch for "_this2": +after transform: SymbolId(2): ScopeId(4) +rebuilt : SymbolId(1): ScopeId(0) tasks/coverage/typescript/tests/cases/conformance/classes/members/instanceAndStaticMembers/thisAndSuperInStaticMembers2.ts -semantic error: Scope children mismatch: +semantic error: Bindings mismatch: +after transform: ScopeId(0): ["C"] +rebuilt : ScopeId(0): ["C", "_this", "_this2"] +Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(4)] rebuilt : ScopeId(0): [ScopeId(1)] +Bindings mismatch: +after transform: ScopeId(4): ["_this", "_this2"] +rebuilt : ScopeId(1): [] +Symbol scope ID mismatch for "_this": +after transform: SymbolId(1): ScopeId(4) +rebuilt : SymbolId(0): ScopeId(0) +Symbol scope ID mismatch for "_this2": +after transform: SymbolId(2): ScopeId(4) +rebuilt : SymbolId(1): ScopeId(0) tasks/coverage/typescript/tests/cases/conformance/classes/members/instanceAndStaticMembers/thisAndSuperInStaticMembers3.ts -semantic error: Scope children mismatch: +semantic error: Bindings mismatch: +after transform: ScopeId(0): ["C"] +rebuilt : ScopeId(0): ["C", "_this", "_this2"] +Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(4)] rebuilt : ScopeId(0): [ScopeId(1)] +Bindings mismatch: +after transform: ScopeId(4): ["_this", "_this2"] +rebuilt : ScopeId(1): [] +Symbol scope ID mismatch for "_this": +after transform: SymbolId(1): ScopeId(4) +rebuilt : SymbolId(0): ScopeId(0) +Symbol scope ID mismatch for "_this2": +after transform: SymbolId(2): ScopeId(4) +rebuilt : SymbolId(1): ScopeId(0) tasks/coverage/typescript/tests/cases/conformance/classes/members/instanceAndStaticMembers/thisAndSuperInStaticMembers4.ts -semantic error: Scope children mismatch: +semantic error: Bindings mismatch: +after transform: ScopeId(0): ["C"] +rebuilt : ScopeId(0): ["C", "_this", "_this2"] +Scope children mismatch: after transform: ScopeId(0): [ScopeId(1), ScopeId(4)] rebuilt : ScopeId(0): [ScopeId(1)] +Bindings mismatch: +after transform: ScopeId(4): ["_this", "_this2"] +rebuilt : ScopeId(1): [] +Symbol scope ID mismatch for "_this": +after transform: SymbolId(1): ScopeId(4) +rebuilt : SymbolId(0): ScopeId(0) +Symbol scope ID mismatch for "_this2": +after transform: SymbolId(2): ScopeId(4) +rebuilt : SymbolId(1): ScopeId(0) tasks/coverage/typescript/tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInInstanceMember2.ts semantic error: Bindings mismatch: @@ -46127,6 +46187,18 @@ rebuilt : Reference symbol mismatch for "x": after transform: SymbolId(0) "x" rebuilt : +Reference symbol mismatch for "x": +after transform: SymbolId(0) "x" +rebuilt : +Reference symbol mismatch for "x": +after transform: SymbolId(0) "x" +rebuilt : +Reference symbol mismatch for "x": +after transform: SymbolId(0) "x" +rebuilt : +Reference symbol mismatch for "x": +after transform: SymbolId(0) "x" +rebuilt : Reference symbol mismatch for "g": after transform: SymbolId(1) "g" rebuilt : @@ -46157,6 +46229,18 @@ rebuilt : Reference symbol mismatch for "x": after transform: SymbolId(0) "x" rebuilt : +Reference symbol mismatch for "x": +after transform: SymbolId(0) "x" +rebuilt : +Reference symbol mismatch for "x": +after transform: SymbolId(0) "x" +rebuilt : +Reference symbol mismatch for "x": +after transform: SymbolId(0) "x" +rebuilt : +Reference symbol mismatch for "x": +after transform: SymbolId(0) "x" +rebuilt : Unresolved references mismatch: after transform: [] rebuilt : ["g", "h", "x"] @@ -48082,14 +48166,29 @@ rebuilt : ["undefined"] tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/callChain/callChain.2.ts semantic error: Bindings mismatch: -after transform: ScopeId(0): ["o1", "o2", "o3"] -rebuilt : ScopeId(0): [] +after transform: ScopeId(0): ["_o3$b", "o1", "o2", "o3"] +rebuilt : ScopeId(0): ["_o3$b"] +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : Reference symbol mismatch for "o1": after transform: SymbolId(0) "o1" rebuilt : Reference symbol mismatch for "o2": after transform: SymbolId(1) "o2" rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : Reference symbol mismatch for "o3": after transform: SymbolId(2) "o3" rebuilt : @@ -48099,8 +48198,8 @@ rebuilt : ["o1", "o2", "o3"] tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/callChain/callChain.ts semantic error: Bindings mismatch: -after transform: ScopeId(0): ["T", "o1", "o2", "o3", "o4", "o5", "v"] -rebuilt : ScopeId(0): ["v"] +after transform: ScopeId(0): ["T", "_o", "_o3$b", "_o3$b10", "_o3$b11", "_o3$b12", "_o3$b2", "_o3$b3", "_o3$b4", "_o3$b5", "_o3$b6", "_o3$b7", "_o3$b8", "_o3$b9", "o1", "o2", "o3", "o4", "o5", "v"] +rebuilt : ScopeId(0): ["_o", "_o3$b", "_o3$b10", "_o3$b11", "_o3$b12", "_o3$b2", "_o3$b3", "_o3$b4", "_o3$b5", "_o3$b6", "_o3$b7", "_o3$b8", "_o3$b9", "v"] Scope children mismatch: after transform: ScopeId(0): [ScopeId(1)] rebuilt : ScopeId(0): [] @@ -48116,6 +48215,33 @@ rebuilt : Reference symbol mismatch for "o1": after transform: SymbolId(0) "o1" rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : Reference symbol mismatch for "o2": after transform: SymbolId(1) "o2" rebuilt : @@ -48140,6 +48266,87 @@ rebuilt : Reference symbol mismatch for "o2": after transform: SymbolId(1) "o2" rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : Reference symbol mismatch for "o3": after transform: SymbolId(2) "o3" rebuilt : @@ -48179,6 +48386,12 @@ rebuilt : Reference symbol mismatch for "o4": after transform: SymbolId(3) "o4" rebuilt : +Reference symbol mismatch for "o4": +after transform: SymbolId(3) "o4" +rebuilt : +Reference symbol mismatch for "o4": +after transform: SymbolId(3) "o4" +rebuilt : Reference symbol mismatch for "o5": after transform: SymbolId(7) "o5" rebuilt : @@ -48188,6 +48401,18 @@ rebuilt : Reference symbol mismatch for "o2": after transform: SymbolId(1) "o2" rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : Unresolved references mismatch: after transform: ["incr"] rebuilt : ["incr", "o1", "o2", "o3", "o4", "o5"] @@ -48208,14 +48433,26 @@ rebuilt : Reference symbol mismatch for "value": after transform: SymbolId(2) "value" rebuilt : +Reference symbol mismatch for "value": +after transform: SymbolId(2) "value" +rebuilt : +Reference symbol mismatch for "value": +after transform: SymbolId(2) "value" +rebuilt : +Reference symbol mismatch for "value": +after transform: SymbolId(2) "value" +rebuilt : +Reference symbol mismatch for "value": +after transform: SymbolId(2) "value" +rebuilt : Unresolved references mismatch: after transform: [] rebuilt : ["value"] tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/callChain/parentheses.ts semantic error: Bindings mismatch: -after transform: ScopeId(0): ["o1", "o2", "o3", "o4"] -rebuilt : ScopeId(0): [] +after transform: ScopeId(0): ["_o4$b", "o1", "o2", "o3", "o4"] +rebuilt : ScopeId(0): ["_o4$b"] Reference symbol mismatch for "o1": after transform: SymbolId(0) "o1" rebuilt : @@ -48231,6 +48468,15 @@ rebuilt : Reference symbol mismatch for "o2": after transform: SymbolId(1) "o2" rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : Reference symbol mismatch for "o1": after transform: SymbolId(0) "o1" rebuilt : @@ -48243,6 +48489,15 @@ rebuilt : Reference symbol mismatch for "o3": after transform: SymbolId(2) "o3" rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : +Reference symbol mismatch for "o3": +after transform: SymbolId(2) "o3" +rebuilt : Reference symbol mismatch for "o1": after transform: SymbolId(0) "o1" rebuilt : @@ -48255,6 +48510,12 @@ rebuilt : Reference symbol mismatch for "o4": after transform: SymbolId(3) "o4" rebuilt : +Reference symbol mismatch for "o4": +after transform: SymbolId(3) "o4" +rebuilt : +Reference symbol mismatch for "o4": +after transform: SymbolId(3) "o4" +rebuilt : Reference symbol mismatch for "o1": after transform: SymbolId(0) "o1" rebuilt : @@ -48270,8 +48531,14 @@ rebuilt : ["o1", "o2", "o3", "o4"] tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/elementAccessChain/elementAccessChain.2.ts semantic error: Bindings mismatch: -after transform: ScopeId(0): ["o1", "o2", "o3"] -rebuilt : ScopeId(0): [] +after transform: ScopeId(0): ["_o3$b", "_o3$b2", "o1", "o2", "o3"] +rebuilt : ScopeId(0): ["_o3$b", "_o3$b2"] +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : Reference symbol mismatch for "o1": after transform: SymbolId(0) "o1" rebuilt : @@ -48281,6 +48548,18 @@ rebuilt : Reference symbol mismatch for "o2": after transform: SymbolId(1) "o2" rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : Reference symbol mismatch for "o3": after transform: SymbolId(2) "o3" rebuilt : @@ -48293,14 +48572,32 @@ rebuilt : ["o1", "o2", "o3"] tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/elementAccessChain/elementAccessChain.ts semantic error: Bindings mismatch: -after transform: ScopeId(0): ["T", "o1", "o2", "o3", "o4", "o5", "o6"] -rebuilt : ScopeId(0): [] +after transform: ScopeId(0): ["T", "_o", "_o3$b", "_o3$b2", "_o4$b", "_o4$b2", "_o5$b", "_o5$b2", "_o5$b3", "_o5$b4", "o1", "o2", "o3", "o4", "o5", "o6"] +rebuilt : ScopeId(0): ["_o", "_o3$b", "_o3$b2", "_o4$b", "_o4$b2", "_o5$b", "_o5$b2", "_o5$b3", "_o5$b4"] Scope children mismatch: after transform: ScopeId(0): [ScopeId(1)] rebuilt : ScopeId(0): [] Reference symbol mismatch for "o1": after transform: SymbolId(0) "o1" rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : Reference symbol mismatch for "o2": after transform: SymbolId(1) "o2" rebuilt : @@ -48331,6 +48628,18 @@ rebuilt : Reference symbol mismatch for "o5": after transform: SymbolId(4) "o5" rebuilt : +Reference symbol mismatch for "o5": +after transform: SymbolId(4) "o5" +rebuilt : +Reference symbol mismatch for "o5": +after transform: SymbolId(4) "o5" +rebuilt : +Reference symbol mismatch for "o5": +after transform: SymbolId(4) "o5" +rebuilt : +Reference symbol mismatch for "o5": +after transform: SymbolId(4) "o5" +rebuilt : Reference symbol mismatch for "o6": after transform: SymbolId(5) "o6" rebuilt : @@ -48346,10 +48655,73 @@ rebuilt : Reference symbol mismatch for "o2": after transform: SymbolId(1) "o2" rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : Unresolved references mismatch: after transform: [] rebuilt : ["o1", "o2", "o3", "o4", "o5", "o6"] +tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/optionalChainingInLoop.ts +semantic error: Bindings mismatch: +after transform: ScopeId(0): ["list"] +rebuilt : ScopeId(0): ["_item$t", "list"] +Bindings mismatch: +after transform: ScopeId(5): ["_item$t"] +rebuilt : ScopeId(5): [] +Symbol scope ID mismatch for "_item$t": +after transform: SymbolId(4): ScopeId(5) +rebuilt : SymbolId(4): ScopeId(0) + +tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterBindingPattern.ts +semantic error: Scope children mismatch: +after transform: ScopeId(0): [ScopeId(1), ScopeId(2)] +rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)] +Bindings mismatch: +after transform: ScopeId(2): ["_a", "c"] +rebuilt : ScopeId(3): ["_a"] +Scope parent mismatch: +after transform: ScopeId(2): Some(ScopeId(0)) +rebuilt : ScopeId(3): Some(ScopeId(2)) +Symbol scope ID mismatch for "c": +after transform: SymbolId(1): ScopeId(2) +rebuilt : SymbolId(1): ScopeId(2) + +tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/optionalChainingInParameterInitializer.ts +semantic error: Scope children mismatch: +after transform: ScopeId(0): [ScopeId(1), ScopeId(2)] +rebuilt : ScopeId(0): [ScopeId(1), ScopeId(2)] +Bindings mismatch: +after transform: ScopeId(2): ["_a", "b"] +rebuilt : ScopeId(3): ["_a"] +Scope parent mismatch: +after transform: ScopeId(2): Some(ScopeId(0)) +rebuilt : ScopeId(3): Some(ScopeId(2)) +Symbol scope ID mismatch for "b": +after transform: SymbolId(1): ScopeId(2) +rebuilt : SymbolId(1): ScopeId(2) + tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/optionalChainingInference.ts semantic error: Bindings mismatch: after transform: ScopeId(0): ["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "fnu", "ofnu", "osu", "su", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8"] @@ -48366,12 +48738,54 @@ rebuilt : Reference symbol mismatch for "su": after transform: SymbolId(2) "su" rebuilt : +Reference symbol mismatch for "su": +after transform: SymbolId(2) "su" +rebuilt : +Reference symbol mismatch for "su": +after transform: SymbolId(2) "su" +rebuilt : +Reference symbol mismatch for "su": +after transform: SymbolId(2) "su" +rebuilt : +Reference symbol mismatch for "su": +after transform: SymbolId(2) "su" +rebuilt : +Reference symbol mismatch for "su": +after transform: SymbolId(2) "su" +rebuilt : +Reference symbol mismatch for "su": +after transform: SymbolId(2) "su" +rebuilt : +Reference symbol mismatch for "fnu": +after transform: SymbolId(3) "fnu" +rebuilt : +Reference symbol mismatch for "fnu": +after transform: SymbolId(3) "fnu" +rebuilt : Reference symbol mismatch for "fnu": after transform: SymbolId(3) "fnu" rebuilt : Reference symbol mismatch for "su": after transform: SymbolId(2) "su" rebuilt : +Reference symbol mismatch for "su": +after transform: SymbolId(2) "su" +rebuilt : +Reference symbol mismatch for "su": +after transform: SymbolId(2) "su" +rebuilt : +Reference symbol mismatch for "osu": +after transform: SymbolId(4) "osu" +rebuilt : +Reference symbol mismatch for "osu": +after transform: SymbolId(4) "osu" +rebuilt : +Reference symbol mismatch for "osu": +after transform: SymbolId(4) "osu" +rebuilt : +Reference symbol mismatch for "osu": +after transform: SymbolId(4) "osu" +rebuilt : Reference symbol mismatch for "osu": after transform: SymbolId(4) "osu" rebuilt : @@ -48381,20 +48795,38 @@ rebuilt : Reference symbol mismatch for "ofnu": after transform: SymbolId(5) "ofnu" rebuilt : +Reference symbol mismatch for "ofnu": +after transform: SymbolId(5) "ofnu" +rebuilt : +Reference symbol mismatch for "ofnu": +after transform: SymbolId(5) "ofnu" +rebuilt : Unresolved references mismatch: after transform: ["unbox"] rebuilt : ["fnu", "ofnu", "osu", "su", "unbox"] tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/propertyAccessChain/propertyAccessChain.2.ts semantic error: Bindings mismatch: -after transform: ScopeId(0): ["o1", "o2", "o3"] -rebuilt : ScopeId(0): [] +after transform: ScopeId(0): ["_o3$b", "o1", "o2", "o3"] +rebuilt : ScopeId(0): ["_o3$b"] +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : Reference symbol mismatch for "o1": after transform: SymbolId(0) "o1" rebuilt : Reference symbol mismatch for "o2": after transform: SymbolId(1) "o2" rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : Reference symbol mismatch for "o3": after transform: SymbolId(2) "o3" rebuilt : @@ -48404,14 +48836,26 @@ rebuilt : ["o1", "o2", "o3"] tasks/coverage/typescript/tests/cases/conformance/expressions/optionalChaining/propertyAccessChain/propertyAccessChain.ts semantic error: Bindings mismatch: -after transform: ScopeId(0): ["T", "o1", "o2", "o3", "o4", "o5", "o6"] -rebuilt : ScopeId(0): [] +after transform: ScopeId(0): ["T", "_o", "_o3$b", "_o4$b", "_o5$b", "o1", "o2", "o3", "o4", "o5", "o6"] +rebuilt : ScopeId(0): ["_o", "_o3$b", "_o4$b", "_o5$b"] Scope children mismatch: after transform: ScopeId(0): [ScopeId(1)] rebuilt : ScopeId(0): [] Reference symbol mismatch for "o1": after transform: SymbolId(0) "o1" rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : Reference symbol mismatch for "o2": after transform: SymbolId(1) "o2" rebuilt : @@ -48424,12 +48868,33 @@ rebuilt : Reference symbol mismatch for "o5": after transform: SymbolId(4) "o5" rebuilt : +Reference symbol mismatch for "o5": +after transform: SymbolId(4) "o5" +rebuilt : Reference symbol mismatch for "o6": after transform: SymbolId(5) "o6" rebuilt : Reference symbol mismatch for "o1": after transform: SymbolId(0) "o1" rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o1": +after transform: SymbolId(0) "o1" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : +Reference symbol mismatch for "o2": +after transform: SymbolId(1) "o2" +rebuilt : Reference symbol mismatch for "o2": after transform: SymbolId(1) "o2" rebuilt : diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/assignment/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/assignment/output.js new file mode 100644 index 0000000000000..b5c7b0a33f2c2 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/assignment/output.js @@ -0,0 +1,8 @@ +"use strict"; +var _obj$a, _obj$b, _obj$a2; +const obj = { a: { b: { c: { d: 2 } } } }; +const a = obj == null ? void 0 : obj.a; +const b = obj == null || (_obj$a = obj.a) == null ? void 0 : _obj$a.b; +const bad = obj == null || (_obj$b = obj.b) == null ? void 0 : _obj$b.b; +let val; +val = obj == null || (_obj$a2 = obj.a) == null ? void 0 : _obj$a2.b; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/output.js new file mode 100644 index 0000000000000..c58ff0c532b9c --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/cast-to-boolean/output.js @@ -0,0 +1,85 @@ +class C { + static testIf(o) { + if (o === null || o === void 0 ? void 0 : o.a.b.c.d) { + return true; + } + return false; + } + static testConditional(o) { + var _o$a$b; + return (o === null || o === void 0 || (_o$a$b = o.a.b) === null || _o$a$b === void 0 ? void 0 : _o$a$b.c.d) ? true : false; + } + static testLoop(o) { + while (o === null || o === void 0 ? void 0 : o.a.b.c.d) { + var _o$a$b$c; + for (; o === null || o === void 0 || (_o$a$b$c = o.a.b.c) === null || _o$a$b$c === void 0 ? void 0 : _o$a$b$c.d;) { + var _o$a$b2; + let i = 0; + do { + i++; + if (i === 2) { + return true; + } + } while (o === null || o === void 0 || (_o$a$b2 = o.a.b) === null || _o$a$b2 === void 0 ? void 0 : _o$a$b2.c.d); + } + } + return false; + } + static testNegate(o) { + var _o$a$b3; + return !!(o === null || o === void 0 || (_o$a$b3 = o.a.b) === null || _o$a$b3 === void 0 ? void 0 : _o$a$b3.c.d); + } + static testIfDeep(o) { + var _o$obj; + if ((_o$obj = o.obj) === null || _o$obj === void 0 || (_o$obj = _o$obj.a.b) === null || _o$obj === void 0 ? void 0 : _o$obj.c.d) { + return true; + } + return false; + } + static testConditionalDeep(o) { + var _o$obj2; + return ((_o$obj2 = o.obj) === null || _o$obj2 === void 0 || (_o$obj2 = _o$obj2.a.b) === null || _o$obj2 === void 0 ? void 0 : _o$obj2.c.d) ? true : false; + } + static testLoopDeep(o) { + var _o$obj3; + while ((_o$obj3 = o.obj) === null || _o$obj3 === void 0 ? void 0 : _o$obj3.a.b.c.d) { + var _o$obj4; + for (; (_o$obj4 = o.obj) === null || _o$obj4 === void 0 || (_o$obj4 = _o$obj4.a.b.c) === null || _o$obj4 === void 0 ? void 0 : _o$obj4.d;) { + var _o$obj5; + let i = 0; + do { + i++; + if (i === 2) { + return true; + } + } while ((_o$obj5 = o.obj) === null || _o$obj5 === void 0 || (_o$obj5 = _o$obj5.a.b) === null || _o$obj5 === void 0 ? void 0 : _o$obj5.c.d); + } + } + return false; + } + static testNegateDeep(o) { + var _o$obj6; + return !!((_o$obj6 = o.obj) === null || _o$obj6 === void 0 || (_o$obj6 = _o$obj6.a.b) === null || _o$obj6 === void 0 ? void 0 : _o$obj6.c.d); + } + static testLogicalInIf(o) { + var _o$a$b4, _o$a; + if ((o === null || o === void 0 || (_o$a$b4 = o.a.b) === null || _o$a$b4 === void 0 ? void 0 : _o$a$b4.c.d) && (o === null || o === void 0 || (_o$a = o.a) === null || _o$a === void 0 ? void 0 : _o$a.b.c.d)) { + return true; + } + return false; + } + static testLogicalInReturn(o) { + var _o$a$b5, _o$a2; + return (o === null || o === void 0 || (_o$a$b5 = o.a.b) === null || _o$a$b5 === void 0 ? void 0 : _o$a$b5.c.d) && (o === null || o === void 0 || (_o$a2 = o.a) === null || _o$a2 === void 0 ? void 0 : _o$a2.b.c.d); + } + static testNullishCoalescing(o) { + var _o$a$b$c$non_existent, _o$a$b6, _o$a$b7, _o$a$b$c$non_existent3, _o$a$b10; + if ((_o$a$b$c$non_existent = o === null || o === void 0 || (_o$a$b6 = o.a.b) === null || _o$a$b6 === void 0 ? void 0 : _o$a$b6.c.non_existent) !== null && _o$a$b$c$non_existent !== void 0 ? _o$a$b$c$non_existent : o === null || o === void 0 || (_o$a$b7 = o.a.b) === null || _o$a$b7 === void 0 ? void 0 : _o$a$b7.c.d) { + var _o$a$b$c$non_existent2, _o$a$b8, _o$a$b9; + return (_o$a$b$c$non_existent2 = o === null || o === void 0 || (_o$a$b8 = o.a.b) === null || _o$a$b8 === void 0 ? void 0 : _o$a$b8.c.non_existent) !== null && _o$a$b$c$non_existent2 !== void 0 ? _o$a$b$c$non_existent2 : o === null || o === void 0 || (_o$a$b9 = o.a.b) === null || _o$a$b9 === void 0 ? void 0 : _o$a$b9.c.d; + } + return (_o$a$b$c$non_existent3 = o === null || o === void 0 || (_o$a$b10 = o.a.b) === null || _o$a$b10 === void 0 ? void 0 : _o$a$b10.c.non_existent) !== null && _o$a$b$c$non_existent3 !== void 0 ? _o$a$b$c$non_existent3 : o; + } +} +C.test(); +C.testNullish(); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/in-function-params/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/in-function-params/output.js new file mode 100644 index 0000000000000..b86b7a4d7883b --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/in-function-params/output.js @@ -0,0 +1,19 @@ +function f(a = (() => { + var _x; + return (_x = x) == null ? void 0 : _x.y; +})()) {} +function g({ a, b = (() => { + return a == null ? void 0 : a.c; +})() }) {} +function h(a, { b = (() => { + var _a$b; + return (_a$b = a.b) == null || (_a$b = _a$b.c) == null ? void 0 : _a$b.d.e; +})() }) {} +function i(a, { b = (() => { + var _a$b2; + return (_a$b2 = a.b) == null || (_a$b2 = _a$b2.c) == null ? void 0 : _a$b2.d; +})().e }) {} +function j(a, { b = (() => { + var _a$b3; + return a == null || (_a$b3 = a.b) == null ? void 0 : _a$b3.c().d.e; +})() }) {} diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/output.js new file mode 100644 index 0000000000000..eef863fbabda7 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/output.js @@ -0,0 +1,18 @@ +function test(foo) { + var _foo$bar, _foo$get, _foo$bar2, _foo$bar3, _foo$bar$baz, _foo$bar$baz2, _foo$bar4, _foo$bar5, _foo$bar6, _foo$bar7, _foo$bar8, _foo$bar8$baz, _foo$bar9, _foo$bar9$baz; + foo == null ? void 0 : foo.bar; + foo == null || (_foo$bar = foo.bar) == null ? void 0 : _foo$bar.baz; + foo == null ? void 0 : foo(foo); + foo == null ? void 0 : foo.bar(); + (_foo$get = foo.get(bar)) == null ? void 0 : _foo$get(); + (_foo$bar2 = foo.bar()) == null ? void 0 : _foo$bar2(); + (_foo$bar3 = foo[bar]()) == null ? void 0 : _foo$bar3(); + (_foo$bar$baz = foo.bar().baz) == null ? void 0 : _foo$bar$baz(); + (_foo$bar$baz2 = foo[bar]().baz) == null ? void 0 : _foo$bar$baz2(); + (_foo$bar4 = foo.bar) == null ? void 0 : _foo$bar4.call(foo, foo.bar, false); + foo == null || (_foo$bar5 = foo.bar) == null ? void 0 : _foo$bar5.call(foo, foo.bar, true); + (_foo$bar6 = foo.bar) == null ? void 0 : _foo$bar6.baz(foo.bar, false); + foo == null || (_foo$bar7 = foo.bar) == null ? void 0 : _foo$bar7.baz(foo.bar, true); + (_foo$bar8 = foo.bar) == null || (_foo$bar8$baz = _foo$bar8.baz) == null ? void 0 : _foo$bar8$baz.call(_foo$bar8, foo.bar, false); + foo == null || (_foo$bar9 = foo.bar) == null || (_foo$bar9$baz = _foo$bar9.baz) == null ? void 0 : _foo$bar9$baz.call(_foo$bar9, foo.bar, true); +} diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/optional-eval-call/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/optional-eval-call/output.js new file mode 100644 index 0000000000000..2a465f6e591c9 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/optional-eval-call/output.js @@ -0,0 +1,10 @@ +var _eval, _eval2, _foo$eval, _eval$foo; +var foo; +eval == null ? void 0 : (0, eval)(foo); +eval == null ? void 0 : (0, eval)(foo); +eval == null ? void 0 : (0, eval)()(); +eval == null ? void 0 : (0, eval)().foo; +(_eval = eval()) == null ? void 0 : _eval(); +(_eval2 = eval()) == null ? void 0 : _eval2.foo; +(_foo$eval = foo.eval) == null ? void 0 : _foo$eval.call(foo, foo); +(_eval$foo = eval.foo) == null ? void 0 : _eval$foo.call(eval, foo); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/super-method-call/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/super-method-call/output.js new file mode 100644 index 0000000000000..627ba1efadab1 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/super-method-call/output.js @@ -0,0 +1,12 @@ +"use strict"; +class Base { + method() { + return "Hello!"; + } +} +class Derived extends Base { + method() { + var _super$method; + return (_super$method = super.method) == null ? void 0 : _super$method.call(this); + } +} diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-pureGetters/function-call/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-pureGetters/function-call/output.js new file mode 100644 index 0000000000000..a21f32b45d016 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-pureGetters/function-call/output.js @@ -0,0 +1,11 @@ +var _foo$bar, _foo$bar2, _foo, _foo$bar3, _foo$bar4, _foo$bar5, _foo$bar6; +foo === null || foo === void 0 ? void 0 : foo(foo); +foo === null || foo === void 0 ? void 0 : foo.bar(); +(_foo$bar = foo.bar) === null || _foo$bar === void 0 ? void 0 : _foo$bar(foo.bar, false); +foo === null || foo === void 0 || (_foo$bar2 = foo.bar) === null || _foo$bar2 === void 0 ? void 0 : _foo$bar2(foo.bar, true); +foo === null || foo === void 0 ? void 0 : foo().bar; +foo === null || foo === void 0 || (_foo = foo()) === null || _foo === void 0 ? void 0 : _foo.bar; +(_foo$bar3 = foo.bar) === null || _foo$bar3 === void 0 ? void 0 : _foo$bar3().baz; +(_foo$bar4 = foo.bar) === null || _foo$bar4 === void 0 || (_foo$bar4 = _foo$bar4()) === null || _foo$bar4 === void 0 ? void 0 : _foo$bar4.baz; +foo === null || foo === void 0 || (_foo$bar5 = foo.bar) === null || _foo$bar5 === void 0 ? void 0 : _foo$bar5().baz; +foo === null || foo === void 0 || (_foo$bar6 = foo.bar) === null || _foo$bar6 === void 0 || (_foo$bar6 = _foo$bar6()) === null || _foo$bar6 === void 0 ? void 0 : _foo$bar6.baz; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-pureGetters/memoize/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-pureGetters/memoize/output.js new file mode 100644 index 0000000000000..0e9ebf2941eff --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-pureGetters/memoize/output.js @@ -0,0 +1,18 @@ +function test(foo) { + var _foo$bar, _foo$get, _foo$bar2, _foo$bar3, _foo$bar$baz, _foo$bar$baz2, _foo$bar4, _foo$bar5, _foo$bar6, _foo$bar7, _foo$bar8, _foo$bar8$baz, _foo$bar9, _foo$bar9$baz; + foo === null || foo === void 0 ? void 0 : foo.bar; + foo === null || foo === void 0 || (_foo$bar = foo.bar) === null || _foo$bar === void 0 ? void 0 : _foo$bar.baz; + foo === null || foo === void 0 ? void 0 : foo(foo); + foo === null || foo === void 0 ? void 0 : foo.bar(); + (_foo$get = foo.get(bar)) === null || _foo$get === void 0 ? void 0 : _foo$get(); + (_foo$bar2 = foo.bar()) === null || _foo$bar2 === void 0 ? void 0 : _foo$bar2(); + (_foo$bar3 = foo[bar]()) === null || _foo$bar3 === void 0 ? void 0 : _foo$bar3(); + (_foo$bar$baz = foo.bar().baz) === null || _foo$bar$baz === void 0 ? void 0 : _foo$bar$baz(); + (_foo$bar$baz2 = foo[bar]().baz) === null || _foo$bar$baz2 === void 0 ? void 0 : _foo$bar$baz2(); + (_foo$bar4 = foo.bar) === null || _foo$bar4 === void 0 ? void 0 : _foo$bar4(foo.bar, false); + foo === null || foo === void 0 || (_foo$bar5 = foo.bar) === null || _foo$bar5 === void 0 ? void 0 : _foo$bar5(foo.bar, true); + (_foo$bar6 = foo.bar) === null || _foo$bar6 === void 0 ? void 0 : _foo$bar6.baz(foo.bar, false); + foo === null || foo === void 0 || (_foo$bar7 = foo.bar) === null || _foo$bar7 === void 0 ? void 0 : _foo$bar7.baz(foo.bar, true); + (_foo$bar8 = foo.bar) === null || _foo$bar8 === void 0 || (_foo$bar8$baz = _foo$bar8.baz) === null || _foo$bar8$baz === void 0 ? void 0 : _foo$bar8$baz(foo.bar, false); + foo === null || foo === void 0 || (_foo$bar9 = foo.bar) === null || _foo$bar9 === void 0 || (_foo$bar9$baz = _foo$bar9.baz) === null || _foo$bar9$baz === void 0 ? void 0 : _foo$bar9$baz(foo.bar, true); +} diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-pureGetters/super-method-call/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-pureGetters/super-method-call/output.js new file mode 100644 index 0000000000000..06fc5eb00fd8d --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/assumption-pureGetters/super-method-call/output.js @@ -0,0 +1,12 @@ +"use strict"; +class Base { + method() { + return "Hello!"; + } +} +class Derived extends Base { + method() { + var _super$method; + return (_super$method = super.method) === null || _super$method === void 0 ? void 0 : _super$method(); + } +} diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/assignment/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/assignment/output.js new file mode 100644 index 0000000000000..5b53552b3dcdb --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/assignment/output.js @@ -0,0 +1,8 @@ +"use strict"; +var _obj$a, _obj$b, _obj$a2; +const obj = { a: { b: { c: { d: 2 } } } }; +const a = obj === null || obj === void 0 ? void 0 : obj.a; +const b = obj === null || obj === void 0 || (_obj$a = obj.a) === null || _obj$a === void 0 ? void 0 : _obj$a.b; +const bad = obj === null || obj === void 0 || (_obj$b = obj.b) === null || _obj$b === void 0 ? void 0 : _obj$b.b; +let val; +val = obj === null || obj === void 0 || (_obj$a2 = obj.a) === null || _obj$a2 === void 0 ? void 0 : _obj$a2.b; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/cast-to-boolean/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/cast-to-boolean/output.js new file mode 100644 index 0000000000000..c58ff0c532b9c --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/cast-to-boolean/output.js @@ -0,0 +1,85 @@ +class C { + static testIf(o) { + if (o === null || o === void 0 ? void 0 : o.a.b.c.d) { + return true; + } + return false; + } + static testConditional(o) { + var _o$a$b; + return (o === null || o === void 0 || (_o$a$b = o.a.b) === null || _o$a$b === void 0 ? void 0 : _o$a$b.c.d) ? true : false; + } + static testLoop(o) { + while (o === null || o === void 0 ? void 0 : o.a.b.c.d) { + var _o$a$b$c; + for (; o === null || o === void 0 || (_o$a$b$c = o.a.b.c) === null || _o$a$b$c === void 0 ? void 0 : _o$a$b$c.d;) { + var _o$a$b2; + let i = 0; + do { + i++; + if (i === 2) { + return true; + } + } while (o === null || o === void 0 || (_o$a$b2 = o.a.b) === null || _o$a$b2 === void 0 ? void 0 : _o$a$b2.c.d); + } + } + return false; + } + static testNegate(o) { + var _o$a$b3; + return !!(o === null || o === void 0 || (_o$a$b3 = o.a.b) === null || _o$a$b3 === void 0 ? void 0 : _o$a$b3.c.d); + } + static testIfDeep(o) { + var _o$obj; + if ((_o$obj = o.obj) === null || _o$obj === void 0 || (_o$obj = _o$obj.a.b) === null || _o$obj === void 0 ? void 0 : _o$obj.c.d) { + return true; + } + return false; + } + static testConditionalDeep(o) { + var _o$obj2; + return ((_o$obj2 = o.obj) === null || _o$obj2 === void 0 || (_o$obj2 = _o$obj2.a.b) === null || _o$obj2 === void 0 ? void 0 : _o$obj2.c.d) ? true : false; + } + static testLoopDeep(o) { + var _o$obj3; + while ((_o$obj3 = o.obj) === null || _o$obj3 === void 0 ? void 0 : _o$obj3.a.b.c.d) { + var _o$obj4; + for (; (_o$obj4 = o.obj) === null || _o$obj4 === void 0 || (_o$obj4 = _o$obj4.a.b.c) === null || _o$obj4 === void 0 ? void 0 : _o$obj4.d;) { + var _o$obj5; + let i = 0; + do { + i++; + if (i === 2) { + return true; + } + } while ((_o$obj5 = o.obj) === null || _o$obj5 === void 0 || (_o$obj5 = _o$obj5.a.b) === null || _o$obj5 === void 0 ? void 0 : _o$obj5.c.d); + } + } + return false; + } + static testNegateDeep(o) { + var _o$obj6; + return !!((_o$obj6 = o.obj) === null || _o$obj6 === void 0 || (_o$obj6 = _o$obj6.a.b) === null || _o$obj6 === void 0 ? void 0 : _o$obj6.c.d); + } + static testLogicalInIf(o) { + var _o$a$b4, _o$a; + if ((o === null || o === void 0 || (_o$a$b4 = o.a.b) === null || _o$a$b4 === void 0 ? void 0 : _o$a$b4.c.d) && (o === null || o === void 0 || (_o$a = o.a) === null || _o$a === void 0 ? void 0 : _o$a.b.c.d)) { + return true; + } + return false; + } + static testLogicalInReturn(o) { + var _o$a$b5, _o$a2; + return (o === null || o === void 0 || (_o$a$b5 = o.a.b) === null || _o$a$b5 === void 0 ? void 0 : _o$a$b5.c.d) && (o === null || o === void 0 || (_o$a2 = o.a) === null || _o$a2 === void 0 ? void 0 : _o$a2.b.c.d); + } + static testNullishCoalescing(o) { + var _o$a$b$c$non_existent, _o$a$b6, _o$a$b7, _o$a$b$c$non_existent3, _o$a$b10; + if ((_o$a$b$c$non_existent = o === null || o === void 0 || (_o$a$b6 = o.a.b) === null || _o$a$b6 === void 0 ? void 0 : _o$a$b6.c.non_existent) !== null && _o$a$b$c$non_existent !== void 0 ? _o$a$b$c$non_existent : o === null || o === void 0 || (_o$a$b7 = o.a.b) === null || _o$a$b7 === void 0 ? void 0 : _o$a$b7.c.d) { + var _o$a$b$c$non_existent2, _o$a$b8, _o$a$b9; + return (_o$a$b$c$non_existent2 = o === null || o === void 0 || (_o$a$b8 = o.a.b) === null || _o$a$b8 === void 0 ? void 0 : _o$a$b8.c.non_existent) !== null && _o$a$b$c$non_existent2 !== void 0 ? _o$a$b$c$non_existent2 : o === null || o === void 0 || (_o$a$b9 = o.a.b) === null || _o$a$b9 === void 0 ? void 0 : _o$a$b9.c.d; + } + return (_o$a$b$c$non_existent3 = o === null || o === void 0 || (_o$a$b10 = o.a.b) === null || _o$a$b10 === void 0 ? void 0 : _o$a$b10.c.non_existent) !== null && _o$a$b$c$non_existent3 !== void 0 ? _o$a$b$c$non_existent3 : o; + } +} +C.test(); +C.testNullish(); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/containers/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/containers/output.js new file mode 100644 index 0000000000000..f71f8a6595dd1 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/containers/output.js @@ -0,0 +1,6 @@ +var _user$address, _user$address2, _a, _a2, _a3; +var street = (_user$address = user.address) === null || _user$address === void 0 ? void 0 : _user$address.street; +street = (_user$address2 = user.address) === null || _user$address2 === void 0 ? void 0 : _user$address2.street; +test((_a = a) === null || _a === void 0 ? void 0 : _a.b, 1); +test((_a2 = a) === null || _a2 === void 0 ? void 0 : _a2.b, 1); +1, (_a3 = a) === null || _a3 === void 0 ? void 0 : _a3.b, 2; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/delete-in-function-params/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/delete-in-function-params/output.js new file mode 100644 index 0000000000000..df6a588a6a7e0 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/delete-in-function-params/output.js @@ -0,0 +1,4 @@ +function f(x = (() => { + var _a; + return (_a = a()) === null || _a === void 0 ? true : delete _a.b; +})()) {} diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/delete/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/delete/output.js new file mode 100644 index 0000000000000..b7a8846c50dae --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/delete/output.js @@ -0,0 +1,7 @@ +"use strict"; +var _obj$a, _obj$b; +const obj = { a: { b: 0 } }; +let test = obj === null || obj === void 0 || (_obj$a = obj.a) === null || _obj$a === void 0 ? true : delete _obj$a.b; +test = obj === null || obj === void 0 ? true : delete obj.a.b; +test = obj === null || obj === void 0 || (_obj$b = obj.b) === null || _obj$b === void 0 ? true : delete _obj$b.b; +obj === null || obj === void 0 ? true : delete obj.a; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/function-call-loose/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/function-call-loose/output.js new file mode 100644 index 0000000000000..5866572b90a14 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/function-call-loose/output.js @@ -0,0 +1,5 @@ +var _foo, _foo2, _foo$bar, _foo3, _foo4, _foo4$bar; +(_foo = foo) === null || _foo === void 0 ? void 0 : _foo(foo); +(_foo2 = foo) === null || _foo2 === void 0 ? void 0 : _foo2.bar(); +(_foo$bar = (_foo3 = foo).bar) === null || _foo$bar === void 0 ? void 0 : _foo$bar.call(_foo3, foo.bar, false); +(_foo4 = foo) === null || _foo4 === void 0 || (_foo4$bar = _foo4.bar) === null || _foo4$bar === void 0 ? void 0 : _foo4$bar.call(_foo4, foo.bar, true); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/function-call-spread/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/function-call-spread/output.js new file mode 100644 index 0000000000000..21133c375ee45 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/function-call-spread/output.js @@ -0,0 +1,5 @@ +var _a, _a2, _a3, _a4; +(_a = a) === null || _a === void 0 ? void 0 : _a(...args); +(_a2 = a) === null || _a2 === void 0 ? void 0 : _a2.b(...args); +(_a3 = a) === null || _a3 === void 0 ? void 0 : _a3.b(...args).c; +(_a4 = a) === null || _a4 === void 0 ? void 0 : _a4.b(...args).c(...args); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/function-call/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/function-call/output.js new file mode 100644 index 0000000000000..42050bf5a2233 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/function-call/output.js @@ -0,0 +1,11 @@ +var _foo, _foo2, _foo$bar, _foo3, _foo4, _foo4$bar, _foo5, _foo6, _foo$bar2, _foo7, _foo$bar3, _foo8, _foo9, _foo9$bar, _foo10, _foo10$bar; +(_foo = foo) === null || _foo === void 0 ? void 0 : _foo(foo); +(_foo2 = foo) === null || _foo2 === void 0 ? void 0 : _foo2.bar(); +(_foo$bar = (_foo3 = foo).bar) === null || _foo$bar === void 0 ? void 0 : _foo$bar.call(_foo3, foo.bar, false); +(_foo4 = foo) === null || _foo4 === void 0 || (_foo4$bar = _foo4.bar) === null || _foo4$bar === void 0 ? void 0 : _foo4$bar.call(_foo4, foo.bar, true); +(_foo5 = foo) === null || _foo5 === void 0 ? void 0 : _foo5().bar; +(_foo6 = foo) === null || _foo6 === void 0 || (_foo6 = _foo6()) === null || _foo6 === void 0 ? void 0 : _foo6.bar; +(_foo$bar2 = (_foo7 = foo).bar) === null || _foo$bar2 === void 0 ? void 0 : _foo$bar2.call(_foo7).baz; +(_foo$bar3 = (_foo8 = foo).bar) === null || _foo$bar3 === void 0 || (_foo$bar3 = _foo$bar3.call(_foo8)) === null || _foo$bar3 === void 0 ? void 0 : _foo$bar3.baz; +(_foo9 = foo) === null || _foo9 === void 0 || (_foo9$bar = _foo9.bar) === null || _foo9$bar === void 0 ? void 0 : _foo9$bar.call(_foo9).baz; +(_foo10 = foo) === null || _foo10 === void 0 || (_foo10$bar = _foo10.bar) === null || _foo10$bar === void 0 || (_foo10$bar = _foo10$bar.call(_foo10)) === null || _foo10$bar === void 0 ? void 0 : _foo10$bar.baz; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-function-params-loose/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-function-params-loose/output.js new file mode 100644 index 0000000000000..0679618bed97d --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-function-params-loose/output.js @@ -0,0 +1,19 @@ +function f(a = (() => { + var _x; + return (_x = x) === null || _x === void 0 ? void 0 : _x.y; +})()) {} +function g({ a, b = (() => { + return a === null || a === void 0 ? void 0 : a.c; +})() }) {} +function h(a, { b = (() => { + var _a$b; + return (_a$b = a.b) === null || _a$b === void 0 || (_a$b = _a$b.c) === null || _a$b === void 0 ? void 0 : _a$b.d.e; +})() }) {} +function i(a, { b = (() => { + var _a$b2; + return (_a$b2 = a.b) === null || _a$b2 === void 0 || (_a$b2 = _a$b2.c) === null || _a$b2 === void 0 ? void 0 : _a$b2.d; +})().e }) {} +function j(a, { b = (() => { + var _a$b3; + return a === null || a === void 0 || (_a$b3 = a.b) === null || _a$b3 === void 0 ? void 0 : _a$b3.c().d.e; +})() }) {} diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-function-params/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-function-params/output.js new file mode 100644 index 0000000000000..0679618bed97d --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-function-params/output.js @@ -0,0 +1,19 @@ +function f(a = (() => { + var _x; + return (_x = x) === null || _x === void 0 ? void 0 : _x.y; +})()) {} +function g({ a, b = (() => { + return a === null || a === void 0 ? void 0 : a.c; +})() }) {} +function h(a, { b = (() => { + var _a$b; + return (_a$b = a.b) === null || _a$b === void 0 || (_a$b = _a$b.c) === null || _a$b === void 0 ? void 0 : _a$b.d.e; +})() }) {} +function i(a, { b = (() => { + var _a$b2; + return (_a$b2 = a.b) === null || _a$b2 === void 0 || (_a$b2 = _a$b2.c) === null || _a$b2 === void 0 ? void 0 : _a$b2.d; +})().e }) {} +function j(a, { b = (() => { + var _a$b3; + return a === null || a === void 0 || (_a$b3 = a.b) === null || _a$b3 === void 0 ? void 0 : _a$b3.c().d.e; +})() }) {} diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-method-key-loose/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-method-key-loose/output.js new file mode 100644 index 0000000000000..2eb95b8bcb6a6 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-method-key-loose/output.js @@ -0,0 +1,3 @@ +var _x$y; +let x; +const a = { [(_x$y = x.y) === null || _x$y === void 0 ? void 0 : _x$y.z]() {} }; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-method-key/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-method-key/output.js new file mode 100644 index 0000000000000..2eb95b8bcb6a6 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-method-key/output.js @@ -0,0 +1,3 @@ +var _x$y; +let x; +const a = { [(_x$y = x.y) === null || _x$y === void 0 ? void 0 : _x$y.z]() {} }; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-var-destructuring/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-var-destructuring/output.js new file mode 100644 index 0000000000000..e1156527c3672 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/in-var-destructuring/output.js @@ -0,0 +1,2 @@ +var _x; +var { a = (_x = x) === null || _x === void 0 ? void 0 : _x.y } = {}; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/member-access/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/member-access/output.js new file mode 100644 index 0000000000000..97c3c76e7571b --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/member-access/output.js @@ -0,0 +1,11 @@ +var _foo, _a, _a$b, _a$b$c, _orders, _orders2, _client, _orders$client$key, _a2, _c, _a3; +(_foo = foo) === null || _foo === void 0 ? void 0 : _foo.bar; +(_a = a) === null || _a === void 0 || (_a = _a.b.c) === null || _a === void 0 ? void 0 : _a.d.e; +(_a$b = a.b) === null || _a$b === void 0 || (_a$b = _a$b.c.d) === null || _a$b === void 0 ? void 0 : _a$b.e; +(_a$b$c = a.b.c) === null || _a$b$c === void 0 || (_a$b$c = _a$b$c.d) === null || _a$b$c === void 0 ? void 0 : _a$b$c.e; +(_orders = orders) === null || _orders === void 0 ? void 0 : _orders[0].price; +(_orders2 = orders) === null || _orders2 === void 0 || (_orders2 = _orders2[0]) === null || _orders2 === void 0 ? void 0 : _orders2.price; +orders[(_client = client) === null || _client === void 0 ? void 0 : _client.key].price; +(_orders$client$key = orders[client.key]) === null || _orders$client$key === void 0 ? void 0 : _orders$client$key.price; +(0, (_a2 = a) === null || _a2 === void 0 ? void 0 : _a2.b).c; +(0, (_c = (0, (_a3 = a) === null || _a3 === void 0 ? void 0 : _a3.b).c) === null || _c === void 0 ? void 0 : _c.d).e; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/memoize-loose/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/memoize-loose/output.js new file mode 100644 index 0000000000000..265f382386d90 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/memoize-loose/output.js @@ -0,0 +1,18 @@ +function test(foo) { + var _foo$bar, _foo$get, _foo$bar2, _foo$bar3, _foo$bar$baz, _foo$bar$baz2, _foo$bar4, _foo$bar5, _foo$bar6, _foo$bar7, _foo$bar8, _foo$bar8$baz, _foo$bar9, _foo$bar9$baz; + foo === null || foo === void 0 ? void 0 : foo.bar; + foo === null || foo === void 0 || (_foo$bar = foo.bar) === null || _foo$bar === void 0 ? void 0 : _foo$bar.baz; + foo === null || foo === void 0 ? void 0 : foo(foo); + foo === null || foo === void 0 ? void 0 : foo.bar(); + (_foo$get = foo.get(bar)) === null || _foo$get === void 0 ? void 0 : _foo$get(); + (_foo$bar2 = foo.bar()) === null || _foo$bar2 === void 0 ? void 0 : _foo$bar2(); + (_foo$bar3 = foo[bar]()) === null || _foo$bar3 === void 0 ? void 0 : _foo$bar3(); + (_foo$bar$baz = foo.bar().baz) === null || _foo$bar$baz === void 0 ? void 0 : _foo$bar$baz(); + (_foo$bar$baz2 = foo[bar]().baz) === null || _foo$bar$baz2 === void 0 ? void 0 : _foo$bar$baz2(); + (_foo$bar4 = foo.bar) === null || _foo$bar4 === void 0 ? void 0 : _foo$bar4.call(foo, foo.bar, false); + foo === null || foo === void 0 || (_foo$bar5 = foo.bar) === null || _foo$bar5 === void 0 ? void 0 : _foo$bar5.call(foo, foo.bar, true); + (_foo$bar6 = foo.bar) === null || _foo$bar6 === void 0 ? void 0 : _foo$bar6.baz(foo.bar, false); + foo === null || foo === void 0 || (_foo$bar7 = foo.bar) === null || _foo$bar7 === void 0 ? void 0 : _foo$bar7.baz(foo.bar, true); + (_foo$bar8 = foo.bar) === null || _foo$bar8 === void 0 || (_foo$bar8$baz = _foo$bar8.baz) === null || _foo$bar8$baz === void 0 ? void 0 : _foo$bar8$baz.call(_foo$bar8, foo.bar, false); + foo === null || foo === void 0 || (_foo$bar9 = foo.bar) === null || _foo$bar9 === void 0 || (_foo$bar9$baz = _foo$bar9.baz) === null || _foo$bar9$baz === void 0 ? void 0 : _foo$bar9$baz.call(_foo$bar9, foo.bar, true); +} diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/memoize/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/memoize/output.js new file mode 100644 index 0000000000000..7a6c9597b828d --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/memoize/output.js @@ -0,0 +1,13 @@ +function test(foo) { + var _foo$bar, _foo$bar2, _foo$bar3, _foo$bar4, _foo$bar5, _foo$bar6, _foo$bar6$baz, _foo$bar7, _foo$bar7$baz; + foo === null || foo === void 0 ? void 0 : foo.bar; + foo === null || foo === void 0 || (_foo$bar = foo.bar) === null || _foo$bar === void 0 ? void 0 : _foo$bar.baz; + foo === null || foo === void 0 ? void 0 : foo(foo); + foo === null || foo === void 0 ? void 0 : foo.bar(); + (_foo$bar2 = foo.bar) === null || _foo$bar2 === void 0 ? void 0 : _foo$bar2.call(foo, foo.bar, false); + foo === null || foo === void 0 || (_foo$bar3 = foo.bar) === null || _foo$bar3 === void 0 ? void 0 : _foo$bar3.call(foo, foo.bar, true); + (_foo$bar4 = foo.bar) === null || _foo$bar4 === void 0 ? void 0 : _foo$bar4.baz(foo.bar, false); + foo === null || foo === void 0 || (_foo$bar5 = foo.bar) === null || _foo$bar5 === void 0 ? void 0 : _foo$bar5.baz(foo.bar, true); + (_foo$bar6 = foo.bar) === null || _foo$bar6 === void 0 || (_foo$bar6$baz = _foo$bar6.baz) === null || _foo$bar6$baz === void 0 ? void 0 : _foo$bar6$baz.call(_foo$bar6, foo.bar, false); + foo === null || foo === void 0 || (_foo$bar7 = foo.bar) === null || _foo$bar7 === void 0 || (_foo$bar7$baz = _foo$bar7.baz) === null || _foo$bar7$baz === void 0 ? void 0 : _foo$bar7$baz.call(_foo$bar7, foo.bar, true); +} diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/optional-eval-call-loose/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/optional-eval-call-loose/output.js new file mode 100644 index 0000000000000..c819a224d83b8 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/optional-eval-call-loose/output.js @@ -0,0 +1,10 @@ +var _eval, _eval2, _foo$eval, _eval$foo; +var foo; +eval === null || eval === void 0 ? void 0 : (0, eval)(foo); +eval === null || eval === void 0 ? void 0 : (0, eval)(foo); +eval === null || eval === void 0 ? void 0 : (0, eval)()(); +eval === null || eval === void 0 ? void 0 : (0, eval)().foo; +(_eval = eval()) === null || _eval === void 0 ? void 0 : _eval(); +(_eval2 = eval()) === null || _eval2 === void 0 ? void 0 : _eval2.foo; +(_foo$eval = foo.eval) === null || _foo$eval === void 0 ? void 0 : _foo$eval.call(foo, foo); +(_eval$foo = eval.foo) === null || _eval$foo === void 0 ? void 0 : _eval$foo.call(eval, foo); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/optional-eval-call/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/optional-eval-call/output.js new file mode 100644 index 0000000000000..c819a224d83b8 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/optional-eval-call/output.js @@ -0,0 +1,10 @@ +var _eval, _eval2, _foo$eval, _eval$foo; +var foo; +eval === null || eval === void 0 ? void 0 : (0, eval)(foo); +eval === null || eval === void 0 ? void 0 : (0, eval)(foo); +eval === null || eval === void 0 ? void 0 : (0, eval)()(); +eval === null || eval === void 0 ? void 0 : (0, eval)().foo; +(_eval = eval()) === null || _eval === void 0 ? void 0 : _eval(); +(_eval2 = eval()) === null || _eval2 === void 0 ? void 0 : _eval2.foo; +(_foo$eval = foo.eval) === null || _foo$eval === void 0 ? void 0 : _foo$eval.call(foo, foo); +(_eval$foo = eval.foo) === null || _eval$foo === void 0 ? void 0 : _eval$foo.call(eval, foo); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/parenthesized-expression-containers/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/parenthesized-expression-containers/output.js new file mode 100644 index 0000000000000..f71f8a6595dd1 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/parenthesized-expression-containers/output.js @@ -0,0 +1,6 @@ +var _user$address, _user$address2, _a, _a2, _a3; +var street = (_user$address = user.address) === null || _user$address === void 0 ? void 0 : _user$address.street; +street = (_user$address2 = user.address) === null || _user$address2 === void 0 ? void 0 : _user$address2.street; +test((_a = a) === null || _a === void 0 ? void 0 : _a.b, 1); +test((_a2 = a) === null || _a2 === void 0 ? void 0 : _a2.b, 1); +1, (_a3 = a) === null || _a3 === void 0 ? void 0 : _a3.b, 2; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/parenthesized-member-call-loose/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/parenthesized-member-call-loose/output.js new file mode 100644 index 0000000000000..99e98cc63a9d9 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/parenthesized-member-call-loose/output.js @@ -0,0 +1,31 @@ +class Foo { + constructor() { + this.x = 1; + this.self = this; + } + m() { + return this.x; + } + getSelf() { + return this; + } + test() { + var _o$Foo, _o$Foo2, _o$Foo3, _o$Foo4, _o$Foo$self, _fn, _fn$Foo$self; + const Foo = this; + const o = { Foo }; + const fn = function() { + return o; + }; + (Foo === null || Foo === void 0 ? void 0 : Foo["m"].bind(Foo))(); + (Foo === null || Foo === void 0 ? void 0 : Foo["m"].bind(Foo))().toString; + (Foo === null || Foo === void 0 ? void 0 : Foo["m"].bind(Foo))().toString(); + (o === null || o === void 0 ? void 0 : (_o$Foo = o.Foo).m.bind(_o$Foo))(); + (o === null || o === void 0 ? void 0 : (_o$Foo2 = o.Foo).m.bind(_o$Foo2))().toString; + (o === null || o === void 0 ? void 0 : (_o$Foo3 = o.Foo).m.bind(_o$Foo3))().toString(); + ((_o$Foo4 = o.Foo) === null || _o$Foo4 === void 0 || (_o$Foo4 = _o$Foo4.self.getSelf()) === null || _o$Foo4 === void 0 ? void 0 : _o$Foo4.m.bind(_o$Foo4))(); + ((_o$Foo$self = o.Foo.self) === null || _o$Foo$self === void 0 || (_o$Foo$self = _o$Foo$self.getSelf()) === null || _o$Foo$self === void 0 ? void 0 : _o$Foo$self.m.bind(_o$Foo$self))(); + ((_fn = fn()) === null || _fn === void 0 || (_fn = _fn.Foo) === null || _fn === void 0 || (_fn = _fn.self.getSelf()) === null || _fn === void 0 ? void 0 : _fn.m.bind(_fn))(); + (fn === null || fn === void 0 || (_fn$Foo$self = fn().Foo.self) === null || _fn$Foo$self === void 0 || (_fn$Foo$self = _fn$Foo$self.getSelf()) === null || _fn$Foo$self === void 0 ? void 0 : _fn$Foo$self.m.bind(_fn$Foo$self))(); + } +} +new Foo().test(); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/parenthesized-member-call/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/parenthesized-member-call/output.js new file mode 100644 index 0000000000000..99e98cc63a9d9 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/parenthesized-member-call/output.js @@ -0,0 +1,31 @@ +class Foo { + constructor() { + this.x = 1; + this.self = this; + } + m() { + return this.x; + } + getSelf() { + return this; + } + test() { + var _o$Foo, _o$Foo2, _o$Foo3, _o$Foo4, _o$Foo$self, _fn, _fn$Foo$self; + const Foo = this; + const o = { Foo }; + const fn = function() { + return o; + }; + (Foo === null || Foo === void 0 ? void 0 : Foo["m"].bind(Foo))(); + (Foo === null || Foo === void 0 ? void 0 : Foo["m"].bind(Foo))().toString; + (Foo === null || Foo === void 0 ? void 0 : Foo["m"].bind(Foo))().toString(); + (o === null || o === void 0 ? void 0 : (_o$Foo = o.Foo).m.bind(_o$Foo))(); + (o === null || o === void 0 ? void 0 : (_o$Foo2 = o.Foo).m.bind(_o$Foo2))().toString; + (o === null || o === void 0 ? void 0 : (_o$Foo3 = o.Foo).m.bind(_o$Foo3))().toString(); + ((_o$Foo4 = o.Foo) === null || _o$Foo4 === void 0 || (_o$Foo4 = _o$Foo4.self.getSelf()) === null || _o$Foo4 === void 0 ? void 0 : _o$Foo4.m.bind(_o$Foo4))(); + ((_o$Foo$self = o.Foo.self) === null || _o$Foo$self === void 0 || (_o$Foo$self = _o$Foo$self.getSelf()) === null || _o$Foo$self === void 0 ? void 0 : _o$Foo$self.m.bind(_o$Foo$self))(); + ((_fn = fn()) === null || _fn === void 0 || (_fn = _fn.Foo) === null || _fn === void 0 || (_fn = _fn.self.getSelf()) === null || _fn === void 0 ? void 0 : _fn.m.bind(_fn))(); + (fn === null || fn === void 0 || (_fn$Foo$self = fn().Foo.self) === null || _fn$Foo$self === void 0 || (_fn$Foo$self = _fn$Foo$self.getSelf()) === null || _fn$Foo$self === void 0 ? void 0 : _fn$Foo$self.m.bind(_fn$Foo$self))(); + } +} +new Foo().test(); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/super-method-call-loose/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/super-method-call-loose/output.js new file mode 100644 index 0000000000000..5d425d69fb101 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/super-method-call-loose/output.js @@ -0,0 +1,12 @@ +"use strict"; +class Base { + method() { + return "Hello!"; + } +} +class Derived extends Base { + method() { + var _super$method; + return (_super$method = super.method) === null || _super$method === void 0 ? void 0 : _super$method.call(this); + } +} diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/super-method-call/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/super-method-call/output.js new file mode 100644 index 0000000000000..5d425d69fb101 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/super-method-call/output.js @@ -0,0 +1,12 @@ +"use strict"; +class Base { + method() { + return "Hello!"; + } +} +class Derived extends Base { + method() { + var _super$method; + return (_super$method = super.method) === null || _super$method === void 0 ? void 0 : _super$method.call(this); + } +} diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/unary/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/unary/output.js new file mode 100644 index 0000000000000..ea6001e7a1aaa --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/general/unary/output.js @@ -0,0 +1,7 @@ +"use strict"; +var _obj$a, _obj$b, _obj$b2; +const obj = { a: { b: 0 } }; +let test = +(obj === null || obj === void 0 || (_obj$a = obj.a) === null || _obj$a === void 0 ? void 0 : _obj$a.b); +test = +(obj === null || obj === void 0 ? void 0 : obj.a.b); +test = +(obj === null || obj === void 0 || (_obj$b = obj.b) === null || _obj$b === void 0 ? void 0 : _obj$b.b); +test = +(obj === null || obj === void 0 || (_obj$b2 = obj.b) === null || _obj$b2 === void 0 ? void 0 : _obj$b2.b); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/loose/cast-to-boolean/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/loose/cast-to-boolean/output.js new file mode 100644 index 0000000000000..c58ff0c532b9c --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/loose/cast-to-boolean/output.js @@ -0,0 +1,85 @@ +class C { + static testIf(o) { + if (o === null || o === void 0 ? void 0 : o.a.b.c.d) { + return true; + } + return false; + } + static testConditional(o) { + var _o$a$b; + return (o === null || o === void 0 || (_o$a$b = o.a.b) === null || _o$a$b === void 0 ? void 0 : _o$a$b.c.d) ? true : false; + } + static testLoop(o) { + while (o === null || o === void 0 ? void 0 : o.a.b.c.d) { + var _o$a$b$c; + for (; o === null || o === void 0 || (_o$a$b$c = o.a.b.c) === null || _o$a$b$c === void 0 ? void 0 : _o$a$b$c.d;) { + var _o$a$b2; + let i = 0; + do { + i++; + if (i === 2) { + return true; + } + } while (o === null || o === void 0 || (_o$a$b2 = o.a.b) === null || _o$a$b2 === void 0 ? void 0 : _o$a$b2.c.d); + } + } + return false; + } + static testNegate(o) { + var _o$a$b3; + return !!(o === null || o === void 0 || (_o$a$b3 = o.a.b) === null || _o$a$b3 === void 0 ? void 0 : _o$a$b3.c.d); + } + static testIfDeep(o) { + var _o$obj; + if ((_o$obj = o.obj) === null || _o$obj === void 0 || (_o$obj = _o$obj.a.b) === null || _o$obj === void 0 ? void 0 : _o$obj.c.d) { + return true; + } + return false; + } + static testConditionalDeep(o) { + var _o$obj2; + return ((_o$obj2 = o.obj) === null || _o$obj2 === void 0 || (_o$obj2 = _o$obj2.a.b) === null || _o$obj2 === void 0 ? void 0 : _o$obj2.c.d) ? true : false; + } + static testLoopDeep(o) { + var _o$obj3; + while ((_o$obj3 = o.obj) === null || _o$obj3 === void 0 ? void 0 : _o$obj3.a.b.c.d) { + var _o$obj4; + for (; (_o$obj4 = o.obj) === null || _o$obj4 === void 0 || (_o$obj4 = _o$obj4.a.b.c) === null || _o$obj4 === void 0 ? void 0 : _o$obj4.d;) { + var _o$obj5; + let i = 0; + do { + i++; + if (i === 2) { + return true; + } + } while ((_o$obj5 = o.obj) === null || _o$obj5 === void 0 || (_o$obj5 = _o$obj5.a.b) === null || _o$obj5 === void 0 ? void 0 : _o$obj5.c.d); + } + } + return false; + } + static testNegateDeep(o) { + var _o$obj6; + return !!((_o$obj6 = o.obj) === null || _o$obj6 === void 0 || (_o$obj6 = _o$obj6.a.b) === null || _o$obj6 === void 0 ? void 0 : _o$obj6.c.d); + } + static testLogicalInIf(o) { + var _o$a$b4, _o$a; + if ((o === null || o === void 0 || (_o$a$b4 = o.a.b) === null || _o$a$b4 === void 0 ? void 0 : _o$a$b4.c.d) && (o === null || o === void 0 || (_o$a = o.a) === null || _o$a === void 0 ? void 0 : _o$a.b.c.d)) { + return true; + } + return false; + } + static testLogicalInReturn(o) { + var _o$a$b5, _o$a2; + return (o === null || o === void 0 || (_o$a$b5 = o.a.b) === null || _o$a$b5 === void 0 ? void 0 : _o$a$b5.c.d) && (o === null || o === void 0 || (_o$a2 = o.a) === null || _o$a2 === void 0 ? void 0 : _o$a2.b.c.d); + } + static testNullishCoalescing(o) { + var _o$a$b$c$non_existent, _o$a$b6, _o$a$b7, _o$a$b$c$non_existent3, _o$a$b10; + if ((_o$a$b$c$non_existent = o === null || o === void 0 || (_o$a$b6 = o.a.b) === null || _o$a$b6 === void 0 ? void 0 : _o$a$b6.c.non_existent) !== null && _o$a$b$c$non_existent !== void 0 ? _o$a$b$c$non_existent : o === null || o === void 0 || (_o$a$b7 = o.a.b) === null || _o$a$b7 === void 0 ? void 0 : _o$a$b7.c.d) { + var _o$a$b$c$non_existent2, _o$a$b8, _o$a$b9; + return (_o$a$b$c$non_existent2 = o === null || o === void 0 || (_o$a$b8 = o.a.b) === null || _o$a$b8 === void 0 ? void 0 : _o$a$b8.c.non_existent) !== null && _o$a$b$c$non_existent2 !== void 0 ? _o$a$b$c$non_existent2 : o === null || o === void 0 || (_o$a$b9 = o.a.b) === null || _o$a$b9 === void 0 ? void 0 : _o$a$b9.c.d; + } + return (_o$a$b$c$non_existent3 = o === null || o === void 0 || (_o$a$b10 = o.a.b) === null || _o$a$b10 === void 0 ? void 0 : _o$a$b10.c.non_existent) !== null && _o$a$b$c$non_existent3 !== void 0 ? _o$a$b$c$non_existent3 : o; + } +} +C.test(); +C.testNullish(); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/10959-transform-optional-chaining/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/10959-transform-optional-chaining/output.js new file mode 100644 index 0000000000000..1ed8d909524c9 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/10959-transform-optional-chaining/output.js @@ -0,0 +1,9 @@ +var _a, _a2, _a3, _b, _a4, _a5, _a6, _a7; +(_a = a) === null || _a === void 0 ? void 0 : _a.b.c; +(_a2 = a) === null || _a2 === void 0 ? void 0 : _a2.b.c.d; +(_a3 = a) === null || _a3 === void 0 ? void 0 : _a3.b.c.d; +(_b = a.b) === null || _b === void 0 ? void 0 : _b.c; +(_a4 = a) === null || _a4 === void 0 || (_a4 = _a4.b) === null || _a4 === void 0 ? void 0 : _a4.c; +(_a5 = a) === null || _a5 === void 0 || (_a5 = _a5.b.c) === null || _a5 === void 0 ? void 0 : _a5.c; +((_a6 = a) === null || _a6 === void 0 ? void 0 : _a6.b).c; +((_a7 = a) === null || _a7 === void 0 ? void 0 : _a7.b).c; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/10959-transform-ts-and-optional-chaining/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/10959-transform-ts-and-optional-chaining/output.js new file mode 100644 index 0000000000000..1ed8d909524c9 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/10959-transform-ts-and-optional-chaining/output.js @@ -0,0 +1,9 @@ +var _a, _a2, _a3, _b, _a4, _a5, _a6, _a7; +(_a = a) === null || _a === void 0 ? void 0 : _a.b.c; +(_a2 = a) === null || _a2 === void 0 ? void 0 : _a2.b.c.d; +(_a3 = a) === null || _a3 === void 0 ? void 0 : _a3.b.c.d; +(_b = a.b) === null || _b === void 0 ? void 0 : _b.c; +(_a4 = a) === null || _a4 === void 0 || (_a4 = _a4.b) === null || _a4 === void 0 ? void 0 : _a4.c; +(_a5 = a) === null || _a5 === void 0 || (_a5 = _a5.b.c) === null || _a5 === void 0 ? void 0 : _a5.c; +((_a6 = a) === null || _a6 === void 0 ? void 0 : _a6.b).c; +((_a7 = a) === null || _a7 === void 0 ? void 0 : _a7.b).c; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/10959-transform-ts/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/10959-transform-ts/output.js new file mode 100644 index 0000000000000..b6d13e7877e7b --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/10959-transform-ts/output.js @@ -0,0 +1,8 @@ +a?.b.c; +a?.b.c.d; +a?.b.c.d; +a.b?.c; +a?.b?.c; +a?.b.c?.c; +(a?.b).c; +(a?.b).c; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/15887/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/15887/output.js new file mode 100644 index 0000000000000..fd6c1f8ab2aad --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/15887/output.js @@ -0,0 +1,3 @@ +var _ref, _ref2; +let a = ((_ref = null) === null || _ref === void 0 ? void 0 : _ref.prop1, (_ref2 = null) === null || _ref2 === void 0 ? void 0 : _ref2.prop2); +expect(a).toBe(undefined); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/7642/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/7642/output.js new file mode 100644 index 0000000000000..32833270a97f2 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/regression/7642/output.js @@ -0,0 +1,7 @@ +{ + const foo = 1; +} +{ + var _ref; + const foo = (_ref = {}) === null || _ref === void 0 ? void 0 : _ref.foo; +} diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-call-context-in-if/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-call-context-in-if/output.js new file mode 100644 index 0000000000000..25b7d27b85b39 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-call-context-in-if/output.js @@ -0,0 +1,4 @@ +(a) => { + var _a$b; + if ((_a$b = a.b) === null || _a$b === void 0 ? void 0 : _a$b.call(a)) {} +}; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-call-context/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-call-context/output.js new file mode 100644 index 0000000000000..a0611735cad8e --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-call-context/output.js @@ -0,0 +1,2 @@ +var _a$b, _a; +(_a$b = (_a = a).b) === null || _a$b === void 0 ? void 0 : _a$b.call(_a); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-function-call-loose/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-function-call-loose/output.js new file mode 100644 index 0000000000000..d8f90df76a1d1 --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-function-call-loose/output.js @@ -0,0 +1,2 @@ +var _bar; +(_bar = foo.bar) === null || _bar === void 0 ? void 0 : _bar(foo.bar, false); diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-in-conditional/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-in-conditional/output.js new file mode 100644 index 0000000000000..4e87c3ebfa54f --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-in-conditional/output.js @@ -0,0 +1,4 @@ +(a) => { + var _a$c; + (a === null || a === void 0 ? void 0 : a.b) && ((_a$c = a.c) === null || _a$c === void 0 ? void 0 : _a$c.d) ? 0 : 1; +}; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-member-expression/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-member-expression/output.js new file mode 100644 index 0000000000000..07f79136703ee --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-member-expression/output.js @@ -0,0 +1,2 @@ +var _a; +(_a = a) === null || _a === void 0 || (_a = _a.b) === null || _a === void 0 ? void 0 : _a.c; diff --git a/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-parenthesized-expression-member-call/output.js b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-parenthesized-expression-member-call/output.js new file mode 100644 index 0000000000000..1bcaf9e41078c --- /dev/null +++ b/tasks/transform_conformance/snapshots/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-parenthesized-expression-member-call/output.js @@ -0,0 +1,2 @@ +var _o, _o$Foo; +((_o = o) === null || _o === void 0 ? void 0 : (_o$Foo = _o.Foo).m.bind(_o$Foo))(); diff --git a/tasks/transform_conformance/snapshots/babel.snap.md b/tasks/transform_conformance/snapshots/babel.snap.md index 1c9354ec6c2a8..b6e0c7a475e0f 100644 --- a/tasks/transform_conformance/snapshots/babel.snap.md +++ b/tasks/transform_conformance/snapshots/babel.snap.md @@ -1,6 +1,6 @@ commit: d20b314c -Passed: 327/574 +Passed: 328/575 # All Passed: * babel-plugin-transform-class-static-block @@ -408,7 +408,7 @@ rebuilt : ScopeId(1): [] x Output mismatch -# babel-plugin-transform-typescript (45/155) +# babel-plugin-transform-typescript (46/156) * cast/as-expression/input.ts Unresolved references mismatch: after transform: ["T", "x"] diff --git a/tasks/transform_conformance/snapshots/babel_exec.snap.md b/tasks/transform_conformance/snapshots/babel_exec.snap.md index 84039ef7f342a..de542525f891f 100644 --- a/tasks/transform_conformance/snapshots/babel_exec.snap.md +++ b/tasks/transform_conformance/snapshots/babel_exec.snap.md @@ -11,9 +11,51 @@ Error: 'eval' and 'arguments' cannot be used as a binding identifier in strict m ❯ ssrTransformScript ../../node_modules/.pnpm/vite@5.4.11_@types+node@22.9.1/node_modules/vite/dist/node/chunks/dep-CB_7IfJ-.js:52381:11 ❯ loadAndTransform ../../node_modules/.pnpm/vite@5.4.11_@types+node@22.9.1/node_modules/vite/dist/node/chunks/dep-CB_7IfJ-.js:51979:72 -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/4]⎯ - -⎯⎯⎯⎯⎯⎯⎯ Failed Tests 3 ⎯⎯⎯⎯⎯⎯⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/7]⎯ + +⎯⎯⎯⎯⎯⎯⎯ Failed Tests 6 ⎯⎯⎯⎯⎯⎯⎯ + + FAIL fixtures/babel-plugin-transform-optional-chaining-test-fixtures-assumption-noDocumentAll-parenthesized-expression-member-call-exec.test.js > exec +TypeError: Cannot read properties of undefined (reading 'x') + ❯ m fixtures/babel-plugin-transform-optional-chaining-test-fixtures-assumption-noDocumentAll-parenthesized-expression-member-call-exec.test.js:10:16 + 8| } + 9| m() { + 10| return this.x; + | ^ + 11| } + 12| getSelf() { + ❯ Foo.test fixtures/babel-plugin-transform-optional-chaining-test-fixtures-assumption-noDocumentAll-parenthesized-expression-member-call-exec.test.js:25:63 + ❯ fixtures/babel-plugin-transform-optional-chaining-test-fixtures-assumption-noDocumentAll-parenthesized-expression-member-call-exec.test.js:68:12 + +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/7]⎯ + + FAIL fixtures/babel-plugin-transform-optional-chaining-test-fixtures-general-parenthesized-expression-member-call-exec.test.js > exec +TypeError: Cannot read properties of undefined (reading 'x') + ❯ m fixtures/babel-plugin-transform-optional-chaining-test-fixtures-general-parenthesized-expression-member-call-exec.test.js:10:16 + 8| } + 9| m() { + 10| return this.x; + | ^ + 11| } + 12| getSelf() { + ❯ Foo.test fixtures/babel-plugin-transform-optional-chaining-test-fixtures-general-parenthesized-expression-member-call-exec.test.js:25:63 + ❯ fixtures/babel-plugin-transform-optional-chaining-test-fixtures-general-parenthesized-expression-member-call-exec.test.js:68:12 + +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/7]⎯ + + FAIL fixtures/babel-plugin-transform-optional-chaining-test-fixtures-general-parenthesized-expression-member-call-loose-exec.test.js > exec +TypeError: Cannot read properties of undefined (reading 'x') + ❯ m fixtures/babel-plugin-transform-optional-chaining-test-fixtures-general-parenthesized-expression-member-call-loose-exec.test.js:10:16 + 8| } + 9| m() { + 10| return this.x; + | ^ + 11| } + 12| getSelf() { + ❯ Foo.test fixtures/babel-plugin-transform-optional-chaining-test-fixtures-general-parenthesized-expression-member-call-loose-exec.test.js:25:63 + ❯ fixtures/babel-plugin-transform-optional-chaining-test-fixtures-general-parenthesized-expression-member-call-loose-exec.test.js:68:12 + +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/7]⎯ FAIL fixtures/babel-preset-env-test-fixtures-plugins-integration-issue-15170-exec.test.js > exec AssertionError: expected [Function] to not throw an error but 'ReferenceError: x is not defined' was thrown @@ -31,7 +73,7 @@ undefined | ^ 7| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/4]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/7]⎯ FAIL fixtures/babel-preset-env-test-fixtures-sanity-check-es2015-constants-exec.test.js > exec TypeError: Assignment to constant variable. @@ -42,7 +84,7 @@ TypeError: Assignment to constant variable. | ^ 6| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/4]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/7]⎯ FAIL fixtures/babel-preset-env-test-fixtures-sanity-regex-dot-all-exec.test.js > exec AssertionError: expected false to be true // Object.is equality @@ -61,5 +103,5 @@ AssertionError: expected false to be true // Object.is equality 11| expect(/hello.world/su.test(input)).toBe(true); 12| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/4]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[7/7]⎯ diff --git a/tasks/transform_conformance/src/constants.rs b/tasks/transform_conformance/src/constants.rs index 49416e76b10de..15fa592141f83 100644 --- a/tasks/transform_conformance/src/constants.rs +++ b/tasks/transform_conformance/src/constants.rs @@ -15,7 +15,7 @@ pub const PLUGINS: &[&str] = &[ // "babel-plugin-transform-export-namespace-from", // "babel-plugin-transform-dynamic-import", "babel-plugin-transform-nullish-coalescing-operator", - // "babel-plugin-transform-optional-chaining", + "babel-plugin-transform-optional-chaining", // // [Syntax] "babel-plugin-transform-syntax-bigint", // // [Syntax] "babel-plugin-transform-syntax-dynamic-import", // // [Syntax] "babel-plugin-transform-syntax-import-meta", @@ -67,7 +67,6 @@ pub const PLUGINS_NOT_SUPPORTED_YET: &[&str] = &[ "transform-classes", "transform-destructuring", "transform-modules-commonjs", - "transform-optional-chaining", "transform-parameters", "transform-private-methods", "transform-property-literals", diff --git a/tasks/transform_conformance/src/test_case.rs b/tasks/transform_conformance/src/test_case.rs index bac60cc023ebc..30665e2b23948 100644 --- a/tasks/transform_conformance/src/test_case.rs +++ b/tasks/transform_conformance/src/test_case.rs @@ -383,7 +383,12 @@ test("exec", () => {{ Ok(code) => code, Err(error) => error, }; - let path = snap_root().join(self.path.strip_prefix(packages_root()).unwrap()); + let mut path = snap_root().join(self.path.strip_prefix(packages_root()).unwrap()); + path.set_file_name("output"); + let input_extension = self.path.extension().unwrap().to_str().unwrap(); + let extension = + input_extension.chars().map(|c| if c == 't' { 'j' } else { c }).collect::(); + path.set_extension(extension); if filtered { println!("Input path: {:?}", &self.path); println!("Output path: {path:?}");