Skip to content

Commit

Permalink
fix(esm-shim): pattern matching (#1560)
Browse files Browse the repository at this point in the history
* fix(esm-shim): correctly find where to place shim in file

* test(esm-shim): add test cases for files with esm imports

* test(esm-shim): use correct snapshots after linting change

* test(esm-shim): use correct snapshots for testing
  • Loading branch information
klevente authored Aug 26, 2023
1 parent d35d007 commit 0f73e2a
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 14 deletions.
30 changes: 16 additions & 14 deletions packages/esm-shim/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,35 @@ function matchAllPolyfill(input: string, pattern: string | RegExp): RegExpMatchA
return [];
}

let idx = 0;
for (let i = 0; i < result.length; i++) {
output.push(result[i].match(new RegExp(pattern)) || []);
const match: RegExpMatchArray = [result[i]];
match.index = idx;
idx += result[i].length;
output.push(match);
}
return output;
}

export function matchAll(regex: RegExp, input: string, addition: Record<string, any>) {
const matches = [];
for (const match of matchAllPolyfill(input, regex)) {
matches.push({
...addition,
...match.groups,
code: match[0],
start: match.index,
end: (match.index || 0) + match[0].length
});
function findPositionToInsertShim(input: string, pattern: RegExp) {
let lastImport;
// mimicking behavior of `String.matchAll` as it returns an iterator, not an array
for (const match of matchAllPolyfill(input, pattern)) {
lastImport = match;
}
return matches;
if (!lastImport) {
return 0;
}

return (lastImport.index || 0) + lastImport[0].length;
}

export function provideCJSSyntax(code: string): Output | null {
if (code.includes(ESMShim) || !CJSyntaxRegex.test(code)) {
return null;
}

const lastESMImport = matchAll(ESMStaticImportRegex, code, { type: 'static' }).pop();
const indexToAppend = lastESMImport ? lastESMImport.end : 0;
const indexToAppend = findPositionToInsertShim(code, ESMStaticImportRegex);
const s = new MagicString(code);
s.appendRight(indexToAppend, ESMShim);

Expand Down
10 changes: 10 additions & 0 deletions packages/esm-shim/test/fixtures/cjs-multiple-imports.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { constants } from 'node:crypto';

import MagicString from 'magic-string';

const child = require('child');

const s = new MagicString('');
const c = constants.SEP;

export { child, s, c };
7 changes: 7 additions & 0 deletions packages/esm-shim/test/fixtures/cjs-single-import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import MagicString from 'magic-string';

const child = require('child');

const s = new MagicString('');

export { child, s };
44 changes: 44 additions & 0 deletions packages/esm-shim/test/snapshots/test.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,47 @@ Generated by [AVA](https://avajs.dev).
␊
exports.child = child;␊
`

## inject cjs shim for esm output with a single import statement

> Snapshot 1
`import MagicString from 'magic-string';␊
␊
␊
// -- Shims --␊
import cjsUrl from 'url';␊
import cjsPath from 'path';␊
import cjsModule from 'module';␊
const __filename = cjsUrl.fileURLToPath(import.meta.url);␊
const __dirname = cjsPath.dirname(__filename);␊
const require = cjsModule.createRequire(import.meta.url);␊
const child = require('child');␊
␊
const s = new MagicString('');␊
␊
export { child, s };␊
`

## inject cjs shim for esm output with multiple import statements

> Snapshot 1
`import { constants } from 'node:crypto';␊
import MagicString from 'magic-string';␊
␊
␊
// -- Shims --␊
import cjsUrl from 'url';␊
import cjsPath from 'path';␊
import cjsModule from 'module';␊
const __filename = cjsUrl.fileURLToPath(import.meta.url);␊
const __dirname = cjsPath.dirname(__filename);␊
const require = cjsModule.createRequire(import.meta.url);␊
const child = require('child');␊
␊
const s = new MagicString('');␊
const c = constants.SEP;␊
␊
export { c, child, s };␊
`
Binary file modified packages/esm-shim/test/snapshots/test.js.snap
Binary file not shown.
26 changes: 26 additions & 0 deletions packages/esm-shim/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,29 @@ test.serial('not inject cjs shim for cjs output', async (t) => {
t.snapshot(output.code);
t.falsy(output.map);
});

test.serial('inject cjs shim for esm output with a single import statement', async (t) => {
const bundle = await rollup({
input: 'test/fixtures/cjs-single-import.js',
plugins: [esmShim()],
external: ['magic-string']
});
const result = await bundle.generate({ format: 'es' });
t.is(result.output.length, 1);
const [output] = result.output;
t.snapshot(output.code);
t.falsy(output.map);
});

test.serial('inject cjs shim for esm output with multiple import statements', async (t) => {
const bundle = await rollup({
input: 'test/fixtures/cjs-multiple-imports.js',
plugins: [esmShim()],
external: ['magic-string', 'node:crypto']
});
const result = await bundle.generate({ format: 'es' });
t.is(result.output.length, 1);
const [output] = result.output;
t.snapshot(output.code);
t.falsy(output.map);
});

0 comments on commit 0f73e2a

Please sign in to comment.