2010-02-22 2 views
16

Я преследую bug в расширении FireFox. Мне, наконец, удалось увидеть это для себя (раньше у меня были только отчеты), и я не могу понять, как то, что я видел, возможно.Объекты в JavaScript определены и не определены одновременно (в расширении FireFox)

Одно сообщение об ошибке из моего расширения в консоли ошибок «gBrowser не определено». Это само по себе было бы достаточно неожиданным, так как наложение над браузером.xul и navigator.xul, и я ожидаю, что gBrowser будет доступен от обоих. Еще хуже то место, где это происходит: строка 101 nextplease.js. То есть, внутри функции isTopLevelDocument, которая только вызывается из onContentLoaded, который только называется из onLoad здесь:

gBrowser.addEventListener(this.loadType, function (event) { 
    nextplease.loadListener.onContentLoaded(event); 
}, 
true); 

Так gBrowser определяется в onLoad, но так или иначе не определено в isTopLevelDocument.

Когда я попытался использовать расширение, я получил еще одну ошибку: «nextplease не определен». Интересно то, что это произошло на линиях 853 и 857. То есть, внутри функций

nextplease.getNextLink = function() { 
    nextplease.getLink(window.content, nextplease.NextPhrasesMap, nextplease.NextImagesMap, nextplease.isNextRegExp, nextplease.NEXT_SEARCH_TYPE); 
} 

nextplease.getPrevLink = function() { 
    nextplease.getLink(window.content, nextplease.PrevPhrasesMap, nextplease.PrevImagesMap, nextplease.isPrevRegExp, nextplease.PREV_SEARCH_TYPE); 
} 

Так nextplease каким-то образом определяется достаточно, чтобы вызвать эти функции, но не определен внутри них.

И, наконец, выполнение typeof(nextplease) в Execute JS возвращает «объект». То же самое для gBrowser.

Как это может произойти? Есть идеи?

+2

Квантовые переменные? –

+7

Ну, контекст, в котором этот код изначально запускается, не обязательно совпадает с контекстом, в котором работают различные определенные функции. (Я не разработчик XUL, поэтому я просто работаю с первыми принципами.) Что произойдет, если вы спрятали «gBrowser» и «nextplease» в объект «nextplease»? Или в закрытии, окружающем определения? – Pointy

+4

@Pointy: Очень хорошо. Это может оказаться прекрасным примером того, почему глобальные переменные являются плохими. Закрытие могло бы быть здесь ... –

ответ

2

Для второго случая:

nextplease.getNextLink = function() { 
    nextplease.getLink(window.content, nextplease.NextPhrasesMap, nextplease.NextImagesMap, nextplease.isNextRegExp, nextplease.NEXT_SEARCH_TYPE); 
} 

nextplease.getPrevLink = function() { 
    nextplease.getLink(window.content, nextplease.PrevPhrasesMap, nextplease.PrevImagesMap, nextplease.isPrevRegExp, nextplease.PREV_SEARCH_TYPE); 
} 

Я бы попробовать это вместо:

nextplease.getNextLink = function() { 
    this.getLink(window.content, this.NextPhrasesMap, this.NextImagesMap, this.isNextRegExp, this.NEXT_SEARCH_TYPE); 
} 

nextplease.getPrevLink = function() { 
    this.getLink(window.content, this.PrevPhrasesMap, this.PrevImagesMap, this.isPrevRegExp, this.PREV_SEARCH_TYPE); 
} 
+0

Возможно, стоит попробовать. –

1

я не уверен, что происходит (в каком контексте код работает, и, следовательно, почему это не видя gbrowser и другие глобальные переменные), но простым решением для gbrowser, которое не определено, было бы получить ссылку на главное окно и получить к нему доступ оттуда:

var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) 
        .getInterface(Components.interfaces.nsIWebNavigation) 
        .QueryInterface(Components.interfaces.nsIDocShellTreeItem) 
        .rootTreeItem 
        .QueryInterface(Components.interfaces.nsIInterfaceRequestor) 
        .getInterface(Components.interfaces.nsIDOMWindow); 

mainWindow.gbrowser.addEventListener(...) 

Это должно работать независимо от контекста, в котором выполняется код, поскольку вы не будете полагаться на глобальные переменные.

Смежные вопросы