Currently in Gecko, we resolve system fonts at compute-time (in
nsRuleNode). It adds much complexity to how we handle many things,
* an extra internal property -x-system-font for cascading,
* a non-standard keyword value for subproperties of font shorthand,
* an extra parameter in SetValue just for system font value,
* much special logic in serialization
This complexity shows up when we need to implement the support for stylo
in bug 1349417 .
It makes me wonder, how does the spec and other browsers handle this
complicated stuff? So I checked the spec, and it doesn't explicitly
mention whether the resolution happens in parse time or compute time,
but it seems to me that its example  indicates this should happen in
Then I checked other browsers, and it seems to me both Chrome and Edge
do resolve system font at parse time , so they are unlikely have that
many complexity as us.
Per jfkthame, the basic idea of resolving system fonts in compute-time
is that we may want to resolve it to different fonts based on the
language . However, in practice, it never happens.
LookAndFeel::GetFont, the function we call to resolve system fonts,
doesn't take a language as a parameter at all .
The only thing that may depend on current language is, when we fail to
resolve the system font, we fallback to the default font, which is
language-dependent. So I then checked the implementation of GetFont, and
it seems on macOS, Linux, and Android, this function simply never
returns false. On Windows, it may return false when some system call
fails , but they are not related to specific system font, so I
suspect whether that really happens in practice.
I propose that, we make system font resolved at parse time via calling
LookAndFeel::GetFont from the parser, and if that returns false (which,
I think, is unlikely to happen), we fallback to the default font of the
UI language. This way, we should remove most of the complexity on system
font. And given other browsers are already doing so, I think the
compatibility risk should be low.