hustcc / timeago.js

:clock8: :hourglass: timeago.js is a tiny(2.0 kb) library used to format date with `*** time ago` statement.
https://timeago.org
MIT License
5.29k stars 411 forks source link

Uncaught TypeError: node.getAttribute is not a function when passed an empty node list #230

Closed haacked closed 8 months ago

haacked commented 3 years ago

Thanks for this great library! I found a potential bug with it though.

Suppose I have the following script that loads on every page.

document.addEventListener("DOMContentLoaded", () => {
    timeago.render(document.querySelectorAll('time.timeago[datetime]'));
});

It works great when a page has elements that match that query selector. But for a page that doesn't match the query selector, I get the following exception.

Uncaught TypeError: node.getAttribute is not a function
Uncaught TypeError: node.getAttribute is not a function
    at getDateAttribute (dom.ts?670d:9)
    at eval (realtime.ts?6dbd:63)
    at Array.forEach ()
    at Module.render (realtime.ts?6dbd:62)

The bug seems to be this line:

const nodeList: HTMLElement[] = nodes.length ? nodes : [nodes];

This assumes that if there's no length property, then it's a node and not a node list. However, if a node list is empty, the nodes.length returns 0 which is interpreted as false, which then falls back to the [nodes] clause, thus creating an array consisting of one empty node list.

I think the correct behavior would be to change this to:

const nodeList: HTMLElement[] = NodeList.prototype.isPrototypeOf(nodes) ? nodes : [nodes];