From 004c3f74edd1ae72abe6454d8eebb1a29e8578dd Mon Sep 17 00:00:00 2001 From: Mayhem Date: Sat, 15 Feb 2014 21:01:59 +0100 Subject: [PATCH] Re-think the Quote Backlink implementation. Before this rewrite, containers and backlinks were created even if the relevant post did not exist in the page. If the post would never end up existing, it resulted in a waste of resources. QuoteBacklink's cache also prevented these containers and backlinks from being garbage collected. We now only store a map of fullIDs. This feature should be faster since less elements gets allocated, although the difference is probably negligible. --- src/Quotelinks/QuoteBacklink.coffee | 77 ++++++++++++++--------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/src/Quotelinks/QuoteBacklink.coffee b/src/Quotelinks/QuoteBacklink.coffee index b6b00d825..ead8fe676 100644 --- a/src/Quotelinks/QuoteBacklink.coffee +++ b/src/Quotelinks/QuoteBacklink.coffee @@ -3,19 +3,19 @@ QuoteBacklink = # - previous, same, and following posts. # - existing and yet-to-exist posts. # - newly fetched posts. - # - in copies. + # - clones. # XXX what about order for fetched posts? # - # First callback creates backlinks and add them to relevant containers. - # Second callback adds relevant containers into posts. - # This is is so that fetched posts can get their backlinks, - # and that as much backlinks are appended in the background as possible. + # First callback creates a map of quoted -> [quoters], + # and append backlinks to posts that already have containers. + # Second callback creates, fill and append containers. init: -> return if !Conf['Quote Backlinks'] format = Conf['backlink'].replace /%id/g, "' + id + '" @funk = Function 'id', "return '#{format}'" - @containers = {} + @frag = $.nodes [$.tn(' '), $.el 'a', className: 'backlink'] + @map = {} Post.callbacks.push name: 'Quote Backlinking Part 1' cb: @firstNode @@ -23,42 +23,39 @@ QuoteBacklink = name: 'Quote Backlinking Part 2' cb: @secondNode firstNode: -> - return if @isClone or !@quotes.length - text = QuoteBacklink.funk @ID - a = $.el 'a', - href: "/#{@board}/res/#{@thread}#p#{@}" - className: 'backlink' - textContent: text - if @isHidden - $.addClass a, 'filtered' - if @isDead - $.addClass a, 'deadlink' - if Conf['Quote Markers'] - QuoteMarkers.parseQuotelink @board, @thread, @, a, false, text - for quote in @quotes - containers = [QuoteBacklink.getContainer quote] - if (post = g.posts[quote]) and post.nodes.backlinkContainer - # Don't add OP clones when OP Backlinks is disabled, - # as the clones won't have the backlink containers. - for clone in post.clones - containers.push clone.nodes.backlinkContainer - for container in containers - link = a.cloneNode true - if Conf['Quote Previewing'] - $.on link, 'mouseover', QuotePreview.mouseover - if Conf['Quote Inlining'] - $.on link, 'click', QuoteInline.toggle - $.add container, [$.tn(' '), link] + return if @isClone + for quoteID in @quotes + (QuoteBacklink.map[quoteID] or= []).push @fullID + continue unless (post = g.posts[quoteID]) and container = post?.nodes.backlinkContainer + for container in [container].concat post.clones.map((clone) -> clone.nodes.backlinkContainer) + $.add container, QuoteBacklink.buildBacklink @ return secondNode: -> - if @isClone and (@origin.isReply or Conf['OP Backlinks']) - @nodes.backlinkContainer = $ '.container', @nodes.info - return # Don't backlink the OP. return unless @isReply or Conf['OP Backlinks'] - container = QuoteBacklink.getContainer @fullID - @nodes.backlinkContainer = container + if @isClone + @nodes.backlinkContainer = $ '.backlink-container', @nodes.info + return + @nodes.backlinkContainer = container = $.el 'span', + className: 'backlink-container' + if @fullID of QuoteBacklink.map + for quoteID in QuoteBacklink.map[@fullID] + if post = g.posts[quoteID] # Post hasn't been collected since. + $.add container, QuoteBacklink.buildBacklink post $.add @nodes.info, container - getContainer: (id) -> - @containers[id] or= - $.el 'span', className: 'container' + buildBacklink: (post) -> + frag = QuoteBacklink.frag.cloneNode true + a = frag.lastElementChild + a.href = "/#{post.board}/res/#{post.thread}#p#{post}" + a.textContent = text = QuoteBacklink.funk post.ID + if post.isDead + $.addClass a, 'deadlink' + if post.isHidden + $.addClass a, 'filtered' + if Conf['Quote Markers'] + QuoteMarkers.parseQuotelink post.board, post.thread, post, a, false, text + if Conf['Quote Previewing'] + $.on a, 'mouseover', QuotePreview.mouseover + if Conf['Quote Inlining'] + $.on a, 'click', QuoteInline.toggle + frag