Notification tooltip script breaks after using the site for a while



  • I'm using @anotherusername's notification tooltip script to preview posts from my notifications. It works, until some unknown triggering condition when it stops working and instead spams TypeError: Cannot convert undefined or null to object to the console. What's strange is that if I wrap the line of code (clearTimeout(mouse_timeout)) in an if block to check if mouse_timeout is not null or undefined, it still throws the error, and what's even stranger is that if I set a breakpoint, the code works no problem.

    I don't think there have been any changes in nodebb recently, and there definitely haven't been any updates to the userscript. Maybe it's something in the latest Chrome update?

    e: Refreshing the page makes it work again, at least for a little while until the next time unknown triggering condition happens.

    Unrelated bug: The first time I tried posting this, the category picker didn't work. It displayed and filtered the categories just fine, but clicking on one did nothing, not even show an error on the console.



  • @hungrier How recently has it started doing this? Does the error message (or the stack trace) include a line number, or the function it was in when the error occurred?

    clearTimeout doesn't care if its argument is null or undefined, by the way. It just does nothing.

    40b6e341-44d3-4c83-b1f2-f7bc58e64b4e-image.png



  • @anotherusername It's not doing it at the moment but it did include a line number and source document (chrome-extension://whatever/userscript.thml?id=someguid); that's where I got the notion that it was the clearTimeout line. Whenever it starts doing it again I'll update with more detail.

    I only noticed it today on my work computer, which is why I think it might have to do with Chrome.



  • userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:154 (console.error in the catch block)
    TypeError: Cannot convert undefined or null to object
    at HTMLUListElement.notif_hover (userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:60) MouseEvent

          if (orig_x == undefined || moved) {
            if (mouse_timeout) { 
                clearTimeout(mouse_timeout); // line 60
            }
            tooltip.remove();
    

    As I mentioned, I tried wrapping it in an if block but that doesn't fix it



  • @hungrier Hm. A bit further down than that, try replacing the line

    if (!post.deleted) {
    

    with

    if (err) {
      console.error(err);
    } else if (!post) {
      console.error('Error: post is', post);
    } else if (!post.deleted) {
    


  • So now it's Monday and I'm back on my work computer, and it's doing it again. I had tried editing the script with the above before I left on Friday, but none of that stuff is printing. I did get something new, though

    userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:159 TypeError: Cannot convert undefined or null to object
        at HTMLUListElement.notif_hover (userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:60) MouseEvent {isTrusted: true, screenX: 1419, screenY: 161, clientX: 1419, clientY: 58, …}
    notif_hover @ userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:159
    userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:159 TypeError: Cannot convert undefined or null to object
        at HTMLUListElement.notif_hover (userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:39) MouseEvent {isTrusted: true, screenX: 1416, screenY: 158, clientX: 1416, clientY: 55, …}
    notif_hover @ userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:159
    userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:159 TypeError: Cannot convert undefined or null to object
        at notif_hover (userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:39) Event {isTrusted: true, type: "scroll", target: document, currentTarget: Window, eventPhase: 3, …}
    notif_hover @ userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:159
    userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:159 TypeError: Cannot convert undefined or null to object
        at notif_hover (userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:39) Event {isTrusted: true, type: "scroll", target: document, currentTarget: Window, eventPhase: 3, …}
    

    It seems line 39 is another problem line...

          // if this is a mouseout event, check whether the mouse has left the ul element
          if (!e.target.closest || !e.target.closest('ul') || !e.target.closest('ul').contains(e.relatedTarget)) {
            if (mouse_timeout) {
                clearTimeout(mouse_timeout); // line 39
            }
            tooltip.remove();
            orig_e = undefined;
    

    :facepalm:

    I'm going to try adding something else and see if anything different happens.



  • if i only had a brain 3499
    userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:157 TypeError: Cannot convert undefined or null to object
        at HTMLUListElement.notif_hover (userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:59) MouseEvent
    notif_hover @ userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:157
    userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:38 hello my name is goofle chrome and im special 3499
    userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:157 TypeError: Cannot convert undefined or null to object
        at HTMLUListElement.notif_hover (userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:39) MouseEvent
    
          // if this is a mouseout event, check whether the mouse has left the ul element
          if (!e.target.closest || !e.target.closest('ul') || !e.target.closest('ul').contains(e.relatedTarget)) {
            console.log('hello my name is goofle chrome and im special',mouse_timeout);
            clearTimeout(mouse_timeout);
            tooltip.remove();
    // ...
          if (orig_x == undefined || moved) {
            console.log('if i only had a brain',mouse_timeout);
            clearTimeout(mouse_timeout);
            tooltip.remove();
    

    ¯\_(ツ)_/¯



  • I also noticed something with this new "goofle" logging: It works just fine when the thing is actually undefined



  • @hungrier I guess you could try changing clearTimeout(mouse_timeout) to if (mouse_timeout) clearTimeout(mouse_timeout), and see if that helps?

    I'm wondering if tooltip might be getting ... I dunno, maybe it's been changed somewhere else? Try logging that and see if it's still the HTML element that it should be.

    edit: what's line 157? It says that the message is being logged from line 38, but the error is on line 157.



  • @anotherusername Line 157 is the console.error line in the catch block at the bottom.

    I've added tooltip to my logs to see if anything happens to it



  • @hungrier doh. Well of course that's what it is.



  • Update: tooltip looks normal and contains the last post that I previewed before it started failing

    hello my name is goofle chrome and im special 2986 <div class=​"notif-tooltip topic" style=​"left:​ 1148px;​ top:​ 126px;​">​…​</div>​
    userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:157 TypeError: Cannot convert undefined or null to object
        at HTMLUListElement.notif_hover (userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:39) MouseEvent
    


  • @hungrier Have you definitely narrowed it down to the clearTimeout line? Another console.log immediately following it would confirm whether or not it's the problem.

    I have no idea why clearTimeout would be causing problems, especially since the value of mouse_timeout is being logged and looks perfectly fine. If that line is actually where the error is coming from, I'm tempted to just say to wrap it in try { ... } catch(e) {} and forget about it. As far as I know, clearTimeout can't throw an error, so if it's doing that, it's a bug. MDN specifically states that it silently does nothing if an invalid ID is passed.

    edit: maybe wait until it's happening, and then set a breakpoint in the code and step through it line by line to see what happens?



  • @anotherusername As you say that makes no sense, but everything still points to the clearTimeout.

    hello my name is goofle chrome and im special 4879 <div class=​"notif-tooltip topic" style=​"left:​ 1207px;​ top:​ 5055px;​">​…​</div>​
    userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:40 goofle after clearing 4879
    userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:38 hello my name is goofle chrome and im special 4879 <div class=​"notif-tooltip topic" style=​"left:​ 1207px;​ top:​ 5055px;​">​…​</div>​
    userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:159 TypeError: Cannot convert undefined or null to object
        at notif_hover (userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:39) Event
    notif_hover @ userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:159
    userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:38 hello my name is goofle chrome and im special 4879 <div class=​"notif-tooltip topic" style=​"left:​ 1207px;​ top:​ 5055px;​">​…​</div>​
    userscript.html?id=bebb72a5-8235-47d7-bedc-47dcaa0be22e:159 TypeError: Cannot convert undefined or null to object
    
                        console.log('hello my name is goofle chrome and im special',mouse_timeout,tooltip);
                        clearTimeout(mouse_timeout);
                        console.log('goofle after clearing',mouse_timeout);
    


  • @hungrier Unless something is replacing clearTimeout with some other zombified function, I'd pretty much just say wrap that line in a try...catch and throw away the error. The really weird part is that it looks like there's actually a valid timeout ID in mouse_timeout.

    ...um, this is a crazy idea, but maybe try changing clearTimeout to window.clearTimeout (or unsafeWindow.clearTimeout)?



  • @anotherusername It may be too early to tell for sure, but adding window. in front of clearTimeout (and as I found out, setTimeout as well) seems to have fixed it.



  • @hungrier Alright, then I think maybe I know what's happening. Somewhere internally, those functions are trying to use this, and they're expecting it to be the window object. They're methods of the window object, but they're not bound to it if you call them stand-alone (even though window is global and you can refer to any of its properties or methods globally).

    I would argue that they should really still work, or at the very least this behavior should be consistent. It appears to be in the browser's native code, so I'd call it a bug in Chrome.



  • @anotherusername It had been working just fine for months, until a few days ago. So it's probably something that changed in Chrome, or maybe in Tampermonkey.



  • @hungrier I wrote a function that triggers that error by trying to access this internally, but interestingly it only generates that specific error message in Chrome, and only for certain types of code.

    3a7da04f-11a0-4aa9-a4dd-6e7809533a24-image.png

    In addition to delete, I've found that calling Object.keys with an undefined argument can also produce that error in Chrome, at least in certain situations.


  • Fake News

    And this, kids, is why I don't do Web front-end work. 🚂


Log in to reply