@parcel/core
Version:
349 lines (346 loc) • 13.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ResolverRunner = void 0;
exports.default = createPathRequest;
function _diagnostic() {
const data = _interopRequireWildcard(require("@parcel/diagnostic"));
_diagnostic = function () {
return data;
};
return data;
}
function _logger() {
const data = require("@parcel/logger");
_logger = function () {
return data;
};
return data;
}
function _nullthrows() {
const data = _interopRequireDefault(require("nullthrows"));
_nullthrows = function () {
return data;
};
return data;
}
function _path() {
const data = _interopRequireDefault(require("path"));
_path = function () {
return data;
};
return data;
}
function _utils() {
const data = require("@parcel/utils");
_utils = function () {
return data;
};
return data;
}
var _ReporterRunner = require("../ReporterRunner");
var _Dependency = require("../public/Dependency");
var _PluginOptions = _interopRequireDefault(require("../public/PluginOptions"));
var _ParcelConfig = _interopRequireDefault(require("../ParcelConfig"));
var _ParcelConfigRequest = _interopRequireWildcard(require("./ParcelConfigRequest"));
var _utils2 = require("../utils");
var _projectPath = require("../projectPath");
var _types = require("../types");
var _buildCache = require("../buildCache");
var _InternalConfig = require("../InternalConfig");
var _ConfigRequest = require("./ConfigRequest");
var _DevDepRequest = require("./DevDepRequest");
function _profiler() {
const data = require("@parcel/profiler");
_profiler = function () {
return data;
};
return data;
}
var _RequestTracker = require("../RequestTracker");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const PIPELINE_REGEX = /^([a-z0-9-]+?):(.*)$/i;
function createPathRequest(input) {
return {
id: input.dependency.id + ':' + input.name,
type: _RequestTracker.requestTypes.path_request,
run,
input
};
}
async function run({
input,
api,
options
}) {
let configResult = (0, _nullthrows().default)(await api.runRequest((0, _ParcelConfigRequest.default)()));
let config = (0, _ParcelConfigRequest.getCachedParcelConfig)(configResult, options);
let {
devDeps,
invalidDevDeps
} = await (0, _DevDepRequest.getDevDepRequests)(api);
(0, _DevDepRequest.invalidateDevDeps)(invalidDevDeps, options, config);
let resolverRunner = new ResolverRunner({
options,
config,
previousDevDeps: devDeps
});
let result = await resolverRunner.resolve(input.dependency);
if (result.invalidateOnEnvChange) {
for (let env of result.invalidateOnEnvChange) {
api.invalidateOnEnvChange(env);
}
}
if (result.invalidateOnFileCreate) {
for (let file of result.invalidateOnFileCreate) {
api.invalidateOnFileCreate((0, _utils2.invalidateOnFileCreateToInternal)(options.projectRoot, file));
}
}
if (result.invalidateOnFileChange) {
for (let filePath of result.invalidateOnFileChange) {
let pp = (0, _projectPath.toProjectPath)(options.projectRoot, filePath);
api.invalidateOnFileUpdate(pp);
api.invalidateOnFileDelete(pp);
}
}
for (let config of resolverRunner.configs.values()) {
await (0, _ConfigRequest.runConfigRequest)(api, config);
}
for (let devDepRequest of resolverRunner.devDepRequests.values()) {
await (0, _DevDepRequest.runDevDepRequest)(api, devDepRequest);
}
if (result.assetGroup) {
api.invalidateOnFileDelete(result.assetGroup.filePath);
return result.assetGroup;
}
if (result.diagnostics && result.diagnostics.length > 0) {
let err = new (_diagnostic().default)({
diagnostic: result.diagnostics
});
// $FlowFixMe[prop-missing]
err.code = 'MODULE_NOT_FOUND';
throw err;
}
}
const configCache = (0, _buildCache.createBuildCache)();
class ResolverRunner {
constructor({
config,
options,
previousDevDeps
}) {
this.config = config;
this.options = options;
this.pluginOptions = new _PluginOptions.default(this.options);
this.previousDevDeps = previousDevDeps;
this.devDepRequests = new Map();
this.configs = new Map();
}
async getDiagnostic(dependency, message) {
let diagnostic = {
message,
origin: '@parcel/core'
};
if (dependency.loc && dependency.sourcePath != null) {
let filePath = (0, _projectPath.fromProjectPath)(this.options.projectRoot, dependency.sourcePath);
diagnostic.codeFrames = [{
filePath,
code: await this.options.inputFS.readFile(filePath, 'utf8').catch(() => ''),
codeHighlights: dependency.loc ? [(0, _diagnostic().convertSourceLocationToHighlight)(dependency.loc)] : []
}];
}
return diagnostic;
}
async loadConfigs(resolvers) {
for (let plugin of resolvers) {
// Only load config for a plugin once per build.
let config = configCache.get(plugin.name);
if (!config && plugin.plugin.loadConfig != null) {
config = (0, _InternalConfig.createConfig)({
plugin: plugin.name,
searchPath: (0, _projectPath.toProjectPathUnsafe)('index')
});
await (0, _ConfigRequest.loadPluginConfig)(plugin, config, this.options);
configCache.set(plugin.name, config);
this.configs.set(plugin.name, config);
}
if (config) {
for (let devDep of config.devDeps) {
let devDepRequest = await (0, _DevDepRequest.createDevDependency)(devDep, this.previousDevDeps, this.options);
this.runDevDepRequest(devDepRequest);
}
this.configs.set(plugin.name, config);
}
}
}
runDevDepRequest(devDepRequest) {
let {
specifier,
resolveFrom
} = devDepRequest;
let key = `${specifier}:${(0, _projectPath.fromProjectPathRelative)(resolveFrom)}`;
this.devDepRequests.set(key, devDepRequest);
}
async resolve(dependency) {
let dep = (0, _Dependency.getPublicDependency)(dependency, this.options);
(0, _ReporterRunner.report)({
type: 'buildProgress',
phase: 'resolving',
dependency: dep
});
let resolvers = await this.config.getResolvers();
await this.loadConfigs(resolvers);
let pipeline;
let specifier;
let validPipelines = new Set(this.config.getNamedPipelines());
let match = dependency.specifier.match(PIPELINE_REGEX);
if (match &&
// Don't consider absolute paths. Absolute paths are only supported for entries,
// and include e.g. `C:\` on Windows, conflicting with pipelines.
!_path().default.isAbsolute(dependency.specifier)) {
[, pipeline, specifier] = match;
if (!validPipelines.has(pipeline)) {
// This may be a url protocol or scheme rather than a pipeline, such as
// `url('http://example.com/foo.png')`. Pass it to resolvers to handle.
specifier = dependency.specifier;
pipeline = null;
}
} else {
specifier = dependency.specifier;
}
// Entrypoints, convert ProjectPath in module specifier to absolute path
if (dep.resolveFrom == null) {
specifier = _path().default.join(this.options.projectRoot, specifier);
}
let diagnostics = [];
let invalidateOnFileCreate = [];
let invalidateOnFileChange = [];
let invalidateOnEnvChange = [];
for (let resolver of resolvers) {
let measurement;
try {
var _this$configs$get;
measurement = _profiler().tracer.createMeasurement(resolver.name, 'resolve', specifier);
let result = await resolver.plugin.resolve({
specifier,
pipeline,
dependency: dep,
options: this.pluginOptions,
logger: new (_logger().PluginLogger)({
origin: resolver.name
}),
tracer: new (_profiler().PluginTracer)({
origin: resolver.name,
category: 'resolver'
}),
config: (_this$configs$get = this.configs.get(resolver.name)) === null || _this$configs$get === void 0 ? void 0 : _this$configs$get.result
});
measurement && measurement.end();
if (result) {
if (result.meta) {
dependency.resolverMeta = result.meta;
dependency.meta = {
...dependency.meta,
...result.meta
};
}
if (result.priority != null) {
dependency.priority = dependency.resolverPriority = _types.Priority[result.priority];
}
if (result.invalidateOnEnvChange) {
invalidateOnEnvChange.push(...result.invalidateOnEnvChange);
}
if (result.invalidateOnFileCreate) {
invalidateOnFileCreate.push(...result.invalidateOnFileCreate);
}
if (result.invalidateOnFileChange) {
invalidateOnFileChange.push(...result.invalidateOnFileChange);
}
if (result.isExcluded) {
return {
assetGroup: null,
invalidateOnFileCreate,
invalidateOnFileChange,
invalidateOnEnvChange
};
}
if (result.filePath != null) {
var _result$query;
let resultFilePath = result.filePath;
if (!_path().default.isAbsolute(resultFilePath)) {
throw new Error((0, _diagnostic().md)`Resolvers must return an absolute path, ${resolver.name} returned: ${resultFilePath}`);
}
return {
assetGroup: {
canDefer: result.canDefer,
filePath: (0, _projectPath.toProjectPath)(this.options.projectRoot, resultFilePath),
query: (_result$query = result.query) === null || _result$query === void 0 ? void 0 : _result$query.toString(),
sideEffects: result.sideEffects,
code: result.code,
env: dependency.env,
pipeline: result.pipeline === undefined ? pipeline ?? dependency.pipeline : result.pipeline,
isURL: dep.specifierType === 'url'
},
invalidateOnFileCreate,
invalidateOnFileChange,
invalidateOnEnvChange
};
}
if (result.diagnostics != null && !(Array.isArray(result.diagnostics) && result.diagnostics.length === 0)) {
let errorDiagnostic = (0, _diagnostic().errorToDiagnostic)(new (_diagnostic().default)({
diagnostic: result.diagnostics
}), {
origin: resolver.name,
filePath: specifier
});
diagnostics.push(...errorDiagnostic);
}
}
} catch (e) {
// Add error to error map, we'll append these to the standard error if we can't resolve the asset
let errorDiagnostic = (0, _diagnostic().errorToDiagnostic)(e, {
origin: resolver.name,
filePath: specifier
});
if (Array.isArray(errorDiagnostic)) {
diagnostics.push(...errorDiagnostic);
} else {
diagnostics.push(errorDiagnostic);
}
break;
} finally {
measurement && measurement.end();
// Add dev dependency for the resolver. This must be done AFTER running it due to
// the potential for lazy require() that aren't executed until the request runs.
let devDepRequest = await (0, _DevDepRequest.createDevDependency)({
specifier: resolver.name,
resolveFrom: resolver.resolveFrom
}, this.previousDevDeps, this.options);
this.runDevDepRequest(devDepRequest);
}
}
if (dep.isOptional) {
return {
assetGroup: null,
invalidateOnFileCreate,
invalidateOnFileChange,
invalidateOnEnvChange
};
}
let resolveFrom = dependency.resolveFrom ?? dependency.sourcePath;
let dir = resolveFrom != null ? (0, _utils().normalizePath)((0, _projectPath.fromProjectPathRelative)(resolveFrom)) : '';
let diagnostic = await this.getDiagnostic(dependency, (0, _diagnostic().md)`Failed to resolve '${dependency.specifier}' ${dir ? `from '${dir}'` : ''}`);
diagnostics.unshift(diagnostic);
return {
assetGroup: null,
invalidateOnFileCreate,
invalidateOnFileChange,
invalidateOnEnvChange,
diagnostics
};
}
}
exports.ResolverRunner = ResolverRunner;