Skip to content

Commit

Permalink
Fix node 20 reexports (#30)
Browse files Browse the repository at this point in the history
Resolves #29

---------

Co-authored-by: Trent Mick <[email protected]>
Co-authored-by: rochdev <[email protected]>
  • Loading branch information
3 people authored Jan 17, 2024
1 parent e29c02d commit 6856bd9
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .eslintrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ rules:

extends:
- "standard"

ignorePatterns:
- test/fixtures/circular-a.js
- test/fixtures/circular-b.js
- test/fixtures/reexport.js
30 changes: 27 additions & 3 deletions lib/get-exports.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,36 @@
const getEsmExports = require('./get-esm-exports.js')
const { parse: getCjsExports } = require('cjs-module-lexer')
const fs = require('fs')
const { fileURLToPath } = require('url')
const { fileURLToPath, pathToFileURL } = require('url')

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

const urlsBeingProcessed = new Set() // Guard against circular imports.

async function getFullCjsExports (url, context, parentLoad, source) {
if (urlsBeingProcessed.has(url)) {
return []
}
urlsBeingProcessed.add(url)

const ex = getCjsExports(source)
const full = Array.from(new Set([
...addDefault(ex.exports),
...(await Promise.all(ex.reexports.map(re => getExports(({
url: (/^(..?($|\/|\\))/).test(re)
? pathToFileURL(require.resolve(fileURLToPath(new URL(re, url)))).toString()
: pathToFileURL(require.resolve(re)).toString(),
context,
parentLoad
}))))).flat()
]))

urlsBeingProcessed.delete(url)
return full
}

/**
* Inspects a module for its type (commonjs or module), attempts to get the
* source code for said module from the loader API, and parses the result
Expand Down Expand Up @@ -56,7 +80,7 @@ async function getExports ({ url, context, parentLoad, defaultAs = 'default' })
return getEsmExports({ moduleSource: source, defaultAs })
}
if (format === 'commonjs') {
return addDefault(getCjsExports(source).exports)
return getFullCjsExports(url, context, parentLoad, source)
}

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

Expand Down
18 changes: 18 additions & 0 deletions test/fixtures/circular-a.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// The following is generated by tslib. __exportStar is a format which cjs-module-lexer exposes as a reexport
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });


__exportStar(require("./circular-b"), exports);

exports.foo = 42;

15 changes: 15 additions & 0 deletions test/fixtures/circular-b.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// The following is generated by tslib. __exportStar is a format which cjs-module-lexer exposes as a reexport
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });

__exportStar(require("./circular-a"), exports);

15 changes: 15 additions & 0 deletions test/fixtures/reexport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// The following is generated by tslib. __exportStar is a format which cjs-module-lexer exposes as a reexport
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });

__exportStar(require("./something"), exports);

11 changes: 11 additions & 0 deletions test/hook/circular-imports.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { foo } from '../fixtures/circular-b.js'
import Hook from '../../index.js'
import { strictEqual } from 'assert'

Hook((exports, name) => {
if (name.match(/circular-[ab].js/)) {
exports.foo += 15
}
})

strictEqual(foo, 57)
11 changes: 11 additions & 0 deletions test/hook/import-reexport-cjs.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { foo } from '../fixtures/reexport.js'
import Hook from '../../index.js'
import { strictEqual } from 'assert'

Hook((exports, name) => {
if (name.match(/reexport.js/)) {
exports.foo += 15
}
})

strictEqual(foo, 57)

0 comments on commit 6856bd9

Please sign in to comment.