2010-02-22 9 views
16

Estoy buscando un bug en una extensión de FireFox. Finalmente pude verlo por mí mismo (solo he tenido informes anteriormente) y no puedo entender cómo lo que vi es posible.Objetos en JavaScript definidos e indefinidos al mismo tiempo (en una extensión de FireFox)

Un mensaje de error de mi extensión en la consola de errores es "gBrowser no está definido". Esto por sí solo sería lo suficientemente sorprendente, ya que la superposición está sobre browser.xul y navigator.xul, y espero que gBrowser esté disponible en ambos. Peor aún es el lugar real donde ocurre: línea 101 de nextplease.js. Es decir, dentro de la función isTopLevelDocument, que sólo se llama desde onContentLoaded, que sólo se llama desde onLoad aquí:

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

Así gBrowser se define en onLoad, pero de alguna manera indefinida en isTopLevelDocument.

Cuando traté de usar realmente la extensión, recibí otro error: "nextplease is not defined". Lo interesante es que sucedió en las líneas 853 y 857. Es decir, en el interior las funciones

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); 
} 

Así nextplease alguna manera es lo suficientemente definida para llamar a estas funciones, pero no se define dentro de ellos.

Finalmente, ejecutar typeof(nextplease) en Execute JS devuelve "objeto". Lo mismo para gBrowser.

¿Cómo puede suceder esto? ¿Algunas ideas?

+2

¿Variables cuánticas? –

+7

Bueno, el contexto en el que se ejecuta inicialmente ese código no es necesariamente el mismo que el contexto en el que se ejecutan las diversas funciones definidas. (No soy desarrollador de XUL, así que solo estoy trabajando desde los primeros principios.) ¿Qué pasaría si ocultaras "gBrowser" y "nextplease" en el objeto "nextplease"? ¿O en un cierre que rodea las definiciones? – Pointy

+4

@Pointy: Muy buen punto en verdad. Esto podría convertirse en un buen ejemplo de por qué las variables globales son malas. Un cierre podría ser el camino a seguir aquí ... –

Respuesta

2

Para el segundo caso:

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); 
} 

me gustaría probar este lugar:

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

Puede valer la pena intentarlo. –

1

No estoy seguro de lo que está pasando (en cuyo contexto se ejecuta el código y, por tanto, por qué no es ver gbrowser y otras variables globales) pero una solución fácil para gbrowser no definido sería obtener una referencia a la ventana principal y acceder a ella desde allí:

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

Esto debería funcionar independientemente del contexto donde se está ejecutando el código ya que no dependería de variables globales.

Cuestiones relacionadas