-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add entryType-specific parameters for observe() #104
Conversation
This PR adds a PerformanceEntryObserverOptions dictionary where entryType-specific parameters are used. The buffered flag is moved to this dictionary. Some <i> tags are changed to <var>. Observe() is updated to consider dictionaries. Queueing an entry is modified to allow passing in a closure. This is in preparation for adding thresholds to certain entry types. Solves w3c#103
Per comment by @tdresser, instead of using a closure we refer to an optionally defined algorithm, similar to how its done in https://dom.spec.whatwg.org/#concept-node-clone-ext.
index.html
Outdated
}; | ||
</pre> | ||
<dl> | ||
<dt><dfn>entryTypes</dfn></dt> | ||
<dd>A list of entry types to be observed. The list MUST NOT be empty | ||
and types not recognized by the user agent MUST be ignored.</dd> | ||
</dl> | ||
<p class="note">Whenever a new kind of <a>PerformanceEntry</a> is defined, this | ||
dictionary should be augmented to include a new optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is "this dictionary"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is in the section titled 'PerformanceObserverInit dictionary' so I think it's clear enough? To reduce ambiguity I could replace that with 'the PerformanceObserverInit dictionary'.
index.html
Outdated
<var>should append to observer</var> which receives a <a>PerformanceEntry</a> and | ||
a <a>PerformanceObserver</a> as input and returns a boolean specifying whether the | ||
observer should be notified of the entry. | ||
<p>The <dfn>queue a PerformanceEntry</dfn> <var>new entry</var> with an optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not following the grammar of this sentence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, which? The one starting with Specifications, or with 'The queue'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely The queue sentence is incorrect. The first word should be 'To'.
index.html
Outdated
<a data-lt="PerformanceObserverInit.entryTypes">entryTypes</a> includes it or it | ||
has a dictionary with that name.</li> | ||
<li><var>should append to observer</var>(<var>new entry</var>, | ||
<var>observer</var>) returns true, if defined by the <i>specification</i> of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For cloning steps, I thought there was an inheritance like approach taken, where specs could override the default. That feels a bit slicker than what we've got here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm no, I don't think there is a default. The closure approach has a default, the cloning steps approach says that a specification may specify additional steps that should be run at a certain point in time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this LGTM.
We should get other folks to take a look though.
index.html
Outdated
<a data-lt="PerformanceObserverInit.entryTypes">entryTypes</a> includes it or it | ||
has a dictionary with that name.</li> | ||
<li><var>should append to observer</var>(<var>new entry</var>, | ||
<var>observer</var>) returns true, if defined by the <i>specification</i> of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right!
Ping Ilya and Todd (or who else could be a good reviewer for this?) |
index.html
Outdated
// retrieve buffered events and subscribe to new events | ||
// for Resource-Timing and User-Timing | ||
// subscribe to new events for Resource-Timing and User-Timing | ||
// and retrieve buffered events from Resource-Timing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably worth spelling out explicitly what's going on here. Specially, that providing names to entryTypes
enables monitoring for said type, initialized with some default settings (e.g. buffered = false). Alternatively, you can specify the entryType name as a key and provide a dictionary with custom settings — e.g. resource : {buffered: true}
.
On that note, @toddreifsteck @yoavweiss would love to get your sanity check and review on this pattern.
index.html
Outdated
sequence.</li> | ||
<li>For each dictionary of name <var>entryType</var> in <var>options</var>, | ||
add the string `<var>entryType</var>` to <var>entry types</var>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I grok what this is doing. What is an example of "each dictionary of name entryType
"? :-)
I think you're enumerating the keys in options and adding them to entryTypes? As an aside, can we actually do this without first cloning the options? As in, I don't think we should be modifying the passed in object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, maybe enumarating keys in options is clearer? Or enumerating keys whose values are dictionaries (to exclude entryTypes itself for example)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per later comment, I don't think we should be modifying this object in place.. But if we're cloning it first, we could: pluck entryTypes out first and <do-stuff>
, then enumerate the remaining keys and <do-more-stuff>
, arriving at a consistent internal object that we can use later in the algorithm?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, so I propose adding something like "Each PerformanceObserver gets an associated |entry types| object". Then here we would modify observer's |entry types| instead of some variable of option's entryTypes array. Does that sound reasonable?
index.html
Outdated
the <a>PerformanceObserverInit</a> dictionary should be augmented to | ||
include a new optional <a>PerformanceEntryObserverOptions</a> dictionary | ||
with the name of the new <a data-lt="PerformanceEntry.entryType"> | ||
entryType</a>.</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't do this today for existing types. If we follow this recommendation, than we should do so.
That said, we've also tried to explicitly avoid enumerating "valid types" in Performance Timeline, as that makes a hard dependency for the perf timeline to be revved whenever we add a new type. Per discussion in #77, the idea is to have other specs call into Perf Timeline to register available types. The logic here should then enumerate the dictionary members, compare against registered + known types and proceed accordingly. This also means that we ignore any unknown types in this algorithm.
WDYT, does that make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not forcing PerformanceTimeline to be modified whenever a new entry type is added. I was thinking the new spec could do something along the lines of 'partial interface' to add the new dictionary corresponding to its entry type. We already "remove all unsupported types", which is a bit hand-wavy but I think it's clear what it means. If we want to make it a bit more formal, we can go with your registration approach, I just don't know if it adds much clarity or if it makes speccing new entry types easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I'm with you now. I like that, that's much cleaner than I what I had in mind before. The one bit I'd change in this proposal is, instead of extending the PerformanceObserverInit
we wanted + need to introduce performance.entryTypes
and that's the interface the various specs should be extending. In turn, we can then filter passed options to PerformanceObserverInit
against said interface.
WDYT, does that make sense? If you're on board with that.. the changes are coupled, and we would need to land the performance.entryTypes
proposal first, and then rebase this against that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I don't follow what you're suggesting here... performance.entryTypes
will only help in knowing which are the entry types that are supported globally (implemented by the browser), right? So we still need a way to specify what filters can be used for each entry type, unless we want to support the same set of filters for all entry types? Even if we have the same set of filters on all entry types, we still need to augment PerformanceObserverInit
with the dictionaries per entry type (I don't think we want to allow it to contain dictionaries like 'longtask' and 'mark' without specifying them anywhere explicitly). The only alternative I can think of that avoids this would be to have something like this:
dictionary PerformanceObserverInit {
required sequence<DOMString> entryTypes;
PerformanceEntryObserverOptions filters;
}
But this would force an observer to apply the same set of filters to all of the observed entry types that it is observing. This is kind of what we're trying to avoid here, since ideally we'd like entryType-specific parameters. If we don't have that, we might as well just keep adding the filters to PerformanceObserverInit
directly. WDYT?
@@ -436,30 +452,39 @@ <h2><dfn>disconnect()</dfn> method</h2> | |||
<h2>Processing</h2> | |||
<section data-link-for="PerformanceObserver"> | |||
<h2>Queue a <code>PerformanceEntry</code></h2> | |||
<p><i>Specifications</i> of performance entries may define an algorithm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe our plan was to have this on by default for all types prior to onload, and no buffering afterwards. If that's the case, I believe we wouldn't need this — correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is about the queue algorithm, not about buffering. An example of where we need this is LongTasks thresholds: we need the spec to provide an algorithm to determine if an entry should be added to an observer (look at the entry's duration, compare with the observer's threshold).
optional <var>add to performance entry buffer</var> flag, which is unset | ||
by default, run these steps:</p> | ||
optional <var>add to performance entry buffer</var> flag, which is unset by | ||
default, run these steps:</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This step should be with respect to before or after onload, not the passed in flag.
For context, we ruled out the flag approach because it would, once again, require updating every upstream spec to have this on by default.. and I can't think of cases where we'd want this to be off by default for before-onload.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, but I haven't added this flag, it's currently in the spec. How about we do a separate PR for this independent change?
index.html
Outdated
<li><var>new entry</var>’s <a data-lt="PerformanceEntry.entryType">entryType</a> | ||
value is in <var>observer</var>'s <a>PerformanceObserverInit</a>: either its | ||
<a data-lt="PerformanceObserverInit.entryTypes">entryTypes</a> includes it or it | ||
has a dictionary with that name.</li> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we doing this here again, if we're modifying entryTypes and adding names to it earlier? Could we preprocess this earlier (either unroll entryTypes into the array with default dicts, or the reverse) and reuse that here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We did this in observe() to the |options| parameter, and now that is gone. I would propose having an internal variable within PerformanceObserver that consists of a list of supported entry types. The list could be populated during observe() and then it could be used here, in the queue an entry algorithm. This is probably how implementations do it anyways. WDYT?
@@ -366,14 +380,27 @@ <h2><dfn>PerformanceObserverInit</dfn> dictionary</h2> | |||
<pre class="idl"> | |||
dictionary PerformanceObserverInit { | |||
required sequence<DOMString> entryTypes; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking we may want to remove the 'required' from |entryTypes| as well as you could specify what you want to observe using the other dictionaries.
By the way I've added the 'supported entry types' and addressed all comments. |
index.html
Outdated
@@ -298,6 +300,9 @@ <h2>The <dfn>PerformanceObserver</dfn> interface</h2> | |||
<li> A <a>PerformanceEntryList</a> object called the <dfn>observer | |||
buffer</dfn> that is initially empty. | |||
</li> | |||
<li>A sequence of strings called <dfn>supported entry types</dfn> that is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/supported entry types/observed entry types/?
I think we should reserve supported entry types
for the global "which entry types does performance timeline support"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
// Subscribe to new events for User-Timing (marks and measures) via the | ||
// |entryTypes| array. The entry-type specific flags are set to their | ||
// default values for these entry types. Also subscribe to and retrieve | ||
// buffered events from Resource-Timing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where's the resource-timing part? It's no longer observed, is it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean in the description, or in the code? In the description, we have at the end "Also subscribe to and retrieve buffered events from Resource-Timing." In the code, per this PR the existence of a dictionary 'resource' implies that this PerformanceObserver observes that entry type.
index.html
Outdated
<li>Set <a>supported entry types</a> to a copy of <var>options</var>' | ||
<a>entryTypes</a> sequence. | ||
</li> | ||
<li>For each key <var>entryType</var> in the <var>options</var> dictonary that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/dictonary/dictionary/
agent SHOULD notify developers if <var>entry types</var> is modified. | ||
For example, a console warning listing removed types might be appropriate.</li> | ||
<li>If the resulting <var>entry types</var> sequence is an empty sequence, | ||
<li>Set <a>observed entry types</a> to a copy of <var>options</var>' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'd be better to explicitly state what the options variable is a line above that.
e.g. "Let options be the input PerformanceObserverInit object" or something along those lines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I think you meant "observed entry types" to be a var, not a link
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added what observer() receives. I really do mean a link to the associated concept of the PerformanceObserver, not a local var. So is correct in this context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*so <a> is correct
index.html
Outdated
<li>Set <a>observed entry types</a> to a copy of <var>options</var>' | ||
<a>entryTypes</a> sequence. | ||
</li> | ||
<li>For each key <var>entryType</var> in the <var>options</var> dictonary that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/dictonary/dictionary/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
index.html
Outdated
</li> | ||
<li>For each key <var>entryType</var> in the <var>options</var> dictonary that | ||
is not <a>entryTypes</a>, add the string <var>entryType</var> to | ||
<a>observed entry types</a>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not clear to me what this does and why. Can you explain?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I mean is: add the entry types that are listed as dictionaries in 'options' to the set of entry types that are observed by this observer. In the example in the code, we had:
observer.observe({
entryTypes: ["mark", "measure"],
resource : {buffered: true}
});
In this case, there is a resource
dictionary. So this step means: since the key resource
is present, add 'resource' to the list of observed entry types
.
I think @igrigorik wanted your opinion on whether this is sane or not. If we think this is too ugly, we can remove this part, so that all entry types to be observed must still be listed in the entryTypes
array.
index.html
Outdated
is not <a>entryTypes</a>, add the string <var>entryType</var> to | ||
<a>observed entry types</a>. | ||
</li> | ||
<li>Remove all unsupported types from <a>observed entry types</a>. The user |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we define somewhere what are the supported types? Can we point to such a definition?
Also, can you rewrite that as an iteration over the sequence?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not define this (this is browser-dependent). If/when we expose performance.entryTypes
then we can point to that, but for now I think we don't have a definition. Rewrote as an iteration (although note that this wording was already present before this PR).
<var>entry type</var> in <var>entry types</var> sequence: | ||
<li>For each <var>entry type</var> in <a>observed entry types</a>, if the | ||
<a data-link-for="PerformanceEntryObserverOptions">buffered</a> flag is set | ||
in <var>options</var>' dictionary named <var>entry type</var>: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
options
is a PerformanceObserverInit
, right? Or is it PerformanceEntryObserverOptions
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but buffered
would be inside the PerformanceEntryObserverOptions
corresponding to that entry type (if it exists), which is itself inside the PerformanceObserverInit
options
. I moved this flag so that it can be an entryType-specific parameter.
index.html
Outdated
<p class="note">Whenever a new kind of <a>PerformanceEntry</a> is defined, | ||
the <a>PerformanceObserverInit</a> dictionary should be augmented to | ||
include a new optional <a>PerformanceEntryObserverOptions</a> dictionary | ||
with the name of the new <a data-lt="PerformanceEntry.entryType"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not clear what you mean by "the name of the new entryType". Can you be more explicit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I mean is that PerformanceObserverInit
needs to be augmented for example if we were adding EventTiming with entries that have entryType 'event':
partial dictionary PerformanceObserverInit {
optional PerformanceEntryObserverOptions event;
}
I reworded that last part, is it better now?
I don't think this approach fits *Observer pattern well. See my comment in #103 (comment). |
I'm open to changing the shape of the API but we probably want something that is backwards compatible. Changing observe() to only allow specifying one type per observe() call isn't. |
We can support both. Either specify a list of types to observe, or specify a type and it's options. |
I'm closing this PR and later sending a new one based on the discussion in #103 |
This PR adds a PerformanceEntryObserverOptions dictionary where entryType-specific parameters are used. The buffered flag is moved to this dictionary. Some <i> tags are changed to <var>. Observe() is updated to consider dictionaries. Queueing an entry is modified to allow passing in a closure. This is in preparation for adding thresholds to certain entry types. Solves #103
@igrigorik @tdresser @toddreifsteck PTAL
Preview | Diff