Version 2.18.0-190.0.dev
Merge commit 'd1affb719fa57e999e96703555085d2065a77d29' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cbd5912..5a94e4e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -140,6 +140,13 @@
### Tools
+#### Dart command line
+
+- **Breaking change** [#46100](https://github.com/dart-lang/sdk/issues/46100):
+ The standalone `dart2js` and `dartdevc` tools have been removed as previously
+ announced. `dart2js` is replaced by the `dart compile js` command, `dartdevc`
+ is no longer exposed as a command-line tool.
+
#### Linter
Updated the Linter to `1.25.0`, which includes changes that
diff --git a/DEPS b/DEPS
index f159d22..d75b9ba 100644
--- a/DEPS
+++ b/DEPS
@@ -105,7 +105,7 @@
# For more details, see https://github.com/dart-lang/sdk/issues/30164.
"dart_style_rev": "d7b73536a8079331c888b7da539b80e6825270ea",
- "dartdoc_rev": "b61647bc3833302c23bd79f03aa1fbe83578af50",
+ "dartdoc_rev": "58348a98b992ce99b95d23131b67227bdb2b4875",
"devtools_rev": "51ac983d2db7eb19b3ce5956cb70b769d74fe784",
"ffi_rev": "0c8364a728cfe4e4ba859c53b99d56b3dbe3add4",
"file_rev": "0132eeedea2933513bf230513a766a8baeab0c4f",
@@ -114,7 +114,7 @@
"html_rev": "f108bce59d136c584969fd24a5006914796cf213",
"http_multi_server_rev": "35a3b947256768426090e3b1f5132e4fc23c175d",
"http_parser_rev": "9126ee04e77fd8e4e2e6435b503ee4dd708d7ddc",
- "http_rev": "2993ea5dff5ffb066b4a35c707e7a2b8dcfa17c2",
+ "http_rev": "0c2293062d7c1fa472f299da764a7dbb3895ee22",
"icu_rev": "81d656878ec611cb0b42d52c82e9dae93920d9ba",
"intl_rev": "9145f308f1458f37630a1ffce3b7d3b471ebbc56",
"jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
diff --git a/docs/process/breaking-changes.md b/docs/process/breaking-changes.md
index 65d85f7..88f2e27 100644
--- a/docs/process/breaking-changes.md
+++ b/docs/process/breaking-changes.md
@@ -42,6 +42,12 @@
documentation (for example, must not mixin a class clearly documented as
not intended to be used as a mixin).
+* Must set an explicit
+ [language version constraint](https://dart.dev/guides/language/evolution#language-versioning)
+ to indicate which version of the language it requires. Incompatibilities
+ introduced in new language versions are not considered breaking as long as
+ the SDK continues to support the older version of the language.
+
Compatibility is only considered between stable releases (i.e. releases from the
[Dart stable channel](https://dart.dev/tools/sdk/archive#stable-channel)).
diff --git a/pkg/_js_interop_checks/lib/src/transformations/js_util_wasm_optimizer.dart b/pkg/_js_interop_checks/lib/src/transformations/js_util_wasm_optimizer.dart
index 5abcdc2..3cb0bdc 100644
--- a/pkg/_js_interop_checks/lib/src/transformations/js_util_wasm_optimizer.dart
+++ b/pkg/_js_interop_checks/lib/src/transformations/js_util_wasm_optimizer.dart
@@ -49,7 +49,7 @@
final Procedure _setPropertyTarget;
final Procedure _jsifyRawTarget;
final Procedure _newObjectTarget;
- final Procedure _wrapDartCallbackTarget;
+ final Procedure _wrapDartFunctionTarget;
final Procedure _allowInteropTarget;
final Class _wasmAnyRefClass;
final Class _objectClass;
@@ -57,7 +57,7 @@
final Field _pragmaName;
final Field _pragmaOptions;
final Member _globalThisMember;
- int _callbackTrampolineN = 1;
+ int _functionTrampolineN = 1;
final CoreTypes _coreTypes;
final StatefulStaticTypeContext _staticTypeContext;
@@ -77,8 +77,8 @@
.getTopLevelProcedure('dart:js_util', 'setProperty'),
_jsifyRawTarget = _coreTypes.index
.getTopLevelProcedure('dart:_js_helper', 'jsifyRaw'),
- _wrapDartCallbackTarget = _coreTypes.index
- .getTopLevelProcedure('dart:_js_helper', '_wrapDartCallback'),
+ _wrapDartFunctionTarget = _coreTypes.index
+ .getTopLevelProcedure('dart:_js_helper', '_wrapDartFunction'),
_newObjectTarget =
_coreTypes.index.getTopLevelProcedure('dart:js_util', 'newObject'),
_allowInteropTarget =
@@ -210,11 +210,11 @@
/// trampoline expects a Dart callback as its first argument, followed by all
/// of the arguments to the Dart callback as Dart objects. The trampoline will
/// cast all incoming Dart objects to the appropriate types, dispatch, and
- /// then `jsifyRaw` any returned value. [_createCallbackTrampoline] Returns a
+ /// then `jsifyRaw` any returned value. [_createFunctionTrampoline] Returns a
/// [String] function name representing the name of the wrapping function.
/// TODO(joshualitt): Share callback trampolines if the [FunctionType]
/// matches.
- String _createCallbackTrampoline(Procedure node, FunctionType function) {
+ String _createFunctionTrampoline(Procedure node, FunctionType function) {
int fileOffset = node.fileOffset;
Library library = node.enclosingLibrary;
@@ -245,11 +245,11 @@
// a native JS value before being returned to JS.
DartType nullableWasmAnyRefType =
_wasmAnyRefClass.getThisType(_coreTypes, Nullability.nullable);
- final callbackTrampolineName =
- '|_callbackTrampoline${_callbackTrampolineN++}';
- final callbackTrampolineImportName = '\$$callbackTrampolineName';
- final callbackTrampoline = Procedure(
- Name(callbackTrampolineName, library),
+ final functionTrampolineName =
+ '|_functionTrampoline${_functionTrampolineN++}';
+ final functionTrampolineImportName = '\$$functionTrampolineName';
+ final functionTrampoline = Procedure(
+ Name(functionTrampolineName, library),
ProcedureKind.Method,
FunctionNode(
ReturnStatement(StaticInvocation(
@@ -268,24 +268,24 @@
fileUri: node.fileUri)
..fileOffset = fileOffset
..isNonNullableByDefault = true;
- callbackTrampoline.addAnnotation(
+ functionTrampoline.addAnnotation(
ConstantExpression(InstanceConstant(_pragmaClass.reference, [], {
_pragmaName.fieldReference: StringConstant('wasm:export'),
_pragmaOptions.fieldReference:
- StringConstant(callbackTrampolineImportName)
+ StringConstant(functionTrampolineImportName)
})));
- library.addProcedure(callbackTrampoline);
- return callbackTrampolineImportName;
+ library.addProcedure(functionTrampoline);
+ return functionTrampolineImportName;
}
/// Lowers a [StaticInvocation] of `allowInterop` to
- /// [_createCallbackTrampoline] followed by `_wrapDartCallback`.
+ /// [_createFunctionTrampoline] followed by `_wrapDartFunction`.
StaticInvocation _allowInterop(
Procedure node, FunctionType type, Expression argument) {
- String callbackTrampolineName = _createCallbackTrampoline(node, type);
+ String functionTrampolineName = _createFunctionTrampoline(node, type);
return StaticInvocation(
- _wrapDartCallbackTarget,
- Arguments([argument, StringLiteral(callbackTrampolineName)],
+ _wrapDartFunctionTarget,
+ Arguments([argument, StringLiteral(functionTrampolineName)],
types: [type]));
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
index d9c3f09..ccea475 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
@@ -153,6 +153,7 @@
filterText: item.filterText,
insertText: newInsertText,
insertTextFormat: item.insertTextFormat,
+ insertTextMode: item.insertTextMode,
textEdit: supportsInsertReplace && insertionRange != replacementRange
? Either2<InsertReplaceEdit, TextEdit>.t1(
InsertReplaceEdit(
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index db49280..b3053c1 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -299,6 +299,10 @@
label += declaration.parameterNames?.isNotEmpty ?? false ? '(…)' : '()';
}
+ final insertionRange = toRange(lineInfo, replacementOffset, insertLength);
+ final replacementRange =
+ toRange(lineInfo, replacementOffset, replacementLength);
+
final insertTextInfo = _buildInsertText(
supportsSnippets: supportsSnippets,
includeCommitCharacters: includeCommitCharacters,
@@ -325,6 +329,7 @@
.contains(lsp.CompletionItemTag.Deprecated);
final supportsAsIsInsertMode =
capabilities.completionInsertTextModes.contains(InsertTextMode.asIs);
+ final supportsInsertReplace = capabilities.insertReplaceCompletionRanges;
final completionKind = declarationKindToCompletionItemKind(
capabilities.completionItemKinds, declaration.kind);
@@ -364,6 +369,20 @@
insertTextMode: supportsAsIsInsertMode && isMultilineCompletion
? InsertTextMode.asIs
: null,
+ textEdit: supportsInsertReplace && insertionRange != replacementRange
+ ? Either2<InsertReplaceEdit, TextEdit>.t1(
+ InsertReplaceEdit(
+ insert: insertionRange,
+ replace: replacementRange,
+ newText: insertText,
+ ),
+ )
+ : Either2<InsertReplaceEdit, TextEdit>.t2(
+ TextEdit(
+ range: replacementRange,
+ newText: insertText,
+ ),
+ ),
// data, used for completionItem/resolve.
data: lsp.DartSuggestionSetCompletionItemResolutionInfo(
file: file,
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_async.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_async.dart
index a26c922..f4585ed 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_async.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_async.dart
@@ -11,6 +11,8 @@
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
class AddAsync extends CorrectionProducer {
+ // todo(pq): consider adding a variation that adds an `await` as well
+
/// A flag indicating whether this producer is producing a fix in the case
/// where a function is missing a return at the end.
final bool isForMissingReturn;
diff --git a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
index 45ad2c3..3461471 100644
--- a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
+++ b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
@@ -1650,7 +1650,7 @@
LintCode.directives_ordering:
status: hasFix
LintCode.discarded_futures:
- status: needsEvaluation
+ status: hasFix
LintCode.do_not_use_environment:
status: needsEvaluation
LintCode.empty_catches:
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 02cf698..a6c5906 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -447,6 +447,9 @@
LintNames.directives_ordering: [
OrganizeImports.new,
],
+ LintNames.discarded_futures: [
+ AddAsync.new,
+ ],
LintNames.empty_catches: [
RemoveEmptyCatch.new,
],
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index 2ca0e71..e37937f 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -53,6 +53,7 @@
static const String diagnostic_describe_all_properties =
'diagnostic_describe_all_properties';
static const String directives_ordering = 'directives_ordering';
+ static const String discarded_futures = 'discarded_futures';
static const String empty_catches = 'empty_catches';
static const String empty_constructor_bodies = 'empty_constructor_bodies';
static const String empty_statements = 'empty_statements';
diff --git a/pkg/analysis_server/test/lsp/completion_dart_test.dart b/pkg/analysis_server/test/lsp/completion_dart_test.dart
index 81b8f26..f55c2bd 100644
--- a/pkg/analysis_server/test/lsp/completion_dart_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_dart_test.dart
@@ -480,11 +480,13 @@
// placeholders.
expect(item.insertTextFormat, equals(InsertTextFormat.Snippet));
expect(item.insertText, equals(r'myFunction(${1:a}, ${2:b}, c: ${3:c})'));
- expect(item.textEdit, isNull);
+ expect(item.textEdit, isNotNull);
+ final originalTextEdit = item.textEdit;
- // Ensure the item can be resolved and gets a proper TextEdit.
+ // Ensure the item can be resolved and retains the correct textEdit (since
+ // textEdit may be recomputed during resolve).
final resolved = await resolveCompletion(item);
- expect(resolved.textEdit, isNotNull);
+ expect(resolved.textEdit, originalTextEdit);
final textEdit = toTextEdit(resolved.textEdit!);
expect(textEdit.newText, equals(item.insertText));
expect(textEdit.range, equals(rangeFromMarkers(content)));
@@ -1612,21 +1614,24 @@
// Find the completion for the class in the other file.
final completion = res.singleWhere((c) => c.label == 'InOtherFile');
expect(completion, isNotNull);
+ expect(completion.textEdit, isNotNull);
+ final originalTextEdit = completion.textEdit;
- // Expect no docs or text edit, since these are added during resolve.
+ // Expect no docs, this is added during resolve.
expect(completion.documentation, isNull);
- expect(completion.textEdit, isNull);
- // Resolve the completion item (via server) to get its edits. This is the
- // LSP's equiv of getSuggestionDetails() and is invoked by LSP clients to
- // populate additional info (in our case, the additional edits for inserting
- // the import).
+ // Resolve the completion item (via server) to get any additional edits.
+ // This is LSP's equiv of getSuggestionDetails() and is invoked by LSP
+ // clients to populate additional info (in our case, any additional edits
+ // for inserting the import).
final resolved = await resolveCompletion(completion);
expect(resolved, isNotNull);
// Ensure the detail field was update to show this will auto-import.
expect(
- resolved.detail, startsWith("Auto import from '../other_file.dart'"));
+ resolved.detail,
+ startsWith("Auto import from '../other_file.dart'"),
+ );
// Ensure the doc comment was added.
expect(
@@ -1634,8 +1639,8 @@
isTrue,
);
- // Ensure the edit was added on.
- expect(resolved.textEdit, isNotNull);
+ // Ensure the edit did not change.
+ expect(resolved.textEdit, originalTextEdit);
// There should be no command for this item because it doesn't need imports
// in other files. Same-file completions are in additionalEdits.
@@ -2047,21 +2052,24 @@
// Find the completion for the class in the other file.
final completion = res.singleWhere((c) => c.label == 'InOtherFile');
expect(completion, isNotNull);
+ expect(completion.textEdit, isNotNull);
+ final originalTextEdit = completion.textEdit;
- // Expect no docs or text edit, since these are added during resolve.
+ // Expect no docs, this is added during resolve.
expect(completion.documentation, isNull);
- expect(completion.textEdit, isNull);
- // Resolve the completion item (via server) to get its edits. This is the
- // LSP's equiv of getSuggestionDetails() and is invoked by LSP clients to
- // populate additional info (in our case, the additional edits for inserting
- // the import).
+ // Resolve the completion item (via server) to get any additional edits.
+ // This is LSP's equiv of getSuggestionDetails() and is invoked by LSP
+ // clients to populate additional info (in our case, any additional edits
+ // for inserting the import).
final resolved = await resolveCompletion(completion);
expect(resolved, isNotNull);
// Ensure the detail field was update to show this will auto-import.
expect(
- resolved.detail, startsWith("Auto import from '../other_file.dart'"));
+ resolved.detail,
+ startsWith("Auto import from '../other_file.dart'"),
+ );
// Ensure the doc comment was added.
expect(
@@ -2069,8 +2077,8 @@
isTrue,
);
- // Ensure the edit was added on.
- expect(resolved.textEdit, isNotNull);
+ // Ensure the edit did not change.
+ expect(resolved.textEdit, originalTextEdit);
// There should be no command for this item because it doesn't need imports
// in other files. Same-file completions are in additionalEdits.
@@ -2265,15 +2273,15 @@
final completion =
res.singleWhere((c) => c.label == 'InOtherFile.fromJson()');
expect(completion, isNotNull);
+ expect(completion.textEdit, isNotNull);
- // Expect no docs or text edit, since these are added during resolve.
+ // Expect no docs, this is added during resolve.
expect(completion.documentation, isNull);
- expect(completion.textEdit, isNull);
- // Resolve the completion item (via server) to get its edits. This is the
- // LSP's equiv of getSuggestionDetails() and is invoked by LSP clients to
- // populate additional info (in our case, the additional edits for inserting
- // the import).
+ // Resolve the completion item (via server) to get any additional edits.
+ // This is LSP's equiv of getSuggestionDetails() and is invoked by LSP
+ // clients to populate additional info (in our case, any additional edits
+ // for inserting the import).
final resolved = await resolveCompletion(completion);
expect(resolved, isNotNull);
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_async_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_async_test.dart
index df3eb40..aff2684 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_async_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_async_test.dart
@@ -14,6 +14,7 @@
defineReflectiveSuite(() {
defineReflectiveTests(AddAsyncTest);
defineReflectiveTests(AvoidReturningNullForFutureTest);
+ defineReflectiveTests(DiscardedFuturesTest);
});
}
@@ -358,3 +359,29 @@
''');
}
}
+
+@reflectiveTest
+class DiscardedFuturesTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.ADD_ASYNC;
+
+ @override
+ String get lintCode => LintNames.discarded_futures;
+
+ Future<void> test_discardedFuture() async {
+ await resolveTestCode('''
+void f() {
+ g();
+}
+
+Future<void> g() async { }
+''');
+ await assertHasFix('''
+Future<void> f() async {
+ g();
+}
+
+Future<void> g() async { }
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/tool/lsp_spec/readme_test.dart b/pkg/analysis_server/test/tool/lsp_spec/readme_test.dart
new file mode 100644
index 0000000..81a8633
--- /dev/null
+++ b/pkg/analysis_server/test/tool/lsp_spec/readme_test.dart
@@ -0,0 +1,48 @@
+// 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:io';
+
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+import '../../../tool/lsp_spec/meta_model_reader.dart';
+
+void main() {
+ final serverPkgPath = _getAnalysisServerPkgPath();
+ final readmeFile = File(path.join(serverPkgPath, 'tool/lsp_spec/README.md'));
+ final metaModelJsonFile =
+ File(path.join(serverPkgPath, 'tool/lsp_spec/lsp_meta_model.json'));
+
+ group('LSP readme', () {
+ test('contains all methods', () {
+ final readmeContent = readmeFile.readAsStringSync();
+ final model = LspMetaModelReader().readFile(metaModelJsonFile);
+
+ final missingMethods = StringBuffer();
+ for (final method in model.methods) {
+ // Handle `foo/*` in the readme as well as `foo/bar`.
+ final methodWildcard = method.replaceAll(RegExp(r'\/[^\/]+$'), '/*');
+ if (!readmeContent.contains(' $method ') &&
+ !readmeContent.contains(' $methodWildcard ')) {
+ missingMethods.writeln(method);
+ }
+ }
+
+ if (missingMethods.isNotEmpty) {
+ fail(
+ 'The following Methods are not listed in the README.md file:\n\n'
+ '$missingMethods',
+ );
+ }
+ });
+ });
+}
+
+String _getAnalysisServerPkgPath() {
+ final script = Platform.script.toFilePath();
+ final components = path.split(script);
+ final index = components.indexOf('analysis_server');
+ return path.joinAll(components.sublist(0, index + 1));
+}
diff --git a/pkg/analysis_server/test/tool/lsp_spec/test_all.dart b/pkg/analysis_server/test/tool/lsp_spec/test_all.dart
index 62b595f..c101149 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/test_all.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/test_all.dart
@@ -8,6 +8,7 @@
import 'generated_classes_test.dart' as generated_classes_test;
import 'json_test.dart' as json_test;
import 'meta_model_test.dart' as meta_model_test;
+import 'readme_test.dart' as readme_test;
void main() {
defineReflectiveSuite(() {
@@ -15,5 +16,6 @@
generated_classes_test.main();
json_test.main();
meta_model_test.main();
+ readme_test.main();
}, name: 'lsp-tool');
}
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index 5c4e9fa..e2cdc3d 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -53,66 +53,101 @@
- Tests: Has automated tests
- Tested Client: Has been manually tested in at least one LSP client editor
-| Method | Basic Impl | Capabilities | Plugins | Tests | Tested Client | Notes |
-| - | - | - | - | - | - | - |
-| initialize | ✅ | ✅ | N/A | ✅ | ✅ | trace and other options NYI
-| initialized | ✅ | ✅ | N/A | ✅ | ✅ |
-| shutdown | ✅ | ✅ | N/A | ✅ | ✅ | supported but does nothing |
-| exit | ✅ | ✅ | N/A | ✅ | ✅ |
-| $/cancelRequest | ✅ | ✅ | | ✅ | ✅ |
-| window/showMessage | ✅ | | | | |
-| window/showMessageRequest | | | | | |
-| window/logMessage | ✅ | | | | |
-| telemetry/event | | | | | |
-| client/registerCapability | ✅ | ✅ | ✅ | ✅ | ✅ |
-| client/unregisterCapability | ✅ | ✅ | ✅ | ✅ | ✅ |
-| workspace/workspaceFolders | | | | | |
-| workspace/didChangeWorkspaceFolders | ✅ | ✅ | ✅ | ✅ | ✅ |
-| workspace/didChangeConfiguration | ✅ | ✅ | | ✅ | ✅ |
-| workspace/configuration | ✅ | ✅ | | ✅ | ✅ |
-| workspace/didChangeWatchedFiles | | | | | | unused, server does own watching |
-| workspace/symbol | ✅ | ✅ | | ✅ | ✅ |
-| workspace/executeCommand | ✅ | ✅ | | ✅ | ✅ |
-| workspace/applyEdit | ✅ | ✅ | | ✅ | ✅ |
-| workspace/onWillRenameFiles | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/didOpen | ✅ | ✅ | ✅ | ✅ | ✅ |
-| textDocument/didChange | ✅ | ✅ | ✅ | ✅ | ✅ |
-| textDocument/willSave | | | | | |
-| textDocument/willSaveWaitUntil | | | | | |
-| textDocument/didClose | ✅ | ✅ | ✅ | ✅ | ✅ |
-| textDocument/publishDiagnostics | ✅ | ✅ | ✅ | ✅ | ✅ |
-| textDocument/completion | ✅ | ✅ | ✅ | ✅ | ✅ |
-| completionItem/resolve | ✅ | ✅ | ✅ | ✅ | ✅ |
-| textDocument/hover | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/signatureHelp | ✅ | ✅ | | ✅ | ✅ | trigger character handling outstanding
-| textDocument/declaration | | | | | |
-| textDocument/definition | ✅ | ✅ | ✅ | ✅ | ✅ |
-| textDocument/typeDefinition | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/implementation | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/references | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/documentHighlight | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/documentSymbol | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/selectionRanges | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/codeAction (sortMembers) | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/codeAction (organiseImports) | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/codeAction (fixAll) | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/codeAction (refactors) | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/codeAction (assists) | ✅ | ✅ | ✅ | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `Refactor`
-| textDocument/codeAction (fixes) | ✅ | ✅ | ✅ | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `QuickFix`
-| textDocument/codeLens | | | | | |
-| codeLens/resolve | | | | | |
-| textDocument/documentLink | | | | | |
-| documentLink/resolve | | | | | |
-| textDocument/documentColor | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/colorPresentation | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/formatting | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/rangeFormatting | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/onTypeFormatting | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/rename | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/prepareRename | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/foldingRange | ✅ | ✅ | ✅ | ✅ | ✅ |
-| textDocument/semanticTokens/full | ✅ | ✅ | ✅ | ✅ | ✅ |
-| textDocument/semanticTokens/range | ✅ | ✅ | ✅ | ✅ | ✅ |
+| Method | Server | Plugins | Notes |
+| - | - | - | - |
+| initialize | ✅ | N/A | trace and other options NYI|
+| initialized | ✅ | N/A | |
+| shutdown | ✅ | N/A | supported but does nothing|
+| exit | ✅ | N/A | |
+| $/cancelRequest | ✅ | | |
+| $/logTrace | | | |
+| $/progress | | | |
+| $/setTrace | | | |
+| client/registerCapability | ✅ | ✅ | |
+| client/unregisterCapability | ✅ | ✅ | |
+| notebookDocument/* | | | |
+| telemetry/event | | | |
+| textDocument/codeAction (assists) | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `Refactor`|
+| textDocument/codeAction (fixAll) | ✅ | | |
+| textDocument/codeAction (fixes) | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `QuickFix`|
+| textDocument/codeAction (organiseImports) | ✅ | | |
+| textDocument/codeAction (refactors) | ✅ | | |
+| textDocument/codeAction (sortMembers) | ✅ | | |
+| codeAction/resolve | | | |
+| textDocument/codeLens | | | |
+| codeLens/resolve | | | |
+| textDocument/completion | ✅ | ✅ | |
+| completionItem/resolve | ✅ | | |
+| textDocument/declaration | | | |
+| textDocument/definition | ✅ | ✅ | |
+| textDocument/diagnostic | | | |
+| textDocument/didChange | ✅ | ✅ | |
+| textDocument/didClose | ✅ | ✅ | |
+| textDocument/didOpen | ✅ | ✅ | |
+| textDocument/didSave | | | |
+| textDocument/documentColor | ✅ | | |
+| textDocument/colorPresentation | ✅ | | |
+| textDocument/documentHighlight | ✅ | | |
+| textDocument/documentLink | | | |
+| documentLink/resolve | | | |
+| textDocument/documentSymbol | ✅ | | |
+| textDocument/foldingRange | ✅ | ✅ | |
+| textDocument/formatting | ✅ | | |
+| textDocument/onTypeFormatting | ✅ | | |
+| textDocument/rangeFormatting | ✅ | | |
+| textDocument/hover | ✅ | | |
+| textDocument/implementation | ✅ | | |
+| textDocument/inlayHint | | | |
+| inlayHint/resolve | | | |
+| textDocument/inlineValue | | | |
+| textDocument/linkedEditingRange | | | |
+| textDocument/moniker | | | |
+| textDocument/prepareCallHierarchy | | | |
+| callHierarchy/incomingCalls | | | |
+| callHierarchy/outgoingCalls | | | |
+| textDocument/prepareRename | ✅ | | |
+| textDocument/rename | ✅ | | |
+| textDocument/prepareTypeHierarchy | | | |
+| typeHierarchy/subtypes | | | |
+| typeHierarchy/supertypes | | | |
+| textDocument/publishDiagnostics | ✅ | ✅ | |
+| textDocument/references | ✅ | | |
+| textDocument/selectionRange | ✅ | | |
+| textDocument/semanticTokens/full | ✅ | ✅ | |
+| textDocument/semanticTokens/full/delta | | | |
+| textDocument/semanticTokens/range | ✅ | ✅ | |
+| workspace/semanticTokens/refresh | | | |
+| textDocument/signatureHelp | ✅ | | |
+| textDocument/typeDefinition | ✅ | | |
+| textDocument/willSave | | | |
+| textDocument/willSaveWaitUntil | | | |
+| window/logMessage | ✅ | | |
+| window/showDocument | | | |
+| window/showMessage | ✅ | | |
+| window/showMessageRequest | | | |
+| window/workDoneProgress/cancel | | | |
+| window/workDoneProgress/create | ✅ | | |
+| workspace/applyEdit | ✅ | | |
+| workspace/codeLens/refresh | | | |
+| workspace/configuration | ✅ | | |
+| workspace/diagnostic | | | |
+| workspace/diagnostic/refresh | | | |
+| workspace/didChangeConfiguration | ✅ | | |
+| workspace/didChangeWatchedFiles | | | unused, server does own watching|
+| workspace/didChangeWorkspaceFolders | ✅ | ✅ | |
+| workspace/didCreateFiles | | | |
+| workspace/didDeleteFiles | | | |
+| workspace/didRenameFiles | | | |
+| workspace/executeCommand | ✅ | | |
+| workspace/inlayHint/refresh | | | |
+| workspace/inlineValue/refresh | | | |
+| workspace/symbol | ✅ | | |
+| workspaceSymbol/resolve | | | |
+| workspace/willCreateFiles | | | |
+| workspace/willDeleteFiles | | | |
+| workspace/willRenameFiles | | | |
+| workspace/willRenameFiles | ✅ | | |
+| workspace/workspaceFolders | | | |
## Custom Fields, Methods and Notifications
diff --git a/pkg/analysis_server/tool/lsp_spec/meta_model.dart b/pkg/analysis_server/tool/lsp_spec/meta_model.dart
index 5f8d860..f6a0835 100644
--- a/pkg/analysis_server/tool/lsp_spec/meta_model.dart
+++ b/pkg/analysis_server/tool/lsp_spec/meta_model.dart
@@ -180,8 +180,9 @@
class LspMetaModel {
final List<LspEntity> types;
+ final List<String> methods;
- LspMetaModel(this.types);
+ LspMetaModel({required this.types, required this.methods});
}
/// A [Map] type parsed from the LSP JSON model.
diff --git a/pkg/analysis_server/tool/lsp_spec/meta_model_cleaner.dart b/pkg/analysis_server/tool/lsp_spec/meta_model_cleaner.dart
index e28c919..ef71c3d 100644
--- a/pkg/analysis_server/tool/lsp_spec/meta_model_cleaner.dart
+++ b/pkg/analysis_server/tool/lsp_spec/meta_model_cleaner.dart
@@ -27,7 +27,7 @@
/// Cleans an entire [LspMetaModel].
LspMetaModel cleanModel(LspMetaModel model) {
final types = cleanTypes(model.types);
- return LspMetaModel(types);
+ return LspMetaModel(types: types, methods: model.methods);
}
/// Cleans a List of types.
diff --git a/pkg/analysis_server/tool/lsp_spec/meta_model_reader.dart b/pkg/analysis_server/tool/lsp_spec/meta_model_reader.dart
index 7b8919b..2da612d 100644
--- a/pkg/analysis_server/tool/lsp_spec/meta_model_reader.dart
+++ b/pkg/analysis_server/tool/lsp_spec/meta_model_reader.dart
@@ -40,18 +40,20 @@
final structures = model['structures'] as List?;
final enums = model['enumerations'] as List?;
final typeAliases = model['typeAliases'] as List?;
+ final methodNames = [...?requests, ...?notifications]
+ .map((item) => item['method'] as String)
+ .toList();
[
...?structures?.map(_readStructure),
...?enums?.map((e) => _readEnum(e)),
...?typeAliases?.map(_readTypeAlias),
].forEach(_addType);
- final methodNames =
- _createMethodNamesEnum([...?requests, ...?notifications]);
- if (methodNames != null) {
- _addType(methodNames);
+ final methodsEnum = _createMethodNamesEnum(methodNames);
+ if (methodsEnum != null) {
+ _addType(methodsEnum);
}
- return LspMetaModel(types);
+ return LspMetaModel(types: types, methods: methodNames);
}
/// Adds [type] to the current list and prevents its name from being used
@@ -65,7 +67,7 @@
str.substring(0, 1).toLowerCase() + str.substring(1);
/// Creates an enum for all LSP method names.
- LspEnum? _createMethodNamesEnum(List items) {
+ LspEnum? _createMethodNamesEnum(List<String> methods) {
Constant toConstant(String value) {
final comment = '''Constant for the '$value' method.''';
return Constant(
@@ -76,8 +78,7 @@
);
}
- final methodConstants =
- items.map((item) => item['method'] as String).map(toConstant).toList();
+ final methodConstants = methods.map(toConstant).toList();
if (methodConstants.isEmpty) {
return null;
diff --git a/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart b/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
index ea0c573..acbd3f8 100644
--- a/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
@@ -6,13 +6,6 @@
import 'package:meta/meta.dart';
-class CacheData {
- final int id;
- final Uint8List bytes;
-
- CacheData(this.id, this.bytes);
-}
-
/// Store of bytes associated with string keys and a hash.
///
/// Each key must be not longer than 100 characters and consist of only `[a-z]`,
@@ -40,18 +33,11 @@
void release(Iterable<String> keys);
}
-class CiderByteStoreTestView {
- int length = 0;
-}
-
/// [CiderByteStore] that keeps all data in local memory.
class MemoryCiderByteStore implements CiderByteStore {
@visibleForTesting
final Map<String, MemoryCiderByteStoreEntry> map = {};
- /// This field gets value only during testing.
- CiderByteStoreTestView? testView;
-
@override
Uint8List? get(String key) {
final entry = map[key];
@@ -69,7 +55,6 @@
throw StateError('Overwriting is not allowed: $key');
}
- testView?.length++;
map[key] = MemoryCiderByteStoreEntry._(bytes);
return bytes;
}
diff --git a/pkg/analyzer/test/src/dart/micro/file_resolution.dart b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
index 8f688a4..fefd22b 100644
--- a/pkg/analyzer/test/src/dart/micro/file_resolution.dart
+++ b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
@@ -85,7 +85,6 @@
convertPath(_testFile),
)!;
- byteStore.testView = CiderByteStoreTestView();
fileResolver = FileResolver(
logger: logger,
resourceProvider: resourceProvider,
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart
index 6e5d625..b6dca48 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/container_type_mask.dart
@@ -17,8 +17,9 @@
@override
final TypeMask forwardTo;
+ final ir.Node /*?*/ _allocationNode;
@override
- final ir.Node allocationNode;
+ ir.Node get allocationNode => _allocationNode /*!*/;
@override
final MemberEntity allocationElement;
@@ -29,7 +30,7 @@
// The length of the container.
final int length;
- const ContainerTypeMask(this.forwardTo, this.allocationNode,
+ const ContainerTypeMask(this.forwardTo, this._allocationNode,
this.allocationElement, this.elementType, this.length);
/// Deserializes a [ContainerTypeMask] object from [source].
@@ -37,13 +38,12 @@
DataSourceReader source, CommonMasks domain) {
source.begin(tag);
TypeMask forwardTo = TypeMask.readFromDataSource(source, domain);
- ir.TreeNode allocationNode = source.readTreeNodeOrNull();
MemberEntity allocationElement = source.readMemberOrNull();
TypeMask elementType = TypeMask.readFromDataSource(source, domain);
int length = source.readIntOrNull();
source.end(tag);
return ContainerTypeMask(
- forwardTo, allocationNode, allocationElement, elementType, length);
+ forwardTo, null, allocationElement, elementType, length);
}
/// Serializes this [ContainerTypeMask] to [sink].
@@ -52,7 +52,6 @@
sink.writeEnum(TypeMaskKind.container);
sink.begin(tag);
forwardTo.writeToDataSink(sink);
- sink.writeTreeNodeOrNull(allocationNode);
sink.writeMemberOrNull(allocationElement);
elementType.writeToDataSink(sink);
sink.writeIntOrNull(length);
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
index fe414d6..c2a4730 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/dictionary_type_mask.dart
@@ -34,15 +34,14 @@
DataSourceReader source, CommonMasks domain) {
source.begin(tag);
TypeMask forwardTo = TypeMask.readFromDataSource(source, domain);
- ir.TreeNode allocationNode = source.readTreeNodeOrNull();
MemberEntity allocationElement = source.readMemberOrNull();
TypeMask keyType = TypeMask.readFromDataSource(source, domain);
TypeMask valueType = TypeMask.readFromDataSource(source, domain);
Map<String, TypeMask> typeMap =
source.readStringMap(() => TypeMask.readFromDataSource(source, domain));
source.end(tag);
- return DictionaryTypeMask(forwardTo, allocationNode, allocationElement,
- keyType, valueType, typeMap);
+ return DictionaryTypeMask(
+ forwardTo, null, allocationElement, keyType, valueType, typeMap);
}
/// Serializes this [DictionaryTypeMask] to [sink].
@@ -51,7 +50,6 @@
sink.writeEnum(TypeMaskKind.dictionary);
sink.begin(tag);
forwardTo.writeToDataSink(sink);
- sink.writeTreeNodeOrNull(allocationNode);
sink.writeMemberOrNull(allocationElement);
keyType.writeToDataSink(sink);
valueType.writeToDataSink(sink);
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
index 7b2651b..16e1cff 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/forwarding_type_mask.dart
@@ -166,8 +166,11 @@
abstract class AllocationTypeMask extends ForwardingTypeMask {
const AllocationTypeMask();
- // The [ir.Node] where this type mask was created.
- ir.Node get allocationNode;
+ // The [ir.Node] where this type mask was created. This value is not used
+ // after type inference and therefore does not need to be serialized by
+ // subclasses. Using it outside of type inference may cause an exception to be
+ // thrown.
+ ir.Node /*?*/ get allocationNode;
// The [Entity] where this type mask was created.
MemberEntity get allocationElement;
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
index 22bb146..20f5caa 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/map_type_mask.dart
@@ -17,8 +17,9 @@
@override
final TypeMask forwardTo;
+ final ir.Node /*?*/ _allocationNode;
@override
- final ir.Node allocationNode;
+ ir.Node get allocationNode => _allocationNode /*!*/;
@override
final MemberEntity allocationElement;
@@ -29,21 +30,19 @@
// The key type of this map.
final TypeMask keyType;
- const MapTypeMask(this.forwardTo, this.allocationNode, this.allocationElement,
- this.keyType, this.valueType);
+ const MapTypeMask(this.forwardTo, this._allocationNode,
+ this.allocationElement, this.keyType, this.valueType);
/// Deserializes a [MapTypeMask] object from [source].
factory MapTypeMask.readFromDataSource(
DataSourceReader source, CommonMasks domain) {
source.begin(tag);
TypeMask forwardTo = TypeMask.readFromDataSource(source, domain);
- ir.TreeNode allocationNode = source.readTreeNodeOrNull();
MemberEntity allocationElement = source.readMemberOrNull();
TypeMask keyType = TypeMask.readFromDataSource(source, domain);
TypeMask valueType = TypeMask.readFromDataSource(source, domain);
source.end(tag);
- return MapTypeMask(
- forwardTo, allocationNode, allocationElement, keyType, valueType);
+ return MapTypeMask(forwardTo, null, allocationElement, keyType, valueType);
}
/// Serializes this [MapTypeMask] to [sink].
@@ -52,7 +51,6 @@
sink.writeEnum(TypeMaskKind.map);
sink.begin(tag);
forwardTo.writeToDataSink(sink);
- sink.writeTreeNodeOrNull(allocationNode);
sink.writeMemberOrNull(allocationElement);
keyType.writeToDataSink(sink);
valueType.writeToDataSink(sink);
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/set_type_mask.dart b/pkg/compiler/lib/src/inferrer/typemasks/set_type_mask.dart
index ece92e5..2e83741 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/set_type_mask.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/set_type_mask.dart
@@ -17,8 +17,9 @@
@override
final TypeMask forwardTo;
+ final ir.Node /*?*/ _allocationNode;
@override
- final ir.Node allocationNode;
+ ir.Node get allocationNode => _allocationNode /*!*/;
@override
final MemberEntity allocationElement;
@@ -26,20 +27,18 @@
// The element type of this set.
final TypeMask elementType;
- const SetTypeMask(this.forwardTo, this.allocationNode, this.allocationElement,
- this.elementType);
+ const SetTypeMask(this.forwardTo, this._allocationNode,
+ this.allocationElement, this.elementType);
/// Deserializes a [SetTypeMask] object from [source].
factory SetTypeMask.readFromDataSource(
DataSourceReader source, CommonMasks domain) {
source.begin(tag);
TypeMask forwardTo = TypeMask.readFromDataSource(source, domain);
- ir.TreeNode allocationNode = source.readTreeNodeOrNull();
MemberEntity allocationElement = source.readMemberOrNull();
TypeMask elementType = TypeMask.readFromDataSource(source, domain);
source.end(tag);
- return SetTypeMask(
- forwardTo, allocationNode, allocationElement, elementType);
+ return SetTypeMask(forwardTo, null, allocationElement, elementType);
}
/// Serializes this [SetTypeMask] to [sink].
@@ -48,7 +47,6 @@
sink.writeEnum(TypeMaskKind.set);
sink.begin(tag);
forwardTo.writeToDataSink(sink);
- sink.writeTreeNodeOrNull(allocationNode);
sink.writeMemberOrNull(allocationElement);
elementType.writeToDataSink(sink);
sink.end(tag);
diff --git a/pkg/compiler/lib/src/js_backend/annotations.dart b/pkg/compiler/lib/src/js_backend/annotations.dart
index fe70a94..7fc51bc 100644
--- a/pkg/compiler/lib/src/js_backend/annotations.dart
+++ b/pkg/compiler/lib/src/js_backend/annotations.dart
@@ -22,6 +22,10 @@
final bool forFieldsOnly;
final bool internalOnly;
+ // TODO(sra): Review [forFunctionsOnly] and [forFieldsOnly]. Fields have
+ // implied getters and setters, so some annotations meant only for functions
+ // could reasonable be placed on a field to apply to the getter and setter.
+
const PragmaAnnotation(this._index, this.name,
{this.forFunctionsOnly = false,
this.forFieldsOnly = false,
@@ -41,15 +45,20 @@
static const PragmaAnnotation tryInline =
PragmaAnnotation(1, 'tryInline', forFunctionsOnly: true);
+ /// Annotation on a member that tells the optimizing compiler to disable
+ /// inlining at call sites within the member.
+ static const PragmaAnnotation disableInlining =
+ PragmaAnnotation(2, 'disable-inlining');
+
static const PragmaAnnotation disableFinal = PragmaAnnotation(
- 2, 'disableFinal',
+ 3, 'disableFinal',
forFunctionsOnly: true, internalOnly: true);
- static const PragmaAnnotation noElision = PragmaAnnotation(3, 'noElision');
+ static const PragmaAnnotation noElision = PragmaAnnotation(4, 'noElision');
/// Tells the optimizing compiler that the annotated method cannot throw.
/// Requires @pragma('dart2js:noInline') to function correctly.
- static const PragmaAnnotation noThrows = PragmaAnnotation(4, 'noThrows',
+ static const PragmaAnnotation noThrows = PragmaAnnotation(5, 'noThrows',
forFunctionsOnly: true, internalOnly: true);
/// Tells the optimizing compiler that the annotated method has no
@@ -58,7 +67,7 @@
///
/// Requires @pragma('dart2js:noInline') to function correctly.
static const PragmaAnnotation noSideEffects = PragmaAnnotation(
- 5, 'noSideEffects',
+ 6, 'noSideEffects',
forFunctionsOnly: true, internalOnly: true);
/// Use this as metadata on method declarations to disable closed world
@@ -66,48 +75,49 @@
/// could be any value. Note that the constraints due to static types still
/// apply.
static const PragmaAnnotation assumeDynamic = PragmaAnnotation(
- 6, 'assumeDynamic',
+ 7, 'assumeDynamic',
forFunctionsOnly: true, internalOnly: true);
- static const PragmaAnnotation asTrust = PragmaAnnotation(7, 'as:trust',
+ static const PragmaAnnotation asTrust = PragmaAnnotation(8, 'as:trust',
forFunctionsOnly: false, internalOnly: false);
- static const PragmaAnnotation asCheck = PragmaAnnotation(8, 'as:check',
+ static const PragmaAnnotation asCheck = PragmaAnnotation(9, 'as:check',
forFunctionsOnly: false, internalOnly: false);
- static const PragmaAnnotation typesTrust = PragmaAnnotation(9, 'types:trust',
+ static const PragmaAnnotation typesTrust = PragmaAnnotation(10, 'types:trust',
forFunctionsOnly: false, internalOnly: false);
- static const PragmaAnnotation typesCheck = PragmaAnnotation(10, 'types:check',
+ static const PragmaAnnotation typesCheck = PragmaAnnotation(11, 'types:check',
forFunctionsOnly: false, internalOnly: false);
static const PragmaAnnotation parameterTrust = PragmaAnnotation(
- 11, 'parameter:trust',
+ 12, 'parameter:trust',
forFunctionsOnly: false, internalOnly: false);
static const PragmaAnnotation parameterCheck = PragmaAnnotation(
- 12, 'parameter:check',
+ 13, 'parameter:check',
forFunctionsOnly: false, internalOnly: false);
static const PragmaAnnotation downcastTrust = PragmaAnnotation(
- 13, 'downcast:trust',
+ 14, 'downcast:trust',
forFunctionsOnly: false, internalOnly: false);
static const PragmaAnnotation downcastCheck = PragmaAnnotation(
- 14, 'downcast:check',
+ 15, 'downcast:check',
forFunctionsOnly: false, internalOnly: false);
static const PragmaAnnotation indexBoundsTrust = PragmaAnnotation(
- 15, 'index-bounds:trust',
+ 16, 'index-bounds:trust',
forFunctionsOnly: false, internalOnly: false);
static const PragmaAnnotation indexBoundsCheck = PragmaAnnotation(
- 16, 'index-bounds:check',
+ 17, 'index-bounds:check',
forFunctionsOnly: false, internalOnly: false);
static const List<PragmaAnnotation> values = [
noInline,
tryInline,
+ disableInlining,
disableFinal,
noElision,
noThrows,
@@ -273,6 +283,9 @@
/// annotation.
bool hasTryInline(MemberEntity member);
+ /// Returns `true` if inlining is disabled at call sites inside [member].
+ bool hasDisableInlining(MemberEntity member);
+
/// Returns `true` if [member] has a `@pragma('dart2js:disableFinal')`
/// annotation.
bool hasDisableFinal(MemberEntity member);
@@ -343,6 +356,7 @@
final CheckPolicy _defaultConditionCheckPolicy;
final CheckPolicy _defaultExplicitCastCheckPolicy;
final CheckPolicy _defaultIndexBoundsCheckPolicy;
+ final bool _defaultDisableInlining;
final Map<MemberEntity, EnumSet<PragmaAnnotation>> pragmaAnnotations;
AnnotationsDataImpl(CompilerOptions options, this.pragmaAnnotations)
@@ -353,7 +367,8 @@
this._defaultExplicitCastCheckPolicy =
options.defaultExplicitCastCheckPolicy,
this._defaultIndexBoundsCheckPolicy =
- options.defaultIndexBoundsCheckPolicy;
+ options.defaultIndexBoundsCheckPolicy,
+ this._defaultDisableInlining = options.disableInlining;
factory AnnotationsDataImpl.readFromDataSource(
CompilerOptions options, DataSourceReader source) {
@@ -393,6 +408,11 @@
_hasPragma(member, PragmaAnnotation.tryInline);
@override
+ bool hasDisableInlining(MemberEntity member) =>
+ _hasPragma(member, PragmaAnnotation.disableInlining) ||
+ _defaultDisableInlining;
+
+ @override
bool hasDisableFinal(MemberEntity member) =>
_hasPragma(member, PragmaAnnotation.disableFinal);
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 8445d27..af68bc6 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -5830,6 +5830,13 @@
return false;
}
+ // Check if inlining is disabled for the current element (includes globally)
+ // before making decsions on the basis of the callee so that cached callee
+ // decisions are not a function of the call site's method.
+ if (closedWorld.annotationsData.hasDisableInlining(_currentFrame.member)) {
+ return false;
+ }
+
bool insideLoop = loopDepth > 0 || graph.calledInLoop;
// Bail out early if the inlining decision is in the cache and we can't
@@ -5840,8 +5847,6 @@
if (cachedCanBeInlined == false) return false;
bool meetsHardConstraints() {
- if (options.disableInlining) return false;
-
assert(
selector != null ||
function.isStatic ||
diff --git a/pkg/compiler/test/annotations/data/basic.dart b/pkg/compiler/test/annotations/data/basic.dart
index c7f29c9..5ffc870 100644
--- a/pkg/compiler/test/annotations/data/basic.dart
+++ b/pkg/compiler/test/annotations/data/basic.dart
@@ -11,6 +11,8 @@
noThrows();
noSideEffects();
assumeDynamic();
+ disableInlining();
+ several();
}
/*member: noInline:noInline*/
@@ -38,3 +40,15 @@
/*member: assumeDynamic:assumeDynamic*/
@pragma('dart2js:assumeDynamic')
assumeDynamic() {}
+
+/*member: disableInlining:disable-inlining*/
+@pragma('dart2js:disable-inlining')
+disableInlining() {}
+
+/*member: several:assumeDynamic,disable-inlining,noInline,noSideEffects,noThrows*/
+@pragma('dart2js:disable-inlining')
+@pragma('dart2js:noThrows')
+@pragma('dart2js:noSideEffects')
+@pragma('dart2js:assumeDynamic')
+@pragma('dart2js:noInline')
+several() {}
diff --git a/pkg/compiler/test/codegen/data/inlining_annotations.dart b/pkg/compiler/test/codegen/data/inlining_annotations.dart
new file mode 100644
index 0000000..4702bfd
--- /dev/null
+++ b/pkg/compiler/test/codegen/data/inlining_annotations.dart
@@ -0,0 +1,76 @@
+// 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.
+
+/*member: foo1:ignore*/
+@pragma('dart2js:tryInline')
+int foo1() => bar1();
+
+/*member: foo2:ignore*/
+@pragma('dart2js:tryInline')
+@pragma('dart2js:disable-inlining')
+int foo2() => bar2();
+
+/*member: foo3:ignore*/
+@pragma('dart2js:noInline')
+int foo3() => bar3();
+
+/*member: bar1:ignore*/
+int bar1() => 1;
+
+/*member: bar2:ignore*/
+int bar2() => 2;
+
+/*member: bar3:ignore*/
+int bar3() => 3;
+
+// All calls to `barN` are inlined because this improves size and performance.
+/*member: test1:function() {
+ A.use(1, 2, 3);
+}*/
+@pragma('dart2js:noInline')
+void test1() {
+ use(bar1(), bar2(), bar3());
+}
+
+// No calls to `barN` are inlined due to `disable-inlining`.
+/*member: test2:function() {
+ A.use(A.bar1(), A.bar2(), A.bar3());
+}*/
+@pragma('dart2js:noInline')
+@pragma('dart2js:disable-inlining')
+void test2() {
+ use(bar1(), bar2(), bar3());
+}
+
+// `foo` and `bar1` are inlined. `foo2` is inlined, but the contained call to
+// `bar2` is not inlined due to `disable-inlining` on `foo2`.
+/*member: test3:function() {
+ A.use(1, A.bar2(), A.foo3());
+}*/
+@pragma('dart2js:noInline')
+void test3() {
+ use(foo1(), foo2(), foo3());
+}
+
+// None of the `fooN` calls are inlined due to `disable-inlining`.
+/*member: test4:function() {
+ A.use(A.foo1(), A.foo2(), A.foo3());
+}*/
+@pragma('dart2js:noInline')
+@pragma('dart2js:disable-inlining')
+void test4() {
+ use(foo1(), foo2(), foo3());
+}
+
+/*member: use:ignore*/
+@pragma('dart2js:noInline')
+void use(int a, int b, int c) {}
+
+/*member: main:ignore*/
+main() {
+ test1();
+ test2();
+ test3();
+ test4();
+}
diff --git a/pkg/compiler/test/serialization/serialization_test_helper.dart b/pkg/compiler/test/serialization/serialization_test_helper.dart
index 240a922..f50d65b 100644
--- a/pkg/compiler/test/serialization/serialization_test_helper.dart
+++ b/pkg/compiler/test/serialization/serialization_test_helper.dart
@@ -235,6 +235,12 @@
return newClosedWorldAndIndices;
}
+/// Tests that cloned inference results serialize to the same data.
+///
+/// Does 3 round trips to serialize/deserialize the provided data. The first
+/// round normalizes the data as some information might be dropped in the
+/// serialization/deserialization process. The second and third rounds are
+/// compared for consistency.
GlobalTypeInferenceResults cloneInferenceResults(
DataSourceIndices indices,
Compiler compiler,
@@ -256,7 +262,7 @@
newComponent,
closedWorldData);
var newIndices = indices == null ? null : newClosedWorldAndIndices.indices;
- GlobalTypeInferenceResults newResults = strategy
+ GlobalTypeInferenceResults initialResults = strategy
.deserializeGlobalTypeInferenceResults(
compiler.options,
compiler.reporter,
@@ -267,8 +273,21 @@
newIndices,
worldData)
.data;
- List<int> newWorldData = strategy.serializeGlobalTypeInferenceResults(
- newIndices, newResults, compiler.options);
- checkData(worldData, newWorldData);
- return newResults;
+ List<int> initialWorldData = strategy.serializeGlobalTypeInferenceResults(
+ newIndices, initialResults, compiler.options);
+ GlobalTypeInferenceResults finalResults = strategy
+ .deserializeGlobalTypeInferenceResults(
+ compiler.options,
+ compiler.reporter,
+ compiler.environment,
+ compiler.abstractValueStrategy,
+ newComponent,
+ newClosedWorldAndIndices.data,
+ newIndices,
+ worldData)
+ .data;
+ List<int> finalWorldData = strategy.serializeGlobalTypeInferenceResults(
+ newIndices, finalResults, compiler.options);
+ checkData(initialWorldData, finalWorldData);
+ return finalResults;
}
diff --git a/pkg/dart2js_info/test/binary_serialization_test.dart b/pkg/dart2js_info/test/binary_serialization_test.dart
index 73869d5..27ac31a 100644
--- a/pkg/dart2js_info/test/binary_serialization_test.dart
+++ b/pkg/dart2js_info/test/binary_serialization_test.dart
@@ -5,7 +5,8 @@
// @dart = 2.11
import 'dart:convert';
-import 'dart:io';
+import 'dart:io' show File, Platform;
+import 'dart:typed_data' show BytesBuilder;
import 'package:dart2js_info/json_info_codec.dart';
import 'package:dart2js_info/binary_serialization.dart' as binary;
diff --git a/pkg/dart2wasm/bin/run_wasm.js b/pkg/dart2wasm/bin/run_wasm.js
index 5e6dcb9..0078a7b 100644
--- a/pkg/dart2wasm/bin/run_wasm.js
+++ b/pkg/dart2wasm/bin/run_wasm.js
@@ -42,17 +42,6 @@
}
}
-// Converts a JS array to a Dart List, and also recursively converts the items
-// in the array.
-function arrayToDartList(array, allocator, adder) {
- var length = array.length;
- var dartList = dartInstance.exports.$listAllocate();
- for (var i = 0; i < length; i++) {
- dartInstance.exports.$listAdd(dartList, array[i]);
- }
- return dartList;
-}
-
// Converts a Dart List to a JS array. Any Dart objects will be converted, but
// this will be cheap for JSValues.
function arrayFromDartList(list, reader) {
@@ -64,35 +53,8 @@
return array;
}
-// TODO(joshualitt): Once we can properly return functions, then we can also try
-// returning a regular closure with some custom keys and a special symbol to
-// disambiguate it from other functions. I suspect this will also be necessary
-// for CSP.
-class WrappedDartCallback extends Function {
- constructor(dartCallback, exportFunctionName) {
- super('dartCallback', '...args',
- `return dartInstance.exports['${exportFunctionName}'](
- dartCallback, ...args.map(dartify));`);
- this.bound = this.bind(this, dartCallback);
- this.bound.dartCallback = dartCallback;
- return this.bound;
- }
-}
-
-// Recursively converts a JS object into a Dart object.
-function dartify(object) {
- if (typeof object === "string") {
- return stringToDartString(object);
- } else if (object instanceof Array) {
- return arrayToDartList(object);
- } else if (object instanceof WrappedDartCallback) {
- return object.dartCallback;
- } else if (object instanceof Object) {
- return dartInstance.exports.$boxJSValue(object);
- } else {
- return object;
- }
-}
+// A special symbol attached to functions that wrap Dart functions.
+var jsWrappedDartFunctionSymbol = Symbol("JSWrappedDartFunction");
// Imports for printing and event loop
var dart2wasm = {
@@ -118,13 +80,64 @@
return stringToDartString(userStackString);
},
arrayFromDartList: arrayFromDartList,
- arrayToDartList: arrayToDartList,
stringFromDartString: stringFromDartString,
stringToDartString: stringToDartString,
- wrapDartCallback: function(dartCallback, exportFunctionName) {
- return new WrappedDartCallback(dartCallback, exportFunctionName);
+ wrapDartFunction: function(dartFunction, exportFunctionName) {
+ var wrapped = function (...args) {
+ return dartInstance.exports[`${exportFunctionName}`](
+ dartFunction, ...args.map(dartInstance.exports.$dartifyRaw));
+ }
+ wrapped.dartFunction = dartFunction;
+ wrapped[jsWrappedDartFunctionSymbol] = true;
+ return wrapped;
},
- dartify: dartify,
+ objectLength: function(o) {
+ return o.length;
+ },
+ objectReadIndex: function(o, i) {
+ return o[i];
+ },
+ unwrapJSWrappedDartFunction: function(o) {
+ return o.dartFunction;
+ },
+ isJSUndefined: function(o) {
+ return o === undefined;
+ },
+ isJSBoolean: function(o) {
+ return typeof o === "boolean";
+ },
+ isJSNumber: function(o) {
+ return typeof o === "number";
+ },
+ isJSBigInt: function(o) {
+ return typeof o === "bigint";
+ },
+ isJSString: function(o) {
+ return typeof o === "string";
+ },
+ isJSSymbol: function(o) {
+ return typeof o === "symbol";
+ },
+ isJSFunction: function(o) {
+ return typeof o === "function";
+ },
+ isJSArray: function(o) {
+ return o instanceof Array;
+ },
+ isJSWrappedDartFunction: function(o) {
+ return typeof o === "function" &&
+ o[jsWrappedDartFunctionSymbol] === true;
+ },
+ isJSObject: function(o) {
+ return o instanceof Object;
+ },
+ roundtrip: function (o) {
+ // This function exists as a hook for the native JS -> Wasm type
+ // conversion rules. The Dart runtime will overload variants of this
+ // function with the necessary return type to trigger the desired
+ // coercion.
+ return o;
+ },
newObject: function() {
return {};
},
diff --git a/pkg/dds/CHANGELOG.md b/pkg/dds/CHANGELOG.md
index c0f272a..b4fa6ec0 100644
--- a/pkg/dds/CHANGELOG.md
+++ b/pkg/dds/CHANGELOG.md
@@ -1,3 +1,6 @@
+# 2.2.2
+- Updated `vm_service` version to 9.0.0.
+
# 2.2.1
- Reduce latency of `streamListen` calls through improved locking behavior.
diff --git a/pkg/dds/lib/src/dap/isolate_manager.dart b/pkg/dds/lib/src/dap/isolate_manager.dart
index df7dd76..5af7f41 100644
--- a/pkg/dds/lib/src/dap/isolate_manager.dart
+++ b/pkg/dds/lib/src/dap/isolate_manager.dart
@@ -10,6 +10,7 @@
import 'package:path/path.dart' as path;
import 'package:vm_service/vm_service.dart' as vm;
+import '../rpc_error_codes.dart';
import 'adapters/dart.dart';
import 'exceptions.dart';
import 'protocol_generated.dart';
@@ -694,7 +695,22 @@
final isDebuggable = libraryUri != null
? await _adapter.libraryIsDebuggable(thread, Uri.parse(libraryUri))
: false;
- await service.setLibraryDebuggable(isolateId, library.id!, isDebuggable);
+ try {
+ await service.setLibraryDebuggable(
+ isolateId, library.id!, isDebuggable);
+ } on vm.RPCError catch (e) {
+ // DWDS does not currently support `setLibraryDebuggable` so instead of
+ // failing (because this code runs in a VM event handler where there's
+ // no incoming request to fail/reject), just log this error.
+ // https://github.com/dart-lang/webdev/issues/606
+ if (e.code == RpcErrorCodes.kMethodNotFound) {
+ _adapter.logger?.call(
+ 'setLibraryDebuggable not available ($libraryUri, $e)',
+ );
+ } else {
+ rethrow;
+ }
+ }
}));
}
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index 40e8453..4145ae3 100644
--- a/pkg/dds/pubspec.yaml
+++ b/pkg/dds/pubspec.yaml
@@ -1,5 +1,5 @@
name: dds
-version: 2.2.1
+version: 2.2.2
description: >-
A library used to spawn the Dart Developer Service, used to communicate with
a Dart VM Service instance.
@@ -26,7 +26,7 @@
sse: ^4.0.0
stack_trace: ^1.10.0
stream_channel: ^2.0.0
- vm_service: ^8.1.0
+ vm_service: ^9.0.0
web_socket_channel: ^2.0.0
# We use 'any' version constraints here as we get our package versions from
diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
index 4ba953c..24a6751 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
@@ -6,8 +6,9 @@
import 'dart:async';
import 'dart:convert';
-import 'dart:io';
+import 'dart:io' show stdin, stdout;
import 'dart:isolate';
+import 'dart:typed_data' show BytesBuilder;
import 'package:args/args.dart';
import 'package:build_integration/file_system/multi_root.dart';
diff --git a/pkg/dev_compiler/tool/ddb b/pkg/dev_compiler/tool/ddb
index 5f3a651..8cfc2e2 100755
--- a/pkg/dev_compiler/tool/ddb
+++ b/pkg/dev_compiler/tool/ddb
@@ -174,7 +174,7 @@
mode: ProcessStartMode.inheritStdio, environment: environment);
}
- Future<void> runDdc(String command, List<String> args) async {
+ Future<void> runDdc(List<String> args) async {
if (debug) {
// Use unbuilt script. This only works from a source checkout.
var vmServicePort = options.wasParsed('vm-service-port')
@@ -188,14 +188,14 @@
'--pause-isolates-on-start',
],
'--enable-asserts',
- p.join(ddcPath, 'bin', '$command.dart')
+ p.join(ddcPath, 'bin', 'dartdevc.dart')
]);
- command = dartBinary;
} else {
// Use built snapshot.
- command = p.join(dartSdk, 'bin', command);
+ args.insertAll(
+ 0, [p.join(dartSdk, 'bin', 'snapshots', 'dartdevc.dart.snapshot')]);
}
- var process = await startProcess('DDC', command, args, <String, String>{
+ var process = await startProcess('DDC', dartBinary, args, <String, String>{
if (options['compile-vm-options'] != null)
'DART_VM_OPTIONS': options['compile-vm-options'] as String
});
@@ -249,7 +249,7 @@
out,
entry
];
- await runDdc('dartdevc', ddcArgs);
+ await runDdc(ddcArgs);
}
if (run) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart b/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart
index 63a7df3..8c4850d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/benchmarker.dart
@@ -234,8 +234,6 @@
body_buildBody_benchmark_specific_diet_parser,
body_buildBody_benchmark_specific_parser,
- inferConstructorParameterTypes,
- inferDeclarationType,
inferImplicitFieldType,
inferFieldInitializer,
inferFunctionBody,
diff --git a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
index 2a69401..dac8657 100644
--- a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
@@ -161,7 +161,8 @@
bodyBuilder.parseFieldInitializer(initializerToken!);
initializerToken = null;
- inferredType = typeInferrer.inferImplicitFieldType(initializer);
+ inferredType =
+ typeInferrer.inferImplicitFieldType(bodyBuilder, initializer);
} else {
inferredType = const DynamicType();
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index c3f4254..08270a4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -44,7 +44,7 @@
ExpressionVisitor1<ExpressionInferenceResult, DartType>,
StatementVisitor<StatementInferenceResult>,
InitializerVisitor<InitializerInferenceResult> {
- final TypeInferrerImpl inferrer;
+ final InferenceVisitorBase inferrer;
Class? mapEntryClass;
@@ -5058,11 +5058,11 @@
.computeFunctionType(inferrer.libraryBuilder.nonNullable)
: interfaceMember.function.returnType;
checkReturn =
- TypeInferrerImpl.returnedTypeParametersOccurNonCovariantly(
+ InferenceVisitorBase.returnedTypeParametersOccurNonCovariantly(
interfaceMember.enclosingClass!, typeToCheck);
} else if (interfaceMember is Field) {
checkReturn =
- TypeInferrerImpl.returnedTypeParametersOccurNonCovariantly(
+ InferenceVisitorBase.returnedTypeParametersOccurNonCovariantly(
interfaceMember.enclosingClass!, interfaceMember.type);
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
index 1c0c5c4..b181fd5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -1019,7 +1019,7 @@
}
Expression? checkWebIntLiteralsErrorIfUnexact(
- TypeInferrerImpl inferrer, int value, String? literal, int charOffset) {
+ InferenceVisitorBase inferrer, int value, String? literal, int charOffset) {
if (value >= 0 && value <= (1 << 53)) return null;
if (inferrer.isTopLevel) return null;
if (!inferrer.libraryBuilder.loader.target.backendTarget
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 25f5456..d1e61b6 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -98,7 +98,6 @@
import '../operator.dart';
import '../problems.dart' show unexpected, unhandled;
import '../scope.dart';
-import '../type_inference/type_inferrer.dart' show TypeInferrer;
import '../util/helpers.dart';
import 'name_scheme.dart';
import 'source_class_builder.dart' show SourceClassBuilder;
@@ -4244,7 +4243,6 @@
DartType receiverType,
TypeEnvironment typeEnvironment,
ClassHierarchy hierarchy,
- TypeInferrer typeInferrer,
Name name,
Member? interfaceTarget,
Arguments arguments,
@@ -4321,7 +4319,6 @@
void checkBoundsInFunctionInvocation(
TypeEnvironment typeEnvironment,
ClassHierarchy hierarchy,
- TypeInferrer typeInferrer,
FunctionType functionType,
String? localName,
Arguments arguments,
@@ -4356,7 +4353,6 @@
void checkBoundsInInstantiation(
TypeEnvironment typeEnvironment,
ClassHierarchy hierarchy,
- TypeInferrer typeInferrer,
FunctionType functionType,
List<DartType> typeArguments,
Uri fileUri,
diff --git a/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart b/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
index c7f66b4..8d0c67b 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
@@ -33,7 +33,7 @@
DartType? get futureValueType;
- factory ClosureContext(TypeInferrerImpl inferrer, AsyncMarker asyncMarker,
+ factory ClosureContext(InferenceVisitorBase inferrer, AsyncMarker asyncMarker,
DartType returnContext, bool needToInferReturnType) {
// ignore: unnecessary_null_comparison
assert(returnContext != null);
@@ -85,7 +85,7 @@
/// If the return type is declared, the expression type is checked. If the
/// return type is inferred the expression type registered for inference
/// in [inferReturnType].
- void handleReturn(TypeInferrerImpl inferrer, ReturnStatement statement,
+ void handleReturn(InferenceVisitorBase inferrer, ReturnStatement statement,
DartType type, bool isArrow);
/// Handles an explicit yield statement.
@@ -93,7 +93,7 @@
/// If the return type is declared, the expression type is checked. If the
/// return type is inferred the expression type registered for inference
/// in [inferReturnType].
- void handleYield(TypeInferrerImpl inferrer, YieldStatement node,
+ void handleYield(InferenceVisitorBase inferrer, YieldStatement node,
ExpressionInferenceResult expressionResult);
/// Handles an implicit return statement.
@@ -101,7 +101,7 @@
/// If the return type is declared, the expression type is checked. If the
/// return type is inferred the expression type registered for inference
/// in [inferReturnType].
- StatementInferenceResult handleImplicitReturn(TypeInferrerImpl inferrer,
+ StatementInferenceResult handleImplicitReturn(InferenceVisitorBase inferrer,
Statement body, StatementInferenceResult inferenceResult, int fileOffset);
/// Infers the return type for the function.
@@ -112,7 +112,7 @@
///
/// If the function is a generator function this is based on the explicit
/// yield statements registered in [handleYield].
- DartType inferReturnType(TypeInferrerImpl inferrer,
+ DartType inferReturnType(InferenceVisitorBase inferrer,
{required bool hasImplicitReturn});
}
@@ -160,7 +160,7 @@
}
}
- void _checkValidReturn(TypeInferrerImpl inferrer, DartType returnType,
+ void _checkValidReturn(InferenceVisitorBase inferrer, DartType returnType,
ReturnStatement statement, DartType expressionType) {
assert(!inferrer.isTopLevel);
if (inferrer.isNonNullableByDefault) {
@@ -289,7 +289,7 @@
/// Updates the inferred return type based on the presence of a return
/// statement returning the given [type].
@override
- void handleReturn(TypeInferrerImpl inferrer, ReturnStatement statement,
+ void handleReturn(InferenceVisitorBase inferrer, ReturnStatement statement,
DartType type, bool isArrow) {
// The first return we see tells us if we have an arrow function.
if (this._isArrow == null) {
@@ -309,13 +309,13 @@
}
@override
- void handleYield(TypeInferrerImpl inferrer, YieldStatement node,
+ void handleYield(InferenceVisitorBase inferrer, YieldStatement node,
ExpressionInferenceResult expressionResult) {
node.expression = expressionResult.expression..parent = node;
}
@override
- DartType inferReturnType(TypeInferrerImpl inferrer,
+ DartType inferReturnType(InferenceVisitorBase inferrer,
{required bool hasImplicitReturn}) {
assert(_needToInferReturnType);
// ignore: unnecessary_null_comparison
@@ -423,7 +423,7 @@
@override
StatementInferenceResult handleImplicitReturn(
- TypeInferrerImpl inferrer,
+ InferenceVisitorBase inferrer,
Statement body,
StatementInferenceResult inferenceResult,
int fileOffset) {
@@ -513,7 +513,7 @@
}
}
- void _checkValidReturn(TypeInferrerImpl inferrer, DartType returnType,
+ void _checkValidReturn(InferenceVisitorBase inferrer, DartType returnType,
ReturnStatement statement, DartType expressionType) {
assert(!inferrer.isTopLevel);
if (inferrer.isNonNullableByDefault) {
@@ -674,7 +674,7 @@
/// Updates the inferred return type based on the presence of a return
/// statement returning the given [type].
@override
- void handleReturn(TypeInferrerImpl inferrer, ReturnStatement statement,
+ void handleReturn(InferenceVisitorBase inferrer, ReturnStatement statement,
DartType type, bool isArrow) {
// The first return we see tells us if we have an arrow function.
if (this._isArrow == null) {
@@ -694,12 +694,12 @@
}
@override
- void handleYield(TypeInferrerImpl inferrer, YieldStatement node,
+ void handleYield(InferenceVisitorBase inferrer, YieldStatement node,
ExpressionInferenceResult expressionResult) {
node.expression = expressionResult.expression..parent = node;
}
- DartType computeAssignableType(TypeInferrerImpl inferrer,
+ DartType computeAssignableType(InferenceVisitorBase inferrer,
DartType contextType, DartType expressionType) {
contextType = inferrer.computeGreatestClosure(contextType);
@@ -722,7 +722,7 @@
}
@override
- DartType inferReturnType(TypeInferrerImpl inferrer,
+ DartType inferReturnType(InferenceVisitorBase inferrer,
{required bool hasImplicitReturn}) {
assert(_needToInferReturnType);
// ignore: unnecessary_null_comparison
@@ -835,7 +835,7 @@
@override
StatementInferenceResult handleImplicitReturn(
- TypeInferrerImpl inferrer,
+ InferenceVisitorBase inferrer,
Statement body,
StatementInferenceResult inferenceResult,
int fileOffset) {
@@ -922,11 +922,11 @@
/// Updates the inferred return type based on the presence of a return
/// statement returning the given [type].
@override
- void handleReturn(TypeInferrerImpl inferrer, ReturnStatement statement,
+ void handleReturn(InferenceVisitorBase inferrer, ReturnStatement statement,
DartType type, bool isArrow) {}
@override
- void handleYield(TypeInferrerImpl inferrer, YieldStatement node,
+ void handleYield(InferenceVisitorBase inferrer, YieldStatement node,
ExpressionInferenceResult expressionResult) {
DartType expectedType = node.isYieldStar
? inferrer.wrapType(
@@ -955,7 +955,7 @@
}
@override
- DartType inferReturnType(TypeInferrerImpl inferrer,
+ DartType inferReturnType(InferenceVisitorBase inferrer,
{required bool hasImplicitReturn}) {
assert(_needToInferReturnType);
// ignore: unnecessary_null_comparison
@@ -1002,7 +1002,7 @@
@override
StatementInferenceResult handleImplicitReturn(
- TypeInferrerImpl inferrer,
+ InferenceVisitorBase inferrer,
Statement body,
StatementInferenceResult inferenceResult,
int fileOffset) {
@@ -1056,11 +1056,11 @@
/// Updates the inferred return type based on the presence of a return
/// statement returning the given [type].
@override
- void handleReturn(TypeInferrerImpl inferrer, ReturnStatement statement,
+ void handleReturn(InferenceVisitorBase inferrer, ReturnStatement statement,
DartType type, bool isArrow) {}
@override
- void handleYield(TypeInferrerImpl inferrer, YieldStatement node,
+ void handleYield(InferenceVisitorBase inferrer, YieldStatement node,
ExpressionInferenceResult expressionResult) {
DartType expectedType = node.isYieldStar
? inferrer.wrapType(_yieldElementContext,
@@ -1088,7 +1088,7 @@
}
@override
- DartType inferReturnType(TypeInferrerImpl inferrer,
+ DartType inferReturnType(InferenceVisitorBase inferrer,
{required bool hasImplicitReturn}) {
assert(_needToInferReturnType);
// ignore: unnecessary_null_comparison
@@ -1134,7 +1134,7 @@
@override
StatementInferenceResult handleImplicitReturn(
- TypeInferrerImpl inferrer,
+ InferenceVisitorBase inferrer,
Statement body,
StatementInferenceResult inferenceResult,
int fileOffset) {
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 293bd91..7a5c30e 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -173,8 +173,6 @@
AssignedVariables<TreeNode, VariableDeclaration> get assignedVariables;
- InferenceHelper get helper;
-
/// Indicates whether the construct we are currently performing inference for
/// is outside of a method body, and hence top level type inference rules
/// should apply.
@@ -182,17 +180,13 @@
/// Performs top level type inference on the given field initializer and
/// returns the computed field type.
- DartType inferImplicitFieldType(Expression initializer);
+ DartType inferImplicitFieldType(
+ InferenceHelper helper, Expression initializer);
/// Performs full type inference on the given field initializer.
ExpressionInferenceResult inferFieldInitializer(
InferenceHelper helper, DartType declaredType, Expression initializer);
- /// Returns the type used as the inferred type of a variable declaration,
- /// based on the static type of the initializer expression, given by
- /// [initializerType].
- DartType inferDeclarationType(DartType initializerType);
-
/// Performs type inference on the given function body.
InferredFunctionBody inferFunctionBody(InferenceHelper helper, int fileOffset,
DartType returnType, AsyncMarker asyncMarker, Statement body);
@@ -213,11 +207,6 @@
DartType declaredType,
bool hasDeclaredInitializer);
- /// Ensures that all parameter types of [constructor] have been inferred.
- // TODO(johnniwinther): We are still parameters on synthesized mixin
- // application constructors.
- void inferConstructorParameterTypes(Constructor constructor);
-
/// Infers the type arguments a redirecting factory target reference.
List<DartType>? inferRedirectingFactoryTypeArguments(
InferenceHelper helper,
@@ -245,7 +234,7 @@
new TypeOperationsCfe(engine.typeSchemaEnvironment),
assignedVariables,
respectImplicitlyTypedVarInitializers:
- libraryFeatures.constructorTearoffs.isEnabled)
+ libraryBuilder.libraryFeatures.constructorTearoffs.isEnabled)
: new FlowAnalysis.legacy(
new TypeOperationsCfe(engine.typeSchemaEnvironment),
assignedVariables);
@@ -273,12 +262,10 @@
@override
final SourceLibraryBuilder libraryBuilder;
- InferenceHelper? _helper;
-
TypeInferrerImpl(
this.engine,
this.uriForInstrumentation,
- bool topLevel,
+ this.isTopLevel,
this.thisType,
this.libraryBuilder,
this.assignedVariables,
@@ -288,31 +275,200 @@
unknownFunction = new FunctionType(
const [], const DynamicType(), libraryBuilder.nonNullable),
classHierarchy = engine.classHierarchy,
- instrumentation = topLevel ? null : engine.instrumentation,
- typeSchemaEnvironment = engine.typeSchemaEnvironment,
- isTopLevel = topLevel {}
+ instrumentation = isTopLevel ? null : engine.instrumentation,
+ typeSchemaEnvironment = engine.typeSchemaEnvironment {}
- @override
- InferenceHelper get helper => _helper!;
-
- void set helper(InferenceHelper helper) {
- if (isTopLevel) {
- throw new StateError("Attempting to assign TypeInferrerImpl.helper "
- "during top-level inference.");
- }
- _helper = helper;
- }
-
- InferenceVisitor _createInferenceVisitor() {
+ InferenceVisitor _createInferenceVisitor(InferenceVisitorBase inferrer) {
// For full (non-top level) inference, we need access to the
// ExpressionGeneratorHelper so that we can perform error recovery.
- assert(isTopLevel || _helper != null,
+ assert(isTopLevel || inferrer._helper != null,
"Helper hasn't been set up for full inference.");
- return new InferenceVisitor(this);
+ return new InferenceVisitor(inferrer);
}
+ @override
+ DartType inferImplicitFieldType(
+ InferenceHelper helper, Expression initializer) {
+ InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
+ InferenceVisitor visitor = _createInferenceVisitor(inferrer);
+ ExpressionInferenceResult result = visitor.inferExpression(
+ initializer, const UnknownType(), true,
+ isVoidAllowed: true);
+ return inferrer.inferDeclarationType(result.inferredType);
+ }
+
+ @override
+ ExpressionInferenceResult inferFieldInitializer(
+ InferenceHelper helper, DartType declaredType, Expression initializer) {
+ assert(!isTopLevel);
+ InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
+ InferenceVisitor visitor = _createInferenceVisitor(inferrer);
+ ExpressionInferenceResult initializerResult = visitor
+ .inferExpression(initializer, declaredType, true, isVoidAllowed: true);
+ initializerResult = inferrer.ensureAssignableResult(
+ declaredType, initializerResult,
+ isVoidAllowed: declaredType is VoidType);
+ return initializerResult;
+ }
+
+ @override
+ InferredFunctionBody inferFunctionBody(InferenceHelper helper, int fileOffset,
+ DartType returnType, AsyncMarker asyncMarker, Statement body) {
+ // ignore: unnecessary_null_comparison
+ assert(body != null);
+ InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
+ ClosureContext closureContext =
+ new ClosureContext(inferrer, asyncMarker, returnType, false);
+ InferenceVisitor visitor = _createInferenceVisitor(inferrer);
+ StatementInferenceResult result =
+ visitor.inferStatement(body, closureContext);
+ if (dataForTesting != null) {
+ if (!flowAnalysis.isReachable) {
+ dataForTesting!.flowAnalysisResult.functionBodiesThatDontComplete
+ .add(body);
+ }
+ }
+ result =
+ closureContext.handleImplicitReturn(inferrer, body, result, fileOffset);
+ DartType? futureValueType = closureContext.futureValueType;
+ assert(!(asyncMarker == AsyncMarker.Async && futureValueType == null),
+ "No future value type computed.");
+ flowAnalysis.finish();
+ return new InferredFunctionBody(
+ result.hasChanged ? result.statement : body, futureValueType);
+ }
+
+ @override
+ List<DartType>? inferRedirectingFactoryTypeArguments(
+ InferenceHelper helper,
+ DartType typeContext,
+ FunctionNode redirectingFactoryFunction,
+ int fileOffset,
+ Member target,
+ FunctionType targetType) {
+ InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
+ InferenceVisitor visitor = _createInferenceVisitor(inferrer);
+ List<Expression> positionalArguments = <Expression>[];
+ for (VariableDeclaration parameter
+ in redirectingFactoryFunction.positionalParameters) {
+ flowAnalysis.declare(parameter, true);
+ positionalArguments
+ .add(new VariableGetImpl(parameter, forNullGuardedAccess: false));
+ }
+ List<NamedExpression> namedArguments = <NamedExpression>[];
+ for (VariableDeclaration parameter
+ in redirectingFactoryFunction.namedParameters) {
+ flowAnalysis.declare(parameter, true);
+ namedArguments.add(new NamedExpression(parameter.name!,
+ new VariableGetImpl(parameter, forNullGuardedAccess: false)));
+ }
+ // If arguments are created using [Forest.createArguments], and the
+ // type arguments are omitted, they are to be inferred.
+ ArgumentsImpl targetInvocationArguments = engine.forest.createArguments(
+ fileOffset, positionalArguments,
+ named: namedArguments);
+
+ InvocationInferenceResult result = inferrer.inferInvocation(
+ visitor, typeContext, fileOffset, targetType, targetInvocationArguments,
+ staticTarget: target);
+ DartType resultType = result.inferredType;
+ if (resultType is InterfaceType) {
+ return resultType.typeArguments;
+ } else {
+ return null;
+ }
+ }
+
+ @override
+ InitializerInferenceResult inferInitializer(
+ InferenceHelper helper, Initializer initializer) {
+ // Use polymorphic dispatch on [KernelInitializer] to perform whatever
+ // kind of type inference is correct for this kind of initializer.
+ // TODO(paulberry): experiment to see if dynamic dispatch would be better,
+ // so that the type hierarchy will be simpler (which may speed up "is"
+ // checks).
+ InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
+ InferenceVisitor visitor = _createInferenceVisitor(inferrer);
+ InitializerInferenceResult inferenceResult;
+ if (initializer is InitializerJudgment) {
+ inferenceResult = initializer.acceptInference(visitor);
+ } else {
+ inferenceResult = initializer.accept(visitor);
+ }
+ return inferenceResult;
+ }
+
+ @override
+ void inferMetadata(
+ InferenceHelper helper, TreeNode? parent, List<Expression>? annotations) {
+ if (annotations != null) {
+ // We bypass the check for assignment of the helper during top-level
+ // inference and use `_helper = helper` instead of `this.helper = helper`
+ // because inference on metadata requires the helper.
+ InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
+ InferenceVisitor visitor = _createInferenceVisitor(inferrer);
+ inferrer.inferMetadataKeepingHelper(visitor, parent, annotations);
+ }
+ }
+
+ @override
+ Expression inferParameterInitializer(
+ InferenceHelper helper,
+ Expression initializer,
+ DartType declaredType,
+ bool hasDeclaredInitializer) {
+ // ignore: unnecessary_null_comparison
+ assert(declaredType != null);
+ InferenceVisitorBase inferrer = new InferenceVisitorBase(this, helper);
+ InferenceVisitor visitor = _createInferenceVisitor(inferrer);
+ ExpressionInferenceResult result =
+ visitor.inferExpression(initializer, declaredType, true);
+ if (hasDeclaredInitializer) {
+ initializer =
+ inferrer.ensureAssignableResult(declaredType, result).expression;
+ }
+ return initializer;
+ }
+}
+
+class InferenceVisitorBase {
+ final TypeInferrerImpl _inferrer;
+
+ final InferenceHelper? _helper;
+
+ InferenceVisitorBase(this._inferrer, this._helper);
+
+ AssignedVariables<TreeNode, VariableDeclaration> get assignedVariables =>
+ _inferrer.assignedVariables;
+
+ FunctionType get unknownFunction => _inferrer.unknownFunction;
+
+ InterfaceType? get thisType => _inferrer.thisType;
+
+ Uri get uriForInstrumentation => _inferrer.uriForInstrumentation;
+
+ Instrumentation? get instrumentation => _inferrer.instrumentation;
+
+ ClassHierarchy get classHierarchy => _inferrer.classHierarchy;
+
+ InferenceDataForTesting? get dataForTesting => _inferrer.dataForTesting;
+
+ FlowAnalysis<TreeNode, Statement, Expression, VariableDeclaration, DartType>
+ get flowAnalysis => _inferrer.flowAnalysis;
+
+ TypeSchemaEnvironment get typeSchemaEnvironment =>
+ _inferrer.typeSchemaEnvironment;
+
+ TypeInferenceEngine get engine => _inferrer.engine;
+
+ bool get isTopLevel => _inferrer.isTopLevel;
+
+ InferenceHelper get helper => _helper!;
+
CoreTypes get coreTypes => engine.coreTypes;
+ SourceLibraryBuilder get libraryBuilder => _inferrer.libraryBuilder;
+
bool get isInferenceUpdate1Enabled =>
libraryBuilder.isInferenceUpdate1Enabled;
@@ -456,7 +612,7 @@
}
}
- @override
+ /// Ensures that all parameter types of [constructor] have been inferred.
void inferConstructorParameterTypes(Constructor target) {
SourceConstructorBuilder? constructor = engine.beingInferred[target];
if (constructor != null) {
@@ -492,27 +648,6 @@
}
}
- @override
- InitializerInferenceResult inferInitializer(
- InferenceHelper helper, Initializer initializer) {
- this.helper = helper;
-
- // Use polymorphic dispatch on [KernelInitializer] to perform whatever
- // kind of type inference is correct for this kind of initializer.
- // TODO(paulberry): experiment to see if dynamic dispatch would be better,
- // so that the type hierarchy will be simpler (which may speed up "is"
- // checks).
- InferenceVisitor visitor = _createInferenceVisitor();
- InitializerInferenceResult inferenceResult;
- if (initializer is InitializerJudgment) {
- inferenceResult = initializer.acceptInference(visitor);
- } else {
- inferenceResult = initializer.accept(visitor);
- }
- _helper = null;
- return inferenceResult;
- }
-
bool isDoubleContext(DartType typeContext) {
// A context is a double context if double is assignable to it but int is
// not. That is the type context is a double context if it is:
@@ -1979,8 +2114,9 @@
}
}
- /// Modifies a type as appropriate when inferring a declared variable's type.
- @override
+ /// Returns the type used as the inferred type of a variable declaration,
+ /// based on the static type of the initializer expression, given by
+ /// [initializerType].
DartType inferDeclarationType(DartType initializerType,
{bool forSyntheticVariable: false}) {
if (initializerType is NullType) {
@@ -2031,99 +2167,6 @@
}
}
- @override
- DartType inferImplicitFieldType(Expression initializer) {
- InferenceVisitor visitor = _createInferenceVisitor();
- ExpressionInferenceResult result = visitor.inferExpression(
- initializer, const UnknownType(), true,
- isVoidAllowed: true);
- return inferDeclarationType(result.inferredType);
- }
-
- @override
- ExpressionInferenceResult inferFieldInitializer(
- InferenceHelper helper, DartType declaredType, Expression initializer) {
- assert(!isTopLevel);
- this.helper = helper;
- InferenceVisitor visitor = _createInferenceVisitor();
- ExpressionInferenceResult initializerResult = visitor
- .inferExpression(initializer, declaredType, true, isVoidAllowed: true);
- initializerResult = ensureAssignableResult(declaredType, initializerResult,
- isVoidAllowed: declaredType is VoidType);
- _helper = null;
- return initializerResult;
- }
-
- @override
- InferredFunctionBody inferFunctionBody(InferenceHelper helper, int fileOffset,
- DartType returnType, AsyncMarker asyncMarker, Statement body) {
- // ignore: unnecessary_null_comparison
- assert(body != null);
- this.helper = helper;
- ClosureContext closureContext =
- new ClosureContext(this, asyncMarker, returnType, false);
- InferenceVisitor visitor = _createInferenceVisitor();
- StatementInferenceResult result =
- visitor.inferStatement(body, closureContext);
- if (dataForTesting != null) {
- if (!flowAnalysis.isReachable) {
- dataForTesting!.flowAnalysisResult.functionBodiesThatDontComplete
- .add(body);
- }
- }
- result =
- closureContext.handleImplicitReturn(this, body, result, fileOffset);
- DartType? futureValueType = closureContext.futureValueType;
- assert(!(asyncMarker == AsyncMarker.Async && futureValueType == null),
- "No future value type computed.");
- _helper = null;
- flowAnalysis.finish();
- return new InferredFunctionBody(
- result.hasChanged ? result.statement : body, futureValueType);
- }
-
- @override
- List<DartType>? inferRedirectingFactoryTypeArguments(
- InferenceHelper helper,
- DartType typeContext,
- FunctionNode redirectingFactoryFunction,
- int fileOffset,
- Member target,
- FunctionType targetType) {
- this.helper = helper;
- InferenceVisitor visitor = _createInferenceVisitor();
- List<Expression> positionalArguments = <Expression>[];
- for (VariableDeclaration parameter
- in redirectingFactoryFunction.positionalParameters) {
- flowAnalysis.declare(parameter, true);
- positionalArguments
- .add(new VariableGetImpl(parameter, forNullGuardedAccess: false));
- }
- List<NamedExpression> namedArguments = <NamedExpression>[];
- for (VariableDeclaration parameter
- in redirectingFactoryFunction.namedParameters) {
- flowAnalysis.declare(parameter, true);
- namedArguments.add(new NamedExpression(parameter.name!,
- new VariableGetImpl(parameter, forNullGuardedAccess: false)));
- }
- // If arguments are created using [Forest.createArguments], and the
- // type arguments are omitted, they are to be inferred.
- ArgumentsImpl targetInvocationArguments = engine.forest.createArguments(
- fileOffset, positionalArguments,
- named: namedArguments);
-
- InvocationInferenceResult result = inferInvocation(
- visitor, typeContext, fileOffset, targetType, targetInvocationArguments,
- staticTarget: target);
- DartType resultType = result.inferredType;
- _helper = null;
- if (resultType is InterfaceType) {
- return resultType.typeArguments;
- } else {
- return null;
- }
- }
-
InvocationInferenceResult inferInvocation(
InferenceVisitor visitor,
DartType typeContext,
@@ -2942,20 +2985,6 @@
return function.computeFunctionType(libraryBuilder.nonNullable);
}
- @override
- void inferMetadata(
- InferenceHelper helper, TreeNode? parent, List<Expression>? annotations) {
- if (annotations != null) {
- // We bypass the check for assignment of the helper during top-level
- // inference and use `_helper = helper` instead of `this.helper = helper`
- // because inference on metadata requires the helper.
- _helper = helper;
- InferenceVisitor visitor = _createInferenceVisitor();
- inferMetadataKeepingHelper(visitor, parent, annotations);
- _helper = null;
- }
- }
-
void inferMetadataKeepingHelper(InferenceVisitor visitor, TreeNode? parent,
List<Expression>? annotations) {
if (annotations != null) {
@@ -4023,7 +4052,6 @@
actualReceiverType,
typeSchemaEnvironment,
classHierarchy,
- this,
actualMethodName,
interfaceTarget,
arguments,
@@ -4041,7 +4069,7 @@
if (!isTopLevel) {
// We only perform checks in full inference.
libraryBuilder.checkBoundsInInstantiation(typeSchemaEnvironment,
- classHierarchy, this, functionType, arguments, helper.uri, fileOffset,
+ classHierarchy, functionType, arguments, helper.uri, fileOffset,
inferred: inferred);
}
}
@@ -4054,7 +4082,6 @@
libraryBuilder.checkBoundsInFunctionInvocation(
typeSchemaEnvironment,
classHierarchy,
- this,
functionType,
localName,
arguments,
@@ -4134,25 +4161,6 @@
inferredType, result.applyResult(expression));
}
- @override
- Expression inferParameterInitializer(
- InferenceHelper helper,
- Expression initializer,
- DartType declaredType,
- bool hasDeclaredInitializer) {
- this.helper = helper;
- // ignore: unnecessary_null_comparison
- assert(declaredType != null);
- InferenceVisitor visitor = _createInferenceVisitor();
- ExpressionInferenceResult result =
- visitor.inferExpression(initializer, declaredType, true);
- if (hasDeclaredInitializer) {
- initializer = ensureAssignableResult(declaredType, result).expression;
- }
- _helper = null;
- return initializer;
- }
-
/// Performs the core type inference algorithm for super property get.
ExpressionInferenceResult inferSuperPropertyGet(
Expression expression, Name name, DartType typeContext, Member? member) {
@@ -4872,25 +4880,10 @@
Uri get uriForInstrumentation => impl.uriForInstrumentation;
@override
- void inferConstructorParameterTypes(Constructor constructor) {
- benchmarker
- .beginSubdivide(BenchmarkSubdivides.inferConstructorParameterTypes);
- impl.inferConstructorParameterTypes(constructor);
- benchmarker.endSubdivide();
- }
-
- @override
- DartType inferDeclarationType(DartType initializerType) {
- benchmarker.beginSubdivide(BenchmarkSubdivides.inferDeclarationType);
- DartType result = impl.inferDeclarationType(initializerType);
- benchmarker.endSubdivide();
- return result;
- }
-
- @override
- DartType inferImplicitFieldType(Expression initializer) {
+ DartType inferImplicitFieldType(
+ InferenceHelper helper, Expression initializer) {
benchmarker.beginSubdivide(BenchmarkSubdivides.inferImplicitFieldType);
- DartType result = impl.inferImplicitFieldType(initializer);
+ DartType result = impl.inferImplicitFieldType(helper, initializer);
benchmarker.endSubdivide();
return result;
}
@@ -4966,9 +4959,6 @@
benchmarker.endSubdivide();
return result;
}
-
- @override
- InferenceHelper get helper => impl.helper;
}
abstract class MixinInferrer {
@@ -5186,7 +5176,7 @@
/// Tells the inferred type and how the code should be transformed.
///
/// It is intended for use by generalized inference methods, such as
-/// [TypeInferrerImpl.inferInvocation], where the input [Expression] isn't
+/// [InferenceVisitorBase.inferInvocation], where the input [Expression] isn't
/// available for rewriting. So, instead of transforming the code, the result
/// of the inference provides a way to transform the code at the point of
/// invocation.
@@ -5449,7 +5439,7 @@
/// The file offset used for the null-test.
int _nullAwareFileOffset;
- final TypeInferrerImpl _inferrer;
+ final InferenceVisitorBase _inferrer;
NullAwareGuard(
this._nullAwareVariable, this._nullAwareFileOffset, this._inferrer)
@@ -5905,7 +5895,7 @@
implements
NonPromotionReasonVisitor<LocatedMessage?, Node, VariableDeclaration,
DartType> {
- final TypeInferrerImpl inferrer;
+ final InferenceVisitorBase inferrer;
Member? propertyReference;
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index 0cb0774..e222ac8 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -602,6 +602,7 @@
..._experimentsArgument(_configuration, testFile),
...testFile.ddcOptions,
if (_configuration.nnbdMode == NnbdMode.strong) '--sound-null-safety',
+ if (_configuration.configuration.builderTag == 'canary') '--canary',
// The file being compiled is the last argument.
args.last
];
diff --git a/pkg/vm_service/test/coverage_async_test.dart b/pkg/vm_service/test/coverage_async_test.dart
new file mode 100644
index 0000000..9d4669f
--- /dev/null
+++ b/pkg/vm_service/test/coverage_async_test.dart
@@ -0,0 +1,123 @@
+// 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';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+Future<int> asyncFunction() async {
+ await Future.delayed(const Duration(milliseconds: 1));
+ return 123;
+}
+
+Stream<int> asyncGenerator() async* {
+ await Future.delayed(const Duration(milliseconds: 1));
+ yield 456;
+}
+
+Iterable<int> syncGenerator() sync* {
+ yield 789;
+}
+
+Future<void> wrapperFunction() async {
+ print(await asyncFunction());
+ await for (final value in asyncGenerator()) {
+ print(value);
+ }
+ for (final value in syncGenerator()) {
+ print(value);
+ }
+}
+
+Future<void> testFunction() async {
+ debugger();
+ await wrapperFunction();
+ debugger();
+}
+
+bool allRangesCompiled(coverage) {
+ for (int i = 0; i < coverage['ranges'].length; i++) {
+ if (!coverage['ranges'][i]['compiled']) {
+ return false;
+ }
+ }
+ return true;
+}
+
+IsolateTest coverageTest(Map<String, dynamic> expectedRange) {
+ return (VmService service, IsolateRef isolateRef) async {
+ final isolateId = isolateRef.id!;
+ final isolate = await service.getIsolate(isolateId);
+ final stack = await service.getStack(isolateId);
+
+ // Make sure we are in the right place.
+ expect(stack.frames!.length, greaterThanOrEqualTo(1));
+ expect(stack.frames![0].function!.name, 'testFunction');
+
+ final root =
+ await service.getObject(isolateId, isolate.rootLib!.id!) as Library;
+ FuncRef funcRef =
+ root.functions!.singleWhere((f) => f.name == 'wrapperFunction');
+ Func func = await service.getObject(isolateId, funcRef.id!) as Func;
+ final location = func.location!;
+
+ final report = await service.getSourceReport(
+ isolateId,
+ [SourceReportKind.kCoverage],
+ scriptId: location.script!.id,
+ tokenPos: location.tokenPos,
+ endTokenPos: location.endTokenPos,
+ forceCompile: true,
+ reportLines: true,
+ );
+ expect(report.ranges!.length, 1);
+ expect(report.ranges![0].toJson(), expectedRange);
+ expect(report.scripts!.length, 1);
+ expect(
+ report.scripts![0].uri,
+ endsWith('coverage_async_test.dart'),
+ );
+ };
+}
+
+var tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ coverageTest(
+ {
+ 'scriptIndex': 0,
+ 'startPos': 674,
+ 'endPos': 878,
+ 'compiled': true,
+ 'coverage': {
+ 'hits': [],
+ 'misses': [27, 28, 28, 29, 29, 29, 30, 32, 32, 33]
+ }
+ },
+ ),
+ resumeIsolate,
+ hasStoppedAtBreakpoint,
+ coverageTest(
+ {
+ 'scriptIndex': 0,
+ 'startPos': 674,
+ 'endPos': 878,
+ 'compiled': true,
+ 'coverage': {
+ 'hits': [27, 28, 28, 29, 29, 29, 30, 32, 32, 33],
+ 'misses': []
+ }
+ },
+ ),
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+ args,
+ tests,
+ 'coverage_async_test.dart',
+ testeeConcurrent: testFunction,
+ );
diff --git a/pkg/vm_service/test/get_stack_test.dart b/pkg/vm_service/test/get_stack_test.dart
index d1b42d3..138876b 100644
--- a/pkg/vm_service/test/get_stack_test.dart
+++ b/pkg/vm_service/test/get_stack_test.dart
@@ -95,7 +95,7 @@
(VmService service, IsolateRef isolateRef) async {
final result = await service.getStack(isolateRef.id!);
- expect(result.frames, hasLength(6));
+ expect(result.frames, hasLength(10));
expect(result.asyncCausalFrames, hasLength(26));
expect(result.awaiterFrames, hasLength(13));
@@ -105,6 +105,10 @@
[equals('Regular'), anything], // Internal mech. ..
[equals('Regular'), anything],
[equals('Regular'), anything],
+ [equals('Regular'), anything],
+ [equals('Regular'), anything],
+ [equals('Regular'), anything],
+ [equals('Regular'), anything],
[equals('Regular'), endsWith(' _RawReceivePortImpl._handleMessage')],
]);
diff --git a/runtime/observatory/tests/service/get_stack_limit_rpc_test.dart b/runtime/observatory/tests/service/get_stack_limit_rpc_test.dart
index f8decf0..35a6493 100644
--- a/runtime/observatory/tests/service/get_stack_limit_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_stack_limit_rpc_test.dart
@@ -51,7 +51,7 @@
var frames = stack['frames'];
var asyncFrames = stack['asyncCausalFrames'];
var awaiterFrames = stack['awaiterFrames'];
- expect(frames.length, greaterThanOrEqualTo(12));
+ expect(frames.length, greaterThanOrEqualTo(20));
expect(asyncFrames.length, greaterThan(frames.length));
expect(awaiterFrames.length, greaterThan(frames.length));
expect(stack['truncated'], false);
diff --git a/runtime/observatory_2/tests/service_2/get_stack_limit_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_stack_limit_rpc_test.dart
index 8570a28..e346afa 100644
--- a/runtime/observatory_2/tests/service_2/get_stack_limit_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_stack_limit_rpc_test.dart
@@ -51,7 +51,7 @@
var frames = stack['frames'];
var asyncFrames = stack['asyncCausalFrames'];
var awaiterFrames = stack['awaiterFrames'];
- expect(frames.length, greaterThanOrEqualTo(12));
+ expect(frames.length, greaterThanOrEqualTo(20));
expect(asyncFrames.length, greaterThan(frames.length));
expect(awaiterFrames.length, greaterThan(frames.length));
expect(stack['truncated'], false);
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index dbd960a..eb2bbd8 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -63,6 +63,7 @@
result->used_in_bytes_ = 0;
result->forwarding_page_ = NULL;
result->card_table_ = NULL;
+ result->progress_bar_ = 0;
result->type_ = type;
LSAN_REGISTER_ROOT_REGION(result, sizeof(*result));
@@ -128,8 +129,6 @@
return;
}
- bool table_is_empty = false;
-
ArrayPtr obj =
static_cast<ArrayPtr>(UntaggedObject::FromAddr(object_start()));
ASSERT(obj->IsArray());
@@ -140,7 +139,10 @@
uword heap_base = obj.heap_base();
const intptr_t size = card_table_size();
- for (intptr_t i = 0; i < size; i++) {
+ for (;;) {
+ intptr_t i = progress_bar_.fetch_add(1);
+ if (i >= size) break;
+
if (card_table_[i] != 0) {
CompressedObjectPtr* card_from =
reinterpret_cast<CompressedObjectPtr*>(this) +
@@ -170,19 +172,15 @@
}
}
- if (has_new_target) {
- // Card remains remembered.
- table_is_empty = false;
- } else {
+ if (!has_new_target) {
card_table_[i] = 0;
}
}
}
+}
- if (table_is_empty) {
- free(card_table_);
- card_table_ = NULL;
- }
+void OldPage::ResetProgressBar() {
+ progress_bar_ = 0;
}
ObjectPtr OldPage::FindObject(FindObjectVisitor* visitor) const {
@@ -833,6 +831,12 @@
}
}
+void PageSpace::ResetProgressBars() const {
+ for (OldPage* page = large_pages_; page != NULL; page = page->next()) {
+ page->ResetProgressBar();
+ }
+}
+
ObjectPtr PageSpace::FindObject(FindObjectVisitor* visitor,
OldPage::PageType type) const {
if (type == OldPage::kExecutable) {
@@ -1474,6 +1478,7 @@
page->used_in_bytes_ = page->object_end_ - page->object_start();
page->forwarding_page_ = NULL;
page->card_table_ = NULL;
+ page->progress_bar_ = 0;
if (is_executable) {
page->type_ = OldPage::kExecutable;
} else {
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 50f334f..aff20f3 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -183,6 +183,7 @@
}
#endif
void VisitRememberedCards(ObjectPointerVisitor* visitor);
+ void ResetProgressBar();
private:
void set_object_end(uword value) {
@@ -205,6 +206,7 @@
uword used_in_bytes_;
ForwardingPage* forwarding_page_;
uint8_t* card_table_; // Remembered set, not marking.
+ RelaxedAtomic<intptr_t> progress_bar_;
PageType type_;
friend class PageSpace;
@@ -403,6 +405,7 @@
void VisitObjectPointers(ObjectPointerVisitor* visitor) const;
void VisitRememberedCards(ObjectPointerVisitor* visitor) const;
+ void ResetProgressBars() const;
ObjectPtr FindObject(FindObjectVisitor* visitor,
OldPage::PageType type) const;
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 9425afd..17155e2 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -247,7 +247,7 @@
thread_ = Thread::Current();
page_space_->AcquireLock(freelist_);
- LongJumpScope jump;
+ LongJumpScope jump(thread_);
if (setjmp(*jump.Set()) == 0) {
scavenger_->IterateRoots(this);
} else {
@@ -256,7 +256,7 @@
}
void ProcessSurvivors() {
- LongJumpScope jump;
+ LongJumpScope jump(thread_);
if (setjmp(*jump.Set()) == 0) {
// Iterate until all work has been drained.
do {
@@ -269,7 +269,7 @@
}
void ProcessAll() {
- LongJumpScope jump;
+ LongJumpScope jump(thread_);
if (setjmp(*jump.Set()) == 0) {
do {
do {
@@ -1282,7 +1282,6 @@
enum RootSlices {
kIsolate = 0,
kObjectIdRing,
- kCards,
kStoreBuffer,
kNumRootSlices,
};
@@ -1292,7 +1291,7 @@
for (;;) {
intptr_t slice = root_slices_started_.fetch_add(1);
if (slice >= kNumRootSlices) {
- return; // No more slices.
+ break; // No more slices.
}
switch (slice) {
@@ -1302,9 +1301,6 @@
case kObjectIdRing:
IterateObjectIdTable(visitor);
break;
- case kCards:
- IterateRememberedCards(visitor);
- break;
case kStoreBuffer:
IterateStoreBuffers(visitor);
break;
@@ -1312,6 +1308,8 @@
UNREACHABLE();
}
}
+
+ IterateRememberedCards(visitor);
}
bool Scavenger::IsUnreachable(ObjectPtr* p) {
@@ -1801,6 +1799,7 @@
ASSERT(promotion_stack_.IsEmpty());
MournWeakHandles();
MournWeakTables();
+ heap_->old_space()->ResetProgressBars();
// Restore write-barrier assumptions.
heap_->isolate_group()->RememberLiveTemporaries();
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index e9375c8..3cf19b9 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -553,11 +553,10 @@
}
ASSERT(!code.IsNull());
- // We skip compiled async functions. Once an async function has
- // been compiled, there is another function with the same range which
- // actually contains the user code.
- if (!func.IsAsyncFunction() && !func.IsAsyncGenerator() &&
- !func.IsSyncGenerator()) {
+ // We skip compiled sync generators. Once a sync generator has been compiled,
+ // there is another function with the same range which actually contains the
+ // user code.
+ if (!func.IsSyncGenerator()) {
JSONObject range(jsarr);
range.AddProperty("scriptIndex", script_index);
range.AddProperty("startPos", begin_pos);
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 281ad47..1e4b8f1 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -90,11 +90,7 @@
# Scripts that go under bin/
_platform_sdk_scripts = [ "dartanalyzer" ]
-_full_sdk_scripts = [
- "dart2js",
- "dartanalyzer",
- "dartdevc",
-]
+_full_sdk_scripts = [ "dartanalyzer" ]
# Snapshots that go under bin/snapshots
_platform_sdk_snapshots = [
diff --git a/sdk/bin/dart2js_sdk b/sdk/bin/dart2js_sdk
deleted file mode 100755
index e7999b4..0000000
--- a/sdk/bin/dart2js_sdk
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (c) 2012, 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.
-
-function follow_links() {
- file="$1"
- while [ -h "$file" ]; do
- # On Mac OS, readlink -f doesn't work.
- file="$(readlink "$file")"
- done
- echo "$file"
-}
-
-# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
-PROG_NAME="$(follow_links "$BASH_SOURCE")"
-
-# Handle the case where dart-sdk/bin has been symlinked to.
-BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
-
-SDK_DIR="$(cd "${BIN_DIR}/.." ; pwd -P)"
-
-DART="$BIN_DIR/dart"
-
-SNAPSHOT_DIR="$BIN_DIR/snapshots"
-SNAPSHOT="$SNAPSHOT_DIR/dart2js.dart.snapshot"
-
-unset EXTRA_OPTIONS
-declare -a EXTRA_OPTIONS
-
-if test -t 1; then
- # Stdout is a terminal.
- if test 8 -le `tput colors`; then
- # Stdout has at least 8 colors, so enable colors.
- EXTRA_OPTIONS+=('--enable-diagnostic-colors')
- fi
-fi
-
-unset EXTRA_VM_OPTIONS
-declare -a EXTRA_VM_OPTIONS
-
-if test -f "$SNAPSHOT"; then
- EXTRA_OPTIONS+=("--libraries-spec=$SDK_DIR/lib/libraries.json")
-fi
-
-case $0 in
- *_developer)
- EXTRA_VM_OPTIONS+=('--enable-asserts')
- ;;
-esac
-
-# We allow extra vm options to be passed in through an environment variable.
-if [[ $DART_VM_OPTIONS ]]; then
- read -a OPTIONS <<< "$DART_VM_OPTIONS"
- EXTRA_VM_OPTIONS+=("${OPTIONS[@]}")
-fi
-
-exec "$DART" "${EXTRA_VM_OPTIONS[@]}" "$SNAPSHOT" "${EXTRA_OPTIONS[@]}" "$@"
diff --git a/sdk/bin/dart2js_sdk.bat b/sdk/bin/dart2js_sdk.bat
deleted file mode 100755
index 0a9293c..0000000
--- a/sdk/bin/dart2js_sdk.bat
+++ /dev/null
@@ -1,57 +0,0 @@
-@echo off
-REM Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-REM for details. All rights reserved. Use of this source code is governed by a
-REM BSD-style license that can be found in the LICENSE file.
-
-setlocal
-rem Handle the case where dart-sdk/bin has been symlinked to.
-set DIR_NAME_WITH_SLASH=%~dp0
-set DIR_NAME=%DIR_NAME_WITH_SLASH:~0,-1%%
-call :follow_links "%DIR_NAME%", RETURNED_BIN_DIR
-rem Get rid of surrounding quotes.
-for %%i in ("%RETURNED_BIN_DIR%") do set BIN_DIR=%%~fi
-
-rem Get absolute full name for SDK_DIR.
-for %%i in ("%BIN_DIR%\..\") do set SDK_DIR=%%~fi
-
-rem Remove trailing backslash if there is one
-IF %SDK_DIR:~-1%==\ set SDK_DIR=%SDK_DIR:~0,-1%
-
-set DART=%BIN_DIR%\dart
-set SNAPSHOT=%BIN_DIR%\snapshots\dart2js.dart.snapshot
-
-set EXTRA_OPTIONS=
-set EXTRA_VM_OPTIONS=
-
-if _%DART2JS_DEVELOPER_MODE%_ == _1_ (
- set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% --enable-asserts
-)
-
-if exist "%SNAPSHOT%" (
- set EXTRA_OPTIONS=%EXTRA_OPTIONS% "--libraries-spec=%SDK_DIR%\lib\libraries.json"
-)
-
-rem We allow extra vm options to be passed in through an environment variable.
-if not "_%DART_VM_OPTIONS%_" == "__" (
- set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% %DART_VM_OPTIONS%
-)
-
-"%DART%" %EXTRA_VM_OPTIONS% "%SNAPSHOT%" %EXTRA_OPTIONS% %*
-
-endlocal
-
-exit /b %errorlevel%
-
-:follow_links
-setlocal
-for %%i in (%1) do set result=%%~fi
-set current=
-for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
- ^| %SystemRoot%\System32\find.exe "> %~n1 [" 2^>nul`) do (
- set current=%%i
-)
-if not "%current%"=="" call :follow_links "%current%", result
-endlocal & set %~2=%result%
-goto :eof
-
-:end
diff --git a/sdk/bin/dartdevc_sdk b/sdk/bin/dartdevc_sdk
deleted file mode 100755
index ba71205..0000000
--- a/sdk/bin/dartdevc_sdk
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (c) 2013, 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.
-
-# Run dev compiler on the Dart VM. This script assumes the Dart SDK's
-# directory structure.
-
-echo "Warning: this 'dartdevc' script is deprecated and will be removed. " 1>&2
-echo "More details at https://github.com/dart-lang/sdk/issues/46100." 1>&2
-
-function follow_links() {
- file="$1"
- while [ -h "$file" ]; do
- # On Mac OS, readlink -f doesn't work.
- file="$(readlink "$file")"
- done
- echo "$file"
-}
-
-# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
-PROG_NAME="$(follow_links "$BASH_SOURCE")"
-
-# Handle the case where dart-sdk/bin has been symlinked to.
-BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
-
-SNAPSHOT="$BIN_DIR/snapshots/dartdevc.dart.snapshot"
-
-# We are running the snapshot in the built SDK.
-DART="$BIN_DIR/dart"
-
-unset EXTRA_VM_OPTIONS
-declare -a EXTRA_VM_OPTIONS
-
-# We allow extra vm options to be passed in through an environment variable.
-if [[ $DART_VM_OPTIONS ]]; then
- read -a OPTIONS <<< "$DART_VM_OPTIONS"
- EXTRA_VM_OPTIONS+=("${OPTIONS[@]}")
-fi
-
-exec "$DART" --enable_experiment=non-nullable "${EXTRA_VM_OPTIONS[@]}" "$SNAPSHOT" "$@"
diff --git a/sdk/bin/dartdevc_sdk.bat b/sdk/bin/dartdevc_sdk.bat
deleted file mode 100644
index 931e410..0000000
--- a/sdk/bin/dartdevc_sdk.bat
+++ /dev/null
@@ -1,62 +0,0 @@
-@echo off
-REM Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-REM for details. All rights reserved. Use of this source code is governed by a
-REM BSD-style license that can be found in the LICENSE file.
-
-echo Warning: this 'dartdevc' script is deprecated and will be removed. 1>&2
-echo More details at https://github.com/dart-lang/sdk/issues/46100. 1>&2
-
-setlocal
-rem Handle the case where dart-sdk/bin has been symlinked to.
-set DIR_NAME_WITH_SLASH=%~dp0
-set DIR_NAME=%DIR_NAME_WITH_SLASH:~0,-1%%
-call :follow_links "%DIR_NAME%", RETURNED_BIN_DIR
-rem Get rid of surrounding quotes.
-for %%i in ("%RETURNED_BIN_DIR%") do set BIN_DIR=%%~fi
-
-set DART=%BIN_DIR%\dart
-set SNAPSHOT=%BIN_DIR%\snapshots\dartdevc.dart.snapshot
-
-rem Get absolute full name for SDK_DIR.
-for %%i in ("%BIN_DIR%\..\") do set SDK_DIR=%%~fi
-
-rem Remove trailing backslash if there is one
-if %SDK_DIR:~-1%==\ set SDK_DIR=%SDK_DIR:~0,-1%
-
-set SDK_ARG=--dart-sdk=%SDK_DIR%
-
-set EXTRA_VM_OPTIONS=
-
-rem We allow extra vm options to be passed in through an environment variable.
-if not "_%DART_VM_OPTIONS%_" == "__" (
- set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% %DART_VM_OPTIONS%
-)
-
-"%DART%" %EXTRA_VM_OPTIONS% "%SNAPSHOT%" "%SDK_ARG%" %*
-
-endlocal
-
-exit /b %errorlevel%
-
-rem Follow the symbolic links (junctions points) using `dir to determine the
-rem canonical path. Output with a link looks something like this
-rem
-rem 01/03/2013 10:11 PM <JUNCTION> abc def
-rem [c:\dart_bleeding\dart-repo.9\dart\out\ReleaseIA32\dart-sdk]
-rem
-rem So in the output of 'dir /a:l "targetdir"' we are looking for a filename
-rem surrounded by right angle bracket and left square bracket. Once we get
-rem the filename, which is name of the link, we recursively follow that.
-:follow_links
-setlocal
-for %%i in (%1) do set result=%%~fi
-set current=
-for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
- ^| %SystemRoot%\System32\find.exe "> %~n1 ["`) do (
- set current=%%i
-)
-if not "%current%"=="" call :follow_links "%current%", result
-endlocal & set %~2=%result%
-goto :eof
-
-:end
diff --git a/sdk/lib/_internal/vm/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart
index 8e1d110..99ebc23 100644
--- a/sdk/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk/lib/_internal/vm/lib/async_patch.dart
@@ -372,69 +372,15 @@
}
}
- @pragma("vm:invisible")
- @pragma("vm:prefer-inline")
- void _awaitCompletedFuture(_Future future) {
- assert(future._isComplete);
- final zone = Zone._current;
- if (future._hasError) {
- @pragma("vm:invisible")
- void run() {
- final AsyncError asyncError =
- unsafeCast<AsyncError>(future._resultOrListeners);
- zone.runBinary(
- unsafeCast<dynamic Function(Object, StackTrace)>(_errorCallback),
- asyncError.error,
- asyncError.stackTrace);
- }
-
- zone.scheduleMicrotask(run);
- } else {
- @pragma("vm:invisible")
- void run() {
- zone.runUnary(unsafeCast<dynamic Function(dynamic)>(_thenCallback),
- future._resultOrListeners);
- }
-
- zone.scheduleMicrotask(run);
- }
- }
-
- @pragma("vm:invisible")
- @pragma("vm:prefer-inline")
- void _awaitNotFuture(Object? object) {
- final zone = Zone._current;
- @pragma("vm:invisible")
- void run() {
- zone.runUnary(
- unsafeCast<dynamic Function(dynamic)>(_thenCallback), object);
- }
-
- zone.scheduleMicrotask(run);
- }
-
@pragma("vm:entry-point", "call")
@pragma("vm:invisible")
Object? _await(Object? object) {
- if (_trace) print('_await (object=$object)');
+ if (_trace) print('_awaitAsync (object=$object)');
if (_thenCallback == null) {
_createAsyncCallbacks();
}
- if (object is _Future) {
- if (object._isComplete) {
- _awaitCompletedFuture(object);
- } else {
- object._thenAwait<dynamic>(
- unsafeCast<dynamic Function(dynamic)>(_thenCallback),
- unsafeCast<dynamic Function(Object, StackTrace)>(_errorCallback));
- }
- } else if (object is! Future) {
- _awaitNotFuture(object);
- } else {
- object.then(unsafeCast<dynamic Function(dynamic)>(_thenCallback),
- onError:
- unsafeCast<dynamic Function(Object, StackTrace)>(_errorCallback));
- }
+ _awaitHelper(object, unsafeCast<dynamic Function(dynamic)>(_thenCallback),
+ unsafeCast<dynamic Function(Object, StackTrace)>(_errorCallback));
return _functionData;
}
diff --git a/sdk/lib/_internal/wasm/lib/js_helper.dart b/sdk/lib/_internal/wasm/lib/js_helper.dart
index 5acce01..3bbe07a 100644
--- a/sdk/lib/_internal/wasm/lib/js_helper.dart
+++ b/sdk/lib/_internal/wasm/lib/js_helper.dart
@@ -18,7 +18,7 @@
WasmAnyRef toAnyRef() => _ref;
String toString() => jsStringToDartString(_ref);
- List<Object?> toObjectList() => jsArrayToDartList(_ref);
+ List<Object?> toObjectList() => toDartList(_ref);
Object toObject() => jsObjectToDartObject(_ref);
}
@@ -34,24 +34,59 @@
JSValue toJS() => JSValue(jsObjectFromDartObject(this));
}
-Object? toDart(WasmAnyRef? ref) {
- if (ref == null) {
- return null;
- }
- return jsObjectToDartObject(dartifyRaw(ref)!);
-}
-
Object jsObjectToDartObject(WasmAnyRef ref) => unsafeCastOpaque<Object>(ref);
WasmAnyRef jsObjectFromDartObject(Object object) =>
unsafeCastOpaque<WasmAnyRef>(object);
+@pragma("wasm:import", "dart2wasm.isJSUndefined")
+external bool isJSUndefined(WasmAnyRef? o);
+
+@pragma("wasm:import", "dart2wasm.isJSBoolean")
+external bool isJSBoolean(WasmAnyRef? o);
+
+@pragma("wasm:import", "dart2wasm.isJSNumber")
+external bool isJSNumber(WasmAnyRef? o);
+
+@pragma("wasm:import", "dart2wasm.isJSBigInt")
+external bool isJSBigInt(WasmAnyRef? o);
+
+@pragma("wasm:import", "dart2wasm.isJSString")
+external bool isJSString(WasmAnyRef? o);
+
+@pragma("wasm:import", "dart2wasm.isJSSymbol")
+external bool isJSSymbol(WasmAnyRef? o);
+
+@pragma("wasm:import", "dart2wasm.isJSFunction")
+external bool isJSFunction(WasmAnyRef? o);
+
+@pragma("wasm:import", "dart2wasm.isJSArray")
+external bool isJSArray(WasmAnyRef? o);
+
+@pragma("wasm:import", "dart2wasm.isJSWrappedDartFunction")
+external bool isJSWrappedDartFunction(WasmAnyRef? o);
+
+@pragma("wasm:import", "dart2wasm.isJSObject")
+external bool isJSObject(WasmAnyRef? o);
+
+@pragma("wasm:import", "dart2wasm.roundtrip")
+external double toDartNumber(WasmAnyRef ref);
+
+@pragma("wasm:import", "dart2wasm.roundtrip")
+external bool toDartBool(WasmAnyRef ref);
+
+@pragma("wasm:import", "dart2wasm.objectLength")
+external double objectLength(WasmAnyRef ref);
+
+@pragma("wasm:import", "dart2wasm.objectReadIndex")
+external WasmAnyRef? objectReadIndex(WasmAnyRef ref, int index);
+
+@pragma("wasm:import", "dart2wasm.unwrapJSWrappedDartFunction")
+external Object? unwrapJSWrappedDartFunction(WasmAnyRef f);
+
@pragma("wasm:import", "dart2wasm.arrayFromDartList")
external WasmAnyRef jsArrayFromDartList(List<Object?> list);
-@pragma("wasm:import", "dart2wasm.arrayToDartList")
-external List<Object?> jsArrayToDartList(WasmAnyRef list);
-
@pragma("wasm:import", "dart2wasm.stringFromDartString")
external WasmAnyRef jsStringFromDartString(String string);
@@ -61,9 +96,6 @@
@pragma("wasm:import", "dart2wasm.eval")
external void evalRaw(WasmAnyRef code);
-@pragma("wasm:import", "dart2wasm.dartify")
-external WasmAnyRef? dartifyRaw(WasmAnyRef? object);
-
@pragma("wasm:import", "dart2wasm.newObject")
external WasmAnyRef newObjectRaw();
@@ -113,15 +145,52 @@
}
}
-@pragma("wasm:import", "dart2wasm.wrapDartCallback")
-external WasmAnyRef _wrapDartCallbackRaw(
- WasmAnyRef callback, WasmAnyRef trampolineName);
+/// TODO(joshualitt): We shouldn't need this, but otherwise we seem to get a
+/// cast error for certain oddball types(I think undefined, but need to dig
+/// deeper).
+@pragma("wasm:export", "\$dartifyRaw")
+Object? dartifyExported(WasmAnyRef? ref) => dartifyRaw(ref);
-F _wrapDartCallback<F extends Function>(F f, String trampolineName) {
+Object? dartifyRaw(WasmAnyRef? ref) {
+ if (ref == null) {
+ return null;
+ } else if (isJSUndefined(ref)) {
+ // TODO(joshualitt): Introduce a `JSUndefined` type.
+ return null;
+ } else if (isJSBoolean(ref)) {
+ return toDartBool(ref);
+ } else if (isJSNumber(ref)) {
+ return toDartNumber(ref);
+ } else if (isJSString(ref)) {
+ return jsStringToDartString(ref);
+ } else if (isJSArray(ref)) {
+ return toDartList(ref);
+ } else if (isJSWrappedDartFunction(ref)) {
+ return unwrapJSWrappedDartFunction(ref);
+ } else if (isJSObject(ref) ||
+ // TODO(joshualitt): We may want to create proxy types for some of these
+ // cases.
+ isJSBigInt(ref) ||
+ isJSSymbol(ref) ||
+ isJSFunction(ref)) {
+ return JSValue(ref);
+ } else {
+ return jsObjectToDartObject(ref);
+ }
+}
+
+List<Object?> toDartList(WasmAnyRef ref) => List<Object?>.generate(
+ objectLength(ref).round(), (int n) => dartifyRaw(objectReadIndex(ref, n)));
+
+@pragma("wasm:import", "dart2wasm.wrapDartFunction")
+external WasmAnyRef _wrapDartFunctionRaw(
+ WasmAnyRef dartFunction, WasmAnyRef trampolineName);
+
+F _wrapDartFunction<F extends Function>(F f, String trampolineName) {
if (functionToJSWrapper.containsKey(f)) {
return f;
}
- JSValue wrappedFunction = JSValue(_wrapDartCallbackRaw(
+ JSValue wrappedFunction = JSValue(_wrapDartFunctionRaw(
f.toJS().toAnyRef(), trampolineName.toJS().toAnyRef()));
functionToJSWrapper[f] = wrappedFunction;
return f;
@@ -134,13 +203,3 @@
@pragma("wasm:export", "\$listRead")
WasmAnyRef? _listRead(List<Object?> list, double index) =>
jsifyRaw(list[index.toInt()]);
-
-@pragma("wasm:export", "\$listAllocate")
-List<Object?> _listAllocate() => [];
-
-@pragma("wasm:export", "\$listAdd")
-void _listAdd(List<Object?> list, WasmAnyRef? item) =>
- list.add(dartifyRaw(item));
-
-@pragma("wasm:export", "\$boxJSValue")
-JSValue _boxJSValue(WasmAnyRef ref) => JSValue(ref);
diff --git a/sdk/lib/_internal/wasm/lib/js_util_patch.dart b/sdk/lib/_internal/wasm/lib/js_util_patch.dart
index cbce99d..fb56093 100644
--- a/sdk/lib/_internal/wasm/lib/js_util_patch.dart
+++ b/sdk/lib/_internal/wasm/lib/js_util_patch.dart
@@ -22,15 +22,15 @@
@patch
T getProperty<T>(Object o, String name) =>
- toDart(getPropertyRaw(jsifyRaw(o)!, name.toJS().toAnyRef())) as T;
+ dartifyRaw(getPropertyRaw(jsifyRaw(o)!, name.toJS().toAnyRef())) as T;
@patch
-T setProperty<T>(Object o, String name, T? value) => toDart(
+T setProperty<T>(Object o, String name, T? value) => dartifyRaw(
setPropertyRaw(jsifyRaw(o)!, name.toJS().toAnyRef(), jsifyRaw(value))) as T;
@patch
T callMethod<T>(Object o, String method, List<Object?> args) =>
- toDart(callMethodVarArgsRaw(
+ dartifyRaw(callMethodVarArgsRaw(
jsifyRaw(o)!, method.toJS().toAnyRef(), args.toJS().toAnyRef())) as T;
@patch
@@ -38,7 +38,7 @@
@patch
T callConstructor<T>(Object o, List<Object?> args) =>
- toDart(callConstructorVarArgsRaw(jsifyRaw(o)!, args.toJS().toAnyRef()))!
+ dartifyRaw(callConstructorVarArgsRaw(jsifyRaw(o)!, args.toJS().toAnyRef()))!
as T;
@patch
@@ -99,7 +99,7 @@
@patch
Object? dartify(Object? object) {
if (object is JSValue) {
- return jsObjectToDartObject(dartifyRaw(object.toAnyRef())!);
+ return dartifyRaw(object.toAnyRef())!;
} else {
return object;
}
diff --git a/tests/web/wasm/js_util_test.dart b/tests/web/wasm/js_util_test.dart
index ce10c7b..9bcf43d 100644
--- a/tests/web/wasm/js_util_test.dart
+++ b/tests/web/wasm/js_util_test.dart
@@ -72,12 +72,21 @@
globalThis.a = null;
globalThis.b = 'foo';
globalThis.c = ['a', 'b', 'c'];
+ globalThis.d = 2.5;
+ globalThis.e = true;
+ globalThis.f = function () { return 'hello world'; };
+ globalThis.invoke = function (f) { return f(); }
''');
Object gt = globalThis;
- Expect.isNull(dartify(getProperty(gt, 'a')));
- Expect.equals('foo', dartify(getProperty(gt, 'b')));
- _expectListEquals(
- ['a', 'b', 'c'], dartify(getProperty(gt, 'c')) as List<Object?>);
+ Expect.isNull(getProperty(gt, 'a'));
+ Expect.equals('foo', getProperty(gt, 'b'));
+ _expectListEquals(['a', 'b', 'c'], getProperty<List<Object?>>(gt, 'c'));
+ Expect.equals(2.5, getProperty(gt, 'd'));
+ Expect.equals(true, getProperty(gt, 'e'));
+
+ // Confirm a function that takes a roundtrip remains a function.
+ Expect.equals('hello world',
+ callMethod(gt, 'invoke', <Object?>[dartify(getProperty(gt, 'f'))]));
}
void main() {
diff --git a/tools/VERSION b/tools/VERSION
index 3fa685a..10b6efa 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 18
PATCH 0
-PRERELEASE 189
+PRERELEASE 190
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index d0f40b6..c47ad38 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -916,6 +916,42 @@
"enable-asserts": true
}
},
+ "dartdevc-checked-(linux|mac|win)-(debug|product|release)-(chrome|firefox)-arm64": {
+ "options": {
+ "checked": true,
+ "use-sdk": true
+ }
+ },
+ "dartdevc-strong-linux-release-chrome-arm64": {
+ "options": {
+ "checked": true,
+ "use-sdk": true,
+ "enable-asserts": true
+ }
+ },
+ "dartdevc-weak-linux-release-chrome-arm64": {
+ "options": {
+ "checked": true,
+ "use-sdk": true,
+ "enable-asserts": true
+ }
+ },
+ "dartdevc-canary-strong-(linux|mac|win)-release-(chrome|firefox)-(x64|arm64)": {
+ "options": {
+ "builder-tag": "canary",
+ "checked": true,
+ "use-sdk": true,
+ "enable-asserts": true
+ }
+ },
+ "dartdevc-canary-weak-(linux|mac|win)-release-(chrome|firefox)-(x64|arm64)": {
+ "options": {
+ "builder-tag": "canary",
+ "checked": true,
+ "use-sdk": true,
+ "enable-asserts": true
+ }
+ },
"cfe-(linux|mac|win)": {
"options": {
"compiler": "fasta"
@@ -2360,6 +2396,77 @@
},
{
"builders": [
+ "ddc-canary-linux-release-chrome"
+ ],
+ "meta": {
+ "description": "This configuration is used by the ddc canary builder group."
+ },
+ "steps": [
+ {
+ "name": "build dart",
+ "script": "tools/build.py",
+ "arguments": [
+ "dartdevc_test",
+ "--gn-args=ddc_canary=true"
+ ]
+ },
+ {
+ "name": "ddc nnbd weak tests",
+ "arguments": [
+ "-ndartdevc-canary-weak-linux-release-chrome-x64",
+ "language",
+ "corelib",
+ "lib",
+ "dartdevc",
+ "web"
+ ],
+ "shards": 2,
+ "fileset": "web_platform_nnbd"
+ },
+ {
+ "name": "ddc nnbd weak co19 tests",
+ "arguments": [
+ "-ndartdevc-canary-weak-linux-release-chrome-x64",
+ "co19"
+ ],
+ "shards": 2,
+ "fileset": "web_platform_nnbd"
+ },
+ {
+ "name": "ddc nnbd strong co19 tests",
+ "arguments": [
+ "-ndartdevc-canary-strong-linux-release-chrome-x64",
+ "co19"
+ ],
+ "shards": 3,
+ "fileset": "web_platform_nnbd"
+ },
+ {
+ "name": "ddc weak modular tests",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
+ "testRunner": true,
+ "arguments": [
+ "pkg/dev_compiler/test/modular_suite_nnbd.dart",
+ "-ndartdevc-canary-weak-linux-release-chrome-x64",
+ "--verbose",
+ "--use-sdk"
+ ]
+ },
+ {
+ "name": "ddc nnbd strong tests",
+ "arguments": [
+ "-ndartdevc-canary-strong-linux-release-chrome-x64",
+ "language",
+ "corelib",
+ "lib",
+ "dartdevc",
+ "web"
+ ]
+ }
+ ]
+ },
+ {
+ "builders": [
"ddc-mac-release-chrome"
],
"meta": {