¿Cómo podemos saber realmente que la función que lanzó el error fue llamada? El problema aquí es que el motor de JavaScript te dirá lo que realmente sucedió es que el primer marco fue un nuevo error. Porque, técnicamente, esto es lo que produjo el error. Pero esto no es útil. De lo contrario, solo veríamos en la mayoría de los casos simplemente nuevo error, nuevo error, nuevo error. Lo que queremos saber es cuál es la función que realmente lo causó.
Entonces, en este caso, sería llamada. Sin embargo, ¿cómo podemos saber que es realmente esto? Tenemos algunos trucos bajo la manga. El primero se llama escaneo hacia atrás, donde tomas el código fuente minificado, lo tokenizas y vas un token a la vez hacia atrás. Entonces, lo que haces es tener error, ir a nuevo, volver a throw, y lo haces mientras veas el nombre minificado de la función. O más bien, veas el token function precedido del nombre minificado. En nuestro caso aquí, era XY, ¿verdad? Una vez que tenemos esta función y los tokens XY, podemos preguntar cuál es la posición del token XY, en este caso, y luego preguntar al mapa de origen, oye, bien, ahora sé la nueva ubicación. Esto no es nuevo error. Sé la ubicación de XY. ¿Tienes un nombre correspondiente para esto? Y si es así, tenemos suerte, ahora podemos decir que fue realmente llamada y no nuevo error lo que causó el error en sí. Sin embargo, no siempre es posible. Si tienes una función anónima o una función flecha de ES6, simplemente no funcionará.
El segundo truco que podemos usar se llama nombramiento del llamador, que hace la suposición de que la función que nos llamó no modificó el nombre original. Por ejemplo, no lo reasignó en ningún lugar o no lo modificó de alguna manera extraña o no lo llamó dinámicamente, aquí está la pila de llamadas, la original, que es la función maybe, que llama a la función llamada, que produce el error, y la minificada, llamada VM llamando a XY, llamando a nuevo error. Lo que podemos hacer en lugar de preguntar cuál es la ubicación de nuevo error, podemos subir un paso hacia arriba, que es XY en este caso, y preguntarle a XY cuál es la columna y la línea correspondiente de este marco. Lo que requiere es que necesitas conocer toda la pila de antemano. Por ejemplo, si solo obtienes el primer marco, volvamos al ejemplo aquí, si solo conoces X asset bundle min JS, el primero, estás fuera de suerte, no puedes hacer esto porque lo que necesitas hacer es consultar el marco debajo de este, que es como una columna 2430, ¿verdad? Esto generalmente da algunas ideas, como podemos recurrir a esto, pero tampoco es genial. No siempre funciona, sigue siendo solo una suposición.
La mejor idea que se nos ocurrió y que usamos con éxito en este momento, y esto es lo que muchos DevTools están haciendo en este momento, es la reconstrucción del AST. Lo que hace es tomar el código fuente minificado y hacer el mismo trabajo que los empaquetadores y transpiladores ya hicieron, pero, nuevamente, es muy ineficiente en memoria, es pesado, básicamente requiere mucho trabajo. Sin embargo, la ventaja de esto es que obtenemos toda la información que podamos necesitar. Por ejemplo, podemos decir que aquí se lanzó un nuevo error dentro del método estático en la clase método bar de foo, ¿verdad? O en este caso, podemos decir exactamente que era solo un literal de objeto, asignado a la variable A mayúscula, y era un método, en realidad la propiedad, lo siento, el otro método, u otro getter personalizado llamado foo. Y aquí podemos decir que era el constructor de la clase B. Entonces podemos saber exactamente dónde estamos en el momento en que ocurrió el error, porque podríamos reconstruir todo. Sin embargo, el problema es que nuevamente, necesitas procesar todo el AST, lo que puede ser muy, muy costoso para archivos muy grandes. Y los empaquetadores y transpiladores ya tenían estos data.
Comments