Title: [267402] trunk
Revision
267402
Author
wei...@apple.com
Date
2020-09-22 01:46:36 -0700 (Tue, 22 Sep 2020)

Log Message

Update User Timing interfaces to User Timing Level 3
https://bugs.webkit.org/show_bug.cgi?id=216787

Reviewed by Alex Christensen.
LayoutTests/imported/w3c:

Import missing case-sensitivity test case from upstream and update the results
of User Timing tests now that we support Level 3.

* web-platform-tests/user-timing/case-sensitivity.any-expected.txt: Added.
* web-platform-tests/user-timing/case-sensitivity.any.html: Added.
* web-platform-tests/user-timing/case-sensitivity.any.js: Added.
* web-platform-tests/user-timing/case-sensitivity.any.worker-expected.txt: Added.
* web-platform-tests/user-timing/case-sensitivity.any.worker.html: Added.
* web-platform-tests/user-timing/idlharness.any-expected.txt:
* web-platform-tests/user-timing/idlharness.any.worker-expected.txt:
* web-platform-tests/user-timing/mark-entry-constructor.any-expected.txt:
* web-platform-tests/user-timing/mark-entry-constructor.any.worker-expected.txt:
* web-platform-tests/user-timing/mark-errors.any-expected.txt:
* web-platform-tests/user-timing/mark-errors.any.worker-expected.txt:
* web-platform-tests/user-timing/mark-l3.any-expected.txt:
* web-platform-tests/user-timing/mark-l3.any.worker-expected.txt:
* web-platform-tests/user-timing/mark-measure-return-objects.any-expected.txt:
* web-platform-tests/user-timing/mark-measure-return-objects.any.worker-expected.txt:
* web-platform-tests/user-timing/measure-l3.any-expected.txt:
* web-platform-tests/user-timing/measure-l3.any.worker-expected.txt:
* web-platform-tests/user-timing/measure-with-dict.any-expected.txt:
* web-platform-tests/user-timing/measure-with-dict.any.worker-expected.txt:
* web-platform-tests/user-timing/measure_exception-expected.txt:
* web-platform-tests/user-timing/performance-measure-invalid.worker-expected.txt:
* web-platform-tests/user-timing/structured-serialize-detail.any-expected.txt:
* web-platform-tests/user-timing/structured-serialize-detail.any.worker-expected.txt:

Source/WebCore:

Adds support for User Timing Level 3 which adds more flexibility in how PerformanceMarks
and PerformanceMeasures are created via synthetic start/end times and associate 'details'
values serialized with events themselves.

Updates results to existing WPT and standalone tests.

* CMakeLists.txt:
* DerivedSources-input.xcfilelist:
* DerivedSources-output.xcfilelist:
* DerivedSources.make:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
Add new files.

* page/Performance.cpp:
(WebCore::Performance::mark):
(WebCore::Performance::clearMarks):
(WebCore::Performance::measure):
(WebCore::Performance::clearMeasures):
* page/Performance.h:
* page/Performance.idl:
Update for new signatures for mark and measure, and rename of UserTiming to PerformanceUserTiming.

* page/PerformanceMark.cpp: Added.
(WebCore::peformanceNow):
(WebCore::PerformanceMark::create):
(WebCore::PerformanceMark::PerformanceMark):
(WebCore::PerformanceMark::detail):
* page/PerformanceMark.h:
* page/PerformanceMark.idl:
Add support for PerformanceMark's constructor `detail` getter. While the spec says to
serialize and the deserialize in the constructor, we only serialize, and delay deserialization
until the first access, which is a non-observable difference. We also utilize [CachedAttribute]
to only ever deserialize once per wrapper world (and also greatly simplify the GC shenanigans).

* page/PerformanceMarkOptions.h: Added.
* page/PerformanceMarkOptions.idl: Added.
Import and bind PerformanceMarkOptions dictionary to a new struct.

* page/PerformanceMeasure.cpp: Added.
(WebCore::PerformanceMeasure::create):
(WebCore::PerformanceMeasure::PerformanceMeasure):
(WebCore::PerformanceMeasure::detail):
* page/PerformanceMeasure.h:
* page/PerformanceMeasure.idl:
Like with PerformanceMark, but there is no constructor here, so we only need to handle adding
support for the detail getter.

* page/PerformanceMeasureOptions.h: Added.
* page/PerformanceMeasureOptions.idl: Added.
Import and bind PerformanceMeasureOptions dictionary to a new struct.

* page/PerformanceUserTiming.cpp:
(WebCore::restrictedMarkNamesToNavigationTimingFunctionMap):
(WebCore::restrictedMarkFunction):
(WebCore::isRestrictedMarkNameNonMainThread):
(WebCore::PerformanceUserTiming::isRestrictedMarkName):
Split up existing map to enable accessing it safely from a worker using conservative
callOnMainThreadAndWait approach, though since the map is immutable after initialization,
we can probably optimize this to allow concurrent querying in the future.

(WebCore::addPerformanceEntry):
Add helper, mirroring clearPerformanceEntries, to add entries.

(WebCore::PerformanceUserTiming::mark):
Matching the spec language, utilize the new PerformanceMark constructor to create
the mark.

(WebCore::PerformanceUserTiming::convertMarkToTimestamp const):
(WebCore::isNonEmptyDictionary):
(WebCore::PerformanceUserTiming::measure):
Implement measure support by dispatching various combinations of arguments to
overloads manually by inspecting the Variant.

* page/PerformanceUserTiming.h:
Renames class from UserTiming to PerformanceUserTiming to match file names.

LayoutTests:

Update error text due to some changes in which exceptions are thrown due to
new support for User Timing Level 3.

* performance-api/performance-measure-name-expected.txt:
* performance-api/performance-now-api-expected.txt:
* performance-api/user-timing-apis-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (267401 => 267402)


--- trunk/LayoutTests/ChangeLog	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/ChangeLog	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,3 +1,17 @@
+2020-09-22  Sam Weinig  <wei...@apple.com>
+
+        Update User Timing interfaces to User Timing Level 3
+        https://bugs.webkit.org/show_bug.cgi?id=216787
+
+        Reviewed by Alex Christensen.
+
+        Update error text due to some changes in which exceptions are thrown due to 
+        new support for User Timing Level 3.
+
+        * performance-api/performance-measure-name-expected.txt:
+        * performance-api/performance-now-api-expected.txt:
+        * performance-api/user-timing-apis-expected.txt:
+
 2020-09-22  Youenn Fablet  <you...@apple.com>
 
         toRTCIceProtocol should handle ssltcp candidates

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,3 +1,37 @@
+2020-09-22  Sam Weinig  <wei...@apple.com>
+
+        Update User Timing interfaces to User Timing Level 3
+        https://bugs.webkit.org/show_bug.cgi?id=216787
+
+        Reviewed by Alex Christensen.
+        
+        Import missing case-sensitivity test case from upstream and update the results
+        of User Timing tests now that we support Level 3.
+
+        * web-platform-tests/user-timing/case-sensitivity.any-expected.txt: Added.
+        * web-platform-tests/user-timing/case-sensitivity.any.html: Added.
+        * web-platform-tests/user-timing/case-sensitivity.any.js: Added.
+        * web-platform-tests/user-timing/case-sensitivity.any.worker-expected.txt: Added.
+        * web-platform-tests/user-timing/case-sensitivity.any.worker.html: Added.
+        * web-platform-tests/user-timing/idlharness.any-expected.txt:
+        * web-platform-tests/user-timing/idlharness.any.worker-expected.txt:
+        * web-platform-tests/user-timing/mark-entry-constructor.any-expected.txt:
+        * web-platform-tests/user-timing/mark-entry-constructor.any.worker-expected.txt:
+        * web-platform-tests/user-timing/mark-errors.any-expected.txt:
+        * web-platform-tests/user-timing/mark-errors.any.worker-expected.txt:
+        * web-platform-tests/user-timing/mark-l3.any-expected.txt:
+        * web-platform-tests/user-timing/mark-l3.any.worker-expected.txt:
+        * web-platform-tests/user-timing/mark-measure-return-objects.any-expected.txt:
+        * web-platform-tests/user-timing/mark-measure-return-objects.any.worker-expected.txt:
+        * web-platform-tests/user-timing/measure-l3.any-expected.txt:
+        * web-platform-tests/user-timing/measure-l3.any.worker-expected.txt:
+        * web-platform-tests/user-timing/measure-with-dict.any-expected.txt:
+        * web-platform-tests/user-timing/measure-with-dict.any.worker-expected.txt:
+        * web-platform-tests/user-timing/measure_exception-expected.txt:
+        * web-platform-tests/user-timing/performance-measure-invalid.worker-expected.txt:
+        * web-platform-tests/user-timing/structured-serialize-detail.any-expected.txt:
+        * web-platform-tests/user-timing/structured-serialize-detail.any.worker-expected.txt:
+
 2020-09-21  Chris Dumez  <cdu...@apple.com>
 
         Throw when AudioConnect::connect() is called for an output that has no channels

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any-expected.txt (0 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -0,0 +1,3 @@
+
+PASS getEntriesByType values are case sensitive 
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any.html (0 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any.html	2020-09-22 08:46:36 UTC (rev 267402)
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any.js (0 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any.js	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any.js	2020-09-22 08:46:36 UTC (rev 267402)
@@ -0,0 +1,25 @@
+  test(function () {
+    assert_equals(typeof self.performance, "object");
+    assert_equals(typeof self.performance.getEntriesByType, "function");
+
+    self.performance.mark("mark1");
+    self.performance.measure("measure1");
+
+    const type = [
+      'mark',
+      'measure',
+    ];
+    type.forEach(function(entryType) {
+      if (PerformanceObserver.supportedEntryTypes.includes(entryType)) {
+        const entryTypeUpperCased = entryType.toUpperCase();
+        const entryTypeCapitalized = entryType[0].toUpperCase() + entryType.substring(1);
+        const lowerList = self.performance.getEntriesByType(entryType);
+        const upperList = self.performance.getEntriesByType(entryTypeUpperCased);
+        const mixedList = self.performance.getEntriesByType(entryTypeCapitalized);
+
+        assert_greater_than(lowerList.length, 0, "Entries exist");
+        assert_equals(upperList.length, 0, "getEntriesByType('" + entryTypeCapitalized + "').length");
+        assert_equals(mixedList.length, 0, "getEntriesByType('" + entryTypeCapitalized + "').length");
+      }
+    });
+  }, "getEntriesByType values are case sensitive");

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any.worker-expected.txt (0 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any.worker-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any.worker-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -0,0 +1,3 @@
+
+PASS getEntriesByType values are case sensitive 
+

Added: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any.worker.html (0 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any.worker.html	                        (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/case-sensitivity.any.worker.html	2020-09-22 08:46:36 UTC (rev 267402)
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/idlharness.any-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/idlharness.any-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/idlharness.any-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -4,15 +4,15 @@
 PASS Partial interface Performance: original interface defined 
 PASS Partial interface Performance: member names are unique 
 PASS PerformanceMark interface: existence and properties of interface object 
-FAIL PerformanceMark interface object length assert_equals: wrong value for PerformanceMark.length expected 1 but got 0
+PASS PerformanceMark interface object length 
 PASS PerformanceMark interface object name 
 PASS PerformanceMark interface: existence and properties of interface prototype object 
 PASS PerformanceMark interface: existence and properties of interface prototype object's "constructor" property 
 PASS PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property 
-FAIL PerformanceMark interface: attribute detail assert_true: The prototype object must have a property "detail" expected true got false
+PASS PerformanceMark interface: attribute detail 
 PASS PerformanceMark must be primary interface of mark 
 PASS Stringification of mark 
-FAIL PerformanceMark interface: mark must inherit property "detail" with the proper type assert_inherits: property "detail" not found in prototype chain
+PASS PerformanceMark interface: mark must inherit property "detail" with the proper type 
 PASS PerformanceMeasure interface: existence and properties of interface object 
 PASS PerformanceMeasure interface object length 
 PASS PerformanceMeasure interface object name 
@@ -19,10 +19,10 @@
 PASS PerformanceMeasure interface: existence and properties of interface prototype object 
 PASS PerformanceMeasure interface: existence and properties of interface prototype object's "constructor" property 
 PASS PerformanceMeasure interface: existence and properties of interface prototype object's @@unscopables property 
-FAIL PerformanceMeasure interface: attribute detail assert_true: The prototype object must have a property "detail" expected true got false
+PASS PerformanceMeasure interface: attribute detail 
 PASS PerformanceMeasure must be primary interface of measure 
 PASS Stringification of measure 
-FAIL PerformanceMeasure interface: measure must inherit property "detail" with the proper type assert_inherits: property "detail" not found in prototype chain
+PASS PerformanceMeasure interface: measure must inherit property "detail" with the proper type 
 PASS Performance interface: operation mark(DOMString, optional PerformanceMarkOptions) 
 PASS Performance interface: operation clearMarks(optional DOMString) 
 PASS Performance interface: operation measure(DOMString, optional (DOMString or PerformanceMeasureOptions), optional DOMString) 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/idlharness.any.worker-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/idlharness.any.worker-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/idlharness.any.worker-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -4,15 +4,15 @@
 PASS Partial interface Performance: original interface defined 
 PASS Partial interface Performance: member names are unique 
 PASS PerformanceMark interface: existence and properties of interface object 
-FAIL PerformanceMark interface object length assert_equals: wrong value for PerformanceMark.length expected 1 but got 0
+PASS PerformanceMark interface object length 
 PASS PerformanceMark interface object name 
 PASS PerformanceMark interface: existence and properties of interface prototype object 
 PASS PerformanceMark interface: existence and properties of interface prototype object's "constructor" property 
 PASS PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property 
-FAIL PerformanceMark interface: attribute detail assert_true: The prototype object must have a property "detail" expected true got false
+PASS PerformanceMark interface: attribute detail 
 PASS PerformanceMark must be primary interface of mark 
 PASS Stringification of mark 
-FAIL PerformanceMark interface: mark must inherit property "detail" with the proper type assert_inherits: property "detail" not found in prototype chain
+PASS PerformanceMark interface: mark must inherit property "detail" with the proper type 
 PASS PerformanceMeasure interface: existence and properties of interface object 
 PASS PerformanceMeasure interface object length 
 PASS PerformanceMeasure interface object name 
@@ -19,10 +19,10 @@
 PASS PerformanceMeasure interface: existence and properties of interface prototype object 
 PASS PerformanceMeasure interface: existence and properties of interface prototype object's "constructor" property 
 PASS PerformanceMeasure interface: existence and properties of interface prototype object's @@unscopables property 
-FAIL PerformanceMeasure interface: attribute detail assert_true: The prototype object must have a property "detail" expected true got false
+PASS PerformanceMeasure interface: attribute detail 
 PASS PerformanceMeasure must be primary interface of measure 
 PASS Stringification of measure 
-FAIL PerformanceMeasure interface: measure must inherit property "detail" with the proper type assert_inherits: property "detail" not found in prototype chain
+PASS PerformanceMeasure interface: measure must inherit property "detail" with the proper type 
 PASS Performance interface: operation mark(DOMString, optional PerformanceMarkOptions) 
 PASS Performance interface: operation clearMarks(optional DOMString) 
 PASS Performance interface: operation measure(DOMString, optional (DOMString or PerformanceMeasureOptions), optional DOMString) 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-entry-constructor.any-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-entry-constructor.any-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-entry-constructor.any-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,8 +1,8 @@
 
-FAIL Mark entry can be created by 'new PerformanceMark(string)'. Illegal constructor
-FAIL Mark entry can be created by 'new PerformanceMark(string, {})'. Illegal constructor
-FAIL Mark entry can be created by 'new PerformanceMark(string, {startTime})'. Illegal constructor
-FAIL Mark entry can be created by 'new PerformanceMark(string, {detail})'. Illegal constructor
-FAIL Mark entry can be created by 'new PerformanceMark(string, {startTime, detail})'. Illegal constructor
-FAIL Using new PerformanceMark() shouldn't add the entry to performance timeline. Illegal constructor
+PASS Mark entry can be created by 'new PerformanceMark(string)'. 
+PASS Mark entry can be created by 'new PerformanceMark(string, {})'. 
+PASS Mark entry can be created by 'new PerformanceMark(string, {startTime})'. 
+PASS Mark entry can be created by 'new PerformanceMark(string, {detail})'. 
+PASS Mark entry can be created by 'new PerformanceMark(string, {startTime, detail})'. 
+PASS Using new PerformanceMark() shouldn't add the entry to performance timeline. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-entry-constructor.any.worker-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-entry-constructor.any.worker-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-entry-constructor.any.worker-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,8 +1,8 @@
 
-FAIL Mark entry can be created by 'new PerformanceMark(string)'. Illegal constructor
-FAIL Mark entry can be created by 'new PerformanceMark(string, {})'. Illegal constructor
-FAIL Mark entry can be created by 'new PerformanceMark(string, {startTime})'. Illegal constructor
-FAIL Mark entry can be created by 'new PerformanceMark(string, {detail})'. Illegal constructor
-FAIL Mark entry can be created by 'new PerformanceMark(string, {startTime, detail})'. Illegal constructor
-FAIL Using new PerformanceMark() shouldn't add the entry to performance timeline. Illegal constructor
+PASS Mark entry can be created by 'new PerformanceMark(string)'. 
+PASS Mark entry can be created by 'new PerformanceMark(string, {})'. 
+PASS Mark entry can be created by 'new PerformanceMark(string, {startTime})'. 
+PASS Mark entry can be created by 'new PerformanceMark(string, {detail})'. 
+PASS Mark entry can be created by 'new PerformanceMark(string, {startTime, detail})'. 
+PASS Using new PerformanceMark() shouldn't add the entry to performance timeline. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-errors.any-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-errors.any-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-errors.any-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,6 +1,6 @@
 
-FAIL Number should be rejected as the mark-options. assert_throws_js: Number passed as a dict argument should cause type-error. function "function () { self.performance.mark("mark1", 123); }" did not throw
-FAIL NaN should be rejected as the mark-options. assert_throws_js: NaN passed as a dict argument should cause type-error. function "function () { self.performance.mark("mark1", NaN); }" did not throw
-FAIL Infinity should be rejected as the mark-options. assert_throws_js: Infinity passed as a dict argument should cause type-error. function "function () { self.performance.mark("mark1", Infinity); }" did not throw
-FAIL String should be rejected as the mark-options. assert_throws_js: String passed as a dict argument should cause type-error. function "function () { self.performance.mark("mark1", "string"); }" did not throw
+PASS Number should be rejected as the mark-options. 
+PASS NaN should be rejected as the mark-options. 
+PASS Infinity should be rejected as the mark-options. 
+PASS String should be rejected as the mark-options. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-errors.any.worker-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-errors.any.worker-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-errors.any.worker-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,6 +1,6 @@
 
-FAIL Number should be rejected as the mark-options. assert_throws_js: Number passed as a dict argument should cause type-error. function "function () { self.performance.mark("mark1", 123); }" did not throw
-FAIL NaN should be rejected as the mark-options. assert_throws_js: NaN passed as a dict argument should cause type-error. function "function () { self.performance.mark("mark1", NaN); }" did not throw
-FAIL Infinity should be rejected as the mark-options. assert_throws_js: Infinity passed as a dict argument should cause type-error. function "function () { self.performance.mark("mark1", Infinity); }" did not throw
-FAIL String should be rejected as the mark-options. assert_throws_js: String passed as a dict argument should cause type-error. function "function () { self.performance.mark("mark1", "string"); }" did not throw
+PASS Number should be rejected as the mark-options. 
+PASS NaN should be rejected as the mark-options. 
+PASS Infinity should be rejected as the mark-options. 
+PASS String should be rejected as the mark-options. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-l3.any-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-l3.any-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-l3.any-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,3 +1,3 @@
 
-FAIL mark entries' detail and startTime are customizable. undefined is not an object (evaluating 'ae.name')
+PASS mark entries' detail and startTime are customizable. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-l3.any.worker-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-l3.any.worker-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-l3.any.worker-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,3 +1,3 @@
 
-FAIL mark entries' detail and startTime are customizable. undefined is not an object (evaluating 'ae.name')
+PASS mark entries' detail and startTime are customizable. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-measure-return-objects.any-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-measure-return-objects.any-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-measure-return-objects.any-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,7 +1,7 @@
 
-FAIL L3: performance.measure(name) should return an entry. assert_true: expected true got false
-FAIL L3: performance.measure(name, param1) should return an entry. The string did not match the expected pattern.
-FAIL L3: performance.measure(name, param1, param2) should return an entry. assert_true: expected true got false
-FAIL L3: performance.mark(name) should return an entry. assert_true: expected true got false
-FAIL L3: performance.mark(name, param) should return an entry. assert_true: expected true got false
+PASS L3: performance.measure(name) should return an entry. 
+PASS L3: performance.measure(name, param1) should return an entry. 
+PASS L3: performance.measure(name, param1, param2) should return an entry. 
+PASS L3: performance.mark(name) should return an entry. 
+PASS L3: performance.mark(name, param) should return an entry. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-measure-return-objects.any.worker-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-measure-return-objects.any.worker-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/mark-measure-return-objects.any.worker-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,7 +1,7 @@
 
-FAIL L3: performance.measure(name) should return an entry. assert_true: expected true got false
-FAIL L3: performance.measure(name, param1) should return an entry. No mark named '[object Object]' exists
-FAIL L3: performance.measure(name, param1, param2) should return an entry. assert_true: expected true got false
-FAIL L3: performance.mark(name) should return an entry. assert_true: expected true got false
-FAIL L3: performance.mark(name, param) should return an entry. assert_true: expected true got false
+PASS L3: performance.measure(name) should return an entry. 
+PASS L3: performance.measure(name, param1) should return an entry. 
+PASS L3: performance.measure(name, param1, param2) should return an entry. 
+PASS L3: performance.mark(name) should return an entry. 
+PASS L3: performance.mark(name, param) should return an entry. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure-l3.any-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure-l3.any-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure-l3.any-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,5 +1,5 @@
 
-FAIL When the end mark is given and the start is unprovided, the end time of the measure entry should be the end mark's time, the start time should be 0. undefined is not an object (evaluating 'measureEntry.startTime')
-FAIL When the start mark is given and the end is unprovided, the start time of the measure entry should be the start mark's time, the end should be now. undefined is not an object (evaluating 'measureEntry.startTime')
-FAIL When start and end mark are both given, the start time and end time of the measure entry should be the the marks' time, repectively undefined is not an object (evaluating 'entry.startTime')
+PASS When the end mark is given and the start is unprovided, the end time of the measure entry should be the end mark's time, the start time should be 0. 
+PASS When the start mark is given and the end is unprovided, the start time of the measure entry should be the start mark's time, the end should be now. 
+PASS When start and end mark are both given, the start time and end time of the measure entry should be the the marks' time, repectively 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure-l3.any.worker-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure-l3.any.worker-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure-l3.any.worker-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,5 +1,5 @@
 
-FAIL When the end mark is given and the start is unprovided, the end time of the measure entry should be the end mark's time, the start time should be 0. undefined is not an object (evaluating 'measureEntry.startTime')
-FAIL When the start mark is given and the end is unprovided, the start time of the measure entry should be the start mark's time, the end should be now. undefined is not an object (evaluating 'measureEntry.startTime')
-FAIL When start and end mark are both given, the start time and end time of the measure entry should be the the marks' time, repectively undefined is not an object (evaluating 'entry.startTime')
+PASS When the end mark is given and the start is unprovided, the end time of the measure entry should be the end mark's time, the start time should be 0. 
+PASS When the start mark is given and the end is unprovided, the start time of the measure entry should be the start mark's time, the end should be now. 
+PASS When start and end mark are both given, the start time and end time of the measure entry should be the the marks' time, repectively 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure-with-dict.any-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure-with-dict.any-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure-with-dict.any-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,8 +1,4 @@
 
-FAIL measure entries' detail and start/end are customizable The string did not match the expected pattern.
-FAIL measure should throw a TypeError when passed an invalid argument combination assert_throws_js: measure should throw a TypeError when passed an options object and an end time function "function () {
-      self.performance.measure("optionsAndNumberEnd", {'start': 2}, 12);
-    }" threw object "SyntaxError: The string did not match the expected pattern." ("SyntaxError") expected instance of function "function TypeError() {
-    [native code]
-}" ("TypeError")
+PASS measure entries' detail and start/end are customizable 
+PASS measure should throw a TypeError when passed an invalid argument combination 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure-with-dict.any.worker-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure-with-dict.any.worker-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure-with-dict.any.worker-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,8 +1,4 @@
 
-FAIL measure entries' detail and start/end are customizable No mark named 'null' exists
-FAIL measure should throw a TypeError when passed an invalid argument combination assert_throws_js: measure should throw a TypeError when passed an options object and an end time function "function () {
-      self.performance.measure("optionsAndNumberEnd", {'start': 2}, 12);
-    }" threw object "SyntaxError: No mark named '12' exists" ("SyntaxError") expected instance of function "function TypeError() {
-    [native code]
-}" ("TypeError")
+PASS measure entries' detail and start/end are customizable 
+PASS measure should throw a TypeError when passed an invalid argument combination 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure_exception-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure_exception-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/measure_exception-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -11,10 +11,6 @@
 PASS Invocation of performance.measure("Exception5", "ExistMark", "NonExistMark1") should throw SYNTAX_ERR Exception. 
 PASS Invocation of performance.measure("Exception6", "NonExistMark1", "NonExistMark2") should throw SYNTAX_ERR Exception. 
 PASS Invocation of performance.measure("Exception7", "redirectStart") should throw INVALID_ACCESS_ERR Exception. 
-FAIL Invocation of performance.measure("Exception8", {"detail": "non-empty"}) should throw TypeError Exception. assert_throws_js: Invocation of performance.measure("Exception8", {"detail": "non-empty"}) should throw TypeError Exception. function "function () {eval(func_str)}" threw object "SyntaxError: The string did not match the expected pattern." ("SyntaxError") expected instance of function "function TypeError() {
-    [native code]
-}" ("TypeError")
-FAIL Invocation of performance.measure("Exception9", {"start": 1, "duration": 2, "end": 3}) should throw TypeError Exception. assert_throws_js: Invocation of performance.measure("Exception9", {"start": 1, "duration": 2, "end": 3}) should throw TypeError Exception. function "function () {eval(func_str)}" threw object "SyntaxError: The string did not match the expected pattern." ("SyntaxError") expected instance of function "function TypeError() {
-    [native code]
-}" ("TypeError")
+PASS Invocation of performance.measure("Exception8", {"detail": "non-empty"}) should throw TypeError Exception. 
+PASS Invocation of performance.measure("Exception9", {"start": 1, "duration": 2, "end": 3}) should throw TypeError Exception. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/performance-measure-invalid.worker-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/performance-measure-invalid.worker-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/performance-measure-invalid.worker-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,7 +1,3 @@
 
-FAIL When converting 'navigationStart' to a timestamp, the global object has to be a Window object. assert_throws_js: function "() => {
-    performance.measure('name', 'navigationStart', 'navigationStart');
-  }" threw object "SyntaxError: No mark named 'navigationStart' exists" ("SyntaxError") expected instance of function "function TypeError() {
-    [native code]
-}" ("TypeError")
+PASS When converting 'navigationStart' to a timestamp, the global object has to be a Window object. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/structured-serialize-detail.any-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/structured-serialize-detail.any-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/structured-serialize-detail.any-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,15 +1,11 @@
 
-FAIL The detail property in the mark constructor should be structured-clone. Illegal constructor
-FAIL The detail property in the mark method should be structured-clone. undefined is not an object (evaluating 'markEntry.detail')
-FAIL When accessing detail from a mark entry and the detail is not provided, just return a null value. undefined is not an object (evaluating 'markEntry.detail')
-FAIL Mark: Throw an exception when the detail property cannot be structured-serialized. assert_throws_dom: Trying to structured-serialize a Symbol. function "()=>{
-    new PerformanceMark("A", { detail });
-  }" threw object "TypeError: Illegal constructor" that is not a DOMException DataCloneError: property "code" is equal to undefined, expected 25
-FAIL The detail property in the measure method should be structured-clone. The string did not match the expected pattern.
-FAIL The detail property in the measure method should be the same reference. The string did not match the expected pattern.
-FAIL When accessing detail from a measure entry and the detail is not provided, just return a null value. undefined is not an object (evaluating 'measureEntry.detail')
-FAIL Measure: Throw an exception when the detail property cannot be structured-serialized. assert_throws_dom: Trying to structured-serialize a Symbol. function "()=>{
-    performance.measure("A", { start: 0, detail });
-  }" threw object "SyntaxError: The string did not match the expected pattern." that is not a DOMException DataCloneError: property "code" is equal to 12, expected 25
-FAIL The detail object is cloned when passed to mark API. undefined is not an object (evaluating 'mark.detail')
+PASS The detail property in the mark constructor should be structured-clone. 
+PASS The detail property in the mark method should be structured-clone. 
+PASS When accessing detail from a mark entry and the detail is not provided, just return a null value. 
+PASS Mark: Throw an exception when the detail property cannot be structured-serialized. 
+PASS The detail property in the measure method should be structured-clone. 
+PASS The detail property in the measure method should be the same reference. 
+PASS When accessing detail from a measure entry and the detail is not provided, just return a null value. 
+PASS Measure: Throw an exception when the detail property cannot be structured-serialized. 
+PASS The detail object is cloned when passed to mark API. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/structured-serialize-detail.any.worker-expected.txt (267401 => 267402)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/structured-serialize-detail.any.worker-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/user-timing/structured-serialize-detail.any.worker-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,15 +1,11 @@
 
-FAIL The detail property in the mark constructor should be structured-clone. Illegal constructor
-FAIL The detail property in the mark method should be structured-clone. undefined is not an object (evaluating 'markEntry.detail')
-FAIL When accessing detail from a mark entry and the detail is not provided, just return a null value. undefined is not an object (evaluating 'markEntry.detail')
-FAIL Mark: Throw an exception when the detail property cannot be structured-serialized. assert_throws_dom: Trying to structured-serialize a Symbol. function "()=>{
-    new PerformanceMark("A", { detail });
-  }" threw object "TypeError: Illegal constructor" that is not a DOMException DataCloneError: property "code" is equal to undefined, expected 25
-FAIL The detail property in the measure method should be structured-clone. No mark named '[object Object]' exists
-FAIL The detail property in the measure method should be the same reference. No mark named '[object Object]' exists
-FAIL When accessing detail from a measure entry and the detail is not provided, just return a null value. undefined is not an object (evaluating 'measureEntry.detail')
-FAIL Measure: Throw an exception when the detail property cannot be structured-serialized. assert_throws_dom: Trying to structured-serialize a Symbol. function "()=>{
-    performance.measure("A", { start: 0, detail });
-  }" threw object "SyntaxError: No mark named '[object Object]' exists" that is not a DOMException DataCloneError: property "code" is equal to 12, expected 25
-FAIL The detail object is cloned when passed to mark API. undefined is not an object (evaluating 'mark.detail')
+PASS The detail property in the mark constructor should be structured-clone. 
+PASS The detail property in the mark method should be structured-clone. 
+PASS When accessing detail from a mark entry and the detail is not provided, just return a null value. 
+PASS Mark: Throw an exception when the detail property cannot be structured-serialized. 
+PASS The detail property in the measure method should be structured-clone. 
+PASS The detail property in the measure method should be the same reference. 
+PASS When accessing detail from a measure entry and the detail is not provided, just return a null value. 
+PASS Measure: Throw an exception when the detail property cannot be structured-serialized. 
+PASS The detail object is cloned when passed to mark API. 
 

Modified: trunk/LayoutTests/performance-api/performance-measure-name-expected.txt (267401 => 267402)


--- trunk/LayoutTests/performance-api/performance-measure-name-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/performance-api/performance-measure-name-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -4,8 +4,8 @@
 
 
 PASS performance.mark("existing-mark-name") did not throw exception.
