list.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. 'use strict';
  5. module.metadata = {
  6. "stability": "experimental"
  7. };
  8. const { Class } = require('../core/heritage');
  9. const listNS = require('../core/namespace').ns();
  10. const { iteratorSymbol } = require('../util/iteration');
  11. const listOptions = {
  12. /**
  13. * List constructor can take any number of element to populate itself.
  14. * @params {Object|String|Number} element
  15. * @example
  16. * List(1,2,3).length == 3 // true
  17. */
  18. initialize: function List() {
  19. listNS(this).keyValueMap = [];
  20. for (let i = 0, ii = arguments.length; i < ii; i++)
  21. addListItem(this, arguments[i]);
  22. },
  23. /**
  24. * Number of elements in this list.
  25. * @type {Number}
  26. */
  27. get length() listNS(this).keyValueMap.length,
  28. /**
  29. * Returns a string representing this list.
  30. * @returns {String}
  31. */
  32. toString: function toString() 'List(' + listNS(this).keyValueMap + ')',
  33. /**
  34. * Custom iterator providing `List`s enumeration behavior.
  35. * We cant reuse `_iterator` that is defined by `Iterable` since it provides
  36. * iteration in an arbitrary order.
  37. * @see https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in
  38. * @param {Boolean} onKeys
  39. */
  40. __iterator__: function __iterator__(onKeys, onKeyValue) {
  41. let array = listNS(this).keyValueMap.slice(0),
  42. i = -1;
  43. for each(let element in array)
  44. yield onKeyValue ? [++i, element] : onKeys ? ++i : element;
  45. },
  46. };
  47. listOptions[iteratorSymbol] = function iterator() {
  48. return listNS(this).keyValueMap.slice(0)[iteratorSymbol]();
  49. };
  50. const List = Class(listOptions);
  51. exports.List = List;
  52. function addListItem(that, value) {
  53. let list = listNS(that).keyValueMap,
  54. index = list.indexOf(value);
  55. if (-1 === index) {
  56. try {
  57. that[that.length] = value;
  58. }
  59. catch (e) {}
  60. list.push(value);
  61. }
  62. }
  63. exports.addListItem = addListItem;
  64. function removeListItem(that, element) {
  65. let list = listNS(that).keyValueMap,
  66. index = list.indexOf(element);
  67. if (0 <= index) {
  68. list.splice(index, 1);
  69. try {
  70. for (let length = list.length; index < length; index++)
  71. that[index] = list[index];
  72. that[list.length] = undefined;
  73. }
  74. catch(e){}
  75. }
  76. }
  77. exports.removeListItem = removeListItem;
  78. exports.listNS = listNS;