mshtml/tests: Fix image element leaks in test helpers.
[wine.git] / dlls / mshtml / tests / documentmode.js
blob3533d7219604b498c49a42dcfe8d9f04a371938f
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         todo_wine.
62         ok(r === "[object PageTransitionEvent]", "pageshow toString = " + r);
63         ok("persisted" in e, "'persisted' not in pageshow event");
64         ok(document.readyState === "complete", "pageshow readyState = " + document.readyState);
65         ok(performance.timing.loadEventEnd > 0, "loadEventEnd <= 0 in pageshow handler");
66     }, true);
68     window.addEventListener("pagehide", function(e) {
69         pagehide_fired = true;
70         ok(document.documentMode >= 11, "pagehide fired");
72         var r = Object.prototype.toString.call(e);
73         todo_wine.
74         ok(r === "[object PageTransitionEvent]", "pagehide toString = " + r);
75         ok("persisted" in e, "'persisted' not in pagehide event");
76     }, true);
78     document.addEventListener("visibilitychange", function() { ok(false, "visibilitychange fired"); });
79     document.addEventListener("beforeunload", function() { ok(false, "beforeunload fired on document"); });
80     document.addEventListener("unload", function() { ok(false, "unload fired on document"); });
81 }else {
82     document.attachEvent("onbeforeunload", function() { ok(false, "beforeunload fired on document"); });
83     document.attachEvent("onunload", function() { ok(false, "unload fired on document"); });
86 sync_test("performance timing", function() {
87     ok(performance.timing.domInteractive >= performance.timing.domLoading, "domInteractive < domLoading");
88     ok(performance.timing.domContentLoadedEventStart >= performance.timing.domInteractive, "domContentLoadedEventStart < domInteractive");
89     ok(performance.timing.domContentLoadedEventEnd >= performance.timing.domContentLoadedEventStart, "domContentLoadedEventEnd < domContentLoadedEventStart");
90     ok(performance.timing.domComplete >= performance.timing.domContentLoadedEventEnd, "domComplete < domContentLoadedEventEnd");
91     ok(performance.timing.loadEventStart >= performance.timing.domComplete, "loadEventStart < domComplete");
92     ok(performance.timing.loadEventEnd >= performance.timing.loadEventStart, "loadEventEnd < loadEventStart");
93     ok(performance.navigation.type === 0, "navigation type = " + performance.navigation.type);
94     ok(performance.navigation.redirectCount === 0, "redirectCount = " + performance.navigation.redirectCount);
95 });
97 sync_test("page transition events", function() {
98     if(document.documentMode < 11)
99         ok(pageshow_fired === false, "pageshow fired");
100     else
101         ok(pageshow_fired === true, "pageshow not fired");
102     ok(pagehide_fired === false, "pagehide fired");
104     if(document.body.addEventListener)
105         document.body.addEventListener("unload", function() { ok(false, "unload fired on document.body"); });
106     else
107         document.body.attachEvent("onunload", function() { ok(false, "unload fired on document.body"); });
110 sync_test("builtin_toString", function() {
111     var tags = [
112         [ "abbr",            "Phrase" ],
113         [ "acronym",         "Phrase" ],
114         [ "address",         "Block" ],
115      // [ "applet",          "Applet" ],  // makes Windows pop up a dialog box
116         [ "article",         "" ],
117         [ "aside",           "" ],
118         [ "audio",           "Audio" ],
119         [ "b",               "Phrase" ],
120         [ "base",            "Base" ],
121         [ "basefont",        "BaseFont" ],
122         [ "bdi",             "Unknown" ],
123         [ "bdo",             "Phrase" ],
124         [ "big",             "Phrase" ],
125         [ "blockquote",      "Block" ],
126         [ "body",            "Body" ],
127         [ "br",              "BR" ],
128         [ "button",          "Button" ],
129         [ "canvas",          "Canvas" ],
130         [ "caption",         "TableCaption" ],
131         [ "center",          "Block" ],
132         [ "cite",            "Phrase" ],
133         [ "code",            "Phrase" ],
134         [ "col",             "TableCol" ],
135         [ "colgroup",        "TableCol" ],
136         [ "data",            "Unknown" ],
137         [ "datalist",        "DataList", 10 ],
138         [ "dd",              "DD" ],
139         [ "del",             "Mod" ],
140         [ "details",         "Unknown" ],
141         [ "dfn",             "Phrase" ],
142         [ "dialog",          "Unknown" ],
143         [ "dir",             "Directory" ],
144         [ "div",             "Div" ],
145         [ "dl",              "DList" ],
146         [ "dt",              "DT" ],
147         [ "em",              "Phrase" ],
148         [ "embed",           "Embed" ],
149         [ "fieldset",        "FieldSet" ],
150         [ "figcaption",      "" ],
151         [ "figure",          "" ],
152         [ "font",            "Font" ],
153         [ "footer",          "" ],
154         [ "form",            "Form" ],
155         [ "frame",           "Frame" ],
156         [ "frameset",        "FrameSet" ],
157         [ "h1",              "Heading" ],
158         [ "h2",              "Heading" ],
159         [ "h3",              "Heading" ],
160         [ "h4",              "Heading" ],
161         [ "h5",              "Heading" ],
162         [ "h6",              "Heading" ],
163         [ "h7",              "Unknown" ],
164         [ "head",            "Head" ],
165         [ "header",          "" ],
166         [ "hr",              "HR" ],
167         [ "html",            "Html" ],
168         [ "i",               "Phrase" ],
169         [ "iframe",          "IFrame" ],
170         [ "img",             "Image" ],
171         [ "input",           "Input" ],
172         [ "ins",             "Mod" ],
173         [ "kbd",             "Phrase" ],
174         [ "label",           "Label" ],
175         [ "legend",          "Legend" ],
176         [ "li",              "LI" ],
177         [ "link",            "Link" ],
178         [ "main",            "Unknown" ],
179         [ "map",             "Map" ],
180         [ "mark",            "" ],
181         [ "meta",            "Meta" ],
182         [ "meter",           "Unknown" ],
183         [ "nav",             "" ],
184         [ "noframes",        "" ],
185         [ "noscript",        "" ],
186         [ "object",          "Object" ],
187         [ "ol",              "OList" ],
188         [ "optgroup",        "OptGroup" ],
189         [ "option",          "Option" ],
190         [ "output",          "Unknown" ],
191         [ "p",               "Paragraph" ],
192         [ "param",           "Param" ],
193         [ "picture",         "Unknown" ],
194         [ "pre",             "Pre" ],
195         [ "progress",        "Progress", 10 ],
196         [ "q",               "Quote" ],
197         [ "rp",              "Phrase" ],
198         [ "rt",              "Phrase" ],
199         [ "ruby",            "Phrase" ],
200         [ "s",               "Phrase" ],
201         [ "samp",            "Phrase" ],
202         [ "script",          "Script" ],
203         [ "section",         "" ],
204         [ "select",          "Select" ],
205         [ "small",           "Phrase" ],
206         [ "source",          "Source" ],
207         [ "span",            "Span" ],
208         [ "strike",          "Phrase" ],
209         [ "strong",          "Phrase" ],
210         [ "style",           "Style" ],
211         [ "sub",             "Phrase" ],
212         [ "summary",         "Unknown" ],
213         [ "sup",             "Phrase" ],
214         [ "svg",             "Unknown" ],
215         [ "table",           "Table" ],
216         [ "tbody",           "TableSection" ],
217         [ "td",              "TableDataCell" ],
218         [ "template",        "Unknown" ],
219         [ "textarea",        "TextArea" ],
220         [ "tfoot",           "TableSection" ],
221         [ "th",              "TableHeaderCell" ],
222         [ "thead",           "TableSection" ],
223         [ "time",            "Unknown" ],
224         [ "title",           "Title" ],
225         [ "tr",              "TableRow" ],
226         [ "track",           "Track", 10 ],
227         [ "tt",              "Phrase" ],
228         [ "u",               "Phrase" ],
229         [ "ul",              "UList" ],
230         [ "var",             "Phrase" ],
231         [ "video",           "Video" ],
232         [ "wbr",             "" ],
233         [ "winetest",        "Unknown" ]
234     ];
235     var v = document.documentMode, e;
237     function test(msg, obj, name, tostr) {
238         var s;
239         if(obj.toString) {
240             s = obj.toString();
241             todo_wine_if(name !== "HTMLElement" && s === "[object HTMLElement]").
242             ok(s === (tostr ? tostr : (v < 9 ? "[object]" : "[object " + name + "]")), msg + " toString returned " + s);
243         }
244         s = Object.prototype.toString.call(obj);
245         todo_wine_if(v >= 9 && name != "Object").
246         ok(s === (v < 9 ? "[object Object]" : "[object " + name + "]"), msg + " Object.toString returned " + s);
247     }
249     for(var i = 0; i < tags.length; i++)
250         if(tags[i].length < 3 || v >= tags[i][2])
251             test("tag '" + tags[i][0] + "'", document.createElement(tags[i][0]), "HTML" + tags[i][1] + "Element");
253     e = document.createElement("a");
254     ok(e.toString() === "", "tag 'a' (without href) toString returned " + e.toString());
255     e.href = "https://www.winehq.org/";
256     test("tag 'a'", e, "HTMLAnchorElement", "https://www.winehq.org/");
258     e = document.createElement("area");
259     ok(e.toString() === "", "tag 'area' (without href) toString returned " + e.toString());
260     e.href = "https://www.winehq.org/";
261     test("tag 'area'", e, "HTMLAreaElement", "https://www.winehq.org/");
263     e = document.createElement("style");
264     document.body.appendChild(e);
265     var sheet = v >= 9 ? e.sheet : e.styleSheet;
266     if(v >= 9)
267         sheet.insertRule("div { border: none }", 0);
268     else
269         sheet.addRule("div", "border: none", 0);
271     e = document.createElement("p");
272     e.className = "testclass    another ";
273     e.textContent = "Test content";
274     e.style.border = "1px solid black";
275     document.body.appendChild(e);
277     var txtRange = document.body.createTextRange();
278     txtRange.moveToElementText(e);
280     var clientRects = e.getClientRects();
281     if(!clientRects) win_skip("getClientRects() is buggy and not available, skipping");
283     var currentStyle = e.currentStyle;
284     if(!currentStyle) win_skip("currentStyle is buggy and not available, skipping");
286     // w10pro64 testbot VM throws WININET_E_INTERNAL_ERROR for some reason
287     var localStorage;
288     try {
289         localStorage = window.localStorage;
290     }catch(e) {
291         ok(e.number === 0x72ee4 - 0x80000000, "localStorage threw " + e.number + ": " + e);
292     }
293     if(!localStorage) win_skip("localStorage is buggy and not available, skipping");
295     test("attribute", document.createAttribute("class"), "Attr");
296     if(false /* todo_wine */) test("attributes", e.attributes, "NamedNodeMap");
297     test("childNodes", document.body.childNodes, "NodeList");
298     if(clientRects) test("clientRect", clientRects[0], "ClientRect");
299     if(clientRects) test("clientRects", clientRects, "ClientRectList");
300     if(currentStyle) test("currentStyle", currentStyle, "MSCurrentStyleCSSProperties");
301     if(v >= 11 /* todo_wine */) test("document", document, v < 11 ? "Document" : "HTMLDocument");
302     test("elements", document.getElementsByTagName("body"), "HTMLCollection");
303     test("history", window.history, "History");
304     test("implementation", document.implementation, "DOMImplementation");
305     if(localStorage) test("localStorage", localStorage, "Storage");
306     test("location", window.location, "Object", window.location.href);
307     if(v >= 11 /* todo_wine */) test("mimeTypes", window.navigator.mimeTypes, v < 11 ? "MSMimeTypesCollection" : "MimeTypeArray");
308     test("navigator", window.navigator, "Navigator");
309     test("performance", window.performance, "Performance");
310     test("performanceNavigation", window.performance.navigation, "PerformanceNavigation");
311     test("performanceTiming", window.performance.timing, "PerformanceTiming");
312     if(v >= 11 /* todo_wine */) test("plugins", window.navigator.plugins, v < 11 ? "MSPluginsCollection" : "PluginArray");
313     test("screen", window.screen, "Screen");
314     test("sessionStorage", window.sessionStorage, "Storage");
315     test("style", document.body.style, "MSStyleCSSProperties");
316     test("styleSheet", sheet, "CSSStyleSheet");
317     test("styleSheetRule", sheet.rules[0], "CSSStyleRule");
318     test("styleSheetRules", sheet.rules, "MSCSSRuleList");
319     test("styleSheets", document.styleSheets, "StyleSheetList");
320     test("textNode", document.createTextNode("testNode"), "Text", v < 9 ? "testNode" : null);
321     test("textRange", txtRange, "TextRange");
322     test("window", window, "Window", "[object Window]");
323     test("xmlHttpRequest", new XMLHttpRequest(), "XMLHttpRequest");
324     if(v < 10) {
325         test("namespaces", document.namespaces, "MSNamespaceInfoCollection");
326     }
327     if(v < 11) {
328         test("eventObject", document.createEventObject(), "MSEventObj");
329         test("selection", document.selection, "MSSelection");
330     }
331     if(v >= 9) {
332         test("computedStyle", window.getComputedStyle(e), "CSSStyleDeclaration");
333         test("doctype", document.doctype, "DocumentType");
335         test("Event", document.createEvent("Event"), "Event");
336         test("CustomEvent", document.createEvent("CustomEvent"), "CustomEvent");
337         test("KeyboardEvent", document.createEvent("KeyboardEvent"), "KeyboardEvent");
338         test("MouseEvent", document.createEvent("MouseEvent"), "MouseEvent");
339         test("UIEvent", document.createEvent("UIEvent"), "UIEvent");
340     }
341     if(v >= 10) {
342         test("classList", e.classList, "DOMTokenList", "testclass    another ");
343         test("console", window.console, "Console");
344         test("mediaQueryList", window.matchMedia("(hover:hover)"), "MediaQueryList");
345     }
346     if(v >= 9) {
347         document.body.innerHTML = "<!--...-->";
348         test("comment", document.body.firstChild, "Comment");
349     }
352 sync_test("elem_props", function() {
353     var elem = document.documentElement;
355     function test_exposed(prop, expect, is_todo) {
356         var ok_ = is_todo ? todo_wine.ok : ok;
357         if(expect)
358             ok_(prop in elem, prop + " not found in element.");
359         else
360             ok_(!(prop in elem), prop + " found in element.");
361     }
363     var v = document.documentMode;
365     test_exposed("attachEvent", v < 11);
366     test_exposed("detachEvent", v < 11);
367     test_exposed("doScroll", v < 11);
368     test_exposed("readyState", v < 11);
369     test_exposed("clientTop", true);
370     test_exposed("title", true);
371     test_exposed("querySelectorAll", v >= 8);
372     test_exposed("textContent", v >= 9);
373     test_exposed("prefix", v >= 9);
374     test_exposed("firstElementChild", v >= 9);
375     test_exposed("onsubmit", v >= 9);
376     test_exposed("getElementsByClassName", v >= 9);
377     test_exposed("removeAttributeNS", v >= 9);
378     test_exposed("addEventListener", v >= 9);
379     test_exposed("hasAttribute", v >= 8, v === 8);
380     test_exposed("removeEventListener", v >= 9);
381     test_exposed("dispatchEvent", v >= 9);
382     test_exposed("msSetPointerCapture", v >= 10);
383     if (v >= 9) test_exposed("spellcheck", v >= 10);
385     elem = document.createElement("style");
386     test_exposed("media", true);
387     test_exposed("type", true);
388     test_exposed("disabled", true);
389     test_exposed("media", true);
390     test_exposed("sheet", v >= 9);
391     test_exposed("readyState", v < 11);
392     test_exposed("styleSheet", v < 11);
393     test_exposed("classList", v >= 10);
395     elem = document.createElement("img");
396     test_exposed("fileSize", v < 11);
399 sync_test("doc_props", function() {
400     function test_exposed(prop, expect, is_todo) {
401         var ok_ = is_todo ? todo_wine.ok : ok;
402         if(expect)
403             ok_(prop in document, prop + " not found in document.");
404         else
405             ok_(!(prop in document), prop + " found in document.");
406     }
408     var v = document.documentMode;
409     ok(document.mimeType === external.getExpectedMimeType("text/html"), "mimeType = " + document.mimeType);
411     test_exposed("attachEvent", v < 11);
412     test_exposed("detachEvent", v < 11);
413     test_exposed("createStyleSheet",v < 11);
414     test_exposed("fileSize", v < 11);
415     test_exposed("selection", v < 11);
416     test_exposed("onstorage", v < 9);
417     test_exposed("textContent", v >= 9);
418     test_exposed("prefix", v >= 9);
419     test_exposed("defaultView", v >= 9);
420     test_exposed("head", v >= 9);
421     test_exposed("addEventListener", v >= 9);
422     test_exposed("removeEventListener", v >= 9);
423     test_exposed("dispatchEvent", v >= 9);
424     test_exposed("createEvent", v >= 9);
426     test_exposed("parentWindow", true);
427     if(v >= 9) ok(document.defaultView === document.parentWindow, "defaultView != parentWindow");
430 sync_test("docfrag_props", function() {
431     var docfrag = document.createDocumentFragment();
433     function test_exposed(prop, expect) {
434         if(expect)
435             ok(prop in docfrag, prop + " not found in document fragent.");
436         else
437             ok(!(prop in docfrag), prop + " found in document fragent.");
438     }
440     var v = document.documentMode;
442     test_exposed("compareDocumentPosition", v >= 9);
445 sync_test("window_props", function() {
446     function test_exposed(prop, expect, is_todo) {
447         var ok_ = is_todo ? todo_wine.ok : ok;
448         if(expect)
449             ok_(prop in window, prop + " not found in window.");
450         else
451             ok_(!(prop in window), prop + " found in window.");
452     }
454     var v = document.documentMode;
456     test_exposed("attachEvent", v < 11);
457     test_exposed("detachEvent", v < 11);
458     test_exposed("execScript", v < 11);
459     test_exposed("createPopup", v < 11);
460     test_exposed("postMessage", true);
461     test_exposed("sessionStorage", true);
462     test_exposed("localStorage", true);
463     test_exposed("addEventListener", v >= 9);
464     test_exposed("removeEventListener", v >= 9);
465     test_exposed("dispatchEvent", v >= 9);
466     test_exposed("getSelection", v >= 9);
467     test_exposed("onfocusout", v >= 9);
468     test_exposed("getComputedStyle", v >= 9);
469     test_exposed("cancelAnimationFrame", v >= 10);
470     test_exposed("requestAnimationFrame", v >= 10);
471     test_exposed("Map", v >= 11);
472     test_exposed("Set", v >= 11);
473     test_exposed("performance", true);
474     test_exposed("console", v >= 10);
475     test_exposed("matchMedia", v >= 10);
478 sync_test("domimpl_props", function() {
479     var domimpl = document.implementation;
480     function test_exposed(prop, expect) {
481         if(expect)
482             ok(prop in domimpl, prop + " not found in DOMImplementation.");
483         else
484             ok(!(prop in domimpl), prop + " found in DOMImplementation.");
485     }
487     var v = document.documentMode;
489     test_exposed("hasFeature", true);
490     test_exposed("createDocument", v >= 9);
491     test_exposed("createDocumentType", v >= 9);
492     test_exposed("createHTMLDocument", v >= 9);
495 sync_test("xhr_props", function() {
496     var xhr = new XMLHttpRequest();
498     function test_exposed(prop, expect) {
499         if(expect)
500             ok(prop in xhr, prop + " not found in XMLHttpRequest.");
501         else
502             ok(!(prop in xhr), prop + " found in XMLHttpRequest.");
503     }
505     var v = document.documentMode;
507     test_exposed("addEventListener", v >= 9);
508     test_exposed("removeEventListener", v >= 9);
509     test_exposed("dispatchEvent", v >= 9);
510     test_exposed("onabort", v >= 10);
511     test_exposed("onerror", v >= 10);
512     test_exposed("onloadend", v >= 10);
513     test_exposed("onloadstart", v >= 10);
514     test_exposed("onprogress", v >= 10);
515     test_exposed("ontimeout", true);
516     test_exposed("overrideMimeType", v >= 11);
517     test_exposed("response", v >= 10);
518     test_exposed("responseType", v >= 10);
519     test_exposed("timeout", true);
520     test_exposed("upload", v >= 10);
521     test_exposed("withCredentials", v >= 10);
524 sync_test("stylesheet_props", function() {
525     var v = document.documentMode;
526     var elem = document.createElement("style");
527     document.body.appendChild(elem);
528     var sheet = v >= 9 ? elem.sheet : elem.styleSheet;
530     function test_exposed(prop, expect) {
531         if(expect)
532             ok(prop in sheet, prop + " not found in style sheet.");
533         else
534             ok(!(prop in sheet), prop + " found in style sheet.");
535     }
537     test_exposed("href", true);
538     test_exposed("title", true);
539     test_exposed("type", true);
540     test_exposed("media", true);
541     test_exposed("ownerNode", v >= 9);
542     test_exposed("ownerRule", v >= 9);
543     test_exposed("cssRules", v >= 9);
544     test_exposed("insertRule", v >= 9);
545     test_exposed("deleteRule", v >= 9);
546     test_exposed("disabled", true);
547     test_exposed("parentStyleSheet", true);
548     test_exposed("owningElement", true);
549     test_exposed("readOnly", true);
550     test_exposed("imports", true);
551     test_exposed("id", true);
552     test_exposed("addImport", true);
553     test_exposed("addRule", true);
554     test_exposed("removeImport", true);
555     test_exposed("removeRule", true);
556     test_exposed("cssText", true);
557     test_exposed("rules", true);
560 sync_test("rect_props", function() {
561     document.body.innerHTML = '<div>test</div>';
562     var elem = document.body.firstChild;
563     var rect = elem.getBoundingClientRect();
564     function test_exposed(prop, expect) {
565         if(expect)
566             ok(prop in rect, prop + " not found in rect object.");
567         else
568             ok(!(prop in rect), prop + " found in rect object.");
569     }
571     var v = document.documentMode;
573     test_exposed("width", v >= 9);
574     test_exposed("height", v >= 9);
577 sync_test("xhr open", function() {
578     var e = false;
579     try {
580         (new XMLHttpRequest()).open("GET", "https://www.winehq.org/");
581     }catch(ex) {
582         e = true;
583     }
585     if(document.documentMode < 10)
586         ok(e, "expected exception");
587     else
588         ok(!e, "unexpected exception");
591 sync_test("style_props", function() {
592     var style = document.body.style;
594     function test_exposed(prop, expect) {
595         if(expect)
596             ok(prop in style, prop + " not found in style object.");
597         else
598             ok(!(prop in style), prop + " found in style object.");
599     }
601     var v = document.documentMode;
603     test_exposed("removeAttribute", true);
604     test_exposed("zIndex", true);
605     test_exposed("z-index", true);
606     test_exposed("filter", true);
607     test_exposed("pixelTop", true);
608     test_exposed("float", true);
609     test_exposed("css-float", false);
610     test_exposed("style-float", false);
611     test_exposed("setProperty", v >= 9);
612     test_exposed("removeProperty", v >= 9);
613     test_exposed("background-clip", v >= 9);
614     test_exposed("msTransform", v >= 9);
615     test_exposed("transform", v >= 10);
617     style = document.body.currentStyle;
619     test_exposed("zIndex", true);
620     test_exposed("z-index", true);
621     test_exposed("filter", true);
622     test_exposed("pixelTop", false);
623     test_exposed("float", true);
624     test_exposed("css-float", false);
625     test_exposed("style-float", false);
626     test_exposed("setProperty", v >= 9);
627     test_exposed("removeProperty", v >= 9);
628     test_exposed("background-clip", v >= 9);
629     test_exposed("transform", v >= 10);
631     if(window.getComputedStyle) {
632         style = window.getComputedStyle(document.body);
634         test_exposed("removeAttribute", false);
635         test_exposed("zIndex", true);
636         test_exposed("z-index", true);
637         test_exposed("pixelTop", false);
638         test_exposed("float", true);
639         test_exposed("css-float", false);
640         test_exposed("style-float", false);
641         test_exposed("setProperty", v >= 9);
642         test_exposed("removeProperty", v >= 9);
643         test_exposed("background-clip", v >= 9);
644         test_exposed("transform", v >= 10);
645     }
648 sync_test("createElement_inline_attr", function() {
649     var v = document.documentMode, e, s;
651     if(v < 9) {
652         s = document.createElement("<div>").tagName;
653         ok(s === "DIV", "<div>.tagName returned " + s);
654         s = document.createElement("<div >").tagName;
655         ok(s === "DIV", "<div >.tagName returned " + s);
656         s = document.createElement("<div/>").tagName;
657         ok(s === "DIV", "<div/>.tagName returned " + s);
658         e = 0;
659         try {
660             document.createElement("<div");
661         }catch(ex) {
662             e = ex.number;
663         }
664         ok(e === 0x4005 - 0x80000000, "<div e = " + e);
665         e = 0;
666         try {
667             document.createElement("<div test=1");
668         }catch(ex) {
669             e = ex.number;
670         }
671         ok(e === 0x4005 - 0x80000000, "<div test=1 e = " + e);
673         var tags = [ "div", "head", "body", "title", "html" ];
675         for(var i = 0; i < tags.length; i++) {
676             e = document.createElement("<" + tags[i] + " test='a\"' abcd=\"&quot;b&#34;\">");
677             ok(e.tagName === tags[i].toUpperCase(), "<" + tags[i] + " test=\"a\" abcd=\"b\">.tagName returned " + e.tagName);
678             ok(e.test === "a\"", "<" + tags[i] + " test='a\"' abcd=\"&quot;b&#34;\">.test returned " + e.test);
679             ok(e.abcd === "\"b\"", "<" + tags[i] + " test='a\"' abcd=\"&quot;b&#34;\">.abcd returned " + e.abcd);
680         }
681     }else {
682         s = "";
683         e = 0;
684         try {
685             document.createElement("<div>");
686         }catch(ex) {
687             s = ex.toString();
688             e = ex.number;
689         }
690         todo_wine.
691         ok(e === undefined, "<div> e = " + e);
692         todo_wine.
693         ok(s === "InvalidCharacterError", "<div> s = " + s);
694         s = "";
695         e = 0;
696         try {
697             document.createElement("<div test=\"a\">");
698         }catch(ex) {
699             s = ex.toString();
700             e = ex.number;
701         }
702         todo_wine.
703         ok(e === undefined, "<div test=\"a\"> e = " + e);
704         todo_wine.
705         ok(s === "InvalidCharacterError", "<div test=\"a\"> s = " + s);
706     }
709 sync_test("JS objs", function() {
710     var g = window;
712     function test_exposed(func, obj, expect, is_todo) {
713         var ok_ = is_todo ? todo_wine.ok : ok;
714         if(expect)
715             ok_(func in obj, func + " not found in " + obj);
716         else
717             ok_(!(func in obj), func + " found in " + obj);
718     }
720     function test_parses(code, expect) {
721         var success;
722         try {
723             eval(code);
724             success = true;
725         }catch(e) {
726             success = false;
727         }
728         if(expect)
729             ok(success === true, code + " did not parse");
730         else
731             ok(success === false, code + " parsed");
732     }
734     var v = document.documentMode;
736     test_exposed("ScriptEngineMajorVersion", g, true);
738     test_exposed("JSON", g, v >= 8);
739     test_exposed("now", Date, true);
740     test_exposed("toISOString", Date.prototype, v >= 9);
741     test_exposed("isArray", Array, v >= 9);
742     test_exposed("forEach", Array.prototype, v >= 9);
743     test_exposed("indexOf", Array.prototype, v >= 9);
744     test_exposed("trim", String.prototype, v >= 9);
745     test_exposed("map", Array.prototype, v >= 9);
747     /* FIXME: IE8 implements weird semi-functional property descriptors. */
748     test_exposed("getOwnPropertyDescriptor", Object, v >= 8, v === 8);
749     test_exposed("defineProperty", Object, v >= 8, v === 8);
750     test_exposed("defineProperties", Object, v >= 9);
752     test_exposed("getPrototypeOf", Object, v >= 9);
754     test_parses("if(false) { o.default; }", v >= 9);
755     test_parses("if(false) { o.with; }", v >= 9);
756     test_parses("if(false) { o.if; }", v >= 9);
759 sync_test("eval", function() {
760     var i, context, code = "this.foobar = 1234", v = document.documentMode;
762     var direct = [
763         function() { eval(code); },
764         function() { (eval)(code); },
765         function() { (function(eval) { eval(code); }).call(this, eval); },
766         function() { eval("eval(" + code + ")"); }
767     ];
769     for(i = 0; i < direct.length; i++) {
770         context = {};
771         direct[i].call(context);
772         ok(context.foobar === 1234, "direct[" + i + "] context foobar = " + context.foobar);
773     }
775     var indirect = [
776         function() { (true, eval)(code); },
777         function() { (eval, eval)(code); },
778         function() { (true ? eval : false)(code); },
779         function() { [eval][0](code); },
780         function() { eval.call(this, code); },
781         function() { var f; (f = eval)(code); },
782         function() { var f = eval; f(code); },
783         function() { (function(f) { f(code); }).call(this, eval); },
784         function() { (function(f) { return f; }).call(this, eval)(code); },
785         function() { (function() { arguments[0](code) }).call(this, eval); },
786         function() { window.eval(code); },
787         function() { window["eval"](code); },
788         function() { eval("eval")(code); }
789     ];
791     for(i = 0; i < indirect.length; i++) {
792         context = {};
793         ok(!("foobar" in window), "indirect[" + i + "] has global foobar before call");
794         indirect[i].call(context);
795         if(v < 9) {
796             ok(context.foobar === 1234, "indirect[" + i + "] context foobar = " + context.foobar);
797             ok(!("foobar" in window), "indirect[" + i + "] has global foobar");
798         }else {
799             ok(!("foobar" in context), "indirect[" + i + "] has foobar");
800             ok(window.foobar === 1234, "indirect[" + i + "] global foobar = " + context.foobar);
801             delete window.foobar;
802         }
803     }
805     context = {};
806     (function(eval) { eval(code); })(function() { context.barfoo = 4321; });
807     ok(context.barfoo === 4321, "context.barfoo = " + context.barfoo);
810 sync_test("for..in", function() {
811     var v = document.documentMode, found = 0, r;
813     function ctor() {}
814     ctor.prototype.test2 = true;
816     var arr = new Array(), obj = new ctor(), i, r;
817     obj.test1 = true;
819     i = 0;
820     for(r in obj) {
821         ctor.prototype.test3 = true;
822         arr[r] = true;
823         i++;
824     }
826     ok(i === 3, "enum did " + i + " iterations");
827     ok(arr["test1"] === true, "arr[test1] !== true");
828     ok(arr["test2"] === true, "arr[test2] !== true");
829     ok(arr["test3"] === true, "arr[test3] !== true");
831     for(r in document)
832         if(r === "ondragstart")
833             found++;
834     ok(found === 1, "ondragstart enumerated " + found + " times in document");
835     document.ondragstart = "";
836     found = 0;
837     for(r in document)
838         if(r === "ondragstart")
839             found++;
840     ok(found === 1, "ondragstart enumerated " + found + " times in document after set to empty string");
843 sync_test("function caller", function() {
844     ok(Function.prototype.hasOwnProperty("caller"), "caller not prop of Function.prototype");
846     function test_caller(expected_caller, stop) {
847         ok(test_caller.caller === expected_caller, "caller = " + test_caller.caller);
848         if(stop) return;
849         function nested() {
850             ok(nested.caller === test_caller, "nested caller = " + nested.caller);
851             test_caller(nested, true);
852             ok(test_caller.caller === expected_caller, "caller within nested = " + test_caller.caller);
853         }
854         nested();
855         ok(test_caller.caller === expected_caller, "caller after nested = " + test_caller.caller);
856     }
857     ok(test_caller.hasOwnProperty("caller"), "caller not prop of test_caller");
858     ok(test_caller.caller === null, "test_caller.caller = " + test_caller.caller);
860     function f1() { test_caller(f1); } f1();
861     function f2() { test_caller(f2); } f2();
864 sync_test("elem_by_id", function() {
865     document.body.innerHTML = '<form id="testid" name="testname"></form>';
866     var v = document.documentMode, found, i;
868     var id_elem = document.getElementById("testid");
869     ok(id_elem.tagName === "FORM", "id_elem.tagName = " + id_elem.tagName);
871     var name_elem = document.getElementById("testname");
872     if(v < 8)
873         ok(id_elem === name_elem, "id_elem != id_elem");
874     else
875         ok(name_elem === null, "name_elem != null");
877     id_elem = window.testid;
878     ok(id_elem.tagName === "FORM", "window.testid = " + id_elem);
880     name_elem = document.testname;
881     ok(name_elem.tagName === "FORM", "document.testname = " + name_elem);
883     for(id_elem in window)
884         ok(id_elem !== "testid" && id_elem != "testname", id_elem + " was enumerated in window");
885     window.testid = 137;
886     found = false;
887     for(id_elem in window) {
888         ok(id_elem != "testname", id_elem + " was enumerated in window after set to 137");
889         if(id_elem === "testid")
890             found = true;
891     }
892     ok(found, "testid was not enumerated in window after set to 137");
894     found = false;
895     for(id_elem in document) {
896         ok(id_elem !== "testid", "testid was enumerated in document");
897         if(id_elem === "testname")
898             found = true;
899     }
900     ok(found, "testname was not enumerated in document");
902     try {
903         document.testname();
904         ok(false, "document.testname() did not throw exception");
905     }catch(e) {
906         ok(e.number === 0xa01b6 - 0x80000000, "document.testname() threw = " + e.number);
907     }
909     try {
910         document.testname = "foo";
911         ok(v >= 9, "Setting document.testname did not throw exception");
913         id_elem = document.testid;
914         ok(id_elem.tagName === "FORM", "document.testid after set = " + id_elem);
915         name_elem = document.testname;
916         ok(name_elem === "foo", "document.testname after set = " + name_elem);
917     }catch(e) {
918         todo_wine_if(v >= 9).
919         ok(v < 9 && e.number === 0xa01b6 - 0x80000000, "Setting document.testname threw = " + e.number);
920     }
922     try {
923         document.testid = "bar";
924         ok(v >= 9, "Setting document.testid did not throw exception");
926         id_elem = document.testid;
927         ok(id_elem === "bar", "document.testid after both set = " + id_elem);
928         name_elem = document.testname;
929         ok(name_elem === "foo", "document.testname after both set = " + name_elem);
931         found = false, name_elem = false;
932         for(id_elem in document) {
933             if(id_elem === "testid")
934                 found = true;
935             if(id_elem === "testname")
936                 name_elem = true;
937         }
938         ok(found, "testid was not enumerated in document after both set");
939         ok(name_elem, "testname was not enumerated in document after both set");
940         delete document.testid;
941         delete document.testname;
942     }catch(e) {
943         todo_wine_if(v >= 9).
944         ok(v < 9 && e.number === 0xa01b6 - 0x80000000, "Setting document.testid threw = " + e.number);
945     }
947     // these tags expose name as props, and id only if they have a name
948     var tags = [ "embed", "form", "iframe", "img" ];
949     for(i in tags) {
950         var tag = tags[i];
951         document.body.innerHTML = '<' + tag + ' id="testid" name="testname"></' + tag + '><' + tag + ' id="foobar"></' + tag + '>';
952         ok("testname" in document, tag + " did not expose testname");
953         ok("testid" in document, tag + " did not expose testid");
954         ok(!("foobar" in document), tag + " exposed foobar");
955     }
957     // these tags always expose their id as well as name (we don't test applet because it makes Windows pop up a dialog box)
958     tags = [ "object" ];
959     for(i in tags) {
960         var tag = tags[i];
961         document.body.innerHTML = '<' + tag + ' id="testid" name="testname"></' + tag + '><' + tag + ' id="foobar"></' + tag + '>';
962         ok("testname" in document, tag + " did not expose testname");
963         ok("testid" in document, tag + " did not expose testid");
964         ok("foobar" in document, tag + " did not expose foobar");
965     }
967     // all other tags don't expose props for either id or name, test a few of them here
968     tags = [ "a", "b", "body", "center", "div", "frame", "h2", "head", "html", "input", "meta", "p", "span", "style", "table", "winetest" ];
969     for(i in tags) {
970         var tag = tags[i];
971         document.body.innerHTML = '<' + tag + ' id="testid" name="testname"></' + tag + '><' + tag + ' id="foobar"></' + tag + '>';
972         ok(!("testname" in document), tag + " exposed testname");
973         ok(!("testid" in document), tag + " exposed testid");
974         ok(!("foobar" in document), tag + " exposed foobar");
975     }
978 sync_test("doc_mode", function() {
979     compat_version = parseInt(document.location.search.substring(1));
981     trace("Testing compatibility mode " + compat_version);
983     if(compat_version > 6 && compat_version > document.documentMode) {
984         win_skip("Document mode not supported (expected " + compat_version + " got " + document.documentMode + ")");
985         reportSuccess();
986         return;
987     }
989     ok(Math.max(compat_version, 5) === document.documentMode, "documentMode = " + document.documentMode);
991     if(document.documentMode > 5)
992         ok(document.compatMode === "CSS1Compat", "document.compatMode = " + document.compatMode);
993     else
994         ok(document.compatMode === "BackCompat", "document.compatMode = " + document.compatMode);
997 sync_test("doctype", function() {
998     var doctype = document.doctype;
1000     if(document.documentMode < 9) {
1001         ok(doctype === null, "doctype = " + document.doctype);
1002         return;
1003     }
1005     ok(doctype.name === "html", "doctype.name = " + doctype.name);
1008 async_test("iframe_doc_mode", function() {
1009     var iframe = document.createElement("iframe");
1011     iframe.onload = function() {
1012         var iframe_mode = iframe.contentWindow.document.documentMode;
1013         if(document.documentMode < 9)
1014             ok(iframe_mode === 5, "iframe_mode = " + iframe_mode);
1015         else
1016             ok(iframe_mode === document.documentMode, "iframe_mode = " + iframe_mode);
1017         next_test();
1018     }
1020     iframe.src = "about:blank";
1021     document.body.appendChild(iframe);
1024 sync_test("conditional_comments", function() {
1025     var div = document.createElement("div");
1026     document.body.appendChild(div);
1028     function test_version(v) {
1029         var version = compat_version ? compat_version : 7;
1031         div.innerHTML = "<!--[if lte IE " + v + "]>true<![endif]-->";
1032         ok(div.innerText === (version <= v ? "true" : ""),
1033            "div.innerText = " + div.innerText + " for version (<=) " + v);
1035         div.innerHTML = "<!--[if lt IE " + v + "]>true<![endif]-->";
1036         ok(div.innerText === (version < v ? "true" : ""),
1037            "div.innerText = " + div.innerText + " for version (<) " + v);
1039         div.innerHTML = "<!--[if gte IE " + v + "]>true<![endif]-->";
1040         ok(div.innerText === (version >= v && version < 10 ? "true" : ""),
1041            "div.innerText = " + div.innerText + " for version (>=) " + v);
1043         div.innerHTML = "<!--[if gt IE " + v + "]>true<![endif]-->";
1044         ok(div.innerText === (version > v && version < 10 ? "true" : ""),
1045            "div.innerText = " + div.innerText + " for version (>) " + v);
1046     }
1048     test_version(5);
1049     test_version(6);
1050     test_version(7);
1051     test_version(8);
1054 var ready_states;
1056 async_test("script_load", function() {
1057     var v = document.documentMode;
1058     if(v < 9) {
1059         next_test();
1060         return;
1061     }
1063     var elem = document.createElement("script");
1064     ready_states = "";
1066     elem.onreadystatechange = guard(function() {
1067         ok(v < 11, "unexpected onreadystatechange call");
1068         ready_states += elem.readyState + ",";
1069     });
1071     elem.onload = guard(function() {
1072         switch(v) {
1073         case 9:
1074             ok(ready_states === "loading,exec,loaded,", "ready_states = " + ready_states);
1075             break;
1076         case 10:
1077             ok(ready_states === "loading,exec,", "ready_states = " + ready_states);
1078             break;
1079         case 11:
1080             ok(ready_states === "exec,", "ready_states = " + ready_states);
1081             break;
1082         }
1083         next_test();
1084     });
1086     document.body.appendChild(elem);
1087     elem.src = "jsstream.php?simple";
1088     external.writeStream("simple", "ready_states += 'exec,';");
1091 sync_test("location", function() {
1092     document.body.innerHTML = '<a name="testanchor">test</a>';
1094     ok(location.hash === "", "initial location.hash = " + location.hash);
1095     location.hash = "TestAnchor";
1096     ok(location.hash === "#TestAnchor", "location.hash after set to TestAnchor = " + location.hash);
1097     location.hash = "##foo";
1098     ok(location.hash === "##foo", "location.hash after set to ##foo = " + location.hash);
1099     location.hash = "#testanchor";
1100     ok(location.hash === "#testanchor", "location.hash after set to #testanchor = " + location.hash);
1103 sync_test("navigator", function() {
1104     var v = document.documentMode, re;
1105     var app = navigator.appVersion;
1106     ok(navigator.userAgent === "Mozilla/" + app,
1107        "userAgent = " + navigator.userAgent + " appVersion = " + app);
1109     re = v < 11
1110         ? "^" + (v < 9 ? "4" : "5") + "\\.0 \\(compatible; MSIE " + (v < 7 ? 7 : v) +
1111           "\\.0; Windows NT [0-9].[0-9]; .*Trident/[678]\\.0.*\\)$"
1112         : "^5.0 \\(Windows NT [0-9].[0-9]; .*Trident/[678]\\.0.*rv:11.0\\) like Gecko$";
1113     ok(new RegExp(re).test(app), "appVersion = " + app);
1115     ok(navigator.appCodeName === "Mozilla", "appCodeName = " + navigator.appCodeName);
1116     ok(navigator.appName === (v < 11 ? "Microsoft Internet Explorer" : "Netscape"),
1117        "appName = " + navigator.appName);
1118     ok(navigator.toString() === (v < 9 ? "[object]" : "[object Navigator]"),
1119        "navigator.toString() = " + navigator.toString());
1122 sync_test("delete_prop", function() {
1123     var v = document.documentMode;
1124     var obj = document.createElement("div"), r, obj2;
1126     obj.prop1 = true;
1127     r = false;
1128     try {
1129         delete obj.prop1;
1130     }catch(ex) {
1131         r = true;
1132     }
1133     if(v < 8) {
1134         ok(r, "did not get an expected exception");
1135         return;
1136     }
1137     ok(!r, "got an unexpected exception");
1138     ok(!("prop1" in obj), "prop1 is still in obj");
1140     /* again, this time prop1 does not exist */
1141     r = false;
1142     try {
1143         delete obj.prop1;
1144     }catch(ex) {
1145         r = true;
1146     }
1147     if(v < 9) {
1148         ok(r, "did not get an expected exception");
1149         return;
1150     }else {
1151         ok(!r, "got an unexpected exception");
1152         ok(!("prop1" in obj), "prop1 is still in obj");
1153     }
1155     r = (delete obj.className);
1156     ok(r, "delete returned " + r);
1157     ok("className" in obj, "className deleted from obj");
1158     ok(obj.className === "", "className = " + obj.className);
1160     /* builtin propertiles don't throw any exception, but are not really deleted */
1161     r = (delete obj.tagName);
1162     ok(r, "delete returned " + r);
1163     ok("tagName" in obj, "tagName deleted from obj");
1164     ok(obj.tagName === "DIV", "tagName = " + obj.tagName);
1166     obj = document.querySelectorAll("*");
1167     ok("0" in obj, "0 is not in obj");
1168     obj2 = obj[0];
1169     r = (delete obj[0]);
1170     ok("0" in obj, "0 is not in obj");
1171     ok(obj[0] === obj2, "obj[0] != obj2");
1173     /* test window object and its global scope handling */
1174     obj = window;
1176     obj.globalprop1 = true;
1177     ok(globalprop1, "globalprop1 = " + globalprop1);
1178     r = false;
1179     try {
1180         delete obj.globalprop1;
1181     }catch(ex) {
1182         r = true;
1183     }
1184     if(v < 9) {
1185         ok(r, "did not get an expected exception");
1186     }else {
1187         ok(!r, "got an unexpected globalprop1 exception");
1188         ok(!("globalprop1" in obj), "globalprop1 is still in obj");
1189     }
1191     globalprop2 = true;
1192     ok(obj.globalprop2, "globalprop2 = " + globalprop2);
1193     r = false;
1194     try {
1195         delete obj.globalprop2;
1196     }catch(ex) {
1197         r = true;
1198     }
1199     if(v < 9) {
1200         ok(r, "did not get an expected globalprop2 exception");
1201     }else {
1202         ok(!r, "got an unexpected exception");
1203         todo_wine.
1204         ok(!("globalprop2" in obj), "globalprop2 is still in obj");
1205     }
1207     obj.globalprop3 = true;
1208     ok(globalprop3, "globalprop3 = " + globalprop3);
1209     r = false;
1210     try {
1211         delete globalprop3;
1212     }catch(ex) {
1213         r = true;
1214     }
1215     if(v < 9) {
1216         ok(r, "did not get an expected exception");
1217         ok("globalprop3" in obj, "globalprop3 is not in obj");
1218     }else {
1219         ok(!r, "got an unexpected globalprop3 exception");
1220         ok(!("globalprop3" in obj), "globalprop3 is still in obj");
1221     }
1223     globalprop4 = true;
1224     ok(obj.globalprop4, "globalprop4 = " + globalprop4);
1225     r = (delete globalprop4);
1226     ok(r, "delete returned " + r);
1227     todo_wine.
1228     ok(!("globalprop4" in obj), "globalprop4 is still in obj");
1231 sync_test("detached arguments", function() {
1232     var args, get_a, set_a, get_x, set_x;
1234     function test_args() {
1235         ok(args[0] === 1, "args[0] = " + args[0]);
1236         set_x(2);
1237         ok(args[0] === 2, "args[0] = " + args[0]);
1238         args[0] = 3;
1239         ok(get_x() === 3, "get_x() = " + get_x());
1240         ok(args[0] === 3, "args[0] = " + args[0]);
1241     }
1243     (function(x) {
1244         args = arguments;
1245         get_x = function() { return x; };
1246         set_x = function(v) { x = v; };
1248         test_args();
1249         x = 1;
1250     })(1);
1251     test_args();
1253     (function(a, a, b, c) {
1254         get_a = function() { return a; }
1255         set_a = function(v) { a = v; }
1256         ok(get_a() === 2, "get_a() = " + get_a());
1257         ok(a === 2, "a = " + a);
1258         ok(b === 3, "b = " + b);
1259         ok(c === 4, "c = " + c);
1260         a = 42;
1261         ok(arguments[0] === 1, "arguments[0] = " + arguments[0]);
1262         ok(arguments[1] === 42, "arguments[1] = " + arguments[1]);
1263         ok(get_a() === 42, "get_a() after assign = " + get_a());
1264         args = arguments;
1265     })(1, 2, 3, 4);
1267     ok(get_a() === 42, "get_a() after detach = " + get_a());
1268     set_a(100);
1269     ok(get_a() === 100, "get_a() after set_a() = " + get_a());
1270     ok(args[0] === 1, "detached args[0] = " + args[0]);
1271     ok(args[1] === 100, "detached args[1] = " + args[1]);
1273     (function(a, a) {
1274         eval("var a = 7;");
1275         ok(a === 7, "function(a, a) a = " + a);
1276         ok(arguments[0] === 5, "function(a, a) arguments[0] = " + arguments[0]);
1277         ok(arguments[1] === 7, "function(a, a) arguments[1] = " + arguments[1]);
1278     })(5, 6);
1281 var func_scope_val = 1;
1282 var func_scope_val2 = 2;
1284 sync_test("func_scope", function() {
1285     var func_scope_val = 2;
1287     var f = function func_scope_val() {
1288         return func_scope_val;
1289     };
1291     func_scope_val = 3;
1292     if(document.documentMode < 9) {
1293         ok(f() === 3, "f() = " + f());
1294         return;
1295     }
1296     ok(f === f(), "f() = " + f());
1298     f = function func_scope_val(a) {
1299         func_scope_val = 4;
1300         return func_scope_val;
1301     };
1303     func_scope_val = 3;
1304     ok(f === f(), "f() = " + f());
1305     ok(func_scope_val === 3, "func_scope_val = " + func_scope_val);
1306     ok(window.func_scope_val === 1, "window.func_scope_val = " + window.func_scope_val);
1308     f = function func_scope_val(a) {
1309         return (function() { return a ? func_scope_val(false) : func_scope_val; })();
1310     };
1312     ok(f === f(true), "f(true) = " + f(true));
1314     window = 1;
1315     ok(window === window.self, "window = " + window);
1317     ! function func_scope_val2() {};
1318     ok(window.func_scope_val2 === 2, "window.func_scope_val2 = " + window.func_scope_val2);
1320     var o = {};
1321     (function(x) {
1322         ok(x === o, "x = " + x);
1323         ! function x() {};
1324         ok(x === o, "x != o");
1325     })(o);
1327     (function(x) {
1328         ok(x === o, "x = " + x);
1329         1, function x() {};
1330         ok(x === o, "x != o");
1331     })(o);
1333     (function() {
1334         ! function x() {};
1335         try {
1336             x();
1337             ok(false, "expected exception");
1338         }catch(e) {}
1339     })(o);
1342 sync_test("set_obj", function() {
1343     if(!("Set" in window)) return;
1345     try {
1346         var s = Set();
1347         ok(false, "expected exception calling constructor as method");
1348     }catch(e) {
1349         ok(e.number === 0xa13fc - 0x80000000, "calling constructor as method threw " + e.number);
1350     }
1352     var s = new Set, r;
1353     ok(Object.getPrototypeOf(s) === Set.prototype, "unexpected Set prototype");
1355     function test_length(name, len) {
1356         ok(Set.prototype[name].length === len, "Set.prototype." + name + " = " + Set.prototype[name].length);
1357         try {
1358             Set.prototype[name].call({}, 0);
1359             ok(false, "expected exception calling Set.prototype." + name + "(object)");
1360         }catch(e) {
1361             ok(e.number === 0xa13fc - 0x80000000, "Set.prototype." + name + "(object) threw " + e.number);
1362         }
1363     }
1364     test_length("add", 1);
1365     test_length("clear", 0);
1366     test_length("delete", 1);
1367     test_length("forEach", 1);
1368     test_length("has", 1);
1369     ok(!("entries" in s), "entries are in Set");
1370     ok(!("keys" in s), "keys are in Set");
1371     ok(!("values" in s), "values are in Set");
1373     r = Object.prototype.toString.call(s);
1374     ok(r === "[object Object]", "toString returned " + r);
1376     r = s.has(-0);
1377     ok(r === false, "has(-0) returned " + r);
1378     ok(s.size === 0, "size = " + s.size);
1380     r = s.add(42);
1381     ok(r === undefined, "add(42) returned " + r);
1382     r = s.add(42);
1383     ok(r === undefined, "add(42) returned " + r);
1384     r = s.add(0);
1385     ok(r === undefined, "add(0) returned " + r);
1386     r = s.has(-0);
1387     ok(r === false, "has(-0) returned " + r);
1388     r = s.add(-0);
1389     ok(r === undefined, "add(-0) returned " + r);
1390     r = s.has(-0);
1391     ok(r === true, "has(-0) after add returned " + r);
1392     r = s.add("test");
1393     ok(r === undefined, "add(test) returned " + r);
1394     r = s.add(13);
1395     ok(r === undefined, "add(13) returned " + r);
1396     r = s.add(s);
1397     ok(r === undefined, "add(s) returned " + r);
1399     r = s["delete"]("test"); /* using s.delete() would break parsing in quirks mode */
1400     ok(r === true, "delete(test) returned " + r);
1401     r = s["delete"]("test");
1402     ok(r === false, "delete(test) returned " + r);
1404     ok(s.size === 5, "size = " + s.size);
1405     s.size = 100;
1406     ok(s.size === 5, "size (after set) = " + s.size);
1408     var a = [];
1409     r = s.forEach(function(value, key, obj) {
1410         var t = s["delete"](key);
1411         ok(t === true, "delete(" + key + ") returned " + r);
1412         ok(value === key, "value = " + value + ", key = " + key);
1413         ok(obj === s, "set = " + obj);
1414         ok(this === a, "this = " + this);
1415         a.push(value);
1416     }, a);
1417     ok(r === undefined, "forEach returned " + r);
1418     ok(a.length === 5, "a.length = " + a.length);
1419     for(var i = 0; i < a.length; i++)
1420         ok(a[i] === [42, 0, -0, 13, s][i], "a[" + i + "] = " + a[i]);
1421     ok(s.size === 0, "size = " + s.size);
1423     s = new Set();
1424     ok(s.size === 0, "size = " + s.size);
1425     s.add(1);
1426     s.add(2);
1427     ok(s.size === 2, "size = " + s.size);
1428     r = s.clear();
1429     ok(r === undefined, "clear returned " + r);
1430     ok(s.size === 0, "size = " + s.size);
1432     s = new Set([1, 2, 3]);
1433     ok(s.size === 0, "size = " + s.size);
1435     s = new Set();
1436     s.add(1);
1437     s.add(2);
1438     s.add(3);
1439     r = 0;
1440     s.forEach(function(value, key, obj) {
1441         r++;
1442         s.clear();
1443         ok(s.size === 0, "size = " + s.size);
1444         ok(this.valueOf() === 42, "this.valueOf() = " + this.valueOf());
1445     }, 42);
1446     ok(r === 1, "r = " + r);
1449 sync_test("map_obj", function() {
1450     if(!("Map" in window)) return;
1452     try {
1453         var s = Map();
1454         ok(false, "expected exception calling constructor as method");
1455     }catch(e) {
1456         ok(e.number === 0xa13fc - 0x80000000, "calling constructor as method threw " + e.number);
1457     }
1459     var s = new Map, r, i;
1460     ok(Object.getPrototypeOf(s) === Map.prototype, "unexpected Map prototype");
1462     function test_length(name, len) {
1463         ok(Map.prototype[name].length === len, "Map.prototype." + name + " = " + Map.prototype[name].length);
1464     }
1465     test_length("clear", 0);
1466     test_length("delete", 1);
1467     test_length("forEach", 1);
1468     test_length("get", 1);
1469     test_length("has", 1);
1470     test_length("set", 2);
1471     ok(!("entries" in s), "entries are in Map");
1472     ok(!("keys" in s), "keys are in Map");
1473     ok(!("values" in s), "values are in Map");
1474     todo_wine.
1475     ok("size" in Map.prototype, "size is not in Map.prototype");
1477     r = Object.prototype.toString.call(s);
1478     ok(r === "[object Object]", "toString returned " + r);
1480     r = s.get("test");
1481     ok(r === undefined, "get(test) returned " + r);
1482     r = s.has("test");
1483     ok(r === false, "has(test) returned " + r);
1484     ok(s.size === 0, "size = " + s.size + " expected 0");
1486     r = s.set("test", 1);
1487     ok(r === undefined, "set returned " + r);
1488     ok(s.size === 1, "size = " + s.size + " expected 1");
1489     r = s.get("test");
1490     ok(r === 1, "get(test) returned " + r);
1491     r = s.has("test");
1492     ok(r === true, "has(test) returned " + r);
1494     s.size = 100;
1495     ok(s.size === 1, "size = " + s.size + " expected 1");
1497     s.set("test", 2);
1498     r = s.get("test");
1499     ok(r === 2, "get(test) returned " + r);
1500     r = s.has("test");
1501     ok(r === true, "has(test) returned " + r);
1503     r = s["delete"]("test"); /* using s.delete() would break parsing in quirks mode */
1504     ok(r === true, "delete(test) returned " + r);
1505     ok(s.size === 0, "size = " + s.size + " expected 0");
1506     r = s["delete"]("test");
1507     ok(r === false, "delete(test) returned " + r);
1509     var test_keys = [undefined, null, NaN, 3, "str", false, true, {}];
1510     for(i in test_keys) {
1511         r = s.set(test_keys[i], test_keys[i] + 1);
1512         ok(r === undefined, "set(test) returned " + r);
1513     }
1514     ok(s.size === test_keys.length, "size = " + s.size + " expected " + test_keys.length);
1515     for(i in test_keys) {
1516         r = s.get(test_keys[i]);
1517         if(isNaN(test_keys[i]))
1518             ok(isNaN(r), "get(" + test_keys[i] + ") returned " + r);
1519         else
1520             ok(r === test_keys[i] + 1, "get(" + test_keys[i] + ") returned " + r);
1521     }
1523     var calls = [];
1524     i = 0;
1525     r = s.forEach(function(value, key, map) {
1526         if(isNaN(test_keys[i])) {
1527             ok(isNaN(key), "key = " + key + " expected NaN");
1528             ok(isNaN(value), "value = " + value + " expected NaN");
1529         }else {
1530             ok(key === test_keys[i], "key = " + key + " expected " + test_keys[i]);
1531             ok(value === key + 1, "value = " + value);
1532         }
1533         ok(map === s, "map = " + map);
1534         ok(this === test_keys, "this = " + this);
1535         i++;
1536     }, test_keys);
1537     ok(i === test_keys.length, "i = " + i);
1538     ok(r === undefined, "forEach returned " + r);
1540     s.set(3, "test2")
1541     calls = [];
1542     i = 0;
1543     s.forEach(function(value, key) {
1544         if(isNaN(test_keys[i]))
1545             ok(isNaN(key), "key = " + key + " expected " + test_keys[i]);
1546         else
1547             ok(key === test_keys[i], "key = " + key + " expected " + test_keys[i]);
1548         i++;
1549     });
1550     ok(i === test_keys.length, "i = " + i);
1552     r = s.clear();
1553     ok(r === undefined, "clear returned " + r);
1554     ok(s.size === 0, "size = " + s.size + " expected 0");
1555     r = s.get(test_keys[0]);
1556     ok(r === undefined, "get returned " + r);
1558     s = new Map();
1559     s.set(1, 10);
1560     s.set(2, 20);
1561     s.set(3, 30);
1562     i = true;
1563     s.forEach(function() {
1564         ok(i, "unexpected call");
1565         s.clear();
1566         i = false;
1567     });
1569     s = new Map();
1570     s.set(1, 10);
1571     s.set(2, 20);
1572     s.set(3, 30);
1573     i = 0;
1574     s.forEach(function(value, key) {
1575         i += key + value;
1576         r = s["delete"](key);
1577         ok(r === true, "delete returned " + r);
1578     });
1579     ok(i === 66, "i = " + i);
1581     s = new Map();
1582     s.set(0,  10);
1583     s.set(-0, 20);
1584     ok(s.size === 2, "size = " + s.size + " expected 2");
1585     r = s.get(-0);
1586     ok(r === 20, "get(-0) returned " + r);
1587     r = s.get(0);
1588     ok(r === 10, "get(0) returned " + r);
1590     try {
1591         Map.prototype.set.call({}, 1, 2);
1592         ok(false, "expected exception");
1593     }catch(e) {
1594         ok(e.number === 0xa13fc - 0x80000000, "e.number = " + e.number);
1595     }
1597     s = new Map();
1598     s.set(1, 10);
1599     s.set(2, 20);
1600     s.set(3, 30);
1601     r = 0;
1602     s.forEach(function(value, key) {
1603         r++;
1604         s.clear();
1605         ok(s.size === 0, "size = " + s.size);
1606         ok(this.valueOf() === 42, "this.valueOf() = " + this.valueOf());
1607     }, 42);
1608     ok(r === 1, "r = " + r);
1611 sync_test("storage", function() {
1612     var v = document.documentMode, i, r, list;
1614     sessionStorage["add-at-end"] = 0;
1615     sessionStorage.removeItem("add-at-end");
1617     sessionStorage.setItem("foobar", "1234");
1618     ok("foobar" in sessionStorage, "foobar not in sessionStorage");
1619     r = sessionStorage.foobar;
1620     ok(r === "1234", "sessionStorage.foobar = " + r);
1621     sessionStorage.barfoo = 4321;
1622     r = sessionStorage.getItem("barfoo");
1623     ok(r === "4321", "sessionStorage.barfoo = " + r);
1624     sessionStorage.setItem("abcd", "blah");
1625     sessionStorage.dcba = "test";
1627     // Order isn't consistent, but changes are reflected during the enumeration.
1628     // Elements that were already traversed in DISPID (even if removed before
1629     // the enumeration) are not enumerated, even if re-added during the enum.
1630     i = 0; list = [ "foobar", "barfoo", "abcd", "dcba" ];
1631     for(r in sessionStorage) {
1632         for(var j = 0; j < list.length; j++)
1633             if(r === list[j])
1634                 break;
1635         ok(j < list.length, "got '" + r + "' enumerating");
1636         list.splice(j, 1);
1637         if(i === 1) {
1638             sessionStorage.removeItem(list[0]);
1639             sessionStorage.setItem("new", "new");
1640             list.splice(0, 1, "new");
1641         }
1642         if(!list.length)
1643             sessionStorage.setItem("add-at-end", "0");
1644         i++;
1645     }
1646     ok(i === 4, "enum did " + i + " iterations");
1648     try {
1649         delete sessionStorage.foobar;
1650         ok(v >= 8, "expected exception deleting sessionStorage.foobar");
1651         ok(!("foobar" in sessionStorage), "foobar in sessionStorage after deletion");
1652         r = sessionStorage.getItem("foobar");
1653         ok(r === null, "sessionStorage.foobar after deletion = " + r);
1654     }catch(e) {
1655         ok(v < 8, "did not expect exception deleting sessionStorage.foobar");
1656         ok(e.number === 0xa01bd - 0x80000000, "deleting sessionStorage.foobar threw = " + e.number);
1657     }
1659     sessionStorage.clear();
1662 async_test("storage events", function() {
1663     var iframe = document.createElement("iframe"), iframe2 = document.createElement("iframe");
1664     var local = false, storage, storage2, v = document.documentMode, i = 0;
1666     var tests = [
1667         function() {
1668             expect();
1669             storage.removeItem("foobar");
1670         },
1671         function() {
1672             expect(0, "foobar", "", "test");
1673             storage.setItem("foobar", "test");
1674         },
1675         function() {
1676             expect(1, "foobar", "test", "TEST", true);
1677             storage2.setItem("foobar", "TEST");
1678         },
1679         function() {
1680             expect(0, "foobar", "TEST", "");
1681             storage.removeItem("foobar");
1682         },
1683         function() {
1684             expect(1, "winetest", "", "WineTest");
1685             storage2.setItem("winetest", "WineTest");
1686         },
1687         function() {
1688             expect(0, "", "", "");
1689             storage.clear();
1690         }
1691     ];
1693     function next() {
1694         if(++i < tests.length)
1695             tests[i]();
1696         else if(local)
1697             next_test();
1698         else {
1699             // w10pro64 testbot VM throws WININET_E_INTERNAL_ERROR for some reason
1700             storage = null, storage2 = null;
1701             try {
1702                 storage = window.localStorage, storage2 = iframe.contentWindow.localStorage;
1703             }catch(e) {
1704                 ok(e.number === 0x72ee4 - 0x80000000, "localStorage threw " + e.number + ": " + e);
1705             }
1706             if(!storage || !storage2) {
1707                 win_skip("localStorage is buggy and not available, skipping");
1708                 next_test();
1709                 return;
1710             }
1711             i = 0, local = true;
1713             if(!storage.length)
1714                 setTimeout(function() { tests[0](); });
1715             else {
1716                 // Get rid of any entries first, since native doesn't update immediately
1717                 var w = [ window, iframe.contentWindow ];
1718                 for(var j = 0; j < w.length; j++)
1719                     w[j].onstorage = w[j].document.onstorage = w[j].document.onstoragecommit = null;
1720                 document.onstoragecommit = function() {
1721                     if(!storage.length)
1722                         setTimeout(function() { tests[0](); });
1723                     else
1724                         storage.clear();
1725                 };
1726                 storage.clear();
1727             }
1728         }
1729     }
1731     function test_event(e, idx, key, oldValue, newValue) {
1732         if(v < 9) {
1733             ok(e === undefined, "event not undefined in legacy mode: " + e);
1734             return;
1735         }
1736         var s = Object.prototype.toString.call(e);
1737         todo_wine.
1738         ok(s === "[object StorageEvent]", "Object.toString = " + s);
1739         ok(e.key === key, "key = " + e.key + ", expected " + key);
1740         ok(e.oldValue === oldValue, "oldValue = " + e.oldValue + ", expected " + oldValue);
1741         ok(e.newValue === newValue, "newValue = " + e.newValue + ", expected " + newValue);
1742         s = (idx ? iframe.contentWindow : window)["location"]["href"].split('#', 1)[0];
1743         ok(e.url === s, "url = " + e.url + ", expected " + s);
1744     }
1746     function expect(idx, key, oldValue, newValue, quirk) {
1747         var window2 = iframe.contentWindow, document2 = window2.document;
1748         window.onstorage = function() { ok(false, "window.onstorage called"); };
1749         document.onstorage = function() { ok(false, "doc.onstorage called"); };
1750         document.onstoragecommit = function() { ok(false, "doc.onstoragecommit called"); };
1751         window2.onstorage = function() { ok(false, "iframe window.onstorage called"); };
1752         document2.onstorage = function() { ok(false, "iframe doc.onstorage called"); };
1753         document2.onstoragecommit = function() { ok(false, "iframe doc.onstoragecommit called"); };
1755         if(idx === undefined) {
1756             setTimeout(function() { next(); });
1757         }else {
1758             // Native sometimes calls this for some reason
1759             if(local && quirk) document.onstoragecommit = null;
1761             (v < 9 ? document2 : window2)["onstorage"] = function(e) {
1762                 (local && idx ? document2 : (local || v < 9 ? document : window))[local ? "onstoragecommit" : "onstorage"] = function(e) {
1763                     test_event(e, idx, local ? "" : key, local ? "" : oldValue, local ? "" : newValue);
1764                     next();
1765                 }
1766                 test_event(e, idx, key, oldValue, newValue);
1767             }
1768         }
1769     }
1771     iframe.onload = function() {
1772         iframe2.onload = function() {
1773             var w = iframe2.contentWindow;
1774             w.onstorage = function() { ok(false, "about:blank window.onstorage called"); };
1775             w.document.onstorage = function() { ok(false, "about:blank document.onstorage called"); };
1776             w.document.onstoragecommit = function() { ok(false, "about:blank document.onstoragecommit called"); };
1778             storage = window.sessionStorage, storage2 = iframe.contentWindow.sessionStorage;
1779             tests[0]();
1780         };
1781         iframe2.src = "about:blank";
1782         document.body.appendChild(iframe2);
1783     };
1784     iframe.src = "blank.html";
1785     document.body.appendChild(iframe);
1788 sync_test("elem_attr", function() {
1789     var v = document.documentMode;
1790     var elem = document.createElement("div"), r;
1792     function test_exposed(prop, expect) {
1793         if(expect)
1794             ok(prop in elem, prop + " is not exposed from elem");
1795         else
1796             ok(!(prop in elem), prop + " is exposed from elem");
1797     }
1799     r = elem.getAttribute("class");
1800     ok(r === null, "class attr = " + r);
1801     r = elem.getAttribute("className");
1802     ok(r === (v < 8 ? "" : null), "className attr = " + r);
1804     elem.className = "cls";
1805     r = elem.getAttribute("class");
1806     ok(r === (v < 8 ? null : "cls"), "class attr = " + r);
1807     r = elem.getAttribute("className");
1808     ok(r === (v < 8 ? "cls" : null), "className attr = " + r);
1810     elem.setAttribute("class", "cls2");
1811     ok(elem.className === (v < 8 ? "cls" : "cls2"), "elem.className = " + elem.className);
1812     r = elem.getAttribute("class");
1813     ok(r === "cls2", "class attr = " + r);
1814     r = elem.getAttribute("className");
1815     ok(r === (v < 8 ? "cls" : null), "className attr = " + r);
1817     elem.setAttribute("className", "cls3");
1818     ok(elem.className === (v < 8 ? "cls3" : "cls2"), "elem.className = " + elem.className);
1819     r = elem.getAttribute("class");
1820     ok(r === "cls2", "class attr = " + r);
1821     r = elem.getAttribute("className");
1822     ok(r === "cls3", "className attr = " + r);
1824     elem.htmlFor = "for";
1825     r = elem.getAttribute("for");
1826     ok(r === null, "for attr = " + r);
1827     r = elem.getAttribute("htmlFor");
1828     ok(r === (v < 9 ? "for" : null), "htmlFor attr = " + r);
1830     elem.setAttribute("for", "for2");
1831     ok(elem.htmlFor === "for", "elem.htmlFor = " + elem.htmlFor);
1832     r = elem.getAttribute("for");
1833     ok(r === "for2", "for attr = " + r);
1834     r = elem.getAttribute("htmlFor");
1835     ok(r === (v < 9 ? "for" : null), "htmlFor attr = " + r);
1837     elem.setAttribute("htmlFor", "for3");
1838     ok(elem.htmlFor === (v < 9 ? "for3" : "for"), "elem.htmlFor = " + elem.htmlFor);
1839     r = elem.getAttribute("for");
1840     ok(r === "for2", "for attr = " + r);
1841     r = elem.getAttribute("htmlFor");
1842     ok(r === "for3", "htmlFor attr = " + r);
1844     elem.setAttribute("testattr", "test", 0, "extra arg", 0xdeadbeef);
1845     test_exposed("class", v < 8);
1846     test_exposed("className", true);
1847     test_exposed("for", v < 9);
1848     test_exposed("htmlFor", true);
1849     test_exposed("testattr", v < 9);
1851     var arr = [3];
1852     elem.setAttribute("testattr", arr);
1853     r = elem.getAttribute("testattr");
1854     ok(r === (v < 8 ? arr : "3"), "testattr = " + r);
1855     ok(elem.testattr === (v < 9 ? arr : undefined), "elem.testattr = " + elem.testattr);
1856     r = elem.removeAttribute("testattr");
1857     ok(r === (v < 9 ? true : undefined), "testattr removeAttribute returned " + r);
1858     ok(elem.testattr === undefined, "removed testattr = " + elem.testattr);
1860     arr[0] = 9;
1861     elem.setAttribute("testattr", "string");
1862     elem.testattr = arr;
1863     r = elem.getAttribute("testattr");
1864     ok(r === (v < 8 ? arr : (v < 9 ? "9" : "string")), "testattr = " + r);
1865     ok(elem.testattr === arr, "elem.testattr = " + elem.testattr);
1866     arr[0] = 3;
1867     r = elem.getAttribute("testattr");
1868     ok(r === (v < 8 ? arr : (v < 9 ? "3" : "string")), "testattr = " + r);
1869     ok(elem.testattr === arr, "elem.testattr = " + elem.testattr);
1870     r = elem.removeAttribute("testattr");
1871     ok(r === (v < 9 ? true : undefined), "testattr removeAttribute returned " + r);
1872     ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr = " + elem.testattr);
1874     arr.toString = function() { return 42; }
1875     elem.testattr = arr;
1876     r = elem.getAttribute("testattr");
1877     ok(r === (v < 8 ? arr : (v < 9 ? "42" : null)), "testattr with custom toString = " + r);
1878     elem.setAttribute("testattr", arr);
1879     r = elem.getAttribute("testattr");
1880     ok(r === (v < 8 ? arr : "42"), "testattr after setAttribute with custom toString = " + r);
1881     ok(elem.testattr === arr, "elem.testattr after setAttribute with custom toString = " + elem.testattr);
1882     r = elem.removeAttribute("testattr");
1883     ok(r === (v < 9 ? true : undefined), "testattr removeAttribute with custom toString returned " + r);
1884     ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr with custom toString = " + elem.testattr);
1886     arr.valueOf = function() { return "arrval"; }
1887     elem.testattr = arr;
1888     r = elem.getAttribute("testattr");
1889     ok(r === (v < 8 ? arr : (v < 9 ? "arrval" : null)), "testattr with custom valueOf = " + r);
1890     elem.setAttribute("testattr", arr);
1891     r = elem.getAttribute("testattr");
1892     ok(r === (v < 8 ? arr : (v < 10 ? "arrval" : "42")), "testattr after setAttribute with custom valueOf = " + r);
1893     ok(elem.testattr === arr, "elem.testattr after setAttribute with custom valueOf = " + elem.testattr);
1894     r = elem.removeAttribute("testattr");
1895     ok(r === (v < 9 ? true : undefined), "testattr removeAttribute with custom valueOf returned " + r);
1896     ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr with custom valueOf = " + elem.testattr);
1898     var func = elem.setAttribute;
1899     try {
1900         func("testattr", arr);
1901         todo_wine_if(v >= 9).
1902         ok(v < 9, "expected exception setting testattr via func");
1903     }catch(ex) {
1904         ok(v >= 9, "did not expect exception setting testattr via func");
1905         elem.setAttribute("testattr", arr);
1906     }
1907     r = elem.getAttribute("testattr");
1908     ok(r === (v < 8 ? arr : (v < 10 ? "arrval" : "42")), "testattr after setAttribute (as func) = " + r);
1909     delete arr.valueOf;
1910     delete arr.toString;
1912     elem.setAttribute("id", arr);
1913     r = elem.getAttribute("id");
1914     todo_wine_if(v >= 8 && v < 10).
1915     ok(r === (v < 8 || v >= 10 ? "3" : "[object]"), "id = " + r);
1916     r = elem.removeAttribute("id");
1917     ok(r === (v < 9 ? true : undefined), "id removeAttribute returned " + r);
1918     ok(elem.id === "", "removed id = " + elem.id);
1920     func = function() { };
1921     elem.onclick = func;
1922     ok(elem.onclick === func, "onclick = " + elem.onclick);
1923     r = elem.getAttribute("onclick");
1924     todo_wine_if(v === 8).
1925     ok(r === (v < 8 ? func : null), "onclick attr = " + r);
1926     r = elem.removeAttribute("onclick");
1927     ok(r === (v < 9 ? false : undefined), "removeAttribute returned " + r);
1928     todo_wine_if(v === 8).
1929     ok(elem.onclick === (v != 8 ? func : null), "removed onclick = " + elem.onclick);
1931     elem.onclick_test = func;
1932     ok(elem.onclick_test === func, "onclick_test = " + elem.onclick_test);
1933     r = elem.getAttribute("onclick_test");
1934     ok(r === (v < 8 ? func : (v < 9 ? func.toString() : null)), "onclick_test attr = " + r);
1936     elem.setAttribute("onclick", "test");
1937     r = elem.getAttribute("onclick");
1938     ok(r === "test", "onclick attr after setAttribute = " + r);
1939     r = elem.removeAttribute("onclick");
1940     ok(r === (v < 9 ? true : undefined), "removeAttribute after setAttribute returned " + r);
1942     /* IE11 returns an empty function, which we can't check directly */
1943     todo_wine_if(v >= 9).
1944     ok((v < 11) ? (elem.onclick === null) : (elem.onclick !== func), "removed onclick after setAttribute = " + elem.onclick);
1946     r = Object.prototype.toString.call(elem.onclick);
1947     todo_wine_if(v >= 9 && v < 11).
1948     ok(r === (v < 9 ? "[object Object]" : (v < 11 ? "[object Null]" : "[object Function]")),
1949         "removed onclick after setAttribute Object.toString returned " + r);
1951     elem.setAttribute("onclick", "string");
1952     r = elem.getAttribute("onclick");
1953     ok(r === "string", "onclick attr after setAttribute = " + r);
1954     elem.onclick = func;
1955     ok(elem.onclick === func, "onclick = " + elem.onclick);
1956     r = elem.getAttribute("onclick");
1957     todo_wine_if(v === 8).
1958     ok(r === (v < 8 ? func : (v < 9 ? null : "string")), "onclick attr = " + r);
1959     elem.onclick = "test";
1960     r = elem.getAttribute("onclick");
1961     ok(r === (v < 9 ? "test" : "string"), "onclick attr = " + r);
1962     r = elem.removeAttribute("onclick");
1963     ok(r === (v < 9 ? true : undefined), "removeAttribute returned " + r);
1964     todo_wine_if(v >= 9).
1965     ok(elem.onclick === null, "removed onclick = " + elem.onclick);
1967     elem.setAttribute("ondblclick", arr);
1968     r = elem.getAttribute("ondblclick");
1969     todo_wine_if(v >= 8 && v < 10).
1970     ok(r === (v < 8 ? arr : (v < 10 ? "[object]" : "3")), "ondblclick = " + r);
1971     r = elem.removeAttribute("ondblclick");
1972     ok(r === (v < 8 ? false : (v < 9 ? true : undefined)), "ondblclick removeAttribute returned " + r);
1973     r = Object.prototype.toString.call(elem.ondblclick);
1974     todo_wine_if(v >= 11).
1975     ok(r === (v < 8 ? "[object Array]" : (v < 9 ? "[object Object]" : (v < 11 ? "[object Null]" : "[object Function]"))),
1976         "removed ondblclick Object.toString returned " + r);
1978     elem.setAttribute("ondblclick", "string");
1979     r = elem.getAttribute("ondblclick");
1980     ok(r === "string", "ondblclick string = " + r);
1981     r = elem.removeAttribute("ondblclick");
1982     ok(r === (v < 9 ? true : undefined), "ondblclick string removeAttribute returned " + r);
1983     ok(elem.ondblclick === null, "removed ondblclick string = " + elem.ondblclick);
1985     if(v < 9) {
1986         /* style is a special case */
1987         try {
1988             elem.style = "opacity: 1.0";
1989             ok(false, "expected exception setting elem.style");
1990         }catch(ex) { }
1992         var style = elem.style;
1993         r = elem.getAttribute("style");
1994         ok(r === (v < 8 ? style : null), "style attr = " + r);
1995         r = elem.removeAttribute("style");
1996         ok(r === true, "removeAttribute('style') returned " + r);
1997         r = elem.style;
1998         ok(r === style, "removed elem.style = " + r);
1999         r = elem.getAttribute("style");
2000         ok(r === (v < 8 ? style : null), "style attr after removal = " + r);
2001         elem.setAttribute("style", "opacity: 1.0");
2002         r = elem.getAttribute("style");
2003         ok(r === (v < 8 ? style : "opacity: 1.0"), "style attr after setAttribute = " + r);
2004         r = elem.style;
2005         ok(r === style, "elem.style after setAttribute = " + r);
2006     }
2009 sync_test("elem_attrNS", function() {
2010     var v = document.documentMode;
2011     if(v < 9) return;  /* not available */
2013     var specialspace_ns = "http://www.mozilla.org/ns/specialspace";
2014     var svg_ns = "http://www.w3.org/2000/svg";
2016     var elem = document.createElement("div"), r;
2018     elem.setAttributeNS(specialspace_ns, "spec:align", "left");
2019     r = elem.hasAttribute("spec:align");
2020     ok(r === true, "spec:align does not exist");
2021     r = elem.getAttribute("spec:align");
2022     ok(r === "left", "spec:align = " + r);
2023     r = elem.hasAttribute("align");
2024     ok(r === false, "align exists");
2025     r = elem.getAttribute("align");
2026     ok(r === null, "align = " + r);
2027     r = elem.hasAttributeNS(null, "spec:align");
2028     ok(r === false, "null spec:align exists");
2029     r = elem.getAttributeNS(null, "spec:align");
2030     ok(r === "", "null spec:align = " + r);
2031     r = elem.hasAttributeNS(null, "spec:align");
2032     ok(r === false, "null align exists");
2033     r = elem.getAttributeNS(null, "align");
2034     ok(r === "", "null align = " + r);
2035     r = elem.hasAttributeNS(svg_ns, "spec:align");
2036     ok(r === false, "svg spec:align exists");
2037     r = elem.getAttributeNS(svg_ns, "spec:align");
2038     ok(r === "", "svg spec:align = " + r);
2039     r = elem.hasAttributeNS(svg_ns, "align");
2040     ok(r === false, "svg align exists");
2041     r = elem.getAttributeNS(svg_ns, "align");
2042     ok(r === "", "svg align = " + r);
2043     r = elem.hasAttributeNS(specialspace_ns, "spec:align");
2044     ok(r === false, "specialspace spec:align exists");
2045     r = elem.getAttributeNS(specialspace_ns, "spec:align");
2046     ok(r === "", "specialspace spec:align = " + r);
2047     r = elem.hasAttributeNS(specialspace_ns, "align");
2048     ok(r === true, "specialspace align does not exist");
2049     r = elem.getAttributeNS(specialspace_ns, "align");
2050     ok(r === "left", "specialspace align = " + r);
2052     try {
2053         elem.setAttributeNS(null, "spec:align", "right");
2054         ok(false, "expected exception setting qualified attr with null ns");
2055     }catch(ex) {
2056         todo_wine.
2057         ok(ex.message === "NamespaceError", "setAttributeNS(null, 'spec:align', 'right') threw " + ex.message);
2058     }
2059     try {
2060         elem.setAttributeNS("", "spec:align", "right");
2061         ok(false, "expected exception setting qualified attr with empty ns");
2062     }catch(ex) {
2063         todo_wine.
2064         ok(ex.message === "NamespaceError", "setAttributeNS('', 'spec:align', 'right') threw " + ex.message);
2065     }
2066     elem.setAttributeNS(null, "align", "right");
2067     r = elem.getAttribute("spec:align");
2068     ok(r === "left", "spec:align (null) = " + r);
2069     r = elem.hasAttribute("align");
2070     ok(r === true, "align (null) does not exist");
2071     r = elem.getAttribute("align");
2072     ok(r === "right", "align (null) = " + r);
2073     r = elem.hasAttributeNS(null, "spec:align");
2074     ok(r === false, "null spec:align exists");
2075     r = elem.getAttributeNS(null, "spec:align");
2076     ok(r === "", "null spec:align (null) = " + r);
2077     r = elem.hasAttributeNS(null, "align");
2078     ok(r === true, "null align does not exist");
2079     r = elem.getAttributeNS(null, "align");
2080     ok(r === "right", "null align (null) = " + r);
2081     r = elem.hasAttributeNS(svg_ns, "spec:align");
2082     ok(r === false, "svg spec:align (null) exists");
2083     r = elem.getAttributeNS(svg_ns, "spec:align");
2084     ok(r === "", "svg spec:align (null) = " + r);
2085     r = elem.hasAttributeNS(svg_ns, "align");
2086     ok(r === false, "svg align (null) exists");
2087     r = elem.getAttributeNS(svg_ns, "align");
2088     ok(r === "", "svg align (null) = " + r);
2089     r = elem.hasAttributeNS(specialspace_ns, "spec:align");
2090     ok(r === false, "specialspace_ns spec:align (null) exists");
2091     r = elem.getAttributeNS(specialspace_ns, "spec:align");
2092     ok(r === "", "specialspace spec:align (null) = " + r);
2093     r = elem.hasAttributeNS(specialspace_ns, "align");
2094     ok(r === true, "specialspace align (null) does not exist");
2095     r = elem.getAttributeNS(specialspace_ns, "align");
2096     ok(r === "left", "specialspace align (null) = " + r);
2098     elem.setAttribute("align", "center");
2099     r = elem.hasAttributeNS(null, "spec:align");
2100     ok(r === false, "null spec:align (non-NS) exists");
2101     r = elem.getAttributeNS(null, "spec:align");
2102     ok(r === "", "null spec:align (non-NS) = " + r);
2103     r = elem.hasAttributeNS(null, "align");
2104     ok(r === true, "null align (non-NS) does not exist");
2105     r = elem.getAttributeNS(null, "align");
2106     ok(r === "center", "null align (non-NS) = " + r);
2107     r = elem.hasAttributeNS(svg_ns, "spec:align");
2108     ok(r === false, "svg spec:align (non-NS) exists");
2109     r = elem.getAttributeNS(svg_ns, "spec:align");
2110     ok(r === "", "svg spec:align (non-NS) = " + r);
2111     r = elem.hasAttributeNS(svg_ns, "align");
2112     ok(r === false, "svg align (non-NS) exists");
2113     r = elem.getAttributeNS(svg_ns, "align");
2114     ok(r === "", "svg align (non-NS) = " + r);
2115     r = elem.hasAttributeNS(specialspace_ns, "spec:align");
2116     ok(r === false, "specialspace spec:align (non-NS) exists");
2117     r = elem.getAttributeNS(specialspace_ns, "spec:align");
2118     ok(r === "", "specialspace spec:align (non-NS) = " + r);
2119     r = elem.hasAttributeNS(specialspace_ns, "align");
2120     ok(r === true, "specialspace align (non-NS) does not exist");
2121     r = elem.getAttributeNS(specialspace_ns, "align");
2122     ok(r === "left", "specialspace align (non-NS) = " + r);
2123     elem.removeAttributeNS(null, "spec:align");
2125     elem.setAttribute("emptynsattr", "none");
2126     elem.setAttributeNS("", "emptynsattr", "test");
2127     r = elem.hasAttribute("emptynsattr");
2128     ok(r === true, "emptynsattr without NS does not exist");
2129     r = elem.getAttribute("emptynsattr");
2130     ok(r === "test", "emptynsattr without NS = " + r);
2131     elem.setAttributeNS(null, "emptynsattr", "wine");
2132     r = elem.hasAttribute("emptynsattr");
2133     ok(r === true, "emptynsattr without NS does not exist");
2134     r = elem.getAttribute("emptynsattr");
2135     ok(r === "wine", "emptynsattr without NS = " + r);
2136     elem.setAttributeNS(specialspace_ns, "emptynsattr", "ns");
2137     r = elem.hasAttribute("emptynsattr");
2138     ok(r === true, "emptynsattr without NS does not exist");
2139     r = elem.getAttribute("emptynsattr");
2140     ok(r === "wine", "emptynsattr without NS = " + r);
2141     r = elem.hasAttributeNS("", "emptynsattr");
2142     ok(r === true, "emptynsattr empty ns does not exist");
2143     r = elem.getAttributeNS("", "emptynsattr");
2144     ok(r === "wine", "emptynsattr empty ns = " + r);
2145     r = elem.hasAttributeNS(null, "emptynsattr");
2146     ok(r === true, "emptynsattr null ns does not exist");
2147     r = elem.getAttributeNS(null, "emptynsattr");
2148     ok(r === "wine", "emptynsattr null ns = " + r);
2149     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
2150     ok(r === true, "emptynsattr specialspace ns does not exist");
2151     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
2152     ok(r === "ns", "emptynsattr specialspace ns = " + r);
2154     elem.removeAttributeNS("", "emptynsattr");
2155     r = elem.hasAttribute("emptynsattr");
2156     ok(r === true, "emptynsattr without NS after remove does not exist");
2157     r = elem.getAttribute("emptynsattr");
2158     ok(r === "ns", "emptynsattr without NS after remove = " + r);
2159     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
2160     ok(r === true, "emptynsattr specialspace ns after empty remove does not exist");
2161     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
2162     ok(r === "ns", "emptynsattr specialspace ns after empty remove = " + r);
2163     elem.setAttribute("emptynsattr", "test");
2164     r = elem.getAttribute("emptynsattr");
2165     ok(r === "test", "emptynsattr without NS after re-set = " + r);
2166     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
2167     ok(r === "test", "emptynsattr specialspace ns after empty re-set = " + r);
2169     elem.removeAttribute("emptynsattr");
2170     r = elem.hasAttribute("emptynsattr");
2171     ok(r === false, "emptynsattr without NS after non-NS remove exists");
2172     r = elem.getAttribute("emptynsattr");
2173     ok(r === null, "emptynsattr without NS after non-NS remove = " + r);
2174     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
2175     ok(r === false, "emptynsattr specialspace ns after non-NS remove exists");
2176     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
2177     ok(r === "", "emptynsattr specialspace ns after non-NS remove = " + r);
2179     elem.setAttributeNS(specialspace_ns, "emptynsattr", "ns");
2180     elem.removeAttributeNS(svg_ns, "emptynsattr");
2181     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
2182     ok(r === true, "emptynsattr specialspace ns after wrong NS remove does not exist");
2183     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
2184     ok(r === "ns", "emptynsattr specialspace ns after wrong NS remove = " + r);
2185     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
2186     ok(r === true, "emptynsattr specialspace ns after remove does not exist");
2187     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
2188     ok(r === "ns", "emptynsattr specialspace ns after remove = " + r);
2190     var ns = {};
2191     ns.toString = function() { return "toString namespace"; }
2192     ns.valueOf = function() { return "valueOf namespace"; }
2193     elem.setAttributeNS(ns, "foobar", "test");
2194     r = elem.hasAttribute("foobar");
2195     ok(r === true, "foobar without NS does not exist");
2196     r = elem.getAttribute("foobar");
2197     ok(r === "test", "foobar without NS = " + r);
2198     r = elem.hasAttributeNS(ns, "foobar");
2199     ok(r === true, "foobar does not exist");
2200     r = elem.getAttributeNS(ns, "foobar");
2201     ok(r === "test", "foobar = " + r);
2202     r = elem.hasAttributeNS("toString namespace", "foobar");
2203     ok(r === (v < 10 ? false : true), "foobar (toString namespace) " + (v < 10 ? "exists" : "does not exist"));
2204     r = elem.getAttributeNS("toString namespace", "foobar");
2205     ok(r === (v < 10 ? "" : "test"), "foobar (toString namespace) = " + r);
2206     r = elem.hasAttributeNS("valueOf namespace", "foobar");
2207     ok(r === (v < 10 ? true : false), "foobar (valueOf namespace) = " + (v < 10 ? "does not exist" : "exists"));
2208     r = elem.getAttributeNS("valueOf namespace", "foobar");
2209     ok(r === (v < 10 ? "test" : ""), "foobar (valueOf namespace) = " + r);
2211     var arr = [3];
2212     elem.setAttributeNS(svg_ns, "testattr", arr);
2213     r = elem.getAttributeNS(svg_ns, "testattr");
2214     ok(r === "3", "testattr = " + r);
2215     ok(elem.testattr === undefined, "elem.testattr = " + elem.testattr);
2216     elem.removeAttributeNS(svg_ns, "testattr");
2217     r = elem.getAttributeNS(svg_ns, "testattr");
2218     ok(r === "", "testattr after remove = " + r);
2220     arr.toString = function() { return 42; }
2221     elem.setAttributeNS(svg_ns, "testattr", arr);
2222     r = elem.getAttributeNS(svg_ns, "testattr");
2223     ok(r === "42", "testattr with custom toString = " + r);
2224     elem.removeAttributeNS(svg_ns, "testattr");
2225     r = elem.getAttributeNS(svg_ns, "testattr");
2226     ok(r === "", "testattr with custom toString after remove = " + r);
2228     arr.valueOf = function() { return "arrval"; }
2229     elem.setAttributeNS(svg_ns, "testattr", arr);
2230     r = elem.getAttributeNS(svg_ns, "testattr");
2231     ok(r === "42", "testattr with custom valueOf = " + r);
2232     elem.removeAttributeNS(svg_ns, "testattr");
2234     elem.setAttributeNS(svg_ns, "boolattr", true);
2235     r = elem.getAttributeNS(svg_ns, "boolattr");
2236     ok(r === "true", "boolattr = " + r);
2238     elem.setAttributeNS(svg_ns, "numattr", 13);
2239     r = elem.getAttributeNS(svg_ns, "numattr");
2240     ok(r === "13", "numattr = " + r);
2243 sync_test("builtins_diffs", function() {
2244     var v = document.documentMode;
2246     /* despite what spec says for ES6, IE still throws */
2247     var props = [
2248         "freeze",
2249         "getPrototypeOf",
2250         "isExtensible",
2251         "isFrozen",
2252         "isSealed",
2253         "keys",
2254         "preventExtensions",
2255         "seal"
2256     ];
2257     for(var i = 0; i < props.length; i++) {
2258         try {
2259             Object[props[i]]("test");
2260             ok(false, "Object." + props[i] + " with non-object: expected exception");
2261         }catch(e) {
2262             ok(e.number === (v < 9 ? 0xa01b6 : 0xa138f) - 0x80000000, "Object." + props[i] + " with non-object: exception = " + e.number);
2263         }
2264     }
2266     try {
2267         RegExp.prototype.toString.call({source: "foo", flags: "g"});
2268         ok(false, "RegExp.toString with non-regexp: expected exception");
2269     }catch(e) {
2270         ok(e.number === 0xa1398 - 0x80000000, "RegExp.toString with non-regexp: exception = " + e.number);
2271     }
2272     try {
2273         RegExp.prototype.toString.call({source: "abc", global: true, ignoreCase: true, multiline: true});
2274         ok(false, "RegExp.toString with non-regexp 2: expected exception");
2275     }catch(e) {
2276         ok(e.number === 0xa1398 - 0x80000000, "RegExp.toString with non-regexp 2: exception = " + e.number);
2277     }
2279     try {
2280         /a/.lastIndex();
2281         ok(false, "/a/.lastIndex(): expected exception");
2282     }catch(e) {
2283         ok(e.number === 0xa138a - 0x80000000, "/a/.lastIndex(): exception = " + e.number);
2284     }
2285     try {
2286         "a".length();
2287         ok(false, "\"a\".length(): expected exception");
2288     }catch(e) {
2289         ok(e.number === 0xa138a - 0x80000000, "\"a\".length(): exception = " + e.number);
2290     }
2293 sync_test("nullDisp", function() {
2294     var v = document.documentMode, nullDisp = external.nullDisp, r;
2296     ok(external.getVT(nullDisp) === "VT_NULL", "getVT(nullDisp) is not VT_NULL");
2297     ok(typeof(nullDisp) === "object", "typeof(nullDisp) = " + typeof(nullDisp));
2298     ok(nullDisp === nullDisp, "nullDisp !== nullDisp");
2299     ok(nullDisp === null, "nullDisp === null");
2300     ok(nullDisp == null, "nullDisp == null");
2301     ok(!nullDisp === true, "!nullDisp = " + !nullDisp);
2302     ok(String(nullDisp) === "null", "String(nullDisp) = " + String(nullDisp));
2303     ok(+nullDisp === 0, "+nullDisp !== 0");
2304     ok(''+nullDisp === "null", "''+nullDisp !== null");
2305     ok(nullDisp != new Object(), "nullDisp == new Object()");
2306     ok(new Object() != nullDisp, "new Object() == nullDisp");
2307     ok((typeof Object(nullDisp)) === "object", "typeof Object(nullDisp) !== 'object'");
2308     r = Object(nullDisp).toString();
2309     ok(r === "[object Object]", "Object(nullDisp).toString() = " + r);
2310     ok(Object(nullDisp) != nullDisp, "Object(nullDisp) == nullDisp");
2311     ok(new Object(nullDisp) != nullDisp, "new Object(nullDisp) == nullDisp");
2312     r = (nullDisp instanceof Object);
2313     ok(r === false, "nullDisp instance of Object");
2315     if(v >= 8) {
2316         r = JSON.stringify.call(null, nullDisp);
2317         ok(r === "null", "JSON.stringify(nullDisp) returned " + r);
2318     }
2320     try {
2321         (new Object()) instanceof nullDisp;
2322         ok(false, "expected exception on (new Object()) instanceof nullDisp");
2323     }catch(e) {
2324         ok(e.number === 0xa138a - 0x80000000, "(new Object()) instanceof nullDisp threw " + e.number);
2325     }
2327     try {
2328         Function.prototype.apply.call(nullDisp, Object, []);
2329         ok(false, "expected exception calling Function.apply on nullDisp");
2330     }catch(e) {
2331         ok(e.number === 0xa138a - 0x80000000, "Function.apply on nullDisp threw " + e.number);
2332     }
2333     try {
2334         Function.prototype.call.call(nullDisp, Object);
2335         ok(false, "expected exception calling Function.call on nullDisp");
2336     }catch(e) {
2337         ok(e.number === 0xa138a - 0x80000000, "Function.call on nullDisp threw " + e.number);
2338     }
2340     try {
2341         new nullDisp;
2342         ok(false, "expected exception for new nullDisp");
2343     }catch(e) {
2344         ok(e.number === 0xa138f - 0x80000000, "new nullDisp threw " + e.number);
2345     }
2348 sync_test("invalid selectors", function() {
2349     var v = document.documentMode, body = document.body, i;
2350     if(v < 8)
2351         return;
2353     var selectors = [
2354         "[s!='']",
2355         "*,:x",
2356         "*,##",
2357         ":x",
2358         "##",
2359         "*,",
2360         ","
2361     ];
2363     for(i = 0; i < selectors.length; i++) {
2364         try {
2365             body.querySelector(selectors[i]);
2366             ok(false, "body.querySelector(\"" + selectors[i] + "\" did not throw exception");
2367         }catch(e) {
2368             if(v < 9)
2369                 ok(e.number === 0x70057 - 0x80000000, "body.querySelector(\"" + selectors[i] + "\" threw " + e.number);
2370             else {
2371                 todo_wine.
2372                 ok(e.name === (v < 10 ? undefined : "SyntaxError"), "body.querySelector(\"" + selectors[i] + "\" threw " + e.name);
2373             }
2374         }
2375         try {
2376             body.querySelectorAll(selectors[i]);
2377             ok(false, "body.querySelectorAll(\"" + selectors[i] + "\" did not throw exception");
2378         }catch(e) {
2379             if(v < 9)
2380                 ok(e.number === 0x70057 - 0x80000000, "body.querySelectorAll(\"" + selectors[i] + "\" threw " + e.number);
2381             else {
2382                 todo_wine.
2383                 ok(e.name === (v < 10 ? undefined : "SyntaxError"), "body.querySelectorAll(\"" + selectors[i] + "\" threw " + e.name);
2384             }
2385         }
2386     }
2388     if(!body.msMatchesSelector)
2389         return;
2391     for(i = 0; i < selectors.length; i++) {
2392         try {
2393             body.msMatchesSelector(selectors[i]);
2394             ok(false, "body.msMatchesSelector(\"" + selectors[i] + "\" did not throw exception");
2395         }catch(e) {
2396             if(v < 9)
2397                 ok(e.number === 0x70057 - 0x80000000, "body.msMatchesSelector(\"" + selectors[i] + "\" threw " + e.number);
2398             else {
2399                 todo_wine.
2400                 ok(e.name === (v < 10 ? undefined : "SyntaxError"), "body.msMatchesSelector(\"" + selectors[i] + "\" threw " + e.name);
2401             }
2402         }
2403     }
2406 sync_test("__proto__", function() {
2407     var v = document.documentMode;
2408     var r, x = 42;
2410     if(v < 11) {
2411         ok(x.__proto__ === undefined, "x.__proto__ = " + x.__proto__);
2412         ok(!("__proto__" in Object), "Object.__proto__ = " + Object.__proto__);
2413         return;
2414     }
2416     ok(x.__proto__ === Number.prototype, "x.__proto__ = " + x.__proto__);
2417     ok(Object.__proto__ === Function.prototype, "Object.__proto__ = " + Object.__proto__);
2418     ok(Object.prototype.__proto__ === null, "Object.prototype.__proto__ = " + Object.prototype.__proto__);
2419     ok(Object.prototype.hasOwnProperty("__proto__"), "__proto__ is not a property of Object.prototype");
2420     ok(!Object.prototype.hasOwnProperty.call(x, "__proto__"), "__proto__ is a property of x");
2422     x.__proto__ = Object.prototype;
2423     ok(x.__proto__ === Number.prototype, "x.__proto__ set to Object.prototype = " + x.__proto__);
2424     ok(!Object.prototype.hasOwnProperty.call(x, "__proto__"), "__proto__ is a property of x after set to Object.prototype");
2425     x = {};
2426     x.__proto__ = null;
2427     r = Object.getPrototypeOf(x);
2428     ok(x.__proto__ === undefined, "x.__proto__ after set to null = " + x.__proto__);
2429     ok(r === null, "getPrototypeOf(x) after set to null = " + r);
2431     function check(expect, msg) {
2432         var r = Object.getPrototypeOf(x);
2433         ok(x.__proto__ === expect, "x.__proto__ " + msg + " = " + x.__proto__);
2434         ok(r === expect, "getPrototypeOf(x) " + msg + " = " + r);
2435         ok(!Object.prototype.hasOwnProperty.call(x, "__proto__"), "__proto__ is a property of x " + msg);
2436     }
2438     x = {};
2439     check(Object.prototype, "after x set to {}");
2440     x.__proto__ = Number.prototype;
2441     check(Number.prototype, "after set to Number.prototype");
2442     x.__proto__ = Object.prototype;
2443     check(Object.prototype, "after re-set to Object.prototype");
2445     function ctor() { }
2446     var obj = new ctor();
2447     x.__proto__ = obj;
2448     check(obj, "after set to obj");
2449     x.__proto__ = ctor.prototype;
2450     check(obj.__proto__, "after set to ctor.prototype");
2451     ok(obj.__proto__ === ctor.prototype, "obj.__proto__ !== ctor.prototype");
2453     r = (delete x.__proto__);
2454     ok(r, "delete x.__proto__ returned " + r);
2455     ok(Object.prototype.hasOwnProperty("__proto__"), "__proto__ is not a property of Object.prototype after delete");
2456     r = Object.getPrototypeOf(x);
2457     ok(r === ctor.prototype, "x.__proto__ after delete = " + r);
2459     var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__");
2460     ok(desc.value === undefined, "__proto__ value = " + desc.value);
2461     ok(Object.getPrototypeOf(desc.get) === Function.prototype, "__proto__ getter not a function");
2462     ok(Object.getPrototypeOf(desc.set) === Function.prototype, "__proto__ setter not a function");
2463     ok(desc.get.length === 0, "__proto__ getter length = " + desc.get.length);
2464     ok(desc.set.length === 1, "__proto__ setter length = " + desc.set.length);
2466     r = desc.get.call(x, 1, 2, 3, 4);
2467     ok(r === x.__proto__, "calling __proto__ getter on x returned " + r);
2469     r = desc.set.call(x, obj);
2470     ok(r === obj, "calling __proto__ setter(obj) on x returned " + r);
2471     check(obj, "after set to obj via calling setter");
2472     r = desc.set.call(x, 42);
2473     ok(r === 42, "calling __proto__ setter(42) on x returned " + r);
2474     check(obj, "after set to obj via calling setter(42)");
2475     r = desc.set.call(x, "foo");
2476     ok(r === "foo", "calling __proto__ setter('foo') on x returned " + r);
2477     check(obj, "after set to obj via calling setter('foo')");
2478     r = desc.set.call(x);
2479     ok(r === undefined, "calling __proto__ setter() on x returned " + r);
2480     r = desc.set.call(true, obj);
2481     ok(r === obj, "calling __proto__ setter(obj) on true value returned " + r);
2482     x = true;
2483     r = desc.set.call(x, obj);
2484     ok(r === obj, "calling __proto__ setter(obj) on x set to true returned " + r);
2485     ok(x.__proto__ === Boolean.prototype, "true value __proto__ after set to obj = " + x.__proto__);
2486     x = new Boolean(true);
2487     r = desc.set.call(x, obj);
2488     ok(r === obj, "calling __proto__ setter(obj) on x set to Boolean(true) returned " + r);
2489     ok(x.__proto__ === obj, "Boolean(true) __proto__ after set to obj = " + x.__proto__);
2491     r = desc.get.call(13);
2492     ok(r === Number.prototype, "calling __proto__ getter on 13 returned " + r);
2493     try {
2494         r = desc.get.call(undefined);
2495         ok(false, "expected exception calling __proto__ getter on undefined");
2496     }catch(e) {
2497         ok(e.number === 0xa138f - 0x80000000, "calling __proto__ getter on undefined threw exception " + e.number);
2498     }
2499     try {
2500         r = desc.get.call(null);
2501         ok(false, "expected exception calling __proto__ getter on null");
2502     }catch(e) {
2503         ok(e.number === 0xa138f - 0x80000000, "calling __proto__ getter on null threw exception " + e.number);
2504     }
2506     try {
2507         r = desc.set.call(undefined, obj);
2508         ok(false, "expected exception calling __proto__ setter on undefined");
2509     }catch(e) {
2510         ok(e.number === 0xa138f - 0x80000000, "calling __proto__ setter on undefined threw exception " + e.number);
2511     }
2512     try {
2513         r = desc.set.call(null, obj);
2514         ok(false, "expected exception calling __proto__ setter on null");
2515     }catch(e) {
2516         ok(e.number === 0xa138f - 0x80000000, "calling __proto__ setter on null threw exception " + e.number);
2517     }
2519     x = {};
2520     r = Object.create(x);
2521     ok(r.__proto__ === x, "r.__proto__ = " + r.__proto__);
2522     r = Object.create(r);
2523     ok(r.__proto__.__proto__ === x, "r.__proto__.__proto__ = " + r.__proto__.__proto__);
2524     try {
2525         x.__proto__ = r;
2526         ok(false, "expected exception setting circular proto chain");
2527     }catch(e) {
2528         ok(e.number === 0xa13b0 - 0x80000000 && e.name === "TypeError",
2529             "setting circular proto chain threw exception " + e.number + " (" + e.name + ")");
2530     }
2532     Object.preventExtensions(x);
2533     x.__proto__ = Object.prototype;  /* same prototype */
2534     try {
2535         x.__proto__ = Number.prototype;
2536         ok(false, "expected exception changing __proto__ on non-extensible object");
2537     }catch(e) {
2538         ok(e.number === 0xa13b6 - 0x80000000 && e.name === "TypeError",
2539             "changing __proto__ on non-extensible object threw exception " + e.number + " (" + e.name + ")");
2540     }
2543 sync_test("__defineGetter__", function() {
2544     var v = document.documentMode;
2545     var r, x = 42;
2547     if(v < 11) {
2548         ok(x.__defineGetter__ === undefined, "x.__defineGetter__ = " + x.__defineGetter__);
2549         ok(!("__defineGetter__" in Object), "Object.__defineGetter__ = " + Object.__defineGetter__);
2550         return;
2551     }
2552     ok(Object.prototype.hasOwnProperty("__defineGetter__"), "__defineGetter__ is not a property of Object.prototype");
2553     ok(Object.prototype.__defineGetter__.length === 2, "__defineGetter__.length = " + Object.prototype.__defineGetter__.length);
2555     function getter() { return "wine"; }
2556     function setter(val) { }
2558     r = x.__defineGetter__("foo", getter);
2559     ok(r === undefined, "__defineGetter__ on 42 returned " + r);
2560     ok(x.foo === undefined, "42.foo = " + x.foo);
2562     x = {};
2563     r = x.__defineGetter__("foo", getter);
2564     ok(r === undefined, "__defineGetter__ returned " + r);
2565     ok(x.foo === "wine", "x.foo = " + x.foo);
2566     r = Object.getOwnPropertyDescriptor(x, "foo");
2567     ok(r.value === undefined, "x.foo value = " + r.value);
2568     ok(r.get === getter, "x.foo get = " + r.get);
2569     ok(r.set === undefined, "x.foo set = " + r.set);
2570     ok(r.writable === undefined, "x.foo writable = " + r.writable);
2571     ok(r.enumerable === true, "x.foo enumerable = " + r.enumerable);
2572     ok(r.configurable === true, "x.foo configurable = " + r.configurable);
2574     Object.defineProperty(x, "foo", { get: undefined, set: setter, configurable: false });
2575     r = Object.getOwnPropertyDescriptor(x, "foo");
2576     ok(r.value === undefined, "x.foo setter value = " + r.value);
2577     ok(r.get === undefined, "x.foo setter get = " + r.get);
2578     ok(r.set === setter, "x.foo setter set = " + r.set);
2579     ok(r.writable === undefined, "x.foo setter writable = " + r.writable);
2580     ok(r.enumerable === true, "x.foo setter enumerable = " + r.enumerable);
2581     ok(r.configurable === false, "x.foo setter configurable = " + r.configurable);
2582     try {
2583         x.__defineGetter__("foo", getter);
2584         ok(false, "expected exception calling __defineGetter__ on non-configurable property");
2585     }catch(e) {
2586         ok(e.number === 0xa13d6 - 0x80000000, "__defineGetter__ on non-configurable property threw exception " + e.number);
2587     }
2589     r = Object.prototype.__defineGetter__.call(undefined, "bar", getter);
2590     ok(r === undefined, "__defineGetter__ on undefined returned " + r);
2591     r = Object.prototype.__defineGetter__.call(null, "bar", getter);
2592     ok(r === undefined, "__defineGetter__ on null returned " + r);
2593     r = x.__defineGetter__(undefined, getter);
2594     ok(r === undefined, "__defineGetter__ undefined prop returned " + r);
2595     ok(x["undefined"] === "wine", "x.undefined = " + x["undefined"]);
2596     r = x.__defineGetter__(false, getter);
2597     ok(r === undefined, "__defineGetter__ undefined prop returned " + r);
2598     ok(x["false"] === "wine", "x.false = " + x["false"]);
2600     try {
2601         x.__defineGetter__("bar", "string");
2602         ok(false, "expected exception calling __defineGetter__ with string");
2603     }catch(e) {
2604         ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with string threw exception " + e.number);
2605     }
2606     try {
2607         x.__defineGetter__("bar", undefined);
2608         ok(false, "expected exception calling __defineGetter__ with undefined");
2609     }catch(e) {
2610         ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with undefined threw exception " + e.number);
2611     }
2612     try {
2613         x.__defineGetter__("bar", null);
2614         ok(false, "expected exception calling __defineGetter__ with null");
2615     }catch(e) {
2616         ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with null threw exception " + e.number);
2617     }
2618     try {
2619         Object.prototype.__defineGetter__.call(x, "bar");
2620         ok(false, "expected exception calling __defineGetter__ with only one arg");
2621     }catch(e) {
2622         ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with only one arg threw exception " + e.number);
2623     }
2625     x.bar = "test";
2626     ok(x.bar === "test", "x.bar = " + x.bar);
2627     x.__defineGetter__("bar", getter);
2628     ok(x.bar === "wine", "x.bar with getter = " + x.bar);
2631 sync_test("__defineSetter__", function() {
2632     var v = document.documentMode;
2633     var r, x = 42;
2635     if(v < 11) {
2636         ok(x.__defineSetter__ === undefined, "x.__defineSetter__ = " + x.__defineSetter__);
2637         ok(!("__defineSetter__" in Object), "Object.__defineSetter__ = " + Object.__defineSetter__);
2638         return;
2639     }
2640     ok(Object.prototype.hasOwnProperty("__defineSetter__"), "__defineSetter__ is not a property of Object.prototype");
2641     ok(Object.prototype.__defineSetter__.length === 2, "__defineSetter__.length = " + Object.prototype.__defineSetter__.length);
2643     function getter() { return "wine"; }
2644     function setter(val) { this.setterVal = val - 1; }
2646     r = x.__defineSetter__("foo", setter);
2647     ok(r === undefined, "__defineSetter__ on 42 returned " + r);
2648     ok(x.foo === undefined, "42.foo = " + x.foo);
2650     x = {};
2651     r = x.__defineSetter__("foo", setter);
2652     ok(r === undefined, "__defineSetter__ returned " + r);
2653     ok(x.setterVal === undefined, "x.setterVal = " + x.setterVal);
2654     x.foo = 13;
2655     ok(x.setterVal === 12, "x.setterVal = " + x.setterVal);
2656     r = Object.getOwnPropertyDescriptor(x, "foo");
2657     ok(r.value === undefined, "x.foo value = " + r.value);
2658     ok(r.get === undefined, "x.foo get = " + r.get);
2659     ok(r.set === setter, "x.foo set = " + r.set);
2660     ok(r.writable === undefined, "x.foo writable = " + r.writable);
2661     ok(r.enumerable === true, "x.foo enumerable = " + r.enumerable);
2662     ok(r.configurable === true, "x.foo configurable = " + r.configurable);
2664     Object.defineProperty(x, "foo", { get: getter, set: undefined, configurable: false });
2665     r = Object.getOwnPropertyDescriptor(x, "foo");
2666     ok(r.value === undefined, "x.foo getter value = " + r.value);
2667     ok(r.get === getter, "x.foo getter get = " + r.get);
2668     ok(r.set === undefined, "x.foo getter set = " + r.set);
2669     ok(r.writable === undefined, "x.foo getter writable = " + r.writable);
2670     ok(r.enumerable === true, "x.foo getter enumerable = " + r.enumerable);
2671     ok(r.configurable === false, "x.foo getter configurable = " + r.configurable);
2672     try {
2673         x.__defineSetter__("foo", setter);
2674         ok(false, "expected exception calling __defineSetter__ on non-configurable property");
2675     }catch(e) {
2676         ok(e.number === 0xa13d6 - 0x80000000, "__defineSetter__ on non-configurable property threw exception " + e.number);
2677     }
2679     r = Object.prototype.__defineSetter__.call(undefined, "bar", setter);
2680     ok(r === undefined, "__defineSetter__ on undefined returned " + r);
2681     r = Object.prototype.__defineSetter__.call(null, "bar", setter);
2682     ok(r === undefined, "__defineSetter__ on null returned " + r);
2683     r = x.__defineSetter__(null, setter);
2684     ok(r === undefined, "__defineSetter__ null prop returned " + r);
2685     x["null"] = 100;
2686     ok(x.setterVal === 99, "x.setterVal after setting x.null = " + x.setterVal);
2687     r = x.__defineSetter__(50, setter);
2688     ok(r === undefined, "__defineSetter__ 50 prop returned " + r);
2689     x["50"] = 33;
2690     ok(x.setterVal === 32, "x.setterVal after setting x.50 = " + x.setterVal);
2692     try {
2693         x.__defineSetter__("bar", true);
2694         ok(false, "expected exception calling __defineSetter__ with bool");
2695     }catch(e) {
2696         ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with bool threw exception " + e.number);
2697     }
2698     try {
2699         x.__defineSetter__("bar", undefined);
2700         ok(false, "expected exception calling __defineSetter__ with undefined");
2701     }catch(e) {
2702         ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with undefined threw exception " + e.number);
2703     }
2704     try {
2705         x.__defineSetter__("bar", null);
2706         ok(false, "expected exception calling __defineSetter__ with null");
2707     }catch(e) {
2708         ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with null threw exception " + e.number);
2709     }
2710     try {
2711         Object.prototype.__defineSetter__.call(x, "bar");
2712         ok(false, "expected exception calling __defineSetter__ with only one arg");
2713     }catch(e) {
2714         ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with only one arg threw exception " + e.number);
2715     }
2717     x.bar = "test";
2718     ok(x.bar === "test", "x.bar = " + x.bar);
2719     x.__defineSetter__("bar", setter);
2720     ok(x.bar === undefined, "x.bar with setter = " + x.bar);
2721     x.bar = 10;
2722     ok(x.bar === undefined, "x.bar with setter = " + x.bar);
2723     ok(x.setterVal === 9, "x.setterVal after setting bar = " + x.setterVal);
2726 async_test("postMessage", function() {
2727     var v = document.documentMode;
2728     var onmessage_called = false;
2729     window.onmessage = function(e) {
2730         onmessage_called = true;
2731         if(v < 9)
2732             ok(e === undefined, "e = " + e);
2733         else {
2734             ok(e.data === (v < 10 ? "10" : 10), "e.data = " + e.data);
2735             next_test();
2736         }
2737     }
2739     var invalid = [
2740         v < 10 ? { toString: function() { return "http://winetest.example.org"; } } : null,
2741         (function() { return "http://winetest.example.org"; }),
2742         "winetest.example.org",
2743         "example.org",
2744         undefined
2745     ];
2746     for(var i = 0; i < invalid.length; i++) {
2747         try {
2748             window.postMessage("invalid " + i, invalid[i]);
2749             ok(false, "expected exception with targetOrigin " + invalid[i]);
2750         }catch(ex) {
2751             var n = ex.number >>> 0;
2752             todo_wine_if(v >= 10).
2753             ok(n === (v < 10 ? 0x80070057 : 0), "postMessage with targetOrigin " + invalid[i] + " threw " + n);
2754             if(v >= 10)
2755                 todo_wine.
2756                 ok(ex.name === "SyntaxError", "postMessage with targetOrigin " + invalid[i] + " threw " + ex.name);
2757         }
2758     }
2759     try {
2760         window.postMessage("invalid empty", "");
2761         ok(false, "expected exception with empty targetOrigin");
2762     }catch(ex) {
2763         var n = ex.number >>> 0;
2764         ok(n === 0x80070057, "postMessage with empty targetOrigin threw " + n);
2765     }
2767     window.postMessage("wrong port", "http://winetest.example.org:1234");
2768     ok(onmessage_called == (v < 9 ? true : false), "onmessage not called with wrong port");
2769     onmessage_called = false;
2771     var not_sent = [
2772         "http://winetest.example.com",
2773         "ftp://winetest.example.org",
2774         "http://wine.example.org",
2775         "http://example.org"
2776     ];
2777     for(var i = 0; i < not_sent.length; i++) {
2778         window.postMessage("not_sent " + i, not_sent[i]);
2779         ok(onmessage_called == false, "onmessage called with targetOrigin " + not_sent[i]);
2780         onmessage_called = false;
2781     }
2783     window.postMessage(10, (v < 10 ? "*" : { toString: function() { return "*"; } }));
2784     ok(onmessage_called == (v < 9 ? true : false), "onmessage not called");
2785     if(v < 9) next_test();