- From: Catalin Grigoroscuta <cataling@adobe.com>
- Date: Thu, 1 Aug 2013 10:26:41 +0100
- To: François REMY <francois.remy.dev@outlook.com>, Mihnea-Vlad Ovidenie <mihnea@adobe.com>, Boris Zbarsky <bzbarsky@mit.edu>, "www-style@w3.org" <www-style@w3.org>
On 7/31/13 7:25 PM, "François REMY" <francois.remy.dev@outlook.com> wrote: >>>Just another reason why not having getNamedFlow(id) is problematic: >>> >>>- you may want to ask the NamedFlow for a flow that doesn't exist yet >>>because the style hasn't been computed (or, depending on the browser, it >>>may or may not have been computed because of different codepaths). >> >> I am not sure about this use-case. Why would you want to do such thing? >> Can you please elaborate? > >You may want to add listeners to a named flow before the page actually >finished loading, and there's no good way to know when all the >stylesheets have been downloaded and applied (you don't want to use the >"load" event because it waits on images). > >Also, you may just want to listen to events on a flow that do not exist >yet but you suspect some script or media query could make alive depending >on conditions you don't want to know about (you just want to know when >you should start acting on the flow). > This is one way to do it, for the case where you know the name of the named flow in advance. Another solution which solves a more general case is to trigger an event when a named flow is created. While this solves the theoretical problem, I don't know a real life use case where this would be needed. What would you do anyway with the NamedFlow object before the images are loaded and the layout completed? > > > > > >> Before moving further with the discussion, would you like to detail the >> behavior of getNamedFlow(flow_identifier) method? Is this method >>supposed >> to stay on the Document interface? What should return this method in the >> case you are calling with a flow_identified that does not exist at the >> call time? > >The function {document.getNamedFlow(...)} would work the same way as >{document.getNamedFlows().namedItem(...)} would, except that you don't >need to return the list of all the active flows so if the page is not >ready yet or the flow do not exist yet, you can return a dummy flow whose >state is NULL according to the spec, at least until the user ask for a >property on the flow (at that point, you've to update the flow state >anyway), but you avoid these steps altoegether if the user intent was >just to add an event listener, which is the most probable use case anyway. > > > >By the way, even if Webkit maintains a live list of named flows at all >time (ie: recompute the styles on the page after every .className >update), that doesn't mean every implementation will have to. I can >perfectly imagine some browsers do not recompute the styles on the page >before they actually need it. For those browsers, calling >getNamedFlows().namedItem('content") would force them to recompute the >styles on the whole page to get an accurate static list of active flows, >whereas they can skip that stuff if I just call getNamedFlow('content") >by returning me the current live NamedFlow object for the flow if it >exists. > > > > > > >Also, did you know I can easily create an unfixable memory leak using the >current NamedFlow API? If I add a listener to a flow that *exists* at >time "T", and that the listener holds a reference to some objects on my >page because of a closure, and then that the flow stops to be active, >I've no way of unregistering the event to the flow because it won't show >up in getNamedFlows anymore... while it still exists in memory! > >You can prove that by using an expando property on it with the following >code (assume #region is the only selector affecting the 'abc' flow to an >element): > > // put stuff on a flow > f=document.webkitGetNamedFlows()["abc"] > f.a="a" > f=null > > // the flow stops to be active > region.id='boo' > > // impossible to get a reference to the flow anymore > f=document.webkitGetNamedFlows()["abc"] // undefined > > // to prove memory leaked, I can reinstanciate the flow > boo.id='region' > f=document.webkitGetNamedFlows()["abc"] > f.a // "a" > I think this is the intended behavior of the spec, comes as a consequence of NamedFlow being a "live object": "A NamedFlow object is live: it always represents the named flow with the corresponding name even if that named flow has transitioned to the NULL state." Since it requires a programatic action to put a named flow in the NULL state (remove all flow-from and flow-into references to that named flow, or do something programmatically that triggers this), the developer has the opportunity to clean up any expandos at that point. Alternatively, this could also be solved using the events approach, by triggering an event when a named flow enters the NULL state (and perhaps a similar event when it enters the CREATED state again). But again, it would be good to bring up a real life use case where this is needed. > > >A solution to this issue would be to return in getNamedFlows() a sequence >of all the flows that either: >- are active right now >- have an expando property on them, or have been mutated in JS in any >observable way (including event listeners) -- those NamedFlow objects >cannot be GCed without affecting the JS world, which is why they aren't >GCed right now. > >That way, a library can properly clean up his actions by unregistering to >all flows, even those that potentially went inactive between the >registration and unregistration time. Obviously the best option would be >for this library to keep a reference to all flows it registers to, but it >may be difficult or unwanted for some reason. It may already be easier to >store a list of the flow names that have been listened to, in which case >my proposed getNamedFlow function may suffice to clear this issue. >
Received on Sunday, 4 August 2013 11:53:07 UTC