Skip to content
This repository was archived by the owner on Aug 4, 2021. It is now read-only.

Commit f3c8320

Browse files
bterlsonlukastaegert
authored andcommittedJun 25, 2019
Fix path fragment inputs (#229)
When resolving an import name that doesn't look like a relative or absolute path, first attempt to resolve the corresponding relative path before resolving the original import name.
1 parent b8ff12f commit f3c8320

File tree

4 files changed

+84
-18
lines changed

4 files changed

+84
-18
lines changed
 

‎src/index.js

+51-18
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,32 @@ const alwaysNull = () => null;
7777

7878
const resolveIdAsync = (file, opts) => new Promise((fulfil, reject) => resolveId(file, opts, (err, contents) => err ? reject(err) : fulfil(contents)));
7979

80+
// Resolve module specifiers in order. Promise resolves to the first
81+
// module that resolves successfully, or the error that resulted from
82+
// the last attempted module resolution.
83+
function resolveImportSpecifiers (importSpecifierList, resolveOptions) {
84+
let p = Promise.resolve();
85+
for (let i = 0; i < importSpecifierList.length; i++) {
86+
p = p.then(v => {
87+
// if we've already resolved to something, just return it.
88+
if (v) return v;
89+
90+
return resolveIdAsync(importSpecifierList[i], resolveOptions);
91+
});
92+
93+
if (i < importSpecifierList.length - 1) {
94+
// swallow MODULE_NOT_FOUND errors from all but the last resolution
95+
p = p.catch(err => {
96+
if (err.code !== 'MODULE_NOT_FOUND') {
97+
throw err;
98+
}
99+
});
100+
}
101+
}
102+
103+
return p;
104+
}
105+
80106
export default function nodeResolve ( options = {} ) {
81107
const mainFields = getMainFields(options);
82108
const useBrowserOverrides = mainFields.indexOf('browser') !== -1;
@@ -238,29 +264,36 @@ export default function nodeResolve ( options = {} ) {
238264
resolveOptions.preserveSymlinks = preserveSymlinks;
239265
}
240266

267+
const importSpecifierList = [];
268+
269+
if (importer === undefined && !importee[0].match(/^\.?\.?\//)) {
270+
// For module graph roots (i.e. when importer is undefined), we
271+
// need to handle 'path fragments` like `foo/bar` that are commonly
272+
// found in rollup config files. If importee doesn't look like a
273+
// relative or absolute path, we make it relative and attempt to
274+
// resolve it. If we don't find anything, we try resolving it as we
275+
// got it.
276+
importSpecifierList.push('./' + importee);
277+
}
278+
241279
const importeeIsBuiltin = builtins.has(importee);
242-
const forceLocalLookup = importeeIsBuiltin && (!preferBuiltins || !isPreferBuiltinsSet);
243-
let importSpecifier = importee;
244280

245-
if (forceLocalLookup) {
246-
// need to attempt to look up a local module
247-
importSpecifier += '/';
281+
if (importeeIsBuiltin && (!preferBuiltins || !isPreferBuiltinsSet)) {
282+
// The `resolve` library will not resolve packages with the same
283+
// name as a node built-in module. If we're resolving something
284+
// that's a builtin, and we don't prefer to find built-ins, we
285+
// first try to look up a local module with that name. If we don't
286+
// find anything, we resolve the builtin which just returns back
287+
// the built-in's name.
288+
importSpecifierList.push(importee + '/');
248289
}
249290

250-
return resolveIdAsync(
251-
importSpecifier,
252-
Object.assign( resolveOptions, customResolveOptions )
253-
)
254-
.catch(err => {
255-
if (forceLocalLookup && err.code === 'MODULE_NOT_FOUND') {
256-
// didn't find a local module, so fall back to the importee
257-
// (i.e. the builtin's name)
258-
return importee;
259-
}
291+
importSpecifierList.push(importee);
260292

261-
// some other error, just forward it
262-
throw err;
263-
})
293+
return resolveImportSpecifiers(
294+
importSpecifierList,
295+
Object.assign(resolveOptions, customResolveOptions)
296+
)
264297
.then(resolved => {
265298
if ( resolved && packageBrowserField ) {
266299
if ( Object.prototype.hasOwnProperty.call(packageBrowserField,resolved) ) {

‎test/package.json

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "test",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "test.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"keywords": [],
10+
"author": "",
11+
"license": "ISC",
12+
"browser": {
13+
"dummy-module": "component-type"
14+
}
15+
}

‎test/samples/browser-local/main.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// test browser mapped imports from the main entrypoint
2+
import s from 'dummy-module';
3+
4+
export default s;

‎test/test.js

+14
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,20 @@ describe( 'rollup-plugin-node-resolve', function () {
337337
});
338338
});
339339

340+
it('respects local browser field', function () {
341+
return rollup.rollup({
342+
input: 'samples/browser-local/main.js',
343+
onwarn: expectNoWarnings,
344+
plugins: [
345+
nodeResolve({
346+
mainFields: ['browser', 'main']
347+
})
348+
]
349+
}).then(executeBundle).then(module => {
350+
assert.equal(module.exports, 'component-type');
351+
});
352+
});
353+
340354
it( 'warns when importing builtins', function () {
341355
return rollup.rollup({
342356
input: 'samples/builtins/main.js',

0 commit comments

Comments
 (0)
This repository has been archived.