Version 2.17.0-282.0.dev
Merge commit '94bc01240cfcd47d645f9e8564561afb5b6b74ee' into 'dev'
diff --git a/DEPS b/DEPS
index db1a550..3c0b60d 100644
--- a/DEPS
+++ b/DEPS
@@ -153,7 +153,7 @@
"source_map_stack_trace_rev": "8eabd96b1811e30a11d3c54c9b4afae4fb72e98f",
"source_maps-0.9.4_rev": "38524",
"source_maps_rev": "6499ee3adac8d469e2953e2e8ba4bdb4c2fbef90",
- "source_span_rev": "dc189b455d823e2919667f6c5dcb41ab7483bce0",
+ "source_span_rev": "8ae724c3e67f5afaacead44e93ff145bfb8775c7",
"sse_rev": "9084339389eb441d0c0518cddac211a097e78657",
"stack_trace_rev": "5220580872625ddee41e9ca9a5f3364789b2f0f6",
"stream_channel_rev": "3fa3e40c75c210d617b8b943b9b8f580e9866a89",
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index 8ceaad2..fd5c2d1 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -110,23 +110,30 @@
if (fileExtension == '.dart' && !unit.isError) {
final result = unit.result;
var performanceOperation = OperationPerformanceImpl('<root>');
- completionPerformance = CompletionPerformance(
- operation: performanceOperation,
- path: result.path,
- content: result.content,
- offset: offset,
- );
- server.performanceStats.completion.add(completionPerformance);
- serverResultsFuture = _getServerDartItems(
- clientCapabilities,
- unit.result,
- completionPerformance,
- performanceOperation,
- offset,
- triggerCharacter,
- token,
- maxResults: maxResults,
+ serverResultsFuture = await performanceOperation.runAsync(
+ 'request',
+ (performance) async {
+ final thisPerformance = CompletionPerformance(
+ operation: performance,
+ path: result.path,
+ content: result.content,
+ offset: offset,
+ );
+ completionPerformance = thisPerformance;
+ server.performanceStats.completion.add(thisPerformance);
+
+ return _getServerDartItems(
+ clientCapabilities,
+ unit.result,
+ thisPerformance,
+ performanceOperation,
+ offset,
+ triggerCharacter,
+ token,
+ maxResults: maxResults,
+ );
+ },
);
} else if (fileExtension == '.yaml') {
YamlCompletionGenerator? generator;
@@ -285,7 +292,7 @@
LspClientCapabilities capabilities,
ResolvedUnitResult unit,
CompletionPerformance completionPerformance,
- OperationPerformanceImpl operationPerformance,
+ OperationPerformanceImpl performance,
int offset,
String? triggerCharacter,
CancellationToken token, {
@@ -294,245 +301,239 @@
final useSuggestionSets =
suggestFromUnimportedLibraries && capabilities.applyEdit;
- return await operationPerformance.runAsync(
- 'request',
- (performance) async {
- final completionRequest = DartCompletionRequest.forResolvedUnit(
- resolvedUnit: unit,
- offset: offset,
- dartdocDirectiveInfo: server.getDartdocDirectiveInfoFor(unit),
- completionPreference: CompletionPreference.replace,
+ final completionRequest = DartCompletionRequest.forResolvedUnit(
+ resolvedUnit: unit,
+ offset: offset,
+ dartdocDirectiveInfo: server.getDartdocDirectiveInfoFor(unit),
+ completionPreference: CompletionPreference.replace,
+ );
+ final target = completionRequest.target;
+
+ if (triggerCharacter != null) {
+ if (!_triggerCharacterValid(offset, triggerCharacter, target)) {
+ return success(CompletionList(isIncomplete: false, items: []));
+ }
+ }
+
+ Set<ElementKind>? includedElementKinds;
+ Set<String>? includedElementNames;
+ List<IncludedSuggestionRelevanceTag>? includedSuggestionRelevanceTags;
+ if (useSuggestionSets) {
+ includedElementKinds = <ElementKind>{};
+ includedElementNames = <String>{};
+ includedSuggestionRelevanceTags = <IncludedSuggestionRelevanceTag>[];
+ }
+
+ try {
+ var contributor = DartCompletionManager(
+ budget: CompletionBudget(CompletionBudget.defaultDuration),
+ includedElementKinds: includedElementKinds,
+ includedElementNames: includedElementNames,
+ includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
+ );
+
+ final serverSuggestions2 = await contributor.computeSuggestions(
+ completionRequest,
+ performance,
+ );
+
+ final serverSuggestions = serverSuggestions2.map((serverSuggestion) {
+ return serverSuggestion.build();
+ }).toList();
+
+ final insertLength = _computeInsertLength(
+ offset,
+ completionRequest.replacementOffset,
+ completionRequest.replacementLength,
+ );
+
+ if (token.isCancellationRequested) {
+ return cancelled();
+ }
+
+ /// completeFunctionCalls should be suppressed if the target is an
+ /// invocation that already has an argument list, otherwise we would
+ /// insert dupes.
+ final completeFunctionCalls = _hasExistingArgList(target.entity)
+ ? false
+ : server.clientConfiguration.global.completeFunctionCalls;
+
+ final results = serverSuggestions.map(
+ (item) {
+ var itemReplacementOffset =
+ item.replacementOffset ?? completionRequest.replacementOffset;
+ var itemReplacementLength =
+ item.replacementLength ?? completionRequest.replacementLength;
+ var itemInsertLength = insertLength;
+
+ // Recompute the insert length if it may be affected by the above.
+ if (item.replacementOffset != null ||
+ item.replacementLength != null) {
+ itemInsertLength = _computeInsertLength(
+ offset, itemReplacementOffset, itemInsertLength);
+ }
+
+ // Convert to LSP ranges using the LineInfo.
+ Range? replacementRange = toRange(
+ unit.lineInfo, itemReplacementOffset, itemReplacementLength);
+ Range? insertionRange =
+ toRange(unit.lineInfo, itemReplacementOffset, itemInsertLength);
+
+ return toCompletionItem(
+ capabilities,
+ unit.lineInfo,
+ item,
+ replacementRange: replacementRange,
+ insertionRange: insertionRange,
+ // TODO(dantup): Move commit characters to the main response
+ // and remove from each individual item (to reduce payload size)
+ // once the following change ships (and the Dart VS Code
+ // extension is updated to use it).
+ // https://github.com/microsoft/vscode-languageserver-node/issues/673
+ includeCommitCharacters:
+ server.clientConfiguration.global.previewCommitCharacters,
+ completeFunctionCalls: completeFunctionCalls,
+ );
+ },
+ ).toList();
+
+ // Now compute items in suggestion sets.
+ var includedSuggestionSets = <IncludedSuggestionSet>[];
+ final declarationsTracker = server.declarationsTracker;
+ if (declarationsTracker != null &&
+ includedElementKinds != null &&
+ includedElementNames != null &&
+ includedSuggestionRelevanceTags != null) {
+ computeIncludedSetList(
+ declarationsTracker,
+ completionRequest,
+ includedSuggestionSets,
+ includedElementNames,
);
- final target = completionRequest.target;
- if (triggerCharacter != null) {
- if (!_triggerCharacterValid(offset, triggerCharacter, target)) {
- return success(CompletionList(isIncomplete: false, items: []));
- }
- }
+ // Build a fast lookup for imported symbols so that we can filter out
+ // duplicates.
+ final alreadyImportedSymbols = _buildLookupOfImportedSymbols(unit);
- Set<ElementKind>? includedElementKinds;
- Set<String>? includedElementNames;
- List<IncludedSuggestionRelevanceTag>? includedSuggestionRelevanceTags;
- if (useSuggestionSets) {
- includedElementKinds = <ElementKind>{};
- includedElementNames = <String>{};
- includedSuggestionRelevanceTags = <IncludedSuggestionRelevanceTag>[];
- }
-
- try {
- var contributor = DartCompletionManager(
- budget: CompletionBudget(CompletionBudget.defaultDuration),
- includedElementKinds: includedElementKinds,
- includedElementNames: includedElementNames,
- includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
- );
-
- final serverSuggestions2 = await contributor.computeSuggestions(
- completionRequest,
- performance,
- );
-
- final serverSuggestions = serverSuggestions2.map((serverSuggestion) {
- return serverSuggestion.build();
- }).toList();
-
- final insertLength = _computeInsertLength(
- offset,
- completionRequest.replacementOffset,
- completionRequest.replacementLength,
- );
-
- if (token.isCancellationRequested) {
- return cancelled();
+ includedSuggestionSets.forEach((includedSet) {
+ final library = declarationsTracker.getLibrary(includedSet.id);
+ if (library == null) {
+ return;
}
- /// completeFunctionCalls should be suppressed if the target is an
- /// invocation that already has an argument list, otherwise we would
- /// insert dupes.
- final completeFunctionCalls = _hasExistingArgList(target.entity)
- ? false
- : server.clientConfiguration.global.completeFunctionCalls;
+ // Make a fast lookup for tag relevance.
+ final tagBoosts = <String, int>{};
+ includedSuggestionRelevanceTags!
+ .forEach((t) => tagBoosts[t.tag] = t.relevanceBoost);
- final results = serverSuggestions.map(
- (item) {
- var itemReplacementOffset =
- item.replacementOffset ?? completionRequest.replacementOffset;
- var itemReplacementLength =
- item.replacementLength ?? completionRequest.replacementLength;
- var itemInsertLength = insertLength;
+ // Only specific types of child declarations should be included.
+ // This list matches what's in _protocolAvailableSuggestion in
+ // the DAS implementation.
+ bool shouldIncludeChild(Declaration child) =>
+ child.kind == DeclarationKind.CONSTRUCTOR ||
+ child.kind == DeclarationKind.ENUM_CONSTANT ||
+ (child.kind == DeclarationKind.GETTER && child.isStatic) ||
+ (child.kind == DeclarationKind.FIELD && child.isStatic);
- // Recompute the insert length if it may be affected by the above.
- if (item.replacementOffset != null ||
- item.replacementLength != null) {
- itemInsertLength = _computeInsertLength(
- offset, itemReplacementOffset, itemInsertLength);
- }
-
- // Convert to LSP ranges using the LineInfo.
- Range? replacementRange = toRange(
- unit.lineInfo, itemReplacementOffset, itemReplacementLength);
- Range? insertionRange = toRange(
- unit.lineInfo, itemReplacementOffset, itemInsertLength);
-
- return toCompletionItem(
- capabilities,
- unit.lineInfo,
- item,
- replacementRange: replacementRange,
- insertionRange: insertionRange,
- // TODO(dantup): Move commit characters to the main response
- // and remove from each individual item (to reduce payload size)
- // once the following change ships (and the Dart VS Code
- // extension is updated to use it).
- // https://github.com/microsoft/vscode-languageserver-node/issues/673
- includeCommitCharacters:
- server.clientConfiguration.global.previewCommitCharacters,
- completeFunctionCalls: completeFunctionCalls,
- );
- },
- ).toList();
-
- // Now compute items in suggestion sets.
- var includedSuggestionSets = <IncludedSuggestionSet>[];
- final declarationsTracker = server.declarationsTracker;
- if (declarationsTracker != null &&
- includedElementKinds != null &&
- includedElementNames != null &&
- includedSuggestionRelevanceTags != null) {
- computeIncludedSetList(
- declarationsTracker,
- completionRequest,
- includedSuggestionSets,
- includedElementNames,
- );
-
- // Build a fast lookup for imported symbols so that we can filter out
- // duplicates.
- final alreadyImportedSymbols = _buildLookupOfImportedSymbols(unit);
-
- includedSuggestionSets.forEach((includedSet) {
- final library = declarationsTracker.getLibrary(includedSet.id);
- if (library == null) {
- return;
- }
-
- // Make a fast lookup for tag relevance.
- final tagBoosts = <String, int>{};
- includedSuggestionRelevanceTags!
- .forEach((t) => tagBoosts[t.tag] = t.relevanceBoost);
-
- // Only specific types of child declarations should be included.
- // This list matches what's in _protocolAvailableSuggestion in
- // the DAS implementation.
- bool shouldIncludeChild(Declaration child) =>
- child.kind == DeclarationKind.CONSTRUCTOR ||
- child.kind == DeclarationKind.ENUM_CONSTANT ||
- (child.kind == DeclarationKind.GETTER && child.isStatic) ||
- (child.kind == DeclarationKind.FIELD && child.isStatic);
-
- // Collect declarations and their children.
- final allDeclarations = library.declarations
- .followedBy(library.declarations.expand(
- (decl) => decl.children.where(shouldIncludeChild)))
- .toList();
-
- final setResults = allDeclarations
- // Filter to only the kinds we should return.
- .where((item) => includedElementKinds!
- .contains(protocolElementKind(item.kind)))
- .where((item) {
- // Check existing imports to ensure we don't already import
- // this element (this exact element from its declaring
- // library, not just something with the same name). If we do
- // we'll want to skip it.
- final declaringUri =
- item.parent?.locationLibraryUri ?? item.locationLibraryUri!;
-
- // For enums and named constructors, only the parent enum/class is in
- // the list of imported symbols so we use the parents name.
- final nameKey = item.kind == DeclarationKind.ENUM_CONSTANT ||
- item.kind == DeclarationKind.CONSTRUCTOR
- ? item.parent!.name
- : item.name;
- final key = _createImportedSymbolKey(nameKey, declaringUri);
- final importingUris = alreadyImportedSymbols[key];
-
- // Keep it only if:
- // - no existing imports include it
- // (in which case all libraries will be offered as
- // auto-imports)
- // - this is the first imported URI that includes it
- // (we don't want to repeat it for each imported library that
- // includes it)
- return importingUris == null ||
- importingUris.first == '${library.uri}';
- }).map((item) => declarationToCompletionItem(
- capabilities,
- unit.path,
- offset,
- includedSet,
- library,
- tagBoosts,
- unit.lineInfo,
- item,
- completionRequest.replacementOffset,
- insertLength,
- completionRequest.replacementLength,
- // TODO(dantup): Move commit characters to the main response
- // and remove from each individual item (to reduce payload size)
- // once the following change ships (and the Dart VS Code
- // extension is updated to use it).
- // https://github.com/microsoft/vscode-languageserver-node/issues/673
- includeCommitCharacters: server
- .clientConfiguration.global.previewCommitCharacters,
- completeFunctionCalls: completeFunctionCalls,
- ));
- results.addAll(setResults);
- });
- }
-
- // Add in any snippets.
- final snippetsEnabled =
- server.clientConfiguration.forResource(unit.path).enableSnippets;
- // We can only produce edits with edit builders for files inside
- // the root, so skip snippets entirely if not.
- final isEditableFile =
- unit.session.analysisContext.contextRoot.isAnalyzed(unit.path);
- if (capabilities.completionSnippets &&
- snippetsEnabled &&
- isEditableFile) {
- results.addAll(await _getDartSnippetItems(
- clientCapabilities: capabilities,
- unit: unit,
- offset: offset,
- lineInfo: unit.lineInfo,
- ));
- }
-
- // Perform fuzzy matching based on the identifier in front of the caret to
- // reduce the size of the payload.
- final fuzzyPattern = completionRequest.targetPrefix;
- final fuzzyMatcher =
- FuzzyMatcher(fuzzyPattern, matchStyle: MatchStyle.TEXT);
-
- final matchingResults = results
- .where((e) => fuzzyMatcher.score(e.filterText ?? e.label) > 0)
+ // Collect declarations and their children.
+ final allDeclarations = library.declarations
+ .followedBy(library.declarations
+ .expand((decl) => decl.children.where(shouldIncludeChild)))
.toList();
- // Transmitted count will be set after combining with plugins.
- completionPerformance.computedSuggestionCount =
- matchingResults.length;
+ final setResults = allDeclarations
+ // Filter to only the kinds we should return.
+ .where((item) => includedElementKinds!
+ .contains(protocolElementKind(item.kind)))
+ .where((item) {
+ // Check existing imports to ensure we don't already import
+ // this element (this exact element from its declaring
+ // library, not just something with the same name). If we do
+ // we'll want to skip it.
+ final declaringUri =
+ item.parent?.locationLibraryUri ?? item.locationLibraryUri!;
- return success(
- CompletionList(isIncomplete: false, items: matchingResults));
- } on AbortCompletion {
- return success(CompletionList(isIncomplete: false, items: []));
- } on InconsistentAnalysisException {
- return success(CompletionList(isIncomplete: false, items: []));
- }
- },
- );
+ // For enums and named constructors, only the parent enum/class is in
+ // the list of imported symbols so we use the parents name.
+ final nameKey = item.kind == DeclarationKind.ENUM_CONSTANT ||
+ item.kind == DeclarationKind.CONSTRUCTOR
+ ? item.parent!.name
+ : item.name;
+ final key = _createImportedSymbolKey(nameKey, declaringUri);
+ final importingUris = alreadyImportedSymbols[key];
+
+ // Keep it only if:
+ // - no existing imports include it
+ // (in which case all libraries will be offered as
+ // auto-imports)
+ // - this is the first imported URI that includes it
+ // (we don't want to repeat it for each imported library that
+ // includes it)
+ return importingUris == null ||
+ importingUris.first == '${library.uri}';
+ }).map((item) => declarationToCompletionItem(
+ capabilities,
+ unit.path,
+ offset,
+ includedSet,
+ library,
+ tagBoosts,
+ unit.lineInfo,
+ item,
+ completionRequest.replacementOffset,
+ insertLength,
+ completionRequest.replacementLength,
+ // TODO(dantup): Move commit characters to the main response
+ // and remove from each individual item (to reduce payload size)
+ // once the following change ships (and the Dart VS Code
+ // extension is updated to use it).
+ // https://github.com/microsoft/vscode-languageserver-node/issues/673
+ includeCommitCharacters: server
+ .clientConfiguration.global.previewCommitCharacters,
+ completeFunctionCalls: completeFunctionCalls,
+ ));
+ results.addAll(setResults);
+ });
+ }
+
+ // Add in any snippets.
+ final snippetsEnabled =
+ server.clientConfiguration.forResource(unit.path).enableSnippets;
+ // We can only produce edits with edit builders for files inside
+ // the root, so skip snippets entirely if not.
+ final isEditableFile =
+ unit.session.analysisContext.contextRoot.isAnalyzed(unit.path);
+ if (capabilities.completionSnippets &&
+ snippetsEnabled &&
+ isEditableFile) {
+ results.addAll(await _getDartSnippetItems(
+ clientCapabilities: capabilities,
+ unit: unit,
+ offset: offset,
+ lineInfo: unit.lineInfo,
+ ));
+ }
+
+ // Perform fuzzy matching based on the identifier in front of the caret to
+ // reduce the size of the payload.
+ final fuzzyPattern = completionRequest.targetPrefix;
+ final fuzzyMatcher =
+ FuzzyMatcher(fuzzyPattern, matchStyle: MatchStyle.TEXT);
+
+ final matchingResults = results
+ .where((e) => fuzzyMatcher.score(e.filterText ?? e.label) > 0)
+ .toList();
+
+ // Transmitted count will be set after combining with plugins.
+ completionPerformance.computedSuggestionCount = matchingResults.length;
+
+ return success(
+ CompletionList(isIncomplete: false, items: matchingResults));
+ } on AbortCompletion {
+ return success(CompletionList(isIncomplete: false, items: []));
+ } on InconsistentAnalysisException {
+ return success(CompletionList(isIncomplete: false, items: []));
+ }
}
Future<ErrorOr<CompletionList>> _getServerYamlItems(
diff --git a/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart b/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
index 2904afc..97dad9b 100644
--- a/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inferrer.dart
@@ -173,7 +173,7 @@
} else if (rawType == null || rawType.typeFormals.isEmpty) {
typeArgumentTypes = const <DartType>[];
} else {
- rawType = getFreshTypeParameters(rawType.typeFormals)
+ this.rawType = rawType = getFreshTypeParameters(rawType.typeFormals)
.applyToFunctionType(rawType);
inferrer = resolver.typeSystem.setupGenericTypeInference(
@@ -193,7 +193,6 @@
List<EqualityInfo<PromotableElement, DartType>?>? identicalInfo =
_isIdentical ? [] : null;
var deferredClosures = _visitArguments(
- rawType: rawType,
identicalInfo: identicalInfo,
substitution: substitution,
inferrer: inferrer);
@@ -206,7 +205,6 @@
rawType!.typeFormals, inferrer.partialInfer());
}
_resolveDeferredClosures(
- rawType: rawType,
deferredClosures: stage,
identicalInfo: identicalInfo,
substitution: substitution,
@@ -382,7 +380,7 @@
final ResolverVisitor resolver;
final Node node;
final ArgumentListImpl argumentList;
- final FunctionType? rawType;
+ FunctionType? rawType;
final DartType? contextType;
final List<WhyNotPromotedGetter> whyNotPromotedList;
@@ -403,10 +401,9 @@
/// Performs type inference on the invocation expression.
void resolveInvocation() {
- var deferredClosures = _visitArguments(rawType: rawType);
+ var deferredClosures = _visitArguments();
if (deferredClosures != null) {
- _resolveDeferredClosures(
- rawType: rawType, deferredClosures: deferredClosures);
+ _resolveDeferredClosures(deferredClosures: deferredClosures);
}
}
@@ -429,8 +426,7 @@
/// Resolves any closures that were deferred by [_visitArguments].
void _resolveDeferredClosures(
- {required FunctionType? rawType,
- required Iterable<_DeferredClosure> deferredClosures,
+ {required Iterable<_DeferredClosure> deferredClosures,
List<EqualityInfo<PromotableElement, DartType>?>? identicalInfo,
Substitution? substitution,
GenericInferrer? inferrer}) {
@@ -465,8 +461,7 @@
/// be deferred due to the `inference-update-1` feature, a list of them is
/// returned.
List<_DeferredClosure>? _visitArguments(
- {required FunctionType? rawType,
- List<EqualityInfo<PromotableElement, DartType>?>? identicalInfo,
+ {List<EqualityInfo<PromotableElement, DartType>?>? identicalInfo,
Substitution? substitution,
GenericInferrer? inferrer}) {
assert(whyNotPromotedList.isEmpty);
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index 609256a..0fb8cf4 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -182,13 +182,12 @@
void registerRuntimeTypeUse(ir.Expression node, RuntimeTypeUseKind kind,
ir.DartType receiverType, ir.DartType argumentType);
- // TODO(johnniwinther): Remove these when CFE provides constants.
void registerConstructorNode(ir.Constructor node);
void registerFieldNode(ir.Field node);
void registerProcedureNode(ir.Procedure node);
void registerStaticInvocationNode(ir.StaticInvocation node);
void registerSwitchStatementNode(ir.SwitchStatement node);
- void registerConstConstructorInvocationNode(ir.ConstructorInvocation node);
+ void registerConstSymbolConstructorInvocationNode();
}
class ImpactBuilderData {
diff --git a/pkg/compiler/lib/src/ir/impact_data.dart b/pkg/compiler/lib/src/ir/impact_data.dart
index 77d8075..96fe2ed 100644
--- a/pkg/compiler/lib/src/ir/impact_data.dart
+++ b/pkg/compiler/lib/src/ir/impact_data.dart
@@ -9,7 +9,11 @@
import 'package:kernel/type_environment.dart' as ir;
import '../common.dart';
+import '../common/elements.dart';
+import '../elements/entities.dart';
+import '../elements/types.dart';
import '../ir/scope.dart';
+import '../kernel/element_map.dart';
import '../serialization/serialization.dart';
import '../util/enumset.dart';
import 'constants.dart';
@@ -21,6 +25,7 @@
/// Visitor that builds an [ImpactData] object for the world impact.
class ImpactBuilder extends StaticTypeVisitor implements ImpactRegistry {
final ImpactData _data = ImpactData();
+ final KernelToElementMap _elementMap;
@override
final VariableScopeModel variableScopeModel;
@@ -34,12 +39,24 @@
@override
final inferEffectivelyFinalVariableTypes;
- ImpactBuilder(this.staticTypeContext, StaticTypeCacheImpl staticTypeCache,
- ir.ClassHierarchy classHierarchy, this.variableScopeModel,
- {this.useAsserts = false, this.inferEffectivelyFinalVariableTypes = true})
+ ImpactBuilder(
+ this._elementMap,
+ this.staticTypeContext,
+ StaticTypeCacheImpl staticTypeCache,
+ ir.ClassHierarchy classHierarchy,
+ this.variableScopeModel,
+ {this.useAsserts = false,
+ this.inferEffectivelyFinalVariableTypes = true})
: super(
staticTypeContext.typeEnvironment, classHierarchy, staticTypeCache);
+ CommonElements get _commonElements => _elementMap.commonElements;
+
+ DiagnosticReporter get _reporter => _elementMap.reporter;
+
+ String _typeToString(DartType type) =>
+ type.toStructuredText(_elementMap.types, _elementMap.options);
+
/// Return the named arguments names as a list of strings.
List<String> _getNamedArguments(ir.Arguments arguments) =>
arguments.named.map((n) => n.name).toList();
@@ -313,6 +330,23 @@
registerProcedureNode(procedure);
}
+ void _handleConstConstructorInvocation(ir.ConstructorInvocation node) {
+ assert(node.isConst);
+ ConstructorEntity constructor = _elementMap.getConstructor(node.target);
+ if (_commonElements.isSymbolConstructor(constructor)) {
+ DartType argumentType = _elementMap.getDartType(
+ node.arguments.positional.first.getStaticType(staticTypeContext));
+ // TODO(joshualitt): Does the CFE check this for us?
+ if (argumentType != _commonElements.stringType) {
+ // TODO(het): Get the actual span for the Symbol constructor argument
+ _reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE,
+ MessageKind.STRING_EXPECTED, {'type': _typeToString(argumentType)});
+ return;
+ }
+ registerConstSymbolConstructorInvocationNode();
+ }
+ }
+
@override
void handleConstructorInvocation(ir.ConstructorInvocation node,
ArgumentTypes argumentTypes, ir.DartType resultType) {
@@ -325,7 +359,7 @@
getDeferredImport(node),
isConst: node.isConst);
if (node.isConst) {
- registerConstConstructorInvocationNode(node);
+ _handleConstConstructorInvocation(node);
}
}
@@ -959,13 +993,15 @@
}
@override
- void registerConstConstructorInvocationNode(ir.ConstructorInvocation node) {
- _data._constConstructorInvocationNodes ??= [];
- _data._constConstructorInvocationNodes.add(node);
+ void registerConstSymbolConstructorInvocationNode() {
+ _data._hasConstSymbolConstructorInvocation = true;
}
}
/// Data object that contains the world impact data derived purely from kernel.
+/// It is critical that all of the data in this class be invariant to changes in
+/// the AST that occur after modular compilation and before deserializing the
+/// impact data.
class ImpactData {
static const String tag = 'ImpactData';
@@ -1012,7 +1048,7 @@
List<ir.Procedure> _procedureNodes;
List<ir.SwitchStatement> _switchStatementNodes;
List<ir.StaticInvocation> _staticInvocationNodes;
- List<ir.ConstructorInvocation> _constConstructorInvocationNodes;
+ bool _hasConstSymbolConstructorInvocation = false;
ImpactData();
@@ -1109,8 +1145,7 @@
source.readTreeNodes<ir.SwitchStatement>(emptyAsNull: true);
_staticInvocationNodes =
source.readTreeNodes<ir.StaticInvocation>(emptyAsNull: true);
- _constConstructorInvocationNodes =
- source.readTreeNodes<ir.ConstructorInvocation>(emptyAsNull: true);
+ _hasConstSymbolConstructorInvocation = source.readBool();
source.end(tag);
}
@@ -1186,13 +1221,12 @@
sink.writeList(_runtimeTypeUses, (_RuntimeTypeUse o) => o.toDataSink(sink),
allowNull: true);
- // TODO(johnniwinther): Remove these when CFE provides constants.
sink.writeMemberNodes(_constructorNodes, allowNull: true);
sink.writeMemberNodes(_fieldNodes, allowNull: true);
sink.writeMemberNodes(_procedureNodes, allowNull: true);
sink.writeTreeNodes(_switchStatementNodes, allowNull: true);
sink.writeTreeNodes(_staticInvocationNodes, allowNull: true);
- sink.writeTreeNodes(_constConstructorInvocationNodes, allowNull: true);
+ sink.writeBool(_hasConstSymbolConstructorInvocation);
sink.end(tag);
}
@@ -1527,10 +1561,8 @@
registry.registerStaticInvocationNode(data);
}
}
- if (_constConstructorInvocationNodes != null) {
- for (ir.ConstructorInvocation data in _constConstructorInvocationNodes) {
- registry.registerConstConstructorInvocationNode(data);
- }
+ if (_hasConstSymbolConstructorInvocation) {
+ registry.registerConstSymbolConstructorInvocationNode();
}
}
}
diff --git a/pkg/compiler/lib/src/ir/modular.dart b/pkg/compiler/lib/src/ir/modular.dart
index baa7842..a5da488 100644
--- a/pkg/compiler/lib/src/ir/modular.dart
+++ b/pkg/compiler/lib/src/ir/modular.dart
@@ -5,7 +5,6 @@
// @dart = 2.10
import 'package:kernel/ast.dart' as ir;
-import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
import 'package:front_end/src/api_unstable/dart2js.dart' as ir
@@ -17,7 +16,7 @@
import '../ir/impact_data.dart';
import '../ir/static_type.dart';
import '../js_backend/annotations.dart';
-import '../options.dart';
+import '../kernel/element_map.dart';
import '../serialization/serialization.dart';
import '../util/enumset.dart';
import 'annotations.dart';
@@ -73,19 +72,20 @@
}
/// Compute [ModularMemberData] from the IR.
-ModularMemberData computeModularMemberData(ir.Member node,
- {CompilerOptions options,
- ir.TypeEnvironment typeEnvironment,
- ir.ClassHierarchy classHierarchy,
+ModularMemberData computeModularMemberData(
+ KernelToElementMap elementMap,
+ ir.Member node,
ScopeModel scopeModel,
- EnumSet<PragmaAnnotation> annotations}) {
+ EnumSet<PragmaAnnotation> annotations) {
var staticTypeCache = StaticTypeCacheImpl();
var impactBuilderData = ImpactBuilder(
- ir.StaticTypeContext(node, typeEnvironment, cache: staticTypeCache),
+ elementMap,
+ ir.StaticTypeContext(node, elementMap.typeEnvironment,
+ cache: staticTypeCache),
staticTypeCache,
- classHierarchy,
+ elementMap.classHierarchy,
scopeModel.variableScopeModel,
- useAsserts: options.enableUserAssertions,
+ useAsserts: elementMap.options.enableUserAssertions,
inferEffectivelyFinalVariableTypes:
!annotations.contains(PragmaAnnotation.disableFinal))
.computeImpact(node);
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index 6b135bc..3756ddd 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -348,22 +348,8 @@
}
@override
- void registerConstConstructorInvocationNode(ir.ConstructorInvocation node) {
- assert(node.isConst);
- ConstructorEntity constructor = elementMap.getConstructor(node.target);
- if (commonElements.isSymbolConstructor(constructor)) {
- ConstantValue value = elementMap.getConstantValue(
- staticTypeContext, node.arguments.positional.first);
- if (!value.isString) {
- // TODO(het): Get the actual span for the Symbol constructor argument
- reporter.reportErrorMessage(
- CURRENT_ELEMENT_SPANNABLE,
- MessageKind.STRING_EXPECTED,
- {'type': typeToString(value.getType(elementMap.commonElements))});
- return;
- }
- registerBackendImpact(_impacts.constSymbol);
- }
+ void registerConstSymbolConstructorInvocationNode() {
+ registerBackendImpact(_impacts.constSymbol);
}
@override
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index 137a26c..0a7cda9 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -440,12 +440,8 @@
ScopeModel scopeModel = _compilerTask.measureSubtask(
'closures', () => ScopeModel.from(node, _elementMap.constantEvaluator));
return _compilerTask.measureSubtask('worldImpact', () {
- return computeModularMemberData(node,
- options: _elementMap.options,
- typeEnvironment: _elementMap.typeEnvironment,
- classHierarchy: _elementMap.classHierarchy,
- scopeModel: scopeModel,
- annotations: annotations);
+ return computeModularMemberData(
+ _elementMap, node, scopeModel, annotations);
});
}
}
diff --git a/pkg/compiler/lib/src/phase/modular_analysis.dart b/pkg/compiler/lib/src/phase/modular_analysis.dart
index 75853c4..748e97c 100644
--- a/pkg/compiler/lib/src/phase/modular_analysis.dart
+++ b/pkg/compiler/lib/src/phase/modular_analysis.dart
@@ -63,13 +63,9 @@
final scopeModel = ScopeModel.from(member, elementMap.constantEvaluator);
final annotations = processMemberAnnotations(
options, reporter, member, computePragmaAnnotationDataFromIr(member));
- result[member] = computeModularMemberData(member,
- options: options,
- typeEnvironment: elementMap.typeEnvironment,
- classHierarchy: elementMap.classHierarchy,
- scopeModel: scopeModel,
- annotations: annotations)
- .impactBuilderData;
+ result[member] =
+ computeModularMemberData(elementMap, member, scopeModel, annotations)
+ .impactBuilderData;
}
for (final library in input.component.libraries) {
diff --git a/pkg/dart_internal/CHANGELOG.md b/pkg/dart_internal/CHANGELOG.md
index 868e075..4b8c21c 100644
--- a/pkg/dart_internal/CHANGELOG.md
+++ b/pkg/dart_internal/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.2.5
+
+- Support the latest Dart SDK.
+
## 0.2.4
- Support the latest Dart SDK.
diff --git a/pkg/dart_internal/pubspec.yaml b/pkg/dart_internal/pubspec.yaml
index 244171e..51a630d 100644
--- a/pkg/dart_internal/pubspec.yaml
+++ b/pkg/dart_internal/pubspec.yaml
@@ -1,5 +1,5 @@
name: dart_internal
-version: 0.2.4
+version: 0.2.5
repository: https://github.com/dart-lang/sdk/tree/master/pkg/dart_internal
description: >-
This package is not intended for wide use. It provides a temporary API to
@@ -9,4 +9,4 @@
environment:
# Restrict the upper bound so that we can remove support for this in a later
# version of the SDK without it being a breaking change.
- sdk: ">=2.12.0 <2.18.0"
+ sdk: ">=2.12.0 <2.19.0"
diff --git a/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
index aea2b09..373a8d8 100644
--- a/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/async_function.dart.weak.transformed.expect
@@ -121,10 +121,10 @@
return null;
else
[yield] null;
- :controller.{asy::_AsyncStarStreamController::addStream}(self::asyncStarString2()){(asy::Stream<core::String>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(self::asyncStarString2()){(asy::Stream<core::String>) → core::bool})
return null;
+ else
+ [yield] null;
[yield] let dynamic #t1 = asy::_awaitHelper(self::asyncString(), :async_op_then, :async_op_error) in null;
if(:controller.{asy::_AsyncStarStreamController::add}(_in::unsafeCast<core::String>(:result_or_exception)){(core::String) → core::bool})
return null;
diff --git a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
index 7af3671..d3d1139 100644
--- a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
@@ -652,10 +652,10 @@
#L16:
{
[yield] let dynamic #t55 = asy::_awaitHelper(func<asy::Stream<core::int>>(self::intStream()){(asy::Stream<core::int>) → FutureOr<asy::Stream<core::int>>}, :async_op_then, :async_op_error) in null;
- :controller.{asy::_AsyncStarStreamController::addStream}(_in::unsafeCast<asy::Stream<core::int>>(:result_or_exception)){(asy::Stream<core::int>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(_in::unsafeCast<asy::Stream<core::int>>(:result_or_exception)){(asy::Stream<core::int>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
diff --git a/pkg/front_end/testcases/general/statements.dart.weak.transformed.expect b/pkg/front_end/testcases/general/statements.dart.weak.transformed.expect
index 2db299f..012142b 100644
--- a/pkg/front_end/testcases/general/statements.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/statements.dart.weak.transformed.expect
@@ -44,10 +44,10 @@
return null;
else
[yield] null;
- :controller.{asy::_AsyncStarStreamController::addStream}(x as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Stream<dynamic>){(asy::Stream<dynamic>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(x as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Stream<dynamic>){(asy::Stream<dynamic>) → core::bool})
return null;
+ else
+ [yield] null;
}
}
else
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.weak.transformed.expect
index 5730a20..2e127fbc 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.weak.transformed.expect
@@ -2,7 +2,6 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
-import "dart:_internal" as _in;
import "dart:async";
@@ -26,10 +25,10 @@
else
[yield] null;
asy::Stream<core::double*>* s;
- :controller.{asy::_AsyncStarStreamController::addStream}(s){(asy::Stream<core::num*>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(s){(asy::Stream<core::num*>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.weak.transformed.expect
index 02bca84..7f9840f 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.weak.transformed.expect
@@ -29,7 +29,6 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
-import "dart:_internal" as _in;
import "dart:async";
@@ -110,18 +109,18 @@
return null;
else
[yield] null;
- :controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:17:64: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Stream<List<int>>'.
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart:17:64: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'Stream<List<int>>'.
- 'List' is from 'dart:core'.
- 'Stream' is from 'dart:async'.
yield* /*error:YIELD_OF_INVALID_TYPE*/ /*@typeArgs=dynamic*/ [];
- ^" in core::_GrowableList::•<dynamic>(0) as{TypeError} asy::Stream<core::List<core::int*>*>*){(asy::Stream<core::List<core::int*>*>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ ^" in core::_GrowableList::•<dynamic>(0) as{TypeError} asy::Stream<core::List<core::int*>*>*){(asy::Stream<core::List<core::int*>*>) → core::bool})
return null;
- :controller.{asy::_AsyncStarStreamController::addStream}(self::MyStream::•<core::List<core::int*>*>()){(asy::Stream<core::List<core::int*>*>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ else
+ [yield] null;
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(self::MyStream::•<core::List<core::int*>*>()){(asy::Stream<core::List<core::int*>*>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
diff --git a/pkg/front_end/testcases/inference/local_return_and_yield.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/local_return_and_yield.dart.weak.transformed.expect
index 251c281..fbcd719 100644
--- a/pkg/front_end/testcases/inference/local_return_and_yield.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/local_return_and_yield.dart.weak.transformed.expect
@@ -10,7 +10,6 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
-import "dart:_internal" as _in;
import "dart:async";
@@ -130,10 +129,10 @@
try {
#L3:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))){(asy::Stream<(core::int*) →* core::int*>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))){(asy::Stream<(core::int*) →* core::int*>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
diff --git a/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.weak.transformed.expect
index 3d5e979..84ea22c 100644
--- a/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.weak.transformed.expect
@@ -10,7 +10,6 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
-import "dart:_internal" as _in;
import "dart:async";
@@ -129,10 +128,10 @@
try {
#L3:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))){(asy::Stream<(core::int*) →* core::int*>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(asy::Stream::fromIterable<(core::int*) →* core::int*>(core::_GrowableList::_literal1<(core::int*) →* core::int*>((core::int* x) → core::int* => x))){(asy::Stream<(core::int*) →* core::int*>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
diff --git a/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
index c8058e6..cfc0b05 100644
--- a/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437c.dart.strong.transformed.expect
@@ -40,7 +40,6 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
-import "dart:_internal" as _in;
static method getNull() → dynamic
return null;
@@ -161,13 +160,13 @@
try {
#L4:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:21:10: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:21:10: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
- 'Stream' is from 'dart:async'.
yield* getStreamNull(); // error
- ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
@@ -204,10 +203,10 @@
try {
#L5:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
@@ -286,13 +285,13 @@
try {
#L8:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:38:12: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:38:12: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
- 'Stream' is from 'dart:async'.
yield* getStreamNull(); // error
- ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
@@ -329,10 +328,10 @@
try {
#L9:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
@@ -403,10 +402,10 @@
try {
#L11:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamNull()){(asy::Stream<dynamic>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamNull()){(asy::Stream<dynamic>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
@@ -441,10 +440,10 @@
try {
#L12:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
diff --git a/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
index c8058e6..cfc0b05 100644
--- a/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41437c.dart.weak.transformed.expect
@@ -40,7 +40,6 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
-import "dart:_internal" as _in;
static method getNull() → dynamic
return null;
@@ -161,13 +160,13 @@
try {
#L4:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:21:10: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:21:10: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
- 'Stream' is from 'dart:async'.
yield* getStreamNull(); // error
- ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
@@ -204,10 +203,10 @@
try {
#L5:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
@@ -286,13 +285,13 @@
try {
#L8:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:38:12: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(invalid-expression "pkg/front_end/testcases/nnbd/issue41437c.dart:38:12: Error: A value of type 'Stream<dynamic>' can't be assigned to a variable of type 'Stream<bool>'.
- 'Stream' is from 'dart:async'.
yield* getStreamNull(); // error
- ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ ^" in self::getStreamNull() as{TypeError,ForNonNullableByDefault} asy::Stream<core::bool>){(asy::Stream<core::bool>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
@@ -329,10 +328,10 @@
try {
#L9:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
@@ -403,10 +402,10 @@
try {
#L11:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamNull()){(asy::Stream<dynamic>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamNull()){(asy::Stream<dynamic>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
@@ -441,10 +440,10 @@
try {
#L12:
{
- :controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → void};
- [yield] null;
- if(_in::unsafeCast<core::bool>(:result_or_exception))
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(self::getStreamBool()){(asy::Stream<core::bool>) → core::bool})
return null;
+ else
+ [yield] null;
}
return;
}
diff --git a/pkg/vm/lib/transformations/continuation.dart b/pkg/vm/lib/transformations/continuation.dart
index fa535fc..b5c3949 100644
--- a/pkg/vm/lib/transformations/continuation.dart
+++ b/pkg/vm/lib/transformations/continuation.dart
@@ -1319,21 +1319,10 @@
functionType: addMethodFunctionType)
..fileOffset = stmt.fileOffset;
- if (stmt.isYieldStar) {
- statements.add(ExpressionStatement(addExpression));
- statements.add(createContinuationPoint()..fileOffset = stmt.fileOffset);
- final wasCancelled = StaticInvocation(
- helper.unsafeCast,
- Arguments(<Expression>[VariableGet(expressionRewriter!.asyncResult)],
- types: <DartType>[helper.coreTypes.boolNonNullableRawType]));
- statements
- .add(IfStatement(wasCancelled, ReturnStatement(NullLiteral()), null));
- } else {
- statements.add(new IfStatement(
- addExpression,
- new ReturnStatement(new NullLiteral()),
- createContinuationPoint()..fileOffset = stmt.fileOffset));
- }
+ statements.add(new IfStatement(
+ addExpression,
+ new ReturnStatement(new NullLiteral()),
+ createContinuationPoint()..fileOffset = stmt.fileOffset));
return removalSentinel ?? EmptyStatement();
}
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index 56c3736..52f6a07 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,5 +1,8 @@
# Changelog
+## 8.2.2+1
+- Documentation update for `FieldRef` and `FuncRef`.
+
## 8.2.2
- Updated the following optional fields to be nullable in `SocketStatistic`:
- `endTime`
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index b8b3cb6..0f80275 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -4302,6 +4302,9 @@
String? name;
/// The owner of this field, which can be either a Library or a Class.
+ ///
+ /// Note: the location of `owner` may not agree with `location` if this is a
+ /// field from a mixin application, patched class, etc.
ObjRef? owner;
/// The declared type of this field.
@@ -4320,6 +4323,9 @@
bool? isStatic;
/// The location of this field in the source code.
+ ///
+ /// Note: this may not agree with the location of `owner` if this is a field
+ /// from a mixin application, patched class, etc.
@optional
SourceLocation? location;
@@ -4386,6 +4392,9 @@
String? name;
/// The owner of this field, which can be either a Library or a Class.
+ ///
+ /// Note: the location of `owner` may not agree with `location` if this is a
+ /// field from a mixin application, patched class, etc.
ObjRef? owner;
/// The declared type of this field.
@@ -4404,6 +4413,9 @@
bool? isStatic;
/// The location of this field in the source code.
+ ///
+ /// Note: this may not agree with the location of `owner` if this is a field
+ /// from a mixin application, patched class, etc.
@optional
SourceLocation? location;
@@ -4630,6 +4642,10 @@
/// The owner of this function, which can be a Library, Class, or a Function.
///
+ /// Note: the location of `owner` may not agree with `location` if this is a
+ /// function from a mixin application, expression evaluation, patched class,
+ /// etc.
+ ///
/// [owner] can be one of [LibraryRef], [ClassRef] or [FuncRef].
dynamic owner;
@@ -4643,6 +4659,10 @@
bool? implicit;
/// The location of this function in the source code.
+ ///
+ /// Note: this may not agree with the location of `owner` if this is a
+ /// function from a mixin application, expression evaluation, patched class,
+ /// etc.
@optional
SourceLocation? location;
@@ -4706,6 +4726,10 @@
/// The owner of this function, which can be a Library, Class, or a Function.
///
+ /// Note: the location of `owner` may not agree with `location` if this is a
+ /// function from a mixin application, expression evaluation, patched class,
+ /// etc.
+ ///
/// [owner] can be one of [LibraryRef], [ClassRef] or [FuncRef].
dynamic owner;
@@ -4719,6 +4743,10 @@
bool? implicit;
/// The location of this function in the source code.
+ ///
+ /// Note: this may not agree with the location of `owner` if this is a
+ /// function from a mixin application, expression evaluation, patched class,
+ /// etc.
@optional
SourceLocation? location;
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 1f9fc98..7de79cf 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -3,7 +3,7 @@
A library to communicate with a service implementing the Dart VM
service protocol.
-version: 8.2.2
+version: 8.2.2+1
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service
diff --git a/pkg/vm_service/test/external_compilation_service_script.dart b/pkg/vm_service/test/external_compilation_service_script.dart
new file mode 100644
index 0000000..0816523
--- /dev/null
+++ b/pkg/vm_service/test/external_compilation_service_script.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2022, 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 'dart:developer';
+
+main() {
+ debugger();
+}
diff --git a/pkg/vm_service/test/external_compilation_service_test.dart b/pkg/vm_service/test/external_compilation_service_test.dart
new file mode 100644
index 0000000..e98c146
--- /dev/null
+++ b/pkg/vm_service/test/external_compilation_service_test.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2022, 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 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+import 'package:vm_service/vm_service_io.dart';
+
+late Uri remoteVmServiceUri;
+
+Future<Process> spawnDartProcess(String script) async {
+ final executable = Platform.executable;
+ final tmpDir = await Directory.systemTemp.createTemp('dart_service');
+ final serviceInfoUri = tmpDir.uri.resolve('service_info.json');
+ final serviceInfoFile = await File.fromUri(serviceInfoUri).create();
+
+ final arguments = [
+ '--disable-dart-dev',
+ '--observe=0',
+ '--disable-service-auth-codes',
+ '--write-service-info=$serviceInfoUri',
+ ...Platform.executableArguments,
+ Platform.script.resolve(script).toString(),
+ ];
+ final process = await Process.start(executable, arguments);
+ process.stdout
+ .transform(utf8.decoder)
+ .listen((line) => print('TESTEE OUT: $line'));
+ process.stderr
+ .transform(utf8.decoder)
+ .listen((line) => print('TESTEE ERR: $line'));
+ while ((await serviceInfoFile.length()) <= 5) {
+ await Future.delayed(const Duration(milliseconds: 50));
+ }
+ final content = await serviceInfoFile.readAsString();
+ final infoJson = json.decode(content);
+ remoteVmServiceUri =
+ Uri.parse(infoJson['uri']).replace(scheme: 'ws', path: 'ws');
+ return process;
+}
+
+Future<void> waitForRunnableIsolate(VmService service, Isolate isolate) async {
+ bool runnable = isolate.runnable!;
+ while (!runnable) {
+ await Future.delayed(const Duration(milliseconds: 100));
+ runnable = (await service.getIsolate(isolate.id!)).runnable!;
+ }
+}
+
+void main() {
+ group('VM Service', () {
+ late Process process;
+
+ setUp(() async {
+ process =
+ await spawnDartProcess('external_compilation_service_script.dart');
+ });
+
+ tearDown(() async {
+ process.kill();
+ });
+
+ test('evaluate invokes client provided compileExpression RPC', () async {
+ final service = await vmServiceConnectUri(remoteVmServiceUri.toString());
+ await service.registerService(
+ 'compileExpression',
+ 'Custom Expression Compilation',
+ );
+ bool invokedCompileExpression = false;
+ service.registerServiceCallback('compileExpression', (params) async {
+ invokedCompileExpression = true;
+ throw 'error';
+ });
+ final vm = await service.getVM();
+ final isolate = await service.getIsolate(vm.isolates!.first.id!);
+ await waitForRunnableIsolate(service, isolate);
+ try {
+ await service.evaluate(
+ isolate.id!, isolate.libraries!.first.id!, '1 + 1');
+ } catch (_) {
+ // ignore error
+ }
+ expect(invokedCompileExpression, true);
+ });
+
+ test('evaluateInFrame invokes client provided compileExpression RPC',
+ () async {
+ final service = await vmServiceConnectUri(remoteVmServiceUri.toString());
+ await service.registerService(
+ 'compileExpression',
+ 'Custom Expression Compilation',
+ );
+ bool invokedCompileExpression = false;
+ service.registerServiceCallback('compileExpression', (params) async {
+ invokedCompileExpression = true;
+ throw 'error';
+ });
+ final vm = await service.getVM();
+ final isolate = await service.getIsolate(vm.isolates!.first.id!);
+ await waitForRunnableIsolate(service, isolate);
+ try {
+ await service.evaluateInFrame(isolate.id!, 0, '1 + 1');
+ } catch (e) {
+ // ignore error
+ }
+ expect(invokedCompileExpression, true);
+ });
+ });
+}
diff --git a/runtime/tests/vm/dart/causal_stacks/flutter_regress_100441_test.dart b/runtime/tests/vm/dart/causal_stacks/flutter_regress_100441_test.dart
deleted file mode 100644
index b5ff8ad..0000000
--- a/runtime/tests/vm/dart/causal_stacks/flutter_regress_100441_test.dart
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2022, 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.
-//
-// VMOptions=--lazy-async-stacks
-
-import 'dart:async';
-
-import 'package:expect/expect.dart';
-
-import 'utils.dart' show assertStack;
-
-String effectOrder = '';
-StackTrace? stackAfterYield = null;
-
-void emit(String m) => effectOrder += m;
-
-main() async {
- emit('1');
- await for (final value in produce()) {
- emit('5');
- Expect.equals('|value|', value);
- }
- emit('8');
- Expect.equals('12345678', effectOrder);
-
- assertStack(const <String>[
- r'^#0 produceInner .*$',
- r'^<asynchronous suspension>$',
- r'^#1 produce .*$',
- r'^<asynchronous suspension>$',
- r'^#2 main .*$',
- r'^<asynchronous suspension>$',
- ], stackAfterYield!);
-
- effectOrder = '';
-
- emit('1');
- await for (final value in produceYieldStar()) {
- emit('5');
- Expect.equals('|value|', value);
- break;
- }
- emit('6');
- Expect.equals('123456', effectOrder);
-}
-
-Stream<dynamic> produce() async* {
- emit('2');
- await for (String response in produceInner()) {
- emit('4');
- yield response;
- }
- emit('7');
-}
-
-Stream produceInner() async* {
- emit('3');
- yield '|value|';
- emit('6');
- stackAfterYield = StackTrace.current;
-}
-
-Stream<dynamic> produceYieldStar() async* {
- emit('2');
- await for (String response in produceInner()) {
- emit('4');
- yield response;
- }
- emit('x');
-}
-
-Stream produceInnerYieldStar() async* {
- emit('3');
- yield* Stream.fromIterable(['|value|', '|value2|']);
- emit('x');
-}
diff --git a/runtime/tests/vm/dart_2/causal_stacks/flutter_regress_100441_test.dart b/runtime/tests/vm/dart_2/causal_stacks/flutter_regress_100441_test.dart
deleted file mode 100644
index 2d4d2ef..0000000
--- a/runtime/tests/vm/dart_2/causal_stacks/flutter_regress_100441_test.dart
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2022, 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.
-//
-// VMOptions=--lazy-async-stacks
-
-// @dart = 2.9
-import 'dart:async';
-
-import 'package:expect/expect.dart';
-
-import 'utils.dart' show assertStack;
-
-String effectOrder = '';
-StackTrace stackAfterYield = null;
-
-void emit(String m) => effectOrder += m;
-
-main() async {
- emit('1');
- await for (final value in produce()) {
- emit('5');
- Expect.equals('|value|', value);
- }
- emit('8');
- Expect.equals('12345678', effectOrder);
-
- assertStack(const <String>[
- r'^#0 produceInner .*$',
- r'^<asynchronous suspension>$',
- r'^#1 produce .*$',
- r'^<asynchronous suspension>$',
- r'^#2 main .*$',
- r'^<asynchronous suspension>$',
- ], stackAfterYield);
-
- effectOrder = '';
-
- emit('1');
- await for (final value in produceYieldStar()) {
- emit('5');
- Expect.equals('|value|', value);
- break;
- }
- emit('6');
- Expect.equals('123456', effectOrder);
-}
-
-Stream<dynamic> produce() async* {
- emit('2');
- await for (String response in produceInner()) {
- emit('4');
- yield response;
- }
- emit('7');
-}
-
-Stream produceInner() async* {
- emit('3');
- yield '|value|';
- emit('6');
- stackAfterYield = StackTrace.current;
-}
-
-Stream<dynamic> produceYieldStar() async* {
- emit('2');
- await for (String response in produceInner()) {
- emit('4');
- yield response;
- }
- emit('x');
-}
-
-Stream produceInnerYieldStar() async* {
- emit('3');
- yield* Stream.fromIterable(['|value|', '|value2|']);
- emit('x');
-}
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 3ec06a6..eabdbb0 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -3507,25 +3507,23 @@
return;
}
-#if !defined(TARGET_ARCH_RISCV32) && !defined(TARGET_ARCH_RISCV64)
// Split moves from stack to stack, none of the architectures provides
- // memory to memory move instructions. But RISC-V needs to avoid TMP.
+ // memory to memory move instructions.
if (source.IsStack() && destination.IsStack()) {
- Register scratch = TMP;
- if (TMP == kNoRegister) {
- scratch = temp->AllocateTemporary();
- }
+ Register scratch = temp->AllocateTemporary();
+ ASSERT(scratch != kNoRegister);
+#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
+ ASSERT(scratch != TMP); // TMP is an argument register.
+ ASSERT(scratch != TMP2); // TMP2 is an argument register.
+#endif
const auto& intermediate =
*new (zone_) compiler::ffi::NativeRegistersLocation(
zone_, dst_payload_type, dst_container_type, scratch);
EmitNativeMove(intermediate, source, temp);
EmitNativeMove(destination, intermediate, temp);
- if (TMP == kNoRegister) {
- temp->ReleaseTemporary();
- }
+ temp->ReleaseTemporary();
return;
}
-#endif
const bool sign_or_zero_extend = dst_container_size > src_container_size;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
index 30d5374..8671e2e 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
@@ -868,15 +868,6 @@
}
}
-// See FfiCallInstr::MakeLocationSummary.
-static Register WithIntermediateMarshalling(Register r) {
- if (r == A2) return T2; // A2=CODE_REG
- if (r == A3) return T3; // A3=TMP
- if (r == A4) return T4; // A4=TMP2
- if (r == A5) return T5; // A5=PP
- return r;
-}
-
void FlowGraphCompiler::EmitNativeMoveArchitecture(
const compiler::ffi::NativeLocation& destination,
const compiler::ffi::NativeLocation& source) {
@@ -894,12 +885,12 @@
if (source.IsRegisters()) {
const auto& src = source.AsRegisters();
ASSERT(src.num_regs() == 1);
- const auto src_reg = WithIntermediateMarshalling(src.reg_at(0));
+ const auto src_reg = src.reg_at(0);
if (destination.IsRegisters()) {
const auto& dst = destination.AsRegisters();
ASSERT(dst.num_regs() == 1);
- const auto dst_reg = WithIntermediateMarshalling(dst.reg_at(0));
+ const auto dst_reg = dst.reg_at(0);
if (!sign_or_zero_extend) {
#if XLEN == 32
__ MoveRegister(dst_reg, src_reg);
@@ -995,7 +986,7 @@
if (destination.IsRegisters()) {
const auto& dst = destination.AsRegisters();
ASSERT(dst.num_regs() == 1);
- const auto dst_reg = WithIntermediateMarshalling(dst.reg_at(0));
+ const auto dst_reg = dst.reg_at(0);
ASSERT(!sign_or_zero_extend);
__ LoadFromOffset(dst_reg, src.base_register(), src.offset_in_bytes(),
BytesToOperandSize(dst_size));
@@ -1015,14 +1006,8 @@
default:
UNIMPLEMENTED();
}
- } else if (destination.IsStack()) {
- const auto& dst = destination.AsStack();
- // TMP=A3, here not remapped to T3.
- __ LoadFromOffset(TMP, src.base_register(), src.offset_in_bytes(),
- BytesToOperandSize(src_size));
- __ StoreToOffset(TMP, dst.base_register(), dst.offset_in_bytes(),
- BytesToOperandSize(dst_size));
} else {
+ ASSERT(destination.IsStack());
UNREACHABLE();
}
}
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 30f6bec..367faf6 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -6532,7 +6532,8 @@
void FfiCallInstr::EmitParamMoves(FlowGraphCompiler* compiler,
const Register saved_fp,
- const Register temp) {
+ const Register temp0,
+ const Register temp1) {
if (compiler::Assembler::EmittingComments()) {
__ Comment("EmitParamMoves");
}
@@ -6546,7 +6547,7 @@
const auto& pointer_register =
pointer_location.IsRegisters()
? pointer_location.AsRegisters().reg_at(0)
- : temp;
+ : temp0;
__ MoveRegister(pointer_register, SPREG);
__ AddImmediate(pointer_register, marshaller_.PassByPointerStackOffset(
compiler::ffi::kResultIndex));
@@ -6586,7 +6587,7 @@
? arg_target.AsPointerToMemory().pointer_location()
: /*arg_target.IsStack()*/ arg_target.Split(zone_, num_defs, i);
- ConstantTemporaryAllocator temp_alloc(temp);
+ ConstantTemporaryAllocator temp_alloc(temp0);
if (origin.IsConstant()) {
// Can't occur because we currently don't inline FFI trampolines (see
// http://dartbug.com/45055), which means all incomming arguments
@@ -6610,11 +6611,11 @@
// TypedData/Pointer data pointed to in temp.
const auto& dst = compiler::ffi::NativeRegistersLocation(
zone_, pointer_loc.payload_type(), pointer_loc.container_type(),
- temp);
+ temp0);
compiler->EmitNativeMove(dst, pointer_loc, &temp_alloc);
- __ LoadField(temp,
+ __ LoadField(temp0,
compiler::FieldAddress(
- temp, compiler::target::PointerBase::data_offset()));
+ temp0, compiler::target::PointerBase::data_offset()));
// Copy chuncks.
const intptr_t sp_offset =
@@ -6624,16 +6625,16 @@
// space on the stack.
for (intptr_t i = 0; i < arg_target.payload_type().SizeInBytes();
i += compiler::target::kWordSize) {
- __ LoadMemoryValue(TMP, temp, i);
- __ StoreMemoryValue(TMP, SPREG, i + sp_offset);
+ __ LoadMemoryValue(temp1, temp0, i);
+ __ StoreMemoryValue(temp1, SPREG, i + sp_offset);
}
// Store the stack address in the argument location.
- __ MoveRegister(temp, SPREG);
- __ AddImmediate(temp, sp_offset);
+ __ MoveRegister(temp0, SPREG);
+ __ AddImmediate(temp0, sp_offset);
const auto& src = compiler::ffi::NativeRegistersLocation(
zone_, pointer_loc.payload_type(), pointer_loc.container_type(),
- temp);
+ temp0);
compiler->EmitNativeMove(pointer_loc, src, &temp_alloc);
}
}
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index a7dd7aa..08d8f81 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -5307,18 +5307,18 @@
bool is_optimizing,
const RegList temps) const;
- // Clobbers both given registers.
+ // Clobbers the first two given registers.
// `saved_fp` is used as the frame base to rebase off of.
+ // `temp1` is only used in case of PointerToMemoryLocation.
void EmitParamMoves(FlowGraphCompiler* compiler,
const Register saved_fp,
- const Register temp);
+ const Register temp0,
+ const Register temp1);
// Clobbers both given temp registers.
void EmitReturnMoves(FlowGraphCompiler* compiler,
const Register temp0,
const Register temp1);
- void EmitCall(FlowGraphCompiler* compiler, Register target);
-
Zone* const zone_;
const compiler::ffi::CallMarshaller& marshaller_;
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index c04289b..f92d297 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -1446,7 +1446,7 @@
// Reserve space for the arguments that go on the stack (if any), then align.
__ ReserveAlignedFrameSpace(marshaller_.RequiredStackSpaceInBytes());
- EmitParamMoves(compiler, is_leaf_ ? FPREG : saved_fp_or_sp, temp1);
+ EmitParamMoves(compiler, is_leaf_ ? FPREG : saved_fp_or_sp, temp1, temp2);
if (compiler::Assembler::EmittingComments()) {
__ Comment(is_leaf_ ? "Leaf Call" : "Call");
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 2467df7..3dbb6b0 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -1270,7 +1270,7 @@
// Reserve space for the arguments that go on the stack (if any), then align.
__ ReserveAlignedFrameSpace(marshaller_.RequiredStackSpaceInBytes());
- EmitParamMoves(compiler, is_leaf_ ? FPREG : saved_fp_or_sp, temp1);
+ EmitParamMoves(compiler, is_leaf_ ? FPREG : saved_fp_or_sp, temp1, temp2);
if (compiler::Assembler::EmittingComments()) {
__ Comment(is_leaf_ ? "Leaf Call" : "Call");
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 0d29e71..4869e16 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -1044,7 +1044,9 @@
// Reserve space for the arguments that go on the stack (if any), then align.
__ ReserveAlignedFrameSpace(stack_required);
- EmitParamMoves(compiler, is_leaf_ ? FPREG : saved_fp_or_sp, temp);
+ // No second temp: PointerToMemoryLocation is not used for arguments in ia32.
+ EmitParamMoves(compiler, is_leaf_ ? FPREG : saved_fp_or_sp, temp,
+ kNoRegister);
if (is_leaf_) {
// We store the pre-align SP at a fixed offset from the final SP.
diff --git a/runtime/vm/compiler/backend/il_riscv.cc b/runtime/vm/compiler/backend/il_riscv.cc
index 5f31d92..a029815 100644
--- a/runtime/vm/compiler/backend/il_riscv.cc
+++ b/runtime/vm/compiler/backend/il_riscv.cc
@@ -1382,18 +1382,17 @@
zone, is_optimizing,
(R(CallingConventions::kSecondNonArgumentRegister) |
R(CallingConventions::kFfiAnyNonAbiRegister) | R(CALLEE_SAVED_TEMP2)));
- // A3/A4/A5 are blocked during Dart register allocation because they are
+
+ // A3/A4/A5 are unavailable in normal register allocation because they are
// assigned to TMP/TMP2/PP. This assignment is important for reducing code
- // size. To work around this for FFI calls, the FFI argument definitions are
- // allocated to other registers and moved to the correct register at the last
- // moment (so there are no conflicting uses of TMP/TMP2/PP).
- // FfiCallInstr itself sometimes also clobbers A2/CODE_REG.
- // See also FfiCallInstr::EmitCall.
+ // size. We can't just override the normal blockage of these registers because
+ // they may be used by other instructions between the argument's definition
+ // and its use in FfiCallInstr.
+ // Note that A3/A4/A5 might be not be the 3rd/4th/5th input because of mixed
+ // integer and floating-point arguments.
for (intptr_t i = 0; i < summary->input_count(); i++) {
if (!summary->in(i).IsRegister()) continue;
- if (summary->in(i).reg() == A2) {
- summary->set_in(i, Location::RegisterLocation(T2));
- } else if (summary->in(i).reg() == A3) {
+ if (summary->in(i).reg() == A3) {
summary->set_in(i, Location::RegisterLocation(T3));
} else if (summary->in(i).reg() == A4) {
summary->set_in(i, Location::RegisterLocation(T4));
@@ -1407,6 +1406,20 @@
#undef R
void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ // Beware! Do not use CODE_REG/TMP/TMP2/PP within FfiCallInstr as they are
+ // assigned to A2/A3/A4/A5, which may be in use as argument registers.
+ __ set_constant_pool_allowed(false);
+ for (intptr_t i = 0; i < locs()->input_count(); i++) {
+ if (!locs()->in(i).IsRegister()) continue;
+ if (locs()->in(i).reg() == T3) {
+ __ mv(A3, T3);
+ } else if (locs()->in(i).reg() == T4) {
+ __ mv(A4, T4);
+ } else if (locs()->in(i).reg() == T5) {
+ __ mv(A5, T5);
+ }
+ }
+
const Register target = locs()->in(TargetAddressIndex()).reg();
// The temps are indexed according to their register number.
@@ -1431,17 +1444,27 @@
__ mv(saved_fp_or_sp, is_leaf_ ? SPREG : FPREG);
if (!is_leaf_) {
- // We need to create a dummy "exit frame". It will share the same pool
- // pointer but have a null code object.
- __ LoadObject(CODE_REG, Object::null_object());
- __ set_constant_pool_allowed(false);
- __ EnterDartFrame(0, PP);
+ // We need to create a dummy "exit frame".
+ // This is EnterDartFrame without accessing A2=CODE_REG or A5=PP.
+ if (FLAG_precompiled_mode) {
+ __ subi(SP, SP, 2 * compiler::target::kWordSize);
+ __ sx(RA, compiler::Address(SP, 1 * compiler::target::kWordSize));
+ __ sx(FP, compiler::Address(SP, 0 * compiler::target::kWordSize));
+ __ addi(FP, SP, 2 * compiler::target::kWordSize);
+ } else {
+ __ subi(SP, SP, 4 * compiler::target::kWordSize);
+ __ sx(RA, compiler::Address(SP, 3 * compiler::target::kWordSize));
+ __ sx(FP, compiler::Address(SP, 2 * compiler::target::kWordSize));
+ __ sx(NULL_REG, compiler::Address(SP, 1 * compiler::target::kWordSize));
+ __ sx(NULL_REG, compiler::Address(SP, 0 * compiler::target::kWordSize));
+ __ addi(FP, SP, 4 * compiler::target::kWordSize);
+ }
}
// Reserve space for the arguments that go on the stack (if any), then align.
__ ReserveAlignedFrameSpace(marshaller_.RequiredStackSpaceInBytes());
- EmitParamMoves(compiler, is_leaf_ ? FPREG : saved_fp_or_sp, temp1);
+ EmitParamMoves(compiler, is_leaf_ ? FPREG : saved_fp_or_sp, temp1, temp2);
if (compiler::Assembler::EmittingComments()) {
__ Comment(is_leaf_ ? "Leaf Call" : "Call");
@@ -1456,10 +1479,7 @@
__ StoreToOffset(target, THR, compiler::target::Thread::vm_tag_offset());
#endif
- EmitCall(compiler, target);
-
- ASSERT(!IsCalleeSavedRegister(PP));
- __ RestorePoolPointer();
+ __ jalr(target);
#if !defined(PRODUCT)
__ LoadImmediate(temp1, compiler::target::Thread::vm_tag_dart_id());
@@ -1484,7 +1504,7 @@
__ TransitionGeneratedToNative(target, FPREG, temp1,
/*enter_safepoint=*/true);
- EmitCall(compiler, target);
+ __ jalr(target);
// Update information in the thread object and leave the safepoint.
__ TransitionNativeToGenerated(temp1, /*leave_safepoint=*/true);
@@ -1500,7 +1520,7 @@
// Calls T0 and clobbers R19 (along with volatile registers).
ASSERT(target == T0);
- EmitCall(compiler, temp1);
+ __ jalr(temp1);
}
// Refresh pinned registers values (inc. write barrier mask and null
@@ -1514,27 +1534,18 @@
// Restore the pre-aligned SP.
__ mv(SPREG, saved_fp_or_sp);
} else {
- // Although PP is a callee-saved register, it may have been moved by the GC.
- __ LeaveDartFrame(compiler::kRestoreCallerPP);
+ __ LeaveDartFrame();
// Restore the global object pool after returning from runtime (old space is
// moving, so the GOP could have been relocated).
if (FLAG_precompiled_mode) {
__ SetupGlobalPoolAndDispatchTable();
}
-
- __ set_constant_pool_allowed(true);
}
-}
-void FfiCallInstr::EmitCall(FlowGraphCompiler* compiler, Register target) {
- // Marshall certain argument registers at the last possible moment.
- // See FfiCallInstr::MakeLocationSummary for the details.
- if (InputCount() > 2) __ mv(A2, T2); // A2=CODE_REG
- if (InputCount() > 3) __ mv(A3, T3); // A3=TMP
- if (InputCount() > 4) __ mv(A4, T4); // A4=TMP2
- if (InputCount() > 5) __ mv(A5, T5); // A5=PP
- __ jalr(target);
+ // PP is a volatile register, so it must be restored even for leaf FFI calls.
+ __ RestorePoolPointer();
+ __ set_constant_pool_allowed(true);
}
// Keep in sync with NativeEntryInstr::EmitNativeCode.
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index f461761..023874d 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -1226,9 +1226,9 @@
__ ReserveAlignedFrameSpace(marshaller_.RequiredStackSpaceInBytes());
if (is_leaf_) {
- EmitParamMoves(compiler, FPREG, saved_fp);
+ EmitParamMoves(compiler, FPREG, saved_fp, TMP);
} else {
- EmitParamMoves(compiler, saved_fp, saved_sp);
+ EmitParamMoves(compiler, saved_fp, saved_sp, TMP);
}
if (compiler::Assembler::EmittingComments()) {
diff --git a/runtime/vm/instructions_riscv.cc b/runtime/vm/instructions_riscv.cc
index 161db93..cabe480 100644
--- a/runtime/vm/instructions_riscv.cc
+++ b/runtime/vm/instructions_riscv.cc
@@ -227,7 +227,9 @@
#endif
if (instr.rs1p() == PP) {
// PP is untagged on RISC-V.
- ASSERT(Utils::IsAligned(offset, kWordSize));
+ if (!Utils::IsAligned(offset, kWordSize)) {
+ return false; // Being used as argument register A5.
+ }
intptr_t index = ObjectPool::IndexFromOffset(offset - kHeapObjectTag);
const ObjectPool& pool = ObjectPool::Handle(code.GetObjectPool());
if (!pool.IsNull() && (index < pool.Length()) &&
@@ -249,7 +251,9 @@
intptr_t offset = instr.itype_imm();
if (instr.rs1() == PP) {
// PP is untagged on RISC-V.
- ASSERT(Utils::IsAligned(offset, kWordSize));
+ if (!Utils::IsAligned(offset, kWordSize)) {
+ return false; // Being used as argument register A5.
+ }
intptr_t index = ObjectPool::IndexFromOffset(offset - kHeapObjectTag);
const ObjectPool& pool = ObjectPool::Handle(code.GetObjectPool());
if (!pool.IsNull() && (index < pool.Length()) &&
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 368f70b..90ebf99 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -2446,6 +2446,9 @@
// The owner of this field, which can be either a Library or a
// Class.
+ //
+ // Note: the location of `owner` may not agree with `location` if this is a field
+ // from a mixin application, patched class, etc.
@Object owner;
// The declared type of this field.
@@ -2464,6 +2467,9 @@
bool static;
// The location of this field in the source code.
+ //
+ // Note: this may not agree with the location of `owner` if this is a field
+ // from a mixin application, patched class, etc.
SourceLocation location [optional];
}
```
@@ -2477,6 +2483,9 @@
// The owner of this field, which can be either a Library or a
// Class.
+ //
+ // Note: the location of `owner` may not agree with `location` if this is a field
+ // from a mixin application, patched class, etc.
@Object owner;
// The declared type of this field.
@@ -2495,6 +2504,9 @@
bool static;
// The location of this field in the source code.
+ //
+ // Note: this may not agree with the location of `owner` if this is a field
+ // from a mixin application, patched class, etc.
SourceLocation location [optional];
// The value of this field, if the field is static. If uninitialized,
@@ -2561,6 +2573,10 @@
string name;
// The owner of this function, which can be a Library, Class, or a Function.
+ //
+ // Note: the location of `owner` may not agree with `location` if this is a
+ // function from a mixin application, expression evaluation, patched class,
+ // etc.
@Library|@Class|@Function owner;
// Is this function static?
@@ -2573,6 +2589,9 @@
bool implicit;
// The location of this function in the source code.
+ //
+ // Note: this may not agree with the location of `owner` if this is a function
+ // from a mixin application, expression evaluation, patched class, etc.
SourceLocation location [optional];
}
```
@@ -2586,6 +2605,10 @@
string name;
// The owner of this function, which can be a Library, Class, or a Function.
+ //
+ // Note: the location of `owner` may not agree with `location` if this is a
+ // function from a mixin application, expression evaluation, patched class,
+ // etc.
@Library|@Class|@Function owner;
// Is this function static?
@@ -2598,6 +2621,9 @@
bool implicit;
// The location of this function in the source code.
+ //
+ // Note: this may not agree with the location of `owner` if this is a function
+ // from a mixin application, expression evaluation, patched class, etc.
SourceLocation location [optional];
// The signature of the function.
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index eee21f8..4c7cbcf 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -71,7 +71,7 @@
future_listener_class(Class::Handle(zone)),
async_start_stream_controller_class(Class::Handle(zone)),
stream_controller_class(Class::Handle(zone)),
- sync_stream_controller_class(Class::Handle(zone)),
+ async_stream_controller_class(Class::Handle(zone)),
controller_subscription_class(Class::Handle(zone)),
buffering_stream_subscription_class(Class::Handle(zone)),
stream_iterator_class(Class::Handle(zone)),
@@ -100,9 +100,9 @@
stream_controller_class =
async_lib.LookupClassAllowPrivate(Symbols::_StreamController());
ASSERT(!stream_controller_class.IsNull());
- sync_stream_controller_class =
- async_lib.LookupClassAllowPrivate(Symbols::_SyncStreamController());
- ASSERT(!sync_stream_controller_class.IsNull());
+ async_stream_controller_class =
+ async_lib.LookupClassAllowPrivate(Symbols::_AsyncStreamController());
+ ASSERT(!async_stream_controller_class.IsNull());
controller_subscription_class =
async_lib.LookupClassAllowPrivate(Symbols::_ControllerSubscription());
ASSERT(!controller_subscription_class.IsNull());
@@ -171,7 +171,7 @@
const Instance& controller = Instance::Cast(context_entry_);
controller_ = controller.GetField(controller_controller_field);
ASSERT(!controller_.IsNull());
- ASSERT(controller_.GetClassId() == sync_stream_controller_class.id());
+ ASSERT(controller_.GetClassId() == async_stream_controller_class.id());
// Get the _StreamController._state field.
state_ = Instance::Cast(controller_).GetField(state_field);
@@ -209,7 +209,7 @@
// contains the iterator's value. In that case we cannot unwind anymore.
//
// Notice: With correct async* semantics this may never be true: The async*
- // generator should only be invoked to produce a value if there's an
+ // generator should only be invoked to produce a vaue if there's an
// in-progress `await streamIterator.moveNext()` call. Once such call has
// finished the async* generator should be paused/yielded until the next
// such call - and being paused/yielded means it should not appear in stack
diff --git a/runtime/vm/stack_trace.h b/runtime/vm/stack_trace.h
index 58a4cba..0683cf7 100644
--- a/runtime/vm/stack_trace.h
+++ b/runtime/vm/stack_trace.h
@@ -78,7 +78,7 @@
Class& future_listener_class;
Class& async_start_stream_controller_class;
Class& stream_controller_class;
- Class& sync_stream_controller_class;
+ Class& async_stream_controller_class;
Class& controller_subscription_class;
Class& buffering_stream_subscription_class;
Class& stream_iterator_class;
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index f96d8d3..52ec048 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -278,6 +278,7 @@
V(Values, "values") \
V(WeakSerializationReference, "WeakSerializationReference") \
V(_AsyncStarStreamController, "_AsyncStarStreamController") \
+ V(_AsyncStreamController, "_AsyncStreamController") \
V(_BufferingStreamSubscription, "_BufferingStreamSubscription") \
V(_ByteBuffer, "_ByteBuffer") \
V(_ByteBufferDot_New, "_ByteBuffer._New") \
@@ -380,7 +381,6 @@
V(_StreamIterator, "_StreamIterator") \
V(_String, "String") \
V(_SyncIterator, "_SyncIterator") \
- V(_SyncStreamController, "_SyncStreamController") \
V(_TransferableTypedDataImpl, "_TransferableTypedDataImpl") \
V(_Type, "_Type") \
V(_FunctionType, "_FunctionType") \
diff --git a/sdk/lib/_internal/vm/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart
index 9fddad2..2e322f1 100644
--- a/sdk/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk/lib/_internal/vm/lib/async_patch.dart
@@ -117,13 +117,6 @@
bool isSuspendedAtYield = false;
_Future? cancellationFuture = null;
- /// Argument passed to the generator when it is resumed after an addStream.
- ///
- /// `true` if the generator should exit after `yield*` resumes.
- /// `false` if the generator should continue after `yield*` resumes.
- /// `null` otherwies.
- bool? continuationArgument = null;
-
Stream<T> get stream {
final Stream<T> local = controller.stream;
if (local is _StreamImpl<T>) {
@@ -135,8 +128,7 @@
void runBody() {
isScheduled = false;
isSuspendedAtYield = false;
- asyncStarBody(continuationArgument, null);
- continuationArgument = null;
+ asyncStarBody(null, null);
}
void scheduleGenerator() {
@@ -160,11 +152,11 @@
bool add(T event) {
if (!onListenReceived) _fatal("yield before stream is listened to");
if (isSuspendedAtYield) _fatal("unexpected yield");
- controller.add(event);
+ // If stream is cancelled, tell caller to exit the async generator.
if (!controller.hasListener) {
return true;
}
-
+ controller.add(event);
scheduleGenerator();
isSuspendedAtYield = true;
return false;
@@ -173,41 +165,22 @@
// Adds the elements of stream into this controller's stream.
// The generator will be scheduled again when all of the
// elements of the added stream have been consumed.
- void addStream(Stream<T> stream) {
+ // Returns true if the caller should terminate
+ // execution of the generator.
+ bool addStream(Stream<T> stream) {
if (!onListenReceived) _fatal("yield before stream is listened to");
-
- if (exitAfterYieldStarIfCancelled()) return;
-
+ // If stream is cancelled, tell caller to exit the async generator.
+ if (!controller.hasListener) return true;
isAdding = true;
- final whenDoneAdding = controller.addStream(stream, cancelOnError: false);
+ var whenDoneAdding = controller.addStream(stream, cancelOnError: false);
whenDoneAdding.then((_) {
isAdding = false;
- if (exitAfterYieldStarIfCancelled()) return;
- resumeNormallyAfterYieldStar();
- });
- }
-
- /// Schedules the generator to exit after `yield*` if stream was cancelled.
- ///
- /// Returns `true` if generator is told to exit and `false` otherwise.
- bool exitAfterYieldStarIfCancelled() {
- // If consumer cancelled subscription we should tell async* generator to
- // finish (i.e. run finally clauses and return).
- if (!controller.hasListener) {
- continuationArgument = true;
scheduleGenerator();
- return true;
- }
+ if (!isScheduled) isSuspendedAtYield = true;
+ });
return false;
}
- /// Schedules the generator to resume normally after `yield*`.
- void resumeNormallyAfterYieldStar() {
- continuationArgument = false;
- scheduleGenerator();
- if (!isScheduled) isSuspendedAtYield = true;
- }
-
void addError(Object error, StackTrace stackTrace) {
// TODO(40614): Remove once non-nullability is sound.
ArgumentError.checkNotNull(error, "error");
@@ -238,7 +211,7 @@
}
_AsyncStarStreamController(this.asyncStarBody)
- : controller = new StreamController(sync: true) {
+ : controller = new StreamController() {
controller.onListen = this.onListen;
controller.onResume = this.onResume;
controller.onCancel = this.onCancel;
diff --git a/tests/language/async_star/pause2_test.dart b/tests/language/async_star/pause2_test.dart
index 3df0223..a240d3d 100644
--- a/tests/language/async_star/pause2_test.dart
+++ b/tests/language/async_star/pause2_test.dart
@@ -72,8 +72,8 @@
f() async* {
int i = 0;
while (true) {
- list.add(i);
yield i;
+ list.add(i);
i++;
}
}
diff --git a/tests/language/async_star/throw_in_catch_test.dart b/tests/language/async_star/throw_in_catch_test.dart
index 7509a00..88982e5 100644
--- a/tests/language/async_star/throw_in_catch_test.dart
+++ b/tests/language/async_star/throw_in_catch_test.dart
@@ -115,7 +115,7 @@
test() async {
// TODO(sigurdm): These tests are too dependent on scheduling, and buffering
// behavior.
- await runTest(foo1, "abcYgC", null, true);
+ await runTest(foo1, "abcYdgC", null, true);
await runTest(foo2, "abcX", "Error", false);
await runTest(foo3, "abcYX", "Error", false);
await runTest(foo4, "abcYdYefX", "Error2", false);
diff --git a/tests/language_2/async_star/pause2_test.dart b/tests/language_2/async_star/pause2_test.dart
index f6e8d5f..11e0429 100644
--- a/tests/language_2/async_star/pause2_test.dart
+++ b/tests/language_2/async_star/pause2_test.dart
@@ -74,8 +74,8 @@
f() async* {
int i = 0;
while (true) {
- list.add(i);
yield i;
+ list.add(i);
i++;
}
}
diff --git a/tests/language_2/async_star/throw_in_catch_test.dart b/tests/language_2/async_star/throw_in_catch_test.dart
index 6a26245..57b6b0e 100644
--- a/tests/language_2/async_star/throw_in_catch_test.dart
+++ b/tests/language_2/async_star/throw_in_catch_test.dart
@@ -118,7 +118,7 @@
test() async {
// TODO(sigurdm): These tests are too dependent on scheduling, and buffering
// behavior.
- await runTest(foo1, "abcYgC", null, true);
+ await runTest(foo1, "abcYdgC", null, true);
await runTest(foo2, "abcX", "Error", false);
await runTest(foo3, "abcYX", "Error", false);
await runTest(foo4, "abcYdYefX", "Error2", false);
diff --git a/tools/VERSION b/tools/VERSION
index f29c189..a082332 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 281
+PRERELEASE 282
PRERELEASE_PATCH 0
\ No newline at end of file