This app provides monitoring and information features for the common freifunk user and the technical stuff of a freifunk community.
Code base is taken from a TUM Practical Course project and added here to see if Freifunk Altdorf can use it.
https://www.freifunk-altdorf.de
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
263 lines
6.3 KiB
263 lines
6.3 KiB
/** |
|
* Copyright (c) 2013-present, Facebook, Inc. |
|
* |
|
* This source code is licensed under the MIT license found in the |
|
* LICENSE file in the root directory of this source tree. |
|
* |
|
* @providesModule enumerate |
|
* |
|
*/ |
|
|
|
const KIND_KEYS = 'keys'; |
|
const KIND_VALUES = 'values'; |
|
const KIND_ENTRIES = 'entries'; |
|
|
|
/** |
|
* Specific Array iterators. |
|
*/ |
|
const ArrayIterators = function () { |
|
|
|
let hasNative = hasNativeIterator(Array); |
|
let ArrayIterator; |
|
|
|
if (!hasNative) { |
|
ArrayIterator = class ArrayIterator { |
|
// 22.1.5.1 CreateArrayIterator Abstract Operation |
|
constructor(array, kind) { |
|
this._iteratedObject = array; |
|
this._kind = kind; |
|
this._nextIndex = 0; |
|
} |
|
|
|
// 22.1.5.2.1 %ArrayIteratorPrototype%.next() |
|
next() { |
|
if (this._iteratedObject == null) { |
|
return { value: undefined, done: true }; |
|
} |
|
|
|
let array = this._iteratedObject; |
|
let len = this._iteratedObject.length; |
|
let index = this._nextIndex; |
|
let kind = this._kind; |
|
|
|
if (index >= len) { |
|
this._iteratedObject = undefined; |
|
return { value: undefined, done: true }; |
|
} |
|
|
|
this._nextIndex = index + 1; |
|
|
|
if (kind === KIND_KEYS) { |
|
return { value: index, done: false }; |
|
} else if (kind === KIND_VALUES) { |
|
return { value: array[index], done: false }; |
|
} else if (kind === KIND_ENTRIES) { |
|
return { value: [index, array[index]], done: false }; |
|
} |
|
} |
|
|
|
// 22.1.5.2.2 %ArrayIteratorPrototype%[@@iterator]() |
|
[Symbol.iterator]() { |
|
return this; |
|
} |
|
}; |
|
} |
|
|
|
return { |
|
keys: hasNative ? array => array.keys() : array => new ArrayIterator(array, KIND_KEYS), |
|
|
|
values: hasNative ? array => array.values() : array => new ArrayIterator(array, KIND_VALUES), |
|
|
|
entries: hasNative ? array => array.entries() : array => new ArrayIterator(array, KIND_ENTRIES) |
|
}; |
|
}(); |
|
|
|
// ----------------------------------------------------------------- |
|
|
|
/** |
|
* Specific String iterators. |
|
*/ |
|
const StringIterators = function () { |
|
|
|
let hasNative = hasNativeIterator(String); |
|
let StringIterator; |
|
|
|
if (!hasNative) { |
|
StringIterator = class StringIterator { |
|
// 21.1.5.1 CreateStringIterator Abstract Operation |
|
constructor(string) { |
|
this._iteratedString = string; |
|
this._nextIndex = 0; |
|
} |
|
|
|
// 21.1.5.2.1 %StringIteratorPrototype%.next() |
|
next() { |
|
if (this._iteratedString == null) { |
|
return { value: undefined, done: true }; |
|
} |
|
|
|
let index = this._nextIndex; |
|
let s = this._iteratedString; |
|
let len = s.length; |
|
|
|
if (index >= len) { |
|
this._iteratedString = undefined; |
|
return { value: undefined, done: true }; |
|
} |
|
|
|
let ret; |
|
let first = s.charCodeAt(index); |
|
|
|
if (first < 0xD800 || first > 0xDBFF || index + 1 === len) { |
|
ret = s[index]; |
|
} else { |
|
let second = s.charCodeAt(index + 1); |
|
if (second < 0xDC00 || second > 0xDFFF) { |
|
ret = s[index]; |
|
} else { |
|
ret = s[index] + s[index + 1]; |
|
} |
|
} |
|
|
|
this._nextIndex = index + ret.length; |
|
|
|
return { value: ret, done: false }; |
|
} |
|
|
|
// 21.1.5.2.2 %StringIteratorPrototype%[@@iterator]() |
|
[Symbol.iterator]() { |
|
return this; |
|
} |
|
}; |
|
} |
|
|
|
return { |
|
keys() { |
|
throw TypeError(`Strings default iterator doesn't implement keys.`); |
|
}, |
|
|
|
values: hasNative ? string => string[Symbol.iterator]() : string => new StringIterator(string), |
|
|
|
entries() { |
|
throw TypeError(`Strings default iterator doesn't implement entries.`); |
|
} |
|
}; |
|
}(); |
|
|
|
function hasNativeIterator(classObject) { |
|
return typeof classObject.prototype[Symbol.iterator] === 'function' && typeof classObject.prototype.values === 'function' && typeof classObject.prototype.keys === 'function' && typeof classObject.prototype.entries === 'function'; |
|
} |
|
|
|
// ----------------------------------------------------------------- |
|
|
|
/** |
|
* Generic object iterator. |
|
*/ |
|
class ObjectIterator { |
|
constructor(object, kind) { |
|
this._iteratedObject = object; |
|
this._kind = kind; |
|
this._keys = Object.keys(object); |
|
this._nextIndex = 0; |
|
} |
|
|
|
next() { |
|
let len = this._keys.length; |
|
let index = this._nextIndex; |
|
let kind = this._kind; |
|
let key = this._keys[index]; |
|
|
|
if (index >= len) { |
|
this._iteratedObject = undefined; |
|
return { value: undefined, done: true }; |
|
} |
|
|
|
this._nextIndex = index + 1; |
|
|
|
if (kind === KIND_KEYS) { |
|
return { value: key, done: false }; |
|
} else if (kind === KIND_VALUES) { |
|
return { value: this._iteratedObject[key], done: false }; |
|
} else if (kind === KIND_ENTRIES) { |
|
return { value: [key, this._iteratedObject[key]], done: false }; |
|
} |
|
} |
|
|
|
[Symbol.iterator]() { |
|
return this; |
|
} |
|
} |
|
|
|
/** |
|
* Generic object iterator, iterates over all own enumerable |
|
* properties. Used only if if no specific iterator is available, |
|
* and object don't implement iterator protocol. |
|
*/ |
|
const GenericIterators = { |
|
keys(object) { |
|
return new ObjectIterator(object, KIND_KEYS); |
|
}, |
|
|
|
values(object) { |
|
return new ObjectIterator(object, KIND_VALUES); |
|
}, |
|
|
|
entries(object) { |
|
return new ObjectIterator(object, KIND_ENTRIES); |
|
} |
|
}; |
|
|
|
// ----------------------------------------------------------------- |
|
|
|
/** |
|
* Main iterator function. Returns default iterator based |
|
* on the class of an instance. |
|
*/ |
|
function enumerate(object, kind) { |
|
|
|
// First check specific iterators. |
|
if (typeof object === 'string') { |
|
return StringIterators[kind || KIND_VALUES](object); |
|
} else if (Array.isArray(object)) { |
|
return ArrayIterators[kind || KIND_VALUES](object); |
|
|
|
// Then see if an object implements own. |
|
} else if (object[Symbol.iterator]) { |
|
return object[Symbol.iterator](); |
|
|
|
// And fallback to generic with entries. |
|
} else { |
|
return GenericIterators[kind || KIND_ENTRIES](object); |
|
} |
|
} |
|
|
|
Object.assign(enumerate, { |
|
/** |
|
* Export constants |
|
*/ |
|
|
|
KIND_KEYS, |
|
KIND_VALUES, |
|
KIND_ENTRIES, |
|
|
|
/** |
|
* Convenient explicit iterators for special kinds. |
|
*/ |
|
|
|
keys(object) { |
|
return enumerate(object, KIND_KEYS); |
|
}, |
|
|
|
values(object) { |
|
return enumerate(object, KIND_VALUES); |
|
}, |
|
|
|
entries(object) { |
|
return enumerate(object, KIND_ENTRIES); |
|
}, |
|
|
|
generic: GenericIterators.entries |
|
|
|
}); |
|
|
|
module.exports = enumerate; |