michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: 'use strict'; michael@0: michael@0: module.metadata = { michael@0: "stability": "experimental" michael@0: }; michael@0: michael@0: const { Class } = require('../core/heritage'); michael@0: const listNS = require('../core/namespace').ns(); michael@0: const { iteratorSymbol } = require('../util/iteration'); michael@0: michael@0: const listOptions = { michael@0: /** michael@0: * List constructor can take any number of element to populate itself. michael@0: * @params {Object|String|Number} element michael@0: * @example michael@0: * List(1,2,3).length == 3 // true michael@0: */ michael@0: initialize: function List() { michael@0: listNS(this).keyValueMap = []; michael@0: michael@0: for (let i = 0, ii = arguments.length; i < ii; i++) michael@0: addListItem(this, arguments[i]); michael@0: }, michael@0: /** michael@0: * Number of elements in this list. michael@0: * @type {Number} michael@0: */ michael@0: get length() listNS(this).keyValueMap.length, michael@0: /** michael@0: * Returns a string representing this list. michael@0: * @returns {String} michael@0: */ michael@0: toString: function toString() 'List(' + listNS(this).keyValueMap + ')', michael@0: /** michael@0: * Custom iterator providing `List`s enumeration behavior. michael@0: * We cant reuse `_iterator` that is defined by `Iterable` since it provides michael@0: * iteration in an arbitrary order. michael@0: * @see https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in michael@0: * @param {Boolean} onKeys michael@0: */ michael@0: __iterator__: function __iterator__(onKeys, onKeyValue) { michael@0: let array = listNS(this).keyValueMap.slice(0), michael@0: i = -1; michael@0: for each(let element in array) michael@0: yield onKeyValue ? [++i, element] : onKeys ? ++i : element; michael@0: }, michael@0: }; michael@0: listOptions[iteratorSymbol] = function iterator() { michael@0: return listNS(this).keyValueMap.slice(0)[iteratorSymbol](); michael@0: }; michael@0: const List = Class(listOptions); michael@0: exports.List = List; michael@0: michael@0: function addListItem(that, value) { michael@0: let list = listNS(that).keyValueMap, michael@0: index = list.indexOf(value); michael@0: michael@0: if (-1 === index) { michael@0: try { michael@0: that[that.length] = value; michael@0: } michael@0: catch (e) {} michael@0: list.push(value); michael@0: } michael@0: } michael@0: exports.addListItem = addListItem; michael@0: michael@0: function removeListItem(that, element) { michael@0: let list = listNS(that).keyValueMap, michael@0: index = list.indexOf(element); michael@0: michael@0: if (0 <= index) { michael@0: list.splice(index, 1); michael@0: try { michael@0: for (let length = list.length; index < length; index++) michael@0: that[index] = list[index]; michael@0: that[list.length] = undefined; michael@0: } michael@0: catch(e){} michael@0: } michael@0: } michael@0: exports.removeListItem = removeListItem; michael@0: michael@0: exports.listNS = listNS;