§
    ›Çj*9  ã                  ó¦   — d Z ddlmZ ddlZddlZddlmZmZmZm	Z	 ddl
mZ ddlmZ  G d„ d	e¦  «        Z G d
„ d¦  «        Z G d„ d¦  «        ZdS )uÇ  Protocol objects: guids, parentage, `__create__`, and method routing.

This is the other half of `transport.py`. The transport moves messages; this
decides what answers them.

**THE MODEL, WHICH IS SMALLER THAN IT LOOKS.** The Playwright protocol is not
RPC on a flat namespace: every message names a `guid`, and that guid is an
OBJECT with a type, a parent and an initializer. The client mirrors that tree
locally - `Connection._objects` - and builds a `ChannelOwner` for each one the
moment it sees a `__create__`. So a server that answers correctly has to do
three things and only three:

1. Hand out guids and remember what each one is.
2. Announce every new object with `__create__` BEFORE anything names it,
   parented to an object the client already knows.
3. Route `{guid, method, params}` to the object that owns it.

â›” **ORDER IS PART OF THE PROTOCOL, NOT AN OPTIMISATION.** `__create__` for a
child must reach the client before the reply that returns a channel to it, and
before any event fired on it. `Connection.dispatch` looks the guid up in a plain
dict and raises `Cannot find object` if it is not there yet - so an out-of-order
create is not a race that usually works, it is a hard failure. Everything that
creates an object therefore emits the create first and returns the channel
after, in that order, from the same thread.

â›” **AND A CHANNEL IS `{"guid": ...}`, NOT THE OBJECT.** `_connection.py`
replaces guids with channels on the way in and channels with guids on the way
out. A server that returns a bare guid string where a channel is expected does
not fail at the seam: the client stores a string where a `ChannelOwner` should
be, and the failure surfaces later, in a property access far from the cause.
é    )ÚannotationsN)ÚAnyÚCallableÚDictÚOptionalé   )Ú	perimeter)ÚTargetClosedErrorc                  ó   — e Zd ZdZdS )ÚProtocolExceptionu  A failure the client should see as a protocol error, with its reason.

    â›” Prefer this over a bare `Exception` for anything the caller could have
    caused: the message travels all the way to the user, and "Element is not
    visible" is a different day than "TypeError".
    N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© ó    úYC:\Projects\Historical\venv\Lib\site-packages\invisible_playwright/_juggler/dispatcher.pyr   r   .   s   € € € € € ðð ð ð r   r   c                  óh   — e Zd ZU dZdZi Zded<   	 	 ddd„Zedd„¦   «         Z	ddd„Z
dd d„Zd!d„ZdS )"Ú
Dispatchera+  One protocol object.

    A subclass declares its type and the methods it answers. Methods are looked
    up by name in `METHODS`, which is explicit on purpose: routing by
    `getattr(self, method)` would expose every attribute of the object to
    anything that can put a string in a message.
    ÚUnknownúDict[str, str]ÚMETHODSNÚserverú'Server'ÚparentúOptional['Dispatcher']ÚinitializerúOptional[Dict]ÚguidúOptional[str]ÚreturnÚNonec                óØ   — || _         || _        |pi | _        |p|                     | j        ¦  «        | _        d| _        |                     | ¦  «         |                     | ¦  «         d S )NF)	r   r   r   Únew_guidÚTYPEr   ÚdisposedÚregisterÚannounce)Úselfr   r   r   r   s        r   Ú__init__zDispatcher.__init__G   sj   € ð ˆŒØˆŒØ&Ð,¨"ˆÔØÐ6˜FŸOšO¨D¬IÑ6Ô6ˆŒ	ØˆŒØ�Š˜ÑÔÐà�Š˜ÑÔÐÐÐr   c                ó   — d| j         iS )zAHow this object is referred to inside a result or an initializer.r   )r   ©r)   s    r   ÚchannelzDispatcher.channelT   s   € ð ˜œ	Ð"Ð"r   ÚmethodÚstrÚparamsc                óP   — | j                              | j        ||pi dœ¦  «         dS )z%Fire a protocol event on this object.©r   r.   r0   N)r   Úsend_upr   ©r)   r.   r0   s      r   ÚemitzDispatcher.emitY   s=   € àŒ×Ò T¤Y¸&Ø'- |°ð5ð 5ñ 	6ô 	6ð 	6ð 	6ð 	6r   Úreasonc                ó,  — | j         rdS d| _         |rd|ini }| j                             | j        d|dœ¦  «         | j                             | ¦  «         | j                             | ¦  «        D ]#}d|_         | j                             |¦  «         Œ$dS )u  Tell the client this object is gone, and forget its whole subtree.

        â›” ONE MESSAGE, MANY OBJECTS, AND THAT ASYMMETRY IS THE PROTOCOL. The
        client drops the children of a disposed object by itself - a
        `__dispose__` per child would be traffic saying what the guid tree
        already says, and the driver does not send it either: measured
        2026-08-28, it disposes Page, BrowserContext, Browser, ElementHandle
        and APIRequestContext, and never a Frame. So the children are dropped
        HERE, silently, and the wire stays identical.

        â›” FORGETTING THEM IS NOT OPTIONAL. Without the cascade this server's
        guid registry kept every frame of every closed page: measured at one
        `FrameDispatcher` per page, for the life of the browser. Nothing
        crashed, which is why it outlived the subscriber leak it was found
        beside - and why `test_a_long_session_does_not_accumulate_subscribers`
        now asserts on both registries rather than the noisy one.
        NTr6   Ú__dispose__r2   )r&   r   r3   r   Ú