-PASS performance.measure("measure-name", "x") threw exception SyntaxError: The string did not match the expected pattern..
-PASS performance.measure("measure-name", "existing-mark-name", "x") threw exception SyntaxError: The string did not match the expected pattern..
+PASS performance.measure("measure-name", "x") threw exception SyntaxError: No mark named 'x' exists.
+PASS performance.measure("measure-name", "existing-mark-name", "x") threw exception SyntaxError: No mark named 'x' exists.
 PASS performance.mark("x") did not throw exception.
 PASS performance.measure("measure-name", "x") did not throw exception.
 PASS performance.measure("measure-name", "existing-mark-name", "x") did not throw exception.

Modified: trunk/LayoutTests/performance-api/performance-now-api-expected.txt (267401 => 267402)


--- trunk/LayoutTests/performance-api/performance-now-api-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/performance-api/performance-now-api-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -6,7 +6,7 @@
 Performance
 PASS Performance is defined.
 PASS Performance.prototype.now is defined.
-PASS new Performance() threw exception TypeError: function is not a constructor (evaluating 'new Performance()').
+PASS new Performance() threw exception TypeError: Illegal constructor.
 performance
 PASS performance is defined.
 PASS performance instanceof Performance is true
@@ -18,7 +18,7 @@
 [Worker] Performance
 PASS [Worker] Performance is defined.
 PASS [Worker] Performance.prototype.now is defined.
-PASS [Worker] new Performance() threw exception TypeError: function is not a constructor (evaluating 'new Performance()').
+PASS [Worker] new Performance() threw exception TypeError: Illegal constructor.
 [Worker] performance
 PASS [Worker] performance is defined.
 PASS [Worker] performance instanceof Performance is true

Modified: trunk/LayoutTests/performance-api/user-timing-apis-expected.txt (267401 => 267402)


--- trunk/LayoutTests/performance-api/user-timing-apis-expected.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/LayoutTests/performance-api/user-timing-apis-expected.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -5,7 +5,7 @@
 
 PerformanceMark
 PASS PerformanceMark is defined.
-PASS new PerformanceMark() threw exception TypeError: Illegal constructor.
+PASS new PerformanceMark() threw exception TypeError: Not enough arguments.
 
 PerformanceMeasure
 PASS PerformanceMeasure is defined.
@@ -28,7 +28,7 @@
 Starting worker: resources/user-timing-api.js
 [Worker] PerformanceMark
 PASS [Worker] PerformanceMark is defined.
-PASS [Worker] new PerformanceMark() threw exception TypeError: Illegal constructor.
+PASS [Worker] new PerformanceMark() threw exception TypeError: Not enough arguments.
 [Worker] 
 [Worker] PerformanceMeasure
 PASS [Worker] PerformanceMeasure is defined.

Modified: trunk/Source/WebCore/CMakeLists.txt (267401 => 267402)


--- trunk/Source/WebCore/CMakeLists.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/CMakeLists.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1052,7 +1052,9 @@
     page/Performance.idl
     page/PerformanceEntry.idl
     page/PerformanceMark.idl
+    page/PerformanceMarkOptions.idl
     page/PerformanceMeasure.idl
+    page/PerformanceMeasureOptions.idl
     page/PerformanceObserver.idl
     page/PerformanceObserverCallback.idl
     page/PerformanceObserverEntryList.idl

Modified: trunk/Source/WebCore/ChangeLog (267401 => 267402)


--- trunk/Source/WebCore/ChangeLog	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/ChangeLog	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1,3 +1,87 @@
+2020-09-22  Sam Weinig  <wei...@apple.com>
+
+        Update User Timing interfaces to User Timing Level 3
+        https://bugs.webkit.org/show_bug.cgi?id=216787
+
+        Reviewed by Alex Christensen.
+
+        Adds support for User Timing Level 3 which adds more flexibility in how PerformanceMarks
+        and PerformanceMeasures are created via synthetic start/end times and associate 'details'
+        values serialized with events themselves.
+
+        Updates results to existing WPT and standalone tests.
+
+        * CMakeLists.txt:
+        * DerivedSources-input.xcfilelist:
+        * DerivedSources-output.xcfilelist:
+        * DerivedSources.make:
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        Add new files.
+
+        * page/Performance.cpp:
+        (WebCore::Performance::mark):
+        (WebCore::Performance::clearMarks):
+        (WebCore::Performance::measure):
+        (WebCore::Performance::clearMeasures):
+        * page/Performance.h:
+        * page/Performance.idl:
+        Update for new signatures for mark and measure, and rename of UserTiming to PerformanceUserTiming.
+
+        * page/PerformanceMark.cpp: Added.
+        (WebCore::peformanceNow):
+        (WebCore::PerformanceMark::create):
+        (WebCore::PerformanceMark::PerformanceMark):
+        (WebCore::PerformanceMark::detail):
+        * page/PerformanceMark.h:
+        * page/PerformanceMark.idl:
+        Add support for PerformanceMark's constructor `detail` getter. While the spec says to
+        serialize and the deserialize in the constructor, we only serialize, and delay deserialization
+        until the first access, which is a non-observable difference. We also utilize [CachedAttribute]
+        to only ever deserialize once per wrapper world (and also greatly simplify the GC shenanigans).
+        
+        * page/PerformanceMarkOptions.h: Added.
+        * page/PerformanceMarkOptions.idl: Added.
+        Import and bind PerformanceMarkOptions dictionary to a new struct.
+        
+        * page/PerformanceMeasure.cpp: Added.
+        (WebCore::PerformanceMeasure::create):
+        (WebCore::PerformanceMeasure::PerformanceMeasure):
+        (WebCore::PerformanceMeasure::detail):
+        * page/PerformanceMeasure.h:
+        * page/PerformanceMeasure.idl:
+        Like with PerformanceMark, but there is no constructor here, so we only need to handle adding
+        support for the detail getter.
+
+        * page/PerformanceMeasureOptions.h: Added.
+        * page/PerformanceMeasureOptions.idl: Added.
+        Import and bind PerformanceMeasureOptions dictionary to a new struct.
+        
+        * page/PerformanceUserTiming.cpp:
+        (WebCore::restrictedMarkNamesToNavigationTimingFunctionMap):
+        (WebCore::restrictedMarkFunction):
+        (WebCore::isRestrictedMarkNameNonMainThread):
+        (WebCore::PerformanceUserTiming::isRestrictedMarkName):
+        Split up existing map to enable accessing it safely from a worker using conservative
+        callOnMainThreadAndWait approach, though since the map is immutable after initialization,
+        we can probably optimize this to allow concurrent querying in the future.
+
+        (WebCore::addPerformanceEntry):
+        Add helper, mirroring clearPerformanceEntries, to add entries.
+
+        (WebCore::PerformanceUserTiming::mark):
+        Matching the spec language, utilize the new PerformanceMark constructor to create
+        the mark.
+
+        (WebCore::PerformanceUserTiming::convertMarkToTimestamp const):
+        (WebCore::isNonEmptyDictionary):
+        (WebCore::PerformanceUserTiming::measure):
+        Implement measure support by dispatching various combinations of arguments to
+        overloads manually by inspecting the Variant.
+
+        * page/PerformanceUserTiming.h:
+        Renames class from UserTiming to PerformanceUserTiming to match file names.
+
 2020-09-22  Youenn Fablet  <you...@apple.com>
 
         toRTCIceProtocol should handle ssltcp candidates

Modified: trunk/Source/WebCore/DerivedSources-input.xcfilelist (267401 => 267402)


--- trunk/Source/WebCore/DerivedSources-input.xcfilelist	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/DerivedSources-input.xcfilelist	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1030,7 +1030,9 @@
 $(PROJECT_DIR)/page/Performance.idl
 $(PROJECT_DIR)/page/PerformanceEntry.idl
 $(PROJECT_DIR)/page/PerformanceMark.idl
+$(PROJECT_DIR)/page/PerformanceMarkOptions.idl
 $(PROJECT_DIR)/page/PerformanceMeasure.idl
+$(PROJECT_DIR)/page/PerformanceMeasureOptions.idl
 $(PROJECT_DIR)/page/PerformanceNavigation.idl
 $(PROJECT_DIR)/page/PerformanceObserver.idl
 $(PROJECT_DIR)/page/PerformanceObserverCallback.idl

Modified: trunk/Source/WebCore/DerivedSources-output.xcfilelist (267401 => 267402)


--- trunk/Source/WebCore/DerivedSources-output.xcfilelist	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/DerivedSources-output.xcfilelist	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1390,8 +1390,12 @@
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPerformanceEntry.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPerformanceMark.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPerformanceMark.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPerformanceMarkOptions.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPerformanceMarkOptions.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPerformanceMeasure.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPerformanceMeasure.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPerformanceMeasureOptions.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPerformanceMeasureOptions.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPerformanceNavigation.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPerformanceNavigation.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSPerformanceObserver.cpp

Modified: trunk/Source/WebCore/DerivedSources.make (267401 => 267402)


--- trunk/Source/WebCore/DerivedSources.make	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/DerivedSources.make	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1041,7 +1041,9 @@
     $(WebCore)/page/Performance.idl \
     $(WebCore)/page/PerformanceEntry.idl \
     $(WebCore)/page/PerformanceMark.idl \
+    $(WebCore)/page/PerformanceMarkOptions.idl \
     $(WebCore)/page/PerformanceMeasure.idl \
+    $(WebCore)/page/PerformanceMeasureOptions.idl \
     $(WebCore)/page/PerformanceNavigation.idl \
     $(WebCore)/page/PerformanceObserver.idl \
     $(WebCore)/page/PerformanceObserverCallback.idl \

Modified: trunk/Source/WebCore/Sources.txt (267401 => 267402)


--- trunk/Source/WebCore/Sources.txt	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/Sources.txt	2020-09-22 08:46:36 UTC (rev 267402)
@@ -1633,6 +1633,8 @@
 page/PerformanceEntry.cpp
 page/PerformanceLogging.cpp
 page/PerformanceLoggingClient.cpp
+page/PerformanceMark.cpp
+page/PerformanceMeasure.cpp
 page/PerformanceMonitor.cpp
 page/PerformanceNavigation.cpp
 page/PerformanceObserver.cpp
@@ -3204,7 +3206,9 @@
 JSPerformance.cpp
 JSPerformanceEntry.cpp
 JSPerformanceMark.cpp
+JSPerformanceMarkOptions.cpp
 JSPerformanceMeasure.cpp
+JSPerformanceMeasureOptions.cpp
 JSPerformanceNavigation.cpp
 JSPerformanceObserver.cpp
 JSPerformanceObserverCallback.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (267401 => 267402)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-09-22 08:46:36 UTC (rev 267402)
