Fail loud when module is not resolved correctly

Summary: @​public
We've been forgiving unresolved modules errors in the past but we've realized that doing so makes the codebase a bit unstable as people don't make sure to fix these errors. From now on we'll early fail and stop the packager when any module cannot be resolved (including assets)

Reviewed By: @amasad

Differential Revision: D2518076

fb-gh-sync-id: e170d95b905cc29afbe46e24b65425ddd887f77c
This commit is contained in:
Martín Bigio 2015-10-13 10:38:23 -07:00 committed by facebook-github-bot-9
parent 44429dc4f4
commit 0a6c851613
2 changed files with 57 additions and 24 deletions

View File

@ -65,7 +65,8 @@ class ResolutionRequest {
};
const forgive = (error) => {
if (error.type !== 'UnableToResolveError') {
if (error.type !== 'UnableToResolveError' ||
this._platform === 'ios') {
throw error;
}
@ -92,7 +93,7 @@ class ResolutionRequest {
return this._resolveNodeDependency(fromModule, toModuleName)
.then(
cacheResult,
forgive
forgive,
);
}
@ -193,12 +194,20 @@ class ResolutionRequest {
path.relative(packageName, realModuleName)
);
return this._tryResolve(
() => this._loadAsFile(potentialModulePath),
() => this._loadAsDir(potentialModulePath),
() => this._loadAsFile(
potentialModulePath,
fromModule,
toModuleName,
),
() => this._loadAsDir(potentialModulePath, fromModule, toModuleName),
);
}
throw new UnableToResolveError('Unable to resolve dependency');
throw new UnableToResolveError(
fromModule,
toModuleName,
'Unable to resolve dependency',
);
});
}
@ -218,8 +227,8 @@ class ResolutionRequest {
path.join(path.dirname(fromModule.path), toModuleName);
return this._redirectRequire(fromModule, potentialModulePath).then(
realModuleName => this._tryResolve(
() => this._loadAsFile(realModuleName),
() => this._loadAsDir(realModuleName)
() => this._loadAsFile(realModuleName, fromModule, toModuleName),
() => this._loadAsDir(realModuleName, fromModule, toModuleName)
)
);
} else {
@ -234,14 +243,18 @@ class ResolutionRequest {
);
}
let p = Promise.reject(new UnableToResolveError('Node module not found'));
let p = Promise.reject(new UnableToResolveError(
fromModule,
toModuleName,
'Node module not found',
));
searchQueue.forEach(potentialModulePath => {
p = this._tryResolve(
() => this._tryResolve(
() => p,
() => this._loadAsFile(potentialModulePath),
() => this._loadAsFile(potentialModulePath, fromModule, toModuleName),
),
() => this._loadAsDir(potentialModulePath)
() => this._loadAsDir(potentialModulePath, fromModule, toModuleName)
);
});
@ -250,12 +263,16 @@ class ResolutionRequest {
}
}
_loadAsFile(potentialModulePath) {
_loadAsFile(potentialModulePath, fromModule, toModule) {
return Promise.resolve().then(() => {
if (this._helpers.isAssetFile(potentialModulePath)) {
const dirname = path.dirname(potentialModulePath);
if (!this._fastfs.dirExists(dirname)) {
throw new UnableToResolveError(`Directory ${dirname} doesn't exist`);
throw new UnableToResolveError(
fromModule,
toModule,
`Directory ${dirname} doesn't exist`,
);
}
const {name, type} = getAssetDataFromName(potentialModulePath);
@ -289,17 +306,25 @@ class ResolutionRequest {
} else if (this._fastfs.fileExists(potentialModulePath + '.json')) {
file = potentialModulePath + '.json';
} else {
throw new UnableToResolveError(`File ${potentialModulePath} doesnt exist`);
throw new UnableToResolveError(
fromModule,
toModule,
`File ${potentialModulePath} doesnt exist`,
);
}
return this._moduleCache.getModule(file);
});
}
_loadAsDir(potentialDirPath) {
_loadAsDir(potentialDirPath, fromModule, toModule) {
return Promise.resolve().then(() => {
if (!this._fastfs.dirExists(potentialDirPath)) {
throw new UnableToResolveError(`Invalid directory ${potentialDirPath}`);
throw new UnableToResolveError(
fromModule,
toModule,
`Invalid directory ${potentialDirPath}`,
);
}
const packageJsonPath = path.join(potentialDirPath, 'package.json');
@ -307,13 +332,17 @@ class ResolutionRequest {
return this._moduleCache.getPackage(packageJsonPath)
.getMain().then(
(main) => this._tryResolve(
() => this._loadAsFile(main),
() => this._loadAsDir(main)
() => this._loadAsFile(main, fromModule, toModule),
() => this._loadAsDir(main, fromModule, toModule)
)
);
}
return this._loadAsFile(path.join(potentialDirPath, 'index'));
return this._loadAsFile(
path.join(potentialDirPath, 'index'),
fromModule,
toModule,
);
});
}
@ -328,17 +357,20 @@ function resolutionHash(modulePath, depName) {
}
function UnableToResolveError() {
function UnableToResolveError(fromModule, toModule, message) {
Error.call(this);
Error.captureStackTrace(this, this.constructor);
var msg = util.format.apply(util, arguments);
this.message = msg;
this.message = util.format(
'Unable to resolve module %s from %s: %s',
toModule,
fromModule.path,
message,
);
this.type = this.name = 'UnableToResolveError';
}
util.inherits(UnableToResolveError, Error);
function normalizePath(modulePath) {
if (path.sep === '/') {
modulePath = path.normalize(modulePath);
@ -349,5 +381,4 @@ function normalizePath(modulePath) {
return modulePath.replace(/\/$/, '');
}
module.exports = ResolutionRequest;

View File

@ -388,7 +388,9 @@ class Server {
'Content-Type': 'application/json; charset=UTF-8',
});
if (error.type === 'TransformError' || error.type === 'NotFoundError') {
if (error.type === 'TransformError' ||
error.type === 'NotFoundError' ||
error.type === 'UnableToResolveError') {
error.errors = [{
description: error.description,
filename: error.filename,