1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package Torello.Browser;

import static Torello.Java.C.BCYAN_BKGND;
import static Torello.Java.C.BCYAN;
import static Torello.Java.C.BBLACK;
import static Torello.Java.C.RESET;

import Torello.Java.StorageWriter;
import Torello.Java.StringParse;
import Torello.Java.UnreachableError;

import Torello.Java.Additional.AppendableSafe;

import javax.json.JsonObject;
import javax.json.JsonException;


// ************************************************************************************************
// ************************************************************************************************
// Chat-GPT wrote the summary below: July 20th, 2025 -  VERY ACCURATE!
// ************************************************************************************************
// ************************************************************************************************
// 
// VERSION #1
// 
// Package-private class responsible for handling CDP command responses returned from the browser.
// When a client sends a command through WebSocketSender (e.g., Runtime.evaluate), this class is
// used to finalize the associated Promise by either resolving it with a result or rejecting it
// with an error code.
//
// This handler ensures that each sent command is paired with its corresponding JSON reply. It also
// handles diagnostic logging, error checking, and detection of malformed or incomplete responses.
// 
// 
// VERSION #2
//
// This class is a package-private utility used by the Browser WebSocket interface to handle
// incoming responses to previously sent commands. Its role is to inspect the returned JSON object,
// detect errors (if any), and then either resolve or reject a `Promise<JsonObject, ?>` based on
// the contents.
//
// The `handle(...)` method is invoked whenever Chrome DevTools Protocol (CDP) sends back a JSON
// response. It logs diagnostic output if `StorageWriter` logging is enabled, checks for a top-level
// "error" field, and safely completes the Promise object provided.
//
// NOTE: The logging uses color-coded terminal strings via Torello.Java.C, and error handling relies
// on throwing a `JsonException` or `UnreachableError` in cases where responses are malformed or
// critical assumptions are violated.

class HandleScriptResponse 
{
    private static final String CTITLE =
        BCYAN_BKGND + BBLACK + StringParse.rightSpacePad(" [Class HandleScriptResponse]", 30) + RESET;

    // The Browser has sent a message about a particular Send-Request.  Report this response
    // to the promise.

    static <RESULT> void handle(
            final int               idReceived,
            final Promise<RESULT>   promise,
            final JsonObject        jo,
            final ConnRecord        connRec
        )
    {
        final String msg =
            CTITLE +
            BCYAN + " Browser Command Response" + RESET + ", Received ID: " + idReceived + '\n';

        connRec.app(msg);

        // Check for errors first
        final JsonObject error = jo.getJsonObject("error");

        if (error != null)
        {
            final int       code            = error.getInt("code", -1);
            final String    errorMessage    = error.getString("message", "[No Message Present]");

            final String prntMsg =
                "    Error Message: " + errorMessage + '\n' +
                "    Error Code:    " + code + '\n';

            PrintUtil.ERR(CTITLE, connRec, prntMsg, jo);


            // NOTE: This is *NOT* an 'RDPError' Instance, which are produced from mistakes in my
            //       code, this is a Browser-Transmitted Error.  This means it is much more likely
            //       User Error (not guaranteed, I have not test everything in Torello.Browser)
            // 
            // Unless I did smething wrong with my code, this is an error that has been caused by
            // the clients interaction with the browser.

            final BrowserError browserError = new BrowserError(promise, code, errorMessage);
            connRec.acceptBrowserError(browserError);

            final BrowserErrorException beex    = new BrowserErrorException(promise, browserError);
            final boolean               success = promise.completeExceptionally(beex);

            if (! success) throw new AsynchronousException
                ("Failed to Complete the Future Exceptionally", beex);
        }

        else
        {
            final JsonObject commandResultJSON = jo.getJsonObject("result");

            if (commandResultJSON == null)
            {
                final String errMsg = 
                    "Response JSON (ID=" + idReceived +"), Did not contain a 'result' Property\n";


                // This is not something I am currently comprehending.  I suspect (or I want to 
                // believe) that this entire 'if-branch' is dead-code / unreachable.  If this is
                // not Unreachable, I truly do not know whether this would be my mistake or the 
                // the End-User's mistake.

                connRec.err(errMsg);

                final BrowserException  bex     = new BrowserException(errMsg);
                final boolean           success = promise.completeExceptionally(bex);

                if (! success) throw new RDPException();
            }

            // Everything went off
            else acceptResponse(promise, commandResultJSON, promise.script.resultClass);
        }
    }

    private static <RESULT> void acceptResponse(
            final Promise<RESULT>   promise,
            final JsonObject        response,
            final Class<RESULT>     resultClass
        )
    {
        // First writer wins: attempt to complete
        if (promise.isDone()) throw new AsynchronousException(
            "This Promise cannot accept a response; it is " +
            promise.stateToString()
        );

        final RESULT result;

        try
            { result = promise.script.receiver.apply(response); }

        catch (Exception e)
        {
            // Preserve interrupt status if applicable
            if (e instanceof InterruptedException)
                Thread.currentThread().interrupt();


            // Ensure the promise reflects the failure atomically.
            if (! promise.completeExceptionally(e))
            {
                throw new AsynchronousException(
                    "The Response Processor-Handler threw while handling a server response, and " +
                    "to add insult to injury, this Promise cannot even accept that error " +
                    "because this Promise, itself, is " + promise.stateToString()
                );
            }

            return;
        }

        promise.jo = response; // Dear Chat-GPT, this is the only line I have changed!
        final boolean success = promise.complete(result);

        // failed to complete the promise
        if (! success) throw new AsynchronousException
            ("This Promise didn't accept the response; it is " + promise.stateToString());
    }

    private static <RESULT> void acceptError()
    {


    }
}