summaryrefslogtreecommitdiffstats
path: root/dom
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@gmail.com>2018-09-27 09:05:25 +0200
committerwolfbeast <mcwerewolf@gmail.com>2018-09-27 09:05:25 +0200
commitfbaab39c94a047f2a0b0bfbe6cf24a790cd7e8b5 (patch)
tree7b0e57d393cb08a895973cab2d2072cb2b93a77f /dom
parent580084e9e1d0355c96a54a9641df6c1fee894948 (diff)
parente3508f55bed8a463d298021633dbc7d079c9d764 (diff)
downloadUXP-fbaab39c94a047f2a0b0bfbe6cf24a790cd7e8b5.tar
UXP-fbaab39c94a047f2a0b0bfbe6cf24a790cd7e8b5.tar.gz
UXP-fbaab39c94a047f2a0b0bfbe6cf24a790cd7e8b5.tar.lz
UXP-fbaab39c94a047f2a0b0bfbe6cf24a790cd7e8b5.tar.xz
UXP-fbaab39c94a047f2a0b0bfbe6cf24a790cd7e8b5.zip
Merge branch 'master' into Basilisk-release
Diffstat (limited to 'dom')
-rw-r--r--dom/base/nsContentUtils.cpp71
-rw-r--r--dom/base/nsContentUtils.h15
-rw-r--r--dom/base/nsIDocument.h18
-rw-r--r--dom/base/nsINode.cpp49
-rw-r--r--dom/fetch/Fetch.cpp2
-rw-r--r--dom/fetch/FetchConsumer.cpp10
-rw-r--r--dom/media/GraphDriver.cpp10
-rw-r--r--dom/media/GraphDriver.h6
-rw-r--r--dom/media/MediaStreamGraph.cpp3
-rw-r--r--dom/media/webrtc/RTCCertificate.cpp2
-rw-r--r--dom/svg/SVGUseElement.cpp9
-rw-r--r--dom/svg/test/reftest_viewport_noninteger.html175
-rw-r--r--dom/workers/ServiceWorkerClient.cpp2
-rw-r--r--dom/workers/ServiceWorkerClients.cpp8
-rw-r--r--dom/workers/ServiceWorkerEvents.cpp20
-rw-r--r--dom/workers/ServiceWorkerPrivate.cpp15
-rw-r--r--dom/workers/ServiceWorkerRegistration.cpp8
-rw-r--r--dom/workers/ServiceWorkerWindowClient.cpp4
-rw-r--r--dom/workers/WorkerPrivate.cpp10
-rw-r--r--dom/workers/WorkerRunnable.cpp17
-rw-r--r--dom/workers/WorkerScope.cpp2
21 files changed, 377 insertions, 79 deletions
diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
index 34c7d23b8..3696195dd 100644
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -7597,6 +7597,24 @@ nsContentUtils::IsFileImage(nsIFile* aFile, nsACString& aType)
}
nsresult
+nsContentUtils::CalculateBufferSizeForImage(const uint32_t& aStride,
+ const IntSize& aImageSize,
+ const SurfaceFormat& aFormat,
+ size_t* aMaxBufferSize,
+ size_t* aUsedBufferSize)
+{
+ CheckedInt32 requiredBytes =
+ CheckedInt32(aStride) * CheckedInt32(aImageSize.height);
+ if (!requiredBytes.isValid()) {
+ return NS_ERROR_FAILURE;
+ }
+ *aMaxBufferSize = requiredBytes.value();
+ *aUsedBufferSize = *aMaxBufferSize - aStride +
+ (aImageSize.width * BytesPerPixel(aFormat));
+ return NS_OK;
+}
+
+nsresult
nsContentUtils::DataTransferItemToImage(const IPCDataTransferItem& aItem,
imgIContainer** aContainer)
{
@@ -7611,6 +7629,22 @@ nsContentUtils::DataTransferItemToImage(const IPCDataTransferItem& aItem,
Shmem data = aItem.data().get_Shmem();
+ // Validate shared memory buffer size
+ size_t imageBufLen = 0;
+ size_t maxBufLen = 0;
+ nsresult rv = CalculateBufferSizeForImage(imageDetails.stride(),
+ size,
+ static_cast<SurfaceFormat>(
+ imageDetails.format()),
+ &maxBufLen,
+ &imageBufLen);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ if (imageBufLen > data.Size<uint8_t>()) {
+ return NS_ERROR_FAILURE;
+ }
+
RefPtr<DataSourceSurface> image =
CreateDataSourceSurfaceFromData(size,
static_cast<SurfaceFormat>(imageDetails.format()),
@@ -7950,20 +7984,19 @@ GetSurfaceDataImpl(mozilla::gfx::DataSourceSurface* aSurface,
return GetSurfaceDataContext::NullValue();
}
- mozilla::gfx::IntSize size = aSurface->GetSize();
- mozilla::CheckedInt32 requiredBytes =
- mozilla::CheckedInt32(map.mStride) * mozilla::CheckedInt32(size.height);
- if (!requiredBytes.isValid()) {
+ size_t bufLen = 0;
+ size_t maxBufLen = 0;
+ nsresult rv = nsContentUtils::CalculateBufferSizeForImage(map.mStride,
+ aSurface->GetSize(),
+ aSurface->GetFormat(),
+ &maxBufLen,
+ &bufLen);
+ if (NS_FAILED(rv)) {
+ // Release mapped memory
+ aSurface->Unmap();
return GetSurfaceDataContext::NullValue();
}
- size_t maxBufLen = requiredBytes.value();
- mozilla::gfx::SurfaceFormat format = aSurface->GetFormat();
-
- // Surface data handling is totally nuts. This is the magic one needs to
- // know to access the data.
- size_t bufLen = maxBufLen - map.mStride + (size.width * BytesPerPixel(format));
-
// nsDependentCString wants null-terminated string.
typename GetSurfaceDataContext::ReturnType surfaceData = aContext.Allocate(maxBufLen + 1);
if (GetSurfaceDataContext::GetBuffer(surfaceData)) {
@@ -9787,3 +9820,19 @@ nsContentUtils::AttemptLargeAllocationLoad(nsIHttpChannel* aChannel)
return reloadSucceeded;
}
+
+/* static */ bool
+nsContentUtils::IsLocalRefURL(const nsString& aString)
+{
+ // Find the first non-"C0 controls + space" character.
+ const char16_t* current = aString.get();
+ for (; *current != '\0'; current++) {
+ if (*current > 0x20) {
+ // if the first non-"C0 controls + space" character is '#', this is a
+ // local-ref URL.
+ return *current == '#';
+ }
+ }
+
+ return false;
+} \ No newline at end of file
diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
index 9ae6d2155..98df92efb 100644
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -975,11 +975,17 @@ public:
static bool PrefetchEnabled(nsIDocShell* aDocShell);
+ static nsresult CalculateBufferSizeForImage(const uint32_t& aStride,
+ const mozilla::gfx::IntSize& aImageSize,
+ const mozilla::gfx::SurfaceFormat& aFormat,
+ size_t* aMaxBufferSize,
+ size_t* aUsedBufferSize);
+
+private:
/**
* Fill (with the parameters given) the localized string named |aKey| in
* properties file |aFile|.
*/
-private:
static nsresult FormatLocalizedString(PropertiesFile aFile,
const char* aKey,
const char16_t** aParams,
@@ -2730,6 +2736,13 @@ public:
static bool AttemptLargeAllocationLoad(nsIHttpChannel* aChannel);
+ /**
+ * Detect whether a string is a (CSS) local-url.
+ * https://drafts.csswg.org/css-values/#local-urls
+ */
+ static bool
+ IsLocalRefURL(const nsString& aString);
+
private:
static bool InitializeEventTable();
diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h
index 7a73fae71..e5d12ab8f 100644
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -3439,13 +3439,29 @@ nsINode::OwnerDocAsNode() const
return OwnerDoc();
}
+// ShouldUseXBLScope is defined here as a template so that we can get the faster
+// version of IsInAnonymousSubtree if we're statically known to be an
+// nsIContent. we could try defining ShouldUseXBLScope separately on nsINode
+// and nsIContent, but then we couldn't put its nsINode implementation here
+// (because this header does not include nsIContent) and we can't put it in
+// nsIContent.h, because the definition of nsIContent::IsInAnonymousSubtree is
+// in nsIContentInlines.h. And then we get include hell from people trying to
+// call nsINode::GetParentObject but not including nsIContentInlines.h and with
+// no really good way to include it.
+template<typename T>
+inline bool ShouldUseXBLScope(const T* aNode)
+{
+ return aNode->IsInAnonymousSubtree() &&
+ !aNode->IsAnonymousContentInSVGUseSubtree();
+}
+
inline mozilla::dom::ParentObject
nsINode::GetParentObject() const
{
mozilla::dom::ParentObject p(OwnerDoc());
// Note that mUseXBLScope is a no-op for chrome, and other places where we
// don't use XBL scopes.
- p.mUseXBLScope = IsInAnonymousSubtree() && !IsAnonymousContentInSVGUseSubtree();
+ p.mUseXBLScope = ShouldUseXBLScope(this);
return p;
}
diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp
index 09e848710..ca507a5fc 100644
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -27,6 +27,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/ShadowRoot.h"
+#include "mozilla/dom/ScriptSettings.h"
#include "nsAttrValueOrString.h"
#include "nsBindingManager.h"
#include "nsCCUncollectableMarker.h"
@@ -1569,6 +1570,48 @@ CheckForOutdatedParent(nsINode* aParent, nsINode* aNode)
return NS_OK;
}
+static nsresult
+ReparentWrappersInSubtree(nsIContent* aRoot)
+{
+ MOZ_ASSERT(ShouldUseXBLScope(aRoot));
+ // Start off with no global so we don't fire any error events on failure.
+ AutoJSAPI jsapi;
+ jsapi.Init();
+
+ JSContext* cx = jsapi.cx();
+
+ nsIGlobalObject* docGlobal = aRoot->OwnerDoc()->GetScopeObject();
+ if (NS_WARN_IF(!docGlobal)) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ JS::Rooted<JSObject*> rootedGlobal(cx, docGlobal->GetGlobalJSObject());
+ if (NS_WARN_IF(!rootedGlobal)) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ rootedGlobal = xpc::GetXBLScope(cx, rootedGlobal);
+
+ nsresult rv;
+ JS::Rooted<JSObject*> reflector(cx);
+ for (nsIContent* cur = aRoot; cur; cur = cur->GetNextNode(aRoot)) {
+ if ((reflector = cur->GetWrapper())) {
+ JSAutoCompartment ac(cx, reflector);
+ rv = ReparentWrapper(cx, reflector);
+ if NS_FAILED(rv) {
+ // We _could_ consider BlastSubtreeToPieces here, but it's not really
+ // needed. Having some nodes in here accessible to content while others
+ // are not is probably OK. We just need to fail out of the actual
+ // insertion, so they're not in the DOM. Returning a failure here will
+ // do that.
+ return rv;
+ }
+ }
+ }
+
+ return NS_OK;
+}
+
nsresult
nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
bool aNotify, nsAttrAndChildArray& aChildArray)
@@ -1606,9 +1649,15 @@ nsINode::doInsertChildAt(nsIContent* aKid, uint32_t aIndex,
nsIContent* parent =
IsNodeOfType(eDOCUMENT) ? nullptr : static_cast<nsIContent*>(this);
+ bool wasInXBLScope = ShouldUseXBLScope(aKid);
rv = aKid->BindToTree(doc, parent,
parent ? parent->GetBindingParent() : nullptr,
true);
+ if (NS_SUCCEEDED(rv) && !wasInXBLScope && ShouldUseXBLScope(aKid)) {
+ MOZ_ASSERT(ShouldUseXBLScope(this),
+ "Why does the kid need to use an XBL scope?");
+ rv = ReparentWrappersInSubtree(aKid);
+ }
if (NS_FAILED(rv)) {
if (GetFirstChild() == aKid) {
mFirstChild = aKid->GetNextSibling();
diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp
index e2c139426..f944352e3 100644
--- a/dom/fetch/Fetch.cpp
+++ b/dom/fetch/Fetch.cpp
@@ -260,7 +260,7 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
}
RefPtr<MainThreadFetchRunnable> run = new MainThreadFetchRunnable(resolver, r);
- worker->DispatchToMainThread(run.forget());
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(run));
}
return p.forget();
diff --git a/dom/fetch/FetchConsumer.cpp b/dom/fetch/FetchConsumer.cpp
index 42dfcbaba..e82e5ec51 100644
--- a/dom/fetch/FetchConsumer.cpp
+++ b/dom/fetch/FetchConsumer.cpp
@@ -339,11 +339,7 @@ FetchBodyConsumer<Derived>::Create(nsIGlobalObject* aGlobal,
nsCOMPtr<nsIRunnable> r = new BeginConsumeBodyRunnable<Derived>(consumer);
- if (workerPrivate) {
- aRv = workerPrivate->DispatchToMainThread(r.forget());
- } else {
- aRv = NS_DispatchToMainThread(r.forget());
- }
+ aRv = NS_DispatchToMainThread(r.forget());
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
@@ -655,9 +651,7 @@ FetchBodyConsumer<Derived>::ShutDownMainThreadConsuming()
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
[self] () { self->ShutDownMainThreadConsuming(); });
- WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
- MOZ_ASSERT(workerPrivate);
- workerPrivate->DispatchToMainThread(r.forget());
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r.forget()));
return;
}
diff --git a/dom/media/GraphDriver.cpp b/dom/media/GraphDriver.cpp
index cae15eb8c..47762c56e 100644
--- a/dom/media/GraphDriver.cpp
+++ b/dom/media/GraphDriver.cpp
@@ -200,7 +200,7 @@ public:
STREAM_LOG(LogLevel::Debug, ("Starting system thread"));
profiler_register_thread("MediaStreamGraph", &aLocal);
LIFECYCLE_LOG("Starting a new system driver for graph %p\n",
- mDriver->mGraphImpl);
+ mDriver->mGraphImpl.get());
RefPtr<GraphDriver> previousDriver;
{
@@ -236,7 +236,7 @@ private:
void
ThreadedDriver::Start()
{
- LIFECYCLE_LOG("Starting thread for a SystemClockDriver %p\n", mGraphImpl);
+ LIFECYCLE_LOG("Starting thread for a SystemClockDriver %p\n", mGraphImpl.get());
Unused << NS_WARN_IF(mThread);
if (!mThread) { // Ensure we haven't already started it
nsCOMPtr<nsIRunnable> event = new MediaStreamGraphInitThreadRunnable(this);
@@ -761,7 +761,7 @@ AudioCallbackDriver::Destroy()
void
AudioCallbackDriver::Resume()
{
- STREAM_LOG(LogLevel::Debug, ("Resuming audio threads for MediaStreamGraph %p", mGraphImpl));
+ STREAM_LOG(LogLevel::Debug, ("Resuming audio threads for MediaStreamGraph %p", mGraphImpl.get()));
if (cubeb_stream_start(mAudioStream) != CUBEB_OK) {
NS_WARNING("Could not start cubeb stream for MSG.");
}
@@ -830,7 +830,9 @@ AudioCallbackDriver::Revive()
mGraphImpl->SetCurrentDriver(NextDriver());
NextDriver()->Start();
} else {
- STREAM_LOG(LogLevel::Debug, ("Starting audio threads for MediaStreamGraph %p from a new thread.", mGraphImpl));
+ STREAM_LOG(LogLevel::Debug,
+ ("Starting audio threads for MediaStreamGraph %p from a new thread.",
+ mGraphImpl.get()));
RefPtr<AsyncCubebTask> initEvent =
new AsyncCubebTask(this, AsyncCubebOperation::INIT);
initEvent->Dispatch();
diff --git a/dom/media/GraphDriver.h b/dom/media/GraphDriver.h
index 411e175d3..bb4f2689b 100644
--- a/dom/media/GraphDriver.h
+++ b/dom/media/GraphDriver.h
@@ -210,10 +210,8 @@ protected:
// Time of the end of this graph iteration. This must be accessed while having
// the monitor.
GraphTime mIterationEnd;
- // The MediaStreamGraphImpl that owns this driver. This has a lifetime longer
- // than the driver, and will never be null. Hence, it can be accesed without
- // monitor.
- MediaStreamGraphImpl* mGraphImpl;
+ // The MediaStreamGraphImpl associated with this driver.
+ const RefPtr<MediaStreamGraphImpl> mGraphImpl;
// This enum specifies the wait state of the driver.
enum WaitState {
diff --git a/dom/media/MediaStreamGraph.cpp b/dom/media/MediaStreamGraph.cpp
index e2934cbb2..1b9e4f674 100644
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -3371,7 +3371,8 @@ MediaStreamGraphImpl::Destroy()
// First unregister from memory reporting.
UnregisterWeakMemoryReporter(this);
- // Clear the self reference which will destroy this instance.
+ // Clear the self reference which will destroy this instance if all
+ // associated GraphDrivers are destroyed.
mSelfRef = nullptr;
}
diff --git a/dom/media/webrtc/RTCCertificate.cpp b/dom/media/webrtc/RTCCertificate.cpp
index 3f778bcbb..9f5e27c56 100644
--- a/dom/media/webrtc/RTCCertificate.cpp
+++ b/dom/media/webrtc/RTCCertificate.cpp
@@ -74,7 +74,7 @@ private:
char buf[sizeof(randomName) * 2 + 4];
PL_strncpy(buf, "CN=", 3);
for (size_t i = 0; i < sizeof(randomName); ++i) {
- snprintf(&buf[i * 2 + 3], 2, "%.2x", randomName[i]);
+ snprintf(&buf[i * 2 + 3], 3, "%.2x", randomName[i]);
}
buf[sizeof(buf) - 1] = '\0';
diff --git a/dom/svg/SVGUseElement.cpp b/dom/svg/SVGUseElement.cpp
index 4911e2cac..9212ab1aa 100644
--- a/dom/svg/SVGUseElement.cpp
+++ b/dom/svg/SVGUseElement.cpp
@@ -15,6 +15,7 @@
#include "mozilla/dom/Element.h"
#include "nsContentUtils.h"
#include "nsIURI.h"
+#include "nsSVGEffects.h"
NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Use)
@@ -418,11 +419,15 @@ SVGUseElement::LookupHref()
return;
}
+ nsCOMPtr<nsIURI> originURI =
+ mOriginal ? mOriginal->GetBaseURI() : GetBaseURI();
+ nsCOMPtr<nsIURI> baseURI = nsContentUtils::IsLocalRefURL(href)
+ ? nsSVGEffects::GetBaseURLForLocalRef(this, originURI)
+ : originURI;
+
nsCOMPtr<nsIURI> targetURI;
- nsCOMPtr<nsIURI> baseURI = mOriginal ? mOriginal->GetBaseURI() : GetBaseURI();
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), href,
GetComposedDoc(), baseURI);
-
mSource.Reset(this, targetURI);
}
diff --git a/dom/svg/test/reftest_viewport_noninteger.html b/dom/svg/test/reftest_viewport_noninteger.html
new file mode 100644
index 000000000..3f4852b53
--- /dev/null
+++ b/dom/svg/test/reftest_viewport_noninteger.html
@@ -0,0 +1,175 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>SVG size test</title>
+ <style>
+ body {
+ margin: 30px;
+ font-family: sans-serif;
+ }
+
+ #tests {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ grid-gap: 30px;
+ }
+
+ #tests div:hover {
+ opacity: 1 !important;
+ }
+
+ #tests p {
+ text-decoration: underline dotted black;
+ }
+
+ svg {
+ background: lightgrey;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>SVG size test</h1>
+
+ <p>The grey boxes below are <code>&lt;svg&gt;</code> elements.</p>
+ <p>All SVGs in each row should have the exact same size.</p>
+ <p>Each row has its own viewBox width and height: <code>viewBox="0 0 width height"</code>.</p>
+ <p>Each column has its own width/height styling. For example, <code>style="width: 200px; height: auto;"</code>.</p>
+ <p>The first column has both an explicit widht and an explicit height, so there's not much that can go wrong there. It acts as a reference.</p>
+ <p>The first row has integer viewBox width and height. Firefox then sizes all SVGs correctly.</p>
+ <p>The remaining rows have at least one non-integer viewBox width and height. Firefox then sizes the SVGs a bit wrong.</p>
+ <p>Chrome, Safari and Edge seem to pass all tests.</p>
+
+ <p id="summary"></p>
+
+ <div id="tests"></div>
+
+ <script>
+ const testsElement = document.getElementById("tests");
+ const summaryElement = document.getElementById("summary");
+
+ // Turn for instance `2.3` into `230` (px). Round to avoid floating point
+ // issues.
+ const scale = (number) => Math.round(100 * number);
+
+ const widths = [2, 2.3, 2.5, 2.8];
+ const heights = [3, 3.3, 3.5, 3.8];
+
+ let numPassed = 0;
+ let numFailed = 0;
+
+ for (const width of widths) {
+ for (const height of heights) {
+ const variations = [
+ {width, height},
+ {width: "auto", height},
+ {width, height: "auto"},
+ {width: "auto", height: "auto"},
+ ];
+
+ for (const variation of variations) {
+ const cellElement = document.createElement("div");
+
+ const titleElement = document.createElement("h2");
+ titleElement.appendChild(makeTitle(width, height, variation));
+
+ const sizeElement = document.createElement("p");
+
+ const svgWrapperElement = document.createElement("div");
+ svgWrapperElement.style.width =
+ variation.width === "auto" && variation.height === "auto"
+ ? `${scale(width)}px`
+ : "auto";
+
+ const svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg");
+ svgElement.setAttribute("viewBox", `0 0 ${width} ${height}`);
+ svgElement.style.width =
+ typeof variation.width === "number"
+ ? `${scale(variation.width)}px`
+ : variation.width;
+ svgElement.style.height =
+ typeof variation.height === "number"
+ ? `${scale(variation.height)}px`
+ : variation.height;
+
+ svgWrapperElement.appendChild(svgElement);
+
+ cellElement.appendChild(titleElement);
+ cellElement.appendChild(sizeElement);
+ cellElement.appendChild(svgWrapperElement);
+
+ testsElement.appendChild(cellElement);
+
+ const rect = svgElement.getBoundingClientRect();
+ const actual = {
+ width: Math.round(rect.width),
+ height: Math.round(rect.height),
+ };
+ const expected = {
+ width: scale(width),
+ height: scale(height),
+ };
+ const passed =
+ actual.width === expected.width &&
+ actual.height === expected.height;
+
+ const icon = passed ? "✔" : "✘";
+ const iconText = passed ? "PASS" : "FAIL";
+ const expectedText = passed ? "" : `\nExpected size: ${expected.width}x${expected.height}`;
+ sizeElement.textContent = `${icon} ${actual.width}x${actual.height}`;
+ sizeElement.title = `${iconText}. Actual size, as measured by element.getBoundingClientRect().${expectedText}`;
+ sizeElement.style.color = passed ? "lime" : "red";
+ sizeElement.style.fontWeight = passed ? "normal" : "bold";
+
+ cellElement.style.opacity = passed ? 0.5 : 1;
+
+ if (passed) {
+ numPassed++;
+ } else {
+ numFailed++;
+ }
+ }
+ }
+ }
+
+ const numTotal = numPassed + numFailed;
+ const passed = numFailed === 0;
+ const icon = passed ? "✔" : "✘";
+ summaryElement.textContent = `${icon} ${numPassed}/${numTotal} tests passed.`;
+ summaryElement.style.color = passed ? "lime" : "red";
+ summaryElement.style.fontWeight = "bold";
+
+ function makeTitle(width, height, variation) {
+ const fragment = document.createDocumentFragment();
+
+ const first = document.createElement("abbr");
+ first.textContent = `${width}/${height}`;
+ first.title = `SVG viewBox width/height: viewBox="0 0 ${width} ${height}"`;
+
+ const separator = document.createTextNode(" | ");
+
+ const second = document.createElement("abbr");
+
+ const widthString = typeof variation.width === "number" ? "px" : variation.width;
+ const heightString = typeof variation.height === "number" ? "px" : variation.height;
+ second.textContent = `${widthString}/${heightString}`;
+
+ const widthExplanation =
+ typeof variation.width === "number"
+ ? "explicit width (px)"
+ : `${variation.width} width`
+ const heightExplanation =
+ typeof variation.height === "number"
+ ? "explicit height (px)"
+ : `${variation.height} height`
+ second.title = `${widthExplanation}, ${heightExplanation}`;
+
+ fragment.appendChild(first);
+ fragment.appendChild(separator);
+ fragment.appendChild(second);
+
+ return fragment;
+ }
+ </script>
+ </body>
+</html>
diff --git a/dom/workers/ServiceWorkerClient.cpp b/dom/workers/ServiceWorkerClient.cpp
index 660512a5f..6ed3a6ea4 100644
--- a/dom/workers/ServiceWorkerClient.cpp
+++ b/dom/workers/ServiceWorkerClient.cpp
@@ -224,7 +224,7 @@ ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
return;
}
- aRv = workerPrivate->DispatchToMainThread(runnable.forget());
+ aRv = NS_DispatchToMainThread(runnable);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
diff --git a/dom/workers/ServiceWorkerClients.cpp b/dom/workers/ServiceWorkerClients.cpp
index 11f864443..38f49e355 100644
--- a/dom/workers/ServiceWorkerClients.cpp
+++ b/dom/workers/ServiceWorkerClients.cpp
@@ -753,7 +753,7 @@ ServiceWorkerClients::Get(const nsAString& aClientId, ErrorResult& aRv)
RefPtr<GetRunnable> r =
new GetRunnable(promiseProxy, aClientId);
- MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r));
return promise.forget();
}
@@ -789,7 +789,7 @@ ServiceWorkerClients::MatchAll(const ClientQueryOptions& aOptions,
new MatchAllRunnable(promiseProxy,
NS_ConvertUTF16toUTF8(scope),
aOptions.mIncludeUncontrolled);
- MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r));
return promise.forget();
}
@@ -830,7 +830,7 @@ ServiceWorkerClients::OpenWindow(const nsAString& aUrl,
RefPtr<OpenWindowRunnable> r = new OpenWindowRunnable(promiseProxy,
aUrl, scope);
- MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r));
return promise.forget();
}
@@ -859,6 +859,6 @@ ServiceWorkerClients::Claim(ErrorResult& aRv)
RefPtr<ClaimRunnable> runnable =
new ClaimRunnable(promiseProxy, NS_ConvertUTF16toUTF8(scope));
- MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(runnable.forget()));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
return promise.forget();
}
diff --git a/dom/workers/ServiceWorkerEvents.cpp b/dom/workers/ServiceWorkerEvents.cpp
index 1f79e2c92..8b375c635 100644
--- a/dom/workers/ServiceWorkerEvents.cpp
+++ b/dom/workers/ServiceWorkerEvents.cpp
@@ -400,13 +400,7 @@ void RespondWithCopyComplete(void* aClosure, nsresult aStatus)
data->mScriptSpec,
data->mResponseURLSpec);
}
- // In theory this can happen after the worker thread is terminated.
- WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
- if (worker) {
- MOZ_ALWAYS_SUCCEEDS(worker->DispatchToMainThread(event.forget()));
- } else {
- MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(event.forget()));
- }
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(event));
}
namespace {
@@ -734,13 +728,7 @@ RespondWithHandler::CancelRequest(nsresult aStatus)
{
nsCOMPtr<nsIRunnable> runnable =
new CancelChannelRunnable(mInterceptedChannel, mRegistration, aStatus);
- // Note, this may run off the worker thread during worker termination.
- WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
- if (worker) {
- MOZ_ALWAYS_SUCCEEDS(worker->DispatchToMainThread(runnable.forget()));
- } else {
- MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable.forget()));
- }
+ NS_DispatchToMainThread(runnable);
mRequestWasHandled = true;
}
@@ -873,8 +861,8 @@ public:
mColumn = column;
}
- MOZ_ALWAYS_SUCCEEDS(mWorkerPrivate->DispatchToMainThread(
- NewRunnableMethod(this, &WaitUntilHandler::ReportOnMainThread)));
+ MOZ_ALWAYS_SUCCEEDS(
+ NS_DispatchToMainThread(NewRunnableMethod(this, &WaitUntilHandler::ReportOnMainThread)));
}
void
diff --git a/dom/workers/ServiceWorkerPrivate.cpp b/dom/workers/ServiceWorkerPrivate.cpp
index 24b2e11e6..23ae3b366 100644
--- a/dom/workers/ServiceWorkerPrivate.cpp
+++ b/dom/workers/ServiceWorkerPrivate.cpp
@@ -214,7 +214,7 @@ private:
mDone = true;
#endif
mCallback->SetResult(aResult);
- MOZ_ALWAYS_SUCCEEDS(mWorkerPrivate->DispatchToMainThread(mCallback));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(mCallback));
}
};
@@ -500,7 +500,7 @@ public:
if (mRegistration) {
nsCOMPtr<nsIRunnable> runnable =
new RegistrationUpdateRunnable(mRegistration, true /* time check */);
- aWorkerPrivate->DispatchToMainThread(runnable.forget());
+ NS_DispatchToMainThread(runnable.forget());
}
ExtendableEventWorkerRunnable::PostRun(aCx, aWorkerPrivate, aRunResult);
@@ -541,7 +541,7 @@ public:
Cancel() override
{
mCallback->SetResult(false);
- MOZ_ALWAYS_SUCCEEDS(mWorkerPrivate->DispatchToMainThread(mCallback));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(mCallback));
return WorkerRunnable::Cancel();
}
@@ -637,7 +637,7 @@ public:
mDone = true;
mCallback->SetResult(aResult);
- nsresult rv = mWorkerPrivate->DispatchToMainThread(mCallback);
+ nsresult rv = NS_DispatchToMainThread(mCallback);
if (NS_WARN_IF(NS_FAILED(rv))) {
NS_RUNTIMEABORT("Failed to dispatch life cycle event handler.");
}
@@ -768,7 +768,6 @@ public:
void Report(uint16_t aReason = nsIPushErrorReporter::DELIVERY_INTERNAL_ERROR)
{
- WorkerPrivate* workerPrivate = mWorkerPrivate;
mWorkerPrivate->AssertIsOnWorkerThread();
mWorkerPrivate = nullptr;
@@ -780,7 +779,7 @@ public:
NewRunnableMethod<uint16_t>(this,
&PushErrorReporter::ReportOnMainThread, aReason);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
- workerPrivate->DispatchToMainThread(runnable.forget())));
+ NS_DispatchToMainThread(runnable.forget())));
}
void ReportOnMainThread(uint16_t aReason)
@@ -1434,7 +1433,7 @@ public:
Cancel() override
{
nsCOMPtr<nsIRunnable> runnable = new ResumeRequest(mInterceptedChannel);
- if (NS_FAILED(mWorkerPrivate->DispatchToMainThread(runnable))) {
+ if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
NS_WARNING("Failed to resume channel on FetchEventRunnable::Cancel()!\n");
}
WorkerRunnable::Cancel();
@@ -1554,7 +1553,7 @@ private:
NS_ERROR_INTERCEPTION_FAILED);
}
- MOZ_ALWAYS_SUCCEEDS(mWorkerPrivate->DispatchToMainThread(runnable.forget()));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
}
RefPtr<Promise> waitUntilPromise = event->GetPromise();
diff --git a/dom/workers/ServiceWorkerRegistration.cpp b/dom/workers/ServiceWorkerRegistration.cpp
index 451bd2be9..b3cda2c10 100644
--- a/dom/workers/ServiceWorkerRegistration.cpp
+++ b/dom/workers/ServiceWorkerRegistration.cpp
@@ -1107,7 +1107,7 @@ ServiceWorkerRegistrationWorkerThread::Update(ErrorResult& aRv)
}
RefPtr<UpdateRunnable> r = new UpdateRunnable(proxy, mScope);
- MOZ_ALWAYS_SUCCEEDS(worker->DispatchToMainThread(r.forget()));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r));
return promise.forget();
}
@@ -1139,7 +1139,7 @@ ServiceWorkerRegistrationWorkerThread::Unregister(ErrorResult& aRv)
}
RefPtr<StartUnregisterRunnable> r = new StartUnregisterRunnable(proxy, mScope);
- MOZ_ALWAYS_SUCCEEDS(worker->DispatchToMainThread(r.forget()));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r));
return promise.forget();
}
@@ -1161,7 +1161,7 @@ ServiceWorkerRegistrationWorkerThread::InitListener()
nsCOMPtr<nsIRunnable> r =
NewRunnableMethod(mListener, &WorkerListener::StartListeningForEvents);
- MOZ_ALWAYS_SUCCEEDS(worker->DispatchToMainThread(r.forget()));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r));
}
void
@@ -1183,7 +1183,7 @@ ServiceWorkerRegistrationWorkerThread::ReleaseListener()
nsCOMPtr<nsIRunnable> r =
NewRunnableMethod(mListener, &WorkerListener::StopListeningForEvents);
- MOZ_ALWAYS_SUCCEEDS(mWorkerPrivate->DispatchToMainThread(r.forget()));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r));
mListener = nullptr;
mWorkerPrivate = nullptr;
diff --git a/dom/workers/ServiceWorkerWindowClient.cpp b/dom/workers/ServiceWorkerWindowClient.cpp
index 2ce0603cf..bae747214 100644
--- a/dom/workers/ServiceWorkerWindowClient.cpp
+++ b/dom/workers/ServiceWorkerWindowClient.cpp
@@ -183,7 +183,7 @@ ServiceWorkerWindowClient::Focus(ErrorResult& aRv) const
if (promiseProxy) {
RefPtr<ClientFocusRunnable> r = new ClientFocusRunnable(mWindowId,
promiseProxy);
- MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r));
} else {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
}
@@ -549,7 +549,7 @@ ServiceWorkerWindowClient::Navigate(const nsAString& aUrl, ErrorResult& aRv)
if (promiseProxy) {
RefPtr<ClientNavigateRunnable> r =
new ClientNavigateRunnable(mWindowId, aUrl, scope, promiseProxy);
- MOZ_ALWAYS_SUCCEEDS(workerPrivate->DispatchToMainThread(r.forget()));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r));
} else {
promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
}
diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
index 612090027..6bc5c4f96 100644
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -404,7 +404,7 @@ private:
RefPtr<MainThreadReleaseRunnable> runnable =
new MainThreadReleaseRunnable(doomed, loadGroupToCancel);
- if (NS_FAILED(mWorkerPrivate->DispatchToMainThread(runnable.forget()))) {
+ if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
NS_WARNING("Failed to dispatch, going to leak!");
}
@@ -4078,7 +4078,7 @@ WorkerDebugger::PostMessageToDebugger(const nsAString& aMessage)
RefPtr<PostDebuggerMessageRunnable> runnable =
new PostDebuggerMessageRunnable(this, aMessage);
- if (NS_FAILED(mWorkerPrivate->DispatchToMainThread(runnable.forget()))) {
+ if (NS_FAILED(NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL))) {
NS_WARNING("Failed to post message to debugger on main thread!");
}
}
@@ -4103,7 +4103,7 @@ WorkerDebugger::ReportErrorToDebugger(const nsAString& aFilename,
RefPtr<ReportDebuggerErrorRunnable> runnable =
new ReportDebuggerErrorRunnable(this, aFilename, aLineno, aMessage);
- if (NS_FAILED(mWorkerPrivate->DispatchToMainThread(runnable.forget()))) {
+ if (NS_FAILED(NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL))) {
NS_WARNING("Failed to report error to debugger on main thread!");
}
}
@@ -4862,7 +4862,7 @@ WorkerPrivate::MaybeDispatchLoadFailedRunnable()
return;
}
- MOZ_ALWAYS_SUCCEEDS(DispatchToMainThread(runnable.forget()));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable.forget()));
}
nsIEventTarget*
@@ -5083,7 +5083,7 @@ WorkerPrivate::ScheduleDeletion(WorkerRanOrNot aRanOrNot)
else {
RefPtr<TopLevelWorkerFinishedRunnable> runnable =
new TopLevelWorkerFinishedRunnable(this);
- if (NS_FAILED(DispatchToMainThread(runnable.forget()))) {
+ if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
NS_WARNING("Failed to dispatch runnable!");
}
}
diff --git a/dom/workers/WorkerRunnable.cpp b/dom/workers/WorkerRunnable.cpp
index 9e6d4cfb8..60d69d4e4 100644
--- a/dom/workers/WorkerRunnable.cpp
+++ b/dom/workers/WorkerRunnable.cpp
@@ -117,7 +117,10 @@ WorkerRunnable::DispatchInternal()
return NS_SUCCEEDED(parent->Dispatch(runnable.forget()));
}
- return NS_SUCCEEDED(mWorkerPrivate->DispatchToMainThread(runnable.forget()));
+ nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+ MOZ_ASSERT(mainThread);
+
+ return NS_SUCCEEDED(mainThread->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL));
}
void
@@ -553,7 +556,10 @@ WorkerControlRunnable::DispatchInternal()
return NS_SUCCEEDED(parent->DispatchControlRunnable(runnable.forget()));
}
- return NS_SUCCEEDED(mWorkerPrivate->DispatchToMainThread(runnable.forget()));
+ nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+ MOZ_ASSERT(mainThread);
+
+ return NS_SUCCEEDED(mainThread->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL));
}
NS_IMPL_ISUPPORTS_INHERITED0(WorkerControlRunnable, WorkerRunnable)
@@ -580,7 +586,10 @@ WorkerMainThreadRunnable::Dispatch(Status aFailStatus, ErrorResult& aRv)
return;
}
- DebugOnly<nsresult> rv = mWorkerPrivate->DispatchToMainThread(this);
+ RefPtr<WorkerMainThreadRunnable> runnable(this);
+
+ DebugOnly<nsresult> rv =
+ NS_DispatchToMainThread(runnable.forget(), NS_DISPATCH_NORMAL);
MOZ_ASSERT(NS_SUCCEEDED(rv),
"Should only fail after xpcom-shutdown-threads and we're gone by then");
@@ -670,7 +679,7 @@ WorkerProxyToMainThreadRunnable::Dispatch()
return false;
}
- if (NS_WARN_IF(NS_FAILED(mWorkerPrivate->DispatchToMainThread(this)))) {
+ if (NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(this)))) {
ReleaseWorker();
RunBackOnWorkerThread();
return false;
diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp
index 54252e53b..ace1a09fc 100644
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -717,7 +717,7 @@ ServiceWorkerGlobalScope::SkipWaiting(ErrorResult& aRv)
new WorkerScopeSkipWaitingRunnable(promiseProxy,
NS_ConvertUTF16toUTF8(mScope));
- MOZ_ALWAYS_SUCCEEDS(mWorkerPrivate->DispatchToMainThread(runnable.forget()));
+ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
return promise.forget();
}