@@ -2300,6 +2300,8 @@
 		7C77C3DC1DEF86D700A50BFA /* JSEndingType.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C77C3DA1DEF86D700A50BFA /* JSEndingType.h */; };
 		7C7903B31F86F95C00463A70 /* ImageBitmapRenderingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C7903B01F86F95C00463A70 /* ImageBitmapRenderingContext.h */; };
 		7C7941E51C56C29300A4C58E /* DataDetectorsCoreSoftLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C7941E31C56C29300A4C58E /* DataDetectorsCoreSoftLink.h */; };
+		7C7BF9422516C90C00808682 /* PerformanceMarkOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C7BF93E2516C8BC00808682 /* PerformanceMarkOptions.h */; };
+		7C7BF94C2516FA5400808682 /* PerformanceMeasureOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C7BF9492516FA5400808682 /* PerformanceMeasureOptions.h */; };
 		7C8139A61ED6286A00CE26E8 /* JSDOMAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C8139A31ED6281D00CE26E8 /* JSDOMAttribute.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		7C8139A71ED6287400CE26E8 /* JSDOMOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C8139A41ED6281D00CE26E8 /* JSDOMOperation.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		7C8139A81ED6287400CE26E8 /* JSDOMOperationReturningPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C8139A51ED6281D00CE26E8 /* JSDOMOperationReturningPromise.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -10262,6 +10264,12 @@
 		7C7903BC1F86FF3400463A70 /* PlaceholderRenderingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaceholderRenderingContext.h; sourceTree = "<group>"; };
 		7C7941E21C56C29300A4C58E /* DataDetectorsCoreSoftLink.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DataDetectorsCoreSoftLink.mm; sourceTree = "<group>"; };
 		7C7941E31C56C29300A4C58E /* DataDetectorsCoreSoftLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataDetectorsCoreSoftLink.h; sourceTree = "<group>"; };
+		7C7BF93E2516C8BC00808682 /* PerformanceMarkOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PerformanceMarkOptions.h; sourceTree = "<group>"; };
+		7C7BF9402516C8BC00808682 /* PerformanceMarkOptions.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = PerformanceMarkOptions.idl; sourceTree = "<group>"; };
+		7C7BF9442516CC9200808682 /* PerformanceMark.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PerformanceMark.cpp; sourceTree = "<group>"; };
+		7C7BF9492516FA5400808682 /* PerformanceMeasureOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PerformanceMeasureOptions.h; sourceTree = "<group>"; };
+		7C7BF94B2516FA5400808682 /* PerformanceMeasureOptions.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = PerformanceMeasureOptions.idl; sourceTree = "<group>"; };
+		7C7BF9502516FB5400808682 /* PerformanceMeasure.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PerformanceMeasure.cpp; sourceTree = "<group>"; };
 		7C7C769C22F67ECD0032BCCD /* WHLSLMangledNames.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLMangledNames.h; sourceTree = "<group>"; };
 		7C8139A31ED6281D00CE26E8 /* JSDOMAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMAttribute.h; sourceTree = "<group>"; };
 		7C8139A41ED6281D00CE26E8 /* JSDOMOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMOperation.h; sourceTree = "<group>"; };
@@ -21574,10 +21582,16 @@
 				AD5A0C201DECA0B500707054 /* PerformanceLogging.h */,
 				0FF2E80C1EE0D430009EABD4 /* PerformanceLoggingClient.cpp */,
 				0F850FE21ED7C18300FB77A7 /* PerformanceLoggingClient.h */,
+				7C7BF9442516CC9200808682 /* PerformanceMark.cpp */,
 				37C738E81EDBD2ED003F2B0B /* PerformanceMark.h */,
 				7CE221EE251429F40006886B /* PerformanceMark.idl */,
+				7C7BF93E2516C8BC00808682 /* PerformanceMarkOptions.h */,
+				7C7BF9402516C8BC00808682 /* PerformanceMarkOptions.idl */,
+				7C7BF9502516FB5400808682 /* PerformanceMeasure.cpp */,
 				37C738EA1EDBD381003F2B0B /* PerformanceMeasure.h */,
 				7CE221F0251429F50006886B /* PerformanceMeasure.idl */,
+				7C7BF9492516FA5400808682 /* PerformanceMeasureOptions.h */,
+				7C7BF94B2516FA5400808682 /* PerformanceMeasureOptions.idl */,
 				83FE90251E307C1C003E9199 /* PerformanceMonitor.cpp */,
 				83FE90261E307C1C003E9199 /* PerformanceMonitor.h */,
 				8AF4E55211DC5A36000ED3DE /* PerformanceNavigation.cpp */,
@@ -33167,7 +33181,9 @@
 				AD5A0C251DECACCC00707054 /* PerformanceLogging.h in Headers */,
 				0F850FE31ED7C18300FB77A7 /* PerformanceLoggingClient.h in Headers */,
 				37C738E91EDBD2FA003F2B0B /* PerformanceMark.h in Headers */,
+				7C7BF9422516C90C00808682 /* PerformanceMarkOptions.h in Headers */,
 				37C738EB1EDBD384003F2B0B /* PerformanceMeasure.h in Headers */,
+				7C7BF94C2516FA5400808682 /* PerformanceMeasureOptions.h in Headers */,
 				83FE90271E307C30003E9199 /* PerformanceMonitor.h in Headers */,
 				8AF4E55611DC5A36000ED3DE /* PerformanceNavigation.h in Headers */,
 				A5A9933D1E37FB19005B5E4D /* PerformanceObserver.h in Headers */,

Modified: trunk/Source/WebCore/page/Performance.cpp (267401 => 267402)


--- trunk/Source/WebCore/page/Performance.cpp	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/page/Performance.cpp	2020-09-22 08:46:36 UTC (rev 267402)
@@ -39,6 +39,8 @@
 #include "EventNames.h"
 #include "Frame.h"
 #include "PerformanceEntry.h"
+#include "PerformanceMarkOptions.h"
+#include "PerformanceMeasureOptions.h"
 #include "PerformanceNavigation.h"
 #include "PerformanceObserver.h"
 #include "PerformancePaintTiming.h"
@@ -296,45 +298,43 @@
     m_waitingForBackupBufferToBeProcessed = false;
 }
 
-ExceptionOr<void> Performance::mark(const String& markName)
+ExceptionOr<Ref<PerformanceMark>> Performance::mark(JSC::JSGlobalObject& globalObject, const String& markName, Optional<PerformanceMarkOptions>&& markOptions)
 {
     if (!m_userTiming)
-        m_userTiming = makeUnique<UserTiming>(*this);
+        m_userTiming = makeUnique<PerformanceUserTiming>(*this);
 
-    auto result = m_userTiming->mark(markName);
-    if (result.hasException())
-        return result.releaseException();
+    auto mark = m_userTiming->mark(globalObject, markName, WTFMove(markOptions));
+    if (mark.hasException())
+        return mark.releaseException();
 
-    queueEntry(result.releaseReturnValue());
-
-    return { };
+    queueEntry(mark.returnValue().get());
+    return mark.releaseReturnValue();
 }
 
 void Performance::clearMarks(const String& markName)
 {
     if (!m_userTiming)
-        m_userTiming = makeUnique<UserTiming>(*this);
+        m_userTiming = makeUnique<PerformanceUserTiming>(*this);
     m_userTiming->clearMarks(markName);
 }
 
-ExceptionOr<void> Performance::measure(const String& measureName, const String& startMark, const String& endMark)
+ExceptionOr<Ref<PerformanceMeasure>> Performance::measure(JSC::JSGlobalObject& globalObject, const String& measureName, Optional<StartOrMeasureOptions>&& startOrMeasureOptions, const String& endMark)
 {
     if (!m_userTiming)
-        m_userTiming = makeUnique<UserTiming>(*this);
+        m_userTiming = makeUnique<PerformanceUserTiming>(*this);
 
-    auto result = m_userTiming->measure(measureName, startMark, endMark);
-    if (result.hasException())
-        return result.releaseException();
+    auto measure = m_userTiming->measure(globalObject, measureName, WTFMove(startOrMeasureOptions), endMark);
+    if (measure.hasException())
+        return measure.releaseException();
 
-    queueEntry(result.releaseReturnValue());
-
-    return { };
+    queueEntry(measure.returnValue().get());
+    return measure.releaseReturnValue();
 }
 
 void Performance::clearMeasures(const String& measureName)
 {
     if (!m_userTiming)
-        m_userTiming = makeUnique<UserTiming>(*this);
+        m_userTiming = makeUnique<PerformanceUserTiming>(*this);
     m_userTiming->clearMeasures(measureName);
 }
 

Modified: trunk/Source/WebCore/page/Performance.h (267401 => 267402)


--- trunk/Source/WebCore/page/Performance.h	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/page/Performance.h	2020-09-22 08:46:36 UTC (rev 267402)
@@ -39,11 +39,19 @@
 #include "GenericTaskQueue.h"
 #include "ReducedResolutionSeconds.h"
 #include <wtf/ListHashSet.h>
+#include <wtf/Variant.h>
 
