include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / mshtml / tests / documentmode.js
blob016b51c9eda097f6fe34b385194ca8fe2201a791
1 /*
2  * Copyright 2016 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
19 var compat_version;
20 var tests = [];
22 ok(performance.timing.navigationStart > 0, "navigationStart <= 0");
23 ok(performance.timing.fetchStart == performance.timing.navigationStart, "fetchStart != navigationStart");
24 ok(performance.timing.domainLookupStart >= performance.timing.fetchStart, "domainLookupStart < fetchStart");
25 ok(performance.timing.domainLookupEnd >= performance.timing.domainLookupStart, "domainLookupEnd < domainLookupStart");
26 ok(performance.timing.connectStart >= performance.timing.domainLookupEnd, "connectStart < domainLookupEnd");
27 ok(performance.timing.connectEnd >= performance.timing.connectStart, "connectEnd < connectStart");
28 ok(performance.timing.requestStart >= performance.timing.connectEnd, "requestStart < connectEnd");
29 ok(performance.timing.responseStart >= performance.timing.requestStart, "responseStart < requestStart");
30 ok(performance.timing.responseEnd >= performance.timing.responseStart, "responseEnd < responseStart");
31 ok(performance.timing.domLoading >= performance.timing.responseEnd, "domLoading < responseEnd");
32 ok(performance.timing.domInteractive === 0, "domInteractive != 0");
33 ok(performance.timing.domComplete === 0, "domComplete != 0");
34 ok(performance.timing.domContentLoadedEventStart === 0, "domContentLoadedEventStart != 0");
35 ok(performance.timing.domContentLoadedEventEnd === 0, "domContentLoadedEventEnd != 0");
36 ok(performance.timing.loadEventStart === 0, "loadEventStart != 0");
37 ok(performance.timing.loadEventEnd === 0, "loadEventEnd != 0");
38 ok(performance.timing.unloadEventStart === 0, "unloadEventStart != 0");
39 ok(performance.timing.unloadEventEnd === 0, "unloadEventEnd != 0");
40 ok(performance.timing.redirectStart === 0, "redirectStart != 0");
41 ok(performance.timing.redirectEnd === 0, "redirectEnd != 0");
42 ok(performance.timing.msFirstPaint === 0, "msFirstPaint != 0");
44 var pageshow_fired = false, pagehide_fired = false;
45 document.doc_unload_events_called = false;
46 window.onbeforeunload = function() { ok(false, "beforeunload fired"); };
47 window.onunload = function() {
48     document.doc_unload_events_called = true;
49     ok(document.readyState === "complete", "unload readyState = " + document.readyState);
50     if(document.documentMode < 11)
51         ok(pagehide_fired === false, "pagehide fired before unload");
52     else
53         ok(pagehide_fired === true, "pagehide not fired before unload");
56 if(window.addEventListener) {
57     window.addEventListener("pageshow", function(e) {
58         pageshow_fired = true;
60         var r = Object.prototype.toString.call(e);
61         ok(r === "[object PageTransitionEvent]", "pageshow toString = " + r);
62         ok("persisted" in e, "'persisted' not in pageshow event");
63         ok(document.readyState === "complete", "pageshow readyState = " + document.readyState);
64         ok(performance.timing.loadEventEnd > 0, "loadEventEnd <= 0 in pageshow handler");
65     }, true);
67     window.addEventListener("pagehide", function(e) {
68         pagehide_fired = true;
69         ok(document.documentMode >= 11, "pagehide fired");
71         var r = Object.prototype.toString.call(e);
72         ok(r === "[object PageTransitionEvent]", "pagehide toString = " + r);
73         ok("persisted" in e, "'persisted' not in pagehide event");
74     }, true);
76     document.addEventListener("visibilitychange", function() { ok(false, "visibilitychange fired"); });
77     document.addEventListener("beforeunload", function() { ok(false, "beforeunload fired on document"); });
78     document.addEventListener("unload", function() { ok(false, "unload fired on document"); });
79 }else {
80     document.attachEvent("onbeforeunload", function() { ok(false, "beforeunload fired on document"); });
81     document.attachEvent("onunload", function() { ok(false, "unload fired on document"); });
84 sync_test("performance timing", function() {
85     ok(performance.timing.domInteractive >= performance.timing.domLoading, "domInteractive < domLoading");
86     ok(performance.timing.domContentLoadedEventStart >= performance.timing.domInteractive, "domContentLoadedEventStart < domInteractive");
87     ok(performance.timing.domContentLoadedEventEnd >= performance.timing.domContentLoadedEventStart, "domContentLoadedEventEnd < domContentLoadedEventStart");
88     ok(performance.timing.domComplete >= performance.timing.domContentLoadedEventEnd, "domComplete < domContentLoadedEventEnd");
89     ok(performance.timing.loadEventStart >= performance.timing.domComplete, "loadEventStart < domComplete");
90     ok(performance.timing.loadEventEnd >= performance.timing.loadEventStart, "loadEventEnd < loadEventStart");
91     ok(performance.navigation.type === 0, "navigation type = " + performance.navigation.type);
92     ok(performance.navigation.redirectCount === 0, "redirectCount = " + performance.navigation.redirectCount);
93 });
95 sync_test("page transition events", function() {
96     if(document.documentMode < 11)
97         ok(pageshow_fired === false, "pageshow fired");
98     else
99         ok(pageshow_fired === true, "pageshow not fired");
100     ok(pagehide_fired === false, "pagehide fired");
102     if(document.body.addEventListener)
103         document.body.addEventListener("unload", function() { ok(false, "unload fired on document.body"); });
104     else
105         document.body.attachEvent("onunload", function() { ok(false, "unload fired on document.body"); });
108 sync_test("builtin_toString", function() {
109     var tags = [
110         [ "abbr",            "Phrase", -1 ],
111         [ "acronym",         "Phrase", -1 ],
112         [ "address",         "Block", -1 ],
113      // [ "applet",          "Applet" ],  // makes Windows pop up a dialog box
114         [ "article",         "" ],
115         [ "aside",           "" ],
116         [ "audio",           "Audio", -1 ],
117         [ "b",               "Phrase", -1 ],
118         [ "base",            "Base", -1 ],
119         [ "basefont",        "BaseFont", -1 ],
120         [ "bdi",             "Unknown" ],
121         [ "bdo",             "Phrase", -1 ],
122         [ "big",             "Phrase", -1 ],
123         [ "blockquote",      "Block", -1 ],
124         [ "body",            "Body" ],
125         [ "br",              "BR", -1 ],
126         [ "button",          "Button" ],
127         [ "canvas",          "Canvas", -1 ],
128         [ "caption",         "TableCaption", -1 ],
129         [ "center",          "Block", -1 ],
130         [ "cite",            "Phrase", -1 ],
131         [ "code",            "Phrase", -1 ],
132         [ "col",             "TableCol", -1 ],
133         [ "colgroup",        "TableCol", -1 ],
134         [ "data",            "Unknown" ],
135         [ "datalist",        "DataList", 10 ],
136         [ "dd",              "DD", -1 ],
137         [ "del",             "Mod", -1 ],
138         [ "details",         "Unknown" ],
139         [ "dfn",             "Phrase", -1 ],
140         [ "dialog",          "Unknown" ],
141         [ "dir",             "Directory", -1 ],
142         [ "div",             "Div", -1 ],
143         [ "dl",              "DList", -1 ],
144         [ "dt",              "DT", -1 ],
145         [ "em",              "Phrase", -1 ],
146         [ "embed",           "Embed" ],
147         [ "fieldset",        "FieldSet", -1 ],
148         [ "figcaption",      "" ],
149         [ "figure",          "" ],
150         [ "font",            "Font", -1 ],
151         [ "footer",          "" ],
152         [ "form",            "Form", -1 ],
153         [ "frame",           "Frame", -1 ],
154         [ "frameset",        "FrameSet", -1 ],
155         [ "h1",              "Heading", -1 ],
156         [ "h2",              "Heading", -1 ],
157         [ "h3",              "Heading", -1 ],
158         [ "h4",              "Heading", -1 ],
159         [ "h5",              "Heading", -1 ],
160         [ "h6",              "Heading", -1 ],
161         [ "h7",              "Unknown" ],
162         [ "head",            "Head" ],
163         [ "header",          "" ],
164         [ "hr",              "HR", -1 ],
165         [ "html",            "Html" ],
166         [ "i",               "Phrase", -1 ],
167         [ "iframe",          "IFrame", -1 ],
168         [ "img",             "Image" ],
169         [ "input",           "Input" ],
170         [ "ins",             "Mod", -1 ],
171         [ "kbd",             "Phrase", -1 ],
172         [ "label",           "Label" ],
173         [ "legend",          "Legend", -1 ],
174         [ "li",              "LI", -1 ],
175         [ "link",            "Link" ],
176         [ "main",            "Unknown" ],
177         [ "map",             "Map", -1 ],
178         [ "mark",            "" ],
179         [ "meta",            "Meta" ],
180         [ "meter",           "Unknown" ],
181         [ "nav",             "" ],
182         [ "noframes",        "" ],
183         [ "noscript",        "" ],
184         [ "object",          "Object", -1 ],
185         [ "ol",              "OList", -1 ],
186         [ "optgroup",        "OptGroup", -1 ],
187         [ "option",          "Option" ],
188         [ "output",          "Unknown" ],
189         [ "p",               "Paragraph", -1 ],
190         [ "param",           "Param", -1 ],
191         [ "picture",         "Unknown" ],
192         [ "pre",             "Pre", -1 ],
193         [ "progress",        "Progress", 10 ],
194         [ "q",               "Quote", -1 ],
195         [ "rp",              "Phrase", -1 ],
196         [ "rt",              "Phrase", -1 ],
197         [ "ruby",            "Phrase", -1 ],
198         [ "s",               "Phrase", -1 ],
199         [ "samp",            "Phrase", -1 ],
200         [ "script",          "Script" ],
201         [ "section",         "" ],
202         [ "select",          "Select", -1 ],
203         [ "small",           "Phrase", -1 ],
204         [ "source",          "Source", -1 ],
205         [ "span",            "Span", -1 ],
206         [ "strike",          "Phrase", -1 ],
207         [ "strong",          "Phrase", -1 ],
208         [ "style",           "Style" ],
209         [ "sub",             "Phrase", -1 ],
210         [ "summary",         "Unknown" ],
211         [ "sup",             "Phrase", -1 ],
212         [ "svg",             "Unknown" ],
213         [ "table",           "Table" ],
214         [ "tbody",           "TableSection", -1 ],
215         [ "td",              "TableDataCell" ],
216         [ "template",        "Unknown" ],
217         [ "textarea",        "TextArea" ],
218         [ "tfoot",           "TableSection", -1 ],
219         [ "th",              "TableHeaderCell", -1 ],
220         [ "thead",           "TableSection", -1 ],
221         [ "time",            "Unknown" ],
222         [ "title",           "Title" ],
223         [ "tr",              "TableRow" ],
224         [ "track",           "Track", 10 ],
225         [ "tt",              "Phrase", -1 ],
226         [ "u",               "Phrase", -1 ],
227         [ "ul",              "UList", -1 ],
228         [ "var",             "Phrase", -1 ],
229         [ "video",           "Video", -1 ],
230         [ "wbr",             "" ],
231         [ "winetest",        "Unknown" ]
232     ];
233     var v = document.documentMode, e;
235     function test(msg, obj, name, tostr, is_todo) {
236         var s;
237         if(obj.toString) {
238             s = obj.toString();
239             todo_wine_if(name !== "HTMLElement" && s === "[object HTMLElement]").
240             ok(s === (tostr ? tostr : (v < 9 ? "[object]" : "[object " + name + "]")), msg + " toString returned " + s);
241         }
242         s = Object.prototype.toString.call(obj);
243         todo_wine_if(v >= 9 && is_todo).
244         ok(s === (v < 9 ? "[object Object]" : "[object " + name + "]"), msg + " Object.toString returned " + s);
245     }
247     for(var i = 0; i < tags.length; i++)
248         if(tags[i].length < 3 || v >= tags[i][2])
249             test("tag '" + tags[i][0] + "'", document.createElement(tags[i][0]), "HTML" + tags[i][1] + "Element", null, tags[i].length > 2);
251     e = document.createElement("a");
252     ok(e.toString() === "", "tag 'a' (without href) toString returned " + e.toString());
253     e.href = "https://www.winehq.org/";
254     test("tag 'a'", e, "HTMLAnchorElement", "https://www.winehq.org/");
256     e = document.createElement("area");
257     ok(e.toString() === "", "tag 'area' (without href) toString returned " + e.toString());
258     e.href = "https://www.winehq.org/";
259     test("tag 'area'", e, "HTMLAreaElement", "https://www.winehq.org/");
261     e = document.createElement("style");
262     document.body.appendChild(e);
263     var sheet = v >= 9 ? e.sheet : e.styleSheet;
264     if(v >= 9)
265         sheet.insertRule("div { border: none }", 0);
266     else
267         sheet.addRule("div", "border: none", 0);
269     e = document.createElement("p");
270     e.className = "testclass    another ";
271     e.textContent = "Test content";
272     e.style.border = "1px solid black";
273     document.body.appendChild(e);
275     var txtRange = document.body.createTextRange();
276     txtRange.moveToElementText(e);
278     var clientRects = e.getClientRects();
279     if(!clientRects) win_skip("getClientRects() is buggy and not available, skipping");
281     var currentStyle = e.currentStyle;
282     if(!currentStyle) win_skip("currentStyle is buggy and not available, skipping");
284     // w10pro64 testbot VM throws WININET_E_INTERNAL_ERROR for some reason
285     var localStorage;
286     try {
287         localStorage = window.localStorage;
288     }catch(e) {
289         ok(e.number === 0x72ee4 - 0x80000000, "localStorage threw " + e.number + ": " + e);
290     }
291     if(!localStorage) win_skip("localStorage is buggy and not available, skipping");
293     test("attribute", document.createAttribute("class"), "Attr");
294     if(false /* todo_wine */) test("attributes", e.attributes, "NamedNodeMap");
295     test("childNodes", document.body.childNodes, "NodeList", null, true);
296     if(clientRects) test("clientRect", clientRects[0], "ClientRect", null, true);
297     if(clientRects) test("clientRects", clientRects, "ClientRectList", null, true);
298     if(currentStyle) test("currentStyle", currentStyle, "MSCurrentStyleCSSProperties", null, true);
299     if(v >= 11 /* todo_wine */) test("document", document, v < 11 ? "Document" : "HTMLDocument", null, true);
300     test("elements", document.getElementsByTagName("body"), "HTMLCollection", null, true);
301     test("history", window.history, "History");
302     test("implementation", document.implementation, "DOMImplementation");
303     if(localStorage) test("localStorage", localStorage, "Storage", null, true);
304     test("location", window.location, "Object", window.location.href, null, true);
305     if(v >= 11 /* todo_wine */) test("mimeTypes", window.navigator.mimeTypes, v < 11 ? "MSMimeTypesCollection" : "MimeTypeArray");
306     test("navigator", window.navigator, "Navigator");
307     test("performance", window.performance, "Performance");
308     test("performanceNavigation", window.performance.navigation, "PerformanceNavigation");
309     test("performanceTiming", window.performance.timing, "PerformanceTiming");
310     if(v >= 11 /* todo_wine */) test("plugins", window.navigator.plugins, v < 11 ? "MSPluginsCollection" : "PluginArray");
311     test("screen", window.screen, "Screen");
312     test("sessionStorage", window.sessionStorage, "Storage", null, true);
313     test("style", document.body.style, "MSStyleCSSProperties", null, true);
314     test("styleSheet", sheet, "CSSStyleSheet", null, true);
315     test("styleSheetRule", sheet.rules[0], "CSSStyleRule", null, true);
316     test("styleSheetRules", sheet.rules, "MSCSSRuleList", null, true);
317     test("styleSheets", document.styleSheets, "StyleSheetList", null, true);
318     test("textNode", document.createTextNode("testNode"), "Text", v < 9 ? "testNode" : null);
319     test("textRange", txtRange, "TextRange");
320     test("window", window, "Window", "[object Window]", true);
321     test("xmlHttpRequest", new XMLHttpRequest(), "XMLHttpRequest");
322     if(v < 10) {
323         test("namespaces", document.namespaces, "MSNamespaceInfoCollection");
324     }
325     if(v < 11) {
326         test("eventObject", document.createEventObject(), "MSEventObj");
327         test("selection", document.selection, "MSSelection");
328     }
329     if(v >= 9) {
330         test("computedStyle", window.getComputedStyle(e), "CSSStyleDeclaration", null, true);
331         test("doctype", document.doctype, "DocumentType");
333         test("Event", document.createEvent("Event"), "Event");
334         test("CustomEvent", document.createEvent("CustomEvent"), "CustomEvent");
335         test("KeyboardEvent", document.createEvent("KeyboardEvent"), "KeyboardEvent");
336         test("MouseEvent", document.createEvent("MouseEvent"), "MouseEvent");
337         test("UIEvent", document.createEvent("UIEvent"), "UIEvent");
338     }
339     if(v >= 10) {
340         test("classList", e.classList, "DOMTokenList", "testclass    another ", true);
341         test("console", window.console, "Console");
342         test("mediaQueryList", window.matchMedia("(hover:hover)"), "MediaQueryList");
343     }
344     if(v >= 11) {
345         test("MutationObserver", new window.MutationObserver(function() {}), "MutationObserver", null, true);
346     }
347     if(v >= 9) {
348         document.body.innerHTML = "<!--...-->";
349         test("comment", document.body.firstChild, "Comment");
350     }
353 sync_test("builtin_obj", function() {
354     var v = document.documentMode;
355     var f = document.createElement;
356     var e;
358     if(v < 9) {
359         ok(!(window instanceof Object), "window instance of Object");
360         ok(!(document instanceof Object), "document instance of Object");
361         ok(!("arguments" in f), "arguments in f");
362         ok(!("length" in f), "length in f");
363         e = 0;
364         try {
365             f.toString();
366         }catch(ex) {
367             e = ex.number;
368         }
369         ok(e === 0xa01b6 - 0x80000000, "[f.toString] e = " + e);
370         try {
371             window.toString.call(null);
372             ok(false, "expected exception calling window.toString with null context");
373         }catch(ex) {}
374     }
376     e = 0;
377     try {
378         f.call(Object, "div");
379     }catch(ex) {
380         e = ex.number;
381     }
382     todo_wine_if(v >= 9).
383     ok(e === (v < 9 ? 0xa0005 : 0x0ffff) - 0x80000000, "[f.call(Object, 'div')] e = " + e);
385     e = 0;
386     try {
387         f.call(null, "div");
388     }catch(ex) {
389         e = ex.number;
390     }
391     todo_wine_if(v >= 9).
392     ok(e === (v < 9 ? 0xa0005 : 0x0ffff) - 0x80000000, "[f.call(null, 'div')] e = " + e);
394     var elem1 = f.call(document, "div");
395     var elem2 = f.call(document, "br");
396     document.body.appendChild(elem1);
397     document.body.appendChild(elem2);
398     elem1.onclick = function() { ok(false, "unexpected elem1.onclick"); };
399     var clicked = false;
400     elem2.onclick = function() { clicked = true; };
401     elem1.click.call(elem2);
402     ok(clicked === true, "elem2.onclick not called");
404     elem1 = f.apply(document, ["div"]);
405     elem2 = f.apply(document, ["br"]);
406     document.body.appendChild(elem1);
407     document.body.appendChild(elem2);
408     elem1.onclick = function() { ok(false, "unexpected elem1.onclick"); };
409     clicked = false;
410     elem2.onclick = function() { clicked = true; };
411     elem1.click.apply(elem2);
412     ok(clicked === true, "elem2.onclick not called");
414     try {
415         elem1.click.apply(elem2, { length: -1 });
416         ok(false, "exception expected");
417     }catch(ex) {}
420 sync_test("elem_props", function() {
421     var elem = document.documentElement;
423     function test_exposed(prop, expect, is_todo) {
424         var ok_ = is_todo ? todo_wine.ok : ok;
425         if(expect)
426             ok_(prop in elem, prop + " not found in element.");
427         else
428             ok_(!(prop in elem), prop + " found in element.");
429     }
431     var v = document.documentMode;
433     test_exposed("attachEvent", v < 11);
434     test_exposed("detachEvent", v < 11);
435     test_exposed("doScroll", v < 11);
436     test_exposed("readyState", v < 11);
437     test_exposed("clientTop", true);
438     test_exposed("title", true);
439     test_exposed("querySelectorAll", v >= 8);
440     test_exposed("textContent", v >= 9);
441     test_exposed("prefix", v >= 9);
442     test_exposed("firstElementChild", v >= 9);
443     test_exposed("onsubmit", v >= 9);
444     test_exposed("getElementsByClassName", v >= 9);
445     test_exposed("removeAttributeNS", v >= 9);
446     test_exposed("addEventListener", v >= 9);
447     test_exposed("hasAttribute", v >= 8, v === 8);
448     test_exposed("removeEventListener", v >= 9);
449     test_exposed("dispatchEvent", v >= 9);
450     test_exposed("msSetPointerCapture", v >= 10);
451     if (v >= 9) test_exposed("spellcheck", v >= 10);
453     elem = document.createElement("style");
454     test_exposed("media", true);
455     test_exposed("type", true);
456     test_exposed("disabled", true);
457     test_exposed("media", true);
458     test_exposed("sheet", v >= 9);
459     test_exposed("readyState", v < 11);
460     test_exposed("styleSheet", v < 11);
461     test_exposed("classList", v >= 10);
463     elem = document.createElement("img");
464     test_exposed("fileSize", v < 11);
467 sync_test("doc_props", function() {
468     function test_exposed(prop, expect, is_todo) {
469         var ok_ = is_todo ? todo_wine.ok : ok;
470         if(expect)
471             ok_(prop in document, prop + " not found in document.");
472         else
473             ok_(!(prop in document), prop + " found in document.");
474     }
476     var v = document.documentMode;
477     ok(document.mimeType === external.getExpectedMimeType("text/html"), "mimeType = " + document.mimeType);
479     test_exposed("attachEvent", v < 11);
480     test_exposed("detachEvent", v < 11);
481     test_exposed("createStyleSheet",v < 11);
482     test_exposed("fileSize", v < 11);
483     test_exposed("selection", v < 11);
484     test_exposed("onstorage", v < 9);
485     test_exposed("textContent", v >= 9);
486     test_exposed("prefix", v >= 9);
487     test_exposed("defaultView", v >= 9);
488     test_exposed("head", v >= 9);
489     test_exposed("addEventListener", v >= 9);
490     test_exposed("removeEventListener", v >= 9);
491     test_exposed("dispatchEvent", v >= 9);
492     test_exposed("createEvent", v >= 9);
494     test_exposed("parentWindow", true);
495     if(v >= 9) ok(document.defaultView === document.parentWindow, "defaultView != parentWindow");
498 sync_test("docfrag_props", function() {
499     var docfrag = document.createDocumentFragment();
501     function test_exposed(prop, expect) {
502         if(expect)
503             ok(prop in docfrag, prop + " not found in document fragent.");
504         else
505             ok(!(prop in docfrag), prop + " found in document fragent.");
506     }
508     var v = document.documentMode;
510     test_exposed("compareDocumentPosition", v >= 9);
513 sync_test("window_props", function() {
514     function test_exposed(prop, expect, is_todo) {
515         var ok_ = is_todo ? todo_wine.ok : ok;
516         if(expect)
517             ok_(prop in window, prop + " not found in window.");
518         else
519             ok_(!(prop in window), prop + " found in window.");
520     }
522     var v = document.documentMode;
524     test_exposed("attachEvent", v < 11);
525     test_exposed("detachEvent", v < 11);
526     test_exposed("execScript", v < 11);
527     test_exposed("createPopup", v < 11);
528     test_exposed("postMessage", true);
529     test_exposed("sessionStorage", true);
530     test_exposed("localStorage", true);
531     test_exposed("addEventListener", v >= 9);
532     test_exposed("removeEventListener", v >= 9);
533     test_exposed("dispatchEvent", v >= 9);
534     test_exposed("getSelection", v >= 9);
535     test_exposed("onfocusout", v >= 9);
536     test_exposed("getComputedStyle", v >= 9);
537     test_exposed("cancelAnimationFrame", v >= 10);
538     test_exposed("requestAnimationFrame", v >= 10);
539     test_exposed("Map", v >= 11);
540     test_exposed("Set", v >= 11);
541     test_exposed("WeakMap", v >= 11);
542     test_exposed("WeakSet", false);
543     test_exposed("performance", true);
544     test_exposed("console", v >= 10);
545     test_exposed("matchMedia", v >= 10);
546     test_exposed("MutationObserver", v >= 11);
549 sync_test("domimpl_props", function() {
550     var domimpl = document.implementation;
551     function test_exposed(prop, expect) {
552         if(expect)
553             ok(prop in domimpl, prop + " not found in DOMImplementation.");
554         else
555             ok(!(prop in domimpl), prop + " found in DOMImplementation.");
556     }
558     var v = document.documentMode;
560     test_exposed("hasFeature", true);
561     test_exposed("createDocument", v >= 9);
562     test_exposed("createDocumentType", v >= 9);
563     test_exposed("createHTMLDocument", v >= 9);
566 sync_test("xhr_props", function() {
567     var xhr = new XMLHttpRequest();
569     function test_exposed(prop, expect) {
570         if(expect)
571             ok(prop in xhr, prop + " not found in XMLHttpRequest.");
572         else
573             ok(!(prop in xhr), prop + " found in XMLHttpRequest.");
574     }
576     var v = document.documentMode;
578     test_exposed("addEventListener", v >= 9);
579     test_exposed("removeEventListener", v >= 9);
580     test_exposed("dispatchEvent", v >= 9);
581     test_exposed("onabort", v >= 10);
582     test_exposed("onerror", v >= 10);
583     test_exposed("onloadend", v >= 10);
584     test_exposed("onloadstart", v >= 10);
585     test_exposed("onprogress", v >= 10);
586     test_exposed("ontimeout", true);
587     test_exposed("overrideMimeType", v >= 11);
588     test_exposed("response", v >= 10);
589     test_exposed("responseType", v >= 10);
590     test_exposed("timeout", true);
591     test_exposed("upload", v >= 10);
592     test_exposed("withCredentials", v >= 10);
595 sync_test("stylesheet_props", function() {
596     var v = document.documentMode;
597     var elem = document.createElement("style");
598     document.body.appendChild(elem);
599     var sheet = v >= 9 ? elem.sheet : elem.styleSheet;
601     function test_exposed(prop, expect) {
602         if(expect)
603             ok(prop in sheet, prop + " not found in style sheet.");
604         else
605             ok(!(prop in sheet), prop + " found in style sheet.");
606     }
608     test_exposed("href", true);
609     test_exposed("title", true);
610     test_exposed("type", true);
611     test_exposed("media", true);
612     test_exposed("ownerNode", v >= 9);
613     test_exposed("ownerRule", v >= 9);
614     test_exposed("cssRules", v >= 9);
615     test_exposed("insertRule", v >= 9);
616     test_exposed("deleteRule", v >= 9);
617     test_exposed("disabled", true);
618     test_exposed("parentStyleSheet", true);
619     test_exposed("owningElement", true);
620     test_exposed("readOnly", true);
621     test_exposed("imports", true);
622     test_exposed("id", true);
623     test_exposed("addImport", true);
624     test_exposed("addRule", true);
625     test_exposed("removeImport", true);
626     test_exposed("removeRule", true);
627     test_exposed("cssText", true);
628     test_exposed("rules", true);
631 sync_test("rect_props", function() {
632     document.body.innerHTML = '<div>test</div>';
633     var elem = document.body.firstChild;
634     var rect = elem.getBoundingClientRect();
635     function test_exposed(prop, expect) {
636         if(expect)
637             ok(prop in rect, prop + " not found in rect object.");
638         else
639             ok(!(prop in rect), prop + " found in rect object.");
640     }
642     var v = document.documentMode;
644     test_exposed("width", v >= 9);
645     test_exposed("height", v >= 9);
648 sync_test("xhr open", function() {
649     var e = false;
650     try {
651         (new XMLHttpRequest()).open("GET", "https://www.winehq.org/");
652     }catch(ex) {
653         e = true;
654     }
656     if(document.documentMode < 10)
657         ok(e, "expected exception");
658     else
659         ok(!e, "unexpected exception");
662 sync_test("style_props", function() {
663     var style = document.body.style;
665     function test_exposed(prop, expect) {
666         if(expect)
667             ok(prop in style, prop + " not found in style object.");
668         else
669             ok(!(prop in style), prop + " found in style object.");
670     }
672     var v = document.documentMode;
674     test_exposed("removeAttribute", true);
675     test_exposed("zIndex", true);
676     test_exposed("z-index", true);
677     test_exposed("filter", true);
678     test_exposed("pixelTop", true);
679     test_exposed("float", true);
680     test_exposed("css-float", false);
681     test_exposed("style-float", false);
682     test_exposed("setProperty", v >= 9);
683     test_exposed("removeProperty", v >= 9);
684     test_exposed("background-clip", v >= 9);
685     test_exposed("msTransform", v >= 9);
686     test_exposed("transform", v >= 10);
688     style = document.body.currentStyle;
690     test_exposed("zIndex", true);
691     test_exposed("z-index", true);
692     test_exposed("filter", true);
693     test_exposed("pixelTop", false);
694     test_exposed("float", true);
695     test_exposed("css-float", false);
696     test_exposed("style-float", false);
697     test_exposed("setProperty", v >= 9);
698     test_exposed("removeProperty", v >= 9);
699     test_exposed("background-clip", v >= 9);
700     test_exposed("transform", v >= 10);
702     if(window.getComputedStyle) {
703         style = window.getComputedStyle(document.body);
705         test_exposed("removeAttribute", false);
706         test_exposed("zIndex", true);
707         test_exposed("z-index", true);
708         test_exposed("pixelTop", false);
709         test_exposed("float", true);
710         test_exposed("css-float", false);
711         test_exposed("style-float", false);
712         test_exposed("setProperty", v >= 9);
713         test_exposed("removeProperty", v >= 9);
714         test_exposed("background-clip", v >= 9);
715         test_exposed("transform", v >= 10);
716     }
719 sync_test("createElement_inline_attr", function() {
720     var v = document.documentMode, e, s;
722     if(v < 9) {
723         s = document.createElement("<div>").tagName;
724         ok(s === "DIV", "<div>.tagName returned " + s);
725         s = document.createElement("<div >").tagName;
726         ok(s === "DIV", "<div >.tagName returned " + s);
727         s = document.createElement("<div/>").tagName;
728         ok(s === "DIV", "<div/>.tagName returned " + s);
729         e = 0;
730         try {
731             document.createElement("<div");
732         }catch(ex) {
733             e = ex.number;
734         }
735         ok(e === 0x4005 - 0x80000000, "<div e = " + e);
736         e = 0;
737         try {
738             document.createElement("<div test=1");
739         }catch(ex) {
740             e = ex.number;
741         }
742         ok(e === 0x4005 - 0x80000000, "<div test=1 e = " + e);
744         var tags = [ "div", "head", "body", "title", "html" ];
746         for(var i = 0; i < tags.length; i++) {
747             e = document.createElement("<" + tags[i] + " test='a\"' abcd=\"&quot;b&#34;\">");
748             ok(e.tagName === tags[i].toUpperCase(), "<" + tags[i] + " test=\"a\" abcd=\"b\">.tagName returned " + e.tagName);
749             ok(e.test === "a\"", "<" + tags[i] + " test='a\"' abcd=\"&quot;b&#34;\">.test returned " + e.test);
750             ok(e.abcd === "\"b\"", "<" + tags[i] + " test='a\"' abcd=\"&quot;b&#34;\">.abcd returned " + e.abcd);
751         }
752     }else {
753         s = "";
754         e = 0;
755         try {
756             document.createElement("<div>");
757         }catch(ex) {
758             s = ex.toString();
759             e = ex.number;
760         }
761         todo_wine.
762         ok(e === undefined, "<div> e = " + e);
763         todo_wine.
764         ok(s === "InvalidCharacterError", "<div> s = " + s);
765         s = "";
766         e = 0;
767         try {
768             document.createElement("<div test=\"a\">");
769         }catch(ex) {
770             s = ex.toString();
771             e = ex.number;
772         }
773         todo_wine.
774         ok(e === undefined, "<div test=\"a\"> e = " + e);
775         todo_wine.
776         ok(s === "InvalidCharacterError", "<div test=\"a\"> s = " + s);
777     }
780 sync_test("JS objs", function() {
781     var g = window;
783     function test_exposed(func, obj, expect, is_todo) {
784         var ok_ = is_todo ? todo_wine.ok : ok;
785         if(expect)
786             ok_(func in obj, func + " not found in " + obj);
787         else
788             ok_(!(func in obj), func + " found in " + obj);
789     }
791     function test_parses(code, expect) {
792         var success;
793         try {
794             eval(code);
795             success = true;
796         }catch(e) {
797             success = false;
798         }
799         if(expect)
800             ok(success === true, code + " did not parse");
801         else
802             ok(success === false, code + " parsed");
803     }
805     var v = document.documentMode;
807     test_exposed("ScriptEngineMajorVersion", g, true);
809     test_exposed("JSON", g, v >= 8);
810     test_exposed("now", Date, true);
811     test_exposed("toISOString", Date.prototype, v >= 9);
812     test_exposed("isArray", Array, v >= 9);
813     test_exposed("forEach", Array.prototype, v >= 9);
814     test_exposed("indexOf", Array.prototype, v >= 9);
815     test_exposed("trim", String.prototype, v >= 9);
816     test_exposed("map", Array.prototype, v >= 9);
818     /* FIXME: IE8 implements weird semi-functional property descriptors. */
819     test_exposed("getOwnPropertyDescriptor", Object, v >= 8, v === 8);
820     test_exposed("defineProperty", Object, v >= 8, v === 8);
821     test_exposed("defineProperties", Object, v >= 9);
823     test_exposed("getPrototypeOf", Object, v >= 9);
825     test_parses("if(false) { o.default; }", v >= 9);
826     test_parses("if(false) { o.with; }", v >= 9);
827     test_parses("if(false) { o.if; }", v >= 9);
830 sync_test("eval", function() {
831     var i, context, code = "this.foobar = 1234", v = document.documentMode;
833     var direct = [
834         function() { eval(code); },
835         function() { (eval)(code); },
836         function() { (function(eval) { eval(code); }).call(this, eval); },
837         function() { eval("eval(" + code + ")"); }
838     ];
840     for(i = 0; i < direct.length; i++) {
841         context = {};
842         direct[i].call(context);
843         ok(context.foobar === 1234, "direct[" + i + "] context foobar = " + context.foobar);
844     }
846     var indirect = [
847         function() { (true, eval)(code); },
848         function() { (eval, eval)(code); },
849         function() { (true ? eval : false)(code); },
850         function() { [eval][0](code); },
851         function() { eval.call(this, code); },
852         function() { var f; (f = eval)(code); },
853         function() { var f = eval; f(code); },
854         function() { (function(f) { f(code); }).call(this, eval); },
855         function() { (function(f) { return f; }).call(this, eval)(code); },
856         function() { (function() { arguments[0](code) }).call(this, eval); },
857         function() { window.eval(code); },
858         function() { window["eval"](code); },
859         function() { eval("eval")(code); }
860     ];
862     for(i = 0; i < indirect.length; i++) {
863         context = {};
864         ok(!("foobar" in window), "indirect[" + i + "] has global foobar before call");
865         indirect[i].call(context);
866         if(v < 9) {
867             ok(context.foobar === 1234, "indirect[" + i + "] context foobar = " + context.foobar);
868             ok(!("foobar" in window), "indirect[" + i + "] has global foobar");
869         }else {
870             ok(!("foobar" in context), "indirect[" + i + "] has foobar");
871             ok(window.foobar === 1234, "indirect[" + i + "] global foobar = " + context.foobar);
872             delete window.foobar;
873         }
874     }
876     context = {};
877     (function(eval) { eval(code); })(function() { context.barfoo = 4321; });
878     ok(context.barfoo === 4321, "context.barfoo = " + context.barfoo);
881 sync_test("for..in", function() {
882     var v = document.documentMode, found = 0, r;
884     function ctor() {}
885     ctor.prototype.test2 = true;
887     var arr = new Array(), obj = new ctor(), i, r;
888     obj.test1 = true;
890     i = 0;
891     for(r in obj) {
892         ctor.prototype.test3 = true;
893         arr[r] = true;
894         i++;
895     }
897     ok(i === 3, "enum did " + i + " iterations");
898     ok(arr["test1"] === true, "arr[test1] !== true");
899     ok(arr["test2"] === true, "arr[test2] !== true");
900     ok(arr["test3"] === true, "arr[test3] !== true");
902     for(r in document)
903         if(r === "ondragstart")
904             found++;
905     ok(found === 1, "ondragstart enumerated " + found + " times in document");
906     document.ondragstart = "";
907     found = 0;
908     for(r in document)
909         if(r === "ondragstart")
910             found++;
911     ok(found === 1, "ondragstart enumerated " + found + " times in document after set to empty string");
914 sync_test("function caller", function() {
915     ok(Function.prototype.hasOwnProperty("caller"), "caller not prop of Function.prototype");
917     function test_caller(expected_caller, stop) {
918         ok(test_caller.caller === expected_caller, "caller = " + test_caller.caller);
919         if(stop) return;
920         function nested() {
921             ok(nested.caller === test_caller, "nested caller = " + nested.caller);
922             test_caller(nested, true);
923             ok(test_caller.caller === expected_caller, "caller within nested = " + test_caller.caller);
924         }
925         nested();
926         ok(test_caller.caller === expected_caller, "caller after nested = " + test_caller.caller);
927     }
928     ok(test_caller.hasOwnProperty("caller"), "caller not prop of test_caller");
929     ok(test_caller.caller === null, "test_caller.caller = " + test_caller.caller);
931     function f1() { test_caller(f1); } f1();
932     function f2() { test_caller(f2); } f2();
935 sync_test("elem_by_id", function() {
936     document.body.innerHTML = '<form id="testid" name="testname"></form>';
937     var v = document.documentMode, found, i;
939     var id_elem = document.getElementById("testid");
940     ok(id_elem.tagName === "FORM", "id_elem.tagName = " + id_elem.tagName);
942     var name_elem = document.getElementById("testname");
943     if(v < 8)
944         ok(id_elem === name_elem, "id_elem != id_elem");
945     else
946         ok(name_elem === null, "name_elem != null");
948     id_elem = window.testid;
949     ok(id_elem.tagName === "FORM", "window.testid = " + id_elem);
951     name_elem = document.testname;
952     ok(name_elem.tagName === "FORM", "document.testname = " + name_elem);
954     for(id_elem in window)
955         ok(id_elem !== "testid" && id_elem != "testname", id_elem + " was enumerated in window");
956     window.testid = 137;
957     found = false;
958     for(id_elem in window) {
959         ok(id_elem != "testname", id_elem + " was enumerated in window after set to 137");
960         if(id_elem === "testid")
961             found = true;
962     }
963     ok(found, "testid was not enumerated in window after set to 137");
965     found = false;
966     for(id_elem in document) {
967         ok(id_elem !== "testid", "testid was enumerated in document");
968         if(id_elem === "testname")
969             found = true;
970     }
971     ok(found, "testname was not enumerated in document");
973     try {
974         document.testname();
975         ok(false, "document.testname() did not throw exception");
976     }catch(e) {
977         ok(e.number === 0xa01b6 - 0x80000000, "document.testname() threw = " + e.number);
978     }
980     try {
981         document.testname = "foo";
982         ok(v >= 9, "Setting document.testname did not throw exception");
984         id_elem = document.testid;
985         ok(id_elem.tagName === "FORM", "document.testid after set = " + id_elem);
986         name_elem = document.testname;
987         ok(name_elem === "foo", "document.testname after set = " + name_elem);
988     }catch(e) {
989         todo_wine_if(v >= 9).
990         ok(v < 9 && e.number === 0xa01b6 - 0x80000000, "Setting document.testname threw = " + e.number);
991     }
993     try {
994         document.testid = "bar";
995         ok(v >= 9, "Setting document.testid did not throw exception");
997         id_elem = document.testid;
998         ok(id_elem === "bar", "document.testid after both set = " + id_elem);
999         name_elem = document.testname;
1000         ok(name_elem === "foo", "document.testname after both set = " + name_elem);
1002         found = false, name_elem = false;
1003         for(id_elem in document) {
1004             if(id_elem === "testid")
1005                 found = true;
1006             if(id_elem === "testname")
1007                 name_elem = true;
1008         }
1009         ok(found, "testid was not enumerated in document after both set");
1010         ok(name_elem, "testname was not enumerated in document after both set");
1011         delete document.testid;
1012         delete document.testname;
1013     }catch(e) {
1014         todo_wine_if(v >= 9).
1015         ok(v < 9 && e.number === 0xa01b6 - 0x80000000, "Setting document.testid threw = " + e.number);
1016     }
1018     window.testid2 = 1;
1019     document.testid2 = 2;
1020     document.body.innerHTML = '<form id="testid2" name="testname"></form>';
1021     ok(window.testid2 == 1, "window.testid2 = " + window.testid2);
1022     id_elem = document.body.firstChild;
1023     ok(document.testid2 == (v < 9 ? id_elem : 2), "document.testid2 = " + document.testid2);
1024     document.body.innerHTML = '';
1025     ok(window.testid2 == 1, "window.testid2 = " + window.testid2);
1026     ok(document.testid2 == 2, "document.testid2 = " + document.testid2 + " expected 2");
1028     ok(document.title === "", "document.title = " + document.title);
1029     document.body.innerHTML = '<form id="title" name="testname"></form>';
1030     id_elem = document.body.firstChild;
1031     todo_wine_if(v < 9).
1032     ok(document.title === (v < 9 ? id_elem : ""), "document.title = " + document.title);
1033     document.body.innerHTML = '';
1034     ok(document.title === "", "document.title = " + document.title);
1036     ok(window.closed === false, "window.closed = " + window.closed);
1037     document.body.innerHTML = '<form id="closed" name="testname"></form>';
1038     id_elem = document.body.firstChild;
1039     ok(window.closed === false, "window.closed = " + window.closed);
1041     // these tags expose name as props, and id only if they have a name
1042     var tags = [ "embed", "form", "iframe", "img" ];
1043     for(i in tags) {
1044         var tag = tags[i];
1045         document.body.innerHTML = '<' + tag + ' id="testid" name="testname"></' + tag + '><' + tag + ' id="foobar"></' + tag + '>';
1046         ok("testname" in document, tag + " did not expose testname");
1047         ok("testid" in document, tag + " did not expose testid");
1048         ok(!("foobar" in document), tag + " exposed foobar");
1049     }
1051     // these tags always expose their id as well as name (we don't test applet because it makes Windows pop up a dialog box)
1052     tags = [ "object" ];
1053     for(i in tags) {
1054         var tag = tags[i];
1055         document.body.innerHTML = '<' + tag + ' id="testid" name="testname"></' + tag + '><' + tag + ' id="foobar"></' + tag + '>';
1056         ok("testname" in document, tag + " did not expose testname");
1057         ok("testid" in document, tag + " did not expose testid");
1058         ok("foobar" in document, tag + " did not expose foobar");
1059     }
1061     // all other tags don't expose props for either id or name, test a few of them here
1062     tags = [ "a", "b", "body", "center", "div", "frame", "h2", "head", "html", "input", "meta", "p", "span", "style", "table", "winetest" ];
1063     for(i in tags) {
1064         var tag = tags[i];
1065         document.body.innerHTML = '<' + tag + ' id="testid" name="testname"></' + tag + '><' + tag + ' id="foobar"></' + tag + '>';
1066         ok(!("testname" in document), tag + " exposed testname");
1067         ok(!("testid" in document), tag + " exposed testid");
1068         ok(!("foobar" in document), tag + " exposed foobar");
1069     }
1072 sync_test("doc_mode", function() {
1073     compat_version = parseInt(document.location.search.substring(1));
1075     trace("Testing compatibility mode " + compat_version);
1077     if(compat_version > 6 && compat_version > document.documentMode) {
1078         win_skip("Document mode not supported (expected " + compat_version + " got " + document.documentMode + ")");
1079         reportSuccess();
1080         return;
1081     }
1083     ok(Math.max(compat_version, 5) === document.documentMode, "documentMode = " + document.documentMode);
1085     if(document.documentMode > 5)
1086         ok(document.compatMode === "CSS1Compat", "document.compatMode = " + document.compatMode);
1087     else
1088         ok(document.compatMode === "BackCompat", "document.compatMode = " + document.compatMode);
1091 sync_test("doctype", function() {
1092     var doctype = document.doctype;
1094     if(document.documentMode < 9) {
1095         ok(doctype === null, "doctype = " + document.doctype);
1096         return;
1097     }
1099     ok(doctype.name === "html", "doctype.name = " + doctype.name);
1102 async_test("iframe_doc_mode", function() {
1103     var iframe = document.createElement("iframe");
1105     iframe.onload = function() {
1106         var iframe_mode = iframe.contentWindow.document.documentMode;
1107         if(document.documentMode < 9)
1108             ok(iframe_mode === 5, "iframe_mode = " + iframe_mode);
1109         else
1110             ok(iframe_mode === document.documentMode, "iframe_mode = " + iframe_mode);
1111         next_test();
1112     }
1114     iframe.src = "about:blank";
1115     document.body.appendChild(iframe);
1118 sync_test("conditional_comments", function() {
1119     var div = document.createElement("div");
1120     document.body.appendChild(div);
1122     function test_version(v) {
1123         var version = compat_version ? compat_version : 7;
1125         div.innerHTML = "<!--[if lte IE " + v + "]>true<![endif]-->";
1126         ok(div.innerText === (version <= v ? "true" : ""),
1127            "div.innerText = " + div.innerText + " for version (<=) " + v);
1129         div.innerHTML = "<!--[if lt IE " + v + "]>true<![endif]-->";
1130         ok(div.innerText === (version < v ? "true" : ""),
1131            "div.innerText = " + div.innerText + " for version (<) " + v);
1133         div.innerHTML = "<!--[if gte IE " + v + "]>true<![endif]-->";
1134         ok(div.innerText === (version >= v && version < 10 ? "true" : ""),
1135            "div.innerText = " + div.innerText + " for version (>=) " + v);
1137         div.innerHTML = "<!--[if gt IE " + v + "]>true<![endif]-->";
1138         ok(div.innerText === (version > v && version < 10 ? "true" : ""),
1139            "div.innerText = " + div.innerText + " for version (>) " + v);
1140     }
1142     test_version(5);
1143     test_version(6);
1144     test_version(7);
1145     test_version(8);
1148 var ready_states;
1150 async_test("script_load", function() {
1151     var v = document.documentMode;
1152     if(v < 9) {
1153         next_test();
1154         return;
1155     }
1157     var elem = document.createElement("script");
1158     ready_states = "";
1160     elem.onreadystatechange = guard(function() {
1161         ok(v < 11, "unexpected onreadystatechange call");
1162         ready_states += elem.readyState + ",";
1163     });
1165     elem.onload = guard(function() {
1166         switch(v) {
1167         case 9:
1168             ok(ready_states === "loading,exec,loaded,", "ready_states = " + ready_states);
1169             break;
1170         case 10:
1171             ok(ready_states === "loading,exec,", "ready_states = " + ready_states);
1172             break;
1173         case 11:
1174             ok(ready_states === "exec,", "ready_states = " + ready_states);
1175             break;
1176         }
1177         next_test();
1178     });
1180     document.body.appendChild(elem);
1181     elem.src = "jsstream.php?simple";
1182     external.writeStream("simple", "ready_states += 'exec,';");
1185 sync_test("location", function() {
1186     document.body.innerHTML = '<a name="testanchor">test</a>';
1188     ok(location.hash === "", "initial location.hash = " + location.hash);
1189     location.hash = "TestAnchor";
1190     ok(location.hash === "#TestAnchor", "location.hash after set to TestAnchor = " + location.hash);
1191     location.hash = "##foo";
1192     ok(location.hash === "##foo", "location.hash after set to ##foo = " + location.hash);
1193     location.hash = "#testanchor";
1194     ok(location.hash === "#testanchor", "location.hash after set to #testanchor = " + location.hash);
1197 sync_test("navigator", function() {
1198     var v = document.documentMode, re;
1199     var app = navigator.appVersion;
1200     ok(navigator.userAgent === "Mozilla/" + app,
1201        "userAgent = " + navigator.userAgent + " appVersion = " + app);
1203     re = v < 11
1204         ? "^" + (v < 9 ? "4" : "5") + "\\.0 \\(compatible; MSIE " + (v < 7 ? 7 : v) +
1205           "\\.0; Windows NT [0-9].[0-9]; .*Trident/[678]\\.0.*\\)$"
1206         : "^5.0 \\(Windows NT [0-9].[0-9]; .*Trident/[678]\\.0.*rv:11.0\\) like Gecko$";
1207     ok(new RegExp(re).test(app), "appVersion = " + app);
1209     ok(navigator.appCodeName === "Mozilla", "appCodeName = " + navigator.appCodeName);
1210     ok(navigator.appName === (v < 11 ? "Microsoft Internet Explorer" : "Netscape"),
1211        "appName = " + navigator.appName);
1212     ok(navigator.toString() === (v < 9 ? "[object]" : "[object Navigator]"),
1213        "navigator.toString() = " + navigator.toString());
1216 sync_test("delete_prop", function() {
1217     var v = document.documentMode;
1218     var obj = document.createElement("div"), r, obj2;
1220     obj.prop1 = true;
1221     r = false;
1222     try {
1223         delete obj.prop1;
1224     }catch(ex) {
1225         r = true;
1226     }
1227     if(v < 8) {
1228         ok(r, "did not get an expected exception");
1229         return;
1230     }
1231     ok(!r, "got an unexpected exception");
1232     ok(!("prop1" in obj), "prop1 is still in obj");
1234     /* again, this time prop1 does not exist */
1235     r = false;
1236     try {
1237         delete obj.prop1;
1238     }catch(ex) {
1239         r = true;
1240     }
1241     if(v < 9) {
1242         ok(r, "did not get an expected exception");
1243         return;
1244     }else {
1245         ok(!r, "got an unexpected exception");
1246         ok(!("prop1" in obj), "prop1 is still in obj");
1247     }
1249     r = (delete obj.className);
1250     ok(r, "delete returned " + r);
1251     ok("className" in obj, "className deleted from obj");
1252     ok(obj.className === "", "className = " + obj.className);
1254     /* builtin propertiles don't throw any exception, but are not really deleted */
1255     r = (delete obj.tagName);
1256     ok(r, "delete returned " + r);
1257     ok("tagName" in obj, "tagName deleted from obj");
1258     ok(obj.tagName === "DIV", "tagName = " + obj.tagName);
1260     obj = document.querySelectorAll("*");
1261     ok("0" in obj, "0 is not in obj");
1262     obj2 = obj[0];
1263     r = (delete obj[0]);
1264     ok("0" in obj, "0 is not in obj");
1265     ok(obj[0] === obj2, "obj[0] != obj2");
1267     /* test window object and its global scope handling */
1268     obj = window;
1270     obj.globalprop1 = true;
1271     ok(globalprop1, "globalprop1 = " + globalprop1);
1272     r = false;
1273     try {
1274         delete obj.globalprop1;
1275     }catch(ex) {
1276         r = true;
1277     }
1278     if(v < 9) {
1279         ok(r, "did not get an expected exception");
1280     }else {
1281         ok(!r, "got an unexpected globalprop1 exception");
1282         ok(!("globalprop1" in obj), "globalprop1 is still in obj");
1283     }
1285     globalprop2 = true;
1286     ok(obj.globalprop2, "globalprop2 = " + globalprop2);
1287     r = false;
1288     try {
1289         delete obj.globalprop2;
1290     }catch(ex) {
1291         r = true;
1292     }
1293     if(v < 9) {
1294         ok(r, "did not get an expected globalprop2 exception");
1295     }else {
1296         ok(!r, "got an unexpected exception");
1297         todo_wine.
1298         ok(!("globalprop2" in obj), "globalprop2 is still in obj");
1299     }
1301     obj.globalprop3 = true;
1302     ok(globalprop3, "globalprop3 = " + globalprop3);
1303     r = false;
1304     try {
1305         delete globalprop3;
1306     }catch(ex) {
1307         r = true;
1308     }
1309     if(v < 9) {
1310         ok(r, "did not get an expected exception");
1311         ok("globalprop3" in obj, "globalprop3 is not in obj");
1312     }else {
1313         ok(!r, "got an unexpected globalprop3 exception");
1314         ok(!("globalprop3" in obj), "globalprop3 is still in obj");
1315     }
1317     globalprop4 = true;
1318     ok(obj.globalprop4, "globalprop4 = " + globalprop4);
1319     r = (delete globalprop4);
1320     ok(r, "delete returned " + r);
1321     todo_wine.
1322     ok(!("globalprop4" in obj), "globalprop4 is still in obj");
1325 sync_test("detached arguments", function() {
1326     var args, get_a, set_a, get_x, set_x;
1328     function test_args() {
1329         ok(args[0] === 1, "args[0] = " + args[0]);
1330         set_x(2);
1331         ok(args[0] === 2, "args[0] = " + args[0]);
1332         args[0] = 3;
1333         ok(get_x() === 3, "get_x() = " + get_x());
1334         ok(args[0] === 3, "args[0] = " + args[0]);
1335     }
1337     (function(x) {
1338         args = arguments;
1339         get_x = function() { return x; };
1340         set_x = function(v) { x = v; };
1342         test_args();
1343         x = 1;
1344     })(1);
1345     test_args();
1347     (function(a, a, b, c) {
1348         get_a = function() { return a; }
1349         set_a = function(v) { a = v; }
1350         ok(get_a() === 2, "get_a() = " + get_a());
1351         ok(a === 2, "a = " + a);
1352         ok(b === 3, "b = " + b);
1353         ok(c === 4, "c = " + c);
1354         a = 42;
1355         ok(arguments[0] === 1, "arguments[0] = " + arguments[0]);
1356         ok(arguments[1] === 42, "arguments[1] = " + arguments[1]);
1357         ok(get_a() === 42, "get_a() after assign = " + get_a());
1358         args = arguments;
1359     })(1, 2, 3, 4);
1361     ok(get_a() === 42, "get_a() after detach = " + get_a());
1362     set_a(100);
1363     ok(get_a() === 100, "get_a() after set_a() = " + get_a());
1364     ok(args[0] === 1, "detached args[0] = " + args[0]);
1365     ok(args[1] === 100, "detached args[1] = " + args[1]);
1367     (function(a, a) {
1368         eval("var a = 7;");
1369         ok(a === 7, "function(a, a) a = " + a);
1370         ok(arguments[0] === 5, "function(a, a) arguments[0] = " + arguments[0]);
1371         ok(arguments[1] === 7, "function(a, a) arguments[1] = " + arguments[1]);
1372     })(5, 6);
1375 var func_scope_val = 1;
1376 var func_scope_val2 = 2;
1378 sync_test("func_scope", function() {
1379     var func_scope_val = 2;
1381     var f = function func_scope_val() {
1382         return func_scope_val;
1383     };
1385     func_scope_val = 3;
1386     if(document.documentMode < 9) {
1387         ok(f() === 3, "f() = " + f());
1388         return;
1389     }
1390     ok(f === f(), "f() = " + f());
1392     f = function func_scope_val(a) {
1393         func_scope_val = 4;
1394         return func_scope_val;
1395     };
1397     func_scope_val = 3;
1398     ok(f === f(), "f() = " + f());
1399     ok(func_scope_val === 3, "func_scope_val = " + func_scope_val);
1400     ok(window.func_scope_val === 1, "window.func_scope_val = " + window.func_scope_val);
1402     f = function func_scope_val(a) {
1403         return (function() { return a ? func_scope_val(false) : func_scope_val; })();
1404     };
1406     ok(f === f(true), "f(true) = " + f(true));
1408     window = 1;
1409     ok(window === window.self, "window = " + window);
1411     ! function func_scope_val2() {};
1412     ok(window.func_scope_val2 === 2, "window.func_scope_val2 = " + window.func_scope_val2);
1414     var o = {};
1415     (function(x) {
1416         ok(x === o, "x = " + x);
1417         ! function x() {};
1418         ok(x === o, "x != o");
1419     })(o);
1421     (function(x) {
1422         ok(x === o, "x = " + x);
1423         1, function x() {};
1424         ok(x === o, "x != o");
1425     })(o);
1427     (function() {
1428         ! function x() {};
1429         try {
1430             x();
1431             ok(false, "expected exception");
1432         }catch(e) {}
1433     })(o);
1436 sync_test("set_obj", function() {
1437     if(!("Set" in window)) return;
1439     try {
1440         var s = Set();
1441         ok(false, "expected exception calling constructor as method");
1442     }catch(e) {
1443         ok(e.number === 0xa13fc - 0x80000000, "calling constructor as method threw " + e.number);
1444     }
1446     var s = new Set, r;
1447     ok(Object.getPrototypeOf(s) === Set.prototype, "unexpected Set prototype");
1449     function test_length(name, len) {
1450         ok(Set.prototype[name].length === len, "Set.prototype." + name + " = " + Set.prototype[name].length);
1451         try {
1452             Set.prototype[name].call({}, 0);
1453             ok(false, "expected exception calling Set.prototype." + name + "(object)");
1454         }catch(e) {
1455             ok(e.number === 0xa13fc - 0x80000000, "Set.prototype." + name + "(object) threw " + e.number);
1456         }
1457     }
1458     test_length("add", 1);
1459     test_length("clear", 0);
1460     test_length("delete", 1);
1461     test_length("forEach", 1);
1462     test_length("has", 1);
1463     ok(!("entries" in s), "entries are in Set");
1464     ok(!("keys" in s), "keys are in Set");
1465     ok(!("values" in s), "values are in Set");
1467     r = Object.prototype.toString.call(s);
1468     ok(r === "[object Object]", "toString returned " + r);
1470     r = s.has(-0);
1471     ok(r === false, "has(-0) returned " + r);
1472     ok(s.size === 0, "size = " + s.size);
1474     r = s.add(42);
1475     ok(r === undefined, "add(42) returned " + r);
1476     r = s.add(42);
1477     ok(r === undefined, "add(42) returned " + r);
1478     r = s.add(0);
1479     ok(r === undefined, "add(0) returned " + r);
1480     r = s.has(-0);
1481     ok(r === false, "has(-0) returned " + r);
1482     r = s.add(-0);
1483     ok(r === undefined, "add(-0) returned " + r);
1484     r = s.has(-0);
1485     ok(r === true, "has(-0) after add returned " + r);
1486     r = s.add("test");
1487     ok(r === undefined, "add(test) returned " + r);
1488     r = s.add(13);
1489     ok(r === undefined, "add(13) returned " + r);
1490     r = s.add(s);
1491     ok(r === undefined, "add(s) returned " + r);
1493     r = s["delete"]("test"); /* using s.delete() would break parsing in quirks mode */
1494     ok(r === true, "delete(test) returned " + r);
1495     r = s["delete"]("test");
1496     ok(r === false, "delete(test) returned " + r);
1498     ok(s.size === 5, "size = " + s.size);
1499     s.size = 100;
1500     ok(s.size === 5, "size (after set) = " + s.size);
1502     var a = [];
1503     r = s.forEach(function(value, key, obj) {
1504         var t = s["delete"](key);
1505         ok(t === true, "delete(" + key + ") returned " + r);
1506         ok(value === key, "value = " + value + ", key = " + key);
1507         ok(obj === s, "set = " + obj);
1508         ok(this === a, "this = " + this);
1509         a.push(value);
1510     }, a);
1511     ok(r === undefined, "forEach returned " + r);
1512     ok(a.length === 5, "a.length = " + a.length);
1513     for(var i = 0; i < a.length; i++)
1514         ok(a[i] === [42, 0, -0, 13, s][i], "a[" + i + "] = " + a[i]);
1515     ok(s.size === 0, "size = " + s.size);
1517     s = new Set();
1518     ok(s.size === 0, "size = " + s.size);
1519     s.add(1);
1520     s.add(2);
1521     ok(s.size === 2, "size = " + s.size);
1522     r = s.clear();
1523     ok(r === undefined, "clear returned " + r);
1524     ok(s.size === 0, "size = " + s.size);
1526     s = new Set([1, 2, 3]);
1527     ok(s.size === 0, "size = " + s.size);
1529     s = new Set();
1530     s.add(1);
1531     s.add(2);
1532     s.add(3);
1533     r = 0;
1534     s.forEach(function(value, key, obj) {
1535         r++;
1536         s.clear();
1537         ok(s.size === 0, "size = " + s.size);
1538         ok(this.valueOf() === 42, "this.valueOf() = " + this.valueOf());
1539     }, 42);
1540     ok(r === 1, "r = " + r);
1543 sync_test("map_obj", function() {
1544     if(!("Map" in window)) return;
1546     try {
1547         var s = Map();
1548         ok(false, "expected exception calling constructor as method");
1549     }catch(e) {
1550         ok(e.number === 0xa13fc - 0x80000000, "calling constructor as method threw " + e.number);
1551     }
1553     var s = new Map, r, i;
1554     ok(Object.getPrototypeOf(s) === Map.prototype, "unexpected Map prototype");
1556     function test_length(name, len) {
1557         ok(Map.prototype[name].length === len, "Map.prototype." + name + " = " + Map.prototype[name].length);
1558     }
1559     test_length("clear", 0);
1560     test_length("delete", 1);
1561     test_length("forEach", 1);
1562     test_length("get", 1);
1563     test_length("has", 1);
1564     test_length("set", 2);
1565     ok(!("entries" in s), "entries are in Map");
1566     ok(!("keys" in s), "keys are in Map");
1567     ok(!("values" in s), "values are in Map");
1568     todo_wine.
1569     ok("size" in Map.prototype, "size is not in Map.prototype");
1571     r = Object.prototype.toString.call(s);
1572     ok(r === "[object Object]", "toString returned " + r);
1574     r = s.get("test");
1575     ok(r === undefined, "get(test) returned " + r);
1576     r = s.has("test");
1577     ok(r === false, "has(test) returned " + r);
1578     ok(s.size === 0, "size = " + s.size + " expected 0");
1580     r = s.set("test", 1);
1581     ok(r === undefined, "set returned " + r);
1582     ok(s.size === 1, "size = " + s.size + " expected 1");
1583     r = s.get("test");
1584     ok(r === 1, "get(test) returned " + r);
1585     r = s.has("test");
1586     ok(r === true, "has(test) returned " + r);
1588     s.size = 100;
1589     ok(s.size === 1, "size = " + s.size + " expected 1");
1591     s.set("test", 2);
1592     r = s.get("test");
1593     ok(r === 2, "get(test) returned " + r);
1594     r = s.has("test");
1595     ok(r === true, "has(test) returned " + r);
1597     r = s["delete"]("test"); /* using s.delete() would break parsing in quirks mode */
1598     ok(r === true, "delete(test) returned " + r);
1599     ok(s.size === 0, "size = " + s.size + " expected 0");
1600     r = s["delete"]("test");
1601     ok(r === false, "delete(test) returned " + r);
1603     var test_keys = [undefined, null, NaN, 3, "str", false, true, {}];
1604     for(i in test_keys) {
1605         r = s.set(test_keys[i], test_keys[i] + 1);
1606         ok(r === undefined, "set(test) returned " + r);
1607     }
1608     ok(s.size === test_keys.length, "size = " + s.size + " expected " + test_keys.length);
1609     for(i in test_keys) {
1610         r = s.get(test_keys[i]);
1611         if(isNaN(test_keys[i]))
1612             ok(isNaN(r), "get(" + test_keys[i] + ") returned " + r);
1613         else
1614             ok(r === test_keys[i] + 1, "get(" + test_keys[i] + ") returned " + r);
1615     }
1617     var calls = [];
1618     i = 0;
1619     r = s.forEach(function(value, key, map) {
1620         if(isNaN(test_keys[i])) {
1621             ok(isNaN(key), "key = " + key + " expected NaN");
1622             ok(isNaN(value), "value = " + value + " expected NaN");
1623         }else {
1624             ok(key === test_keys[i], "key = " + key + " expected " + test_keys[i]);
1625             ok(value === key + 1, "value = " + value);
1626         }
1627         ok(map === s, "map = " + map);
1628         ok(this === test_keys, "this = " + this);
1629         i++;
1630     }, test_keys);
1631     ok(i === test_keys.length, "i = " + i);
1632     ok(r === undefined, "forEach returned " + r);
1634     s.set(3, "test2")
1635     calls = [];
1636     i = 0;
1637     s.forEach(function(value, key) {
1638         if(isNaN(test_keys[i]))
1639             ok(isNaN(key), "key = " + key + " expected " + test_keys[i]);
1640         else
1641             ok(key === test_keys[i], "key = " + key + " expected " + test_keys[i]);
1642         i++;
1643     });
1644     ok(i === test_keys.length, "i = " + i);
1646     r = s.clear();
1647     ok(r === undefined, "clear returned " + r);
1648     ok(s.size === 0, "size = " + s.size + " expected 0");
1649     r = s.get(test_keys[0]);
1650     ok(r === undefined, "get returned " + r);
1652     s = new Map();
1653     s.set(1, 10);
1654     s.set(2, 20);
1655     s.set(3, 30);
1656     i = true;
1657     s.forEach(function() {
1658         ok(i, "unexpected call");
1659         s.clear();
1660         i = false;
1661     });
1663     s = new Map();
1664     s.set(1, 10);
1665     s.set(2, 20);
1666     s.set(3, 30);
1667     i = 0;
1668     s.forEach(function(value, key) {
1669         i += key + value;
1670         r = s["delete"](key);
1671         ok(r === true, "delete returned " + r);
1672     });
1673     ok(i === 66, "i = " + i);
1675     s = new Map();
1676     s.set(0,  10);
1677     s.set(-0, 20);
1678     ok(s.size === 2, "size = " + s.size + " expected 2");
1679     r = s.get(-0);
1680     ok(r === 20, "get(-0) returned " + r);
1681     r = s.get(0);
1682     ok(r === 10, "get(0) returned " + r);
1684     try {
1685         Map.prototype.set.call({}, 1, 2);
1686         ok(false, "expected exception");
1687     }catch(e) {
1688         ok(e.number === 0xa13fc - 0x80000000, "e.number = " + e.number);
1689     }
1691     s = new Map();
1692     s.set(1, 10);
1693     s.set(2, 20);
1694     s.set(3, 30);
1695     r = 0;
1696     s.forEach(function(value, key) {
1697         r++;
1698         s.clear();
1699         ok(s.size === 0, "size = " + s.size);
1700         ok(this.valueOf() === 42, "this.valueOf() = " + this.valueOf());
1701     }, 42);
1702     ok(r === 1, "r = " + r);
1705 async_test("weakmap_obj", function() {
1706     if(!("WeakMap" in window)) { next_test(); return; }
1708     try {
1709         var s = WeakMap();
1710         ok(false, "expected exception calling constructor as method");
1711     }catch(e) {
1712         ok(e.number === 0xa13fc - 0x80000000, "calling constructor as method threw " + e.number);
1713     }
1715     var s = new WeakMap, r, o, o2;
1716     ok(Object.getPrototypeOf(s) === WeakMap.prototype, "unexpected WeakMap prototype");
1718     function test_length(name, len) {
1719         ok(WeakMap.prototype[name].length === len, "WeakMap.prototype." + name + " = " + WeakMap.prototype[name].length);
1720     }
1721     test_length("clear", 0);
1722     test_length("delete", 1);
1723     test_length("get", 1);
1724     test_length("has", 1);
1725     test_length("set", 2);
1726     ok(!("entries" in s), "entries is in WeakMap");
1727     ok(!("forEach" in s), "forEach is in WeakMap");
1728     ok(!("keys" in s), "keys is in WeakMap");
1729     ok(!("size" in s), "size is in WeakMap");
1730     ok(!("values" in s), "values is in WeakMap");
1732     r = Object.prototype.toString.call(s);
1733     ok(r === "[object Object]", "toString returned " + r);
1735     r = s.get("test");
1736     ok(r === undefined, "get('test') returned " + r);
1737     r = s.has("test");
1738     ok(r === false, "has('test') returned " + r);
1740     try {
1741         r = s.set("test", 1);
1742         ok(false, "set('test') did not throw");
1743     }catch(e) {
1744         ok(e.number === 0xa13fd - 0x80000000, "set('test') threw " + e.number);
1745     }
1746     try {
1747         r = s.set(external.testHostContext(true), 1);
1748         ok(false, "set(host_obj) did not throw");
1749     }catch(e) {
1750         ok(e.number === 0xa13fd - 0x80000000, "set(host_obj) threw " + e.number);
1751     }
1753     r = s.set({}, 1);
1754     ok(r === undefined, "set({}, 1) returned " + r);
1756     o = {}, o2 = {};
1757     r = s.get({});
1758     ok(r === undefined, "get({}) returned " + r);
1759     r = s.has({});
1760     ok(r === false, "has({}) returned " + r);
1762     r = s.set(o, 2);
1763     ok(r === undefined, "set(o, 2) returned " + r);
1764     r = s.get(o);
1765     ok(r === 2, "get(o) returned " + r);
1766     r = s.has(o);
1767     ok(r === true, "has(o) returned " + r);
1768     r = s.get(o2);
1769     ok(r === undefined, "get(o2) before set returned " + r);
1770     r = s.has(o2);
1771     ok(r === false, "has(o2) before set returned " + r);
1772     r = s.set(o2, "test");
1773     ok(r === undefined, "set(o2, 'test') returned " + r);
1774     r = s.get(o2);
1775     ok(r === "test", "get(o2) returned " + r);
1776     r = s.has(o2);
1777     ok(r === true, "has(o2) returned " + r);
1779     r = s["delete"]("test"); /* using s.delete() would break parsing in quirks mode */
1780     ok(r === false, "delete('test') returned " + r);
1781     r = s["delete"]({});
1782     ok(r === false, "delete({}) returned " + r);
1783     r = s["delete"](o);
1784     ok(r === true, "delete(o) returned " + r);
1786     r = s.get(o);
1787     ok(r === undefined, "get(o) after delete returned " + r);
1788     r = s.has(o);
1789     ok(r === false, "has(o) after delete returned " + r);
1790     r = s.get(o2);
1791     ok(r === "test", "get(o2) after delete returned " + r);
1792     r = s.has(o2);
1793     ok(r === true, "has(o2) after delete returned " + r);
1795     r = s.set(o, undefined);
1796     ok(r === undefined, "set(o, undefined) returned " + r);
1797     r = s.get(o);
1798     ok(r === undefined, "get(o) after re-set returned " + r);
1799     r = s.has(o);
1800     ok(r === true, "has(o) after re-set returned " + r);
1802     r = s.clear();
1803     ok(r === undefined, "clear() returned " + r);
1804     r = s.get(o);
1805     ok(r === undefined, "get(o) after clear returned " + r);
1806     r = s.has(o);
1807     ok(r === false, "has(o) after clear returned " + r);
1808     r = s.get(o2);
1809     ok(r === undefined, "get(o2) after clear returned " + r);
1810     r = s.has(o2);
1811     ok(r === false, "has(o2) after clear returned " + r);
1813     r = external.newRefTest();
1814     ok(r.ref === 1, "wrong ref after newRefTest: " + r.ref);
1815     o = { val: r.get(), map: s };
1816     s.set(o, o);
1817     ok(r.ref > 1, "map entry released");
1819     o = Date.now();
1820     CollectGarbage();
1821     function retry() {
1822         if(r.ref > 1 && Date.now() - o < 5000) {
1823             CollectGarbage();
1824             window.setTimeout(retry);
1825             return;
1826         }
1827         ok(r.ref === 1, "map entry not released");
1828         next_test();
1829     }
1830     window.setTimeout(retry);
1833 sync_test("storage", function() {
1834     var v = document.documentMode, i, r, list;
1836     sessionStorage["add-at-end"] = 0;
1837     sessionStorage.removeItem("add-at-end");
1839     sessionStorage.setItem("foobar", "1234");
1840     ok("foobar" in sessionStorage, "foobar not in sessionStorage");
1841     r = sessionStorage.foobar;
1842     ok(r === "1234", "sessionStorage.foobar = " + r);
1843     sessionStorage.barfoo = 4321;
1844     r = sessionStorage.getItem("barfoo");
1845     ok(r === "4321", "sessionStorage.barfoo = " + r);
1846     sessionStorage.setItem("abcd", "blah");
1847     sessionStorage.dcba = "test";
1849     // Order isn't consistent, but changes are reflected during the enumeration.
1850     // Elements that were already traversed in DISPID (even if removed before
1851     // the enumeration) are not enumerated, even if re-added during the enum.
1852     i = 0; list = [ "foobar", "barfoo", "abcd", "dcba" ];
1853     for(r in sessionStorage) {
1854         for(var j = 0; j < list.length; j++)
1855             if(r === list[j])
1856                 break;
1857         ok(j < list.length, "got '" + r + "' enumerating");
1858         list.splice(j, 1);
1859         if(i === 1) {
1860             sessionStorage.removeItem(list[0]);
1861             sessionStorage.setItem("new", "new");
1862             list.splice(0, 1, "new");
1863         }
1864         if(!list.length)
1865             sessionStorage.setItem("add-at-end", "0");
1866         i++;
1867     }
1868     ok(i === 4, "enum did " + i + " iterations");
1870     try {
1871         delete sessionStorage.foobar;
1872         ok(v >= 8, "expected exception deleting sessionStorage.foobar");
1873         ok(!("foobar" in sessionStorage), "foobar in sessionStorage after deletion");
1874         r = sessionStorage.getItem("foobar");
1875         ok(r === null, "sessionStorage.foobar after deletion = " + r);
1876     }catch(e) {
1877         ok(v < 8, "did not expect exception deleting sessionStorage.foobar");
1878         ok(e.number === 0xa01bd - 0x80000000, "deleting sessionStorage.foobar threw = " + e.number);
1879     }
1881     sessionStorage.clear();
1884 async_test("storage events", function() {
1885     var iframe = document.createElement("iframe"), iframe2 = document.createElement("iframe");
1886     var local = false, storage, storage2, v = document.documentMode, i = 0;
1888     var tests = [
1889         function() {
1890             expect();
1891             storage.removeItem("foobar");
1892         },
1893         function() {
1894             expect(0, "foobar", "", "test");
1895             storage.setItem("foobar", "test");
1896         },
1897         function() {
1898             expect(1, "foobar", "test", "TEST", true);
1899             storage2.setItem("foobar", "TEST");
1900         },
1901         function() {
1902             expect(0, "foobar", "TEST", "");
1903             storage.removeItem("foobar");
1904         },
1905         function() {
1906             expect(1, "winetest", "", "WineTest");
1907             storage2.setItem("winetest", "WineTest");
1908         },
1909         function() {
1910             expect(0, "", "", "");
1911             storage.clear();
1912         }
1913     ];
1915     function next() {
1916         if(++i < tests.length)
1917             tests[i]();
1918         else if(local)
1919             next_test();
1920         else {
1921             // w10pro64 testbot VM throws WININET_E_INTERNAL_ERROR for some reason
1922             storage = null, storage2 = null;
1923             try {
1924                 storage = window.localStorage, storage2 = iframe.contentWindow.localStorage;
1925             }catch(e) {
1926                 ok(e.number === 0x72ee4 - 0x80000000, "localStorage threw " + e.number + ": " + e);
1927             }
1928             if(!storage || !storage2) {
1929                 win_skip("localStorage is buggy and not available, skipping");
1930                 next_test();
1931                 return;
1932             }
1933             i = 0, local = true;
1935             if(!storage.length)
1936                 setTimeout(function() { tests[0](); });
1937             else {
1938                 // Get rid of any entries first, since native doesn't update immediately
1939                 var w = [ window, iframe.contentWindow ];
1940                 for(var j = 0; j < w.length; j++)
1941                     w[j].onstorage = w[j].document.onstorage = w[j].document.onstoragecommit = null;
1942                 document.onstoragecommit = function() {
1943                     if(!storage.length)
1944                         setTimeout(function() { tests[0](); });
1945                     else
1946                         storage.clear();
1947                 };
1948                 storage.clear();
1949             }
1950         }
1951     }
1953     function test_event(e, idx, key, oldValue, newValue) {
1954         if(v < 9) {
1955             ok(e === undefined, "event not undefined in legacy mode: " + e);
1956             return;
1957         }
1958         var s = Object.prototype.toString.call(e);
1959         todo_wine_if(e.target != window && e.target != document).
1960         ok(s === "[object StorageEvent]", "Object.toString = " + s);
1961         ok(e.key === key, "key = " + e.key + ", expected " + key);
1962         ok(e.oldValue === oldValue, "oldValue = " + e.oldValue + ", expected " + oldValue);
1963         ok(e.newValue === newValue, "newValue = " + e.newValue + ", expected " + newValue);
1964         s = (idx ? iframe.contentWindow : window)["location"]["href"].split('#', 1)[0];
1965         ok(e.url === s, "url = " + e.url + ", expected " + s);
1966     }
1968     function expect(idx, key, oldValue, newValue, quirk) {
1969         var window2 = iframe.contentWindow, document2 = window2.document;
1970         window.onstorage = function() { ok(false, "window.onstorage called"); };
1971         document.onstorage = function() { ok(false, "doc.onstorage called"); };
1972         document.onstoragecommit = function() { ok(false, "doc.onstoragecommit called"); };
1973         window2.onstorage = function() { ok(false, "iframe window.onstorage called"); };
1974         document2.onstorage = function() { ok(false, "iframe doc.onstorage called"); };
1975         document2.onstoragecommit = function() { ok(false, "iframe doc.onstoragecommit called"); };
1977         if(idx === undefined) {
1978             setTimeout(function() { next(); });
1979         }else {
1980             // Native sometimes calls this for some reason
1981             if(local && quirk) document.onstoragecommit = null;
1983             (v < 9 ? document2 : window2)["onstorage"] = function(e) {
1984                 (local && idx ? document2 : (local || v < 9 ? document : window))[local ? "onstoragecommit" : "onstorage"] = function(e) {
1985                     test_event(e, idx, local ? "" : key, local ? "" : oldValue, local ? "" : newValue);
1986                     next();
1987                 }
1988                 test_event(e, idx, key, oldValue, newValue);
1989             }
1990         }
1991     }
1993     iframe.onload = function() {
1994         iframe2.onload = function() {
1995             var w = iframe2.contentWindow;
1996             w.onstorage = function() { ok(false, "about:blank window.onstorage called"); };
1997             w.document.onstorage = function() { ok(false, "about:blank document.onstorage called"); };
1998             w.document.onstoragecommit = function() { ok(false, "about:blank document.onstoragecommit called"); };
2000             storage = window.sessionStorage, storage2 = iframe.contentWindow.sessionStorage;
2001             tests[0]();
2002         };
2003         iframe2.src = "about:blank";
2004         document.body.appendChild(iframe2);
2005     };
2006     iframe.src = "blank.html";
2007     document.body.appendChild(iframe);
2010 sync_test("elem_attr", function() {
2011     var v = document.documentMode;
2012     var elem = document.createElement("div"), r;
2014     function test_exposed(prop, expect) {
2015         if(expect)
2016             ok(prop in elem, prop + " is not exposed from elem");
2017         else
2018             ok(!(prop in elem), prop + " is exposed from elem");
2019     }
2021     r = elem.getAttribute("class");
2022     ok(r === null, "class attr = " + r);
2023     r = elem.getAttribute("className");
2024     ok(r === (v < 8 ? "" : null), "className attr = " + r);
2026     elem.className = "cls";
2027     r = elem.getAttribute("class");
2028     ok(r === (v < 8 ? null : "cls"), "class attr = " + r);
2029     r = elem.getAttribute("className");
2030     ok(r === (v < 8 ? "cls" : null), "className attr = " + r);
2032     elem.setAttribute("class", "cls2");
2033     ok(elem.className === (v < 8 ? "cls" : "cls2"), "elem.className = " + elem.className);
2034     r = elem.getAttribute("class");
2035     ok(r === "cls2", "class attr = " + r);
2036     r = elem.getAttribute("className");
2037     ok(r === (v < 8 ? "cls" : null), "className attr = " + r);
2039     elem.setAttribute("className", "cls3");
2040     ok(elem.className === (v < 8 ? "cls3" : "cls2"), "elem.className = " + elem.className);
2041     r = elem.getAttribute("class");
2042     ok(r === "cls2", "class attr = " + r);
2043     r = elem.getAttribute("className");
2044     ok(r === "cls3", "className attr = " + r);
2046     elem.htmlFor = "for";
2047     r = elem.getAttribute("for");
2048     ok(r === null, "for attr = " + r);
2049     r = elem.getAttribute("htmlFor");
2050     ok(r === (v < 9 ? "for" : null), "htmlFor attr = " + r);
2052     elem.setAttribute("for", "for2");
2053     ok(elem.htmlFor === "for", "elem.htmlFor = " + elem.htmlFor);
2054     r = elem.getAttribute("for");
2055     ok(r === "for2", "for attr = " + r);
2056     r = elem.getAttribute("htmlFor");
2057     ok(r === (v < 9 ? "for" : null), "htmlFor attr = " + r);
2059     elem.setAttribute("htmlFor", "for3");
2060     ok(elem.htmlFor === (v < 9 ? "for3" : "for"), "elem.htmlFor = " + elem.htmlFor);
2061     r = elem.getAttribute("for");
2062     ok(r === "for2", "for attr = " + r);
2063     r = elem.getAttribute("htmlFor");
2064     ok(r === "for3", "htmlFor attr = " + r);
2066     elem.setAttribute("testattr", "test", 0, "extra arg", 0xdeadbeef);
2067     test_exposed("class", v < 8);
2068     test_exposed("className", true);
2069     test_exposed("for", v < 9);
2070     test_exposed("htmlFor", true);
2071     test_exposed("testattr", v < 9);
2073     var arr = [3];
2074     elem.setAttribute("testattr", arr);
2075     r = elem.getAttribute("testattr");
2076     ok(r === (v < 8 ? arr : "3"), "testattr = " + r);
2077     ok(elem.testattr === (v < 9 ? arr : undefined), "elem.testattr = " + elem.testattr);
2078     r = elem.removeAttribute("testattr");
2079     ok(r === (v < 9 ? true : undefined), "testattr removeAttribute returned " + r);
2080     ok(elem.testattr === undefined, "removed testattr = " + elem.testattr);
2082     arr[0] = 9;
2083     elem.setAttribute("testattr", "string");
2084     elem.testattr = arr;
2085     r = elem.getAttribute("testattr");
2086     ok(r === (v < 8 ? arr : (v < 9 ? "9" : "string")), "testattr = " + r);
2087     ok(elem.testattr === arr, "elem.testattr = " + elem.testattr);
2088     arr[0] = 3;
2089     r = elem.getAttribute("testattr");
2090     ok(r === (v < 8 ? arr : (v < 9 ? "3" : "string")), "testattr = " + r);
2091     ok(elem.testattr === arr, "elem.testattr = " + elem.testattr);
2092     r = elem.removeAttribute("testattr");
2093     ok(r === (v < 9 ? true : undefined), "testattr removeAttribute returned " + r);
2094     ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr = " + elem.testattr);
2096     arr.toString = function() { return 42; }
2097     elem.testattr = arr;
2098     r = elem.getAttribute("testattr");
2099     ok(r === (v < 8 ? arr : (v < 9 ? "42" : null)), "testattr with custom toString = " + r);
2100     elem.setAttribute("testattr", arr);
2101     r = elem.getAttribute("testattr");
2102     ok(r === (v < 8 ? arr : "42"), "testattr after setAttribute with custom toString = " + r);
2103     ok(elem.testattr === arr, "elem.testattr after setAttribute with custom toString = " + elem.testattr);
2104     r = elem.removeAttribute("testattr");
2105     ok(r === (v < 9 ? true : undefined), "testattr removeAttribute with custom toString returned " + r);
2106     ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr with custom toString = " + elem.testattr);
2108     arr.valueOf = function() { return "arrval"; }
2109     elem.testattr = arr;
2110     r = elem.getAttribute("testattr");
2111     ok(r === (v < 8 ? arr : (v < 9 ? "arrval" : null)), "testattr with custom valueOf = " + r);
2112     elem.setAttribute("testattr", arr);
2113     r = elem.getAttribute("testattr");
2114     ok(r === (v < 8 ? arr : (v < 10 ? "arrval" : "42")), "testattr after setAttribute with custom valueOf = " + r);
2115     ok(elem.testattr === arr, "elem.testattr after setAttribute with custom valueOf = " + elem.testattr);
2116     r = elem.removeAttribute("testattr");
2117     ok(r === (v < 9 ? true : undefined), "testattr removeAttribute with custom valueOf returned " + r);
2118     ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr with custom valueOf = " + elem.testattr);
2120     var func = elem.setAttribute;
2121     try {
2122         func("testattr", arr);
2123         todo_wine_if(v >= 9).
2124         ok(v < 9, "expected exception setting testattr via func");
2125     }catch(ex) {
2126         ok(v >= 9, "did not expect exception setting testattr via func");
2127         elem.setAttribute("testattr", arr);
2128     }
2129     r = elem.getAttribute("testattr");
2130     ok(r === (v < 8 ? arr : (v < 10 ? "arrval" : "42")), "testattr after setAttribute (as func) = " + r);
2131     delete arr.valueOf;
2132     delete arr.toString;
2134     elem.setAttribute("id", arr);
2135     r = elem.getAttribute("id");
2136     todo_wine_if(v >= 8 && v < 10).
2137     ok(r === (v < 8 || v >= 10 ? "3" : "[object]"), "id = " + r);
2138     r = elem.removeAttribute("id");
2139     ok(r === (v < 9 ? true : undefined), "id removeAttribute returned " + r);
2140     ok(elem.id === "", "removed id = " + elem.id);
2142     func = function() { };
2143     elem.onclick = func;
2144     ok(elem.onclick === func, "onclick = " + elem.onclick);
2145     r = elem.getAttribute("onclick");
2146     todo_wine_if(v === 8).
2147     ok(r === (v < 8 ? func : null), "onclick attr = " + r);
2148     r = elem.removeAttribute("onclick");
2149     ok(r === (v < 9 ? false : undefined), "removeAttribute returned " + r);
2150     todo_wine_if(v === 8).
2151     ok(elem.onclick === (v != 8 ? func : null), "removed onclick = " + elem.onclick);
2153     elem.onclick_test = func;
2154     ok(elem.onclick_test === func, "onclick_test = " + elem.onclick_test);
2155     r = elem.getAttribute("onclick_test");
2156     ok(r === (v < 8 ? func : (v < 9 ? func.toString() : null)), "onclick_test attr = " + r);
2158     elem.setAttribute("onclick", "test");
2159     r = elem.getAttribute("onclick");
2160     ok(r === "test", "onclick attr after setAttribute = " + r);
2161     r = elem.removeAttribute("onclick");
2162     ok(r === (v < 9 ? true : undefined), "removeAttribute after setAttribute returned " + r);
2164     /* IE11 returns an empty function, which we can't check directly */
2165     todo_wine_if(v >= 9).
2166     ok((v < 11) ? (elem.onclick === null) : (elem.onclick !== func), "removed onclick after setAttribute = " + elem.onclick);
2168     r = Object.prototype.toString.call(elem.onclick);
2169     todo_wine_if(v >= 9 && v < 11).
2170     ok(r === (v < 9 ? "[object Object]" : (v < 11 ? "[object Null]" : "[object Function]")),
2171         "removed onclick after setAttribute Object.toString returned " + r);
2173     elem.setAttribute("onclick", "string");
2174     r = elem.getAttribute("onclick");
2175     ok(r === "string", "onclick attr after setAttribute = " + r);
2176     elem.onclick = func;
2177     ok(elem.onclick === func, "onclick = " + elem.onclick);
2178     r = elem.getAttribute("onclick");
2179     todo_wine_if(v === 8).
2180     ok(r === (v < 8 ? func : (v < 9 ? null : "string")), "onclick attr = " + r);
2181     elem.onclick = "test";
2182     r = elem.getAttribute("onclick");
2183     ok(r === (v < 9 ? "test" : "string"), "onclick attr = " + r);
2184     r = elem.removeAttribute("onclick");
2185     ok(r === (v < 9 ? true : undefined), "removeAttribute returned " + r);
2186     todo_wine_if(v >= 9).
2187     ok(elem.onclick === null, "removed onclick = " + elem.onclick);
2189     elem.setAttribute("ondblclick", arr);
2190     r = elem.getAttribute("ondblclick");
2191     todo_wine_if(v >= 8 && v < 10).
2192     ok(r === (v < 8 ? arr : (v < 10 ? "[object]" : "3")), "ondblclick = " + r);
2193     r = elem.removeAttribute("ondblclick");
2194     ok(r === (v < 8 ? false : (v < 9 ? true : undefined)), "ondblclick removeAttribute returned " + r);
2195     r = Object.prototype.toString.call(elem.ondblclick);
2196     todo_wine_if(v >= 11).
2197     ok(r === (v < 8 ? "[object Array]" : (v < 9 ? "[object Object]" : (v < 11 ? "[object Null]" : "[object Function]"))),
2198         "removed ondblclick Object.toString returned " + r);
2200     elem.setAttribute("ondblclick", "string");
2201     r = elem.getAttribute("ondblclick");
2202     ok(r === "string", "ondblclick string = " + r);
2203     r = elem.removeAttribute("ondblclick");
2204     ok(r === (v < 9 ? true : undefined), "ondblclick string removeAttribute returned " + r);
2205     ok(elem.ondblclick === null, "removed ondblclick string = " + elem.ondblclick);
2207     if(v < 9) {
2208         /* style is a special case */
2209         try {
2210             elem.style = "opacity: 1.0";
2211             ok(false, "expected exception setting elem.style");
2212         }catch(ex) { }
2214         var style = elem.style;
2215         r = elem.getAttribute("style");
2216         ok(r === (v < 8 ? style : null), "style attr = " + r);
2217         r = elem.removeAttribute("style");
2218         ok(r === true, "removeAttribute('style') returned " + r);
2219         r = elem.style;
2220         ok(r === style, "removed elem.style = " + r);
2221         r = elem.getAttribute("style");
2222         ok(r === (v < 8 ? style : null), "style attr after removal = " + r);
2223         elem.setAttribute("style", "opacity: 1.0");
2224         r = elem.getAttribute("style");
2225         ok(r === (v < 8 ? style : "opacity: 1.0"), "style attr after setAttribute = " + r);
2226         r = elem.style;
2227         ok(r === style, "elem.style after setAttribute = " + r);
2228     }
2231 sync_test("elem_attrNS", function() {
2232     var v = document.documentMode;
2233     if(v < 9) return;  /* not available */
2235     var specialspace_ns = "http://www.mozilla.org/ns/specialspace";
2236     var svg_ns = "http://www.w3.org/2000/svg";
2238     var elem = document.createElement("div"), r;
2240     elem.setAttributeNS(specialspace_ns, "spec:align", "left");
2241     r = elem.hasAttribute("spec:align");
2242     ok(r === true, "spec:align does not exist");
2243     r = elem.getAttribute("spec:align");
2244     ok(r === "left", "spec:align = " + r);
2245     r = elem.hasAttribute("align");
2246     ok(r === false, "align exists");
2247     r = elem.getAttribute("align");
2248     ok(r === null, "align = " + r);
2249     r = elem.hasAttributeNS(null, "spec:align");
2250     ok(r === false, "null spec:align exists");
2251     r = elem.getAttributeNS(null, "spec:align");
2252     ok(r === "", "null spec:align = " + r);
2253     r = elem.hasAttributeNS(null, "spec:align");
2254     ok(r === false, "null align exists");
2255     r = elem.getAttributeNS(null, "align");
2256     ok(r === "", "null align = " + r);
2257     r = elem.hasAttributeNS(svg_ns, "spec:align");
2258     ok(r === false, "svg spec:align exists");
2259     r = elem.getAttributeNS(svg_ns, "spec:align");
2260     ok(r === "", "svg spec:align = " + r);
2261     r = elem.hasAttributeNS(svg_ns, "align");
2262     ok(r === false, "svg align exists");
2263     r = elem.getAttributeNS(svg_ns, "align");
2264     ok(r === "", "svg align = " + r);
2265     r = elem.hasAttributeNS(specialspace_ns, "spec:align");
2266     ok(r === false, "specialspace spec:align exists");
2267     r = elem.getAttributeNS(specialspace_ns, "spec:align");
2268     ok(r === "", "specialspace spec:align = " + r);
2269     r = elem.hasAttributeNS(specialspace_ns, "align");
2270     ok(r === true, "specialspace align does not exist");
2271     r = elem.getAttributeNS(specialspace_ns, "align");
2272     ok(r === "left", "specialspace align = " + r);
2274     try {
2275         elem.setAttributeNS(null, "spec:align", "right");
2276         ok(false, "expected exception setting qualified attr with null ns");
2277     }catch(ex) {
2278         todo_wine.
2279         ok(ex.message === "NamespaceError", "setAttributeNS(null, 'spec:align', 'right') threw " + ex.message);
2280     }
2281     try {
2282         elem.setAttributeNS("", "spec:align", "right");
2283         ok(false, "expected exception setting qualified attr with empty ns");
2284     }catch(ex) {
2285         todo_wine.
2286         ok(ex.message === "NamespaceError", "setAttributeNS('', 'spec:align', 'right') threw " + ex.message);
2287     }
2288     elem.setAttributeNS(null, "align", "right");
2289     r = elem.getAttribute("spec:align");
2290     ok(r === "left", "spec:align (null) = " + r);
2291     r = elem.hasAttribute("align");
2292     ok(r === true, "align (null) does not exist");
2293     r = elem.getAttribute("align");
2294     ok(r === "right", "align (null) = " + r);
2295     r = elem.hasAttributeNS(null, "spec:align");
2296     ok(r === false, "null spec:align exists");
2297     r = elem.getAttributeNS(null, "spec:align");
2298     ok(r === "", "null spec:align (null) = " + r);
2299     r = elem.hasAttributeNS(null, "align");
2300     ok(r === true, "null align does not exist");
2301     r = elem.getAttributeNS(null, "align");
2302     ok(r === "right", "null align (null) = " + r);
2303     r = elem.hasAttributeNS(svg_ns, "spec:align");
2304     ok(r === false, "svg spec:align (null) exists");
2305     r = elem.getAttributeNS(svg_ns, "spec:align");
2306     ok(r === "", "svg spec:align (null) = " + r);
2307     r = elem.hasAttributeNS(svg_ns, "align");
2308     ok(r === false, "svg align (null) exists");
2309     r = elem.getAttributeNS(svg_ns, "align");
2310     ok(r === "", "svg align (null) = " + r);
2311     r = elem.hasAttributeNS(specialspace_ns, "spec:align");
2312     ok(r === false, "specialspace_ns spec:align (null) exists");
2313     r = elem.getAttributeNS(specialspace_ns, "spec:align");
2314     ok(r === "", "specialspace spec:align (null) = " + r);
2315     r = elem.hasAttributeNS(specialspace_ns, "align");
2316     ok(r === true, "specialspace align (null) does not exist");
2317     r = elem.getAttributeNS(specialspace_ns, "align");
2318     ok(r === "left", "specialspace align (null) = " + r);
2320     elem.setAttribute("align", "center");
2321     r = elem.hasAttributeNS(null, "spec:align");
2322     ok(r === false, "null spec:align (non-NS) exists");
2323     r = elem.getAttributeNS(null, "spec:align");
2324     ok(r === "", "null spec:align (non-NS) = " + r);
2325     r = elem.hasAttributeNS(null, "align");
2326     ok(r === true, "null align (non-NS) does not exist");
2327     r = elem.getAttributeNS(null, "align");
2328     ok(r === "center", "null align (non-NS) = " + r);
2329     r = elem.hasAttributeNS(svg_ns, "spec:align");
2330     ok(r === false, "svg spec:align (non-NS) exists");
2331     r = elem.getAttributeNS(svg_ns, "spec:align");
2332     ok(r === "", "svg spec:align (non-NS) = " + r);
2333     r = elem.hasAttributeNS(svg_ns, "align");
2334     ok(r === false, "svg align (non-NS) exists");
2335     r = elem.getAttributeNS(svg_ns, "align");
2336     ok(r === "", "svg align (non-NS) = " + r);
2337     r = elem.hasAttributeNS(specialspace_ns, "spec:align");
2338     ok(r === false, "specialspace spec:align (non-NS) exists");
2339     r = elem.getAttributeNS(specialspace_ns, "spec:align");
2340     ok(r === "", "specialspace spec:align (non-NS) = " + r);
2341     r = elem.hasAttributeNS(specialspace_ns, "align");
2342     ok(r === true, "specialspace align (non-NS) does not exist");
2343     r = elem.getAttributeNS(specialspace_ns, "align");
2344     ok(r === "left", "specialspace align (non-NS) = " + r);
2345     elem.removeAttributeNS(null, "spec:align");
2347     elem.setAttribute("emptynsattr", "none");
2348     elem.setAttributeNS("", "emptynsattr", "test");
2349     r = elem.hasAttribute("emptynsattr");
2350     ok(r === true, "emptynsattr without NS does not exist");
2351     r = elem.getAttribute("emptynsattr");
2352     ok(r === "test", "emptynsattr without NS = " + r);
2353     elem.setAttributeNS(null, "emptynsattr", "wine");
2354     r = elem.hasAttribute("emptynsattr");
2355     ok(r === true, "emptynsattr without NS does not exist");
2356     r = elem.getAttribute("emptynsattr");
2357     ok(r === "wine", "emptynsattr without NS = " + r);
2358     elem.setAttributeNS(specialspace_ns, "emptynsattr", "ns");
2359     r = elem.hasAttribute("emptynsattr");
2360     ok(r === true, "emptynsattr without NS does not exist");
2361     r = elem.getAttribute("emptynsattr");
2362     ok(r === "wine", "emptynsattr without NS = " + r);
2363     r = elem.hasAttributeNS("", "emptynsattr");
2364     ok(r === true, "emptynsattr empty ns does not exist");
2365     r = elem.getAttributeNS("", "emptynsattr");
2366     ok(r === "wine", "emptynsattr empty ns = " + r);
2367     r = elem.hasAttributeNS(null, "emptynsattr");
2368     ok(r === true, "emptynsattr null ns does not exist");
2369     r = elem.getAttributeNS(null, "emptynsattr");
2370     ok(r === "wine", "emptynsattr null ns = " + r);
2371     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
2372     ok(r === true, "emptynsattr specialspace ns does not exist");
2373     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
2374     ok(r === "ns", "emptynsattr specialspace ns = " + r);
2376     elem.removeAttributeNS("", "emptynsattr");
2377     r = elem.hasAttribute("emptynsattr");
2378     ok(r === true, "emptynsattr without NS after remove does not exist");
2379     r = elem.getAttribute("emptynsattr");
2380     ok(r === "ns", "emptynsattr without NS after remove = " + r);
2381     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
2382     ok(r === true, "emptynsattr specialspace ns after empty remove does not exist");
2383     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
2384     ok(r === "ns", "emptynsattr specialspace ns after empty remove = " + r);
2385     elem.setAttribute("emptynsattr", "test");
2386     r = elem.getAttribute("emptynsattr");
2387     ok(r === "test", "emptynsattr without NS after re-set = " + r);
2388     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
2389     ok(r === "test", "emptynsattr specialspace ns after empty re-set = " + r);
2391     elem.removeAttribute("emptynsattr");
2392     r = elem.hasAttribute("emptynsattr");
2393     ok(r === false, "emptynsattr without NS after non-NS remove exists");
2394     r = elem.getAttribute("emptynsattr");
2395     ok(r === null, "emptynsattr without NS after non-NS remove = " + r);
2396     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
2397     ok(r === false, "emptynsattr specialspace ns after non-NS remove exists");
2398     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
2399     ok(r === "", "emptynsattr specialspace ns after non-NS remove = " + r);
2401     elem.setAttributeNS(specialspace_ns, "emptynsattr", "ns");
2402     elem.removeAttributeNS(svg_ns, "emptynsattr");
2403     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
2404     ok(r === true, "emptynsattr specialspace ns after wrong NS remove does not exist");
2405     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
2406     ok(r === "ns", "emptynsattr specialspace ns after wrong NS remove = " + r);
2407     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
2408     ok(r === true, "emptynsattr specialspace ns after remove does not exist");
2409     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
2410     ok(r === "ns", "emptynsattr specialspace ns after remove = " + r);
2412     var ns = {};
2413     ns.toString = function() { return "toString namespace"; }
2414     ns.valueOf = function() { return "valueOf namespace"; }
2415     elem.setAttributeNS(ns, "foobar", "test");
2416     r = elem.hasAttribute("foobar");
2417     ok(r === true, "foobar without NS does not exist");
2418     r = elem.getAttribute("foobar");
2419     ok(r === "test", "foobar without NS = " + r);
2420     r = elem.hasAttributeNS(ns, "foobar");
2421     ok(r === true, "foobar does not exist");
2422     r = elem.getAttributeNS(ns, "foobar");
2423     ok(r === "test", "foobar = " + r);
2424     r = elem.hasAttributeNS("toString namespace", "foobar");
2425     ok(r === (v < 10 ? false : true), "foobar (toString namespace) " + (v < 10 ? "exists" : "does not exist"));
2426     r = elem.getAttributeNS("toString namespace", "foobar");
2427     ok(r === (v < 10 ? "" : "test"), "foobar (toString namespace) = " + r);
2428     r = elem.hasAttributeNS("valueOf namespace", "foobar");
2429     ok(r === (v < 10 ? true : false), "foobar (valueOf namespace) = " + (v < 10 ? "does not exist" : "exists"));
2430     r = elem.getAttributeNS("valueOf namespace", "foobar");
2431     ok(r === (v < 10 ? "test" : ""), "foobar (valueOf namespace) = " + r);
2433     var arr = [3];
2434     elem.setAttributeNS(svg_ns, "testattr", arr);
2435     r = elem.getAttributeNS(svg_ns, "testattr");
2436     ok(r === "3", "testattr = " + r);
2437     ok(elem.testattr === undefined, "elem.testattr = " + elem.testattr);
2438     elem.removeAttributeNS(svg_ns, "testattr");
2439     r = elem.getAttributeNS(svg_ns, "testattr");
2440     ok(r === "", "testattr after remove = " + r);
2442     arr.toString = function() { return 42; }
2443     elem.setAttributeNS(svg_ns, "testattr", arr);
2444     r = elem.getAttributeNS(svg_ns, "testattr");
2445     ok(r === "42", "testattr with custom toString = " + r);
2446     elem.removeAttributeNS(svg_ns, "testattr");
2447     r = elem.getAttributeNS(svg_ns, "testattr");
2448     ok(r === "", "testattr with custom toString after remove = " + r);
2450     arr.valueOf = function() { return "arrval"; }
2451     elem.setAttributeNS(svg_ns, "testattr", arr);
2452     r = elem.getAttributeNS(svg_ns, "testattr");
2453     ok(r === "42", "testattr with custom valueOf = " + r);
2454     elem.removeAttributeNS(svg_ns, "testattr");
2456     elem.setAttributeNS(svg_ns, "boolattr", true);
2457     r = elem.getAttributeNS(svg_ns, "boolattr");
2458     ok(r === "true", "boolattr = " + r);
2460     elem.setAttributeNS(svg_ns, "numattr", 13);
2461     r = elem.getAttributeNS(svg_ns, "numattr");
2462     ok(r === "13", "numattr = " + r);
2465 sync_test("builtins_diffs", function() {
2466     var v = document.documentMode;
2468     /* despite what spec says for ES6, IE still throws */
2469     var props = [
2470         "freeze",
2471         "getPrototypeOf",
2472         "isExtensible",
2473         "isFrozen",
2474         "isSealed",
2475         "keys",
2476         "preventExtensions",
2477         "seal"
2478     ];
2479     for(var i = 0; i < props.length; i++) {
2480         try {
2481             Object[props[i]]("test");
2482             ok(false, "Object." + props[i] + " with non-object: expected exception");
2483         }catch(e) {
2484             ok(e.number === (v < 9 ? 0xa01b6 : 0xa138f) - 0x80000000, "Object." + props[i] + " with non-object: exception = " + e.number);
2485         }
2486     }
2488     try {
2489         RegExp.prototype.toString.call({source: "foo", flags: "g"});
2490         ok(false, "RegExp.toString with non-regexp: expected exception");
2491     }catch(e) {
2492         ok(e.number === 0xa1398 - 0x80000000, "RegExp.toString with non-regexp: exception = " + e.number);
2493     }
2494     try {
2495         RegExp.prototype.toString.call({source: "abc", global: true, ignoreCase: true, multiline: true});
2496         ok(false, "RegExp.toString with non-regexp 2: expected exception");
2497     }catch(e) {
2498         ok(e.number === 0xa1398 - 0x80000000, "RegExp.toString with non-regexp 2: exception = " + e.number);
2499     }
2501     try {
2502         /a/.lastIndex();
2503         ok(false, "/a/.lastIndex(): expected exception");
2504     }catch(e) {
2505         ok(e.number === 0xa138a - 0x80000000, "/a/.lastIndex(): exception = " + e.number);
2506     }
2507     try {
2508         "a".length();
2509         ok(false, "\"a\".length(): expected exception");
2510     }catch(e) {
2511         ok(e.number === 0xa138a - 0x80000000, "\"a\".length(): exception = " + e.number);
2512     }
2515 sync_test("nullDisp", function() {
2516     var v = document.documentMode, nullDisp = external.nullDisp, r;
2518     ok(external.getVT(nullDisp) === "VT_NULL", "getVT(nullDisp) is not VT_NULL");
2519     ok(typeof(nullDisp) === "object", "typeof(nullDisp) = " + typeof(nullDisp));
2520     ok(nullDisp === nullDisp, "nullDisp !== nullDisp");
2521     ok(nullDisp === null, "nullDisp === null");
2522     ok(nullDisp == null, "nullDisp == null");
2523     ok(!nullDisp === true, "!nullDisp = " + !nullDisp);
2524     ok(String(nullDisp) === "null", "String(nullDisp) = " + String(nullDisp));
2525     ok(+nullDisp === 0, "+nullDisp !== 0");
2526     ok(''+nullDisp === "null", "''+nullDisp !== null");
2527     ok(nullDisp != new Object(), "nullDisp == new Object()");
2528     ok(new Object() != nullDisp, "new Object() == nullDisp");
2529     ok((typeof Object(nullDisp)) === "object", "typeof Object(nullDisp) !== 'object'");
2530     r = Object(nullDisp).toString();
2531     ok(r === "[object Object]", "Object(nullDisp).toString() = " + r);
2532     ok(Object(nullDisp) != nullDisp, "Object(nullDisp) == nullDisp");
2533     ok(new Object(nullDisp) != nullDisp, "new Object(nullDisp) == nullDisp");
2534     r = (nullDisp instanceof Object);
2535     ok(r === false, "nullDisp instance of Object");
2537     if(v >= 8) {
2538         r = JSON.stringify.call(null, nullDisp);
2539         ok(r === "null", "JSON.stringify(nullDisp) returned " + r);
2540     }
2542     try {
2543         (new Object()) instanceof nullDisp;
2544         ok(false, "expected exception on (new Object()) instanceof nullDisp");
2545     }catch(e) {
2546         ok(e.number === 0xa138a - 0x80000000, "(new Object()) instanceof nullDisp threw " + e.number);
2547     }
2549     try {
2550         Function.prototype.apply.call(nullDisp, Object, []);
2551         ok(false, "expected exception calling Function.apply on nullDisp");
2552     }catch(e) {
2553         ok(e.number === 0xa138a - 0x80000000, "Function.apply on nullDisp threw " + e.number);
2554     }
2555     try {
2556         Function.prototype.call.call(nullDisp, Object);
2557         ok(false, "expected exception calling Function.call on nullDisp");
2558     }catch(e) {
2559         ok(e.number === 0xa138a - 0x80000000, "Function.call on nullDisp threw " + e.number);
2560     }
2562     try {
2563         new nullDisp;
2564         ok(false, "expected exception for new nullDisp");
2565     }catch(e) {
2566         ok(e.number === 0xa138f - 0x80000000, "new nullDisp threw " + e.number);
2567     }
2570 sync_test("invalid selectors", function() {
2571     var v = document.documentMode, body = document.body, i;
2572     if(v < 8)
2573         return;
2575     var selectors = [
2576         "[s!='']",
2577         "*,:x",
2578         "*,##",
2579         ":x",
2580         "##",
2581         "*,",
2582         ","
2583     ];
2585     for(i = 0; i < selectors.length; i++) {
2586         try {
2587             body.querySelector(selectors[i]);
2588             ok(false, "body.querySelector(\"" + selectors[i] + "\" did not throw exception");
2589         }catch(e) {
2590             if(v < 9)
2591                 ok(e.number === 0x70057 - 0x80000000, "body.querySelector(\"" + selectors[i] + "\" threw " + e.number);
2592             else {
2593                 todo_wine.
2594                 ok(e.name === (v < 10 ? undefined : "SyntaxError"), "body.querySelector(\"" + selectors[i] + "\" threw " + e.name);
2595             }
2596         }
2597         try {
2598             body.querySelectorAll(selectors[i]);
2599             ok(false, "body.querySelectorAll(\"" + selectors[i] + "\" did not throw exception");
2600         }catch(e) {
2601             if(v < 9)
2602                 ok(e.number === 0x70057 - 0x80000000, "body.querySelectorAll(\"" + selectors[i] + "\" threw " + e.number);
2603             else {
2604                 todo_wine.
2605                 ok(e.name === (v < 10 ? undefined : "SyntaxError"), "body.querySelectorAll(\"" + selectors[i] + "\" threw " + e.name);
2606             }
2607         }
2608     }
2610     if(!body.msMatchesSelector)
2611         return;
2613     for(i = 0; i < selectors.length; i++) {
2614         try {
2615             body.msMatchesSelector(selectors[i]);
2616             ok(false, "body.msMatchesSelector(\"" + selectors[i] + "\" did not throw exception");
2617         }catch(e) {
2618             if(v < 9)
2619                 ok(e.number === 0x70057 - 0x80000000, "body.msMatchesSelector(\"" + selectors[i] + "\" threw " + e.number);
2620             else {
2621                 todo_wine.
2622                 ok(e.name === (v < 10 ? undefined : "SyntaxError"), "body.msMatchesSelector(\"" + selectors[i] + "\" threw " + e.name);
2623             }
2624         }
2625     }
2628 sync_test("__proto__", function() {
2629     var v = document.documentMode;
2630     var r, x = 42;
2632     if(v < 11) {
2633         ok(x.__proto__ === undefined, "x.__proto__ = " + x.__proto__);
2634         ok(!("__proto__" in Object), "Object.__proto__ = " + Object.__proto__);
2635         return;
2636     }
2638     ok(x.__proto__ === Number.prototype, "x.__proto__ = " + x.__proto__);
2639     ok(Object.__proto__ === Function.prototype, "Object.__proto__ = " + Object.__proto__);
2640     ok(Object.prototype.__proto__ === null, "Object.prototype.__proto__ = " + Object.prototype.__proto__);
2641     ok(Object.prototype.hasOwnProperty("__proto__"), "__proto__ is not a property of Object.prototype");
2642     ok(!Object.prototype.hasOwnProperty.call(x, "__proto__"), "__proto__ is a property of x");
2644     x.__proto__ = Object.prototype;
2645     ok(x.__proto__ === Number.prototype, "x.__proto__ set to Object.prototype = " + x.__proto__);
2646     ok(!Object.prototype.hasOwnProperty.call(x, "__proto__"), "__proto__ is a property of x after set to Object.prototype");
2647     x = {};
2648     x.__proto__ = null;
2649     r = Object.getPrototypeOf(x);
2650     ok(x.__proto__ === undefined, "x.__proto__ after set to null = " + x.__proto__);
2651     ok(r === null, "getPrototypeOf(x) after set to null = " + r);
2653     function check(expect, msg) {
2654         var r = Object.getPrototypeOf(x);
2655         ok(x.__proto__ === expect, "x.__proto__ " + msg + " = " + x.__proto__);
2656         ok(r === expect, "getPrototypeOf(x) " + msg + " = " + r);
2657         ok(!Object.prototype.hasOwnProperty.call(x, "__proto__"), "__proto__ is a property of x " + msg);
2658     }
2660     x = {};
2661     check(Object.prototype, "after x set to {}");
2662     x.__proto__ = Number.prototype;
2663     check(Number.prototype, "after set to Number.prototype");
2664     x.__proto__ = Object.prototype;
2665     check(Object.prototype, "after re-set to Object.prototype");
2667     function ctor() { }
2668     var obj = new ctor();
2669     x.__proto__ = obj;
2670     check(obj, "after set to obj");
2671     x.__proto__ = ctor.prototype;
2672     check(obj.__proto__, "after set to ctor.prototype");
2673     ok(obj.__proto__ === ctor.prototype, "obj.__proto__ !== ctor.prototype");
2675     r = (delete x.__proto__);
2676     ok(r, "delete x.__proto__ returned " + r);
2677     ok(Object.prototype.hasOwnProperty("__proto__"), "__proto__ is not a property of Object.prototype after delete");
2678     r = Object.getPrototypeOf(x);
2679     ok(r === ctor.prototype, "x.__proto__ after delete = " + r);
2681     var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__");
2682     ok(desc.value === undefined, "__proto__ value = " + desc.value);
2683     ok(Object.getPrototypeOf(desc.get) === Function.prototype, "__proto__ getter not a function");
2684     ok(Object.getPrototypeOf(desc.set) === Function.prototype, "__proto__ setter not a function");
2685     ok(desc.get.length === 0, "__proto__ getter length = " + desc.get.length);
2686     ok(desc.set.length === 1, "__proto__ setter length = " + desc.set.length);
2688     r = desc.get.call(x, 1, 2, 3, 4);
2689     ok(r === x.__proto__, "calling __proto__ getter on x returned " + r);
2691     r = desc.set.call(x, obj);
2692     ok(r === obj, "calling __proto__ setter(obj) on x returned " + r);
2693     check(obj, "after set to obj via calling setter");
2694     r = desc.set.call(x, 42);
2695     ok(r === 42, "calling __proto__ setter(42) on x returned " + r);
2696     check(obj, "after set to obj via calling setter(42)");
2697     r = desc.set.call(x, "foo");
2698     ok(r === "foo", "calling __proto__ setter('foo') on x returned " + r);
2699     check(obj, "after set to obj via calling setter('foo')");
2700     r = desc.set.call(x);
2701     ok(r === undefined, "calling __proto__ setter() on x returned " + r);
2702     r = desc.set.call(true, obj);
2703     ok(r === obj, "calling __proto__ setter(obj) on true value returned " + r);
2704     x = true;
2705     r = desc.set.call(x, obj);
2706     ok(r === obj, "calling __proto__ setter(obj) on x set to true returned " + r);
2707     ok(x.__proto__ === Boolean.prototype, "true value __proto__ after set to obj = " + x.__proto__);
2708     x = new Boolean(true);
2709     r = desc.set.call(x, obj);
2710     ok(r === obj, "calling __proto__ setter(obj) on x set to Boolean(true) returned " + r);
2711     ok(x.__proto__ === obj, "Boolean(true) __proto__ after set to obj = " + x.__proto__);
2713     r = desc.get.call(13);
2714     ok(r === Number.prototype, "calling __proto__ getter on 13 returned " + r);
2715     try {
2716         r = desc.get.call(undefined);
2717         ok(false, "expected exception calling __proto__ getter on undefined");
2718     }catch(e) {
2719         ok(e.number === 0xa138f - 0x80000000, "calling __proto__ getter on undefined threw exception " + e.number);
2720     }
2721     try {
2722         r = desc.get.call(null);
2723         ok(false, "expected exception calling __proto__ getter on null");
2724     }catch(e) {
2725         ok(e.number === 0xa138f - 0x80000000, "calling __proto__ getter on null threw exception " + e.number);
2726     }
2728     try {
2729         r = desc.set.call(undefined, obj);
2730         ok(false, "expected exception calling __proto__ setter on undefined");
2731     }catch(e) {
2732         ok(e.number === 0xa138f - 0x80000000, "calling __proto__ setter on undefined threw exception " + e.number);
2733     }
2734     try {
2735         r = desc.set.call(null, obj);
2736         ok(false, "expected exception calling __proto__ setter on null");
2737     }catch(e) {
2738         ok(e.number === 0xa138f - 0x80000000, "calling __proto__ setter on null threw exception " + e.number);
2739     }
2741     x = {};
2742     r = Object.create(x);
2743     ok(r.__proto__ === x, "r.__proto__ = " + r.__proto__);
2744     r = Object.create(r);
2745     ok(r.__proto__.__proto__ === x, "r.__proto__.__proto__ = " + r.__proto__.__proto__);
2746     try {
2747         x.__proto__ = r;
2748         ok(false, "expected exception setting circular proto chain");
2749     }catch(e) {
2750         ok(e.number === 0xa13b0 - 0x80000000 && e.name === "TypeError",
2751             "setting circular proto chain threw exception " + e.number + " (" + e.name + ")");
2752     }
2754     Object.preventExtensions(x);
2755     x.__proto__ = Object.prototype;  /* same prototype */
2756     try {
2757         x.__proto__ = Number.prototype;
2758         ok(false, "expected exception changing __proto__ on non-extensible object");
2759     }catch(e) {
2760         ok(e.number === 0xa13b6 - 0x80000000 && e.name === "TypeError",
2761             "changing __proto__ on non-extensible object threw exception " + e.number + " (" + e.name + ")");
2762     }
2765 sync_test("__defineGetter__", function() {
2766     var v = document.documentMode;
2767     var r, x = 42;
2769     if(v < 11) {
2770         ok(x.__defineGetter__ === undefined, "x.__defineGetter__ = " + x.__defineGetter__);
2771         ok(!("__defineGetter__" in Object), "Object.__defineGetter__ = " + Object.__defineGetter__);
2772         return;
2773     }
2774     ok(Object.prototype.hasOwnProperty("__defineGetter__"), "__defineGetter__ is not a property of Object.prototype");
2775     ok(Object.prototype.__defineGetter__.length === 2, "__defineGetter__.length = " + Object.prototype.__defineGetter__.length);
2777     function getter() { return "wine"; }
2778     function setter(val) { }
2780     r = x.__defineGetter__("foo", getter);
2781     ok(r === undefined, "__defineGetter__ on 42 returned " + r);
2782     ok(x.foo === undefined, "42.foo = " + x.foo);
2784     x = {};
2785     r = x.__defineGetter__("foo", getter);
2786     ok(r === undefined, "__defineGetter__ returned " + r);
2787     ok(x.foo === "wine", "x.foo = " + x.foo);
2788     r = Object.getOwnPropertyDescriptor(x, "foo");
2789     ok(r.value === undefined, "x.foo value = " + r.value);
2790     ok(r.get === getter, "x.foo get = " + r.get);
2791     ok(r.set === undefined, "x.foo set = " + r.set);
2792     ok(r.writable === undefined, "x.foo writable = " + r.writable);
2793     ok(r.enumerable === true, "x.foo enumerable = " + r.enumerable);
2794     ok(r.configurable === true, "x.foo configurable = " + r.configurable);
2796     Object.defineProperty(x, "foo", { get: undefined, set: setter, configurable: false });
2797     r = Object.getOwnPropertyDescriptor(x, "foo");
2798     ok(r.value === undefined, "x.foo setter value = " + r.value);
2799     ok(r.get === undefined, "x.foo setter get = " + r.get);
2800     ok(r.set === setter, "x.foo setter set = " + r.set);
2801     ok(r.writable === undefined, "x.foo setter writable = " + r.writable);
2802     ok(r.enumerable === true, "x.foo setter enumerable = " + r.enumerable);
2803     ok(r.configurable === false, "x.foo setter configurable = " + r.configurable);
2804     try {
2805         x.__defineGetter__("foo", getter);
2806         ok(false, "expected exception calling __defineGetter__ on non-configurable property");
2807     }catch(e) {
2808         ok(e.number === 0xa13d6 - 0x80000000, "__defineGetter__ on non-configurable property threw exception " + e.number);
2809     }
2811     r = Object.prototype.__defineGetter__.call(undefined, "bar", getter);
2812     ok(r === undefined, "__defineGetter__ on undefined returned " + r);
2813     r = Object.prototype.__defineGetter__.call(null, "bar", getter);
2814     ok(r === undefined, "__defineGetter__ on null returned " + r);
2815     r = x.__defineGetter__(undefined, getter);
2816     ok(r === undefined, "__defineGetter__ undefined prop returned " + r);
2817     ok(x["undefined"] === "wine", "x.undefined = " + x["undefined"]);
2818     r = x.__defineGetter__(false, getter);
2819     ok(r === undefined, "__defineGetter__ undefined prop returned " + r);
2820     ok(x["false"] === "wine", "x.false = " + x["false"]);
2822     try {
2823         x.__defineGetter__("bar", "string");
2824         ok(false, "expected exception calling __defineGetter__ with string");
2825     }catch(e) {
2826         ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with string threw exception " + e.number);
2827     }
2828     try {
2829         x.__defineGetter__("bar", undefined);
2830         ok(false, "expected exception calling __defineGetter__ with undefined");
2831     }catch(e) {
2832         ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with undefined threw exception " + e.number);
2833     }
2834     try {
2835         x.__defineGetter__("bar", null);
2836         ok(false, "expected exception calling __defineGetter__ with null");
2837     }catch(e) {
2838         ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with null threw exception " + e.number);
2839     }
2840     try {
2841         Object.prototype.__defineGetter__.call(x, "bar");
2842         ok(false, "expected exception calling __defineGetter__ with only one arg");
2843     }catch(e) {
2844         ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with only one arg threw exception " + e.number);
2845     }
2847     x.bar = "test";
2848     ok(x.bar === "test", "x.bar = " + x.bar);
2849     x.__defineGetter__("bar", getter);
2850     ok(x.bar === "wine", "x.bar with getter = " + x.bar);
2853 sync_test("__defineSetter__", function() {
2854     var v = document.documentMode;
2855     var r, x = 42;
2857     if(v < 11) {
2858         ok(x.__defineSetter__ === undefined, "x.__defineSetter__ = " + x.__defineSetter__);
2859         ok(!("__defineSetter__" in Object), "Object.__defineSetter__ = " + Object.__defineSetter__);
2860         return;
2861     }
2862     ok(Object.prototype.hasOwnProperty("__defineSetter__"), "__defineSetter__ is not a property of Object.prototype");
2863     ok(Object.prototype.__defineSetter__.length === 2, "__defineSetter__.length = " + Object.prototype.__defineSetter__.length);
2865     function getter() { return "wine"; }
2866     function setter(val) { this.setterVal = val - 1; }
2868     r = x.__defineSetter__("foo", setter);
2869     ok(r === undefined, "__defineSetter__ on 42 returned " + r);
2870     ok(x.foo === undefined, "42.foo = " + x.foo);
2872     x = {};
2873     r = x.__defineSetter__("foo", setter);
2874     ok(r === undefined, "__defineSetter__ returned " + r);
2875     ok(x.setterVal === undefined, "x.setterVal = " + x.setterVal);
2876     x.foo = 13;
2877     ok(x.setterVal === 12, "x.setterVal = " + x.setterVal);
2878     r = Object.getOwnPropertyDescriptor(x, "foo");
2879     ok(r.value === undefined, "x.foo value = " + r.value);
2880     ok(r.get === undefined, "x.foo get = " + r.get);
2881     ok(r.set === setter, "x.foo set = " + r.set);
2882     ok(r.writable === undefined, "x.foo writable = " + r.writable);
2883     ok(r.enumerable === true, "x.foo enumerable = " + r.enumerable);
2884     ok(r.configurable === true, "x.foo configurable = " + r.configurable);
2886     Object.defineProperty(x, "foo", { get: getter, set: undefined, configurable: false });
2887     r = Object.getOwnPropertyDescriptor(x, "foo");
2888     ok(r.value === undefined, "x.foo getter value = " + r.value);
2889     ok(r.get === getter, "x.foo getter get = " + r.get);
2890     ok(r.set === undefined, "x.foo getter set = " + r.set);
2891     ok(r.writable === undefined, "x.foo getter writable = " + r.writable);
2892     ok(r.enumerable === true, "x.foo getter enumerable = " + r.enumerable);
2893     ok(r.configurable === false, "x.foo getter configurable = " + r.configurable);
2894     try {
2895         x.__defineSetter__("foo", setter);
2896         ok(false, "expected exception calling __defineSetter__ on non-configurable property");
2897     }catch(e) {
2898         ok(e.number === 0xa13d6 - 0x80000000, "__defineSetter__ on non-configurable property threw exception " + e.number);
2899     }
2901     r = Object.prototype.__defineSetter__.call(undefined, "bar", setter);
2902     ok(r === undefined, "__defineSetter__ on undefined returned " + r);
2903     r = Object.prototype.__defineSetter__.call(null, "bar", setter);
2904     ok(r === undefined, "__defineSetter__ on null returned " + r);
2905     r = x.__defineSetter__(null, setter);
2906     ok(r === undefined, "__defineSetter__ null prop returned " + r);
2907     x["null"] = 100;
2908     ok(x.setterVal === 99, "x.setterVal after setting x.null = " + x.setterVal);
2909     r = x.__defineSetter__(50, setter);
2910     ok(r === undefined, "__defineSetter__ 50 prop returned " + r);
2911     x["50"] = 33;
2912     ok(x.setterVal === 32, "x.setterVal after setting x.50 = " + x.setterVal);
2914     try {
2915         x.__defineSetter__("bar", true);
2916         ok(false, "expected exception calling __defineSetter__ with bool");
2917     }catch(e) {
2918         ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with bool threw exception " + e.number);
2919     }
2920     try {
2921         x.__defineSetter__("bar", undefined);
2922         ok(false, "expected exception calling __defineSetter__ with undefined");
2923     }catch(e) {
2924         ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with undefined threw exception " + e.number);
2925     }
2926     try {
2927         x.__defineSetter__("bar", null);
2928         ok(false, "expected exception calling __defineSetter__ with null");
2929     }catch(e) {
2930         ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with null threw exception " + e.number);
2931     }
2932     try {
2933         Object.prototype.__defineSetter__.call(x, "bar");
2934         ok(false, "expected exception calling __defineSetter__ with only one arg");
2935     }catch(e) {
2936         ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with only one arg threw exception " + e.number);
2937     }
2939     x.bar = "test";
2940     ok(x.bar === "test", "x.bar = " + x.bar);
2941     x.__defineSetter__("bar", setter);
2942     ok(x.bar === undefined, "x.bar with setter = " + x.bar);
2943     x.bar = 10;
2944     ok(x.bar === undefined, "x.bar with setter = " + x.bar);
2945     ok(x.setterVal === 9, "x.setterVal after setting bar = " + x.setterVal);
2948 sync_test("MutationObserver", function() {
2949     if (!window.MutationObserver) {
2950         return;
2951     }
2953     try {
2954         window.MutationObserver();
2955         ok(false, "MutationObserver without args should fail");
2956     } catch(e) {
2957         ok(e.number == 0xffff - 0x80000000, "MutationObserver without new threw exception " + e.number);
2958     }
2960     try {
2961         window.MutationObserver(42);
2962         ok(false, "MutationObserver with non-function should fail");
2963     } catch(e) {
2964         todo_wine.
2965         ok(e.name == "TypeMismatchError", "MutationObserver with non-function arg threw exception " + e.name);
2966     }
2968     try {
2969         window.MutationObserver(function() {});
2970     } catch(e) {
2971         ok(false, "MutationObserver without new threw exception " + e.number);
2972     }
2974     try {
2975         new window.MutationObserver();
2976         ok(false, "MutationObserver with no args should fail");
2977     } catch(e) {
2978         ok(e.number == 0xffff - 0x80000000, "MutationObserver with no args threw exception " + e.number);
2979     }
2981     try {
2982         new window.MutationObserver(1);
2983         ok(false, "MutationObserver with non-function arg should fail");
2984     } catch(e) {
2985         todo_wine.
2986         ok(e.name == "TypeMismatchError", "MutationObserver with non-function arg threw exception " + e.name);
2987     }
2989     try {
2990         new window.MutationObserver(function() {});
2991     } catch(e) {
2992         ok(false, "MutationObserver threw exception " + e.number);
2993     }
2995     try {
2996         new window.MutationObserver(function() {}, 1);
2997     } catch(e) {
2998         ok(false, "MutationObserver with extra args threw exception " + e.number);
2999     }
3001     var mutation_observer = new MutationObserver(function() {});
3002     function test_exposed(prop) {
3003         ok(prop in mutation_observer, prop + " not found in MutationObserver.");
3004     }
3005     test_exposed("observe");
3006     test_exposed("disconnect");
3007     test_exposed("takeRecords");
3010 sync_test("initMessageEvent", function() {
3011     var e, v = document.documentMode;
3012     if(!document.createEvent)
3013         return;
3014     e = document.createEvent("MessageEvent");
3015     ok(e.data === (v < 10 ? "" : undefined), "e.data = " + e.data);
3016     ok(e.bubbles === false, "bubbles = " + e.bubbles);
3017     ok(e.cancelable === false, "cancelable = " + e.cancelable);
3018     ok(e.source === null, "e.source = " + e.source);
3019     ok(e.origin === "", "e.origin = " + e.origin);
3021     e.initMessageEvent("blah", true, true, 137, "wine", 1234, window);
3022     ok(e.data === "137", "e.data = " + e.data);
3023     ok(e.bubbles === true, "bubbles = " + e.bubbles);
3024     ok(e.cancelable === true, "cancelable = " + e.cancelable);
3025     ok(e.source === window, "e.source = " + e.source);
3026     ok(e.origin === "wine", "e.origin = " + e.origin);
3028     e.initMessageEvent("abcd", false, false, "testdata", "origin", 42, null);
3029     ok(e.data === "testdata", "e.data = " + e.data);
3030     ok(e.bubbles === false, "bubbles = " + e.bubbles);
3031     ok(e.cancelable === false, "cancelable = " + e.cancelable);
3032     ok(e.source === null, "e.source = " + e.source);
3033     ok(e.origin === "origin", "e.origin = " + e.origin);
3036 async_test("postMessage", function() {
3037     var v = document.documentMode;
3038     var onmessage_called = false;
3039     window.onmessage = function(e) {
3040         onmessage_called = true;
3041         if(v < 9)
3042             ok(e === undefined, "e = " + e);
3043         else {
3044             ok(e.data === (v < 10 ? "10" : 10), "e.data = " + e.data);
3045             ok(e.source === window, "e.source = " + e.source);
3046             ok(e.origin === "http://winetest.example.org", "e.origin = " + e.origin);
3048             e = document.createEvent("MessageEvent");
3049             ok(e.data === (v < 10 ? "" : undefined), "created e.data = " + e.data);
3050             next_test();
3051         }
3052     }
3054     var invalid = [
3055         v < 10 ? { toString: function() { return "http://winetest.example.org"; } } : null,
3056         (function() { return "http://winetest.example.org"; }),
3057         "winetest.example.org",
3058         "example.org",
3059         undefined
3060     ];
3061     for(var i = 0; i < invalid.length; i++) {
3062         try {
3063             window.postMessage("invalid " + i, invalid[i]);
3064             ok(false, "expected exception with targetOrigin " + invalid[i]);
3065         }catch(ex) {
3066             var n = ex.number >>> 0;
3067             todo_wine_if(v >= 10).
3068             ok(n === (v < 10 ? 0x80070057 : 0), "postMessage with targetOrigin " + invalid[i] + " threw " + n);
3069             if(v >= 10)
3070                 todo_wine.
3071                 ok(ex.name === "SyntaxError", "postMessage with targetOrigin " + invalid[i] + " threw " + ex.name);
3072         }
3073     }
3074     try {
3075         window.postMessage("invalid empty", "");
3076         ok(false, "expected exception with empty targetOrigin");
3077     }catch(ex) {
3078         var n = ex.number >>> 0;
3079         ok(n === 0x80070057, "postMessage with empty targetOrigin threw " + n);
3080     }
3082     window.postMessage("wrong port", "http://winetest.example.org:1234");
3083     ok(onmessage_called == (v < 9 ? true : false), "onmessage not called with wrong port");
3084     onmessage_called = false;
3086     var not_sent = [
3087         "http://winetest.example.com",
3088         "ftp://winetest.example.org",
3089         "http://wine.example.org",
3090         "http://example.org"
3091     ];
3092     for(var i = 0; i < not_sent.length; i++) {
3093         window.postMessage("not_sent " + i, not_sent[i]);
3094         ok(onmessage_called == false, "onmessage called with targetOrigin " + not_sent[i]);
3095         onmessage_called = false;
3096     }
3098     window.postMessage(10, (v < 10 ? "*" : { toString: function() { return "*"; } }));
3099     ok(onmessage_called == (v < 9 ? true : false), "onmessage not called");
3100     if(v < 9) next_test();
3103 sync_test("form", function() {
3104     document.body.innerHTML = "";
3105     var form = document.createElement("form");
3106     document.body.appendChild(form);
3108     form[0] = "test";
3109     form.innerHTML = "<input type=\"text\" id = \"i1\" /><input type=\"text\" id = \"i2\" />";
3110     ok(form.length === 2, "form.length = " + form.length);
3111     ok(typeof(form[0]) === "object", "form[0] = " + form[0]);
3112     ok(typeof(form[1]) === "object", "form[1] = " + form[1]);
3113     form.innerHTML = "";
3114     ok(form[0] === "test", "form[0] = " + form[0]);