Функция readStringReplaceMalformed() не работает в версиях Mozilla Firefox ниже 22?

Я новичок в разработке расширения Mozilla-Firefox. Я создаю дополнительный файл .xpi для Firefox. Он работал нормально до сегодняшнего дня. Но сегодня я установил версию Firefox, т.е. Firefox-15.1, и надстройка начала выдавать следующее исключение:

введите здесь описание изображения

При проверке различных версий 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:

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

}

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

person Anonymous    schedule 31.07.2015    source источник
comment
Я не знал об этом. Но переходите на irc, и я могу помочь вам лично: client00.chat.mibbit.com/   -  person Noitidart    schedule 31.07.2015


Ответы (1)


Похоже, вы предполагаете, что CData является статическим в течение всего срока службы Firefox. Тем не менее, это, конечно, было чем-то, что развивалось с течением времени (точно так же, как весь Firefox или почти любой крупный программный проект). Доступность конкретной функции в более старой версии Firefox зависит от того, когда эта функция была реализована и включена в Firefox.

Что касается документации, окончательной документацией является исходный код Firefox. Чтобы точно определить, в какой версии Firefox эта функция была впервые доступна, я ожидаю, что мне придется просмотреть исходный код и посмотреть, когда она была добавлена. Однако вы можете получить некоторые подсказки относительно того, когда это произошло из других вещей.

Документация для него была добавлена ​​в Страница CData на MDN от 19 февраля 2013 г.. Без изменений этой страницы с момента 9 августа 2010 г.. Очевидно, что это было проблемой по состоянию на 17 мая 2012 г., когда Ошибка 756120 — завершена. реализация CData readString была зарегистрирована.

Страница CData на MDN даже включает то, что фактически является polyfill для использования, когда 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();
    }
}

Этот тип изменений, добавление функции readStringReplaceMalformed(), является нормальным для разработки таких интерфейсов. Это то, о чем вы должны знать, и что такие изменения/улучшения в API — это то, о чем вы, как потребитель API, должны знать, и об их влиянии на вашу работу.

Старые версии Firefox и совместимость:

Одна из задач, которую вы должны выполнить при разработке расширения Firefox, — это выбрать самая старая версия Firefox, которую вы хотите поддерживать. Вы можете сделать это различными способами, но самая старая версия, которую вы выберете для поддержки, ограничивает функциональность, которую вы можете использовать в своем дополнении, или требует, чтобы вы реализовали функциональность двумя или более разными способами. Например, в Firefox 29 произошли значительные изменения в том, как вставлять/удалять/изменять элементы из пользовательского интерфейса Firefox. Если вы вносите такие изменения в пользовательский интерфейс Firefox (даже просто добавляете кнопку), вам нужен другой код для разных версий Firefox. до Firefox 29 и Firefox 29 и более поздних версий, которые ваш код должен использовать в зависимости от версии (или доступности функций). Версия, которая имеет такие основные и значительные изменения, часто является хорошим выбором для самой старой версии для поддержки вашего дополнения.

Пример изменения API, с которым я недавно столкнулся, когда отвечая на другой вопрос, был пользователь, желающий использовать Element.closest() для упрощения своего кода. Однако такой выбор ограничил бы совместимость этого кода только с Firefox 35.0 или более поздней версии. Этот тип выбора (использовать новую функциональность или оставаться совместимым со старыми версиями) — это то, с чем вы будете сталкиваться много раз при написании кода, взаимодействующего с другими блоками кода (модули, API и т. д.).

Как правило, вы обычно основываете выбор на том, какую самую старую версию Firefox поддерживать, на множестве факторов, таких как:

  1. необходимость поддержки клиентов, использующих определенную старую версию.
  2. Доступность требуемой функциональности (есть ли что-то, что нужно вашему дополнению в качестве основной функциональности, просто недоступное в более старой версии, для которой нет обходного пути/полифилла).
  3. Процент установленной базы с использованием более старых версий
  4. Простота поддержки (т. е. сколько изменений между версиями, какое дополнительное кодирование вам нужно сделать для поддержки более старой версии).
  5. Были ли вы уже совместимы (т.е. ваше дополнение существовало до какого-то серьезного изменения, и вам нужно было написать код, чтобы быть совместимым с новой версией, (например, любое дополнение Firefox, которое работало до Firefox 29 и добавило код для совместимости? с новым UI API)).
  6. Многие другие факторы

Предполагая, что у вас нет конкретных проблем, требующих поддержки более старой версии или минимальной версии, которую вы можете поддерживать, вы можете принять это решение на основе версии, которая была Выпуск расширенной поддержки (ESR) (например, 24.0esr, 31.0esr).

В общем, вы, вероятно, захотите поддерживать хотя бы самый последний выпуск ESR.

person Makyen♦    schedule 31.07.2015
comment
Спасибо @Mayken за сообщение MDN, моя функция не является заменой readStringReplaceMalformed, но является альтернативой, поэтому она пытается даже прочитать искаженный формат с помощью String.fromCharCode, поэтому никаких замен не производится, у меня не было проблем с тем, чтобы она успешно читала все. :) - person Noitidart; 01.08.2015