diff --git a/dlls/mshtml/main.c b/dlls/mshtml/main.c index bbaed1f1967872f40d8771c2c7b4c5a30fc744ee..1a64bdb9b7dc106640b6e8d455a258233f391788 100644 --- a/dlls/mshtml/main.c +++ b/dlls/mshtml/main.c @@ -154,7 +154,7 @@ static BOOL read_compat_mode(HKEY key, compat_mode_t *r) if(status != ERROR_SUCCESS || type != REG_SZ) return FALSE; - return parse_compat_version(version, r); + return parse_compat_version(version, r) != NULL; } static BOOL WINAPI load_compat_settings(INIT_ONCE *once, void *param, void **context) diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index d8b4ddef249396bad8d84b6c7c580fb2746fd342..2e30210db2e7013eac35c5e7af0051fd68325140 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -297,6 +297,7 @@ PRIVATE_TID_LIST } tid_t; typedef enum { + COMPAT_MODE_INVALID = -1, COMPAT_MODE_QUIRKS, COMPAT_MODE_IE5, COMPAT_MODE_IE7, @@ -1253,7 +1254,7 @@ HRESULT set_task_timer(HTMLInnerWindow*,LONG,enum timer_type,IDispatch*,LONG*) D HRESULT clear_task_timer(HTMLInnerWindow*,DWORD) DECLSPEC_HIDDEN; HRESULT clear_animation_timer(HTMLInnerWindow*,DWORD) DECLSPEC_HIDDEN; -BOOL parse_compat_version(const WCHAR*,compat_mode_t*) DECLSPEC_HIDDEN; +const WCHAR *parse_compat_version(const WCHAR*,compat_mode_t*) DECLSPEC_HIDDEN; const char *debugstr_mshtml_guid(const GUID*) DECLSPEC_HIDDEN; diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index 79918278b3d99702c07b54d0536c3c58f2459adf..02b511e309ebfa0d1ac954880ef6f39a68ce6237 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -412,15 +412,20 @@ static void set_document_mode(HTMLDocumentNode *doc, compat_mode_t document_mode lock_document_mode(doc); } -BOOL parse_compat_version(const WCHAR *version_string, compat_mode_t *r) +static BOOL is_ua_compatible_delimiter(WCHAR c) +{ + return !c || c == ';' || c == ',' || iswspace(c); +} + +const WCHAR *parse_compat_version(const WCHAR *version_string, compat_mode_t *r) { DWORD version = 0; const WCHAR *p; for(p = version_string; '0' <= *p && *p <= '9'; p++) version = version * 10 + *p-'0'; - if((*p && *p != ';') || p == version_string) - return FALSE; + if(!is_ua_compatible_delimiter(*p) || p == version_string) + return NULL; switch(version){ case 5: @@ -442,13 +447,14 @@ BOOL parse_compat_version(const WCHAR *version_string, compat_mode_t *r) default: *r = version < 5 ? COMPAT_MODE_QUIRKS : COMPAT_MODE_IE11; } - return TRUE; + return p; } static BOOL parse_ua_compatible(const WCHAR *p, compat_mode_t *r) { static const WCHAR ie_eqW[] = {'I','E','='}; static const WCHAR edgeW[] = {'e','d','g','e'}; + compat_mode_t mode = COMPAT_MODE_INVALID; TRACE("%s\n", debugstr_w(p)); @@ -456,15 +462,22 @@ static BOOL parse_ua_compatible(const WCHAR *p, compat_mode_t *r) return FALSE; p += 3; - if(!wcsnicmp(p, edgeW, ARRAY_SIZE(edgeW))) { - p += ARRAY_SIZE(edgeW); - if(*p && *p != ';') - return FALSE; - *r = COMPAT_MODE_IE11; - return TRUE; - } + do { + while(iswspace(*p)) p++; + if(!wcsnicmp(p, edgeW, ARRAY_SIZE(edgeW))) { + p += ARRAY_SIZE(edgeW); + if(is_ua_compatible_delimiter(*p)) + mode = COMPAT_MODE_IE11; + break; + }else if(!(p = parse_compat_version(p, r))) + break; + if(mode < *r) + mode = *r; + while(iswspace(*p)) p++; + } while(*p++ == ','); - return parse_compat_version(p, r); + *r = mode; + return mode != COMPAT_MODE_INVALID; } void process_document_response_headers(HTMLDocumentNode *doc, IBinding *binding) diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index cd4daa84e0a40b22b74807a60ff325df4bbf26b2..d25c7ac0df805101b18c18aacf597be699c6d25c 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -11441,6 +11441,26 @@ static void test_document_mode(IHTMLDocument2 *doc2) static void test_quirks_mode(void) { + static const struct { + const char *str; + unsigned expected_mode; + } tests[] = { + { "9", 9 }, + { " \t9 ", 9 }, + { " 5 , 8 , 7", 8 }, + { " 8 , 7 , 5", 8 }, + { " 5 , 5 , 7", 7 }, + { " 5 , 9 , 7", 9 }, + { " 5, 7,9", 9 }, + { " 5, 7;9", 7 }, + { " 5, edge,8", 11 }, + { " 5, foo,8", 5 }, + { " 5, 8,foo", 8 }, + { " 5, ,,7", 5 }, + { " 5, , ,7", 5 }, + }; + unsigned i; + run_domtest("<html></html>", check_quirks_mode); run_domtest("<!DOCTYPE html>\n<html></html>", check_strict_mode); run_domtest("<!-- comment --><!DOCTYPE html>\n<html></html>", check_quirks_mode); @@ -11455,15 +11475,14 @@ static void test_quirks_mode(void) if(!is_ie9plus) return; - expected_document_mode = 9; - run_domtest("<!DOCTYPE html>\n" - "<html>" - " <head>" - " <meta http-equiv=\"x-ua-compatible\" content=\"IE=9\" />" - " </head>" - " <body>" - " </body>" - "</html>", test_document_mode); + for(i = 0; i < ARRAY_SIZE(tests); i++) { + char buf[128]; + expected_document_mode = tests[i].expected_mode; + sprintf(buf, "<!DOCTYPE html>\n<html><head>" + " <meta http-equiv=\"x-ua-compatible\" content=\"IE=%s\" />" + "</head><body></body></html>", tests[i].str); + run_domtest(buf, test_document_mode); + } expected_document_mode = 8; run_domtest("<!DOCTYPE html>\n"