diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php
index 46934289e9..a84a14a316 100644
--- a/src/__celerity_resource_map__.php
+++ b/src/__celerity_resource_map__.php
@@ -2661,7 +2661,7 @@ celerity_register_resource_map(array(
   ),
   'javelin-uri' =>
   array(
-    'uri' => '/res/0f8f2aef/rsrc/externals/javelin/lib/URI.js',
+    'uri' => '/res/a1e5cbb3/rsrc/externals/javelin/lib/URI.js',
     'type' => 'js',
     'requires' =>
     array(
@@ -4176,7 +4176,7 @@ celerity_register_resource_map(array(
       'uri' => '/res/pkg/f96657b8/diffusion.pkg.js',
       'type' => 'js',
     ),
-    'c9168ae3' =>
+    '7d174323' =>
     array(
       'name' => 'javelin.pkg.js',
       'symbols' =>
@@ -4201,7 +4201,7 @@ celerity_register_resource_map(array(
         17 => 'javelin-typeahead-ondemand-source',
         18 => 'javelin-tokenizer',
       ),
-      'uri' => '/res/pkg/c9168ae3/javelin.pkg.js',
+      'uri' => '/res/pkg/7d174323/javelin.pkg.js',
       'type' => 'js',
     ),
     '6b1fccc6' =>
@@ -4261,7 +4261,7 @@ celerity_register_resource_map(array(
     'global-drag-and-drop-css' => '55644450',
     'inline-comment-summary-css' => '8aaacd1b',
     'javelin-aphlict' => '26980a1c',
-    'javelin-behavior' => 'c9168ae3',
+    'javelin-behavior' => '7d174323',
     'javelin-behavior-aphlict-dropdown' => '26980a1c',
     'javelin-behavior-aphlict-listen' => '26980a1c',
     'javelin-behavior-aphront-basic-tokenizer' => '26980a1c',
@@ -4312,24 +4312,24 @@ celerity_register_resource_map(array(
     'javelin-behavior-repository-crossreference' => '27c55b30',
     'javelin-behavior-toggle-class' => '26980a1c',
     'javelin-behavior-workflow' => '26980a1c',
-    'javelin-dom' => 'c9168ae3',
-    'javelin-event' => 'c9168ae3',
-    'javelin-install' => 'c9168ae3',
-    'javelin-json' => 'c9168ae3',
-    'javelin-mask' => 'c9168ae3',
-    'javelin-request' => 'c9168ae3',
-    'javelin-resource' => 'c9168ae3',
-    'javelin-stratcom' => 'c9168ae3',
-    'javelin-tokenizer' => 'c9168ae3',
-    'javelin-typeahead' => 'c9168ae3',
-    'javelin-typeahead-normalizer' => 'c9168ae3',
-    'javelin-typeahead-ondemand-source' => 'c9168ae3',
-    'javelin-typeahead-preloaded-source' => 'c9168ae3',
-    'javelin-typeahead-source' => 'c9168ae3',
-    'javelin-uri' => 'c9168ae3',
-    'javelin-util' => 'c9168ae3',
-    'javelin-vector' => 'c9168ae3',
-    'javelin-workflow' => 'c9168ae3',
+    'javelin-dom' => '7d174323',
+    'javelin-event' => '7d174323',
+    'javelin-install' => '7d174323',
+    'javelin-json' => '7d174323',
+    'javelin-mask' => '7d174323',
+    'javelin-request' => '7d174323',
+    'javelin-resource' => '7d174323',
+    'javelin-stratcom' => '7d174323',
+    'javelin-tokenizer' => '7d174323',
+    'javelin-typeahead' => '7d174323',
+    'javelin-typeahead-normalizer' => '7d174323',
+    'javelin-typeahead-ondemand-source' => '7d174323',
+    'javelin-typeahead-preloaded-source' => '7d174323',
+    'javelin-typeahead-source' => '7d174323',
+    'javelin-uri' => '7d174323',
+    'javelin-util' => '7d174323',
+    'javelin-vector' => '7d174323',
+    'javelin-workflow' => '7d174323',
     'lightbox-attachment-css' => '55644450',
     'maniphest-task-summary-css' => '6b1fccc6',
     'maniphest-transaction-detail-css' => '6b1fccc6',
diff --git a/webroot/rsrc/externals/javelin/lib/URI.js b/webroot/rsrc/externals/javelin/lib/URI.js
index cca2d4e3bb..35e614fc7a 100644
--- a/webroot/rsrc/externals/javelin/lib/URI.js
+++ b/webroot/rsrc/externals/javelin/lib/URI.js
@@ -44,7 +44,6 @@ JX.$U = function(uri) {
 JX.install('URI', {
   statics : {
     _uriPattern : /(?:([^:\/?#]+):)?(?:\/\/([^:\/?#]*)(?::(\d*))?)?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/,
-    _queryPattern : /(?:^|&)([^&=]*)=?([^&]*)/g,
 
     /**
      *  Convert a Javascript object into an HTTP query string.
@@ -62,6 +61,10 @@ JX.install('URI', {
       }
 
       return kv_pairs.join('&');
+    },
+
+    _decode : function(str) {
+      return decodeURIComponent(str.replace(/\+/g, ' '));
     }
   },
 
@@ -94,14 +97,23 @@ JX.install('URI', {
       this.setPath(path.charAt(0) == '/' ? path : '/' + path);
 
       // parse the query data
-      if (query) {
-        var queryData = {};
-        var data;
-        while ((data = JX.URI._queryPattern.exec(query)) != null) {
-          queryData[decodeURIComponent(data[1].replace(/\+/g, ' '))] =
-            decodeURIComponent(data[2].replace(/\+/g, ' '));
+      if (query && query.length) {
+        var dict = {};
+        var parts = query.split('&');
+        for (var ii = 0; ii < parts.length; ii++) {
+          var part = parts[ii];
+          if (!part.length) {
+            continue;
+          }
+          var pieces = part.split('=');
+          var name = pieces[0];
+          if (!name.length) {
+            continue;
+          }
+          var value = pieces.slice(1).join('=') || '';
+          dict[JX.URI._decode(name)] = JX.URI._decode(value);
         }
-        this.setQueryParams(queryData);
+        this.setQueryParams(dict);
       }
     }
   },
diff --git a/webroot/rsrc/externals/javelin/lib/__tests__/URI.js b/webroot/rsrc/externals/javelin/lib/__tests__/URI.js
index 3dbaa3f968..56639a161f 100644
--- a/webroot/rsrc/externals/javelin/lib/__tests__/URI.js
+++ b/webroot/rsrc/externals/javelin/lib/__tests__/URI.js
@@ -289,5 +289,15 @@ describe('Javelin URI', function() {
     expect(uri2.getQueryParams()).not.toEqual({'key' : 'value'});
   });
 
+  it('should not loop indefinitely when parsing empty params', function() {
+    expect(JX.$U('/?&key=value').getQueryParams()).toEqual({'key' : 'value'});
+    expect(JX.$U('/?&&&key=value').getQueryParams()).toEqual({'key' : 'value'});
+    expect(JX.$U('/?&&').getQueryParams()).toEqual({});
+  });
+
+  it('should parse values with =', function() {
+    expect(JX.$U('/?x=1=1').getQueryParams()).toEqual({'x' : '1=1'});
+  });
+
 });