Refactorisation CDP de l'évaluation navigateur
Plan de refactorisation CDP de l’évaluation navigateur
Section intitulée « Plan de refactorisation CDP de l’évaluation navigateur »Contexte
Section intitulée « Contexte »act:evaluate exécute le JavaScript fourni par l’utilisateur dans la page. Aujourd’hui, il s’exécute via Playwright
(page.evaluate ou locator.evaluate). Playwright sérialise les commandes CDP par page, donc une
evaluation bloquée ou longue peut bloquer la file de commandes de la page et faire en sorte que chaque action ultérieure
sur cet onglet semble “bloquée”.
La PR #13498 ajoute un filet de sécurité pragmatique (évaluation bornée, propagation de l’abandon et récupération
au mieux). Ce document décrit une refactorisation plus importante qui rend act:evaluate intrinsèquement
isolé de Playwright, afin qu’une évaluation bloquée ne puisse pas coincer les opérations normales de Playwright.
Objectifs
Section intitulée « Objectifs »act:evaluatene peut pas bloquer de manière permanente les actions ultérieures du navigateur sur le même onglet.- Les délais d’attente sont la source unique de vérité de bout en bout, afin qu’un appelant puisse se fier à un budget.
- L’abandon et le délai d’attente sont traités de la même manière sur HTTP et pour la répartition intra-processus.
- Le ciblage d’éléments pour l’évaluation est pris en charge sans tout basculer hors de Playwright.
- Maintenir la compatibilité descendante pour les appelants et les charges utiles existants.
Non-objectifs
Section intitulée « Non-objectifs »- Remplacer toutes les actions du navigateur (clic, saisie, attente, etc.) par des implémentations CDP.
- Supprimer le filet de sécurité existant introduit dans la PR #13498 (il reste un repli utile).
- Introduire de nouvelles capacités non sécurisées au-delà de la porte
browser.evaluateEnabledexistante. - Ajouter une isolation de processus (processus de travail/thread) pour l’évaluation. Si nous rencontrons toujours des états bloqués difficiles à récupérer après cette refactorisation, c’est une idée de suivi.
Architecture actuelle (Pourquoi elle se bloque)
Section intitulée « Architecture actuelle (Pourquoi elle se bloque) »À un niveau élevé :
- Les appelants envoient
act:evaluateau service de contrôle du navigateur. - Le gestionnaire de route appelle Playwright pour exécuter le JavaScript.
- Playwright sérialise les commandes de page, donc une évaluation qui ne se termine jamais bloque la file d’attente.
- Une file d’attente bloquée signifie que les opérations ultérieures de clic/saisie/attente sur l’onglet peuvent sembler figées.
Architecture proposée
Section intitulée « Architecture proposée »1. Propagation du délai (Deadline)
Section intitulée « 1. Propagation du délai (Deadline) »Introduire un concept unique de budget et tout dériver de celui-ci :
- L’appelant définit
timeoutMs(ou un délai dans le futur). - Le délai d’expiration de la requête externe, la logique du gestionnaire de route et le budget d’exécution dans la page utilisent tous le même budget, avec une petite marge là où c’est nécessaire pour la surcharge de sérialisation.
- L’annulation est propagée sous forme de
AbortSignalpartout pour que l’annulation soit cohérente.
Direction de mise en œuvre :
- Ajouter un petit assistant (par exemple
createBudget({ timeoutMs, signal })) qui renvoie :signal: le AbortSignal liédeadlineAtMs: délai absoluremainingMs(): budget restant pour les opérations enfants
- Utiliser cet assistant dans :
src/browser/client-fetch.ts(distribution HTTP et en processus)src/node-host/runner.ts(chemin proxy)- implémentations d’actions de navigateur (Playwright et CDP)
2. Moteur d’évaluation séparé (Chemin CDP)
Section intitulée « 2. Moteur d’évaluation séparé (Chemin CDP) »Ajouter une implémentation d’évaluation basée sur CDP qui ne partage pas la file d’attente de commandes par page de Playwright. La propriété clé est que le transport d’évaluation est une connexion WebSocket distincte et une session CDP distincte attachée à la cible.
Direction de mise en œuvre :
- Nouveau module, par exemple
src/browser/cdp-evaluate.ts, qui :- Se connecte au point de terminaison CDP configuré (socket au niveau du navigateur).
- Utilise
Target.attachToTarget({ targetId, flatten: true })pour obtenir unsessionId. - Exécute soit :
Runtime.evaluatepour une évaluation au niveau de la page, ouDOM.resolveNodeplusRuntime.callFunctionOnpour l’évaluation d’élément.
- En cas de délai d’expiration ou d’annulation :
- Envoie
Runtime.terminateExecutionau mieux (best-effort) pour la session. - Ferme le WebSocket et renvoie une erreur claire.
- Envoie
Notes :
- Cela exécute toujours du JavaScript dans la page, donc la résiliation peut avoir des effets secondaires. L’avantage est que cela ne bloque pas la file d’attente Playwright, et qu’elle est annulable au niveau de la couche de transport en tuant la session CDP.
3. Histoire de référence (Ciblage d’élément sans réécriture complète)
Section intitulée « 3. Histoire de référence (Ciblage d’élément sans réécriture complète) »La partie difficile est le ciblage des éléments. CDP a besoin d’un gestionnaire DOM ou de backendDOMNodeId, alors
qu’aujourd’hui la plupart des actions du navigateur utilisent les localisateurs Playwright basés sur les références des instantanés.
Approche recommandée : conserver les références existantes, mais attacher un ID résolvable CDP optionnel.
3.1 Étendre les informations de référence stockées
Section intitulée « 3.1 Étendre les informations de référence stockées »Étendre les métadonnées de référence de rôle stockées pour inclure optionnellement un ID CDP :
- Aujourd’hui :
{ role, name, nth } - Proposé :
{ role, name, nth, backendDOMNodeId?: number }
Cela permet à toutes les actions existantes basées sur Playwright de continuer à fonctionner et permet à l’évaluation CDP d’accepter
la même valeur ref lorsque le backendDOMNodeId est disponible.
3.2 Remplir backendDOMNodeId au moment de l’instantané
Section intitulée « 3.2 Remplir backendDOMNodeId au moment de l’instantané »Lors de la production d’un instantané de rôle :
- Générer la carte de référence de rôle existante comme aujourd’hui (rôle, nom, nième).
- Récupérer l’arbre AX via CDP (
Accessibility.getFullAXTree) et calculer une carte parallèle de(role, name, nth) -> backendDOMNodeIden utilisant les mêmes règles de gestion des doublons. - Fusionner l’ID dans les informations de référence stockées pour l’onglet actuel.
Si le mappage échoue pour une référence, laisser le backendDOMNodeId indéfini. Cela rend la fonctionnalité
au mieux (best-effort) et sûre à déployer.
3.3 Comportement de l’évaluation avec référence
Section intitulée « 3.3 Comportement de l’évaluation avec référence »Dans act:evaluate :
- Si
refest présent et possèdebackendDOMNodeId, exécuter l’évaluation d’élément via CDP. - Si
refest présent mais n’a pas debackendDOMNodeId, revenir au chemin Playwright (avec le filet de sécurité).
Échappatoire optionnelle :
- Étendre la structure de la demande pour accepter
backendDOMNodeIddirectement pour les appelants avancés (et pour le débogage), tout en conservantrefcomme interface principale.
4. Conserver un chemin de récupération de dernier recours
Section intitulée « 4. Conserver un chemin de récupération de dernier recours »Même avec l’évaluation CDP, il existe d’autres moyens de bloquer un onglet ou une connexion. Conservez les mécanismes de récupération existants (terminer l’exécution + déconnecter Playwright) en dernier recours pour :
- appelants existants
- environnements où la connexion CDP est bloquée
- cas limites inattendus de Playwright
Plan de mise en œuvre (itération unique)
Section intitulée « Plan de mise en œuvre (itération unique) »Livrables
Section intitulée « Livrables »- Un moteur d’évaluation basé sur CDP qui s’exécute en dehors de la file de commandes par page de Playwright.
- Un budget unique d’expiration/d’abandon de bout en bout utilisé de manière cohérente par les appelants et les gestionnaires.
- Les métadonnées de référence pouvant éventuellement contenir
backendDOMNodeIdpour l’évaluation d’élément. act:evaluatepréfère le moteur CDP lorsque cela est possible et revient à Playwright dans le cas contraire.- Des tests prouvant qu’une évaluation bloquée ne bloque pas les actions ultérieures.
- Des journaux/métriques qui rendent les échecs et les replis visibles.
Liste de contrôle de mise en œuvre
Section intitulée « Liste de contrôle de mise en œuvre »- Ajouter un assistant “budget” partagé pour lier
timeoutMs+ en amontAbortSignaldans :- un seul
AbortSignal - une date limite absolue
- un assistant
remainingMs()pour les opérations en aval
- un seul
- Mettre à jour tous les chemins d’appel pour utiliser cet assistant afin que
timeoutMssignifie la même chose partout :src/browser/client-fetch.ts(répartition HTTP et in-process)src/node-host/runner.ts(chemin du proxy de nœud)- Les wrappers CLI qui appellent
/act(ajouter--timeout-msàbrowser evaluate)
- Implémenter
src/browser/cdp-evaluate.ts:- se connecter au socket CDP au niveau du navigateur
Target.attachToTargetpour obtenir unsessionId- exécuter
Runtime.evaluatepour l’évaluation de page - exécuter
DOM.resolveNode+Runtime.callFunctionOnpour l’évaluation d’élément - en cas d’expiration/d’abandon :
Runtime.terminateExecutionde meilleur effort, puis fermer le socket
- Étendre les métadonnées de référence de rôle stockées pour inclure facultativement
backendDOMNodeId:- conserver le comportement
{ role, name, nth }existant pour les actions Playwright - ajouter
backendDOMNodeId?: numberpour le ciblage d’éléments CDP
- conserver le comportement
- Remplir
backendDOMNodeIdlors de la création du snapshot (de meilleur effort) :- récupérer l’arbre AX via CDP (
Accessibility.getFullAXTree) - calculer
(role, name, nth) -> backendDOMNodeIdet fusionner dans la carte de référence stockée - si le mappage est ambigu ou manquant, laisser l’identifiant non défini
- récupérer l’arbre AX via CDP (
- Mettre à jour le routage
act:evaluate:- s’il n’y a pas de
ref: toujours utiliser l’évaluation CDP - si
refrésout vers unbackendDOMNodeId: utiliser l’évaluation d’élément CDP - sinon : revenir à l’évaluation Playwright (toujours bornée et annulable)
- s’il n’y a pas de
- Conserver le chemin de récupération « dernier recours » existant comme solution de repli, pas comme chemin par défaut.
- Ajouter des tests :
- une évaluation bloquée expire dans le budget et le clic/frappe suivant réussit
- l’abandon annule l’évaluation (déconnexion du client ou expiration) et débloque les actions ultérieures
- les échecs de mappage reviennent proprement à Playwright
- Ajouter l’observabilité :
- compteurs de durée et d’expiration de l’évaluation
- utilisation de terminateExecution
- taux de repli (CDP -> Playwright) et raisons
Critères d’acceptation
Section intitulée « Critères d’acceptation »- Un
act:evaluatedélibérément bloqué revient dans le budget de l’appelant et ne bloque pas l’onglet pour les actions ultérieures. timeoutMsse comporte de manière cohérente sur le CLI, l’agent tool, le node proxy et les appels in-process.- Si
refpeut être mappé àbackendDOMNodeId, l’évaluation d’élément utilise CDP ; sinon le chemin de repli reste borné et récupérable.
Plan de test
Section intitulée « Plan de test »- Tests unitaires :
- Logique de correspondance
(role, name, nth)entre les références de rôle et les nœuds de l’arbre AX. - Comportement de l’assistant de budget (marge de manœuvre, calcul du temps restant).
- Logique de correspondance
- Tests d’intégration :
- Le délai d’attente de l’évaluation CDP retourne dans les limites du budget et ne bloque pas l’action suivante.
- L’abandon annule l’évaluation et déclenche la terminaison au mieux.
- Tests contractuels :
- Assurer que
BrowserActRequestetBrowserActResponserestent compatibles.
- Assurer que
Risques et atténuations
Section intitulée « Risques et atténuations »- Le mappage est imparfait :
- Atténuation : mappage au mieux, retour à l’évaluation Playwright, et ajout d’outils de débogage.
Runtime.terminateExecutiona des effets secondaires :- Atténuation : utiliser uniquement lors d’un délai d’attente ou d’un abandon et documenter le comportement dans les erreurs.
- Surcharge supplémentaire :
- Atténuation : récupérer l’arbre AX uniquement lorsque les instantanés sont demandés, mettre en cache par cible, et garder la session CDP de courte durée.
- Limitations du relais d’extension :
- Atténuation : utiliser les API d’attachement au niveau du navigateur lorsque les sockets par page ne sont pas disponibles, et conserver le chemin actuel de Playwright en secours.
Questions ouvertes
Section intitulée « Questions ouvertes »- Le nouveau moteur doit-il être configurable comme
playwright,cdpouauto? - Voulons-nous exposer un nouveau format « nodeRef » pour les utilisateurs avancés, ou garder uniquement
ref? - Comment les instantanés de frame et les instantanés délimités par sélecteur doivent-ils participer au mappage AX ?