@checkly/playwright-core 1.41.2-beta.1 → 1.41.2-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/lib/checkly/fetch.js +106 -0
  2. package/lib/client/fetch.js +12 -1
  3. package/lib/protocol/validator.js +23 -2
  4. package/lib/server/chromium/crNetworkManager.js +27 -12
  5. package/lib/server/chromium/videoRecorder.js +1 -1
  6. package/lib/server/dispatchers/frameDispatcher.js +6 -0
  7. package/lib/server/dispatchers/networkDispatchers.js +8 -1
  8. package/lib/server/fetch.js +26 -3
  9. package/lib/server/network.js +5 -23
  10. package/lib/utils/happy-eyeballs.js +17 -1
  11. package/lib/vite/recorder/assets/codeMirrorModule-85487eb6.js +24 -0
  12. package/lib/vite/recorder/assets/{index-bbf80321.js → index-b14c63fe.js} +1 -1
  13. package/lib/vite/recorder/index.html +1 -1
  14. package/lib/vite/{recorder/assets/codeMirrorModule-2a26f817.js → traceViewer/assets/codeMirrorModule-75b0ca4f.js} +13 -13
  15. package/lib/vite/traceViewer/assets/codeMirrorModule-c1454a2e.js +24 -0
  16. package/lib/vite/traceViewer/assets/codeMirrorModule-f333a775.js +24 -0
  17. package/lib/vite/traceViewer/assets/wsPort-762c6840.js +64 -0
  18. package/lib/vite/traceViewer/assets/wsPort-98e00a94.js +64 -0
  19. package/lib/vite/traceViewer/assets/wsPort-ee2830d7.js +64 -0
  20. package/lib/vite/traceViewer/index.a265fbdb.js +2 -0
  21. package/lib/vite/traceViewer/index.decad628.js +2 -0
  22. package/lib/vite/traceViewer/index.ed9a3c58.js +2 -0
  23. package/lib/vite/traceViewer/index.html +2 -2
  24. package/lib/vite/traceViewer/uiMode.08ab2d90.js +4 -0
  25. package/lib/vite/traceViewer/uiMode.0d0d667b.js +4 -0
  26. package/lib/vite/traceViewer/uiMode.3ff70f7d.js +4 -0
  27. package/lib/vite/traceViewer/uiMode.html +2 -2
  28. package/package.json +1 -1
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.setSWatcherCurrentStepData = exports.parseQueryParameters = exports.initializeTimings = exports.getTimings = exports.getRequestHeaders = exports.getClientCertificates = exports.getBody = exports.addRequestListeners = void 0;
7
+ /**
8
+ * Get client custom certificates.
9
+ *
10
+ * @param {Object} options
11
+ * @returns Object
12
+ */
13
+ const getClientCertificates = options => {
14
+ if (!options.certs) return {};
15
+ return {
16
+ cert: options.cert,
17
+ key: options.key,
18
+ passphrase: options.passphrase,
19
+ ca: options.ca
20
+ };
21
+ };
22
+ exports.getClientCertificates = getClientCertificates;
23
+ const setSWatcherCurrentStepData = (sWatcher, result) => {
24
+ if (!sWatcher) return;
25
+ sWatcher.appendCurrentStepData({
26
+ ...result.response,
27
+ checklyStepCategory: 'api-call'
28
+ });
29
+ };
30
+ exports.setSWatcherCurrentStepData = setSWatcherCurrentStepData;
31
+ const getRequestHeaders = headers => {
32
+ return Object.entries(headers).map(([key, value]) => {
33
+ return {
34
+ name: key,
35
+ value: value
36
+ };
37
+ });
38
+ };
39
+ exports.getRequestHeaders = getRequestHeaders;
40
+ const parseQueryParameters = url => {
41
+ const searchParams = new URL(url).searchParams;
42
+ const parameters = [];
43
+ for (const [name, value] of searchParams.entries()) {
44
+ parameters.push({
45
+ name,
46
+ value
47
+ });
48
+ }
49
+ return parameters;
50
+ };
51
+ exports.parseQueryParameters = parseQueryParameters;
52
+ const getTimings = eventTimes => {
53
+ const {
54
+ agent,
55
+ values
56
+ } = eventTimes;
57
+ const end = performance.now() - values.startTimeNow;
58
+ const socket = values.socket || 0;
59
+ const lookup = values.lookup || socket;
60
+ const connect = values.connect || lookup;
61
+ const response = values.response || connect;
62
+ return {
63
+ wait: agent ? socket - lookup : socket,
64
+ dns: agent ? lookup : lookup - socket,
65
+ tcp: agent ? connect - socket : connect - lookup,
66
+ firstByte: response - connect,
67
+ download: end - response,
68
+ total: end
69
+ };
70
+ };
71
+ exports.getTimings = getTimings;
72
+ const getBody = body => {
73
+ const responseBodySizeLimit = 100000;
74
+ //@ts-ignore
75
+ const bodyAsText = Buffer.byteLength(body, 'utf-8') > responseBodySizeLimit ? body.slice(0, responseBodySizeLimit).toString('utf8') + '...' : body.toString('utf8');
76
+ try {
77
+ return JSON.parse(bodyAsText);
78
+ } catch {
79
+ return bodyAsText;
80
+ }
81
+ };
82
+ exports.getBody = getBody;
83
+ const initializeTimings = () => {
84
+ return {
85
+ values: {
86
+ startTimeNow: performance.now()
87
+ },
88
+ agent: false
89
+ };
90
+ };
91
+ exports.initializeTimings = initializeTimings;
92
+ const addRequestListeners = (request, timings) => {
93
+ request.on('socket', socket => {
94
+ timings.values.socket = performance.now() - timings.values.startTimeNow;
95
+ socket.on('connect', () => {
96
+ timings.values.connect = performance.now() - timings.values.startTimeNow;
97
+ });
98
+ socket.on('lookup', () => {
99
+ timings.values.lookup = performance.now() - timings.values.startTimeNow;
100
+ });
101
+ socket.on('secureConnect', () => {
102
+ timings.values.tlsHandshake = performance.now() - timings.values.startTimeNow;
103
+ });
104
+ });
105
+ };
106
+ exports.addRequestListeners = addRequestListeners;
@@ -13,6 +13,7 @@ var _channelOwner = require("./channelOwner");
13
13
  var _network = require("./network");
14
14
  var _tracing = require("./tracing");
15
15
  var _errors = require("./errors");
16
+ var _fetch = require("playwright-core/lib/checkly/fetch");
16
17
  let _Symbol$asyncDispose, _Symbol$asyncDispose2, _util$inspect$custom;
17
18
  /**
18
19
  * Copyright (c) Microsoft Corporation.
@@ -55,6 +56,9 @@ class APIRequest {
55
56
  storageState,
56
57
  tracesDir
57
58
  })).request);
59
+ // Checkly related code.
60
+ //@ts-ignore
61
+ context.__sWatcher__ = options.sWatcher;
58
62
  this._contexts.add(context);
59
63
  context._request = this;
60
64
  context._tracing._tracesDir = tracesDir;
@@ -198,8 +202,12 @@ class APIRequestContext extends _channelOwner.ChannelOwner {
198
202
  failOnStatusCode: options.failOnStatusCode,
199
203
  ignoreHTTPSErrors: options.ignoreHTTPSErrors,
200
204
  maxRedirects: maxRedirects,
201
- ...fixtures
205
+ tokenizedURL: options.tokenizedURL,
206
+ ...fixtures,
207
+ ...(0, _fetch.getClientCertificates)(options)
202
208
  });
209
+ //@ts-ignore
210
+ (0, _fetch.setSWatcherCurrentStepData)(this.__sWatcher__, result);
203
211
  return new APIResponse(this, result.response);
204
212
  });
205
213
  }
@@ -251,6 +259,9 @@ class APIResponse {
251
259
  headersArray() {
252
260
  return this._headers.headersArray();
253
261
  }
262
+ timings() {
263
+ return this._initializer.timings;
264
+ }
254
265
  async body() {
255
266
  try {
256
267
  const result = await this._request._channel.fetchResponseBody({
@@ -207,7 +207,12 @@ _validatorPrimitives.scheme.APIRequestContextFetchParams = (0, _validatorPrimiti
207
207
  timeout: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tNumber),
208
208
  failOnStatusCode: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tBoolean),
209
209
  ignoreHTTPSErrors: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tBoolean),
210
- maxRedirects: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tNumber)
210
+ maxRedirects: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tNumber),
211
+ tokenizedURL: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tString),
212
+ cert: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tString),
213
+ key: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tString),
214
+ ca: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tString),
215
+ passphrase: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tString)
211
216
  });
212
217
  _validatorPrimitives.scheme.APIRequestContextFetchResult = (0, _validatorPrimitives.tObject)({
213
218
  response: (0, _validatorPrimitives.tType)('APIResponse')
@@ -240,7 +245,23 @@ _validatorPrimitives.scheme.APIResponse = (0, _validatorPrimitives.tObject)({
240
245
  url: _validatorPrimitives.tString,
241
246
  status: _validatorPrimitives.tNumber,
242
247
  statusText: _validatorPrimitives.tString,
243
- headers: (0, _validatorPrimitives.tArray)((0, _validatorPrimitives.tType)('NameValue'))
248
+ headers: (0, _validatorPrimitives.tArray)((0, _validatorPrimitives.tType)('NameValue')),
249
+ requestHeaders: (0, _validatorPrimitives.tArray)((0, _validatorPrimitives.tType)('NameValue')),
250
+ responseHeaders: (0, _validatorPrimitives.tArray)((0, _validatorPrimitives.tType)('NameValue')),
251
+ body: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tAny),
252
+ method: _validatorPrimitives.tString,
253
+ tokenizedURL: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tString),
254
+ timings: (0, _validatorPrimitives.tObject)({
255
+ wait: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tNumber),
256
+ dns: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tNumber),
257
+ lookup: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tNumber),
258
+ connect: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tNumber),
259
+ tcp: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tNumber),
260
+ firstByte: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tNumber),
261
+ download: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tNumber),
262
+ total: (0, _validatorPrimitives.tOptional)(_validatorPrimitives.tNumber)
263
+ }),
264
+ queryParams: (0, _validatorPrimitives.tOptional)((0, _validatorPrimitives.tArray)((0, _validatorPrimitives.tType)('NameValue')))
244
265
  });
245
266
  _validatorPrimitives.scheme.LifecycleEvent = (0, _validatorPrimitives.tEnum)(['load', 'domcontentloaded', 'networkidle', 'commit']);
246
267
  _validatorPrimitives.scheme.LocalUtilsInitializer = (0, _validatorPrimitives.tObject)({
@@ -8,6 +8,7 @@ var _helper = require("../helper");
8
8
  var _eventsHelper = require("../../utils/eventsHelper");
9
9
  var network = _interopRequireWildcard(require("../network"));
10
10
  var _utils = require("../../utils");
11
+ var _protocolError = require("../protocolError");
11
12
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
12
13
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
13
14
  /**
@@ -543,30 +544,44 @@ class RouteImpl {
543
544
  method: overrides.method,
544
545
  postData: overrides.postData ? overrides.postData.toString('base64') : undefined
545
546
  };
546
- await this._session.send('Fetch.continueRequest', this._alreadyContinuedParams);
547
+ await catchDisallowedErrors(async () => {
548
+ await this._session.send('Fetch.continueRequest', this._alreadyContinuedParams);
549
+ });
547
550
  }
548
551
  async fulfill(response) {
549
552
  const body = response.isBase64 ? response.body : Buffer.from(response.body).toString('base64');
550
553
  const responseHeaders = splitSetCookieHeader(response.headers);
551
- await this._session.send('Fetch.fulfillRequest', {
552
- requestId: this._interceptionId,
553
- responseCode: response.status,
554
- responsePhrase: network.STATUS_TEXTS[String(response.status)],
555
- responseHeaders,
556
- body
554
+ await catchDisallowedErrors(async () => {
555
+ await this._session.send('Fetch.fulfillRequest', {
556
+ requestId: this._interceptionId,
557
+ responseCode: response.status,
558
+ responsePhrase: network.STATUS_TEXTS[String(response.status)],
559
+ responseHeaders,
560
+ body
561
+ });
557
562
  });
558
563
  }
559
564
  async abort(errorCode = 'failed') {
560
565
  const errorReason = errorReasons[errorCode];
561
566
  (0, _utils.assert)(errorReason, 'Unknown error code: ' + errorCode);
562
- // In certain cases, protocol will return error if the request was already canceled
563
- // or the page was closed. We should tolerate these errors.
564
- await this._session._sendMayFail('Fetch.failRequest', {
565
- requestId: this._interceptionId,
566
- errorReason
567
+ await catchDisallowedErrors(async () => {
568
+ await this._session.send('Fetch.failRequest', {
569
+ requestId: this._interceptionId,
570
+ errorReason
571
+ });
567
572
  });
568
573
  }
569
574
  }
575
+
576
+ // In certain cases, protocol will return error if the request was already canceled
577
+ // or the page was closed. We should tolerate these errors but propagate other.
578
+ async function catchDisallowedErrors(callback) {
579
+ try {
580
+ return await callback();
581
+ } catch (e) {
582
+ if ((0, _protocolError.isProtocolError)(e) && e.message.includes('Invalid http status code or phrase')) throw e;
583
+ }
584
+ }
570
585
  function splitSetCookieHeader(headers) {
571
586
  const index = headers.findIndex(({
572
587
  name
@@ -25,7 +25,7 @@ var _instrumentation = require("../instrumentation");
25
25
  * limitations under the License.
26
26
  */
27
27
 
28
- const fps = 25;
28
+ const fps = 12;
29
29
  class VideoRecorder {
30
30
  static async launch(page, ffmpegPath, options) {
31
31
  if (!options.outputFile.endsWith('.webm')) throw new Error('File must have .webm extension');
@@ -281,6 +281,12 @@ class FrameDispatcher extends _dispatcher.Dispatcher {
281
281
  expectedValue
282
282
  });
283
283
  if (result.received !== undefined) result.received = (0, _jsHandleDispatcher.serializeResult)(result.received);
284
+ if (result.matches === params.isNot) metadata.error = {
285
+ error: {
286
+ name: 'Expect',
287
+ message: 'Expect failed'
288
+ }
289
+ };
284
290
  return result;
285
291
  }
286
292
  }
@@ -199,7 +199,14 @@ class APIRequestContextDispatcher extends _dispatcher.Dispatcher {
199
199
  status: fetchResponse.status,
200
200
  statusText: fetchResponse.statusText,
201
201
  headers: fetchResponse.headers,
202
- fetchUid: fetchResponse.fetchUid
202
+ fetchUid: fetchResponse.fetchUid,
203
+ requestHeaders: fetchResponse.requestHeaders,
204
+ responseHeaders: fetchResponse.responseHeaders,
205
+ timings: fetchResponse.timings,
206
+ queryParams: fetchResponse.queryParams,
207
+ body: fetchResponse.body,
208
+ method: fetchResponse.method,
209
+ tokenizedURL: fetchResponse.tokenizedURL
203
210
  }
