Closed Bug 132844 Opened 22 years ago Closed 22 years ago

Transformed docs lack the DOCTYPE, detect the MathML namespace

Categories

(Core :: MathML, defect, P1)

defect

Tracking

()

RESOLVED FIXED
mozilla1.0

People

(Reporter: rbs, Assigned: rbs)

References

()

Details

Attachments

(1 file, 1 obsolete file)

The ability to load mathml.css on demand depends on a reliable detection of the 
presence of MathML content inside the document (bug 124570).

The current way of doing this detection uses the <DOCTYPE>, but documents
produced on the fly with XSLT don't have a <DOCTYPE>. So it was suggested on
n.p.m.mathml to also look for the presence of the declaration of the MathML 
namespace in <html>.

Thread: "XSL Stylesheet for Cross Browser MathML viewing" - 21 March 2002
http://groups.google.com/groups?threadm=3C9A7135.BF7DC4DD%40maths.uq.edu.au
Uh, how about documents that just have MathML somewhere in the middle?

   <a>
     <b> This is a random document in a random language. </b>
     <b>
       <math xmlns="http://www.w3.org/1998/Math/MathML">
         <mi> x </mi> <mo> = </mo> <mi> y </mi>
       </math>
     </b>
   </a>
The idea is to ask authors to please declare xmlns:mathml="..." within <html>
so that there is only one place to test for that for cross-browser support, like
that other bug where IE expected the XHTML prefix to be "html", remember?

[In reality, this is only compliant with transformed docs, since all XHTML docs
must have a DOCTYPE in order to be XHTML compliant per the XHTML spec.]
XHTML documents need not be valid, only well formed. And my sample document was
not XHTML. What about cases where the auther adds MathML content through the
DOM? What if he doesn't know in advance that it will be MathML content?

I'm sorry, but we can't depend on a namespace being declared in a particular
place. There is zero basis in the specs for behaviour of that kind.

How about the MathML frame constructor checks to see if the MathML stylesheet
has been enabled in that document's UA stylesheet set when it creates the
document's first MathML frame?
(The examples that you gave are way too sophisticated... Do you know that for
some of the other renderers you have to add the "mml:" prefix on every tag :-)

>There is zero basis in the specs for behaviour of that kind.

Yes, it is a hack pending a better proposal. I haven't yet started coding
anything. If there is a better way, I am taker.

>How about the MathML frame constructor checks to see if the MathML stylesheet
>has been enabled in that document's UA stylesheet set when it creates the
>document's first MathML frame?

So you mean loading mathml.css upfront and disabling it? That's what the other
bug aimed at avoiding. No mathml.css anywhere until MathML content is
encountered.

It is technically possible to load the mathml.css on the fly (there are APIs for
that). The side-effect is that if done from the frame construction code, it will
be done half-way during the construction, causing the frame tree to be destroyed
in a re-entrant manner. If done from the DOM/content construction, then that
might be okay. To do so would require testing every node against the MathML
namespace. I am not sure how much of a cost that would be. I haven't yet looked
at the code ATM.
I didn't particularly mean disabled vs not loaded -- whichever you need.

> It is technically possible to load the mathml.css on the fly (there are APIs 
> for that). The side-effect is that if done from the frame construction code, 
> it will be done half-way during the construction, causing the frame tree to be 
> destroyed in a re-entrant manner.

Can this be scheduled? Or can frame construction be aborted or re-started? This
will probably happen during the initial frame construction that occurs (after
1.2s or when the page is completed) -- can this fact be used to optimise this
somehow?

I actually just thought of a much neater way of doing this. Simply add an XBL
binding on the root MathML element, and import the stylesheet through that.

Or, use the stylesheet scoping mechanism of XBL, but hook it in manually at the
frame constructor level. This should mean we don't need to reframe anything.


> If done from the DOM/content construction, then that might be okay. To do so 
> would require testing every node against the MathML namespace. I am not sure 
> how much of a cost that would be. I haven't yet looked at the code ATM.

Won't that have to be done anyway when we implement the MathML DOM?
>I didn't particularly mean disabled vs not loaded -- whichever you need.

It was concluded that the increase came mostly from the I/O (17.5ms). We are
speaking of at an atomic level here :-). Plus, not loading it has a positive
impact on the bloat numbers.

>Can this be scheduled? Or can frame construction be aborted or re-started? This
>will probably happen during the initial frame construction that occurs (after
>1.2s or when the page is completed) -- can this fact be used to optimise this
>somehow?

We are speaking of mathml.css, it needs a little friendly solution, not a big
scary thing...

>I actually just thought of a much neater way of doing this. Simply add an XBL
>binding on the root MathML element, and import the stylesheet through that.

Wouldn't that import it several times, i.e., for _all_ <math> elements?
Did you try it already?

>Won't that have to be done anyway when we implement the MathML DOM?

At that time, yes.
Here is what you have to do to get MathML elsewhere, <html m:mathmlNS> needs to 
occur as the first line in your document:
http://www.dessci.com/webmath/mathplayer/authoring.stm

