reflect.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. /* Any copyright is dedicated to the Public Domain.
  2. http://creativecommons.org/publicdomain/zero/1.0/ */
  3. /**
  4. * reflect.js is a collection of methods to test HTML attribute reflection.
  5. * Each of attribute is reflected differently, depending on various parameters,
  6. * see:
  7. * http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes
  8. *
  9. * Do not forget to add these line at the beginning of each new reflect* method:
  10. * ok(attr in element, attr + " should be an IDL attribute of this element");
  11. * is(typeof element[attr], <type>, attr + " IDL attribute should be a <type>");
  12. */
  13. /**
  14. * Checks that a given attribute is correctly reflected as a string.
  15. *
  16. * @param aParameters Object object containing the parameters, which are:
  17. * - element Element node to test
  18. * - attribute String name of the attribute
  19. * OR
  20. * attribute Object object containing two attributes, 'content' and 'idl'
  21. * - otherValues Array [optional] other values to test in addition of the default ones
  22. * - extendedAttributes Object object which can have 'TreatNullAs': "EmptyString"
  23. */
  24. function reflectString(aParameters)
  25. {
  26. var element = aParameters.element;
  27. var contentAttr = typeof aParameters.attribute === "string"
  28. ? aParameters.attribute : aParameters.attribute.content;
  29. var idlAttr = typeof aParameters.attribute === "string"
  30. ? aParameters.attribute : aParameters.attribute.idl;
  31. var otherValues = aParameters.otherValues !== undefined
  32. ? aParameters.otherValues : [];
  33. var treatNullAs = aParameters.extendedAttributes ?
  34. aParameters.extendedAttributes.TreatNullAs : null;
  35. ok(idlAttr in element,
  36. idlAttr + " should be an IDL attribute of this element");
  37. is(typeof element[idlAttr], "string",
  38. "'" + idlAttr + "' IDL attribute should be a string");
  39. // Tests when the attribute isn't set.
  40. is(element.getAttribute(contentAttr), null,
  41. "When not set, the content attribute should be null.");
  42. is(element[idlAttr], "",
  43. "When not set, the IDL attribute should return the empty string");
  44. /**
  45. * TODO: as long as null stringification doesn't follow the WebIDL
  46. * specifications, don't add it to the loop below and keep it here.
  47. */
  48. element.setAttribute(contentAttr, null);
  49. is(element.getAttribute(contentAttr), "null",
  50. "null should have been stringified to 'null' for '" + contentAttr + "'");
  51. is(element[idlAttr], "null",
  52. "null should have been stringified to 'null' for '" + idlAttr + "'");
  53. element.removeAttribute(contentAttr);
  54. element[idlAttr] = null;
  55. if (treatNullAs == "EmptyString") {
  56. is(element.getAttribute(contentAttr), "",
  57. "null should have been stringified to '' for '" + contentAttr + "'");
  58. is(element[idlAttr], "",
  59. "null should have been stringified to '' for '" + idlAttr + "'");
  60. } else {
  61. is(element.getAttribute(contentAttr), "null",
  62. "null should have been stringified to 'null' for '" + contentAttr + "'");
  63. is(element[idlAttr], "null",
  64. "null should have been stringified to 'null' for '" + contentAttr + "'");
  65. }
  66. element.removeAttribute(contentAttr);
  67. // Tests various strings.
  68. var stringsToTest = [
  69. // [ test value, expected result ]
  70. [ "", "" ],
  71. [ "null", "null" ],
  72. [ "undefined", "undefined" ],
  73. [ "foo", "foo" ],
  74. [ contentAttr, contentAttr ],
  75. [ idlAttr, idlAttr ],
  76. // TODO: uncomment this when null stringification will follow the specs.
  77. // [ null, "null" ],
  78. [ undefined, "undefined" ],
  79. [ true, "true" ],
  80. [ false, "false" ],
  81. [ 42, "42" ],
  82. // ES5, verse 8.12.8.
  83. [ { toString: function() { return "foo" } },
  84. "foo" ],
  85. [ { valueOf: function() { return "foo" } },
  86. "[object Object]" ],
  87. [ { valueOf: function() { return "quux" },
  88. toString: undefined },
  89. "quux" ],
  90. [ { valueOf: function() { return "foo" },
  91. toString: function() { return "bar" } },
  92. "bar" ]
  93. ];
  94. otherValues.forEach(function(v) { stringsToTest.push([v, v]) });
  95. stringsToTest.forEach(function([v, r]) {
  96. element.setAttribute(contentAttr, v);
  97. is(element[idlAttr], r,
  98. "IDL attribute '" + idlAttr + "' should return the value it has been set to.");
  99. is(element.getAttribute(contentAttr), r,
  100. "Content attribute '" + contentAttr + "'should return the value it has been set to.");
  101. element.removeAttribute(contentAttr);
  102. element[idlAttr] = v;
  103. is(element[idlAttr], r,
  104. "IDL attribute '" + idlAttr + "' should return the value it has been set to.");
  105. is(element.getAttribute(contentAttr), r,
  106. "Content attribute '" + contentAttr + "' should return the value it has been set to.");
  107. element.removeAttribute(contentAttr);
  108. });
  109. // Tests after removeAttribute() is called. Should be equivalent with not set.
  110. is(element.getAttribute(contentAttr), null,
  111. "When not set, the content attribute should be null.");
  112. is(element[idlAttr], "",
  113. "When not set, the IDL attribute should return the empty string");
  114. }
  115. /**
  116. * Checks that a given attribute name for a given element is correctly reflected
  117. * as an unsigned int.
  118. *
  119. * @param aParameters Object object containing the parameters, which are:
  120. * - element Element node to test on
  121. * - attribute String name of the attribute
  122. * - nonZero Boolean whether the attribute should be non-null
  123. * - defaultValue Integer [optional] default value, if different from the default one
  124. */
  125. function reflectUnsignedInt(aParameters)
  126. {
  127. var element = aParameters.element;
  128. var attr = aParameters.attribute;
  129. var nonZero = aParameters.nonZero;
  130. var defaultValue = aParameters.defaultValue;
  131. var fallback = aParameters.fallback;
  132. if (defaultValue === undefined) {
  133. if (nonZero) {
  134. defaultValue = 1;
  135. } else {
  136. defaultValue = 0;
  137. }
  138. }
  139. if (fallback === undefined) {
  140. fallback = false;
  141. }
  142. ok(attr in element, attr + " should be an IDL attribute of this element");
  143. is(typeof element[attr], "number", attr + " IDL attribute should be a number");
  144. // Check default value.
  145. is(element[attr], defaultValue, "default value should be " + defaultValue);
  146. ok(!element.hasAttribute(attr), attr + " shouldn't be present");
  147. var values = [ 1, 3, 42, 2147483647 ];
  148. for (var value of values) {
  149. element[attr] = value;
  150. is(element[attr], value, "." + attr + " should be equals " + value);
  151. is(element.getAttribute(attr), String(value),
  152. "@" + attr + " should be equals " + value);
  153. element.setAttribute(attr, value);
  154. is(element[attr], value, "." + attr + " should be equals " + value);
  155. is(element.getAttribute(attr), String(value),
  156. "@" + attr + " should be equals " + value);
  157. }
  158. // -3000000000 is equivalent to 1294967296 when using the IDL attribute.
  159. element[attr] = -3000000000;
  160. is(element[attr], 1294967296, "." + attr + " should be equals to 1294967296");
  161. is(element.getAttribute(attr), "1294967296",
  162. "@" + attr + " should be equals to 1294967296");
  163. // When setting the content attribute, it's a string so it will be invalid.
  164. element.setAttribute(attr, -3000000000);
  165. is(element.getAttribute(attr), "-3000000000",
  166. "@" + attr + " should be equals to " + -3000000000);
  167. is(element[attr], defaultValue,
  168. "." + attr + " should be equals to " + defaultValue);
  169. // When interpreted as unsigned 32-bit integers, all of these fall between
  170. // 2^31 and 2^32 - 1, so per spec they return the default value.
  171. var nonValidValues = [ -2147483648, -1, 3147483647];
  172. for (var value of nonValidValues) {
  173. element[attr] = value;
  174. is(element.getAttribute(attr), String(defaultValue),
  175. "@" + attr + " should be equals to " + defaultValue);
  176. is(element[attr], defaultValue,
  177. "." + attr + " should be equals to " + defaultValue);
  178. }
  179. for (var values of nonValidValues) {
  180. element.setAttribute(attr, values[0]);
  181. is(element.getAttribute(attr), String(values[0]),
  182. "@" + attr + " should be equals to " + values[0]);
  183. is(element[attr], defaultValue,
  184. "." + attr + " should be equals to " + defaultValue);
  185. }
  186. // Setting to 0 should throw an error if nonZero is true.
  187. var caught = false;
  188. try {
  189. element[attr] = 0;
  190. } catch(e) {
  191. caught = true;
  192. is(e.name, "IndexSizeError", "exception should be IndexSizeError");
  193. is(e.code, DOMException.INDEX_SIZE_ERR, "exception code should be INDEX_SIZE_ERR");
  194. }
  195. if (nonZero && !fallback) {
  196. ok(caught, "an exception should have been caught");
  197. } else {
  198. ok(!caught, "no exception should have been caught");
  199. }
  200. // If 0 is set in @attr, it will be ignored when calling .attr.
  201. element.setAttribute(attr, "0");
  202. is(element.getAttribute(attr), "0", "@" + attr + " should be equals to 0");
  203. if (nonZero) {
  204. is(element[attr], defaultValue,
  205. "." + attr + " should be equals to " + defaultValue);
  206. } else {
  207. is(element[attr], 0, "." + attr + " should be equals to 0");
  208. }
  209. }
  210. /**
  211. * Checks that a given attribute is correctly reflected as limited to known
  212. * values enumerated attribute.
  213. *
  214. * @param aParameters Object object containing the parameters, which are:
  215. * - element Element node to test on
  216. * - attribute String name of the attribute
  217. * OR
  218. * attribute Object object containing two attributes, 'content' and 'idl'
  219. * - validValues Array valid values we support
  220. * - invalidValues Array invalid values
  221. * - defaultValue String [optional] default value when no valid value is set
  222. * OR
  223. * defaultValue Object [optional] object containing two attributes, 'invalid' and 'missing'
  224. * - unsupportedValues Array [optional] valid values we do not support
  225. * - nullable boolean [optional] whether the attribute is nullable
  226. */
  227. function reflectLimitedEnumerated(aParameters)
  228. {
  229. var element = aParameters.element;
  230. var contentAttr = typeof aParameters.attribute === "string"
  231. ? aParameters.attribute : aParameters.attribute.content;
  232. var idlAttr = typeof aParameters.attribute === "string"
  233. ? aParameters.attribute : aParameters.attribute.idl;
  234. var validValues = aParameters.validValues;
  235. var invalidValues = aParameters.invalidValues;
  236. var defaultValueInvalid = aParameters.defaultValue === undefined
  237. ? "" : typeof aParameters.defaultValue === "string"
  238. ? aParameters.defaultValue : aParameters.defaultValue.invalid
  239. var defaultValueMissing = aParameters.defaultValue === undefined
  240. ? "" : typeof aParameters.defaultValue === "string"
  241. ? aParameters.defaultValue : aParameters.defaultValue.missing
  242. var unsupportedValues = aParameters.unsupportedValues !== undefined
  243. ? aParameters.unsupportedValues : [];
  244. var nullable = aParameters.nullable;
  245. ok(idlAttr in element, idlAttr + " should be an IDL attribute of this element");
  246. if (nullable) {
  247. // The missing value default is null, which is typeof == "object"
  248. is(typeof element[idlAttr], "object", "'" + idlAttr + "' IDL attribute should be null, which has typeof == object");
  249. is(element[idlAttr], null, "'" + idlAttr + "' IDL attribute should be null");
  250. } else {
  251. is(typeof element[idlAttr], "string", "'" + idlAttr + "' IDL attribute should be a string");
  252. }
  253. if (nullable) {
  254. element.setAttribute(contentAttr, "something");
  255. // Now it will be a string
  256. is(typeof element[idlAttr], "string", "'" + idlAttr + "' IDL attribute should be a string");
  257. }
  258. // Explicitly check the default value.
  259. element.removeAttribute(contentAttr);
  260. is(element[idlAttr], defaultValueMissing,
  261. "When no attribute is set, the value should be the default value.");
  262. // Check valid values.
  263. validValues.forEach(function (v) {
  264. element.setAttribute(contentAttr, v);
  265. is(element[idlAttr], v,
  266. "'" + v + "' should be accepted as a valid value for " + idlAttr);
  267. is(element.getAttribute(contentAttr), v,
  268. "Content attribute should return the value it has been set to.");
  269. element.removeAttribute(contentAttr);
  270. element.setAttribute(contentAttr, v.toUpperCase());
  271. is(element[idlAttr], v,
  272. "Enumerated attributes should be case-insensitive.");
  273. is(element.getAttribute(contentAttr), v.toUpperCase(),
  274. "Content attribute should not be lower-cased.");
  275. element.removeAttribute(contentAttr);
  276. element[idlAttr] = v;
  277. is(element[idlAttr], v,
  278. "'" + v + "' should be accepted as a valid value for " + idlAttr);
  279. is(element.getAttribute(contentAttr), v,
  280. "Content attribute should return the value it has been set to.");
  281. element.removeAttribute(contentAttr);
  282. element[idlAttr] = v.toUpperCase();
  283. is(element[idlAttr], v,
  284. "Enumerated attributes should be case-insensitive.");
  285. is(element.getAttribute(contentAttr), v.toUpperCase(),
  286. "Content attribute should not be lower-cased.");
  287. element.removeAttribute(contentAttr);
  288. });
  289. // Check invalid values.
  290. invalidValues.forEach(function (v) {
  291. element.setAttribute(contentAttr, v);
  292. is(element[idlAttr], defaultValueInvalid,
  293. "When the content attribute is set to an invalid value, the default value should be returned.");
  294. is(element.getAttribute(contentAttr), v,
  295. "Content attribute should not have been changed.");
  296. element.removeAttribute(contentAttr);
  297. element[idlAttr] = v;
  298. is(element[idlAttr], defaultValueInvalid,
  299. "When the value is set to an invalid value, the default value should be returned.");
  300. is(element.getAttribute(contentAttr), v,
  301. "Content attribute should not have been changed.");
  302. element.removeAttribute(contentAttr);
  303. });
  304. // Check valid values we currently do not support.
  305. // Basically, it's like the checks for the valid values but with some todo's.
  306. unsupportedValues.forEach(function (v) {
  307. element.setAttribute(contentAttr, v);
  308. todo_is(element[idlAttr], v,
  309. "'" + v + "' should be accepted as a valid value for " + idlAttr);
  310. is(element.getAttribute(contentAttr), v,
  311. "Content attribute should return the value it has been set to.");
  312. element.removeAttribute(contentAttr);
  313. element.setAttribute(contentAttr, v.toUpperCase());
  314. todo_is(element[idlAttr], v,
  315. "Enumerated attributes should be case-insensitive.");
  316. is(element.getAttribute(contentAttr), v.toUpperCase(),
  317. "Content attribute should not be lower-cased.");
  318. element.removeAttribute(contentAttr);
  319. element[idlAttr] = v;
  320. todo_is(element[idlAttr], v,
  321. "'" + v + "' should be accepted as a valid value for " + idlAttr);
  322. is(element.getAttribute(contentAttr), v,
  323. "Content attribute should return the value it has been set to.");
  324. element.removeAttribute(contentAttr);
  325. element[idlAttr] = v.toUpperCase();
  326. todo_is(element[idlAttr], v,
  327. "Enumerated attributes should be case-insensitive.");
  328. is(element.getAttribute(contentAttr), v.toUpperCase(),
  329. "Content attribute should not be lower-cased.");
  330. element.removeAttribute(contentAttr);
  331. });
  332. if (nullable) {
  333. is(defaultValueMissing, null,
  334. "Missing default value should be null for nullable attributes");
  335. ok(validValues.length > 0, "We better have at least one valid value");
  336. element.setAttribute(contentAttr, validValues[0]);
  337. ok(element.hasAttribute(contentAttr),
  338. "Should have content attribute: we just set it");
  339. element[idlAttr] = null;
  340. ok(!element.hasAttribute(contentAttr),
  341. "Should have removed content attribute");
  342. }
  343. }
  344. /**
  345. * Checks that a given attribute is correctly reflected as a boolean.
  346. *
  347. * @param aParameters Object object containing the parameters, which are:
  348. * - element Element node to test on
  349. * - attribute String name of the attribute
  350. * OR
  351. * attribute Object object containing two attributes, 'content' and 'idl'
  352. */
  353. function reflectBoolean(aParameters)
  354. {
  355. var element = aParameters.element;
  356. var contentAttr = typeof aParameters.attribute === "string"
  357. ? aParameters.attribute : aParameters.attribute.content;
  358. var idlAttr = typeof aParameters.attribute === "string"
  359. ? aParameters.attribute : aParameters.attribute.idl;
  360. ok(idlAttr in element,
  361. idlAttr + " should be an IDL attribute of this element");
  362. is(typeof element[idlAttr], "boolean",
  363. idlAttr + " IDL attribute should be a boolean");
  364. // Tests when the attribute isn't set.
  365. is(element.getAttribute(contentAttr), null,
  366. "When not set, the content attribute should be null.");
  367. is(element[idlAttr], false,
  368. "When not set, the IDL attribute should return false");
  369. /**
  370. * Test various values.
  371. * Each value to test is actually an object containing a 'value' property
  372. * containing the value to actually test, a 'stringified' property containing
  373. * the stringified value and a 'result' property containing the expected
  374. * result when the value is set to the IDL attribute.
  375. */
  376. var valuesToTest = [
  377. { value: true, stringified: "true", result: true },
  378. { value: false, stringified: "false", result: false },
  379. { value: "true", stringified: "true", result: true },
  380. { value: "false", stringified: "false", result: true },
  381. { value: "foo", stringified: "foo", result: true },
  382. { value: idlAttr, stringified: idlAttr, result: true },
  383. { value: contentAttr, stringified: contentAttr, result: true },
  384. { value: "null", stringified: "null", result: true },
  385. { value: "undefined", stringified: "undefined", result: true },
  386. { value: "", stringified: "", result: false },
  387. { value: undefined, stringified: "undefined", result: false },
  388. { value: null, stringified: "null", result: false },
  389. { value: +0, stringified: "0", result: false },
  390. { value: -0, stringified: "0", result: false },
  391. { value: NaN, stringified: "NaN", result: false },
  392. { value: 42, stringified: "42", result: true },
  393. { value: Infinity, stringified: "Infinity", result: true },
  394. { value: -Infinity, stringified: "-Infinity", result: true },
  395. // ES5, verse 9.2.
  396. { value: { toString: function() { return "foo" } }, stringified: "foo",
  397. result: true },
  398. { value: { valueOf: function() { return "foo" } },
  399. stringified: "[object Object]", result: true },
  400. { value: { valueOf: function() { return "quux" }, toString: undefined },
  401. stringified: "quux", result: true },
  402. { value: { valueOf: function() { return "foo" },
  403. toString: function() { return "bar" } }, stringified: "bar",
  404. result: true },
  405. { value: { valueOf: function() { return false } },
  406. stringified: "[object Object]", result: true },
  407. { value: { foo: false, bar: false }, stringified: "[object Object]",
  408. result: true },
  409. { value: { }, stringified: "[object Object]", result: true },
  410. ];
  411. valuesToTest.forEach(function(v) {
  412. element.setAttribute(contentAttr, v.value);
  413. is(element[idlAttr], true,
  414. "IDL attribute should return always return 'true' if the content attribute has been set");
  415. is(element.getAttribute(contentAttr), v.stringified,
  416. "Content attribute should return the stringified value it has been set to.");
  417. element.removeAttribute(contentAttr);
  418. element[idlAttr] = v.value;
  419. is(element[idlAttr], v.result, "IDL attribute should return " + v.result);
  420. is(element.getAttribute(contentAttr), v.result ? "" : null,
  421. v.result ? "Content attribute should return the empty string."
  422. : "Content attribute should return null.");
  423. is(element.hasAttribute(contentAttr), v.result,
  424. v.result ? contentAttr + " should not be present"
  425. : contentAttr + " should be present");
  426. element.removeAttribute(contentAttr);
  427. });
  428. // Tests after removeAttribute() is called. Should be equivalent with not set.
  429. is(element.getAttribute(contentAttr), null,
  430. "When not set, the content attribute should be null.");
  431. is(element[contentAttr], false,
  432. "When not set, the IDL attribute should return false");
  433. }
  434. /**
  435. * Checks that a given attribute name for a given element is correctly reflected
  436. * as an signed integer.
  437. *
  438. * @param aParameters Object object containing the parameters, which are:
  439. * - element Element node to test on
  440. * - attribute String name of the attribute
  441. * - nonNegative Boolean true if the attribute is limited to 'non-negative numbers', false otherwise
  442. * - defaultValue Integer [optional] default value, if one exists
  443. */
  444. function reflectInt(aParameters)
  445. {
  446. // Expected value returned by .getAttribute() when |value| has been previously passed to .setAttribute().
  447. function expectedGetAttributeResult(value) {
  448. return String(value);
  449. }
  450. function stringToInteger(value, nonNegative, defaultValue) {
  451. // Parse: Ignore leading whitespace, find [+/-][numbers]
  452. var result = /^[ \t\n\f\r]*([\+\-]?[0-9]+)/.exec(value);
  453. if (result) {
  454. var resultInt = parseInt(result[1], 10);
  455. if ((nonNegative ? 0 : -0x80000000) <= resultInt && resultInt <= 0x7FFFFFFF) {
  456. // If the value is within allowed value range for signed/unsigned
  457. // integer, return it -- but add 0 to it to convert a possible -0 into
  458. // +0, the only zero present in the signed integer range.
  459. return resultInt + 0;
  460. }
  461. }
  462. return defaultValue;
  463. }
  464. // Expected value returned by .getAttribute(attr) or .attr if |value| has been set via the IDL attribute.
  465. function expectedIdlAttributeResult(value) {
  466. // This returns the result of calling the ES ToInt32 algorithm on value.
  467. return value << 0;
  468. }
  469. var element = aParameters.element;
  470. var attr = aParameters.attribute;
  471. var nonNegative = aParameters.nonNegative;
  472. var defaultValue = aParameters.defaultValue !== undefined
  473. ? aParameters.defaultValue
  474. : nonNegative ? -1 : 0;
  475. ok(attr in element, attr + " should be an IDL attribute of this element");
  476. is(typeof element[attr], "number", attr + " IDL attribute should be a number");
  477. // Check default value.
  478. is(element[attr], defaultValue, "default value should be " + defaultValue);
  479. ok(!element.hasAttribute(attr), attr + " shouldn't be present");
  480. /**
  481. * Test various values.
  482. * value: The test value that will be set using both setAttribute(value) and
  483. * element[attr] = value
  484. */
  485. var valuesToTest = [
  486. // Test numeric inputs up to max signed integer
  487. 0, 1, 55555, 2147483647, +42,
  488. // Test string inputs up to max signed integer
  489. "0", "1", "777777", "2147483647", "+42",
  490. // Test negative numeric inputs up to min signed integer
  491. -0, -1, -3333, -2147483648,
  492. // Test negative string inputs up to min signed integer
  493. "-0", "-1", "-222", "-2147483647", "-2147483648",
  494. // Test numeric inputs that are outside legal 32 bit signed values
  495. -2147483649, -3000000000, -4294967296, 2147483649, 4000000000, -4294967297,
  496. // Test string inputs with extra padding
  497. " 1111111", " 23456 ",
  498. // Test non-numeric string inputs
  499. "", " ", "+", "-", "foo", "+foo", "-foo", "+ foo", "- foo", "+-2", "-+2", "++2", "--2", "hello1234", "1234hello",
  500. "444 world 555", "why 567 what", "-3 nots", "2e5", "300e2", "42+-$", "+42foo", "-514not", "\vblah", "0x10FFFF", "-0xABCDEF",
  501. // Test decimal numbers
  502. 1.2345, 42.0, 3456789.1, -2.3456, -6789.12345, -2147483649.1234,
  503. // Test decimal strings
  504. "1.2345", "42.0", "3456789.1", "-2.3456", "-6789.12345", "-2147483649.1234",
  505. // Test special values
  506. undefined, null, NaN, Infinity, -Infinity,
  507. ];
  508. valuesToTest.forEach(function(v) {
  509. var intValue = stringToInteger(v, nonNegative, defaultValue);
  510. element.setAttribute(attr, v);
  511. is(element.getAttribute(attr), expectedGetAttributeResult(v), element.localName + ".setAttribute(" +
  512. attr + ", " + v + "), " + element.localName + ".getAttribute(" + attr + ") ");
  513. is(element[attr], intValue, element.localName +
  514. ".setAttribute(" + attr + ", " + v + "), " + element.localName + "[" + attr + "] ");
  515. element.removeAttribute(attr);
  516. if (nonNegative && expectedIdlAttributeResult(v) < 0) {
  517. try {
  518. element[attr] = v;
  519. ok(false, element.localName + "[" + attr + "] = " + v + " should throw IndexSizeError");
  520. } catch(e) {
  521. is(e.name, "IndexSizeError", element.localName + "[" + attr + "] = " + v +
  522. " should throw IndexSizeError");
  523. is(e.code, DOMException.INDEX_SIZE_ERR, element.localName + "[" + attr + "] = " + v +
  524. " should throw INDEX_SIZE_ERR");
  525. }
  526. } else {
  527. element[attr] = v;
  528. is(element[attr], expectedIdlAttributeResult(v), element.localName + "[" + attr + "] = " + v +
  529. ", " + element.localName + "[" + attr + "] ");
  530. is(element.getAttribute(attr), String(expectedIdlAttributeResult(v)),
  531. element.localName + "[" + attr + "] = " + v + ", " +
  532. element.localName + ".getAttribute(" + attr + ") ");
  533. }
  534. element.removeAttribute(attr);
  535. });
  536. // Tests after removeAttribute() is called. Should be equivalent with not set.
  537. is(element.getAttribute(attr), null,
  538. "When not set, the content attribute should be null.");
  539. is(element[attr], defaultValue,
  540. "When not set, the IDL attribute should return default value.");
  541. }
  542. /**
  543. * Checks that a given attribute is correctly reflected as a url.
  544. *
  545. * @param aParameters Object object containing the parameters, which are:
  546. * - element Element node to test
  547. * - attribute String name of the attribute
  548. * OR
  549. * attribute Object object containing two attributes, 'content' and 'idl'
  550. */
  551. function reflectURL(aParameters)
  552. {
  553. var element = aParameters.element;
  554. var contentAttr = typeof aParameters.attribute === "string"
  555. ? aParameters.attribute : aParameters.attribute.content;
  556. var idlAttr = typeof aParameters.attribute === "string"
  557. ? aParameters.attribute : aParameters.attribute.idl;
  558. element[idlAttr] = "";
  559. is(element[idlAttr], document.URL, "Empty string should resolve to document URL");
  560. }