通过iframe脚本加载器避免全局污染?

问题...

存在需要包含在网页中的编码不佳的脚本。

这些脚本通过执行如下操作来污染全局范围:

  • 将值分配给未声明的标识符
  • 将属性添加到内置的构造函数(如ObjectArray )及其原型
  • 其他讨厌的东西。

  • 解?

    我想包括脚本没有不良副作用。 我认为这可以通过在iframe中加载脚本并将对象导出为父窗口的属性来实现。 以下是我迄今所得到的结果:

    <script>
    
    (function(){
      var g=this, frameIndex=frames.length, f=document.createElement('iframe');
    
      // hide it like this instead of display:none, because some old browser ignores
      // iframes with display:none, or is this an ancient habit I can drop?
      f.style.width='0px'; f.style.height='0px'; 
      f.style.border='none'; f.style.position='absolute';
    
      // append it to document.body or document.documentElement?
      // documentElement seems to work before body is loaded,
      // but is it cross-browser safe?  
      document.body.appendChild(f);
    
      // window object for our iframe
      var w=frames[frameIndex];
    
      // callback function pulls the object into the current window when script loads
      w.cb=function(){ g.SomeObject=w.SomeObject };
    
      // will this work on IE, or do I need to use document.createElement?
      // wanted to avoid document.createElement in this case because I'm not sure 
      // whether to call it from window.document or frames[frameIndex].document
      w.document.innerHTML='<script onload="cb()" src="myscript.js"></script>';
    
    }());
    
    </script>
    

    问题:

  • 如果脚本修改了内置的原型并将其移至另一个窗口,或者我的父窗口的内置插件保持干净并且所有内容都“正常工作?”,是否会有潜在的破坏?

  • 这个想法是在'最''浏览器上运行,还是有一个显示屏? 到目前为止,除了铬和莫兹之外,还没有测试过任何其他产品。

  • 我想在将对象拉入当前窗口后删除iframe,但如果iframe被删除,moz将失去对象引用。 有没有人知道解决方法?

  • 这已经完成了,还是有更好的方法来实现我的目标? 如果是这样,我应该寻找的脚本或技术的名称是什么?

  • (从这里移植的问题)


    要复制一个函数,你可以将它转换为一个字符串,然后对其进行评估....下面的代码还表明,在执行此操作后可以删除iframe,并且您的副本保持不变。

    以下代码示例使用FF

    Child.html片段

    <script>
    
    //
    // modify the prototype
    //
    Object.prototype.test = function(msg)
    {
            alert(msg);
    };  
    
    //
    // Simply declare a function
    //
    var whoo_hoo = function(){alert("whoo hoo");}
    </script>
    

    父母与iframe:

     <iframe id="help_frame" src="http://localhost/child.html"
     onLoad="javascript:Help.import_functions(this)"></iframe>
    
        <script>
        var Help = {
    
              imported_function :null,
                  import_functions : function(iframe)
       {
        this.imported_function = String(iframe.contentWindow.whoo_hoo);
        eval("this.imported_function = " + this.imported_function);
        iframe.parentNode.removeChild(iframe);
    
       //
       // displays 'whoo hoo' in an alert box
       //
       this.imported_function();
    
       try
       {
          //
          // If the Object prototype was changed in the parent
          // this would have displayed 'should not work' in an alert
          //
          this.test('should not work');
       }
       catch(e){alert('object prototype is unmodified');}
    
       }, 
        </script>
    

    http://thecodeabode.blogspot.com/


    加布里埃尔回答下的评论代码..

    var r = {
        init : null,
        _init: function(){
            var obj = new XMLHttpRequest();
            obj.onreadystatechange = function(){
                if ((this.status == 200) && this.readyState==4){
                    try{
                        eval("r.init = function(){" + this.responseText + "}");
                        r.init();
                    } catch(e){/*something bad in the script...*/}
                }
            }
            obj.open("GET","/jspolute_bad.js", true);
            obj.send();
        }   
    }
    r._init();
    

    将方法添加到原型中时,如果一个或两个导出的函数期望在外部代码中修改该方法,则可能会遇到麻烦。 想到的单调乏味的解决方案是,在对array.prototype,string.prototype进行评估之前,先将responseText正则表达并修复它。 将尝试这一点,让你知道..但它大多只会迎合直接脚本。


    这可能是一个可能的解决方案:

  • 将所有外部代码包装到一个类中
  • 使该类的所有未声明的标识符成员
  • 在调用乱码之前,先制作一个内置类的副本并以不同的方式命名它们
    (这可能吗??)。
  • 我认为这应该解决所有问题。

    用我的建议,你的样品

    var badA = "hahaha";
    this.badB = "hehehe";
    badC = "hohoho";
    
    String.prototype.star = function(){ return '***' + this + '***' }
    
    var somethingUseful = {
      doStuff: function () {
        alert((badA + badB + badC).star());
      }
    }
    

    应该得到这样的

    // Identifies the added properties to prototypes (ie String and Function)
    // for later filtering if you need a for-in loop.
    var stringAddons = [];
    var functionAddons = []
    var _string = new String();
    var _function = function() {};
    for (var property in _string) { if (!_string.hasOwnProperty(property)) { stringAddons.push(property); }}
    for (var property in _function) { if (!_function.hasOwnProperty(property)) { functionAddons.push(property); }}
    
    // Wraps the undeclared identifiers
    var global = function()
    {
      this.badA = "hahaha";
      this.badB = "hehehe";
      this.badC = "hohoho";
    
      String.prototype.star = function(){ return '***' + this + '***' }
    
      this.somethingUseful = {
        doStuff: function () {
          alert((global.badA + global.badB + global.badC).star());
        }
      }
    }
    var global = new Global();
    global.somethingUseful.doStuff();
    

    棘手的部分是使所有未声明的标识符全局属性。 也许一个好的正则表达式脚本可以做到这一点。 我不是很好,正则表达式:)

    链接地址: http://www.djcxy.com/p/3019.html

    上一篇: Avoiding pollution of globals via iframe script loader?

    下一篇: Displaying SVG in Flex 4