Bug 1285036 - Part 1: Use an enum for ProgressEvent types and use consts for the event name strings. r=baku
authorThomas Wisniewski <wisniewskit@gmail.com>
Fri, 08 Jul 2016 12:44:33 -0400
changeset 304464 e42827ec652175101256d38e0df27a96c867ec44
parent 304463 3bfaef234b2be9524717dd83861d5e8d5f35325b
child 304465 9c7274bdcd99e4bfb5f566975437e27d01b7cc53
push id30426
push usercbook@mozilla.com
push dateMon, 11 Jul 2016 14:21:30 +0000
treeherdermozilla-central@214884d507ee [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1285036
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1285036 - Part 1: Use an enum for ProgressEvent types and use consts for the event name strings. r=baku
dom/xhr/XMLHttpRequestMainThread.cpp
dom/xhr/XMLHttpRequestMainThread.h
--- a/dom/xhr/XMLHttpRequestMainThread.cpp
+++ b/dom/xhr/XMLHttpRequestMainThread.cpp
@@ -90,24 +90,34 @@ namespace dom {
 // once doubling reaches this threshold
 #define XML_HTTP_REQUEST_ARRAYBUFFER_MAX_GROWTH (32*1024*1024)
 // start at 32k to avoid lots of doubling right at the start
 #define XML_HTTP_REQUEST_ARRAYBUFFER_MIN_SIZE (32*1024)
 // the maximum Content-Length that we'll preallocate.  1GB.  Must fit
 // in an int32_t!
 #define XML_HTTP_REQUEST_MAX_CONTENT_LENGTH_PREALLOCATE (1*1024*1024*1024LL)
 
-#define LOAD_STR "load"
-#define ERROR_STR "error"
-#define ABORT_STR "abort"
-#define TIMEOUT_STR "timeout"
-#define LOADSTART_STR "loadstart"
-#define PROGRESS_STR "progress"
-#define READYSTATE_STR "readystatechange"
-#define LOADEND_STR "loadend"
+namespace {
+  const nsLiteralString ProgressEventTypeStrings[] = {
+    NS_LITERAL_STRING("loadstart"),
+    NS_LITERAL_STRING("progress"),
+    NS_LITERAL_STRING("error"),
+    NS_LITERAL_STRING("abort"),
+    NS_LITERAL_STRING("timeout"),
+    NS_LITERAL_STRING("load"),
+    NS_LITERAL_STRING("loadend")
+  };
+  static_assert(MOZ_ARRAY_LENGTH(ProgressEventTypeStrings) ==
+                  size_t(XMLHttpRequestMainThread::ProgressEventType::ENUM_MAX),
+                "Mismatched lengths for ProgressEventTypeStrings and ProgressEventType enums");
+
+  const nsString kLiteralString_readystatechange = NS_LITERAL_STRING("readystatechange");
+  const nsString kLiteralString_xmlhttprequest = NS_LITERAL_STRING("xmlhttprequest");
+  const nsString kLiteralString_DOMContentLoaded = NS_LITERAL_STRING("DOMContentLoaded");
+}
 
 // CIDs
 
 // State
 #define XML_HTTP_REQUEST_UNSENT           (1 << 0) // 0 UNSENT
 #define XML_HTTP_REQUEST_OPENED           (1 << 1) // 1 OPENED
 #define XML_HTTP_REQUEST_HEADERS_RECEIVED (1 << 2) // 2 HEADERS_RECEIVED
 #define XML_HTTP_REQUEST_LOADING          (1 << 3) // 3 LOADING
@@ -1016,17 +1026,17 @@ XMLHttpRequestMainThread::GetStatusText(
   if (httpChannel) {
     httpChannel->GetResponseStatusText(aStatusText);
   } else {
     aStatusText.AssignLiteral("OK");
   }
 }
 
 void
-XMLHttpRequestMainThread::CloseRequestWithError(const nsAString& aType,
+XMLHttpRequestMainThread::CloseRequestWithError(const ProgressEventType aType,
                                                 const uint32_t aFlag)
 {
   if (mChannel) {
     mChannel->Cancel(NS_BINDING_ABORTED);
   }
   if (mTimeoutTimer) {
     mTimeoutTimer->Cancel();
   }
@@ -1064,17 +1074,17 @@ XMLHttpRequestMainThread::CloseRequestWi
   }
 
   mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
 }
 
 void
 XMLHttpRequestMainThread::Abort(ErrorResult& arv)
 {
-  CloseRequestWithError(NS_LITERAL_STRING(ABORT_STR), XML_HTTP_REQUEST_ABORTED);
+  CloseRequestWithError(ProgressEventType::abort, XML_HTTP_REQUEST_ABORTED);
 }
 
 NS_IMETHODIMP
 XMLHttpRequestMainThread::SlowAbort()
 {
   Abort();
   return NS_OK;
 }
@@ -1293,59 +1303,56 @@ XMLHttpRequestMainThread::GetLoadGroup()
 }
 
 nsresult
 XMLHttpRequestMainThread::CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent)
 {
   RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
   event.forget(aDOMEvent);
 
-  (*aDOMEvent)->InitEvent(NS_LITERAL_STRING(READYSTATE_STR),
-                          false, false);
+  (*aDOMEvent)->InitEvent(kLiteralString_readystatechange, false, false);
 
   // We assume anyone who managed to call CreateReadystatechangeEvent is trusted
   (*aDOMEvent)->SetTrusted(true);
 
   return NS_OK;
 }
 
 void
 XMLHttpRequestMainThread::DispatchProgressEvent(DOMEventTargetHelper* aTarget,
-                                                const nsAString& aType,
+                                                const ProgressEventType aType,
                                                 bool aLengthComputable,
                                                 int64_t aLoaded, int64_t aTotal)
 {
   NS_ASSERTION(aTarget, "null target");
-  NS_ASSERTION(!aType.IsEmpty(), "missing event type");
 
   if (NS_FAILED(CheckInnerWindowCorrectness()) ||
       (!AllowUploadProgress() && aTarget == mUpload)) {
     return;
   }
 
-  bool dispatchLoadend = aType.EqualsLiteral(LOAD_STR) ||
-                         aType.EqualsLiteral(ERROR_STR) ||
-                         aType.EqualsLiteral(TIMEOUT_STR) ||
-                         aType.EqualsLiteral(ABORT_STR);
-
   ProgressEventInit init;
   init.mBubbles = false;
   init.mCancelable = false;
   init.mLengthComputable = aLengthComputable;
   init.mLoaded = aLoaded;
   init.mTotal = (aTotal == -1) ? 0 : aTotal;
 
+  const nsAString& typeString = ProgressEventTypeStrings[(uint8_t)aType];
   RefPtr<ProgressEvent> event =
-    ProgressEvent::Constructor(aTarget, aType, init);
+    ProgressEvent::Constructor(aTarget, typeString, init);
   event->SetTrusted(true);
 
   aTarget->DispatchDOMEvent(nullptr, event, nullptr, nullptr);
 
-  if (dispatchLoadend) {
-    DispatchProgressEvent(aTarget, NS_LITERAL_STRING(LOADEND_STR),
+  // If we're sending a load, error, timeout or abort event, then
+  // also dispatch the subsequent loadend event.
+  if (aType == ProgressEventType::load || aType == ProgressEventType::error ||
+      aType == ProgressEventType::timeout || aType == ProgressEventType::abort) {
+    DispatchProgressEvent(aTarget, ProgressEventType::loadend,
                           aLengthComputable, aLoaded, aTotal);
   }
 }
 
 already_AddRefed<nsIHttpChannel>
 XMLHttpRequestMainThread::GetCurrentHttpChannel()
 {
   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
@@ -1558,17 +1565,17 @@ XMLHttpRequestMainThread::Open(const nsA
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mChannel));
   if (httpChannel) {
     rv = httpChannel->SetRequestMethod(method);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Set the initiator type
     nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(httpChannel));
     if (timedChannel) {
-      timedChannel->SetInitiatorType(NS_LITERAL_STRING("xmlhttprequest"));
+      timedChannel->SetInitiatorType(kLiteralString_xmlhttprequest);
     }
   }
 
   ChangeState(XML_HTTP_REQUEST_OPENED);
 
   return NS_OK;
 }
 
