AngularJS - 堆栈跟踪忽略源地图 [英] AngularJS - Stack trace ignoring source map

查看:105
本文介绍了AngularJS - 堆栈跟踪忽略源地图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经写了一个AngularJS应用程序,但它的证明有点一场噩梦调试。我使用的步兵+丑化来连接,然后再缩小我的应用程序code。它还创建一个源地图旁边的缩小的JS文件。

源地图似乎正常工作时,有文件中的JS错误,但AngularJS应用程序之外。例如如果我写的console.log('A·B'); 在一个文件的顶部,登录了在Chrome调试器显示线+文件信息的错误原始文件,而不是缩小的之一。

在没有与code一个问题,即角运行本身(例如,在控制器code)出现问题。我从角一个不错的堆栈跟踪,但它仅详细说明缩小的文件不是原来的。

有什么我可以做的就是角承认源地图?

以下示例错误:

 类型错误:无法调用未定义的方法'getElement
在Object.addMapControls(HTTP://my-site/wp-content/plugins/my-maps/assets/js/app.min.js:1:2848)
在Object.g [莫过于init(HTTP://my-site/wp-content/plugins/my-maps/assets/js/app.min.js:1:344)
在新一(HTTP://my-site/wp-content/plugins/my-maps/assets/js/app.min.js:1:591)
在d(http://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.min.js:29:495)
在Object.instantiate(http://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.min.js:30:123)


解决方案

我能找到的唯一解决办法是硬着头皮分析源映射自己。下面是一些code,将做到这一点。首先,你需要源地图添加到您的网页。然后添加此code:

  angular.module('共享')。工厂('$ exceptionHandler的,
功能($日志$窗口,$喷油器){
  VAR getSourceMappedStackTrace =功能(例外){
    VAR $ Q = $ injector.get('$ Q'),
        $ HTTP = $ injector.get('$ HTTP),
        SMConsumer = window.sourceMap.SourceMapConsumer,
        缓存= {};    //检索SourceMap对象为缩小的脚本URL
    VAR getMapForScript =功能(URL){
      如果(缓存[URL]){
        返回高速缓存[URL]
      }其他{
        VAR承诺= $ http.get(URL)。然后(功能(响应){
          变种M = response.data.match(/ \\ / \\ /#= sourceMappingURL(+ \\图)/。);
          如果(米){
            VAR路径= url.match(/^(.+)\\/[^/]+$/);
            路径=路径和放大器;&安培;路径[1];
            返回$ http.get(路径+'/'+ M [1])。然后(功能(响应){
              返回新SMConsumer(response.data);
            });
          }其他{
            返回$ q.reject();
          }
        });
        缓存[URL] =承诺;
        返回的承诺;
      }
    };    如果(exception.stack){//不是所有的浏览器都支持堆栈跟踪
      返回$ q.all(_。图(exception.stack.split(/ \\ n /),功能(stackLine){
        变种匹配= stackLine.match(/ ^(+)(HTTP +):(\\ D +):(\\ D +)/);
        如果(匹配){
          VAR preFIX =匹配[1],URL =匹配[2],行=匹配[3],COL =匹配[4];
          返回getMapForScript(URL)。然后(功能(图){
            VAR POS = map.originalPositionFor({
              行:parseInt函数(线,10),
              列形式:parseInt(COL 10)
            });
            VAR mangledName = prefix.match(/ \\ S *(上)\\ S *(*)\\ S *(\\(| @)/)?。?;
            mangledName =(mangledName&放大器;&放大器; mangledName [2])|| '';
            在'+回报(?pos.name pos.name:mangledName)+''+
              $ window.location.origin + pos.source +:+ pos.line +:+
              pos.column;
          },函数(){
            返回stackLine;
          });
        }其他{
          返回$ q.when(stackLine);
        }
      }))。然后(函数(线){
        返回lines.join('\\ n');
      });
    }其他{
      返回$ q.when('');
    }
  };  复位功能(例外){
    getSourceMappedStackTrace(例外)。然后($ log.error);
  };
});

这code会下载源代码,然后下载sourcemaps,解析它们,最后试图更换堆栈中的位置跟踪映射的位置。这工作完全在Chrome中,相当可以接受在Firefox。缺点是要添加一个相当大的依赖性到code碱基,而且你非常快的同步错误报告给移动相当缓慢异步错误报告。

I've written an AngularJS app but it's proving a bit of a nightmare to debug. I'm using Grunt + uglify to concatenate and minify my application code. It also creates a source map alongside the minified JS file.

The source map seems to work properly when there is a JS error in the file, but outside of the AngularJS application. e.g. If I write console.log('a.b'); at the top of one of the files, the error logged in the Chrome debugger displays line + file info for the original file, not the minified one.

The problem occurs when there is a problem with code that Angular runs itself (e.g. in Controller code). I get a nice stack trace from Angular, but it only details the minified file not the original.

Is there anything I can do to get Angular to acknowledge the source map?

Example error below:

TypeError: Cannot call method 'getElement' of undefined
at Object.addMapControls (http://my-site/wp-content/plugins/my-maps/assets/js/app.min.js:1:2848)
at Object.g [as init] (http://my-site/wp-content/plugins/my-maps/assets/js/app.min.js:1:344)
at new a (http://my-site/wp-content/plugins/my-maps/assets/js/app.min.js:1:591)
at d (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.min.js:29:495)
at Object.instantiate (http://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.min.js:30:123)

解决方案

The only solution I could find is to bite the bullet and parse the source maps yourself. Here is some code that will do this. First you need to add source-map to your page. Then add this code:

angular.module('Shared').factory('$exceptionHandler', 
function($log, $window, $injector) {
  var getSourceMappedStackTrace = function(exception) {
    var $q = $injector.get('$q'),
        $http = $injector.get('$http'),
        SMConsumer = window.sourceMap.SourceMapConsumer,
        cache = {};

    // Retrieve a SourceMap object for a minified script URL
    var getMapForScript = function(url) {
      if (cache[url]) {
        return cache[url];
      } else {
        var promise = $http.get(url).then(function(response) {
          var m = response.data.match(/\/\/# sourceMappingURL=(.+\.map)/);
          if (m) {
            var path = url.match(/^(.+)\/[^/]+$/);
            path = path && path[1];
            return $http.get(path + '/' + m[1]).then(function(response) {
              return new SMConsumer(response.data);
            });
          } else {
            return $q.reject();
          }
        });
        cache[url] = promise;
        return promise;
      }
    };

    if (exception.stack) { // not all browsers support stack traces
      return $q.all(_.map(exception.stack.split(/\n/), function(stackLine) {
        var match = stackLine.match(/^(.+)(http.+):(\d+):(\d+)/);
        if (match) {
          var prefix = match[1], url = match[2], line = match[3], col = match[4];
          return getMapForScript(url).then(function(map) {
            var pos = map.originalPositionFor({
              line: parseInt(line, 10), 
              column: parseInt(col, 10)
            });
            var mangledName = prefix.match(/\s*(at)?\s*(.*?)\s*(\(|@)/);
            mangledName = (mangledName && mangledName[2]) || '';
            return '    at ' + (pos.name ? pos.name : mangledName) + ' ' + 
              $window.location.origin + pos.source + ':' + pos.line + ':' + 
              pos.column;
          }, function() {
            return stackLine;
          });
        } else {
          return $q.when(stackLine);
        }
      })).then(function (lines) {
        return lines.join('\n');
      });
    } else {
      return $q.when('');
    }
  };

  return function(exception) {
    getSourceMappedStackTrace(exception).then($log.error);
  };
});

This code will download the source, then download the sourcemaps, parse them, and finally attempt to replace the locations in the stack trace the mapped locations. This works perfectly in Chrome, and quite acceptably in Firefox. The disadvantage is that you are adding a fairly large dependency to your code base and that you move from very fast synchronous error reporting to fairly slow async error reporting.

这篇关于AngularJS - 堆栈跟踪忽略源地图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