ID Bindings in XBL need to be made local

RESOLVED WONTFIX

Status

()

--
blocker
RESOLVED WONTFIX
13 years ago
a year ago

People

(Reporter: kurt.cagle, Unassigned)

Tracking

Trunk
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

13 years ago
User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9a1) Gecko/20051001 Firefox/1.6a1
Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9a1) Gecko/20051001 Firefox/1.6a1

This is a structural problem with the XBL mechanism, one that radically limits
it for larger scale development work. Currently, if an id attribute is defined
within a content block, that id block is automatically passed on to the shadow
tree of the  element, opening up the possibility of multiple elements defined
within the environment that all have the same id attribute, necessitating of
course in an error.

The current solution to this is to utilize the getAnonymousElementByAttribute()
method on the document object. The problem with this comes with the use of
indirectly referenced content in subordinate languages such as SVG. For
instance, suppose that you had an SVG based binding of the form (bypassing
namespaces here for clarity sake):

<xbl:content>
   <svg>
      <defs>
          <linearGradient id="background">
               <stop stop-color="red" offset="0%"/>
               <stop stop-color="blue" offset="100%"/>
          </linearGradient>
      </defs>
      <rect fill="url(#background)"/>
   </svg>
</xbl:content>

This particular example will draw the rectangle, but will only draw it with the
gradient fill IF there is only one rectangle being bound. In the case of two or
more such bindings, there are two identical linearGradient elements with the
same ids introduced, and the rectangle consequently appears unfilled. This is a
critical problem not just for gradients but for the
<use>,<pattern>,<filter>,<mask>, and other SVG elements.

Reproducible: Always




Ideally, an object with an id attribute should be considered private within a
binding relative to the larger context that the binding is sited in. This means
that when the object is instantiated, id references made within the binding
should be exposed to the internal processes of the binding but not to any
external environment. I'm not quite sure whether the alternative case of
external objects with a given id should be referenceable from within the binding
- I'd say probably not - the binding could create a local instance of that
global bound object and pass it in.

This is going to be a critical problem within both SVG and XForms if they are
used from within bindings (as they should be), and the anonymousElements
approach just does not work for this without significant refactoring of code.
Assignee: nobody → general
Component: General → XBL
Product: Firefox → Core
QA Contact: general → ian
Version: unspecified → Trunk
The first question (on which the jury is still out, last I checked) is whether
the #background refers to nodes in the binding document or the bound document. 
In the former case, there is no problem here -- there is only one node in the
binding document with that ID.
(Reporter)

Comment 2

13 years ago
(In reply to comment #1)
> The first question (on which the jury is still out, last I checked) is whether
> the #background refers to nodes in the binding document or the bound document. 
> In the former case, there is no problem here -- there is only one node in the
> binding document with that ID.

This means that all of the resources used by a given binding must then perforce
be outside of the binding in question, which consequently breaks encapsulation.
Here's another example.

Calling document:
<html>
<body>
<div id="background">This may have some form of background content in it.</div>
<foo style="-moz-binding:url(myBinding.xml#bg)">This is a backgrounded object
from a binding.</for>
<foo style="-moz-binding:url(myBinding.xml#bg)">This is a second backgrounded
object from a binding.</for>
</body>

In myBinding.xml

<xbl:binding id="bg">
    <xbl:content>
<xbl:content>
   <svg>
      <defs>
          <linearGradient id="background">
               <stop stop-color="red" offset="0%"/>
               <stop stop-color="blue" offset="100%"/>
          </linearGradient>
      </defs>
      <rect fill="url(#background)"/>
   </svg>
</xbl:content>
         
Here's an illustration of three problems:

1) The author of the web page may be unaware that the background id is in fact
reserved within the binding, meaning that Javascript code looking for
"background" as an id will be confounded.

2) If the fill is looking at external content, then it will attempt to use an
HTML DIV element, rather than the gradient, as a fill, resulting in an error.

3) Because there are two instances of the gradient created within the shadow
tree, even if there was no <div id="background"> element there would be
confounded ids within the document.

-- Kurt
> must then perforce be outside of the binding in question

Why?

> meaning that Javascript code looking for "background" as an id will be 
> confounded.

Code running in which document?  Code in the bound document will see the div;
code in the binding document will see the linearGradient.

> 2) If the fill is looking at external content, then it will attempt to use an
> HTML DIV element, rather than the gradient, as a fill, resulting in an error.

If the fill looks for an element with id "background" in the binding document, I
don't see an issue.

> 3) Because there are two instances of the gradient created within the shadow
> tree, even if there was no <div id="background"> element there would be
> confounded ids within the document.

None of those nodes are visible to the DOM, so I don't see a problem.  That is,
as far as anyone is concerned, those nodes do not exist.  That's the whole point
of "shadow".

Note that I'm not claiming this is what we implement at the moment.  ;)
(Reporter)

Comment 4

13 years ago
Boris,

Let me go back and see if the behavior has changed from what it was in the past.
If it has, then I'll be ecstatic, but at this stage the shadow is still visible
in the id space, from what I can tell.

-- Kurt
Yeah, at the moment we have some bugs in how this works.  But the way to fix
them is what I said in comment 1, imo, not what you said in comment 0.
(Reporter)

Comment 6

13 years ago
Make the referenced items only be visible from the outside?

Hmm. THis could make complex SVG documents difficult. Suppose you had a binding
such as:

<xbl:content>
   <svg>
       <defs>
       <circle id="c1" r="500" cx="0" cy="0"/>
       </defs>
       <use xlink:href="#c1" fill="red" x="100" y="100"/>
       <use xlink:href="#c1" fill="red" x="200" y="100"/>
   </svg>
</xbl:content>

and you could only access external resources, then the SVG would be in error (if
the external resource was an SVG entity, then this binding would use that
resource here and not the two circles, according to what I think you are
saying). The problem here is that neither XUL nor XHTML uses internally
referenced ids as targets, but SVG does (as does XForms). The W3C sXBL
specification specifically utilizes internal ids in bindings that are hidden
from the external document for precisely this reason.

I'm sorry to drop this on your plate, but ID/IDREF pairs are used extensively
with SVG and XForms, and I see both of these languages as being primary ones for
building bindings.




