Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A commonjs module could be wrongly marked with __esModule: true while enabling external helpers #6500

Open
hyf0 opened this issue Nov 23, 2022 · 6 comments
Labels
Milestone

Comments

@hyf0
Copy link
Contributor

hyf0 commented Nov 23, 2022

Describe the bug

The input code is commonjs. If SWC triggers any helpers in transpiling or other processes, which will inject import ... from '@swc/...' statements, the commonjs visitor will detect these import statements and mark it with __esModule: true. But the original module is actually a commonjs module.

Input code

const a = require('./foo')
const foo = async () => {}

Config

{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": false
    },
    "target": "es5",
    "loose": false,
    "minify": {
      "compress": false,
      "mangle": false
    },
    "externalHelpers": true,
    "transform": {
      "react": {
        "refresh": {}
      }
    }
  },
  "module": {
    "type": "commonjs"
  },
  "minify": false,
  "isModule": true
}

Playground link

https://play.swc.rs/?version=1.3.19&code=H4sIAAAAAAAAA0vOzysuUUhUsFUoSi0szSxK1VDX00%2FLz1fX5EoGSwHZQMnE4sq8ZAUNTQVbO4XqWgCakFypNQAAAA%3D%3D&config=H4sIAAAAAAAAA0WOSwrDMAxE76J1tt3kBN30EMKVUwf%2FkBRICL57JRKINx48jzc%2BYZUA8wkdWYg9yVEVd5iBQkEJnLrCZJg9RcxCYwJFXkgdkZd1uTWhu52gpJri4abQSmcSeSqsS6bHQ7sSV8xvyp3YOOXNMGWsEhsXlzBh0CtEk%2F0sDjsma9%2FNZSfo0e32udLqKjCeT9zDST437QvjD6ne0KH2AAAA

Expected behavior

"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var a = require('./foo');
var foo = /*#__PURE__*/function () {
  var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() {
    return _regenerator["default"].wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
          case "end":
            return _context.stop();
        }
      }
    }, _callee);
  }));
  return function foo() {
    return _ref.apply(this, arguments);
  };
}();

Actual behavior

"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
var _asyncToGenerator = require("@swc/helpers/lib/_async_to_generator.js").default;
var _tsGenerator = require("@swc/helpers/lib/_ts_generator.js").default;
var a = require("./foo");
var foo = function() {
    var _ref = _asyncToGenerator(function() {
        return _tsGenerator(this, function(_state) {
            return [
                2
            ];
        });
    });
    return function foo() {
        return _ref.apply(this, arguments);
    };
}();

Version

1.3.19

Additional context

No response

@hyf0 hyf0 added the C-bug label Nov 23, 2022
@magic-akari
Copy link
Member

The swc input has only module and script, which are distinguished by isModule.
Although we can tell from common sense that this code is commonjs, it could be module.
We can create the require method at module runtime, a common example is as follows.

import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);

// sibling-module.js is a CommonJS module.
const siblingModule = require('./sibling-module');

https://nodejs.org/api/module.html#modulecreaterequirefilename

@magic-akari
Copy link
Member

Do you imply another way to introduce swc helpers? For example, use require instead of import.

@hyf0
Copy link
Contributor Author

hyf0 commented Nov 23, 2022

Do you imply another way to introduce swc helpers? For example, use require instead of import.

That's one way to solve it.

@hyf0
Copy link
Contributor Author

hyf0 commented Nov 23, 2022

The swc input has only module and script, which are distinguished by isModule. Although we can tell from common sense that this code is commonjs, it could be module. We can create the require method at module runtime, a common example is as follows.

import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);

// sibling-module.js is a CommonJS module.
const siblingModule = require('./sibling-module');

https://nodejs.org/api/module.html#modulecreaterequirefilename

The use case is when you transpile react.cjs.js to downgrade some syntax, the output will be marked as an ES module.

@RiESAEX
Copy link
Contributor

RiESAEX commented Jan 2, 2023

what abut check ModuleDecl's span before set has_module_decl = true?

@keadex
Copy link

keadex commented Aug 29, 2023

Any update or workaround for this issue? External helpers are very useful for reducing the bundle size, but this issue prevents their usage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

5 participants