Skip to content

Commit bb4a949

Browse files
authored
Make _getIndexOf() lookup O(1)
Add a property-to-index Map to improve _getIndexOf() lookup times.
1 parent f712f54 commit bb4a949

File tree

1 file changed

+27
-22
lines changed

1 file changed

+27
-22
lines changed

lib/CSSStyleDeclaration.js

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class CSSStyleDeclaration {
4848

4949
// Other internals
5050
this._length = 0;
51+
this._propertyIndices = new Map();
5152
this._priorities = new Map();
5253
this._values = new Map();
5354

@@ -118,7 +119,7 @@ class CSSStyleDeclaration {
118119
const name = "NoModificationAllowedError";
119120
throw new this._global.DOMException(msg, name);
120121
}
121-
this._removeIndexedProperties(0, this._length);
122+
this._clearIndexedProperties();
122123
this._values.clear();
123124
this._priorities.clear();
124125
if (this._parentRule || (this._ownerNode && this._updating)) {
@@ -298,7 +299,7 @@ class CSSStyleDeclaration {
298299
this._priorities.delete(property);
299300
const index = this._getIndexOf(property);
300301
if (index >= 0) {
301-
this._removeIndexedProperties(index, 1);
302+
this._removeIndexedProperty(index);
302303
if (this._onChange) {
303304
this._onChange(this.cssText);
304305
}
@@ -346,25 +347,33 @@ class CSSStyleDeclaration {
346347
}
347348

348349
/**
349-
* Removes indexed properties at the specified index and shifts others.
350-
* Removes all indexed properties if count === this._length.
350+
* Clears all indexed properties, properties indices and resets length to 0.
351351
*
352352
* @private
353-
* @param {number} index - The start index.
354-
* @param {number} count - The number of properties to remove.
355353
*/
356-
_removeIndexedProperties(index, count) {
357-
const length = this._length;
358-
// Shift subsequent properties.
359-
// Will be skipped if count === length.
360-
for (let i = index; i < length - count; i++) {
361-
this[i] = this[i + count];
362-
}
363-
// Delete properties at the end.
364-
for (let i = length - count; i < length; i++) {
354+
_clearIndexedProperties() {
355+
this._propertyIndices.clear();
356+
for (let i = 0; i < this._length; i++) {
365357
delete this[i];
366358
}
367-
this._length -= count;
359+
this._length = 0;
360+
}
361+
362+
/**
363+
* Removes an indexed property at the specified index, shifts others, and updates indices.
364+
*
365+
* @private
366+
* @param {number} index - The index of the property to remove.
367+
*/
368+
_removeIndexedProperty(index) {
369+
this._propertyIndices.delete(this[index]);
370+
for (let i = index; i < this._length - 1; i++) {
371+
const property = this[i + 1];
372+
this[i] = property;
373+
this._propertyIndices.set(property, i);
374+
}
375+
delete this[this._length - 1];
376+
this._length--;
368377
}
369378

370379
/**
@@ -375,12 +384,7 @@ class CSSStyleDeclaration {
375384
* @returns {number} The index of the property, or -1 if not found.
376385
*/
377386
_getIndexOf(property) {
378-
for (let i = 0; i < this._length; i++) {
379-
if (this[i] === property) {
380-
return i;
381-
}
382-
}
383-
return -1;
387+
return this._propertyIndices.get(property) ?? -1;
384388
}
385389

386390
/**
@@ -406,6 +410,7 @@ class CSSStyleDeclaration {
406410
if (!this._values.has(property)) {
407411
// New property.
408412
this[this._length] = property;
413+
this._propertyIndices.set(property, this._length);
409414
this._length++;
410415
}
411416
if (priority === "important") {

0 commit comments

Comments
 (0)