CodeVetter · Repo Unpack · Behavior traces
flutter/flutter
Three end-to-end flows were traced. (1) CLI bootstrap: bin/flutter -> shared.sh -> Dart SDK fetch + snapshot compile -> flutter_tools.dart -> executable.main -> runner.run -> FlutterCommandRunner -> FlutterCommand.runCommand. (2) `flutter run` hot path: RunCommand picks HotRunner -> FlutterDevice.create (ResidentCompiler + shader compiler) -> device launch -> attach to VM service -> keystroke-triggered _reloadSources -> DevFS push -> VM reloadSources -> reassemble. (3) On-device app start: embedder creates Shell/Engine -> RuntimeController.LaunchRootIsolate -> dart:ui _runMain -> user main() -> runApp -> WidgetsFlutterBinding frame pipeline -> rasterized by the engine's Animator/Rasterizer.
- Bootstrap order (posix): bin/flutter -> follow_links -> source bin/internal/shared.sh -> shared::execute -> update_engine_version.sh -> staleness check on flutter_tools.stamp -> _wait_for_lock -> update_dart_sdk.sh -> pub_upgrade_with_retry (10 tries) -> `dart --snapshot-kind=app-jit` compile -> exec dart flutter_tools.snapshot "$@".
- Guard rails in bootstrap: shared::execute refuses to run without git on PATH and without $FLUTTER_ROOT/.git (must be a real clone), warns when EUID==0 outside Docker/CI, and sources bin/internal/bootstrap.sh first if present.
- Tool dispatch order: bin/flutter_tools.dart main -> executable.main (sets Cache.flutterRoot via defaultFlutterRoot) -> runner.run -> runInContext -> ToolDependencies.bootstrap -> FlutterCommandRunner -> commands().forEach(runner.addCommand) -> runner.run(args) -> FlutterCommand.verifyThenRun -> runCommand.
- Error exit contract: UsageException -> exit 64; ToolExit -> its exitCode or 1; ProcessExit(immediate) -> direct exit; missing-git ProcessException -> friendly message + exit 1; anything else -> crash report path with exit 1.
- `flutter run` flow: RunCommand.runCommand computes BuildInfo via getBuildInfo(), picks hotMode = shouldUseHotMode(buildInfo), constructs HotRunner(flutterDevices, debuggingOptions...) or ColdRunner, then ResidentRunner.run() launches the app on each Device and attaches to the VM service (vmservice.dart).
- Hot reload flow: user presses r -> HotRunner.reload -> _reloadSources -> projectFileInvalidator finds changed sources -> ResidentCompiler.recompile -> devFS update -> _reloadSourcesService issues VM-service reloadSources -> _reassembleHelper invokes reassemble in the app -> DeviceReloadReport aggregated per view; timings tracked via named Stopwatches (reloadSources:reload, :vm, :reassemble).
- Engine app launch flow: the embedder (embedder.h API or platform embedder like FlutterEngine.java) creates a Shell, which constructs Engine with a RuntimeController; Engine::Run/LaunchRootIsolate starts the Dart isolate, which enters dart:ui's _runMain (hooks.dart) -> user's main() -> runApp -> WidgetsFlutterBinding.ensureInitialized + scheduleAttachRootWidget + scheduleWarmUpFrame.
- Frame pipeline order (documented in binding.dart): transient callbacks -> handleBeginFrame (animations, transient frame callbacks) -> microtasks -> handleDrawFrame -> build/layout/paint -> compositing -> semantics -> finalization; super.drawFrame() ordering keeps the layer stack consistent.
- `flutter test` flow on CI: LUCI target -> flutter_drone recipe -> `dart dev/bots/test.dart` -> selectShard() picks the shard runner (e.g. frameworkTestsRunner, _runToolTests) -> suite runner invokes `flutter test` with flutterTestArgs; --local-engine flags are exported as FLUTTER_LOCAL_ENGINE env vars for subprocesses.
- First-run persistence flow: when artifacts are missing, commands call Cache.updateAll -> downloads zip from storage.googleapis.com -> unzip into bin/cache/artifacts -> stamp files written; failed downloads leave no partial artifacts because downloads go through temp files (cache.dart Net/HttpClient path).