moebius#157: The Performance Observer (improvements)

https://github.com/MoonchildProductions/moebius/pull/157
This commit is contained in:
janekptacijarabaci 2018-04-22 04:25:34 +02:00 • committed by Roy Tam
commit 6a97ee9379
13 changed files with 107 additions and 150 deletions

View file

@ -38,27 +38,6 @@ using namespace workers;
namespace { namespace {
// Helper classes
class MOZ_STACK_CLASS PerformanceEntryComparator final
{
public:
bool Equals(const PerformanceEntry* aElem1,
const PerformanceEntry* aElem2) const
{
MOZ_ASSERT(aElem1 && aElem2,
"Trying to compare null performance entries");
return aElem1->StartTime() == aElem2->StartTime();
}
bool LessThan(const PerformanceEntry* aElem1,
const PerformanceEntry* aElem2) const
{
MOZ_ASSERT(aElem1 && aElem2,
"Trying to compare null performance entries");
return aElem1->StartTime() < aElem2->StartTime();
}
};
class PrefEnabledRunnable final class PrefEnabledRunnable final
: public WorkerCheckAPIExposureOnMainThreadRunnable : public WorkerCheckAPIExposureOnMainThreadRunnable
{ {

View file

@ -90,6 +90,27 @@ protected:
nsString mEntryType; nsString mEntryType;
}; };
// Helper classes
class MOZ_STACK_CLASS PerformanceEntryComparator final
{
public:
bool Equals(const PerformanceEntry* aElem1,
const PerformanceEntry* aElem2) const
{
MOZ_ASSERT(aElem1 && aElem2,
"Trying to compare null performance entries");
return aElem1->StartTime() == aElem2->StartTime();
}
bool LessThan(const PerformanceEntry* aElem1,
const PerformanceEntry* aElem2) const
{
MOZ_ASSERT(aElem1 && aElem2,
"Trying to compare null performance entries");
return aElem1->StartTime() < aElem2->StartTime();
}
};
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View file

@ -114,12 +114,13 @@ PerformanceObserver::Notify()
RefPtr<PerformanceObserverEntryList> list = RefPtr<PerformanceObserverEntryList> list =
new PerformanceObserverEntryList(this, mQueuedEntries); new PerformanceObserverEntryList(this, mQueuedEntries);
mQueuedEntries.Clear();
ErrorResult rv; ErrorResult rv;
mCallback->Call(this, *list, *this, rv); mCallback->Call(this, *list, *this, rv);
if (NS_WARN_IF(rv.Failed())) { if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException(); rv.SuppressException();
} }
mQueuedEntries.Clear();
} }
void void
@ -170,6 +171,17 @@ PerformanceObserver::Observe(const PerformanceObserverInit& aOptions,
mEntryTypes.SwapElements(validEntryTypes); mEntryTypes.SwapElements(validEntryTypes);
mPerformance->AddObserver(this); mPerformance->AddObserver(this);
if (aOptions.mBuffered) {
for (auto entryType : mEntryTypes) {
nsTArray<RefPtr<PerformanceEntry>> existingEntries;
mPerformance->GetEntriesByType(entryType, existingEntries);
if (!existingEntries.IsEmpty()) {
mQueuedEntries.AppendElements(existingEntries);
}
}
}
mConnected = true; mConnected = true;
} }

View file

@ -66,6 +66,7 @@ PerformanceObserverEntryList::GetEntries(
aRetval.AppendElement(entry); aRetval.AppendElement(entry);
} }
aRetval.Sort(PerformanceEntryComparator());
} }
void void
@ -79,6 +80,7 @@ PerformanceObserverEntryList::GetEntriesByType(
aRetval.AppendElement(entry); aRetval.AppendElement(entry);
} }
} }
aRetval.Sort(PerformanceEntryComparator());
} }
void void
@ -88,9 +90,18 @@ PerformanceObserverEntryList::GetEntriesByName(
nsTArray<RefPtr<PerformanceEntry>>& aRetval) nsTArray<RefPtr<PerformanceEntry>>& aRetval)
{ {
aRetval.Clear(); aRetval.Clear();
const bool typePassed = aEntryType.WasPassed();
for (const RefPtr<PerformanceEntry>& entry : mEntries) { for (const RefPtr<PerformanceEntry>& entry : mEntries) {
if (entry->GetName().Equals(aName)) { if (!entry->GetName().Equals(aName)) {
continue;
}
if (typePassed &&
!entry->GetEntryType().Equals(aEntryType.Value())) {
continue;
}
aRetval.AppendElement(entry); aRetval.AppendElement(entry);
} }
} aRetval.Sort(PerformanceEntryComparator());
} }