204
211
  };
205
212
  }
@@ -9,6 +9,7 @@ var https = _interopRequireWildcard(require("https"));
9
9
  var _stream = require("stream");
10
10
  var _url = _interopRequireDefault(require("url"));
11
11
  var _zlib = _interopRequireDefault(require("zlib"));
12
+ var _perf_hooks = require("perf_hooks");
12
13
  var _timeoutSettings = require("../common/timeoutSettings");
13
14
  var _userAgent = require("../utils/userAgent");
14
15
  var _utils = require("../utils");
@@ -21,6 +22,7 @@ var _instrumentation = require("./instrumentation");
21
22
  var _progress = require("./progress");
22
23
  var _tracing = require("./trace/recorder/tracing");
23
24
  var _network = require("./network");
25
+ var _fetch = require("playwright-core/lib/checkly/fetch");
24
26
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
27
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
26
28
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -124,7 +126,9 @@ class APIRequestContext extends _instrumentation.SdkObject {
124
126
  maxRedirects: params.maxRedirects === 0 ? -1 : params.maxRedirects === undefined ? 20 : params.maxRedirects,
125
127
  timeout,
126
128
  deadline,
127
- __testHookLookup: params.__testHookLookup
129
+ __testHookLookup: params.__testHookLookup,
130
+ tokenizedURL: params.tokenizedURL,
131
+ ...(0, _fetch.getClientCertificates)(params)
128
132
  };
129
133
  // rejectUnauthorized = undefined is treated as true in node 12.
130
134
  if (params.ignoreHTTPSErrors || defaults.ignoreHTTPSErrors) options.rejectUnauthorized = false;
@@ -139,7 +143,14 @@ class APIRequestContext extends _instrumentation.SdkObject {
139
143
  if (params.failOnStatusCode && (fetchResponse.status < 200 || fetchResponse.status >= 400)) throw new Error(`${fetchResponse.status} ${fetchResponse.statusText}`);
140
144
  return {
141
145
  ...fetchResponse,
142
- fetchUid
146
+ fetchUid,
147
+ requestHeaders: (0, _fetch.getRequestHeaders)(headers),
148
+ responseHeaders: fetchResponse.headers,
149
+ queryParams: (0, _fetch.parseQueryParameters)(fetchResponse.url),
150
+ url: params.tokenizedURL || fetchResponse.url,
151
+ timings: (0, _fetch.getTimings)(fetchResponse.timings),
152
+ body: (0, _fetch.getBody)(fetchResponse.body),
153
+ method: options.method
143
154
  };
144
155
  }
