diff --git a/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart b/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart index 7799b9ed6e1..8c545e2b480 100644 --- a/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart +++ b/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart @@ -436,12 +436,39 @@ class LineException { TargetEntry findEnclosingFunction( String sources, SourceFile file, int start, SingleMapping mapping) { if (sources == null) return null; - int index = sources.lastIndexOf(': function(', start); - if (index < 0) return null; - index += 2; - var line = file.getLine(index); - var lineEntry = _findLineInternal(mapping, line); - return _findColumn(line, file.getColumn(index), lineEntry); + var index = start; + while (true) { + index = nextDeclarationCandidate(sources, index); + if (index < 0) return null; + var line = file.getLine(index); + var lineEntry = _findLineInternal(mapping, line); + var result = _findColumn(line, file.getColumn(index), lineEntry); + if (result?.column == file.getColumn(index)) return result; + index--; + } +} + +/// Returns the index of a candidate location of a enclosing function +/// declaration. We try to find the beginning of a `function` keyword or the +/// `(` of an ES6 method definition, but the search contains some false +/// positives. To rule out false positives, [findEnclosingFunction] +/// validates that the returned location contains a source-map entry, searching +/// for another candidate if not. +int nextDeclarationCandidate(String sources, int start) { + var indexForFunctionKeyword = sources.lastIndexOf('function', start); + // We attempt to identify potential method definitions by looking for any '(' + // that precedes a '{'. This method will fail if 1) Dart2JS starts emitting + // functions with initializers or 2) sourcemap boundaries appear at '(' for + // non-method-definition constructs. + var indexForMethodDefinition = sources.lastIndexOf('{', start); + if (indexForFunctionKeyword > indexForMethodDefinition || + indexForFunctionKeyword < 0) { + return indexForFunctionKeyword; + } + indexForMethodDefinition = sources.lastIndexOf('(', indexForMethodDefinition); + return indexForFunctionKeyword > indexForMethodDefinition + ? indexForFunctionKeyword + : indexForMethodDefinition; } Map> _loadInlinedFrameData(