compilationCache.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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_globals = require("../common/globals");
  53. var import_utilsBundle = require("../utilsBundle");
  54. const cacheDir = process.env.PWTEST_CACHE_DIR || (() => {
  55. if (process.platform === "win32")
  56. return import_path.default.join(import_os.default.tmpdir(), `playwright-transform-cache`);
  57. return import_path.default.join(import_os.default.tmpdir(), `playwright-transform-cache-` + process.geteuid?.());
  58. })();
  59. const sourceMaps = /* @__PURE__ */ new Map();
  60. const memoryCache = /* @__PURE__ */ new Map();
  61. const fileDependencies = /* @__PURE__ */ new Map();
  62. const externalDependencies = /* @__PURE__ */ new Map();
  63. function installSourceMapSupport() {
  64. Error.stackTraceLimit = 200;
  65. import_utilsBundle.sourceMapSupport.install({
  66. environment: "node",
  67. handleUncaughtExceptions: false,
  68. retrieveSourceMap(source) {
  69. if (!sourceMaps.has(source))
  70. return null;
  71. const sourceMapPath = sourceMaps.get(source);
  72. try {
  73. return {
  74. map: JSON.parse(import_fs.default.readFileSync(sourceMapPath, "utf-8")),
  75. url: source
  76. };
  77. } catch {
  78. return null;
  79. }
  80. }
  81. });
  82. }
  83. function _innerAddToCompilationCacheAndSerialize(filename, entry) {
  84. sourceMaps.set(entry.moduleUrl || filename, entry.sourceMapPath);
  85. memoryCache.set(filename, entry);
  86. return {
  87. sourceMaps: [[entry.moduleUrl || filename, entry.sourceMapPath]],
  88. memoryCache: [[filename, entry]],
  89. fileDependencies: [],
  90. externalDependencies: []
  91. };
  92. }
  93. function getFromCompilationCache(filename, hash, moduleUrl) {
  94. const cache = memoryCache.get(filename);
  95. if (cache?.codePath) {
  96. try {
  97. return { cachedCode: import_fs.default.readFileSync(cache.codePath, "utf-8") };
  98. } catch {
  99. }
  100. }
  101. const cachePath = calculateCachePath(filename, hash);
  102. const codePath = cachePath + ".js";
  103. const sourceMapPath = cachePath + ".map";
  104. const dataPath = cachePath + ".data";
  105. try {
  106. const cachedCode = import_fs.default.readFileSync(codePath, "utf8");
  107. const serializedCache = _innerAddToCompilationCacheAndSerialize(filename, { codePath, sourceMapPath, dataPath, moduleUrl });
  108. return { cachedCode, serializedCache };
  109. } catch {
  110. }
  111. return {
  112. addToCache: (code, map, data) => {
  113. if ((0, import_globals.isWorkerProcess)())
  114. return {};
  115. import_fs.default.mkdirSync(import_path.default.dirname(cachePath), { recursive: true });
  116. if (map)
  117. import_fs.default.writeFileSync(sourceMapPath, JSON.stringify(map), "utf8");
  118. if (data.size)
  119. import_fs.default.writeFileSync(dataPath, JSON.stringify(Object.fromEntries(data.entries()), void 0, 2), "utf8");
  120. import_fs.default.writeFileSync(codePath, code, "utf8");
  121. const serializedCache = _innerAddToCompilationCacheAndSerialize(filename, { codePath, sourceMapPath, dataPath, moduleUrl });
  122. return { serializedCache };
  123. }
  124. };
  125. }
  126. function serializeCompilationCache() {
  127. return {
  128. sourceMaps: [...sourceMaps.entries()],
  129. memoryCache: [...memoryCache.entries()],
  130. fileDependencies: [...fileDependencies.entries()].map(([filename, deps]) => [filename, [...deps]]),
  131. externalDependencies: [...externalDependencies.entries()].map(([filename, deps]) => [filename, [...deps]])
  132. };
  133. }
  134. function addToCompilationCache(payload) {
  135. for (const entry of payload.sourceMaps)
  136. sourceMaps.set(entry[0], entry[1]);
  137. for (const entry of payload.memoryCache)
  138. memoryCache.set(entry[0], entry[1]);
  139. for (const entry of payload.fileDependencies) {
  140. const existing = fileDependencies.get(entry[0]) || [];
  141. fileDependencies.set(entry[0], /* @__PURE__ */ new Set([...entry[1], ...existing]));
  142. }
  143. for (const entry of payload.externalDependencies) {
  144. const existing = externalDependencies.get(entry[0]) || [];
  145. externalDependencies.set(entry[0], /* @__PURE__ */ new Set([...entry[1], ...existing]));
  146. }
  147. }
  148. function calculateCachePath(filePath, hash) {
  149. const fileName = import_path.default.basename(filePath, import_path.default.extname(filePath)).replace(/\W/g, "") + "_" + hash;
  150. return import_path.default.join(cacheDir, hash[0] + hash[1], fileName);
  151. }
  152. let depsCollector;
  153. function startCollectingFileDeps() {
  154. depsCollector = /* @__PURE__ */ new Set();
  155. }
  156. function stopCollectingFileDeps(filename) {
  157. if (!depsCollector)
  158. return;
  159. depsCollector.delete(filename);
  160. for (const dep of depsCollector) {
  161. if (belongsToNodeModules(dep))
  162. depsCollector.delete(dep);
  163. }
  164. fileDependencies.set(filename, depsCollector);
  165. depsCollector = void 0;
  166. }
  167. function currentFileDepsCollector() {
  168. return depsCollector;
  169. }
  170. function setExternalDependencies(filename, deps) {
  171. const depsSet = new Set(deps.filter((dep) => !belongsToNodeModules(dep) && dep !== filename));
  172. externalDependencies.set(filename, depsSet);
  173. }
  174. function fileDependenciesForTest() {
  175. return fileDependencies;
  176. }
  177. function collectAffectedTestFiles(changedFile, testFileCollector) {
  178. const isTestFile = (file) => fileDependencies.has(file);
  179. if (isTestFile(changedFile))
  180. testFileCollector.add(changedFile);
  181. for (const [testFile, deps] of fileDependencies) {
  182. if (deps.has(changedFile))
  183. testFileCollector.add(testFile);
  184. }
  185. for (const [importingFile, depsOfImportingFile] of externalDependencies) {
  186. if (depsOfImportingFile.has(changedFile)) {
  187. if (isTestFile(importingFile))
  188. testFileCollector.add(importingFile);
  189. for (const [testFile, depsOfTestFile] of fileDependencies) {
  190. if (depsOfTestFile.has(importingFile))
  191. testFileCollector.add(testFile);
  192. }
  193. }
  194. }
  195. }
  196. function affectedTestFiles(changes) {
  197. const result = /* @__PURE__ */ new Set();
  198. for (const change of changes)
  199. collectAffectedTestFiles(change, result);
  200. return [...result];
  201. }
  202. function internalDependenciesForTestFile(filename) {
  203. return fileDependencies.get(filename);
  204. }
  205. function dependenciesForTestFile(filename) {
  206. const result = /* @__PURE__ */ new Set();
  207. for (const testDependency of fileDependencies.get(filename) || []) {
  208. result.add(testDependency);
  209. for (const externalDependency of externalDependencies.get(testDependency) || [])
  210. result.add(externalDependency);
  211. }
  212. for (const dep of externalDependencies.get(filename) || [])
  213. result.add(dep);
  214. return result;
  215. }
  216. const kPlaywrightInternalPrefix = import_path.default.resolve(__dirname, "../../../playwright");
  217. function belongsToNodeModules(file) {
  218. if (file.includes(`${import_path.default.sep}node_modules${import_path.default.sep}`))
  219. return true;
  220. if (file.startsWith(kPlaywrightInternalPrefix) && (file.endsWith(".js") || file.endsWith(".mjs")))
  221. return true;
  222. return false;
  223. }
  224. async function getUserData(pluginName) {
  225. const result = /* @__PURE__ */ new Map();
  226. for (const [fileName, cache] of memoryCache) {
  227. if (!cache.dataPath)
  228. continue;
  229. if (!import_fs.default.existsSync(cache.dataPath))
  230. continue;
  231. const data = JSON.parse(await import_fs.default.promises.readFile(cache.dataPath, "utf8"));
  232. if (data[pluginName])
  233. result.set(fileName, data[pluginName]);
  234. }
  235. return result;
  236. }
  237. // Annotate the CommonJS export names for ESM import in node:
  238. 0 && (module.exports = {
  239. addToCompilationCache,
  240. affectedTestFiles,
  241. belongsToNodeModules,
  242. cacheDir,
  243. collectAffectedTestFiles,
  244. currentFileDepsCollector,
  245. dependenciesForTestFile,
  246. fileDependenciesForTest,
  247. getFromCompilationCache,
  248. getUserData,
  249. installSourceMapSupport,
  250. internalDependenciesForTestFile,
  251. serializeCompilationCache,
  252. setExternalDependencies,
  253. startCollectingFileDeps,
  254. stopCollectingFileDeps
  255. });