Skip to content

Commit

Permalink
Merge pull request #25540 from mlazari/next
Browse files Browse the repository at this point in the history
Webpack5: Make export-order-loader compatible with both esm and cjs
  • Loading branch information
valentinpalkovic authored Jan 16, 2024
2 parents 99cb295 + c003796 commit dfb08da
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 21 deletions.
1 change: 1 addition & 0 deletions code/builders/builder-webpack5/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"@types/semver": "^7.3.4",
"browser-assert": "^1.2.1",
"case-sensitive-paths-webpack-plugin": "^2.4.0",
"cjs-module-lexer": "^1.2.3",
"constants-browserify": "^1.0.0",
"css-loader": "^6.7.1",
"es-module-lexer": "^1.4.1",
Expand Down
66 changes: 45 additions & 21 deletions code/builders/builder-webpack5/src/loaders/export-order-loader.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,58 @@
import { parse } from 'es-module-lexer';
import assert from 'assert';
import { parse as parseCjs, init as initCjsParser } from 'cjs-module-lexer';
import { parse as parseEs } from 'es-module-lexer';
import MagicString from 'magic-string';
import type { LoaderContext } from 'webpack';

export default async function loader(this: LoaderContext<any>, source: string) {
export default async function loader(
this: LoaderContext<any>,
source: string,
map: any,
meta: any
) {
const callback = this.async();

try {
// Do NOT remove await here. The types are wrong! It has to be awaited,
// otherwise it will return a Promise<Promise<...>> when wasm isn't loaded.
const [, exports = []] = await parse(source);
const magicString = new MagicString(source);

// Trying to parse as ES module
try {
// Do NOT remove await here. The types are wrong! It has to be awaited,
// otherwise it will return a Promise<Promise<...>> when wasm isn't loaded.
const parseResult = await parseEs(source);
const namedExportsOrder = (parseResult[1] || [])
.map((e) => source.substring(e.s, e.e))
.filter((e) => e !== 'default');

assert(
namedExportsOrder.length > 0,
'No named exports found. Very likely that this is not a ES module.'
);

const namedExportsOrder = exports.some(
(e) => source.substring(e.s, e.e) === '__namedExportsOrder'
);
magicString.append(
`;export const __namedExportsOrder = ${JSON.stringify(namedExportsOrder)};`
);
// Try to parse as CJS module
} catch {
await initCjsParser();
const namedExportsOrder = (parseCjs(source).exports || []).filter(
(e: string) => e !== 'default' && e !== '__esModule'
);

if (namedExportsOrder) {
return callback(null, source);
assert(
namedExportsOrder.length > 0,
'No named exports found. Very likely that this is not a CJS module.'
);

magicString.append(
`;module.exports.__namedExportsOrder = ${JSON.stringify(namedExportsOrder)};`
);
}

const magicString = new MagicString(source);
const orderedExports = exports.filter((e) => source.substring(e.s, e.e) !== 'default');
magicString.append(
`;export const __namedExportsOrder = ${JSON.stringify(
orderedExports.map((e) => source.substring(e.s, e.e))
)};`
);

const map = magicString.generateMap({ hires: true });
return callback(null, magicString.toString(), map);
const generatedMap = magicString.generateMap({ hires: true });

return callback(null, magicString.toString(), generatedMap, meta);
} catch (err) {
return callback(err as any);
return callback(null, source, map, meta);
}
}
8 changes: 8 additions & 0 deletions code/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5367,6 +5367,7 @@ __metadata:
"@types/webpack-virtual-modules": "npm:^0.1.1"
browser-assert: "npm:^1.2.1"
case-sensitive-paths-webpack-plugin: "npm:^2.4.0"
cjs-module-lexer: "npm:^1.2.3"
constants-browserify: "npm:^1.0.0"
css-loader: "npm:^6.7.1"
es-module-lexer: "npm:^1.4.1"
Expand Down Expand Up @@ -11409,6 +11410,13 @@ __metadata:
languageName: node
linkType: hard

"cjs-module-lexer@npm:^1.2.3":
version: 1.2.3
resolution: "cjs-module-lexer@npm:1.2.3"
checksum: 0de9a9c3fad03a46804c0d38e7b712fb282584a9c7ef1ed44cae22fb71d9bb600309d66a9711ac36a596fd03422f5bb03e021e8f369c12a39fa1786ae531baab
languageName: node
linkType: hard

"class-utils@npm:^0.3.5":
version: 0.3.6
resolution: "class-utils@npm:0.3.6"
Expand Down

0 comments on commit dfb08da

Please sign in to comment.