Permalink
Cannot retrieve contributors at this time
178 lines (157 sloc)
4.75 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
codeql-action/node_modules/enhanced-resolve/lib/ImportsFieldPlugin.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
MIT License http://www.opensource.org/licenses/mit-license.php | |
Author Ivan Kopeykin @vankop | |
*/ | |
"use strict"; | |
const path = require("path"); | |
const DescriptionFileUtils = require("./DescriptionFileUtils"); | |
const forEachBail = require("./forEachBail"); | |
const { processImportsField } = require("./util/entrypoints"); | |
const { parseIdentifier } = require("./util/identifier"); | |
const { checkImportsExportsFieldTarget } = require("./util/path"); | |
/** @typedef {import("./Resolver")} Resolver */ | |
/** @typedef {import("./Resolver").ResolveStepHook} ResolveStepHook */ | |
/** @typedef {import("./util/entrypoints").FieldProcessor} FieldProcessor */ | |
/** @typedef {import("./util/entrypoints").ImportsField} ImportsField */ | |
const dotCode = ".".charCodeAt(0); | |
module.exports = class ImportsFieldPlugin { | |
/** | |
* @param {string | ResolveStepHook} source source | |
* @param {Set<string>} conditionNames condition names | |
* @param {string | string[]} fieldNamePath name path | |
* @param {string | ResolveStepHook} targetFile target file | |
* @param {string | ResolveStepHook} targetPackage target package | |
*/ | |
constructor( | |
source, | |
conditionNames, | |
fieldNamePath, | |
targetFile, | |
targetPackage | |
) { | |
this.source = source; | |
this.targetFile = targetFile; | |
this.targetPackage = targetPackage; | |
this.conditionNames = conditionNames; | |
this.fieldName = fieldNamePath; | |
/** @type {WeakMap<any, FieldProcessor>} */ | |
this.fieldProcessorCache = new WeakMap(); | |
} | |
/** | |
* @param {Resolver} resolver the resolver | |
* @returns {void} | |
*/ | |
apply(resolver) { | |
const targetFile = resolver.ensureHook(this.targetFile); | |
const targetPackage = resolver.ensureHook(this.targetPackage); | |
resolver | |
.getHook(this.source) | |
.tapAsync("ImportsFieldPlugin", (request, resolveContext, callback) => { | |
// When there is no description file, abort | |
if (!request.descriptionFilePath || request.request === undefined) { | |
return callback(); | |
} | |
const remainingRequest = | |
request.request + request.query + request.fragment; | |
/** @type {ImportsField|null} */ | |
const importsField = DescriptionFileUtils.getField( | |
request.descriptionFileData, | |
this.fieldName | |
); | |
if (!importsField) return callback(); | |
if (request.directory) { | |
return callback( | |
new Error( | |
`Resolving to directories is not possible with the imports field (request was ${remainingRequest}/)` | |
) | |
); | |
} | |
let paths; | |
try { | |
// We attach the cache to the description file instead of the importsField value | |
// because we use a WeakMap and the importsField could be a string too. | |
// Description file is always an object when exports field can be accessed. | |
let fieldProcessor = this.fieldProcessorCache.get( | |
request.descriptionFileData | |
); | |
if (fieldProcessor === undefined) { | |
fieldProcessor = processImportsField(importsField); | |
this.fieldProcessorCache.set( | |
request.descriptionFileData, | |
fieldProcessor | |
); | |
} | |
paths = fieldProcessor(remainingRequest, this.conditionNames); | |
} catch (err) { | |
if (resolveContext.log) { | |
resolveContext.log( | |
`Imports field in ${request.descriptionFilePath} can't be processed: ${err}` | |
); | |
} | |
return callback(err); | |
} | |
if (paths.length === 0) { | |
return callback( | |
new Error( | |
`Package import ${remainingRequest} is not imported from package ${request.descriptionFileRoot} (see imports field in ${request.descriptionFilePath})` | |
) | |
); | |
} | |
forEachBail( | |
paths, | |
(p, callback) => { | |
const parsedIdentifier = parseIdentifier(p); | |
if (!parsedIdentifier) return callback(); | |
const [path_, query, fragment] = parsedIdentifier; | |
const error = checkImportsExportsFieldTarget(path_); | |
if (error) { | |
return callback(error); | |
} | |
switch (path_.charCodeAt(0)) { | |
// should be relative | |
case dotCode: { | |
const obj = { | |
...request, | |
request: undefined, | |
path: path.join( | |
/** @type {string} */ (request.descriptionFileRoot), | |
path_ | |
), | |
relativePath: path_, | |
query, | |
fragment | |
}; | |
resolver.doResolve( | |
targetFile, | |
obj, | |
"using imports field: " + p, | |
resolveContext, | |
callback | |
); | |
break; | |
} | |
// package resolving | |
default: { | |
const obj = { | |
...request, | |
request: path_, | |
relativePath: path_, | |
fullySpecified: true, | |
query, | |
fragment | |
}; | |
resolver.doResolve( | |
targetPackage, | |
obj, | |
"using imports field: " + p, | |
resolveContext, | |
callback | |
); | |
} | |
} | |
}, | |
(err, result) => callback(err, result || null) | |
); | |
}); | |
} | |
}; |