debugFindConstructingStackFrame static method
Finds the first non-constructor frame in the stack trace.
stackTrace defaults to StackTrace.current.
Implementation
@visibleForTesting
static String? debugFindConstructingStackFrame([StackTrace? stackTrace]) {
String? stackFrame;
assert(() {
if (debugAddStackTraceInObserverName) {
final stackTraceString = (stackTrace ?? StackTrace.current).toString();
final frames = LineSplitter.split(stackTraceString).toList();
final rawStackFrame = frames
.asMap()
.entries
// We are skipping frames representing:
// 1. The anonymous function in the assert
// 2. The debugFindConstructingStackFrame method
// 3. The constructor invoking debugFindConstructingStackFrame
//
// The 4th frame is either user source (which is what we want), or
// an Observer subclass' constructor (which we skip past with the
// regex)
.skip(3)
// Search for the first non-constructor frame
.where((entry) {
if (_constructorStackFramePattern.hasMatch(entry.value)) {
return false;
}
// Wasm emits a constructor entry immediately after its
// initializer frame. Both belong to construction, not the caller.
return !(entry.value.contains(':wasm-function[') &&
frames[entry.key - 1].contains('(initializer)'));
})
.map((entry) => entry.value)
.firstWhere((_) => true, orElse: () => '');
final stackFrameCore =
_stackFrameCleanUpPattern.firstMatch(rawStackFrame)?.group(1);
final cleanedStackFrame = stackFrameCore == null
? null
: 'Observer constructed from: $stackFrameCore';
stackFrame = cleanedStackFrame;
}
return true;
}());
return stackFrame;
}