惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

美团技术团队
T
The Exploit Database - CXSecurity.com
aimingoo的专栏
aimingoo的专栏
小众软件
小众软件
T
Tailwind CSS Blog
V
V2EX
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
WordPress大学
WordPress大学
Hugging Face - Blog
Hugging Face - Blog
IT之家
IT之家
PCI Perspectives
PCI Perspectives
腾讯CDC
酷 壳 – CoolShell
酷 壳 – CoolShell
Recent Commits to openclaw:main
Recent Commits to openclaw:main
大猫的无限游戏
大猫的无限游戏
The Cloudflare Blog
N
News and Events Feed by Topic
博客园 - 三生石上(FineUI控件)
Help Net Security
Help Net Security
雷峰网
雷峰网
有赞技术团队
有赞技术团队
Last Week in AI
Last Week in AI
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
量子位
GbyAI
GbyAI
O
OpenAI News
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
AI
AI
S
Security Affairs
F
Fortinet All Blogs
L
LINUX DO - 最新话题
博客园 - 【当耐特】
Webroot Blog
Webroot Blog
Schneier on Security
Schneier on Security
W
WeLiveSecurity
Security Latest
Security Latest
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Tenable Blog
L
LINUX DO - 热门话题
Google DeepMind News
Google DeepMind News
Simon Willison's Weblog
Simon Willison's Weblog
Cyberwarzone
Cyberwarzone
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
C
CERT Recently Published Vulnerability Notes
Engineering at Meta
Engineering at Meta
P
Palo Alto Networks Blog
博客园 - 叶小钗
T
Threatpost
H
Heimdal Security Blog
Microsoft Security Blog
Microsoft Security Blog

Henri Sivonen’s pages

Parin vuoden tutkimattomuus crates.io: Rust Package Registry Asiakirjatonta toimintaa It’s not wrong that "🤦🏼‍♂️".length == 7 Koulutartuntojen tilastointimenettely Perusteasiakirjoja hallussapitämättä ikärajoitettu Asiantuntijat ja nukkuva vallan vahtikoira Koronapassilausunto Suppealla tietopohjalla ohimeneväksi väitetty Text Encoding Menu in 2021 The Text Encoding Submenu Is Gone An HTML5 Conformance Checker Not Part of the Technology Stack Browser Technology Stack Bogo-XML Declaration Returns to Gecko A Look at Encoding Detection and Encoding Menu Telemetry from Firefox 86 Why Supporting Unlabeled UTF-8 in HTML on the Web Would Be Problematic Rust Target Names Aren’t Passed to LLVM Toimintamalli Activating Browser Modes with Doctype Johtopäätöksiä mallin rakenteesta Tehtävänmäärittelyä kirjoittamatta ja kuolemia laskematta laumasuojamallinnettu Character Encoding Menu in 2014 Erillissuosituksen tarpeettomuudesta yleissuosituksen poikkeukseksi? STM:n maskiaikajana Rust 2021 Oma-aloitteisesti mallinnettu Kokopinovaatimuksin kilpailutettu chardetng: A More Compact Character Encoding Detector for the Legacy Web Varauksia paisutellen tiedotettu Perusteasiakirjoitta tiedotettu Always Use UTF-8 & Always Label Your HTML Saying So IME Smoke Testing The Validator.nu HTML Parser About the Hiragino Fonts with CSS It’s Time to Stop Adding New Features for Non-Unicode Execution Encodings in C++ Rust 2020 The Last of the Parsing Quirks About about:blank Rust 2019 a Web-Compatible Character Encoding Library in Rust How I Wrote a Modern C++ Library in Rust Using cargo-fuzz to Transfer Code Review of Simple Safe Code to Complex Code that Uses unsafe A Rust Crate that Also Quacks Like a Modern C++ Library #Rust2018 No Namespaces in JSON, Please A Lecture about HTML5 Julkisesti luotettu varmenne ikidomainille TLS:ää (SSL:ää) varten -webkit-HTML5 Lists in Attribute Values The Sad Story of PNG Gamma “Correction” If You Want Software Freedom on Phones, You Should Work on Firefox OS, Custom Hardware and Web App Self-Hostablility HTML5 Parser Improvements ARIA in HTML5 Integration: Document Conformance (Draft, Take Two) Schema.org and Pre-Existing Communities Lowering memory requirements by replacing Schematron HTML5 Parsing in Gecko: A Build Introducing SAX Tree NVDL Support in Validator.nu HOWTO Avoid Being Called a Bozo When Producing XML An Unofficial Q&A about the Discontinuation of the XHTML2 WG Thoughts on HTML5 Becoming a W3C Recommendation Four Finnish Banks Training Users to Give Banking Credentials to Another Site Unimpressed by Leopard Sergeant Semantics The Content Sink Inheritance Diagram – 2006-06-30 What is EME? About Points and Pixels as Units The Performance Cost of the HTML Tree Builder Social Media Impression Management The spacer Element Is Gone Openmind 2006 Performance Mistake XHTML and Mobile Devices WebM-Enabled Browser Usage Share Exceeds H.264-Enabled Browser Usage Share on Desktop (in StatCounter Numbers) HTML5 Parser-Based View Source Syntax Highlighting Vendor Prefixes Are Hurting the Web Accept-Charset Is No More Dualroids Writing Structural Stylable Document in Mozilla Editor ISO-8859-15 on haitallinen Hourglass The Scientific Method According to Hixie Maemo Source Code Karpelan lukkovertaus ontuu Digitaalisesta arkistoinnista ARIA in HTML5 Integration: Document Conformance (Draft) XHTML—What’s the Point? (Draft, incomplete) Mac OS X Browser Comparison HOWTO Spot a Wannabe Web Standards Advocate An Idea About Intermediate Language Trees and Web UI Generation Thoughts on Using SSL/TLS Certificates as the Solution to Phishing Bureaucracy Meets the Web Europe Day HOWTO Establish a 100% Literacy Rate What to Do with All These Photos? Charmod Norm Checking Validator Web Service Interface Ideas DTDs Don’t Work on the Web EFFI’s Day in Court
Planning the XML Content Sink Incrementalization Work – 2006-06-10
Henri Sivonen · 2011-12-22 · via Henri Sivonen’s pages

