Skip to content

Commit 1459cf0

Browse files
authored
fix(node-resolve): do not ignore exceptions (#564)
* do not ignore errors * do not error when import specifier does not map to file * always swallow MODULE_NOT_FOUND errors as not being able to resolve the id is a valid output * return null from resolveId early if can't resolve * strip null byte from importer if there is one * fix root-dir test this was passing before because the real error was being ignored * remove try/catch * use async exists() and realpath() like we do in index.js * pretend importer is `undefined` if it starts will \0 * return null if file not found with modulesOnly option
1 parent 5d292b5 commit 1459cf0

File tree

3 files changed

+63
-62
lines changed

3 files changed

+63
-62
lines changed

packages/node-resolve/src/index.js

+47-44
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ export function nodeResolve(opts = {}) {
100100
// ignore IDs with null character, these belong to other plugins
101101
if (/\0/.test(importee)) return null;
102102

103+
if (/\0/.test(importer)) {
104+
importer = undefined;
105+
}
106+
103107
// strip query params from import
104108
const [importPath, params] = importee.split('?');
105109
const importSuffix = `${params ? `?${params}` : ''}`;
@@ -218,62 +222,61 @@ export function nodeResolve(opts = {}) {
218222
importSpecifierList.push(importee);
219223
resolveOptions = Object.assign(resolveOptions, customResolveOptions);
220224

221-
try {
222-
let resolved = await resolveImportSpecifiers(importSpecifierList, resolveOptions);
225+
let resolved = await resolveImportSpecifiers(importSpecifierList, resolveOptions);
226+
if (!resolved) {
227+
return null;
228+
}
223229

224-
if (resolved && packageBrowserField) {
225-
if (Object.prototype.hasOwnProperty.call(packageBrowserField, resolved)) {
226-
if (!packageBrowserField[resolved]) {
227-
browserMapCache.set(resolved, packageBrowserField);
228-
return ES6_BROWSER_EMPTY;
229-
}
230-
resolved = packageBrowserField[resolved];
230+
if (packageBrowserField) {
231+
if (Object.prototype.hasOwnProperty.call(packageBrowserField, resolved)) {
232+
if (!packageBrowserField[resolved]) {
233+
browserMapCache.set(resolved, packageBrowserField);
234+
return ES6_BROWSER_EMPTY;
231235
}
232-
browserMapCache.set(resolved, packageBrowserField);
236+
resolved = packageBrowserField[resolved];
233237
}
238+
browserMapCache.set(resolved, packageBrowserField);
239+
}
234240

235-
if (hasPackageEntry && !preserveSymlinks && resolved) {
236-
const fileExists = await exists(resolved);
237-
if (fileExists) {
238-
resolved = await realpath(resolved);
239-
}
241+
if (hasPackageEntry && !preserveSymlinks) {
242+
const fileExists = await exists(resolved);
243+
if (fileExists) {
244+
resolved = await realpath(resolved);
240245
}
246+
}
241247

242-
idToPackageInfo.set(resolved, packageInfo);
243-
244-
if (hasPackageEntry) {
245-
if (builtins.has(resolved) && preferBuiltins && isPreferBuiltinsSet) {
246-
return null;
247-
} else if (importeeIsBuiltin && preferBuiltins) {
248-
if (!isPreferBuiltinsSet) {
249-
this.warn(
250-
`preferring built-in module '${importee}' over local alternative at '${resolved}', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning`
251-
);
252-
}
253-
return null;
254-
} else if (jail && resolved.indexOf(normalize(jail.trim(sep))) !== 0) {
255-
return null;
256-
}
257-
}
248+
idToPackageInfo.set(resolved, packageInfo);
258249

259-
if (resolved && options.modulesOnly) {
260-
const code = await readFile(resolved, 'utf-8');
261-
if (isModule(code)) {
262-
return {
263-
id: `${resolved}${importSuffix}`,
264-
moduleSideEffects: hasModuleSideEffects(resolved)
265-
};
250+
if (hasPackageEntry) {
251+
if (builtins.has(resolved) && preferBuiltins && isPreferBuiltinsSet) {
252+
return null;
253+
} else if (importeeIsBuiltin && preferBuiltins) {
254+
if (!isPreferBuiltinsSet) {
255+
this.warn(
256+
`preferring built-in module '${importee}' over local alternative at '${resolved}', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning`
257+
);
266258
}
267259
return null;
260+
} else if (jail && resolved.indexOf(normalize(jail.trim(sep))) !== 0) {
261+
return null;
262+
}
263+
}
264+
265+
if (options.modulesOnly && (await exists(resolved))) {
266+
const code = await readFile(resolved, 'utf-8');
267+
if (isModule(code)) {
268+
return {
269+
id: `${resolved}${importSuffix}`,
270+
moduleSideEffects: hasModuleSideEffects(resolved)
271+
};
268272
}
269-
const result = {
270-
id: `${resolved}${importSuffix}`,
271-
moduleSideEffects: hasModuleSideEffects(resolved)
272-
};
273-
return result;
274-
} catch (error) {
275273
return null;
276274
}
275+
const result = {
276+
id: `${resolved}${importSuffix}`,
277+
moduleSideEffects: hasModuleSideEffects(resolved)
278+
};
279+
return result;
277280
},
278281

279282
load(importee) {

packages/node-resolve/src/util.js

+15-15
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { createFilter } from '@rollup/pluginutils';
55

66
import resolveModule from 'resolve';
77

8-
import { realpathSync } from './fs';
8+
import { exists, realpath, realpathSync } from './fs';
99

1010
const resolveId = promisify(resolveModule);
1111

@@ -165,28 +165,28 @@ export function resolveImportSpecifiers(importSpecifierList, resolveOptions) {
165165
let promise = Promise.resolve();
166166

167167
for (let i = 0; i < importSpecifierList.length; i++) {
168-
promise = promise.then((value) => {
168+
// eslint-disable-next-line no-loop-func
169+
promise = promise.then(async (value) => {
169170
// if we've already resolved to something, just return it.
170171
if (value) {
171172
return value;
172173
}
173174

174-
return resolveId(importSpecifierList[i], resolveOptions).then((result) => {
175-
if (!resolveOptions.preserveSymlinks) {
176-
result = realpathSync(result);
175+
let result = await resolveId(importSpecifierList[i], resolveOptions);
176+
if (!resolveOptions.preserveSymlinks) {
177+
if (await exists(result)) {
178+
result = await realpath(result);
177179
}
178-
return result;
179-
});
180+
}
181+
return result;
180182
});
181183

182-
if (i < importSpecifierList.length - 1) {
183-
// swallow MODULE_NOT_FOUND errors from all but the last resolution
184-
promise = promise.catch((error) => {
185-
if (error.code !== 'MODULE_NOT_FOUND') {
186-
throw error;
187-
}
188-
});
189-
}
184+
// swallow MODULE_NOT_FOUND errors
185+
promise = promise.catch((error) => {
186+
if (error.code !== 'MODULE_NOT_FOUND') {
187+
throw error;
188+
}
189+
});
190190
}
191191

192192
return promise;

packages/node-resolve/test/root-dir.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ const { testBundle } = require('../../../util/test');
77

88
const { nodeResolve } = require('..');
99

10-
process.chdir(join(__dirname, 'fixtures', 'monorepo-dedupe', 'packages', 'package-a'));
11-
1210
test('deduplicates modules from the given root directory', async (t) => {
1311
const bundle = await rollup({
14-
input: 'index.js',
12+
input: './packages/package-a/index.js',
1513
plugins: [
1614
nodeResolve({
1715
dedupe: ['react'],

0 commit comments

Comments
 (0)