source: frontend/node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/utils/getModuleSystem.js@ 9af201e

Last change on this file since 9af201e was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 5.2 KB
Line 
1const { promises: fsPromises } = require('fs');
2const path = require('path');
3
4/** @type {Map<string, string | undefined>} */
5let packageJsonTypeMap = new Map();
6
7/**
8 * Infers the current active module system from loader context and options.
9 * @this {import('webpack').loader.LoaderContext}
10 * @param {import('webpack').ModuleFilenameHelpers} ModuleFilenameHelpers Webpack's module filename helpers.
11 * @param {import('../types').NormalizedLoaderOptions} options The normalized loader options.
12 * @return {Promise<'esm' | 'cjs'>} The inferred module system.
13 */
14async function getModuleSystem(ModuleFilenameHelpers, options) {
15 // Check loader options -
16 // if `esModule` is set we don't have to do extra guess work.
17 switch (typeof options.esModule) {
18 case 'boolean': {
19 return options.esModule ? 'esm' : 'cjs';
20 }
21 case 'object': {
22 if (
23 options.esModule.include &&
24 ModuleFilenameHelpers.matchPart(this.resourcePath, options.esModule.include)
25 ) {
26 return 'esm';
27 }
28 if (
29 options.esModule.exclude &&
30 ModuleFilenameHelpers.matchPart(this.resourcePath, options.esModule.exclude)
31 ) {
32 return 'cjs';
33 }
34
35 break;
36 }
37 default: // Do nothing
38 }
39
40 // Check current resource's extension
41 if (/\.mjs$/.test(this.resourcePath)) return 'esm';
42 if (/\.cjs$/.test(this.resourcePath)) return 'cjs';
43
44 if (typeof this.addMissingDependency !== 'function') {
45 // This is Webpack 4 which does not support `import.meta`.
46 // We assume `.js` files are CommonJS because the output cannot be ESM anyway.
47 return 'cjs';
48 }
49
50 // We will assume CommonJS if we cannot determine otherwise
51 let packageJsonType = '';
52
53 // We begin our search for relevant `package.json` files,
54 // at the directory of the resource being loaded.
55 // These paths should already be resolved,
56 // but we resolve them again to ensure we are dealing with an aboslute path.
57 const resourceContext = path.dirname(this.resourcePath);
58 let searchPath = resourceContext;
59 let previousSearchPath = '';
60 // We start our search just above the root context of the webpack compilation
61 const stopPath = path.dirname(this.rootContext);
62
63 // If the module context is a resolved symlink outside the `rootContext` path,
64 // then we will never find the `stopPath` - so we also halt when we hit the root.
65 // Note that there is a potential that the wrong `package.json` is found in some pathalogical cases,
66 // such as a folder that is conceptually a package + does not have an ancestor `package.json`,
67 // but there exists a `package.json` higher up.
68 // This might happen if you have a folder of utility JS files that you symlink but did not organize as a package.
69 // We consider this an unsupported edge case for now.
70 while (searchPath !== stopPath && searchPath !== previousSearchPath) {
71 // If we have already determined the `package.json` type for this path we can stop searching.
72 // We do however still need to cache the found value,
73 // from the `resourcePath` folder up to the matching `searchPath`,
74 // to avoid retracing these steps when processing sibling resources.
75 if (packageJsonTypeMap.has(searchPath)) {
76 packageJsonType = packageJsonTypeMap.get(searchPath);
77
78 let currentPath = resourceContext;
79 while (currentPath !== searchPath) {
80 // We set the found type at least level from `resourcePath` folder up to the matching `searchPath`
81 packageJsonTypeMap.set(currentPath, packageJsonType);
82 currentPath = path.dirname(currentPath);
83 }
84 break;
85 }
86
87 let packageJsonPath = path.join(searchPath, 'package.json');
88 try {
89 const packageSource = await fsPromises.readFile(packageJsonPath, 'utf-8');
90 try {
91 const packageObject = JSON.parse(packageSource);
92
93 // Any package.json is sufficient as long as it can be parsed.
94 // If it does not explicitly have a `type: "module"` it will be assumed to be CommonJS.
95 packageJsonType = typeof packageObject.type === 'string' ? packageObject.type : '';
96 packageJsonTypeMap.set(searchPath, packageJsonType);
97
98 // We set the type in the cache for all paths from the `resourcePath` folder,
99 // up to the matching `searchPath` to avoid retracing these steps when processing sibling resources.
100 let currentPath = resourceContext;
101 while (currentPath !== searchPath) {
102 packageJsonTypeMap.set(currentPath, packageJsonType);
103 currentPath = path.dirname(currentPath);
104 }
105 } catch (e) {
106 // `package.json` exists but could not be parsed.
107 // We track it as a dependency so we can reload if this file changes.
108 }
109
110 this.addDependency(packageJsonPath);
111 break;
112 } catch (e) {
113 // `package.json` does not exist.
114 // We track it as a missing dependency so we can reload if this file is added.
115 this.addMissingDependency(packageJsonPath);
116 }
117
118 // Try again at the next level up
119 previousSearchPath = searchPath;
120 searchPath = path.dirname(searchPath);
121 }
122
123 // Check `package.json` for the `type` field -
124 // fallback to use `cjs` for anything ambiguous.
125 return packageJsonType === 'module' ? 'esm' : 'cjs';
126}
127
128module.exports = getModuleSystem;
Note: See TracBrowser for help on using the repository browser.