playwrightConnection.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. "use strict";
  2. var __defProp = Object.defineProperty;
  3. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  4. var __getOwnPropNames = Object.getOwnPropertyNames;
  5. var __hasOwnProp = Object.prototype.hasOwnProperty;
  6. var __export = (target, all) => {
  7. for (var name in all)
  8. __defProp(target, name, { get: all[name], enumerable: true });
  9. };
  10. var __copyProps = (to, from, except, desc) => {
  11. if (from && typeof from === "object" || typeof from === "function") {
  12. for (let key of __getOwnPropNames(from))
  13. if (!__hasOwnProp.call(to, key) && key !== except)
  14. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  15. }
  16. return to;
  17. };
  18. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  19. var playwrightConnection_exports = {};
  20. __export(playwrightConnection_exports, {
  21. PlaywrightConnection: () => PlaywrightConnection
  22. });
  23. module.exports = __toCommonJS(playwrightConnection_exports);
  24. var import_server = require("../server");
  25. var import_android = require("../server/android/android");
  26. var import_browser = require("../server/browser");
  27. var import_debugControllerDispatcher = require("../server/dispatchers/debugControllerDispatcher");
  28. var import_profiler = require("../server/utils/profiler");
  29. var import_utils = require("../utils");
  30. var import_debugLogger = require("../server/utils/debugLogger");
  31. class PlaywrightConnection {
  32. constructor(semaphore, ws, controller, playwright, initialize, id) {
  33. this._cleanups = [];
  34. this._disconnected = false;
  35. this._ws = ws;
  36. this._semaphore = semaphore;
  37. this._id = id;
  38. this._profileName = (/* @__PURE__ */ new Date()).toISOString();
  39. const lock = this._semaphore.acquire();
  40. this._dispatcherConnection = new import_server.DispatcherConnection();
  41. this._dispatcherConnection.onmessage = async (message) => {
  42. await lock;
  43. if (ws.readyState !== ws.CLOSING) {
  44. const messageString = JSON.stringify(message);
  45. if (import_debugLogger.debugLogger.isEnabled("server:channel"))
  46. import_debugLogger.debugLogger.log("server:channel", `[${this._id}] ${(0, import_utils.monotonicTime)() * 1e3} SEND \u25BA ${messageString}`);
  47. if (import_debugLogger.debugLogger.isEnabled("server:metadata"))
  48. this.logServerMetadata(message, messageString, "SEND");
  49. ws.send(messageString);
  50. }
  51. };
  52. ws.on("message", async (message) => {
  53. await lock;
  54. const messageString = Buffer.from(message).toString();
  55. const jsonMessage = JSON.parse(messageString);
  56. if (import_debugLogger.debugLogger.isEnabled("server:channel"))
  57. import_debugLogger.debugLogger.log("server:channel", `[${this._id}] ${(0, import_utils.monotonicTime)() * 1e3} \u25C0 RECV ${messageString}`);
  58. if (import_debugLogger.debugLogger.isEnabled("server:metadata"))
  59. this.logServerMetadata(jsonMessage, messageString, "RECV");
  60. this._dispatcherConnection.dispatch(jsonMessage);
  61. });
  62. ws.on("close", () => this._onDisconnect());
  63. ws.on("error", (error) => this._onDisconnect(error));
  64. if (controller) {
  65. import_debugLogger.debugLogger.log("server", `[${this._id}] engaged reuse controller mode`);
  66. this._root = new import_debugControllerDispatcher.DebugControllerDispatcher(this._dispatcherConnection, playwright.debugController);
  67. return;
  68. }
  69. this._root = new import_server.RootDispatcher(this._dispatcherConnection, async (scope, params) => {
  70. await (0, import_profiler.startProfiling)();
  71. const options = await initialize();
  72. if (options.preLaunchedBrowser) {
  73. const browser = options.preLaunchedBrowser;
  74. browser.options.sdkLanguage = params.sdkLanguage;
  75. browser.on(import_browser.Browser.Events.Disconnected, () => {
  76. this.close({ code: 1001, reason: "Browser closed" });
  77. });
  78. }
  79. if (options.preLaunchedAndroidDevice) {
  80. const androidDevice = options.preLaunchedAndroidDevice;
  81. androidDevice.on(import_android.AndroidDevice.Events.Close, () => {
  82. this.close({ code: 1001, reason: "Android device disconnected" });
  83. });
  84. }
  85. if (options.dispose)
  86. this._cleanups.push(options.dispose);
  87. const dispatcher = new import_server.PlaywrightDispatcher(scope, playwright, options);
  88. this._cleanups.push(() => dispatcher.cleanup());
  89. return dispatcher;
  90. });
  91. }
  92. async _onDisconnect(error) {
  93. this._disconnected = true;
  94. import_debugLogger.debugLogger.log("server", `[${this._id}] disconnected. error: ${error}`);
  95. await this._root.stopPendingOperations(new Error("Disconnected")).catch(() => {
  96. });
  97. this._root._dispose();
  98. import_debugLogger.debugLogger.log("server", `[${this._id}] starting cleanup`);
  99. for (const cleanup of this._cleanups)
  100. await cleanup().catch(() => {
  101. });
  102. await (0, import_profiler.stopProfiling)(this._profileName);
  103. this._semaphore.release();
  104. import_debugLogger.debugLogger.log("server", `[${this._id}] finished cleanup`);
  105. }
  106. logServerMetadata(message, messageString, direction) {
  107. const serverLogMetadata = {
  108. wallTime: Date.now(),
  109. id: message.id,
  110. guid: message.guid,
  111. method: message.method,
  112. payloadSizeInBytes: Buffer.byteLength(messageString, "utf-8")
  113. };
  114. import_debugLogger.debugLogger.log("server:metadata", (direction === "SEND" ? "SEND \u25BA " : "\u25C0 RECV ") + JSON.stringify(serverLogMetadata));
  115. }
  116. async close(reason) {
  117. if (this._disconnected)
  118. return;
  119. import_debugLogger.debugLogger.log("server", `[${this._id}] force closing connection: ${reason?.reason || ""} (${reason?.code || 0})`);
  120. try {
  121. this._ws.close(reason?.code, reason?.reason);
  122. } catch (e) {
  123. }
  124. }
  125. }
  126. // Annotate the CommonJS export names for ESM import in node:
  127. 0 && (module.exports = {
  128. PlaywrightConnection
  129. });