Closed Bug 276037 Opened 20 years ago Closed 18 years ago

In application/xhtml+xml during page load getElementsByTagNameNS and getElementsByTagName does not find all currently parsed elements

Categories

(Core :: DOM: Core & HTML, defect)

x86
Windows XP
defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: martin.honnen, Unassigned)

References

()

Details

Attachments

(3 files)

HTML and XHTML allow the use of the <script> element to embed script code in the document. The script code inside of a <script> element has traditionally been executed during loading of the document, directly after the <script> element has been parsed. For instance in HTML (text/html) documents people use document.write to insert content into the document during page load. With "real" XHTML, meaning with application/xhtml+xml content, document.write is no longer available but of course scripters would still like to insert content into the document with script while the page loads. My solution for that is to use document.getElementsByTagName('script') respectively document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'script') to grab the last <script> element in the document and call appendChild on its parent node, in the hope that while the script code inside of a <script> element is executed that <script> element is already available in the DOM tree and thus any content is executed directly after the <script> element, the same way document.write would do it. However with Mozilla (tested with the latest nightly Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8a6) Gecko/20041225 as well as with Firefox 1.0 Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0) the approach doesn't work when the <script> element sits inside of a table cell inside of a document served as application/xhtml+xml. The test case at: http://home.arcor.de/martin.honnen/mozillaBugs/domInsertionDuringPageLoad/domInsertionDuringPageLoad.xhtml shows that the <script> element inside of the table cell is not yet found by the getElementsByTagName/getElementsByTagNameNS('script') so that the text meant to be inserted into the table cell ends up as a child of the parent node of an earlier <script> element. The same test case served as text/html, available here: http://home.arcor.de/martin.honnen/mozillaBugs/domInsertionDuringPageLoad/domInsertionDuringPageLoad.html however works as intended, the code inside of a <script> element finds that <script> element in the DOM tree and is able to append to its parent node. While I cannot cite a specification saying that script code run during page load needs to have access to the DOM tree including the <script> element the code is contained in that would be highly desirable in my view as it is the only way for script in application/xhtml+xml to insert content at the position of the <script> element. Therefore I file this bug on Mozilla. I add that this is becoming more important as an increasing number of people are using content type negotiation to serve XHTML as text/html to IE but as application/xhtml+xml to Mozilla (or other browsers understanding XML) and therefore use script in application/xhtml+xml and run into the problem to have the script run during page load insert content into the page when and where the script is executed. One newsgroup post about that topic is here: http://groups-beta.google.com/group/netscape.public.mozilla.dom/browse_frm/thread/a9be9f42491271ad/09ad74e3c8fec90c?tvc=1&scrollSave=&&d#09ad74e3c8fec90c
I think this is because of bug 18333. See also 232004 comment 9.
Depends on: incrementalxml
Martin, is the table cell relevant? That is, if you replace it with a paragraph, do you still see the problem? What about if the <script> is just a child of <body>? Anne, this is rather unlikely to be a consequence of bug 18333 -- that bug is about _layout_ objects not being constructed, and this bug is about the content model and looks like it should be reproducible even in a display:none iframe (where there are no layout objects in sight).
No longer depends on: incrementalxml
I have done some further tests and Boris rightly suspects that the table is not relevant, changing summary to reflect that. In the following application/xhtml+xml test case: http://home.arcor.de/martin.honnen/mozillaBugs/domInsertionDuringPageLoad/domInsertionDuringPageLoadParagraph.xhtml there are only paragraphs but only the script code in the first <script> element inserts content into its parent node while all following scripts insert content as a child of the first paragraph which is the parent node of the first <script> element. The same test case as text/html works fine: http://home.arcor.de/martin.honnen/mozillaBugs/domInsertionDuringPageLoad/domInsertionDuringPageLoadParagraph.html
Summary: In application/xhtml+xml a script element inside a table cell is not yet available in the DOM when the script executes → In application/xhtml+xml a script element is not yet available in the DOM when the script executes
Further investigation shows that the problem is that during page load in application/xhtml+xml content the methods document.getElementsByTagName and document.getElementsByTagNameNS do not find all parsed elements. The test case during page load counts XHTML span and script elements using the two methods and manually walking the document tree, while the tree walks shows that the last span and script element has been parsed and is in the document tree the two methods do not find those elements, only after onload the methods find the correct number of elements.
Changing summary again to reflect the findings of the last test case <https://bugzilla.mozilla.org/attachment.cgi?id=169634> which shows that the problem is not restricted to <script> elements not being found but other elements like <span> too.
Summary: In application/xhtml+xml a script element is not yet available in the DOM when the script executes → In application/xhtml+xml during page load getElementsByTagNameNS and getElementsByTagName does not find all currently parsed elements
Hmm... It'd be interesting to see exactly what the callstack looks like when we actually do anything in nsHTMLScriptElement::MaybeProcessScript, i.e. when we reach line 649 in that file. I would exect things to work since we in nsGenericElement::AppendChildTo add the new child to mAttrsAndChildren before we call SetDocument on it.
The problem is that content lists are lazy and rely on the ContentAppended/ContentInserted/ContentRemoved notifications to clear their cached state. But the XML content sink doesn't fire these notifications until the parsing is finished and it fires a single ContentInserted on the root.... Perhaps content lists should be non-lazy for still-loading xml documents (as a short-term hack or something)? What should the behavior of content lists be when they're created by a script element in a document that is then transformed with xslt, btw?
Shouldn't "we" "just" make the XML content sink fire the notifications like the HTML content sink?
I'm not sure, in part because I'm not sure how that interacts with XSLT. When we transform, do we change document objects too, or just stick the transformation result into the original document? If the latter, content lists created in the pre-transform document would start seeing post-transform content, which is undesirable. For the rest, I think it should be safe to do content notifications, since we wouldn't call InitialReflow, so frame construction would be suppressed. But we may still up with significant inefficiency from once-per-content notification, whereas a batching system like the HTML sink would take some work (see bug 18333).
ccing people who may know answers to my questions...
XSLT creates a compleatly new document (so that we can create an html document rather then an xml one). Also, it shouldn't be an issue with stuff created in the original document, since we shouldn't be running any scripts at all in that document once we detect that we're going to XSLT transform it (not sure if we actually do that currently). XSLT currently use DOM methods to create the result tree, so I would think that we send out notifications continously. This might change though if we switch over to the faster nsIContent interfaces.
I attach this as workaround as long as the bug is not fixed as the problem of inserting content during page load into application/xhtml+xml comes up again and again in newsgroups. Instead of using getElementsByTagName(NS) to find the last and current <script> element the workaround looks at the childNodes and that way is able to find the correct <script> element.
Just as an additional information: I've tripped on this problem in one of my projects too, where a script basically needs to located its own script element in order to be able to "include" more script files automatically. This currently fails, because getElementByTagName() does not return all script DOM nodes. However, when looking at document and its child DOM elements, I can find the "missing" DOM node.
Fixed by bug 18333. (I was able to reproduce the bug using an opt build from a few days ago, but not using a debug build with the fix for bug 18333.)
Status: NEW → RESOLVED
Closed: 18 years ago
Resolution: --- → FIXED
PLEASE mark the in-testsuite stuff when resolving. Or better yet, add the tests!
Flags: in-testsuite?
OK. So I wrote a regression test for this based on attachment 169634 [details]. Sometimes the test succeeds. Sometimes it fails. Reopening.
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
could be a regression from 18333
No, it was broken before 18333.
Depends on: 369011
Attached patch TestsSplinter Review
The random failures are due to bug 369011 (yay writing regression tests!). Once that lands I'll land these tests.
Tests committed. Now they pass.
Status: REOPENED → RESOLVED
Closed: 18 years ago18 years ago
Flags: in-testsuite? → in-testsuite+
Resolution: --- → FIXED
Component: DOM: Core → DOM: Core & HTML
QA Contact: ian → general
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: