Bug Tracker

Opened 10 years ago

Closed 10 years ago

#13904 closed bug (notabug)

"on" events leak memory in the checkContext variable

Reported by: [email protected] Owned by: [email protected]
Priority: undecided Milestone: None
Component: unfiled Version: 1.9.1
Keywords: Cc: gibson042, Timmy Willison
Blocked by: Blocking:

Description

I've created a small sample which shows how the "on" function can leak memory. This was tested in Chrome 26, looking at the Memory Heap. To reproduce:

1) Load this test page (I've not used jsFiddle as it has it's own leaks and confuses the situation).

<html>
<head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
</head>
<body>

<div class="i_will_leak">
    <input type="text" />
</div>
<button>Leak</button>

<script>
    $(function () {

        $('div').on('click', 'input', function () {
            this.value = 'clicked';
        })
        
        $('button').click(function () {
            $('div').off().unbind().remove();
        })
    });
</script>
</body>
</html>

2) Click on the input box 3) Click the "Leak" button. This simply removes all events and trashes the element. (I've purposefully called all the removes I can think of, although remove() should suffice) 4) Check the memory profile for detached nodes and the "i_will_leak" DIV will have leaked against the checkContext variable.

NOTE: This ONLY happens if you actually click the input box, if you don't interact with it, then it doesn't leak. Hence the issue is in dispatching the event, rather than attaching or removing it.

Expected Result: It shouldn't leak

I hope this is enough information.

Change History (7)

comment:1 Changed 10 years ago by dmethvin

Owner: set to [email protected]
Status: newpending

It's just caching the selector there I think, we don't attempt to removed cached selectors because they can be reused. Or are you saying this continues without bound?

comment:2 Changed 10 years ago by [email protected]

Status: pendingnew

I don't believe it is as I've not seen it go away. Unless you have examples of how a subsequent query clears the cache? Surely if I've removed the event and node there is noting left to cache?

comment:3 Changed 10 years ago by dmethvin

Status: newpending

It won't go away, but it also shouldn't happen a second time. You've cached a selector there.

My question, restated, is: Does it "leak" every time you run that, or only the first time? You'll need to redo your example to allow you to re-attach the event handler.

comment:4 Changed 10 years ago by [email protected]

Status: pendingnew

Hi, I'm not sure I follow 100%, but I've changed the sample to allow a recreation and does appear to leak only once. Please confirm this is correct:

<html>
<head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
</head>
<body>

<div id="newAdd">
</div>

<button id="leak">Leak</button>


<button id="readd">Re-add</button>

<script>

    function buildSample() {
        $('#newAdd').append('<div class="i_will_leak"><input type="text" /></div>');
        $('.i_will_leak').on('click', 'input', function () {
            this.value = 'clicked';
        })
    }

    $(function () {

        $('#leak').click(function () {
            $('.i_will_leak').off().unbind().remove();
        })

        $('#readd').click(buildSample)

        buildSample();

    });
</script>
</body>
</html>

Thanks.

comment:5 Changed 10 years ago by dmethvin

Cc: gibson042 Timmy Willison added

We're caching a reference to the selector the first time we see it, so that we don't need to recompute it each time it's used. This is not a leak, we still have and in the future will use the reference to the code used to compute the 'input' selector string when needed.

timmywil, gibson042 am I misinterpreting this?

comment:6 Changed 10 years ago by gibson042

You've basically got it, dmethvin... as documented in the source:

The foundational matcher ensures that elements are reachable from top-level context(s)

We store a reference to the context and then test it with one of two functions (based on whether context is a node or an array). This allows us to use the same code when searching subtrees as we do with entire documents.

comment:7 Changed 10 years ago by dmethvin

Resolution: notabug
Status: newclosed

Okay, that's what I thought.

Note: See TracTickets for help on using tickets.