readStringReplaceMalformed()函数不适用于22以下的Mozilla Firefox版本?

时间:2015-07-31 09:46:45

标签: javascript firefox firefox-addon jsctypes

我是Mozilla-Firefox扩展的新手。我正在为Firefox创建一个附加.xpi文件。它一直工作到今天。但是,今天我安装了一个版本的Firefox,即Firefox-15.1和附加组件开始抛出以下异常:

enter image description here

在检查各种版本的Firefox时,我发现此加载项会在Firefox-22下面的版本上引发相同的异常。

所以任何人都可以告诉我为什么会发生这种情况。我在代码中犯了错误,或者Firefox存在任何兼容性问题?如果是兼容性问题,请您提供任何参考文档。

以下是我的示例代码导致错误:

MyJS.js:



var path="D:\\DemoExportFunction.dll";
Components.utils.import("resource://gre/modules/ctypes.jsm");						
var lib = ctypes.open(path);							
var getStr = lib.declare("getString",ctypes.default_abi,ctypes.char.ptr); 

function func_PageLoad(event) 
{   
   try  
   {
		alert("func_PageLoad");
		var str=getStr();
		str=str.readStringReplaceMalformed();
		alert("String:"+str);
		
  }
  catch(err)
  {
	alert("Exception in func_PageLoad Message : "+err.message);
  }
}

gBrowser.addEventListener("DOMContentLoaded", func_PageLoad, true);




.Dll finction code:

#include "stdafx.h"
extern "C"
{
    __declspec( dllexport ) char * getString( );

}

char * getString( )
{
    return "Hello . . . . This is message from dll";
}

1 个答案:

答案 0 :(得分:2)

您似乎假设CData在Firefox的生命周期内是静态的。然而,它当然是随着时间的推移而发展起来的(就像整个Firefox或几乎任何大型软件项目一样)。如果旧版Firefox中的特定功能可用,则取决于该功能何时实施并包含在Firefox中。

至于文档,最终文档是Firefox source code。要准确地本地化这个功能首次出现在哪个版本的Firefox中,我希望看看源代码并查看它的添加时间。但是,您可以从其他事情中获得一些提示。

它的文档已添加到CData page on MDN on Feb 19, 2013。自Aug 9, 2010以来没有对该页面进行任何修订。很明显,截至2012-05-17提交Bug 756120 - Complete implementation of CData readString时,这是一个问题。

MDN上的CData页面甚至包括readStringReplaceMalformed()function readAsChar8ThenAsChar16(stringPtr, known_len, jschar) { // when reading as jschar it assumes max length of 500 // stringPtr is either char or jschar, if you know its jschar for sure, pass 2nd arg as true // if known_len is passed, then assumption is not made, at the known_len position in array we will see a null char // i tried getting known_len from stringPtr but its not possible, it has be known, i tried this: //"stringPtr.contents.toString()" "95" //"stringPtr.toString()" "ctypes.unsigned_char.ptr(ctypes.UInt64("0x7f73d5c87650"))" // so as we see neither of these is 77, this is for the example of "_scratchpad/EnTeHandle.js at master · Noitidart/_scratchpad - Mozilla Firefox" // tries to do read string on stringPtr, if it fails then it falls to read as jschar var readJSCharString = function() { var assumption_max_len = known_len ? known_len : 500; var ptrAsArr = ctypes.cast(stringPtr, ctypes.unsigned_char.array(assumption_max_len).ptr).contents; // MUST cast to unsigned char (not ctypes.jschar, or ctypes.char) as otherwise i dont get foreign characters, as they are got as negative values, and i should read till i find a 0 which is null terminator which will have unsigned_char code of 0 // can test this by reading a string like this: "_scratchpad/EnTeHandle.js at master · Noitidart/_scratchpad - Mozilla Firefox" at js array position 36 (so 37 if count from 1), we see 183, and at 77 we see char code of 0 IF casted to unsigned_char, if casted to char we see -73 at pos 36 but pos 77 still 0, if casted to jschar we see chineese characters in all spots expect spaces even null terminator is a chineese character console.info('ptrAsArr.length:', ptrAsArr.length); //console.log('debug-msg :: dataCasted:', dataCasted, uneval(dataCasted), dataCasted.toString()); var charCode = []; var fromCharCode = [] for (var i=0; i<ptrAsArr.length; i++) { //if known_len is correct, then will not hit null terminator so like in example of "_scratchpad/EnTeHandle.js at master · Noitidart/_scratchpad - Mozilla Firefox" if you pass length of 77, then null term will not get hit by this loop as null term is at pos 77 and we go till `< known_len` var thisUnsignedCharCode = ptrAsArr.addressOfElement(i).contents; if (thisUnsignedCharCode == 0) { // reached null terminator, break console.log('reached null terminator, at pos: ', i); break; } charCode.push(thisUnsignedCharCode); fromCharCode.push(String.fromCharCode(thisUnsignedCharCode)); } console.info('charCode:', charCode); console.info('fromCharCode:', fromCharCode); var char16_val = fromCharCode.join(''); console.info('char16_val:', char16_val); return char16_val; } if (!jschar) { try { var char8_val = stringPtr.readString(); console.info('stringPtr.readString():', char8_val); return char8_val; } catch (ex if ex.message.indexOf('malformed UTF-8 character sequence at offset ') == 0) { console.warn('ex of offset utf8 read error when trying to do readString so using alternative method, ex:', ex); return readJSCharString(); } } else { return readJSCharString(); } } 不可用时实际使用的polyfill。该代码是:

readStringReplaceMalformed()

添加{{1}}函数的这种类型的更改对于此类接口的开发是正常的。这是您应该注意的事情,并且作为API的使用者,您应该了解API的这些更改/增强以及它们对您的工作的影响。

旧版本的Firefox及兼容性:

开发Firefox扩展时应该执行的任务之一是choose the oldest version of Firefox which you wish to support。您可以通过各种方法执行此操作,但您选择支持的最旧版本限制了您可以在附加组件中使用的功能,或者要求您以两种或更多种不同的方式实现功能。例如,在Firefox 29中如何从Firefox UI插入/删除/更改项目方面发生了相当大的变化。如果您对Firefox UI进行了这样的更改(甚至只是添加了一个按钮),那么Firefox的版本需要不同的代码在Firefox 29和Firefox 29及更高版本之前,您的代码必须根据版本(或功能的可用性)选择使用它们。对于支持附加组件的最旧版本,具有此类基本且重大更改的版本通常是不错的选择。

answering another question用户想要使用Element.closest()来简化代码时,我最近遇到的API更改示例。但是,这样做的选择会限制该代码仅与Firefox 35.0或更高版本兼容。这种类型的选择(使用新功能与旧版本保持兼容)在编写与其他代码块(模块,API等)交互的代码时会遇到很多次。

一般情况下,您通常会根据以下各种因素选择支持哪个最旧版本的Firefox:

  1. 需要以支持使用特定旧版本的客户。
  2. 所需功能的可用性(您的附加组件需要哪些内容作为核心功能,在没有解决方法/ polyfill的旧版本中不可用)。
  3. 使用旧版本的已安装基础的百分比
  4. 易于支持(即版本之间有多大的变化,您需要为支持旧版本做些额外的编码)。
  5. 您是否已经兼容(即您的插件存在于某些重大更改之前,您必须编写代码以与新版本兼容,(例如,在Firefox 29之前工作的任何Firefox插件并添加了代码与新的UI API兼容))。
  6. 许多其他因素
  7. 假设您没有要求支持旧版本或您可以支持的最低版本的特定问题,您可能希望根据Extended Support Release (ESR)的版本做出此决定(例如{ {3}})。

    通常,您可能希望至少支持最新的ESR版本。