【问题标题】:Why does this userscript cause a memory leak?为什么这个用户脚本会导致内存泄漏?
【发布时间】:2013-05-21 09:28:30
【问题描述】:

我的浏览器是 SRWare Iron 24.0 Portable,Tampermonkey 版本是 2.12.3124.256 OR
3.0.3389.11。我写了以下用户脚本:

// ==UserScript==
// @name        Night Mode
// @namespace   http://use.i.E.your.homepage/
// @version     1.0
// @description  Add night mode style
// @include     http*
// @run-at      document-start
// ==/UserScript==

function addNightStyle(){
    var rules = ['html, body { background: #383838 !important; }',
        'div { background-color: #383838 !important; }',
        'header,nav,table,th,tr,td,dl,ul,li,ol,fieldset,form,h1,h2,h3,h4,h5,h6,pre { background: transparent !important;}',
        '* { color: #B6AA7B !important; }',
        'a:link,a:link *,a:link:hover,a:link:hover *,a:link:active,a:link:active * { color: #B6AA7B !important; }',
        'a:visited,a:visited *,a:visited:hover,a:visited:hover *,a:visited:active,a:visited:active * { color: #D9C077 !important; }'
        ];
    with( document.head.appendChild(document.createElement('style')) ){
        id = 'nightmode';
        for(var i=0; i<rules.length; i++){
            sheet.insertRule(rules[i], i);
        }
    }
}
setTimeout(addNightStyle,90);

当此脚本处于活动状态时,随着我浏览更多页面,渲染器进程的内存使用量和虚拟大小会逐渐增加。只有关闭相应渲染器进程的所有选项卡才能释放内存。

为什么这个脚本会导致内存泄漏?

如何解决?

【问题讨论】:

  • sheet 应该是什么?
  • 别这样!对于样式更改,请使用 Stylish。否则,请使用GM_addStyle()。当脚本只有一行console.log()时,内存是否泄漏?完成后尝试清除该 setTimeout ,但在这种情况下无论如何您都不应该使用计时器;测试 DOM 状态或在启动时不运行。

标签: javascript memory-leaks userscripts tampermonkey srware-iron


【解决方案1】:

首先,rules 在这种情况下是一个关键字,你的循环甚至没有开始,你必须为你的规则列表选择一个不同的名称。无论如何,根据MDN Reference - CSSStyleSheet,您无法通过这种方式访问​​insertRule,但您可以这样做:

function addNightStyle(){
    var ruleList = ['html, body { background: #383838 !important; }',
        'div { background-color: #383838 !important; }',
        'header,nav,table,th,tr,td,dl,ul,li,ol,fieldset,form,h1,h2,h3,h4,h5,h6,pre { background: transparent !important;}',
        '* { color: #B6AA7B !important; }',
        'a:link,a:link *,a:link:hover,a:link:hover *,a:link:active,a:link:active * { color: #B6AA7B !important; }',
        'a:visited,a:visited *,a:visited:hover,a:visited:hover *,a:visited:active,a:visited:active * { color: #D9C077 !important; }'
        ];
    document.head.appendChild(document.createElement('style'));
    with(sheet = document.styleSheets[document.styleSheets.length - 1]){
        id = 'nightmode';
        for (var i = 0; i < ruleList.length; i++) {
            sheet.insertRule(ruleList[i], i);
        }
    }
}

工作JSFiddle

【讨论】:

  • 经过测试。还是内存泄漏。通过 document.styleSheets 或 style 元素的 sheet 属性访问的样式表对象是严格相等的(===)。所以我认为这不是内存泄漏的原因。 --- 另外,如果正文中有样式元素,则最后一个样式表不是附加到头部的样式表。 (我知道这不是标准的,但有些页面会这样做。)
  • 是的,你是对的,我没有注意到这一点。无论如何,我真的不明白为什么它不起作用,在小提琴中它没有给我任何问题......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-19
相关资源
最近更新 更多