packages/babel-plugin-proposal-nullish-coalescing-operator/src/index.js

Summary

Maintainability
A
1 hr
Test Coverage
import { declare } from "@babel/helper-plugin-utils";
import syntaxNullishCoalescingOperator from "@babel/plugin-syntax-nullish-coalescing-operator";
import { types as t } from "@babel/core";

export default declare((api, { loose = false }) => {
  api.assertVersion(7);

  return {
    name: "proposal-nullish-coalescing-operator",
    inherits: syntaxNullishCoalescingOperator,

    visitor: {
      LogicalExpression(path) {
        const { node, scope } = path;
        if (node.operator !== "??") {
          return;
        }

        let ref = scope.maybeGenerateMemoised(node.left);
        let assignment;
        // skip creating extra reference when `left` is static
        if (ref === null) {
          ref = node.left;
          assignment = t.cloneNode(node.left);
        } else {
          assignment = t.assignmentExpression("=", ref, node.left);
        }

        path.replaceWith(
          t.conditionalExpression(
            // We cannot use `!= null` in spec mode because
            // `document.all == null` and `document.all` is not "nullish".
            loose
              ? t.binaryExpression("!=", assignment, t.nullLiteral())
              : t.logicalExpression(
                  "&&",
                  t.binaryExpression("!==", assignment, t.nullLiteral()),
                  t.binaryExpression(
                    "!==",
                    t.cloneNode(ref),
                    scope.buildUndefinedNode(),
                  ),
                ),
            t.cloneNode(ref),
            node.right,
          ),
        );
      },
    },
  };
});