+namespace JSC {
+class JSGlobalObject;
+}
+
 namespace WebCore {
 
 class LoadTiming;
+class PerformanceUserTiming;
 class PerformanceEntry;
+class PerformanceMark;
+class PerformanceMeasure;
 class PerformanceNavigation;
 class PerformanceObserver;
 class PerformancePaintTiming;
@@ -51,7 +59,8 @@
 class ResourceResponse;
 class ResourceTiming;
 class ScriptExecutionContext;
-class UserTiming;
+struct PerformanceMarkOptions;
+struct PerformanceMeasureOptions;
 
 class Performance final : public RefCounted<Performance>, public ContextDestructionObserver, public EventTargetWithInlineData {
     WTF_MAKE_ISO_ALLOCATED(Performance);
@@ -73,10 +82,11 @@
     void clearResourceTimings();
     void setResourceTimingBufferSize(unsigned);
 
-    ExceptionOr<void> mark(const String& markName);
+    ExceptionOr<Ref<PerformanceMark>> mark(JSC::JSGlobalObject&, const String& markName, Optional<PerformanceMarkOptions>&&);
     void clearMarks(const String& markName);
 
-    ExceptionOr<void> measure(const String& measureName, const String& startMark, const String& endMark);
+    using StartOrMeasureOptions = Variant<String, PerformanceMeasureOptions>;
+    ExceptionOr<Ref<PerformanceMeasure>> measure(JSC::JSGlobalObject&, const String& measureName, Optional<StartOrMeasureOptions>&&, const String& endMark);
     void clearMeasures(const String& measureName);
 
     void addResourceTiming(ResourceTiming&&);
@@ -128,7 +138,7 @@
     MonotonicTime m_timeOrigin;
 
     RefPtr<PerformancePaintTiming> m_firstContentfulPaint;
-    std::unique_ptr<UserTiming> m_userTiming;
+    std::unique_ptr<PerformanceUserTiming> m_userTiming;
 
     GenericTaskQueue<ScriptExecutionContext> m_performanceTimelineTaskQueue;
     ListHashSet<RefPtr<PerformanceObserver>> m_observers;

Modified: trunk/Source/WebCore/page/Performance.idl (267401 => 267402)


--- trunk/Source/WebCore/page/Performance.idl	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/page/Performance.idl	2020-09-22 08:46:36 UTC (rev 267402)
@@ -57,11 +57,9 @@
     attribute EventHandler onresourcetimingbufferfull;
 
     // https://w3c.github.io/user-timing/#extensions-performance-interface
-    // FIXME: 'mark' should return a PerformanceMark.
-    [MayThrowException] undefined mark(DOMString markName);
+    [MayThrowException, CallWith=GlobalObject] PerformanceMark mark(DOMString markName, optional PerformanceMarkOptions markOptions);
     undefined clearMarks(optional DOMString markName);
-    // FIXME: 'measure' should return a PerformanceMeasure.
-    [MayThrowException] undefined measure(DOMString measureName, optional DOMString startMark, optional DOMString endMark);
+    [MayThrowException, CallWith=GlobalObject] PerformanceMeasure measure(DOMString measureName, optional (DOMString or PerformanceMeasureOptions) startOrMeasureOptions, optional DOMString endMark);
     undefined clearMeasures(optional DOMString measureName);
 };
 

Added: trunk/Source/WebCore/page/PerformanceMark.cpp (0 => 267402)


--- trunk/Source/WebCore/page/PerformanceMark.cpp	                        (rev 0)
+++ trunk/Source/WebCore/page/PerformanceMark.cpp	2020-09-22 08:46:36 UTC (rev 267402)
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PerformanceMark.h"
+
+#include "DOMWindow.h"
+#include "DOMWrapperWorld.h"
+#include "Document.h"
+#include "MessagePort.h"
+#include "Performance.h"
+#include "PerformanceMarkOptions.h"
+#include "PerformanceUserTiming.h"
+#include "SerializedScriptValue.h"
+#include "WorkerGlobalScope.h"
+
+namespace WebCore {
+
+static double performanceNow(ScriptExecutionContext& scriptExecutionContext)
+{
+    // FIXME: We should consider moving the Performance object to be owned by the
+    // the ScriptExecutionContext to avoid this.
+
+    if (is<Document>(scriptExecutionContext)) {
+        if (auto window = downcast<Document>(scriptExecutionContext).domWindow())
+            return window->performance().now();
+        return 0;
+    }
+
+    if (is<WorkerGlobalScope>(scriptExecutionContext))
+        return downcast<WorkerGlobalScope>(scriptExecutionContext).performance().now();
+
+    return 0;
+}
+
+ExceptionOr<Ref<PerformanceMark>> PerformanceMark::create(JSC::JSGlobalObject& globalObject, ScriptExecutionContext& scriptExecutionContext, const String& name, Optional<PerformanceMarkOptions>&& markOptions)
+{
+    if (is<Document>(scriptExecutionContext) && PerformanceUserTiming::isRestrictedMarkName(name))
+        return Exception { SyntaxError };
+
+    double startTime;
+    JSC::JSValue detail;
+    if (markOptions) {
+        if (markOptions->startTime) {
+            if (*markOptions->startTime < 0)
+                return Exception { TypeError };
+            startTime = *markOptions->startTime;
+        } else
+            startTime = performanceNow(scriptExecutionContext);
+        
+        if (markOptions->detail.isUndefined())
+            detail = JSC::jsNull();
+        else
+            detail = markOptions->detail;
+    } else {
+        startTime = performanceNow(scriptExecutionContext);
+        detail = JSC::jsNull();
+    }
+
+    Vector<RefPtr<MessagePort>> ignoredMessagePorts;
+    auto serializedDetail = SerializedScriptValue::create(globalObject, detail, { }, ignoredMessagePorts);
+    if (serializedDetail.hasException())
+        return serializedDetail.releaseException();
+
+    return adoptRef(*new PerformanceMark(name, startTime, serializedDetail.releaseReturnValue()));
+}
+
+PerformanceMark::PerformanceMark(const String& name, double startTime, Ref<SerializedScriptValue>&& serializedDetail)
+    : PerformanceEntry(name, startTime, startTime)
+    , m_serializedDetail(WTFMove(serializedDetail))
+{
+}
+
+PerformanceMark::~PerformanceMark() = default;
+
+JSC::JSValue PerformanceMark::detail(JSC::JSGlobalObject& globalObject)
+{
+    return m_serializedDetail->deserialize(globalObject, &globalObject);
+}
+
+}

Modified: trunk/Source/WebCore/page/PerformanceMark.h (267401 => 267402)


--- trunk/Source/WebCore/page/PerformanceMark.h	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/page/PerformanceMark.h	2020-09-22 08:46:36 UTC (rev 267402)
@@ -28,22 +28,30 @@
 #include "PerformanceEntry.h"
 #include <wtf/text/WTFString.h>
 
+namespace JSC {
+class JSGlobalObject;
+class JSValue;
+}
+
 namespace WebCore {
 
+class SerializedScriptValue;
+class ScriptExecutionContext;
+
 class PerformanceMark final : public PerformanceEntry {
 public:
-    static Ref<PerformanceMark> create(const String& name, double startTime) { return adoptRef(*new PerformanceMark(name, startTime)); }
+    static ExceptionOr<Ref<PerformanceMark>> create(JSC::JSGlobalObject&, ScriptExecutionContext&, const String& name, Optional<PerformanceMarkOptions>&&);
 
+    JSC::JSValue detail(JSC::JSGlobalObject&);
+
 private:
-    PerformanceMark(const String& name, double startTime)
-        : PerformanceEntry(name, startTime, startTime)
-    {
-    }
+    PerformanceMark(const String& name, double startTime, Ref<SerializedScriptValue>&&);
+    ~PerformanceMark();
 
     Type type() const final { return Type::Mark; }
     ASCIILiteral entryType() const final { return "mark"_s; }
 
-    ~PerformanceMark() = default;
+    Ref<SerializedScriptValue> m_serializedDetail;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/PerformanceMark.idl (267401 => 267402)


--- trunk/Source/WebCore/page/PerformanceMark.idl	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/page/PerformanceMark.idl	2020-09-22 08:46:36 UTC (rev 267402)
@@ -27,8 +27,6 @@
 [
     Exposed=(Window,Worker),
 ] interface PerformanceMark : PerformanceEntry {
-    // FIXME: Implement constructor.
-    // constructor(DOMString markName, optional PerformanceMarkOptions markOptions = {});
-    // FIXME: Implement 'detail'.
-    // readonly attribute any detail;
+    [CallWith=GlobalObject&ScriptExecutionContext] constructor(DOMString markName, optional PerformanceMarkOptions markOptions);
+    [CallWith=GlobalObject, CachedAttribute] readonly attribute any detail;
 };

Added: trunk/Source/WebCore/page/PerformanceMarkOptions.h (0 => 267402)


--- trunk/Source/WebCore/page/PerformanceMarkOptions.h	                        (rev 0)
+++ trunk/Source/WebCore/page/PerformanceMarkOptions.h	2020-09-22 08:46:36 UTC (rev 267402)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <_javascript_Core/JSCJSValue.h>
+#include <wtf/Optional.h>
+
+namespace WebCore {
+
+struct PerformanceMarkOptions {
+    JSC::JSValue detail;
+    Optional<double> startTime;
+};
+
+}

Added: trunk/Source/WebCore/page/PerformanceMarkOptions.idl (0 => 267402)


--- trunk/Source/WebCore/page/PerformanceMarkOptions.idl	                        (rev 0)
+++ trunk/Source/WebCore/page/PerformanceMarkOptions.idl	2020-09-22 08:46:36 UTC (rev 267402)
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+typedef double DOMHighResTimeStamp;
+
+// https://w3c.github.io/user-timing/#ref-for-dom-performancemarkoptions-1
+dictionary PerformanceMarkOptions {
+    any detail;
+    DOMHighResTimeStamp startTime;
+};

Added: trunk/Source/WebCore/page/PerformanceMeasure.cpp (0 => 267402)


--- trunk/Source/WebCore/page/PerformanceMeasure.cpp	                        (rev 0)
+++ trunk/Source/WebCore/page/PerformanceMeasure.cpp	2020-09-22 08:46:36 UTC (rev 267402)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PerformanceMeasure.h"
+
+#include "SerializedScriptValue.h"
+
+namespace WebCore {
+
+ExceptionOr<Ref<PerformanceMeasure>> PerformanceMeasure::create(const String& name, double startTime, double endTime, Ref<SerializedScriptValue>&& serializedDetail)
+{
+    return adoptRef(*new PerformanceMeasure(name, startTime, endTime, WTFMove(serializedDetail)));
+}
+
+PerformanceMeasure::PerformanceMeasure(const String& name, double startTime, double endTime, Ref<SerializedScriptValue>&& serializedDetail)
+    : PerformanceEntry(name, startTime, endTime)
+    , m_serializedDetail(WTFMove(serializedDetail))
+{
+}
+
+PerformanceMeasure::~PerformanceMeasure() = default;
+
+JSC::JSValue PerformanceMeasure::detail(JSC::JSGlobalObject& globalObject)
+{
+    return m_serializedDetail->deserialize(globalObject, &globalObject);
+}
+
+}
+

Modified: trunk/Source/WebCore/page/PerformanceMeasure.h (267401 => 267402)


--- trunk/Source/WebCore/page/PerformanceMeasure.h	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/page/PerformanceMeasure.h	2020-09-22 08:46:36 UTC (rev 267402)
@@ -28,22 +28,30 @@
 #include "PerformanceEntry.h"
 #include <wtf/text/WTFString.h>
 
+namespace JSC {
+class JSGlobalObject;
+class JSValue;
+}
+
 namespace WebCore {
 
+class SerializedScriptValue;
+class ScriptExecutionContext;
+
 class PerformanceMeasure final : public PerformanceEntry {
 public:
-    static Ref<PerformanceMeasure> create(const String& name, double startTime, double duration) { return adoptRef(*new PerformanceMeasure(name, startTime, duration)); }
+    static ExceptionOr<Ref<PerformanceMeasure>> create(const String& name, double startTime, double endTime, Ref<SerializedScriptValue>&& detail);
 
+    JSC::JSValue detail(JSC::JSGlobalObject&);
+
 private:
-    PerformanceMeasure(const String& name, double startTime, double duration)
-        : PerformanceEntry(name, startTime, duration)
-    {
-    }
+    PerformanceMeasure(const String& name, double startTime, double endTime, Ref<SerializedScriptValue>&& detail);
+    ~PerformanceMeasure();
 
     Type type() const final { return Type::Measure; }
     ASCIILiteral entryType() const final { return "measure"_s; }
 
-    ~PerformanceMeasure() = default;
+    Ref<SerializedScriptValue> m_serializedDetail;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/PerformanceMeasure.idl (267401 => 267402)


--- trunk/Source/WebCore/page/PerformanceMeasure.idl	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/page/PerformanceMeasure.idl	2020-09-22 08:46:36 UTC (rev 267402)
@@ -27,6 +27,5 @@
 [
     Exposed=(Window,Worker),
 ] interface PerformanceMeasure : PerformanceEntry {
-    // FIXME: Implement 'detail'.
-    // readonly attribute any detail;
+    [CallWith=GlobalObject, CachedAttribute] readonly attribute any detail;
 };

Added: trunk/Source/WebCore/page/PerformanceMeasureOptions.h (0 => 267402)


--- trunk/Source/WebCore/page/PerformanceMeasureOptions.h	                        (rev 0)
+++ trunk/Source/WebCore/page/PerformanceMeasureOptions.h	2020-09-22 08:46:36 UTC (rev 267402)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <_javascript_Core/JSCJSValue.h>
+#include <wtf/Optional.h>
+#include <wtf/Variant.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+struct PerformanceMeasureOptions {
+    JSC::JSValue detail;
+    Optional<Variant<String, double>> start;
+    Optional<double> duration;
+    Optional<Variant<String, double>> end;
+};
+
+}

Added: trunk/Source/WebCore/page/PerformanceMeasureOptions.idl (0 => 267402)


--- trunk/Source/WebCore/page/PerformanceMeasureOptions.idl	                        (rev 0)
+++ trunk/Source/WebCore/page/PerformanceMeasureOptions.idl	2020-09-22 08:46:36 UTC (rev 267402)
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+typedef double DOMHighResTimeStamp;
+
+// https://w3c.github.io/user-timing/#ref-for-dom-performancemeasureoptions-1
+dictionary PerformanceMeasureOptions {
+    any detail;
+    (DOMString or DOMHighResTimeStamp) start;
+    DOMHighResTimeStamp duration;
+    (DOMString or DOMHighResTimeStamp) end;
+};

Modified: trunk/Source/WebCore/page/PerformanceUserTiming.cpp (267401 => 267402)


--- trunk/Source/WebCore/page/PerformanceUserTiming.cpp	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/page/PerformanceUserTiming.cpp	2020-09-22 08:46:36 UTC (rev 267402)
@@ -28,51 +28,71 @@
 #include "PerformanceUserTiming.h"
 
 #include "Document.h"
+#include "MessagePort.h"
+#include "PerformanceMarkOptions.h"
+#include "PerformanceMeasureOptions.h"
 #include "PerformanceTiming.h"
+#include "SerializedScriptValue.h"
 #include <wtf/NeverDestroyed.h>
 
 namespace WebCore {
 
 using NavigationTimingFunction = unsigned long long (PerformanceTiming::*)() const;
+static const HashMap<String, NavigationTimingFunction>& restrictedMarkNamesToNavigationTimingFunctionMap()
+{
+    ASSERT(isMainThread());
 
+    static auto map = makeNeverDestroyed<HashMap<String, NavigationTimingFunction>>({
+        { "connectEnd"_s, &PerformanceTiming::connectEnd },
+        { "connectStart"_s, &PerformanceTiming::connectStart },
+        { "domComplete"_s, &PerformanceTiming::domComplete },
+        { "domContentLoadedEventEnd"_s, &PerformanceTiming::domContentLoadedEventEnd },
+        { "domContentLoadedEventStart"_s, &PerformanceTiming::domContentLoadedEventStart },
+        { "domInteractive"_s, &PerformanceTiming::domInteractive },
+        { "domLoading"_s, &PerformanceTiming::domLoading },
+        { "domainLookupEnd"_s, &PerformanceTiming::domainLookupEnd },
+        { "domainLookupStart"_s, &PerformanceTiming::domainLookupStart },
+        { "fetchStart"_s, &PerformanceTiming::fetchStart },
+        { "loadEventEnd"_s, &PerformanceTiming::loadEventEnd },
+        { "loadEventStart"_s, &PerformanceTiming::loadEventStart },
+        { "navigationStart"_s, &PerformanceTiming::navigationStart },
+        { "redirectEnd"_s, &PerformanceTiming::redirectEnd },
+        { "redirectStart"_s, &PerformanceTiming::redirectStart },
+        { "requestStart"_s, &PerformanceTiming::requestStart },
+        { "responseEnd"_s, &PerformanceTiming::responseEnd },
+        { "responseStart"_s, &PerformanceTiming::responseStart },
+        { "secureConnectionStart"_s, &PerformanceTiming::secureConnectionStart },
+        { "unloadEventEnd"_s, &PerformanceTiming::unloadEventEnd },
+        { "unloadEventStart"_s, &PerformanceTiming::unloadEventStart },
+    });
+    
+    return map;
+}
+
 static NavigationTimingFunction restrictedMarkFunction(const String& markName)
 {
     ASSERT(isMainThread());
+    return restrictedMarkNamesToNavigationTimingFunctionMap().get(markName);
+}
 
-    static const auto map = makeNeverDestroyed([] {
-        static const std::pair<ASCIILiteral, NavigationTimingFunction> pairs[] = {
-            { "connectEnd"_s, &PerformanceTiming::connectEnd },
-            { "connectStart"_s, &PerformanceTiming::connectStart },
-            { "domComplete"_s, &PerformanceTiming::domComplete },
-            { "domContentLoadedEventEnd"_s, &PerformanceTiming::domContentLoadedEventEnd },
-            { "domContentLoadedEventStart"_s, &PerformanceTiming::domContentLoadedEventStart },
-            { "domInteractive"_s, &PerformanceTiming::domInteractive },
-            { "domLoading"_s, &PerformanceTiming::domLoading },
-            { "domainLookupEnd"_s, &PerformanceTiming::domainLookupEnd },
-            { "domainLookupStart"_s, &PerformanceTiming::domainLookupStart },
-            { "fetchStart"_s, &PerformanceTiming::fetchStart },
-            { "loadEventEnd"_s, &PerformanceTiming::loadEventEnd },
-            { "loadEventStart"_s, &PerformanceTiming::loadEventStart },
-            { "navigationStart"_s, &PerformanceTiming::navigationStart },
-            { "redirectEnd"_s, &PerformanceTiming::redirectEnd },
-            { "redirectStart"_s, &PerformanceTiming::redirectStart },
-            { "requestStart"_s, &PerformanceTiming::requestStart },
-            { "responseEnd"_s, &PerformanceTiming::responseEnd },
-            { "responseStart"_s, &PerformanceTiming::responseStart },
-            { "secureConnectionStart"_s, &PerformanceTiming::secureConnectionStart },
-            { "unloadEventEnd"_s, &PerformanceTiming::unloadEventEnd },
-            { "unloadEventStart"_s, &PerformanceTiming::unloadEventStart },
-        };
-        HashMap<String, NavigationTimingFunction> map;
-        for (auto& pair : pairs)
-            map.add(pair.first, pair.second);
-        return map;
-    }());
+static bool isRestrictedMarkNameNonMainThread(const String& markName)
+{
+    ASSERT(!isMainThread());
 
-    return map.get().get(markName);
+    bool isRestricted;
+    callOnMainThreadAndWait([&isRestricted, markName = markName.isolatedCopy()] {
+        isRestricted = restrictedMarkNamesToNavigationTimingFunctionMap().contains(markName);
+    });
+    return isRestricted;
 }
 
-UserTiming::UserTiming(Performance& performance)
+bool PerformanceUserTiming::isRestrictedMarkName(const String& markName)
+{
+    ASSERT(isMainThread());
+    return restrictedMarkNamesToNavigationTimingFunctionMap().contains(markName);
+}
+
+PerformanceUserTiming::PerformanceUserTiming(Performance& performance)
     : m_performance(performance)
 {
 }
@@ -85,73 +105,182 @@
         map.remove(name);
 }
 
-ExceptionOr<Ref<PerformanceMark>> UserTiming::mark(const String& markName)
+static void addPerformanceEntry(PerformanceEntryMap& map, const String& name, PerformanceEntry& entry)
 {
-    if (is<Document>(m_performance.scriptExecutionContext()) && restrictedMarkFunction(markName))
-        return Exception { SyntaxError };
+    auto& performanceEntryList = map.ensure(name, [] { return Vector<RefPtr<PerformanceEntry>>(); }).iterator->value;
+    performanceEntryList.append(&entry);
+}
 
-    auto& performanceEntryList = m_marksMap.ensure(markName, [] { return Vector<RefPtr<PerformanceEntry>>(); }).iterator->value;
-    auto entry = PerformanceMark::create(markName, m_performance.now());
-    performanceEntryList.append(entry.copyRef());
-    return entry;
+ExceptionOr<Ref<PerformanceMark>> PerformanceUserTiming::mark(JSC::JSGlobalObject& globalObject, const String& markName, Optional<PerformanceMarkOptions>&& markOptions)
+{
+    auto mark = PerformanceMark::create(globalObject, *m_performance.scriptExecutionContext(), markName, WTFMove(markOptions));
+    if (mark.hasException())
+        return mark.releaseException();
+
+    addPerformanceEntry(m_marksMap, markName, mark.returnValue().get());
+    return mark.releaseReturnValue();
 }
 
-void UserTiming::clearMarks(const String& markName)
+void PerformanceUserTiming::clearMarks(const String& markName)
 {
     clearPerformanceEntries(m_marksMap, markName);
 }
 
-ExceptionOr<double> UserTiming::findExistingMarkStartTime(const String& markName)
+ExceptionOr<double> PerformanceUserTiming::convertMarkToTimestamp(const Variant<String, double>& mark) const
 {
-    auto iterator = m_marksMap.find(markName);
-    if (iterator != m_marksMap.end())
-        return iterator->value.last()->startTime();
+    return WTF::switchOn(mark, [&](auto& value) {
+        return convertMarkToTimestamp(value);
+    });
+}
 
-    auto* timing = m_performance.timing();
-    if (!timing)
-        return Exception { SyntaxError, makeString("No mark named '", markName, "' exists") };
+ExceptionOr<double> PerformanceUserTiming::convertMarkToTimestamp(const String& mark) const
+{
+    if (!is<Document>(m_performance.scriptExecutionContext())) {
+        if (isRestrictedMarkNameNonMainThread(mark))
+            return Exception { TypeError };
+    } else {
+        if (auto function = restrictedMarkFunction(mark)) {
+            if (function == &PerformanceTiming::navigationStart)
+                return 0.0;
 
-    if (auto function = restrictedMarkFunction(markName)) {
-        double value = ((*timing).*(function))();
-        if (!value)
-            return Exception { InvalidAccessError };
-        return value - timing->navigationStart();
+            // PerformanceTiming should always be non-null for the Document ScriptExecutionContext.
+            ASSERT(m_performance.timing());
+            auto timing = m_performance.timing();
+            auto startTime = timing->navigationStart();
+            auto endTime = ((*timing).*(function))();
+            if (!endTime)
+                return Exception { InvalidAccessError };
+            return endTime - startTime;
+        }
     }
 
-    return Exception { SyntaxError };
+    auto iterator = m_marksMap.find(mark);
+    if (iterator != m_marksMap.end())
+        return iterator->value.last()->startTime();
+
+    return Exception { SyntaxError, makeString("No mark named '", mark, "' exists") };
 }
 
-ExceptionOr<Ref<PerformanceMeasure>> UserTiming::measure(const String& measureName, const String& startMark, const String& endMark)
+ExceptionOr<double> PerformanceUserTiming::convertMarkToTimestamp(double mark) const
 {
-    double startTime = 0.0;
-    double endTime = 0.0;
+    if (mark < 0)
+        return Exception { TypeError };
+    return mark;
+}
 
-    if (startMark.isNull())
+ExceptionOr<Ref<PerformanceMeasure>> PerformanceUserTiming::measure(const String& measureName, const String& startMark, const String& endMark)
+{
+    double endTime;
+    if (!endMark.isNull()) {
+        auto end = convertMarkToTimestamp(endMark);
+        if (end.hasException())
+            return end.releaseException();
+        endTime = end.returnValue();
+    } else
         endTime = m_performance.now();
-    else if (endMark.isNull()) {
+
+    double startTime;
+    if (!startMark.isNull()) {
+        auto start = convertMarkToTimestamp(startMark);
+        if (start.hasException())
+            return start.releaseException();
+        startTime = start.returnValue();
+    } else
+        startTime = 0.0;
+        
+    auto measure = PerformanceMeasure::create(measureName, startTime, endTime, SerializedScriptValue::nullValue());
+    if (measure.hasException())
+        return measure.releaseException();
+
+    addPerformanceEntry(m_measuresMap, measureName, measure.returnValue().get());
+    return measure.releaseReturnValue();
+}
+
+ExceptionOr<Ref<PerformanceMeasure>> PerformanceUserTiming::measure(JSC::JSGlobalObject& globalObject, const String& measureName, const PerformanceMeasureOptions& measureOptions)
+{
+    double endTime;
+    if (measureOptions.end) {
+        auto end = convertMarkToTimestamp(*measureOptions.end);
+        if (end.hasException())
+            return end.releaseException();
+        endTime = end.returnValue();
+    } else if (measureOptions.start && measureOptions.duration) {
+        auto start = convertMarkToTimestamp(*measureOptions.start);
+        if (start.hasException())
+            return start.releaseException();
+        auto duration = convertMarkToTimestamp(*measureOptions.duration);
+        if (duration.hasException())
+            return start.releaseException();
+        endTime = start.returnValue() + duration.returnValue();
+    } else
         endTime = m_performance.now();
-        auto startMarkResult = findExistingMarkStartTime(startMark);
-        if (startMarkResult.hasException())
-            return startMarkResult.releaseException();
-        startTime = startMarkResult.releaseReturnValue();
-    } else {
-        auto endMarkResult = findExistingMarkStartTime(endMark);
-        if (endMarkResult.hasException())
-            return endMarkResult.releaseException();
-        auto startMarkResult = findExistingMarkStartTime(startMark);
-        if (startMarkResult.hasException())
-            return startMarkResult.releaseException();
-        startTime = startMarkResult.releaseReturnValue();
-        endTime = endMarkResult.releaseReturnValue();
+
+    double startTime;
+    if (measureOptions.start) {
+        auto start = convertMarkToTimestamp(*measureOptions.start);
+        if (start.hasException())
+            return start.releaseException();
+        startTime = start.returnValue();
+    } else if (measureOptions.duration && measureOptions.end) {
+        auto duration = convertMarkToTimestamp(*measureOptions.duration);
+        if (duration.hasException())
+            return duration.releaseException();
+        auto end = convertMarkToTimestamp(*measureOptions.end);
+        if (end.hasException())
+            return end.releaseException();
+        startTime = end.returnValue() - duration.returnValue();
+    } else
+        startTime = 0;
+
+
+    JSC::JSValue detail = measureOptions.detail;
+    if (detail.isUndefined())
+        detail = JSC::jsNull();
+
+    Vector<RefPtr<MessagePort>> ignoredMessagePorts;
+    auto serializedDetail = SerializedScriptValue::create(globalObject, detail, { }, ignoredMessagePorts);
+    if (serializedDetail.hasException())
+        return serializedDetail.releaseException();
+
+    auto measure = PerformanceMeasure::create(measureName, startTime, endTime, serializedDetail.releaseReturnValue());
+    if (measure.hasException())
+        return measure.releaseException();
+
+    addPerformanceEntry(m_measuresMap, measureName, measure.returnValue().get());
+    return measure.releaseReturnValue();
+}
+
+static bool isNonEmptyDictionary(const PerformanceMeasureOptions& measureOptions)
+{
+    return !measureOptions.detail.isUndefined() || measureOptions.start || measureOptions.duration || measureOptions.end;
+}
+
+ExceptionOr<Ref<PerformanceMeasure>> PerformanceUserTiming::measure(JSC::JSGlobalObject& globalObject, const String& measureName, Optional<StartOrMeasureOptions>&& startOrMeasureOptions, const String& endMark)
+{
+    if (startOrMeasureOptions) {
+        return WTF::switchOn(*startOrMeasureOptions,
+            [&] (const PerformanceMeasureOptions& measureOptions) -> ExceptionOr<Ref<PerformanceMeasure>> {
+                if (isNonEmptyDictionary(measureOptions)) {
+                    if (!endMark.isNull())
+                        return Exception { TypeError };
+                    if (!measureOptions.start && !measureOptions.end)
+                        return Exception { TypeError };
+                    if (measureOptions.start && measureOptions.duration && measureOptions.end)
+                        return Exception { TypeError };
+                }
+
+                return measure(globalObject, measureName, measureOptions);
+            },
+            [&] (const String& startMark) {
+                return measure(measureName, startMark, endMark);
+            }
+        );
     }
 
-    auto& performanceEntryList = m_measuresMap.ensure(measureName, [] { return Vector<RefPtr<PerformanceEntry>>(); }).iterator->value;
-    auto entry = PerformanceMeasure::create(measureName, startTime, endTime);
-    performanceEntryList.append(entry.copyRef());
-    return entry;
+    return measure(measureName, { }, endMark);
 }
 
-void UserTiming::clearMeasures(const String& measureName)
+void PerformanceUserTiming::clearMeasures(const String& measureName)
 {
     clearPerformanceEntries(m_measuresMap, measureName);
 }
@@ -164,22 +293,22 @@
     return entries;
 }
 
-Vector<RefPtr<PerformanceEntry>> UserTiming::getMarks() const
+Vector<RefPtr<PerformanceEntry>> PerformanceUserTiming::getMarks() const
 {
     return convertToEntrySequence(m_marksMap);
 }
 
-Vector<RefPtr<PerformanceEntry>> UserTiming::getMarks(const String& name) const
+Vector<RefPtr<PerformanceEntry>> PerformanceUserTiming::getMarks(const String& name) const
 {
     return m_marksMap.get(name);
 }
 
-Vector<RefPtr<PerformanceEntry>> UserTiming::getMeasures() const
+Vector<RefPtr<PerformanceEntry>> PerformanceUserTiming::getMeasures() const
 {
     return convertToEntrySequence(m_measuresMap);
 }
 
-Vector<RefPtr<PerformanceEntry>> UserTiming::getMeasures(const String& name) const
+Vector<RefPtr<PerformanceEntry>> PerformanceUserTiming::getMeasures(const String& name) const
 {
     return m_measuresMap.get(name);
 }

Modified: trunk/Source/WebCore/page/PerformanceUserTiming.h (267401 => 267402)


--- trunk/Source/WebCore/page/PerformanceUserTiming.h	2020-09-22 08:03:38 UTC (rev 267401)
+++ trunk/Source/WebCore/page/PerformanceUserTiming.h	2020-09-22 08:46:36 UTC (rev 267402)
@@ -31,6 +31,10 @@
 #include <wtf/HashMap.h>
 #include <wtf/text/StringHash.h>
 
+namespace JSC {
+class JSGlobalObject;
+}
+
 namespace WebCore {
 
 class Performance;
@@ -37,15 +41,16 @@
 
 using PerformanceEntryMap = HashMap<String, Vector<RefPtr<PerformanceEntry>>>;
 
-class UserTiming {
+class PerformanceUserTiming {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    explicit UserTiming(Performance&);
+    explicit PerformanceUserTiming(Performance&);
 
-    ExceptionOr<Ref<PerformanceMark>> mark(const String& markName);
+    ExceptionOr<Ref<PerformanceMark>> mark(JSC::JSGlobalObject&, const String& markName, Optional<PerformanceMarkOptions>&&);
     void clearMarks(const String& markName);
 
-    ExceptionOr<Ref<PerformanceMeasure>> measure(const String& measureName, const String& startMark, const String& endMark);
+    using StartOrMeasureOptions = Variant<String, PerformanceMeasureOptions>;
+    ExceptionOr<Ref<PerformanceMeasure>> measure(JSC::JSGlobalObject&, const String& measureName, Optional<StartOrMeasureOptions>&&, const String& endMark);
     void clearMeasures(const String& measureName);
 
     Vector<RefPtr<PerformanceEntry>> getMarks() const;
@@ -54,9 +59,16 @@
     Vector<RefPtr<PerformanceEntry>> getMarks(const String& name) const;
     Vector<RefPtr<PerformanceEntry>> getMeasures(const String& name) const;
 
+    static bool isRestrictedMarkName(const String& markName);
+
 private:
-    ExceptionOr<double> findExistingMarkStartTime(const String& markName);
+    ExceptionOr<double> convertMarkToTimestamp(const Variant<String, double>&) const;
+    ExceptionOr<double> convertMarkToTimestamp(const String& markName) const;
+    ExceptionOr<double> convertMarkToTimestamp(double) const;
 
+    ExceptionOr<Ref<PerformanceMeasure>> measure(const String& measureName, const String& startMark, const String& endMark);
+    ExceptionOr<Ref<PerformanceMeasure>> measure(JSC::JSGlobalObject&, const String& measureName, const PerformanceMeasureOptions&);
+
     Performance& m_performance;
     PerformanceEntryMap m_marksMap;
     PerformanceEntryMap m_measuresMap;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to