@@ -1792,17 +1799,17 @@ XMLHttpRequestMainThread::OnStartRequest
     }
     if (mUploadTransferred < mUploadTotal) {
       mUploadTransferred = mUploadTotal;
       mProgressSinceLastProgressEvent = true;
       mUploadLengthComputable = true;
       MaybeDispatchProgressEvents(true);
     }
     mUploadComplete = true;
-    DispatchProgressEvent(mUpload, NS_LITERAL_STRING(LOAD_STR),
+    DispatchProgressEvent(mUpload, ProgressEventType::load,
                           true, mUploadTotal, mUploadTotal);
   }
 
   mContext = ctxt;
   mState |= XML_HTTP_REQUEST_PARSEBODY;
   ChangeState(XML_HTTP_REQUEST_HEADERS_RECEIVED);
 
   ResetResponse();
@@ -2110,17 +2117,17 @@ XMLHttpRequestMainThread::OnStopRequest(
   }
   if (mIsHtml) {
     NS_ASSERTION(!(mState & XML_HTTP_REQUEST_SYNCLOOPING),
       "We weren't supposed to support HTML parsing with XHR!");
     nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(mResponseXML);
     EventListenerManager* manager =
       eventTarget->GetOrCreateListenerManager();
     manager->AddEventListenerByType(new nsXHRParseEndListener(this),
-                                    NS_LITERAL_STRING("DOMContentLoaded"),
+                                    kLiteralString_DOMContentLoaded,
                                     TrustedEventsAtSystemGroupBubble());
     return NS_OK;
   }
   // We might have been sent non-XML data. If that was the case,
   // we should null out the document member. The idea in this
   // check here is that if there is no document element it is not
   // an XML document. We might need a fancier check...
   if (!mResponseXML->GetRootElement()) {
@@ -2139,25 +2146,23 @@ XMLHttpRequestMainThread::ChangeStateToD
     MaybeDispatchProgressEvents(true);
   }
 
   ChangeState(XML_HTTP_REQUEST_DONE, true);
   if (mTimeoutTimer) {
     mTimeoutTimer->Cancel();
   }
 
-  NS_NAMED_LITERAL_STRING(errorStr, ERROR_STR);
-  NS_NAMED_LITERAL_STRING(loadStr, LOAD_STR);
   DispatchProgressEvent(this,
-                        mErrorLoad ? errorStr : loadStr,
+                        mErrorLoad ? ProgressEventType::error : ProgressEventType::load,
                         !mErrorLoad,
                         mLoadTransferred,
                         mErrorLoad ? 0 : mLoadTransferred);
   if (mErrorLoad && mUpload && !mUploadComplete) {
-    DispatchProgressEvent(mUpload, errorStr, true,
+    DispatchProgressEvent(mUpload, ProgressEventType::error, true,
                           mUploadTransferred, mUploadTotal);
   }
 
   if (mErrorLoad) {
     // By nulling out channel here we make it so that Send() can test
     // for that and throw. Also calling the various status
     // methods/members will not throw.
     // This matches what IE does.
@@ -2828,20 +2833,20 @@ XMLHttpRequestMainThread::Send(nsIVarian
     // Now that we've successfully opened the channel, we can change state.  Note
     // that this needs to come after the AsyncOpen() and rv check, because this
     // can run script that would try to restart this request, and that could end
     // up doing our AsyncOpen on a null channel if the reentered AsyncOpen fails.
     ChangeState(XML_HTTP_REQUEST_SENT);
     if (mUpload && mUpload->HasListenersFor(nsGkAtoms::onprogress)) {
       StartProgressEventTimer();
     }
-    DispatchProgressEvent(this, NS_LITERAL_STRING(LOADSTART_STR), false,
+    DispatchProgressEvent(this, ProgressEventType::loadstart, false,
                           0, 0);
     if (mUpload && !mUploadComplete) {
-      DispatchProgressEvent(mUpload, NS_LITERAL_STRING(LOADSTART_STR), true,
+      DispatchProgressEvent(mUpload, ProgressEventType::loadstart, true,
                             0, mUploadTotal);
     }
   }
 
   if (!mChannel) {
     return NS_ERROR_FAILURE;
   }
 
@@ -3258,26 +3263,26 @@ XMLHttpRequestMainThread::MaybeDispatchP
   if (!aFinalProgress) {
     StartProgressEventTimer();
   }
 
   // We're uploading if our state is XML_HTTP_REQUEST_OPENED or
   // XML_HTTP_REQUEST_SENT
   if ((XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT) & mState) {
     if (mUpload && !mUploadComplete) {
-      DispatchProgressEvent(mUpload, NS_LITERAL_STRING(PROGRESS_STR),
+      DispatchProgressEvent(mUpload, ProgressEventType::progress,
                             mUploadLengthComputable, mUploadTransferred,
                             mUploadTotal);
     }
   } else {
     if (aFinalProgress) {
       mLoadTotal = mLoadTransferred;
     }
     mInLoadProgressEvent = true;
-    DispatchProgressEvent(this, NS_LITERAL_STRING(PROGRESS_STR),
+    DispatchProgressEvent(this, ProgressEventType::progress,
                           mLoadLengthComputable, mLoadTransferred,
                           mLoadTotal);
     mInLoadProgressEvent = false;
     if (mResponseType == XMLHttpRequestResponseType::Moz_chunked_text ||
         mResponseType == XMLHttpRequestResponseType::Moz_chunked_arraybuffer) {
       mResponseBody.Truncate();
       mResponseText.Truncate();
       mResultArrayBuffer = nullptr;
@@ -3476,18 +3481,17 @@ void
 XMLHttpRequestMainThread::HandleTimeoutCallback()
 {
   if (mState & XML_HTTP_REQUEST_DONE) {
     NS_NOTREACHED("XMLHttpRequestMainThread::HandleTimeoutCallback with completed request");
     // do nothing!
     return;
   }
 
-  CloseRequestWithError(NS_LITERAL_STRING(TIMEOUT_STR),
-                        XML_HTTP_REQUEST_TIMED_OUT);
+  CloseRequestWithError(ProgressEventType::timeout, XML_HTTP_REQUEST_TIMED_OUT);
 }
 
 NS_IMETHODIMP
 XMLHttpRequestMainThread::Notify(nsITimer* aTimer)
 {
   if (mProgressNotifier == aTimer) {
     HandleProgressTimerCallback();
     return NS_OK;
--- a/dom/xhr/XMLHttpRequestMainThread.h
+++ b/dom/xhr/XMLHttpRequestMainThread.h
@@ -122,16 +122,27 @@ class XMLHttpRequestMainThread final : p
                                        public nsSupportsWeakReference,
                                        public nsITimerCallback,
                                        public nsISizeOfEventTarget
 {
   friend class nsXHRParseEndListener;
   friend class nsXMLHttpRequestXPCOMifier;
 
 public:
+  enum class ProgressEventType : uint8_t {
+    loadstart,
+    progress,
+    error,
+    abort,
+    timeout,
+    load,
+    loadend,
+    ENUM_MAX
+  };
+
   XMLHttpRequestMainThread();
 
   void Construct(nsIPrincipal* aPrincipal,
                  nsIGlobalObject* aGlobalObject,
                  nsIURI* aBaseURI = nullptr,
                  nsILoadGroup* aLoadGroup = nullptr)
   {
     MOZ_ASSERT(aPrincipal);
@@ -507,17 +518,17 @@ public:
   GetInterface(JSContext* aCx, nsIJSID* aIID,
                JS::MutableHandle<JS::Value> aRetval,
                ErrorResult& aRv) override;
 
   // This creates a trusted readystatechange event, which is not cancelable and
   // doesn't bubble.
   nsresult CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent);
   void DispatchProgressEvent(DOMEventTargetHelper* aTarget,
-                             const nsAString& aType,
+                             const ProgressEventType aType,
                              bool aLengthComputable,
                              int64_t aLoaded, int64_t aTotal);
 
   // Dispatch the "progress" event on the XHR or XHR.upload object if we've
   // received data since the last "progress" event. Also dispatches
   // "uploadprogress" as needed.
   void MaybeDispatchProgressEvents(bool aFinalProgress);
 
@@ -712,17 +723,17 @@ protected:
   /**
    * Close the XMLHttpRequest's channels and dispatch appropriate progress
    * events.
    *
    * @param aType The progress event type.
    * @param aFlag A XML_HTTP_REQUEST_* state flag defined in
    *              XMLHttpRequestMainthread.cpp.
    */
-  void CloseRequestWithError(const nsAString& aType, const uint32_t aFlag);
+  void CloseRequestWithError(const ProgressEventType aType, const uint32_t aFlag);
 
   bool mFirstStartRequestSeen;
   bool mInLoadProgressEvent;
 
   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
   nsCOMPtr<nsIChannel> mNewRedirectChannel;
 
   JS::Heap<JS::Value> mResultJSON;