I spent the past week hacking dir=uba support into Gecko. Here are the problems I have hit:

HTML and CSS incompatibility

HTML will have the dir=uba attribute inherited to child elements but there is no matching CSS direction:uba. The idea is that the direction will be calculated from the content and then set in the CSS. So if one queries an element for its calculated direction from Javascript you should get back either rtl or ltr depending on the content.

dir=uba also sets the following CSS:

[dir="uba"] {
direction: inherit;
unicode-bidi: plaintext isolate;
}

Gecko handles attributes that are inherited by setting CSS values and let those get inherited. This currently works for all cases exceptdir=uba as there is no CSS equivalent to uba. However, it is possible to created a simple HTML attribute inheritance by inheriting dir=uba when an element is attached to the content tree in nsGenericHTMLElement::BindToTree.

What I would like to do is set a flag in the content node but dir=uba sets unicode-bidi and unicode-bidi is a CSS attribute that is not inherited. So I am setting a full attribute on the element - I still need figure out a way to set unicode-bidi on the basis of the inherited dir value without explicitly setting a dir attribute.

Redefinition of unicode-bidi

Gecko treats unicode-bidi as a property that takes a single value. Now it needs to take multiple values. So the internal representation needs to change from eCSSType_Value, to eCSSType_ValueList and all the relevant code should be changed.

Applying the CSS direction

Gecko parses the HTML and CSS code in a number of passes that run in the following order:

1/ read in the HTML content and build the basic content tree and construct the internal frames.

#6 0x1123b0788 in nsCSSFrameConstructor::ConstructFrameFromItemInternal at nsCSSFrameConstructor.cpp:3820
#7 0x1123b0c6b in nsCSSFrameConstructor::ConstructFramesFromItem at nsCSSFrameConstructor.cpp:5465
#8 0x1123b1388 in nsCSSFrameConstructor::ConstructFrame at nsCSSFrameConstructor.cpp:5012
#9 0x1123b173d in nsCSSFrameConstructor::CreateAnonymousFrames at nsCSSFrameConstructor.cpp:3921
#10 0x1123b1890 in nsCSSFrameConstructor::BeginBuildingScrollFrame at nsCSSFrameConstructor.cpp:4273
#11 0x1123b1fa4 in nsCSSFrameConstructor::SetUpDocElementContainingBlock at nsCSSFrameConstructor.cpp:2789
#12 0x1123b3c95 in nsCSSFrameConstructor::ConstructDocElementFrame at nsCSSFrameConstructor.cpp:2325
#13 0x1123b48cf in nsCSSFrameConstructor::ContentRangeInserted at nsCSSFrameConstructor.cpp:6947
#14 0x1123b57d1 in nsCSSFrameConstructor::ContentInserted at nsCSSFrameConstructor.cpp:6844
#15 0x112410b98 in PresShell::InitialReflow at nsPresShell.cpp:2616
#16 0x1126113a8 in nsContentSink::StartLayout at nsContentSink.cpp:1279

2/ process events to parse and apply attributes and CSS

#1 0x112758a3f in nsHTMLDivElement::ParseAttribute at nsHTMLDivElement.cpp:137
#2 0x112683e2a in nsGenericElement::SetAttr at nsGenericElement.cpp:4582
#3 0x11273d575 in nsGenericHTMLElement::SetAttr at nsGenericHTMLElement.cpp:1198
#4 0x1129ef4fa in nsHtml5TreeOperation::Perform at nsHtml5TreeOperation.cpp:461

3/ first part of reflow - to run through the frames and calculate their positions and bidi state

#1 0x112427f8e in nsBlockFrame::ResolveBidi at nsBlockFrame.cpp:6910
#2 0x112434cb3 in nsBlockFrame::Reflow at nsBlockFrame.cpp:966
#3 0x112441297 in nsContainerFrame::ReflowChild at nsContainerFrame.cpp:738
#4 0x11246e957 in nsCanvasFrame::Reflow at nsCanvasFrame.cpp:496
#5 0x112441297 in nsContainerFrame::ReflowChild at nsContainerFrame.cpp:738
#6 0x112465b11 in nsHTMLScrollFrame::ReflowScrolledFrame at nsGfxScrollFrame.cpp:508
#7 0x1124662ee in nsHTMLScrollFrame::ReflowContents at nsGfxScrollFrame.cpp:601
#8 0x1124685de in nsHTMLScrollFrame::Reflow at nsGfxScrollFrame.cpp:807
#9 0x112441297 in nsContainerFrame::ReflowChild at nsContainerFrame.cpp:738
#10 0x1124c5bb7 in ViewportFrame::Reflow at nsViewportFrame.cpp:285
#11 0x112407b6f in PresShell::DoReflow at nsPresShell.cpp:7427

4/ second part of the reflow to reposition the frames that need to move

#0 0x11242250f in nsBidiPresUtils::Reorder at nsBidiPresUtils.cpp:821
#1 0x112422b57 in nsBidiPresUtils::ReorderFrames at nsBidiPresUtils.cpp:814
#2 0x11243105a in nsBlockFrame::PlaceLine at nsBlockFrame.cpp:4146
#3 0x112431b02 in nsBlockFrame::DoReflowInlineFrames at nsBlockFrame.cpp:3651
#4 0x112431e70 in nsBlockFrame::ReflowInlineFrames at nsBlockFrame.cpp:3371
#5 0x1124332db in nsBlockFrame::ReflowLine at nsBlockFrame.cpp:2467
#6 0x112433aad in nsBlockFrame::ReflowDirtyLines at nsBlockFrame.cpp:1907

I handle inheritance of dir=uba at stage 2, and calculate the direction in ResolveBidi() as it is already doing the hard work of extracting the text.

However this is not the right place. At the beginning of the reflow cycle the direction value is cached in a class of type nsHTMLReflowState. So need a new function to walk the content tree to calculate the UBA direction at the beginning of stage 3 and set a flag in the current presentation context. This flag can then be used when resolving the CSS direction.

Anyway at the end of all this I have a functional,if incomplete implementation that can be used for a proof of concept. You can download and try the patch from bugzilla. You do know how to build Firefox right?