Provide source map info for simple async methods.

R=sigmund@google.com

Review URL: https://codereview.chromium.org/2510073002 .
This commit is contained in:
Johnni Winther 2016-11-18 09:28:40 +01:00
parent 7125282478
commit d0e057903e
7 changed files with 135 additions and 49 deletions

View file

@ -5,13 +5,14 @@
library rewrite_async;
import 'dart:collection';
import "dart:math" show max;
import 'dart:math' show max;
import 'package:js_runtime/shared/async_await_error_codes.dart' as error_codes;
import '../common.dart';
import '../io/source_information.dart' show SourceInformation;
import '../util/util.dart' show Pair;
import "js.dart" as js;
import 'js.dart' as js;
/// Rewrites a [js.Fun] with async/sync*/async* functions and await and yield
/// (with dart-like semantics) to an equivalent function without these.
@ -519,7 +520,8 @@ abstract class AsyncRewriterBase extends js.NodeVisitor {
js.Fun finishFunction(
List<js.Parameter> parameters,
js.Statement rewrittenBody,
js.VariableDeclarationList variableDeclarations);
js.VariableDeclarationList variableDeclarations,
SourceInformation sourceInformation);
Iterable<js.VariableInitialization> variableInitializations();
@ -705,7 +707,8 @@ abstract class AsyncRewriterBase extends js.NodeVisitor {
js.VariableDeclarationList variableDeclarations =
new js.VariableDeclarationList(variables);
return finishFunction(node.params, rewrittenBody, variableDeclarations);
return finishFunction(node.params, rewrittenBody, variableDeclarations,
node.sourceInformation);
}
@override
@ -851,7 +854,8 @@ abstract class AsyncRewriterBase extends js.NodeVisitor {
bool storeTarget = node.arguments.any(shouldTransform);
return withCallTargetExpression(node.target, (target) {
return withExpressions(node.arguments, (List<js.Expression> arguments) {
return new js.Call(target, arguments);
return new js.Call(target, arguments)
.withSourceInformation(node.sourceInformation);
});
}, store: storeTarget);
}
@ -1405,7 +1409,8 @@ abstract class AsyncRewriterBase extends js.NodeVisitor {
@override
void visitThrow(js.Throw node) {
withExpression(node.expression, (js.Expression expression) {
addStatement(new js.Throw(expression));
addStatement(new js.Throw(expression)
.withSourceInformation(node.sourceInformation));
}, store: false);
}
@ -1712,14 +1717,13 @@ class AsyncRewriter extends AsyncRewriterBase {
addStatement(new js.Comment("implicit return"));
}
addStatement(js.js.statement(
"return #runtimeHelper(#returnValue, #successCode, #completer);",
{
"runtimeHelper": asyncHelper,
"successCode": js.number(error_codes.SUCCESS),
"returnValue":
analysis.hasExplicitReturns ? returnValue : new js.LiteralNull(),
"completer": completer
}));
"return #runtimeHelper(#returnValue, #successCode, #completer);", {
"runtimeHelper": asyncHelper,
"successCode": js.number(error_codes.SUCCESS),
"returnValue":
analysis.hasExplicitReturns ? returnValue : new js.LiteralNull(),
"completer": completer
}));
}
@override
@ -1759,7 +1763,8 @@ class AsyncRewriter extends AsyncRewriterBase {
js.Fun finishFunction(
List<js.Parameter> parameters,
js.Statement rewrittenBody,
js.VariableDeclarationList variableDeclarations) {
js.VariableDeclarationList variableDeclarations,
SourceInformation sourceInformation) {
return js.js(
"""
function (#parameters) {
@ -1787,7 +1792,7 @@ class AsyncRewriter extends AsyncRewriterBase {
"asyncHelper": asyncHelper,
"completer": completer,
"wrapBody": wrapBody,
});
}).withSourceInformation(sourceInformation);
}
}
@ -1838,7 +1843,8 @@ class SyncStarRewriter extends AsyncRewriterBase {
js.Fun finishFunction(
List<js.Parameter> parameters,
js.Statement rewrittenBody,
js.VariableDeclarationList variableDeclarations) {
js.VariableDeclarationList variableDeclarations,
SourceInformation sourceInformation) {
// Each iterator invocation on the iterable should work on its own copy of
// the parameters.
// TODO(sigurdm): We only need to do this copying for parameters that are
@ -1891,7 +1897,7 @@ class SyncStarRewriter extends AsyncRewriterBase {
"handler": handler,
"currentError": currentErrorName,
"ERROR": js.number(error_codes.ERROR),
});
}).withSourceInformation(sourceInformation);
}
void addErrorExit() {
@ -2030,7 +2036,8 @@ class AsyncStarRewriter extends AsyncRewriterBase {
js.Fun finishFunction(
List<js.Parameter> parameters,
js.Statement rewrittenBody,
js.VariableDeclarationList variableDeclarations) {
js.VariableDeclarationList variableDeclarations,
SourceInformation sourceInformation) {
return js.js(
"""
function (#parameters) {
@ -2074,7 +2081,7 @@ class AsyncStarRewriter extends AsyncRewriterBase {
"streamOfController": streamOfController,
"controller": controllerName,
"wrapBody": wrapBody,
});
}).withSourceInformation(sourceInformation);
}
@override

