| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
- */
- "use strict";
- const { pathToFileURL } = require("url");
- const memoize = require("../util/memoize");
- const getLoaderLoadingError = memoize(() =>
- require("../errors/LoaderLoadingError")
- );
- /** @import { LoaderObject } from "./LoaderRunner" */
- /**
- * Lazily-compiled dynamic `import()`. Built on first use so this file still
- * parses on Node versions without native `import()` (<13.2), then reused.
- * @type {((url: URL) => Promise<EXPECTED_ANY>) | undefined}
- */
- let importModule;
- /**
- * @param {LoaderObject} loader the loader to load into
- * @param {EXPECTED_ANY} module the loaded module
- * @param {(err?: Error) => void} callback callback
- * @returns {void}
- */
- function handleResult(loader, module, callback) {
- if (typeof module !== "function" && typeof module !== "object") {
- return callback(
- new (getLoaderLoadingError())(
- `Module '${loader.path}' is not a loader (export function or es6 module)`
- )
- );
- }
- loader.normal = typeof module === "function" ? module : module.default;
- loader.pitch = module.pitch;
- loader.raw = module.raw;
- if (
- typeof loader.normal !== "function" &&
- typeof loader.pitch !== "function"
- ) {
- return callback(
- new (getLoaderLoadingError())(
- `Module '${loader.path}' is not a loader (must have normal or pitch function)`
- )
- );
- }
- callback();
- }
- /**
- * @param {LoaderObject} loader the loader to load
- * @param {(err?: Error) => void} callback callback
- * @returns {void}
- */
- function loadLoader(loader, callback) {
- if (loader.type === "module") {
- try {
- if (importModule === undefined) {
- // `eval` defers parsing `import()` to runtime, so this file stays
- // loadable on Node versions that can't parse it (<13.2).
- // eslint-disable-next-line no-eval
- const dynamicImport = eval("(url) => import(url)");
- importModule = /** @type {(url: URL) => Promise<EXPECTED_ANY>} */ (
- dynamicImport
- );
- }
- importModule(pathToFileURL(loader.path)).then(
- (/** @type {EXPECTED_ANY} */ module) => {
- handleResult(loader, module, callback);
- },
- callback
- );
- } catch (err) {
- callback(/** @type {Error} */ (err));
- }
- return;
- }
- let loadedModule;
- try {
- loadedModule = require(loader.path);
- } catch (err) {
- // node can choke on require when the FD limit is hit; defer to recover.
- if (
- err instanceof Error &&
- /** @type {NodeJS.ErrnoException} */ (err).code === "EMFILE"
- ) {
- setImmediate(loadLoader, loader, callback);
- return;
- }
- return callback(/** @type {Error} */ (err));
- }
- return handleResult(loader, loadedModule, callback);
- }
- module.exports = loadLoader;
|