mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-28 03:17:31 +09:00
Merge remote-tracking branch 'origin/tracking' into custom
This commit is contained in:
commit
265490b550
18 changed files with 554 additions and 95 deletions
|
|
@ -157,6 +157,12 @@ DOM4_MSG_DEF(NotSupportedError, "The media resource indicated by the src attribu
|
||||||
DOM4_MSG_DEF(SyntaxError, "The URI is malformed.", NS_ERROR_DOM_MALFORMED_URI)
|
DOM4_MSG_DEF(SyntaxError, "The URI is malformed.", NS_ERROR_DOM_MALFORMED_URI)
|
||||||
DOM4_MSG_DEF(SyntaxError, "Invalid header name.", NS_ERROR_DOM_INVALID_HEADER_NAME)
|
DOM4_MSG_DEF(SyntaxError, "Invalid header name.", NS_ERROR_DOM_INVALID_HEADER_NAME)
|
||||||
|
|
||||||
|
/* User Timing API errors */
|
||||||
|
DOM4_MSG_DEF(SyntaxError, "An unknown mark name was provided.", NS_ERROR_DOM_UT_UNKNOWN_MARK_NAME)
|
||||||
|
DOM4_MSG_DEF(SyntaxError, "markName cannot be a performance timing attribute.", NS_ERROR_DOM_UT_INVALID_TIMING_ATTR)
|
||||||
|
DOM4_MSG_DEF(InvalidAccessError, "A PerformanceTiming attribute which isn't available yet was provided.", NS_ERROR_DOM_UT_UNAVAILABLE_ATTR)
|
||||||
|
DOM4_MSG_DEF(InvalidStateError, "Global object is unavailable.", NS_ERROR_DOM_UT_UNAVAILABLE_GLOBAL_OBJECT)
|
||||||
|
|
||||||
/* XMLHttpRequest errors. */
|
/* XMLHttpRequest errors. */
|
||||||
DOM4_MSG_DEF(InvalidStateError, "XMLHttpRequest has an invalid context.", NS_ERROR_DOM_INVALID_STATE_XHR_HAS_INVALID_CONTEXT)
|
DOM4_MSG_DEF(InvalidStateError, "XMLHttpRequest has an invalid context.", NS_ERROR_DOM_INVALID_STATE_XHR_HAS_INVALID_CONTEXT)
|
||||||
DOM4_MSG_DEF(InvalidStateError, "XMLHttpRequest state must be OPENED.", NS_ERROR_DOM_INVALID_STATE_XHR_MUST_BE_OPENED)
|
DOM4_MSG_DEF(InvalidStateError, "XMLHttpRequest state must be OPENED.", NS_ERROR_DOM_INVALID_STATE_XHR_MUST_BE_OPENED)
|
||||||
|
|
|
||||||
|
|
@ -659,6 +659,12 @@ DOMInterfaces = {
|
||||||
'wrapperCache': False
|
'wrapperCache': False
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'Performance' : {
|
||||||
|
'implicitJSContext': [
|
||||||
|
'mark'
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
'Plugin': {
|
'Plugin': {
|
||||||
'headerFile' : 'nsPluginArray.h',
|
'headerFile' : 'nsPluginArray.h',
|
||||||
'nativeType': 'nsPluginElement',
|
'nativeType': 'nsPluginElement',
|
||||||
|
|
|
||||||
|
|
@ -100,3 +100,10 @@ MSG_DEF(MSG_TIME_VALUE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "{0} is outside the suppo
|
||||||
MSG_DEF(MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN, 1, JSEXN_TYPEERR, "Request mode '{0}' was used, but request cache mode 'only-if-cached' can only be used with request mode 'same-origin'.")
|
MSG_DEF(MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN, 1, JSEXN_TYPEERR, "Request mode '{0}' was used, but request cache mode 'only-if-cached' can only be used with request mode 'same-origin'.")
|
||||||
MSG_DEF(MSG_THRESHOLD_RANGE_ERROR, 0, JSEXN_RANGEERR, "Threshold values must all be in the range [0, 1].")
|
MSG_DEF(MSG_THRESHOLD_RANGE_ERROR, 0, JSEXN_RANGEERR, "Threshold values must all be in the range [0, 1].")
|
||||||
MSG_DEF(MSG_CACHE_OPEN_FAILED, 0, JSEXN_TYPEERR, "CacheStorage.open() failed to access the storage system.")
|
MSG_DEF(MSG_CACHE_OPEN_FAILED, 0, JSEXN_TYPEERR, "CacheStorage.open() failed to access the storage system.")
|
||||||
|
MSG_DEF(MSG_NO_NEGATIVE_ATTR, 1, JSEXN_TYPEERR, "Given attribute {0} cannot be negative.")
|
||||||
|
MSG_DEF(MSG_PMO_NO_SEPARATE_ENDMARK, 0, JSEXN_TYPEERR, "Cannot provide separate endMark argument if PerformanceMeasureOptions argument is given.")
|
||||||
|
MSG_DEF(MSG_PMO_MISSING_STARTENDMARK, 0, JSEXN_TYPEERR, "PerformanceMeasureOptions must have start and/or end member.")
|
||||||
|
MSG_DEF(MSG_PMO_INVALID_MEMBERS, 0, JSEXN_TYPEERR, "PerformanceMeasureOptions cannot have all of the following members: start, duration, and end.")
|
||||||
|
MSG_DEF(MSG_PMO_CONSTRUCTOR_INACCESSIBLE, 0, JSEXN_TYPEERR, "Can't access PerformanceMark constructor, performance is null.")
|
||||||
|
MSG_DEF(MSG_PMO_UNEXPECTED_START_TIME, 0, JSEXN_TYPEERR, "Expected startTime >= 0.")
|
||||||
|
MSG_DEF(MSG_PMO_INVALID_ATTR_FOR_NON_GLOBAL, 1, JSEXN_TYPEERR, "Cannot get PerformanceTiming attribute values for non-Window global object. Given: {0}.")
|
||||||
|
|
|
||||||
|
|
@ -195,6 +195,7 @@ CreateException(JSContext* aCx, nsresult aRv, const nsACString& aMessage)
|
||||||
case NS_ERROR_MODULE_DOM_ANIM:
|
case NS_ERROR_MODULE_DOM_ANIM:
|
||||||
case NS_ERROR_MODULE_DOM_PUSH:
|
case NS_ERROR_MODULE_DOM_PUSH:
|
||||||
case NS_ERROR_MODULE_DOM_MEDIA:
|
case NS_ERROR_MODULE_DOM_MEDIA:
|
||||||
|
case NS_ERROR_MODULE_DOM_USER_TIMING:
|
||||||
if (aMessage.IsEmpty()) {
|
if (aMessage.IsEmpty()) {
|
||||||
return DOMException::Create(aRv);
|
return DOMException::Create(aRv);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,13 @@
|
||||||
#include "mozilla/dom/PerformanceNavigationBinding.h"
|
#include "mozilla/dom/PerformanceNavigationBinding.h"
|
||||||
#include "mozilla/dom/PerformanceObserverBinding.h"
|
#include "mozilla/dom/PerformanceObserverBinding.h"
|
||||||
#include "mozilla/dom/PerformanceNavigationTiming.h"
|
#include "mozilla/dom/PerformanceNavigationTiming.h"
|
||||||
|
#include "mozilla/dom/MessagePortBinding.h"
|
||||||
#include "mozilla/IntegerPrintfMacros.h"
|
#include "mozilla/IntegerPrintfMacros.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/TimerClamping.h"
|
#include "mozilla/TimerClamping.h"
|
||||||
#include "WorkerPrivate.h"
|
#include "WorkerPrivate.h"
|
||||||
#include "WorkerRunnable.h"
|
#include "WorkerRunnable.h"
|
||||||
|
#include "WorkerScope.h"
|
||||||
|
|
||||||
#define PERFLOG(msg, ...) printf_stderr(msg, ##__VA_ARGS__)
|
#define PERFLOG(msg, ...) printf_stderr(msg, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
|
@ -65,6 +67,12 @@ private:
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
enum class Performance::ResolveTimestampAttribute {
|
||||||
|
Start,
|
||||||
|
End,
|
||||||
|
Duration,
|
||||||
|
};
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Performance)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Performance)
|
||||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||||
|
|
||||||
|
|
@ -98,6 +106,27 @@ Performance::CreateForWorker(workers::WorkerPrivate* aWorkerPrivate)
|
||||||
return performance.forget();
|
return performance.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
already_AddRefed<Performance> Performance::Get(JSContext* aCx,
|
||||||
|
nsIGlobalObject* aGlobal) {
|
||||||
|
RefPtr<Performance> performance;
|
||||||
|
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
|
||||||
|
if (window) {
|
||||||
|
performance = window->GetPerformance();
|
||||||
|
} else {
|
||||||
|
const WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||||
|
if (!workerPrivate) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkerGlobalScope* scope = workerPrivate->GlobalScope();
|
||||||
|
MOZ_ASSERT(scope);
|
||||||
|
performance = scope->GetPerformance();
|
||||||
|
}
|
||||||
|
|
||||||
|
return performance.forget();
|
||||||
|
}
|
||||||
|
|
||||||
Performance::Performance()
|
Performance::Performance()
|
||||||
: mResourceTimingBufferSize(kDefaultResourceTimingBufferSize)
|
: mResourceTimingBufferSize(kDefaultResourceTimingBufferSize)
|
||||||
, mPendingNotificationObserversTask(false)
|
, mPendingNotificationObserversTask(false)
|
||||||
|
|
@ -227,27 +256,42 @@ Performance::RoundTime(double aTime) const
|
||||||
return floor(aTime / maxResolutionMs) * maxResolutionMs;
|
return floor(aTime / maxResolutionMs) * maxResolutionMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<PerformanceMark> Performance::Mark(
|
||||||
void
|
JSContext* aCx,
|
||||||
Performance::Mark(const nsAString& aName, ErrorResult& aRv)
|
const nsAString& aName,
|
||||||
|
const PerformanceMarkOptions& aMarkOptions,
|
||||||
|
ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
// Don't add the entry if the buffer is full. XXX should be removed by bug 1159003.
|
// Don't add the entry if the buffer is full. XXX should be removed by bug 1159003.
|
||||||
if (mUserEntries.Length() >= mResourceTimingBufferSize) {
|
if (mUserEntries.Length() >= mResourceTimingBufferSize) {
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsPerformanceTimingAttribute(aName)) {
|
nsCOMPtr<nsIGlobalObject> parent = GetParentObject();
|
||||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
if (!parent || parent->IsDying() || !parent->GetGlobalJSObject()) {
|
||||||
return;
|
aRv.Throw(NS_ERROR_DOM_UT_UNAVAILABLE_GLOBAL_OBJECT);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalObject global(aCx, parent->GetGlobalJSObject());
|
||||||
|
if (global.Failed()) {
|
||||||
|
aRv.Throw(NS_ERROR_DOM_UT_UNAVAILABLE_GLOBAL_OBJECT);
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<PerformanceMark> performanceMark =
|
RefPtr<PerformanceMark> performanceMark =
|
||||||
new PerformanceMark(GetAsISupports(), aName, Now());
|
PerformanceMark::Constructor(global, aName, aMarkOptions, aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
InsertUserEntry(performanceMark);
|
InsertUserEntry(performanceMark);
|
||||||
|
|
||||||
if (profiler_is_active()) {
|
if (profiler_is_active()) {
|
||||||
PROFILER_MARKER(NS_ConvertUTF16toUTF8(aName).get());
|
PROFILER_MARKER(NS_ConvertUTF16toUTF8(aName).get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return performanceMark.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -256,12 +300,37 @@ Performance::ClearMarks(const Optional<nsAString>& aName)
|
||||||
ClearUserEntries(aName, NS_LITERAL_STRING("mark"));
|
ClearUserEntries(aName, NS_LITERAL_STRING("mark"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To be removed once bug 1124165 lands
|
||||||
|
bool
|
||||||
|
Performance::IsPerformanceTimingAttribute(const nsAString& aName) const
|
||||||
|
{
|
||||||
|
// Note that toJSON is added to this list due to bug 1047848
|
||||||
|
static const char* attributes[] =
|
||||||
|
{"navigationStart", "unloadEventStart", "unloadEventEnd", "redirectStart",
|
||||||
|
"redirectEnd", "fetchStart", "domainLookupStart", "domainLookupEnd",
|
||||||
|
"connectStart", "secureConnectionStart", "connectEnd", "requestStart", "responseStart",
|
||||||
|
"responseEnd", "domLoading", "domInteractive",
|
||||||
|
"domContentLoadedEventStart", "domContentLoadedEventEnd", "domComplete",
|
||||||
|
"loadEventStart", "loadEventEnd", nullptr};
|
||||||
|
|
||||||
|
for (uint32_t i = 0; attributes[i]; ++i) {
|
||||||
|
if (aName.EqualsASCII(attributes[i])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
Performance::ResolveTimestampFromName(const nsAString& aName,
|
Performance::ConvertMarkToTimestampWithString(const nsAString& aName,
|
||||||
ErrorResult& aRv)
|
ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
|
if (IsPerformanceTimingAttribute(aName)) {
|
||||||
|
return ConvertNameToTimestamp(aName, aRv);
|
||||||
|
}
|
||||||
|
|
||||||
AutoTArray<RefPtr<PerformanceEntry>, 1> arr;
|
AutoTArray<RefPtr<PerformanceEntry>, 1> arr;
|
||||||
DOMHighResTimeStamp ts;
|
|
||||||
Optional<nsAString> typeParam;
|
Optional<nsAString> typeParam;
|
||||||
nsAutoString str;
|
nsAutoString str;
|
||||||
str.AssignLiteral("mark");
|
str.AssignLiteral("mark");
|
||||||
|
|
@ -271,64 +340,223 @@ Performance::ResolveTimestampFromName(const nsAString& aName,
|
||||||
return arr.LastElement()->StartTime();
|
return arr.LastElement()->StartTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsPerformanceTimingAttribute(aName)) {
|
aRv.Throw(NS_ERROR_DOM_UT_UNKNOWN_MARK_NAME);
|
||||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ts = GetPerformanceTimingFromString(aName);
|
DOMHighResTimeStamp
|
||||||
if (!ts) {
|
Performance::ConvertMarkToTimestampWithDOMHighResTimeStamp(
|
||||||
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
const ResolveTimestampAttribute aAttribute,
|
||||||
|
const DOMHighResTimeStamp aTimestamp,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
if (aTimestamp < 0) {
|
||||||
|
nsAutoString attributeName;
|
||||||
|
switch (aAttribute) {
|
||||||
|
case ResolveTimestampAttribute::Start:
|
||||||
|
attributeName = NS_LITERAL_STRING("start");
|
||||||
|
break;
|
||||||
|
case ResolveTimestampAttribute::End:
|
||||||
|
attributeName = NS_LITERAL_STRING("end");
|
||||||
|
break;
|
||||||
|
case ResolveTimestampAttribute::Duration:
|
||||||
|
attributeName = NS_LITERAL_STRING("duration");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
aRv.ThrowTypeError<MSG_NO_NEGATIVE_ATTR>(attributeName);
|
||||||
|
}
|
||||||
|
return aTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMHighResTimeStamp
|
||||||
|
Performance::ConvertMarkToTimestamp(
|
||||||
|
const ResolveTimestampAttribute aAttribute,
|
||||||
|
const OwningStringOrDouble& aMarkNameOrTimestamp,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
if (aMarkNameOrTimestamp.IsString()) {
|
||||||
|
return ConvertMarkToTimestampWithString(aMarkNameOrTimestamp.GetAsString(),
|
||||||
|
aRv);
|
||||||
|
}
|
||||||
|
return ConvertMarkToTimestampWithDOMHighResTimeStamp(
|
||||||
|
aAttribute, aMarkNameOrTimestamp.GetAsDouble(), aRv);
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMHighResTimeStamp Performance::ConvertNameToTimestamp(const nsAString& aName,
|
||||||
|
ErrorResult& aRv) {
|
||||||
|
if (!IsGlobalObjectWindow()) {
|
||||||
|
aRv.ThrowTypeError<MSG_PMO_INVALID_ATTR_FOR_NON_GLOBAL>(aName);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ts - CreationTime();
|
if (aName.EqualsASCII("navigationStart")) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
// We use GetPerformanceTimingFromString, rather than calling the
|
||||||
Performance::Measure(const nsAString& aName,
|
// navigationStart method timing function directly, because the former handles
|
||||||
const Optional<nsAString>& aStartMark,
|
// reducing precision against timing attacks.
|
||||||
|
const DOMHighResTimeStamp startTime =
|
||||||
|
GetPerformanceTimingFromString(NS_LITERAL_STRING("navigationStart"));
|
||||||
|
const DOMHighResTimeStamp endTime =
|
||||||
|
GetPerformanceTimingFromString(aName);
|
||||||
|
MOZ_ASSERT(endTime >= 0);
|
||||||
|
if (endTime == 0) {
|
||||||
|
aRv.Throw(NS_ERROR_DOM_UT_UNAVAILABLE_ATTR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return endTime - startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMHighResTimeStamp
|
||||||
|
Performance::ResolveEndTimeForMeasure(
|
||||||
|
const Optional<nsAString>& aEndMark,
|
||||||
|
const PerformanceMeasureOptions* aOptions,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
DOMHighResTimeStamp endTime;
|
||||||
|
if (aEndMark.WasPassed()) {
|
||||||
|
endTime = ConvertMarkToTimestampWithString(aEndMark.Value(), aRv);
|
||||||
|
} else if (aOptions != nullptr && aOptions->mEnd.WasPassed()) {
|
||||||
|
endTime = ConvertMarkToTimestamp(ResolveTimestampAttribute::End,
|
||||||
|
aOptions->mEnd.Value(), aRv);
|
||||||
|
} else if (aOptions != nullptr && aOptions->mStart.WasPassed() &&
|
||||||
|
aOptions->mDuration.WasPassed()) {
|
||||||
|
const DOMHighResTimeStamp start = ConvertMarkToTimestamp(
|
||||||
|
ResolveTimestampAttribute::Start, aOptions->mStart.Value(), aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const DOMHighResTimeStamp duration =
|
||||||
|
ConvertMarkToTimestampWithDOMHighResTimeStamp(
|
||||||
|
ResolveTimestampAttribute::Duration,
|
||||||
|
aOptions->mDuration.Value(),
|
||||||
|
aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
endTime = start + duration;
|
||||||
|
} else {
|
||||||
|
endTime = Now();
|
||||||
|
}
|
||||||
|
return endTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMHighResTimeStamp
|
||||||
|
Performance::ResolveStartTimeForMeasure(
|
||||||
|
const nsAString* aStartMark,
|
||||||
|
const PerformanceMeasureOptions* aOptions,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
DOMHighResTimeStamp startTime;
|
||||||
|
if (aOptions != nullptr && aOptions->mStart.WasPassed()) {
|
||||||
|
startTime = ConvertMarkToTimestamp(ResolveTimestampAttribute::Start,
|
||||||
|
aOptions->mStart.Value(),
|
||||||
|
aRv);
|
||||||
|
} else if (aOptions != nullptr && aOptions->mDuration.WasPassed() &&
|
||||||
|
aOptions->mEnd.WasPassed()) {
|
||||||
|
const DOMHighResTimeStamp duration =
|
||||||
|
ConvertMarkToTimestampWithDOMHighResTimeStamp(
|
||||||
|
ResolveTimestampAttribute::Duration,
|
||||||
|
aOptions->mDuration.Value(),
|
||||||
|
aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DOMHighResTimeStamp end = ConvertMarkToTimestamp(
|
||||||
|
ResolveTimestampAttribute::End, aOptions->mEnd.Value(), aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
startTime = end - duration;
|
||||||
|
} else if (aStartMark != nullptr) {
|
||||||
|
startTime = ConvertMarkToTimestampWithString(*aStartMark, aRv);
|
||||||
|
} else {
|
||||||
|
startTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<PerformanceMeasure>
|
||||||
|
Performance::Measure(JSContext* aCx,
|
||||||
|
const nsAString& aName,
|
||||||
|
const StringOrPerformanceMeasureOptions& aStartOrMeasureOptions,
|
||||||
const Optional<nsAString>& aEndMark,
|
const Optional<nsAString>& aEndMark,
|
||||||
ErrorResult& aRv)
|
ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
// Don't add the entry if the buffer is full. XXX should be removed by bug
|
// Don't add the entry if the buffer is full. XXX should be removed by bug
|
||||||
// 1159003.
|
// 1159003.
|
||||||
if (mUserEntries.Length() >= mResourceTimingBufferSize) {
|
if (mUserEntries.Length() >= mResourceTimingBufferSize) {
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DOMHighResTimeStamp startTime;
|
const PerformanceMeasureOptions* options = nullptr;
|
||||||
DOMHighResTimeStamp endTime;
|
if (aStartOrMeasureOptions.IsPerformanceMeasureOptions()) {
|
||||||
|
options = &aStartOrMeasureOptions.GetAsPerformanceMeasureOptions();
|
||||||
if (IsPerformanceTimingAttribute(aName)) {
|
|
||||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aStartMark.WasPassed()) {
|
|
||||||
startTime = ResolveTimestampFromName(aStartMark.Value(), aRv);
|
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Navigation start is used in this case, but since DOMHighResTimeStamp is
|
|
||||||
// in relation to navigation start, this will be zero if a name is not
|
|
||||||
// passed.
|
|
||||||
startTime = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool isOptionsNotEmpty =
|
||||||
|
(options != nullptr) &&
|
||||||
|
(!options->mDetail.isUndefined() || options->mStart.WasPassed() ||
|
||||||
|
options->mEnd.WasPassed() || options->mDuration.WasPassed());
|
||||||
|
if (isOptionsNotEmpty) {
|
||||||
if (aEndMark.WasPassed()) {
|
if (aEndMark.WasPassed()) {
|
||||||
endTime = ResolveTimestampFromName(aEndMark.Value(), aRv);
|
aRv.ThrowTypeError<MSG_PMO_NO_SEPARATE_ENDMARK>();
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
return nullptr;
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
endTime = Now();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<PerformanceMeasure> performanceMeasure =
|
if (!options->mStart.WasPassed() && !options->mEnd.WasPassed()) {
|
||||||
new PerformanceMeasure(GetAsISupports(), aName, startTime, endTime);
|
aRv.ThrowTypeError<MSG_PMO_MISSING_STARTENDMARK>();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options->mStart.WasPassed() && options->mDuration.WasPassed() &&
|
||||||
|
options->mEnd.WasPassed()) {
|
||||||
|
aRv.ThrowTypeError<MSG_PMO_INVALID_MEMBERS>();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DOMHighResTimeStamp endTime =
|
||||||
|
ResolveEndTimeForMeasure(aEndMark, options, aRv);
|
||||||
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nsAString* startMark = nullptr;
|
||||||
|
if (aStartOrMeasureOptions.IsString()) {
|
||||||
|
startMark = &aStartOrMeasureOptions.GetAsString();
|
||||||
|
}
|
||||||
|
const DOMHighResTimeStamp startTime =
|
||||||
|
ResolveStartTimeForMeasure(startMark, options, aRv);
|
||||||
|
if (NS_WARN_IF(aRv.Failed())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JS::Value> detail(aCx);
|
||||||
|
if (options != nullptr && !options->mDetail.isNullOrUndefined()) {
|
||||||
|
StructuredSerializeOptions serializeOptions;
|
||||||
|
JS::Rooted<JS::Value> valueToClone(aCx, options->mDetail);
|
||||||
|
nsContentUtils::StructuredClone(aCx, GetParentObject(), valueToClone,
|
||||||
|
serializeOptions, &detail, aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
detail.setNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<PerformanceMeasure> performanceMeasure = new PerformanceMeasure(
|
||||||
|
GetAsISupports(), aName, startTime, endTime, detail);
|
||||||
InsertUserEntry(performanceMeasure);
|
InsertUserEntry(performanceMeasure);
|
||||||
|
|
||||||
|
return performanceMeasure.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,18 @@ class ErrorResult;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
|
class OwningStringOrDouble;
|
||||||
|
class StringOrPerformanceMeasureOptions;
|
||||||
class PerformanceEntry;
|
class PerformanceEntry;
|
||||||
|
class PerformanceMark;
|
||||||
|
struct PerformanceMarkOptions;
|
||||||
|
struct PerformanceMeasureOptions;
|
||||||
|
class PerformanceMeasure;
|
||||||
class PerformanceNavigation;
|
class PerformanceNavigation;
|
||||||
class PerformanceObserver;
|
class PerformanceObserver;
|
||||||
class PerformanceService;
|
class PerformanceService;
|
||||||
class PerformanceTiming;
|
class PerformanceTiming;
|
||||||
|
struct StructuredSerializeOptions;
|
||||||
|
|
||||||
namespace workers {
|
namespace workers {
|
||||||
class WorkerPrivate;
|
class WorkerPrivate;
|
||||||
|
|
@ -50,6 +57,10 @@ public:
|
||||||
static already_AddRefed<Performance>
|
static already_AddRefed<Performance>
|
||||||
CreateForWorker(workers::WorkerPrivate* aWorkerPrivate);
|
CreateForWorker(workers::WorkerPrivate* aWorkerPrivate);
|
||||||
|
|
||||||
|
// This will return nullptr if called outside of a Window or Worker.
|
||||||
|
static already_AddRefed<Performance> Get(JSContext* aCx,
|
||||||
|
nsIGlobalObject* aGlobal);
|
||||||
|
|
||||||
JSObject* WrapObject(JSContext *cx,
|
JSObject* WrapObject(JSContext *cx,
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
|
|
@ -71,14 +82,16 @@ public:
|
||||||
|
|
||||||
DOMHighResTimeStamp TimeOrigin();
|
DOMHighResTimeStamp TimeOrigin();
|
||||||
|
|
||||||
void Mark(const nsAString& aName, ErrorResult& aRv);
|
already_AddRefed<PerformanceMark> Mark(
|
||||||
|
JSContext* aCx, const nsAString& aName,
|
||||||
|
const PerformanceMarkOptions& aMarkOptions, ErrorResult& aRv);
|
||||||
|
|
||||||
void ClearMarks(const Optional<nsAString>& aName);
|
void ClearMarks(const Optional<nsAString>& aName);
|
||||||
|
|
||||||
void Measure(const nsAString& aName,
|
already_AddRefed<PerformanceMeasure> Measure(
|
||||||
const Optional<nsAString>& aStartMark,
|
JSContext* aCx, const nsAString& aName,
|
||||||
const Optional<nsAString>& aEndMark,
|
const StringOrPerformanceMeasureOptions& aStartOrMeasureOptions,
|
||||||
ErrorResult& aRv);
|
const Optional<nsAString>& aEndMark, ErrorResult& aRv);
|
||||||
|
|
||||||
void ClearMeasures(const Optional<nsAString>& aName);
|
void ClearMeasures(const Optional<nsAString>& aName);
|
||||||
|
|
||||||
|
|
@ -104,6 +117,13 @@ public:
|
||||||
|
|
||||||
virtual nsITimedChannel* GetChannel() const = 0;
|
virtual nsITimedChannel* GetChannel() const = 0;
|
||||||
|
|
||||||
|
bool IsPerformanceTimingAttribute(const nsAString& aName) const;
|
||||||
|
|
||||||
|
virtual bool IsGlobalObjectWindow() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Performance();
|
Performance();
|
||||||
explicit Performance(nsPIDOMWindowInner* aWindow);
|
explicit Performance(nsPIDOMWindowInner* aWindow);
|
||||||
|
|
@ -116,9 +136,6 @@ protected:
|
||||||
void ClearUserEntries(const Optional<nsAString>& aEntryName,
|
void ClearUserEntries(const Optional<nsAString>& aEntryName,
|
||||||
const nsAString& aEntryType);
|
const nsAString& aEntryType);
|
||||||
|
|
||||||
DOMHighResTimeStamp ResolveTimestampFromName(const nsAString& aName,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
virtual nsISupports* GetAsISupports() = 0;
|
virtual nsISupports* GetAsISupports() = 0;
|
||||||
|
|
||||||
virtual void DispatchBufferFullEvent() = 0;
|
virtual void DispatchBufferFullEvent() = 0;
|
||||||
|
|
@ -127,11 +144,6 @@ protected:
|
||||||
|
|
||||||
virtual DOMHighResTimeStamp CreationTime() const = 0;
|
virtual DOMHighResTimeStamp CreationTime() const = 0;
|
||||||
|
|
||||||
virtual bool IsPerformanceTimingAttribute(const nsAString& aName)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual DOMHighResTimeStamp
|
virtual DOMHighResTimeStamp
|
||||||
GetPerformanceTimingFromString(const nsAString& aTimingName)
|
GetPerformanceTimingFromString(const nsAString& aTimingName)
|
||||||
{
|
{
|
||||||
|
|
@ -159,10 +171,36 @@ protected:
|
||||||
nsTArray<RefPtr<PerformanceEntry>> mResourceEntries;
|
nsTArray<RefPtr<PerformanceEntry>> mResourceEntries;
|
||||||
|
|
||||||
uint64_t mResourceTimingBufferSize;
|
uint64_t mResourceTimingBufferSize;
|
||||||
static const uint64_t kDefaultResourceTimingBufferSize = 150;
|
static const uint64_t kDefaultResourceTimingBufferSize = 1500;
|
||||||
bool mPendingNotificationObserversTask;
|
bool mPendingNotificationObserversTask;
|
||||||
|
|
||||||
RefPtr<PerformanceService> mPerformanceService;
|
RefPtr<PerformanceService> mPerformanceService;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The attributes of a PerformanceMeasureOptions that we call
|
||||||
|
// ResolveTimestamp* on.
|
||||||
|
enum class ResolveTimestampAttribute;
|
||||||
|
|
||||||
|
DOMHighResTimeStamp ConvertMarkToTimestampWithString(const nsAString& aName,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
DOMHighResTimeStamp ConvertMarkToTimestampWithDOMHighResTimeStamp(
|
||||||
|
const ResolveTimestampAttribute aAttribute, const double aTimestamp,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
DOMHighResTimeStamp ConvertMarkToTimestamp(
|
||||||
|
const ResolveTimestampAttribute aAttribute,
|
||||||
|
const OwningStringOrDouble& aMarkNameOrTimestamp, ErrorResult& aRv);
|
||||||
|
|
||||||
|
DOMHighResTimeStamp ConvertNameToTimestamp(const nsAString& aName,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
|
||||||
|
DOMHighResTimeStamp ResolveEndTimeForMeasure(
|
||||||
|
const Optional<nsAString>& aEndMark,
|
||||||
|
const PerformanceMeasureOptions* aOptions,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
DOMHighResTimeStamp ResolveStartTimeForMeasure(
|
||||||
|
const nsAString* aStartMark,
|
||||||
|
const PerformanceMeasureOptions* aOptions,
|
||||||
|
ErrorResult& aRv);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
||||||
|
|
@ -177,28 +177,6 @@ PerformanceMainThread::AddEntry(nsIHttpChannel* channel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// To be removed once bug 1124165 lands
|
|
||||||
bool
|
|
||||||
PerformanceMainThread::IsPerformanceTimingAttribute(const nsAString& aName)
|
|
||||||
{
|
|
||||||
// Note that toJSON is added to this list due to bug 1047848
|
|
||||||
static const char* attributes[] =
|
|
||||||
{"navigationStart", "unloadEventStart", "unloadEventEnd", "redirectStart",
|
|
||||||
"redirectEnd", "fetchStart", "domainLookupStart", "domainLookupEnd",
|
|
||||||
"connectStart", "secureConnectionStart", "connectEnd", "requestStart", "responseStart",
|
|
||||||
"responseEnd", "domLoading", "domInteractive",
|
|
||||||
"domContentLoadedEventStart", "domContentLoadedEventEnd", "domComplete",
|
|
||||||
"loadEventStart", "loadEventEnd", nullptr};
|
|
||||||
|
|
||||||
for (uint32_t i = 0; attributes[i]; ++i) {
|
|
||||||
if (aName.EqualsASCII(attributes[i])) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
PerformanceMainThread::GetPerformanceTimingFromString(const nsAString& aProperty)
|
PerformanceMainThread::GetPerformanceTimingFromString(const nsAString& aProperty)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,11 @@ public:
|
||||||
const Optional<nsAString>& aEntryType,
|
const Optional<nsAString>& aEntryType,
|
||||||
nsTArray<RefPtr<PerformanceEntry>>& aRetval) override;
|
nsTArray<RefPtr<PerformanceEntry>>& aRetval) override;
|
||||||
|
|
||||||
|
bool IsGlobalObjectWindow() const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~PerformanceMainThread();
|
~PerformanceMainThread();
|
||||||
|
|
||||||
|
|
@ -67,8 +72,6 @@ protected:
|
||||||
|
|
||||||
void InsertUserEntry(PerformanceEntry* aEntry) override;
|
void InsertUserEntry(PerformanceEntry* aEntry) override;
|
||||||
|
|
||||||
bool IsPerformanceTimingAttribute(const nsAString& aName) override;
|
|
||||||
|
|
||||||
DOMHighResTimeStamp
|
DOMHighResTimeStamp
|
||||||
GetPerformanceTimingFromString(const nsAString& aTimingName) override;
|
GetPerformanceTimingFromString(const nsAString& aTimingName) override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,25 +6,119 @@
|
||||||
#include "PerformanceMark.h"
|
#include "PerformanceMark.h"
|
||||||
#include "MainThreadUtils.h"
|
#include "MainThreadUtils.h"
|
||||||
#include "mozilla/dom/PerformanceMarkBinding.h"
|
#include "mozilla/dom/PerformanceMarkBinding.h"
|
||||||
|
#include "mozilla/dom/MessagePortBinding.h"
|
||||||
|
|
||||||
|
using mozilla::dom::StructuredSerializeOptions;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
PerformanceMark::PerformanceMark(nsISupports* aParent,
|
PerformanceMark::PerformanceMark(nsISupports* aParent,
|
||||||
const nsAString& aName,
|
const nsAString& aName,
|
||||||
DOMHighResTimeStamp aStartTime)
|
DOMHighResTimeStamp aStartTime,
|
||||||
|
const JS::Handle<JS::Value>& aDetail)
|
||||||
: PerformanceEntry(aParent, aName, NS_LITERAL_STRING("mark"))
|
: PerformanceEntry(aParent, aName, NS_LITERAL_STRING("mark"))
|
||||||
, mStartTime(aStartTime)
|
, mStartTime(aStartTime)
|
||||||
|
, mDetail(aDetail)
|
||||||
{
|
{
|
||||||
// mParent is null in workers.
|
// mParent is null in workers.
|
||||||
MOZ_ASSERT(mParent || !NS_IsMainThread());
|
MOZ_ASSERT(mParent || !NS_IsMainThread());
|
||||||
|
mozilla::HoldJSObjects(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
already_AddRefed<PerformanceMark> PerformanceMark::Constructor(
|
||||||
|
const GlobalObject& aGlobal,
|
||||||
|
const nsAString& aMarkName,
|
||||||
|
const PerformanceMarkOptions& aMarkOptions,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
const nsCOMPtr<nsIGlobalObject> global =
|
||||||
|
do_QueryInterface(aGlobal.GetAsSupports());
|
||||||
|
return PerformanceMark::Constructor(aGlobal.Context(), global, aMarkName,
|
||||||
|
aMarkOptions, aRv);
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<PerformanceMark> PerformanceMark::Constructor(
|
||||||
|
JSContext* aCx,
|
||||||
|
nsIGlobalObject* aGlobal,
|
||||||
|
const nsAString& aMarkName,
|
||||||
|
const PerformanceMarkOptions& aMarkOptions,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
RefPtr<Performance> performance = Performance::Get(aCx, aGlobal);
|
||||||
|
if (!performance) {
|
||||||
|
// This is similar to the message that occurs when accessing `performance`
|
||||||
|
// from outside a valid global.
|
||||||
|
aRv.ThrowTypeError<MSG_PMO_CONSTRUCTOR_INACCESSIBLE>();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (performance->IsGlobalObjectWindow() &&
|
||||||
|
performance->IsPerformanceTimingAttribute(aMarkName)) {
|
||||||
|
aRv.Throw(NS_ERROR_DOM_UT_INVALID_TIMING_ATTR);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMHighResTimeStamp startTime = aMarkOptions.mStartTime.WasPassed() ?
|
||||||
|
aMarkOptions.mStartTime.Value() :
|
||||||
|
performance->Now();
|
||||||
|
if (startTime < 0) {
|
||||||
|
aRv.ThrowTypeError<MSG_PMO_UNEXPECTED_START_TIME>();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JS::Value> detail(aCx);
|
||||||
|
if (aMarkOptions.mDetail.isNullOrUndefined()) {
|
||||||
|
detail.setNull();
|
||||||
|
} else {
|
||||||
|
StructuredSerializeOptions serializeOptions;
|
||||||
|
JS::Rooted<JS::Value> valueToClone(aCx, aMarkOptions.mDetail);
|
||||||
|
nsContentUtils::StructuredClone(aCx, aGlobal, valueToClone,
|
||||||
|
serializeOptions, &detail, aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return do_AddRef(new PerformanceMark(aGlobal, aMarkName, startTime, detail));
|
||||||
}
|
}
|
||||||
|
|
||||||
PerformanceMark::~PerformanceMark()
|
PerformanceMark::~PerformanceMark()
|
||||||
{
|
{
|
||||||
|
mozilla::DropJSObjects(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CLASS(PerformanceMark)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PerformanceMark,
|
||||||
|
PerformanceEntry)
|
||||||
|
tmp->mDetail.setUndefined();
|
||||||
|
mozilla::DropJSObjects(tmp);
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PerformanceMark,
|
||||||
|
PerformanceEntry)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceMark,
|
||||||
|
PerformanceEntry)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDetail)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceMark)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(PerformanceEntry)
|
||||||
|
NS_IMPL_ADDREF_INHERITED(PerformanceMark, PerformanceEntry)
|
||||||
|
NS_IMPL_RELEASE_INHERITED(PerformanceMark, PerformanceEntry)
|
||||||
|
|
||||||
JSObject*
|
JSObject*
|
||||||
PerformanceMark::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
PerformanceMark::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||||
{
|
{
|
||||||
return PerformanceMarkBinding::Wrap(aCx, this, aGivenProto);
|
return PerformanceMarkBinding::Wrap(aCx, this, aGivenProto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PerformanceMark::GetDetail(JSContext* aCx,
|
||||||
|
JS::MutableHandle<JS::Value> aRv)
|
||||||
|
{
|
||||||
|
// Return a copy so that this method always returns the value it is set to
|
||||||
|
// (i.e. it'll return the same value even if the caller assigns to it). Note
|
||||||
|
// that if detail is an object, its contents can be mutated and this is
|
||||||
|
// expected.
|
||||||
|
aRv.set(mDetail);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,16 +11,40 @@
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
|
struct PerformanceMarkOptions;
|
||||||
|
|
||||||
// http://www.w3.org/TR/user-timing/#performancemark
|
// http://www.w3.org/TR/user-timing/#performancemark
|
||||||
class PerformanceMark final : public PerformanceEntry
|
class PerformanceMark final : public PerformanceEntry
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
PerformanceMark(nsISupports* aParent,
|
PerformanceMark(nsISupports* aParent,
|
||||||
const nsAString& aName,
|
const nsAString& aName,
|
||||||
DOMHighResTimeStamp aStartTime);
|
DOMHighResTimeStamp aStartTime,
|
||||||
|
const JS::Handle<JS::Value>& aDetail);
|
||||||
|
|
||||||
|
JS::Heap<JS::Value> mDetail;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PerformanceMark,
|
||||||
|
PerformanceEntry);
|
||||||
|
|
||||||
|
static already_AddRefed<PerformanceMark> Constructor(
|
||||||
|
const GlobalObject& aGlobal,
|
||||||
|
const nsAString& aMarkName,
|
||||||
|
const PerformanceMarkOptions& aMarkOptions,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
|
||||||
|
static already_AddRefed<PerformanceMark> Constructor(
|
||||||
|
JSContext* aCx, nsIGlobalObject* aGlobal,
|
||||||
|
const nsAString& aMarkName,
|
||||||
|
const PerformanceMarkOptions& aMarkOptions,
|
||||||
|
ErrorResult& aRv);
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
|
void GetDetail(JSContext* aCx, JS::MutableHandle<JS::Value> aRv);
|
||||||
|
|
||||||
virtual DOMHighResTimeStamp StartTime() const override
|
virtual DOMHighResTimeStamp StartTime() const override
|
||||||
{
|
{
|
||||||
return mStartTime;
|
return mStartTime;
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,12 @@ using namespace mozilla::dom;
|
||||||
PerformanceMeasure::PerformanceMeasure(nsISupports* aParent,
|
PerformanceMeasure::PerformanceMeasure(nsISupports* aParent,
|
||||||
const nsAString& aName,
|
const nsAString& aName,
|
||||||
DOMHighResTimeStamp aStartTime,
|
DOMHighResTimeStamp aStartTime,
|
||||||
DOMHighResTimeStamp aEndTime)
|
DOMHighResTimeStamp aEndTime,
|
||||||
: PerformanceEntry(aParent, aName, NS_LITERAL_STRING("measure")),
|
const JS::Handle<JS::Value>& aDetail)
|
||||||
mStartTime(aStartTime),
|
: PerformanceEntry(aParent, aName, NS_LITERAL_STRING("measure"))
|
||||||
mDuration(aEndTime - aStartTime)
|
, mStartTime(aStartTime)
|
||||||
|
, mDuration(aEndTime - aStartTime)
|
||||||
|
, mDetail(aDetail)
|
||||||
{
|
{
|
||||||
// mParent is null in workers.
|
// mParent is null in workers.
|
||||||
MOZ_ASSERT(mParent || !NS_IsMainThread());
|
MOZ_ASSERT(mParent || !NS_IsMainThread());
|
||||||
|
|
@ -23,10 +25,43 @@ PerformanceMeasure::PerformanceMeasure(nsISupports* aParent,
|
||||||
|
|
||||||
PerformanceMeasure::~PerformanceMeasure()
|
PerformanceMeasure::~PerformanceMeasure()
|
||||||
{
|
{
|
||||||
|
mozilla::DropJSObjects(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CLASS(PerformanceMeasure)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PerformanceMeasure,
|
||||||
|
PerformanceEntry)
|
||||||
|
tmp->mDetail.setUndefined();
|
||||||
|
mozilla::DropJSObjects(tmp);
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PerformanceMeasure,
|
||||||
|
PerformanceEntry)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceMeasure,
|
||||||
|
PerformanceEntry)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDetail)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PerformanceMeasure)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(PerformanceEntry)
|
||||||
|
NS_IMPL_ADDREF_INHERITED(PerformanceMeasure, PerformanceEntry)
|
||||||
|
NS_IMPL_RELEASE_INHERITED(PerformanceMeasure, PerformanceEntry)
|
||||||
|
|
||||||
JSObject*
|
JSObject*
|
||||||
PerformanceMeasure::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
PerformanceMeasure::WrapObject(JSContext* aCx,
|
||||||
|
JS::Handle<JSObject*> aGivenProto)
|
||||||
{
|
{
|
||||||
return PerformanceMeasureBinding::Wrap(aCx, this, aGivenProto);
|
return PerformanceMeasureBinding::Wrap(aCx, this, aGivenProto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PerformanceMeasure::GetDetail(JSContext* aCx,
|
||||||
|
JS::MutableHandle<JS::Value> aRv)
|
||||||
|
{
|
||||||
|
// Return a copy so that this method always returns the value it is set to
|
||||||
|
// (i.e. it'll return the same value even if the caller assigns to it). Note
|
||||||
|
// that if detail is an object, its contents can be mutated and this is
|
||||||
|
// expected.
|
||||||
|
aRv.set(mDetail);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,15 @@ namespace dom {
|
||||||
class PerformanceMeasure final : public PerformanceEntry
|
class PerformanceMeasure final : public PerformanceEntry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(PerformanceMeasure,
|
||||||
|
PerformanceEntry);
|
||||||
|
|
||||||
PerformanceMeasure(nsISupports* aParent,
|
PerformanceMeasure(nsISupports* aParent,
|
||||||
const nsAString& aName,
|
const nsAString& aName,
|
||||||
DOMHighResTimeStamp aStartTime,
|
DOMHighResTimeStamp aStartTime,
|
||||||
DOMHighResTimeStamp aEndTime);
|
DOMHighResTimeStamp aEndTime,
|
||||||
|
const JS::Handle<JS::Value>& aDetail);
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
|
|
@ -32,10 +37,15 @@ public:
|
||||||
return mDuration;
|
return mDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GetDetail(JSContext* aCx, JS::MutableHandle<JS::Value> aRv);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~PerformanceMeasure();
|
virtual ~PerformanceMeasure();
|
||||||
DOMHighResTimeStamp mStartTime;
|
DOMHighResTimeStamp mStartTime;
|
||||||
DOMHighResTimeStamp mDuration;
|
DOMHighResTimeStamp mDuration;
|
||||||
|
|
||||||
|
private:
|
||||||
|
JS::Heap<JS::Value> mDetail;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ typedef double DOMHighResTimeStamp;
|
||||||
typedef sequence <PerformanceEntry> PerformanceEntryList;
|
typedef sequence <PerformanceEntry> PerformanceEntryList;
|
||||||
|
|
||||||
[Exposed=(Window,Worker)]
|
[Exposed=(Window,Worker)]
|
||||||
interface Performance {
|
interface Performance : EventTarget {
|
||||||
[DependsOn=DeviceState, Affects=Nothing]
|
[DependsOn=DeviceState, Affects=Nothing]
|
||||||
DOMHighResTimeStamp now();
|
DOMHighResTimeStamp now();
|
||||||
|
|
||||||
|
|
@ -44,6 +44,14 @@ partial interface Performance {
|
||||||
entryType);
|
entryType);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// https://w3c.github.io/user-timing/#extensions-performance-interface
|
||||||
|
dictionary PerformanceMeasureOptions {
|
||||||
|
any detail;
|
||||||
|
(DOMString or DOMHighResTimeStamp) start;
|
||||||
|
DOMHighResTimeStamp duration;
|
||||||
|
(DOMString or DOMHighResTimeStamp)end;
|
||||||
|
};
|
||||||
|
|
||||||
// http://www.w3.org/TR/resource-timing/#extensions-performance-interface
|
// http://www.w3.org/TR/resource-timing/#extensions-performance-interface
|
||||||
[Exposed=Window]
|
[Exposed=Window]
|
||||||
partial interface Performance {
|
partial interface Performance {
|
||||||
|
|
@ -64,15 +72,23 @@ partial interface Performance {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// https://w3c.github.io/user-timing/#extensions-performance-interface
|
||||||
|
dictionary PerformanceMarkOptions {
|
||||||
|
any detail;
|
||||||
|
DOMHighResTimeStamp startTime;
|
||||||
|
};
|
||||||
|
|
||||||
// http://www.w3.org/TR/user-timing/
|
// http://www.w3.org/TR/user-timing/
|
||||||
[Exposed=(Window,Worker)]
|
[Exposed=(Window,Worker)]
|
||||||
partial interface Performance {
|
partial interface Performance {
|
||||||
[Func="Performance::IsEnabled", Throws]
|
[Func="Performance::IsEnabled", Throws]
|
||||||
void mark(DOMString markName);
|
PerformanceMark mark(DOMString markName, optional PerformanceMarkOptions markOptions);
|
||||||
[Func="Performance::IsEnabled"]
|
[Func="Performance::IsEnabled"]
|
||||||
void clearMarks(optional DOMString markName);
|
void clearMarks(optional DOMString markName);
|
||||||
[Func="Performance::IsEnabled", Throws]
|
[Func="Performance::IsEnabled", Throws]
|
||||||
void measure(DOMString measureName, optional DOMString startMark, optional DOMString endMark);
|
PerformanceMeasure measure(DOMString measureName,
|
||||||
|
optional (DOMString or PerformanceMeasureOptions) startOrMeasureOptions,
|
||||||
|
optional DOMString endMark);
|
||||||
[Func="Performance::IsEnabled"]
|
[Func="Performance::IsEnabled"]
|
||||||
void clearMeasures(optional DOMString measureName);
|
void clearMeasures(optional DOMString measureName);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
* http://www.w3.org/TR/user-timing/#performancemark
|
* http://www.w3.org/TR/user-timing/#performancemark
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[Exposed=(Window,Worker)]
|
[Exposed=(Window,Worker), Constructor(DOMString markName, optional PerformanceMarkOptions markOptions)]
|
||||||
interface PerformanceMark : PerformanceEntry
|
interface PerformanceMark : PerformanceEntry
|
||||||
{
|
{
|
||||||
|
readonly attribute any detail;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,5 @@
|
||||||
[Exposed=(Window,Worker)]
|
[Exposed=(Window,Worker)]
|
||||||
interface PerformanceMeasure : PerformanceEntry
|
interface PerformanceMeasure : PerformanceEntry
|
||||||
{
|
{
|
||||||
|
readonly attribute any detail;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ pref("dom.enable_resource_timing", true);
|
||||||
pref("dom.enable_user_timing", true);
|
pref("dom.enable_user_timing", true);
|
||||||
|
|
||||||
// Whether performance.GetEntries* will contain an entry for the active document
|
// Whether performance.GetEntries* will contain an entry for the active document
|
||||||
pref("dom.enable_performance_navigation_timing", false);
|
pref("dom.enable_performance_navigation_timing", true);
|
||||||
|
|
||||||
// Enable printing performance marks/measures to log
|
// Enable printing performance marks/measures to log
|
||||||
pref("dom.performance.enable_user_timing_logging", false);
|
pref("dom.performance.enable_user_timing_logging", false);
|
||||||
|
|
|
||||||
|
|
@ -990,6 +990,16 @@
|
||||||
ERROR(NS_ERROR_DOM_MEDIA_CUBEB_INITIALIZATION_ERR, FAILURE(101)),
|
ERROR(NS_ERROR_DOM_MEDIA_CUBEB_INITIALIZATION_ERR, FAILURE(101)),
|
||||||
#undef MODULE
|
#undef MODULE
|
||||||
|
|
||||||
|
/* ======================================================================= */
|
||||||
|
/* 42: NS_ERROR_MODULE_DOM_USER_TIMING */
|
||||||
|
/* ======================================================================= */
|
||||||
|
#define MODULE NS_ERROR_MODULE_DOM_USER_TIMING
|
||||||
|
ERROR(NS_ERROR_DOM_UT_UNKNOWN_MARK_NAME, FAILURE(1)),
|
||||||
|
ERROR(NS_ERROR_DOM_UT_INVALID_TIMING_ATTR, FAILURE(2)),
|
||||||
|
ERROR(NS_ERROR_DOM_UT_UNAVAILABLE_ATTR, FAILURE(3)),
|
||||||
|
ERROR(NS_ERROR_DOM_UT_UNAVAILABLE_GLOBAL_OBJECT, FAILURE(4)),
|
||||||
|
#undef MODULE
|
||||||
|
|
||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
/* 51: NS_ERROR_MODULE_GENERAL */
|
/* 51: NS_ERROR_MODULE_GENERAL */
|
||||||
/* ======================================================================= */
|
/* ======================================================================= */
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@
|
||||||
#define NS_ERROR_MODULE_DOM_ANIM 39
|
#define NS_ERROR_MODULE_DOM_ANIM 39
|
||||||
#define NS_ERROR_MODULE_DOM_PUSH 40
|
#define NS_ERROR_MODULE_DOM_PUSH 40
|
||||||
#define NS_ERROR_MODULE_DOM_MEDIA 41
|
#define NS_ERROR_MODULE_DOM_MEDIA 41
|
||||||
|
#define NS_ERROR_MODULE_DOM_USER_TIMING 42
|
||||||
|
|
||||||
/* NS_ERROR_MODULE_GENERAL should be used by modules that do not
|
/* NS_ERROR_MODULE_GENERAL should be used by modules that do not
|
||||||
* care if return code values overlap. Callers of methods that
|
* care if return code values overlap. Callers of methods that
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue