compilationCache.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. "use strict";
  2. var __create = Object.create;
  3. var __defProp = Object.defineProperty;
  4. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  5. var __getOwnPropNames = Object.getOwnPropertyNames;
  6. var __getProtoOf = Object.getPrototypeOf;
  7. var __hasOwnProp = Object.prototype.hasOwnProperty;
  8. var __export = (target, all) => {
  9. for (var name in all)
  10. __defProp(target, name, { get: all[name], enumerable: true });
  11. };
  12. var __copyProps = (to, from, except, desc) => {
  13. if (from && typeof from === "object" || typeof from === "function") {
  14. for (let key of __getOwnPropNames(from))
  15. if (!__hasOwnProp.call(to, key) && key !== except)
  16. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  17. }
  18. return to;
  19. };
  20. var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  21. // If the importer is in node compatibility mode or this is not an ESM
  22. // file that has been converted to a CommonJS file using a Babel-
  23. // compatible transform (i.e. "__esModule" has not been set), then set
  24. // "default" to the CommonJS "module.exports" for node compatibility.
  25. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  26. mod
  27. ));
  28. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  29. var compilationCache_exports = {};
  30. __export(compilationCache_exports, {
  31. addToCompilationCache: () => addToCompilationCache,
  32. affectedTestFiles: () => affectedTestFiles,
  33. belongsToNodeModules: () => belongsToNodeModules,
  34. cacheDir: () => cacheDir,
  35. collectAffectedTestFiles: () => collectAffectedTestFiles,
  36. currentFileDepsCollector: () => currentFileDepsCollector,
  37. dependenciesForTestFile: () => dependenciesForTestFile,
  38. fileDependenciesForTest: () => fileDependenciesForTest,
  39. getFromCompilationCache: () => getFromCompilationCache,
  40. getUserData: () => getUserData,
  41. installSourceMapSupport: () => installSourceMapSupport,
  42. internalDependenciesForTestFile: () => internalDependenciesForTestFile,
  43. serializeCompilationCache: () => serializeCompilationCache,
  44. setExternalDependencies: () => setExternalDependencies,
  45. startCollectingFileDeps: () => startCollectingFileDeps,
  46. stopCollectingFileDeps: () => stopCollectingFileDeps
  47. });
  48. module.exports = __toCommonJS(compilationCache_exports);
  49. var import_fs = __toESM(require("fs"));
  50. var import_os = __toESM(require("os"));
  51. var import_path = __toESM(require("path"));
  52. var import_utils = require("playwright-core/lib/utils");
  53. var import_globals = require("../common/globals");
  54. var import_utilsBundle = require("../utilsBundle");
  55. const cacheDir = process.env.PWTEST_CACHE_DIR || (() => {
  56. if (process.platform === "win32")
  57. return import_path.default.join(import_os.default.tmpdir(), `playwright-transform-cache`);
  58. return import_path.default.join(import_os.default.tmpdir(), `playwright-transform-cache-` + process.geteuid?.());
  59. })();
  60. const sourceMaps = /* @__PURE__ */ new Map();
  61. const memoryCache = /* @__PURE__ */ new Map();
  62. const fileDependencies = /* @__PURE__ */ new Map();
  63. const externalDependencies = /* @__PURE__ */ new Map();
  64. function installSourceMapSupport() {
  65. Error.stackTraceLimit = 200;
  66. import_utilsBundle.sourceMapSupport.install({
  67. environment: "node",
  68. handleUncaughtExceptions: false,
  69. retrieveSourceMap(source) {
  70. if (!sourceMaps.has(source))
  71. return null;
  72. const sourceMapPath = sourceMaps.get(source);
  73. try {
  74. return {
  75. map: JSON.parse(import_fs.default.readFileSync(sourceMapPath, "utf-8")),
  76. url: source
  77. };
  78. } catch {
  79. return null;
  80. }
  81. }
  82. });
  83. }
  84. function _innerAddToCompilationCacheAndSerialize(filename, entry) {
  85. sourceMaps.set(entry.moduleUrl || filename, entry.sourceMapPath);
  86. memoryCache.set(filename, entry);
  87. return {
  88. sourceMaps: [[entry.moduleUrl || filename, entry.sourceMapPath]],
  89. memoryCache: [[filename, entry]],
  90. fileDependencies: [],
  91. externalDependencies: []
  92. };
  93. }
  94. function getFromCompilationCache(filename, contentHash, moduleUrl) {
  95. const cache = memoryCache.get(filename);
  96. if (cache?.codePath) {
  97. try {
  98. return { cachedCode: import_fs.default.readFileSync(cache.codePath, "utf-8") };
  99. } catch {
  100. }
  101. }
  102. const filePathHash = calculateFilePathHash(filename);
  103. const hashPrefix = filePathHash + "_" + contentHash.substring(0, 7);
  104. const cacheFolderName = filePathHash.substring(0, 2);
  105. const cachePath = calculateCachePath(filename, cacheFolderName, hashPrefix);
  106. const codePath = cachePath + ".js";
  107. const sourceMapPath = cachePath + ".map";
  108. const dataPath = cachePath + ".data";
  109. try {
  110. const cachedCode = import_fs.default.readFileSync(codePath, "utf8");
  111. const serializedCache = _innerAddToCompilationCacheAndSerialize(filename, { codePath, sourceMapPath, dataPath, moduleUrl });
  112. return { cachedCode, serializedCache };
  113. } catch {
  114. }
  115. return {
  116. addToCache: (code, map, data) => {
  117. if ((0, import_globals.isWorkerProcess)())
  118. return {};
  119. clearOldCacheEntries(cacheFolderName, filePathHash);
  120. import_fs.default.mkdirSync(import_path.default.dirname(cachePath), { recursive: true });
  121. if (map)
  122. import_fs.default.writeFileSync(sourceMapPath, JSON.stringify(map), "utf8");
  123. if (data.size)
  124. import_fs.default.writeFileSync(dataPath, JSON.stringify(Object.fromEntries(data.entries()), void 0, 2), "utf8");
  125. import_fs.default.writeFileSync(codePath, code, "utf8");
  126. const serializedCache = _innerAddToCompilationCacheAndSerialize(filename, { codePath, sourceMapPath, dataPath, moduleUrl });
  127. return { serializedCache };
  128. }
  129. };
  130. }
  131. function serializeCompilationCache() {
  132. return {
  133. sourceMaps: [...sourceMaps.entries()],
  134. memoryCache: [...memoryCache.entries()],
  135. fileDependencies: [...fileDependencies.entries()].map(([filename, deps]) => [filename, [...deps]]),
  136. externalDependencies: [...externalDependencies.entries()].map(([filename, deps]) => [filename, [...deps]])
  137. };
  138. }
  139. function addToCompilationCache(payload) {
  140. for (const entry of payload.sourceMaps)
  141. sourceMaps.set(entry[0], entry[1]);
  142. for (const entry of payload.memoryCache)
  143. memoryCache.set(entry[0], entry[1]);
  144. for (const entry of payload.fileDependencies) {
  145. const existing = fileDependencies.get(entry[0]) || [];
  146. fileDependencies.set(entry[0], /* @__PURE__ */ new Set([...entry[1], ...existing]));
  147. }
  148. for (const entry of payload.externalDependencies) {
  149. const existing = externalDependencies.get(entry[0]) || [];
  150. externalDependencies.set(entry[0], /* @__PURE__ */ new Set([...entry[1], ...existing]));
  151. }
  152. }
  153. function calculateFilePathHash(filePath) {
  154. return (0, import_utils.calculateSha1)(filePath).substring(0, 10);
  155. }
  156. function calculateCachePath(filePath, cacheFolderName, hashPrefix) {
  157. const fileName = hashPrefix + "_" + import_path.default.basename(filePath, import_path.default.extname(filePath)).replace(/\W/g, "");
  158. return import_path.default.join(cacheDir, cacheFolderName, fileName);
  159. }
  160. function clearOldCacheEntries(cacheFolderName, filePathHash) {
  161. const cachePath = import_path.default.join(cacheDir, cacheFolderName);
  162. try {
  163. const cachedRelevantFiles = import_fs.default.readdirSync(cachePath).filter((file) => file.startsWith(filePathHash));
  164. for (const file of cachedRelevantFiles)
  165. import_fs.default.rmSync(import_path.default.join(cachePath, file), { force: true });
  166. } catch {
  167. }
  168. }
  169. let depsCollector;
  170. function startCollectingFileDeps() {
  171. depsCollector = /* @__PURE__ */ new Set();
  172. }
  173. function stopCollectingFileDeps(filename) {
  174. if (!depsCollector)
  175. return;
  176. depsCollector.delete(filename);
  177. for (const dep of depsCollector) {
  178. if (belongsToNodeModules(dep))
  179. depsCollector.delete(dep);
  180. }
  181. fileDependencies.set(filename, depsCollector);
  182. depsCollector = void 0;
  183. }
  184. function currentFileDepsCollector() {
  185. return depsCollector;
  186. }
  187. function setExternalDependencies(filename, deps) {
  188. const depsSet = new Set(deps.filter((dep) => !belongsToNodeModules(dep) && dep !== filename));
  189. externalDependencies.set(filename, depsSet);
  190. }
  191. function fileDependenciesForTest() {
  192. return fileDependencies;
  193. }
  194. function collectAffectedTestFiles(changedFile, testFileCollector) {
  195. const isTestFile = (file) => fileDependencies.has(file);
  196. if (isTestFile(changedFile))
  197. testFileCollector.add(changedFile);
  198. for (const [testFile, deps] of fileDependencies) {
  199. if (deps.has(changedFile))
  200. testFileCollector.add(testFile);
  201. }
  202. for (const [importingFile, depsOfImportingFile] of externalDependencies) {
  203. if (depsOfImportingFile.has(changedFile)) {
  204. if (isTestFile(importingFile))
  205. testFileCollector.add(importingFile);
  206. for (const [testFile, depsOfTestFile] of fileDependencies) {
  207. if (depsOfTestFile.has(importingFile))
  208. testFileCollector.add(testFile);
  209. }
  210. }
  211. }
  212. }
  213. function affectedTestFiles(changes) {
  214. const result = /* @__PURE__ */ new Set();
  215. for (const change of changes)
  216. collectAffectedTestFiles(change, result);
  217. return [...result];
  218. }
  219. function internalDependenciesForTestFile(filename) {
  220. return fileDependencies.get(filename);
  221. }
  222. function dependenciesForTestFile(filename) {
  223. const result = /* @__PURE__ */ new Set();
  224. for (const testDependency of fileDependencies.get(filename) || []) {
  225. result.add(testDependency);
  226. for (const externalDependency of externalDependencies.get(testDependency) || [])
  227. result.add(externalDependency);
  228. }
  229. for (const dep of externalDependencies.get(filename) || [])
  230. result.add(dep);
  231. return result;
  232. }
  233. const kPlaywrightInternalPrefix = import_path.default.resolve(__dirname, "../../../playwright");
  234. function belongsToNodeModules(file) {
  235. if (file.includes(`${import_path.default.sep}node_modules${import_path.default.sep}`))
  236. return true;
  237. if (file.startsWith(kPlaywrightInternalPrefix) && (file.endsWith(".js") || file.endsWith(".mjs")))
  238. return true;
  239. return false;
  240. }
  241. async function getUserData(pluginName) {
  242. const result = /* @__PURE__ */ new Map();
  243. for (const [fileName, cache] of memoryCache) {
  244. if (!cache.dataPath)
  245. continue;
  246. if (!import_fs.default.existsSync(cache.dataPath))
  247. continue;
  248. const data = JSON.parse(await import_fs.default.promises.readFile(cache.dataPath, "utf8"));
  249. if (data[pluginName])
  250. result.set(fileName, data[pluginName]);
  251. }
  252. return result;
  253. }
  254. // Annotate the CommonJS export names for ESM import in node:
  255. 0 && (module.exports = {
  256. addToCompilationCache,
  257. affectedTestFiles,
  258. belongsToNodeModules,
  259. cacheDir,
  260. collectAffectedTestFiles,
  261. currentFileDepsCollector,
  262. dependenciesForTestFile,
  263. fileDependenciesForTest,
  264. getFromCompilationCache,
  265. getUserData,
  266. installSourceMapSupport,
  267. internalDependenciesForTestFile,
  268. serializeCompilationCache,
  269. setExternalDependencies,
  270. startCollectingFileDeps,
  271. stopCollectingFileDeps
  272. });