");
}catch(ex) {
s = ex.toString();
e = ex.number;
}
todo_wine.
ok(e === undefined, "
e = " + e);
todo_wine.
ok(s === "InvalidCharacterError", "
s = " + s);
}
});
sync_test("JS objs", function() {
var g = window;
function test_exposed(func, obj, expect) {
if(expect)
ok(func in obj, func + " not found in " + obj);
else
ok(!(func in obj), func + " found in " + obj);
}
function test_parses(code, expect) {
var success;
try {
eval(code);
success = true;
}catch(e) {
success = false;
}
if(expect)
ok(success === true, code + " did not parse");
else
ok(success === false, code + " parsed");
}
var v = document.documentMode;
test_exposed("ScriptEngineMajorVersion", g, true);
test_exposed("JSON", g, v >= 8);
test_exposed("now", Date, true);
test_exposed("toISOString", Date.prototype, v >= 9);
test_exposed("isArray", Array, v >= 9);
test_exposed("forEach", Array.prototype, v >= 9);
test_exposed("indexOf", Array.prototype, v >= 9);
test_exposed("trim", String.prototype, v >= 9);
test_exposed("map", Array.prototype, v >= 9);
/* FIXME: IE8 implements weird semi-functional property descriptors. */
if(v != 8) {
test_exposed("getOwnPropertyDescriptor", Object, v >= 8);
test_exposed("defineProperty", Object, v >= 8);
test_exposed("defineProperties", Object, v >= 8);
}
test_exposed("getPrototypeOf", Object, v >= 9);
test_parses("if(false) { o.default; }", v >= 9);
test_parses("if(false) { o.with; }", v >= 9);
test_parses("if(false) { o.if; }", v >= 9);
});
sync_test("elem_by_id", function() {
document.body.innerHTML = '';
var id_elem = document.getElementById("testid");
ok(id_elem.tagName === "FORM", "id_elem.tagName = " + id_elem.tagName);
var name_elem = document.getElementById("testname");
if(document.documentMode < 8)
ok(id_elem === name_elem, "id_elem != id_elem");
else
ok(name_elem === null, "name_elem != null");
});
sync_test("doc_mode", function() {
compat_version = parseInt(document.location.search.substring(1));
trace("Testing compatibility mode " + compat_version);
if(compat_version > 6 && compat_version > document.documentMode) {
win_skip("Document mode not supported (expected " + compat_version + " got " + document.documentMode + ")");
reportSuccess();
return;
}
ok(Math.max(compat_version, 5) === document.documentMode, "documentMode = " + document.documentMode);
if(document.documentMode > 5)
ok(document.compatMode === "CSS1Compat", "document.compatMode = " + document.compatMode);
else
ok(document.compatMode === "BackCompat", "document.compatMode = " + document.compatMode);
});
async_test("iframe_doc_mode", function() {
var iframe = document.createElement("iframe");
iframe.onload = function() {
var iframe_mode = iframe.contentWindow.document.documentMode;
if(document.documentMode < 9)
ok(iframe_mode === 5, "iframe_mode = " + iframe_mode);
else
ok(iframe_mode === document.documentMode, "iframe_mode = " + iframe_mode);
next_test();
}
iframe.src = "about:blank";
document.body.appendChild(iframe);
});
sync_test("conditional_comments", function() {
var div = document.createElement("div");
document.body.appendChild(div);
function test_version(v) {
var version = compat_version ? compat_version : 7;
div.innerHTML = "";
ok(div.innerText === (version <= v ? "true" : ""),
"div.innerText = " + div.innerText + " for version (<=) " + v);
div.innerHTML = "";
ok(div.innerText === (version < v ? "true" : ""),
"div.innerText = " + div.innerText + " for version (<) " + v);
div.innerHTML = "";
ok(div.innerText === (version >= v && version < 10 ? "true" : ""),
"div.innerText = " + div.innerText + " for version (>=) " + v);
div.innerHTML = "";
ok(div.innerText === (version > v && version < 10 ? "true" : ""),
"div.innerText = " + div.innerText + " for version (>) " + v);
}
test_version(5);
test_version(6);
test_version(7);
test_version(8);
});
var ready_states;
async_test("script_load", function() {
var v = document.documentMode;
if(v < 9) {
next_test();
return;
}
var elem = document.createElement("script");
ready_states = "";
elem.onreadystatechange = guard(function() {
ok(v < 11, "unexpected onreadystatechange call");
ready_states += elem.readyState + ",";
});
elem.onload = guard(function() {
switch(v) {
case 9:
ok(ready_states === "loading,exec,loaded,", "ready_states = " + ready_states);
break;
case 10:
ok(ready_states === "loading,exec,", "ready_states = " + ready_states);
break;
case 11:
ok(ready_states === "exec,", "ready_states = " + ready_states);
break;
}
next_test();
});
document.body.appendChild(elem);
elem.src = "jsstream.php?simple";
external.writeStream("simple", "ready_states += 'exec,';");
});
sync_test("navigator", function() {
var v = document.documentMode, re;
var app = navigator.appVersion;
ok(navigator.userAgent === "Mozilla/" + app,
"userAgent = " + navigator.userAgent + " appVersion = " + app);
re = v < 11
? "^" + (v < 9 ? "4" : "5") + "\\.0 \\(compatible; MSIE " + (v < 7 ? 7 : v) +
"\\.0; Windows NT [0-9].[0-9]; .*Trident/[678]\\.0.*\\)$"
: "^5.0 \\(Windows NT [0-9].[0-9]; .*Trident/[678]\\.0.*rv:11.0\\) like Gecko$";
ok(new RegExp(re).test(app), "appVersion = " + app);
ok(navigator.appCodeName === "Mozilla", "appCodeName = " + navigator.appCodeName);
ok(navigator.appName === (v < 11 ? "Microsoft Internet Explorer" : "Netscape"),
"appName = " + navigator.appName);
ok(navigator.toString() === (v < 9 ? "[object]" : "[object Navigator]"),
"navigator.toString() = " + navigator.toString());
});
sync_test("delete_prop", function() {
var v = document.documentMode;
var obj = document.createElement("div"), r, obj2;
obj.prop1 = true;
r = false;
try {
delete obj.prop1;
}catch(ex) {
r = true;
}
if(v < 8) {
ok(r, "did not get an expected exception");
return;
}
ok(!r, "got an unexpected exception");
ok(!("prop1" in obj), "prop1 is still in obj");
/* again, this time prop1 does not exist */
r = false;
try {
delete obj.prop1;
}catch(ex) {
r = true;
}
if(v < 9) {
ok(r, "did not get an expected exception");
return;
}else {
ok(!r, "got an unexpected exception");
ok(!("prop1" in obj), "prop1 is still in obj");
}
r = (delete obj.className);
ok(r, "delete returned " + r);
ok("className" in obj, "className deleted from obj");
ok(obj.className === "", "className = " + obj.className);
/* builtin propertiles don't throw any exception, but are not really deleted */
r = (delete obj.tagName);
ok(r, "delete returned " + r);
ok("tagName" in obj, "tagName deleted from obj");
ok(obj.tagName === "DIV", "tagName = " + obj.tagName);
obj = document.querySelectorAll("*");
ok("0" in obj, "0 is not in obj");
obj2 = obj[0];
r = (delete obj[0]);
ok("0" in obj, "0 is not in obj");
ok(obj[0] === obj2, "obj[0] != obj2");
/* test window object and its global scope handling */
obj = window;
obj.globalprop1 = true;
ok(globalprop1, "globalprop1 = " + globalprop1);
r = false;
try {
delete obj.globalprop1;
}catch(ex) {
r = true;
}
if(v < 9) {
ok(r, "did not get an expected exception");
}else {
ok(!r, "got an unexpected globalprop1 exception");
ok(!("globalprop1" in obj), "globalprop1 is still in obj");
}
globalprop2 = true;
ok(obj.globalprop2, "globalprop2 = " + globalprop2);
r = false;
try {
delete obj.globalprop2;
}catch(ex) {
r = true;
}
if(v < 9) {
ok(r, "did not get an expected globalprop2 exception");
}else {
ok(!r, "got an unexpected exception");
todo_wine.
ok(!("globalprop2" in obj), "globalprop2 is still in obj");
}
obj.globalprop3 = true;
ok(globalprop3, "globalprop3 = " + globalprop3);
r = false;
try {
delete globalprop3;
}catch(ex) {
r = true;
}
if(v < 9) {
ok(r, "did not get an expected exception");
ok("globalprop3" in obj, "globalprop3 is not in obj");
}else {
ok(!r, "got an unexpected globalprop3 exception");
ok(!("globalprop3" in obj), "globalprop3 is still in obj");
}
globalprop4 = true;
ok(obj.globalprop4, "globalprop4 = " + globalprop4);
r = (delete globalprop4);
ok(r, "delete returned " + r);
todo_wine.
ok(!("globalprop4" in obj), "globalprop4 is still in obj");
});
var func_scope_val = 1;
var func_scope_val2 = 2;
sync_test("func_scope", function() {
var func_scope_val = 2;
var f = function func_scope_val() {
return func_scope_val;
};
func_scope_val = 3;
if(document.documentMode < 9) {
ok(f() === 3, "f() = " + f());
return;
}
ok(f === f(), "f() = " + f());
f = function func_scope_val(a) {
func_scope_val = 4;
return func_scope_val;
};
func_scope_val = 3;
ok(f === f(), "f() = " + f());
ok(func_scope_val === 3, "func_scope_val = " + func_scope_val);
ok(window.func_scope_val === 1, "window.func_scope_val = " + window.func_scope_val);
f = function func_scope_val(a) {
return (function() { return a ? func_scope_val(false) : func_scope_val; })();
};
ok(f === f(true), "f(true) = " + f(true));
window = 1;
ok(window === window.self, "window = " + window);
! function func_scope_val2() {};
ok(window.func_scope_val2 === 2, "window.func_scope_val2 = " + window.func_scope_val2);
var o = {};
(function(x) {
ok(x === o, "x = " + x);
! function x() {};
ok(x === o, "x != o");
})(o);
(function(x) {
ok(x === o, "x = " + x);
1, function x() {};
ok(x === o, "x != o");
})(o);
(function() {
! function x() {};
try {
x();
ok(false, "expected exception");
}catch(e) {}
})(o);
});
sync_test("set_obj", function() {
if(!("Set" in window)) return;
var s = new Set, r;
ok(Object.getPrototypeOf(s) === Set.prototype, "unexpected Set prototype");
function test_length(name, len) {
ok(Set.prototype[name].length === len, "Set.prototype." + name + " = " + Set.prototype[name].length);
try {
Set.prototype[name].call({}, 0);
ok(false, "expected exception calling Set.prototype." + name + "(object)");
}catch(e) {
ok(e.number === 0xa13fc - 0x80000000, "Set.prototype." + name + "(object) threw " + e.number);
}
}
test_length("add", 1);
test_length("clear", 0);
test_length("delete", 1);
test_length("forEach", 1);
test_length("has", 1);
ok(!("entries" in s), "entries are in Set");
ok(!("keys" in s), "keys are in Set");
ok(!("values" in s), "values are in Set");
r = Object.prototype.toString.call(s);
ok(r === "[object Object]", "toString returned " + r);
r = s.has(-0);
ok(r === false, "has(-0) returned " + r);
ok(s.size === 0, "size = " + s.size);
r = s.add(42);
ok(r === undefined, "add(42) returned " + r);
r = s.add(42);
ok(r === undefined, "add(42) returned " + r);
r = s.add(0);
ok(r === undefined, "add(0) returned " + r);
r = s.has(-0);
ok(r === false, "has(-0) returned " + r);
r = s.add(-0);
ok(r === undefined, "add(-0) returned " + r);
r = s.has(-0);
ok(r === true, "has(-0) after add returned " + r);
r = s.add("test");
ok(r === undefined, "add(test) returned " + r);
r = s.add(13);
ok(r === undefined, "add(13) returned " + r);
r = s.add(s);
ok(r === undefined, "add(s) returned " + r);
r = s["delete"]("test"); /* using s.delete() would break parsing in quirks mode */
ok(r === true, "delete(test) returned " + r);
r = s["delete"]("test");
ok(r === false, "delete(test) returned " + r);
ok(s.size === 5, "size = " + s.size);
s.size = 100;
ok(s.size === 5, "size (after set) = " + s.size);
var a = [];
r = s.forEach(function(value, key, obj) {
var t = s["delete"](key);
ok(t === true, "delete(" + key + ") returned " + r);
ok(value === key, "value = " + value + ", key = " + key);
ok(obj === s, "set = " + obj);
ok(this === a, "this = " + this);
a.push(value);
}, a);
ok(r === undefined, "forEach returned " + r);
ok(a.length === 5, "a.length = " + a.length);
for(var i = 0; i < a.length; i++)
ok(a[i] === [42, 0, -0, 13, s][i], "a[" + i + "] = " + a[i]);
ok(s.size === 0, "size = " + s.size);
s = new Set();
ok(s.size === 0, "size = " + s.size);
s.add(1);
s.add(2);
ok(s.size === 2, "size = " + s.size);
r = s.clear();
ok(r === undefined, "clear returned " + r);
ok(s.size === 0, "size = " + s.size);
s = new Set([1, 2, 3]);
ok(s.size === 0, "size = " + s.size);
});
sync_test("map_obj", function() {
if(!("Map" in window)) return;
var s = new Map, r, i;
ok(Object.getPrototypeOf(s) === Map.prototype, "unexpected Map prototype");
function test_length(name, len) {
ok(Map.prototype[name].length === len, "Map.prototype." + name + " = " + Map.prototype[name].length);
}
test_length("clear", 0);
test_length("delete", 1);
test_length("forEach", 1);
test_length("get", 1);
test_length("has", 1);
test_length("set", 2);
ok(!("entries" in s), "entries are in Map");
ok(!("keys" in s), "keys are in Map");
ok(!("values" in s), "values are in Map");
todo_wine.
ok("size" in Map.prototype, "size is not in Map.prototype");
r = Object.prototype.toString.call(s);
ok(r === "[object Object]", "toString returned " + r);
r = s.get("test");
ok(r === undefined, "get(test) returned " + r);
r = s.has("test");
ok(r === false, "has(test) returned " + r);
ok(s.size === 0, "size = " + s.size + " expected 0");
r = s.set("test", 1);
ok(r === undefined, "set returned " + r);
ok(s.size === 1, "size = " + s.size + " expected 1");
r = s.get("test");
ok(r === 1, "get(test) returned " + r);
r = s.has("test");
ok(r === true, "has(test) returned " + r);
s.size = 100;
ok(s.size === 1, "size = " + s.size + " expected 1");
s.set("test", 2);
r = s.get("test");
ok(r === 2, "get(test) returned " + r);
r = s.has("test");
ok(r === true, "has(test) returned " + r);
r = s["delete"]("test"); /* using s.delete() would break parsing in quirks mode */
ok(r === true, "delete(test) returned " + r);
ok(s.size === 0, "size = " + s.size + " expected 0");
r = s["delete"]("test");
ok(r === false, "delete(test) returned " + r);
var test_keys = [undefined, null, NaN, 3, "str", false, true, {}];
for(i in test_keys) {
r = s.set(test_keys[i], test_keys[i] + 1);
ok(r === undefined, "set(test) returned " + r);
}
ok(s.size === test_keys.length, "size = " + s.size + " expected " + test_keys.length);
for(i in test_keys) {
r = s.get(test_keys[i]);
if(isNaN(test_keys[i]))
ok(isNaN(r), "get(" + test_keys[i] + ") returned " + r);
else
ok(r === test_keys[i] + 1, "get(" + test_keys[i] + ") returned " + r);
}
var calls = [];
i = 0;
r = s.forEach(function(value, key, map) {
if(isNaN(test_keys[i])) {
ok(isNaN(key), "key = " + key + " expected NaN");
ok(isNaN(value), "value = " + value + " expected NaN");
}else {
ok(key === test_keys[i], "key = " + key + " expected " + test_keys[i]);
ok(value === key + 1, "value = " + value);
}
ok(map === s, "map = " + map);
ok(this === test_keys, "this = " + this);
i++;
}, test_keys);
ok(i === test_keys.length, "i = " + i);
ok(r === undefined, "forEach returned " + r);
s.set(3, "test2")
calls = [];
i = 0;
s.forEach(function(value, key) {
if(isNaN(test_keys[i]))
ok(isNaN(key), "key = " + key + " expected " + test_keys[i]);
else
ok(key === test_keys[i], "key = " + key + " expected " + test_keys[i]);
i++;
});
ok(i === test_keys.length, "i = " + i);
r = s.clear();
ok(r === undefined, "clear returned " + r);
ok(s.size === 0, "size = " + s.size + " expected 0");
r = s.get(test_keys[0]);
ok(r === undefined, "get returned " + r);
s = new Map();
s.set(1, 10);
s.set(2, 20);
s.set(3, 30);
i = true;
s.forEach(function() {
ok(i, "unexpected call");
s.clear();
i = false;
});
s = new Map();
s.set(1, 10);
s.set(2, 20);
s.set(3, 30);
i = 0;
s.forEach(function(value, key) {
i += key + value;
r = s["delete"](key);
ok(r === true, "delete returned " + r);
});
ok(i === 66, "i = " + i);
s = new Map();
s.set(0, 10);
s.set(-0, 20);
ok(s.size === 2, "size = " + s.size + " expected 2");
r = s.get(-0);
ok(r === 20, "get(-0) returned " + r);
r = s.get(0);
ok(r === 10, "get(0) returned " + r);
try {
Map.prototype.set.call({}, 1, 2);
ok(false, "expected exception");
}catch(e) {
ok(e.number === 0xa13fc - 0x80000000, "e.number = " + e.number);
}
});
sync_test("elem_attr", function() {
var v = document.documentMode;
var elem = document.createElement("div"), r;
function test_exposed(prop, expect) {
if(expect)
ok(prop in elem, prop + " is not exposed from elem");
else
ok(!(prop in elem), prop + " is exposed from elem");
}
r = elem.getAttribute("class");
ok(r === null, "class attr = " + r);
r = elem.getAttribute("className");
ok(r === (v < 8 ? "" : null), "className attr = " + r);
elem.className = "cls";
r = elem.getAttribute("class");
ok(r === (v < 8 ? null : "cls"), "class attr = " + r);
r = elem.getAttribute("className");
ok(r === (v < 8 ? "cls" : null), "className attr = " + r);
elem.setAttribute("class", "cls2");
ok(elem.className === (v < 8 ? "cls" : "cls2"), "elem.className = " + elem.className);
r = elem.getAttribute("class");
ok(r === "cls2", "class attr = " + r);
r = elem.getAttribute("className");
ok(r === (v < 8 ? "cls" : null), "className attr = " + r);
elem.setAttribute("className", "cls3");
ok(elem.className === (v < 8 ? "cls3" : "cls2"), "elem.className = " + elem.className);
r = elem.getAttribute("class");
ok(r === "cls2", "class attr = " + r);
r = elem.getAttribute("className");
ok(r === "cls3", "className attr = " + r);
elem.htmlFor = "for";
r = elem.getAttribute("for");
ok(r === null, "for attr = " + r);
r = elem.getAttribute("htmlFor");
ok(r === (v < 9 ? "for" : null), "htmlFor attr = " + r);
elem.setAttribute("for", "for2");
ok(elem.htmlFor === "for", "elem.htmlFor = " + elem.htmlFor);
r = elem.getAttribute("for");
ok(r === "for2", "for attr = " + r);
r = elem.getAttribute("htmlFor");
ok(r === (v < 9 ? "for" : null), "htmlFor attr = " + r);
elem.setAttribute("htmlFor", "for3");
ok(elem.htmlFor === (v < 9 ? "for3" : "for"), "elem.htmlFor = " + elem.htmlFor);
r = elem.getAttribute("for");
ok(r === "for2", "for attr = " + r);
r = elem.getAttribute("htmlFor");
ok(r === "for3", "htmlFor attr = " + r);
elem.setAttribute("testattr", "test", 0, "extra arg", 0xdeadbeef);
test_exposed("class", v < 8);
test_exposed("className", true);
test_exposed("for", v < 9);
test_exposed("htmlFor", true);
test_exposed("testattr", v < 9);
var arr = [3];
elem.setAttribute("testattr", arr);
r = elem.getAttribute("testattr");
ok(r === (v < 8 ? arr : "3"), "testattr = " + r);
ok(elem.testattr === (v < 9 ? arr : undefined), "elem.testattr = " + elem.testattr);
r = elem.removeAttribute("testattr");
ok(r === (v < 9 ? true : undefined), "testattr removeAttribute returned " + r);
ok(elem.testattr === undefined, "removed testattr = " + elem.testattr);
arr[0] = 9;
elem.setAttribute("testattr", "string");
elem.testattr = arr;
r = elem.getAttribute("testattr");
ok(r === (v < 8 ? arr : (v < 9 ? "9" : "string")), "testattr = " + r);
ok(elem.testattr === arr, "elem.testattr = " + elem.testattr);
arr[0] = 3;
r = elem.getAttribute("testattr");
ok(r === (v < 8 ? arr : (v < 9 ? "3" : "string")), "testattr = " + r);
ok(elem.testattr === arr, "elem.testattr = " + elem.testattr);
r = elem.removeAttribute("testattr");
ok(r === (v < 9 ? true : undefined), "testattr removeAttribute returned " + r);
ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr = " + elem.testattr);
arr.toString = function() { return 42; }
elem.testattr = arr;
r = elem.getAttribute("testattr");
ok(r === (v < 8 ? arr : (v < 9 ? "42" : null)), "testattr with custom toString = " + r);
elem.setAttribute("testattr", arr);
r = elem.getAttribute("testattr");
ok(r === (v < 8 ? arr : "42"), "testattr after setAttribute with custom toString = " + r);
ok(elem.testattr === arr, "elem.testattr after setAttribute with custom toString = " + elem.testattr);
r = elem.removeAttribute("testattr");
ok(r === (v < 9 ? true : undefined), "testattr removeAttribute with custom toString returned " + r);
ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr with custom toString = " + elem.testattr);
arr.valueOf = function() { return "arrval"; }
elem.testattr = arr;
r = elem.getAttribute("testattr");
ok(r === (v < 8 ? arr : (v < 9 ? "arrval" : null)), "testattr with custom valueOf = " + r);
elem.setAttribute("testattr", arr);
r = elem.getAttribute("testattr");
ok(r === (v < 8 ? arr : (v < 10 ? "arrval" : "42")), "testattr after setAttribute with custom valueOf = " + r);
ok(elem.testattr === arr, "elem.testattr after setAttribute with custom valueOf = " + elem.testattr);
r = elem.removeAttribute("testattr");
ok(r === (v < 9 ? true : undefined), "testattr removeAttribute with custom valueOf returned " + r);
ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr with custom valueOf = " + elem.testattr);
var func = elem.setAttribute;
try {
func("testattr", arr);
todo_wine_if(v >= 9).
ok(v < 9, "expected exception setting testattr via func");
}catch(ex) {
ok(v >= 9, "did not expect exception setting testattr via func");
elem.setAttribute("testattr", arr);
}
r = elem.getAttribute("testattr");
ok(r === (v < 8 ? arr : (v < 10 ? "arrval" : "42")), "testattr after setAttribute (as func) = " + r);
delete arr.valueOf;
delete arr.toString;
elem.setAttribute("id", arr);
r = elem.getAttribute("id");
todo_wine_if(v >= 8 && v < 10).
ok(r === (v < 8 || v >= 10 ? "3" : "[object]"), "id = " + r);
r = elem.removeAttribute("id");
ok(r === (v < 9 ? true : undefined), "id removeAttribute returned " + r);
ok(elem.id === "", "removed id = " + elem.id);
func = function() { };
elem.onclick = func;
ok(elem.onclick === func, "onclick = " + elem.onclick);
r = elem.getAttribute("onclick");
todo_wine_if(v === 8).
ok(r === (v < 8 ? func : null), "onclick attr = " + r);
r = elem.removeAttribute("onclick");
ok(r === (v < 9 ? false : undefined), "removeAttribute returned " + r);
todo_wine_if(v === 8).
ok(elem.onclick === (v != 8 ? func : null), "removed onclick = " + elem.onclick);
elem.onclick_test = func;
ok(elem.onclick_test === func, "onclick_test = " + elem.onclick_test);
r = elem.getAttribute("onclick_test");
ok(r === (v < 8 ? func : (v < 9 ? func.toString() : null)), "onclick_test attr = " + r);
elem.setAttribute("onclick", "test");
r = elem.getAttribute("onclick");
ok(r === "test", "onclick attr after setAttribute = " + r);
r = elem.removeAttribute("onclick");
ok(r === (v < 9 ? true : undefined), "removeAttribute after setAttribute returned " + r);
/* IE11 returns an empty function, which we can't check directly */
todo_wine_if(v >= 9).
ok((v < 11) ? (elem.onclick === null) : (elem.onclick !== func), "removed onclick after setAttribute = " + elem.onclick);
r = Object.prototype.toString.call(elem.onclick);
todo_wine_if(v >= 9 && v < 11).
ok(r === (v < 9 ? "[object Object]" : (v < 11 ? "[object Null]" : "[object Function]")),
"removed onclick after setAttribute Object.toString returned " + r);
elem.setAttribute("onclick", "string");
r = elem.getAttribute("onclick");
ok(r === "string", "onclick attr after setAttribute = " + r);
elem.onclick = func;
ok(elem.onclick === func, "onclick = " + elem.onclick);
r = elem.getAttribute("onclick");
todo_wine_if(v === 8).
ok(r === (v < 8 ? func : (v < 9 ? null : "string")), "onclick attr = " + r);
elem.onclick = "test";
r = elem.getAttribute("onclick");
ok(r === (v < 9 ? "test" : "string"), "onclick attr = " + r);
r = elem.removeAttribute("onclick");
ok(r === (v < 9 ? true : undefined), "removeAttribute returned " + r);
todo_wine_if(v >= 9).
ok(elem.onclick === null, "removed onclick = " + elem.onclick);
elem.setAttribute("ondblclick", arr);
r = elem.getAttribute("ondblclick");
todo_wine_if(v >= 8 && v < 10).
ok(r === (v < 8 ? arr : (v < 10 ? "[object]" : "3")), "ondblclick = " + r);
r = elem.removeAttribute("ondblclick");
ok(r === (v < 8 ? false : (v < 9 ? true : undefined)), "ondblclick removeAttribute returned " + r);
r = Object.prototype.toString.call(elem.ondblclick);
todo_wine_if(v >= 11).
ok(r === (v < 8 ? "[object Array]" : (v < 9 ? "[object Object]" : (v < 11 ? "[object Null]" : "[object Function]"))),
"removed ondblclick Object.toString returned " + r);
elem.setAttribute("ondblclick", "string");
r = elem.getAttribute("ondblclick");
ok(r === "string", "ondblclick string = " + r);
r = elem.removeAttribute("ondblclick");
ok(r === (v < 9 ? true : undefined), "ondblclick string removeAttribute returned " + r);
ok(elem.ondblclick === null, "removed ondblclick string = " + elem.ondblclick);
if(v < 9) {
/* style is a special case */
try {
elem.style = "opacity: 1.0";
ok(false, "expected exception setting elem.style");
}catch(ex) { }
var style = elem.style;
r = elem.getAttribute("style");
ok(r === (v < 8 ? style : null), "style attr = " + r);
r = elem.removeAttribute("style");
ok(r === true, "removeAttribute('style') returned " + r);
r = elem.style;
ok(r === style, "removed elem.style = " + r);
r = elem.getAttribute("style");
ok(r === (v < 8 ? style : null), "style attr after removal = " + r);
elem.setAttribute("style", "opacity: 1.0");
r = elem.getAttribute("style");
ok(r === (v < 8 ? style : "opacity: 1.0"), "style attr after setAttribute = " + r);
r = elem.style;
ok(r === style, "elem.style after setAttribute = " + r);
}
});
sync_test("builtins_diffs", function() {
var v = document.documentMode;
/* despite what spec says for ES6, IE still throws */
var props = [
"freeze",
"getPrototypeOf",
"isExtensible",
"isFrozen",
"isSealed",
"keys",
"preventExtensions",
"seal"
];
for(var i = 0; i < props.length; i++) {
try {
Object[props[i]]("test");
ok(false, "Object." + props[i] + " with non-object: expected exception");
}catch(e) {
ok(e.number === (v < 9 ? 0xa01b6 : 0xa138f) - 0x80000000, "Object." + props[i] + " with non-object: exception = " + e.number);
}
}
try {
RegExp.prototype.toString.call({source: "foo", flags: "g"});
ok(false, "RegExp.toString with non-regexp: expected exception");
}catch(e) {
ok(e.number === 0xa1398 - 0x80000000, "RegExp.toString with non-regexp: exception = " + e.number);
}
try {
/a/.lastIndex();
ok(false, "/a/.lastIndex(): expected exception");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "/a/.lastIndex(): exception = " + e.number);
}
try {
"a".length();
ok(false, "\"a\".length(): expected exception");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "\"a\".length(): exception = " + e.number);
}
});
sync_test("nullDisp", function() {
var v = document.documentMode, nullDisp = external.nullDisp, r;
ok(external.getVT(nullDisp) === "VT_NULL", "getVT(nullDisp) is not VT_NULL");
ok(typeof(nullDisp) === "object", "typeof(nullDisp) = " + typeof(nullDisp));
ok(nullDisp === nullDisp, "nullDisp !== nullDisp");
ok(nullDisp === null, "nullDisp === null");
ok(nullDisp == null, "nullDisp == null");
ok(!nullDisp === true, "!nullDisp = " + !nullDisp);
ok(String(nullDisp) === "null", "String(nullDisp) = " + String(nullDisp));
ok(+nullDisp === 0, "+nullDisp !== 0");
ok(''+nullDisp === "null", "''+nullDisp !== null");
ok(nullDisp != new Object(), "nullDisp == new Object()");
ok(new Object() != nullDisp, "new Object() == nullDisp");
ok((typeof Object(nullDisp)) === "object", "typeof Object(nullDisp) !== 'object'");
r = Object(nullDisp).toString();
ok(r === "[object Object]", "Object(nullDisp).toString() = " + r);
ok(Object(nullDisp) != nullDisp, "Object(nullDisp) == nullDisp");
ok(new Object(nullDisp) != nullDisp, "new Object(nullDisp) == nullDisp");
r = (nullDisp instanceof Object);
ok(r === false, "nullDisp instance of Object");
if(v >= 8) {
r = JSON.stringify.call(null, nullDisp);
ok(r === "null", "JSON.stringify(nullDisp) returned " + r);
}
try {
(new Object()) instanceof nullDisp;
ok(false, "expected exception on (new Object()) instanceof nullDisp");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "(new Object()) instanceof nullDisp threw " + e.number);
}
try {
Function.prototype.apply.call(nullDisp, Object, []);
ok(false, "expected exception calling Function.apply on nullDisp");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "Function.apply on nullDisp threw " + e.number);
}
try {
Function.prototype.call.call(nullDisp, Object);
ok(false, "expected exception calling Function.call on nullDisp");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "Function.call on nullDisp threw " + e.number);
}
try {
new nullDisp;
ok(false, "expected exception for new nullDisp");
}catch(e) {
ok(e.number === 0xa138f - 0x80000000, "new nullDisp threw " + e.number);
}
});
sync_test("__proto__", function() {
var v = document.documentMode;
var r, x = 42;
if(v < 11) {
ok(x.__proto__ === undefined, "x.__proto__ = " + x.__proto__);
ok(!("__proto__" in Object), "Object.__proto__ = " + Object.__proto__);
return;
}
ok(x.__proto__ === Number.prototype, "x.__proto__ = " + x.__proto__);
ok(Object.__proto__ === Function.prototype, "Object.__proto__ = " + Object.__proto__);
ok(Object.prototype.__proto__ === null, "Object.prototype.__proto__ = " + Object.prototype.__proto__);
ok(Object.prototype.hasOwnProperty("__proto__"), "__proto__ is not a property of Object.prototype");
ok(!Object.prototype.hasOwnProperty.call(x, "__proto__"), "__proto__ is a property of x");
x.__proto__ = Object.prototype;
ok(x.__proto__ === Number.prototype, "x.__proto__ set to Object.prototype = " + x.__proto__);
ok(!Object.prototype.hasOwnProperty.call(x, "__proto__"), "__proto__ is a property of x after set to Object.prototype");
x = {};
x.__proto__ = null;
r = Object.getPrototypeOf(x);
ok(x.__proto__ === undefined, "x.__proto__ after set to null = " + x.__proto__);
ok(r === null, "getPrototypeOf(x) after set to null = " + r);
function check(expect, msg) {
var r = Object.getPrototypeOf(x);
ok(x.__proto__ === expect, "x.__proto__ " + msg + " = " + x.__proto__);
ok(r === expect, "getPrototypeOf(x) " + msg + " = " + r);
ok(!Object.prototype.hasOwnProperty.call(x, "__proto__"), "__proto__ is a property of x " + msg);
}
x = {};
check(Object.prototype, "after x set to {}");
x.__proto__ = Number.prototype;
check(Number.prototype, "after set to Number.prototype");
x.__proto__ = Object.prototype;
check(Object.prototype, "after re-set to Object.prototype");
function ctor() { }
var obj = new ctor();
x.__proto__ = obj;
check(obj, "after set to obj");
x.__proto__ = ctor.prototype;
check(obj.__proto__, "after set to ctor.prototype");
ok(obj.__proto__ === ctor.prototype, "obj.__proto__ !== ctor.prototype");
r = (delete x.__proto__);
ok(r, "delete x.__proto__ returned " + r);
ok(Object.prototype.hasOwnProperty("__proto__"), "__proto__ is not a property of Object.prototype after delete");
r = Object.getPrototypeOf(x);
ok(r === ctor.prototype, "x.__proto__ after delete = " + r);
var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__");
ok(desc.value === undefined, "__proto__ value = " + desc.value);
ok(Object.getPrototypeOf(desc.get) === Function.prototype, "__proto__ getter not a function");
ok(Object.getPrototypeOf(desc.set) === Function.prototype, "__proto__ setter not a function");
ok(desc.get.length === 0, "__proto__ getter length = " + desc.get.length);
ok(desc.set.length === 1, "__proto__ setter length = " + desc.set.length);
r = desc.get.call(x, 1, 2, 3, 4);
ok(r === x.__proto__, "calling __proto__ getter on x returned " + r);
r = desc.set.call(x, obj);
ok(r === obj, "calling __proto__ setter(obj) on x returned " + r);
check(obj, "after set to obj via calling setter");
r = desc.set.call(x, 42);
ok(r === 42, "calling __proto__ setter(42) on x returned " + r);
check(obj, "after set to obj via calling setter(42)");
r = desc.set.call(x, "foo");
ok(r === "foo", "calling __proto__ setter('foo') on x returned " + r);
check(obj, "after set to obj via calling setter('foo')");
r = desc.set.call(x);
ok(r === undefined, "calling __proto__ setter() on x returned " + r);
r = desc.set.call(true, obj);
ok(r === obj, "calling __proto__ setter(obj) on true value returned " + r);
x = true;
r = desc.set.call(x, obj);
ok(r === obj, "calling __proto__ setter(obj) on x set to true returned " + r);
ok(x.__proto__ === Boolean.prototype, "true value __proto__ after set to obj = " + x.__proto__);
x = new Boolean(true);
r = desc.set.call(x, obj);
ok(r === obj, "calling __proto__ setter(obj) on x set to Boolean(true) returned " + r);
ok(x.__proto__ === obj, "Boolean(true) __proto__ after set to obj = " + x.__proto__);
r = desc.get.call(13);
ok(r === Number.prototype, "calling __proto__ getter on 13 returned " + r);
try {
r = desc.get.call(undefined);
ok(false, "expected exception calling __proto__ getter on undefined");
}catch(e) {
ok(e.number === 0xa138f - 0x80000000, "calling __proto__ getter on undefined threw exception " + e.number);
}
try {
r = desc.get.call(null);
ok(false, "expected exception calling __proto__ getter on null");
}catch(e) {
ok(e.number === 0xa138f - 0x80000000, "calling __proto__ getter on null threw exception " + e.number);
}
try {
r = desc.set.call(undefined, obj);
ok(false, "expected exception calling __proto__ setter on undefined");
}catch(e) {
ok(e.number === 0xa138f - 0x80000000, "calling __proto__ setter on undefined threw exception " + e.number);
}
try {
r = desc.set.call(null, obj);
ok(false, "expected exception calling __proto__ setter on null");
}catch(e) {
ok(e.number === 0xa138f - 0x80000000, "calling __proto__ setter on null threw exception " + e.number);
}
x = {};
r = Object.create(x);
ok(r.__proto__ === x, "r.__proto__ = " + r.__proto__);
r = Object.create(r);
ok(r.__proto__.__proto__ === x, "r.__proto__.__proto__ = " + r.__proto__.__proto__);
try {
x.__proto__ = r;
ok(false, "expected exception setting circular proto chain");
}catch(e) {
ok(e.number === 0xa13b0 - 0x80000000 && e.name === "TypeError",
"setting circular proto chain threw exception " + e.number + " (" + e.name + ")");
}
Object.preventExtensions(x);
x.__proto__ = Object.prototype; /* same prototype */
try {
x.__proto__ = Number.prototype;
ok(false, "expected exception changing __proto__ on non-extensible object");
}catch(e) {
ok(e.number === 0xa13b6 - 0x80000000 && e.name === "TypeError",
"changing __proto__ on non-extensible object threw exception " + e.number + " (" + e.name + ")");
}
});
sync_test("__defineGetter__", function() {
var v = document.documentMode;
var r, x = 42;
if(v < 11) {
ok(x.__defineGetter__ === undefined, "x.__defineGetter__ = " + x.__defineGetter__);
ok(!("__defineGetter__" in Object), "Object.__defineGetter__ = " + Object.__defineGetter__);
return;
}
ok(Object.prototype.hasOwnProperty("__defineGetter__"), "__defineGetter__ is not a property of Object.prototype");
ok(Object.prototype.__defineGetter__.length === 2, "__defineGetter__.length = " + Object.prototype.__defineGetter__.length);
function getter() { return "wine"; }
function setter(val) { }
r = x.__defineGetter__("foo", getter);
ok(r === undefined, "__defineGetter__ on 42 returned " + r);
ok(x.foo === undefined, "42.foo = " + x.foo);
x = {};
r = x.__defineGetter__("foo", getter);
ok(r === undefined, "__defineGetter__ returned " + r);
ok(x.foo === "wine", "x.foo = " + x.foo);
r = Object.getOwnPropertyDescriptor(x, "foo");
ok(r.value === undefined, "x.foo value = " + r.value);
ok(r.get === getter, "x.foo get = " + r.get);
ok(r.set === undefined, "x.foo set = " + r.set);
ok(r.writable === undefined, "x.foo writable = " + r.writable);
ok(r.enumerable === true, "x.foo enumerable = " + r.enumerable);
ok(r.configurable === true, "x.foo configurable = " + r.configurable);
Object.defineProperty(x, "foo", { get: undefined, set: setter, configurable: false });
r = Object.getOwnPropertyDescriptor(x, "foo");
ok(r.value === undefined, "x.foo setter value = " + r.value);
ok(r.get === undefined, "x.foo setter get = " + r.get);
ok(r.set === setter, "x.foo setter set = " + r.set);
ok(r.writable === undefined, "x.foo setter writable = " + r.writable);
ok(r.enumerable === true, "x.foo setter enumerable = " + r.enumerable);
ok(r.configurable === false, "x.foo setter configurable = " + r.configurable);
try {
x.__defineGetter__("foo", getter);
ok(false, "expected exception calling __defineGetter__ on non-configurable property");
}catch(e) {
ok(e.number === 0xa13d6 - 0x80000000, "__defineGetter__ on non-configurable property threw exception " + e.number);
}
r = Object.prototype.__defineGetter__.call(undefined, "bar", getter);
ok(r === undefined, "__defineGetter__ on undefined returned " + r);
r = Object.prototype.__defineGetter__.call(null, "bar", getter);
ok(r === undefined, "__defineGetter__ on null returned " + r);
r = x.__defineGetter__(undefined, getter);
ok(r === undefined, "__defineGetter__ undefined prop returned " + r);
ok(x["undefined"] === "wine", "x.undefined = " + x["undefined"]);
r = x.__defineGetter__(false, getter);
ok(r === undefined, "__defineGetter__ undefined prop returned " + r);
ok(x["false"] === "wine", "x.false = " + x["false"]);
try {
x.__defineGetter__("bar", "string");
ok(false, "expected exception calling __defineGetter__ with string");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with string threw exception " + e.number);
}
try {
x.__defineGetter__("bar", undefined);
ok(false, "expected exception calling __defineGetter__ with undefined");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with undefined threw exception " + e.number);
}
try {
x.__defineGetter__("bar", null);
ok(false, "expected exception calling __defineGetter__ with null");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with null threw exception " + e.number);
}
try {
Object.prototype.__defineGetter__.call(x, "bar");
ok(false, "expected exception calling __defineGetter__ with only one arg");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "__defineGetter__ with only one arg threw exception " + e.number);
}
x.bar = "test";
ok(x.bar === "test", "x.bar = " + x.bar);
x.__defineGetter__("bar", getter);
ok(x.bar === "wine", "x.bar with getter = " + x.bar);
});
sync_test("__defineSetter__", function() {
var v = document.documentMode;
var r, x = 42;
if(v < 11) {
ok(x.__defineSetter__ === undefined, "x.__defineSetter__ = " + x.__defineSetter__);
ok(!("__defineSetter__" in Object), "Object.__defineSetter__ = " + Object.__defineSetter__);
return;
}
ok(Object.prototype.hasOwnProperty("__defineSetter__"), "__defineSetter__ is not a property of Object.prototype");
ok(Object.prototype.__defineSetter__.length === 2, "__defineSetter__.length = " + Object.prototype.__defineSetter__.length);
function getter() { return "wine"; }
function setter(val) { this.setterVal = val - 1; }
r = x.__defineSetter__("foo", setter);
ok(r === undefined, "__defineSetter__ on 42 returned " + r);
ok(x.foo === undefined, "42.foo = " + x.foo);
x = {};
r = x.__defineSetter__("foo", setter);
ok(r === undefined, "__defineSetter__ returned " + r);
ok(x.setterVal === undefined, "x.setterVal = " + x.setterVal);
x.foo = 13;
ok(x.setterVal === 12, "x.setterVal = " + x.setterVal);
r = Object.getOwnPropertyDescriptor(x, "foo");
ok(r.value === undefined, "x.foo value = " + r.value);
ok(r.get === undefined, "x.foo get = " + r.get);
ok(r.set === setter, "x.foo set = " + r.set);
ok(r.writable === undefined, "x.foo writable = " + r.writable);
ok(r.enumerable === true, "x.foo enumerable = " + r.enumerable);
ok(r.configurable === true, "x.foo configurable = " + r.configurable);
Object.defineProperty(x, "foo", { get: getter, set: undefined, configurable: false });
r = Object.getOwnPropertyDescriptor(x, "foo");
ok(r.value === undefined, "x.foo getter value = " + r.value);
ok(r.get === getter, "x.foo getter get = " + r.get);
ok(r.set === undefined, "x.foo getter set = " + r.set);
ok(r.writable === undefined, "x.foo getter writable = " + r.writable);
ok(r.enumerable === true, "x.foo getter enumerable = " + r.enumerable);
ok(r.configurable === false, "x.foo getter configurable = " + r.configurable);
try {
x.__defineSetter__("foo", setter);
ok(false, "expected exception calling __defineSetter__ on non-configurable property");
}catch(e) {
ok(e.number === 0xa13d6 - 0x80000000, "__defineSetter__ on non-configurable property threw exception " + e.number);
}
r = Object.prototype.__defineSetter__.call(undefined, "bar", setter);
ok(r === undefined, "__defineSetter__ on undefined returned " + r);
r = Object.prototype.__defineSetter__.call(null, "bar", setter);
ok(r === undefined, "__defineSetter__ on null returned " + r);
r = x.__defineSetter__(null, setter);
ok(r === undefined, "__defineSetter__ null prop returned " + r);
x["null"] = 100;
ok(x.setterVal === 99, "x.setterVal after setting x.null = " + x.setterVal);
r = x.__defineSetter__(50, setter);
ok(r === undefined, "__defineSetter__ 50 prop returned " + r);
x["50"] = 33;
ok(x.setterVal === 32, "x.setterVal after setting x.50 = " + x.setterVal);
try {
x.__defineSetter__("bar", true);
ok(false, "expected exception calling __defineSetter__ with bool");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with bool threw exception " + e.number);
}
try {
x.__defineSetter__("bar", undefined);
ok(false, "expected exception calling __defineSetter__ with undefined");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with undefined threw exception " + e.number);
}
try {
x.__defineSetter__("bar", null);
ok(false, "expected exception calling __defineSetter__ with null");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with null threw exception " + e.number);
}
try {
Object.prototype.__defineSetter__.call(x, "bar");
ok(false, "expected exception calling __defineSetter__ with only one arg");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "__defineSetter__ with only one arg threw exception " + e.number);
}
x.bar = "test";
ok(x.bar === "test", "x.bar = " + x.bar);
x.__defineSetter__("bar", setter);
ok(x.bar === undefined, "x.bar with setter = " + x.bar);
x.bar = 10;
ok(x.bar === undefined, "x.bar with setter = " + x.bar);
ok(x.setterVal === 9, "x.setterVal after setting bar = " + x.setterVal);
});
async_test("postMessage", function() {
var v = document.documentMode;
var onmessage_called = false;
window.onmessage = function() {
onmessage_called = true;
next_test();
}
window.postMessage("test", "*");
ok(onmessage_called == (v < 9 ? true : false), "onmessage not called");
});