Ensure inlining of getter/setters is recorded in our source-map extension

Change-Id: I6eac59f756b2a6a87842e5a4b1d8aa47df619042
Reviewed-on: https://dart-review.googlesource.com/c/88580
Commit-Queue: Sigmund Cherem <sigmund@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index 4fb641a..0d3b387 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -549,6 +549,7 @@
             CallPosition.getSemanticPositionForCall(node);
         registerPosition(callPosition.sourcePositionKind);
         break;
+      case StepKind.ACCESS:
       case StepKind.NEW:
       case StepKind.RETURN:
       case StepKind.BREAK:
@@ -771,6 +772,7 @@
   FUN_EXIT,
   CALL,
   NEW,
+  ACCESS,
   RETURN,
   BREAK,
   CONTINUE,
@@ -1010,6 +1012,18 @@
   @override
   visitAccess(js.PropertyAccess node) {
     visit(node.receiver);
+    notifyStep(
+        node,
+        // Technically we'd like to use the offset of the `.` in the property
+        // access, but the js_ast doesn't expose it. Since this is only used to
+        // search backwards for inlined frames, we use the receiver's END offset
+        // instead as an approximation. Note that the END offset points one
+        // character after the end of the node, so it is likely always the
+        // offset we want.
+        getOffsetForNode(
+            node, getSyntaxOffset(node.receiver, kind: CodePositionKind.END)),
+        StepKind.ACCESS);
+    steps.add(node);
     visit(node.selector);
   }
 
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 9a23841..ea0e94a 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -2194,7 +2194,10 @@
     use(node.receiver);
     js.Expression receiver = pop();
     use(node.value);
-    push(new js.Assignment(new js.PropertyAccess(receiver, name), pop())
+    push(new js.Assignment(
+            new js.PropertyAccess(receiver, name)
+                .withSourceInformation(node.sourceInformation),
+            pop())
         .withSourceInformation(node.sourceInformation));
   }
 
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 72a69eb..dd6084d 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -1253,7 +1253,8 @@
           field, _globalInferenceResults);
     }
 
-    return new HFieldGet(field, receiver, type, isAssignable: isAssignable);
+    return new HFieldGet(field, receiver, type, isAssignable: isAssignable)
+      ..sourceInformation = node.sourceInformation;
   }
 
   HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
@@ -1289,7 +1290,8 @@
       }
     }
     HFieldSet result =
-        new HFieldSet(_abstractValueDomain, field, receiver, value);
+        new HFieldSet(_abstractValueDomain, field, receiver, value)
+          ..sourceInformation = node.sourceInformation;
     _log?.registerFieldSet(node, result);
     return result;
   }
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart b/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart
index aacf1c6..bc504c76 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/js_tracer.dart
@@ -53,6 +53,7 @@
             CallPosition.getSemanticPositionForCall(node);
         sourcePositionKind = callPosition.sourcePositionKind;
         break;
+      case StepKind.ACCESS:
       case StepKind.NEW:
       case StepKind.RETURN:
       case StepKind.BREAK:
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
index 7b45545..8826468 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
@@ -523,6 +523,7 @@
   /// Called when [node] defines a step of the given [kind] at the given
   /// [offset] when the generated JavaScript code.
   void onStep(js.Node node, Offset offset, StepKind kind) {
+    if (kind == StepKind.ACCESS) return;
     register(kind, node);
   }
 
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/getter_inlining.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/getter_inlining.dart
new file mode 100644
index 0000000..ea1874b
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/getter_inlining.dart
@@ -0,0 +1,16 @@
+class MyClass {
+  int fieldName;
+
+  MyClass(this.fieldName);
+
+  int get getterName => /*1:getterName(inlined)*/ fieldName;
+}
+
+@pragma('dart2js:noInline')
+confuse(x) => x;
+
+main() {
+  confuse(new MyClass(3));
+  var m = confuse(null);
+  m. /*0:main*/ getterName;
+}
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/setter_inlining.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/setter_inlining.dart
new file mode 100644
index 0000000..9b5ab60
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/setter_inlining.dart
@@ -0,0 +1,16 @@
+class MyClass {
+  int fieldName;
+
+  MyClass(this.fieldName);
+
+  set setterName(int v) => /*1:setterName(inlined)*/ fieldName = v;
+}
+
+@pragma('dart2js:noInline')
+confuse(x) => x;
+
+main() {
+  confuse(new MyClass(3));
+  var m = confuse(null);
+  m. /*0:main*/ setterName = 2;
+}