20faaa5d94
Change-Id: Ib18f554c1076f27a3f7c0df5a36410da41a1f467 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/148784 Reviewed-by: Paul Berry <paulberry@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
148 lines
4.3 KiB
Dart
148 lines
4.3 KiB
Dart
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
// @dart = 2.7
|
|
|
|
library sourcemap.js_tracer;
|
|
|
|
import 'package:compiler/src/io/source_information.dart';
|
|
import 'package:compiler/src/io/position_information.dart';
|
|
import 'package:compiler/src/js/js.dart' as js;
|
|
import 'package:compiler/src/js/js_source_mapping.dart';
|
|
import 'sourcemap_helper.dart';
|
|
import 'trace_graph.dart';
|
|
|
|
/// Create a [TraceGraph] for [info] registering usage in [coverage].
|
|
TraceGraph createTraceGraph(SourceMapInfo info, Coverage coverage) {
|
|
TraceGraph graph = new TraceGraph();
|
|
TraceListener listener = new StepTraceListener(graph);
|
|
CodePositionMap codePositions =
|
|
new CodePositionCoverage(info.jsCodePositions, coverage);
|
|
JavaScriptTracer tracer = new JavaScriptTracer(
|
|
codePositions, const SourceInformationReader(), [
|
|
new CoverageListener(coverage, const SourceInformationReader()),
|
|
listener
|
|
]);
|
|
info.node.accept(tracer);
|
|
return graph;
|
|
}
|
|
|
|
class StepTraceListener extends TraceListener
|
|
with NodeToSourceInformationMixin {
|
|
Map<js.Node, TraceStep> steppableMap = <js.Node, TraceStep>{};
|
|
final TraceGraph graph;
|
|
|
|
StepTraceListener(this.graph);
|
|
|
|
@override
|
|
SourceInformationReader get reader => const SourceInformationReader();
|
|
|
|
@override
|
|
void onStep(js.Node node, Offset offset, StepKind kind) {
|
|
SourceInformation sourceInformation = computeSourceInformation(node);
|
|
SourcePositionKind sourcePositionKind = SourcePositionKind.START;
|
|
List text = [node];
|
|
switch (kind) {
|
|
case StepKind.FUN_ENTRY:
|
|
text = ['<entry>'];
|
|
break;
|
|
case StepKind.FUN_EXIT:
|
|
sourcePositionKind = SourcePositionKind.INNER;
|
|
text = ['<exit>'];
|
|
break;
|
|
case StepKind.CALL:
|
|
CallPosition callPosition =
|
|
CallPosition.getSemanticPositionForCall(node);
|
|
sourcePositionKind = callPosition.sourcePositionKind;
|
|
break;
|
|
case StepKind.ACCESS:
|
|
case StepKind.NEW:
|
|
case StepKind.RETURN:
|
|
case StepKind.BREAK:
|
|
case StepKind.CONTINUE:
|
|
case StepKind.THROW:
|
|
case StepKind.EXPRESSION_STATEMENT:
|
|
break;
|
|
case StepKind.IF_CONDITION:
|
|
js.If ifNode = node;
|
|
text = ['if(', ifNode.condition, ') ...'];
|
|
break;
|
|
case StepKind.FOR_INITIALIZER:
|
|
js.For forNode = node;
|
|
text = ['for(', forNode.init, '; ...) ...'];
|
|
break;
|
|
case StepKind.FOR_CONDITION:
|
|
js.For forNode = node;
|
|
text = ['for(...;', forNode.condition, '; ...) ...'];
|
|
break;
|
|
case StepKind.FOR_UPDATE:
|
|
js.For forNode = node;
|
|
text = ['for(...; ...', forNode.update, ') ...'];
|
|
break;
|
|
case StepKind.WHILE_CONDITION:
|
|
js.While whileNode = node;
|
|
text = ['while(', whileNode.condition, ') ...'];
|
|
break;
|
|
case StepKind.DO_CONDITION:
|
|
js.Do doNode = node;
|
|
text = ['do {... } (', doNode.condition, ')'];
|
|
break;
|
|
case StepKind.SWITCH_EXPRESSION:
|
|
js.Switch switchNode = node;
|
|
text = ['switch(', switchNode.key, ') ...'];
|
|
break;
|
|
case StepKind.NO_INFO:
|
|
break;
|
|
}
|
|
createTraceStep(kind, node,
|
|
offset: offset,
|
|
sourceLocation:
|
|
getSourceLocation(sourceInformation, sourcePositionKind),
|
|
text: text);
|
|
}
|
|
|
|
void createTraceStep(StepKind kind, js.Node node,
|
|
{Offset offset, List text, String note, SourceLocation sourceLocation}) {
|
|
int id = steppableMap.length;
|
|
|
|
if (text == null) {
|
|
text = [node];
|
|
}
|
|
|
|
TraceStep step =
|
|
new TraceStep(kind, id, node, offset, text, sourceLocation);
|
|
graph.addStep(step);
|
|
|
|
steppableMap[node] = step;
|
|
}
|
|
|
|
@override
|
|
void pushBranch(BranchKind kind, [value]) {
|
|
var branch;
|
|
switch (kind) {
|
|
case BranchKind.CONDITION:
|
|
branch = value ? 't' : 'f';
|
|
break;
|
|
case BranchKind.LOOP:
|
|
branch = 'l';
|
|
break;
|
|
case BranchKind.CATCH:
|
|
branch = 'c';
|
|
break;
|
|
case BranchKind.FINALLY:
|
|
branch = 'F';
|
|
break;
|
|
case BranchKind.CASE:
|
|
branch = '$value';
|
|
break;
|
|
}
|
|
graph.pushBranch(branch);
|
|
}
|
|
|
|
@override
|
|
void popBranch() {
|
|
graph.popBranch();
|
|
}
|
|
}
|