2010-05-09 9 views
13

Estoy tratando de mostrar una página HTML con código JavaScript incorporado dentro de un control System.Windows.Forms.WebBrowser. Se espera que el código de JavaScript interactúe con el entorno de incrustación a través del objeto window.external. Antes de invocar un método en window.external, se supone que JavaScript verifica la existencia del método. Si no está allí, el código debe invocar un método de respaldo genérico.Método sin argumentos en window.external se invoca al verificar con typeof

// basic idea 
if (typeof(window.external.MyMethod) != 'undefined') { 
    window.external.MyMethod(args); 
} else { 
    window.external.Generic("MyMethod", args); 
} 

Sin embargo, la comprobación de un método sin argumentos con typeof parece invocar el método ya. Es decir, si MyMethod acepta cualquier número positivo de argumentos, el código anterior funcionará perfectamente; pero, si MyMethod es un método sin argumento, entonces la expresión typeof(window.external.MyMethod) no buscará su tipo, sino que lo invocará también.

¿Hay alguna solución a este problema? ¿Puedo escapar de alguna manera a la expresión window.external.MyMethod para evitar que ocurra la llamada al método?

+0

¿Ha intentado utilizar typeof como operador en lugar de como función? 'typeof window.external.MyMethod! ==" undefined "' –

+0

Cualquiera que responda esta pregunta necesita ** probar su solución con 'window.external' en IE ** - formas regulares de probar la existencia de un objeto en Javascript do no funciona para 'window.external'. – funkybro

Respuesta

9

no he depurado su situación exacta, pero creo que mis poderes psíquicos pueden trabajar en lo que está pasando aquí.

idioma La JScript hace una distinción entre el uso de una función y la mera mención de ella. Cuando usted dice

x = f; 

que dice "asignar una referencia a la función identificada por f de la variable x". Es menciona f. Por el contrario,

x = f(); 

utiliza f. Significa "llamar a la función identificada por f y asignar el valor devuelto a x".

En resumen, las funciones en JScript son esencialmente lo que podríamos pensar como propiedades del tipo de delegado en C#.

Algunos idiomas no hacen esta distinción. En VBScript, si dice x = f yf es una función, eso significa llamar a la función, igual que x = f(). VBScript no hace una fuerte distinción sintáctica entre el uso y la mención de una función.

La forma en que todo esto se implementa es que utilizamos COM; específicamente, usamos Automatización OLE. Al despachar un campo de un objeto para obtener su valor, el motor de JScript pasa indicadores que significan "propiedad obtener" o "método invocar", dependiendo de si fue uso o mención.

Pero supongamos que su objeto enviado se escribió con la expectativa de que se llamaría desde VB. Quizás fue escrito en VB. Es perfectamente razonable y legal que un objeto VB diga "oh, veo que me estás pidiendo el valor de este método.Como no entiendo la diferencia entre mencionar un método y usarlo, lo invocaré sin importar qué indicador pase ".

No sé si hay una solución alternativa, pero estaría dispuesto a apostar tanto como un dólar que lo que está sucediendo es el objeto invocado está asumiendo que la persona que llama quiere semántica VB.

+0

Hola Eric, gracias por tu excelente respuesta. Esperé que sucediera algo así detrás de las escenas ya que ayer leí el comentario de tu blog del 2004 (http://discuss.techinterview.org/default.asp?joel.3.18644.7). Supongo que las cosas COM están implementadas en algún lugar dentro del control WebBrowser, ¿no es así? No podré parchar en otro manejo de búsqueda?¿O puedo marcar explícitamente un método como "COM visible como método y no como propiedad"? – janko

+0

Si este es el caso, puede intentar jugar con la implementación 'IDispatch' en su clase C#. Primero, probaría el atributo 'IDispatchImpl' - intente configurarlo en' CompatibleImpl' y 'InternalImpl' y ver si funciona de alguna manera. O bien, puede proporcionar su propia implementación de 'IDispatch' - marcar su objeto' [ClassInterface (ClassInterfaceType.None)] 'y hacer que implemente explícitamente' IDispatch'. También sospecho (realmente no sé) que el 'IDynamicObject' de .NET 4.0 se puede usar para el mapeo' IDispatch'. –

-1

No estoy seguro de si te puede ayudar, pero prueba window.external["MyMethod"].

Si eso no ayuda, intente almacenar este valor en una variable y solo luego verifique el tipo de esa variable. A ver si eso ayuda.

+0

Ni una variante funciona, desafortunadamente. 'window.external [" MyMethod "]' lo invoca, así como 'var f = window.external [" MyMethod "]'. – janko

0

probar uno de estos

/* Methods for feature testing 
* From http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting 
*/ 
function isHostMethod(object, property){ 
    var t = typeof object[property]; 
    return t == 'function' || 
    (!!(t == 'object' && object[property])) || 
    t == 'unknown'; 
} 

function isHostObject(object, property){ 
    return !!(typeof(object[property]) == 'object' && object[property]); 
} 

if (isHostObject(window.external, "MyMethod")) {.... 
+0

Hola Sean, tu 'isHostMethod' tampoco funciona. La línea 'object [property]' aún invoca el método. – janko

6

encontré este

if ('MyMethod' in window.external) 

no invoca MiMetodo

+0

Pero esto no ayuda mucho, el script fallará si 'window.external' no está presente. – funkybro

+0

@funkybro En ese caso, todo lo que necesita hacer es agregar un cheque adicional, p. 'if (window.external && 'MyMethod' en window.external)'. – erdomke

+0

cierto, sin embargo, si ve mi respuesta a continuación, simplemente haciendo 'window.external' fallará en IE. – funkybro

0

este efecto puede ser visto en el escritorio de Internet Explorer. Una secuencia de comandos, tales como:

for (var i in window) { 
    console.log('window.' + i + ' = ' + window[i]); 
} 

fallará tan pronto como se alcanza external.

Parece que window.external no es un objeto Javascript normal, es un objeto VBScript.

declaraciones Así como window.external y window['external']son, por tanto, las declaraciones de VBScript - y, como dice Eric L, window.external en VBScript es equivalente a window.external().

Mighty confusing. También parece que este es el único objeto que se comporta de esa manera en Internet Explorer.

Para cross-browser aplicaciones web móviles que hacen uso de IE Mobile window.external.Notify() para comunicarse con nativa en Windows Phone 8, pero que también desee establecer document.location en IOS, las pruebas de la existencia de window.external.Notify parecería lógico - pero no funciona por este motivo

No he encontrado una manera de prevenir esto; todavía ocurre cuando se especifica type="text/javascript" en la etiqueta script.

0

Así que realmente la única opción son las soluciones: 1) Simplemente no use 0 funciones de parámetros. 2) Realice una función de comprobación (tomando un parámetro) para detectar si hay un externo para llamar.

if (typeof(window.external.HasExternal(null)) != 'undefined') 

y compruebe que en lugar de la función si las funciones externas están todas allí o no están allí. 3) Para cada función sin parámetros que desee, haga que utilice un parámetro falso o agregue una función de comprobación de 1 parámetro si el código externo varía en función de qué funciones admite.

Cuestiones relacionadas