SourceMapConsumerV3 feature request: allow disabling of approximated mappings

48 views
Skip to first unread message

Kyle Mantzel

unread,
Feb 26, 2021, 3:54:05 PM2/26/21
to Closure Compiler Discuss

Hello,

I am a consumer of SourceMapConsumerV3 :)

I am using the getMappingForLine API to retrieve a source line from a transpiled line and column.

There are some cases where calling this API will not find a direct mapping and approximate it, either by retrieving previous transpiled line mappings or by grabbing a mapping with a different column than was requested.

It would be nice if one could opt out of this behavior, so that the caller could have the visibility that a mapping was not found vs it being approximated.

Are there any objections to this feature request? If not I would be willing to contribute the change.

Thanks,
Kyle

Kyle Mantzel

unread,
Feb 26, 2021, 4:12:07 PM2/26/21
to Closure Compiler Discuss

Please find example files embedded below to showcase an example:

Example Files

Source Script

class Shape {
    constructor (id) {
        this.id = id;
    }
}
class Rectangle extends Shape {
    constructor(id) {
        super(id);
    }
}
var s = new Rectangle("Shape ID");

Transpiled Script

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol ===  "function" && typeof Symbol.iterator === "symbol") { _typeof =  function _typeof(obj) { return typeof obj; }; } else { _typeof =  function _typeof(obj) { return obj && typeof Symbol ===  "function" && obj.constructor === Symbol && obj !==  Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function  _inherits(subClass, superClass) { if (typeof superClass !== "function"  && superClass !== null) { throw new TypeError("Super expression  must either be null or a function"); } subClass.prototype =  Object.create(superClass && superClass.prototype, { constructor:  { value: subClass, writable: true, configurable: true } }); if  (superClass) _setPrototypeOf(subClass, superClass); }

function  _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ||  function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return  _setPrototypeOf(o, p); }

function _createSuper(Derived) { var  hasNativeReflectConstruct = _isNativeReflectConstruct(); return function  _createSuperInternal() { var Super = _getPrototypeOf(Derived), result;  if (hasNativeReflectConstruct) { var NewTarget =  _getPrototypeOf(this).constructor; result = Reflect.construct(Super,  arguments, NewTarget); } else { result = Super.apply(this, arguments); }  return _possibleConstructorReturn(this, result); }; }

function  _possibleConstructorReturn(self, call) { if (call &&  (_typeof(call) === "object" || typeof call === "function")) { return  call; } return _assertThisInitialized(self); }

function  _assertThisInitialized(self) { if (self === void 0) { throw new  ReferenceError("this hasn't been initialised - super() hasn't been  called"); } return self; }

function _isNativeReflectConstruct() {  if (typeof Reflect === "undefined" || !Reflect.construct) return false;  if (Reflect.construct.sham) return false; if (typeof Proxy ===  "function") return true; try {  Date.prototype.toString.call(Reflect.construct(Date, [], function ()  {})); return true; } catch (e) { return false; } }

function  _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ?  Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__  || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function  _classCallCheck(instance, Constructor) { if (!(instance instanceof  Constructor)) { throw new TypeError("Cannot call a class as a  function"); } }

var Shape = function Shape(id) {
  "use strict";

  _classCallCheck(this, Shape);

  this.id = id;
};

var Rectangle = /*#__PURE__*/function (_Shape) {
  "use strict";

  _inherits(Rectangle, _Shape);

  var _super = _createSuper(Rectangle);

  function Rectangle(id) {
    _classCallCheck(this, Rectangle);

    return _super.call(this, id);
  }

  return Rectangle;
}(Shape);

Source Map

{"version":3,"sources":["../src/class_inheritance.js"],"names":["Shape","id","Rectangle","s"],"mappings":";;;;;;;;;;;;;;;;;;IAAMA,K,GACL,eAAaC,EAAb,EAAiB;AAAA;;AAAA;;AAChB,OAAKA,EAAL,GAAUA,EAAV;AACA,C;;IAEIC,S;;;;;;;AACL,qBAAYD,EAAZ,EAAgB;AAAA;;AAAA,6BACTA,EADS;AAEf;;;EAHsBD,K;;AAKxB,IAAIG,CAAC,GAAG,IAAID,SAAJ,CAAc,UAAd,CAAR","sourcesContent":["class  Shape {\n\tconstructor (id) {\n\t\tthis.id = id;\n\t}\n}\nclass  Rectangle extends Shape {\n\tconstructor(id)  {\n\t\tsuper(id);\n\t}\n}\nvar s = new Rectangle(\"Shape  ID\");"],"file":"class_inheritance.js"}

Scenario

Calling SourceMapConsumerV3#getMappingForLine(40, 10) returns 9 when I would expect a null mapping.
Using the source-map library
https://github.com/mozilla/source-map
produces a null mapping: console.log(consumer.originalPositionFor({ line: 40, column: 9 }));

rish...@google.com

unread,
Mar 1, 2021, 8:09:04 PM3/1/21
to Closure Compiler Discuss
Are you requesting a new method in SourceMapConsumerV3.java which either returns an accurate mapping for the provided line and column, or null?
Or are you requesting a change to the existing `getMappingForLine` API?
The former may be quite simple to do. 

Kyle Mantzel

unread,
Mar 2, 2021, 12:25:23 AM3/2/21
to Closure Compiler Discuss
I'd say I prefer the latter to avoid duplication of code. I was thinking of adding a new constructor with a feature flag.

rough example here:

Also I know I originally mentioned that the approximation can "grab a mapping with a different column than was requested", but I think that was an error on my part for not understanding source mapping. As a variable name can span multiple columns. So I just ended up making the approximation around the existing `getPreviousLine` method for now.

Just out of curiosity, is changing the behavior without this feature flag an option?

lha...@google.com

unread,
Mar 9, 2021, 11:43:46 AM3/9/21
to Closure Compiler Discuss
Hi Kyle! Since you haven't gotten an answer yet, and I'm not familiar enough with SourceMapConsumerV3 to respond, I filed this as https://github.com/google/closure-compiler/issues/3781. It will get looked at during our weekly bug scrub meeting.

Thanks,
Laura

Kyle Mantzel

unread,
Mar 10, 2021, 10:16:51 AM3/10/21
to closure-comp...@googlegroups.com
Thank you for setting this up for me Laura! I appreciate it.

Regards,
Kyle 

--

---
You received this message because you are subscribed to the Google Groups "Closure Compiler Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to closure-compiler-d...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/closure-compiler-discuss/92a84bbf-bc79-4d65-950f-cb395dea435fn%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages