-
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
PerformanceObserver.observe() needs 'target' #29
Conversation
sync from upstream
sync local branch
Hmm, why? I thought we intentionally omitted target because its always the same. |
It's not always the same.. you can access window.performance for multiple (same domain) iframes. You need a way to distinguish which ones. |
Ah, right.. I see. My guess is that the most common use case will be to observe |
I'm fine with that. How do you specify it that in IDL? |
s/eventTypes/typeFilter in readme example
Good question, not sure. @bzbarsky is this doable? |
You have a few options, depending on the shape of the API you want: Option 1:
Option 2:
Option 3: Add a member to PerformanceObserverInit that allows specifying a The first two options assume that the |
Hm, any of those would work for me. @bzbarsky - any preference? Also, just as a side-note, is it reasonable for var observer = new PerformanceObserver(callback);
o.observe({filterType:["resource"]}); to be limited to window.performance's events? Should it be explicit about what the var observer = window.performance.createObserver(callback); so that it's clear the scope. Thoughts? |
I think my preference would be to just add a dictionary member in this situation. For the rest, I think having which things the observer observes be magic is pretty confusing; having those be explicit either via a constructor argument or factory function would make more sense to me... |
Ok, so in the interest of "no magic" does Constructor(PerformanceObserverCallback callback)
void observe(Performance target, PerformanceObserverInit options); B: Constructor(Performance target, PerformanceObserverCallback callback)
void observe(PerformanceObserverInit options); or C: Constructor(PerformanceObserverCallback callback)
void observe(PerformanceObserverInit options);
dictionary PerformanceObserverInit {
required sequence<DOMString> typeFilter;
required Performance target;
}; sound better?
|
Well, the first question is why there is this distinction between constructor and observe method at all. Can a single |
Yes.. So the way it's currently set up, you create one observer and it can observe multiple targets, but only have one set of filter criteria per target. And it can start and stop observations on those targets independently. The other way to set it up would be create an observer that is hardcoded to a particular filter criteria and target, and have start & stop method that takes no arguments. The only reason we picked the current direction is to keep it more in line with mutation observers (which function this way) and people more or less understand now. We don't yet have a use-case argument one way or the other. |
(Currently, if you call observe with the same target, it will just adjust the filter criteria on that target to be the new ones you supplied.) |
I can't think of any reasons why we would want to disallow observing multiple Performance instances. (c) with target as part of the dictionary seems reasonable. Can we also make it default to window.performance? |
Actually, wait.. You're relying on the fact that "name" is reporting a URI, which is not true for all event types. |
Well, it's true for resource, render and composite events. For user timing events it will be user-specified so I think that's fine as well. |
That said, I'm not sure if this is an issue, since this would be opt-in behavior.
Make target optional, and as part of processing define it as window.performance if left unspecified? I'm not sure if IDL allows us to define the default as "performance interface of current context". |
"required" doesn't seem to be a keyword in http://www.w3.org/TR/WebIDL/ dictionary PerformanceObserverInit {
required sequence<DOMString> typeFilter
optional Performance target
} or dictionary PerformanceObserverInit {
required sequence<DOMString> typeFilter
Performance? target
} ? |
Does this look any better? |
This is a slight tangent, but since we're iterating on the dictionary, a couple of thoughts: Instead of defining
To address #30, we can then define processing as "typeFilter is a required field that must be a non-empty sequence". The benefit here is that this would nudge developers to be specific about what they want to observe and explicitly opt-in into each event.. which is something we want to encourage to avoid unnecessary overhead. Thoughts? |
I don't think we should add this target argument, it's too easy for a developer to leak the whole context across frames and it's very strange to create an observer in one context and observe the entries in another. For example the entries in that other context will have properties with the wrong prototypes unexpectedly, (ex. Arrays will have a different Array.prototype), and the PerformanceEntry objects themselves will be of a different type. |
I have no objection to this. |
I much rather would go the route of having the context defaulted to the current context (however you define that in IDL), and provide the API to specify a different Performance context. The use case for this being in Firefox OS, we can observe in our System/parent process for performance entries generated in child processes, e.g. individual applications. This would give us the ability to observe without needing to create an observer in each individual application, especially for ones which we do not control. |
As @esprehn noted earlier (#29 (comment)) this runs the risk of opening up some weird behaviors. As one further example, the timestamps will have different time origins and there is no way to tell which origin each event belongs to. FWIW, you can still get the behavior you want, you'll just need to create separate observers (~process.performance.createObserver) and then provide own logic for how/if you want to merge those and/or translate the timestamps.
This last bit sounds like a security hole? :) |
Heh, possibly, I hadn't really thought it through, was more concerned with the API. |
Anything you could have done with var observer = new PerformanceObserver(callback);
observer.observe({target:otherwindow.performance, typeFilter:["server"]}); you can do with var observer = otherwindow.performance.createObserver(callback);
observer.observe({typeFilter:["server"]}); It sounds like we have a consensus, more or less. Right? |
Ok, I sync'ed with the w3c/performance-timeline gh-pages and updated the API from |
The merge history on this pull request is getting confusing. Moving request to #35, using the new interface. Thanks! |
Resolved via #35, closing. |
Sorry I was on vacation, I disagree with bz that: "That's weird magic-at-a-distance that I personally think we should try to avoid in API design." That's how new Text() gets an ownerDocument, how new EventSource() finds an origin, how new Notification() works, how new Worker() gets an origin... most of the web platform is based around the idea of looking up objects in the current context. Unless we plan to never add another object that looks up the document on the current window this shouldn't be any different about looking up the current performance instance. |
Strong -1 for changing from
It's no more magical than The way I think about it is that if we ever did want to fully expose what's going on here, we'd add a |
PerformanceObserver.observe(options) should really be PerformanceObserver.observe(target, options) , where 'target' is a Performance.
The API is a little vague otherwise.
Not sure if this means we want to introduce observer.disconnect(target) or just keep observer.disconnect() as a "disconnect all" function.