1

从阅读示例来看,这似乎应该很容易。这是我的代码:

rhkTest = {
  onPageLoad: function(event) {
    var doc = event.originalTarget;
    var wnd = doc.defaultView;
    var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
      .getService(Components.interfaces.mozIJSSubScriptLoader);
    loader.loadSubScript("chrome://rhkoshi-extension/content/testfoo.js", wnd);
    alert('typeof(wnd) = ' + typeof(wnd));
    alert('typeof(wnd.window.rhk_test1) = ' + typeof(wnd.window.rhk_test1));
    alert('typeof(wnd.window.rhk_test2) = ' + typeof(wnd.window.rhk_test2));
    alert('typeof(wnd.window.rhk_test3) = ' + typeof(wnd.window.rhk_test3));
    alert('typeof(wnd.rhk_test1) = ' + typeof(wnd.rhk_test1));
    alert('typeof(wnd.rhk_test2) = ' + typeof(wnd.rhk_test2));
    alert('typeof(wnd.rhk_test3) = ' + typeof(wnd.rhk_test3));
    alert('typeof(rhk_test1) = ' + typeof(rhk_test1));
    alert('typeof(rhk_test2) = ' + typeof(rhk_test2));
    alert('typeof(rhk_test3) = ' + typeof(rhk_test3));
    alert('typeof(this.rhk_test1) = ' + typeof(this.rhk_test1));
    alert('typeof(this.rhk_test2) = ' + typeof(this.rhk_test2));
    alert('typeof(this.rhk_test3) = ' + typeof(this.rhk_test3));
    alert('typeof(window.rhk_test1) = ' + typeof(window.rhk_test1));
    alert('typeof(window.rhk_test2) = ' + typeof(window.rhk_test2));
    alert('typeof(window.rhk_test3) = ' + typeof(window.rhk_test3));
  },
  onLoad: function(event) {
    var appcontent = document.getElementById("appcontent");
    if (appcontent) {
      appcontent.addEventListener("DOMContentLoaded", rhkTest.onPageLoad, true);
    }
  },
};  

window.addEventListener("load", function(e) { rhkTest.onLoad(e); }, false);

其中 testfoo.js 包含:

window.rhk_test1 = 'testval1';
rhk_test2 = 'testval2';
var rhk_test3 = 'testval3';

window.alert('Running testfoo.js');

我收到警报“正在运行 testfoo.js”,因此找到并执行了该文件。我还收到一条警告,指出 wnd 是一个“对象”(正如预期的那样——它已在其他地方初始化)。但是,对于各种 typeof() 调用,所有其他警报都显示“未定义”。当然,我不希望所有这些都具有价值,但我希望其中至少有一个可以显示一些东西。

我的价值观怎么了?他们不应该在 wnd 的属性中吗?

我在 Windows 7 上运行 Firefox 19.0(如果重要的话)。

4

2 回答 2

3

它实际上有点复杂,取决于是什么wnd。您可以使用常规对象作为下标的范围:

var myScope = this;
var subscriptScope = {};
loader.loadSubScript("testfoo.js", subscriptScope);

但是,那时范围并没有完全隔离。这里有一些代码示例testfoo.js

var foo = "bar;      // Creates subscriptScope.foo
xyz = 1;             // Creates myScope.xyz
function dummy() {}  // Creates subscriptScope.dummy
var outer = myScope; // Assigns a value from outer scope

因此,虽然下标的变量和函数在其作用域中定义,但它仍然可以访问加载它的脚本的作用域——未声明的变量仍将在外部作用域中创建,并且将在外部作用域中搜索不能被在下标范围内解析。

如果您真的想隔离下标,那么您应该使用“适当的”全局对象,例如窗口对象或沙箱:

var myScope = this;
var subscriptScope = new Components.utils.Sandbox("about:blank");
loader.loadSubScript("testfoo.js", subscriptScope);

现在testfoo.js将无法再访问外部范围:

var foo = "bar;      // Creates subscriptScope.foo
xyz = 1;             // Creates subscriptScope.xyz
function dummy() {}  // Creates subscriptScope.dummy
var outer = myScope; // Exception: myScope is not defined

请注意,该变量没有什么特别之处window- 如果您希望下标具有该变量,则必须在范围对象中定义它,例如:

subscriptScope.window = subscriptScope;

范围对象本身可以在下this标的顶层访问。

于 2013-03-03T22:25:46.520 回答
1

注意:有关更一般的概述,请参阅 Wladimir Palant 的回答。

在我的示例中,我实际上是正确地使用了该函数,并且具有或多或少的合理期望。该问题是由 Firefox 的 XPCNativeWrapper 功能引起的。

我仍在努力理解细节,但简而言之,我的wnd对象被包装在 XPCNativeWrapper 中,并且testfoo.js被认为是“受保护”脚本,这意味着一旦控制权传回,我就看不到对对象所做的任何更改从testfoo.js.

解决方案是在将对象传递给下标之前(或之后——也可以)解开对象,如下所示:

var wnd = XPCNativeWrapper.unwrap(doc.defaultView);

一旦我这样做,由 修改的变量/属性testfoo.js对父脚本可见。

我还不太了解完整的基础设施,无法知道这是否“安全”。毕竟,这是一种安全机制,旨在保护我的扩展免受浏览器页面上的恶意代码的影响。

我还看到将对象传递给由下标定义的方法时存在一些问题(在我的示例中未显示)。为此,我将提出一个单独的问题。

长话短说:展开是我的问题中提出的直接问题的(可能是“该”)解决方案,但似乎并不是解决我首先遇到的困难的完整解决方案。

于 2013-03-06T19:47:24.427 回答