@crawlee/playwright 4.0.0-beta.251 → 4.0.0-beta.253

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.
@@ -186,8 +186,26 @@ export class AdaptivePlaywrightCrawler extends BasicCrawler {
186
186
  });
187
187
  this.#staticCrawler = staticCrawler;
188
188
  this.#browserCrawler = browserCrawler;
189
- this.#staticContextPipeline = staticCrawler.contextPipeline.compose(this.#adaptCheerioContext.bind(this));
190
- this.#browserContextPipeline = browserCrawler.contextPipeline.compose(this.#adaptPlaywrightContext.bind(this));
189
+ // Each attempt needs its own deferred cleanups, and they must share the attempt's cleanup stack: resources the
190
+ // pipeline defers releasing (the page) have to outlive the user's cleanups, which may still use them.
191
+ const deferredCleanup = ContextPipeline.create().compose((_context, onCleanup) => ({
192
+ registerDeferredCleanup: (cleanup) => {
193
+ onCleanup(async () => {
194
+ try {
195
+ await cleanup();
196
+ }
197
+ catch (error) {
198
+ this.log.debug('Error in deferred cleanup', { error });
199
+ }
200
+ });
201
+ },
202
+ }));
203
+ this.#staticContextPipeline = deferredCleanup
204
+ .chain(staticCrawler.contextPipeline)
205
+ .compose(this.#adaptCheerioContext.bind(this));
206
+ this.#browserContextPipeline = deferredCleanup
207
+ .chain(browserCrawler.contextPipeline)
208
+ .compose(this.#adaptPlaywrightContext.bind(this));
191
209
  }
192
210
  async init() {
193
211
  // A crawler can be run again after a teardown.
@@ -243,9 +261,14 @@ export class AdaptivePlaywrightCrawler extends BasicCrawler {
243
261
  async #adaptPlaywrightContext(playwrightContext) {
244
262
  // Capture the original response to avoid infinite recursion when the getter is copied to the context
245
263
  const originalResponse = playwrightContext.response;
264
+ // `headers()` can return repeated headers (e.g. `set-cookie`) joined with `\n`, which `Headers` rejects
265
+ const headers = new Headers();
266
+ for (const { name, value } of await originalResponse.headersArray()) {
267
+ headers.append(name, value);
268
+ }
246
269
  return {
247
270
  response: new ResponseWithUrl(Uint8Array.from(await originalResponse.body()), {
248
- headers: originalResponse.headers(),
271
+ headers,
249
272
  status: originalResponse.status(),
250
273
  statusText: originalResponse.statusText(),
251
274
  url: originalResponse.url(),
@@ -280,7 +303,6 @@ export class AdaptivePlaywrightCrawler extends BasicCrawler {
280
303
  });
281
304
  transactions.push(transaction);
282
305
  const logs = [];
283
- const deferredCleanup = [];
284
306
  const contextModifications = {
285
307
  request: new MutationJournal(),
286
308
  state: new MutationJournal(),
@@ -290,7 +312,6 @@ export class AdaptivePlaywrightCrawler extends BasicCrawler {
290
312
  request: contextModifications.request.track(request),
291
313
  useState: async (defaultValue) => contextModifications.state.track(await useStateFunction(defaultValue)),
292
314
  log: this.#createLogProxy(context.log, logs),
293
- registerDeferredCleanup: (cleanup) => deferredCleanup.push(cleanup),
294
315
  // The sub-crawler pipeline keeps this attempt's navigation deadline on `subCrawlerContext`, but the
295
316
  // outer `extendTimeout` only pushes the deadline it finds on `context`, so push this one as well.
296
317
  extendTimeout: (secs) => {
@@ -328,9 +349,6 @@ export class AdaptivePlaywrightCrawler extends BasicCrawler {
328
349
  catch (error) {
329
350
  return { ok: false, error, transaction, contextModifications, logs };
330
351
  }
331
- finally {
332
- await Promise.all(deferredCleanup.map((cleanup) => cleanup()));
333
- }
334
352
  }
335
353
  async runRequestHandler(crawlingContext) {
336
354
  const renderingTypePrediction = await this.#renderingTypePredictor.value.predict(crawlingContext.request);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crawlee/playwright",
3
- "version": "4.0.0-beta.251",
3
+ "version": "4.0.0-beta.253",
4
4
  "description": "The scalable web crawling and scraping library for JavaScript/Node.js. Enables development of data extraction and web automation jobs (not only) with headless Chrome and Puppeteer.",
5
5
  "engines": {
6
6
  "node": ">=22.13.0"
@@ -49,14 +49,14 @@
49
49
  "dependencies": {
50
50
  "@apify/datastructures": "^3.0.1",
51
51
  "@apify/timeout": "^1.0.1",
52
- "@crawlee/basic": "4.0.0-beta.251",
53
- "@crawlee/browser": "4.0.0-beta.251",
54
- "@crawlee/browser-pool": "4.0.0-beta.251",
55
- "@crawlee/cheerio": "4.0.0-beta.251",
56
- "@crawlee/core": "4.0.0-beta.251",
57
- "@crawlee/http-client": "4.0.0-beta.251",
58
- "@crawlee/types": "4.0.0-beta.251",
59
- "@crawlee/utils": "4.0.0-beta.251",
52
+ "@crawlee/basic": "4.0.0-beta.253",
53
+ "@crawlee/browser": "4.0.0-beta.253",
54
+ "@crawlee/browser-pool": "4.0.0-beta.253",
55
+ "@crawlee/cheerio": "4.0.0-beta.253",
56
+ "@crawlee/core": "4.0.0-beta.253",
57
+ "@crawlee/http-client": "4.0.0-beta.253",
58
+ "@crawlee/types": "4.0.0-beta.253",
59
+ "@crawlee/utils": "4.0.0-beta.253",
60
60
  "cheerio": "^1.2.0",
61
61
  "domhandler": "^6.0.1",
62
62
  "jquery": "^3.7.1",
@@ -81,5 +81,5 @@
81
81
  }
82
82
  }
83
83
  },
84
- "gitHead": "e8a0d8a538fabf624c73b6354dbf7194882300a5"
84
+ "gitHead": "f93aa3970468c422d9626db0d21175e8a39fdfed"
85
85
  }