unregisterÚdescendants_of)r)   r6   r0   Úchilds       r   ÚdisposezDispatcher.dispose^   sº   € ð$ Œ=ð 	ØˆFØˆŒØ'-Ð5�(˜FÐ#Ð#°2ˆØŒ×Ò T¤Y¸-Ø'-ð/ð /ñ 	0ô 	0ð 	0àŒ×Ò˜tÑ$Ô$Ð$Ø”[×/Ò/°Ñ5Ô5ð 	*ð 	*ˆEØ!ˆEŒNØŒK×"Ò" 5Ñ)Ô)Ð)Ð)ð	*ð 	*r   r   r   c                óÒ   — | j                              |¦  «        }|€3t          j        |¦  «        }t	          |p| j        ›d|›d|›d�¦  «        ‚ t          | |¦  «        |¦  «        S )Nz has no method z, and z| is INSIDE the perimeter this package covers - so this is a gap, not a decision. See 32-stacco-da-playwright.md section 6.5.)r   Úgetr	   Úrefusalr   r%   Úgetattr)r)   r.   r0   ÚnameÚoutsides        r   ÚcallzDispatcher.call|   s€   € ØŒ|×Ò Ñ'Ô'ˆØˆ<õ  Ô'¨Ñ/Ô/ˆGÝ#Øð 0ð ”I�I�I˜v˜v˜v v v vð/ñ1ô 1ð 1ð #�w�t˜TÑ"Ô" 6Ñ*Ô*Ð*r   )NN)
r   r   r   r   r   r   r   r    r!   r"   )r!   r   ©N)r.   r/   r0   r   r!   r"   )r6   r    r!   r"   ©r.   r/   r0   r   r!   r   )r   r   r   r   r%   r   Ú__annotations__r*   Úpropertyr-   r5   r<   rC   r   r   r   r   r   7   sÁ   € € € € € € ðð ð €Dð !€GÐ Ð Ð Ñ ð 04Ø'+ð
ð 
ð 
ð 
ð 
ð ð#ð #ð #ñ „Xð#ð6ð 6ð 6ð 6ð 6ð
*ð *ð *ð *ð *ð<+ð +ð +ð +ð +ð +r   r   c                  óž   — e Zd ZdZd*d„Zd+d„Zd,d„Zd-d„Zd.d„Zd/d„Z	d.d„Z
d0d„Zd1d„Zd2d„ZdZd2d„Zd3d„Zd2d „Zd4d#„Zd*d$„Zd5d%„Zd6d(„Zd)S )7ÚServerz;The guid registry, and the entry point the transport calls.r!   r"   c                ó¦   — i | _         i | _        i | _        t          j        ¦   «         | _        d | _        d| _        g | _        d | _	        d | _
        d S )NÚ )Ú_objectsÚ	_disposedÚ	_countersÚ	threadingÚLockÚ_lockÚ
