jQuery / Sizzle checkContext内存泄漏 [英] jQuery/Sizzle checkContext memory leak

查看:129
本文介绍了jQuery / Sizzle checkContext内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在DevTools中使用Profiles调试我的应用程序时,我发现已分离的DOM树已累积。这些分离的节点具有主要由 checkContext 函数组成的保留树(来自,修复它,运行所有Sizzle测试,并做了一个拉请求。



如果您要修补现有的jQuery或Sizzle副本:


  1. 打开您的jQuery或Sizzle文件


  2. 搜索 matcherFromTokens function


  3. 查找此代码(靠近顶部):

      matchers = [function(elem,context,xml){
    return(!leadingRelative&&(xml || context!==mostContext))|| (
    (checkContext = context).nodeType?
    matchContext(elem,context,xml):
    matchAnyContext(elem,context,xml));
    }];


  4. 返回 code> var rv = ,并添加 checkContext = undefined; 然后 return rv; 在匿名函数的末尾,例如:

      matchers = [function(elem,context,xml){
    var ret =(!leadingRelative&&((xml || context!==mostContext))|| (
    (checkContext = context).nodeType?
    matchContext(elem,context,xml):
    matchAnyContext(elem,context,xml));
    //释放上下文节点(问题#299)
    checkContext = null;
    return ret;
    }];


注意该代码将 null 分配给 checkContext ,因为这显然是他们的风格。如果是我,我会分配 undefined



如果提出修复有任何问题在拉动请求/合并过程中,我将更新答案。



最好不要让Sizzle缓存选择器,因为jQuery使用编译的选择器事件与事件委托,而且您每次发生相关事件时,都不需要重新分析并重建匹配器函数,因此可以确定元素是否匹配。






不幸的是,这不是jQuery对编译选择器中元素的唯一位置。它所做的每个地方可能是一个可以使用修复的bug。我只有时间跟踪另一个,我也已经报告和修复(等待提出请求登陆):



如果您搜索潜在复杂的伪造你会发现这个:不是伪选择器:

  pseudos:​​{
//潜在的复杂伪元素
not:markFunction(function(selector){
//修剪传递给编译器
//以避免将
//空格作为组合器处理
var input = [],
results = [],
matcher = compile(selector)替换(rtrim,$ 1));

返回匹配器[expando]?
markFunction(function(seed,matches,context,xml){
var elem,
unmatched = matcher(seed,null,xml,[]),
i = seed.length;

//匹配不匹配的元素matcher
while(i--){
if((elem = unmatched [i])){
seed [i] =!(matches [i] = elem);
}
}
}):
函数(elem,context,xml){
input [0] = elem;
匹配(input,null,xml,results);
return!results.pop();
};
}),

问题出在在条件运算符中:

 函数(elem,context,xml){
输入[0] = elem;
匹配(input,null,xml,results);
return!results.pop();
};

请注意,它不会清除 input [0] 。这是修复:

  function(elem,context,xml){
input [0] = elem;
匹配(input,null,xml,results);
//不要保留元素(问题#299)
input [0] = null;
return!results.pop();
};

现在我有时间跟踪。


While debugging my app with 'Profiles' in DevTools I found "Detached DOM tree's" accumulating. These detached nodes have retaining tree consisting mostly of checkContext functions (coming from sizzle inside jQuery - v1.10.1).

I'm not sure how to proceed with this. What does this result mean?

解决方案

This is actually a bug, there's no reason that Sizzle needs to hang onto the context node, it's only doing it because it's not cleaning up after setting a temporary variable. I filed an issue for it, fixed it, ran all the Sizzle tests, and did a pull request.

If you want to patch your existing copy of jQuery or Sizzle:

  1. Open your jQuery or Sizzle file

  2. Search for the matcherFromTokens function

  3. Find this code within it (near the top):

    matchers = [ function( elem, context, xml ) {
        return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
            (checkContext = context).nodeType ?
                matchContext( elem, context, xml ) :
                matchAnyContext( elem, context, xml ) );
    } ];
    

  4. Change the return to var rv =, and add checkContext = undefined; and then return rv; at the end of the anonymous function, e.g.:

    matchers = [ function( elem, context, xml ) {
        var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
            (checkContext = context).nodeType ?
                matchContext( elem, context, xml ) :
                matchAnyContext( elem, context, xml ) );
        // Release the context node (issue #299)
        checkContext = null;
        return ret;
    } ];
    

Note: That code assigns null to checkContext because apparently that's their style. If it were me, I'd've assigned undefined instead.

If there's any issue with the fix raised during the pull request / merge process, I'll update the answer.

It's better to keep letting Sizzle cache selectors, because jQuery uses the compiled selector stuff with event delegation, and you don't really want it to have to reparse and rebuild the matcher functions each time a relevant event occurs so it can figure out whether elements match it.


This isn't the only place jQuery holds onto elements in compiled selectors, unfortunately. Each place it does is probably a bug that could use fixing. I've only had the time to track down one other, which I've also reported and fixed (pending the pull request being landed):

If you search for "Potentially complex pseudos" you'll find this for the :not pseudo-selector:

pseudos: {
    // Potentially complex pseudos
    "not": markFunction(function( selector ) {
        // Trim the selector passed to compile
        // to avoid treating leading and trailing
        // spaces as combinators
        var input = [],
            results = [],
            matcher = compile( selector.replace( rtrim, "$1" ) );

        return matcher[ expando ] ?
            markFunction(function( seed, matches, context, xml ) {
                var elem,
                    unmatched = matcher( seed, null, xml, [] ),
                    i = seed.length;

                // Match elements unmatched by `matcher`
                while ( i-- ) {
                    if ( (elem = unmatched[i]) ) {
                        seed[i] = !(matches[i] = elem);
                    }
                }
            }) :
            function( elem, context, xml ) {
                input[0] = elem;
                matcher( input, null, xml, results );
                return !results.pop();
            };
    }),

The problem is in the function after the : in the conditional operator:

function( elem, context, xml ) {
    input[0] = elem;
    matcher( input, null, xml, results );
    return !results.pop();
};

Note that it never clears input[0]. Here's the fix:

function( elem, context, xml ) {
    input[0] = elem;
    matcher( input, null, xml, results );
    // Don't keep the element (issue #299)
    input[0] = null;
    return !results.pop();
};

That's all I have the time to track down at present.

这篇关于jQuery / Sizzle checkContext内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