From d539c78af1a282c2694a93f06760da1b8791975d Mon Sep 17 00:00:00 2001 From: Johnni Winther Date: Fri, 12 Jan 2018 21:23:40 +0000 Subject: [PATCH] Add source information to parameter stubs. Change-Id: If942cc13203752361c3104c89190d75979073498 Reviewed-on: https://dart-review.googlesource.com/34440 Commit-Queue: Johnni Winther Reviewed-by: Sigmund Cherem --- pkg/compiler/lib/src/closure.dart | 2 + .../lib/src/io/kernel_source_information.dart | 62 +++++++++------ .../lib/src/io/multi_information.dart | 8 ++ .../lib/src/io/position_information.dart | 20 ++++- .../lib/src/io/source_information.dart | 59 ++++++++++---- .../lib/src/io/start_end_information.dart | 26 +++++-- .../lib/src/js_emitter/code_emitter_task.dart | 1 + .../js_emitter/parameter_stub_generator.dart | 20 ++++- .../program_builder/program_builder.dart | 13 +++- .../lib/src/stacktrace_helper.dart | 5 +- .../sourcemaps/helpers/output_structure.dart | 4 +- .../helpers/source_map_validator_helper.dart | 6 ++ .../sourcemaps/stacktrace/parameters.dart | 76 +++++++++++++++++++ .../dart2js/sourcemaps/stacktrace_test.dart | 15 +++- .../dart2js/sourcemaps/tools/diff_view.dart | 7 +- .../tools/source_mapping_tester.dart | 2 +- 16 files changed, 269 insertions(+), 57 deletions(-) create mode 100644 tests/compiler/dart2js/sourcemaps/stacktrace/parameters.dart diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart index d585eec3ebe..869ed634f20 100644 --- a/pkg/compiler/lib/src/closure.dart +++ b/pkg/compiler/lib/src/closure.dart @@ -667,6 +667,8 @@ class SynthesizedCallMethodElementX extends BaseFunctionElementX return closureClass.methodElement.memberContext; } + SourceSpan get sourcePosition => expression.sourcePosition; + bool get hasNode => node != null; FunctionExpression parseNode(ParsingContext parsing) => node; diff --git a/pkg/compiler/lib/src/io/kernel_source_information.dart b/pkg/compiler/lib/src/io/kernel_source_information.dart index da70b55fc33..93d324ef847 100644 --- a/pkg/compiler/lib/src/io/kernel_source_information.dart +++ b/pkg/compiler/lib/src/io/kernel_source_information.dart @@ -11,6 +11,7 @@ import 'package:kernel/ast.dart' as ir; import '../elements/entities.dart'; import '../kernel/element_map.dart'; import '../js_model/js_strategy.dart'; +import '../universe/call_structure.dart'; import 'source_information.dart'; import 'position_information.dart'; @@ -28,13 +29,15 @@ class KernelSourceInformationStrategy } } -/// Compute the source map name for kernel based [member]. +/// Compute the source map name for kernel based [member]. If [callStructure] +/// is non-null it is used to name the parameter stub for [element]. /// /// [elementMap] is used to compute names for closure call methods. // TODO(johnniwinther): Make the closure call names available to // `sourcemap_helper.dart`. String computeKernelElementNameForSourceMaps( - KernelToElementMapForBuilding elementMap, MemberEntity member) { + KernelToElementMapForBuilding elementMap, MemberEntity member, + [CallStructure callStructure]) { MemberDefinition definition = elementMap.getMemberDefinition(member); switch (definition.kind) { case MemberKind.closureCall: @@ -58,10 +61,10 @@ String computeKernelElementNameForSourceMaps( } MemberEntity enclosingMember = elementMap.getMember(node); String enclosingMemberName = - computeElementNameForSourceMaps(enclosingMember); + computeElementNameForSourceMaps(enclosingMember, callStructure); return '$enclosingMemberName.$name'; default: - return computeElementNameForSourceMaps(member); + return computeElementNameForSourceMaps(member, callStructure); } } @@ -77,11 +80,13 @@ class KernelSourceInformationBuilder : this._name = computeKernelElementNameForSourceMaps(_elementMap, _member); - /// Returns the [SourceLocation] for the [offset] within [node]. + /// Returns the [SourceLocation] for the [offset] within [node] using [name] + /// as the name of the source location. /// /// If [offset] is `null`, the first `fileOffset` of [node] or its parents is /// used. - SourceLocation _getSourceLocation(ir.TreeNode node, [int offset]) { + SourceLocation _getSourceLocation(String name, ir.TreeNode node, + [int offset]) { ir.Location location; if (offset != null) { location = node.location; @@ -93,7 +98,7 @@ class KernelSourceInformationBuilder location = node.location; offset = node.fileOffset; } - return new KernelSourceLocation(location, offset, _name); + return new KernelSourceLocation(location, offset, name); } /// Creates the source information for a function definition defined by the @@ -101,10 +106,10 @@ class KernelSourceInformationBuilder /// /// This method handles both methods, constructors, and local functions. SourceInformation _buildFunction( - ir.TreeNode node, ir.FunctionNode functionNode) { + String name, ir.TreeNode node, ir.FunctionNode functionNode) { if (functionNode.fileEndOffset != ir.TreeNode.noOffset) { - return new PositionSourceInformation(_getSourceLocation(node), - _getSourceLocation(functionNode, functionNode.fileEndOffset)); + return new PositionSourceInformation(_getSourceLocation(name, node), + _getSourceLocation(name, functionNode, functionNode.fileEndOffset)); } return _buildTreeNode(node); } @@ -116,31 +121,32 @@ class KernelSourceInformationBuilder /// to the end of the member as the closing position. SourceInformation _buildFunctionEnd(MemberEntity member, [ir.TreeNode base]) { MemberDefinition definition = _elementMap.getMemberDefinition(member); + String name = computeKernelElementNameForSourceMaps(_elementMap, member); ir.Node node = definition.node; switch (definition.kind) { case MemberKind.regular: if (node is ir.Procedure) { - return _buildFunction(base ?? node, node.function); + return _buildFunction(name, base ?? node, node.function); } break; case MemberKind.constructor: case MemberKind.constructorBody: if (node is ir.Procedure) { - return _buildFunction(base ?? node, node.function); + return _buildFunction(name, base ?? node, node.function); } else if (node is ir.Constructor) { - return _buildFunction(base ?? node, node.function); + return _buildFunction(name, base ?? node, node.function); } break; case MemberKind.closureCall: if (node is ir.FunctionDeclaration) { - return _buildFunction(base ?? node, node.function); + return _buildFunction(name, base ?? node, node.function); } else if (node is ir.FunctionExpression) { - return _buildFunction(base ?? node, node.function); + return _buildFunction(name, base ?? node, node.function); } break; default: } - return _buildTreeNode(base ?? node); + return _buildTreeNode(base ?? node, name: name); } /// Creates the source information for exiting a function definition defined @@ -151,7 +157,7 @@ class KernelSourceInformationBuilder ir.TreeNode node, ir.FunctionNode functionNode) { if (functionNode.fileEndOffset != ir.TreeNode.noOffset) { return new PositionSourceInformation( - _getSourceLocation(functionNode, functionNode.fileEndOffset)); + _getSourceLocation(_name, functionNode, functionNode.fileEndOffset)); } return _buildTreeNode(node); } @@ -164,12 +170,12 @@ class KernelSourceInformationBuilder SourceLocation location; if (body != null) { if (body is ir.Block && body.statements.isNotEmpty) { - location = _getSourceLocation(body.statements.first); + location = _getSourceLocation(_name, body.statements.first); } else { - location = _getSourceLocation(body); + location = _getSourceLocation(_name, body); } } else { - location = _getSourceLocation(node); + location = _getSourceLocation(_name, node); } return new PositionSourceInformation(location); } @@ -242,9 +248,9 @@ class KernelSourceInformationBuilder /// Creates source information based on the location of [node]. SourceInformation _buildTreeNode(ir.TreeNode node, - [SourceLocation closingPosition]) { + {SourceLocation closingPosition, String name}) { return new PositionSourceInformation( - _getSourceLocation(node), closingPosition); + _getSourceLocation(name ?? _name, node), closingPosition); } @override @@ -370,7 +376,7 @@ class KernelSourceInformationBuilder SourceInformation buildCall( covariant ir.TreeNode receiver, covariant ir.TreeNode call) { return new PositionSourceInformation( - _getSourceLocation(receiver), _getSourceLocation(call)); + _getSourceLocation(_name, receiver), _getSourceLocation(_name, call)); } @override @@ -409,6 +415,16 @@ class KernelSourceInformationBuilder return _buildFunctionEnd(member); } + @override + SourceInformation buildStub( + FunctionEntity function, CallStructure callStructure) { + MemberDefinition definition = _elementMap.getMemberDefinition(function); + String name = computeKernelElementNameForSourceMaps( + _elementMap, function, callStructure); + ir.Node node = definition.node; + return _buildTreeNode(node, name: name); + } + @override SourceInformation buildGoto(ir.Node node) { return _buildTreeNode(node); diff --git a/pkg/compiler/lib/src/io/multi_information.dart b/pkg/compiler/lib/src/io/multi_information.dart index 84c34214ac7..25c61fe774f 100644 --- a/pkg/compiler/lib/src/io/multi_information.dart +++ b/pkg/compiler/lib/src/io/multi_information.dart @@ -11,6 +11,7 @@ import '../common.dart'; import '../elements/entities.dart'; import '../js/js_source_mapping.dart'; import '../js/js.dart' as js; +import '../universe/call_structure.dart'; import 'code_output.dart' show BufferedCodeOutput; import 'source_information.dart'; @@ -288,6 +289,13 @@ class MultiSourceInformationBuilder implements SourceInformationBuilder { builders.map((b) => b.buildDeclaration(member)).toList()); } + @override + SourceInformation buildStub( + FunctionEntity function, CallStructure callStructure) { + return new MultiSourceInformation( + builders.map((b) => b.buildStub(function, callStructure)).toList()); + } + @override SourceInformation buildGoto(T node) { return new MultiSourceInformation( diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart index 4e1fd6ce5d0..5704c6e4f2f 100644 --- a/pkg/compiler/lib/src/io/position_information.dart +++ b/pkg/compiler/lib/src/io/position_information.dart @@ -9,11 +9,12 @@ library dart2js.source_information.position; import '../common.dart'; import '../elements/elements.dart' - show MemberElement, ResolvedAst, ResolvedAstKind; + show MemberElement, MethodElement, ResolvedAst, ResolvedAstKind; import '../js/js.dart' as js; import '../js/js_debug.dart'; import '../js/js_source_mapping.dart'; import '../tree/tree.dart' show Node, Send; +import '../universe/call_structure.dart'; import 'code_output.dart' show BufferedCodeOutput; import 'source_file.dart'; import 'source_information.dart'; @@ -158,7 +159,8 @@ class PositionSourceInformationBuilder SourceInformation buildDeclaration(MemberElement member) { ResolvedAst resolvedAst = member.resolvedAst; - SourceFile sourceFile = computeSourceFile(member.resolvedAst); + String name = computeElementNameForSourceMaps(resolvedAst.element); + SourceFile sourceFile = computeSourceFile(resolvedAst); if (resolvedAst.kind != ResolvedAstKind.PARSED) { SourceSpan span = resolvedAst.element.sourcePosition; return new PositionSourceInformation( @@ -172,6 +174,20 @@ class PositionSourceInformationBuilder } } + @override + SourceInformation buildStub( + MethodElement function, CallStructure callStructure) { + ResolvedAst resolvedAst = function.resolvedAst; + String name = + computeElementNameForSourceMaps(resolvedAst.element, callStructure); + SourceFile sourceFile = computeSourceFile(resolvedAst); + SourceSpan span = resolvedAst.element.sourcePosition; + assert( + span != null, failedAt(function, "No source position for $function.")); + return new PositionSourceInformation( + new OffsetSourceLocation(sourceFile, span.begin, name)); + } + /// Builds a source information object pointing the start position of [node]. SourceInformation buildBegin(Node node) { return new PositionSourceInformation(new OffsetSourceLocation( diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart index 34a80d77152..ae2216142d3 100644 --- a/pkg/compiler/lib/src/io/source_information.dart +++ b/pkg/compiler/lib/src/io/source_information.dart @@ -16,6 +16,7 @@ import '../elements/elements.dart' import '../elements/entities.dart'; import '../js/js.dart' show JavaScriptNodeSourceInformation; import '../script.dart'; +import '../universe/call_structure.dart'; import 'source_file.dart'; /// Interface for passing source information, for instance for use in source @@ -67,9 +68,14 @@ class SourceInformationBuilder { /// Create a [SourceInformationBuilder] for [member]. SourceInformationBuilder forContext(covariant MemberEntity member) => this; - /// Generate [SourceInformation] the declaration of the [member]. + /// Generate [SourceInformation] for the declaration of the [member]. SourceInformation buildDeclaration(covariant MemberEntity member) => null; + /// Generate [SourceInformation] for the stub of [callStructure] for [member]. + SourceInformation buildStub( + covariant FunctionEntity function, CallStructure callStructure) => + null; + /// Generate [SourceInformation] for the generic [node]. @deprecated SourceInformation buildGeneric(T node) => null; @@ -271,35 +277,41 @@ class OffsetSourceLocation extends AbstractSourceLocation { String toString() => '${super.toString()}:$sourceName'; } -/// Compute the source map name for [element]. -String computeElementNameForSourceMaps(Entity element) { +/// Compute the source map name for [element]. If [callStructure] is non-null +/// it is used to name the parameter stub for [element]. +String computeElementNameForSourceMaps(Entity element, + [CallStructure callStructure]) { if (element is AstElement) { - return _computeAstElementNameForSourceMaps(element); + return _computeAstElementNameForSourceMaps(element, callStructure); } else if (element is ClassEntity) { return element.name; } else if (element is MemberEntity) { + String suffix = computeStubSuffix(callStructure); if (element is ConstructorEntity || element is ConstructorBodyEntity) { String className = element.enclosingClass.name; if (element.name == '') { return className; } - return '$className.${element.name}'; + return '$className.${element.name}$suffix'; } else if (element.enclosingClass != null) { if (element.enclosingClass.isClosure) { - return computeElementNameForSourceMaps(element.enclosingClass); + return computeElementNameForSourceMaps( + element.enclosingClass, callStructure); } - return '${element.enclosingClass.name}.${element.name}'; + return '${element.enclosingClass.name}.${element.name}$suffix'; } else { - return element.name; + return '${element.name}$suffix'; } } // TODO(redemption): Create element names from kernel locals and closures. return element.name; } -String _computeAstElementNameForSourceMaps(AstElement element) { +String _computeAstElementNameForSourceMaps( + AstElement element, CallStructure callStructure) { if (element.isClosure) { - return computeElementNameForSourceMaps(element.enclosingElement); + return computeElementNameForSourceMaps( + element.enclosingElement, callStructure); } else if (element.isClass) { return element.name; } else if (element.isConstructor || element.isGenerativeConstructorBody) { @@ -314,17 +326,36 @@ String _computeAstElementNameForSourceMaps(AstElement element) { if (name == '') { name = ''; } - return '${computeElementNameForSourceMaps(local.executableContext)}.$name'; + String enclosingName = + computeElementNameForSourceMaps(local.executableContext, callStructure); + return '$enclosingName.$name'; } else if (element.enclosingClass != null) { + String suffix = computeStubSuffix(callStructure); if (element.enclosingClass.isClosure) { - return computeElementNameForSourceMaps(element.enclosingClass); + return computeElementNameForSourceMaps( + element.enclosingClass, callStructure); } - return '${element.enclosingClass.name}.${element.name}'; + return '${element.enclosingClass.name}.${element.name}$suffix'; } else { - return element.name; + String suffix = computeStubSuffix(callStructure); + return '${element.name}$suffix'; } } +/// Compute the suffix used for a parameter stub for [callStructure]. +String computeStubSuffix(CallStructure callStructure) { + if (callStructure == null) return ''; + StringBuffer sb = new StringBuffer(); + sb.write(r'[function-entry$'); + sb.write(callStructure.positionalArgumentCount); + if (callStructure.namedArguments.isNotEmpty) { + sb.write(r'$'); + sb.write(callStructure.getOrderedNamedArguments().join(r'$')); + } + sb.write(']'); + return sb.toString(); +} + /// Computes the [SourceFile] for the source code of [resolvedAst]. SourceFile computeSourceFile(ResolvedAst resolvedAst) { SourceFile sourceFile; diff --git a/pkg/compiler/lib/src/io/start_end_information.dart b/pkg/compiler/lib/src/io/start_end_information.dart index d67d6a2a707..099917df6dc 100644 --- a/pkg/compiler/lib/src/io/start_end_information.dart +++ b/pkg/compiler/lib/src/io/start_end_information.dart @@ -12,10 +12,11 @@ import 'package:front_end/src/fasta/scanner.dart' show Token; import '../common.dart'; import '../diagnostics/messages.dart' show MessageTemplate; import '../elements/elements.dart' - show MemberElement, ResolvedAst, ResolvedAstKind; + show MemberElement, MethodElement, ResolvedAst, ResolvedAstKind; import '../js/js.dart' as js; import '../js/js_source_mapping.dart'; import '../tree/tree.dart' show Node, Send; +import '../universe/call_structure.dart'; import 'source_file.dart'; import 'source_information.dart'; @@ -62,8 +63,10 @@ class StartEndSourceInformation extends SourceInformation { // TODO(johnniwinther): Inline this in // [StartEndSourceInformationBuilder.buildDeclaration]. static StartEndSourceInformation _computeSourceInformation( - ResolvedAst resolvedAst) { - String name = computeElementNameForSourceMaps(resolvedAst.element); + ResolvedAst resolvedAst, + [CallStructure callStructure]) { + String name = + computeElementNameForSourceMaps(resolvedAst.element, callStructure); SourceFile sourceFile = computeSourceFile(resolvedAst); int begin; int end; @@ -113,8 +116,9 @@ class StartEndSourceInformationStrategy const StartEndSourceInformationStrategy(); @override - SourceInformationBuilder createBuilderForContext(MemberElement member) { - return new StartEndSourceInformationBuilder(member); + SourceInformationBuilder createBuilderForContext(MemberElement member, + [CallStructure callStructure]) { + return new StartEndSourceInformationBuilder(member, callStructure); } @override @@ -193,15 +197,23 @@ class StartEndSourceInformationBuilder extends SourceInformationBuilder { final SourceFile sourceFile; final String name; - StartEndSourceInformationBuilder(MemberElement member) + StartEndSourceInformationBuilder(MemberElement member, + [CallStructure callStructure]) : sourceFile = computeSourceFile(member.resolvedAst), - name = computeElementNameForSourceMaps(member.resolvedAst.element); + name = computeElementNameForSourceMaps( + member.resolvedAst.element, callStructure); SourceInformation buildDeclaration(MemberElement member) { return StartEndSourceInformation ._computeSourceInformation(member.resolvedAst); } + SourceInformation buildStub( + MethodElement member, CallStructure callStructure) { + return StartEndSourceInformation._computeSourceInformation( + member.resolvedAst, callStructure); + } + SourceLocation sourceFileLocationForToken(Token token) { SourceLocation location = new OffsetSourceLocation(sourceFile, token.charOffset, name); diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart index ecd5f248176..d9cf7614843 100644 --- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart +++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart @@ -207,6 +207,7 @@ class CodeEmitterTask extends CompilerTask { namer, this, closedWorld, + backend.sourceInformationStrategy, compiler.backendStrategy.sorter, typeTestRegistry.rtiNeededClasses, closedWorld.elementEnvironment.mainFunction, diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart index db80fe3db6f..b945d9337de 100644 --- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart +++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart @@ -7,6 +7,7 @@ library dart2js.js_emitter.parameter_stub_generator; import '../constants/values.dart'; import '../elements/entities.dart'; import '../elements/types.dart'; +import '../io/source_information.dart'; import '../js/js.dart' as jsAst; import '../js/js.dart' show js; import '../js_backend/namer.dart' show Namer; @@ -31,9 +32,16 @@ class ParameterStubGenerator { final InterceptorData _interceptorData; final CodegenWorldBuilder _codegenWorldBuilder; final ClosedWorld _closedWorld; + final SourceInformationStrategy _sourceInformationStrategy; - ParameterStubGenerator(this._emitterTask, this._namer, this._nativeData, - this._interceptorData, this._codegenWorldBuilder, this._closedWorld); + ParameterStubGenerator( + this._emitterTask, + this._namer, + this._nativeData, + this._interceptorData, + this._codegenWorldBuilder, + this._closedWorld, + this._sourceInformationStrategy); Emitter get _emitter => _emitterTask.emitter; @@ -59,6 +67,11 @@ class ParameterStubGenerator { ParameterStubMethod generateParameterStub( FunctionEntity member, Selector selector, Selector callSelector) { CallStructure callStructure = selector.callStructure; + SourceInformationBuilder sourceInformationBuilder = + _sourceInformationStrategy.createBuilderForContext(member); + SourceInformation sourceInformation = + sourceInformationBuilder.buildStub(member, callStructure); + ParameterStructure parameterStructure = member.parameterStructure; int positionalArgumentCount = callStructure.positionalArgumentCount; bool needsTypeArguments = @@ -182,7 +195,8 @@ class ParameterStubGenerator { [_emitter.staticFunctionAccess(member), argumentsBuffer]); } - jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]); + jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]) + .withSourceInformation(sourceInformation); jsAst.Name name = member.isStatic ? null : _namer.invocationName(selector); jsAst.Name callName = diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart index 33b9496c55c..8edc01d4bc4 100644 --- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart +++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart @@ -19,6 +19,7 @@ import '../../elements/elements.dart' show ClassElement, FieldElement, LibraryElement, MethodElement; import '../../elements/entities.dart'; import '../../elements/types.dart'; +import '../../io/source_information.dart'; import '../../js/js.dart' as js; import '../../js_backend/backend.dart' show SuperMemberData; import '../../js_backend/backend_usage.dart'; @@ -89,6 +90,7 @@ class ProgramBuilder { final Namer _namer; final CodeEmitterTask _task; final ClosedWorld _closedWorld; + final SourceInformationStrategy _sourceInformationStrategy; /// The [Sorter] used for ordering elements in the generated JavaScript. final Sorter _sorter; @@ -136,6 +138,7 @@ class ProgramBuilder { this._namer, this._task, this._closedWorld, + this._sourceInformationStrategy, this._sorter, Set rtiNeededClasses, this._mainFunction, @@ -976,8 +979,14 @@ class ProgramBuilder { FunctionEntity element, bool canTearOff) { if (!_methodNeedsStubs(element)) return const []; - ParameterStubGenerator generator = new ParameterStubGenerator(_task, _namer, - _nativeData, _interceptorData, _worldBuilder, _closedWorld); + ParameterStubGenerator generator = new ParameterStubGenerator( + _task, + _namer, + _nativeData, + _interceptorData, + _worldBuilder, + _closedWorld, + _sourceInformationStrategy); return generator.generateParameterStubs(element, canTearOff: canTearOff); } diff --git a/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart b/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart index f84ecbef2a6..4a989c25b7c 100644 --- a/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart +++ b/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart @@ -104,7 +104,8 @@ Future testStackTrace(Test test, String config, CompileFunc compile, List afterExceptions: const [], bool useJsMethodNamesOnAbsence: false, String Function(String name) jsNameConverter: identityConverter, - Directory forcedTmpDir: null}) async { + Directory forcedTmpDir: null, + int stackTraceLimit: 10}) async { Expect.isTrue(test.expectationMap.keys.contains(config), "No expectations found for '$config' in ${test.expectationMap.keys}"); @@ -132,6 +133,8 @@ Future testStackTrace(Test test, String config, CompileFunc compile, } print("Running d8 $output"); List d8Arguments = []; + d8Arguments.add('--stack-trace-limit'); + d8Arguments.add('$stackTraceLimit'); d8Arguments.addAll(jsPreambles(input, output)); d8Arguments.add(output); ProcessResult runResult = Process.runSync(d8executable, d8Arguments); diff --git a/tests/compiler/dart2js/sourcemaps/helpers/output_structure.dart b/tests/compiler/dart2js/sourcemaps/helpers/output_structure.dart index 9f0bccbe9a5..f12212a6bac 100644 --- a/tests/compiler/dart2js/sourcemaps/helpers/output_structure.dart +++ b/tests/compiler/dart2js/sourcemaps/helpers/output_structure.dart @@ -648,7 +648,9 @@ class CodeLocation { final String name; final int offset; - CodeLocation(this.uri, this.name, this.offset); + CodeLocation(this.uri, this.name, this.offset) { + assert(uri != null); + } String toString() => '$uri:$name:$offset'; diff --git a/tests/compiler/dart2js/sourcemaps/helpers/source_map_validator_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/source_map_validator_helper.dart index 23aede27a8c..75c211b6981 100644 --- a/tests/compiler/dart2js/sourcemaps/helpers/source_map_validator_helper.dart +++ b/tests/compiler/dart2js/sourcemaps/helpers/source_map_validator_helper.dart @@ -180,6 +180,12 @@ checkNames( if (interval != null && interval.contains(sourcePosition)) { AstElement innerElement = findInnermost(element); String expectedName = computeElementNameForSourceMaps(innerElement); + int stubIndex = name.indexOf('[function-entry'); + if (stubIndex != -1) { + Expect.isTrue(innerElement is FunctionElement, + "Unexpected element $innerElement for stub '$name'."); + name = name.substring(0, stubIndex); + } if (name != expectedName) { // For the code // (){}(); diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/parameters.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/parameters.dart new file mode 100644 index 00000000000..f9a6d06558f --- /dev/null +++ b/tests/compiler/dart2js/sourcemaps/stacktrace/parameters.dart @@ -0,0 +1,76 @@ +// Copyright (c) 2018, 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. + +import 'package:meta/dart2js.dart'; + +main() { + var c = new Class(); + c. /*1:main*/ instancePositional1(0); +} + +class Class { + @noInline + /*2:Class.instancePositional1[function-entry$1]*/ instancePositional1(a, + [b = 42, c = 87]) { + print('instancePositional1($a,$b,$c)'); + /*3:Class.instancePositional1*/ instancePositional2(1, 2); + } + + @noInline + /*4:Class.instancePositional2[function-entry$2]*/ instancePositional2(a, + [b = 42, c = 87]) { + print('instancePositional2($a,$b,$c)'); + /*5:Class.instancePositional2*/ instancePositional3(3, 4, 5); + } + + @noInline + instancePositional3(a, [b = 42, c = 87]) { + print('instancePositional3($a,$b,$c)'); + /*6:Class.instancePositional3*/ instanceNamed1(0); + } + + @noInline + /*7:Class.instanceNamed1[function-entry$1]*/ instanceNamed1(a, + {b: 42, c: 87, d: 735}) { + print('instanceNamed1($a,b:$b,c:$c,d:$d)'); + /*8:Class.instanceNamed1*/ instanceNamed2(1, b: 2); + } + + @noInline + /*9:Class.instanceNamed2[function-entry$1$b]*/ instanceNamed2(a, + {b: 42, c: 87, d: 735}) { + print('instanceNamed2($a,b:$b,c:$c,d:$d)'); + /*10:Class.instanceNamed2*/ instanceNamed3(3, c: 123); + } + + @noInline + /*11:Class.instanceNamed3[function-entry$1$c]*/ instanceNamed3(a, + {b: 42, c: 87, d: 735}) { + print('instanceNamed3($a,b:$b,c:$c,d:$d)'); + /*12:Class.instanceNamed3*/ instanceNamed4(4, c: 45, b: 76); + } + + @noInline + /*13:Class.instanceNamed4[function-entry$1$b$c]*/ instanceNamed4(a, + {b: 42, c: 87, d: 735}) { + print('instanceNamed4($a,b:$b,c:$c,d:$d)'); + /*14:Class.instanceNamed4*/ instanceNamed5(5, c: 6, b: 7, d: 8); + } + + @noInline + instanceNamed5(a, {b: 42, c: 87, d: 735}) { + print('instanceNamed5($a,b:$b,c:$c,d:$d)'); + /*18:Class.instanceNamed5[function-entry$0].local*/ local([e = 42]) { + print('instanceNamed5.local($e)'); + /*19:Class.instanceNamed5.local*/ throw '>ExceptionMarker<'; + } + + var anonymous = /*16:Class.instanceNamed5[function-entry$0].*/ ( + {f: 87}) { + print('instanceNamed5.*/ local(); + }; + anonymous. /*15:Class.instanceNamed5*/ call(); + } +} diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart index 12fd74875a9..76ed3de2884 100644 --- a/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart +++ b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart @@ -92,7 +92,11 @@ Future runTest(Test test, String config, jsPreambles: (input, output) => ['sdk/lib/_internal/js_runtime/lib/preambles/d8.js'], afterExceptions: testAfterExceptions, - beforeExceptions: beforeExceptions); + beforeExceptions: beforeExceptions, + verbose: verbose, + printJs: printJs, + writeJs: writeJs, + stackTraceLimit: 100); } /// Lines allowed before the intended stack trace. Typically from helper @@ -119,4 +123,13 @@ const List afterExceptions = const [ const LineException('_Future._propagateToListeners', 'future_impl.dart'), const LineException( '_Future._addListener.', 'future_impl.dart'), + const LineException('_microtaskLoop', 'schedule_microtask.dart'), + const LineException('_startMicrotaskLoop', 'schedule_microtask.dart'), + const LineException('_AsyncRun._scheduleImmediateJsOverride.internalCallback', + 'async_patch.dart'), + const LineException('invokeClosure.', 'js_helper.dart'), + const LineException('_IsolateContext.eval', 'isolate_helper.dart'), + const LineException('_callInIsolate', 'isolate_helper.dart'), + const LineException('invokeClosure', 'js_helper.dart'), + const LineException('convertDartClosureToJS', 'js_helper.dart'), ]; diff --git a/tests/compiler/dart2js/sourcemaps/tools/diff_view.dart b/tests/compiler/dart2js/sourcemaps/tools/diff_view.dart index 2a1a1f1a770..194dfed9986 100644 --- a/tests/compiler/dart2js/sourcemaps/tools/diff_view.dart +++ b/tests/compiler/dart2js/sourcemaps/tools/diff_view.dart @@ -598,8 +598,9 @@ Source mapped Dart code
'''); - new File(out).writeAsStringSync(sb.toString()); - print('Diff generated in $out'); + File file = new File(out); + file.writeAsStringSync(sb.toString()); + print('Diff generated in ${file.absolute.uri}'); } class CodeLinesResult { @@ -729,9 +730,11 @@ Future computeCodeLines( locations = []; } List codeLocations = locations + .where((l) => l.sourceUri != null) .map((l) => new CodeLocation(l.sourceUri, l.sourceName, l.offset)) .toList(); List codeSourceList = locations + .where((l) => l.sourceUri != null) .map(codeSources.sourceLocationToCodeSource) .where((c) => c != null) .toList(); diff --git a/tests/compiler/dart2js/sourcemaps/tools/source_mapping_tester.dart b/tests/compiler/dart2js/sourcemaps/tools/source_mapping_tester.dart index a7e96458ab1..f1c2423d026 100644 --- a/tests/compiler/dart2js/sourcemaps/tools/source_mapping_tester.dart +++ b/tests/compiler/dart2js/sourcemaps/tools/source_mapping_tester.dart @@ -158,7 +158,7 @@ Future runTests( {bool verbose: true}) async { SourceMapProcessor processor = new SourceMapProcessor(uri); SourceMaps sourceMaps = await processor.process( - ['--csp', '--disable-inlining']..addAll(options), + [Flags.useContentSecurityPolicy, Flags.disableInlining]..addAll(options), verbose: verbose); TestResult result = new TestResult(config, filename, processor); for (SourceMapInfo info in sourceMaps.elementSourceMapInfos.values) {