Version 2.14.0-153.0.dev
Merge commit 'c362bc085c2b7dc3224af6702902817457144ab4' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f8c7ddd..4a3942c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -85,6 +85,8 @@
* Global ignores are no longer taken into account.
* Even packages that are not in git source control will have their
`.gitignore` files respected.
+ * `.gitignore` and `.pubignore` is always case-insensitive on MacOs and
+ Windows (as is default for `git` repositories).
* New flag `dart pub deps --json` gives a machine parsable overview of the
current dependencies.
@@ -100,6 +102,8 @@
This should fix several issues we had with incompatibilities between different
system `tar`s.
* `PUB_HOSTED_URL` can now include a trailing slash.
+* Incremental compilation is now used for compilation of executables from
+ dependencies when using `dart run <package>:<command>`.
### Language
diff --git a/DEPS b/DEPS
index 4017423..accfc1b 100644
--- a/DEPS
+++ b/DEPS
@@ -142,7 +142,7 @@
"pool_rev": "7abe634002a1ba8a0928eded086062f1307ccfae",
"process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
"protobuf_rev": "0d03fd588df69e9863e2a2efc0059dee8f18d5b2",
- "pub_rev": "00c00e8adf9706bebe8f94483b7663c5f36f59d2",
+ "pub_rev": "def32ceb1d660552eaec24839d377199aea5a569",
"pub_semver_rev": "f50d80ef10c4b2fa5f4c8878036a4d9342c0cc82",
"resource_rev": "6b79867d0becf5395e5819a75720963b8298e9a7",
"root_certificates_rev": "7e5ec82c99677a2e5b95ce296c4d68b0d3378ed8",
diff --git a/benchmarks/DartCLIStartup/dart/DartCLIStartup.dart b/benchmarks/DartCLIStartup/dart/DartCLIStartup.dart
new file mode 100644
index 0000000..79ae11f
--- /dev/null
+++ b/benchmarks/DartCLIStartup/dart/DartCLIStartup.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2021, 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:benchmark_harness/benchmark_harness.dart';
+
+class DartCLIStartup extends BenchmarkBase {
+ const DartCLIStartup() : super('DartCLIStartup');
+
+ // The benchmark code.
+ @override
+ void run() {
+ Process.runSync(Platform.executable, ['help']);
+ }
+}
+
+void main() {
+ const DartCLIStartup().report();
+}
diff --git a/benchmarks/DartCLIStartup/dart2/DartCLIStartup.dart b/benchmarks/DartCLIStartup/dart2/DartCLIStartup.dart
new file mode 100644
index 0000000..8f98e9b
--- /dev/null
+++ b/benchmarks/DartCLIStartup/dart2/DartCLIStartup.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2021, 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.
+
+// @dart=2.9
+
+import 'dart:io';
+
+import 'package:benchmark_harness/benchmark_harness.dart';
+
+class DartCLIStartup extends BenchmarkBase {
+ const DartCLIStartup() : super('DartCLIStartup');
+
+ // The benchmark code.
+ @override
+ void run() {
+ Process.runSync(Platform.executable, ['help']);
+ }
+}
+
+void main() {
+ const DartCLIStartup().report();
+}
diff --git a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
new file mode 100644
index 0000000..d1f4ee9
--- /dev/null
+++ b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2021, 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.
+
+// Reports the sizes of binary artifacts shipped with the SDK.
+
+import 'dart:io';
+
+const executables = <String>[
+ 'dart',
+ 'dartaotruntime',
+];
+
+const libs = <String>[
+ 'vm_platform_strong.dill',
+ 'vm_platform_strong_product.dill',
+];
+
+const snapshots = <String>[
+ 'analysis_server',
+ 'dart2js',
+ 'dart2native',
+ 'dartanalyzer',
+ 'dartdev',
+ 'dartdevc',
+ 'dartdoc',
+ 'dartfmt',
+ 'dds',
+ 'frontend_server',
+ 'gen_kernel',
+ 'kernel-service',
+ 'kernel_worker',
+ 'pub',
+];
+
+Future<void> reportArtifactSize(String path, String name) async {
+ final size = await File(path).length();
+ print('SDKArtifactSize_$name(CodeSize): $size');
+}
+
+Future<void> main() async {
+ final topDirIndex =
+ Platform.resolvedExecutable.lastIndexOf(Platform.pathSeparator);
+ final rootDir = Platform.resolvedExecutable.substring(0, topDirIndex);
+
+ for (final executable in executables) {
+ final executablePath = '$rootDir/dart-sdk/bin/$executable';
+ await reportArtifactSize(executablePath, executable);
+ }
+
+ for (final lib in libs) {
+ final libPath = '$rootDir/dart-sdk/lib/_internal/$lib';
+ await reportArtifactSize(libPath, lib);
+ }
+
+ for (final snapshot in snapshots) {
+ final snapshotPath =
+ '$rootDir/dart-sdk/bin/snapshots/$snapshot.dart.snapshot';
+ await reportArtifactSize(snapshotPath, snapshot);
+ }
+}
diff --git a/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
new file mode 100644
index 0000000..d1f4ee9
--- /dev/null
+++ b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2021, 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.
+
+// Reports the sizes of binary artifacts shipped with the SDK.
+
+import 'dart:io';
+
+const executables = <String>[
+ 'dart',
+ 'dartaotruntime',
+];
+
+const libs = <String>[
+ 'vm_platform_strong.dill',
+ 'vm_platform_strong_product.dill',
+];
+
+const snapshots = <String>[
+ 'analysis_server',
+ 'dart2js',
+ 'dart2native',
+ 'dartanalyzer',
+ 'dartdev',
+ 'dartdevc',
+ 'dartdoc',
+ 'dartfmt',
+ 'dds',
+ 'frontend_server',
+ 'gen_kernel',
+ 'kernel-service',
+ 'kernel_worker',
+ 'pub',
+];
+
+Future<void> reportArtifactSize(String path, String name) async {
+ final size = await File(path).length();
+ print('SDKArtifactSize_$name(CodeSize): $size');
+}
+
+Future<void> main() async {
+ final topDirIndex =
+ Platform.resolvedExecutable.lastIndexOf(Platform.pathSeparator);
+ final rootDir = Platform.resolvedExecutable.substring(0, topDirIndex);
+
+ for (final executable in executables) {
+ final executablePath = '$rootDir/dart-sdk/bin/$executable';
+ await reportArtifactSize(executablePath, executable);
+ }
+
+ for (final lib in libs) {
+ final libPath = '$rootDir/dart-sdk/lib/_internal/$lib';
+ await reportArtifactSize(libPath, lib);
+ }
+
+ for (final snapshot in snapshots) {
+ final snapshotPath =
+ '$rootDir/dart-sdk/bin/snapshots/$snapshot.dart.snapshot';
+ await reportArtifactSize(snapshotPath, snapshot);
+ }
+}
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
index b167dc0..a0d6ba6 100644
--- a/pkg/_fe_analyzer_shared/pubspec.yaml
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -1,5 +1,5 @@
name: _fe_analyzer_shared
-version: 21.0.0
+version: 22.0.0
description: Logic that is shared between the front_end and analyzer packages.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/_fe_analyzer_shared
diff --git a/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
index bd38471..6c0624e 100644
--- a/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
+++ b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
@@ -11,21 +11,47 @@
class JsUtilOptimizer extends Transformer {
final Procedure _jsTarget;
final Procedure _getPropertyTarget;
+ final Procedure _setPropertyTarget;
+ final Procedure _setPropertyUncheckedTarget;
+
+ /// Dynamic members in js_util that interop allowed.
+ static final Iterable<String> _allowedInteropJsUtilMembers = <String>[
+ 'callConstructor',
+ 'callMethod',
+ 'getProperty',
+ 'jsify',
+ 'newObject',
+ 'setProperty'
+ ];
+ final Iterable<Procedure> _allowedInteropJsUtilTargets;
+ final Procedure _allowInteropTarget;
JsUtilOptimizer(CoreTypes coreTypes)
: _jsTarget =
coreTypes.index.getTopLevelMember('dart:_foreign_helper', 'JS'),
_getPropertyTarget =
- coreTypes.index.getTopLevelMember('dart:js_util', 'getProperty') {}
+ coreTypes.index.getTopLevelMember('dart:js_util', 'getProperty'),
+ _setPropertyTarget =
+ coreTypes.index.getTopLevelMember('dart:js_util', 'setProperty'),
+ _setPropertyUncheckedTarget = coreTypes.index
+ .getTopLevelMember('dart:js_util', '_setPropertyUnchecked'),
+ _allowInteropTarget =
+ coreTypes.index.getTopLevelMember('dart:js', 'allowInterop'),
+ _allowedInteropJsUtilTargets = _allowedInteropJsUtilMembers.map(
+ (member) =>
+ coreTypes.index.getTopLevelMember('dart:js_util', member)) {}
- /// Replaces js_util method calls with lowering straight to JS fragment call.
+ /// Replaces js_util method calls with optimization when possible.
///
- /// Lowers the following types of js_util calls:
- /// - `getProperty` for any argument types
+ /// Lowers `getProperty` for any argument type straight to JS fragment call.
+ /// Lowers `setProperty` to `_setPropertyUnchecked` for values that are
+ /// not Function type and guaranteed to be interop allowed.
@override
visitStaticInvocation(StaticInvocation node) {
if (node.target == _getPropertyTarget) {
node = _lowerGetProperty(node);
+ } else if (node.target == _setPropertyTarget) {
+ node = _lowerSetProperty(node);
}
node.transformChildren(this);
return node;
@@ -49,7 +75,60 @@
],
// TODO(rileyporter): Copy type from getProperty when it's generic.
types: [DynamicType()],
- )..fileOffset = node.arguments.fileOffset)
+ )..fileOffset = arguments.fileOffset)
..fileOffset = node.fileOffset;
}
+
+ /// Lowers the given js_util `setProperty` call to `_setPropertyUnchecked`
+ /// when the additional validation checks in `setProperty` can be elided.
+ /// Removing the checks allows further inlining by the compilers.
+ StaticInvocation _lowerSetProperty(StaticInvocation node) {
+ Arguments arguments = node.arguments;
+ assert(arguments.types.isEmpty);
+ assert(arguments.positional.length == 3);
+ assert(arguments.named.isEmpty);
+
+ if (!_allowedInterop(arguments.positional.last)) {
+ return node;
+ }
+
+ return StaticInvocation(_setPropertyUncheckedTarget, arguments)
+ ..fileOffset = node.fileOffset;
+ }
+
+ /// Returns whether the given TreeNode is guaranteed to be allowed to interop
+ /// with JS.
+ ///
+ /// Returns true when the node is guaranteed to be not a function:
+ /// - has a DartType that is NullType or an InterfaceType that is not
+ /// Function or Object
+ /// Also returns true for allowed method calls within the JavaScript domain:
+ /// - dart:_foreign_helper JS
+ /// - dart:js `allowInterop`
+ /// - dart:js_util and any of the `_allowedInteropJsUtilMembers`
+ bool _allowedInterop(TreeNode node) {
+ // TODO(rileyporter): Detect functions that have been wrapped at some point
+ // with `allowInterop`
+ // TODO(rileyporter): Use staticTypeContext to generalize type checking and
+ // allow more non-function types. Currently, we skip all literal types.
+ var checkType;
+ if (node is VariableGet) {
+ checkType = node.variable.type;
+ }
+
+ if (node is StaticInvocation) {
+ if (node.target == _allowInteropTarget) return true;
+ if (node.target == _jsTarget) return true;
+ if (_allowedInteropJsUtilTargets.contains(node.target)) return true;
+ checkType = node.target.function.returnType;
+ }
+
+ if (checkType is InterfaceType) {
+ return checkType.classNode.name != 'Function' &&
+ checkType.classNode.name != 'Object';
+ } else {
+ // Only other DartType guaranteed to not be a function.
+ return checkType is NullType;
+ }
+ }
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
index b9f376a..8f452a1 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
@@ -54,6 +54,7 @@
extendedType.element, type.element);
_addTypeMembers(type, inheritanceDistance);
}
+ _addExtensionMembers(containingLibrary, extendedType);
}
}
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_interpolation.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_interpolation.dart
index 639f53f..48ddf53 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_interpolation.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_interpolation.dart
@@ -105,12 +105,12 @@
buffer.write(quotes);
for (var i = 0; i < components.length; i++) {
var component = components[i];
- if (component is SimpleStringLiteral) {
+ if (component is SingleStringLiteral) {
var contents = utils.getRangeText(range.startOffsetEndOffset(
component.contentsOffset, component.contentsEnd));
buffer.write(contents);
} else if (component is SimpleIdentifier) {
- if (_nextStartsWithLetter(components, i)) {
+ if (_nextStartsWithIdentifierContinuation(components, i)) {
buffer.write(r'${');
buffer.write(component.name);
buffer.write('}');
@@ -129,20 +129,22 @@
}
/// Return `true` if the component after [index] in the list of [components]
- /// is one that would begin with a letter when written into the resulting
- /// string.
- bool _nextStartsWithLetter(List<AstNode> components, int index) {
- bool startsWithLetter(String string) =>
- string.startsWith(RegExp('[a-zA-Z]'));
+ /// is one that would begin with a valid identifier continuation character
+ /// when written into the resulting string.
+ bool _nextStartsWithIdentifierContinuation(
+ List<AstNode> components, int index) {
+ bool startsWithIdentifierContinuation(String string) =>
+ string.startsWith(RegExp(r'[a-zA-Z0-9_$]'));
if (index + 1 >= components.length) {
return false;
}
var next = components[index + 1];
if (next is SimpleStringLiteral) {
- return startsWithLetter(next.value);
+ return startsWithIdentifierContinuation(next.value);
} else if (next is StringInterpolation) {
- return startsWithLetter((next.elements[0] as InterpolationString).value);
+ return startsWithIdentifierContinuation(
+ (next.elements[0] as InterpolationString).value);
}
return false;
}
diff --git a/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart b/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
index 004e07b..f1a747c 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
@@ -10,6 +10,7 @@
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(ConstructorCompletionTest);
+ defineReflectiveTests(ExtensionCompletionTest);
defineReflectiveTests(PropertyAccessorCompletionTest);
});
}
@@ -32,6 +33,142 @@
}
@reflectiveTest
+class ExtensionCompletionTest extends CompletionTestCase {
+ Future<void> test_explicitTarget_getter_sameUnit() async {
+ addTestFile('''
+void f(String s) {
+ s.^;
+}
+extension E on String {
+ int get g => length;
+}
+''');
+ await getSuggestions();
+ assertHasCompletion('g');
+ }
+
+ Future<void> test_explicitTarget_method_imported() async {
+ newFile(convertPath('/project/bin/lib.dart'), content: '''
+extension E on String {
+ void m() {}
+}
+''');
+ addTestFile('''
+import 'lib.dart';
+void f(String s) {
+ s.^;
+}
+''');
+ await getSuggestions();
+ assertHasCompletion('m');
+ }
+
+ Future<void> test_explicitTarget_method_inLibrary() async {
+ newFile(convertPath('/project/bin/lib.dart'), content: '''
+part 'test.dart';
+extension E on String {
+ void m() {}
+}
+''');
+ addTestFile('''
+part of 'lib.dart';
+void f(String s) {
+ s.^;
+}
+''');
+ await getSuggestions();
+ assertHasCompletion('m');
+ }
+
+ Future<void> test_explicitTarget_method_inPart() async {
+ newFile(convertPath('/project/bin/part.dart'), content: '''
+extension E on String {
+ void m() {}
+}
+''');
+ addTestFile('''
+part 'part.dart';
+void f(String s) {
+ s.^;
+}
+''');
+ await getSuggestions();
+ assertHasCompletion('m');
+ }
+
+ @failingTest
+ Future<void> test_explicitTarget_method_notImported() async {
+ // Available suggestions data doesn't yet have information about extension
+ // methods.
+ newFile(convertPath('/project/bin/lib.dart'), content: '''
+extension E on String {
+ void m() {}
+}
+''');
+ addTestFile('''
+void f(String s) {
+ s.^;
+}
+''');
+ await getSuggestions();
+ assertHasCompletion('m');
+ }
+
+ Future<void> test_explicitTarget_method_sameUnit() async {
+ addTestFile('''
+void f(String s) {
+ s.^;
+}
+extension E on String {
+ void m() {}
+}
+''');
+ await getSuggestions();
+ assertHasCompletion('m');
+ }
+
+ Future<void> test_explicitTarget_setter_sameUnit() async {
+ addTestFile('''
+void f(String s) {
+ s.^;
+}
+extension E on String {
+ set e(int v) {}
+}
+''');
+ await getSuggestions();
+ assertHasCompletion('e');
+ }
+
+ Future<void> test_implicitTarget_inClass_method_sameUnit() async {
+ addTestFile('''
+class C {
+ void c() {
+ ^
+ }
+}
+extension E on C {
+ void m() {}
+}
+''');
+ await getSuggestions();
+ assertHasCompletion('m');
+ }
+
+ Future<void> test_implicitTarget_inExtension_method_sameUnit() async {
+ addTestFile('''
+extension E on String {
+ void m() {
+ ^
+ }
+}
+''');
+ await getSuggestions();
+ assertHasCompletion('m');
+ }
+}
+
+@reflectiveTest
class PropertyAccessorCompletionTest extends CompletionTestCase {
Future<void> test_setter_deprecated() async {
addTestFile('''
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_interpolation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_interpolation_test.dart
index 0a2539b..5dc54a1 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/replace_with_interpolation_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_with_interpolation_test.dart
@@ -146,6 +146,19 @@
''');
}
+ Future<void> test_variable_stringInterpolation_runTogether_letter() async {
+ await resolveTestCode(r'''
+String f(String s) {
+ return s + 'and $s';
+}
+''');
+ await assertHasFix(r'''
+String f(String s) {
+ return '${s}and $s';
+}
+''');
+ }
+
Future<void> test_variable_stringLiteral_noRuntogther() async {
await resolveTestCode('''
var a = 'a';
@@ -157,7 +170,20 @@
''');
}
- Future<void> test_variable_stringLiteral_runtogther() async {
+ Future<void> test_variable_stringLiteral_runTogether_digit() async {
+ await resolveTestCode('''
+String f(String s) {
+ return s + '1';
+}
+''');
+ await assertHasFix(r'''
+String f(String s) {
+ return '${s}1';
+}
+''');
+ }
+
+ Future<void> test_variable_stringLiteral_runTogether_variable() async {
await resolveTestCode('''
var a = 'a';
var c = a + 'b';
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index bd7f1e8..2bf63ff 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,4 +1,4 @@
-## 1.6.0-dev
+## 1.6.0
* Deprecated `AnalysisDriver` default constructor. Added `tmp1`. The goal
is to allow deprecating and removing unused parameters.
* Added AST structures and visit methods to support the upcoming "constructor
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index c995737..774b215 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -265,6 +265,7 @@
PerformanceLog logger,
ResourceProvider resourceProvider,
ByteStore byteStore,
+ // ignore: avoid_unused_constructor_parameters
FileContentOverlay? contentOverlay,
// ignore: avoid_unused_constructor_parameters
ContextRoot? contextRoot,
@@ -280,7 +281,6 @@
logger: logger,
resourceProvider: resourceProvider,
byteStore: byteStore,
- contentOverlay: contentOverlay,
sourceFactory: sourceFactory,
analysisOptions: analysisOptions,
packages: packages ?? Packages.empty,
@@ -299,8 +299,6 @@
required PerformanceLog logger,
required ResourceProvider resourceProvider,
required ByteStore byteStore,
- @Deprecated('Use OverlayResourceProvider instead')
- FileContentOverlay? contentOverlay,
required SourceFactory sourceFactory,
required AnalysisOptionsImpl analysisOptions,
required Packages packages,
@@ -310,7 +308,7 @@
}) : _scheduler = scheduler,
_resourceProvider = resourceProvider,
_byteStore = byteStore,
- _contentOverlay = contentOverlay ?? FileContentOverlay(),
+ _contentOverlay = FileContentOverlay(),
_analysisOptions = analysisOptions,
enableIndex = enableIndex,
_logger = logger,
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 5d25278..117c8db 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 1.6.0-dev
+version: 1.6.0
description: This package provides a library that performs static analysis of Dart code.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -7,7 +7,7 @@
sdk: '>=2.12.0 <3.0.0'
dependencies:
- _fe_analyzer_shared: ^21.0.0
+ _fe_analyzer_shared: ^22.0.0
cli_util: ^0.3.0
collection: ^1.15.0
convert: ^3.0.0
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index eb08931..01c06dd 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -112,6 +112,7 @@
'dart:_interceptors',
'dart:_js_helper',
'dart:_late_helper',
+ 'dart:js',
'dart:js_util'
];
diff --git a/pkg/compiler/lib/src/util/enumset.dart b/pkg/compiler/lib/src/util/enumset.dart
index 8db885e..e301cf4 100644
--- a/pkg/compiler/lib/src/util/enumset.dart
+++ b/pkg/compiler/lib/src/util/enumset.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
library dart2js.util.enumset;
import 'dart:collection';
@@ -19,11 +21,11 @@
/// Create a set containing the [values]. If [fixed] is `true` the set is
/// immutable.
- factory EnumSet.fromValues(Iterable<E> values, {bool fixed: false}) {
+ factory EnumSet.fromValues(Iterable<E> values, {bool fixed = false}) {
if (fixed) {
- return new _ConstEnumSet<E>.fromValues(values);
+ return _ConstEnumSet<E>.fromValues(values);
} else {
- return new _EnumSet<E>.fromValues(values);
+ return _EnumSet<E>.fromValues(values);
}
}
@@ -53,19 +55,19 @@
/// Returns a new set containing all values in both this and the [other] set.
EnumSet<E> intersection(EnumSet<E> other) {
- return new EnumSet.fromValue(value & other.value);
+ return EnumSet.fromValue(value & other.value);
}
/// Returns a new set containing all values either in this set or in the
/// [other] set.
EnumSet<E> union(EnumSet<E> other) {
- return new EnumSet.fromValue(value | other.value);
+ return EnumSet.fromValue(value | other.value);
}
/// Returns a new set containing all values in this set that are not in the
/// [other] set.
EnumSet<E> minus(EnumSet<E> other) {
- return new EnumSet.fromValue(value & ~other.value);
+ return EnumSet.fromValue(value & ~other.value);
}
/// Clears this set.
@@ -86,7 +88,7 @@
/// Iterable<EnumClass> iterable = set.iterable(EnumClass.values);
///
Iterable<E> iterable(List<E> values) {
- return new _EnumSetIterable(this, values);
+ return _EnumSetIterable(this, values);
}
/// Returns `true` if this and [other] have any elements in common.
@@ -101,7 +103,7 @@
bool get isNotEmpty => value != 0;
/// Returns a new mutable enum set that contains the values of this set.
- EnumSet<E> clone() => new EnumSet<E>.fromValue(value);
+ EnumSet<E> clone() => EnumSet<E>.fromValue(value);
@override
int get hashCode => value.hashCode * 19;
@@ -115,16 +117,7 @@
@override
String toString() {
- if (value == 0) return '0';
- int index = value.bitLength - 1;
- StringBuffer sb = new StringBuffer();
- int mask = 1 << index;
- while (index >= 0) {
- sb.write((value & mask) != 0 ? '1' : '0');
- index--;
- mask >>= 1;
- }
- return sb.toString();
+ return value.toRadixString(2);
}
}
@@ -173,7 +166,7 @@
EnumSet<E> removeAll(EnumSet<E> set) {
int removed = _value & set.value;
_value &= ~set.value;
- return new EnumSet<E>.fromValue(removed);
+ return EnumSet<E>.fromValue(removed);
}
@override
@@ -198,22 +191,22 @@
}
values.forEach(add);
- return new _ConstEnumSet(value);
+ return _ConstEnumSet(value);
}
@override
void set value(int mask) {
- throw new UnsupportedError('EnumSet.value=');
+ throw UnsupportedError('EnumSet.value=');
}
@override
bool add(E enumValue) {
- throw new UnsupportedError('EnumSet.add');
+ throw UnsupportedError('EnumSet.add');
}
@override
void addAll(EnumSet<E> set) {
- throw new UnsupportedError('EnumSet.addAll');
+ throw UnsupportedError('EnumSet.addAll');
}
@override
@@ -222,7 +215,7 @@
// We allow this no-op operation on an immutable set to support using a
// constant empty set together with mutable sets where applicable.
} else {
- throw new UnsupportedError('EnumSet.clear');
+ throw UnsupportedError('EnumSet.clear');
}
}
@@ -233,7 +226,7 @@
// constant empty set together with mutable sets where applicable.
return false;
}
- throw new UnsupportedError('EnumSet.remove');
+ throw UnsupportedError('EnumSet.remove');
}
@override
@@ -248,7 +241,7 @@
// constant empty set together with mutable sets where applicable.
return set.clone();
}
- throw new UnsupportedError('EnumSet.removeAll');
+ throw UnsupportedError('EnumSet.removeAll');
}
}
@@ -259,42 +252,28 @@
_EnumSetIterable(this._enumSet, this._values);
@override
- Iterator<E> get iterator => new _EnumSetIterator(_enumSet.value, _values);
+ Iterator<E> get iterator => _EnumSetIterator(_enumSet.value, _values);
}
class _EnumSetIterator<E> implements Iterator<E> {
int _value;
- int _index;
- int _mask;
final List<E> _values;
- E _current;
+ E? _current;
_EnumSetIterator(this._value, this._values);
@override
- E get current => _current;
+ E get current => _current as E;
@override
bool moveNext() {
if (_value == 0) {
- return false;
- } else {
- if (_mask == null) {
- _index = _value.bitLength - 1;
- _mask = 1 << _index;
- }
_current = null;
- while (_index >= 0) {
- if (_mask & _value != 0) {
- _current = _values[_index];
- }
- _mask >>= 1;
- _index--;
- if (_current != null) {
- break;
- }
- }
- return _current != null;
+ return false;
}
+ int index = _value.bitLength - 1;
+ _current = _values[index];
+ _value &= ~(1 << index);
+ return true;
}
}
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index aab6be3..c7c4e10 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -93,6 +93,7 @@
'dart:collection',
'dart:html',
'dart:indexed_db',
+ 'dart:js',
'dart:js_util',
'dart:math',
'dart:svg',
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 6f0bc6c..47d868c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -20090,6 +20090,23 @@
if (IsDynamicType() || IsVoidType()) {
return false;
}
+ // Left TypeRef.
+ if (IsTypeRef()) {
+ if (TestAndAddBuddyToTrail(&trail, other)) {
+ return true;
+ }
+ const AbstractType& ref_type =
+ AbstractType::Handle(TypeRef::Cast(*this).type());
+ return ref_type.IsSubtypeOf(other, space, trail);
+ }
+ // Right TypeRef.
+ if (other.IsTypeRef()) {
+ // Unfold right hand type. Divergence is controlled by left hand type.
+ const AbstractType& other_ref_type =
+ AbstractType::Handle(TypeRef::Cast(other).type());
+ ASSERT(!other_ref_type.IsTypeRef());
+ return IsSubtypeOf(other_ref_type, space, trail);
+ }
// Left Null type.
if (IsNullType()) {
return Instance::NullIsAssignableTo(other);
@@ -20113,8 +20130,11 @@
const TypeParameter& type_param = TypeParameter::Cast(*this);
if (other.IsTypeParameter()) {
const TypeParameter& other_type_param = TypeParameter::Cast(other);
+ // It is ok to pass the IsSubtypeOf trail to TypeParameter::IsEquivalent,
+ // because it will only be used in a IsSubtypeOf test of the type
+ // parameter bounds.
if (type_param.IsEquivalent(other_type_param,
- TypeEquality::kInSubtypeTest)) {
+ TypeEquality::kInSubtypeTest, trail)) {
return true;
}
}
@@ -21521,8 +21541,12 @@
AbstractType& other_type_param_upper_bound =
AbstractType::Handle(other_type_param.bound());
// Bounds that are mutual subtypes are considered equal.
- if (!upper_bound.IsSubtypeOf(other_type_param_upper_bound, Heap::kOld) ||
- !other_type_param_upper_bound.IsSubtypeOf(upper_bound, Heap::kOld)) {
+ // It is ok to pass the IsEquivalent trail as the IsSubtypeOf trail,
+ // because it is more restrictive (equivalence implies subtype).
+ if (!upper_bound.IsSubtypeOf(other_type_param_upper_bound, Heap::kOld,
+ trail) ||
+ !other_type_param_upper_bound.IsSubtypeOf(upper_bound, Heap::kOld,
+ trail)) {
return false;
}
} else {
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index d119a05..a2af1aa 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -3956,6 +3956,13 @@
return result.ptr();
}
+static FunctionPtr GetFunction(const Library& lib, const char* name) {
+ const Function& result = Function::Handle(
+ lib.LookupLocalFunction(String::Handle(String::New(name))));
+ EXPECT(!result.IsNull());
+ return result.ptr();
+}
+
static FunctionPtr GetStaticFunction(const Class& cls, const char* name) {
const auto& error = cls.EnsureIsFinalized(Thread::Current());
EXPECT(error == Error::null());
@@ -4891,4 +4898,25 @@
EXPECT(str.Equals(char_codes, ARRAY_SIZE(char_codes)));
}
+TEST_CASE(TypeParameterTypeRef) {
+ // Regression test for issue 82890.
+ const char* kScriptChars =
+ "void foo<T extends C<T>>(T x) {}\n"
+ "void bar<M extends U<M>>(M x) {}\n"
+ "abstract class C<T> {}\n"
+ "abstract class U<T> extends C<T> {}\n";
+ TestCase::LoadTestScript(kScriptChars, NULL);
+ TransitionNativeToVM transition(thread);
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
+ const String& name = String::Handle(String::New(TestCase::url()));
+ const Library& lib = Library::Handle(Library::LookupLibrary(thread, name));
+ EXPECT(!lib.IsNull());
+
+ const Function& foo = Function::Handle(GetFunction(lib, "foo"));
+ const Function& bar = Function::Handle(GetFunction(lib, "bar"));
+ const TypeParameter& t = TypeParameter::Handle(foo.TypeParameterAt(0));
+ const TypeParameter& m = TypeParameter::Handle(bar.TypeParameterAt(0));
+ EXPECT(!m.IsSubtypeOf(t, Heap::kNew));
+}
+
} // namespace dart
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
index 5264f8a..96fc0a8 100644
--- a/sdk/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -998,6 +998,13 @@
// method. The Rti object is 'this'.
Rti testRti = _Utils.asRti(JS('', 'this'));
if (object == null) return _nullIs(testRti);
+
+ // Only JavaScript values with `typeof x == "object"` are Dart Lists. Other
+ // typeof results (undefined/string/number/boolean/function/symbol/bigint) are
+ // all non-Lists. Dart `null`, being JavaScript `null` or JavaScript
+ // `undefined`, is handled above.
+ if (JS('bool', 'typeof # != "object"', object)) return false;
+
if (_Utils.isArray(object)) return true;
var tag = Rti._getSpecializedTestResource(testRti);
diff --git a/sdk/lib/js_util/js_util.dart b/sdk/lib/js_util/js_util.dart
index df75900..867fd7f 100644
--- a/sdk/lib/js_util/js_util.dart
+++ b/sdk/lib/js_util/js_util.dart
@@ -68,14 +68,24 @@
bool hasProperty(Object o, Object name) => JS('bool', '# in #', name, o);
+// All usage optimized away in a CFE transformation. Changes here will not
+// affect the generated JS.
dynamic getProperty(Object o, Object name) =>
JS('Object|Null', '#[#]', o, name);
+// Some usage optimized away in a CFE transformation. If given value is a
+// function, changes here will not affect the generated JS.
dynamic setProperty(Object o, Object name, Object? value) {
assertInterop(value);
return JS('', '#[#]=#', o, name, value);
}
+/// Unchecked version of setProperty, only used in a CFE transformation.
+@pragma('dart2js:tryInline')
+dynamic _setPropertyUnchecked(Object o, Object name, Object? value) {
+ return JS('', '#[#]=#', o, name, value);
+}
+
dynamic callMethod(Object o, String method, List<Object?> args) {
assertInteropArgs(args);
return JS('Object|Null', '#[#].apply(#, #)', o, method, o, args);
diff --git a/tests/language/regress/regress34091.dart b/tests/language/regress/regress34091_test.dart
similarity index 100%
rename from tests/language/regress/regress34091.dart
rename to tests/language/regress/regress34091_test.dart
diff --git a/tests/language_2/regress/regress34091.dart b/tests/language_2/regress/regress34091_test.dart
similarity index 100%
rename from tests/language_2/regress/regress34091.dart
rename to tests/language_2/regress/regress34091_test.dart
diff --git a/tests/lib/js/js_util/properties_test.dart b/tests/lib/js/js_util/properties_test.dart
index d21a2c3..64f74bd 100644
--- a/tests/lib/js/js_util/properties_test.dart
+++ b/tests/lib/js/js_util/properties_test.dart
@@ -257,6 +257,8 @@
js_util.setProperty(f, 'a', 100);
expect(f.a, equals(100));
expect(js_util.getProperty(f, 'a'), equals(100));
+ js_util.setProperty(f, 'a', null);
+ expect(f.a, equals(null));
expect(js_util.getProperty(f, 'list') is List, isTrue);
js_util.setProperty(f, 'list', [8]);
@@ -265,6 +267,23 @@
js_util.setProperty(f, 'newProperty', 'new');
expect(js_util.getProperty(f, 'newProperty'), equals('new'));
+
+ // Using a variable for the property value.
+ var num = 4;
+ js_util.setProperty(f, 'a', num);
+ expect(f.a, equals(num));
+ var str = 'bar';
+ js_util.setProperty(f, 'a', str);
+ expect(f.a, equals(str));
+ var b = false;
+ js_util.setProperty(f, 'a', b);
+ expect(f.a, equals(b));
+ var list = [2, 4, 6];
+ js_util.setProperty(f, 'a', list);
+ expect(f.a, equals(list));
+ var fn = allowInterop(dartFunction);
+ js_util.setProperty(f, 'a', fn);
+ expect(f.a, equals(fn));
});
test('typed literal', () {
@@ -319,6 +338,13 @@
String bar = _getBarWithSideEffect();
js_util.setProperty(f, bar, 'baz');
expect(js_util.getProperty(f, bar), equals('baz'));
+ js_util.setProperty(f, _getBarWithSideEffect(), 'mumble');
+ expect(js_util.getProperty(f, bar), equals('mumble'));
+
+ // Set property to a function call.
+ js_util.setProperty(f, 'a', dartFunction());
+ String expected = dartFunction();
+ expect(f.a, equals(expected));
// Using a tearoff as the property value
js_util.setProperty(f, 'tearoff', allowInterop(ExampleTearoff().foo));
diff --git a/tests/lib_2/js/js_util/properties_test.dart b/tests/lib_2/js/js_util/properties_test.dart
index 3d2110b..7bd608f 100644
--- a/tests/lib_2/js/js_util/properties_test.dart
+++ b/tests/lib_2/js/js_util/properties_test.dart
@@ -259,6 +259,8 @@
js_util.setProperty(f, 'a', 100);
expect(f.a, equals(100));
expect(js_util.getProperty(f, 'a'), equals(100));
+ js_util.setProperty(f, 'a', null);
+ expect(f.a, equals(null));
expect(js_util.getProperty(f, 'list') is List, isTrue);
js_util.setProperty(f, 'list', [8]);
@@ -267,6 +269,23 @@
js_util.setProperty(f, 'newProperty', 'new');
expect(js_util.getProperty(f, 'newProperty'), equals('new'));
+
+ // Using a variable for the property value.
+ var num = 4;
+ js_util.setProperty(f, 'a', num);
+ expect(f.a, equals(num));
+ var str = 'bar';
+ js_util.setProperty(f, 'a', str);
+ expect(f.a, equals(str));
+ var b = false;
+ js_util.setProperty(f, 'a', b);
+ expect(f.a, equals(b));
+ var list = [2, 4, 6];
+ js_util.setProperty(f, 'a', list);
+ expect(f.a, equals(list));
+ var fn = allowInterop(dartFunction);
+ js_util.setProperty(f, 'a', fn);
+ expect(f.a, equals(fn));
});
test('typed literal', () {
@@ -321,6 +340,13 @@
String bar = _getBarWithSideEffect();
js_util.setProperty(f, bar, 'baz');
expect(js_util.getProperty(f, bar), equals('baz'));
+ js_util.setProperty(f, _getBarWithSideEffect(), 'mumble');
+ expect(js_util.getProperty(f, bar), equals('mumble'));
+
+ // Set property to a function call.
+ js_util.setProperty(f, 'a', dartFunction());
+ String expected = dartFunction();
+ expect(f.a, equals(expected));
// Using a tearoff as the property value
js_util.setProperty(f, 'tearoff', allowInterop(ExampleTearoff().foo));
diff --git a/tools/VERSION b/tools/VERSION
index 59fa74d..f1b398f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 152
+PRERELEASE 153
PRERELEASE_PATCH 0
\ No newline at end of file