[ddc] Fix capture issue with temp names within async scopes.

`needsCapture` will ensure that any variables used within an async scope get included in the 'asyncScope' object that's created for that scope.

The variables used to lower Dart late variables in particular get emitted separately. But they can still be used across async scopes so they need the special capture logic as well.

Bug: https://github.com/dart-lang/sdk/issues/60748
Change-Id: I2486fce41f88f186fd799029c2cc59635f7ad8f5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/429780
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Commit-Queue: Nate Biggs <natebiggs@google.com>
This commit is contained in:
Nate Biggs
2025-05-21 17:49:22 -07:00
committed by Commit Queue
parent 7a4c651eb3
commit e688981385
3 changed files with 37 additions and 2 deletions
@@ -4918,7 +4918,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
if (_isTemporaryVariable(v)) {
var name = _debuggerFriendlyTemporaryVariableName(v);
name ??= 't\$${_tempVariables.length}';
return _tempVariables.putIfAbsent(v, () => _emitScopedId(name!));
return _tempVariables.putIfAbsent(
v, () => _emitScopedId(name!, needsCapture: true));
}
var name = v.name!;
if (isLateLoweredLocal(v)) {
@@ -5403,7 +5403,8 @@ class LibraryCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
if (_isTemporaryVariable(v)) {
var name = _debuggerFriendlyTemporaryVariableName(v);
name ??= 't\$${_tempVariables.length}';
return _tempVariables.putIfAbsent(v, () => _emitScopedId(name!));
return _tempVariables.putIfAbsent(
v, () => _emitScopedId(name!, needsCapture: true));
}
var name = v.name!;
if (isLateLoweredLocal(v)) {
+33
View File
@@ -0,0 +1,33 @@
// Copyright (c) 2025, 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:expect/async_helper.dart';
import 'package:expect/expect.dart';
Future<void> main() async {
asyncStart();
List<Object Function()> callbacks = [];
List<int> expectedHashCodes = [];
void save(Object o) {
expectedHashCodes.add(o.hashCode);
}
void check(Object o, int i) {
Expect.equals(expectedHashCodes[i], o.hashCode);
}
for (int i = 0; i < 3; i++) {
late Object o = Object();
o;
Object record() => o;
callbacks.add(record);
save(record());
}
for (int i = callbacks.length - 1; i >= 0; i--) {
check(callbacks[i](), i);
}
asyncEnd();
}