>>1755Here are some old posts from lainchan with some anon explaining the posts below the line bug #207 as it existed back then, as well as a few related bugs. Parts of the explanation are likely to still apply to the current leftypol.
2019-03-13 14:51:52 No.12838
The new post insertion in auto-reload.js >>12829 is wrong.
if ($("div.post").length > 1){
$(this).parent().insertAfter($('div.post:not(.post-hover):last').parent().next()).after('<br class="clear">');
}
else {
$(this).insertAfter($('div.post:not(.post-hover):last')).after('<br class="clear">');
}
The structure of div.thread in a thread page without JS is defined by templates/post_thread.html, templates/post_reply.html and templates/post. It looks like this:
a.post_anchor
div.files
div.post.op
repeat (
div.postcontainer
<br/>) for every reply
<br class="clear"/><hr/> https://github.com/lainchan/lainchan/blob/master/templates/post_thread.htmlhttps://github.com/lainchan/lainchan/blob/master/templates/post_reply.htmlOne issue is that the 'after' calls should use '<br/>' as used by templates/post_reply.html. The '<br class="clear"/>' is only used once by templates/post_thread.html, to separate the horizontal rule / thematic break, and it would have lacked the closing slash anyway. More importantly, the else branch inserts the wrong element. It inserts the div.post.reply instead of the div.postcontainer, which is its .parent(). And while the insertion point is correct, right after the only div.post, that :last can be removed and an .op class added before the :not, which will be faster.
The effect of inserting the wrong element, div.post.reply, is that the next insertion, which will take the first branch, will find that the last reply's .parent() is the div.thread, the .next() is the div.thread-interactions, and will insert after that, completely outside the reply list. This is the mechanism by which replies can end up under the separator line. This effect can be deterministically replicated by the following procedure.
- Go to a thread with a small number of replies, not less than two, with scripts enabled. E.g. >>12786
- Uncheck the auto update box.
- Inspect the page and delete the div.postcontainer elements and the br elements immediately following each one, leaving only the op.
- Click '[Update]'.
You will see the replies from the second onward go under the reply area, below the separator and some links. Inserting the .parent() on the else branch will fix this.
2019-03-13 21:57:10 No.12844
For some light entertainment, the >>12838 test can be performed on a thread with a large number of replies. The deletion can be performed by
$('div.postcontainer').remove ();
$('div.thread > br:not(.clear)').remove ();
which reduces the thread to the op. Clicking '[Update]' then demonstrates the effect.
2019-03-17 04:09:58 No.12885
Here is one mechanism that will cause auto-reload.js >>12829 to skip posts when updating. When polling the thread is reread via ajax and the replies are looped over and added if they pass this test:
$(data).find('div.post.reply').each(function() {
var id = $(this).attr('id');
if($('#' + id).length == 0) {
This seems reasonable in isolation, since it avoids readding existing replies. The problem appears in js/post-hover.js which attempts to support hovering over crossboard links.
https://github.com/lainchan/lainchan/blob/master/js/post-hover.jsIf a linked post is hovered and not already present in this thread, its thread is obtained via ajax and then:
var mythreadid = $(data).find('div[id^="thread_"]').attr('id').replace("thread_", "");
if (mythreadid
== threadid && parentboard
== board) {
$(data).find('div.post.reply').each(function() {
if($('[data-board="' + board + '"] #' + $(this).attr('id')).length == 0) {
$('[data-board="' + board + '"]#thread_' + threadid + " .post.reply:first").before($(this).hide().addClass('hidden'));
}
});
}
else if ($('[data-board="' + board + '"]#thread_'+mythreadid).length > 0) {
$(data).find('div.post.reply').each(function() {
if($('[data-board="' + board + '"] #' + $(this).attr('id')).length == 0) {
$('[data-board="' + board + '"]#thread_' + mythreadid + " .post.reply:first").before($(this).hide().addClass('hidden'));
}
});
}
else {
$(data).find('div[id^="thread_"]').hide().attr('data-cached', 'yes').prependTo('form[name="postcontrols"]');
}
If the post belongs to this thread, or to a thread already stored in this one, it is added as a hidden post to the top of its thread in reverse order. If the post belongs to another thread not yet stored in this one, its entire div.thread is added as a hidden element to the top of the postcontrols form. This can be observed in the new CA thread >>12868 where someone linked the old one from the archive. Before hovering over the archive link the postcontrols form starts with the hidden input and div.thread#thread_9558. After hovering over the archive link the postcontrols form acquires a hidden div.thread#thread_17 as its first child. In this particular case this will not be a problem, because all post numbers in the old thread are lower than all post numbers in the new thread.
The problem is that while post numbers are unique within a board, they are not unique across boards. By storing a foreign thread in the current one, post-hover.js risks duplicating post numbers and thus duplicating ids, which is already illegal in plain HTML. The id namespace of a page is flat, so care must be taken to separate ids that use the same post number. For example, templates/post_reply.html uses #pcNNN for post containers and reply_NNN for replies.
https://github.com/lainchan/lainchan/blob/master/templates/post_reply.htmlThe same care is not exercised by post-hover.js with crossboard post numbers, which can collide. This lack of namespacing of crossboard ids in a flat page id space was introduced by czaks on Aug 5 2013 in commit:
https://github.com/lainchan/lainchan/commit/185e68de47210b9886d87196832d166ff85dc72cAuto-reload.js can skip posts like this. If the current thread has a crossboard link to a thread with higher ids, that thread is stored in the current one upon hover. If the current thread then receives a new reply with a post number that is already used in the foreign thread, that reply will not pass the insertion test and auto-reload.js will not add it, believing it to be already present.
The solution is to either have post-hover.js use a different storage location for foreign threads, outside the DOM, or to apply namespacing to all ids inserted from foreign threads, using their board name. For example, the foreign thread's div.thread could be traversed and any id modified with the foreign board name as a prefix or suffix. The same scheme would then be used for looking up foreign posts.
No offense to the original Tinyboard crew but the architecture of JS extensions is looking increasingly like a haphazardly thrown together pile of good intentions, held up by hope and faith.
2019-03-17 12:32:38 No.12887
Experimental verification of >>12885. On the test board, a music post is linked that is in a thread that contains the next post number from the test thread. The next test post is the skip test. This procedure follows:
- Uncheck auto reload.
- Inspect the page and remove the skip test post's postcontainer and br.
- Enabling auto reload brings in the removed post as if it were a new reply.
- Uncheck auto reload again.
- Remove the skip test post again.
- Hover the music post's link and wait for the overlay to load.
- Enabling auto reload does not bring in the removed post. Instead, the countdown interval is doubled.
This happens because the removed post's id was added by post-hover.js as part of the hidden copy of the music thread. So auto-reload.js considers that reply to be already present and sees nothing that needs to be inserted. To verify this final state:
>> $('#reply_725')Object { 0: <div#reply_725.post.reply>, length: 1, context: HTMLDocument → 528.html, selector: "#reply_725" }
>> $('#reply_725').parent ().parent ()Object { 0: <div#thread_667.thread>, length: 1, prevObject: Object, context: HTMLDocument → 528.html }
>> $('#reply_725').parent ().parent () [0].attributesNamedNodeMap [ data-board="music", id="thread_667", class="thread", style="display: none;", data-cached="yes" ]
2019-03-20 11:32:23 No.12913
The new post insertion in ajax.js is even more broken than in auto-reload.js >>12838.
https://github.com/lainchan/lainchan/blob/master/js/ajax.js$(data).find('div.post.reply').each(function() {
var id = $(this).attr('id');
if($('#' + id).length == 0) {
$(this).insertAfter($('div.post:last').next()).after('<br class="clear">');
- The insertion needs the branching that handles OP-only threads.
- The inserted element has to be the parent div.postcontainer instead of the div.post.reply.
- The insertion point is explained in the linked post.
- The 'after' should be the '<br/>' used by templates/post_reply.html.
Since this is causing trouble and is used in at least two places, it might be worth factoring out into a function.
2019-03-29 00:51:32 No.13036
In addition to a mechanism that causes auto-reload.js to skip >>12885 posts, here is one mechanism that causes posts to appear out of order. Clicking on '[Last 50 Posts]' on an index page loads a page like
https://lainchan.org/%CE%BB/res/10399+50.htmlwith the OP and the last 50 replies – choosing a large thread. If one of the loaded posts is deleted between updates, usually one of the last ones, and no new posts are made in the same update interval, the next update will fetch a 50-post slice that has moved back by one position. The first post of the new slice has a post number smaller than the first displayed reply and is not in the current DOM, so auto-reload.js will consider it a new post, and just like any other new post it will be added to the end of the thread. This causes it to be out of order. To replicate this open a +50.html page, uncheck auto update, then inspect and remove the first reply's postcontainer and br. This is equivalent to having had the last reply of the incremented slice removed. Clicking '[Update]' then brings in a lower numbered post, into the last position.
To deal with this in the general case, binary search can be used to find the insertion point that maintains the sorted list invariant at every step. To accelerate the most common case of a new reply, the higher end can be tested first. To avoid each inserter script having to reinvent the wheel, sorted post insertion that correctly handles OP-only threads should be moved into a common utility function.