GM_xmlhttpRequest на Tampermonkey не прилага свойството „контекст“?

Написах UserScript за Greasemonkey (Firefox) и го тествам за съвместимост с Tampermonkey на Chrome и получавам грешки в конзолата за програмисти:

Uncaught TypeError: Cannot read property 'profile_url' of undefined
Uncaught TypeError: Cannot read property 'encoded_name' of undefined

Грешките изглежда препращат към обратното извикване onreadystatechanged на GM_xmlhttpRequest, което се извиква така:

var flairs = document.querySelectorAll('span.flair');
var steam_re = /(?:(?:https?:\/\/)?www\.)?(?:steam|pc)(?:community\.com\/?(?:(id|profiles)\/?)?|[\s\-_]*id)?[\/:\s\|]*(.{2,}?)(?:[\/|:\-\[(] ?(?:\/?(?:ghost|enforcer|tech|mm|master))+[\[)]?)?$/i

function get_text(e) { return e.innerText || e.textContent; }

function set_text(e, t) {
    if (e.innerText)
        e.innerText = t;
    else
        e.textContent = t;
}

var parser = new DOMParser();

for (var i = 0; i < flairs.length; i++) {
    var text = get_text(flairs[i]);
    var match = steam_re.exec(text);
    if (match == null || match.length < 3)
        continue;
    var type = match[1] || 'id';
    var name = encodeURIComponent(match[2]);
    var url = 'http://steamcommunity.com/' + type + '/' + name;
    var xml_url = url + '?xml=1';
    GM_xmlhttpRequest({
        method: 'GET',
        url: xml_url, // Link to a steam profile with ?xml=1 added
        accept: 'text/xml',
        context: {
            flair_index: i,
            flair_text: text, // textContent of span element
            encoded_name: name,
            profile_url: url, // Link to steam profile
            query_url: xml_url
        },
        onreadystatechange: function(response) {
            if (response.readyState != 4)
                return;
            // Attempt to fall back to alternate forms of context,
            // none of which works. response.context works on Firefox/Greasemonkey.
            var context = response.context || this.context || context;
            var doc = parser.parseFromString(response.responseText, 'text/xml');
            var validProfile = doc.documentElement.nodeName == 'profile';
            var a = document.createElement('a');
            a.href = validProfile ?
                context.profile_url : // TypeError here, context is undefined
                ('http://steamcommunity.com/actions/SearchFriends?K=' + context.encoded_name);
            a.className += (validProfile ? 'steam-profile-link' : 'steam-profile-search-link');
            var a_text = document.createTextNode(context.flair_text);
            a.appendChild(a_text);
            set_text(flairs[context.flair_index], '');
            flairs[context.flair_index].appendChild(a);
        }
    });
}

Самата функция се нарича fine и обратното извикване се извиква, но след като се опитам да осъществя достъп до context var в нея, тя е недефинирана.

Всичко работи според очакванията във Firefox. Това, което прави, е итериране на span елемента, които имат класа "flair" и проверка с регулярен израз дали съдържат потребителско име на Steam, и ако е така, го прави връзка към тяхната страница SteamCommunity. (Пълният източник в github). Скриптът се изпълнява на /r/PaydayTheHeistOnline.

Тествах с помощта на масив, дефиниран извън функцията, за съхраняване на данните, вместо да използвам свойството контекст, предадено на xmlhttpRequest, но получавам абсолютно същата грешка.


person Sharparam    schedule 26.08.2013    source източник


Отговори (1)


Актуализация:
Tampermonkey сега съобщава, че тази функция е коригирана от версия 3.8.4116 (в момента в бета). Вижте:


По-старо/генерично решение:
Свойството context е относително нова функция на GM_xmlhttpRequest(), във Firefox. Съмнявам се, че все още е внедрен в Tampermonkey; вижте документите на Tampermonkey за GM_xmlhttpRequest().

Междувременно изпитаният метод за този вид неща е да се използва затваряне.

Променете вашето GM_xmlhttpRequest() обаждане на нещо като:

( function (flair_index, flair_text, encoded_name, profile_url, query_url) {
    GM_xmlhttpRequest ( {
        method: 'GET',
        url:    xml_url, // Link to a steam profile with ?xml=1 added
        accept: 'text/xml',
        onreadystatechange: function (response) {
            if (response.readyState != 4)
                return;

            var doc = parser.parseFromString (response.responseText, 'text/xml');
            var validProfile = doc.documentElement.nodeName == 'profile';
            var a = document.createElement ('a');
            a.href = validProfile ?
                profile_url : 
                ('http://steamcommunity.com/actions/SearchFriends?K=' + encoded_name);
            a.className += (validProfile ? 'steam-profile-link' : 'steam-profile-search-link');
            var a_text = document.createTextNode (flair_text);
            a.appendChild (a_text);
            set_text (flairs[flair_index], '');
            flairs[flair_index].appendChild (a);
        }
    } );
} ) (
    i,
    text, // textContent of span element
    name,
    url, // Link to steam profile
    xml_url
);
person Brock Adams    schedule 26.08.2013
comment
Това работи перфектно, благодаря! Ще трябва да прочета за затварянията и обхватите. - person Sharparam; 26.08.2013