// ESM syntax is supported. import { Farr } from 'farr' import isIterable from 'is-iterable' /** * Arrays of functions with shared 'this' properties. */ class FarrThis extends Farr { /** * o - an object shared by all bound function elements * @memberof FarrThis# * @name o */ o = {} #P #premapper = null #funcWrapper = (w, i) => { w = typeof this.#premapper === 'function' ? this.#premapper(w) : w let f = typeof w === 'function' ? w : function () { return w } // console.log(f) f = f.bind(Object.defineProperties({ f, i, a: this.#P }, { o: { get: () => this.o } })) return f } #unsupportedInheritances = ['generated', 'givenFunc'] /** * constructor - create a FarrThis instance that can contain bound functions, where each function's this value is a plain object with some common parameters: * * 1. `a`: the containing instance (`FarrThis`) * 2. `i`: the index of this element in the containing instance (`integer`) * 3. `f`: a reference to this element (`function`) * 4. `o`: any user-specified object, also accessible as the `o` property of the containing instance ('object') * * * @param {(object|iterable|number)} [p = { a: [], o: {} }] if a number, creates instance of that length. if an iterable, use its elements to generate new bound functions * @param {iterable} p.a iterable source for generating elements * @param {object} p.o object to use for shared this binding */ constructor (p = { a: [], o: {} }) { if (typeof p === 'number') { super(p) return } else { super() } p = isIterable(p) ? { a: p } : p this.#P = new Proxy(this, { set (target, prop, value) { if (Farr.isSafeIndex(prop)) { return Reflect.set(target, prop, target.#funcWrapper(value, parseInt(prop))) } return Reflect.set(target, prop, value) }, get (target, prop, value) { if (Farr.nonTerminalKeys.includes(prop)) { // console.log(prop) return (...args) => { if (prop === 'premap') { target.#premapper = typeof args[0] === 'function' ? args[0] : null } else { target[prop](...args) } return target.#P } } return Reflect.get(target, prop, value) } }) this.o = typeof p.o === 'object' ? p.o : this.o const arr = isIterable(p.a) ? Array.from(p.a) : [] for (let x of arr) { this.#P.push(x) } return this.#P } } export { FarrThis, Farr }