I hope Mozilla can do something better/transparent than that, but if it is too 
much trouble, why make our life so hard at this already crucial stage where the 
tree closes in a week.
[note: it reminds the proposal in bug 51684 - Revisiting nsIFrame]
hyatt: Can you give us some insight into how XBL could help us? (See above.)

rbs: Using the stylesheet scoping mechanism of XBL, but hooked in manually at the
frame constructor level, might be the relatively simple way you are looking for.


You mean there is some XBL magic that could trigger the load of mathml.css if
the transformed doc has a node with an attribute that read:
'<html ... xmlns:m="http://www.w3.org/1998/Math/MathML">
if so, that will be great, no code-level changes...
No, I meant that there would be a way of bringing in the MathML sheet only for
MathML content, just like in the chrome we only bring in the button stylesheets
for buttons, the menu stylesheets for menus, etc. My theory is that there is a
way to trigger that without even using the overhead of XBL by simply hooking in
the scoped stylesheet import at the frame construction level.

I am strongly against anything that limits users' abilities to insert MathML
nodes dynamically without any sort of special provisions. That other renderers
are screwed up in that way is in no way a reason for us to make that kind of
fundamental mistake.
Ok hixie, no time for theory. m1.0 is around the corner. If there is an easy way 
to fix this bug, let's take it rather than stick on an idealized solution.

Actually, I already have some code that creates a stylesheet on the fly from the 
frame construction side -- that's how I added the support for the inline MathML 
stylistic attributes (c.f. bug 69409 comment 4) - the source for that is at: 
nsMathMLFrame::MapAttributesIntoCSS().

I had some troubles at that time because of a reframe mid-way (not sure if the 
related bugs have been fixed since then). If there is a more robust XBL way to 
load mathml.css, I will be more inclined toward it.

Status: NEW → ASSIGNED
Priority: -- → P1
Target Milestone: --- → mozilla1.0
> Ok hixie, no time for theory. m1.0 is around the corner.

Well, XBL works now. We could fix this most easily just by adding a single line
to html.css, namely 

   mathml|math { -moz-binding: url(resource:/.../mathml.css); }

I don't know what this does w.r.t. memory footprint, but since that's how the
chrome does stuff for each <button>, I assume it's optimised for sharing.
Tried it, but it doesn't work yet. Directly trying to use -moz-binding on the 
.css file caused an invalid syntaxt error. So I switched to the following steps:

1: create a mathml-test-xbl.xhtml with the following content:
=============================================================

<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Bug 132844</title>
<style>
*|math {
  -moz-binding: url("mathmlBindings.xml#math-element");
}
</style>
</head>
<body>

<math xmlns="http://www.w3.org/1998/Math/MathML">
<mfrac>
  <mi>a</mi>
  <mi>b</mi>
</mfrac>
</math>

</body>
</html>

2: create a mathmlBindings.xml file with the content:
=====================================================

<?xml version="1.0"?>
<bindings id="mathmlBindings"
  xmlns="http://www.mozilla.org/xbl">

  <binding id="math-element">
    <resources>
      <stylesheet src="resource:/res/mathml.css"/>
    </resources>
  </binding>

</bindings>

============
But when I try to load mathml-test-xbl.xhtml in the browser, I get a fraction 
in which 'a' and 'b' don't appear italicized in scriptstyle. Got a clue?
Severity: normal → blocker
It's something to do with the scoping rules for stylesheets... there are
attributes on one of the elements in the binding that control what the
stylesheets apply to (children, only anonymous nodes, etc). I forget what they
are called.
And you are not that much thrilled to lookup... The attribute turned out to be:

styleexplicitcontent:
 The styleexplicitcontent attribute indicates whether or not style sheets loaded
 from an XBL document are applied to a bound element's explicit children (in
 addition to the bound element itself). If omitted, a value of false is assumed.

Guess what? It isn't yet implemented. So I have little option at this stage than 
to hand-roll a hack to fix this bug.
I didn't look it up because I don't know _where_ to look it up. I'm the author
of the latest version of the XBL specification, so I could tell you that the
official way to do it is as follows:

   <?xml version="1.0"?>
   <bindings xmlns="http://www.mozilla.org/xbl">
     <binding id="math-element">
       <content><children applybindingsheets="true"/></content>
       <stylesheet src="resource:/res/mathml.css"/>
     </binding>
   </bindings>

   mathml|math { binding: -moz-mathml; }

However, I know for a fact that Mozilla doesn't implement that version of the
XBL specification and therefore it wouldn't help you much. I was hoping hyatt
might chime in and give you some pointers -- I know very little about our XBL
implementation. I'm just a theory guy, sorry! :-)
With the fix, mathml.css is now loaded when creating MathML nodes in the DOM.
If the document has a DOCTYPE, then the stylesheet is loaded as per bug 124570.
Otherwise, the first MathML node that is created triggers the load.