View file

@ -11,11 +11,7 @@ import 'output_structure.dart';
import 'sourcemap_helper.dart';
import 'sourcemap_html_helper.dart';
enum DiffKind {
UNMATCHED,
MATCHING,
IDENTICAL,
}
enum DiffKind { UNMATCHED, MATCHING, IDENTICAL, }
/// Id for an output column.
class DiffColumn {

View file

@ -125,15 +125,7 @@ class HtmlPrintContext {
}
}
enum HtmlPartKind {
CODE,
LINE,
CONST,
NEWLINE,
TEXT,
TAG,
LINE_NUMBER,
}
enum HtmlPartKind { CODE, LINE, CONST, NEWLINE, TEXT, TAG, LINE_NUMBER, }
abstract class HtmlPart {
void printHtmlOn(StringBuffer buffer, HtmlPrintContext context);

View file

@ -51,9 +51,8 @@ void main() {
expect(decode('{"foo":"bar"}'), equals({'foo': 'bar'}));
expect(decode('{"foo":"bar",}'), equals({'foo': 'bar'}));
expect(
decode(
'{"foo":true, "bar": false, "baz": true, '
'"boz": \nnull\n,"qux": false,}'),
decode('{"foo":true, "bar": false, "baz": true, '
'"boz": \nnull\n,"qux": false,}'),
equals({
'foo': true,
'bar': false,

View file

@ -637,11 +637,7 @@ class Interval {
String toString() => '[$from,$to[';
}
enum CodeKind {
LIBRARY,
CLASS,
MEMBER,
}
enum CodeKind { LIBRARY, CLASS, MEMBER, }
class CodeLocation {
final Uri uri;

View file

@ -307,7 +307,9 @@ List<CodeLine> convertAnnotatedCodeToCodeLines(
void addAnnotations(List<Annotation> annotations) {
currentAnnotations.addAll(annotations);
currentLine.annotations.addAll(annotations);
if (currentLine != null) {
currentLine.annotations.addAll(annotations);
}
}
void beginLine(int currentOffset) {

View file

@ -27,29 +27,35 @@ main() {
}
''',
'''
import 'package:expect/expect.dart';
main() {
@{1:main}test();
}
@NoInline()
test() {
@{2:test}throw '$EXCEPTION_MARKER';
}
''',
'''
import 'package:expect/expect.dart';
main() {
@{1:main}Class.test();
}
class Class {
@NoInline()
static test() {
@{2:Class.test}throw '$EXCEPTION_MARKER';
}
}
''',
'''
import 'package:expect/expect.dart';
main() {
var c = new Class();
c.@{1:main}test();
}
class Class {
@NoInline()
test() {
@{2:Class.test}throw '$EXCEPTION_MARKER';
}
@ -66,6 +72,85 @@ class Class {
@{2:Class}throw '$EXCEPTION_MARKER';
}
}
''',
'''
import 'package:expect/expect.dart';
main() {
@{1:main}test();
}
@NoInline()
test() {
try {
@{2:test}throw '$EXCEPTION_MARKER';
} finally {
}
}
''',
'''
import 'package:expect/expect.dart';
main() {
@{1:main}test();
}
@NoInline()
test() {
try {
@{2:test}throw '$EXCEPTION_MARKER';
} on Error catch (e) {
}
}
''',
'''
import 'package:expect/expect.dart';
main() {
@{1:main}test();
}
@NoInline()
test() {
try {
@{2:test}throw '$EXCEPTION_MARKER';
} on String catch (e) {
rethrow;
}
}
''',
'''
import 'package:expect/expect.dart';
main() {
test(); // This call is no longer on the stack when the error is thrown.
}
@NoInline()
test() async {
@{1:test}throw '$EXCEPTION_MARKER';
}
''',
'''
import 'package:expect/expect.dart';
main() {
test1();
}
@NoInline()
test1() async {
// This call is no longer on the stack when the error is thrown.
await test2();
}
@NoInline()
test2() async {
@{1:test2}throw '$EXCEPTION_MARKER';
}
''',
'''
import 'package:expect/expect.dart';
main() {
test1();
}
@NoInline()
test1() async {
@{1:test1}test2();
}
@NoInline()
test2() {
@{2:test2}throw '$EXCEPTION_MARKER';
}
''',
];
@ -80,7 +165,6 @@ const int _LF = 0x0A;
const int _CR = 0x0D;
const int _LBRACE = 0x7B;
Test processTestCode(String code) {
StringBuffer codeBuffer = new StringBuffer();
Map<int, StackTraceLine> stackTraceMap = <int, StackTraceLine>{};
@ -135,12 +219,12 @@ Test processTestCode(String code) {
void main(List<String> arguments) {
asyncTest(() async {
for (String code in TESTS) {
await runTest(processTestCode(code));
await runTest(processTestCode(code), verbose: arguments.contains('-v'));
}
});
}
Future runTest(Test test) async {
Future runTest(Test test, {bool verbose: false}) async {
Directory tmpDir = await createTempDir();
String input = '${tmpDir.path}/$INPUT_FILE_NAME';
new File(input).writeAsStringSync(test.code);
@ -162,9 +246,13 @@ Future runTest(Test test) async {
JSON.decode(new File('$output.map').readAsStringSync()));
print("Running d8 $output");
ProcessResult runResult =
Process.runSync(d8executable, [output]);
ProcessResult runResult = Process.runSync(d8executable,
['sdk/lib/_internal/js_runtime/lib/preambles/d8.js', output]);
String out = '${runResult.stderr}\n${runResult.stdout}';
if (verbose) {
print('d8 output:');
print(out);
}
List<String> lines = out.split(new RegExp(r'(\r|\n|\r\n)'));
List<StackTraceLine> jsStackTrace = <StackTraceLine>[];
bool seenMarker = false;
@ -210,6 +298,12 @@ Future runTest(Test test) async {
}
}
}
if (verbose) {
print('JavaScript stacktrace:');
print(jsStackTrace.join('\n'));
print('Dart stacktrace:');
print(dartStackTrace.join('\n'));
}
Expect.equals(
expectedIndex,
test.expectedLines.length,
@ -341,4 +435,4 @@ String get d8executable {
return 'third_party/d8/macos/d8';
}
throw new UnsupportedError('Unsupported platform.');
}
}