From owner-svn-ports-all@freebsd.org Tue Nov 14 19:04:08 2017 Return-Path: Delivered-To: svn-ports-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 7E6F4DDB253; Tue, 14 Nov 2017 19:04:08 +0000 (UTC) (envelope-from jbeich@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 179896B561; Tue, 14 Nov 2017 19:04:08 +0000 (UTC) (envelope-from jbeich@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id vAEJ477s000676; Tue, 14 Nov 2017 19:04:07 GMT (envelope-from jbeich@FreeBSD.org) Received: (from jbeich@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id vAEJ46mR000668; Tue, 14 Nov 2017 19:04:06 GMT (envelope-from jbeich@FreeBSD.org) Message-Id: <201711141904.vAEJ46mR000668@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jbeich set sender to jbeich@FreeBSD.org using -f From: Jan Beich Date: Tue, 14 Nov 2017 19:04:06 +0000 (UTC) To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r454192 - in head/www/firefox: . files X-SVN-Group: ports-head X-SVN-Commit-Author: jbeich X-SVN-Commit-Paths: in head/www/firefox: . files X-SVN-Commit-Revision: 454192 X-SVN-Commit-Repository: ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-ports-all@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the ports tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 14 Nov 2017 19:04:08 -0000 Author: jbeich Date: Tue Nov 14 19:04:06 2017 New Revision: 454192 URL: https://svnweb.freebsd.org/changeset/ports/454192 Log: www/firefox: backport more FF57+ fixes No time to track down upstream commits for https://bugzilla.mozilla.org/buglist.cgi?bug_id=1384615,1386490,1393840,1403716 PR: 222859 Security: f78eac48-c3d1-4666-8de5-63ceea25a578 MFH: 2017Q4 (r454000 followup, FF57 alternative until 2018Q1) Added: head/www/firefox/files/patch-a-bug1399540 (contents, props changed) head/www/firefox/files/patch-bug1325923 (contents, props changed) head/www/firefox/files/patch-bug1365894 (contents, props changed) head/www/firefox/files/patch-bug1366420 (contents, props changed) head/www/firefox/files/patch-bug1370497 (contents, props changed) head/www/firefox/files/patch-bug1377587 (contents, props changed) head/www/firefox/files/patch-bug1381761 (contents, props changed) head/www/firefox/files/patch-bug1383019 (contents, props changed) head/www/firefox/files/patch-bug1384121 (contents, props changed) head/www/firefox/files/patch-bug1387811 (contents, props changed) head/www/firefox/files/patch-bug1387845 (contents, props changed) head/www/firefox/files/patch-bug1394031 (contents, props changed) head/www/firefox/files/patch-bug1399922 (contents, props changed) head/www/firefox/files/patch-bug1401339 (contents, props changed) head/www/firefox/files/patch-bug1402363 (contents, props changed) head/www/firefox/files/patch-bug1402876 (contents, props changed) head/www/firefox/files/patch-bug1402896 (contents, props changed) head/www/firefox/files/patch-bug1402966 (contents, props changed) head/www/firefox/files/patch-bug1403646 (contents, props changed) head/www/firefox/files/patch-bug1406154 (contents, props changed) head/www/firefox/files/patch-bug1407032 (contents, props changed) head/www/firefox/files/patch-bug1408782 (contents, props changed) Modified: head/www/firefox/Makefile (contents, props changed) Modified: head/www/firefox/Makefile ============================================================================== --- head/www/firefox/Makefile Tue Nov 14 19:01:01 2017 (r454191) +++ head/www/firefox/Makefile Tue Nov 14 19:04:06 2017 (r454192) @@ -4,7 +4,7 @@ PORTNAME= firefox DISTVERSION= 56.0.2 DISTVERSIONSUFFIX=.source -PORTREVISION= 9 +PORTREVISION= 10 PORTEPOCH= 1 CATEGORIES= www ipv6 MASTER_SITES= MOZILLA/${PORTNAME}/releases/${DISTVERSION}/source \ Added: head/www/firefox/files/patch-a-bug1399540 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/firefox/files/patch-a-bug1399540 Tue Nov 14 19:04:06 2017 (r454192) @@ -0,0 +1,148 @@ +commit 99ad73e4743d +Author: Jonathan Kew +Date: Sat Sep 16 11:49:47 2017 +0100 + + Bug 1399540 - patch 1 - Failure to decode an individual label within the IDN should not block decoding of other valid punycode labels. r=valentin +--- + netwerk/dns/nsIDNService.cpp | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +diff --git netwerk/dns/nsIDNService.cpp netwerk/dns/nsIDNService.cpp +index 9cc8fdcf6fa1..3adcddf654e1 100644 +--- netwerk/dns/nsIDNService.cpp ++++ netwerk/dns/nsIDNService.cpp +@@ -300,6 +300,10 @@ nsresult nsIDNService::ACEtoUTF8(const nsACString & input, nsACString & _retval, + // RFC 3490 - 4.2 ToUnicode + // ToUnicode never fails. If any step fails, then the original input + // sequence is returned immediately in that step. ++ // ++ // Note that this refers to the decoding of a single label. ++ // ACEtoUTF8 may be called with a sequence of labels separated by dots; ++ // this test applies individually to each label. + + uint32_t len = 0, offset = 0; + nsAutoCString decodedBuf; +@@ -313,13 +317,15 @@ nsresult nsIDNService::ACEtoUTF8(const nsACString & input, nsACString & _retval, + while (start != end) { + len++; + if (*start++ == '.') { +- if (NS_FAILED(decodeACE(Substring(input, offset, len - 1), decodedBuf, +- flag))) { +- _retval.Assign(input); +- return NS_OK; ++ nsDependentCSubstring origLabel(input, offset, len - 1); ++ if (NS_FAILED(decodeACE(origLabel, decodedBuf, flag))) { ++ // If decoding failed, use the original input sequence ++ // for this label. ++ _retval.Append(origLabel); ++ } else { ++ _retval.Append(decodedBuf); + } + +- _retval.Append(decodedBuf); + _retval.Append('.'); + offset += len; + len = 0; +@@ -327,11 +333,12 @@ nsresult nsIDNService::ACEtoUTF8(const nsACString & input, nsACString & _retval, + } + // decode the last node + if (len) { +- if (NS_FAILED(decodeACE(Substring(input, offset, len), decodedBuf, +- flag))) +- _retval.Assign(input); +- else ++ nsDependentCSubstring origLabel(input, offset, len); ++ if (NS_FAILED(decodeACE(origLabel, decodedBuf, flag))) { ++ _retval.Append(origLabel); ++ } else { + _retval.Append(decodedBuf); ++ } + } + + return NS_OK; + +commit eddd7a4f4eae +Author: Jonathan Kew +Date: Sat Sep 16 11:49:56 2017 +0100 + + Bug 1399540 - patch 2 - Handle invalid punycode better in stringPrep to avoid mangling display of fake-punycode labels. r=valentin +--- + netwerk/dns/nsIDNService.cpp | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git netwerk/dns/nsIDNService.cpp netwerk/dns/nsIDNService.cpp +index 3adcddf654e1..4c45a2d52e45 100644 +--- netwerk/dns/nsIDNService.cpp ++++ netwerk/dns/nsIDNService.cpp +@@ -222,7 +222,15 @@ nsIDNService::IDNA2008StringPrep(const nsAString& input, + } + NS_ENSURE_SUCCESS(rv, rv); + +- // Output the result of nameToUnicode even if there were errors ++ // Output the result of nameToUnicode even if there were errors. ++ // But in the case of invalid punycode, the uidna_labelToUnicode result ++ // appears to get an appended U+FFFD REPLACEMENT CHARACTER, which will ++ // confuse our subsequent processing, so we drop that. ++ // (https://bugzilla.mozilla.org/show_bug.cgi?id=1399540#c9) ++ if ((info.errors & UIDNA_ERROR_PUNYCODE) && ++ outLen > 0 && outputBuffer[outLen - 1] == 0xfffd) { ++ --outLen; ++ } + ICUUtils::AssignUCharArrayToString(outputBuffer, outLen, output); + + if (flag == eStringPrepIgnoreErrors) { + +commit 2a3883ef55d2 +Author: Jonathan Kew +Date: Sat Sep 16 11:50:08 2017 +0100 + + Bug 1399540 - Add some IDN testcases with mixed punycode and non-punycode labels. r=valentin +--- + netwerk/test/unit/test_idn_urls.js | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +diff --git netwerk/test/unit/test_idn_urls.js netwerk/test/unit/test_idn_urls.js +index 358854093f65..0d8cf3216293 100644 +--- netwerk/test/unit/test_idn_urls.js ++++ netwerk/test/unit/test_idn_urls.js +@@ -286,10 +286,17 @@ const testcases = [ + // Thai (also tests that node with over 63 UTF-8 octets doesn't fail) + ["เครื่องทําน้ําทําน้ําแข็ง", + "xn--22cdjb2fanb9fyepcbbb9dwh4a3igze4fdcd", +- false, true, true] ++ false, true, true], ++ ++ // Effect of adding valid or invalid subdomains (bug 1399540) ++ ["䕮䕵䕶䕱.ascii", "xn--google.ascii", false, true, true], ++ ["ascii.䕮䕵䕶䕱", "ascii.xn--google", false, true, true], ++ ["中国123.䕮䕵䕶䕱", "xn--123-u68dy61b.xn--google", false, true, true], ++ ["䕮䕵䕶䕱.中国123", "xn--google.xn--123-u68dy61b", false, true, true], ++ ["xn--accountlogin.䕮䕵䕶䕱", "xn--accountlogin.xn--google", false, true, true], ++ ["䕮䕵䕶䕱.xn--accountlogin", "xn--google.xn--accountlogin", false, true, true], + ]; + +- + const profiles = ["ASCII", "high", "moderate"]; + + function run_test() { +@@ -311,13 +318,13 @@ function run_test() { + var expectedUnicode = test[2 + i]; + var isASCII = {}; + +- var result; +- try { +- result = idnService.convertToDisplayIDN(URL, isASCII); +- } catch(e) { +- result = ".com"; +- } +- if (punycodeURL.substr(0, 4) == "xn--") { ++ var result; ++ try { ++ result = idnService.convertToDisplayIDN(URL, isASCII); ++ } catch(e) { ++ result = ".com"; ++ } ++ if (punycodeURL.substr(0, 4) == "xn--" || punycodeURL.indexOf(".xn--") > 0) { + // test convertToDisplayIDN with a Unicode URL and with a + // Punycode URL if we have one + do_check_eq(escape(result), Added: head/www/firefox/files/patch-bug1325923 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/firefox/files/patch-bug1325923 Tue Nov 14 19:04:06 2017 (r454192) @@ -0,0 +1,121 @@ +commit d9ad239a35bf +Author: Blake Kaplan +Date: Wed Aug 16 16:39:32 2017 -0700 + + Bug 1325923 - Implement the "cookie averse document" concept. r=Ehsan + + See https://html.spec.whatwg.org/multipage/dom.html#resource-metadata-management:cookie-averse-document-object + + MozReview-Commit-ID: GndxqhU77cS +--- + dom/base/nsIDocument.h | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git dom/base/nsIDocument.h dom/base/nsIDocument.h +index e834f5785cad..921e03e107d1 100644 +--- dom/base/nsIDocument.h ++++ dom/base/nsIDocument.h +@@ -2073,6 +2073,34 @@ public: + return mMarkedCCGeneration; + } + ++ /** ++ * Returns whether this document is cookie averse. See ++ * https://html.spec.whatwg.org/multipage/dom.html#cookie-averse-document-object ++ */ ++ bool IsCookieAverse() const ++ { ++ // If we are a document that "has no browsing context." ++ if (!GetInnerWindow()) { ++ return true; ++ } ++ ++ // If we are a document "whose URL's scheme is not a network scheme." ++ // NB: Explicitly allow file: URIs to store cookies. ++ nsCOMPtr codebaseURI; ++ NodePrincipal()->GetURI(getter_AddRefs(codebaseURI)); ++ ++ if (!codebaseURI) { ++ return true; ++ } ++ ++ nsAutoCString scheme; ++ codebaseURI->GetScheme(scheme); ++ return !scheme.EqualsLiteral("http") && ++ !scheme.EqualsLiteral("https") && ++ !scheme.EqualsLiteral("ftp") && ++ !scheme.EqualsLiteral("file"); ++ } ++ + bool IsLoadedAsData() + { + return mLoadedAsData; + +commit 10775852824c +Author: Blake Kaplan +Date: Wed Aug 16 16:58:19 2017 -0700 + + Bug 1325923 - Use this new API. r=Ehsan + + MozReview-Commit-ID: 6tuaEqQA551 +--- + dom/base/nsContentSink.cpp | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git dom/base/nsContentSink.cpp dom/base/nsContentSink.cpp +index c52761c8521f..c3e9f43846d4 100644 +--- dom/base/nsContentSink.cpp ++++ dom/base/nsContentSink.cpp +@@ -843,6 +843,12 @@ nsContentSink::ProcessMETATag(nsIContent* aContent) + return NS_OK; + } + ++ // Don't allow setting cookies in in cookie averse ++ // documents. ++ if (nsGkAtoms::setcookie->Equals(header) && mDocument->IsCookieAverse()) { ++ return NS_OK; ++ } ++ + nsAutoString result; + aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::content, result); + if (!result.IsEmpty()) { + +commit f48bc2cbf262 +Author: Blake Kaplan +Date: Wed Aug 16 17:22:31 2017 -0700 + + Bug 1325923 - Use this API where we're supposed to. r=Ehsan + + MozReview-Commit-ID: HGU5YtUzv9U +--- + dom/html/nsHTMLDocument.cpp | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git dom/html/nsHTMLDocument.cpp dom/html/nsHTMLDocument.cpp +index fa3d614854d9..b146698b6494 100644 +--- dom/html/nsHTMLDocument.cpp ++++ dom/html/nsHTMLDocument.cpp +@@ -1347,6 +1347,11 @@ nsHTMLDocument::GetCookie(nsAString& aCookie, ErrorResult& rv) + return; + } + ++ // If the document is a cookie-averse Document... return the empty string. ++ if (IsCookieAverse()) { ++ return; ++ } ++ + // not having a cookie service isn't an error + nsCOMPtr service = do_GetService(NS_COOKIESERVICE_CONTRACTID); + if (service) { +@@ -1400,6 +1405,11 @@ nsHTMLDocument::SetCookie(const nsAString& aCookie, ErrorResult& rv) + return; + } + ++ // If the document is a cookie-averse Document... do nothing. ++ if (IsCookieAverse()) { ++ return; ++ } ++ + // not having a cookie service isn't an error + nsCOMPtr service = do_GetService(NS_COOKIESERVICE_CONTRACTID); + if (service && mDocumentURI) { Added: head/www/firefox/files/patch-bug1365894 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/firefox/files/patch-bug1365894 Tue Nov 14 19:04:06 2017 (r454192) @@ -0,0 +1,60 @@ +commit 97515a9302ed +Author: James Cheng +Date: Mon Oct 9 13:40:12 2017 -0400 + + Bug 1365894 - Make SystemGroupImpl be a normal ref-counted object. r=ehsan, a=ritu + + MozReview-Commit-ID: LUcoBhNx2M5 + + --HG-- + extra : source : 3959033a31666770047dd460979032464a48ba66 +--- + xpcom/threads/SystemGroup.cpp | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) + +diff --git xpcom/threads/SystemGroup.cpp xpcom/threads/SystemGroup.cpp +index a95ecc6cdd77..04bf3bd248ef 100644 +--- xpcom/threads/SystemGroup.cpp ++++ xpcom/threads/SystemGroup.cpp +@@ -16,7 +16,7 @@ class SystemGroupImpl final : public SchedulerGroup + { + public: + SystemGroupImpl(); +- ~SystemGroupImpl() {} ++ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SystemGroupImpl) + + static void InitStatic(); + static void ShutdownStatic(); +@@ -24,20 +24,12 @@ public: + + static bool Initialized() { return !!sSingleton; } + +- NS_METHOD_(MozExternalRefCountType) AddRef(void) +- { +- return 2; +- } +- NS_METHOD_(MozExternalRefCountType) Release(void) +- { +- return 1; +- } +- + private: +- static UniquePtr sSingleton; ++ ~SystemGroupImpl() = default; ++ static StaticRefPtr sSingleton; + }; + +-UniquePtr SystemGroupImpl::sSingleton; ++StaticRefPtr SystemGroupImpl::sSingleton; + + SystemGroupImpl::SystemGroupImpl() + { +@@ -49,7 +41,7 @@ SystemGroupImpl::InitStatic() + { + MOZ_ASSERT(!sSingleton); + MOZ_ASSERT(NS_IsMainThread()); +- sSingleton = MakeUnique(); ++ sSingleton = new SystemGroupImpl(); + } + + /* static */ void Added: head/www/firefox/files/patch-bug1366420 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/firefox/files/patch-bug1366420 Tue Nov 14 19:04:06 2017 (r454192) @@ -0,0 +1,128 @@ +commit dfe9efffb57b +Author: Marco Bonardo +Date: Wed Oct 4 11:13:19 2017 +0200 + + Bug 1366420. r=standard8, a=ritu + + MozReview-Commit-ID: FOIqr5RdRjz + + --HG-- + extra : source : 08312cdfb2304264e6871357fe2e6e7831272d21 +--- + toolkit/components/places/BookmarkHTMLUtils.jsm | 2 +- + .../unit/test_bookmarks_html_escape_entities.js | 81 ++++++++++++++++++++++ + toolkit/components/places/tests/unit/xpcshell.ini | 1 + + 3 files changed, 83 insertions(+), 1 deletion(-) + +diff --git toolkit/components/places/BookmarkHTMLUtils.jsm toolkit/components/places/BookmarkHTMLUtils.jsm +index 653e29fc5875..f4c1e7495d32 100644 +--- toolkit/components/places/BookmarkHTMLUtils.jsm ++++ toolkit/components/places/BookmarkHTMLUtils.jsm +@@ -1143,7 +1143,7 @@ BookmarkExporter.prototype = { + if (aItem.charset) + this._writeAttribute("LAST_CHARSET", escapeHtmlEntities(aItem.charset)); + if (aItem.tags) +- this._writeAttribute("TAGS", aItem.tags); ++ this._writeAttribute("TAGS", escapeHtmlEntities(aItem.tags)); + this._writeLine(">" + escapeHtmlEntities(aItem.title) + ""); + this._writeDescription(aItem, aIndent); + }, +diff --git toolkit/components/places/tests/unit/test_bookmarks_html_escape_entities.js toolkit/components/places/tests/unit/test_bookmarks_html_escape_entities.js +new file mode 100644 +index 000000000000..73c5e0e0744d +--- /dev/null ++++ toolkit/components/places/tests/unit/test_bookmarks_html_escape_entities.js +@@ -0,0 +1,81 @@ ++/* Any copyright is dedicated to the Public Domain. ++ * http://creativecommons.org/publicdomain/zero/1.0/ */ ++ ++"use strict"; ++ ++// Checks that html entities are escaped in bookmarks.html files. ++ ++const DESCRIPTION_ANNO = "bookmarkProperties/description"; ++ ++add_task(async function() { ++ // Removes bookmarks.html if the file already exists. ++ let HTMLFile = OS.Path.join(OS.Constants.Path.profileDir, "bookmarks.html"); ++ if ((await OS.File.exists(HTMLFile))) { ++ await OS.File.remove(HTMLFile); ++ } ++ ++ let unescaped = ''; ++ // Adds bookmarks and tags to the database. ++ const url = 'http://www.google.it/"/'; ++ let bm = await PlacesUtils.bookmarks.insert({ ++ parentGuid: PlacesUtils.bookmarks.unfiledGuid, ++ url, ++ title: unescaped ++ }); ++ await PlacesUtils.keywords.insert({ url, keyword: unescaped, postData: unescaped }) ++ let uri = Services.io.newURI(url); ++ PlacesUtils.tagging.tagURI(uri, [unescaped]); ++ await PlacesUtils.setCharsetForURI(uri, unescaped); ++ PlacesUtils.annotations.setItemAnnotation( ++ await PlacesUtils.promiseItemId(bm.guid), ++ DESCRIPTION_ANNO, unescaped, 0, PlacesUtils.annotations.EXPIRE_NEVER); ++ ++ // Exports the bookmarks as a HTML file. ++ await BookmarkHTMLUtils.exportToFile(HTMLFile); ++ await PlacesUtils.bookmarks.remove(bm); ++ ++ // Check there are no unescaped entities in the html file. ++ let xml = await new Promise((resolve, reject) => { ++ let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] ++ .createInstance(Ci.nsIXMLHttpRequest); ++ xhr.onload = () => { ++ try { ++ resolve(xhr.responseXML); ++ } catch (e) { ++ reject(e); ++ } ++ }; ++ xhr.onabort = xhr.onerror = xhr.ontimeout = () => { ++ reject(new Error("xmlhttprequest failed")); ++ }; ++ xhr.open("GET", OS.Path.toFileURI(HTMLFile)); ++ xhr.responseType = "document"; ++ xhr.overrideMimeType("text/html"); ++ xhr.send(); ++ }); ++ ++ let checksCount = 6; ++ for (let current = xml; current; ++ current = current.firstChild || current.nextSibling || current.parentNode.nextSibling) { ++ switch (current.nodeType) { ++ case Ci.nsIDOMNode.ELEMENT_NODE: ++ for (let {name, value} of current.attributes) { ++ do_print("Found attribute: " + name); ++ // Check tags, keyword, postData and charSet. ++ if (["tags", "last_charset", "shortcuturl", "post_data"].includes(name)) { ++ Assert.equal(value, unescaped, `Attribute ${name} should be complete`); ++ checksCount--; ++ } ++ } ++ break; ++ case Ci.nsIDOMNode.TEXT_NODE: ++ // Check Title and description. ++ if (!current.data.startsWith("\n") && !current.data.includes("Bookmarks")) { ++ Assert.equal(current.data.trim(), unescaped, "Text node should be complete"); ++ checksCount--; ++ } ++ break; ++ } ++ } ++ Assert.equal(checksCount, 0, "All the checks ran") ++}); +diff --git toolkit/components/places/tests/unit/xpcshell.ini toolkit/components/places/tests/unit/xpcshell.ini +index 6952e4158753..776e7e548f92 100644 +--- toolkit/components/places/tests/unit/xpcshell.ini ++++ toolkit/components/places/tests/unit/xpcshell.ini +@@ -67,6 +67,7 @@ skip-if = (os == "win" && os_version == "5.1") # Bug 1158887 + [test_bookmarks_json.js] + [test_bookmarks_html.js] + [test_bookmarks_html_corrupt.js] ++[test_bookmarks_html_escape_entities.js] + [test_bookmarks_html_import_tags.js] + [test_bookmarks_html_singleframe.js] + [test_bookmarks_restore_notification.js] Added: head/www/firefox/files/patch-bug1370497 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/firefox/files/patch-bug1370497 Tue Nov 14 19:04:06 2017 (r454192) @@ -0,0 +1,100 @@ +commit c79086d4c25c +Author: Jonathan Kew +Date: Wed Sep 27 11:16:35 2017 +0100 + + Bug 1370497 - Check ScriptExtensions property of combining marks when available. r=valentin, a=ritu + + --HG-- + extra : source : 6bd2d96c0c3d952b205e1bb2f6915cbc820a61a1 + extra : amend_source : b0c6b6fbea0bf77c8d1527e131d3773b4d959ea0 +--- + netwerk/dns/nsIDNService.cpp | 45 ++++++++++++++++++++++++++++++++------ + netwerk/test/unit/test_idn_urls.js | 5 +++++ + 2 files changed, 43 insertions(+), 7 deletions(-) + +diff --git netwerk/dns/nsIDNService.cpp netwerk/dns/nsIDNService.cpp +index 4c45a2d52e45..e07910a7e70d 100644 +--- netwerk/dns/nsIDNService.cpp ++++ netwerk/dns/nsIDNService.cpp +@@ -26,6 +26,7 @@ + const bool kIDNA2008_TransitionalProcessing = false; + + #include "ICUUtils.h" ++#include "unicode/uscript.h" + #endif + + using namespace mozilla::unicode; +@@ -900,8 +901,8 @@ bool nsIDNService::isLabelSafe(const nsAString &label) + } + + // Check for mixed numbering systems +- if (GetGeneralCategory(ch) == +- HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) { ++ auto genCat = GetGeneralCategory(ch); ++ if (genCat == HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) { + uint32_t zeroCharacter = ch - GetNumericValue(ch); + if (savedNumberingSystem == 0) { + // If we encounter a decimal number, save the zero character from that +@@ -912,11 +913,41 @@ bool nsIDNService::isLabelSafe(const nsAString &label) + } + } + +- // Check for consecutive non-spacing marks +- if (previousChar != 0 && +- previousChar == ch && +- GetGeneralCategory(ch) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { +- return false; ++ if (genCat == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) { ++ // Check for consecutive non-spacing marks. ++ if (previousChar != 0 && previousChar == ch) { ++ return false; ++ } ++ // Check for marks whose expected script doesn't match the base script. ++ if (lastScript != Script::INVALID) { ++ const size_t kMaxScripts = 32; // more than ample for current values ++ // of ScriptExtensions property ++ UScriptCode scripts[kMaxScripts]; ++ UErrorCode errorCode = U_ZERO_ERROR; ++ int nScripts = uscript_getScriptExtensions(ch, scripts, kMaxScripts, ++ &errorCode); ++ MOZ_ASSERT(U_SUCCESS(errorCode), "uscript_getScriptExtensions failed"); ++ if (U_FAILURE(errorCode)) { ++ return false; ++ } ++ // nScripts will always be >= 1, because even for undefined characters ++ // uscript_getScriptExtensions will return Script::INVALID. ++ // If the mark just has script=COMMON or INHERITED, we can't check any ++ // more carefully, but if it has specific scriptExtension codes, then ++ // assume those are the only valid scripts to use it with. ++ if (nScripts > 1 || ++ (Script(scripts[0]) != Script::COMMON && ++ Script(scripts[0]) != Script::INHERITED)) { ++ while (--nScripts >= 0) { ++ if (Script(scripts[nScripts]) == lastScript) { ++ break; ++ } ++ } ++ if (nScripts == -1) { ++ return false; ++ } ++ } ++ } + } + + // Simplified/Traditional Chinese check temporarily disabled -- bug 857481 +diff --git netwerk/test/unit/test_idn_urls.js netwerk/test/unit/test_idn_urls.js +index 0d8cf3216293..f39a9650a13b 100644 +--- netwerk/test/unit/test_idn_urls.js ++++ netwerk/test/unit/test_idn_urls.js +@@ -295,6 +295,11 @@ const testcases = [ + ["䕮䕵䕶䕱.中国123", "xn--google.xn--123-u68dy61b", false, true, true], + ["xn--accountlogin.䕮䕵䕶䕱", "xn--accountlogin.xn--google", false, true, true], + ["䕮䕵䕶䕱.xn--accountlogin", "xn--google.xn--accountlogin", false, true, true], ++ ++ // Arabic diacritic not allowed in Latin text (bug 1370497) ++ ["goo\u0650gle", "xn--google-yri", false, false, false], ++ // ...but Arabic diacritics are allowed on Arabic text ++ ["العَرَبِي", "xn--mgbc0a5a6cxbzabt", false, true, true], + ]; + + const profiles = ["ASCII", "high", "moderate"]; Added: head/www/firefox/files/patch-bug1377587 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/firefox/files/patch-bug1377587 Tue Nov 14 19:04:06 2017 (r454192) @@ -0,0 +1,929 @@ +commit 2b68b38709b1 +Author: Andrew McCreight +Date: Tue Aug 22 14:24:11 2017 -0700 + + Bug 1377587, part 1 - Always act like __exposedProps__ is missing. r=krizsa + + This patch gently removes support for __exposedProps__ by changing + ExposedPropertiesOnly::check() to always return false, while still + failing silently in deny for some kinds of access. + + The tests that I changed all involve testing the behavior with + __exposedProps__. I adjusted them to expect it to fail, or to adjust + the error message they get when they fail. That seemed better than + deleting them entirely. + + Note that test_bug1065185.html had a bug, so that it never executed + the first case. I fixed that, and then fixed up the test to work when + __exposedProps__ is not supported. + + This also removes various bits of the test framework that use + __exposedProps__, but don't actually need to. + + MozReview-Commit-ID: 8fvkAmITmXY + + --HG-- + extra : rebase_source : ef7e2c55adc12511f17f3865ebb46c343875f0b3 +--- + addon-sdk/source/lib/sdk/console/plain-text.js | 10 -- + addon-sdk/source/lib/sdk/test/loader.js | 5 - + .../addons/e10s-content/lib/test-content-script.js | 6 +- + addon-sdk/source/test/test-content-script.js | 6 +- + devtools/server/tests/unit/test_objectgrips-17.js | 4 - + dom/base/nsDeprecatedOperationList.h | 1 - + dom/base/test/chrome/cpows_child.js | 12 +- + dom/locales/en-US/chrome/dom/dom.properties | 2 - + js/xpconnect/src/XPCJSRuntime.cpp | 1 - + js/xpconnect/src/xpcprivate.h | 1 - + js/xpconnect/tests/chrome/test_bug1065185.html | 6 +- + js/xpconnect/tests/chrome/test_cows.xul | 80 +++------ + js/xpconnect/tests/chrome/test_exposeInDerived.xul | 13 +- + js/xpconnect/tests/unit/test_bug1082450.js | 20 +-- + js/xpconnect/tests/unit/test_bug780370.js | 7 +- + js/xpconnect/tests/unit/test_bug813901.js | 2 +- + js/xpconnect/tests/unit/test_bug853709.js | 4 +- + js/xpconnect/tests/unit/test_bug854558.js | 2 +- + js/xpconnect/tests/unit/test_bug930091.js | 2 +- + js/xpconnect/wrappers/AccessCheck.cpp | 179 --------------------- + js/xpconnect/wrappers/AccessCheck.h | 11 +- + js/xpconnect/wrappers/ChromeObjectWrapper.h | 6 +- + js/xpconnect/wrappers/WrapperFactory.cpp | 4 +- + js/xpconnect/wrappers/XrayWrapper.cpp | 2 +- + testing/mochitest/tests/SimpleTest/ChromePowers.js | 9 -- + .../specialpowers/content/MockPermissionPrompt.jsm | 12 -- + .../components/addoncompat/RemoteAddonsParent.jsm | 2 +- + 27 files changed, 74 insertions(+), 335 deletions(-) + +diff --git addon-sdk/source/lib/sdk/console/plain-text.js addon-sdk/source/lib/sdk/console/plain-text.js +index 0e44cf106d52..07b8eb629e12 100644 +--- addon-sdk/source/lib/sdk/console/plain-text.js ++++ addon-sdk/source/lib/sdk/console/plain-text.js +@@ -62,16 +62,6 @@ function PlainTextConsole(print, innerID) { + } + }); + +- // We defined the `__exposedProps__` in our console chrome object. +- // +- // Meanwhile we're investigating with the platform team if `__exposedProps__` +- // are needed, or are just a left-over. +- +- console.__exposedProps__ = Object.keys(ConsoleAPI.prototype).reduce(function(exposed, prop) { +- exposed[prop] = "r"; +- return exposed; +- }, {}); +- + Object.freeze(console); + return console; + }; +diff --git addon-sdk/source/lib/sdk/test/loader.js addon-sdk/source/lib/sdk/test/loader.js +index 33ba2ca5a029..b555de63f02a 100644 +--- addon-sdk/source/lib/sdk/test/loader.js ++++ addon-sdk/source/lib/sdk/test/loader.js +@@ -53,11 +53,6 @@ function HookedPlainTextConsole(hook, print, innerID) { + this.exception = hook.bind(null, "exception", innerID); + this.time = hook.bind(null, "time", innerID); + this.timeEnd = hook.bind(null, "timeEnd", innerID); +- +- this.__exposedProps__ = { +- log: "rw", info: "rw", warn: "rw", error: "rw", debug: "rw", +- exception: "rw", time: "rw", timeEnd: "rw" +- }; + } + + // Creates a custom loader instance whose console module is hooked in order +diff --git addon-sdk/source/test/addons/e10s-content/lib/test-content-script.js addon-sdk/source/test/addons/e10s-content/lib/test-content-script.js +index 477895e40481..3dccfec618d3 100644 +--- addon-sdk/source/test/addons/e10s-content/lib/test-content-script.js ++++ addon-sdk/source/test/addons/e10s-content/lib/test-content-script.js +@@ -444,7 +444,7 @@ exports["test Highlight toString Behavior"] = createProxyTest("", function (help + let strToString = helper.rawWindow.Object.prototype.toString.call(""); + assert.ok(/\[object String.*\]/.test(strToString), "strings are strings"); + +- let o = {__exposedProps__:{}}; ++ let o = {}; + let objToString = helper.rawWindow.Object.prototype.toString.call(o); + assert.ok(/\[object Object.*\]/.test(objToString), "objects are objects"); + +@@ -622,10 +622,6 @@ exports["test Functions"] = createProxyTest("", function (helper) { + helper.rawWindow.isEqual = function isEqual(a, b) { + return a == b; + }; +- // bug 784116: workaround in order to allow proxy code to cache proxies on +- // these functions: +- helper.rawWindow.callFunction.__exposedProps__ = {__proxy: 'rw'}; +- helper.rawWindow.isEqual.__exposedProps__ = {__proxy: 'rw'}; + + helper.createWorker( + 'new ' + function ContentScriptScope() { +diff --git addon-sdk/source/test/test-content-script.js addon-sdk/source/test/test-content-script.js +index 709fb5a3aa91..a02e66f65eea 100644 +--- addon-sdk/source/test/test-content-script.js ++++ addon-sdk/source/test/test-content-script.js +@@ -444,7 +444,7 @@ exports["test Highlight toString Behavior"] = createProxyTest("", function (help + let strToString = helper.rawWindow.Object.prototype.toString.call(""); + assert.ok(/\[object String.*\]/.test(strToString), "strings are strings"); + +- let o = {__exposedProps__:{}}; ++ let o = {}; + let objToString = helper.rawWindow.Object.prototype.toString.call(o); + assert.ok(/\[object Object.*\]/.test(objToString), "objects are objects"); + +@@ -622,10 +622,6 @@ exports["test Functions"] = createProxyTest("", function (helper) { + helper.rawWindow.isEqual = function isEqual(a, b) { + return a == b; + }; +- // bug 784116: workaround in order to allow proxy code to cache proxies on +- // these functions: +- helper.rawWindow.callFunction.__exposedProps__ = {__proxy: 'rw'}; +- helper.rawWindow.isEqual.__exposedProps__ = {__proxy: 'rw'}; + + helper.createWorker( + 'new ' + function ContentScriptScope() { +diff --git dom/base/nsDeprecatedOperationList.h dom/base/nsDeprecatedOperationList.h +index 2523187c63a7..adcf4d9d8202 100644 +--- dom/base/nsDeprecatedOperationList.h ++++ dom/base/nsDeprecatedOperationList.h +@@ -21,7 +21,6 @@ DEPRECATED_OPERATION(NodeValue) + DEPRECATED_OPERATION(TextContent) + DEPRECATED_OPERATION(EnablePrivilege) + DEPRECATED_OPERATION(DOMExceptionCode) +-DEPRECATED_OPERATION(NoExposedProps) + DEPRECATED_OPERATION(MutationEvent) + DEPRECATED_OPERATION(Components) + DEPRECATED_OPERATION(PrefixedVisibilityAPI) +diff --git dom/base/test/chrome/cpows_child.js dom/base/test/chrome/cpows_child.js +index 6d240a7eaa51..fc7e3f2c9d0f 100644 +--- dom/base/test/chrome/cpows_child.js ++++ dom/base/test/chrome/cpows_child.js +@@ -105,7 +105,13 @@ function parent_test(finish) + + addMessageListener("cpows:from_parent", (msg) => { + let obj = msg.objects.obj; +- ok(obj.a == 1, "correct value from parent"); ++ if (is_remote) { ++ ok(obj.a == undefined, "__exposedProps__ should not work"); ++ } else { ++ // The same process test is not run as content, so the field can ++ // be accessed even though __exposedProps__ has been removed. ++ ok(obj.a == 1, "correct value from parent"); ++ } + + // Test that a CPOW reference to a function in the chrome process + // is callable from unprivileged content. Greasemonkey uses this +@@ -260,11 +266,11 @@ function lifetime_test(finish) + var obj = {"will_die": {"f": 1}}; + let [result] = sendRpcMessage("cpows:lifetime_test_1", {}, {obj: obj}); + ok(result == 10, "got sync result"); +- ok(obj.wont_die.f == 2, "got reverse CPOW"); ++ ok(obj.wont_die.f == undefined, "got reverse CPOW"); + obj.will_die = null; + Components.utils.schedulePreciseGC(function() { + addMessageListener("cpows:lifetime_test_3", (msg) => { +- ok(obj.wont_die.f == 2, "reverse CPOW still works"); ++ ok(obj.wont_die.f == undefined, "reverse CPOW still works"); + finish(); + }); + sendRpcMessage("cpows:lifetime_test_2"); +diff --git dom/locales/en-US/chrome/dom/dom.properties dom/locales/en-US/chrome/dom/dom.properties +index 5c94a580287a..ac9dbed58e08 100644 +--- dom/locales/en-US/chrome/dom/dom.properties ++++ dom/locales/en-US/chrome/dom/dom.properties +@@ -154,8 +154,6 @@ MediaEMENoCapabilitiesDeprecatedWarning=Calling navigator.requestMediaKeySystemA + MediaEMENoCodecsDeprecatedWarning=Calling navigator.requestMediaKeySystemAccess() (at %S) passing a candidate MediaKeySystemConfiguration containing audioCapabilities or videoCapabilities without a contentType with a “codecs” string is deprecated and will soon become unsupported. + # LOCALIZATION NOTE: Do not translate "DOMException", "code" and "name" + DOMExceptionCodeWarning=Use of DOMException’s code attribute is deprecated. Use name instead. +-# LOCALIZATION NOTE: Do not translate "__exposedProps__" +-NoExposedPropsWarning=Exposing chrome JS objects to content without __exposedProps__ is insecure and deprecated. See https://developer.mozilla.org/en/XPConnect_wrappers for more information. + # LOCALIZATION NOTE: Do not translate "Mutation Event" and "MutationObserver" + MutationEventWarning=Use of Mutation Events is deprecated. Use MutationObserver instead. + # LOCALIZATION NOTE: Do not translate "Components" +diff --git js/xpconnect/src/XPCJSRuntime.cpp js/xpconnect/src/XPCJSRuntime.cpp +index 455b9f8e963f..ff9aea0a41eb 100644 +--- js/xpconnect/src/XPCJSRuntime.cpp ++++ js/xpconnect/src/XPCJSRuntime.cpp +@@ -93,7 +93,6 @@ const char* const XPCJSRuntime::mStrings[] = { + "item", // IDX_ITEM + "__proto__", // IDX_PROTO + "__iterator__", // IDX_ITERATOR +- "__exposedProps__", // IDX_EXPOSEDPROPS + "eval", // IDX_EVAL + "controllers", // IDX_CONTROLLERS + "Controllers", // IDX_CONTROLLERS_CLASS +diff --git js/xpconnect/src/xpcprivate.h js/xpconnect/src/xpcprivate.h +index fb7e43c22cd0..5d877f09d301 100644 +--- js/xpconnect/src/xpcprivate.h ++++ js/xpconnect/src/xpcprivate.h +@@ -460,7 +460,6 @@ public: + IDX_ITEM , + IDX_PROTO , + IDX_ITERATOR , +- IDX_EXPOSEDPROPS , + IDX_EVAL , + IDX_CONTROLLERS , + IDX_CONTROLLERS_CLASS , +diff --git js/xpconnect/tests/chrome/test_bug1065185.html js/xpconnect/tests/chrome/test_bug1065185.html +index cdd65326f9c8..7ea81fc8aa6f 100644 +--- js/xpconnect/tests/chrome/test_bug1065185.html ++++ js/xpconnect/tests/chrome/test_bug1065185.html +@@ -25,11 +25,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1065185 + + var gLoadCount = 0; + function loaded() { +- switch(++gLoadCount) { ++ switch(gLoadCount++) { + case 0: +- doMonitor([]); ++ doMonitor([/access to property "a"/i]); + window[0].wrappedJSObject.probe = { a: 2, __exposedProps__: { 'a': 'r' } }; +- is(window[0].eval('probe.a'), 2, "Accessed exposed prop"); ++ is(window[0].eval('probe.a'), undefined, "Accessed exposed prop"); + endMonitor(); + break; + case 1: +diff --git js/xpconnect/tests/chrome/test_cows.xul js/xpconnect/tests/chrome/test_cows.xul +index 75c5250dd150..adfdd686540b 100644 +--- js/xpconnect/tests/chrome/test_cows.xul ++++ js/xpconnect/tests/chrome/test_cows.xul +@@ -49,13 +49,6 @@ sandbox.getCOW = getCOW; + const TEST_API = ['is', 'isnot', 'ok', 'todo_is', 'todo_isnot', 'todo']; + TEST_API.forEach(function(name) { sandbox[name] = window[name]; }); + +-sandbox.alienObject = { +- __exposedProps__: {funProp: 'r'}, +- funProp: function foo(x) { +- return x + 1; +- } +-}; +- + sandbox.chromeGet = function (obj, prop) { return obj[prop]; }; + + function COWTests() { +@@ -74,17 +67,6 @@ function COWTests() { + // functions like assertIsWritable(myObj, 'someproperty') might + // be useful. + +- function isProp(obj, propName, value, desc) { +- try { +- is(obj[propName], value, "getting " + propName + " on " + desc); +- ok(propName in obj, +- propName + " on " + desc + " should exist"); +- ok(Object.hasOwnProperty.call(obj, propName), +- propName + " on " + desc + " should exist"); +- } catch (e) { +- ok(false, "getting " + propName + " on " + desc + " threw " + e); +- } +- } + function isPropHidden(obj, propName, desc) { + try { + is(obj[propName], undefined, +@@ -103,7 +85,7 @@ function COWTests() { + var empty = {}; + var nonempty = {foo: 42, bar: 33}; + is(getCOW(empty).foo, undefined, +- "shouldn't throw when accessing exposed properties that doesn't exist"); ++ "shouldn't throw when accessing exposed properties that don't exist"); + + PROPS_TO_TEST.forEach(function(name) { + isPropHidden(getCOW(nonempty), name, "object without exposedProps"); +@@ -135,18 +117,12 @@ function COWTests() { + var strict = { __exposedProps__: { foo: "r" }, foo: "foo property" }; + var strictCOWr = getCOW(strict); + PROPS_TO_TEST.forEach(function(name) { +- if (name == "foo") { +- isProp(strictCOWr, name, "foo property", +- "object with exposed 'foo'"); +- } +- else { +- isPropHidden(strictCOW, name, "object with exposed 'foo'"); +- } ++ isPropHidden(strictCOW, name, "object with exposed 'foo'"); + }); +- is(getNames(strictCOWr).length, 1, +- "object with exposedProps only enumerate exposed props"); +- is(getNames(strictCOWr)[0], "foo", +- "object with exposedProps only enumerate exposed props"); ++ is(getNames(strictCOWr).length, 0, ++ "exposed props does not enumerate anything"); ++ is(getNames(strictCOWr)[0], undefined, ++ "exposed props does not enumerate anything"); + + // Test writable property + var writable = getCOW({ __exposedProps__: {foo: 'w'}}); +@@ -154,25 +130,18 @@ function COWTests() { + ok(!("foo" in writable), + "non-existing write-only property shouldn't exist"); + writable.foo = 5; +- is(chromeGet(writable, "foo"), 5, "writing to a write-only exposed prop works"); +- todo("foo" in writable, +- "existing write-only property should exist"); +- } catch (e) { +- ok(false, "writing to a write-only exposed prop shouldn't throw " + e); +- } +- try { +- writable.foo; +- todo(false, "reading from a write-only exposed prop should throw"); ++ ok(false, "writing to a write-only exposed prop should throw"); + } catch (e) { +- todo(/Permission denied/.test(e), +- "reading from a write-only exposed prop should throw"); ++ ok(/Permission denied/.test(e), ++ "writing to a write-only exposed prop should throw the right error"); + } ++ is(writable.foo, undefined, ++ "reading from a write-only exposed prop should return undefined"); + try { + delete writable.foo; +- is(chromeGet(writable, "foo"), undefined, +- "deleting a write-only exposed prop works"); ++ ok(false, "deleting a write-only exposed prop should throw"); + } catch (e) { +- ok(false, "deleting a write-only exposed prop shouldn't throw " + e); ++ ok(true, "deleting a write-only exposed prop should throw " + e); + } + + // Test readable property +@@ -180,8 +149,8 @@ function COWTests() { + foo: 5, + bar: 6 }; + try { +- isProp(getCOW(readable), "foo", 5, +- "reading from a readable exposed prop works"); ++ isPropHidden(getCOW(readable), "foo", undefined, ++ "reading from a readable exposed prop shouldn't work"); + } catch (e) { + ok(false, "reading from a readable exposed prop shouldn't throw " + e); + } +@@ -202,8 +171,7 @@ function COWTests() { + + try { + var props = getNames(getCOW(readable)); +- is(props.length, 1, "COW w/ one exposed prop should enumerate once"); +- is(props[0], 'foo', "COW w/ one exposed prop should enumerate it"); ++ is(props.length, 0, "COW w/ one exposed prop should not enumerate"); + } catch (e) { + ok(false, "COW w/ a readable prop should not raise exc " + + "on enumeration: " + e); +@@ -215,21 +183,17 @@ function COWTests() { + ok(!("foo" in readwrite), + "non-existing readwrite property shouldn't exist"); + readwrite.foo = 5; +- is(readwrite.foo, 5, "writing to a readwrite exposed prop looks like it worked"); +- is(chromeGet(readwrite, "foo"), 5, "writing to a readwrite exposed prop works"); +- ok("foo" in readwrite, +- "existing readwrite property should exist"); ++ ok(false, "writing to a readwrite exposed prop should throw"); + } catch (e) { +- ok(false, "writing to a readwrite exposed prop shouldn't throw " + e); ++ ok(/Permission denied/.test(e), ++ "writing to a readwrite exposed prop should throw the right error"); + } + try { + delete readwrite.foo; +- is(readwrite.foo, undefined, "deleting readwrite prop looks like it worked"); +- ok(!("foo" in readwrite), "deleting readwrite prop looks like it really worked"); +- is(chromeGet(readwrite, "foo"), undefined, +- "deleting a readwrite exposed prop works"); ++ ok(false, "deleting a readwrite prop should throw"); + } catch (e) { +- ok(false, "deleting a readwrite exposed prop shouldn't throw " + e); ++ ok(/Permission denied/.test(e), ++ "deleting a readwrite exposed prop should throw the right error"); + } + + // Readables and functions +diff --git js/xpconnect/tests/chrome/test_exposeInDerived.xul js/xpconnect/tests/chrome/test_exposeInDerived.xul +index 2ed3bb91e7fd..7e6c24e56db1 100644 +--- js/xpconnect/tests/chrome/test_exposeInDerived.xul ++++ js/xpconnect/tests/chrome/test_exposeInDerived.xul +@@ -17,7 +17,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=804630 + +