我正在寻找引导扩展。看看这些扩展的代码,我看到了很多变量,常量&函数声明。
它们都在window object中声明了吗?是否存在命名空间污染/冲突的问题?
在我所做的覆盖扩展中,我在一个对象/命名空间中包装了每一个单独的东西。bootstrap扩展在这方面有什么不同吗?我注意到所有bootstrapped.js
使用相同的/标准函数名。这是否意味着自引导扩展是沙盒的,或者它们的作用域是封闭的?
bootstrap.js
范围
它们都在window object中声明了吗?是否存在命名空间污染/冲突的问题?
…
我注意到所有bootstrapped.js都使用相同的/标准函数名。这是否意味着自引导扩展是沙盒的,或者它们的作用域是封闭的?
扩展@paa注释:bootstrap.js
确实有它自己的作用域。
AddonManager
将为每个bootstrap.js创建一个新的作用域(或者"命名空间")。现在实现使用Components.utils.Sandbox
,但这是一个实现细节。
这意味着没有window
对象。bootstrap.js
将在每个Firefox进程中加载一次,并且没有window
对象。这与覆盖脚本非常不同,覆盖脚本将在每个新窗口加载一次,并与Firefox代码和其他附加组件的覆盖脚本共享一个共同的作用域(window
对象本身)。
这也意味着自引导的附加组件可以在其作用域内自由选择他们喜欢的任何名称(他们的个人沙盒),而不必担心与其他附加组件冲突,只要这些名称在Javascript中通常是有效的。
唯一例外是
- 加载项管理器将调用的加载项必须实现的入口点函数名,因此具有特殊含义(
startup
,shutdown
,install
,uninstall
), - 预定义的东西,要么是
Sandbox
(Components
,和Javascript内置如Object
,String
,Array
,Map
等) -
AddonManager
将注入的东西(如__SCRIPT_URI_SPEC__
,ADDON_*
,APP_*
常量)。
预定义名称的完整列表,从Firefox 30开始:
Components.utils.reportError(Object.getOwnPropertyNames(this).join(", "));
// Object, Function, eval, Components, XPCNativeWrapper, dump, debug,
// importFunction, IDBCursor, IDBCursorWithValue, EventTarget, IDBDatabase,
// IDBFactory, FileHandle, IDBFileHandle, IDBIndex, IDBKeyRange,
// IDBObjectStore, IDBRequest, IDBOpenDBRequest, IDBTransaction, Event,
// IDBVersionChangeEvent, indexedDB, APP_STARTUP, APP_SHUTDOWN, ADDON_ENABLE,
// ADDON_DISABLE, ADDON_INSTALL, ADDON_UNINSTALL, ADDON_UPGRADE,
// ADDON_DOWNGRADE, Worker, ChromeWorker, __SCRIPT_URI_SPEC__, undefined,
// Array, Boolean, JSON, Date, Math, isNaN, isFinite, parseFloat, parseInt,
// NaN, Infinity, Number, String, escape, unescape, uneval, decodeURI,
// encodeURI, decodeURIComponent, encodeURIComponent, RegExp, Error,
// InternalError, EvalError, RangeError, ReferenceError, SyntaxError,
// TypeError, URIError, Iterator, StopIteration, Int8Array, Uint8Array,
// Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array,
// Float64Array, Uint8ClampedArray, DataView, ArrayBuffer, Proxy, WeakMap,
// Map, Set, Intl
操作其他作用域
然而,引导附加组件在与其他作用域交互时仍然需要考虑并避免冲突,例如windows, JS代码模块,其他附加组件引导作用域等等。操纵其他作用域也可能导致附加引导作用域的泄漏。
。
Cu.import("resource://gre/modules/Services.jsm");
Services.foo = "bar";
这将在共享Services.jsm
代码模块中的Services
对象中添加一个foo
属性。所有其他附加组件和浏览器代码也会看到Services.foo
,所以它可能会导致冲突,并且常规的不会污染共享命名空间-规则适用。
另外,当您的附加组件获得shutdown
时,您必须再次删除Services.foo
,否则Services.jsm
作用域将保留对它的引用,并且由于foo
(字符串"bar"
)的值在您的引导隔间内,它将保持您的引导隔间的活力,因为该引用并有效地创建内存泄漏,否则(称为僵尸隔间在mozilla俚语中)。
或
// Get the most recent browser window
var browserWindow = Services.wm.getMostRecentWindow("navigator:browser");
browserWindow.doSomething = function() {
browserWindow.alert("hello world");
};
这相当于有一个覆盖脚本:
function doSomething() {
alert("hello world");
}
都将添加一个新名称doSomething
到浏览器窗口作用域,因此该名称可能与其他附加组件冲突,并且不会污染共享命名空间-适用规则。同样,这可能会泄漏与前面的例子相同的方式,所以一个引导的附加组件将不得不再次删除shutdown
上的属性,以避免这种情况。