(In reply to comment #5)
> Yeah, at the moment we have some bugs in how this works.  But the way to fix
> them is what I said in comment 1, imo, not what you said in comment 0.

> and you could only access external resources

Meaning what?  All I'm saying is that the fragment identifier should be resolved
relative to the URI of the binding document, not the bound document.
(Reporter)

Comment 8

13 years ago
(In reply to comment #7)
> > and you could only access external resources
> 
> Meaning what?  All I'm saying is that the fragment identifier should be resolved
> relative to the URI of the binding document, not the bound document.
Okay, to clear this up, since I think we're probably talking about the same thing:

binding document: the XBL file
bound document: the XUL, SVG, XHTML or whatever document.

If that is the case, then yes, that is correct, though that doesn't seem to be
the existing behavior.

Yes, that is correct.  And no, it's not existing behavior; it's where I think we
want to end up.
(Reporter)

Comment 10

13 years ago
Excellent, it then sounds like it is a known bug. Is there anything I can do to
help? (I'd have no problem getting into the code, if it came to that)
Hmm...  Well, basically a lot of XBL needs to be redesigned from the ground up
to deal with the new setup.  There's just no way to backwards-compatibly make
things work like they should.  :(

I'm not sure what the current timeframe on doing that is, to be truthful.  :(
(Reporter)

Comment 12

13 years ago
What about forward compatible? W3C's moving toward WebApps with an XBL 2.0
architecture. I wonder if it would be possible to create an sXBL and/or XBL 2.0
binding module that could be added into the tree as an external project. There
are some other minor nits with inheritance in the MozXBL model, and if the
problem is (as I suspected it might be) backwards compatibility, then going with
a v2 version makes more sense. I'd even be willing to take on some of that, as
I'm already doing an analysis of MozXBL vs. sXBL anyway and am working on an
alternative binding language.
ccing some people who should be in on this discussion...  See comment 12.
Status: UNCONFIRMED → NEW
Ever confirmed: true

Comment 14

13 years ago
Yes, we need to rework XBL significantly, either totally dumping the existing
structure or providing compatibility glue (probably the latter, especially if it
could be done with XSLT transforms or whatnot).

One of the core problem that needs looking at is that the .ownerDocument of the
anonymous nodes is the bound document, which IMO is incorrect for a bunch of
reasons.

Having a real separate document tree for the anonymous nodes is I believe
specified in sXBL/XBL2, but it has the potential to significantly impact
Mozilla's performance because of the way we use shared xblprototypes.
It might be possible, as an interim patch, to have
nsSVGUtils::GetReferencedFrame find the "correct" anonymous element. For
example, if aContent is anonymous it could search its anonymous subtree for an
element with the right ID before calling GetElementById.
Ah ... yeah! I'll take it up there :-)
(Reporter)

Comment 18

13 years ago
That would work. I'm still not sure whether it would solve the issue for XForms
(I'm not even remotely familiar with THAT code base) but it would take care of
the immediate issue of SVG, which I see as being the more immediately important.
The idea in sXBL/XBL2 was that URIs would be relative to the binding document
(not the bound document) and #fragment-id references would therefore be relative
to nodes in the original binding document (in sXBL/XBL2 the binding document is
not thrown away at all, it is kept around and is always live).

IIRC.
The hackaround in bug 309020 would be compatible with that in most cases.
(In reply to comment #19)
> The idea in sXBL/XBL2 was that URIs would be relative to the binding document
> (not the bound document) and #fragment-id references would therefore be relative
> to nodes in the original binding document (in sXBL/XBL2 the binding document is
> not thrown away at all, it is kept around and is always live).

But that means that you won't be referencing the anonymous nodes in the
displayed document. This is ok in the svg example, but wouldn't solve the
problem when you need to modify the nodes.

Comment 22

13 years ago
Sicking, in sXBL/XBL2 the anonymous nodes *aren't* in the displayed document.
There are two separate domtrees.
True. Maybe we should define it as looking in the anon nodes first then falling
back to the binding document? Or is that too gross for people to accept?

Comment 24

13 years ago
I found this thread while preparing to submit my own bug. Is it relevant to the topic or not but: as of Fx 1.5.0.2 references in anonymous SVG content do not work at all: neither one nor multiple. Is it a consequence of this bug, or a new one or I'm screwing up something?

// HTML file:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN"
 "http://www.w3.org/TR/html401/strict.dtd">
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type"
 content="text/html; charset=iso-8859-1">
<style type="text/css">
body {
 background-color: white;
 color: black;
 font: 1em Verdana, sans-serif;
}

.test {
 -moz-binding: url(grad.xml#default);
}
</style> 
</head>

<body>

<div class="test" style="position:relative; width: 90%;">
 <p>Gradient fill fails to be addressed</p>
</div>

</body>
</html>


// grad.xml file:

<?xml version="1.0"?>
<bindings
 xmlns="http://www.mozilla.org/xbl"
 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
 xmlns:svg="http://www.w3.org/2000/svg"
 xmlns:xlink="http://www.w3.org/1999/xlink">

<binding id="default">
 <implementation>
 
  <constructor><![CDATA[
 // your code here
  ]]></constructor>

  <destructor><![CDATA[
 // your code here
  ]]></destructor>

 </implementation>

 <content>
  <children/>
   <svg:svg>
    <svg:defs>
     <svg:linearGradient id="grad01">
      <svg:stop offset="0%"   stop-color="#0000FF"/>
      <svg:stop offset="100%" stop-color="#FFFF00"/>
     </svg:linearGradient>
    </svg:defs>
    <svg:rect x="0" y="0" width="100%" height="32" fill="url(#grad01)" stroke="#0000FF"/>
   </svg:svg>
 </content>

</binding>

</bindings>

Comment 25

11 years ago
Some issues described in this bug might be fixed in bugs #309020 #387466
Assignee: xbl → nobody
QA Contact: ian → xbl

Comment 26

a year ago
Web Components \o/
Status: NEW → RESOLVED
Last Resolved: a year ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.