Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/registry/domain/require-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ const requireCoreDependency = (x: string) =>
const requireDependency = (requirePath: string) => {
const nodeModulesPath = path.resolve('.', 'node_modules');
const modulePath = path.resolve(nodeModulesPath, requirePath);
return tryRequire(modulePath);
// ESM only modules might not define a "main" field and therefore the absolute path of modulePath will not work
return tryRequire(modulePath) || tryRequire(requirePath);
};

const throwError = (requirePath: string) => {
Expand All @@ -34,8 +35,8 @@ export default (injectedDependencies: string[]) =>
}

return (
requireDependency(requirePath) ||
requireCoreDependency(requirePath) ||
requireDependency(requirePath) ||
throwError(requirePath)
);
};
87 changes: 87 additions & 0 deletions test/unit/registry-domain-require-wrapper.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const expect = require('chai').expect;
const injectr = require('injectr');
const sinon = require('sinon');
const vm = require('node:vm');

describe('registry : domain : require-wrapper', () => {
Expand Down Expand Up @@ -58,6 +60,17 @@ describe('registry : domain : require-wrapper', () => {
});
});

describe('when requiring a core dependency with node: prefix', () => {
before(() => {
const script = `var path = require('node:path'); result = path.join('a', 'b');`;
execute(['node:path'], script);
});

it('should correctly require and use the dependency', () => {
expect(result).to.equal('a/b');
});
});

describe('when requiring an unvetted core dependency', () => {
before(() => {
const script = `var url = require('url'); result = url.parse('www.google.com').href;`;
Expand Down Expand Up @@ -96,5 +109,79 @@ describe('registry : domain : require-wrapper', () => {
});
});
});

describe('when try-require fails with absolute path but succeeds with package name', () => {
let tryRequireStub;

before(() => {
tryRequireStub = sinon.stub();
tryRequireStub.onCall(0).returns(undefined);
tryRequireStub.onCall(1).returns({ esmFallback: true });

const InjectedRequireWrapper = injectr(
'../../dist/registry/domain/require-wrapper.js',
{
'try-require': tryRequireStub
}
).default;

const context = {
require: InjectedRequireWrapper(['esm-only-module']),
result: null,
console
};
try {
vm.runInNewContext(
`var m = require('esm-only-module'); result = m.esmFallback;`,
context
);
result = context.result;
} catch (e) {
error = e;
}
});

it('should fall back to requiring by package name', () => {
expect(result).to.be.true;
});
});

describe('when a core module and npm package share the same name', () => {
let tryRequireStub;

before(() => {
tryRequireStub = sinon.stub();
tryRequireStub
.withArgs(sinon.match(/node_modules/))
.returns({ isNpmPackage: true });
tryRequireStub.withArgs('url').returns({ isCoreModule: true });

const InjectedRequireWrapper = injectr(
'../../dist/registry/domain/require-wrapper.js',
{
'try-require': tryRequireStub
}
).default;

const context = {
require: InjectedRequireWrapper(['url']),
result: null,
console
};
try {
vm.runInNewContext(
`var m = require('url'); result = m.isCoreModule;`,
context
);
result = context.result;
} catch (e) {
error = e;
}
});

it('should prefer the core module', () => {
expect(result).to.be.true;
});
});
});
});
Loading