I have problem passing JavaScript arrays to an Add-On, which I'm writing in Add-on Builder.
To communication I'm using events and sending an event with an array, but the Add-on (Content Script) gets an object, not an array.
This is event:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script type="application/x-javascript">
$(function() {
$(window).bind('Runner-PageEvent', function(event) {
console.log('PAGE: Reakcja na Runner-PageEvent na stronie');
});
$(window).bind('RunnerResult', function(event) {
console.log('PAGE: Result is ' + event.originalEvent.detail.Result);
//// PROBLEM!!!
console.log('PAGE: Should be array: ' + event.originalEvent.detail.array); // firebug shows object
});
$(window).bind('Runner-DetectCallback', function(event) {
console.log('PAGE: Reakcja na Runner-DetectCallback na stronie');
$('#browser-detection').text('Extension detected').css('background-color', 'green').css('color', 'white');
});
var event = new CustomEvent("Runner-Detect", {});
window.dispatchEvent(event);
console.log('PAGE: Runner-Detect sent');
});
function CallExtension() {
var event = new CustomEvent("Runner-PageEvent", { detail : {
a: "messageA",
b: "messageB",
c: "messageC",
d: "messageD",
arrayA: ["a", "b", "c", "d"],
arrayB: [0, "info", "info2", 3]
}});
window.dispatchEvent(event);
console.log('PAGE: CALL EXTENSION clicked');
}
</script>
</head>
<body>
<div id="browser-detection" style="background-color: red">No extension</div>
<br/>
Run extension: <button onclick="CallExtension()">Run!</button>
</body>
</html>
Firebug shows me event as object with one property detail.tab
as array with four items.
Content script receives an object e
, where e.detail.tab
is an object (but should be an array).
window.addEventListener(
'eventname',
function(e) {
// console.log(e.detail.tab.length); -> produce an error on console (Ctrl+Shift+J)
// console.log(e.detail.tab[0]); -> as above
for(var x in e.detail.tab){
console.log(x);
console.log(e.detail.tab[x]);
}
self.port.emit('SendToExtension', e.detail);
}
);
I don't know if there is a problem with Add-on Builder or I'm doing something wrong?
Please help!
There appears to be a bug in how
CustomEvent()
transmits information in and out of the sandbox (XPCNativeWrapper). It's improperly serializing theCustomEventInit.detail
value in certain circumstances and, after the first such instance, fails to pass thedetail
value at all -- suggesting some kind of memory/state corruption is taking place.For the following, refer to this test page: jsbin.com/ajegib/1.
Install, or run in "Test" mode, this Firefox add-on: CustomEvent data_ across the sandbox.
Note that both the test web-page, and the extension's content script have code like this:
Open both Firebug's console, and the Firefox Error Console (CtrlShiftJ) to observe the results as custom events with array values for
detail
are sent. (You can press the Normal array data button, to send them.)What should happen:
Both the web page and the extension should see the data, from both events, as an array.
The Firebug console should display:
The FF Error console should display:
What does happen:
On the First Event:
The Firebug console displays:
The FF Error console displays:
On the All subsequent Events:
The Firebug console displays:
The FF Error console displays:
Observe:
null
)!Workaround:
Both the CustomEvent documentation and the DOM Standard state that
eventInitDict.detail
can have any type. But for events sent across the add-on sandbox, this is clearly not the case.There don't seem to be any Firefox bugs for this. Perhaps we should open one.
Anyway, the workaround that seems to work is to JSON encode the data we send with
CustomEvent()
.Send like so:
Receive like so:
You can see this at work on the test page + extension by pressing the JSON-encoded array data button. (Be sure to refresh the page first to clear the corruption discussed above.)