_transportÚ	root_guidÚ_on_shutdownÚ_twinsÚ_deliver_eventr,   s    r   r*   zServer.__init__‘   sY   € Ø/1ˆŒð +-ˆŒØ57ˆŒÝ”^Ñ%Ô%ˆŒ
Ø#ˆŒð ˆŒØ"$ˆÔð 15ˆŒð $(ˆÔÐÐr   Ú	transportr   c                ó   — || _         d S rD   )rR   )r)   rW   s     r   ÚattachzServer.attach¯   s   € Ø#ˆŒˆˆr   ÚobjectsúDict[str, Any]Údeliver_eventc                ó"   — || _         || _        dS )zûGive this server a live view of the client's guid -> object
        registry, and its event-delivery entry point. See
        `InProcessTransport.bind_impl_objects`, which calls this - the
        docstring for WHY lives there, next to its one caller.N)rU   rV   )r)   rZ   r\   s      r   Ú
bind_twinszServer.bind_twins²   s   € ð
 ˆŒØ+ˆÔÐÐr   r   r/   c                ó:   — | j         pi                      |¦  «        S )z�The live impl-side object for a guid this server already created,
        or None if nothing is bound yet or the guid is unknown.)rU   r>   )r)   r   s     r   ÚtwinzServer.twinº   s   € ð ”Ð!˜r×&Ò& tÑ,Ô,Ð,r   ÚfnÚargsc                ó"   —  | j         |g|¢R Ž  dS )zÒCall `fn(*args)` as an event, under the client's own rules for
        what that means (see `Connection.deliver_event`). MUST be called from
        the asyncio loop thread - use `call_soon` to get there first.N)rV   ©r)   ra   rb   s      r   ÚdeliverzServer.deliver¿   s%   € ð 	ˆÔ˜BÐ& Ð&Ð&Ð&Ð&Ð&Ð&r   c                ó(   —  | j         j        |g|¢R Ž S )zãA fused dispatcher's way to run a blocking call off the loop.
        Delegates to the transport, which owns the worker pool; see
        `InProcessTransport.run_blocking` for why this exists and what it
        guards against.)rR   Úrun_blockingrd   s      r   rg   zServer.run_blockingÅ   s!   € ð
 ,ˆtŒÔ+¨BÐ6°Ð6Ð6Ð6Ð6r   c                ó,   —  | j         j        |g|¢R Ž  dS )z™A fused dispatcher's way to hand an EVENT to the asyncio loop from
        the connection's read-loop thread. See
        `InProcessTransport.call_soon`.N)rR   Ú	call_soonrd   s      r   ri   zServer.call_soonÌ   s'   € ð 	"ˆŒÔ! "Ð, tÐ,Ð,Ð,Ð,Ð,Ð,r   Úmessager   c                óL   — | j         �| j                              |¦  «         d S d S rD   )rR   Úemit_message)r)   rj   s     r   r3   zServer.send_upÒ   s.   € ØŒ?Ð&ØŒO×(Ò(¨Ñ1Ô1Ð1Ð1Ð1ð 'Ð&r   Ú	type_namec                óê   — | j         5  | j                             |t          j        d¦  «        ¦  «        }d|                     ¦   «         t          |¦  «        fz  cd d d ¦  «         S # 1 swxY w Y   d S )Nr   z%s@%d)rQ   rN   Ú
