index.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. const path_1 = __importDefault(require("path"));
  6. const virtual_stats_1 = require("./virtual-stats");
  7. let inode = 45000000;
  8. const ALL = 'all';
  9. const STATIC = 'static';
  10. const DYNAMIC = 'dynamic';
  11. function checkActivation(instance) {
  12. if (!instance._compiler) {
  13. throw new Error('You must use this plugin only after creating webpack instance!');
  14. }
  15. }
  16. function getModulePath(filePath, compiler) {
  17. return path_1.default.isAbsolute(filePath) ? filePath : path_1.default.join(compiler.context, filePath);
  18. }
  19. function createWebpackData(result) {
  20. return (backendOrStorage) => {
  21. if (backendOrStorage._data) {
  22. const curLevelIdx = backendOrStorage._currentLevel;
  23. const curLevel = backendOrStorage._levels[curLevelIdx];
  24. return {
  25. result,
  26. level: curLevel,
  27. };
  28. }
  29. return [null, result];
  30. };
  31. }
  32. function getData(storage, key) {
  33. if (storage._data instanceof Map) {
  34. return storage._data.get(key);
  35. }
  36. else if (storage._data) {
  37. return storage.data[key];
  38. }
  39. else if (storage.data instanceof Map) {
  40. return storage.data.get(key);
  41. }
  42. else {
  43. return storage.data[key];
  44. }
  45. }
  46. function setData(backendOrStorage, key, valueFactory) {
  47. const value = valueFactory(backendOrStorage);
  48. if (backendOrStorage._data instanceof Map) {
  49. backendOrStorage._data.set(key, value);
  50. }
  51. else if (backendOrStorage._data) {
  52. backendOrStorage.data[key] = value;
  53. }
  54. else if (backendOrStorage.data instanceof Map) {
  55. backendOrStorage.data.set(key, value);
  56. }
  57. else {
  58. backendOrStorage.data[key] = value;
  59. }
  60. }
  61. function getStatStorage(fileSystem) {
  62. if (fileSystem._statStorage) {
  63. return fileSystem._statStorage;
  64. }
  65. else if (fileSystem._statBackend) {
  66. return fileSystem._statBackend;
  67. }
  68. else {
  69. throw new Error("Couldn't find a stat storage");
  70. }
  71. }
  72. function getFileStorage(fileSystem) {
  73. if (fileSystem._readFileStorage) {
  74. return fileSystem._readFileStorage;
  75. }
  76. else if (fileSystem._readFileBackend) {
  77. return fileSystem._readFileBackend;
  78. }
  79. else {
  80. throw new Error("Couldn't find a readFileStorage");
  81. }
  82. }
  83. function getReadDirBackend(fileSystem) {
  84. if (fileSystem._readdirBackend) {
  85. return fileSystem._readdirBackend;
  86. }
  87. else if (fileSystem._readdirStorage) {
  88. return fileSystem._readdirStorage;
  89. }
  90. else {
  91. throw new Error("Couldn't find a readDirStorage from Webpack Internals");
  92. }
  93. }
  94. function getRealpathBackend(fileSystem) {
  95. if (fileSystem._realpathBackend) {
  96. return fileSystem._realpathBackend;
  97. }
  98. }
  99. class VirtualModulesPlugin {
  100. constructor(modules) {
  101. this._compiler = null;
  102. this._watcher = null;
  103. this._staticModules = modules || null;
  104. }
  105. getModuleList(filter = ALL) {
  106. var _a, _b;
  107. let modules = {};
  108. const shouldGetStaticModules = filter === ALL || filter === STATIC;
  109. const shouldGetDynamicModules = filter === ALL || filter === DYNAMIC;
  110. if (shouldGetStaticModules) {
  111. modules = Object.assign(Object.assign({}, modules), this._staticModules);
  112. }
  113. if (shouldGetDynamicModules) {
  114. const finalInputFileSystem = (_a = this._compiler) === null || _a === void 0 ? void 0 : _a.inputFileSystem;
  115. const virtualFiles = (_b = finalInputFileSystem === null || finalInputFileSystem === void 0 ? void 0 : finalInputFileSystem._virtualFiles) !== null && _b !== void 0 ? _b : {};
  116. const dynamicModules = {};
  117. Object.keys(virtualFiles).forEach((key) => {
  118. dynamicModules[key] = virtualFiles[key].contents;
  119. });
  120. modules = Object.assign(Object.assign({}, modules), dynamicModules);
  121. }
  122. return modules;
  123. }
  124. writeModule(filePath, contents) {
  125. if (!this._compiler) {
  126. throw new Error(`Plugin has not been initialized`);
  127. }
  128. checkActivation(this);
  129. const len = contents ? contents.length : 0;
  130. const time = Date.now();
  131. const date = new Date(time);
  132. const stats = new virtual_stats_1.VirtualStats({
  133. dev: 8675309,
  134. nlink: 0,
  135. uid: 1000,
  136. gid: 1000,
  137. rdev: 0,
  138. blksize: 4096,
  139. ino: inode++,
  140. mode: 33188,
  141. size: len,
  142. blocks: Math.floor(len / 4096),
  143. atime: date,
  144. mtime: date,
  145. ctime: date,
  146. birthtime: date,
  147. });
  148. const modulePath = getModulePath(filePath, this._compiler);
  149. if (process.env.WVM_DEBUG)
  150. console.log(this._compiler.name, 'Write virtual module:', modulePath, contents);
  151. let finalWatchFileSystem = this._watcher && this._watcher.watchFileSystem;
  152. while (finalWatchFileSystem && finalWatchFileSystem.wfs) {
  153. finalWatchFileSystem = finalWatchFileSystem.wfs;
  154. }
  155. let finalInputFileSystem = this._compiler.inputFileSystem;
  156. while (finalInputFileSystem && finalInputFileSystem._inputFileSystem) {
  157. finalInputFileSystem = finalInputFileSystem._inputFileSystem;
  158. }
  159. finalInputFileSystem._writeVirtualFile(modulePath, stats, contents);
  160. if (finalWatchFileSystem &&
  161. finalWatchFileSystem.watcher &&
  162. (finalWatchFileSystem.watcher.fileWatchers.size || finalWatchFileSystem.watcher.fileWatchers.length)) {
  163. const fileWatchers = finalWatchFileSystem.watcher.fileWatchers instanceof Map
  164. ? Array.from(finalWatchFileSystem.watcher.fileWatchers.values())
  165. : finalWatchFileSystem.watcher.fileWatchers;
  166. for (let fileWatcher of fileWatchers) {
  167. if ('watcher' in fileWatcher) {
  168. fileWatcher = fileWatcher.watcher;
  169. }
  170. if (fileWatcher.path === modulePath) {
  171. if (process.env.DEBUG)
  172. console.log(this._compiler.name, 'Emit file change:', modulePath, time);
  173. delete fileWatcher.directoryWatcher._cachedTimeInfoEntries;
  174. fileWatcher.emit('change', time, null);
  175. }
  176. }
  177. }
  178. }
  179. apply(compiler) {
  180. this._compiler = compiler;
  181. const afterEnvironmentHook = () => {
  182. let finalInputFileSystem = compiler.inputFileSystem;
  183. while (finalInputFileSystem && finalInputFileSystem._inputFileSystem) {
  184. finalInputFileSystem = finalInputFileSystem._inputFileSystem;
  185. }
  186. if (!finalInputFileSystem._writeVirtualFile) {
  187. const originalPurge = finalInputFileSystem.purge;
  188. finalInputFileSystem.purge = () => {
  189. originalPurge.apply(finalInputFileSystem, []);
  190. if (finalInputFileSystem._virtualFiles) {
  191. Object.keys(finalInputFileSystem._virtualFiles).forEach((file) => {
  192. const data = finalInputFileSystem._virtualFiles[file];
  193. finalInputFileSystem._writeVirtualFile(file, data.stats, data.contents);
  194. });
  195. }
  196. };
  197. finalInputFileSystem._writeVirtualFile = (file, stats, contents) => {
  198. const statStorage = getStatStorage(finalInputFileSystem);
  199. const fileStorage = getFileStorage(finalInputFileSystem);
  200. const readDirStorage = getReadDirBackend(finalInputFileSystem);
  201. const realPathStorage = getRealpathBackend(finalInputFileSystem);
  202. finalInputFileSystem._virtualFiles = finalInputFileSystem._virtualFiles || {};
  203. finalInputFileSystem._virtualFiles[file] = { stats: stats, contents: contents };
  204. setData(statStorage, file, createWebpackData(stats));
  205. setData(fileStorage, file, createWebpackData(contents));
  206. const segments = file.split(/[\\/]/);
  207. let count = segments.length - 1;
  208. const minCount = segments[0] ? 1 : 0;
  209. while (count > minCount) {
  210. const dir = segments.slice(0, count).join(path_1.default.sep) || path_1.default.sep;
  211. try {
  212. finalInputFileSystem.readdirSync(dir);
  213. }
  214. catch (e) {
  215. const time = Date.now();
  216. const dirStats = new virtual_stats_1.VirtualStats({
  217. dev: 8675309,
  218. nlink: 0,
  219. uid: 1000,
  220. gid: 1000,
  221. rdev: 0,
  222. blksize: 4096,
  223. ino: inode++,
  224. mode: 16877,
  225. size: stats.size,
  226. blocks: Math.floor(stats.size / 4096),
  227. atime: time,
  228. mtime: time,
  229. ctime: time,
  230. birthtime: time,
  231. });
  232. setData(readDirStorage, dir, createWebpackData([]));
  233. if (realPathStorage) {
  234. setData(realPathStorage, dir, createWebpackData(dir));
  235. }
  236. setData(statStorage, dir, createWebpackData(dirStats));
  237. }
  238. let dirData = getData(getReadDirBackend(finalInputFileSystem), dir);
  239. dirData = dirData[1] || dirData.result;
  240. const filename = segments[count];
  241. if (dirData.indexOf(filename) < 0) {
  242. const files = dirData.concat([filename]).sort();
  243. setData(getReadDirBackend(finalInputFileSystem), dir, createWebpackData(files));
  244. }
  245. else {
  246. break;
  247. }
  248. count--;
  249. }
  250. };
  251. }
  252. };
  253. const afterResolversHook = () => {
  254. if (this._staticModules) {
  255. for (const [filePath, contents] of Object.entries(this._staticModules)) {
  256. this.writeModule(filePath, contents);
  257. }
  258. this._staticModules = null;
  259. }
  260. };
  261. const version = typeof compiler.webpack === 'undefined' ? 4 : 5;
  262. const watchRunHook = (watcher, callback) => {
  263. this._watcher = watcher.compiler || watcher;
  264. const virtualFiles = compiler.inputFileSystem._virtualFiles;
  265. const fts = compiler.fileTimestamps;
  266. if (virtualFiles && fts && typeof fts.set === 'function') {
  267. Object.keys(virtualFiles).forEach((file) => {
  268. const mtime = +virtualFiles[file].stats.mtime;
  269. fts.set(file, version === 4
  270. ? mtime
  271. : {
  272. safeTime: mtime,
  273. timestamp: mtime,
  274. });
  275. });
  276. }
  277. callback();
  278. };
  279. if (compiler.hooks) {
  280. compiler.hooks.afterEnvironment.tap('VirtualModulesPlugin', afterEnvironmentHook);
  281. compiler.hooks.afterResolvers.tap('VirtualModulesPlugin', afterResolversHook);
  282. compiler.hooks.watchRun.tapAsync('VirtualModulesPlugin', watchRunHook);
  283. }
  284. else {
  285. compiler.plugin('after-environment', afterEnvironmentHook);
  286. compiler.plugin('after-resolvers', afterResolversHook);
  287. compiler.plugin('watch-run', watchRunHook);
  288. }
  289. }
  290. }
  291. module.exports = VirtualModulesPlugin;
  292. //# sourceMappingURL=index.js.map