I've been thinking about non-same-document references in SVG, and wanted to check on something. When the referenced document should be loaded from the network, and when is it OK to use an already-parsed version?
For comparison, here are the caches that seem similar to me that we already have:
1) Image cache. This stores decoded images, and tries to do cache entry validation (looking at Expires times, etc) before hitting the cache. This is because web pages actually rely on images being refetched from the server when setting .src to its current value, in many cases. The decoded images are shared across documents, but there is a way to associate a particular cache request with a particular document, to handle force-reload and the like.
If I understand correctly, if http://foo.com/bar.gif points to a no-cache no-store image, we will hit the server twice given the markup:
2) Stylesheet cache. There are several caches here, actually, all storing the parsed representation of a stylesheet. There's a global cache that's only used for chrome stylesheets. Once we've loaded such a stylesheet, it's in the cache for the lifetime of the app (modulo skin switches). There is also a per-document cache. Once we load a sheet for the document, it's in this cache for the lifetime of the document.
In other words, if http://foo.com/bar.css is a no-cache no-store stylesheet, and I have this HTML:
My first instinct is that it would make the most sense to have SVG behave the way CSS does. That is, have a per-document cache that caches the referenced SVG documents and never revalidates for the lifetime of the document doing the referencing.
Does that make sense? If so, what about stylesheets? If a stylesheet points to some SVG, should the resulting SVG document be associated with that stylesheet, or with the document the stylesheet is attached to? Note that right now there might not even be much of a difference between those options in Gecko, since we don't cache stylesheets across documents, but at some point we might want to start doing that.
Also note that if we ever give DOM access to these referenced SVG documents the issue of how much they're shared becomes particularly acute, since it becomes a lot more testable: mutate the document and see what updates.
Thoughts?
-Boris
P.S. Any setup like this will mean either weaning GetPaintServer off of its dependence on having an nsIFrame or creating frame trees for these cached SVG documents. Honestly, the former sounds easier to me, especially if we don't allow mutation of the referenced documents (at which point we can just resolve style and stick it on the nodes or something).
On Jun 11, 4:35 pm, Boris Zbarsky <bzbar...@mit.edu> wrote:
> My first instinct is that it would make the most sense to have SVG behave the > way CSS does. That is, have a per-document cache that caches the referenced SVG > documents and never revalidates for the lifetime of the document doing the > referencing.
> Does that make sense? If so, what about stylesheets? If a stylesheet points to > some SVG, should the resulting SVG document be associated with that > stylesheet, or with the document the stylesheet is attached to?
I think it should be associated with the document the stylesheet is attached to. One reason for doing that is that I'd like to create a DOM API that lets documents access the DOM of these resource documents, and if there's only one resource document per (base document, URI) pair, then that API will be much simpler.
> Note that right > now there might not even be much of a difference between those options in Gecko, > since we don't cache stylesheets across documents, but at some point we might > want to start doing that. > Also note that if we ever give DOM access to these referenced SVG documents the > issue of how much they're shared becomes particularly acute, since it becomes a > lot more testable: mutate the document and see what updates.
Yep. We can still share resource documents across base documents as long as we do a copy-on-write scheme. It should be easy enough for the DOM API to clone a shared resource document the first time it's referenced from a base document.
> P.S. Any setup like this will mean either weaning GetPaintServer off of its > dependence on having an nsIFrame or creating frame trees for these cached SVG > documents. Honestly, the former sounds easier to me, especially if we don't > allow mutation of the referenced documents (at which point we can just resolve > style and stick it on the nodes or something).
I think we need to create frame trees. For example, one can reference an SVG <pattern> containing a <foreignObject> containing anything at all. Also, without frame trees we don't have a way to track style changes.
There is a related problem that display:none <pattern>s are still supposed to render. I'm not sure what we do about that right now, but for the above reasons I don't have a good solution other than change the spec. I probably should discuss that with the WG. I suppose we could try something crazy like create isolated frame subtrees for <svg> elements in display:none subtrees.
rob...@ocallahan.org wrote: > I think it should be associated with the document the stylesheet is > attached to.
Hmm. See, the same style data can be attached to multiple documents (in the case of chrome sheets, at least). From the point of view of web content this will never be a problem (just like there is no problem with images right now), but if someone tries to stick SVG into a chrome sheet things would be pretty odd if we do the loading at style resolution time like we do for images... Here "odd" means that it would only work for the first chrome document to use the sheet.
I'll think about this some more.
> Yep. We can still share resource documents across base documents as > long as we do a copy-on-write scheme.
And a cache-invalidation scheme, at that point... or something.
> I think we need to create frame trees. For example, one can reference > an SVG <pattern> containing a <foreignObject> containing anything at > all. Also, without frame trees we don't have a way to track style > changes.
Hmm. So right now frame trees (and style resolution for that matter) have various dependencies on being in a prescontext which is in a docshell. We'll have to remove all those assumptions.
On Jun 14, 8:03 am, Boris Zbarsky <bzbar...@mit.edu> wrote:
> rob...@ocallahan.org wrote: > > I think it should be associated with the document the stylesheet is > > attached to.
> Hmm. See, the same style data can be attached to multiple documents (in the > case of chrome sheets, at least).
OK, I didn't know that.
> From the point of view of web content this > will never be a problem (just like there is no problem with images right now), > but if someone tries to stick SVG into a chrome sheet things would be pretty odd > if we do the loading at style resolution time like we do for images... Here > "odd" means that it would only work for the first chrome document to use the sheet.
Then let's disable external document references for chrome, or find a way to selectively not share that style data. I don't think we should allow chrome implementation issues to affect the design of a feature for the Web.
> > Yep. We can still share resource documents across base documents as > > long as we do a copy-on-write scheme.
> And a cache-invalidation scheme, at that point... or something.
I was going to point out a problem if we give away nsIContent* references to a shared document and then decide to clone it later. But we shouldn't be giving out such references really; nsReferencedElement can track a reference changing from one element to another, and nsIContent* references obtained from nsReferencedElement should not be retained.
It's probably obvious but nsReferencedElement also solves the problem of asynchronous loading. References to an external document will start off matching nothing and when the document loads and the referenced element becomes available, we'll handle that reference change like any other.
> > I think we need to create frame trees. For example, one can reference > > an SVG <pattern> containing a <foreignObject> containing anything at > > all. Also, without frame trees we don't have a way to track style > > changes.
> Hmm. So right now frame trees (and style resolution for that matter) have > various dependencies on being in a prescontext which is in a docshell. We'll > have to remove all those assumptions.
What's the best change to make? Make prescontext/presshell work without a docshell? Create a docshell for external documents?
rob...@ocallahan.org wrote: > Then let's disable external document references for chrome, or find a > way to selectively not share that style data. I don't think we should > allow chrome implementation issues to affect the design of a feature > for the Web.
The former is easier in the short term, I guess. I'd like to think about this a little more, in any case.
>>> I think we need to create frame trees. For example, one can reference >>> an SVG <pattern> containing a <foreignObject> containing anything at >>> all. Also, without frame trees we don't have a way to track style >>> changes. >> Hmm. So right now frame trees (and style resolution for that matter) have >> various dependencies on being in a prescontext which is in a docshell. We'll >> have to remove all those assumptions.
> What's the best change to make? Make prescontext/presshell work > without a docshell? Create a docshell for external documents?
I'm not sure offhand. Both will require a good bit of code auditing to make sure we don't introduce various issues...
The auditing needed for the second one is more or less identical to the auditing needed to allow docshells out of a docshell tree in general, so that may be more fruitful at least.
rob...@ocallahan.org wrote: >>> Yep. We can still share resource documents across base documents as >>> long as we do a copy-on-write scheme. >> And a cache-invalidation scheme, at that point... or something.
> I was going to point out a problem if we give away nsIContent* > references to a shared document and then decide to clone it later. But > we shouldn't be giving out such references really; nsReferencedElement > can track a reference changing from one element to another, and > nsIContent* references obtained from nsReferencedElement should not be > retained.
> It's probably obvious but nsReferencedElement also solves the problem > of asynchronous loading. References to an external document will start > off matching nothing and when the document loads and the referenced > element becomes available, we'll handle that reference change like any > other.
What's nsReferencedElement? Would it be a full implementation of all the interfaces supported by elements, but that would defer all the DOM stuff to an internal 'real' element?
This is basically what the XUL prototypes are. It turns out that there isn't much that can be shared except attribute values. Though this is a decent win of course. One possible way to solve this would be to make XUL prototypes usable by all elements, not just XUL. It would simplify some code and make other code more complex, but I think it's doable in a decent amount of time.
But wouldn't clone-on-reference be simpler to implement? I.e. when someone grabs a reference to the inner document using script we clone at that point. Seems like the only real usecase for grabbing the inner document is to mutate it anyway, no?
In fact, we can do clone-on-reference for now, and at some point in the future implement generic prototypes which would make the cloning more lightweight.
On Jun 26, 8:09 am, Jonas Sicking <jo...@sicking.cc> wrote:
> What's nsReferencedElement? Would it be a full implementation of all the > interfaces supported by elements, but that would defer all the DOM stuff > to an internal 'real' element?
No! http://mxr.mozilla.org/mozilla-central/source/content/base/public/nsR... It's just a helper class for tracking which element is associated with a given ID and sending notifications when that changes. I'm having SVG use it in various places, but really we need it everywhere we have URI references to elements in mutable documents.
I should really write some better comments for it. I'll do that now.
Another interesting question. Should scripts execute in the external SVG document? That is, if I have a document that references "url(foo.svg#bar)" and foo.svg has <script> elements, should they execute?
Boris Zbarsky wrote: > Another interesting question. Should scripts execute in the external > SVG document? That is, if I have a document that references > "url(foo.svg#bar)" and foo.svg has <script> elements, should they execute?
I would say no. That seems like a big can of security worms. I think we and others have decided not to do that for <img src=foo.svg> for example.
On Jul 9, 12:41 pm, Jonas Sicking <jo...@sicking.cc> wrote:
> Boris Zbarsky wrote: > > Another interesting question. Should scripts execute in the external > > SVG document? That is, if I have a document that references > > "url(foo.svg#bar)" and foo.svg has <script> elements, should they execute?
> I would say no. That seems like a big can of security worms. I think we > and others have decided not to do that for <img src=foo.svg> for example.
> / Jonas
I agree with this. Just to continue exploring this, this would have to include onload, onclick, etc attributes on the referenced SVG element?
codedread wrote: > I agree with this. Just to continue exploring this, this would have > to include onload, onclick, etc attributes on the referenced SVG > element?
Yes for the former. The latter would have been the case no matter what: since we're just using the element as a paint server, there is no event dispatch to it, I would think.