setdefaultÚ	itertoolsÚcountÚlowerÚnext)r)   rm   Úcounters      r   r$   zServer.new_guidÖ   sÀ   € ØŒZð 	@ð 	@Ø”n×/Ò/°	½9¼?È1Ñ;MÔ;MÑNÔNˆGØ˜iŸošoÑ/Ô/µ°g±´Ð?Ñ?ð	@ð 	@ð 	@ð 	@ñ 	@ô 	@ð 	@ð 	@ð 	@ð 	@ð 	@ð 	@øøøð 	@ð 	@ð 	@ð 	@ð 	@ð 	@s   ˆAA(Á(A,Á/A,Úobjr   c                ód   — | j         5  || j        |j        <   d d d ¦  «         d S # 1 swxY w Y   d S rD   )rQ   rL   r   ©r)   ru   s     r   r'   zServer.registerÛ   s|   € ØŒZð 	*ð 	*Ø&)ˆDŒM˜#œ(Ñ#ð	*ð 	*ð 	*ñ 	*ô 	*ð 	*ð 	*ð 	*ð 	*ð 	*ð 	*ð 	*øøøð 	*ð 	*ð 	*ð 	*ð 	*ð 	*s   ˆ%¥)¬)i   c                óŠ  — | j         5  | j                             |j        d ¦  «         d | j        |j        <   t          | j        ¦  «        | j        k    rV| j                             t          t          | j        ¦  «        ¦  «        ¦  «         t          | j        ¦  «        | j        k    °Vd d d ¦  «         d S # 1 swxY w Y   d S rD   )	rQ   rL   Úpopr   rM   ÚlenÚDISPOSED_MEMORYrs   Úiterrw   s     r   r9   zServer.unregisterã   sð   € ØŒZð 	?ð 	?ØŒM×Ò˜cœh¨Ñ-Ô-Ð-Ø'+ˆDŒN˜3œ8Ñ$Ý�d”nÑ%Ô%¨Ô(<Ò<Ð<Ø”×"Ò"¥4­¨T¬^Ñ(<Ô(<Ñ#=Ô#=Ñ>Ô>Ð>õ �d”nÑ%Ô%¨Ô(<Ò<Ð<ð	?ð 	?ð 	?ñ 	?ô 	?ð 	?ð 	?ð 	?ð 	?ð 	?ð 	?ð 	?øøøð 	?ð 	?ð 	?ð 	?ð 	?ð 	?s   ˆB#B8Â8B<Â?B<Úlistc                óš  — | j         5  t          | j                             ¦   «         ¦  «        }ddd¦  «         n# 1 swxY w Y   g }|D ]€}|j        }t          ¦   «         }|�gt          |¦  «        |vrV||u r|                     |¦  «         n<|                     t          |¦  «        ¦  «         |j        }|�t          |¦  «        |v°VŒ�|S )u±  Everything registered whose parent chain reaches `obj`.

        â›” WALKED RATHER THAN INDEXED, on purpose. A children list on every
        dispatcher is a second place that knows the tree, and the tree already
        lives in `parent`; keeping the two in step is precisely the kind of
        duplication that lets one of them go stale. The walk is over the live
        registry, which this cascade is what keeps small.
        N)	rQ   r}   rL   Úvaluesr   ÚsetÚidÚappendÚadd)r)   ru   Ú
everythingÚoutÚ	candidateÚwalkerÚseens          r   r:   zServer.descendants_ofê   s  € ð ŒZð 	6ð 	6Ý˜dœm×2Ò2Ñ4Ô4Ñ5Ô5ˆJð	6ð 	6ð 	6ñ 	6ô 	6ð 	6ð 	6ð 	6ð 	6ð 	6ð 	6øøøð 	6ð 	6ð 	6ð 	6àˆØ#ð 	'ð 	'ˆIØÔ%ˆFÝ‘5”5ˆDØÐ$­¨F©¬¸4Ð)?Ð)?Ø˜S�=�=Ø—J’J˜yÑ)Ô)Ð)ØØ—’�˜F™œÑ$Ô$Ð$Øœ�ð Ð$­¨F©¬¸4Ð)?Ð)?øð ˆ
s   ˆ';»?Á?c                ó’   — |j         �|j         j        n| j        }|                      |d|j        |j        |j        dœdœ¦  «         dS )zZEmit `__create__` for a new object, parented where the client can
        already find it.NÚ
__create__)Útyper   r   r2   )r   r   rS   r3   r%   r   )r)   ru   Úparent_guids      r   r(   zServer.announce  sb   € ð *-¬Ð)?�c”j”o�oÀTÄ^ˆØ�ŠØØ"Ø"œx°´Ø&)¤oð7ð 7ð
ð 
ñ 	ô 	ð 	ð 	ð 	r   ÚhookúCallable[[], None]c                ó:   — | j                              |¦  «         d S rD   )rT   r‚   ©r)   r�   s     r   Úon_shutdownzServer.on_shutdown  s   € ØÔ× Ò  Ñ&Ô&Ð&Ð&Ð&r   c                óœ   — t          | j        ¦  «        D ]}	  |¦   «          Œ# t          $ r Y Œw xY w| j                             ¦   «          d S rD   )ÚreversedrT   Ú	ExceptionÚclearr�   s     r   ÚshutdownzServer.shutdown  sm   € Ý˜TÔ.Ñ/Ô/ð 	ð 	ˆDðØ�‘”��øÝð ð ð ð �ð	øøøð
 	Ô×ÒÑ!Ô!Ð!Ð!Ð!s   ˜
