From 025c136561a8b692f19babe00b675a66045999ef Mon Sep 17 00:00:00 2001
From: David Rowe <david@ctrlaltstudio.com>
Date: Tue, 17 Dec 2019 09:19:47 +1300
Subject: [PATCH 1/2] XMLHttpRequest API JSDoc

---
 .../script-engine/src/XMLHttpRequestClass.cpp |   8 +
 .../script-engine/src/XMLHttpRequestClass.h   | 247 ++++++++++++++++++
 2 files changed, 255 insertions(+)

diff --git a/libraries/script-engine/src/XMLHttpRequestClass.cpp b/libraries/script-engine/src/XMLHttpRequestClass.cpp
index 571c0e2a0e..57514a2231 100644
--- a/libraries/script-engine/src/XMLHttpRequestClass.cpp
+++ b/libraries/script-engine/src/XMLHttpRequestClass.cpp
@@ -110,6 +110,10 @@ QScriptValue XMLHttpRequestClass::getResponseHeader(const QString& name) const {
     return QScriptValue::NullValue;
 }
 
+/**jsdoc
+ * Called when the request's ready state changes.
+ * @callback XMLHttpRequest~onReadyStateChangeCallback
+ */
 void XMLHttpRequestClass::setReadyState(ReadyState readyState) {
     if (readyState != _readyState) {
         _readyState = readyState;
@@ -183,6 +187,10 @@ void XMLHttpRequestClass::doSend() {
     }
 }
 
+/**jsdoc
+ * Called when the request times out.
+ * @callback XMLHttpRequest~onTimeoutCallback 
+ */
 void XMLHttpRequestClass::requestTimeout() {
     if (_onTimeout.isFunction()) {
         _onTimeout.call(QScriptValue::NullValue);
diff --git a/libraries/script-engine/src/XMLHttpRequestClass.h b/libraries/script-engine/src/XMLHttpRequestClass.h
index d7f3c2e059..cb86cafb67 100644
--- a/libraries/script-engine/src/XMLHttpRequestClass.h
+++ b/libraries/script-engine/src/XMLHttpRequestClass.h
@@ -21,6 +21,132 @@
 #include <QScriptValue>
 #include <QTimer>
 
+/*
+XMlHttpRequest object
+XMlHttpRequest.objectName string
+XMlHttpRequest.response undefined
+XMlHttpRequest.responseText string
+XMlHttpRequest.responseType string
+XMlHttpRequest.status number
+XMlHttpRequest.statusText string
+XMlHttpRequest.readyState number
+XMlHttpRequest.errorCode number
+XMlHttpRequest.timeout number
+XMlHttpRequest.UNSENT number
+XMlHttpRequest.OPENED number
+XMlHttpRequest.HEADERS_RECEIVED number
+XMlHttpRequest.LOADING number
+XMlHttpRequest.DONE number
+XMlHttpRequest.ontimeout object
+XMlHttpRequest.onreadystatechange object
+XMlHttpRequest.destroyed(QObject*) function
+XMlHttpRequest.destroyed() function
+XMlHttpRequest.objectNameChanged(QString) function
+XMlHttpRequest.deleteLater() function
+XMlHttpRequest.requestComplete() function
+XMlHttpRequest.abort() function
+XMlHttpRequest.setRequestHeader(QString,QString) function
+XMlHttpRequest.open(QString,QString,bool,QString,QString) function
+XMlHttpRequest.open(QString,QString,bool,QString) function
+XMlHttpRequest.open(QString,QString,bool) function
+XMlHttpRequest.open(QString,QString) function
+XMlHttpRequest.send() function
+XMlHttpRequest.send(QScriptValue) function
+XMlHttpRequest.getAllResponseHeaders() function
+XMlHttpRequest.getResponseHeader(QString) function
+*/
+
+/**jsdoc
+ * Provides a means to interact with web servers. It is a near-complete implementation of the XMLHttpRequest API described in 
+ * the Mozilla docs:
+ * <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest">https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest</a>.
+ * 
+ * @class XMLHttpRequest
+ *
+ * @hifi-interface
+ * @hifi-client-entity
+ * @hifi-avatar
+ * @hifi-server-entity
+ * @hifi-assignment-client
+ *
+ * @property {*} response - The response data.
+ *     <em>Read-only.</em>
+ * @property {string} responseText - The response data as text.
+ *     <em>Read-only.</em>
+ * @property {string} responseType - The response type required or received (e.g., <code>"text"</code>, <code>"json"</code>, 
+ *     <code>"arraybuffer"</code>, ...).
+ * @property {number} status - The <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status">HTTP response status 
+ *      code</a> (<code>100</code> &ndash; <code>599</code>).
+ *     <em>Read-only.</em>
+ * @property {string} statusText - The HTTP response status text.
+ *     <em>Read-only.</em>
+ * @property {XMLHttpRequest.ReadyState} readyState - The status of the request.
+ *     <em>Read-only.</em>
+ * @property {XMLHttpRequest.NetworkError} errorCode - The network result of the request: including, <code>0</code> (NoError) 
+ *     if there was no error, <code>4</code> (TimeoutError) if the request timed out.
+ *     <em>Read-only.</em>
+ * @property {number} timeout - The time a request can take before timing out, in ms.
+ *
+ * @property {XMLHttpRequest.ReadyState} UNSENT - Request has been created; {@link XMLHttpRequest.open} not called yet.
+ *     <em>Read-only.</em>
+ * @property {XMLHttpRequest.ReadyState} OPENED - {@link XMLHttpRequest.open} has been called. 
+ *     <em>Read-only.</em>
+ * @property {XMLHttpRequest.ReadyState} HEADERS_RECEIVED - {@link XMLHttpRequest.send} has been called; headers and status 
+ *     are available.
+ *     <em>Read-only.</em>
+ * @property {XMLHttpRequest.ReadyState} LOADING - Downloading; {@link XMLHttpRequest|XMLHttpRequest.responseText} has partial 
+ *     data.
+ *     <em>Read-only.</em>
+ * @property {XMLHttpRequest.ReadyState} DONE - Operation complete.
+ *     <em>Read-only.</em>
+ *
+ * @property {XMLHttpRequest~onTimeoutCallback} ontimeout - Function called when the request times out.
+ *     <p>Note: This is called in addition to any function set for <code>onreadystatechange</code>.</p>
+ * @property {XMLHttpRequest~onReadyStateChangeCallback} onreadystatechange - Function called when the request's ready state 
+ *     changes.
+ *
+ * @example <caption>Get a web page's HTML.</caption>
+ * var URL = "https://www.highfidelity.com/";
+ * 
+ * var req = new XMLHttpRequest();
+ * req.onreadystatechange = function () {
+ *     if (req.readyState === req.DONE) {
+ *         if (req.status === 200) {
+ *             print("Success");
+ *             print("Content type:", req.getResponseHeader("content-type"));
+ *             print("Content:", req.responseText.slice(0, 100), "...");
+ * 
+ *         } else {
+ *             print("Error", req.status, req.statusText);
+ *         }
+ * 
+ *         req = null;
+ *     }
+ * };
+ * 
+ * req.open("GET", URL);
+ * req.send();
+ *
+ * @example <caption>Get a web page's HTML &mdash; alternative method.</caption>
+ * var URL = "https://www.highfidelity.com/";
+ * 
+ * var req = new XMLHttpRequest();
+ * req.requestComplete.connect(function () {
+ *     if (req.status === 200) {
+ *         print("Success");
+ *         print("Content type:", req.getResponseHeader("content-type"));
+ *         print("Content:", req.responseText.slice(0, 100), "...");
+ * 
+ *     } else {
+ *         print("Error", req.status, req.statusText);
+ *     }
+ * 
+ *     req = null;
+ * });
+ * 
+ * req.open("GET", URL);
+ * req.send();
+ */
 class XMLHttpRequestClass : public QObject {
     Q_OBJECT
     Q_PROPERTY(QScriptValue response READ getResponse)
@@ -46,6 +172,26 @@ public:
     ~XMLHttpRequestClass();
 
     static const int MAXIMUM_REDIRECTS = 5;
+
+    /**jsdoc
+     * <p>The state of an XMLHttpRequest.</p>
+     * <table>
+     *   <thead>
+     *     <tr><th>Value</th><th>Name</th><th>Description</th></tr>
+     *   </thead>
+     *   <tbody>
+     *     <tr><td><code>0</code></td><td>UNSENT</td><td>Request has been created; {@link XMLHttpRequest.open} not called 
+     *       yet.</td></tr>
+     *     <tr><td><code>1</code></td><td>OPENED</td><td>{@link XMLHttpRequest.open} has been called.</td></tr>
+     *     <tr><td><code>2</code></td><td>HEADERS_RECEIVED</td><td>{@link XMLHttpRequest.send} has been called; headers and 
+     *       status are available.</td></tr>
+     *     <tr><td><code>3</code></td><td>LOADING</td><td>Downloading; {@link XMLHttpRequest|XMLHttpRequest.responseText} has 
+     *       partial data.</td></tr>
+     *     <tr><td><code>4</code></td><td>DONE</td><td>Operation complete.</td></tr>
+     *   </tbody>
+     * </table>
+     * @typedef {number} XMLHttpRequest.ReadyState
+     */
     enum ReadyState {
         UNSENT = 0,
         OPENED,
@@ -79,16 +225,66 @@ public:
     void setOnReadyStateChange(QScriptValue function) { _onReadyStateChange = function; }
 
 public slots:
+
+    /**jsdoc
+     * Aborts the request.
+     * @function XMLHttpRequest.abort
+     */
     void abort();
+
+    /**jsdoc
+     * Sets the value of an HTTP request header. Must be called after {@link XMLHttpRequest.open} but before 
+     * {@link XMLHttpRequest.send};
+     * @function XMLHttpRequest.setRequestHeader
+     * @param {string} name - The name of the header to set.
+     * @param {string} value - The value of the header.
+     */
     void setRequestHeader(const QString& name, const QString& value);
+
+    /**jsdoc
+     * Initializes a request.
+     * @function XMLHttpRequest.open
+     * @param {string} method - The <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods">HTTP request method</a> 
+     *     to use, e.g., <code>"GET"</code>, <code>"POST"</code>, <code>"PUT"</code>, or <code>"DELETE"</code>.
+     * @param {string} url - The URL to send the request to.
+     * @param {boolean} [async=true] - <code>true</code> if the method returns without waiting for the response, 
+     *     <code>false</code> if the method returns only once the request is complete.
+     * @param {string} [username=""] - User name for authentication.
+     * @param {string} [password=""] - Password for authentication.
+     */
     void open(const QString& method, const QString& url, bool async = true, const QString& username = "",
               const QString& password = "");
+
+    /**jsdoc
+     * Sends the request to the server.
+     * @function XMLHttpRequest.send
+     * @param {*} [data] - The data to send.
+     */
     void send();
     void send(const QScriptValue& data);
+
+    /**jsdoc
+     * Gets the response headers.
+     * @function XMLHttpRequest.getAllResponseHeaders
+     * @returns {string} The response headers, separated by <code>"\n"</code> characters.
+     */
     QScriptValue getAllResponseHeaders() const;
+
+    /**jsdoc
+     * Gets a response header.
+     * @function XMLHttpRequest.getResponseHeader
+     * @param {string} name - 
+     * @returns {string} The response header.
+     */
     QScriptValue getResponseHeader(const QString& name) const;
 
 signals:
+
+    /**jsdoc
+     * Triggered when the request is complete &mdash; with or without error (incl. timeout).
+     * @function XMLHttpRequest.requestComplete
+     * @returns {Signal}
+     */
     void requestComplete();
 
 private:
@@ -111,7 +307,58 @@ private:
     QScriptValue _onTimeout { QScriptValue::NullValue };
     QScriptValue _onReadyStateChange { QScriptValue::NullValue };
     ReadyState _readyState { XMLHttpRequestClass::UNSENT };
+
+    /**jsdoc
+     * <p>The type of network error.</p>
+     * <table>
+     *   <thead>
+     *     <tr><th>Value</th><th>Name</th><th>Description</th></tr>
+     *   </thead>
+     *   <tbody>
+     *     <tr><td><code>0</code></td><td>NoError</td><td>No error.</td></tr>
+     *     <tr><td><code>1</code></td><td>ConnectionRefusedError</td><td>The server refused the connection.</td></tr>
+     *     <tr><td><code>2</code></td><td>RemoteHostClosedError</td><td>The server closed the connection.</td></tr>
+     *     <tr><td><code>3</code></td><td>HostNotFoundError</td><td>Host name not found.</td></tr>
+     *     <tr><td><code>4</code></td><td>TimeoutError</td><td>Connection timed out</td></tr>
+     *     <tr><td><code>5</code></td><td>OperationCanceledError</td><td>Operation canceled by 
+     *       {@link XMLHttpRequest.abort}.</td></tr>
+     *     <tr><td><code>6</code></td><td>SslHandshakeFailedError</td><td>SSL/TLS handshake failed.</td></tr>
+     *     <tr><td><code>7</code></td><td>TemporaryNetworkFailureError</td><td>Temporarily disconnected from the 
+     *       network.</td></tr>
+     *     <tr><td><code>8</code></td><td>NetworkSessionFailedError</td><td>Disconnection from the network.</td></tr>
+     *     <tr><td><code>9</code></td><td>BackgroundRequestNotAllowedError</td><td>Background request not allowed.</td></tr>
+     *     <tr><td><code>10</code></td><td>TooManyRedirectsError</td><td>Too many redirects.</td></tr>
+     *     <tr><td><code>11</code></td><td>InsecureRedirectError</td><td>Redirect from secure to insecure protocol.</td></tr>
+     *     <tr><td><code>101</code></td><td>ProxyConnectionRefusedError</td><td>Connection to proxy server refused.</td></tr>
+     *     <tr><td><code>102</code></td><td>ProxyConnectionClosedError</td><td>Proxy server closed the connection.</td></tr>
+     *     <tr><td><code>103</code></td><td>ProxyNotFoundError</td><td>Proxy host name not found.</td></tr>
+     *     <tr><td><code>104</code></td><td>ProxyTimeoutError</td><td>Proxy connection timed out.</td></tr>
+     *     <tr><td><code>105</code></td><td>ProxyAuthenticationRequiredError</td><td>Proxy requires authentication.</td></tr>
+     *     <tr><td><code>201</code></td><td>ContentAccessDenied</td><td>Access denied.</td></tr>
+     *     <tr><td><code>202</code></td><td>ContentOperationNotPermittedError</td><td>Operation not permitted.</td></tr>
+     *     <tr><td><code>203</code></td><td>ContentNotFoundError</td><td>Content not found.</td></tr>
+     *     <tr><td><code>204</code></td><td>AuthenticationRequiredError</td><td>Authentication required.</td></tr>
+     *     <tr><td><code>205</code></td><td>ContentReSendError</td><td>Resend failed.</td></tr>
+     *     <tr><td><code>206</code></td><td>ContentConflictError</td><td>Resource state conflict.</td></tr>
+     *     <tr><td><code>207</code></td><td>ContentGoneError</td><td>Resource no longer available.</td></tr>
+     *     <tr><td><code>401</code></td><td>InternalServerError</td><td>Internal server error.</td></tr>
+     *     <tr><td><code>402</code></td><td>OperationNotImplementedError</td><td>Operation not supported.</td></tr>
+     *     <tr><td><code>403</code></td><td>ServiceUnavailableError</td><td>Request not able to be handled at this 
+     *       time.</td></tr>
+     *     <tr><td><code>301</code></td><td>ProtocolUnknownError</td><td>Protocol unknown.</td></tr>
+     *     <tr><td><code>302</code></td><td>ProtocolInvalidOperationError</td><td>Operation invalid fro protocol.</td></tr>
+     *     <tr><td><code>99</code></td><td>UnknownNetworkError</td><td>Unknown network-related error.</td></tr>
+     *     <tr><td><code>199</code></td><td>UnknownProxyError</td><td>Unknown proxy-related error.</td></tr>
+     *     <tr><td><code>299</code></td><td>UnknownContentError</td><td>Unknown content-related error.</td></tr>
+     *     <tr><td><code>399</code></td><td>ProtocolFailure</td><td>Protocol error.</td></tr>
+     *     <tr><td><code>499</code></td><td>UnknownServerError</td><td>Unknown server response error.</td></tr>
+
+     *   </tbody>
+     * </table>
+     * @typedef {number} XMLHttpRequest.NetworkError
+     */
     QNetworkReply::NetworkError _errorCode { QNetworkReply::NoError };
+
     int _timeout { 0 };
     QTimer _timer;
     int _numRedirects { 0 };

From 3aaeba76a9c6585bbf82f98dc0f1e4c122926ccc Mon Sep 17 00:00:00 2001
From: David Rowe <david@ctrlaltstudio.com>
Date: Tue, 17 Dec 2019 09:20:18 +1300
Subject: [PATCH 2/2] Fix typos in WebSocket JSDoc

---
 libraries/script-engine/src/WebSocketClass.cpp | 2 +-
 libraries/script-engine/src/WebSocketClass.h   | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/libraries/script-engine/src/WebSocketClass.cpp b/libraries/script-engine/src/WebSocketClass.cpp
index 73774912a9..7333e38037 100644
--- a/libraries/script-engine/src/WebSocketClass.cpp
+++ b/libraries/script-engine/src/WebSocketClass.cpp
@@ -99,7 +99,7 @@ void WebSocketClass::handleOnClose() {
  * @param {WebSocket.SocketError} error - The error.
  */
 /**jsdoc
- * Information on a socket error.
+ * <p>The type of socket error.</p>
  * <table>
  *   <thead>
  *     <tr><th>Value</th><th>Name</th><th>Description</th></tr>
diff --git a/libraries/script-engine/src/WebSocketClass.h b/libraries/script-engine/src/WebSocketClass.h
index 56fb334152..c181965bf7 100644
--- a/libraries/script-engine/src/WebSocketClass.h
+++ b/libraries/script-engine/src/WebSocketClass.h
@@ -17,9 +17,9 @@
 #include <QWebSocket>
 
 /**jsdoc
- * Provides a bi-direcctional, event-driven communication session between the script and another WebSocket connection. It is a 
+ * Provides a bi-directional, event-driven communication session between the script and another WebSocket connection. It is a 
  * near-complete implementation of the WebSocket API described in the Mozilla docs: 
- * <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSocket">https://developer.mozilla.org/en-US/docs/Web/API/WebSocket</a>.</p>
+ * <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSocket">https://developer.mozilla.org/en-US/docs/Web/API/WebSocket</a>.
  *
  * <p>Constructed by <code>new WebSocket(...)</code> in Interface, client entity, avatar, and server entity scripts, or the 
  * {@link WebSocketServer} class in server entity and assignment client scripts.