From 3eee31df91dd0cc650fc9507785b303f0bdabc0e Mon Sep 17 00:00:00 2001 From: tsctx <91457664+tsctx@users.noreply.github.com> Date: Tue, 13 Feb 2024 01:55:40 +0900 Subject: [PATCH] perf: createFastIterator.ts --- createIterator.ts | 123 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/createIterator.ts b/createIterator.ts index 001b900..5131e48 100644 --- a/createIterator.ts +++ b/createIterator.ts @@ -67,3 +67,126 @@ export function createIterator( return iterator; }; } + +export function createFastIterator any[]>( + name: string, + internalIteratorSymbol: symbol, + keyIndex: string | number = 0, + valueIndex: string | number = 1, +) { + type T = Parameters[0]; + type K = ReturnType[number][0]; + type V = ReturnType[number][1]; + class FastIterableIterator { + #target: any; + #kind: "key" | "value" | "key+value"; + #index; + + // https://webidl.spec.whatwg.org/#dfn-default-iterator-object + constructor(target: T, kind: "key" | "value" | "key+value") { + this.#target = target; + this.#kind = kind; + this.#index = 0; + } + + next() { + // 1. Let interface be the interface for which the iterator prototype object exists. + // 2. Let thisValue be the this value. + // 3. Let object be ? ToObject(thisValue). + // 4. If object is a platform object, then perform a security + // check, passing: + // 5. If object is not a default iterator object for interface, + // then throw a TypeError. + // Object.getPrototypeOf(this) !== FastIterator.prototype + if (typeof this !== "object" || this === null || !(#target in this)) { + throw new TypeError( + `'next' called on an object that does not implement interface ${name} Iterator.`, + ); + } + + // 6. Let index be object’s index. + // 7. Let kind be object’s kind. + // 8. Let values be object’s target's value pairs to iterate over. + const index = this.#index; + const values = this.#target[internalIteratorSymbol]; + + // 9. Let len be the length of values. + const len = values.length; + + // 10. If index is greater than or equal to len, then return + // CreateIterResultObject(undefined, true). + if (index >= len) { + return { + value: undefined, + done: true, + }; + } + + // 11. Let pair be the entry in values at index index. + const { [keyIndex!]: key, [valueIndex!]: value } = values[index]; + + // 12. Set object’s index to index + 1. + this.#index = index + 1; + + // 13. Return the iterator result for pair and kind. + + // https://webidl.spec.whatwg.org/#iterator-result + + // 1. Let result be a value determined by the value of kind: + let result; + if (this.#kind === "key") { + // 1. Let idlKey be pair’s key. + // 2. Let key be the result of converting idlKey to an + // ECMAScript value. + // 3. result is key. + result = key; + } else if (this.#kind === "value") { + // 1. Let idlValue be pair’s value. + // 2. Let value be the result of converting idlValue to + // an ECMAScript value. + // 3. result is value. + result = value; + } else { + // 1. Let idlKey be pair’s key. + // 2. Let idlValue be pair’s value. + // 3. Let key be the result of converting idlKey to an + // ECMAScript value. + // 4. Let value be the result of converting idlValue to + // an ECMAScript value. + // 5. Let array be ! ArrayCreate(2). + // 6. Call ! CreateDataProperty(array, "0", key). + // 7. Call ! CreateDataProperty(array, "1", value). + // 8. result is array. + result = [key, value]; + } + // 2. Return CreateIterResultObject(result, false). + return { + value: result, + done: false, + }; + } + } + // https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object + //@ts-ignore + delete FastIterableIterator.prototype.constructor; + + Object.setPrototypeOf( + FastIterableIterator.prototype, + Object.getPrototypeOf(Array.prototype[Symbol.iterator]()), + ); + + Object.defineProperties(FastIterableIterator.prototype, { + [Symbol.toStringTag]: { + writable: false, + enumerable: false, + configurable: true, + value: `${name} Iterator`, + }, + next: { writable: true, enumerable: true, configurable: true }, + }); + + return (target: T, kind: Kind) => + new FastIterableIterator(target, kind) as unknown as IterableIterator< + Kind extends "key" ? K : Kind extends "value" ? V : [K, V] + >; +}