Skip to content

Commit 6856bd9

Browse files
luxaritastrentmrochdev
authored
Fix node 20 reexports (#30)
Resolves #29 --------- Co-authored-by: Trent Mick <[email protected]> Co-authored-by: rochdev <[email protected]>
1 parent e29c02d commit 6856bd9

7 files changed

Lines changed: 102 additions & 3 deletions

File tree

.eslintrc.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,8 @@ rules:
1616

1717
extends:
1818
- "standard"
19+
20+
ignorePatterns:
21+
- test/fixtures/circular-a.js
22+
- test/fixtures/circular-b.js
23+
- test/fixtures/reexport.js

lib/get-exports.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,36 @@
33
const getEsmExports = require('./get-esm-exports.js')
44
const { parse: getCjsExports } = require('cjs-module-lexer')
55
const fs = require('fs')
6-
const { fileURLToPath } = require('url')
6+
const { fileURLToPath, pathToFileURL } = require('url')
77

88
function addDefault (arr) {
99
return Array.from(new Set(['default', ...arr]))
1010
}
1111

12+
const urlsBeingProcessed = new Set() // Guard against circular imports.
13+
14+
async function getFullCjsExports (url, context, parentLoad, source) {
15+
if (urlsBeingProcessed.has(url)) {
16+
return []
17+
}
18+
urlsBeingProcessed.add(url)
19+
20+
const ex = getCjsExports(source)
21+
const full = Array.from(new Set([
22+
...addDefault(ex.exports),
23+
...(await Promise.all(ex.reexports.map(re => getExports(({
24+
url: (/^(..?($|\/|\\))/).test(re)
25+
? pathToFileURL(require.resolve(fileURLToPath(new URL(re, url)))).toString()
26+
: pathToFileURL(require.resolve(re)).toString(),
27+
context,
28+
parentLoad
29+
}))))).flat()
30+
]))
31+
32+
urlsBeingProcessed.delete(url)
33+
return full
34+
}
35+
1236
/**
1337
* Inspects a module for its type (commonjs or module), attempts to get the
1438
* source code for said module from the loader API, and parses the result
@@ -56,7 +80,7 @@ async function getExports ({ url, context, parentLoad, defaultAs = 'default' })
5680
return getEsmExports({ moduleSource: source, defaultAs })
5781
}
5882
if (format === 'commonjs') {
59-
return addDefault(getCjsExports(source).exports)
83+
return getFullCjsExports(url, context, parentLoad, source)
6084
}
6185

6286
// At this point our `format` is either undefined or not known by us. Fall
@@ -67,7 +91,7 @@ async function getExports ({ url, context, parentLoad, defaultAs = 'default' })
6791
// isn't set at first and yet we have an ESM module with no exports.
6892
// I couldn't construct an example that would do this, so maybe it's
6993
// impossible?
70-
return addDefault(getCjsExports(source).exports)
94+
return getFullCjsExports(url, context, parentLoad, source)
7195
}
7296
}
7397

test/fixtures/circular-a.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// The following is generated by tslib. __exportStar is a format which cjs-module-lexer exposes as a reexport
2+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3+
if (k2 === undefined) k2 = k;
4+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5+
}) : (function(o, m, k, k2) {
6+
if (k2 === undefined) k2 = k;
7+
o[k2] = m[k];
8+
}));
9+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
10+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11+
};
12+
Object.defineProperty(exports, "__esModule", { value: true });
13+
14+
15+
__exportStar(require("./circular-b"), exports);
16+
17+
exports.foo = 42;
18+

test/fixtures/circular-b.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// The following is generated by tslib. __exportStar is a format which cjs-module-lexer exposes as a reexport
2+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3+
if (k2 === undefined) k2 = k;
4+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5+
}) : (function(o, m, k, k2) {
6+
if (k2 === undefined) k2 = k;
7+
o[k2] = m[k];
8+
}));
9+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
10+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11+
};
12+
Object.defineProperty(exports, "__esModule", { value: true });
13+
14+
__exportStar(require("./circular-a"), exports);
15+

test/fixtures/reexport.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// The following is generated by tslib. __exportStar is a format which cjs-module-lexer exposes as a reexport
2+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3+
if (k2 === undefined) k2 = k;
4+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5+
}) : (function(o, m, k, k2) {
6+
if (k2 === undefined) k2 = k;
7+
o[k2] = m[k];
8+
}));
9+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
10+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11+
};
12+
Object.defineProperty(exports, "__esModule", { value: true });
13+
14+
__exportStar(require("./something"), exports);
15+

test/hook/circular-imports.mjs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { foo } from '../fixtures/circular-b.js'
2+
import Hook from '../../index.js'
3+
import { strictEqual } from 'assert'
4+
5+
Hook((exports, name) => {
6+
if (name.match(/circular-[ab].js/)) {
7+
exports.foo += 15
8+
}
9+
})
10+
11+
strictEqual(foo, 57)

test/hook/import-reexport-cjs.mjs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { foo } from '../fixtures/reexport.js'
2+
import Hook from '../../index.js'
3+
import { strictEqual } from 'assert'
4+
5+
Hook((exports, name) => {
6+
if (name.match(/reexport.js/)) {
7+
exports.foo += 15
8+
}
9+
})
10+
11+
strictEqual(foo, 57)

0 commit comments

Comments
 (0)