View file

@ -1,13 +1,11 @@
[DEFAULT] [DEFAULT]
support-files = support-files =
performance_observer.html
test_performance_observer.js test_performance_observer.js
test_performance_user_timing.js test_performance_user_timing.js
test_worker_performance_now.js test_worker_performance_now.js
worker_performance_user_timing.js worker_performance_user_timing.js
worker_performance_observer.js worker_performance_observer.js
sharedworker_performance_user_timing.js sharedworker_performance_user_timing.js
worker_performance_observer.html
[test_performance_observer.html] [test_performance_observer.html]
[test_performance_user_timing.html] [test_performance_user_timing.html]

View file

@ -1,74 +0,0 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE html>
<meta charset=utf-8>
<html>
<head>
<title>Test for performance observer</title>
<script>
'use strict';
[
"promise_test", "test", "setup",
"assert_true", "assert_equals", "assert_array_equals",
"assert_throws", "assert_unreached"
].forEach(func => {
window[func] = opener[func].bind(opener);
});
function done() {
opener.add_completion_callback(() => {
self.close();
});
opener.done();
}
</script>
<script src="test_performance_observer.js"></script>
</head>
<body>
<div id="log"></div>
<script>
function makeXHR(aUrl) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("get", aUrl, true);
xmlhttp.send();
}
promise_test(t => {
var promise = new Promise(resolve => {
performance.clearResourceTimings();
var observer = new PerformanceObserver(list => resolve(list));
observer.observe({entryTypes: ['resource']});
t.add_cleanup(() => observer.disconnect());
});
makeXHR("test-data.json");
return promise.then(list => {
assert_equals(list.getEntries().length, 1);
assert_array_equals(list.getEntries(),
performance.getEntriesByType("resource"),
"Observed 'resource' entries should equal to entries obtained by getEntriesByType.");
// getEntries filtering tests
assert_array_equals(list.getEntries({name: "http://mochi.test:8888/tests/dom/base/test/test-data.json"}),
performance.getEntriesByName("http://mochi.test:8888/tests/dom/base/test/test-data.json"),
"getEntries with name filter should return correct results.");
assert_array_equals(list.getEntries({entryType: "resource"}),
performance.getEntriesByType("resource"),
"getEntries with entryType filter should return correct results.");
assert_array_equals(list.getEntries({initiatorType: "xmlhttprequest"}),
performance.getEntriesByType("resource"),
"getEntries with initiatorType filter should return correct results.");
assert_array_equals(list.getEntries({initiatorType: "link"}),
[],
"getEntries with non-existent initiatorType filter should return an empty array.");
});
}, "resource-timing test");
done();
</script>
</body>

View file

@ -3,15 +3,55 @@
http://creativecommons.org/publicdomain/zero/1.0/ http://creativecommons.org/publicdomain/zero/1.0/
--> -->
<!DOCTYPE html> <!DOCTYPE html>
<html>
<head>
<meta charset=utf-8> <meta charset=utf-8>
<title>Test for performance observer</title> <title>Test for performance observer</title>
<script src="/resources/testharness.js"></script> <script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<div id=log></div> </head>
<body>
<div id="log"></div>
<script src="test_performance_observer.js"></script>
<script> <script>
'use strict'; function makeXHR(aUrl) {
SpecialPowers.pushPrefEnv({"set": [["dom.enable_performance_observer", true]]}, var xmlhttp = new XMLHttpRequest();
function() { xmlhttp.open("get", aUrl, true);
window.open("performance_observer.html"); xmlhttp.send();
}
promise_test(t => {
var promise = new Promise(resolve => {
performance.clearResourceTimings();
var observer = new PerformanceObserver(list => resolve(list));
observer.observe({entryTypes: ['resource']});
t.add_cleanup(() => observer.disconnect());
}); });
makeXHR("test-data.json");
return promise.then(list => {
assert_equals(list.getEntries().length, 1);
assert_array_equals(list.getEntries(),
performance.getEntriesByType("resource"),
"Observed 'resource' entries should equal to entries obtained by getEntriesByType.");
// getEntries filtering tests
assert_array_equals(list.getEntries({name: "http://mochi.test:8888/tests/dom/base/test/test-data.json"}),
performance.getEntriesByName("http://mochi.test:8888/tests/dom/base/test/test-data.json"),
"getEntries with name filter should return correct results.");
assert_array_equals(list.getEntries({entryType: "resource"}),
performance.getEntriesByType("resource"),
"getEntries with entryType filter should return correct results.");
assert_array_equals(list.getEntries({initiatorType: "xmlhttprequest"}),
performance.getEntriesByType("resource"),
"getEntries with initiatorType filter should return correct results.");
assert_array_equals(list.getEntries({initiatorType: "link"}),
[],
"getEntries with non-existent initiatorType filter should return an empty array.");
});
}, "resource-timing test");
</script> </script>
</body>

View file

@ -3,15 +3,16 @@
http://creativecommons.org/publicdomain/zero/1.0/ http://creativecommons.org/publicdomain/zero/1.0/
--> -->
<!DOCTYPE html> <!DOCTYPE html>
<html>
<head>
<meta charset=utf-8> <meta charset=utf-8>
<title>Test for performance observer in worker</title> <title>Test for performance observer in worker</title>
<script src="/resources/testharness.js"></script> <script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>
<div id=log></div> </head>
<body>
<div id="log"></div>
<script> <script>
'use strict'; fetch_tests_from_worker(new Worker("worker_performance_observer.js"));
SpecialPowers.pushPrefEnv({"set": [["dom.enable_performance_observer", true]]},
function() {
window.open("worker_performance_observer.html");
});
</script> </script>
</body>

View file

@ -1,32 +0,0 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE html>
<meta charset=utf-8>
<html>
<head>
<title>Test for performance observer in worker</title>
</head>
<body>
<div id="log"></div>
<script>
[
"async_test", "test", "setup",
"assert_true", "assert_equals", "assert_array_equals",
"assert_throws", "fetch_tests_from_worker"
].forEach(func => {
window[func] = opener[func].bind(opener);
});
function done() {
opener.add_completion_callback(() => {
self.close();
});
opener.done();
}
fetch_tests_from_worker(new Worker("worker_performance_observer.js"));
done();
</script>
</body>

View file

@ -751,9 +751,9 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceNavigation", "PerformanceNavigation",
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{name: "PerformanceObserver", nightly: true}, "PerformanceObserver",
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{name: "PerformanceObserverEntryList", nightly: true}, "PerformanceObserverEntryList",
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceResourceTiming", "PerformanceResourceTiming",
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!

View file

@ -9,6 +9,7 @@
dictionary PerformanceObserverInit { dictionary PerformanceObserverInit {
required sequence<DOMString> entryTypes; required sequence<DOMString> entryTypes;
boolean buffered = false;
}; };
callback PerformanceObserverCallback = void (PerformanceObserverEntryList entries, PerformanceObserver observer); callback PerformanceObserverCallback = void (PerformanceObserverEntryList entries, PerformanceObserver observer);

View file

@ -172,9 +172,9 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceMeasure", "PerformanceMeasure",
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "PerformanceObserver", nightly: true }, "PerformanceObserver",
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "PerformanceObserverEntryList", nightly: true }, "PerformanceObserverEntryList",
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
"Request", "Request",
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!

View file

@ -163,9 +163,9 @@ var interfaceNamesInGlobalScope =
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
"PerformanceMeasure", "PerformanceMeasure",
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "PerformanceObserver", nightly: true }, "PerformanceObserver",
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{ name: "PerformanceObserverEntryList", nightly: true }, "PerformanceObserverEntryList",
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
"Request", "Request",
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!