* Provide source that is understood by one of Node's translators. * * Internally, this behaves like a backwards iterator, wherein the stack of * hooks starts at the top and each call to `nextLoad()` moves down 1 step * until it reaches the bottom or short-circuits. * @param {URL['href
(url, context = kEmptyObject)
| 355 | * @returns {Promise<{ format: ModuleFormat, source: ModuleSource }>} |
| 356 | */ |
| 357 | async load(url, context = kEmptyObject) { |
| 358 | const chain = this.#chains.load; |
| 359 | const meta = { |
| 360 | chainFinished: null, |
| 361 | context, |
| 362 | hookErrIdentifier: '', |
| 363 | hookName: 'load', |
| 364 | shortCircuited: false, |
| 365 | }; |
| 366 | |
| 367 | const validateArgs = (hookErrIdentifier, nextUrl, ctx) => { |
| 368 | if (typeof nextUrl !== 'string') { |
| 369 | // Non-strings can be coerced to a URL string |
| 370 | // validateString() throws a less-specific error |
| 371 | throw new ERR_INVALID_ARG_TYPE( |
| 372 | `${hookErrIdentifier} url`, |
| 373 | 'a URL string', |
| 374 | nextUrl, |
| 375 | ); |
| 376 | } |
| 377 | |
| 378 | // Avoid expensive URL instantiation for known-good URLs |
| 379 | if (!this.#validatedUrls.has(nextUrl)) { |
| 380 | // No need to convert to string, since the type is already validated |
| 381 | if (!URLCanParse(nextUrl)) { |
| 382 | throw new ERR_INVALID_ARG_VALUE( |
| 383 | `${hookErrIdentifier} url`, |
| 384 | nextUrl, |
| 385 | 'should be a URL string', |
| 386 | ); |
| 387 | } |
| 388 | |
| 389 | this.#validatedUrls.add(nextUrl); |
| 390 | } |
| 391 | |
| 392 | if (ctx) { validateObject(ctx, `${hookErrIdentifier} context`); } |
| 393 | }; |
| 394 | const validateOutput = (hookErrIdentifier, output) => { |
| 395 | if (typeof output !== 'object' || output === null) { // [2] |
| 396 | throw new ERR_INVALID_RETURN_VALUE( |
| 397 | 'an object', |
| 398 | hookErrIdentifier, |
| 399 | output, |
| 400 | ); |
| 401 | } |
| 402 | }; |
| 403 | |
| 404 | const nextLoad = nextHookFactory(chain[chain.length - 1], meta, { validateArgs, validateOutput }); |
| 405 | |
| 406 | const loaded = await nextLoad(url, defineImportAssertionAlias(context)); |
| 407 | const { hookErrIdentifier } = meta; // Retrieve the value after all settled |
| 408 | |
| 409 | validateOutput(hookErrIdentifier, loaded); |
| 410 | |
| 411 | if (loaded?.shortCircuit === true) { meta.shortCircuited = true; } |
| 412 | |
| 413 | if (!meta.chainFinished && !meta.shortCircuited) { |
| 414 | throw new ERR_LOADER_CHAIN_INCOMPLETE(hookErrIdentifier); |
nothing calls this directly
no test coverage detected