diff options
Diffstat (limited to 'dom/bindings/test/test_bug1123516_maplikesetlike.html')
-rw-r--r-- | dom/bindings/test/test_bug1123516_maplikesetlike.html | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/dom/bindings/test/test_bug1123516_maplikesetlike.html b/dom/bindings/test/test_bug1123516_maplikesetlike.html new file mode 100644 index 0000000000..bc5048eb05 --- /dev/null +++ b/dom/bindings/test/test_bug1123516_maplikesetlike.html @@ -0,0 +1,278 @@ +<!-- Any copyright is dedicated to the Public Domain. +- http://creativecommons.org/publicdomain/zero/1.0/ --> +<!DOCTYPE HTML> +<html> + <head> + <title>Test Maplike Interface</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> + </head> + <body> + <script class="testbody" type="application/javascript"> + /* global TestInterfaceMaplike, TestInterfaceSetlike, TestInterfaceMaplikeObject, TestInterfaceMaplikeJSObject*/ + SimpleTest.waitForExplicitFinish(); + SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, function() { + var base_properties = [["has", "function", 1], + ["entries", "function", 0], + ["keys", "function", 0], + ["values", "function", 0], + ["forEach", "function", 1], + ["size", "number"]]; + var maplike_properties = base_properties.concat([["set", "function", 2]]); + var rw_properties = [["clear", "function", 0], + ["delete", "function", 1]]; + var setlike_rw_properties = base_properties.concat(rw_properties).concat([["add", "function", 1]]); + var maplike_rw_properties = maplike_properties.concat(rw_properties).concat([["get", "function", 1]]); + var testExistence = function testExistence(prefix, obj, properties) { + for (var [name, type, args] of properties) { + // Properties are somewhere up the proto chain, hasOwnProperty won't work + isnot(obj[name], undefined, + `${prefix} object has property ${name}`); + + is(typeof obj[name], type, + `${prefix} object property ${name} is a ${type}`); + // Check function length + if (type == "function") { + is(obj[name].length, args, + `${prefix} object property ${name} is length ${args}`); + is(obj[name].name, name, + `${prefix} object method name is ${name}`); + } + + // Find where property is on proto chain, check for enumerablility there. + var owner = obj; + while (owner) { + var propDesc = Object.getOwnPropertyDescriptor(owner, name); + if (propDesc) { + ok(propDesc.enumerable, + `${prefix} object property ${name} should be enumerable`); + break; + } + owner = Object.getPrototypeOf(owner); + } + } + }; + + var m; + var testSet; + var testIndex; + + // Simple map creation and functionality test + info("SimpleMap: Testing simple map creation and functionality"); + m = new TestInterfaceMaplike(); + ok(m, "SimpleMap: got a TestInterfaceMaplike object"); + testExistence("SimpleMap: ", m, maplike_rw_properties); + is(m.size, 0, "SimpleMap: size should be zero"); + ok(!m.has("test"), "SimpleMap: maplike has should return false"); + is(m.get("test"), undefined, "SimpleMap: maplike get should return undefined on bogus lookup"); + var m1 = m.set("test", 1); + is(m, m1, "SimpleMap: return from set should be map object"); + is(m.size, 1, "SimpleMap: size should be 1"); + ok(m.has("test"), "SimpleMap: maplike has should return true"); + is(m.get("test"), 1, "SimpleMap: maplike get should return value entered"); + m.set("test2", 2); + is(m.size, 2, "SimpleMap: size should be 2"); + testSet = [["test", 1], ["test2", 2]]; + testIndex = 0; + m.forEach(function(v, k, o) { + "use strict"; + is(o, m, "SimpleMap: foreach obj is correct"); + is(k, testSet[testIndex][0], "SimpleMap: foreach map key: " + k + " = " + testSet[testIndex][0]); + is(v, testSet[testIndex][1], "SimpleMap: foreach map value: " + v + " = " + testSet[testIndex][1]); + testIndex += 1; + }); + is(testIndex, 2, "SimpleMap: foreach ran correct number of times"); + ok(m.has("test2"), "SimpleMap: maplike has should return true"); + is(m.get("test2"), 2, "SimpleMap: maplike get should return value entered"); + is(m.delete("test2"), true, "SimpleMap: maplike deletion should return boolean"); + is(m.size, 1, "SimpleMap: size should be 1"); + var iterable = false; + for (let e of m) { + iterable = true; + is(e[0], "test", "SimpleMap: iterable first array element should be key"); + is(e[1], 1, "SimpleMap: iterable second array element should be value"); + } + is(m[Symbol.iterator].length, 0, "SimpleMap: @@iterator symbol is correct length"); + is(m[Symbol.iterator].name, "entries", "SimpleMap: @@iterator symbol has correct name"); + is(m[Symbol.iterator], m.entries, 'SimpleMap: @@iterator is an alias for "entries"'); + ok(iterable, "SimpleMap: @@iterator symbol resolved correctly"); + for (let k of m.keys()) { + is(k, "test", "SimpleMap: first keys element should be 'test'"); + } + for (let v of m.values()) { + is(v, 1, "SimpleMap: first values elements should be 1"); + } + for (let e of m.entries()) { + is(e[0], "test", "SimpleMap: entries first array element should be 'test'"); + is(e[1], 1, "SimpleMap: entries second array element should be 1"); + } + m.clear(); + is(m.size, 0, "SimpleMap: size should be 0 after clear"); + + // Simple set creation and functionality test + info("SimpleSet: Testing simple set creation and functionality"); + m = new TestInterfaceSetlike(); + ok(m, "SimpleSet: got a TestInterfaceSetlike object"); + testExistence("SimpleSet: ", m, setlike_rw_properties); + is(m.size, 0, "SimpleSet: size should be zero"); + ok(!m.has("test"), "SimpleSet: maplike has should return false"); + m1 = m.add("test"); + is(m, m1, "SimpleSet: return from set should be map object"); + is(m.size, 1, "SimpleSet: size should be 1"); + ok(m.has("test"), "SimpleSet: maplike has should return true"); + m.add("test2"); + is(m.size, 2, "SimpleSet: size should be 2"); + testSet = ["test", "test2"]; + testIndex = 0; + m.forEach(function(v, k, o) { + "use strict"; + is(o, m, "SimpleSet: foreach obj is correct"); + is(k, testSet[testIndex], "SimpleSet: foreach set key: " + k + " = " + testSet[testIndex]); + testIndex += 1; + }); + is(testIndex, 2, "SimpleSet: foreach ran correct number of times"); + ok(m.has("test2"), "SimpleSet: maplike has should return true"); + is(m.delete("test2"), true, "SimpleSet: maplike deletion should return true"); + is(m.size, 1, "SimpleSet: size should be 1"); + iterable = false; + for (let e of m) { + iterable = true; + is(e, "test", "SimpleSet: iterable first array element should be key"); + } + is(m[Symbol.iterator].length, 0, "SimpleSet: @@iterator symbol is correct length"); + is(m[Symbol.iterator].name, "values", "SimpleSet: @@iterator symbol has correct name"); + is(m[Symbol.iterator], m.values, 'SimpleSet: @@iterator is an alias for "values"'); + ok(iterable, "SimpleSet: @@iterator symbol resolved correctly"); + for (let k of m.keys()) { + is(k, "test", "SimpleSet: first keys element should be 'test'"); + } + for (let v of m.values()) { + is(v, "test", "SimpleSet: first values elements should be 'test'"); + } + for (let e of m.entries()) { + is(e[0], "test", "SimpleSet: Entries first array element should be 'test'"); + is(e[1], "test", "SimpleSet: Entries second array element should be 'test'"); + } + m.clear(); + is(m.size, 0, "SimpleSet: size should be 0 after clear"); + + // Map convenience function test + info("Testing map convenience functions"); + m = new TestInterfaceMaplike(); + ok(m, "MapConvenience: got a TestInterfaceMaplike object"); + is(m.size, 0, "MapConvenience: size should be zero"); + ok(!m.hasInternal("test"), "MapConvenience: maplike hasInternal should return false"); + // It's fine to let getInternal to return 0 if the key doesn't exist + // because this API can only be used internally in C++ and we'd throw + // an error if the key doesn't exist. + SimpleTest.doesThrow(() => m.getInternal("test"), 0, "MapConvenience: maplike getInternal should throw if the key doesn't exist"); + m.setInternal("test", 1); + is(m.size, 1, "MapConvenience: size should be 1"); + ok(m.hasInternal("test"), "MapConvenience: maplike hasInternal should return true"); + is(m.get("test"), 1, "MapConvenience: maplike get should return value entered"); + is(m.getInternal("test"), 1, "MapConvenience: maplike getInternal should return value entered"); + m.setInternal("test2", 2); + is(m.size, 2, "size should be 2"); + ok(m.hasInternal("test2"), "MapConvenience: maplike hasInternal should return true"); + is(m.get("test2"), 2, "MapConvenience: maplike get should return value entered"); + is(m.getInternal("test2"), 2, "MapConvenience: maplike getInternal should return value entered"); + is(m.deleteInternal("test2"), true, "MapConvenience: maplike deleteInternal should return true"); + is(m.size, 1, "MapConvenience: size should be 1"); + m.clearInternal(); + is(m.size, 0, "MapConvenience: size should be 0 after clearInternal"); + + // Map convenience function test using objects and readonly + + info("Testing Map convenience function test using objects and readonly"); + m = new TestInterfaceMaplikeObject(); + ok(m, "ReadOnlyMapConvenience: got a TestInterfaceMaplikeObject object"); + is(m.size, 0, "ReadOnlyMapConvenience: size should be zero"); + is(m.set, undefined, "ReadOnlyMapConvenience: readonly map, should be no set function"); + is(m.clear, undefined, "ReadOnlyMapConvenience: readonly map, should be no clear function"); + is(m.delete, undefined, "ReadOnlyMapConvenience: readonly map, should be no delete function"); + ok(!m.hasInternal("test"), "ReadOnlyMapConvenience: maplike hasInternal should return false"); + SimpleTest.doesThrow(() => m.getInternal("test"), "ReadOnlyMapConvenience: maplike getInternal should throw when the key doesn't exist"); + m.setInternal("test"); + is(m.size, 1, "size should be 1"); + ok(m.hasInternal("test"), "ReadOnlyMapConvenience: maplike hasInternal should return true"); + ok(m.getInternal("test") instanceof TestInterfaceMaplike, "ReadOnlyMapConvenience: maplike getInternal should return the object"); + m.setInternal("test2"); + is(m.size, 2, "size should be 2"); + ok(m.hasInternal("test2"), "ReadOnlyMapConvenience: maplike hasInternal should return true"); + ok(m.getInternal("test2") instanceof TestInterfaceMaplike, "ReadOnlyMapConvenience: maplike getInternal should return the object"); + is(m.deleteInternal("test2"), true, "ReadOnlyMapConvenience: maplike deleteInternal should return true"); + is(m.size, 1, "ReadOnlyMapConvenience: size should be 1"); + m.clearInternal(); + is(m.size, 0, "ReadOnlyMapConvenience: size should be 0 after clearInternal"); + + // Map convenience function test using JavaScript objects + info("Testing Map convenience function test using javascript objects"); + m = new TestInterfaceMaplikeJSObject(); + ok(m, "JSObjectMapConvenience: got a TestInterfaceMaplikeJSObject object"); + is(m.size, 0, "JSObjectMapConvenience: size should be zero"); + is(m.set, undefined, "JSObjectMapConvenience: readonly map, should be no set function"); + is(m.clear, undefined, "JSObjectMapConvenience: readonly map, should be no clear function"); + is(m.delete, undefined, "JSObjectMapConvenience: readonly map, should be no delete function"); + ok(!m.hasInternal("test"), "JSObjectMapConvenience: maplike hasInternal should return false"); + SimpleTest.doesThrow(() => m.getInternal("test"), "JSObjectMapConvenience: maplike getInternal should throw when the key doesn't exist"); + let testObject = {"Hey1": 1}; + m.setInternal("test", testObject); + is(m.size, 1, "size should be 1"); + ok(m.hasInternal("test"), "JSObjectMapConvenience: maplike hasInternal should return true"); + let addedObject = m.getInternal("test"); + is(addedObject, testObject, "JSObjectMapConvenience: maplike getInternal should return the object"); + testObject = {"Hey2": 2}; + m.setInternal("test2", testObject); + is(m.size, 2, "size should be 2"); + ok(m.hasInternal("test2"), "JSObjectMapConvenience: maplike hasInternal should return true"); + addedObject = m.getInternal("test2"); + is(addedObject, testObject, "JSObjectMapConvenience: maplike getInternal should return the object"); + is(m.deleteInternal("test2"), true, "JSObjectMapConvenience: maplike deleteInternal should return true"); + is(m.size, 1, "JSObjectMapConvenience: size should be 1"); + m.clearInternal(); + is(m.size, 0, "JSObjectMapConvenience: size should be 0 after clearInternal"); + // JS implemented map creation convenience function test + + // Test this override for forEach + info("ForEachThisOverride: Testing this override for forEach"); + m = new TestInterfaceMaplike(); + m.set("test", 1); + m.forEach(function(v, k, o) { + "use strict"; + is(o, m, "ForEachThisOverride: foreach obj is correct"); + is(this, 5, "ForEachThisOverride: 'this' value should be correct"); + }, 5); + + // Test defaulting arguments on maplike to undefined + info("MapArgsDefault: Testing maplike defaulting arguments to undefined"); + m = new TestInterfaceMaplike(); + m.set(); + is(m.size, 1, "MapArgsDefault: should have 1 entry"); + m.forEach(function(v, k) { + "use strict"; + is(typeof k, "string", "MapArgsDefault: key is a string"); + is(k, "undefined", "MapArgsDefault: key is the string undefined"); + is(v, 0, "MapArgsDefault: value is 0"); + }); + is(m.get(), 0, "MapArgsDefault: no argument to get() returns correct value"); + m.delete(); + is(m.size, 0, "MapArgsDefault: should have 0 entries"); + + // Test defaulting arguments on setlike to undefined + info("SetArgsDefault: Testing setlike defaulting arguments to undefined"); + m = new TestInterfaceSetlike(); + m.add(); + is(m.size, 1, "SetArgsDefault: should have 1 entry"); + m.forEach(function(v, k) { + "use strict"; + is(typeof k, "string", "SetArgsDefault: key is a string"); + is(k, "undefined", "SetArgsDefault: key is the string undefined"); + }); + m.delete(); + is(m.size, 0, "SetArgsDefault: should have 0 entries"); + + SimpleTest.finish(); + }); + </script> + </body> +</html> |