@@ -150,7 +150,7 @@ export interface AdaptivePlaywrightCrawlerContext<UserData extends Dictionary =
150150 */
151151 parseWithCheerio ( selector ?: string , timeoutMs ?: number ) : Promise < CheerioRoot > ;
152152
153- enqueueLinks ( options ?: EnqueueLinksOptions ) : Promise < void > ;
153+ enqueueLinks ( options ?: EnqueueLinksOptions ) : Promise < unknown > ;
154154}
155155
156156interface AdaptiveHook
@@ -299,17 +299,11 @@ export class AdaptivePlaywrightCrawler<
299299
300300 super ( {
301301 ...rest ,
302- // Pass error handlers to the "main" crawler - we only pluck them from `rest` so that they don't go to the sub crawlers
303302 errorHandler,
304303 failedRequestHandler,
305- // Same for request handler
306304 requestHandler,
307- // The builder intentionally returns null so that it crashes the crawler when it tries to use this instead of one of two the specialized context pipelines
308- // (that would be a logical error in this class)
309- contextPipelineBuilder : ( ) =>
310- null as unknown as ContextPipeline < CrawlingContext , AdaptivePlaywrightCrawlerContext > ,
305+ contextPipelineBuilder : contextPipelineBuilder ?? ( ( ) => this . buildContextPipeline ( ) ) ,
311306 } ) ;
312-
313307 this . individualRequestHandlerTimeoutMillis = requestHandlerTimeoutSecs * 1000 ;
314308
315309 this . renderingTypePredictor =
@@ -408,6 +402,34 @@ export class AdaptivePlaywrightCrawler<
408402 return await super . _init ( ) ;
409403 }
410404
405+ protected override buildContextPipeline ( ) {
406+ const errorMessage = ( prop : string ) =>
407+ `The \`${ prop } \` property is not available on the outer context pipeline of AdaptivePlaywrightCrawler - it is provided by the inner (static/browser) pipelines` ;
408+
409+ return super . buildContextPipeline ( ) . compose ( {
410+ action : async ( { request } ) => ( {
411+ get request ( ) : LoadedRequest < Request < Dictionary > > {
412+ return request as LoadedRequest < Request < Dictionary > > ;
413+ } ,
414+ get response ( ) : Response {
415+ throw new Error ( errorMessage ( 'response' ) ) ;
416+ } ,
417+ get page ( ) : Page {
418+ throw new Error ( errorMessage ( 'page' ) ) ;
419+ } ,
420+ get querySelector ( ) : AdaptivePlaywrightCrawlerContext [ 'querySelector' ] {
421+ throw new Error ( errorMessage ( 'querySelector' ) ) ;
422+ } ,
423+ get waitForSelector ( ) : AdaptivePlaywrightCrawlerContext [ 'waitForSelector' ] {
424+ throw new Error ( errorMessage ( 'waitForSelector' ) ) ;
425+ } ,
426+ get parseWithCheerio ( ) : AdaptivePlaywrightCrawlerContext [ 'parseWithCheerio' ] {
427+ throw new Error ( errorMessage ( 'parseWithCheerio' ) ) ;
428+ } ,
429+ } ) ,
430+ } ) ;
431+ }
432+
411433 private async adaptCheerioContext ( cheerioContext : CheerioCrawlingContext ) {
412434 // Capture the original response to avoid infinite recursion when the getter is copied to the context
413435 const result = this . resultObjects . get ( cheerioContext ) ;
@@ -507,28 +529,29 @@ export class AdaptivePlaywrightCrawler<
507529 pushData : result . pushData ,
508530 useState : this . allowStorageAccess ( useStateFunction ) ,
509531 getKeyValueStore : this . allowStorageAccess ( result . getKeyValueStore ) ,
510- enqueueLinks : async ( options : SetRequired < EnqueueLinksOptions , 'urls' > ) => {
511- return await this . enqueueLinks ( options , context . request , result ) ;
512- } ,
513532 log : this . createLogProxy ( context . log , logs ) ,
514533 registerDeferredCleanup : ( cleanup : ( ) => Promise < unknown > ) => deferredCleanup . push ( cleanup ) ,
515534 } ;
516535
517- const subCrawlerContext = { ...context , ...resultBoundContextHelpers } ;
536+ const subCrawlerContext = Object . defineProperties (
537+ { } ,
538+ Object . getOwnPropertyDescriptors ( context ) ,
539+ ) as typeof context ;
540+
541+ // Mark result-bound helpers as non-configurable so they survive the sub-crawler context pipeline
542+ // (which would otherwise override them with the sub-crawler's own versions, losing the result binding).
543+ for ( const [ key , descriptor ] of Object . entries ( Object . getOwnPropertyDescriptors ( resultBoundContextHelpers ) ) ) {
544+ Object . defineProperty ( subCrawlerContext , key , { ...descriptor , configurable : false } ) ;
545+ }
546+
518547 this . resultObjects . set ( subCrawlerContext , result ) ;
519548
520549 try {
521550 const callAdaptiveRequestHandler = async ( ) => {
522551 if ( renderingType === 'static' ) {
523- await this . staticContextPipeline . call (
524- subCrawlerContext ,
525- async ( finalContext ) => await this . requestHandler ( finalContext ) ,
526- ) ;
552+ await this . staticContextPipeline . call ( subCrawlerContext , this . requestHandler . bind ( this ) ) ;
527553 } else if ( renderingType === 'clientOnly' ) {
528- await this . browserContextPipeline . call (
529- subCrawlerContext ,
530- async ( finalContext ) => await this . requestHandler ( finalContext ) ,
531- ) ;
554+ await this . browserContextPipeline . call ( subCrawlerContext , this . requestHandler . bind ( this ) ) ;
532555 }
533556 } ;
534557
0 commit comments