@@ -6,6 +6,7 @@ import { mkdir } from 'node:fs/promises';
66import { homedir } from 'node:os' ;
77import { join } from 'node:path' ;
88import readline from 'node:readline' ;
9+ import { pathToFileURL } from 'node:url' ;
910
1011import {
1112 Browser as BrowserBinary ,
@@ -46,6 +47,24 @@ import {
4647} from './browser-protocol.js' ;
4748import { normalizeAutomationUrl } from './automation-url.js' ;
4849
50+ const PUPPETEER_KEY_NAMES = new Set ( [
51+ 'Backspace' , 'Tab' , 'Enter' , 'Escape' , 'Shift' , 'Control' , 'Alt' , 'Meta' ,
52+ 'CapsLock' , 'Delete' , 'Insert' , 'Home' , 'End' , 'PageUp' , 'PageDown' ,
53+ 'ArrowLeft' , 'ArrowUp' , 'ArrowRight' , 'ArrowDown' , 'NumLock' , 'ScrollLock' ,
54+ 'Pause' , 'PrintScreen' , 'ContextMenu' ,
55+ ] ) ;
56+
57+ export function toPuppeteerKeyInput ( key : string , code ?: string ) : string | null {
58+ void code ;
59+ if ( key === 'OS' ) return 'Meta' ;
60+ if ( key === 'Scroll' ) return 'ScrollLock' ;
61+ if ( key === 'Esc' ) return 'Escape' ;
62+ if ( key === 'Del' ) return 'Delete' ;
63+ if ( key === ' ' ) return 'Space' ;
64+ if ( PUPPETEER_KEY_NAMES . has ( key ) || / ^ F (?: [ 1 - 9 ] | 1 [ 0 - 2 ] ) $ / . test ( key ) || key . length === 1 ) return key ;
65+ return null ;
66+ }
67+
4968type Tab = {
5069 id : string ;
5170 page : Page ;
@@ -335,12 +354,18 @@ class BrowserRuntime {
335354 } else if ( input . kind === 'text' ) {
336355 await cdp . send ( 'Input.insertText' , { text : input . text } ) ;
337356 } else {
338- await cdp . send ( 'Input.dispatchKeyEvent' , {
339- type : input . event === 'down' ? 'keyDown' : 'keyUp' ,
340- key : input . key ,
341- code : input . code ?? input . key ,
342- modifiers : input . modifiers ?? 0 ,
343- } ) ;
357+ const keyInput = toPuppeteerKeyInput ( input . key , input . code ) ;
358+ if ( keyInput ) {
359+ if ( input . event === 'down' ) await tab . page . keyboard . down ( keyInput as KeyInput ) ;
360+ else await tab . page . keyboard . up ( keyInput as KeyInput ) ;
361+ } else {
362+ await cdp . send ( 'Input.dispatchKeyEvent' , {
363+ type : input . event === 'down' ? 'keyDown' : 'keyUp' ,
364+ key : input . key ,
365+ code : input . code ?? input . key ,
366+ modifiers : input . modifiers ?? 0 ,
367+ } ) ;
368+ }
344369 }
345370 return { accepted : true } ;
346371 }
@@ -770,15 +795,19 @@ function enqueue(frame: BrowserRequestFrame): void {
770795 globalRequestQueue = globalRequestQueue . then ( ( ) => handle ( frame ) ) . catch ( reportQueueError ) ;
771796}
772797
773- readline . createInterface ( { input : process . stdin , crlfDelay : Infinity } ) . on ( 'line' , ( line ) => {
774- try {
775- for ( const frame of decoder . push ( `${ line } \n` ) ) {
776- if ( frame . kind !== 'request' ) throw new Error ( 'Only request frames are accepted.' ) ;
777- enqueue ( frame ) ;
798+ function runBrowserSidecarEntrypoint ( ) : void {
799+ readline . createInterface ( { input : process . stdin , crlfDelay : Infinity } ) . on ( 'line' , ( line ) => {
800+ try {
801+ for ( const frame of decoder . push ( `${ line } \n` ) ) {
802+ if ( frame . kind !== 'request' ) throw new Error ( 'Only request frames are accepted.' ) ;
803+ enqueue ( frame ) ;
804+ }
805+ } catch ( error ) {
806+ reportQueueError ( error ) ;
778807 }
779- } catch ( error ) {
780- reportQueueError ( error ) ;
781- }
782- } ) ;
808+ } ) ;
809+
810+ emit ( 'ready' , { protocolVersion : BROWSER_PROTOCOL_VERSION } ) ;
811+ }
783812
784- emit ( 'ready' , { protocolVersion : BROWSER_PROTOCOL_VERSION } ) ;
813+ if ( process . argv [ 1 ] && import . meta . url === pathToFileURL ( process . argv [ 1 ] ) . href ) runBrowserSidecarEntrypoint ( ) ;
0 commit comments