To my surprise with XLST, my good printf friend is telling me that it is loaded
_thrice_ for the XSLT case: when parsing the initial doc, when transforming,
and then, some copying of the doc that the XSLT engine is doing. I couldn't
tell from within the element factory what is going on with the document, and
therefore I couldn't figure out how to avoid loading the stylesheet if the
document is just in a transient transformation state. I wonder why
nsXSLContentSink is not overloading nsXMLContentSink::CreateElement() to just
create vanilla XML elements rather than going through the overhead of creating
elements through the factory since these elements are going to be transformed.
If it was doing so, it will avoid loading the stylesheet unnecessarily. There
are perhaps other things that nsXSLContentSink may overload too to tighten
things a bit. But these are questions for another time... I am just going to
hunt for r/sr/a on what I have so far...
Testcase:
http://www.w3.org/Math/XSL/csmall2.xml

The Universal MathML Stylesheets:
http://www.w3.org/Math/XSL/
Summary: Transformed docs lack the DOCTYPE, detect the MathML namespace within <html> → Transformed docs lack the DOCTYPE, detect the MathML namespace
Attachment #77138 - Attachment is obsolete: true
For the record, the nsXSLContentSink could and should override CreateElement(). 
(That'll also avoid loading <script>s and <style>s).
Summary: Transformed docs lack the DOCTYPE, detect the MathML namespace → [fix, awaiting r/sr/a] Transformed docs lack the DOCTYPE, detect the MathML namespace
Comment on attachment 77166 [details] [diff] [review]
same as patch 77138 - but with a missing portion from mathml/content

- In NS_NewMathMLElementFactory():

+  NS_ADDREF(result);
+  *aResult = result;

I'd swap those two lines and addref the out param, which is what you really
want here. No big deal though...

sr=jst
Attachment #77166 - Flags: superreview+
Indeed, that's what I want. Corrected in my tree. (Also corrected in the code 
just above -- where the copy-paste came from :-)
Summary: [fix, awaiting r/sr/a] Transformed docs lack the DOCTYPE, detect the MathML namespace → [fix, have sr, awaiting r/a] Transformed docs lack the DOCTYPE, detect the MathML namespace
Whiteboard: have sr=jst, awaiting r/sr
Comment on attachment 77166 [details] [diff] [review]
same as patch 77138 - but with a missing portion from mathml/content

+  NS_PRECONDITION(aResult != nsnull, "null ptr");
+  if (! aResult)
+    return NS_ERROR_NULL_POINTER;

could be simply:

NS_ENSURE_ARG_POINTER(aResult);

Are you sure you will always get a sheet below, wouldn't it be safer to test if
you got it (null check)?
+      doc->GetStyleSheetAt(i, getter_AddRefs(sheet));
+      nsCOMPtr<nsIURI> uri;
+      sheet->GetURL(*getter_AddRefs(uri));

Same with uri right after that.

Fix those and r=heikki
Attachment #77166 - Flags: review+
fixed in my tree. I have also left an assertion in the null check for the 
stylesheet since it is an unexpected situtation.
Summary: [fix, have sr, awaiting r/a] Transformed docs lack the DOCTYPE, detect the MathML namespace → [fix, have r/sr, awaiting a] Transformed docs lack the DOCTYPE, detect the MathML namespace
Whiteboard: have sr=jst, awaiting r/sr → have r=heikki & sr=jst, awaiting a=
Comment on attachment 77166 [details] [diff] [review]
same as patch 77138 - but with a missing portion from mathml/content

a=asa (on behalf of drivers) for checkin to the 1.0 trunk
Attachment #77166 - Flags: approval+
it seems awfully expensive to search for the mathml.css stylesheet for every
mathml-element that is created. Couldn't you set a flag in the document when the
stylesheet is added and just look at that flag? We never have many documents
alive so bloat shouldn't be a problem.
yay, just realized that adding the stylesheet on creation won't work if an
element is moved from one document to another. You could fix this by creating
special mathml-elements and adding the stylesheet in nsMathMLElement::SetDocument.

Not sure if it's a big deal though
If we want this, fiddle importNode instead. Just moving an element between 
documents is verboten
>it seems awfully expensive to search for the mathml.css stylesheet for every
>mathml-element that is created. Couldn't you set a flag in the document when
>the stylesheet is added and just look at that flag?

Yeah, it is a pain. I considered setting up such a flag in the document but
thought that it will be too MathML-specific. Then I thought of setting up a
hashtable in the factory to record documents for which the stylesheet has
already been added. Maybe later -- when this thing is factored out in his
separate file.

But notice that actually, what will practically happen is that the stylesheet
will be added as the _first_ stylesheet (due to the catalog flag) and so, the
loop will generally stop at the first iteration. It is in the case where someone
has explicitly included the stylesheet that it will slow the loop down.
Fortunately, people are unlikely to include such a stylesheet explicitly.

I have taken note of comment #29 -- provided that comment #30 is not saying that
it is not a clean thing to do?
Patch checked in. Resolving as FIXED.
Status: ASSIGNED → RESOLVED
Closed: 22 years ago
Resolution: --- → FIXED
Summary: [fix, have r/sr, awaiting a] Transformed docs lack the DOCTYPE, detect the MathML namespace → Transformed docs lack the DOCTYPE, detect the MathML namespace
Whiteboard: have r=heikki & sr=jst, awaiting a=
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: