Most all objects on a target web page that a user script sees are wrapped in XPCNativeWrapper. The reason for this is so that a script can change the properties of an object (actually the wrapper) without any JavaScript on the target page being able to see it. Mostly the wrapping is "transparent" - wrapped and unwrapped objects seem to behave the same because the wrapping object passes methods to the wrapped object, though there are some some exceptions.
For a script to access the real underlying object there is the method
Fair sample:
var realObj = wrappedObj.wrappedJSObject;
Be very careful when using the wrappedJSObject property. It is just as dangerous as unsafeWindow is.
Related to security.
[Expando_Properties] do not work on XPCNativeWrappers. This means that, for example, this will not work:
Bad sample:
var el = document.createElement('a'); el.onclick = 'alert("Error"); return false;';
Instead, use setAttribute and addEventListener methods. Note the use of the preventDefault method to emulate the "return false" behavior above.
addEventListener example:
function showTheError(event) { event.preventDefault(); /* some code */ } var el = document.createElement('a'); el.addEventListener('click', showTheError, false);
setAttribute example:
var el = document.createElement('a'); el.setAttribute('onclick', 'alert("Error"); return false;');
This applies to any element, not just new ones you create (those references from createElement
and those from getElementById
, and any event handler, not just onclick.
DOM methods like getElementsByTagName
return HTMLCollection
s.
Bad sample:
var arInputs = document.getElementsByTagName('input'); for (var elmInput in arInputs) { /* some code */ }
Instead use this...
var arInputs = document.getElementsByTagName('input'); var elmInput; for (var i = arInputs.length - 1; i >= 0; --i) { elmInput = arInputs[i]; /* some code */ }
Items like frames, form elements, and so on can be referenced by name in normal JavaScript.
XPCNativeWrappers cannot reference items by name. Use the namedItem
method.
With a <input name="foo">
in the form:
Bad sample:
form.foo;
Instead use this...
form.elements.namedItem('foo');
The same goes for frames:
Bad sample
window.framename;
Instead use this...
window.frames['framename'];
Normal JavaScript can access an element's event handlers with code like:
Bad samples:
element.onclick = myClickHandler;
or
element.onclick = 'myClickHandler(this)';
This does not work on XPCNativeWrappers; it will result in a Component not available
error in the JavaScript console. Instead, use addEventListener
element.addEventListener('click', myClickHandler, false);
Any Greasemonkey script written before version 0.5 was released in mid-2005 may need updating to use addEventListener.
Wiki: Global_object
Wiki: Greasemonkey_Manual:Environment
Wiki: Greasemonkey_Manual:Other_Useful_Tools
Wiki: Main_Page
Wiki: Metadata_Block
Wiki: Sandbox
Wiki: Security
Wiki: unsafeWindow