Skip to content

Commit 19a7d8d

Browse files
committed
perf: use class make faster
1 parent 0962d5a commit 19a7d8d

1 file changed

Lines changed: 59 additions & 51 deletions

File tree

lib/fetch/util.js

Lines changed: 59 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -745,55 +745,72 @@ const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbo
745745
* @param {string | number} [keyIndex]
746746
* @param {string | number} [valueIndex]
747747
*/
748-
function createIterator (name, kInternalIterator, keyIndex = 0, valueIndex = 1) {
749-
const kInternalObject = Symbol('internal Object')
750-
751-
// The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%.
752-
const iteratorObject = Object.create(esIteratorPrototype)
748+
function createFastIterator (name, kInternalIterator, keyIndex = 0, valueIndex = 1) {
749+
class FastIterableIterator {
750+
/** @type {any} */
751+
#target
752+
/** @type {'key' | 'value' | 'key+value'} */
753+
#kind
754+
/** @type {number} */
755+
#index
756+
757+
/**
758+
* @see https://webidl.spec.whatwg.org/#dfn-default-iterator-object
759+
* @param {unknown} target
760+
* @param {'key' | 'value' | 'key+value'} kind
761+
*/
762+
constructor (target, kind) {
763+
this.#target = target
764+
this.#kind = kind
765+
this.#index = 0
766+
}
753767

754-
Object.defineProperty(iteratorObject, 'next', {
755-
value: function next () {
768+
next () {
756769
// 1. Let interface be the interface for which the iterator prototype object exists.
757-
758770
// 2. Let thisValue be the this value.
759-
760771
// 3. Let object be ? ToObject(thisValue).
761-
762772
// 4. If object is a platform object, then perform a security
763773
// check, passing:
764-
765774
// 5. If object is not a default iterator object for interface,
766775
// then throw a TypeError.
767-
if (typeof this !== 'object' || this === null || !(kInternalObject in this)) {
776+
// Object.getPrototypeOf(this) !== FastIterator.prototype
777+
if (typeof this !== 'object' || this === null || !(#target in this)) {
768778
throw new TypeError(
769779
`'next' called on an object that does not implement interface ${name} Iterator.`
770780
)
771781
}
772-
const object = this[kInternalObject]
773782

774783
// 6. Let index be object’s index.
775784
// 7. Let kind be object’s kind.
776785
// 8. Let values be object’s target's value pairs to iterate over.
777-
const { index, kind, target } = object
778-
const values = target[kInternalIterator]
786+
const index = this.#index
787+
const values = this.#target[kInternalIterator]
779788

780789
// 9. Let len be the length of values.
781790
const len = values.length
782791

783792
// 10. If index is greater than or equal to len, then return
784793
// CreateIterResultObject(undefined, true).
785794
if (index >= len) {
786-
return { value: undefined, done: true }
795+
return {
796+
value: undefined,
797+
done: true
798+
}
787799
}
800+
788801
// 11. Let pair be the entry in values at index index.
789802
const { [keyIndex]: key, [valueIndex]: value } = values[index]
803+
790804
// 12. Set object’s index to index + 1.
791-
object.index = index + 1
805+
this.#index = index + 1
806+
792807
// 13. Return the iterator result for pair and kind.
808+
793809
// https://webidl.spec.whatwg.org/#iterator-result
810+
794811
// 1. Let result be a value determined by the value of kind:
795812
let result
796-
switch (kind) {
813+
switch (this.#kind) {
797814
case 'key':
798815
// 1. Let idlKey be pair’s key.
799816
// 2. Let key be the result of converting idlKey to an
@@ -822,45 +839,37 @@ function createIterator (name, kInternalIterator, keyIndex = 0, valueIndex = 1)
822839
result = [key, value]
823840
break
824841
}
842+
825843
// 2. Return CreateIterResultObject(result, false).
826844
return {
827845
value: result,
828846
done: false
829847
}
830-
},
831-
writable: true,
832-
enumerable: true,
833-
configurable: true
834-
})
848+
}
849+
}
850+
851+
// https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object
852+
// @ts-ignore
853+
delete FastIterableIterator.prototype.constructor
854+
855+
Object.setPrototypeOf(FastIterableIterator.prototype, esIteratorPrototype)
835856

836-
// The class string of an iterator prototype object for a given interface is the
837-
// result of concatenating the identifier of the interface and the string " Iterator".
838-
Object.defineProperty(iteratorObject, Symbol.toStringTag, {
839-
value: `${name} Iterator`,
840-
writable: false,
841-
enumerable: false,
842-
configurable: true
857+
Object.defineProperties(FastIterableIterator.prototype, {
858+
[Symbol.toStringTag]: {
859+
writable: false,
860+
enumerable: false,
861+
configurable: true,
862+
value: `${name} Iterator`
863+
},
864+
next: { writable: true, enumerable: true, configurable: true }
843865
})
844866

845867
/**
846868
* @param {unknown} target
847-
* @param {'key'|'value'|'key+value'} kind
869+
* @param {'key' | 'value' | 'key+value'} kind
848870
*/
849871
return function (target, kind) {
850-
// esIteratorPrototype needs to be the prototype of iteratorObject
851-
// which is the prototype of an empty object. Yes, it's confusing.
852-
const iterator = Object.create(iteratorObject)
853-
Object.defineProperty(iterator, kInternalObject, {
854-
value: {
855-
target,
856-
kind,
857-
index: 0
858-
},
859-
writable: false,
860-
enumerable: false,
861-
configurable: true
862-
})
863-
return iterator
872+
return new FastIterableIterator(target, kind)
864873
}
865874
}
866875

@@ -873,7 +882,7 @@ function createIterator (name, kInternalIterator, keyIndex = 0, valueIndex = 1)
873882
* @param {string | number} [valueIndex]
874883
*/
875884
function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueIndex = 1) {
876-
const makeIterator = createIterator(name, kInternalIterator, keyIndex, valueIndex)
885+
const createIterator = createFastIterator(name, kInternalIterator, keyIndex, valueIndex)
877886

878887
const properties = {
879888
keys: {
@@ -882,7 +891,7 @@ function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueInde
882891
configurable: true,
883892
value: function keys () {
884893
webidl.brandCheck(this, object)
885-
return makeIterator(this, 'key')
894+
return createIterator(this, 'key')
886895
}
887896
},
888897
values: {
@@ -891,7 +900,7 @@ function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueInde
891900
configurable: true,
892901
value: function values () {
893902
webidl.brandCheck(this, object)
894-
return makeIterator(this, 'value')
903+
return createIterator(this, 'value')
895904
}
896905
},
897906
entries: {
@@ -900,7 +909,7 @@ function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueInde
900909
configurable: true,
901910
value: function entries () {
902911
webidl.brandCheck(this, object)
903-
return makeIterator(this, 'key+value')
912+
return createIterator(this, 'key+value')
904913
}
905914
},
906915
forEach: {
@@ -915,7 +924,7 @@ function iteratorMixin (name, object, kInternalIterator, keyIndex = 0, valueInde
915924
`Failed to execute 'forEach' on '${name}': parameter 1 is not of type 'Function'.`
916925
)
917926
}
918-
for (const { 0: key, 1: value } of makeIterator(this, 'key+value')) {
927+
for (const { 0: key, 1: value } of createIterator(this, 'key+value')) {
919928
callbackfn.call(thisArg, value, key, this)
920929
}
921930
}
@@ -1448,7 +1457,6 @@ module.exports = {
14481457
sameOrigin,
14491458
normalizeMethod,
14501459
serializeJavascriptValueToJSONString,
1451-
createIterator,
14521460
iteratorMixin,
14531461
isValidHeaderName,
14541462
isValidHeaderValue,

0 commit comments

Comments
 (0)