debugger.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.Debugger = void 0;
  6. exports.shouldSlowMo = shouldSlowMo;
  7. var _events = require("events");
  8. var _utils = require("../utils");
  9. var _browserContext = require("./browserContext");
  10. var _debug = require("../protocol/debug");
  11. /**
  12. * Copyright (c) Microsoft Corporation.
  13. *
  14. * Licensed under the Apache License, Version 2.0 (the "License");
  15. * you may not use this file except in compliance with the License.
  16. * You may obtain a copy of the License at
  17. *
  18. * http://www.apache.org/licenses/LICENSE-2.0
  19. *
  20. * Unless required by applicable law or agreed to in writing, software
  21. * distributed under the License is distributed on an "AS IS" BASIS,
  22. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  23. * See the License for the specific language governing permissions and
  24. * limitations under the License.
  25. */
  26. const symbol = Symbol('Debugger');
  27. class Debugger extends _events.EventEmitter {
  28. constructor(context) {
  29. super();
  30. this._pauseOnNextStatement = false;
  31. this._pausedCallsMetadata = new Map();
  32. this._enabled = void 0;
  33. this._context = void 0;
  34. this._muted = false;
  35. this._slowMo = void 0;
  36. this._context = context;
  37. this._context[symbol] = this;
  38. this._enabled = (0, _utils.debugMode)() === 'inspector';
  39. if (this._enabled) this.pauseOnNextStatement();
  40. context.instrumentation.addListener(this, context);
  41. this._context.once(_browserContext.BrowserContext.Events.Close, () => {
  42. this._context.instrumentation.removeListener(this);
  43. });
  44. this._slowMo = this._context._browser.options.slowMo;
  45. }
  46. async setMuted(muted) {
  47. this._muted = muted;
  48. }
  49. async onBeforeCall(sdkObject, metadata) {
  50. if (this._muted) return;
  51. if (shouldPauseOnCall(sdkObject, metadata) || this._pauseOnNextStatement && shouldPauseBeforeStep(metadata)) await this.pause(sdkObject, metadata);
  52. }
  53. async _doSlowMo() {
  54. await new Promise(f => setTimeout(f, this._slowMo));
  55. }
  56. async onAfterCall(sdkObject, metadata) {
  57. if (this._slowMo && shouldSlowMo(metadata)) await this._doSlowMo();
  58. }
  59. async onBeforeInputAction(sdkObject, metadata) {
  60. if (this._muted) return;
  61. if (this._enabled && this._pauseOnNextStatement) await this.pause(sdkObject, metadata);
  62. }
  63. async pause(sdkObject, metadata) {
  64. if (this._muted) return;
  65. this._enabled = true;
  66. metadata.pauseStartTime = (0, _utils.monotonicTime)();
  67. const result = new Promise(resolve => {
  68. this._pausedCallsMetadata.set(metadata, {
  69. resolve,
  70. sdkObject
  71. });
  72. });
  73. this.emit(Debugger.Events.PausedStateChanged);
  74. return result;
  75. }
  76. resume(step) {
  77. if (!this.isPaused()) return;
  78. this._pauseOnNextStatement = step;
  79. const endTime = (0, _utils.monotonicTime)();
  80. for (const [metadata, {
  81. resolve
  82. }] of this._pausedCallsMetadata) {
  83. metadata.pauseEndTime = endTime;
  84. resolve();
  85. }
  86. this._pausedCallsMetadata.clear();
  87. this.emit(Debugger.Events.PausedStateChanged);
  88. }
  89. pauseOnNextStatement() {
  90. this._pauseOnNextStatement = true;
  91. }
  92. isPaused(metadata) {
  93. if (metadata) return this._pausedCallsMetadata.has(metadata);
  94. return !!this._pausedCallsMetadata.size;
  95. }
  96. pausedDetails() {
  97. const result = [];
  98. for (const [metadata, {
  99. sdkObject
  100. }] of this._pausedCallsMetadata) result.push({
  101. metadata,
  102. sdkObject
  103. });
  104. return result;
  105. }
  106. }
  107. exports.Debugger = Debugger;
  108. Debugger.Events = {
  109. PausedStateChanged: 'pausedstatechanged'
  110. };
  111. function shouldPauseOnCall(sdkObject, metadata) {
  112. var _sdkObject$attributio;
  113. if (sdkObject.attribution.playwright.options.isServer) return false;
  114. if (!((_sdkObject$attributio = sdkObject.attribution.browser) !== null && _sdkObject$attributio !== void 0 && _sdkObject$attributio.options.headful) && !(0, _utils.isUnderTest)()) return false;
  115. return metadata.method === 'pause';
  116. }
  117. function shouldPauseBeforeStep(metadata) {
  118. // Don't stop on internal.
  119. if (!metadata.apiName) return false;
  120. // Always stop on 'close'
  121. if (metadata.method === 'close') return true;
  122. if (metadata.method === 'waitForSelector' || metadata.method === 'waitForEventInfo') return false; // Never stop on those, primarily for the test harness.
  123. const step = metadata.type + '.' + metadata.method;
  124. // Stop before everything that generates snapshot. But don't stop before those marked as pausesBeforeInputActions
  125. // since we stop in them on a separate instrumentation signal.
  126. return _debug.commandsWithTracingSnapshots.has(step) && !_debug.pausesBeforeInputActions.has(metadata.type + '.' + metadata.method);
  127. }
  128. function shouldSlowMo(metadata) {
  129. return _debug.slowMoActions.has(metadata.type + '.' + metadata.method);
  130. }