test_bug1123516_maplikesetlike.html (16766B)
1 <!-- Any copyright is dedicated to the Public Domain. 2 - http://creativecommons.org/publicdomain/zero/1.0/ --> 3 <!DOCTYPE HTML> 4 <html> 5 <head> 6 <title>Test Maplike Interface</title> 7 <script src="/tests/SimpleTest/SimpleTest.js"></script> 8 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 9 </head> 10 <body> 11 <script class="testbody" type="application/javascript"> 12 /* global TestInterfaceMaplike, TestInterfaceSetlike, TestInterfaceMaplikeObject, TestInterfaceMaplikeJSObject*/ 13 SimpleTest.waitForExplicitFinish(); 14 SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}, function() { 15 var base_properties = [["has", "function", 1], 16 ["entries", "function", 0], 17 ["keys", "function", 0], 18 ["values", "function", 0], 19 ["forEach", "function", 1], 20 ["size", "number"]]; 21 var maplike_properties = base_properties.concat([["set", "function", 2]]); 22 var rw_properties = [["clear", "function", 0], 23 ["delete", "function", 1]]; 24 var setlike_rw_properties = base_properties.concat(rw_properties).concat([["add", "function", 1]]); 25 var maplike_rw_properties = maplike_properties.concat(rw_properties).concat([["get", "function", 1]]); 26 var testExistence = function testExistence(prefix, obj, properties) { 27 for (var [name, type, args] of properties) { 28 // Properties are somewhere up the proto chain, hasOwnProperty won't work 29 isnot(obj[name], undefined, 30 `${prefix} object has property ${name}`); 31 32 is(typeof obj[name], type, 33 `${prefix} object property ${name} is a ${type}`); 34 // Check function length 35 if (type == "function") { 36 is(obj[name].length, args, 37 `${prefix} object property ${name} is length ${args}`); 38 is(obj[name].name, name, 39 `${prefix} object method name is ${name}`); 40 } 41 42 // Find where property is on proto chain, check for enumerablility there. 43 var owner = obj; 44 while (owner) { 45 var propDesc = Object.getOwnPropertyDescriptor(owner, name); 46 if (propDesc) { 47 ok(propDesc.enumerable, 48 `${prefix} object property ${name} should be enumerable`); 49 break; 50 } 51 owner = Object.getPrototypeOf(owner); 52 } 53 } 54 }; 55 56 var m; 57 var testSet; 58 var testIndex; 59 60 // Simple map creation and functionality test 61 info("SimpleMap: Testing simple map creation and functionality"); 62 m = new TestInterfaceMaplike(); 63 ok(m, "SimpleMap: got a TestInterfaceMaplike object"); 64 testExistence("SimpleMap: ", m, maplike_rw_properties); 65 is(m.size, 0, "SimpleMap: size should be zero"); 66 ok(!m.has("test"), "SimpleMap: maplike has should return false"); 67 is(m.get("test"), undefined, "SimpleMap: maplike get should return undefined on bogus lookup"); 68 var m1 = m.set("test", 1); 69 is(m, m1, "SimpleMap: return from set should be map object"); 70 is(m.size, 1, "SimpleMap: size should be 1"); 71 ok(m.has("test"), "SimpleMap: maplike has should return true"); 72 is(m.get("test"), 1, "SimpleMap: maplike get should return value entered"); 73 m.set("test2", 2); 74 is(m.size, 2, "SimpleMap: size should be 2"); 75 testSet = [["test", 1], ["test2", 2]]; 76 testIndex = 0; 77 m.forEach(function(v, k, o) { 78 "use strict"; 79 is(o, m, "SimpleMap: foreach obj is correct"); 80 is(k, testSet[testIndex][0], "SimpleMap: foreach map key: " + k + " = " + testSet[testIndex][0]); 81 is(v, testSet[testIndex][1], "SimpleMap: foreach map value: " + v + " = " + testSet[testIndex][1]); 82 testIndex += 1; 83 }); 84 is(testIndex, 2, "SimpleMap: foreach ran correct number of times"); 85 ok(m.has("test2"), "SimpleMap: maplike has should return true"); 86 is(m.get("test2"), 2, "SimpleMap: maplike get should return value entered"); 87 is(m.delete("test2"), true, "SimpleMap: maplike deletion should return boolean"); 88 is(m.size, 1, "SimpleMap: size should be 1"); 89 var iterable = false; 90 for (let e of m) { 91 iterable = true; 92 is(e[0], "test", "SimpleMap: iterable first array element should be key"); 93 is(e[1], 1, "SimpleMap: iterable second array element should be value"); 94 } 95 is(m[Symbol.iterator].length, 0, "SimpleMap: @@iterator symbol is correct length"); 96 is(m[Symbol.iterator].name, "entries", "SimpleMap: @@iterator symbol has correct name"); 97 is(m[Symbol.iterator], m.entries, 'SimpleMap: @@iterator is an alias for "entries"'); 98 ok(iterable, "SimpleMap: @@iterator symbol resolved correctly"); 99 for (let k of m.keys()) { 100 is(k, "test", "SimpleMap: first keys element should be 'test'"); 101 } 102 for (let v of m.values()) { 103 is(v, 1, "SimpleMap: first values elements should be 1"); 104 } 105 for (let e of m.entries()) { 106 is(e[0], "test", "SimpleMap: entries first array element should be 'test'"); 107 is(e[1], 1, "SimpleMap: entries second array element should be 1"); 108 } 109 m.clear(); 110 is(m.size, 0, "SimpleMap: size should be 0 after clear"); 111 112 // Simple set creation and functionality test 113 info("SimpleSet: Testing simple set creation and functionality"); 114 m = new TestInterfaceSetlike(); 115 ok(m, "SimpleSet: got a TestInterfaceSetlike object"); 116 testExistence("SimpleSet: ", m, setlike_rw_properties); 117 is(m.size, 0, "SimpleSet: size should be zero"); 118 ok(!m.has("test"), "SimpleSet: maplike has should return false"); 119 m1 = m.add("test"); 120 is(m, m1, "SimpleSet: return from set should be map object"); 121 is(m.size, 1, "SimpleSet: size should be 1"); 122 ok(m.has("test"), "SimpleSet: maplike has should return true"); 123 m.add("test2"); 124 is(m.size, 2, "SimpleSet: size should be 2"); 125 testSet = ["test", "test2"]; 126 testIndex = 0; 127 m.forEach(function(v, k, o) { 128 "use strict"; 129 is(o, m, "SimpleSet: foreach obj is correct"); 130 is(k, testSet[testIndex], "SimpleSet: foreach set key: " + k + " = " + testSet[testIndex]); 131 testIndex += 1; 132 }); 133 is(testIndex, 2, "SimpleSet: foreach ran correct number of times"); 134 ok(m.has("test2"), "SimpleSet: maplike has should return true"); 135 is(m.delete("test2"), true, "SimpleSet: maplike deletion should return true"); 136 is(m.size, 1, "SimpleSet: size should be 1"); 137 iterable = false; 138 for (let e of m) { 139 iterable = true; 140 is(e, "test", "SimpleSet: iterable first array element should be key"); 141 } 142 is(m[Symbol.iterator].length, 0, "SimpleSet: @@iterator symbol is correct length"); 143 is(m[Symbol.iterator].name, "values", "SimpleSet: @@iterator symbol has correct name"); 144 is(m[Symbol.iterator], m.values, 'SimpleSet: @@iterator is an alias for "values"'); 145 ok(iterable, "SimpleSet: @@iterator symbol resolved correctly"); 146 for (let k of m.keys()) { 147 is(k, "test", "SimpleSet: first keys element should be 'test'"); 148 } 149 for (let v of m.values()) { 150 is(v, "test", "SimpleSet: first values elements should be 'test'"); 151 } 152 for (let e of m.entries()) { 153 is(e[0], "test", "SimpleSet: Entries first array element should be 'test'"); 154 is(e[1], "test", "SimpleSet: Entries second array element should be 'test'"); 155 } 156 m.clear(); 157 is(m.size, 0, "SimpleSet: size should be 0 after clear"); 158 159 // Map convenience function test 160 info("Testing map convenience functions"); 161 m = new TestInterfaceMaplike(); 162 ok(m, "MapConvenience: got a TestInterfaceMaplike object"); 163 is(m.size, 0, "MapConvenience: size should be zero"); 164 ok(!m.hasInternal("test"), "MapConvenience: maplike hasInternal should return false"); 165 // It's fine to let getInternal to return 0 if the key doesn't exist 166 // because this API can only be used internally in C++ and we'd throw 167 // an error if the key doesn't exist. 168 SimpleTest.doesThrow(() => m.getInternal("test"), 0, "MapConvenience: maplike getInternal should throw if the key doesn't exist"); 169 m.setInternal("test", 1); 170 is(m.size, 1, "MapConvenience: size should be 1"); 171 ok(m.hasInternal("test"), "MapConvenience: maplike hasInternal should return true"); 172 is(m.get("test"), 1, "MapConvenience: maplike get should return value entered"); 173 is(m.getInternal("test"), 1, "MapConvenience: maplike getInternal should return value entered"); 174 m.setInternal("test2", 2); 175 is(m.size, 2, "size should be 2"); 176 ok(m.hasInternal("test2"), "MapConvenience: maplike hasInternal should return true"); 177 is(m.get("test2"), 2, "MapConvenience: maplike get should return value entered"); 178 is(m.getInternal("test2"), 2, "MapConvenience: maplike getInternal should return value entered"); 179 is(m.deleteInternal("test2"), true, "MapConvenience: maplike deleteInternal should return true"); 180 is(m.size, 1, "MapConvenience: size should be 1"); 181 m.clearInternal(); 182 is(m.size, 0, "MapConvenience: size should be 0 after clearInternal"); 183 184 // Map convenience function test using objects and readonly 185 186 info("Testing Map convenience function test using objects and readonly"); 187 m = new TestInterfaceMaplikeObject(); 188 ok(m, "ReadOnlyMapConvenience: got a TestInterfaceMaplikeObject object"); 189 is(m.size, 0, "ReadOnlyMapConvenience: size should be zero"); 190 is(m.set, undefined, "ReadOnlyMapConvenience: readonly map, should be no set function"); 191 is(m.clear, undefined, "ReadOnlyMapConvenience: readonly map, should be no clear function"); 192 is(m.delete, undefined, "ReadOnlyMapConvenience: readonly map, should be no delete function"); 193 ok(!m.hasInternal("test"), "ReadOnlyMapConvenience: maplike hasInternal should return false"); 194 SimpleTest.doesThrow(() => m.getInternal("test"), "ReadOnlyMapConvenience: maplike getInternal should throw when the key doesn't exist"); 195 m.setInternal("test"); 196 is(m.size, 1, "size should be 1"); 197 ok(m.hasInternal("test"), "ReadOnlyMapConvenience: maplike hasInternal should return true"); 198 ok(m.getInternal("test") instanceof TestInterfaceMaplike, "ReadOnlyMapConvenience: maplike getInternal should return the object"); 199 m.setInternal("test2"); 200 is(m.size, 2, "size should be 2"); 201 ok(m.hasInternal("test2"), "ReadOnlyMapConvenience: maplike hasInternal should return true"); 202 ok(m.getInternal("test2") instanceof TestInterfaceMaplike, "ReadOnlyMapConvenience: maplike getInternal should return the object"); 203 is(m.deleteInternal("test2"), true, "ReadOnlyMapConvenience: maplike deleteInternal should return true"); 204 is(m.size, 1, "ReadOnlyMapConvenience: size should be 1"); 205 m.clearInternal(); 206 is(m.size, 0, "ReadOnlyMapConvenience: size should be 0 after clearInternal"); 207 208 // Map convenience function test using JavaScript objects 209 info("Testing Map convenience function test using javascript objects"); 210 m = new TestInterfaceMaplikeJSObject(); 211 ok(m, "JSObjectMapConvenience: got a TestInterfaceMaplikeJSObject object"); 212 is(m.size, 0, "JSObjectMapConvenience: size should be zero"); 213 is(m.set, undefined, "JSObjectMapConvenience: readonly map, should be no set function"); 214 is(m.clear, undefined, "JSObjectMapConvenience: readonly map, should be no clear function"); 215 is(m.delete, undefined, "JSObjectMapConvenience: readonly map, should be no delete function"); 216 ok(!m.hasInternal("test"), "JSObjectMapConvenience: maplike hasInternal should return false"); 217 SimpleTest.doesThrow(() => m.getInternal("test"), "JSObjectMapConvenience: maplike getInternal should throw when the key doesn't exist"); 218 let testObject = {"Hey1": 1}; 219 m.setInternal("test", testObject); 220 is(m.size, 1, "size should be 1"); 221 ok(m.hasInternal("test"), "JSObjectMapConvenience: maplike hasInternal should return true"); 222 let addedObject = m.getInternal("test"); 223 is(addedObject, testObject, "JSObjectMapConvenience: maplike getInternal should return the object"); 224 testObject = {"Hey2": 2}; 225 m.setInternal("test2", testObject); 226 is(m.size, 2, "size should be 2"); 227 ok(m.hasInternal("test2"), "JSObjectMapConvenience: maplike hasInternal should return true"); 228 addedObject = m.getInternal("test2"); 229 is(addedObject, testObject, "JSObjectMapConvenience: maplike getInternal should return the object"); 230 is(m.deleteInternal("test2"), true, "JSObjectMapConvenience: maplike deleteInternal should return true"); 231 is(m.size, 1, "JSObjectMapConvenience: size should be 1"); 232 m.clearInternal(); 233 is(m.size, 0, "JSObjectMapConvenience: size should be 0 after clearInternal"); 234 // JS implemented map creation convenience function test 235 236 // Test this override for forEach 237 info("ForEachThisOverride: Testing this override for forEach"); 238 m = new TestInterfaceMaplike(); 239 m.set("test", 1); 240 m.forEach(function(v, k, o) { 241 "use strict"; 242 is(o, m, "ForEachThisOverride: foreach obj is correct"); 243 is(this, 5, "ForEachThisOverride: 'this' value should be correct"); 244 }, 5); 245 246 // Test defaulting arguments on maplike to undefined 247 info("MapArgsDefault: Testing maplike defaulting arguments to undefined"); 248 m = new TestInterfaceMaplike(); 249 m.set(); 250 is(m.size, 1, "MapArgsDefault: should have 1 entry"); 251 m.forEach(function(v, k) { 252 "use strict"; 253 is(typeof k, "string", "MapArgsDefault: key is a string"); 254 is(k, "undefined", "MapArgsDefault: key is the string undefined"); 255 is(v, 0, "MapArgsDefault: value is 0"); 256 }); 257 is(m.get(), 0, "MapArgsDefault: no argument to get() returns correct value"); 258 m.delete(); 259 is(m.size, 0, "MapArgsDefault: should have 0 entries"); 260 261 // Test defaulting arguments on setlike to undefined 262 info("SetArgsDefault: Testing setlike defaulting arguments to undefined"); 263 m = new TestInterfaceSetlike(); 264 m.add(); 265 is(m.size, 1, "SetArgsDefault: should have 1 entry"); 266 m.forEach(function(v, k) { 267 "use strict"; 268 is(typeof k, "string", "SetArgsDefault: key is a string"); 269 is(k, "undefined", "SetArgsDefault: key is the string undefined"); 270 }); 271 m.delete(); 272 is(m.size, 0, "SetArgsDefault: should have 0 entries"); 273 274 SimpleTest.finish(); 275 }); 276 </script> 277 </body> 278 </html>