Skip to content

Commit

Permalink
Port resolver unit tests (parcel-bundler#4995)
Browse files Browse the repository at this point in the history
* Port test

* Update failing tests

* Fix failing windows test
  • Loading branch information
mischnic authored Aug 10, 2020
1 parent 46e8ffa commit 76922b0
Show file tree
Hide file tree
Showing 64 changed files with 980 additions and 49 deletions.
3 changes: 2 additions & 1 deletion packages/resolvers/default/src/DefaultResolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ export default (new Resolver({
}

const resolver = new NodeResolver({
fs: options.inputFS,
projectRoot: options.projectRoot,
extensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'css', 'styl', 'vue'],
mainFields,
options,
});
return resolver.resolve({
filename: filePath,
Expand Down
1 change: 1 addition & 0 deletions packages/utils/node-resolver-core/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!/test/fixture/node_modules
102 changes: 54 additions & 48 deletions packages/utils/node-resolver-core/src/NodeResolver.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// @flow
import type {
PluginOptions,
PackageJSON,
FilePath,
PackageJSON,
PackageName,
ResolveResult,
Environment,
} from '@parcel/types';
import type {FileSystem} from '@parcel/fs';

import invariant from 'assert';
import path from 'path';
Expand All @@ -28,7 +28,8 @@ const EMPTY_SHIM = require.resolve('./_empty');

type InternalPackageJSON = PackageJSON & {pkgdir: string, pkgfile: string, ...};
type Options = {|
options: PluginOptions,
fs: FileSystem,
projectRoot: FilePath,
extensions: Array<string>,
mainFields: Array<string>,
|};
Expand All @@ -37,6 +38,16 @@ type ResolvedFile = {|
pkg: InternalPackageJSON | null,
|};

type Env = {
+includeNodeModules:
| boolean
| Array<PackageName>
| {[PackageName]: boolean, ...},
isBrowser(): boolean,
isNode(): boolean,
...
};

type Aliases =
| string
| {[string]: string, ...}
Expand All @@ -63,7 +74,8 @@ type Module = {|
* - The package.json alias field in the root package for global aliases across all modules.
*/
export default class NodeResolver {
options: PluginOptions;
fs: FileSystem;
projectRoot: FilePath;
extensions: Array<string>;
mainFields: Array<string>;
packageCache: Map<string, InternalPackageJSON>;
Expand All @@ -74,7 +86,8 @@ export default class NodeResolver {
ext.startsWith('.') ? ext : '.' + ext,
);
this.mainFields = opts.mainFields;
this.options = opts.options;
this.fs = opts.fs;
this.projectRoot = opts.projectRoot;
this.packageCache = new Map();
this.rootPackage = null;
}
Expand All @@ -88,7 +101,7 @@ export default class NodeResolver {
filename: FilePath,
parent: ?FilePath,
isURL: boolean,
env: Environment,
env: Env,
|}): Promise<?ResolveResult> {
// Get file extensions to search
let extensions = this.extensions.slice();
Expand Down Expand Up @@ -126,7 +139,7 @@ export default class NodeResolver {
module.filePath,
extensions,
env,
parent ? path.dirname(parent) : this.options.projectRoot,
parent ? path.dirname(parent) : this.projectRoot,
);
}

Expand Down Expand Up @@ -159,9 +172,9 @@ export default class NodeResolver {

try {
let modulesDir = path.join(dir, 'node_modules');
let stats = await this.options.inputFS.stat(modulesDir);
let stats = await this.fs.stat(modulesDir);
if (stats.isDirectory()) {
let dirContent = await this.options.inputFS.readdir(modulesDir);
let dirContent = await this.fs.readdir(modulesDir);

// Filter out the modules that interest us
let modules = dirContent.filter(i =>
Expand All @@ -173,9 +186,7 @@ export default class NodeResolver {
await Promise.all(
modules.map(async item => {
let orgDirPath = path.join(modulesDir, item);
let orgDirContent = await this.options.inputFS.readdir(
orgDirPath,
);
let orgDirContent = await this.fs.readdir(orgDirPath);

// Add all org packages
potentialModules.push(
Expand Down Expand Up @@ -209,13 +220,13 @@ export default class NodeResolver {
maxlength: number,
collected: Array<string>,
|}): Promise<mixed> {
let dirContent = await this.options.inputFS.readdir(dir);
let dirContent = await this.fs.readdir(dir);
return Promise.all(
dirContent.map(async item => {
let fullPath = path.join(dir, item);
let relativeFilePath = relativePath(basedir, fullPath);
if (relativeFilePath.length < maxlength) {
let stats = await this.options.inputFS.stat(fullPath);
let stats = await this.fs.stat(fullPath);
let isDir = stats.isDirectory();
if (isDir || stats.isFile()) {
collected.push(relativeFilePath);
Expand Down Expand Up @@ -268,9 +279,9 @@ export default class NodeResolver {
filename: string,
parent: ?FilePath,
isURL: boolean,
env: Environment,
env: Env,
|}): Promise<?Module> {
let dir = parent ? path.dirname(parent) : this.options.inputFS.cwd();
let dir = parent ? path.dirname(parent) : this.fs.cwd();

// If this isn't the entrypoint, resolve the input file to an absolute path
if (parent) {
Expand Down Expand Up @@ -372,10 +383,7 @@ export default class NodeResolver {
return resolved;
}

shouldIncludeNodeModule(
{includeNodeModules}: Environment,
name: string,
): boolean {
shouldIncludeNodeModule({includeNodeModules}: Env, name: string): boolean {
if (includeNodeModules === false) {
return false;
}
Expand Down Expand Up @@ -404,7 +412,7 @@ export default class NodeResolver {
switch (filename[0]) {
case '/': {
// Absolute path. Resolve relative to project root.
return path.resolve(this.options.projectRoot, filename.slice(1));
return path.resolve(this.projectRoot, filename.slice(1));
}

case '~': {
Expand All @@ -413,17 +421,15 @@ export default class NodeResolver {
const insideNodeModules = dir.includes('node_modules');

while (
dir !== this.options.projectRoot &&
dir !== this.projectRoot &&
path.basename(path.dirname(dir)) !== 'node_modules' &&
(insideNodeModules ||
!(await this.options.inputFS.exists(
path.join(dir, 'package.json'),
)))
!(await this.fs.exists(path.join(dir, 'package.json'))))
) {
dir = path.dirname(dir);

if (dir === path.dirname(dir)) {
dir = this.options.projectRoot;
dir = this.projectRoot;
break;
}
}
Expand All @@ -450,7 +456,7 @@ export default class NodeResolver {
async loadRelative(
filename: string,
extensions: Array<string>,
env: Environment,
env: Env,
parentdir: string,
): Promise<?ResolvedFile> {
// Find a package.json file in the current package.
Expand Down Expand Up @@ -482,7 +488,7 @@ export default class NodeResolver {
throw new ThrowableDiagnostic({
diagnostic: {
message: `Cannot load file '${relativeFileSpecifier}' in '${relativePath(
this.options.projectRoot,
this.projectRoot,
parentdir,
)}'.`,
hints: potentialFiles.map(r => {
Expand All @@ -495,7 +501,7 @@ export default class NodeResolver {
return resolvedFile;
}

findBuiltin(filename: string, env: Environment): ?Module {
findBuiltin(filename: string, env: Env): ?Module {
if (builtins[filename]) {
if (env.isNode()) {
return null;
Expand All @@ -518,7 +524,7 @@ export default class NodeResolver {
try {
// First, check if the module directory exists. This prevents a lot of unnecessary checks later.
let moduleDir = path.join(dir, 'node_modules', moduleName);
let stats = await this.options.inputFS.stat(moduleDir);
let stats = await this.fs.stat(moduleDir);
if (stats.isDirectory()) {
return {
moduleName: moduleName,
Expand All @@ -541,7 +547,7 @@ export default class NodeResolver {
async loadNodeModules(
module: Module,
extensions: Array<string>,
env: Environment,
env: Env,
): Promise<?ResolvedFile> {
// If a module was specified as a module sub-path (e.g. some-module/some/path),
// it is likely a file. Try loading it as a file first.
Expand All @@ -568,7 +574,7 @@ export default class NodeResolver {

async isFile(file: FilePath): Promise<boolean> {
try {
let stat = await this.options.inputFS.stat(file);
let stat = await this.fs.stat(file);
return stat.isFile() || stat.isFIFO();
} catch (err) {
return false;
Expand All @@ -583,7 +589,7 @@ export default class NodeResolver {
}: {|
dir: string,
extensions: Array<string>,
env: Environment,
env: Env,
pkg?: InternalPackageJSON | null,
|}): Promise<?ResolvedFile> {
let failedEntry;
Expand Down Expand Up @@ -639,10 +645,7 @@ export default class NodeResolver {
);

let alternative = alternatives[0];
let pkgContent = await this.options.inputFS.readFile(
pkg.pkgfile,
'utf8',
);
let pkgContent = await this.fs.readFile(pkg.pkgfile, 'utf8');
throw new ThrowableDiagnostic({
diagnostic: {
message: `Could not load '${fileSpecifier}' from module '${pkg.name}' found in package.json#${failedEntry.field}`,
Expand Down Expand Up @@ -681,7 +684,7 @@ export default class NodeResolver {
return cached;
}

let json = await this.options.inputFS.readFile(file, 'utf8');
let json = await this.fs.readFile(file, 'utf8');
let pkg = JSON.parse(json);

pkg.pkgfile = file;
Expand All @@ -690,7 +693,7 @@ export default class NodeResolver {
// If the package has a `source` field, check if it is behind a symlink.
// If so, we treat the module as source code rather than a pre-compiled module.
if (pkg.source) {
let realpath = await this.options.inputFS.realpath(file);
let realpath = await this.fs.realpath(file);
if (realpath === file) {
delete pkg.source;
}
Expand All @@ -702,7 +705,7 @@ export default class NodeResolver {

getPackageEntries(
pkg: InternalPackageJSON,
env: Environment,
env: Env,
): Array<{|
filename: string,
field: string,
Expand Down Expand Up @@ -753,7 +756,7 @@ export default class NodeResolver {
}: {|
file: string,
extensions: Array<string>,
env: Environment,
env: Env,
pkg: InternalPackageJSON | null,
|}): Promise<?ResolvedFile> {
// Try all supported extensions
Expand All @@ -767,7 +770,7 @@ export default class NodeResolver {
async expandFile(
file: string,
extensions: Array<string>,
env: Environment,
env: Env,
pkg: InternalPackageJSON | null,
expandAliases?: boolean = true,
): Promise<Array<string>> {
Expand Down Expand Up @@ -802,7 +805,7 @@ export default class NodeResolver {

async resolveAliases(
filename: string,
env: Environment,
env: Env,
pkg: InternalPackageJSON | null,
): Promise<string | Array<string>> {
let localAliases = await this.resolvePackageAliases(filename, env, pkg);
Expand All @@ -816,7 +819,7 @@ export default class NodeResolver {

async resolvePackageAliases(
filename: string,
env: Environment,
env: Env,
pkg: InternalPackageJSON | null,
): Promise<string | Array<string>> {
if (!pkg) {
Expand Down Expand Up @@ -856,8 +859,11 @@ export default class NodeResolver {
let [moduleName, subPath] = this.getModuleParts(filename);
alias = await this.lookupAlias(aliases, moduleName);
if (typeof alias === 'string' && subPath) {
let isRelative = alias.startsWith('./');
// Append the filename back onto the aliased module.
alias = path.join(alias, subPath);
alias = path.posix.join(alias, subPath);
// because of path.join('./nested', 'sub') === 'nested/sub'
if (isRelative) alias = './' + alias;
}
}
}
Expand Down Expand Up @@ -933,11 +939,11 @@ export default class NodeResolver {
async loadAlias(
filename: string,
dir: string,
env: Environment,
env: Env,
): Promise<string | Array<string>> {
// Load the root project's package.json file if we haven't already
if (!this.rootPackage) {
this.rootPackage = await this.findPackage(this.options.projectRoot);
this.rootPackage = await this.findPackage(this.projectRoot);
}

// Load the local package, and resolve aliases
Expand Down
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.
Empty file.
Empty file.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.
Empty file.
Empty file.
Empty file.
Empty file.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.
Empty file.
Empty file.
Empty file.
Loading

0 comments on commit 76922b0

Please sign in to comment.