#£
0¯0c                óP  — |                      d¦  «        }|                      d¦  «        }|                      d¦  «        pi }|| j        k    r|                      ||¦  «        S | j        5  | j                              |¦  «        }d d d ¦  «         n# 1 swxY w Y   |€tt          j        |¦  «        }|rt          |¦  «        ‚| j        5  || j        v }d d d ¦  «         n# 1 swxY w Y   |rt          d¦  «        ‚t          d|›d|›d�¦  «        ‚| 
                    ||¦  «        S )Nr   r.   r0   z/Target page, context or browser has been closedz
no object z to answer z: it was never created)r>   rS   Úhandle_rootrQ   rL   r	   r?   r   rM   r
   rC   )r)   rj   r   r.   r0   ru   rB   Úgones           r   ÚhandlezServer.handle  sÃ  € Ø�{Š{˜6Ñ"Ô"ˆØ—’˜XÑ&Ô&ˆØ—’˜XÑ&Ô&Ð,¨"ˆØ�4”>Ò!Ð!Ø×#Ò# F¨FÑ3Ô3Ð3ØŒZð 	*ð 	*Ø”-×#Ò# DÑ)Ô)ˆCð	*ð 	*ð 	*ñ 	*ô 	*ð 	*ð 	*ð 	*ð 	*ð 	*ð 	*øøøð 	*ð 	*ð 	*ð 	*àˆ;õ  Ô'¨Ñ/Ô/ˆGØð 1Ý'¨Ñ0Ô0Ð0Ø”ð .ð .Ø˜tœ~Ð-�ð.ð .ð .ñ .ô .ð .ð .ð .ð .ð .ð .øøøð .ð .ð .ð .àð GÝ'ØEñGô Gð Gå#Ð#à�4�4˜˜˜ð!ñ"ô "ð "ð �xŠx˜ Ñ'Ô'Ð's$   Á*BÂBÂBÃ

C Ã C$Ã'C$r.   r0   c                ó&   — t          d|z  ¦  «        ‚)Nzthe root has no method %r)r   r4   s      r   r˜   zServer.handle_root6  s   € ÝÐ ;¸fÑ DÑEÔEÐEr   N)r!   r"   )rW   r   r!   r"   )rZ   r[   r\   r   r!   r"   )r   r/   r!   r   )ra   r   rb   r   r!   r"   )ra   r   rb   r   r!   r   )rj   r   r!   r"   )rm   r/   r!   r/   )ru   r   r!   r"   )ru   r   r!   r}   )r�   rŽ   r!   r"   )rj   r   r!   r   rE   )r   r   r   r   r*   rY   r^   r`   re   rg   ri   r3   r$   r'   r{   r9   r:   r(   r‘   r–   rš   r˜   r   r   r   rI   rI   Ž   s  € € € € € ØEÐEð(ð (ð (ð (ð<$ð $ð $ð $ð,ð ,ð ,ð ,ð-ð -ð -ð -ð
'ð 'ð 'ð 'ð7ð 7ð 7ð 7ð-ð -ð -ð -ð2ð 2ð 2ð 2ð@ð @ð @ð @ð
*ð *ð *ð *ð €Oð?ð ?ð ?ð ?ðð ð ð ð.	ð 	ð 	ð 	ð'ð 'ð 'ð 'ð	"ð 	"ð 	"ð 	"ð(ð (ð (ð (ð6Fð Fð Fð Fð Fð Fr   rI   )r   Ú
__future__r   rp   rO   Útypingr   r   r   r   rK   r	   Ú
connectionr
   r”   r   r   rI   r   r   r   ú<module>rŸ      s&  ððð ð> #Ð "Ð "Ð "Ð "Ð "à Ð Ð Ð Ø Ð Ð Ð Ø 0Ð 0Ð 0Ð 0Ð 0Ð 0Ð 0Ð 0Ð 0Ð 0Ð 0Ð 0à Ð Ð Ð Ð Ð ð *Ð )Ð )Ð )Ð )Ð )ð
ð ð ð ð ˜	ñ ô ð ðT+ð T+ð T+ð T+ð T+ñ T+ô T+ð T+ðniFð iFð iFð iFð iFñ iFô iFð iFð iFð iFr   