火狐浏览器扩展将Javascript数组作为对象发送

3

我遇到了一个问题,无法将JavaScript数组传递给我正在Add-on Builder中编写的插件。

为了通信,我使用事件并发送一个带有数组的事件,但是插件(内容脚本)收到的是一个对象,而不是一个数组。

这是事件:

<!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将事件显示为一个带有一个属性detail.tab的对象数组,其中包含四个项目。
内容脚本接收一个对象e,其中e.detail.tab是一个对象(但应该是一个数组)。
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);
    }
);


我不知道是Add-on Builder出了问题还是我做错了什么?
请帮忙!


您在Builder中使用的SDK版本是哪个?请确保您将Builder设置为最新版本的SDK,目前为1.10。 - therealjeffg
1
另外,我有点困惑 - 哪个文件包含创建事件的代码?这是在HTML文件中吗? - therealjeffg
第一段代码创建事件,这是HTML代码;第二段(window.addEventListener)是来自Addon Builder中内容脚本的代码。 - Tomasz Dzięcielewski
1个回答

3

似乎在 CustomEvent() 在沙箱(XPCNativeWrapper)中传输信息的方式存在错误。在某些情况下,它会错误地序列化 CustomEventInit.detail 的值,并且在第一次出现此类情况后,将不再传递 detail 值——这表明发生了某种内存/状态损坏。

  1. For the following, refer to this test page: jsbin.com/ajegib/1.

  2. Install, or run in "Test" mode, this Firefox add-on: CustomEvent data_ across the sandbox.

  3. Note that both the test web-page, and the extension's content script have code like this:

    window.addEventListener ("EventWithArrayData", function (zEvent) {
        console.log (
            "Event detail: ", zEvent.detail, Array.isArray (zEvent.detail)
        );
    } );
    
    var zEvent = new CustomEvent ("EventWithArrayData",
        {"detail": [5,6,7] }
    );
    window.dispatchEvent (zEvent)
    
  4. 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.)

应该发生的事情:
网页和扩展程序都应该将来自两个事件的数据视为数组。
  1. The Firebug console should display:

    **The Normal button was pressed.**
    In web page (Normal) from page: [1, 2, 3]  true
    In web page (Normal) to page: [5, 6, 7]  true
    
  2. The FF Error console should display:

    info: In Content Script (Normal) from page:  1,2,3 true
    info: In Content Script (Normal) to page:  5,6,7 true
    
发生了什么事情:
  1. On the First Event:

    1. The Firebug console displays:

      **The Normal button was pressed.**
      In web page (Normal) from page: [1, 2, 3]  true
      In web page (Normal) to page: {0: 5, 1: 6, 2: 7}  false
      
    2. The FF Error console displays:

      info: In Content Script (Normal) from page:  [object Object] false
      info: In Content Script (Normal) to page:  5,6,7 true
      
  2. On the All subsequent Events:

    1. The Firebug console displays:

      **The Normal button was pressed.**
      In web page (Normal) from page: [1, 2, 3]  true
      In web page (Normal) to page: null  false
      
    2. The FF Error console displays:

      info: In Content Script (Normal) from page:  [object Object] false
      info: In Content Script (Normal) to page:  null false
      
观察:
  1. 在所有情况下,网页正确地看到了由其自己的事件发送的数组数据。它看到了一个数组。
  2. 但是,扩展程序只看到了类似于数组的对象。
  3. 从扩展程序发送的数组数据在第一次传递时显示正确,但在所有后续尝试中为 null。
  4. 从扩展程序发送的数组数据在页面上显示为对象,然后完全消失(null)!

解决方法:

无论CustomEvent文档还是DOM标准都说明eventInitDict.detail可以有任何类型。但是对于跨插件沙箱发送的事件,显然不是这种情况。
这方面似乎没有Firefox bug。也许我们应该打开一个。

无论如何,似乎有效的解决方法是使用CustomEvent()发送的数据进行JSON编码。

像这样发送:

var detailVal   = JSON.stringify ( [1, 2, 3] );

var zEvent = new CustomEvent ("EventWithJSON_Data",
    {"detail": detailVal }
);
window.dispatchEvent (zEvent)

接收方式如下:
window.addEventListener ("EventWithJSON_Data", function (zEvent) {
    var datArray    = JSON.parse (zEvent.detail);
    console.log (
        "JSON data: ", datArray, Array.isArray (datArray)
    );
} );

您可以在测试页面+扩展上按下“JSON编码数组数据”按钮来查看这个过程。(请确保先刷新页面以清除上述损坏。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接