I’ve been researching the problem area of bug 18333. That is, I have talked to gurus, read code, visualized the class structure and planned possible approaches.

What’s a Content Sink

Just a quick note to casual observers: A content sink is an object that sits between the parser and the content model (DOM tree) and gets data (tokenized on the markup level like start element, end element, etc.) from the parser and builds the content model (DOM tree). On the server side one usually talks about a SAX-to-DOM tree builder.

Requirements

So what is wanted here? Basically, when an XML document (including XHTML, MathML and SVG) is loaded in the browser for rendering in the content area, we want the document to render incrementally if wall clock time indicates that building the content model (DOM) takes long enough for the duration to be noticed by a human.

However, the scenarios can be more complex. First, if the document references an XSLT transformation, the content sink must not give the source document to the layout engine. Instead, the content sink must build the source document without layout, hand the source doc to the XSLT engine and pass the transformation result to layout. Second, if an XML document has neither an CSS style sheet nor an XSLT transformation associated with it and none of the elements has a specialized DOM interface, the content sink kicks off the XML pretty-printer. If a chance of pretty-printing exists, the layout mustn’t start.

Also, the changes must not break XUL, XBL, RDF or XMLHttpRequest. Then there’s even a content sink for XML fragments. That looks suspicious. It appears to be used for innerHTML in the XHTML context.

Finally, since a fatal error can be encountered after the layout has been kicked off, something needs to be done with error reporting. Tearing down the document in mid-layout and replacing it with the Yellow Screen of Death would make the user experience unstable. I think the right way to address the problem is to show an error banner similar to the missing plug-in banner.

