mshtml: Don't create dynamic prop before checking if elem prop even exists.
[wine.git] / dlls / mshtml / tests / documentmode.js
bloba9ff38d5781106373f14c14654c445f22083dae7
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 sync_test("builtin_toString", function() {
23     var tags = [
24         [ "abbr",            "Phrase" ],
25         [ "acronym",         "Phrase" ],
26         [ "address",         "Block" ],
27      // [ "applet",          "Applet" ],  // makes Windows pop up a dialog box
28         [ "article",         "" ],
29         [ "aside",           "" ],
30         [ "audio",           "Audio" ],
31         [ "b",               "Phrase" ],
32         [ "base",            "Base" ],
33         [ "basefont",        "BaseFont" ],
34         [ "bdi",             "Unknown" ],
35         [ "bdo",             "Phrase" ],
36         [ "big",             "Phrase" ],
37         [ "blockquote",      "Block" ],
38         [ "body",            "Body" ],
39         [ "br",              "BR" ],
40         [ "button",          "Button" ],
41         [ "canvas",          "Canvas" ],
42         [ "caption",         "TableCaption" ],
43         [ "center",          "Block" ],
44         [ "cite",            "Phrase" ],
45         [ "code",            "Phrase" ],
46         [ "col",             "TableCol" ],
47         [ "colgroup",        "TableCol" ],
48         [ "data",            "Unknown" ],
49         [ "datalist",        "DataList", 10 ],
50         [ "dd",              "DD" ],
51         [ "del",             "Mod" ],
52         [ "details",         "Unknown" ],
53         [ "dfn",             "Phrase" ],
54         [ "dialog",          "Unknown" ],
55         [ "dir",             "Directory" ],
56         [ "div",             "Div" ],
57         [ "dl",              "DList" ],
58         [ "dt",              "DT" ],
59         [ "em",              "Phrase" ],
60         [ "embed",           "Embed" ],
61         [ "fieldset",        "FieldSet" ],
62         [ "figcaption",      "" ],
63         [ "figure",          "" ],
64         [ "font",            "Font" ],
65         [ "footer",          "" ],
66         [ "form",            "Form" ],
67         [ "frame",           "Frame" ],
68         [ "frameset",        "FrameSet" ],
69         [ "h1",              "Heading" ],
70         [ "h2",              "Heading" ],
71         [ "h3",              "Heading" ],
72         [ "h4",              "Heading" ],
73         [ "h5",              "Heading" ],
74         [ "h6",              "Heading" ],
75         [ "h7",              "Unknown" ],
76         [ "head",            "Head" ],
77         [ "header",          "" ],
78         [ "hr",              "HR" ],
79         [ "html",            "Html" ],
80         [ "i",               "Phrase" ],
81         [ "iframe",          "IFrame" ],
82         [ "img",             "Image" ],
83         [ "input",           "Input" ],
84         [ "ins",             "Mod" ],
85         [ "kbd",             "Phrase" ],
86         [ "label",           "Label" ],
87         [ "legend",          "Legend" ],
88         [ "li",              "LI" ],
89         [ "link",            "Link" ],
90         [ "main",            "Unknown" ],
91         [ "map",             "Map" ],
92         [ "mark",            "" ],
93         [ "meta",            "Meta" ],
94         [ "meter",           "Unknown" ],
95         [ "nav",             "" ],
96         [ "noframes",        "" ],
97         [ "noscript",        "" ],
98         [ "object",          "Object" ],
99         [ "ol",              "OList" ],
100         [ "optgroup",        "OptGroup" ],
101         [ "option",          "Option" ],
102         [ "output",          "Unknown" ],
103         [ "p",               "Paragraph" ],
104         [ "param",           "Param" ],
105         [ "picture",         "Unknown" ],
106         [ "pre",             "Pre" ],
107         [ "progress",        "Progress", 10 ],
108         [ "q",               "Quote" ],
109         [ "rp",              "Phrase" ],
110         [ "rt",              "Phrase" ],
111         [ "ruby",            "Phrase" ],
112         [ "s",               "Phrase" ],
113         [ "samp",            "Phrase" ],
114         [ "script",          "Script" ],
115         [ "section",         "" ],
116         [ "select",          "Select" ],
117         [ "small",           "Phrase" ],
118         [ "source",          "Source" ],
119         [ "span",            "Span" ],
120         [ "strike",          "Phrase" ],
121         [ "strong",          "Phrase" ],
122         [ "style",           "Style" ],
123         [ "sub",             "Phrase" ],
124         [ "summary",         "Unknown" ],
125         [ "sup",             "Phrase" ],
126         [ "svg",             "Unknown" ],
127         [ "table",           "Table" ],
128         [ "tbody",           "TableSection" ],
129         [ "td",              "TableDataCell" ],
130         [ "template",        "Unknown" ],
131         [ "textarea",        "TextArea" ],
132         [ "tfoot",           "TableSection" ],
133         [ "th",              "TableHeaderCell" ],
134         [ "thead",           "TableSection" ],
135         [ "time",            "Unknown" ],
136         [ "title",           "Title" ],
137         [ "tr",              "TableRow" ],
138         [ "track",           "Track", 10 ],
139         [ "tt",              "Phrase" ],
140         [ "u",               "Phrase" ],
141         [ "ul",              "UList" ],
142         [ "var",             "Phrase" ],
143         [ "video",           "Video" ],
144         [ "wbr",             "" ],
145         [ "winetest",        "Unknown" ]
146     ];
147     var v = document.documentMode, e;
149     function test(msg, obj, name, tostr) {
150         var s;
151         if(obj.toString) {
152             s = obj.toString();
153             todo_wine_if(name !== "HTMLElement" && s === "[object HTMLElement]").
154             ok(s === (tostr ? tostr : (v < 9 ? "[object]" : "[object " + name + "]")), msg + " toString returned " + s);
155         }
156         s = Object.prototype.toString.call(obj);
157         todo_wine_if(v >= 9 && name != "Object").
158         ok(s === (v < 9 ? "[object Object]" : "[object " + name + "]"), msg + " Object.toString returned " + s);
159     }
161     for(var i = 0; i < tags.length; i++)
162         if(tags[i].length < 3 || v >= tags[i][2])
163             test("tag '" + tags[i][0] + "'", document.createElement(tags[i][0]), "HTML" + tags[i][1] + "Element");
165     e = document.createElement("a");
166     ok(e.toString() === "", "tag 'a' (without href) toString returned " + e.toString());
167     e.href = "https://www.winehq.org/";
168     test("tag 'a'", e, "HTMLAnchorElement", "https://www.winehq.org/");
170     e = document.createElement("area");
171     ok(e.toString() === "", "tag 'area' (without href) toString returned " + e.toString());
172     e.href = "https://www.winehq.org/";
173     test("tag 'area'", e, "HTMLAreaElement", "https://www.winehq.org/");
175     e = document.createElement("style");
176     document.body.appendChild(e);
177     var sheet = v >= 9 ? e.sheet : e.styleSheet;
178     if(v >= 9)
179         sheet.insertRule("div { border: none }", 0);
180     else
181         sheet.addRule("div", "border: none", 0);
183     e = document.createElement("p");
184     e.className = "testclass    another ";
185     e.textContent = "Test content";
186     e.style.border = "1px solid black";
187     document.body.appendChild(e);
189     var txtRange = document.body.createTextRange();
190     txtRange.moveToElementText(e);
192     var clientRects = e.getClientRects();
193     if(!clientRects) win_skip("getClientRects() is buggy and not available, skipping");
195     var currentStyle = e.currentStyle;
196     if(!currentStyle) win_skip("currentStyle is buggy and not available, skipping");
198     // w10pro64 testbot VM throws WININET_E_INTERNAL_ERROR for some reason
199     var localStorage;
200     try {
201         localStorage = window.localStorage;
202     }catch(e) {
203         ok(e.number === 0x72ee4 - 0x80000000, "localStorage threw " + e.number + ": " + e);
204     }
205     if(!localStorage) win_skip("localStorage is buggy and not available, skipping");
207     test("attribute", document.createAttribute("class"), "Attr");
208     if(false /* todo_wine */) test("attributes", e.attributes, "NamedNodeMap");
209     test("childNodes", document.body.childNodes, "NodeList");
210     if(clientRects) test("clientRect", clientRects[0], "ClientRect");
211     if(clientRects) test("clientRects", clientRects, "ClientRectList");
212     if(currentStyle) test("currentStyle", currentStyle, "MSCurrentStyleCSSProperties");
213     if(v >= 11 /* todo_wine */) test("document", document, v < 11 ? "Document" : "HTMLDocument");
214     test("elements", document.getElementsByTagName("body"), "HTMLCollection");
215     test("history", window.history, "History");
216     test("implementation", document.implementation, "DOMImplementation");
217     if(localStorage) test("localStorage", localStorage, "Storage");
218     test("location", window.location, "Object", window.location.href);
219     if(v >= 11 /* todo_wine */) test("mimeTypes", window.navigator.mimeTypes, v < 11 ? "MSMimeTypesCollection" : "MimeTypeArray");
220     test("navigator", window.navigator, "Navigator");
221     test("performance", window.performance, "Performance");
222     test("performanceNavigation", window.performance.navigation, "PerformanceNavigation");
223     test("performanceTiming", window.performance.timing, "PerformanceTiming");
224     if(v >= 11 /* todo_wine */) test("plugins", window.navigator.plugins, v < 11 ? "MSPluginsCollection" : "PluginArray");
225     test("screen", window.screen, "Screen");
226     test("sessionStorage", window.sessionStorage, "Storage");
227     test("style", document.body.style, "MSStyleCSSProperties");
228     test("styleSheet", sheet, "CSSStyleSheet");
229     test("styleSheetRule", sheet.rules[0], "CSSStyleRule");
230     test("styleSheetRules", sheet.rules, "MSCSSRuleList");
231     test("styleSheets", document.styleSheets, "StyleSheetList");
232     test("textNode", document.createTextNode("testNode"), "Text", v < 9 ? "testNode" : null);
233     test("textRange", txtRange, "TextRange");
234     test("window", window, "Window", "[object Window]");
235     test("xmlHttpRequest", new XMLHttpRequest(), "XMLHttpRequest");
236     if(v < 10) {
237         test("namespaces", document.namespaces, "MSNamespaceInfoCollection");
238     }
239     if(v < 11) {
240         test("eventObject", document.createEventObject(), "MSEventObj");
241         test("selection", document.selection, "MSSelection");
242     }
243     if(v >= 9) {
244         test("computedStyle", window.getComputedStyle(e), "CSSStyleDeclaration");
245         test("doctype", document.doctype, "DocumentType");
247         test("Event", document.createEvent("Event"), "Event");
248         test("CustomEvent", document.createEvent("CustomEvent"), "CustomEvent");
249         test("KeyboardEvent", document.createEvent("KeyboardEvent"), "KeyboardEvent");
250         test("MouseEvent", document.createEvent("MouseEvent"), "MouseEvent");
251         test("UIEvent", document.createEvent("UIEvent"), "UIEvent");
252     }
253     if(v >= 10) {
254         test("classList", e.classList, "DOMTokenList", "testclass    another ");
255         test("console", window.console, "Console");
256         test("mediaQueryList", window.matchMedia("(hover:hover)"), "MediaQueryList");
257     }
258     if(v >= 9) {
259         document.body.innerHTML = "<!--...-->";
260         test("comment", document.body.firstChild, "Comment");
261     }
264 sync_test("elem_props", function() {
265     var elem = document.documentElement;
267     function test_exposed(prop, expect) {
268         if(expect)
269             ok(prop in elem, prop + " not found in element.");
270         else
271             ok(!(prop in elem), prop + " found in element.");
272     }
274     var v = document.documentMode;
276     test_exposed("doScroll", v < 11);
277     test_exposed("readyState", v < 11);
278     test_exposed("clientTop", true);
279     test_exposed("title", true);
280     test_exposed("querySelectorAll", v >= 8);
281     test_exposed("textContent", v >= 9);
282     test_exposed("prefix", v >= 9);
283     test_exposed("firstElementChild", v >= 9);
284     test_exposed("onsubmit", v >= 9);
285     test_exposed("getElementsByClassName", v >= 9);
286     test_exposed("removeAttributeNS", v >= 9);
287     test_exposed("addEventListener", v >= 9);
288     if (v != 8 /* todo_wine */) test_exposed("hasAttribute", v >= 8);
289     test_exposed("removeEventListener", v >= 9);
290     test_exposed("dispatchEvent", v >= 9);
291     test_exposed("msSetPointerCapture", v >= 10);
292     if (v >= 9) test_exposed("spellcheck", v >= 10);
294     elem = document.createElement("style");
295     test_exposed("media", true);
296     test_exposed("type", true);
297     test_exposed("disabled", true);
298     test_exposed("media", true);
299     test_exposed("sheet", v >= 9);
300     test_exposed("readyState", v < 11);
301     test_exposed("styleSheet", v < 11);
302     test_exposed("classList", v >= 10);
305 sync_test("doc_props", function() {
306     function test_exposed(prop, expect) {
307         if(expect)
308             ok(prop in document, prop + " not found in document.");
309         else
310             ok(!(prop in document), prop + " found in document.");
311     }
313     var v = document.documentMode;
315     test_exposed("onstorage", v < 9);
316     test_exposed("textContent", v >= 9);
317     test_exposed("prefix", v >= 9);
318     test_exposed("defaultView", v >= 9);
319     test_exposed("head", v >= 9);
320     test_exposed("addEventListener", v >= 9);
321     test_exposed("removeEventListener", v >= 9);
322     test_exposed("dispatchEvent", v >= 9);
323     test_exposed("createEvent", v >= 9);
325     test_exposed("parentWindow", true);
326     if(v >= 9) ok(document.defaultView === document.parentWindow, "defaultView != parentWindow");
329 sync_test("docfrag_props", function() {
330     var docfrag = document.createDocumentFragment();
332     function test_exposed(prop, expect) {
333         if(expect)
334             ok(prop in docfrag, prop + " not found in document fragent.");
335         else
336             ok(!(prop in docfrag), prop + " found in document fragent.");
337     }
339     var v = document.documentMode;
341     test_exposed("compareDocumentPosition", v >= 9);
344 sync_test("window_props", function() {
345     function test_exposed(prop, expect) {
346         if(expect)
347             ok(prop in window, prop + " not found in window.");
348         else
349             ok(!(prop in window), prop + " found in window.");
350     }
352     var v = document.documentMode;
354     test_exposed("postMessage", true);
355     test_exposed("sessionStorage", true);
356     test_exposed("localStorage", true);
357     test_exposed("addEventListener", v >= 9);
358     test_exposed("removeEventListener", v >= 9);
359     test_exposed("dispatchEvent", v >= 9);
360     test_exposed("getSelection", v >= 9);
361     test_exposed("onfocusout", v >= 9);
362     test_exposed("getComputedStyle", v >= 9);
363     test_exposed("cancelAnimationFrame", v >= 10);
364     test_exposed("requestAnimationFrame", v >= 10);
365     test_exposed("Map", v >= 11);
366     test_exposed("Set", v >= 11);
367     test_exposed("performance", true);
368     test_exposed("console", v >= 10);
369     test_exposed("matchMedia", v >= 10);
372 sync_test("domimpl_props", function() {
373     var domimpl = document.implementation;
374     function test_exposed(prop, expect) {
375         if(expect)
376             ok(prop in domimpl, prop + " not found in DOMImplementation.");
377         else
378             ok(!(prop in domimpl), prop + " found in DOMImplementation.");
379     }
381     var v = document.documentMode;
383     test_exposed("hasFeature", true);
384     test_exposed("createDocument", v >= 9);
385     test_exposed("createDocumentType", v >= 9);
386     test_exposed("createHTMLDocument", v >= 9);
389 sync_test("xhr_props", function() {
390     var xhr = new XMLHttpRequest();
392     function test_exposed(prop, expect) {
393         if(expect)
394             ok(prop in xhr, prop + " not found in XMLHttpRequest.");
395         else
396             ok(!(prop in xhr), prop + " found in XMLHttpRequest.");
397     }
399     var v = document.documentMode;
401     test_exposed("addEventListener", v >= 9);
402     test_exposed("removeEventListener", v >= 9);
403     test_exposed("dispatchEvent", v >= 9);
404     test_exposed("onabort", v >= 10);
405     test_exposed("onerror", v >= 10);
406     test_exposed("onloadend", v >= 10);
407     test_exposed("onloadstart", v >= 10);
408     test_exposed("onprogress", v >= 10);
409     test_exposed("ontimeout", true);
410     test_exposed("overrideMimeType", v >= 11);
411     test_exposed("response", v >= 10);
412     test_exposed("responseType", v >= 10);
413     test_exposed("timeout", true);
414     test_exposed("upload", v >= 10);
415     test_exposed("withCredentials", v >= 10);
418 sync_test("stylesheet_props", function() {
419     var v = document.documentMode;
420     var elem = document.createElement("style");
421     document.body.appendChild(elem);
422     var sheet = v >= 9 ? elem.sheet : elem.styleSheet;
424     function test_exposed(prop, expect) {
425         if(expect)
426             ok(prop in sheet, prop + " not found in style sheet.");
427         else
428             ok(!(prop in sheet), prop + " found in style sheet.");
429     }
431     test_exposed("href", true);
432     test_exposed("title", true);
433     test_exposed("type", true);
434     test_exposed("media", true);
435     test_exposed("ownerNode", v >= 9);
436     test_exposed("ownerRule", v >= 9);
437     test_exposed("cssRules", v >= 9);
438     test_exposed("insertRule", v >= 9);
439     test_exposed("deleteRule", v >= 9);
440     test_exposed("disabled", true);
441     test_exposed("parentStyleSheet", true);
442     test_exposed("owningElement", true);
443     test_exposed("readOnly", true);
444     test_exposed("imports", true);
445     test_exposed("id", true);
446     test_exposed("addImport", true);
447     test_exposed("addRule", true);
448     test_exposed("removeImport", true);
449     test_exposed("removeRule", true);
450     test_exposed("cssText", true);
451     test_exposed("rules", true);
454 sync_test("xhr open", function() {
455     var e = false;
456     try {
457         (new XMLHttpRequest()).open("GET", "https://www.winehq.org/");
458     }catch(ex) {
459         e = true;
460     }
462     if(document.documentMode < 10)
463         ok(e, "expected exception");
464     else
465         ok(!e, "unexpected exception");
468 sync_test("style_props", function() {
469     var style = document.body.style;
471     function test_exposed(prop, expect) {
472         if(expect)
473             ok(prop in style, prop + " not found in style object.");
474         else
475             ok(!(prop in style), prop + " found in style object.");
476     }
478     var v = document.documentMode;
480     test_exposed("removeAttribute", true);
481     test_exposed("zIndex", true);
482     test_exposed("z-index", true);
483     test_exposed("filter", true);
484     test_exposed("pixelTop", true);
485     test_exposed("float", true);
486     test_exposed("css-float", false);
487     test_exposed("style-float", false);
488     test_exposed("setProperty", v >= 9);
489     test_exposed("removeProperty", v >= 9);
490     test_exposed("background-clip", v >= 9);
491     test_exposed("msTransform", v >= 9);
492     test_exposed("transform", v >= 10);
494     style = document.body.currentStyle;
496     test_exposed("zIndex", true);
497     test_exposed("z-index", true);
498     test_exposed("filter", true);
499     test_exposed("pixelTop", false);
500     test_exposed("float", true);
501     test_exposed("css-float", false);
502     test_exposed("style-float", false);
503     test_exposed("setProperty", v >= 9);
504     test_exposed("removeProperty", v >= 9);
505     test_exposed("background-clip", v >= 9);
506     test_exposed("transform", v >= 10);
508     if(window.getComputedStyle) {
509         style = window.getComputedStyle(document.body);
511         test_exposed("removeAttribute", false);
512         test_exposed("zIndex", true);
513         test_exposed("z-index", true);
514         test_exposed("pixelTop", false);
515         test_exposed("float", true);
516         test_exposed("css-float", false);
517         test_exposed("style-float", false);
518         test_exposed("setProperty", v >= 9);
519         test_exposed("removeProperty", v >= 9);
520         test_exposed("background-clip", v >= 9);
521         test_exposed("transform", v >= 10);
522     }
525 sync_test("createElement_inline_attr", function() {
526     var v = document.documentMode, e, s;
528     if(v < 9) {
529         s = document.createElement("<div>").tagName;
530         ok(s === "DIV", "<div>.tagName returned " + s);
531         s = document.createElement("<div >").tagName;
532         ok(s === "DIV", "<div >.tagName returned " + s);
533         s = document.createElement("<div/>").tagName;
534         ok(s === "DIV", "<div/>.tagName returned " + s);
535         e = 0;
536         try {
537             document.createElement("<div");
538         }catch(ex) {
539             e = ex.number;
540         }
541         ok(e === 0x4005 - 0x80000000, "<div e = " + e);
542         e = 0;
543         try {
544             document.createElement("<div test=1");
545         }catch(ex) {
546             e = ex.number;
547         }
548         ok(e === 0x4005 - 0x80000000, "<div test=1 e = " + e);
550         var tags = [ "div", "head", "body", "title", "html" ];
552         for(var i = 0; i < tags.length; i++) {
553             e = document.createElement("<" + tags[i] + " test='a\"' abcd=\"&quot;b&#34;\">");
554             ok(e.tagName === tags[i].toUpperCase(), "<" + tags[i] + " test=\"a\" abcd=\"b\">.tagName returned " + e.tagName);
555             ok(e.test === "a\"", "<" + tags[i] + " test='a\"' abcd=\"&quot;b&#34;\">.test returned " + e.test);
556             ok(e.abcd === "\"b\"", "<" + tags[i] + " test='a\"' abcd=\"&quot;b&#34;\">.abcd returned " + e.abcd);
557         }
558     }else {
559         s = "";
560         e = 0;
561         try {
562             document.createElement("<div>");
563         }catch(ex) {
564             s = ex.toString();
565             e = ex.number;
566         }
567         todo_wine.
568         ok(e === undefined, "<div> e = " + e);
569         todo_wine.
570         ok(s === "InvalidCharacterError", "<div> s = " + s);
571         s = "";
572         e = 0;
573         try {
574             document.createElement("<div test=\"a\">");
575         }catch(ex) {
576             s = ex.toString();
577             e = ex.number;
578         }
579         todo_wine.
580         ok(e === undefined, "<div test=\"a\"> e = " + e);
581         todo_wine.
582         ok(s === "InvalidCharacterError", "<div test=\"a\"> s = " + s);
583     }
586 sync_test("JS objs", function() {
587     var g = window;
589     function test_exposed(func, obj, expect) {
590         if(expect)
591             ok(func in obj, func + " not found in " + obj);
592         else
593             ok(!(func in obj), func + " found in " + obj);
594     }
596     function test_parses(code, expect) {
597         var success;
598         try {
599             eval(code);
600             success = true;
601         }catch(e) {
602             success = false;
603         }
604         if(expect)
605             ok(success === true, code + " did not parse");
606         else
607             ok(success === false, code + " parsed");
608     }
610     var v = document.documentMode;
612     test_exposed("ScriptEngineMajorVersion", g, true);
614     test_exposed("JSON", g, v >= 8);
615     test_exposed("now", Date, true);
616     test_exposed("toISOString", Date.prototype, v >= 9);
617     test_exposed("isArray", Array, v >= 9);
618     test_exposed("forEach", Array.prototype, v >= 9);
619     test_exposed("indexOf", Array.prototype, v >= 9);
620     test_exposed("trim", String.prototype, v >= 9);
621     test_exposed("map", Array.prototype, v >= 9);
623     /* FIXME: IE8 implements weird semi-functional property descriptors. */
624     if(v != 8) {
625         test_exposed("getOwnPropertyDescriptor", Object, v >= 8);
626         test_exposed("defineProperty", Object, v >= 8);
627         test_exposed("defineProperties", Object, v >= 8);
628     }
630     test_exposed("getPrototypeOf", Object, v >= 9);
632     test_parses("if(false) { o.default; }", v >= 9);
633     test_parses("if(false) { o.with; }", v >= 9);
634     test_parses("if(false) { o.if; }", v >= 9);
637 sync_test("for..in", function() {
638     var v = document.documentMode, found = 0, r;
640     function ctor() {}
641     ctor.prototype.test2 = true;
643     var arr = new Array(), obj = new ctor(), i, r;
644     obj.test1 = true;
646     i = 0;
647     for(r in obj) {
648         ctor.prototype.test3 = true;
649         arr[r] = true;
650         i++;
651     }
653     ok(i === 3, "enum did " + i + " iterations");
654     ok(arr["test1"] === true, "arr[test1] !== true");
655     ok(arr["test2"] === true, "arr[test2] !== true");
656     ok(arr["test3"] === true, "arr[test3] !== true");
658     for(r in document)
659         if(r === "ondragstart")
660             found++;
661     ok(found === 1, "ondragstart enumerated " + found + " times in document");
662     document.ondragstart = "";
663     found = 0;
664     for(r in document)
665         if(r === "ondragstart")
666             found++;
667     ok(found === 1, "ondragstart enumerated " + found + " times in document after set to empty string");
670 sync_test("elem_by_id", function() {
671     document.body.innerHTML = '<form id="testid" name="testname"></form>';
672     var v = document.documentMode, found, i;
674     var id_elem = document.getElementById("testid");
675     ok(id_elem.tagName === "FORM", "id_elem.tagName = " + id_elem.tagName);
677     var name_elem = document.getElementById("testname");
678     if(v < 8)
679         ok(id_elem === name_elem, "id_elem != id_elem");
680     else
681         ok(name_elem === null, "name_elem != null");
683     id_elem = window.testid;
684     ok(id_elem.tagName === "FORM", "window.testid = " + id_elem);
686     name_elem = document.testname;
687     ok(name_elem.tagName === "FORM", "document.testname = " + name_elem);
689     for(id_elem in window)
690         ok(id_elem !== "testid" && id_elem != "testname", id_elem + " was enumerated in window");
691     window.testid = 137;
692     found = false;
693     for(id_elem in window) {
694         ok(id_elem != "testname", id_elem + " was enumerated in window after set to 137");
695         if(id_elem === "testid")
696             found = true;
697     }
698     ok(found, "testid was not enumerated in window after set to 137");
700     found = false;
701     for(id_elem in document) {
702         ok(id_elem !== "testid", "testid was enumerated in document");
703         if(id_elem === "testname")
704             found = true;
705     }
706     ok(found, "testname was not enumerated in document");
708     try {
709         document.testname();
710         ok(false, "document.testname() did not throw exception");
711     }catch(e) {
712         ok(e.number === 0xa01b6 - 0x80000000, "document.testname() threw = " + e.number);
713     }
715     try {
716         document.testname = "foo";
717         ok(v >= 9, "Setting document.testname did not throw exception");
719         id_elem = document.testid;
720         ok(id_elem.tagName === "FORM", "document.testid after set = " + id_elem);
721         name_elem = document.testname;
722         ok(name_elem === "foo", "document.testname after set = " + name_elem);
723     }catch(e) {
724         todo_wine_if(v >= 9).
725         ok(v < 9 && e.number === 0xa01b6 - 0x80000000, "Setting document.testname threw = " + e.number);
726     }
728     try {
729         document.testid = "bar";
730         ok(v >= 9, "Setting document.testid did not throw exception");
732         id_elem = document.testid;
733         ok(id_elem === "bar", "document.testid after both set = " + id_elem);
734         name_elem = document.testname;
735         ok(name_elem === "foo", "document.testname after both set = " + name_elem);
737         found = false, name_elem = false;
738         for(id_elem in document) {
739             if(id_elem === "testid")
740                 found = true;
741             if(id_elem === "testname")
742                 name_elem = true;
743         }
744         ok(found, "testid was not enumerated in document after both set");
745         ok(name_elem, "testname was not enumerated in document after both set");
746         delete document.testid;
747         delete document.testname;
748     }catch(e) {
749         todo_wine_if(v >= 9).
750         ok(v < 9 && e.number === 0xa01b6 - 0x80000000, "Setting document.testid threw = " + e.number);
751     }
753     // these tags expose name as props, and id only if they have a name
754     var tags = [ "embed", "form", "iframe", "img" ];
755     for(i in tags) {
756         var tag = tags[i];
757         document.body.innerHTML = '<' + tag + ' id="testid" name="testname"></' + tag + '><' + tag + ' id="foobar"></' + tag + '>';
758         ok("testname" in document, tag + " did not expose testname");
759         ok("testid" in document, tag + " did not expose testid");
760         ok(!("foobar" in document), tag + " exposed foobar");
761     }
763     // these tags always expose their id as well as name (we don't test applet because it makes Windows pop up a dialog box)
764     tags = [ "object" ];
765     for(i in tags) {
766         var tag = tags[i];
767         document.body.innerHTML = '<' + tag + ' id="testid" name="testname"></' + tag + '><' + tag + ' id="foobar"></' + tag + '>';
768         ok("testname" in document, tag + " did not expose testname");
769         ok("testid" in document, tag + " did not expose testid");
770         ok("foobar" in document, tag + " did not expose foobar");
771     }
773     // all other tags don't expose props for either id or name, test a few of them here
774     tags = [ "a", "b", "body", "center", "div", "frame", "h2", "head", "html", "input", "meta", "p", "span", "style", "table", "winetest" ];
775     for(i in tags) {
776         var tag = tags[i];
777         document.body.innerHTML = '<' + tag + ' id="testid" name="testname"></' + tag + '><' + tag + ' id="foobar"></' + tag + '>';
778         ok(!("testname" in document), tag + " exposed testname");
779         ok(!("testid" in document), tag + " exposed testid");
780         ok(!("foobar" in document), tag + " exposed foobar");
781     }
784 sync_test("doc_mode", function() {
785     compat_version = parseInt(document.location.search.substring(1));
787     trace("Testing compatibility mode " + compat_version);
789     if(compat_version > 6 && compat_version > document.documentMode) {
790         win_skip("Document mode not supported (expected " + compat_version + " got " + document.documentMode + ")");
791         reportSuccess();
792         return;
793     }
795     ok(Math.max(compat_version, 5) === document.documentMode, "documentMode = " + document.documentMode);
797     if(document.documentMode > 5)
798         ok(document.compatMode === "CSS1Compat", "document.compatMode = " + document.compatMode);
799     else
800         ok(document.compatMode === "BackCompat", "document.compatMode = " + document.compatMode);
803 sync_test("doctype", function() {
804     var doctype = document.doctype;
806     if(document.documentMode < 9) {
807         ok(doctype === null, "doctype = " + document.doctype);
808         return;
809     }
811     ok(doctype.name === "html", "doctype.name = " + doctype.name);
814 async_test("iframe_doc_mode", function() {
815     var iframe = document.createElement("iframe");
817     iframe.onload = function() {
818         var iframe_mode = iframe.contentWindow.document.documentMode;
819         if(document.documentMode < 9)
820             ok(iframe_mode === 5, "iframe_mode = " + iframe_mode);
821         else
822             ok(iframe_mode === document.documentMode, "iframe_mode = " + iframe_mode);
823         next_test();
824     }
826     iframe.src = "about:blank";
827     document.body.appendChild(iframe);
830 sync_test("conditional_comments", function() {
831     var div = document.createElement("div");
832     document.body.appendChild(div);
834     function test_version(v) {
835         var version = compat_version ? compat_version : 7;
837         div.innerHTML = "<!--[if lte IE " + v + "]>true<![endif]-->";
838         ok(div.innerText === (version <= v ? "true" : ""),
839            "div.innerText = " + div.innerText + " for version (<=) " + v);
841         div.innerHTML = "<!--[if lt IE " + v + "]>true<![endif]-->";
842         ok(div.innerText === (version < v ? "true" : ""),
843            "div.innerText = " + div.innerText + " for version (<) " + v);
845         div.innerHTML = "<!--[if gte IE " + v + "]>true<![endif]-->";
846         ok(div.innerText === (version >= v && version < 10 ? "true" : ""),
847            "div.innerText = " + div.innerText + " for version (>=) " + v);
849         div.innerHTML = "<!--[if gt IE " + v + "]>true<![endif]-->";
850         ok(div.innerText === (version > v && version < 10 ? "true" : ""),
851            "div.innerText = " + div.innerText + " for version (>) " + v);
852     }
854     test_version(5);
855     test_version(6);
856     test_version(7);
857     test_version(8);
860 var ready_states;
862 async_test("script_load", function() {
863     var v = document.documentMode;
864     if(v < 9) {
865         next_test();
866         return;
867     }
869     var elem = document.createElement("script");
870     ready_states = "";
872     elem.onreadystatechange = guard(function() {
873         ok(v < 11, "unexpected onreadystatechange call");
874         ready_states += elem.readyState + ",";
875     });
877     elem.onload = guard(function() {
878         switch(v) {
879         case 9:
880             ok(ready_states === "loading,exec,loaded,", "ready_states = " + ready_states);
881             break;
882         case 10:
883             ok(ready_states === "loading,exec,", "ready_states = " + ready_states);
884             break;
885         case 11:
886             ok(ready_states === "exec,", "ready_states = " + ready_states);
887             break;
888         }
889         next_test();
890     });
892     document.body.appendChild(elem);
893     elem.src = "jsstream.php?simple";
894     external.writeStream("simple", "ready_states += 'exec,';");
897 sync_test("navigator", function() {
898     var v = document.documentMode, re;
899     var app = navigator.appVersion;
900     ok(navigator.userAgent === "Mozilla/" + app,
901        "userAgent = " + navigator.userAgent + " appVersion = " + app);
903     re = v < 11
904         ? "^" + (v < 9 ? "4" : "5") + "\\.0 \\(compatible; MSIE " + (v < 7 ? 7 : v) +
905           "\\.0; Windows NT [0-9].[0-9]; .*Trident/[678]\\.0.*\\)$"
906         : "^5.0 \\(Windows NT [0-9].[0-9]; .*Trident/[678]\\.0.*rv:11.0\\) like Gecko$";
907     ok(new RegExp(re).test(app), "appVersion = " + app);
909     ok(navigator.appCodeName === "Mozilla", "appCodeName = " + navigator.appCodeName);
910     ok(navigator.appName === (v < 11 ? "Microsoft Internet Explorer" : "Netscape"),
911        "appName = " + navigator.appName);
912     ok(navigator.toString() === (v < 9 ? "[object]" : "[object Navigator]"),
913        "navigator.toString() = " + navigator.toString());
916 sync_test("delete_prop", function() {
917     var v = document.documentMode;
918     var obj = document.createElement("div"), r, obj2;
920     obj.prop1 = true;
921     r = false;
922     try {
923         delete obj.prop1;
924     }catch(ex) {
925         r = true;
926     }
927     if(v < 8) {
928         ok(r, "did not get an expected exception");
929         return;
930     }
931     ok(!r, "got an unexpected exception");
932     ok(!("prop1" in obj), "prop1 is still in obj");
934     /* again, this time prop1 does not exist */
935     r = false;
936     try {
937         delete obj.prop1;
938     }catch(ex) {
939         r = true;
940     }
941     if(v < 9) {
942         ok(r, "did not get an expected exception");
943         return;
944     }else {
945         ok(!r, "got an unexpected exception");
946         ok(!("prop1" in obj), "prop1 is still in obj");
947     }
949     r = (delete obj.className);
950     ok(r, "delete returned " + r);
951     ok("className" in obj, "className deleted from obj");
952     ok(obj.className === "", "className = " + obj.className);
954     /* builtin propertiles don't throw any exception, but are not really deleted */
955     r = (delete obj.tagName);
956     ok(r, "delete returned " + r);
957     ok("tagName" in obj, "tagName deleted from obj");
958     ok(obj.tagName === "DIV", "tagName = " + obj.tagName);
960     obj = document.querySelectorAll("*");
961     ok("0" in obj, "0 is not in obj");
962     obj2 = obj[0];
963     r = (delete obj[0]);
964     ok("0" in obj, "0 is not in obj");
965     ok(obj[0] === obj2, "obj[0] != obj2");
967     /* test window object and its global scope handling */
968     obj = window;
970     obj.globalprop1 = true;
971     ok(globalprop1, "globalprop1 = " + globalprop1);
972     r = false;
973     try {
974         delete obj.globalprop1;
975     }catch(ex) {
976         r = true;
977     }
978     if(v < 9) {
979         ok(r, "did not get an expected exception");
980     }else {
981         ok(!r, "got an unexpected globalprop1 exception");
982         ok(!("globalprop1" in obj), "globalprop1 is still in obj");
983     }
985     globalprop2 = true;
986     ok(obj.globalprop2, "globalprop2 = " + globalprop2);
987     r = false;
988     try {
989         delete obj.globalprop2;
990     }catch(ex) {
991         r = true;
992     }
993     if(v < 9) {
994         ok(r, "did not get an expected globalprop2 exception");
995     }else {
996         ok(!r, "got an unexpected exception");
997         todo_wine.
998         ok(!("globalprop2" in obj), "globalprop2 is still in obj");
999     }
1001     obj.globalprop3 = true;
1002     ok(globalprop3, "globalprop3 = " + globalprop3);
1003     r = false;
1004     try {
1005         delete globalprop3;
1006     }catch(ex) {
1007         r = true;
1008     }
1009     if(v < 9) {
1010         ok(r, "did not get an expected exception");
1011         ok("globalprop3" in obj, "globalprop3 is not in obj");
1012     }else {
1013         ok(!r, "got an unexpected globalprop3 exception");
1014         ok(!("globalprop3" in obj), "globalprop3 is still in obj");
1015     }
1017     globalprop4 = true;
1018     ok(obj.globalprop4, "globalprop4 = " + globalprop4);
1019     r = (delete globalprop4);
1020     ok(r, "delete returned " + r);
1021     todo_wine.
1022     ok(!("globalprop4" in obj), "globalprop4 is still in obj");
1025 var func_scope_val = 1;
1026 var func_scope_val2 = 2;
1028 sync_test("func_scope", function() {
1029     var func_scope_val = 2;
1031     var f = function func_scope_val() {
1032         return func_scope_val;
1033     };
1035     func_scope_val = 3;
1036     if(document.documentMode < 9) {
1037         ok(f() === 3, "f() = " + f());
1038         return;
1039     }
1040     ok(f === f(), "f() = " + f());
1042     f = function func_scope_val(a) {
1043         func_scope_val = 4;
1044         return func_scope_val;
1045     };
1047     func_scope_val = 3;
1048     ok(f === f(), "f() = " + f());
1049     ok(func_scope_val === 3, "func_scope_val = " + func_scope_val);
1050     ok(window.func_scope_val === 1, "window.func_scope_val = " + window.func_scope_val);
1052     f = function func_scope_val(a) {
1053         return (function() { return a ? func_scope_val(false) : func_scope_val; })();
1054     };
1056     ok(f === f(true), "f(true) = " + f(true));
1058     window = 1;
1059     ok(window === window.self, "window = " + window);
1061     ! function func_scope_val2() {};
1062     ok(window.func_scope_val2 === 2, "window.func_scope_val2 = " + window.func_scope_val2);
1064     var o = {};
1065     (function(x) {
1066         ok(x === o, "x = " + x);
1067         ! function x() {};
1068         ok(x === o, "x != o");
1069     })(o);
1071     (function(x) {
1072         ok(x === o, "x = " + x);
1073         1, function x() {};
1074         ok(x === o, "x != o");
1075     })(o);
1077     (function() {
1078         ! function x() {};
1079         try {
1080             x();
1081             ok(false, "expected exception");
1082         }catch(e) {}
1083     })(o);
1086 sync_test("set_obj", function() {
1087     if(!("Set" in window)) return;
1089     var s = new Set, r;
1090     ok(Object.getPrototypeOf(s) === Set.prototype, "unexpected Set prototype");
1092     function test_length(name, len) {
1093         ok(Set.prototype[name].length === len, "Set.prototype." + name + " = " + Set.prototype[name].length);
1094         try {
1095             Set.prototype[name].call({}, 0);
1096             ok(false, "expected exception calling Set.prototype." + name + "(object)");
1097         }catch(e) {
1098             ok(e.number === 0xa13fc - 0x80000000, "Set.prototype." + name + "(object) threw " + e.number);
1099         }
1100     }
1101     test_length("add", 1);
1102     test_length("clear", 0);
1103     test_length("delete", 1);
1104     test_length("forEach", 1);
1105     test_length("has", 1);
1106     ok(!("entries" in s), "entries are in Set");
1107     ok(!("keys" in s), "keys are in Set");
1108     ok(!("values" in s), "values are in Set");
1110     r = Object.prototype.toString.call(s);
1111     ok(r === "[object Object]", "toString returned " + r);
1113     r = s.has(-0);
1114     ok(r === false, "has(-0) returned " + r);
1115     ok(s.size === 0, "size = " + s.size);
1117     r = s.add(42);
1118     ok(r === undefined, "add(42) returned " + r);
1119     r = s.add(42);
1120     ok(r === undefined, "add(42) returned " + r);
1121     r = s.add(0);
1122     ok(r === undefined, "add(0) returned " + r);
1123     r = s.has(-0);
1124     ok(r === false, "has(-0) returned " + r);
1125     r = s.add(-0);
1126     ok(r === undefined, "add(-0) returned " + r);
1127     r = s.has(-0);
1128     ok(r === true, "has(-0) after add returned " + r);
1129     r = s.add("test");
1130     ok(r === undefined, "add(test) returned " + r);
1131     r = s.add(13);
1132     ok(r === undefined, "add(13) returned " + r);
1133     r = s.add(s);
1134     ok(r === undefined, "add(s) returned " + r);
1136     r = s["delete"]("test"); /* using s.delete() would break parsing in quirks mode */
1137     ok(r === true, "delete(test) returned " + r);
1138     r = s["delete"]("test");
1139     ok(r === false, "delete(test) returned " + r);
1141     ok(s.size === 5, "size = " + s.size);
1142     s.size = 100;
1143     ok(s.size === 5, "size (after set) = " + s.size);
1145     var a = [];
1146     r = s.forEach(function(value, key, obj) {
1147         var t = s["delete"](key);
1148         ok(t === true, "delete(" + key + ") returned " + r);
1149         ok(value === key, "value = " + value + ", key = " + key);
1150         ok(obj === s, "set = " + obj);
1151         ok(this === a, "this = " + this);
1152         a.push(value);
1153     }, a);
1154     ok(r === undefined, "forEach returned " + r);
1155     ok(a.length === 5, "a.length = " + a.length);
1156     for(var i = 0; i < a.length; i++)
1157         ok(a[i] === [42, 0, -0, 13, s][i], "a[" + i + "] = " + a[i]);
1158     ok(s.size === 0, "size = " + s.size);
1160     s = new Set();
1161     ok(s.size === 0, "size = " + s.size);
1162     s.add(1);
1163     s.add(2);
1164     ok(s.size === 2, "size = " + s.size);
1165     r = s.clear();
1166     ok(r === undefined, "clear returned " + r);
1167     ok(s.size === 0, "size = " + s.size);
1169     s = new Set([1, 2, 3]);
1170     ok(s.size === 0, "size = " + s.size);
1172     s = new Set();
1173     s.add(1);
1174     s.add(2);
1175     s.add(3);
1176     r = 0;
1177     s.forEach(function(value, key, obj) {
1178         r++;
1179         s.clear();
1180         ok(s.size === 0, "size = " + s.size);
1181     });
1182     ok(r === 1, "r = " + r);
1185 sync_test("map_obj", function() {
1186     if(!("Map" in window)) return;
1188     var s = new Map, r, i;
1189     ok(Object.getPrototypeOf(s) === Map.prototype, "unexpected Map prototype");
1191     function test_length(name, len) {
1192         ok(Map.prototype[name].length === len, "Map.prototype." + name + " = " + Map.prototype[name].length);
1193     }
1194     test_length("clear", 0);
1195     test_length("delete", 1);
1196     test_length("forEach", 1);
1197     test_length("get", 1);
1198     test_length("has", 1);
1199     test_length("set", 2);
1200     ok(!("entries" in s), "entries are in Map");
1201     ok(!("keys" in s), "keys are in Map");
1202     ok(!("values" in s), "values are in Map");
1203     todo_wine.
1204     ok("size" in Map.prototype, "size is not in Map.prototype");
1206     r = Object.prototype.toString.call(s);
1207     ok(r === "[object Object]", "toString returned " + r);
1209     r = s.get("test");
1210     ok(r === undefined, "get(test) returned " + r);
1211     r = s.has("test");
1212     ok(r === false, "has(test) returned " + r);
1213     ok(s.size === 0, "size = " + s.size + " expected 0");
1215     r = s.set("test", 1);
1216     ok(r === undefined, "set returned " + r);
1217     ok(s.size === 1, "size = " + s.size + " expected 1");
1218     r = s.get("test");
1219     ok(r === 1, "get(test) returned " + r);
1220     r = s.has("test");
1221     ok(r === true, "has(test) returned " + r);
1223     s.size = 100;
1224     ok(s.size === 1, "size = " + s.size + " expected 1");
1226     s.set("test", 2);
1227     r = s.get("test");
1228     ok(r === 2, "get(test) returned " + r);
1229     r = s.has("test");
1230     ok(r === true, "has(test) returned " + r);
1232     r = s["delete"]("test"); /* using s.delete() would break parsing in quirks mode */
1233     ok(r === true, "delete(test) returned " + r);
1234     ok(s.size === 0, "size = " + s.size + " expected 0");
1235     r = s["delete"]("test");
1236     ok(r === false, "delete(test) returned " + r);
1238     var test_keys = [undefined, null, NaN, 3, "str", false, true, {}];
1239     for(i in test_keys) {
1240         r = s.set(test_keys[i], test_keys[i] + 1);
1241         ok(r === undefined, "set(test) returned " + r);
1242     }
1243     ok(s.size === test_keys.length, "size = " + s.size + " expected " + test_keys.length);
1244     for(i in test_keys) {
1245         r = s.get(test_keys[i]);
1246         if(isNaN(test_keys[i]))
1247             ok(isNaN(r), "get(" + test_keys[i] + ") returned " + r);
1248         else
1249             ok(r === test_keys[i] + 1, "get(" + test_keys[i] + ") returned " + r);
1250     }
1252     var calls = [];
1253     i = 0;
1254     r = s.forEach(function(value, key, map) {
1255         if(isNaN(test_keys[i])) {
1256             ok(isNaN(key), "key = " + key + " expected NaN");
1257             ok(isNaN(value), "value = " + value + " expected NaN");
1258         }else {
1259             ok(key === test_keys[i], "key = " + key + " expected " + test_keys[i]);
1260             ok(value === key + 1, "value = " + value);
1261         }
1262         ok(map === s, "map = " + map);
1263         ok(this === test_keys, "this = " + this);
1264         i++;
1265     }, test_keys);
1266     ok(i === test_keys.length, "i = " + i);
1267     ok(r === undefined, "forEach returned " + r);
1269     s.set(3, "test2")
1270     calls = [];
1271     i = 0;
1272     s.forEach(function(value, key) {
1273         if(isNaN(test_keys[i]))
1274             ok(isNaN(key), "key = " + key + " expected " + test_keys[i]);
1275         else
1276             ok(key === test_keys[i], "key = " + key + " expected " + test_keys[i]);
1277         i++;
1278     });
1279     ok(i === test_keys.length, "i = " + i);
1281     r = s.clear();
1282     ok(r === undefined, "clear returned " + r);
1283     ok(s.size === 0, "size = " + s.size + " expected 0");
1284     r = s.get(test_keys[0]);
1285     ok(r === undefined, "get returned " + r);
1287     s = new Map();
1288     s.set(1, 10);
1289     s.set(2, 20);
1290     s.set(3, 30);
1291     i = true;
1292     s.forEach(function() {
1293         ok(i, "unexpected call");
1294         s.clear();
1295         i = false;
1296     });
1298     s = new Map();
1299     s.set(1, 10);
1300     s.set(2, 20);
1301     s.set(3, 30);
1302     i = 0;
1303     s.forEach(function(value, key) {
1304         i += key + value;
1305         r = s["delete"](key);
1306         ok(r === true, "delete returned " + r);
1307     });
1308     ok(i === 66, "i = " + i);
1310     s = new Map();
1311     s.set(0,  10);
1312     s.set(-0, 20);
1313     ok(s.size === 2, "size = " + s.size + " expected 2");
1314     r = s.get(-0);
1315     ok(r === 20, "get(-0) returned " + r);
1316     r = s.get(0);
1317     ok(r === 10, "get(0) returned " + r);
1319     try {
1320         Map.prototype.set.call({}, 1, 2);
1321         ok(false, "expected exception");
1322     }catch(e) {
1323         ok(e.number === 0xa13fc - 0x80000000, "e.number = " + e.number);
1324     }
1326     s = new Map();
1327     s.set(1, 10);
1328     s.set(2, 20);
1329     s.set(3, 30);
1330     r = 0;
1331     s.forEach(function(value, key) {
1332         r++;
1333         s.clear();
1334         ok(s.size === 0, "size = " + s.size);
1335     });
1336     ok(r === 1, "r = " + r);
1339 sync_test("storage", function() {
1340     var v = document.documentMode, i, r, list;
1342     sessionStorage["add-at-end"] = 0;
1343     sessionStorage.removeItem("add-at-end");
1345     sessionStorage.setItem("foobar", "1234");
1346     ok("foobar" in sessionStorage, "foobar not in sessionStorage");
1347     r = sessionStorage.foobar;
1348     ok(r === "1234", "sessionStorage.foobar = " + r);
1349     sessionStorage.barfoo = 4321;
1350     r = sessionStorage.getItem("barfoo");
1351     ok(r === "4321", "sessionStorage.barfoo = " + r);
1352     sessionStorage.setItem("abcd", "blah");
1353     sessionStorage.dcba = "test";
1355     // Order isn't consistent, but changes are reflected during the enumeration.
1356     // Elements that were already traversed in DISPID (even if removed before
1357     // the enumeration) are not enumerated, even if re-added during the enum.
1358     i = 0; list = [ "foobar", "barfoo", "abcd", "dcba" ];
1359     for(r in sessionStorage) {
1360         for(var j = 0; j < list.length; j++)
1361             if(r === list[j])
1362                 break;
1363         ok(j < list.length, "got '" + r + "' enumerating");
1364         list.splice(j, 1);
1365         if(i === 1) {
1366             sessionStorage.removeItem(list[0]);
1367             sessionStorage.setItem("new", "new");
1368             list.splice(0, 1, "new");
1369         }
1370         if(!list.length)
1371             sessionStorage.setItem("add-at-end", "0");
1372         i++;
1373     }
1374     ok(i === 4, "enum did " + i + " iterations");
1376     try {
1377         delete sessionStorage.foobar;
1378         ok(v >= 8, "expected exception deleting sessionStorage.foobar");
1379         ok(!("foobar" in sessionStorage), "foobar in sessionStorage after deletion");
1380         r = sessionStorage.getItem("foobar");
1381         ok(r === null, "sessionStorage.foobar after deletion = " + r);
1382     }catch(e) {
1383         ok(v < 8, "did not expect exception deleting sessionStorage.foobar");
1384         ok(e.number === 0xa01bd - 0x80000000, "deleting sessionStorage.foobar threw = " + e.number);
1385     }
1387     sessionStorage.clear();
1390 async_test("storage events", function() {
1391     var iframe = document.createElement("iframe"), iframe2 = document.createElement("iframe");
1392     var local = false, storage, storage2, v = document.documentMode, i = 0;
1394     var tests = [
1395         function() {
1396             expect();
1397             storage.removeItem("foobar");
1398         },
1399         function() {
1400             expect(0, "foobar", "", "test");
1401             storage.setItem("foobar", "test");
1402         },
1403         function() {
1404             expect(1, "foobar", "test", "TEST", true);
1405             storage2.setItem("foobar", "TEST");
1406         },
1407         function() {
1408             expect(0, "foobar", "TEST", "");
1409             storage.removeItem("foobar");
1410         },
1411         function() {
1412             expect(1, "winetest", "", "WineTest");
1413             storage2.setItem("winetest", "WineTest");
1414         },
1415         function() {
1416             expect(0, "", "", "");
1417             storage.clear();
1418         }
1419     ];
1421     function next() {
1422         if(++i < tests.length)
1423             tests[i]();
1424         else if(local)
1425             next_test();
1426         else {
1427             // w10pro64 testbot VM throws WININET_E_INTERNAL_ERROR for some reason
1428             storage = null, storage2 = null;
1429             try {
1430                 storage = window.localStorage, storage2 = iframe.contentWindow.localStorage;
1431             }catch(e) {
1432                 ok(e.number === 0x72ee4 - 0x80000000, "localStorage threw " + e.number + ": " + e);
1433             }
1434             if(!storage || !storage2) {
1435                 win_skip("localStorage is buggy and not available, skipping");
1436                 next_test();
1437                 return;
1438             }
1439             i = 0, local = true;
1441             if(!storage.length)
1442                 setTimeout(function() { tests[0](); });
1443             else {
1444                 // Get rid of any entries first, since native doesn't update immediately
1445                 var w = [ window, iframe.contentWindow ];
1446                 for(var j = 0; j < w.length; j++)
1447                     w[j].onstorage = w[j].document.onstorage = w[j].document.onstoragecommit = null;
1448                 document.onstoragecommit = function() {
1449                     if(!storage.length)
1450                         setTimeout(function() { tests[0](); });
1451                     else
1452                         storage.clear();
1453                 };
1454                 storage.clear();
1455             }
1456         }
1457     }
1459     function test_event(e, idx, key, oldValue, newValue) {
1460         if(v < 9) {
1461             ok(e === undefined, "event not undefined in legacy mode: " + e);
1462             return;
1463         }
1464         var s = Object.prototype.toString.call(e);
1465         todo_wine.
1466         ok(s === "[object StorageEvent]", "Object.toString = " + s);
1467         ok(e.key === key, "key = " + e.key + ", expected " + key);
1468         ok(e.oldValue === oldValue, "oldValue = " + e.oldValue + ", expected " + oldValue);
1469         ok(e.newValue === newValue, "newValue = " + e.newValue + ", expected " + newValue);
1470         s = (idx ? iframe.contentWindow : window)["location"]["href"];
1471         ok(e.url === s, "url = " + e.url + ", expected " + s);
1472     }
1474     function expect(idx, key, oldValue, newValue, quirk) {
1475         var window2 = iframe.contentWindow, document2 = window2.document;
1476         window.onstorage = function() { ok(false, "window.onstorage called"); };
1477         document.onstorage = function() { ok(false, "doc.onstorage called"); };
1478         document.onstoragecommit = function() { ok(false, "doc.onstoragecommit called"); };
1479         window2.onstorage = function() { ok(false, "iframe window.onstorage called"); };
1480         document2.onstorage = function() { ok(false, "iframe doc.onstorage called"); };
1481         document2.onstoragecommit = function() { ok(false, "iframe doc.onstoragecommit called"); };
1483         if(idx === undefined) {
1484             setTimeout(function() { next(); });
1485         }else {
1486             // Native sometimes calls this for some reason
1487             if(local && quirk) document.onstoragecommit = null;
1489             (v < 9 ? document2 : window2)["onstorage"] = function(e) {
1490                 (local && idx ? document2 : (local || v < 9 ? document : window))[local ? "onstoragecommit" : "onstorage"] = function(e) {
1491                     test_event(e, idx, local ? "" : key, local ? "" : oldValue, local ? "" : newValue);
1492                     next();
1493                 }
1494                 test_event(e, idx, key, oldValue, newValue);
1495             }
1496         }
1497     }
1499     iframe.onload = function() {
1500         iframe2.onload = function() {
1501             var w = iframe2.contentWindow;
1502             w.onstorage = function() { ok(false, "about:blank window.onstorage called"); };
1503             w.document.onstorage = function() { ok(false, "about:blank document.onstorage called"); };
1504             w.document.onstoragecommit = function() { ok(false, "about:blank document.onstoragecommit called"); };
1506             storage = window.sessionStorage, storage2 = iframe.contentWindow.sessionStorage;
1507             tests[0]();
1508         };
1509         iframe2.src = "about:blank";
1510         document.body.appendChild(iframe2);
1511     };
1512     iframe.src = "blank.html";
1513     document.body.appendChild(iframe);
1516 sync_test("elem_attr", function() {
1517     var v = document.documentMode;
1518     var elem = document.createElement("div"), r;
1520     function test_exposed(prop, expect) {
1521         if(expect)
1522             ok(prop in elem, prop + " is not exposed from elem");
1523         else
1524             ok(!(prop in elem), prop + " is exposed from elem");
1525     }
1527     r = elem.getAttribute("class");
1528     ok(r === null, "class attr = " + r);
1529     r = elem.getAttribute("className");
1530     ok(r === (v < 8 ? "" : null), "className attr = " + r);
1532     elem.className = "cls";
1533     r = elem.getAttribute("class");
1534     ok(r === (v < 8 ? null : "cls"), "class attr = " + r);
1535     r = elem.getAttribute("className");
1536     ok(r === (v < 8 ? "cls" : null), "className attr = " + r);
1538     elem.setAttribute("class", "cls2");
1539     ok(elem.className === (v < 8 ? "cls" : "cls2"), "elem.className = " + elem.className);
1540     r = elem.getAttribute("class");
1541     ok(r === "cls2", "class attr = " + r);
1542     r = elem.getAttribute("className");
1543     ok(r === (v < 8 ? "cls" : null), "className attr = " + r);
1545     elem.setAttribute("className", "cls3");
1546     ok(elem.className === (v < 8 ? "cls3" : "cls2"), "elem.className = " + elem.className);
1547     r = elem.getAttribute("class");
1548     ok(r === "cls2", "class attr = " + r);
1549     r = elem.getAttribute("className");
1550     ok(r === "cls3", "className attr = " + r);
1552     elem.htmlFor = "for";
1553     r = elem.getAttribute("for");
1554     ok(r === null, "for attr = " + r);
1555     r = elem.getAttribute("htmlFor");
1556     ok(r === (v < 9 ? "for" : null), "htmlFor attr = " + r);
1558     elem.setAttribute("for", "for2");
1559     ok(elem.htmlFor === "for", "elem.htmlFor = " + elem.htmlFor);
1560     r = elem.getAttribute("for");
1561     ok(r === "for2", "for attr = " + r);
1562     r = elem.getAttribute("htmlFor");
1563     ok(r === (v < 9 ? "for" : null), "htmlFor attr = " + r);
1565     elem.setAttribute("htmlFor", "for3");
1566     ok(elem.htmlFor === (v < 9 ? "for3" : "for"), "elem.htmlFor = " + elem.htmlFor);
1567     r = elem.getAttribute("for");
1568     ok(r === "for2", "for attr = " + r);
1569     r = elem.getAttribute("htmlFor");
1570     ok(r === "for3", "htmlFor attr = " + r);
1572     elem.setAttribute("testattr", "test", 0, "extra arg", 0xdeadbeef);
1573     test_exposed("class", v < 8);
1574     test_exposed("className", true);
1575     test_exposed("for", v < 9);
1576     test_exposed("htmlFor", true);
1577     test_exposed("testattr", v < 9);
1579     var arr = [3];
1580     elem.setAttribute("testattr", arr);
1581     r = elem.getAttribute("testattr");
1582     ok(r === (v < 8 ? arr : "3"), "testattr = " + r);
1583     ok(elem.testattr === (v < 9 ? arr : undefined), "elem.testattr = " + elem.testattr);
1584     r = elem.removeAttribute("testattr");
1585     ok(r === (v < 9 ? true : undefined), "testattr removeAttribute returned " + r);
1586     ok(elem.testattr === undefined, "removed testattr = " + elem.testattr);
1588     arr[0] = 9;
1589     elem.setAttribute("testattr", "string");
1590     elem.testattr = arr;
1591     r = elem.getAttribute("testattr");
1592     ok(r === (v < 8 ? arr : (v < 9 ? "9" : "string")), "testattr = " + r);
1593     ok(elem.testattr === arr, "elem.testattr = " + elem.testattr);
1594     arr[0] = 3;
1595     r = elem.getAttribute("testattr");
1596     ok(r === (v < 8 ? arr : (v < 9 ? "3" : "string")), "testattr = " + r);
1597     ok(elem.testattr === arr, "elem.testattr = " + elem.testattr);
1598     r = elem.removeAttribute("testattr");
1599     ok(r === (v < 9 ? true : undefined), "testattr removeAttribute returned " + r);
1600     ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr = " + elem.testattr);
1602     arr.toString = function() { return 42; }
1603     elem.testattr = arr;
1604     r = elem.getAttribute("testattr");
1605     ok(r === (v < 8 ? arr : (v < 9 ? "42" : null)), "testattr with custom toString = " + r);
1606     elem.setAttribute("testattr", arr);
1607     r = elem.getAttribute("testattr");
1608     ok(r === (v < 8 ? arr : "42"), "testattr after setAttribute with custom toString = " + r);
1609     ok(elem.testattr === arr, "elem.testattr after setAttribute with custom toString = " + elem.testattr);
1610     r = elem.removeAttribute("testattr");
1611     ok(r === (v < 9 ? true : undefined), "testattr removeAttribute with custom toString returned " + r);
1612     ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr with custom toString = " + elem.testattr);
1614     arr.valueOf = function() { return "arrval"; }
1615     elem.testattr = arr;
1616     r = elem.getAttribute("testattr");
1617     ok(r === (v < 8 ? arr : (v < 9 ? "arrval" : null)), "testattr with custom valueOf = " + r);
1618     elem.setAttribute("testattr", arr);
1619     r = elem.getAttribute("testattr");
1620     ok(r === (v < 8 ? arr : (v < 10 ? "arrval" : "42")), "testattr after setAttribute with custom valueOf = " + r);
1621     ok(elem.testattr === arr, "elem.testattr after setAttribute with custom valueOf = " + elem.testattr);
1622     r = elem.removeAttribute("testattr");
1623     ok(r === (v < 9 ? true : undefined), "testattr removeAttribute with custom valueOf returned " + r);
1624     ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr with custom valueOf = " + elem.testattr);
1626     var func = elem.setAttribute;
1627     try {
1628         func("testattr", arr);
1629         todo_wine_if(v >= 9).
1630         ok(v < 9, "expected exception setting testattr via func");
1631     }catch(ex) {
1632         ok(v >= 9, "did not expect exception setting testattr via func");
1633         elem.setAttribute("testattr", arr);
1634     }
1635     r = elem.getAttribute("testattr");
1636     ok(r === (v < 8 ? arr : (v < 10 ? "arrval" : "42")), "testattr after setAttribute (as func) = " + r);
1637     delete arr.valueOf;
1638     delete arr.toString;
1640     elem.setAttribute("id", arr);
1641     r = elem.getAttribute("id");
1642     todo_wine_if(v >= 8 && v < 10).
1643     ok(r === (v < 8 || v >= 10 ? "3" : "[object]"), "id = " + r);
1644     r = elem.removeAttribute("id");
1645     ok(r === (v < 9 ? true : undefined), "id removeAttribute returned " + r);
1646     ok(elem.id === "", "removed id = " + elem.id);
1648     func = function() { };
1649     elem.onclick = func;
1650     ok(elem.onclick === func, "onclick = " + elem.onclick);
1651     r = elem.getAttribute("onclick");
1652     todo_wine_if(v === 8).
1653     ok(r === (v < 8 ? func : null), "onclick attr = " + r);
1654     r = elem.removeAttribute("onclick");
1655     ok(r === (v < 9 ? false : undefined), "removeAttribute returned " + r);
1656     todo_wine_if(v === 8).
1657     ok(elem.onclick === (v != 8 ? func : null), "removed onclick = " + elem.onclick);
1659     elem.onclick_test = func;
1660     ok(elem.onclick_test === func, "onclick_test = " + elem.onclick_test);
1661     r = elem.getAttribute("onclick_test");
1662     ok(r === (v < 8 ? func : (v < 9 ? func.toString() : null)), "onclick_test attr = " + r);
1664     elem.setAttribute("onclick", "test");
1665     r = elem.getAttribute("onclick");
1666     ok(r === "test", "onclick attr after setAttribute = " + r);
1667     r = elem.removeAttribute("onclick");
1668     ok(r === (v < 9 ? true : undefined), "removeAttribute after setAttribute returned " + r);
1670     /* IE11 returns an empty function, which we can't check directly */
1671     todo_wine_if(v >= 9).
1672     ok((v < 11) ? (elem.onclick === null) : (elem.onclick !== func), "removed onclick after setAttribute = " + elem.onclick);
1674     r = Object.prototype.toString.call(elem.onclick);
1675     todo_wine_if(v >= 9 && v < 11).
1676     ok(r === (v < 9 ? "[object Object]" : (v < 11 ? "[object Null]" : "[object Function]")),
1677         "removed onclick after setAttribute Object.toString returned " + r);
1679     elem.setAttribute("onclick", "string");
1680     r = elem.getAttribute("onclick");
1681     ok(r === "string", "onclick attr after setAttribute = " + r);
1682     elem.onclick = func;
1683     ok(elem.onclick === func, "onclick = " + elem.onclick);
1684     r = elem.getAttribute("onclick");
1685     todo_wine_if(v === 8).
1686     ok(r === (v < 8 ? func : (v < 9 ? null : "string")), "onclick attr = " + r);
1687     elem.onclick = "test";
1688     r = elem.getAttribute("onclick");
1689     ok(r === (v < 9 ? "test" : "string"), "onclick attr = " + r);
1690     r = elem.removeAttribute("onclick");
1691     ok(r === (v < 9 ? true : undefined), "removeAttribute returned " + r);
1692     todo_wine_if(v >= 9).
1693     ok(elem.onclick === null, "removed onclick = " + elem.onclick);
1695     elem.setAttribute("ondblclick", arr);
1696     r = elem.getAttribute("ondblclick");
1697     todo_wine_if(v >= 8 && v < 10).
1698     ok(r === (v < 8 ? arr : (v < 10 ? "[object]" : "3")), "ondblclick = " + r);
1699     r = elem.removeAttribute("ondblclick");
1700     ok(r === (v < 8 ? false : (v < 9 ? true : undefined)), "ondblclick removeAttribute returned " + r);
1701     r = Object.prototype.toString.call(elem.ondblclick);
1702     todo_wine_if(v >= 11).
1703     ok(r === (v < 8 ? "[object Array]" : (v < 9 ? "[object Object]" : (v < 11 ? "[object Null]" : "[object Function]"))),
1704         "removed ondblclick Object.toString returned " + r);
1706     elem.setAttribute("ondblclick", "string");
1707     r = elem.getAttribute("ondblclick");
1708     ok(r === "string", "ondblclick string = " + r);
1709     r = elem.removeAttribute("ondblclick");
1710     ok(r === (v < 9 ? true : undefined), "ondblclick string removeAttribute returned " + r);
1711     ok(elem.ondblclick === null, "removed ondblclick string = " + elem.ondblclick);
1713     if(v < 9) {
1714         /* style is a special case */
1715         try {
1716             elem.style = "opacity: 1.0";
1717             ok(false, "expected exception setting elem.style");
1718         }catch(ex) { }
1720         var style = elem.style;
1721         r = elem.getAttribute("style");
1722         ok(r === (v < 8 ? style : null), "style attr = " + r);
1723         r = elem.removeAttribute("style");
1724         ok(r === true, "removeAttribute('style') returned " + r);
1725         r = elem.style;
1726         ok(r === style, "removed elem.style = " + r);
1727         r = elem.getAttribute("style");
1728         ok(r === (v < 8 ? style : null), "style attr after removal = " + r);
1729         elem.setAttribute("style", "opacity: 1.0");
1730         r = elem.getAttribute("style");
1731         ok(r === (v < 8 ? style : "opacity: 1.0"), "style attr after setAttribute = " + r);
1732         r = elem.style;
1733         ok(r === style, "elem.style after setAttribute = " + r);
1734     }
1737 sync_test("elem_attrNS", function() {
1738     var v = document.documentMode;
1739     if(v < 9) return;  /* not available */
1741     var specialspace_ns = "http://www.mozilla.org/ns/specialspace";
1742     var svg_ns = "http://www.w3.org/2000/svg";
1744     var elem = document.createElement("div"), r;
1746     elem.setAttributeNS(specialspace_ns, "spec:align", "left");
1747     r = elem.hasAttribute("spec:align");
1748     ok(r === true, "spec:align does not exist");
1749     r = elem.getAttribute("spec:align");
1750     ok(r === "left", "spec:align = " + r);
1751     r = elem.hasAttribute("align");
1752     ok(r === false, "align exists");
1753     r = elem.getAttribute("align");
1754     ok(r === null, "align = " + r);
1755     r = elem.hasAttributeNS(null, "spec:align");
1756     ok(r === false, "null spec:align exists");
1757     r = elem.getAttributeNS(null, "spec:align");
1758     ok(r === "", "null spec:align = " + r);
1759     r = elem.hasAttributeNS(null, "spec:align");
1760     ok(r === false, "null align exists");
1761     r = elem.getAttributeNS(null, "align");
1762     ok(r === "", "null align = " + r);
1763     r = elem.hasAttributeNS(svg_ns, "spec:align");
1764     ok(r === false, "svg spec:align exists");
1765     r = elem.getAttributeNS(svg_ns, "spec:align");
1766     ok(r === "", "svg spec:align = " + r);
1767     r = elem.hasAttributeNS(svg_ns, "align");
1768     ok(r === false, "svg align exists");
1769     r = elem.getAttributeNS(svg_ns, "align");
1770     ok(r === "", "svg align = " + r);
1771     r = elem.hasAttributeNS(specialspace_ns, "spec:align");
1772     ok(r === false, "specialspace spec:align exists");
1773     r = elem.getAttributeNS(specialspace_ns, "spec:align");
1774     ok(r === "", "specialspace spec:align = " + r);
1775     r = elem.hasAttributeNS(specialspace_ns, "align");
1776     ok(r === true, "specialspace align does not exist");
1777     r = elem.getAttributeNS(specialspace_ns, "align");
1778     ok(r === "left", "specialspace align = " + r);
1780     try {
1781         elem.setAttributeNS(null, "spec:align", "right");
1782         ok(false, "expected exception setting qualified attr with null ns");
1783     }catch(ex) {
1784         todo_wine.
1785         ok(ex.message === "NamespaceError", "setAttributeNS(null, 'spec:align', 'right') threw " + ex.message);
1786     }
1787     try {
1788         elem.setAttributeNS("", "spec:align", "right");
1789         ok(false, "expected exception setting qualified attr with empty ns");
1790     }catch(ex) {
1791         todo_wine.
1792         ok(ex.message === "NamespaceError", "setAttributeNS('', 'spec:align', 'right') threw " + ex.message);
1793     }
1794     elem.setAttributeNS(null, "align", "right");
1795     r = elem.getAttribute("spec:align");
1796     ok(r === "left", "spec:align (null) = " + r);
1797     r = elem.hasAttribute("align");
1798     ok(r === true, "align (null) does not exist");
1799     r = elem.getAttribute("align");
1800     ok(r === "right", "align (null) = " + r);
1801     r = elem.hasAttributeNS(null, "spec:align");
1802     ok(r === false, "null spec:align exists");
1803     r = elem.getAttributeNS(null, "spec:align");
1804     ok(r === "", "null spec:align (null) = " + r);
1805     r = elem.hasAttributeNS(null, "align");
1806     ok(r === true, "null align does not exist");
1807     r = elem.getAttributeNS(null, "align");
1808     ok(r === "right", "null align (null) = " + r);
1809     r = elem.hasAttributeNS(svg_ns, "spec:align");
1810     ok(r === false, "svg spec:align (null) exists");
1811     r = elem.getAttributeNS(svg_ns, "spec:align");
1812     ok(r === "", "svg spec:align (null) = " + r);
1813     r = elem.hasAttributeNS(svg_ns, "align");
1814     ok(r === false, "svg align (null) exists");
1815     r = elem.getAttributeNS(svg_ns, "align");
1816     ok(r === "", "svg align (null) = " + r);
1817     r = elem.hasAttributeNS(specialspace_ns, "spec:align");
1818     ok(r === false, "specialspace_ns spec:align (null) exists");
1819     r = elem.getAttributeNS(specialspace_ns, "spec:align");
1820     ok(r === "", "specialspace spec:align (null) = " + r);
1821     r = elem.hasAttributeNS(specialspace_ns, "align");
1822     ok(r === true, "specialspace align (null) does not exist");
1823     r = elem.getAttributeNS(specialspace_ns, "align");
1824     ok(r === "left", "specialspace align (null) = " + r);
1826     elem.setAttribute("align", "center");
1827     r = elem.hasAttributeNS(null, "spec:align");
1828     ok(r === false, "null spec:align (non-NS) exists");
1829     r = elem.getAttributeNS(null, "spec:align");
1830     ok(r === "", "null spec:align (non-NS) = " + r);
1831     r = elem.hasAttributeNS(null, "align");
1832     ok(r === true, "null align (non-NS) does not exist");
1833     r = elem.getAttributeNS(null, "align");
1834     ok(r === "center", "null align (non-NS) = " + r);
1835     r = elem.hasAttributeNS(svg_ns, "spec:align");
1836     ok(r === false, "svg spec:align (non-NS) exists");
1837     r = elem.getAttributeNS(svg_ns, "spec:align");
1838     ok(r === "", "svg spec:align (non-NS) = " + r);
1839     r = elem.hasAttributeNS(svg_ns, "align");
1840     ok(r === false, "svg align (non-NS) exists");
1841     r = elem.getAttributeNS(svg_ns, "align");
1842     ok(r === "", "svg align (non-NS) = " + r);
1843     r = elem.hasAttributeNS(specialspace_ns, "spec:align");
1844     ok(r === false, "specialspace spec:align (non-NS) exists");
1845     r = elem.getAttributeNS(specialspace_ns, "spec:align");
1846     ok(r === "", "specialspace spec:align (non-NS) = " + r);
1847     r = elem.hasAttributeNS(specialspace_ns, "align");
1848     ok(r === true, "specialspace align (non-NS) does not exist");
1849     r = elem.getAttributeNS(specialspace_ns, "align");
1850     ok(r === "left", "specialspace align (non-NS) = " + r);
1851     elem.removeAttributeNS(null, "spec:align");
1853     elem.setAttribute("emptynsattr", "none");
1854     elem.setAttributeNS("", "emptynsattr", "test");
1855     r = elem.hasAttribute("emptynsattr");
1856     ok(r === true, "emptynsattr without NS does not exist");
1857     r = elem.getAttribute("emptynsattr");
1858     ok(r === "test", "emptynsattr without NS = " + r);
1859     elem.setAttributeNS(null, "emptynsattr", "wine");
1860     r = elem.hasAttribute("emptynsattr");
1861     ok(r === true, "emptynsattr without NS does not exist");
1862     r = elem.getAttribute("emptynsattr");
1863     ok(r === "wine", "emptynsattr without NS = " + r);
1864     elem.setAttributeNS(specialspace_ns, "emptynsattr", "ns");
1865     r = elem.hasAttribute("emptynsattr");
1866     ok(r === true, "emptynsattr without NS does not exist");
1867     r = elem.getAttribute("emptynsattr");
1868     ok(r === "wine", "emptynsattr without NS = " + r);
1869     r = elem.hasAttributeNS("", "emptynsattr");
1870     ok(r === true, "emptynsattr empty ns does not exist");
1871     r = elem.getAttributeNS("", "emptynsattr");
1872     ok(r === "wine", "emptynsattr empty ns = " + r);
1873     r = elem.hasAttributeNS(null, "emptynsattr");
1874     ok(r === true, "emptynsattr null ns does not exist");
1875     r = elem.getAttributeNS(null, "emptynsattr");
1876     ok(r === "wine", "emptynsattr null ns = " + r);
1877     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
1878     ok(r === true, "emptynsattr specialspace ns does not exist");
1879     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
1880     ok(r === "ns", "emptynsattr specialspace ns = " + r);
1882     elem.removeAttributeNS("", "emptynsattr");
1883     r = elem.hasAttribute("emptynsattr");
1884     ok(r === true, "emptynsattr without NS after remove does not exist");
1885     r = elem.getAttribute("emptynsattr");
1886     ok(r === "ns", "emptynsattr without NS after remove = " + r);
1887     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
1888     ok(r === true, "emptynsattr specialspace ns after empty remove does not exist");
1889     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
1890     ok(r === "ns", "emptynsattr specialspace ns after empty remove = " + r);
1891     elem.setAttribute("emptynsattr", "test");
1892     r = elem.getAttribute("emptynsattr");
1893     ok(r === "test", "emptynsattr without NS after re-set = " + r);
1894     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
1895     ok(r === "test", "emptynsattr specialspace ns after empty re-set = " + r);
1897     elem.removeAttribute("emptynsattr");
1898     r = elem.hasAttribute("emptynsattr");
1899     ok(r === false, "emptynsattr without NS after non-NS remove exists");
1900     r = elem.getAttribute("emptynsattr");
1901     ok(r === null, "emptynsattr without NS after non-NS remove = " + r);
1902     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
1903     ok(r === false, "emptynsattr specialspace ns after non-NS remove exists");
1904     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
1905     ok(r === "", "emptynsattr specialspace ns after non-NS remove = " + r);
1907     elem.setAttributeNS(specialspace_ns, "emptynsattr", "ns");
1908     elem.removeAttributeNS(svg_ns, "emptynsattr");
1909     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
1910     ok(r === true, "emptynsattr specialspace ns after wrong NS remove does not exist");
1911     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
1912     ok(r === "ns", "emptynsattr specialspace ns after wrong NS remove = " + r);
1913     r = elem.hasAttributeNS(specialspace_ns, "emptynsattr");
1914     ok(r === true, "emptynsattr specialspace ns after remove does not exist");
1915     r = elem.getAttributeNS(specialspace_ns, "emptynsattr");
1916     ok(r === "ns", "emptynsattr specialspace ns after remove = " + r);
1918     var ns = {};
1919     ns.toString = function() { return "toString namespace"; }
1920     ns.valueOf = function() { return "valueOf namespace"; }
1921     elem.setAttributeNS(ns, "foobar", "test");
1922     r = elem.hasAttribute("foobar");
1923     ok(r === true, "foobar without NS does not exist");
1924     r = elem.getAttribute("foobar");
1925     ok(r === "test", "foobar without NS = " + r);
1926     r = elem.hasAttributeNS(ns, "foobar");
1927     ok(r === true, "foobar does not exist");
1928     r = elem.getAttributeNS(ns, "foobar");
1929     ok(r === "test", "foobar = " + r);
1930     r = elem.hasAttributeNS("toString namespace", "foobar");
1931     ok(r === (v < 10 ? false : true), "foobar (toString namespace) " + (v < 10 ? "exists" : "does not exist"));
1932     r = elem.getAttributeNS("toString namespace", "foobar");
1933     ok(r === (v < 10 ? "" : "test"), "foobar (toString namespace) = " + r);
1934     r = elem.hasAttributeNS("valueOf namespace", "foobar");
1935     ok(r === (v < 10 ? true : false), "foobar (valueOf namespace) = " + (v < 10 ? "does not exist" : "exists"));
1936     r = elem.getAttributeNS("valueOf namespace", "foobar");
1937     ok(r === (v < 10 ? "test" : ""), "foobar (valueOf namespace) = " + r);
1939     var arr = [3];
1940     elem.setAttributeNS(svg_ns, "testattr", arr);
1941     r = elem.getAttributeNS(svg_ns, "testattr");
1942     ok(r === "3", "testattr = " + r);
1943     ok(elem.testattr === undefined, "elem.testattr = " + elem.testattr);
1944     elem.removeAttributeNS(svg_ns, "testattr");
1945     r = elem.getAttributeNS(svg_ns, "testattr");
1946     ok(r === "", "testattr after remove = " + r);
1948     arr.toString = function() { return 42; }
1949     elem.setAttributeNS(svg_ns, "testattr", arr);
1950     r = elem.getAttributeNS(svg_ns, "testattr");
1951     ok(r === "42", "testattr with custom toString = " + r);
1952     elem.removeAttributeNS(svg_ns, "testattr");
1953     r = elem.getAttributeNS(svg_ns, "testattr");
1954     ok(r === "", "testattr with custom toString after remove = " + r);
1956     arr.valueOf = function() { return "arrval"; }
1957     elem.setAttributeNS(svg_ns, "testattr", arr);
1958     r = elem.getAttributeNS(svg_ns, "testattr");
1959     ok(r === "42", "testattr with custom valueOf = " + r);
1960     elem.removeAttributeNS(svg_ns, "testattr");
1962     elem.setAttributeNS(svg_ns, "boolattr", true);
1963     r = elem.getAttributeNS(svg_ns, "boolattr");
1964     ok(r === "true", "boolattr = " + r);
1966     elem.setAttributeNS(svg_ns, "numattr", 13);
1967     r = elem.getAttributeNS(svg_ns, "numattr");
1968     ok(r === "13", "numattr = " + r);
1971 sync_test("builtins_diffs", function() {
1972     var v = document.documentMode;
1974     /* despite what spec says for ES6, IE still throws */
1975     var props = [
1976         "freeze",
1977         "getPrototypeOf",
1978         "isExtensible",
1979         "isFrozen",
1980         "isSealed",
1981         "keys",
1982         "preventExtensions",
1983         "seal"
1984     ];
1985     for(var i = 0; i < props.length; i++) {
1986         try {
1987             Object[props[i]]("test");
1988             ok(false, "Object." + props[i] + " with non-object: expected exception");
1989         }catch(e) {
1990             ok(e.number === (v < 9 ? 0xa01b6 : 0xa138f) - 0x80000000, "Object." + props[i] + " with non-object: exception = " + e.number);
1991         }
1992     }
1994     try {
1995         RegExp.prototype.toString.call({source: "foo", flags: "g"});
1996         ok(false, "RegExp.toString with non-regexp: expected exception");
1997     }catch(e) {
1998         ok(e.number === 0xa1398 - 0x80000000, "RegExp.toString with non-regexp: exception = " + e.number);
1999     }
2001     try {
2002         /a/.lastIndex();
2003         ok(false, "/a/.lastIndex(): expected exception");
2004     }catch(e) {
2005         ok(e.number === 0xa138a - 0x80000000, "/a/.lastIndex(): exception = " + e.number);
2006     }
2007     try {
2008         "a".length();
2009         ok(false, "\"a\".length(): expected exception");
2010     }catch(e) {
2011         ok(e.number === 0xa138a - 0x80000000, "\"a\".length(): exception = " + e.number);
2012     }
2015 sync_test("nullDisp", function() {
2016     var v = document.documentMode, nullDisp = external.nullDisp, r;
2018     ok(external.getVT(nullDisp) === "VT_NULL", "getVT(nullDisp) is not VT_NULL");
2019     ok(typeof(nullDisp) === "object", "typeof(nullDisp) = " + typeof(nullDisp));
2020     ok(nullDisp === nullDisp, "nullDisp !== nullDisp");
2021     ok(nullDisp === null, "nullDisp === null");
2022     ok(nullDisp == null, "nullDisp == null");
2023     ok(!nullDisp === true, "!nullDisp = " + !nullDisp);
2024     ok(String(nullDisp) === "null", "String(nullDisp) = " + String(nullDisp));
2025     ok(+nullDisp === 0, "+nullDisp !== 0");
2026     ok(''+nullDisp === "null", "''+nullDisp !== null");
2027     ok(nullDisp != new Object(), "nullDisp == new Object()");
2028     ok(new Object() != nullDisp, "new Object() == nullDisp");
2029     ok((typeof Object(nullDisp)) === "object", "typeof Object(nullDisp) !== 'object'");
2030     r = Object(nullDisp).toString();
2031     ok(r === "[object Object]", "Object(nullDisp).toString() = " + r);
2032     ok(Object(nullDisp) != nullDisp, "Object(nullDisp) == nullDisp");
2033     ok(new Object(nullDisp) != nullDisp, "new Object(nullDisp) == nullDisp");
2034     r = (nullDisp instanceof Object);
2035     ok(r === false, "nullDisp instance of Object");
2037     if(v >= 8) {
2038         r = JSON.stringify.call(null, nullDisp);
2039         ok(r === "null", "JSON.stringify(nullDisp) returned " + r);
2040     }
2042     try {
2043         (new Object()) instanceof nullDisp;
2044         ok(false, "expected exception on (new Object()) instanceof nullDisp");
2045     }catch(e) {
2046         ok(e.number === 0xa138a - 0x80000000, "(new Object()) instanceof nullDisp threw " + e.number);
2047     }
2049     try {
2050         Function.prototype.apply.call(nullDisp, Object, []);
2051         ok(false, "expected exception calling Function.apply on nullDisp");
2052     }catch(e) {
2053         ok(e.number === 0xa138a - 0x80000000, "Function.apply on nullDisp threw " + e.number);
2054     }
2055     try {
2056         Function.prototype.call.call(nullDisp, Object);
2057         ok(false, "expected exception calling Function.call on nullDisp");
2058     }catch(e) {
2059         ok(e.number === 0xa138a - 0x80000000, "Function.call on nullDisp threw " + e.number);
2060     }
2062     try {
2063         new nullDisp;
2064         ok(false, "expected exception for new nullDisp");
2065     }catch(e) {
2066         ok(e.number === 0xa138f - 0x80000000, "new nullDisp threw " + e.number);
2067     }
2070 sync_test("__proto__", function() {
2071     var v = document.documentMode;
2072     var r, x = 42;
2074     if(v < 11) {
2075         ok(x.__proto__ === undefined, "x.__proto__ = " + x.__proto__);
2076         ok(!("__proto__" in Object), "Object.__proto__ = " + Object.__proto__);
2077         return;
2078     }
2080     ok(x.__proto__ === Number.prototype, "x.__proto__ = " + x.__proto__);
2081     ok(Object.__proto__ === Function.prototype, "Object.__proto__ = " + Object.__proto__);
2082     ok(Object.prototype.__proto__ === null, "Object.prototype.__proto__ = " + Object.prototype.__proto__);
2083     ok(Object.prototype.hasOwnProperty("__proto__"), "__proto__ is not a property of Object.prototype");
2084     ok(!Object.prototype.hasOwnProperty.call(x, "__proto__"), "__proto__ is a property of x");
2086     x.__proto__ = Object.prototype;
2087     ok(x.__proto__ === Number.prototype, "x.__proto__ set to Object.prototype = " + x.__proto__);
2088     ok(!Object.prototype.hasOwnProperty.call(x, "__proto__"), "__proto__ is a property of x after set to Object.prototype");
2089     x = {};
2090     x.__proto__ = null;
2091     r = Object.getPrototypeOf(x);
2092     ok(x.__proto__ === undefined, "x.__proto__ after set to null = " + x.__proto__);
2093     ok(r === null, "getPrototypeOf(x) after set to null = " + r);
2095     function check(expect, msg) {
2096         var r = Object.getPrototypeOf(x);
2097         ok(x.__proto__ === expect, "x.__proto__ " + msg + " = " + x.__proto__);
2098         ok(r === expect, "getPrototypeOf(x) " + msg + " = " + r);
2099         ok(!Object.prototype.hasOwnProperty.call(x, "__proto__"), "__proto__ is a property of x " + msg);
2100     }
2102     x = {};
2103     check(Object.prototype, "after x set to {}");
2104     x.__proto__ = Number.prototype;
2105     check(Number.prototype, "after set to Number.prototype");
2106     x.__proto__ = Object.prototype;
2107     check(Object.prototype, "after re-set to Object.prototype");
2109     function ctor() { }
2110     var obj = new ctor();
2111     x.__proto__ = obj;
2112     check(obj, "after set to obj");
2113     x.__proto__ = ctor.prototype;
2114     check(obj.__proto__, "after set to ctor.prototype");
2115     ok(obj.__proto__ === ctor.prototype, "obj.__proto__ !== ctor.prototype");
2117     r = (delete x.__proto__);
2118     ok(r, "delete x.__proto__ returned " + r);
2119     ok(Object.prototype.hasOwnProperty("__proto__"), "__proto__ is not a property of Object.prototype after delete");
2120     r = Object.getPrototypeOf(x);
2121     ok(r === ctor.prototype, "x.__proto__ after delete = " + r);
2123     var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__");
2124     ok(desc.value === undefined, "__proto__ value = " + desc.value);
2125     ok(Object.getPrototypeOf(desc.get) === Function.prototype, "__proto__ getter not a function");
2126     ok(Object.getPrototypeOf(desc.set) === Function.prototype, "__proto__ setter not a function");
2127     ok(desc.get.length === 0, "__proto__ getter length = " + desc.get.length);
2128     ok(desc.set.length === 1, "__proto__ setter length = " + desc.set.length);
2130     r = desc.get.call(x, 1, 2, 3, 4);
2131     ok(r === x.__proto__, "calling __proto__ getter on x returned " + r);
2133     r = desc.set.call(x, obj);
2134     ok(r === obj, "calling __proto__ setter(obj) on x returned " + r);
2135     check(obj, "after set to obj via calling setter");
2136     r = desc.set.call(x, 42);
2137     ok(r === 42, "calling __proto__ setter(42) on x returned " + r);
2138     check(obj, "after set to obj via calling setter(42)");
2139     r = desc.set.call(x, "foo");
2140     ok(r === "foo", "calling __proto__ setter('foo') on x returned " + r);
2141     check(obj, "after set to obj via calling setter('foo')");
2142     r = desc.set.call(x);
2143     ok(r === undefined, "calling __proto__ setter() on x returned " + r);
2144     r = desc.set.call(true, obj);
2145     ok(r === obj, "calling __proto__ setter(obj) on true value returned " + r);
2146     x = true;
2147     r = desc.set.call(x, obj);
2148     ok(r === obj, "calling __proto__ setter(obj) on x set to true returned " + r);
2149     ok(x.__proto__ === Boolean.prototype, "true value __proto__ after set to obj = " + x.__proto__);
2150     x = new Boolean(true);
2151     r = desc.set.call(x, obj);
2152     ok(r === obj, "calling __proto__ setter(obj) on x set to Boolean(true) returned " + r);
2153     ok(x.__proto__ === obj, "Boolean(true) __proto__ after set to obj = " + x.__proto__);
2155     r = desc.get.call(13);
2156     ok(r === Number.prototype, "calling __proto__ getter on 13 returned " + r);
2157     try {
2158         r = desc.get.call(undefined);
2159         ok(false, "expected exception calling __proto__ getter on undefined");
2160     }catch(e) {
2161         ok(e.number === 0xa138f - 0x80000000, "calling __proto__ getter on undefined threw exception " + e.number);
2162     }
2163     try {
2164         r = desc.get.call(null);
2165         ok(false, "expected exception calling __proto__ getter on null");
2166     }catch(e) {
2167         ok(e.number === 0xa138f - 0x80000000, "calling __proto__ getter on null threw exception " + e.number);
2168     }
2170     try {
2171         r = desc.set.call(undefined, obj);
2172         ok(false, "expected exception calling __proto__ setter on undefined");
2173     }catch(e) {
2174         ok(e.number === 0xa138f - 0x80000000, "calling __proto__ setter on undefined threw exception " + e.number);
2175     }
2176     try {
2177         r = desc.set.call(null, obj);
2178         ok(false, "expected exception calling __proto__ setter on null");
2179     }catch(e) {
2180         ok(e.number === 0xa138f - 0x80000000, "calling __proto__ setter on null threw exception " + e.number);
2181     }
2183     x = {};
2184     r = Object.create(x);
2185     ok(r.__proto__ === x, "r.__proto__ = " + r.__proto__);
2186     r = Object.create(r);
2187     ok(r.__proto__.__proto__ === x, "r.__proto__.__proto__ = " + r.__proto__.__proto__);
2188     try {
2189         x.__proto__ = r;
2190         ok(false, "expected exception setting circular proto chain");
2191     }catch(e) {
2192         ok(e.number === 0xa13b0 - 0x80000000 && e.name === "TypeError",
2193             "setting circular proto chain threw exception " + e.number + " (" + e.name + ")");
2194     }
2196     Object.preventExtensions(x);
2197     x.__proto__ = Object.prototype;  /* same prototype */
2198     try {
2199         x.__proto__ = Number.prototype;
2200         ok(false, "expected exception changing __proto__ on non-extensible object");
2201     }catch(e) {
2202         ok(e.number === 0xa13b6 - 0x80000000 && e.name === "TypeError",
2203             "changing __proto__ on non-extensible object threw exception " + e.number + " (" + e.name + ")");
2204     }
2207 sync_test("__defineGetter__", function() {
2208     var v = document.documentMode;
2209     var r, x = 42;
2211     if(v < 11) {
2212         ok(x.__defineGetter__ === undefined, "x.__defineGetter__ = " + x.__defineGetter__);
2213         ok(!("__defineGetter__" in Object), "Object.__defineGetter__ = " + Object.__defineGetter__);
2214         return;
2215     }
2216     ok(Object.prototype.hasOwnProperty("__defineGetter__"), "__defineGetter__ is not a property of Object.prototype");
2217     ok(Object.prototype.__defineGetter__.length === 2, "__defineGetter__.length = " + Object.prototype.__defineGetter__.length);
2219     function getter() { return "wine"; }
2220     function setter(val) { }
2222     r = x.__defineGetter__("foo", getter);
2223     ok(r === undefined, "__defineGetter__ on 42 returned " + r);
2224     ok(x.foo === undefined, "42.foo = " + x.foo);
2226     x = {};
2227     r = x.__defineGetter__("foo", getter);
2228     ok(r === undefined, "__defineGetter__ returned " + r);
2229     ok(x.foo === "wine", "x.foo = " + x.foo);
2230     r = Object.getOwnPropertyDescriptor(x, "foo");
2231     ok(r.value === undefined, "x.foo value = " + r.value);
2232     ok(r.get === getter, "x.foo get = " + r.get);
2233     ok(r.set === undefined, "x.foo set = " + r.set);
2234     ok(r.writable === undefined, "x.foo writable = " + r.writable);
2235     ok(r.enumerable === true, "x.foo enumerable = " + r.enumerable);
2236     ok(r.configurable === true, "x.foo configurable = " + r.configurable);
2238     Object.defineProperty(x, "foo", { get: undefined, set: setter, configurable: false });
2239     r = Object.getOwnPropertyDescriptor(x, "foo");
2240     ok(r.value === undefined, "x.foo setter value = " + r.value);
2241     ok(r.get === undefined, "x.foo setter get = " + r.get);
2242     ok(r.set === setter, "x.foo setter set = " + r.set);
2243     ok(r.writable === undefined, "x.foo setter writable = " + r.writable);
2244     ok(r.enumerable === true, "x.foo setter enumerable = " + r.enumerable);
2245     ok(r.configurable === false, "x.foo setter configurable = " + r.configurable);
2246     try {
2247         x.__defineGetter__("foo", getter);
2248         ok(false, "expected exception calling __defineGetter__ on non-configurable property");
2249     }catch(e) {
2250         ok(e.number === 0xa13d6 - 0x80000000, "__defineGetter__ on non-configurable property threw exception " + e.number);
2251     }
2253     r = Object.prototype.__defineGetter__.call(undefined, "bar", getter);
2254     ok(r === undefined, "__defineGetter__ on undefined returned " + r);
2255     r = Object.prototype.__defineGetter__.call(null, "bar", getter);
2256     ok(r === undefined, "__defineGetter__ on null returned " + r);
2257     r = x.__defineGetter__(undefined, getter);
2258     ok(r === undefined, "__defineGetter__ undefined prop returned " + r);
2259     ok(x["undefined"] === "wine", "x.undefined = " + x["undefined"]);
2260     r = x.__defineGetter__(false, getter);
2261     ok(r === undefined, "__defineGetter__ undefined prop returned " + r);
2262     ok(x["false"] === "wine", "x.false = " + x["false"]);
2264     try {
2265         x.__defineGetter__("bar", "string");
2266         ok(false, "expected exception calling __defineGetter__ with string");
2267     }catch(e) {
2268         ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with string threw exception " + e.number);
2269     }
2270     try {
2271         x.__defineGetter__("bar", undefined);
2272         ok(false, "expected exception calling __defineGetter__ with undefined");
2273     }catch(e) {
2274         ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with undefined threw exception " + e.number);
2275     }
2276     try {
2277         x.__defineGetter__("bar", null);
2278         ok(false, "expected exception calling __defineGetter__ with null");
2279     }catch(e) {
2280         ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with null threw exception " + e.number);
2281     }
2282     try {
2283         Object.prototype.__defineGetter__.call(x, "bar");
2284         ok(false, "expected exception calling __defineGetter__ with only one arg");
2285     }catch(e) {
2286         ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with only one arg threw exception " + e.number);
2287     }
2289     x.bar = "test";
2290     ok(x.bar === "test", "x.bar = " + x.bar);
2291     x.__defineGetter__("bar", getter);
2292     ok(x.bar === "wine", "x.bar with getter = " + x.bar);
2295 sync_test("__defineSetter__", function() {
2296     var v = document.documentMode;
2297     var r, x = 42;
2299     if(v < 11) {
2300         ok(x.__defineSetter__ === undefined, "x.__defineSetter__ = " + x.__defineSetter__);
2301         ok(!("__defineSetter__" in Object), "Object.__defineSetter__ = " + Object.__defineSetter__);
2302         return;
2303     }
2304     ok(Object.prototype.hasOwnProperty("__defineSetter__"), "__defineSetter__ is not a property of Object.prototype");
2305     ok(Object.prototype.__defineSetter__.length === 2, "__defineSetter__.length = " + Object.prototype.__defineSetter__.length);
2307     function getter() { return "wine"; }
2308     function setter(val) { this.setterVal = val - 1; }
2310     r = x.__defineSetter__("foo", setter);
2311     ok(r === undefined, "__defineSetter__ on 42 returned " + r);
2312     ok(x.foo === undefined, "42.foo = " + x.foo);
2314     x = {};
2315     r = x.__defineSetter__("foo", setter);
2316     ok(r === undefined, "__defineSetter__ returned " + r);
2317     ok(x.setterVal === undefined, "x.setterVal = " + x.setterVal);
2318     x.foo = 13;
2319     ok(x.setterVal === 12, "x.setterVal = " + x.setterVal);
2320     r = Object.getOwnPropertyDescriptor(x, "foo");
2321     ok(r.value === undefined, "x.foo value = " + r.value);
2322     ok(r.get === undefined, "x.foo get = " + r.get);
2323     ok(r.set === setter, "x.foo set = " + r.set);
2324     ok(r.writable === undefined, "x.foo writable = " + r.writable);
2325     ok(r.enumerable === true, "x.foo enumerable = " + r.enumerable);
2326     ok(r.configurable === true, "x.foo configurable = " + r.configurable);
2328     Object.defineProperty(x, "foo", { get: getter, set: undefined, configurable: false });
2329     r = Object.getOwnPropertyDescriptor(x, "foo");
2330     ok(r.value === undefined, "x.foo getter value = " + r.value);
2331     ok(r.get === getter, "x.foo getter get = " + r.get);
2332     ok(r.set === undefined, "x.foo getter set = " + r.set);
2333     ok(r.writable === undefined, "x.foo getter writable = " + r.writable);
2334     ok(r.enumerable === true, "x.foo getter enumerable = " + r.enumerable);
2335     ok(r.configurable === false, "x.foo getter configurable = " + r.configurable);
2336     try {
2337         x.__defineSetter__("foo", setter);
2338         ok(false, "expected exception calling __defineSetter__ on non-configurable property");
2339     }catch(e) {
2340         ok(e.number === 0xa13d6 - 0x80000000, "__defineSetter__ on non-configurable property threw exception " + e.number);
2341     }
2343     r = Object.prototype.__defineSetter__.call(undefined, "bar", setter);
2344     ok(r === undefined, "__defineSetter__ on undefined returned " + r);
2345     r = Object.prototype.__defineSetter__.call(null, "bar", setter);
2346     ok(r === undefined, "__defineSetter__ on null returned " + r);
2347     r = x.__defineSetter__(null, setter);
2348     ok(r === undefined, "__defineSetter__ null prop returned " + r);
2349     x["null"] = 100;
2350     ok(x.setterVal === 99, "x.setterVal after setting x.null = " + x.setterVal);
2351     r = x.__defineSetter__(50, setter);
2352     ok(r === undefined, "__defineSetter__ 50 prop returned " + r);
2353     x["50"] = 33;
2354     ok(x.setterVal === 32, "x.setterVal after setting x.50 = " + x.setterVal);
2356     try {
2357         x.__defineSetter__("bar", true);
2358         ok(false, "expected exception calling __defineSetter__ with bool");
2359     }catch(e) {
2360         ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with bool threw exception " + e.number);
2361     }
2362     try {
2363         x.__defineSetter__("bar", undefined);
2364         ok(false, "expected exception calling __defineSetter__ with undefined");
2365     }catch(e) {
2366         ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with undefined threw exception " + e.number);
2367     }
2368     try {
2369         x.__defineSetter__("bar", null);
2370         ok(false, "expected exception calling __defineSetter__ with null");
2371     }catch(e) {
2372         ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with null threw exception " + e.number);
2373     }
2374     try {
2375         Object.prototype.__defineSetter__.call(x, "bar");
2376         ok(false, "expected exception calling __defineSetter__ with only one arg");
2377     }catch(e) {
2378         ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with only one arg threw exception " + e.number);
2379     }
2381     x.bar = "test";
2382     ok(x.bar === "test", "x.bar = " + x.bar);
2383     x.__defineSetter__("bar", setter);
2384     ok(x.bar === undefined, "x.bar with setter = " + x.bar);
2385     x.bar = 10;
2386     ok(x.bar === undefined, "x.bar with setter = " + x.bar);
2387     ok(x.setterVal === 9, "x.setterVal after setting bar = " + x.setterVal);
2390 async_test("postMessage", function() {
2391     var v = document.documentMode;
2392     var onmessage_called = false;
2393     window.onmessage = function(e) {
2394         onmessage_called = true;
2395         if(v < 9)
2396             ok(e === undefined, "e = " + e);
2397         else {
2398             ok(e.data === (v < 10 ? "10" : 10), "e.data = " + e.data);
2399             next_test();
2400         }
2401     }
2403     var invalid = [
2404         v < 10 ? { toString: function() { return "http://winetest.example.org"; } } : null,
2405         (function() { return "http://winetest.example.org"; }),
2406         "winetest.example.org",
2407         "example.org",
2408         undefined
2409     ];
2410     for(var i = 0; i < invalid.length; i++) {
2411         try {
2412             window.postMessage("invalid " + i, invalid[i]);
2413             ok(false, "expected exception with targetOrigin " + invalid[i]);
2414         }catch(ex) {
2415             var n = ex.number >>> 0;
2416             todo_wine_if(v >= 10).
2417             ok(n === (v < 10 ? 0x80070057 : 0), "postMessage with targetOrigin " + invalid[i] + " threw " + n);
2418             if(v >= 10)
2419                 todo_wine.
2420                 ok(ex.name === "SyntaxError", "postMessage with targetOrigin " + invalid[i] + " threw " + ex.name);
2421         }
2422     }
2423     try {
2424         window.postMessage("invalid empty", "");
2425         ok(false, "expected exception with empty targetOrigin");
2426     }catch(ex) {
2427         var n = ex.number >>> 0;
2428         ok(n === 0x80070057, "postMessage with empty targetOrigin threw " + n);
2429     }
2431     window.postMessage("wrong port", "http://winetest.example.org:1234");
2432     ok(onmessage_called == (v < 9 ? true : false), "onmessage not called with wrong port");
2433     onmessage_called = false;
2435     var not_sent = [
2436         "http://winetest.example.com",
2437         "ftp://winetest.example.org",
2438         "http://wine.example.org",
2439         "http://example.org"
2440     ];
2441     for(var i = 0; i < not_sent.length; i++) {
2442         window.postMessage("not_sent " + i, not_sent[i]);
2443         ok(onmessage_called == false, "onmessage called with targetOrigin " + not_sent[i]);
2444         onmessage_called = false;
2445     }
2447     window.postMessage(10, (v < 10 ? "*" : { toString: function() { return "*"; } }));
2448     ok(onmessage_called == (v < 9 ? true : false), "onmessage not called");
2449     if(v < 9) next_test();