From c5c80107e3c201cba00e27c03f678b15e8de76b5 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 5 Oct 2021 23:30:20 +0300 Subject: [PATCH] fix: crash with the `exportLocalsConvention` option --- src/loader.js | 3 +- .../expected/main.js | 89 +++++++++++++++++++ .../index.js | 4 + .../style.css | 11 +++ .../webpack.config.js | 32 +++++++ .../expected/main.js | 65 ++++++++++++++ .../export-only-locals-commonjs/index.js | 4 + .../export-only-locals-commonjs/style.css | 11 +++ .../webpack.config.js | 32 +++++++ .../cases/export-only-locals/expected/main.js | 65 ++++++++++++++ test/cases/export-only-locals/index.js | 4 + test/cases/export-only-locals/style.css | 11 +++ .../export-only-locals/webpack.config.js | 31 +++++++ 13 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 test/cases/export-only-locals-and-es-named-export/expected/main.js create mode 100644 test/cases/export-only-locals-and-es-named-export/index.js create mode 100644 test/cases/export-only-locals-and-es-named-export/style.css create mode 100644 test/cases/export-only-locals-and-es-named-export/webpack.config.js create mode 100644 test/cases/export-only-locals-commonjs/expected/main.js create mode 100644 test/cases/export-only-locals-commonjs/index.js create mode 100644 test/cases/export-only-locals-commonjs/style.css create mode 100644 test/cases/export-only-locals-commonjs/webpack.config.js create mode 100644 test/cases/export-only-locals/expected/main.js create mode 100644 test/cases/export-only-locals/index.js create mode 100644 test/cases/export-only-locals/style.css create mode 100644 test/cases/export-only-locals/webpack.config.js diff --git a/src/loader.js b/src/loader.js index d509562f..001b0fd2 100644 --- a/src/loader.js +++ b/src/loader.js @@ -98,7 +98,8 @@ export function pitch(request) { namedExport = // eslint-disable-next-line no-underscore-dangle - originalExports.__esModule && !("locals" in originalExports.default); + originalExports.__esModule && + (!originalExports.default || !("locals" in originalExports.default)); if (namedExport) { Object.keys(originalExports).forEach((key) => { diff --git a/test/cases/export-only-locals-and-es-named-export/expected/main.js b/test/cases/export-only-locals-and-es-named-export/expected/main.js new file mode 100644 index 00000000..0dc7fbd8 --- /dev/null +++ b/test/cases/export-only-locals-and-es-named-export/expected/main.js @@ -0,0 +1,89 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ([ +/* 0 */, +/* 1 */ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "aClass": () => (/* binding */ aClass), +/* harmony export */ "bClass": () => (/* binding */ bClass), +/* harmony export */ "cClass": () => (/* binding */ cClass) +/* harmony export */ }); +// extracted by mini-css-extract-plugin +var aClass = "foo__style__a-class"; +var bClass = "foo__style__b__class"; +var cClass = "foo__style__cClass"; + +/***/ }) +/******/ ]); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); + + +// eslint-disable-next-line no-console +console.log({ aClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.aClass, bClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.bClass, cClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.cClass }); + +})(); + +/******/ })() +; \ No newline at end of file diff --git a/test/cases/export-only-locals-and-es-named-export/index.js b/test/cases/export-only-locals-and-es-named-export/index.js new file mode 100644 index 00000000..60873693 --- /dev/null +++ b/test/cases/export-only-locals-and-es-named-export/index.js @@ -0,0 +1,4 @@ +import { aClass, bClass, cClass } from "./style.css"; + +// eslint-disable-next-line no-console +console.log({ aClass, bClass, cClass }); diff --git a/test/cases/export-only-locals-and-es-named-export/style.css b/test/cases/export-only-locals-and-es-named-export/style.css new file mode 100644 index 00000000..a9085408 --- /dev/null +++ b/test/cases/export-only-locals-and-es-named-export/style.css @@ -0,0 +1,11 @@ +.a-class { + background: red; +} + +.b__class { + color: green; +} + +.cClass { + color: blue; +} diff --git a/test/cases/export-only-locals-and-es-named-export/webpack.config.js b/test/cases/export-only-locals-and-es-named-export/webpack.config.js new file mode 100644 index 00000000..2cbb9676 --- /dev/null +++ b/test/cases/export-only-locals-and-es-named-export/webpack.config.js @@ -0,0 +1,32 @@ +import Self from "../../../src"; + +module.exports = { + entry: "./index.js", + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: Self.loader, + }, + { + loader: "css-loader", + options: { + modules: { + namedExport: true, + localIdentName: "foo__[name]__[local]", + exportOnlyLocals: true, + }, + }, + }, + ], + }, + ], + }, + plugins: [ + new Self({ + filename: "[name].css", + }), + ], +}; diff --git a/test/cases/export-only-locals-commonjs/expected/main.js b/test/cases/export-only-locals-commonjs/expected/main.js new file mode 100644 index 00000000..72d4ede0 --- /dev/null +++ b/test/cases/export-only-locals-commonjs/expected/main.js @@ -0,0 +1,65 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ([ +/* 0 */, +/* 1 */ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +// extracted by mini-css-extract-plugin + + +/***/ }) +/******/ ]); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); + + +// eslint-disable-next-line no-console +console.log({ aClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.aClass, bClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.bClass, cClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.cClass }); + +})(); + +/******/ })() +; \ No newline at end of file diff --git a/test/cases/export-only-locals-commonjs/index.js b/test/cases/export-only-locals-commonjs/index.js new file mode 100644 index 00000000..60873693 --- /dev/null +++ b/test/cases/export-only-locals-commonjs/index.js @@ -0,0 +1,4 @@ +import { aClass, bClass, cClass } from "./style.css"; + +// eslint-disable-next-line no-console +console.log({ aClass, bClass, cClass }); diff --git a/test/cases/export-only-locals-commonjs/style.css b/test/cases/export-only-locals-commonjs/style.css new file mode 100644 index 00000000..a9085408 --- /dev/null +++ b/test/cases/export-only-locals-commonjs/style.css @@ -0,0 +1,11 @@ +.a-class { + background: red; +} + +.b__class { + color: green; +} + +.cClass { + color: blue; +} diff --git a/test/cases/export-only-locals-commonjs/webpack.config.js b/test/cases/export-only-locals-commonjs/webpack.config.js new file mode 100644 index 00000000..74b9b8e3 --- /dev/null +++ b/test/cases/export-only-locals-commonjs/webpack.config.js @@ -0,0 +1,32 @@ +import Self from "../../../src"; + +module.exports = { + entry: "./index.js", + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: Self.loader, + }, + { + loader: "css-loader", + options: { + esModule: false, + modules: { + localIdentName: "foo__[name]__[local]", + exportOnlyLocals: true, + }, + }, + }, + ], + }, + ], + }, + plugins: [ + new Self({ + filename: "[name].css", + }), + ], +}; diff --git a/test/cases/export-only-locals/expected/main.js b/test/cases/export-only-locals/expected/main.js new file mode 100644 index 00000000..72d4ede0 --- /dev/null +++ b/test/cases/export-only-locals/expected/main.js @@ -0,0 +1,65 @@ +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ([ +/* 0 */, +/* 1 */ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +// extracted by mini-css-extract-plugin + + +/***/ }) +/******/ ]); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1); + + +// eslint-disable-next-line no-console +console.log({ aClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.aClass, bClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.bClass, cClass: _style_css__WEBPACK_IMPORTED_MODULE_0__.cClass }); + +})(); + +/******/ })() +; \ No newline at end of file diff --git a/test/cases/export-only-locals/index.js b/test/cases/export-only-locals/index.js new file mode 100644 index 00000000..60873693 --- /dev/null +++ b/test/cases/export-only-locals/index.js @@ -0,0 +1,4 @@ +import { aClass, bClass, cClass } from "./style.css"; + +// eslint-disable-next-line no-console +console.log({ aClass, bClass, cClass }); diff --git a/test/cases/export-only-locals/style.css b/test/cases/export-only-locals/style.css new file mode 100644 index 00000000..a9085408 --- /dev/null +++ b/test/cases/export-only-locals/style.css @@ -0,0 +1,11 @@ +.a-class { + background: red; +} + +.b__class { + color: green; +} + +.cClass { + color: blue; +} diff --git a/test/cases/export-only-locals/webpack.config.js b/test/cases/export-only-locals/webpack.config.js new file mode 100644 index 00000000..0a8dcf63 --- /dev/null +++ b/test/cases/export-only-locals/webpack.config.js @@ -0,0 +1,31 @@ +import Self from "../../../src"; + +module.exports = { + entry: "./index.js", + module: { + rules: [ + { + test: /\.css$/, + use: [ + { + loader: Self.loader, + }, + { + loader: "css-loader", + options: { + modules: { + localIdentName: "foo__[name]__[local]", + exportOnlyLocals: true, + }, + }, + }, + ], + }, + ], + }, + plugins: [ + new Self({ + filename: "[name].css", + }), + ], +};