dylang / node-rss

RSS feed generator for Node.
https://npmjs.org/package/rss
MIT License
999 stars 133 forks source link

feed.item errors when passed directly to Array.prototype.forEach #66

Open strugee opened 7 years ago

strugee commented 7 years ago

I have a static site generator which, shockingly, is using node-rss to output RSS feeds.

This code runs successfully:

file.data.posts.map(function(post) {
    return {
        title: post.title,
        url: urlPrefix + file.relative,
        categories: post.categories,
        // TODO: normalize URLs to absolute URLs
        // See the `rss` docs for details
        description: post.contents,
        date: new Date(post.time.epoch * 1000)
    };
}).forEach(function(item) {
    feed.item(item);
});

As I'm sure you've guessed, file.data.posts is an array of posts. All that this does is map each post in to a node-rss-compatible item object and then call .item() on each object.

This code is theoretically functionally equivalent:

file.data.posts.map(function(post) {
    return {
        title: post.title,
        url: urlPrefix + file.relative,
        categories: post.categories,
        // TODO: normalize URLs to absolute URLs
        // See the `rss` docs for details
        description: post.contents,
        date: new Date(post.time.epoch * 1000)
    };
}).forEach(feed.item);

but it fails with TypeError: Cannot read property 'items' of undefined. Note that feed.item is being passed directly into forEach - presumably this is mangling this somehow, causing the error.

Here's the full stack trace:

/Users/alex/Development/github/strugee.github.com/node_modules/rss/lib/index.js:179
        this.items.push(item);
            ^

TypeError: Cannot read property 'items' of undefined
    at RSS.item (/Users/alex/Development/github/strugee.github.com/node_modules/rss/lib/index.js:179:13)
    at Array.forEach (native)
    at DestroyableTransform._transform (/Users/alex/Development/github/strugee.github.com/node_modules/stratic-indexes-to-rss/index.js:62:6)
    at DestroyableTransform.Transform._read (/Users/alex/Development/github/strugee.github.com/node_modules/readable-stream/lib/_stream_transform.js:159:10)
    at DestroyableTransform.Transform._write (/Users/alex/Development/github/strugee.github.com/node_modules/readable-stream/lib/_stream_transform.js:147:83)
    at doWrite (/Users/alex/Development/github/strugee.github.com/node_modules/readable-stream/lib/_stream_writable.js:313:64)
    at writeOrBuffer (/Users/alex/Development/github/strugee.github.com/node_modules/readable-stream/lib/_stream_writable.js:302:5)
    at DestroyableTransform.Writable.write (/Users/alex/Development/github/strugee.github.com/node_modules/readable-stream/lib/_stream_writable.js:241:11)
    at DestroyableTransform.ondata (/Users/alex/Development/github/strugee.github.com/node_modules/readable-stream/lib/_stream_readable.js:531:20)
    at emitOne (events.js:96:13)

I'm on Node.js@4.4, node-rss@1.2.1.

maxnowack commented 7 years ago

You can simply bind the this context to the function.

file.data.posts.map(function(post) {
    return {
        title: post.title,
        url: urlPrefix + file.relative,
        categories: post.categories,
        // TODO: normalize URLs to absolute URLs
        // See the `rss` docs for details
        description: post.contents,
        date: new Date(post.time.epoch * 1000)
    };
}).forEach(feed.item.bind(feed));