Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions lib/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ function docGUID(doc) {
* without defining or constraining how this collection is implemented.
* NodeList objects in the DOM are live.
* The items in the NodeList are accessible via an integral index, starting from 0.
* You can also access the items of the NodeList with a `for...of` loop.
*
* @class NodeList
* @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
Expand Down Expand Up @@ -361,6 +362,30 @@ NodeList.prototype = {
return Array.prototype.indexOf.call(this, item);
},
};
NodeList.prototype[Symbol.iterator] = function () {
var me = this;
var index = 0;

return {
next: function () {
if (index < me.length) {
return {
value: me[index++],
done: false,
};
} else {
return {
done: true,
};
}
},
return: function () {
return {
done: true,
};
},
};
};

/**
* Represents a live collection of nodes that is automatically updated when its associated
Expand Down Expand Up @@ -667,6 +692,30 @@ NamedNodeMap.prototype = {
return null;
},
};
NamedNodeMap.prototype[Symbol.iterator] = function () {
var me = this;
var index = 0;

return {
next: function () {
if (index < me.length) {
return {
value: me[index++],
done: false,
};
} else {
return {
done: true,
};
}
},
return: function () {
return {
done: true,
};
},
};
};

/**
* The DOMImplementation interface provides a number of methods for performing operations that
Expand Down
57 changes: 57 additions & 0 deletions test/dom/named-node-map.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,63 @@ const HTML_OWNER_ELEMENT = { _isInHTMLDocumentAndNamespace: () => true };
const XML_OWNER_ELEMENT = { _isInHTMLDocumentAndNamespace: () => false };

describe('NamedNodeMap', () => {
describe('Iterator', () => {
test('should iterate over 3/3 items when using a for...of loop without interruption', () => {
const it = new NamedNodeMap();
const first = new Attr();
it[0] = first;
const second = new Attr();
it[1] = second;
const third = new Attr();
it[2] = third;
it.length = 3;

let count = 0;
for (const _item of it) {
count++;
}
expect(count).toBe(it.length);
});
test('should iterate over 1/3 items when using a for...of loop and breaking after first iteration', () => {
const it = new NamedNodeMap();
const first = new Attr();
it[0] = first;
const second = new Attr();
it[1] = second;
const third = new Attr();
it[2] = third;
it.length = 3;

let count = 0;
for (const _item of it) {
count++;
break;
}
expect(count).toBe(1);
});
test('should iterate over 3/3 items when using two for...of loops subsequently', () => {
const it = new NamedNodeMap();
const first = new Attr();
it[0] = first;
const second = new Attr();
it[1] = second;
const third = new Attr();
it[2] = third;
it.length = 3;

let firstCount = 0;
for (const _item of it) {
firstCount++;
}
let secondCount = 0;
for (const _item of it) {
secondCount++;
}

expect(firstCount).toBe(it.length);
expect(secondCount).toBe(it.length);
});
});
describe('getNamedItem', () => {
test('should return null when no attribute is found', () => {
const it = new NamedNodeMap();
Expand Down
59 changes: 58 additions & 1 deletion test/dom/node-list.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,66 @@
'use strict';

const { describe, expect, test } = require('@jest/globals');
const { NodeList, LiveNodeList, DOMImplementation } = require('../../lib/dom');
const { NodeList, LiveNodeList, DOMImplementation, Element } = require('../../lib/dom');

describe('NodeList', () => {
describe('Iterator', () => {
test('should iterate over 3/3 items when using a for...of loop without interruption', () => {
const it = new NodeList();
const first = new Element();
it[0] = first;
const second = new Element();
it[1] = second;
const third = new Element();
it[2] = third;
it.length = 3;

let count = 0;
for (const _item of it) {
count++;
}
expect(count).toBe(it.length);
});
test('should iterate over 1/3 items when using a for...of loop and breaking after first iteration', () => {
const it = new NodeList();
const first = new Element();
it[0] = first;
const second = new Element();
it[1] = second;
const third = new Element();
it[2] = third;
it.length = 3;

let count = 0;
for (const _item of it) {
count++;
break;
}
expect(count).toBe(1);
});
test('should iterate over 3/3 items when using two for...of loops subsequently', () => {
const it = new NodeList();
const first = new Element();
it[0] = first;
const second = new Element();
it[1] = second;
const third = new Element();
it[2] = third;
it.length = 3;

let firstCount = 0;
for (const _item of it) {
firstCount++;
}
let secondCount = 0;
for (const _item of it) {
secondCount++;
}

expect(firstCount).toBe(it.length);
expect(secondCount).toBe(it.length);
});
});
describe('item', () => {
test('should return null for items outside length', () => {
const it = new NodeList();
Expand Down