Firefox extension is sending Javascript Array as an Object instead

若如初见. 提交于 2019-12-05 22:06:07

There appears to be a bug in how CustomEvent() transmits information in and out of the sandbox (XPCNativeWrapper). It's improperly serializing the CustomEventInit.detail value in certain circumstances and, after the first such instance, fails to pass the detail value at all -- suggesting some kind of memory/state corruption is taking place.

  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.)


What should happen:

Both the web page and the extension should see the data, from both events, as an array.

  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
    


What does happen:

  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
      

Observe:

  1. In all cases, the web page sees the array data sent by its own event correctly. It sees an array.
  2. But, the extension sees an array-like object instead.
  3. Array data, sent from the extension, appears correctly to the extension on the first pass but is null on all subsequent attempts.
  4. Array data, sent from the extension, appears as an object to the page and then not at all (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:

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

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

Receive like so:

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


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.)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!