145
156
  _parseSetCookieHeader(responseUrl, setCookie) {
@@ -195,7 +206,9 @@ class APIRequestContext extends _instrumentation.SdkObject {
195
206
  ...options,
196
207
  agent
197
208
  };
209
+ const timings = (0, _fetch.initializeTimings)();
198
210
  const request = requestConstructor(url, requestOptions, async response => {
211
+ timings.values.response = _perf_hooks.performance.now() - timings.values.startTimeNow;
199
212
  const notifyRequestFinished = body => {
200
213
  const requestFinishedEvent = {
201
214
  requestEvent,
@@ -292,6 +305,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
292
305
  response.on('aborted', () => reject(new Error('aborted')));
293
306
  const chunks = [];
294
307
  const notifyBodyFinished = () => {
308
+ timings.values.endAt = _perf_hooks.performance.now();
295
309
  const body = Buffer.concat(chunks);
296
310
  notifyRequestFinished(body);
297
311
  fulfill({
@@ -299,7 +313,15 @@ class APIRequestContext extends _instrumentation.SdkObject {
299
313
  status: response.statusCode || 0,
300
314
  statusText: response.statusMessage || '',
301
315
  headers: toHeadersArray(response.rawHeaders),
302
- body
316
+ body,
317
+ timings: {
318
+ //@ts-ignore
319
+ values: {
320
+ ...timings.values,
321
+ ..._happyEyeballs.httpHappyEyeballsTimings.values
322
+ },
323
+ agent: _happyEyeballs.httpHappyEyeballsTimings.agent || timings.agent
324
+ }
303
325
  });
304
326
  };
305
327
  let body = response;
@@ -328,6 +350,7 @@ class APIRequestContext extends _instrumentation.SdkObject {
328
350
  body.on('data', chunk => chunks.push(chunk));
329
351
  body.on('end', notifyBodyFinished);
330
352
  });
353
+ (0, _fetch.addRequestListeners)(request, timings);
331
354
  request.on('error', reject);
332
355
  const disposeListener = () => {
333
356
  reject(new Error('Request context disposed.'));
@@ -126,15 +126,6 @@ class Request extends _instrumentation.SdkObject {
126
126
  this._failureText = failureText;
127
127
  this._waitForResponsePromise.resolve(null);
128
128
  }
129
- async _waitForRequestFailure() {
130
- const response = await this._waitForResponsePromise;
131
- // If response is null it was a failure an we are done.
132
- if (!response) return;
133
- await response._finishedPromise;
134
- if (this.failure()) return;
135
- // If request finished without errors, we stall.
136
- await new Promise(() => {});
137
- }
138
129
  _setOverrides(overrides) {
139
130
  this._overrides = overrides;
140
131
  this._updateHeadersMap();
@@ -241,10 +232,7 @@ class Route extends _instrumentation.SdkObject {
241
232
  async abort(errorCode = 'failed') {
242
233
  this._startHandling();
243
234
  this._request._context.emit(_browserContext.BrowserContext.Events.RequestAborted, this._request);
244
- await Promise.race([this._delegate.abort(errorCode),
245
- // If the request is already cancelled by the page before we handle the route,
246
- // we'll receive loading failed event and will ignore route handling error.
247
- this._request._waitForRequestFailure()]);
235
+ await this._delegate.abort(errorCode);
248
236
  this._endHandling();
249
237
  }
250
238
  async redirectNavigationRequest(url) {
@@ -270,15 +258,12 @@ class Route extends _instrumentation.SdkObject {
270
258
  const headers = [...(overrides.headers || [])];
271
259
  this._maybeAddCorsHeaders(headers);
272
260
  this._request._context.emit(_browserContext.BrowserContext.Events.RequestFulfilled, this._request);
273
- await Promise.race([this._delegate.fulfill({
261
+ await this._delegate.fulfill({
274
262
  status: overrides.status || 200,
275
263
  headers,
276
- body,
264
+ body: body,
277
265
  isBase64
278
- }),
279
- // If the request is already cancelled by the page before we handle the route,
280
- // we'll receive loading failed event and will ignore route handling error.
281
- this._request._waitForRequestFailure()]);
266
+ });
282
267
  this._endHandling();
283
268
  }
284
269
 
@@ -315,10 +300,7 @@ class Route extends _instrumentation.SdkObject {
315
300
  }
316
301
  this._request._setOverrides(overrides);
317
302
  if (!overrides.isFallback) this._request._context.emit(_browserContext.BrowserContext.Events.RequestContinued, this._request);
318
- await Promise.race([this._delegate.continue(this._request, overrides),
319
- // If the request is already cancelled by the page before we handle the route,
320
- // we'll receive loading failed event and will ignore route handling error.
321
- this._request._waitForRequestFailure()]);
303
+ await this._delegate.continue(this._request, overrides);
322
304
  this._endHandling();
323
305
  }
324
306
  _startHandling() {
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.createSocket = createSocket;
7
- exports.httpsHappyEyeballsAgent = exports.httpHappyEyeballsAgent = void 0;
7
+ exports.httpsHappyEyeballsAgent = exports.httpHappyEyeballsTimings = exports.httpHappyEyeballsAgent = void 0;
8
8
  var dns = _interopRequireWildcard(require("dns"));
9
9
  var http = _interopRequireWildcard(require("http"));
10
10
  var https = _interopRequireWildcard(require("https"));
@@ -33,6 +33,15 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
33
33
  // https://www.rfc-editor.org/rfc/rfc8305
34
34
  // Same as in Chromium (https://source.chromium.org/chromium/chromium/src/+/5666ff4f5077a7e2f72902f3a95f5d553ea0d88d:net/socket/transport_connect_job.cc;l=102)
35
35
  const connectionAttemptDelayMs = 300;
36
+ const timings = {
37
+ values: {
38
+ startTimeNow: 0,
39
+ socket: 0,
40
+ connect: 0,
41
+ lookup: 0
42
+ },
43
+ agent: false
44
+ };
36
45
  class HttpHappyEyeballsAgent extends http.Agent {
37
46
  createConnection(options, oncreate) {
38
47
  // There is no ambiguity in case of IP address.
@@ -42,6 +51,8 @@ class HttpHappyEyeballsAgent extends http.Agent {
42
51
  }
43
52
  class HttpsHappyEyeballsAgent extends https.Agent {
44
53
  createConnection(options, oncreate) {
54
+ timings.values.startTimeNow = performance.now();
55
+ timings.agent = true;
45
56
  // There is no ambiguity in case of IP address.
46
57
  if (net.isIP(clientRequestArgsToHostName(options))) return tls.connect(options);
47
58
  createConnectionAsync(options, oncreate, /* useTLS */true).catch(err => oncreate === null || oncreate === void 0 ? void 0 : oncreate(err));
@@ -49,6 +60,7 @@ class HttpsHappyEyeballsAgent extends https.Agent {
49
60
  }
50
61
  const httpsHappyEyeballsAgent = exports.httpsHappyEyeballsAgent = new HttpsHappyEyeballsAgent();
51
62
  const httpHappyEyeballsAgent = exports.httpHappyEyeballsAgent = new HttpHappyEyeballsAgent();
63
+ const httpHappyEyeballsTimings = exports.httpHappyEyeballsTimings = timings;
52
64
  async function createSocket(host, port) {
53
65
  return new Promise((resolve, reject) => {
54
66
  if (net.isIP(host)) {
@@ -97,10 +109,13 @@ async function createConnectionAsync(options, oncreate, useTLS) {
97
109
  port: options.port,
98
110
  host: address
99
111
  });
112
+ // Socket created
113
+ timings.values.socket = performance.now() - timings.values.startTimeNow;
100
114
 
101
115
  // Each socket may fire only one of 'connect', 'timeout' or 'error' events.
102
116
  // None of these events are fired after socket.destroy() is called.
103
117
  socket.on('connect', () => {
118
+ timings.values.connect = performance.now() - timings.values.startTimeNow;
104
119
  connected.resolve();
105
120
  oncreate === null || oncreate === void 0 ? void 0 : oncreate(null, socket);
106
121
  // TODO: Cache the result?
@@ -126,6 +141,7 @@ async function lookupAddresses(hostname) {
126
141
  family: 0,
127
142
  verbatim: true
128
143
  });
144
+ timings.values.lookup = performance.now() - timings.values.startTimeNow;
129
145
  let firstFamily = addresses.filter(({
130
146
  family
131
147
  }) => family === 6);