From cead38d6476d03e976068fefdc05ff55315b94c8 Mon Sep 17 00:00:00 2001 From: hi-ogawa <4232207+hi-ogawa@users.noreply.github.com> Date: Tue, 4 Mar 2025 12:15:47 +0000 Subject: [PATCH] fix(transformer/optional-chaining): fix context of optional chain call (#9526) - closes https://github.com/oxc-project/oxc/issues/9498 `this.f?.()` is handled by https://github.com/oxc-project/oxc/pull/9505, but it looks like the same needs to be applied for member expressions in general, such as `repro.x.f?.()`. Here is an output of esbuild https://esbuild.github.io/try/#dAAwLjI1LjAALS10YXJnZXQ9ZXMyMDE1AGNvbnN0IHJlcHJvID0ge30KcmVwcm8uZj8uKCk7CnJlcHJvLnguZj8uKCk7CnJlcHJvLnhbImYiXT8uKCk7 --- This PR fixes following case: - Not only member expressions but also arbitrary expressions can be a call context, such as: ```js (0, repro).f?.(); ``` - same logic is required for `transform_and_join_expression`, which is used in cases, such as ```js repro.x?.y.f?.() ``` --- .../src/es2020/optional_chaining.rs | 51 +++++++++++-------- .../memoize/output.js | 32 ++++++------ .../fixtures/general/memoize-loose/output.js | 32 ++++++------ .../ts-as-function-call-loose/output.js | 4 +- .../snapshots/babel_exec.snap.md | 20 +------- .../test/fixtures/oxc/keep-this/input.ts | 23 ++++++++- .../test/fixtures/oxc/keep-this/output.js | 27 ++++++++-- 7 files changed, 107 insertions(+), 82 deletions(-) diff --git a/crates/oxc_transformer/src/es2020/optional_chaining.rs b/crates/oxc_transformer/src/es2020/optional_chaining.rs index a84fed2cee27d..168aa0dd9b3f9 100644 --- a/crates/oxc_transformer/src/es2020/optional_chaining.rs +++ b/crates/oxc_transformer/src/es2020/optional_chaining.rs @@ -554,28 +554,7 @@ impl<'a> OptionalChaining<'a, '_> { // We should generate a temp binding for the expression first to avoid the next step changing the expression. let temp_binding = self.ctx.var_declarations.create_uid_var_based_on_node(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 = - self.get_existing_binding_for_identifier(ident, ctx).unwrap_or_else(|| { - let binding = - self.ctx.var_declarations.create_uid_var_based_on_node(object, ctx); - // `(_foo = foo)` - *object = Self::create_assignment_expression( - binding.create_write_target(ctx), - ctx.ast.move_expression(object), - ctx, - ); - binding.to_maybe_bound_identifier() - }); - self.set_binding_context(binding); - } else if matches!(object, Expression::Super(_) | Expression::ThisExpression(_)) { - self.set_this_context(); - } - } + self.set_chain_call_context(expr, ctx); } // Replace the expression with the temp binding and assign the original expression to the temp binding @@ -620,6 +599,7 @@ impl<'a> OptionalChaining<'a, '_> { if let Some(temp_binding) = self.temp_binding.take() { self.set_binding_context(temp_binding.to_maybe_bound_identifier()); } + self.set_chain_call_context(expr, ctx); } let temp_binding = { @@ -651,4 +631,31 @@ impl<'a> OptionalChaining<'a, '_> { Self::create_logical_expression(left, Self::wrap_void0_check(reference, ctx), ctx) } } + + fn set_chain_call_context(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { + 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 matches!(object, Expression::Super(_) | Expression::ThisExpression(_)) { + self.set_this_context(); + } else { + let binding = object + .get_identifier_reference() + .and_then(|ident| self.get_existing_binding_for_identifier(ident, ctx)) + .unwrap_or_else(|| { + let binding = + self.ctx.var_declarations.create_uid_var_based_on_node(object, ctx); + // `(_foo = foo)` + *object = Self::create_assignment_expression( + binding.create_write_target(ctx), + ctx.ast.move_expression(object), + ctx, + ); + binding.to_maybe_bound_identifier() + }); + self.set_binding_context(binding); + } + } + } } diff --git a/tasks/transform_conformance/overrides/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/output.js b/tasks/transform_conformance/overrides/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/output.js index eef863fbabda7..211081e930a58 100644 --- a/tasks/transform_conformance/overrides/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/output.js +++ b/tasks/transform_conformance/overrides/babel-plugin-transform-optional-chaining/test/fixtures/assumption-noDocumentAll/memoize/output.js @@ -1,18 +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); + var _foo$bar, _foo$get, _foo$bar2, _foo$bar3, _foo$bar$baz, _foo$bar4, _foo$bar$baz2, _foo$bar5, _foo$bar6, _foo$bar7, _foo$bar8, _foo$bar9, _foo$bar10, _foo$bar10$baz, _foo$bar11, _foo$bar11$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$bar4 = foo.bar()).baz) == null ? void 0 : _foo$bar$baz.call(_foo$bar4); + (_foo$bar$baz2 = (_foo$bar5 = foo[bar]()).baz) == null ? void 0 : _foo$bar$baz2.call(_foo$bar5); + (_foo$bar6 = foo.bar) == null ? void 0 : _foo$bar6.call(foo, foo.bar, false); + foo == null || (_foo$bar7 = foo.bar) == null ? void 0 : _foo$bar7.call(foo, foo.bar, true); + (_foo$bar8 = foo.bar) == null ? void 0 : _foo$bar8.baz(foo.bar, false); + foo == null || (_foo$bar9 = foo.bar) == null ? void 0 : _foo$bar9.baz(foo.bar, true); + (_foo$bar10 = foo.bar) == null || (_foo$bar10$baz = _foo$bar10.baz) == null ? void 0 : _foo$bar10$baz.call(_foo$bar10, foo.bar, false); + foo == null || (_foo$bar11 = foo.bar) == null || (_foo$bar11$baz = _foo$bar11.baz) == null ? void 0 : _foo$bar11$baz.call(_foo$bar11, foo.bar, true); } diff --git a/tasks/transform_conformance/overrides/babel-plugin-transform-optional-chaining/test/fixtures/general/memoize-loose/output.js b/tasks/transform_conformance/overrides/babel-plugin-transform-optional-chaining/test/fixtures/general/memoize-loose/output.js index 265f382386d90..14d754162d39e 100644 --- a/tasks/transform_conformance/overrides/babel-plugin-transform-optional-chaining/test/fixtures/general/memoize-loose/output.js +++ b/tasks/transform_conformance/overrides/babel-plugin-transform-optional-chaining/test/fixtures/general/memoize-loose/output.js @@ -1,18 +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); + var _foo$bar, _foo$get, _foo$bar2, _foo$bar3, _foo$bar$baz, _foo$bar4, _foo$bar$baz2, _foo$bar5, _foo$bar6, _foo$bar7, _foo$bar8, _foo$bar9, _foo$bar10, _foo$bar10$baz, _foo$bar11, _foo$bar11$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$bar4 = foo.bar()).baz) === null || _foo$bar$baz === void 0 ? void 0 : _foo$bar$baz.call(_foo$bar4); + (_foo$bar$baz2 = (_foo$bar5 = foo[bar]()).baz) === null || _foo$bar$baz2 === void 0 ? void 0 : _foo$bar$baz2.call(_foo$bar5); + (_foo$bar6 = foo.bar) === null || _foo$bar6 === void 0 ? void 0 : _foo$bar6.call(foo, foo.bar, false); + foo === null || foo === void 0 || (_foo$bar7 = foo.bar) === null || _foo$bar7 === void 0 ? void 0 : _foo$bar7.call(foo, foo.bar, true); + (_foo$bar8 = foo.bar) === null || _foo$bar8 === void 0 ? void 0 : _foo$bar8.baz(foo.bar, false); + foo === null || foo === void 0 || (_foo$bar9 = foo.bar) === null || _foo$bar9 === void 0 ? void 0 : _foo$bar9.baz(foo.bar, true); + (_foo$bar10 = foo.bar) === null || _foo$bar10 === void 0 || (_foo$bar10$baz = _foo$bar10.baz) === null || _foo$bar10$baz === void 0 ? void 0 : _foo$bar10$baz.call(_foo$bar10, foo.bar, false); + foo === null || foo === void 0 || (_foo$bar11 = foo.bar) === null || _foo$bar11 === void 0 || (_foo$bar11$baz = _foo$bar11.baz) === null || _foo$bar11$baz === void 0 ? void 0 : _foo$bar11$baz.call(_foo$bar11, foo.bar, true); } diff --git a/tasks/transform_conformance/overrides/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-function-call-loose/output.js b/tasks/transform_conformance/overrides/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-function-call-loose/output.js index d8f90df76a1d1..d7ed9e8b2c345 100644 --- a/tasks/transform_conformance/overrides/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-function-call-loose/output.js +++ b/tasks/transform_conformance/overrides/babel-plugin-transform-optional-chaining/test/fixtures/transparent-expr-wrappers/ts-as-function-call-loose/output.js @@ -1,2 +1,2 @@ -var _bar; -(_bar = foo.bar) === null || _bar === void 0 ? void 0 : _bar(foo.bar, false); +var _bar, _ref; +(_bar = (_ref = foo).bar) === null || _bar === void 0 ? void 0 : _bar.call(_ref, foo.bar, false); diff --git a/tasks/transform_conformance/snapshots/babel_exec.snap.md b/tasks/transform_conformance/snapshots/babel_exec.snap.md index 82a85d2ccd75f..297e4df29d254 100644 --- a/tasks/transform_conformance/snapshots/babel_exec.snap.md +++ b/tasks/transform_conformance/snapshots/babel_exec.snap.md @@ -2,7 +2,7 @@ commit: 578ac4df node: v22.14.0 -Passed: 318 of 406 (78.33%) +Passed: 320 of 406 (78.82%) Failures: @@ -26,24 +26,6 @@ At file: ./tasks/transform_conformance/fixtures/babel/babel-plugin-transform-cla AssertionError: expected undefined to be 'hello' // Object.is equality at ./tasks/transform_conformance/fixtures/babel/babel-plugin-transform-class-properties-test-fixtures-nested-class-super-property-in-decorator-exec.test.js:22:28 -./fixtures/babel/babel-plugin-transform-class-properties-test-fixtures-private-loose-optional-chain-in-function-param-with-transform-exec.test.js -TypeError: Cannot convert undefined or null to object - at hasOwnProperty () - at _classPrivateFieldBase (./npm/runtime/src/helpers/classPrivateFieldLooseBase.js:2:26) - at value (./tasks/transform_conformance/fixtures/babel/babel-plugin-transform-class-properties-test-fixtures-private-loose-optional-chain-in-function-param-with-transform-exec.test.js:63:11) - at ./tasks/transform_conformance/fixtures/babel/babel-plugin-transform-class-properties-test-fixtures-private-loose-optional-chain-in-function-param-with-transform-exec.test.js:44:198 - at j (./tasks/transform_conformance/fixtures/babel/babel-plugin-transform-class-properties-test-fixtures-private-loose-optional-chain-in-function-param-with-transform-exec.test.js:45:6) - at Function.test (./tasks/transform_conformance/fixtures/babel/babel-plugin-transform-class-properties-test-fixtures-private-loose-optional-chain-in-function-param-with-transform-exec.test.js:52:11) - at ./tasks/transform_conformance/fixtures/babel/babel-plugin-transform-class-properties-test-fixtures-private-loose-optional-chain-in-function-param-with-transform-exec.test.js:71:6 - -./fixtures/babel/babel-plugin-transform-class-properties-test-fixtures-private-loose-optional-chain-member-optional-call-with-transform-exec.test.js -TypeError: Cannot convert undefined or null to object - at hasOwnProperty () - at _classPrivateFieldBase (./npm/runtime/src/helpers/classPrivateFieldLooseBase.js:2:26) - at value (./tasks/transform_conformance/fixtures/babel/babel-plugin-transform-class-properties-test-fixtures-private-loose-optional-chain-member-optional-call-with-transform-exec.test.js:123:11) - at Function.test (./tasks/transform_conformance/fixtures/babel/babel-plugin-transform-class-properties-test-fixtures-private-loose-optional-chain-member-optional-call-with-transform-exec.test.js:24:134) - at ./tasks/transform_conformance/fixtures/babel/babel-plugin-transform-class-properties-test-fixtures-private-loose-optional-chain-member-optional-call-with-transform-exec.test.js:131:6 - ./fixtures/babel/babel-plugin-transform-class-properties-test-fixtures-private-loose-parenthesized-optional-member-call-exec.test.js TypeError: Cannot read properties of undefined (reading 'bind') at Foo.test (./tasks/transform_conformance/fixtures/babel/babel-plugin-transform-class-properties-test-fixtures-private-loose-parenthesized-optional-member-call-exec.test.js:20:59) diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-optional-chaining/test/fixtures/oxc/keep-this/input.ts b/tasks/transform_conformance/tests/babel-plugin-transform-optional-chaining/test/fixtures/oxc/keep-this/input.ts index 31e3c5b9502ab..a3e1264bcd669 100644 --- a/tasks/transform_conformance/tests/babel-plugin-transform-optional-chaining/test/fixtures/oxc/keep-this/input.ts +++ b/tasks/transform_conformance/tests/babel-plugin-transform-optional-chaining/test/fixtures/oxc/keep-this/input.ts @@ -1,5 +1,24 @@ -export class Repro { +class Repro { test() { - this.y?.(); + this.f?.(); + this.x.f?.(); + this.x.y.f?.(); + this.x?.f?.(); + this.x?.y.f?.(); + this.x.y?.f?.(); + this.x?.y?.f?.(); + this["x"].f?.(); + (0, this).f?.(); } } + +const repro = {}; +repro.f?.(); +repro.x.f?.(); +repro.x.y.f?.(); +repro.x?.f?.(); +repro.x?.y.f?.(); +repro.x.y?.f?.(); +repro.x?.y?.f?.(); +repro["x"].f?.(); +(0, repro).f?.() diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-optional-chaining/test/fixtures/oxc/keep-this/output.js b/tasks/transform_conformance/tests/babel-plugin-transform-optional-chaining/test/fixtures/oxc/keep-this/output.js index 60feb09f29ad5..7efab5698a79f 100644 --- a/tasks/transform_conformance/tests/babel-plugin-transform-optional-chaining/test/fixtures/oxc/keep-this/output.js +++ b/tasks/transform_conformance/tests/babel-plugin-transform-optional-chaining/test/fixtures/oxc/keep-this/output.js @@ -1,8 +1,25 @@ -export class Repro { +var _repro$f, _repro$x$f, _repro$x, _repro$x$y$f, _repro$x$y, _repro$x2, _repro$x2$f, _repro$x3, _repro$x3$y, _repro$x3$y$f, _repro$x$y2, _repro$x$y2$f, _repro$x4, _repro$x4$f, _repro$x$f2, _repro$x5, _f2, _ref2; +class Repro { test() { - var _this$y; - (_this$y = this.y) === null || _this$y === void 0 - ? void 0 - : _this$y.call(this); + var _this$f, _this$x$f, _this$x, _this$x$y$f, _this$x$y, _this$x2, _this$x2$f, _this$x3, _this$x3$y, _this$x3$y$f, _this$x$y2, _this$x$y2$f, _this$x4, _this$x4$f, _this$x$f2, _this$x5, _f, _ref; + (_this$f = this.f) === null || _this$f === void 0 ? void 0 : _this$f.call(this); + (_this$x$f = (_this$x = this.x).f) === null || _this$x$f === void 0 ? void 0 : _this$x$f.call(_this$x); + (_this$x$y$f = (_this$x$y = this.x.y).f) === null || _this$x$y$f === void 0 ? void 0 : _this$x$y$f.call(_this$x$y); + (_this$x2 = this.x) === null || _this$x2 === void 0 || (_this$x2$f = _this$x2.f) === null || _this$x2$f === void 0 ? void 0 : _this$x2$f.call(_this$x2); + (_this$x3 = this.x) === null || _this$x3 === void 0 || (_this$x3$y$f = (_this$x3$y = _this$x3.y).f) === null || _this$x3$y$f === void 0 ? void 0 : _this$x3$y$f.call(_this$x3$y); + (_this$x$y2 = this.x.y) === null || _this$x$y2 === void 0 || (_this$x$y2$f = _this$x$y2.f) === null || _this$x$y2$f === void 0 ? void 0 : _this$x$y2$f.call(_this$x$y2); + (_this$x4 = this.x) === null || _this$x4 === void 0 || (_this$x4 = _this$x4.y) === null || _this$x4 === void 0 || (_this$x4$f = _this$x4.f) === null || _this$x4$f === void 0 ? void 0 : _this$x4$f.call(_this$x4); + (_this$x$f2 = (_this$x5 = this["x"]).f) === null || _this$x$f2 === void 0 ? void 0 : _this$x$f2.call(_this$x5); + (_f = (_ref = (0, this)).f) === null || _f === void 0 ? void 0 : _f.call(_ref); } } +const repro = {}; +(_repro$f = repro.f) === null || _repro$f === void 0 ? void 0 : _repro$f.call(repro); +(_repro$x$f = (_repro$x = repro.x).f) === null || _repro$x$f === void 0 ? void 0 : _repro$x$f.call(_repro$x); +(_repro$x$y$f = (_repro$x$y = repro.x.y).f) === null || _repro$x$y$f === void 0 ? void 0 : _repro$x$y$f.call(_repro$x$y); +(_repro$x2 = repro.x) === null || _repro$x2 === void 0 || (_repro$x2$f = _repro$x2.f) === null || _repro$x2$f === void 0 ? void 0 : _repro$x2$f.call(_repro$x2); +(_repro$x3 = repro.x) === null || _repro$x3 === void 0 || (_repro$x3$y$f = (_repro$x3$y = _repro$x3.y).f) === null || _repro$x3$y$f === void 0 ? void 0 : _repro$x3$y$f.call(_repro$x3$y); +(_repro$x$y2 = repro.x.y) === null || _repro$x$y2 === void 0 || (_repro$x$y2$f = _repro$x$y2.f) === null || _repro$x$y2$f === void 0 ? void 0 : _repro$x$y2$f.call(_repro$x$y2); +(_repro$x4 = repro.x) === null || _repro$x4 === void 0 || (_repro$x4 = _repro$x4.y) === null || _repro$x4 === void 0 || (_repro$x4$f = _repro$x4.f) === null || _repro$x4$f === void 0 ? void 0 : _repro$x4$f.call(_repro$x4); +(_repro$x$f2 = (_repro$x5 = repro["x"]).f) === null || _repro$x$f2 === void 0 ? void 0 : _repro$x$f2.call(_repro$x5); +(_f2 = (_ref2 = (0, repro)).f) === null || _f2 === void 0 ? void 0 : _f2.call(_ref2);