IE isVersion vs isDocumentMode (Browser Mode vs Document Mode)

701 views
Skip to first unread message

Hochhaus, Andrew

unread,
Jul 27, 2011, 7:10:06 PM7/27/11
to closure-lib...@googlegroups.com
Hi,

IE has both a "Browser Mode" and a "Document Mode" which are defined
[0] as following:

"""
* Browser mode controls the way Internet Explorer identifies itself to
the server hosting a webpage.
...
* Document mode controls the way Internet Explorer interprets and
displays a webpage
"""

My understanding is that "Document Mode" determines HTML/CSS/JS
support and "Browser Mode" is mostly a surface level user agent thing.
At the end of the day, most of the closure-library samples have taken
to setting X-UA-Compatible to IE=edge to force the _document mode_ to
the most recent available (however this does not change the _browser
mode_). This msdn post [1] has a helpful flow chart to show how
_document mode_ is determined.

In addition to above, setting X-UA-Compatible also removes the ability
of the user to manually toggle on/off compatibility view (the "torn
paper" icon the right side of the location bar). However, it is still
possible for the user to force the _browser mode_ to something old.
For example, by selecting the "Display all websites in Compatibility
View" option. If a page also sets IE=edge this can result of a
_browser mode_ of 7 and a _document mode_ of 9 for example. To the
best of my knowledge, in this case the browser will function entirely
like IE9 (other than the user agent reported). Can anyone confirm if
this is true?

Which brings me to the closure-library portion of my question. In r263
[2] goog.userAgent.isVersion is modified to use the _document mode_ if
it is greater than the version returned in the user agent string.

Later in r837 [3] goog.userAgent.isDocumentMode is added to allow
clients to check the document mode directly.

What is the difference between isVersion and isDocumentMode? When
should each be used?

Thanks,
-Andy

[0] http://msdn.microsoft.com/en-us/library/cc288325(v=vs.85).aspx

[1] http://blogs.msdn.com/b/ie/archive/2010/03/02/how-ie8-determines-document-mode.aspx

[2] http://code.google.com/p/closure-library/source/diff?spec=svn263&r=263&format=side&path=/trunk/closure/goog/useragent/useragent.js

[3] http://code.google.com/p/closure-library/source/diff?spec=svn837&r=837&format=side&path=/trunk/closure/goog/useragent/useragent.js

Luke Page

unread,
Jul 28, 2011, 2:15:03 AM7/28/11
to closure-lib...@googlegroups.com

Browser mode should be ignored - it only effects what browser ie pretends to be and based on that and many other factors what the document mode is. Only the document mode changes ie's rendering, so i think you are right. I can only think that the change makes isVersion more accurate by catching cases you describe where the browser version is lower than the document version. However since the browser version doesn't effect rendering and does not equal the document mode, the document mode is more accurate for use client side in determining differences in rendering.

However, am I right in thinking that if x-ua-compatability is edge the browser mode will now equal the document mode in all circumstances as document mode will never be less than browser mode?

Hochhaus, Andrew

unread,
Jul 28, 2011, 11:56:47 AM7/28/11
to closure-lib...@googlegroups.com
On Thu, Jul 28, 2011 at 1:15 AM, Luke Page <luke....@gmail.com> wrote:
> Browser mode should be ignored - it only effects what browser ie pretends to
> be and based on that and many other factors what the document mode is. Only
> the document mode changes ie's rendering, so i think you are right.

Thanks for the confirmation. It sounds like we have the same understanding.

> I can
> only think that the change makes isVersion more accurate by catching cases
> you describe where the browser version is lower than the document version.
> However since the browser version doesn't effect rendering and does not
> equal the document mode, the document mode is more accurate for use client
> side in determining differences in rendering.

Sounds right to me.

If I'm not missing anything this means that IE feature detection in
closure-library should always be done using _document mode_. Does
anyone know of a case when this is not true?

However, currently IE feature detection is done using both isVersion
[0] and isDocumentMode [1]. Given their implementations it is not
immediately clear to me in all of the cases when they will differ. Can
anyone comment on these cases?

The isVersion implementation starts with the user agent string
(changed by _browser mode_) and then increases the version (if
applicable) using the _document version_ as described previously. The
isDocumentMode implementation uses the raw document mode.

I see three changes converting some (but not all) calls from isVersion
to isDocumentMode [2]. Can one of the authors of these changes
(wuyingbing, gboyer) comment on if the lingering isVersion calls
should be updated?

> However, am I right in thinking that if x-ua-compatability is edge the
> browser mode will now equal the document mode in all circumstances as
> document mode will never be less than browser mode?

I believe this is correct.

Per my understanding browser mode (as displayed in the dev tools) is
always >= the document mode. If the webpage sets IE=edge, the largest
available document mode is selected (making browser mode == document
mode).

A weirdness that I have seen here (mentioned previously) is in IE8
when the user sets the "Display all websites in Compatibility View"
option and the page sets IE=edge. In this case I see the following
output (note the MSIE 7 in user agent):

Browser Mode (from dev tools): IE8 Compat
Document Mode (from dev tools): IE8 Standards
User Agent (Note MSIE 7): Mozilla/4.0 (compatible; MSIE 7.0; Windows
NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC
5.0; .NET CLR 3.0.30729; .NET CLR 3.5.30729; .NET4.0C)
document.documentMode: 8
goog.userAgent.VERSION: 8

In this case using isVersion is the same as using isDocumentMode so I
must be overlooking the subtle difference.

Thanks,
-Andy

[0]
~/closure-library-read-only$ grep -Ri "IE.*isVersion" . | grep -v
_test | grep -v "\.svn"
./closure/goog/events/onlinehandler.js: goog.userAgent.IE &&
goog.userAgent.isVersion('8') ||
./closure/goog/storage/mechanism/ieuserdata.js: if (goog.userAgent.IE
&& !goog.userAgent.isVersion(9)) {
./closure/goog/style/style.js: if (goog.userAgent.IE &&
!goog.userAgent.isVersion('8')) {
./closure/goog/style/style.js: if (goog.userAgent.IE &&
!goog.userAgent.isVersion('8')) {
./closure/goog/style/style.js: if (goog.userAgent.IE &&
!goog.userAgent.isVersion('8')) {
./closure/goog/net/browsertestchannel.js: if (goog.userAgent.IE &&
!goog.userAgent.isVersion('8')) {
./closure/goog/net/browserchannel.js: if (goog.userAgent.IE &&
!goog.userAgent.isVersion('8')) {
./closure/goog/net/browserchannel.js: return goog.userAgent.IE &&
!goog.userAgent.isVersion('8');
./closure/goog/net/iframeloadmonitor.js: var isIe6OrLess =
goog.userAgent.IE && !goog.userAgent.isVersion('7');
./closure/goog/dom/browserfeature.js: CAN_USE_INNER_TEXT:
goog.userAgent.IE && !goog.userAgent.isVersion('9'),
./closure/goog/editor/plugins/enterhandler.js: if (goog.userAgent.IE
&& !goog.userAgent.isVersion(9)) {
./closure/goog/ui/hsvpalette.js: var noalpha = (goog.userAgent.IE &&
!goog.userAgent.isVersion('7')) ?
./closure/goog/ui/controlrenderer.js: if (goog.userAgent.IE &&
!goog.userAgent.isVersion('7')) {
./closure/goog/ui/controlrenderer.js: if (goog.userAgent.IE &&
!goog.userAgent.isVersion('7')) {
./closure/goog/ui/controlrenderer.js: if (goog.userAgent.IE &&
!goog.userAgent.isVersion('7')) {
./closure/goog/graphics/graphics.js: if (goog.userAgent.IE &&
!goog.userAgent.isVersion('9')) {

[1]
~/closure-library-read-only$ grep -Ri "IE.*isDocumentMode" . | grep -v
_test | grep -v "\.svn"
./closure/goog/events/keycodes.js: return !(goog.userAgent.IE &&
goog.userAgent.isDocumentMode(9));
./closure/goog/events/browserfeature.js: HAS_W3C_BUTTON:
!goog.userAgent.IE || goog.userAgent.isDocumentMode(9),
./closure/goog/style/style.js: if (goog.userAgent.IE &&
!goog.userAgent.isDocumentMode(9) &&
./closure/goog/dom/textrange.js: if (goog.userAgent.IE &&
!goog.userAgent.isDocumentMode(9)) {
./closure/goog/dom/textrange.js: (!(goog.userAgent.IE &&
!goog.userAgent.isDocumentMode(9)) ||
./closure/goog/dom/browserfeature.js: goog.userAgent.IE &&
goog.userAgent.isDocumentMode(9) ||
./closure/goog/dom/browserrange/browserrange.js: if
(goog.userAgent.IE && !goog.userAgent.isDocumentMode(9)) {
./closure/goog/dom/browserrange/browserrange.js: if
(goog.userAgent.IE && !goog.userAgent.isDocumentMode(9)) {
./closure/goog/dom/browserrange/browserrange.js: if
(goog.userAgent.IE && !goog.userAgent.isDocumentMode(9)) {
./closure/goog/editor/browserfeature.js: HAS_IE_RANGES:
goog.userAgent.IE && !goog.userAgent.isDocumentMode(9),
./closure/goog/editor/browserfeature.js: (goog.userAgent.IE &&
goog.userAgent.isDocumentMode(9)),

[2]
http://code.google.com/p/closure-library/source/detail?r=837
http://code.google.com/p/closure-library/source/detail?r=1038
http://code.google.com/p/closure-library/source/detail?r=1039

Garry Boyer

unread,
Jul 28, 2011, 1:17:25 PM7/28/11
to Hochhaus, Andrew, closure-lib...@googlegroups.com
I personally worked on some IE9 document mode issues recently. I'll add a little color, but not enough time to write as much as I should :-)

Generally, I've found if you're deciding whether to work around a rendering bug, document mode is the right thing. If you just want to know if a new feature is available, usually the browser version provides more useful information.

Most people should when possible stick to only supporting one document mode. But for example, a widget embedded across the Web must support IE9 in both 8 and 9 documentMode, because IE9 can't mix IE9 and IE8- frames on the same page. e.g. if the parent page is anything but IE9 standards mode, all iframes in it will be forced into IE8 mode. But IE doesn't tell you that this will happen -- it still identifies on the server as IE9, so you have to do your checks in JS.




Hochhaus, Andrew

unread,
Jul 28, 2011, 3:21:07 PM7/28/11
to Garry Boyer, closure-lib...@googlegroups.com
Thanks Garry!

On Thu, Jul 28, 2011 at 12:17 PM, Garry Boyer <gbo...@google.com> wrote:
> If you just want to know if a new feature is available, usually the browser
> version provides more useful information.

Why is that?

The problem I have seen with using browser version for feature
detection is when compatibility view (or "all pages compat view") is
turned on the document mode may end up supporting a feature while the
user agent string (browser mode) implies the feature would not be
supported. I think this is why isVersion "bumps up" the version based
on the document mode.

> But for example, a widget embedded across the Web must support IE9 in both 8
> and 9 documentMode, because IE9 can't mix IE9 and IE8- frames on the same
> page. e.g. if the parent page is anything but IE9 standards mode, all
> iframes in it will be forced into IE8 mode. But IE doesn't tell you that
> this will happen -- it still identifies on the server as IE9, so you have to
> do your checks in JS.

Thanks for the example! I was unaware of this case and I can recreate
the exact behavior your describe.

Based on my test, this still seems to imply feature detection should
always be done based on documentMode. The IE9 in IE8 mode iframe does
not support IE9 features (as you state -- which corresponds with the
documentMode). My test case:

http://69.164.217.215/force_ie8.htm
http://69.164.217.215/browser_mode.htm

At the end of the day, it seems to me that the isVersion logic can be
simplified to help avoid the types of bugs that were resolved in r837,
r1038 and r1039. For IE, my current understanding is that isVersion()
should use the raw documentMode if it exists and fall back to the user
agent if it does not (ex: IE6 or no DOM). To be concrete:

http://codereview.appspot.com/4794066/diff/1/closure/goog/useragent/useragent.js

Can you help me understand the case when this logic does the "wrong thing"?

Many thanks for your help!
-Andy

Hochhaus, Andrew

unread,
Jul 28, 2011, 4:12:05 PM7/28/11
to Garry Boyer, closure-lib...@googlegroups.com
On Thu, Jul 28, 2011 at 2:21 PM, Hochhaus, Andrew
<ahoc...@samegoal.com> wrote:
> http://codereview.appspot.com/4794066/diff/1/closure/goog/useragent/useragent.js

I added a comment describing the reasoning behind this change:

http://codereview.appspot.com/4794066/diff/2001/closure/goog/useragent/useragent.js

-Andy

Hochhaus, Andrew

unread,
Aug 2, 2011, 12:46:10 PM8/2/11
to Garry Boyer, closure-lib...@googlegroups.com
I added a bug describing this issue and my proposed fix.

http://code.google.com/p/closure-library/issues/detail?id=355

Feedback is appreciated as time permits.

Thanks,
-Andy

Hochhaus, Andrew

unread,
Sep 15, 2011, 4:41:00 PM9/15/11
to Garry Boyer, closure-lib...@googlegroups.com
Does anyone have availability to comment on this patch?

Thanks!
-Andy

On Thu, Jul 28, 2011 at 2:21 PM, Hochhaus, Andrew
<ahoc...@samegoal.com> wrote:

Hochhaus, Andrew

unread,
Sep 27, 2011, 6:16:33 PM9/27/11
to Garry Boyer, closure-lib...@googlegroups.com
Do any of goog.userAgent authors have time to look into this?

:)

Thanks!
-Andy

On Thu, Sep 15, 2011 at 3:41 PM, Hochhaus, Andrew

Hochhaus, Andrew

unread,
Nov 7, 2011, 5:08:07 PM11/7/11
to Garry Boyer, closure-lib...@googlegroups.com
Ping.

Does anyone have time to comment on this change?

On Tue, Sep 27, 2011 at 5:16 PM, Hochhaus, Andrew

Hochhaus, Andrew

unread,
Apr 18, 2012, 2:35:42 PM4/18/12
to Garry Boyer, closure-lib...@googlegroups.com
Sorry to ping again, but this change would still be helpful to me.

Does anyone have time to review it?

Thanks,
-Andy

Garry Boyer

unread,
Apr 19, 2012, 5:37:17 PM4/19/12
to closure-lib...@googlegroups.com
Take a look at browserfeature.js -- I added this comment clarifying it's specifically the user agent version, not the document mode, that is needed here. I tried switching to documentMode but it really broke. The only safe way we can submit your proposal safely is if we change all uses of isVersion('9') to isBrowserMode('9') across the board, first -- OR to audit every single usage in the code base. There are thousands of uses of isVersion('9') in Google's internal code, and while it's probably feasible to do a conservative search/replace around the board, it's definitely not possible to audit all usages exactly. I don't think we're prepared to follow up on this particular change.

  /**
   * Opera, Safari 3, and Internet Explorer 9 all support innerText but they
   * include text nodes in script and style tags. Not document-mode-dependent.
   */

Hochhaus, Andrew

unread,
Apr 22, 2012, 8:02:33 PM4/22/12
to closure-lib...@googlegroups.com
Hi Garry,

Thanks for your feedback.

On Thu, Apr 19, 2012 at 4:37 PM, Garry Boyer <gbo...@google.com> wrote:
> Take a look at browserfeature.js -- I added this comment clarifying it's
> specifically the user agent version, not the document mode, that is needed
> here.

I attempted to recreate this example, but as best I can tell, the
presence of text node descendants in style elements depends on
documentMode (not browser mode). For a minimal example load this page
in IE9:

http://69.164.217.215/inner_text_force_ie8.htm
http://69.164.217.215/inner_text.htm

Am I missing something? If not, this seems to be an example of when
document mode is the correct detection mechanism (and points to a
possible subtle bug in closure-library).

Earlier in this thread, you stated:

"""
Generally, I've found if you're deciding whether to work around a
rendering bug, document mode is the right thing. If you just want to
know if a new feature is available, usually the browser version
provides more useful information.
"""

Can you offer more context or an example when browser mode is the
right way to detect if a feature is available?

> I tried switching to documentMode but it really broke.

Can you point me to one or two cases that broke in specific so that I
can understand them?

> The only safe
> way we can submit your proposal safely is if we change all uses of
> isVersion('9') to isBrowserMode('9') across the board, first -- OR to audit
> every single usage in the code base. There are thousands of uses of
> isVersion('9') in Google's internal code, and while it's probably feasible
> to do a conservative search/replace around the board, it's definitely not
> possible to audit all usages exactly. I don't think we're prepared to follow
> up on this particular change.

I agree that auditing all uses of isVersion is impractical and I am
not proposing it.

However, I think the current API leads to extremely subtle bugs like
those resolved in r837, r1038 and r1039. To clarify, in the current
API:

* goog.userAgent.VERSION returns max(user agent version, document.documentMode)
* goog.userAgent.isDocumentMode returns document.documentMode

Given the current behavior of isVersion(), my proposed change only
affects the cases where documentMode < browser mode (such as the
nested iframe case). For these cases, can you help me see when using
documentMode for feature detection is the wrong thing? It is very
possible that I am not understanding IEs behavior completely.

If we can't find a situation when browser mode is the correct
mechinism for feature detection, this change could be deployed in one
of two ways:

1) Modify goog.userAgent.determineVersion_ to always use documentMode
when present; Mark isDocumentMode as deprecated. (only touches
goog/useragent/useragent.js)
2) Instead of deprecating isDocumentMode do a global replace to use
isVersion instead. (touches many files in an automated manner)

Thanks for your help and consideration,
Andy

Garry Boyer

unread,
Apr 22, 2012, 8:34:27 PM4/22/12
to closure-lib...@googlegroups.com
On Sun, Apr 22, 2012 at 5:02 PM, Hochhaus, Andrew <ahoc...@samegoal.com> wrote:
Hi Garry,

Thanks for your feedback.

On Thu, Apr 19, 2012 at 4:37 PM, Garry Boyer <gbo...@google.com> wrote:
> Take a look at browserfeature.js -- I added this comment clarifying it's
> specifically the user agent version, not the document mode, that is needed
> here.

I attempted to recreate this example, but as best I can tell, the
presence of text node descendants in style elements depends on
documentMode (not browser mode). For a minimal example load this page
in IE9:

http://69.164.217.215/inner_text_force_ie8.htm
http://69.164.217.215/inner_text.htm

Am I missing something? If not, this seems to be an example of when
document mode is the correct detection mechanism (and points to a
possible subtle bug in closure-library).

I just tested and it appears this is correct, though previous testing showed this to be false. IE may have changed their behavior. http://pastehtml.com/view/bvo53ndbe.html

Sounds like a good fix.

Earlier in this thread, you stated:

"""
Generally, I've found if you're deciding whether to work around a
rendering bug, document mode is the right thing. If you just want to
know if a new feature is available, usually the browser version
provides more useful information.
"""

Can you offer more context or an example when browser mode is the
right way to detect if a feature is available?

Like if there's some new feature available in the Javascript engine, although most of the time those can be detected by doing property checks. I can't remember off the top of my head, it's been a while.
 
> I tried switching to documentMode but it really broke.

Can you point me to one or two cases that broke in specific so that I
can understand them?

The case above was the case I remembered, but it seems to work consistently with document mode now.

Seems like a reasonable request, though I personally don't have much time to see this change through. I guess I no longer object. :-P

Hochhaus, Andrew

unread,
Apr 22, 2012, 8:51:50 PM4/22/12
to closure-lib...@googlegroups.com
On Sun, Apr 22, 2012 at 7:34 PM, Garry Boyer <gbo...@google.com> wrote:
> Seems like a reasonable request, though I personally don't have much time to
> see this change through. I guess I no longer object. :-P

Thanks Garry. :)

Does anyone else on the list have the time to review (and potentially
ingest) this change?

-Andy

Michael Davidson

unread,
Apr 23, 2012, 11:01:41 PM4/23/12
to closure-lib...@googlegroups.com
I'm swamped right now, but I would love to see a change like this ingested. 

Nathan, is there someone on the Closure team who can work with Andrew?

Michael

Hochhaus, Andrew

unread,
May 22, 2012, 11:23:34 AM5/22/12
to closure-lib...@googlegroups.com
My employer (SameGoal, LLC), has signed the corporate CLA. Could
someone update the label from "NoCLA" to "CLASigned" so it does not
get overlooked for review?

http://code.google.com/p/closure-library/issues/detail?id=355

Thanks.
Reply all
Reply to author
Forward
0 new messages