Bug 1426501 - Change JS code to use nsIURIMutator instead of the nsIURI.spec setter draft
authorValentin Gosu <valentin.gosu@gmail.com>
Mon, 08 Jan 2018 15:20:29 +0100
changeset 717301 3d8e37a3b1b34e8226a8096a953c6f93da8d00c0
parent 717193 369c881aee3fa22121fd6a7333357731a54fd56d
child 717302 613bd4450706c5aa36a29b83b0e56d42fa3866b6
push id94613
push uservalentin.gosu@gmail.com
push dateMon, 08 Jan 2018 14:47:20 +0000
bugs1426501
milestone59.0a1
Bug 1426501 - Change JS code to use nsIURIMutator instead of the nsIURI.spec setter MozReview-Commit-ID: FI6WrsQT2ke
chrome/test/unit/test_no_remote_registration.js
dom/base/test/chrome/test_bug682305.html
dom/base/test/test_bug422403-1.html
dom/base/test/test_bug422403-2.xhtml
dom/base/test/test_bug424359-1.html
dom/base/test/test_bug424359-2.html
dom/base/test/test_bug498433.html
dom/tests/unit/test_bug465752.js
dom/xslt/tests/XSLTMark/XSLTMark-static.js
dom/xslt/tests/XSLTMark/XSLTMark-view.js
netwerk/test/browser/browser_nsIFormPOSTActionChannel.js
netwerk/test/unit/test_1351443-missing-NewChannel2.js
netwerk/test/unit/test_bug1177909.js
netwerk/test/unit/test_bug261425.js
netwerk/test/unit/test_bug412457.js
netwerk/test/unit/test_bug429347.js
netwerk/test/unit/test_bug479485.js
netwerk/test/unit/test_bug660066.js
netwerk/test/unit/test_bug894586.js
netwerk/test/unit/test_protocolproxyservice.js
netwerk/test/unit/test_standardurl.js
netwerk/test/unit/test_standardurl_port.js
testing/mochitest/tests/Harness_sanity/test_SpecialPowersExtension.html
toolkit/components/mozprotocol/mozProtocolHandler.js
toolkit/components/places/PageIconProtocolHandler.js
widget/tests/unit/test_taskbar_jumplistitems.js
--- a/chrome/test/unit/test_no_remote_registration.js
+++ b/chrome/test/unit/test_no_remote_registration.js
@@ -18,24 +18,24 @@ function ProtocolHandler(aScheme, aFlags
   this.contractID = "@mozilla.org/network/protocol;1?name=" + aScheme;
 }
 
 ProtocolHandler.prototype =
 {
   defaultPort: -1,
   allowPort: () => false,
   newURI(aSpec, aCharset, aBaseURI) {
-    let uri = Cc["@mozilla.org/network/standard-url;1"].
-              createInstance(Ci.nsIURI);
-    uri.spec = aSpec;
-    if (!uri.scheme) {
-      // We got a partial uri, so let's resolve it with the base one
-      uri.spec = aBaseURI.resolve(aSpec);
+    let mutator = Cc["@mozilla.org/network/standard-url-mutator;1"]
+                    .createInstance(Ci.nsIURIMutator);
+    if (aBaseURI) {
+      mutator.setSpec(aBaseURI.resolve(aSpec));
+    } else {
+      mutator.setSpec(aSpec);
     }
-    return uri;
+    return mutator.finalize();
   },
   newChannel2() { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
   newChannel() { throw Cr.NS_ERROR_NOT_IMPLEMENTED; },
   QueryInterface: XPCOMUtils.generateQI([
     Ci.nsIProtocolHandler
   ])
 };
 
--- a/dom/base/test/chrome/test_bug682305.html
+++ b/dom/base/test/chrome/test_bug682305.html
@@ -27,17 +27,16 @@ SimpleTest.waitForExplicitFinish();
  */
 
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cr = Components.results;
 var Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-var SimpleURI = Cc["@mozilla.org/network/simple-uri;1"];
 var ios = Cc["@mozilla.org/network/io-service;1"]
             .getService(Ci.nsIIOService);
 var contentSecManager = Cc["@mozilla.org/contentsecuritymanager;1"]
                           .getService(Ci.nsIContentSecurityManager);
 
 var PROTOCOL_SCHEME = "jsproto";
 
 
@@ -115,19 +114,20 @@ CustomProtocol.prototype = {
   },
   get defaultPort() {
     return -1;
   },
   allowPort: function allowPort() {
     return false;
   },
   newURI: function newURI(spec, charset, baseURI) {
-    var uri = SimpleURI.createInstance(Ci.nsIURI)
-    uri.spec = spec;
-    return uri.QueryInterface(Ci.nsIURI);
+    return Cc["@mozilla.org/network/simple-uri-mutator;1"]
+             .createInstance(Ci.nsIURIMutator)
+             .setSpec(spec)
+             .finalize();
   },
   newChannel2: function newChannel2(URI, loadInfo) {
     return new CustomChannel(URI, loadInfo);
   },
   newChannel: function newChannel(URI) {
     return newChannel2(URI);
   },
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
--- a/dom/base/test/test_bug422403-1.html
+++ b/dom/base/test/test_bug422403-1.html
@@ -19,19 +19,20 @@
 <script class="testbody" type="text/javascript">
 
 
 function loadFileContent(aFile, aCharset) {
     //if(aAsIso == undefined) aAsIso = false;
     if(aCharset == undefined)
         aCharset = 'UTF-8';
 
-    var baseUri = SpecialPowers.Cc['@mozilla.org/network/standard-url;1']
-                   .createInstance(SpecialPowers.Ci.nsIURI);
-    baseUri.spec = window.location.href;
+    var baseUri = SpecialPowers.Cc['@mozilla.org/network/standard-url-mutator;1']
+                                  .createInstance(SpecialPowers.Ci.nsIURIMutator)
+                                  .setSpec(window.location.href)
+                                  .finalize();
 
     var ios = SpecialPowers.Cc['@mozilla.org/network/io-service;1']
             .getService(SpecialPowers.Ci.nsIIOService);
     var chann = ios.newChannel2(aFile,
                                 aCharset,
                                 baseUri,
                                 null,      // aLoadingNode
                                 SpecialPowers.Services.scriptSecurityManager.getSystemPrincipal(),
--- a/dom/base/test/test_bug422403-2.xhtml
+++ b/dom/base/test/test_bug422403-2.xhtml
@@ -18,19 +18,20 @@
 <script class="testbody" type="text/javascript">
 //<![CDATA[
 
 function loadFileContent(aFile, aCharset) {
     //if(aAsIso == undefined) aAsIso = false;
     if(aCharset == undefined)
         aCharset = 'UTF-8';
 
-    var baseUri = SpecialPowers.Cc['@mozilla.org/network/standard-url;1']
-                   .createInstance(SpecialPowers.Ci.nsIURI);
-    baseUri.spec = window.location.href;
+    var baseUri = SpecialPowers.Cc['@mozilla.org/network/standard-url-mutator;1']
+                                  .createInstance(SpecialPowers.Ci.nsIURIMutator)
+                                  .setSpec(window.location.href)
+                                  .finalize();
 
     var ios = SpecialPowers.Cc['@mozilla.org/network/io-service;1']
             .getService(SpecialPowers.Ci.nsIIOService);
     var chann = ios.newChannel2(aFile,
                                 aCharset,
                                 baseUri,
                                 null,      // aLoadingNode
                                 SpecialPowers.Services.scriptSecurityManager.getSystemPrincipal(),
--- a/dom/base/test/test_bug424359-1.html
+++ b/dom/base/test/test_bug424359-1.html
@@ -19,19 +19,20 @@
 <script class="testbody" type="text/javascript">
 
 
 function loadFileContent(aFile, aCharset) {
     //if(aAsIso == undefined) aAsIso = false;
     if(aCharset == undefined)
         aCharset = 'UTF-8';
 
-    var baseUri = SpecialPowers.Cc['@mozilla.org/network/standard-url;1']
-                   .createInstance(SpecialPowers.Ci.nsIURI);
-    baseUri.spec = window.location.href;
+    var baseUri = SpecialPowers.Cc['@mozilla.org/network/standard-url-mutator;1']
+                                  .createInstance(SpecialPowers.Ci.nsIURIMutator)
+                                  .setSpec(window.location.href)
+                                  .finalize();
 
     var ios = SpecialPowers.Cc['@mozilla.org/network/io-service;1']
             .getService(SpecialPowers.Ci.nsIIOService);
     var chann = ios.newChannel2(aFile,
                                 aCharset,
                                 baseUri,
                                 null,      // aLoadingNode
                                 SpecialPowers.Services.scriptSecurityManager.getSystemPrincipal(),
--- a/dom/base/test/test_bug424359-2.html
+++ b/dom/base/test/test_bug424359-2.html
@@ -18,19 +18,20 @@
 <script class="testbody" type="text/javascript">
 
 
 function loadFileContent(aFile, aCharset) {
     //if(aAsIso == undefined) aAsIso = false;
     if(aCharset == undefined)
         aCharset = 'UTF-8';
 
-    var baseUri = SpecialPowers.Cc['@mozilla.org/network/standard-url;1']
-                   .createInstance(SpecialPowers.Ci.nsIURI);
-    baseUri.spec = window.location.href;
+    var baseUri = SpecialPowers.Cc['@mozilla.org/network/standard-url-mutator;1']
+                                  .createInstance(SpecialPowers.Ci.nsIURIMutator)
+                                  .setSpec(window.location.href)
+                                  .finalize();
 
     var ios = SpecialPowers.Cc['@mozilla.org/network/io-service;1']
             .getService(SpecialPowers.Ci.nsIIOService);
     var chann = ios.newChannel2(aFile,
                                 aCharset,
                                 baseUri,
                                 null,      // aLoadingNode
                                 SpecialPowers.Services.scriptSecurityManager.getSystemPrincipal(),
--- a/dom/base/test/test_bug498433.html
+++ b/dom/base/test/test_bug498433.html
@@ -17,19 +17,20 @@
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 
 function loadFileContent(aFile, aCharset) {
     if (aCharset == undefined)
         aCharset = 'UTF-8';
 
-    var baseUri = SpecialPowers.Cc['@mozilla.org/network/standard-url;1']
-                   .createInstance(SpecialPowers.Ci.nsIURI);
-    baseUri.spec = window.location.href;
+    var baseUri = SpecialPowers.Cc['@mozilla.org/network/standard-url-mutator;1']
+                                  .createInstance(SpecialPowers.Ci.nsIURIMutator)
+                                  .setSpec(window.location.href)
+                                  .finalize();
 
     var ios = SpecialPowers.Cc['@mozilla.org/network/io-service;1']
             .getService(SpecialPowers.Ci.nsIIOService);
     var chann = ios.newChannel2(aFile,
                                 aCharset,
                                 baseUri,
                                 null,      // aLoadingNode
                                 SpecialPowers.Services.scriptSecurityManager.getSystemPrincipal(),
--- a/dom/tests/unit/test_bug465752.js
+++ b/dom/tests/unit/test_bug465752.js
@@ -14,15 +14,16 @@ function run_test()
   var uri3 = ios.newURI(str2);
   Assert.ok(uri.equals(uri));
   Assert.ok(uri.equals(uri2));
   Assert.ok(uri2.equals(uri));
   Assert.ok(uri2.equals(uri2));
   Assert.ok(!uri3.equals(uri2));
   Assert.ok(!uri2.equals(uri3));
 
-  var simple = Components.classes["@mozilla.org/network/simple-uri;1"]
-                         .createInstance(Components.interfaces.nsIURI);
-  simple.spec = str;
+  var simple = Components.classes["@mozilla.org/network/simple-uri-mutator;1"]
+                         .createInstance(Components.interfaces.nsIURIMutator)
+                         .setSpec(str)
+                         .finalize();
   Assert.equal(simple.spec, uri.spec);
   Assert.ok(!simple.equals(uri));
   Assert.ok(!uri.equals(simple));
 }
--- a/dom/xslt/tests/XSLTMark/XSLTMark-static.js
+++ b/dom/xslt/tests/XSLTMark/XSLTMark-static.js
@@ -4,18 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const enablePrivilege = netscape.security.PrivilegeManager.enablePrivilege;
 const IOSERVICE_CTRID = "@mozilla.org/network/io-service;1";
 const nsIIOService    = Components.interfaces.nsIIOService;
 const SIS_CTRID       = "@mozilla.org/scriptableinputstream;1";
 const nsISIS          = Components.interfaces.nsIScriptableInputStream;
 const nsIFilePicker   = Components.interfaces.nsIFilePicker;
-const STDURL_CTRID    = "@mozilla.org/network/standard-url;1";
-const nsIURI          = Components.interfaces.nsIURI;
+const STDURLMUT_CTRID = "@mozilla.org/network/standard-url-mutator;1";
+const nsIURIMutator   = Components.interfaces.nsIURIMutator;
 
 Components.utils.import("resource://gre/modules/NetUtil.jsm");
 
 var gStop = false;
 
 function loadFile(aUriSpec)
 {
     enablePrivilege('UniversalXPConnect');
--- a/dom/xslt/tests/XSLTMark/XSLTMark-view.js
+++ b/dom/xslt/tests/XSLTMark/XSLTMark-view.js
@@ -15,18 +15,20 @@ var view =
         var fp = Components.classes["@mozilla.org/filepicker;1"].
         createInstance(nsIFilePicker);
         fp.init(window,'XSLTMark Description File',nsIFilePicker.modeOpen);
         fp.appendFilter('*.conf', '*.conf');
         fp.appendFilters(nsIFilePicker.filterAll);
         var res = fp.show();
 
         if (res == nsIFilePicker.returnOK) {
-            this.configUrl = Components.classes[STDURL_CTRID].createInstance(nsIURI);
-            this.configUrl.spec = fp.fileURL.spec;
+            this.configUrl = Components.classes[STDURLMUT_CTRID]
+                                       .createInstance(nsIURIMutator)
+                                       .setSpec(fp.fileURL.spec)
+                                       .finalize();
             document.getElementById('config').setAttribute('value', this.configUrl.spec);
         }
         this.parseConfig();
         return true;
     },
 
     parseConfig: function()
     {
@@ -148,18 +150,21 @@ var view =
         }
     },
 
     runBenchmark: function()
     {
         enablePrivilege('UniversalXPConnect');
         if (!this.testArray) {
             if (!this.configUrl) {
-                this.configUrl = Components.classes[STDURL_CTRID].createInstance(nsIURI);
-                this.configUrl.spec = document.getElementById('config').value;
+                this.configUrl =
+                    Components.classes[STDURLMUT_CTRID]
+                              .createInstance(nsIURIMutator)
+                              .setSpec(document.getElementById('config').value)
+                              .finalize();
             }
             this.parseConfig();
         }
 
         this.mCurrent = 0;
         var test = this.testArray[this.mCurrent];
         this.mOutput.value = '';
         if (this.mDetail) {
--- a/netwerk/test/browser/browser_nsIFormPOSTActionChannel.js
+++ b/netwerk/test/browser/browser_nsIFormPOSTActionChannel.js
@@ -28,20 +28,20 @@ CustomProtocolHandler.prototype = {
   get defaultPort() {
     return -1;
   },
   get protocolFlags() {
     return Ci.nsIProtocolHandler.URI_NORELATIVE |
            Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE;
   },
   newURI: function(aSpec, aOriginCharset, aBaseURI) {
-    var uri = Cc["@mozilla.org/network/standard-url;1"].
-              createInstance(Ci.nsIURI);
-    uri.spec = aSpec;
-    return uri;
+    return Cc["@mozilla.org/network/standard-url-mutator;1"]
+             .createInstance(Ci.nsIURIMutator)
+             .setSpec(aSpec)
+             .finalize()
   },
   newChannel2: function(aURI, aLoadInfo) {
     return new CustomChannel(aURI, aLoadInfo);
   },
   newChannel: function(aURI) {
     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
   },
   allowPort: function(port, scheme) {
--- a/netwerk/test/unit/test_1351443-missing-NewChannel2.js
+++ b/netwerk/test/unit/test_1351443-missing-NewChannel2.js
@@ -8,19 +8,20 @@
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 
 var contentSecManager = Cc["@mozilla.org/contentsecuritymanager;1"]
                           .getService(Ci.nsIContentSecurityManager);
 
 function ProtocolHandler() {
-  this.uri = Cc["@mozilla.org/network/simple-uri;1"].
-               createInstance(Ci.nsIURI);
-  this.uri.spec = this.scheme + ":dummy";
+  this.uri = Cc["@mozilla.org/network/simple-uri-mutator;1"]
+               .createInstance(Ci.nsIURIMutator)
+               .setSpec(this.scheme + ":dummy")
+               .finalize();
   this.uri.QueryInterface(Ci.nsIMutable).mutable = false;
 }
 
 ProtocolHandler.prototype = {
   /** nsIProtocolHandler */
   get scheme() {
     return "x-1351443";
   },
--- a/netwerk/test/unit/test_bug1177909.js
+++ b/netwerk/test/unit/test_bug1177909.js
@@ -94,20 +94,23 @@ add_task(async function testSocksProxy()
   let pi = await TestProxyTypeByURI("http://www.mozilla.org:1234/");
   equal(pi.host, "localhost", "Expected proxy host to be localhost");
   equal(pi.port, 9050, "Expected proxy port to be 8080");
   equal(pi.type, "socks", "Expected proxy type to be http");
 });
 
 add_task(async function testDirectProxy() {
   // Do what |WebSocketChannel::AsyncOpen| do, but do not prefer https proxy.
-  let proxyURI = Cc["@mozilla.org/network/standard-url;1"].createInstance(Ci.nsIURI);
-  proxyURI.spec = "wss://ws.mozilla.org/";
-  let uri = proxyURI.clone();
-  uri.scheme = "https";
+  let proxyURI = Cc["@mozilla.org/network/standard-url-mutator;1"]
+                   .createInstance(Ci.nsIURIMutator)
+                   .setSpec("wss://ws.mozilla.org/")
+                   .finalize();
+  let uri = proxyURI.mutate()
+                    .setScheme("https")
+                    .finalize();
 
   let ioService = Cc["@mozilla.org/network/io-service;1"].
                     getService(Ci.nsIIOService);
   let chan = ioService.
     newChannelFromURIWithProxyFlags2(uri,
                                      proxyURI,
                                      0,
                                      null,
@@ -117,20 +120,23 @@ add_task(async function testDirectProxy(
                                      Ci.nsIContentPolicy.TYPE_OTHER);
 
   let pi = await TestProxyType(chan, 0);
   equal(pi, null, "Expected proxy host to be null");
 });
 
 add_task(async function testWebSocketProxy() {
   // Do what |WebSocketChannel::AsyncOpen| do
-  let proxyURI = Cc["@mozilla.org/network/standard-url;1"].createInstance(Ci.nsIURI);
-  proxyURI.spec = "wss://ws.mozilla.org/";
-  let uri = proxyURI.clone();
-  uri.scheme = "https";
+  let proxyURI = Cc["@mozilla.org/network/standard-url-mutator;1"]
+                   .createInstance(Ci.nsIURIMutator)
+                   .setSpec("wss://ws.mozilla.org/")
+                   .finalize();
+  let uri = proxyURI.mutate()
+                    .setScheme("https")
+                    .finalize();
 
   let proxyFlags = Ci.nsIProtocolProxyService.RESOLVE_PREFER_HTTPS_PROXY |
                    Ci.nsIProtocolProxyService.RESOLVE_ALWAYS_TUNNEL;
 
   let ioService = Cc["@mozilla.org/network/io-service;1"].
                     getService(Ci.nsIIOService);
   let chan = ioService.
     newChannelFromURIWithProxyFlags2(uri,
--- a/netwerk/test/unit/test_bug261425.js
+++ b/netwerk/test/unit/test_bug261425.js
@@ -1,17 +1,17 @@
 function run_test() {
   var ios = Cc["@mozilla.org/network/io-service;1"].
     getService(Ci.nsIIOService);
 
   var newURI = ios.newURI("http://foo.com");
 
   var success = false;
   try {
-    newURI.spec = "http: //foo.com";
+    newURI = newURI.mutate().setSpec("http: //foo.com").finalize();
   }
   catch (e) {
     success = e.result == Cr.NS_ERROR_MALFORMED_URI;
   }
   if (!success)
     do_throw("We didn't throw NS_ERROR_MALFORMED_URI when a space was passed in the hostname!");
 
   success = false;
--- a/netwerk/test/unit/test_bug412457.js
+++ b/netwerk/test/unit/test_bug412457.js
@@ -2,43 +2,43 @@ function run_test() {
   var ios = Cc["@mozilla.org/network/io-service;1"].
     getService(Ci.nsIIOService);
 
   // check if hostname is unescaped before applying IDNA
   var newURI = ios.newURI("http://\u5341%2ecom/");
   Assert.equal(newURI.asciiHost, "xn--kkr.com");
 
   // escaped UTF8
-  newURI.spec = "http://%e5%8d%81.com";
+  newURI = newURI.mutate().setSpec("http://%e5%8d%81.com").finalize();
   Assert.equal(newURI.asciiHost, "xn--kkr.com");
 
   // There should be only allowed characters in hostname after
   // unescaping and attempting to apply IDNA. "\x80" is illegal in
   // UTF-8, so IDNA fails, and 0x80 is illegal in DNS too.
-  Assert.throws(() => { newURI.spec = "http://%80.com"; }, "illegal UTF character");
+  Assert.throws(() => { newURI = newURI.mutate().setSpec("http://%80.com").finalize(); }, "illegal UTF character");
 
   // test parsing URL with all possible host terminators
-  newURI.spec = "http://example.com?foo";
+  newURI = newURI.mutate().setSpec("http://example.com?foo").finalize();
   Assert.equal(newURI.asciiHost, "example.com");
 
-  newURI.spec = "http://example.com#foo";
+  newURI = newURI.mutate().setSpec("http://example.com#foo").finalize();
   Assert.equal(newURI.asciiHost, "example.com");
 
-  newURI.spec = "http://example.com:80";
+  newURI = newURI.mutate().setSpec("http://example.com:80").finalize();
   Assert.equal(newURI.asciiHost, "example.com");
 
-  newURI.spec = "http://example.com/foo";
+  newURI = newURI.mutate().setSpec("http://example.com/foo").finalize();
   Assert.equal(newURI.asciiHost, "example.com");
 
   // Characters that are invalid in the host, shouldn't be decoded.
-  newURI.spec = "http://example.com%3ffoo";
+  newURI = newURI.mutate().setSpec("http://example.com%3ffoo").finalize();
   Assert.equal(newURI.asciiHost, "example.com%3ffoo");
-  newURI.spec = "http://example.com%23foo";
+  newURI = newURI.mutate().setSpec("http://example.com%23foo").finalize();
   Assert.equal(newURI.asciiHost, "example.com%23foo");
-  newURI.spec = "http://example.com%3bfoo";
+  newURI = newURI.mutate().setSpec("http://example.com%3bfoo").finalize();
   Assert.equal(newURI.asciiHost, "example.com%3bfoo");
-  newURI.spec = "http://example.com%3a80";
+  newURI = newURI.mutate().setSpec("http://example.com%3a80").finalize();
   Assert.equal(newURI.asciiHost, "example.com%3a80");
-  newURI.spec = "http://example.com%2ffoo";
+  newURI = newURI.mutate().setSpec("http://example.com%2ffoo").finalize();
   Assert.equal(newURI.asciiHost, "example.com%2ffoo");
-  newURI.spec = "http://example.com%00";
+  newURI = newURI.mutate().setSpec("http://example.com%00").finalize();
   Assert.equal(newURI.asciiHost, "example.com%00");
 }
\ No newline at end of file
--- a/netwerk/test/unit/test_bug429347.js
+++ b/netwerk/test/unit/test_bug429347.js
@@ -1,38 +1,38 @@
 function run_test() {
   var ios = Cc["@mozilla.org/network/io-service;1"].
     getService(Ci.nsIIOService);
 
   var uri1 = ios.newURI("http://example.com#bar");
   var uri2 = ios.newURI("http://example.com/#bar");
   Assert.ok(uri1.equals(uri2));
 
-  uri1.spec = "http://example.com?bar";
-  uri2.spec = "http://example.com/?bar";
+  uri1 = uri1.mutate().setSpec("http://example.com?bar").finalize();
+  uri2 = uri2.mutate().setSpec("http://example.com/?bar").finalize();
   Assert.ok(uri1.equals(uri2));
 
   // see https://bugzilla.mozilla.org/show_bug.cgi?id=665706
   // ";" is not parsed as special anymore and thus ends up
   // in the authority component (see RFC 3986)
-  uri1.spec = "http://example.com;bar";
-  uri2.spec = "http://example.com/;bar";
+  uri1 = uri1.mutate().setSpec("http://example.com;bar").finalize();
+  uri2 = uri2.mutate().setSpec("http://example.com/;bar").finalize();
   Assert.ok(!uri1.equals(uri2));
 
-  uri1.spec = "http://example.com#";
-  uri2.spec = "http://example.com/#";
+  uri1 = uri1.mutate().setSpec("http://example.com#").finalize();
+  uri2 = uri2.mutate().setSpec("http://example.com/#").finalize();
   Assert.ok(uri1.equals(uri2));
 
-  uri1.spec = "http://example.com?";
-  uri2.spec = "http://example.com/?";
+  uri1 = uri1.mutate().setSpec("http://example.com?").finalize();
+  uri2 = uri2.mutate().setSpec("http://example.com/?").finalize();
   Assert.ok(uri1.equals(uri2));
 
   // see https://bugzilla.mozilla.org/show_bug.cgi?id=665706
   // ";" is not parsed as special anymore and thus ends up
   // in the authority component (see RFC 3986)
-  uri1.spec = "http://example.com;";
-  uri2.spec = "http://example.com/;";
+  uri1 = uri1.mutate().setSpec("http://example.com;").finalize();
+  uri2 = uri2.mutate().setSpec("http://example.com/;").finalize();
   Assert.ok(!uri1.equals(uri2));
 
-  uri1.spec = "http://example.com";
-  uri2.spec = "http://example.com/";
+  uri1 = uri1.mutate().setSpec("http://example.com").finalize();
+  uri2 = uri2.mutate().setSpec("http://example.com/").finalize();
   Assert.ok(uri1.equals(uri2));
 }
--- a/netwerk/test/unit/test_bug479485.js
+++ b/netwerk/test/unit/test_bug479485.js
@@ -14,17 +14,17 @@ function run_test() {
     }
     if (exception_threw != exception_expected)
       do_throw("We did"+(exception_expected?"n't":"")+" throw NS_ERROR_MALFORMED_URI when creating a new URI with "+port+" as a port");
     Assert.equal(exception_threw, exception_expected);
   
     exception_threw = false;
     newURI = ios.newURI("http://foo.com");
     try {
-      newURI.spec = "http://foo.com"+port;
+      newURI = newURI.mutate().setSpec("http://foo.com"+port).finalize();
     }
     catch (e) {
       exception_threw = e.result == Cr.NS_ERROR_MALFORMED_URI;
     }
     if (exception_threw != exception_expected)
       do_throw("We did"+(exception_expected?"n't":"")+" throw NS_ERROR_MALFORMED_URI when setting a spec of a URI with "+port+" as a port");
     Assert.equal(exception_threw, exception_expected);
   }
--- a/netwerk/test/unit/test_bug660066.js
+++ b/netwerk/test/unit/test_bug660066.js
@@ -27,16 +27,16 @@ function run_test()
 {
   var simpleURI = NetUtil.newURI(SIMPLEURI_SPEC);
   var fileDataURI = NetUtil.newURI(BLOBURI_SPEC);
 
   do_info("Checking that " + SIMPLEURI_SPEC + " != " + BLOBURI_SPEC);
   do_check_uri_neq(simpleURI, fileDataURI);
 
   do_info("Changing the nsSimpleURI spec to match the nsFileDataURI");
-  simpleURI.spec = BLOBURI_SPEC;
+  simpleURI = simpleURI.mutate().setSpec(BLOBURI_SPEC).finalize();
 
   do_info("Verifying that .spec matches");
   Assert.equal(simpleURI.spec, fileDataURI.spec);
 
   do_info("Checking that nsSimpleURI != nsFileDataURI despite their .spec matching")
   do_check_uri_neq(simpleURI, fileDataURI);
 }
--- a/netwerk/test/unit/test_bug894586.js
+++ b/netwerk/test/unit/test_bug894586.js
@@ -6,19 +6,20 @@
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 
 var contentSecManager = Cc["@mozilla.org/contentsecuritymanager;1"]
                           .getService(Ci.nsIContentSecurityManager);
 
 function ProtocolHandler() {
-  this.uri = Cc["@mozilla.org/network/simple-uri;1"].
-               createInstance(Ci.nsIURI);
-  this.uri.spec = this.scheme + ":dummy";
+  this.uri = Cc["@mozilla.org/network/simple-uri-mutator;1"]
+               .createInstance(Ci.nsIURIMutator)
+               .setSpec(this.scheme + ":dummy")
+               .finalize();
   this.uri.QueryInterface(Ci.nsIMutable).mutable = false;
 }
 
 ProtocolHandler.prototype = {
   /** nsIProtocolHandler */
   get scheme() {
     return "x-bug894586";
   },
--- a/netwerk/test/unit/test_protocolproxyservice.js
+++ b/netwerk/test/unit/test_protocolproxyservice.js
@@ -44,20 +44,20 @@ TestProtocolHandler.prototype = {
   },
   scheme: "moz-test",
   defaultPort: -1,
   protocolFlags: Components.interfaces.nsIProtocolHandler.URI_NOAUTH |
                  Components.interfaces.nsIProtocolHandler.URI_NORELATIVE |
                  Components.interfaces.nsIProtocolHandler.ALLOWS_PROXY |
                  Components.interfaces.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD,
   newURI: function(spec, originCharset, baseURI) {
-    var uri = Components.classes["@mozilla.org/network/simple-uri;1"]
-                        .createInstance(Components.interfaces.nsIURI);
-    uri.spec = spec;
-    return uri;
+    return Components.classes["@mozilla.org/network/simple-uri-mutator;1"]
+                     .createInstance(Components.interfaces.nsIURIMutator)
+                     .setSpec(spec)
+                     .finalize();
   },
   newChannel2: function(uri, aLoadInfo) {
     throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
   },
   newChannel: function(uri) {
     throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
   },
   allowPort: function(port, scheme) {
--- a/netwerk/test/unit/test_standardurl.js
+++ b/netwerk/test/unit/test_standardurl.js
@@ -213,18 +213,18 @@ add_test(function test_ipv6_fail()
   Assert.throws(() => { url.hostPort = "[2001::1]:"; }, "missing port number");
   Assert.throws(() => { url.hostPort = "[2001::1]:bad"; }, "bad port number");
   run_next_test();
 });
 
 add_test(function test_clearedSpec()
 {
   var url = stringToURL("http://example.com/path");
-  Assert.throws(() => { url.spec = "http: example"; }, "set bad spec");
-  Assert.throws(() => { url.spec = ""; }, "set empty spec");
+  Assert.throws(() => { url = url.mutate().setSpec("http: example").finalize(); }, "set bad spec");
+  Assert.throws(() => { url = url.mutate().setSpec("").finalize(); }, "set empty spec");
   Assert.equal(url.spec, "http://example.com/path");
   url.host = "allizom.org";
 
   var ref = stringToURL("http://allizom.org/path");
   symmetricEquality(true, url, ref);
   run_next_test();
 });
 
@@ -354,19 +354,21 @@ add_test(function test_authority_host()
 
   run_next_test();
 });
 
 add_test(function test_trim_C0_and_space()
 {
   var url = stringToURL("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f http://example.com/ \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f ");
   Assert.equal(url.spec, "http://example.com/");
-  url.spec = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f http://test.com/ \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f ";
+  url = url.mutate()
+           .setSpec("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f http://test.com/ \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f ")
+           .finalize();
   Assert.equal(url.spec, "http://test.com/");
-  Assert.throws(() => { url.spec = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19 "; }, "set empty spec");
+  Assert.throws(() => { url = url.mutate().setSpec("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19 ").finalize(); }, "set empty spec");
   run_next_test();
 });
 
 // This tests that C0-and-space characters in the path, query and ref are
 // percent encoded.
 add_test(function test_encode_C0_and_space()
 {
   function toHex(d) {
--- a/netwerk/test/unit/test_standardurl_port.js
+++ b/netwerk/test/unit/test_standardurl_port.js
@@ -18,19 +18,19 @@ function run_test() {
   // Setting to default after setting to non-default shouldn't cause a change (bug 403480)
   httpURI.port = 123;
   Assert.equal(123, httpURI.port);
   httpURI.port = 80;
   Assert.equal(-1, httpURI.port);
   Assert.ok(!/80/.test(httpURI.spec));
 
   // URL parsers shouldn't set ports to default value (bug 407538)
-  httpURI.spec = "http://foo.com:81";
+  httpURI = httpURI.mutate().setSpec("http://foo.com:81").finalize();
   Assert.equal(81, httpURI.port);
-  httpURI.spec = "http://foo.com:80";
+  httpURI = httpURI.mutate().setSpec("http://foo.com:80").finalize();
   Assert.equal(-1, httpURI.port);
   Assert.ok(!/80/.test(httpURI.spec));
 
   httpURI = makeURI("http://foo.com");
   Assert.equal(-1, httpURI.port);
   Assert.ok(!/80/.test(httpURI.spec));
 
   httpURI = makeURI("http://foo.com:80");
--- a/testing/mochitest/tests/Harness_sanity/test_SpecialPowersExtension.html
+++ b/testing/mochitest/tests/Harness_sanity/test_SpecialPowersExtension.html
@@ -90,19 +90,20 @@ function starttest(){
 
   //
   // Test the SpecialPowers wrapper.
   //
 
   // Try some basic stuff with XHR.
   var xhr2 = SpecialPowers.Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(SpecialPowers.Ci.nsIXMLHttpRequest);
   is(xhr2.readyState, XMLHttpRequest.UNSENT, "Should be able to get props off privileged objects");
-  var testURI = SpecialPowers.Cc['@mozilla.org/network/standard-url;1']
-                                              .createInstance(SpecialPowers.Ci.nsIURI);
-  testURI.spec = "http://www.foobar.org/";
+  var testURI = SpecialPowers.Cc['@mozilla.org/network/standard-url-mutator;1']
+                             .createInstance(SpecialPowers.Ci.nsIURIMutator)
+                             .setSpec("http://www.foobar.org/")
+                             .finalize();
   is(testURI.spec, "http://www.foobar.org/", "Getters/Setters should work correctly");
   is(SpecialPowers.wrap(document).getElementsByTagName('details').length, 0, "Should work with proxy-based DOM bindings.");
 
   // Play with the window object.
   var webnav = SpecialPowers.wrap(window).QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
                                          .getInterface(SpecialPowers.Ci.nsIWebNavigation);
   webnav.QueryInterface(SpecialPowers.Ci.nsIDocShell);
   ok(webnav.allowJavascript, "Able to pull properties off of docshell!");
--- a/toolkit/components/mozprotocol/mozProtocolHandler.js
+++ b/toolkit/components/mozprotocol/mozProtocolHandler.js
@@ -15,23 +15,24 @@ function mozProtocolHandler() {
 }
 
 mozProtocolHandler.prototype = {
   scheme: "moz",
   defaultPort: -1,
   protocolFlags: Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD,
 
   newURI(spec, charset, base) {
-    let uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI);
+    let mutator = Cc["@mozilla.org/network/simple-uri-mutator;1"]
+                    .createInstance(Ci.nsIURIMutator);
     if (base) {
-      uri.spec = base.resolve(spec);
+      mutator.setSpec(base.resolve(spec));
     } else {
-      uri.spec = spec;
+      mutator.setSpec(spec);
     }
-    return uri;
+    return mutator.finalize();
   },
 
   newChannel2(uri, loadInfo) {
     const kCanada = "https://www.mozilla.org/contact/communities/canada/";
     let realURL = NetUtil.newURI((uri && uri.spec == "moz://eh") ? kCanada : this.urlToLoad);
     let channel = Services.io.newChannelFromURIWithLoadInfo(realURL, loadInfo);
     loadInfo.resultPrincipalURI = realURL;
     return channel;
--- a/toolkit/components/places/PageIconProtocolHandler.js
+++ b/toolkit/components/places/PageIconProtocolHandler.js
@@ -68,19 +68,20 @@ PageIconProtocolHandler.prototype = {
   get protocolFlags() {
     return Ci.nsIProtocolHandler.URI_NORELATIVE |
            Ci.nsIProtocolHandler.URI_NOAUTH |
            Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD |
            Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE;
   },
 
   newURI(spec, originCharset, baseURI) {
-    let uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI);
-    uri.spec = spec;
-    return uri;
+    return Cc["@mozilla.org/network/simple-uri-mutator;1"]
+             .createInstance(Ci.nsIURIMutator)
+             .setSpec(spec)
+             .finalize();
   },
 
   newChannel2(uri, loadInfo) {
     try {
       // Create a pipe that will give us an output stream that we can use once
       // we got all the favicon data.
       let pipe = Cc["@mozilla.org/pipe;1"]
                    .createInstance(Ci.nsIPipe);
--- a/widget/tests/unit/test_taskbar_jumplistitems.js
+++ b/widget/tests/unit/test_taskbar_jumplistitems.js
@@ -53,91 +53,100 @@ function test_separator()
 
   Assert.ok(item.type == Ci.nsIJumpListItem.JUMPLIST_ITEM_SEPARATOR);
 }
 
 function test_hashes()
 {
   var link = Cc["@mozilla.org/windows-jumplistlink;1"]
              .createInstance(Ci.nsIJumpListLink);
-  var uri1 = Cc["@mozilla.org/network/simple-uri;1"]
-            .createInstance(Ci.nsIURI);
-  var uri2 = Cc["@mozilla.org/network/simple-uri;1"]
-            .createInstance(Ci.nsIURI);
-
-  uri1.spec = "http://www.123.com/";
-  uri2.spec = "http://www.123.com/";
+  var uri1 = Cc["@mozilla.org/network/simple-uri-mutator;1"]
+               .createInstance(Ci.nsIURIMutator)
+               .setSpec("http://www.123.com/")
+               .finalize();
+  var uri2 = Cc["@mozilla.org/network/simple-uri-mutator;1"]
+               .createInstance(Ci.nsIURIMutator)
+               .setSpec("http://www.123.com/")
+               .finalize();
 
   link.uri = uri1;
 
   Assert.ok(link.compareHash(uri2))
-  uri2.spec = "http://www.456.com/";
+  uri2 = uri2.mutate().setSpec("http://www.456.com/").finalize();
   Assert.ok(!link.compareHash(uri2))
-  uri2.spec = "http://www.123.com/";
+  uri2 = uri2.mutate().setSpec("http://www.123.com/").finalize();
   Assert.ok(link.compareHash(uri2))
-  uri2.spec = "https://www.123.com/";
+  uri2 = uri2.mutate().setSpec("https://www.123.com/").finalize();
   Assert.ok(!link.compareHash(uri2))
-  uri2.spec = "http://www.123.com/test/";
+  uri2 = uri2.mutate().setSpec("http://www.123.com/test/").finalize();
   Assert.ok(!link.compareHash(uri2))
-  uri1.spec = "http://www.123.com/test/";
-  uri2.spec = "http://www.123.com/test/";
+  uri1 = uri1.mutate().setSpec("http://www.123.com/test/").finalize();
+  link.uri = uri1;
+  uri2 = uri2.mutate().setSpec("http://www.123.com/test/").finalize();
   Assert.ok(link.compareHash(uri2))
-  uri1.spec = "https://www.123.com/test/";
-  uri2.spec = "https://www.123.com/test/";
+  uri1 = uri1.mutate().setSpec("https://www.123.com/test/").finalize();
+  link.uri = uri1;
+  uri2 = uri2.mutate().setSpec("https://www.123.com/test/").finalize();
   Assert.ok(link.compareHash(uri2))
-  uri2.spec = "ftp://www.123.com/test/";
+  uri2 = uri2.mutate().setSpec("ftp://www.123.com/test/").finalize();
+  Assert.ok(!link.compareHash(uri2))
+  uri2 = uri2.mutate().setSpec("http://123.com/test/").finalize();
   Assert.ok(!link.compareHash(uri2))
-  uri2.spec = "http://123.com/test/";
-  Assert.ok(!link.compareHash(uri2))
-  uri1.spec = "https://www.123.com/test/";
-  uri2.spec = "https://www.123.com/Test/";
+  uri1 = uri1.mutate().setSpec("https://www.123.com/test/").finalize();
+  link.uri = uri1;
+  uri2 = uri2.mutate().setSpec("https://www.123.com/Test/").finalize();
   Assert.ok(!link.compareHash(uri2))
 
-  uri1.spec = "http://www.123.com/";
+  uri1 = uri1.mutate().setSpec("http://www.123.com/").finalize();
+  link.uri = uri1;
   Assert.equal(link.uriHash, "QGLmWuwuTozr3tOfXSf5mg==");
-  uri1.spec = "http://www.123.com/test/";
+  uri1 = uri1.mutate().setSpec("http://www.123.com/test/").finalize();
+  link.uri = uri1;
   Assert.equal(link.uriHash, "AG87Ls+GmaUYSUJFETRr3Q==");
-  uri1.spec = "https://www.123.com/";
+  uri1 = uri1.mutate().setSpec("https://www.123.com/").finalize();
+  link.uri = uri1;
   Assert.equal(link.uriHash, "iSx6UH1a9enVPzUA9JZ42g==");
 
   var uri3 = Cc["@mozilla.org/network/simple-uri;1"]
             .createInstance(Ci.nsIURI);
   link.uri = uri3;
   Assert.equal(link.uriHash, "hTrpDwNRMkvXPqYV5kh1Fw==");
 }
 
 function test_links()
 {
   // links:
   var link1 = Cc["@mozilla.org/windows-jumplistlink;1"]
              .createInstance(Ci.nsIJumpListLink);
   var link2 = Cc["@mozilla.org/windows-jumplistlink;1"]
               .createInstance(Ci.nsIJumpListLink);
 
-  var uri1 = Cc["@mozilla.org/network/simple-uri;1"]
-            .createInstance(Ci.nsIURI);
-  var uri2 = Cc["@mozilla.org/network/simple-uri;1"]
-            .createInstance(Ci.nsIURI);
-
-  uri1.spec = "http://www.test.com/";
-  uri2.spec = "http://www.test.com/";
+  var uri1 = Cc["@mozilla.org/network/simple-uri-mutator;1"]
+               .createInstance(Ci.nsIURIMutator)
+               .setSpec("http://www.test.com/")
+               .finalize();
+  var uri2 = Cc["@mozilla.org/network/simple-uri-mutator;1"]
+               .createInstance(Ci.nsIURIMutator)
+               .setSpec("http://www.test.com/")
+               .finalize();
 
   link1.uri = uri1;
   link1.uriTitle = "Test";
   link2.uri = uri2;
   link2.uriTitle = "Test";
 
   Assert.ok(link1.equals(link2));
 
   link2.uriTitle = "Testing";
 
   Assert.ok(!link1.equals(link2));
 
   link2.uriTitle = "Test";
-  uri2.spec = "http://www.testing.com/";
+  uri2 = uri2.mutate().setSpec("http://www.testing.com/").finalize();
+  link2.uri = uri2;
 
   Assert.ok(!link1.equals(link2));
 }
 
 function test_shortcuts()
 {
   // shortcuts:
   var sc = Cc["@mozilla.org/windows-jumplistshortcut;1"]
@@ -148,19 +157,20 @@ function test_shortcuts()
 
   handlerApp.name = "TestApp";
   handlerApp.detailedDescription = "TestApp detailed description.";
   handlerApp.appendParameter("-test");
 
   sc.iconIndex = 1;
   Assert.equal(sc.iconIndex, 1);
 
-  var faviconPageUri = Cc["@mozilla.org/network/simple-uri;1"]
-                    .createInstance(Ci.nsIURI);
-  faviconPageUri.spec = "http://www.123.com/";
+  var faviconPageUri = Cc["@mozilla.org/network/simple-uri-mutator;1"]
+                         .createInstance(Ci.nsIURIMutator)
+                         .setSpec("http://www.123.com/")
+                         .finalize();
   sc.faviconPageUri = faviconPageUri;
   Assert.equal(sc.faviconPageUri, faviconPageUri);
 
   var dirSvc = Cc["@mozilla.org/file/directory_service;1"].
                   getService(Ci.nsIProperties).
                   QueryInterface(Ci.nsIDirectoryService);
   var notepad = dirSvc.get("WinD", Ci.nsIFile);
   notepad.append("notepad.exe");