istanbuljs / babel-plugin-istanbul

A babel plugin that adds istanbul instrumentation to ES6 code
BSD 3-Clause "New" or "Revised" License
616 stars 72 forks source link

Destructuring imports are broken #258

Closed rehandalal closed 3 years ago

rehandalal commented 3 years ago

I created a little sample repo to outline the problem: https://github.com/rehandalal/bugxample

The example file looks like this:

import React from "react";
import { Button, IconButton } from "rsuite";

const Tester = ({ withIcon }) => {
    let Component = Button;
    if (withIcon) {
        Component = IconButton;
    }
    return <Component>Test</Component>;
}

export default Tester;

It compiles to:

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;

require("rsuite/lib/IconButton/styles/themes/default");

var _IconButton2 = _interopRequireDefault(require("rsuite/lib/IconButton"));

var _react = _interopRequireDefault(require("react"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function cov_11jt33zmh9() {
  var path = "/home/rdalal/Projects/bugxample/index.js";
  var hash = "582beb4c1f8b235b4a325433b850fdd28179fed4";
  var global = new Function("return this")();
  var gcv = "__coverage__";
  var coverageData = {
    path: "/home/rdalal/Projects/bugxample/index.js",
    statementMap: {
      "0": {
        start: {
          line: 4,
          column: 15
        },
        end: {
          line: 10,
          column: 1
        }
      },
      "1": {
        start: {
          line: 5,
          column: 20
        },
        end: {
          line: 5,
          column: 26
        }
      },
      "2": {
        start: {
          line: 6,
          column: 4
        },
        end: {
          line: 8,
          column: 5
        }
      },
      "3": {
        start: {
          line: 7,
          column: 8
        },
        end: {
          line: 7,
          column: 31
        }
      },
      "4": {
        start: {
          line: 9,
          column: 4
        },
        end: {
          line: 9,
          column: 39
        }
      }
    },
    fnMap: {
      "0": {
        name: "(anonymous_0)",
        decl: {
          start: {
            line: 4,
            column: 15
          },
          end: {
            line: 4,
            column: 16
          }
        },
        loc: {
          start: {
            line: 4,
            column: 33
          },
          end: {
            line: 10,
            column: 1
          }
        },
        line: 4
      }
    },
    branchMap: {
      "0": {
        loc: {
          start: {
            line: 6,
            column: 4
          },
          end: {
            line: 8,
            column: 5
          }
        },
        type: "if",
        locations: [{
          start: {
            line: 6,
            column: 4
          },
          end: {
            line: 8,
            column: 5
          }
        }, {
          start: {
            line: 6,
            column: 4
          },
          end: {
            line: 8,
            column: 5
          }
        }],
        line: 6
      }
    },
    s: {
      "0": 0,
      "1": 0,
      "2": 0,
      "3": 0,
      "4": 0
    },
    f: {
      "0": 0
    },
    b: {
      "0": [0, 0]
    },
    _coverageSchema: "1a1c01bbd47fc00a2c39e90264f33305004495a9",
    hash: "582beb4c1f8b235b4a325433b850fdd28179fed4"
  };
  var coverage = global[gcv] || (global[gcv] = {});

  if (!coverage[path] || coverage[path].hash !== hash) {
    coverage[path] = coverageData;
  }

  var actualCoverage = coverage[path];
  {
    // @ts-ignore
    cov_11jt33zmh9 = function () {
      return actualCoverage;
    };
  }
  return actualCoverage;
}

cov_11jt33zmh9();
cov_11jt33zmh9().s[0]++;

var Tester = function Tester(_ref) {
  var withIcon = _ref.withIcon;
  cov_11jt33zmh9().f[0]++;
  var Component = (cov_11jt33zmh9().s[1]++, Button);
  cov_11jt33zmh9().s[2]++;

  if (withIcon) {
    cov_11jt33zmh9().b[0][0]++;
    cov_11jt33zmh9().s[3]++;
    Component = _IconButton2["default"];
  } else {
    cov_11jt33zmh9().b[0][1]++;
  }

  cov_11jt33zmh9().s[4]++;
  return /*#__PURE__*/_react["default"].createElement(Component, null, "Test");
};

var _default = Tester;
exports["default"] = _default;

This results in a ReferenceError as Button does not seem to get imported or defined at all:

ReferenceError: Button is not defined

      3 | 
      4 | const Tester = ({ withIcon }) => {
    > 5 |     let Component = Button;
rehandalal commented 3 years ago

Making this change does appear to fix things but this definitely feels like a bug:

import React from "react";
import * as rsuite from "rsuite";

const Tester = ({ withIcon }) => {
    let Component = rsuite.Button;
    if (withIcon) {
        Component = rsuite.IconButton;
    }
    return <Component>Test</Component>;
}

export default Tester;
coreyfarrell commented 3 years ago

I use destructuring imports with many projects without issue. Likely there is a conflict between babel-plugin-istanbul and another babel plugin you are using, though I'm unsure what we (istanbul) would do to remedy this. We don't actually manipulate import statements at all (no coverage counters are added to them).

rehandalal commented 3 years ago

Looking at the Yarn lockfile there are two potential plugins: babel-plugin-import and babel-plugin-dynamic-import-node which seem like they may be culprits. I do notice that #161 is filed for babel-plugin-import and seems to describe a similar issue.

coreyfarrell commented 3 years ago

Thanks for the update, closing this as I believe you are experiencing the babel-plugin-import issue.