Skip to content
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

Use element re-write & related changes #206

Merged
merged 38 commits into from
Jul 28, 2016
Merged

Use element re-write & related changes #206

merged 38 commits into from
Jul 28, 2016

Conversation

AmeliaBR
Copy link
Contributor

@AmeliaBR AmeliaBR commented Jul 13, 2016

Overview

Re-write all text related to <use> element
to be compatible with shadow DOM,
to define all the aspects of use elements that are currently undefined
(including those we'd added warnings about last year),
and to address various related issues.

To make it easier to review, I've pushed a built version of the changes to my GitHub Pages branch.

Major changes are in the section on the Use element.

Other changes include:

See below & issues in the text for some remaining questions. Please do not merge until the issues I've added have been removed from the source code.

Breaking Changes from SVG 1.1

Many of these features were never implemented to the SVG 1.1 spec in Firefox; in Blink, some SVG 1.1 aspect were previously implemented but have since been changed (to be closer to the new shadow DOM model).

  • Use element shadow trees now consist of actual SVGElement objects in a proper shadow DOM node tree, not SVGElementInstance pseudo-nodes.
  • The root of the shadow tree is a ShadowRoot object.
  • Events bubbling out of a use-element shadow tree must follow the shadow DOM re-targetting rules.
  • Styles rules are resolved independently for clones versus the referenced graphics; in some cases (particularly re interactive pseudo-classes), this will result in different styles than the SVG 1.1 model.
  • Some interactive animations are now triggered independently on the shadow content vs the referenced graphics.
  • Never-rendered elements will now have a computed style of display: none. Rendering shouldn't change.

Other new requirements & functionality

  • The shadow tree must now have a ShadowRoot object, and implement extra functionality from shadow DOM specs.
  • A new interface SVGUseElementShadowRoot is defined, inheriting from ShadowRoot, in case we want to add functionality later that is unique to use-element shadow trees.
  • All elements in a subtree must now be cloned, not only graphics elements.
  • The shadow tree has scoped stylesheets.
  • Symbol elements can have x/y/width/height properties.
  • SVGElement has been extended to replace the core functionality from SVGElementInstance.
  • SVGSymbolElement now inherits from SVGGraphicsElement (so you can call getBBox, etc., on a symbol instance)
  • A ShadowAnimation interface is defined, to represent WAAPI animations that need to be cloned to apply to an element instance, but must be kept in sync with their source.

Clarified requirements (undefined or inconsistently implemented from SVG 1.1)

  • External files are processed in secure static mode, so scripts don't run and references to additional resources are not followed unless the elements that reference those resources are actually cloned into this document. Same-document style blocks, however, are processed, and those style rules are copied over and must apply in the shadow DOM scope. Media queries in those copied stylesheets are interpretted in the main document's media. Animations do not run in the external document, but they are copied over to the shadow tree, where they operate in the main document's timeline.
  • External files do not have to be .svg files, so long as the referenced element can be a child of an SVG container element.
  • Percentage lengths in shadow DOM content are resolved based on the coordinate system into which they are rendered, not based on the source. This is consistent with SVG 1.1 spec text, but inconsistent with implementations.
  • A use-element shadow tree must not be generated if the ‘use’ element is excluded because of conditional processing.
  • Web Animations API animations must be duplicated, in addition to animation element. CSS animations & transitions are covered under the general stylesheet duplication, and so are not duplicated directly.
  • Animation elements that are triggered by an event on another element are also triggered by that event on an instance of the other element.
  • Event listeners defined with addEventListener are copied to instances, the same as event attributes.
  • secure processing mode is required for external resource files
  • when a same-document URL reference to a resource can't initially be matched, the user agent should listen for DOM changes (e.g., new elements inserted) to find the match when available

Clarifications or changes from previous drafts of SVG 2

  • All aspects of use elements referencing external resources are now defined, so no warnings are required. (Except there is still a warning re CORS not being supported, I haven't changed that.)
  • refX, refY on symbol have an initial value of (none), different from a value of 0, to preserve backwards compatibility when the symbol has a viewBox.
  • audio and video elements have additional requirements to maintain synchronization.
  • A use element is not automatically a stacking context. Patterns, markers, etc. are automatically isolation groups for blending. Previous draft of the rendering chapter tried to apply the same rules for both cases.
  • Role mappings for symbol and use have been changed to reflect that use-element shadow content must be fully accessible.
  • The instanceRoot (and animatedInstanceRoot) IDL properties have been restored on SVGUseElement. The animated version is just an alias, there's no requirement to maintain multiple shadow trees.

Issues Addressed

When merged, this pull request:

Issues Remaining

Most of these are noted in the textAll resolved, with only a couple permanent issues re at-risk features:

  • I would really, really prefer to have x/y/width/height on <use> elements be proper geometric properties, instead of simple attributes. I just haven't quite figured out how that would conceptually work. As is, it's going to be a surprise & a pain for authors who are going to want to control these properties with CSS.

    Resolved: Made the switch, as discussed. One way or the other, values on the use element override CSS properties on the shadow child; might as well make the use values convenient.

  • Re defs element: Is there any justification for continuing to recommend "that, wherever possible, referenced elements be defined inside of a ‘defs’ element"?

    Resolved: Removed/replaced with a gentler suggestion for good code organization

  • Re resolving cross-references: Should this section, or parts of it, be moved to the Linking chapter, and made to apply for all external resources (e.g., external paint servers, filters, etc.)? Also: Do we need to reference specifics re fetching an external document and security modes? Related to Update href attribute descriptions to reference HTML51's obtain the resource algorithm #90.

    Resolved: Section is moved & greatly re-written to make it apply to all external resources, including specifics re fetching & security

  • Should there be some sort of load event that is dispatched after the use tree is successfully generated? If so, which event in particular?

    Resolved: Make this a future wish list item

  • Does it make sense that conditional processing stop formation of a use-element shadow tree? Consistent with audio/video not playing with conditional processing (see Does conditional processing mute sound playback? #44), and with the idea that it stops all processing (including fetching external resources), not only rendering. (display: none does not prevent shadow tree formation).

    Resolved: Conditional processing only affects display, not processing.

  • Is NoModificationAllowedError the best choice for the error type whenever something is blocked by the read-only nature of the shadow tree? (Other options include ReadOnlyError and NotAllowedError.) Needs to encompass both DOM modification attempts as well as attribute or property changes.

Resolved: Keep it as written.

  • Should width & height on a use element affect foreignObject and embedded content? The section on establishing a new viewport also includes foreignObject, iframe, and image, although then it qualifies that for image and iframe the new viewport actually is created by the root element of the embedded document. Mostly, that whole section needs re-writing. But for this section: should auto width/height on a re-used foreignObject be influenced by width/height on the use element? SVG 1.1 didn't allow foreignObject to be re-used, so it would not be a breaking change either way.

    Resolved: No, foreignObject doesn't behave like svg/symbol element; referenced section clarified to distinguish between different types of viewports & coordinate system resets.

  • Should the details on how animations work in use shadow trees be moved to the SVG Animations specification and/or WAAPI? Most of the details are dependent on those specs. However, implementers that currently support SVG animation elements and Web Animations are going to need guidance on how to update those implementations to match the new shadow DOM model. Also, it would be nice to have a TR version of SVG Animations to link to!

    Resolved: Keep section here.

  • Is it going to be an implementation hassle to have detached Element objects (cloned animation elements that affect the shadow tree but aren't cloned as part of it) that must behave as if they are part of the node tree? Another option would be to actually make them additional child nodes of the ShadowRoot node. I don't think that would have any problematic side effects, although I'd need to change the wording a few places where I specify that the use-element shadow root only ever has one child.

    Resolved: Keep it as written, unless someone complains when implementing.

  • Is distinguishing between begin="target.event" and begin="event" worth the extra implementation complexity? It creates useful functionality and is consistent with the CSS model, but it is technically a breaking change from SVG 1.1.

    Resolved: Keep it as written.

  • Re SVGElementInstance mixin-interface: Is it appropriate to define this as a [NoInterfaceObject] interface? As defined in this spec, the interface is only used to supplement SVGElement. But SVG 1.1 scripts could be explicitly testing for the presence of Window.SVGElementInstance to determine if the browser supports an inspectable use-element shadow DOM.

    Resolved: Keep as written.

  • Re SVGElementInstance::correspondingElement: Should this still point to a valid element object even if it is in a different document? That implies that the entire DOM of the external file must be maintained in memory (since the element linked from this property would be linked to all other nodes in its DOM tree). I've already said that that external DOM is read-only, so there's no real function to having it available.

    Resolved: Keep as written, but add explanation & at-risk warning.

Still To Do

AmeliaBR added 18 commits July 3, 2016 18:50
- Change definitions of when a symbol will/won't render to reflect shadow DOM model.
- Allow x,y,width,height geometry properties on symbol.
- Make the SVGSymbolElement interface inherit from SVGGraphicsElement, so that it can be queried as a proper container element when it is rendered within the shadow DOM.
(and additional details on layout)
…btree" / "referenced graphics"

(to avoid confusion with "SVG document fragment", which is always rooted by a `<svg>`, and also confusion with the DOM concept of document fragment, e.g. the DocumentFragment interface)
… DOM.

Clarifies differences between use elements and other re-used graphics (e.g. markers, paint servers): use elements are *not* stacking context or isolated group by default.  This is consistent with shadow DOM in general.  Paint servers and markers *are* isolated groups.

Added the term "instance root" to help clarify distinction between rendered and non-rendered symbol elements.
@@ -729,13 +777,13 @@ <h3 id="SymbolAttributes">Attributes</h3>
<tr>
<td><dfn data-dfn-type="element-attr" data-dfn-for="symbol" id="SymbolElementRefXAttribute">refX</dfn></td>
<td><a>&lt;length&gt;</a> | left | center | right</td>
<td>0</td>
<td>(none)</td>
<td>yes</td>
</tr>
<tr>
<td><dfn data-dfn-type="element-attr" data-dfn-for="symbol" id="SymbolElementRefYAttribute">refY</dfn></td>
<td><a>&lt;length&gt;</a> | top | center | bottom</td>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to define what the keywords evaluate to here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, probably just with a link to the equivalent definitions for <marker>.

@nikosandronikos
Copy link
Member

I would really, really prefer to have x/y/width/height on elements be proper geometric properties, instead of simple attributes. I just haven't quite figured out how that would conceptually work. As is, it's going to be a surprise & a pain for authors who are going to want to control these properties with CSS.

Is the only issue the difference in initial values for width and height?

@nikosandronikos
Copy link
Member

Re defs element: Is there any justification for continuing to recommend "that, wherever possible, referenced elements be defined inside of a ‘defs’ element"?

If you can't think of any then I highly doubt it, since the justification is accessibility and understandability. I'm happy for you to remove it.

@nikosandronikos
Copy link
Member

nikosandronikos commented Jul 20, 2016

Re resolving cross-references: Should this section, or parts of it, be moved to the Linking chapter, and made to apply for all external resources (e.g., external paint servers, filters, etc.)? Also: Do we need to reference specifics re fetching an external document and security modes? Related to #90.

It would be nice to have in one place. I'd like to get some review from the HTML and DOM editors so maybe leave it for now and we'll see what they recommend?

@nikosandronikos
Copy link
Member

Should there be some sort of load event that is dispatched after the use tree is successfully generated? If so, which event in particular?

Sounds useful, but has it been discussed before? I say file a new issue tagged 'future wish list' for now.

@AmeliaBR
Copy link
Contributor Author

PS, I could add this example to the note warning about the change, if that would be helpful.

@Tavmjong

@nikosandronikos
Copy link
Member

Should there be some sort of load event that is dispatched after the use tree is successfully generated? If so, which event in particular?

Sounds useful, but has it been discussed before? I say file a new issue tagged 'future wish list' for now.

I've filed this as #214

@adanilo
Copy link

adanilo commented Jul 22, 2016

I really should have paid more attention to this earlier, apologies. Anyway, this is a major breaking change from 1.1, namely specifying an actual clone. I get that aligning with Shadow DOM is a nice idea, but was always supposed to be a 'effective' clone, not an actual one. i.e. it's supposed to be a DAG primitive, not a templating mechanism. As far as I recall, Ikivo, Presto, Abbra and I believe Edge use a DAG approach for rendering. A large number of bugs in webkit/Blink/Gecko are unfortunate side-effects from implementing an actual cloning mechanism, and then trying to keep the clones all in sync when the referenced tree changes. It'd be nicer to have a new element if you want to create true clones IMO, or just not break it:-)

@birtles
Copy link
Contributor

birtles commented Jul 22, 2016

I haven't followed the discussion on this topic so I didn't know we were actually exposing the shadow tree. Assuming that is the approach we want going forward, then I think the animation section here seems reasonable.

However, with regards to how we spec the Web Animations part, I think that rather than defining everything in prose, it would be preferable to introduce a new sub-type of Animation that exhibits the mirroring behavior. e.g.

[Constructor (Animation source)]
interface ShadowAnimation : Animation { };

Then we could define that ShadowAnimation objects throw NoModificationAllowedError (or whatever the appropriate error is in this case) for each of the mutator methods (e.g. pause() etc.).

Furthermore, you might expose the source Animation as a readonly attribute and further spec that this object reflects all changes to source.

So, I guess what I'm suggesting is to define ShadowAnimation as a generic thing that could be potentially used in other situations, and then just use that concept here.

The idea of adding sub-types of Animation is not new. The CSSAnimation and CSSTransition interfaces are already defined elsewhere and we're currently looking at defining a FillAnimation sub-interface that would also throws on most mutation operations--it's slightly different, however, in that it still allows cancelling.

The interaction between FillAnimation objects and ShadowAnimation objects would need to be defined, but first we need to investigate if FillAnimation is going to happen or not.

@AmeliaBR
Copy link
Contributor Author

AmeliaBR commented Jul 22, 2016

@adanilo

I appreciate the input, but I think that it's a little late to reverse course. Certainly, you'd need to convince the Blink team, who have already moved ahead unilaterally with many of the Shadow DOM changes.

Quite frankly, with the movement of geometry to CSS, including the potential to inherit a variable that changes geometry, I don't see much performance benefit in not having distinct clones. All rendering & layout information will need to be calculated independently for the instances. Event handling and interaction was also always supposed to be independent.

I recognize that the remaining mirroring behavior is still a pain, but it should help that dynamic style changes will no longer need to be propagated. Similarly, animations will be mirrored by mirroring the original animation instructions, rather than by propagating animated values. So this should make it easier to run animations of any type on independent threads. Only actual DOM changes, new event listeners, and new animation objects will force the two trees to sync.

I've suggested elsewhere ( #184 ) that I'd like to add a toggle attribute to <use> elements to create unlinked, independent clones, but that will have to wait for a future spec.

@AmeliaBR
Copy link
Contributor Author

@birtles

The <use> tree was always open in the SVG spec. It has just never got a lot of attention in practice because Firefox didn't implement it that way!

I like your suggestion of sub-classing Animation to define the mirrored copies.

Would you be open to using correspondingAnimation instead of source, to mirror the SVG terminology? Or is that uncomfortably verbose for a feature that you hope to have wider use?

@birtles
Copy link
Contributor

birtles commented Jul 22, 2016

Would you be open to using correspondingAnimation instead of source, to mirror the SVG terminology? Or is that uncomfortably verbose for a feature that you hope to have wider use?

@AmeliaBR It's pretty verbose and remembering the double 'r' in corresponding is going to trip up non-native English speakers everywhere. On the other hand, source might be a bit too ambiguous, so sourceAnimation ?

@adanilo
Copy link

adanilo commented Jul 25, 2016

Hi @AmeliaBR yes, I know it's too late, that's why I apologized for not paying attention. Performance we can speculate about, but memory is another thing altogether. With the DAG model, if I design a nice intricate graphic (e.g. a snowflake) with 1,000 nodes and reference it 1,000 times in my snow village, I get 2,000 DOM nodes of memory consumed vs. 1,001,000 which is fairly considerable. It's just a bit strange to formalize a 'mistake' in some implementations... In any case, event handling from an implementation that implements the DAG correctly doesn't seem to have caused existing implementers any difficulty in the past. I agree this will have little effect on rendering. Anyway, we'll see what implementers do over time. I do like the concept of bringing Shadow DOM into SVG, just not necessarily via <use> which already worked IMHO.

AmeliaBR added 19 commits July 25, 2016 15:32
…rom 21 July.

- Change warning in defs section to reflect current best practices.
- Add cross-reference to markers for the definition of keywords in refX and refY.
- Remove issue about load event ( added to future wish list as #214)
- Make conditional processing equivalent to display: none; does not stop formation of shadow tree.
- Remove issue about error type; keep as `NoModificationAllowedError`.
- Change issue text re Animations section.
- Remove issue re SVGElementInstance as a NoInterfaceObject.
- Edit issue text to create an at-risk warning re SVGElementInstance::correspondingElement and external file references.
# Conflicts:
#	master/definitions.xml
…s svg/symbol viewport element

Also clarify that HTML embedded content elements behave like foreignObject when fallback content is rendered instead of the media.
(still need to update section for other issues)
Define common behavior for processing all URLs, with reference to HTML's potential-CORS fetch algorithm.  Some normative details which were previously unspecified:

- Consistent with the Masking spec, references from style properties should support anonymous CORS.
-  All subresources with specific element targets must be processed in secure static mode.
- Embedded images must be processed in secure static or animated mode.

Also clean-up various other out-of-date bits in the Linking chapter to match changes to other chapters:

- textPath may reference basic shapes
- hatch accepts an href attribute
- xml:base is only valid in XML documents, and HTML `<base>` is valid in SVG.

Add an example to the `image` section demonstrating how URLs with target fragment refer to the entire document, even when that document is the same one with the image in it.

Closes #90 (Update href attribute descriptions to reference HTML5.1) and addresses some of the discussion in pull request #206.
Replaces a lot of the prose re how to make a read-only copy of a WAAPI animation object with a re-usable interface, as recommended by @birtles in [comments on the pull request](#206 (comment)).
Including the demonstration of different style rules in SVG 1.1 vs SVG 2,
and a practical example of visibility: hidden on the use element being over-ridden on elements in the shadow tree.
re adjusting URLs from external files cloned into the shadow tree
…nces

Normative changes:

- External references are allowed; SVG 1.1 disallowed them in the painting chapter but allowed them in the Linking chapter, leading to inconsistent implementations.

- "Inheriting" of child content is defined to occur using the same shadow DOM implementation as for <use> elements. This should address most of the implementation issues with external file references, provides a common implementation model, and enables style-based templating (e.g., same pattern in different colors), without the circular reference issues of context-stroke & context-fill keywords.

- Descriptive child content should not prevent graphics from being inherited from a template.  Previously, gradient element templating was defined to only be affected by `<stop>` element children; patterns were affected by any children.  Now, it's consistent for all: any child elements, other than descriptive elements, are used.

- The "inheritable" attributes for each paint server type are explicitly defined; closes #121.

Also cleans up the list of valid reference targets in the Linking chapter (to add some missing elements & to alphabetize the rest).
…tributes

(even though they have the same names as geometry properties)

Also fixes some typos & tweaks the wording on some overly long paragraphs.
To cover all the changes in pull request #206
@AmeliaBR AmeliaBR merged commit 42e645b into master Jul 28, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment