* Resolve a module request for CommonJS, invoking hooks from module.registerHooks() * if necessary. * @param {string} specifier * @param {Module|undefined} parent * @param {boolean} isMain * @param {CJSModuleLoadInternalOptions} internalOptions * @returns {{url?: string, format?: string, paren
(specifier, parent, isMain, internalOptions)
| 1165 | * @returns {{url?: string, format?: string, parentURL?: string, filename: string}} |
| 1166 | */ |
| 1167 | function resolveForCJSWithHooks(specifier, parent, isMain, internalOptions) { |
| 1168 | const { requireResolveOptions, shouldSkipModuleHooks } = internalOptions; |
| 1169 | const defaultResolveImpl = requireResolveOptions ? |
| 1170 | wrapResolveFilename : defaultResolveImplForCJSLoading; |
| 1171 | // Fast path: no hooks, just return simple results. |
| 1172 | if (!resolveHooks.length || shouldSkipModuleHooks) { |
| 1173 | return defaultResolveImpl(specifier, parent, isMain, requireResolveOptions); |
| 1174 | } |
| 1175 | |
| 1176 | // Slow path: has hooks, do the URL conversions and invoke hooks with contexts. |
| 1177 | let parentURL; |
| 1178 | if (parent) { |
| 1179 | if (!parent[kURL] && parent.filename) { |
| 1180 | parent[kURL] = convertCJSFilenameToURL(parent.filename); |
| 1181 | } |
| 1182 | parentURL = parent[kURL]; |
| 1183 | } |
| 1184 | |
| 1185 | // This is used as the last nextResolve for the resolve hooks. |
| 1186 | function defaultResolve(specifier, context) { |
| 1187 | // TODO(joyeecheung): parent and isMain should be part of context, then we |
| 1188 | // no longer need to use a different defaultResolve for every resolution. |
| 1189 | // In the hooks, context.conditions is passed around as an array, but internally |
| 1190 | // the resolution helpers expect a SafeSet. Do the conversion here. |
| 1191 | let conditionSet; |
| 1192 | const conditions = context.conditions; |
| 1193 | if (conditions !== undefined && conditions !== getCjsConditionsArray()) { |
| 1194 | if (!ArrayIsArray(conditions)) { |
| 1195 | throw new ERR_INVALID_ARG_VALUE('context.conditions', conditions, |
| 1196 | 'expected an array'); |
| 1197 | } |
| 1198 | conditionSet = new SafeSet(conditions); |
| 1199 | } else { |
| 1200 | conditionSet = getCjsConditions(); |
| 1201 | } |
| 1202 | |
| 1203 | const result = defaultResolveImpl(specifier, parent, isMain, { |
| 1204 | __proto__: null, |
| 1205 | paths: requireResolveOptions?.paths, |
| 1206 | conditions: conditionSet, |
| 1207 | }); |
| 1208 | // If the default resolver does not return a URL, convert it for the public API. |
| 1209 | result.url ??= convertCJSFilenameToURL(result.filename); |
| 1210 | |
| 1211 | // Remove filename because it's not part of the public API. |
| 1212 | // TODO(joyeecheung): maybe expose it in the public API to avoid re-conversion for users too. |
| 1213 | return { __proto__: null, url: result.url, format: result.format }; |
| 1214 | } |
| 1215 | |
| 1216 | const resolveResult = resolveWithHooks(specifier, parentURL, /* importAttributes */ undefined, |
| 1217 | getCjsConditionsArray(), defaultResolve); |
| 1218 | const { url, format } = resolveResult; |
| 1219 | // Convert the URL from the hook chain back to a filename for internal use. |
| 1220 | const filename = convertURLToCJSFilename(url); |
| 1221 | const result = { __proto__: null, url, format, filename, parentURL }; |
| 1222 | debug('resolveForCJSWithHooks', specifier, parent?.id, isMain, shouldSkipModuleHooks, '->', result); |
| 1223 | return result; |
| 1224 | } |
no test coverage detected
searching dependent graphs…