So in the cognitive style of PowerPoint:

  • Use a banner for error reporting.

  • Don’t be incremental with XSLT.

  • Don’t be incremental if pretty-printing might still happen.

  • Don’t be incremental with innerHTML.

  • Don’t be incremental with XHR.

  • Don’t be incremental with DOM LS.

  • Don’t be incremental with XUL—at least not when loading the local UI.

  • Don’t be incremental with XBL when loading a binding.

  • Don’t be incremental with RDF when loading a graph.

  • Otherwise, be incremental.

The Behavior of the HTML Content Sink

The HTML content sink is already incremental and has been for years. It builds the content model using Gecko’s internal nsIContent family of interfaces rather than the public DOM interfaces. With the internal interfaces, adding nodes to the content model and notifying observers that nodes have been added are two different operations. The HTML content sink adds nodes to the tree straight away when it gets a token from the parser, but the notifications are deferred.

The actual tree building code is mostly in an inner class called SinkContext to which the content sink delegates. This makes the code unamenable to subclassing. Sink contexts implement what conceptually is more or less the same idea as the insertion mode in the HTML5 parsing spec.

The main part of incremental flushing lives in HTMLContentSink itself. There are two timers. One timer is used to measure the time the calls to the content sink take. That is, the timer is used to sample the clock—not to fire a callback. The other timer fires a callback. The first timer is used to cause flushes as side effects to calls to the content sink. My guess is that the point of the second timer that fires on its own is to make sure that flushing happens even if the network stalls and there are no incoming parser tokens for a while.

Since Gecko runs the parser, content sink and layout on the UI thread, there’s an interesting leaky abstraction in the content sink (quoting the comments):

There is both a high frequency interrupt mode and a low frequency interrupt mode controlled by the flag NS_SINK_FLAG_DYNAMIC_LOWER_VALUE The high frequency mode interrupts the parser frequently to provide UI responsiveness at the expense of page load time. The low frequency mode interrupts the parser and samples the system clock infrequently to provide fast page load time. When the user moves the mouse, clicks or types the mode switches to the high frequency interrupt mode. If the user stops moving the mouse or typing for a duration of time (mDynamicIntervalSwitchThreshold) it switches to low frequency interrupt mode.

The code that handles this stuff liven in HTMLContentSink itself and, therefore, could be hoisted to a superclass. However, the methods involved are not the token handling methods themselves but in methods that get called before and after the methods that process the tokens. The XML content sink does not use such pre/post-methods at all right now.

What Changes to Implement?

I discussed this with gurus both via email and face to face at XTech. The clear consensus was that I should hoist the incrementality handling code to a common superclass of HTMLContentSink and nsXMLContentSink.

I mapped the class structure and discovered that my preconceptions about it were wrong. For example, I thought XBL was handled similarly to XUL separately from generic XML. It is not. The XUL content sink does not inherit from the generic XML content sink but the XBL content sink does.

The green box (HTMLContentSink) has the incrementality code. The blue boxes (nsContentSink and nsXMLContentSink) are the ones that should be refactored to get stuff that is now only in the green box. The red boxes (nsXMLFragmentContentSink, nsXBLContentSink and nsLoadSaveContentSink) are in danger of getting adverse fallout of the refactoring.

I think there needs to be a flag for turning all the new code off. This flag should be set if XSLT is involved, if the code is called from XHR or DOM LS or if we are actually in an instance of a subclass of nsXMLContentSink.

Then I should hoist all the methods dealing with incrementality management and their related fields form HTMLContentSink to nsContentSink. The code that actually does the content model flushes should probably be left in the subclasses and be called as abstract methods in nsContentSink.

All the flushes on the XML side need to check if it is (from the pretty-printing point of view) safe to be incremental and only start flushing once it is certain that pretty-printing won’t happen.

I’d rather not factor anything out of SinkContext. I don’t want to revamp the HTML side right now. I think it would be great to have an HTML5-compliant fresh reimplementation of both the HTML parser and the sink, but I’m supposed to focus on the XML side.

I should also figure out how to show an error banner and get rid of the Yellow Screen of Death.

Feedback?

Does this look right? I’d appreciate feedback in mozilla.dev.tech.xml.