Version 2.11.0-226.0.dev
Merge commit '80f12af7e804c8a7dc9664eac7cedac3c9ba3a1d' into 'dev'
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 57531d9..9fd158d 100644
--- a/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
@@ -5,6 +5,13 @@
import 'package:analyzer/src/dart/analysis/cache.dart';
import 'package:collection/collection.dart';
+class CacheData {
+ final int id;
+ final List<int> 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]`,
@@ -18,39 +25,52 @@
/// [signature].
///
/// Return `null` if the association does not exist.
- List<int> get(String key, List<int> signature);
+ CacheData get(String key, List<int> signature);
- /// Associate the given [bytes] with the [key] and [digest].
- void put(String key, List<int> signature, List<int> bytes);
+ /// Associate the given [bytes] with the [key] and [signature]. Return the
+ /// [CacheData].
+ CacheData putGet(String key, List<int> signature, List<int> bytes);
+
+ /// Used to decrement reference count for the given ids, if implemented.
+ void release(Iterable<int> ids);
}
class CiderCachedByteStore implements CiderByteStore {
final Cache<String, CiderCacheEntry> _cache;
+ int idCounter = 0;
CiderCachedByteStore(int maxCacheSize)
- : _cache =
- Cache<String, CiderCacheEntry>(maxCacheSize, (v) => v.bytes.length);
+ : _cache = Cache<String, CiderCacheEntry>(
+ maxCacheSize, (v) => v.data.bytes.length);
@override
- List<int> get(String key, List<int> signature) {
+ CacheData get(String key, List<int> signature) {
var entry = _cache.get(key, () => null);
if (entry != null &&
const ListEquality<int>().equals(entry.signature, signature)) {
- return entry.bytes;
+ return entry.data;
}
return null;
}
@override
- void put(String key, List<int> signature, List<int> bytes) {
- _cache.put(key, CiderCacheEntry(signature, bytes));
+ CacheData putGet(String key, List<int> signature, List<int> bytes) {
+ idCounter++;
+ var entry = CiderCacheEntry(signature, CacheData(idCounter, bytes));
+ _cache.put(key, entry);
+ return entry.data;
+ }
+
+ @override
+ void release(Iterable<int> ids) {
+ // do nothing
}
}
class CiderCacheEntry {
+ final CacheData data;
final List<int> signature;
- final List<int> bytes;
- CiderCacheEntry(this.signature, this.bytes);
+ CiderCacheEntry(this.signature, this.data);
}
diff --git a/pkg/analyzer/lib/src/dart/micro/library_graph.dart b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
index b870957..d116df5 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
@@ -90,6 +90,9 @@
UnlinkedUnit2 unlinked2;
LibraryCycle _libraryCycle;
+ /// id of the cache entry.
+ int id;
+
FileState._(
this._fsState,
this.path,
@@ -219,7 +222,8 @@
// Prepare bytes of the unlinked bundle - existing or new.
List<int> bytes;
{
- bytes = _fsState._byteStore.get(unlinkedKey, _digest);
+ var cacheData = _fsState._byteStore.get(unlinkedKey, _digest);
+ bytes = cacheData?.bytes;
if (bytes == null || bytes.isEmpty) {
var content = performance.run('content', (_) {
@@ -236,7 +240,8 @@
var unlinkedBuilder = serializeAstCiderUnlinked(_digest, unit);
bytes = unlinkedBuilder.toBuffer();
performance.getDataInt('length').add(bytes.length);
- _fsState._byteStore.put(unlinkedKey, _digest, bytes);
+ cacheData = _fsState._byteStore.putGet(unlinkedKey, _digest, bytes);
+ bytes = cacheData.bytes;
});
performance.run('prefetch', (_) {
@@ -244,6 +249,7 @@
_prefetchDirectReferences(unlinked2);
});
}
+ id = cacheData.id;
}
// Read the unlinked bundle.
@@ -645,6 +651,9 @@
/// The hash of all the paths of the files in this cycle.
String cyclePathsHash;
+ /// id of the cache entry.
+ int id;
+
LibraryCycle();
String get signatureStr {
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index bd7ab2fa..ab523a5 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -83,6 +83,11 @@
_LibraryContext libraryContext;
+ /// List of ids for cache elements that are invalidated. Track elements that
+ /// are invalidated during [changeFile]. Used in [releaseAndClearRemovedIds] to
+ /// release the cache items and is then cleared.
+ final Set<int> removedCacheIds = {};
+
FileResolver(
PerformanceLog logger,
ResourceProvider resourceProvider,
@@ -132,7 +137,8 @@
/// Update the resolver to reflect the fact that the file with the given
/// [path] was changed. We need to make sure that when this file, of any file
/// that directly or indirectly referenced it, is resolved, we used the new
- /// state of the file.
+ /// state of the file. Updates [removedCacheIds] with the ids of the invalidated
+ /// items, used in [releaseAndClearRemovedIds] to release the cache items.
void changeFile(String path) {
if (fsState == null) {
return;
@@ -149,12 +155,13 @@
path: removedFile.path,
uri: removedFile.uri,
);
+ removedCacheIds.add(removedFile.id);
}
// Remove libraries represented by removed files.
// If we need these libraries later, we will relink and reattach them.
if (libraryContext != null) {
- libraryContext.remove(removedFiles);
+ libraryContext.remove(removedFiles, removedCacheIds);
}
}
@@ -184,7 +191,7 @@
var errorsSignature = errorsSignatureBuilder.toByteList();
var errorsKey = file.path + '.errors';
- var bytes = byteStore.get(errorsKey, errorsSignature);
+ var bytes = byteStore.get(errorsKey, errorsSignature)?.bytes;
List<AnalysisError> errors;
if (bytes != null) {
var data = CiderUnitErrors.fromBuffer(bytes);
@@ -204,7 +211,7 @@
signature: errorsSignature,
errors: errors.map(ErrorEncoding.encode).toList(),
).toBuffer();
- byteStore.put(errorsKey, errorsSignature, bytes);
+ bytes = byteStore.putGet(errorsKey, errorsSignature, bytes).bytes;
}
return ErrorsResultImpl(
@@ -314,6 +321,12 @@
_resetContextObjects();
}
+ /// Update the cache with list of invalidated ids and clears [removedCacheIds].
+ void releaseAndClearRemovedIds() {
+ byteStore.release(removedCacheIds);
+ removedCacheIds.clear();
+ }
+
/// The [completionLine] and [completionColumn] are zero based.
ResolvedUnitResult resolve({
int completionLine,
@@ -680,7 +693,8 @@
cycle.directDependencies.forEach(loadBundle);
var key = cycle.cyclePathsHash;
- var bytes = byteStore.get(key, cycle.signature);
+ var data = byteStore.get(key, cycle.signature);
+ var bytes = data?.bytes;
if (bytes == null) {
librariesLinkedTimer.start();
@@ -732,7 +746,8 @@
bytes = serializeBundle(cycle.signature, linkResult).toBuffer();
- byteStore.put(key, cycle.signature, bytes);
+ data = byteStore.putGet(key, cycle.signature, bytes);
+ bytes = data.bytes;
performance.getDataInt('bytesPut').add(bytes.length);
librariesLinkedTimer.stop();
@@ -740,6 +755,7 @@
performance.getDataInt('bytesGet').add(bytes.length);
performance.getDataInt('libraryLoadCount').add(cycle.libraries.length);
}
+ cycle.id = data.id;
var cBundle = CiderLinkedLibraryCycle.fromBuffer(bytes);
inputBundles.add(cBundle.bundle);
@@ -775,14 +791,18 @@
/// Remove libraries represented by the [removed] files.
/// If we need these libraries later, we will relink and reattach them.
- void remove(List<FileState> removed) {
+ void remove(List<FileState> removed, Set<int> removedIds) {
elementFactory.removeLibraries(
removed.map((e) => e.uriStr).toSet(),
);
var removedSet = removed.toSet();
loadedBundles.removeWhere((cycle) {
- return cycle.libraries.any(removedSet.contains);
+ if (cycle.libraries.any(removedSet.contains)) {
+ removedIds.add(cycle.id);
+ return true;
+ }
+ return false;
});
}
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index ae2ec2a..03df87d 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -104,6 +104,8 @@
);
}
argParser
+ ..addMultiOption('define',
+ abbr: 'D', help: 'Defines an environment variable', hide: true)
..addFlag(
'disable-service-auth-codes',
hide: !verbose,
diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart
index fc444ae..5738c65 100644
--- a/pkg/dartdev/test/commands/run_test.dart
+++ b/pkg/dartdev/test/commands/run_test.dart
@@ -154,6 +154,7 @@
'--no-pause-isolates-on-start',
'--no-pause-isolates-on-exit',
'--no-pause-isolates-on-unhandled-exceptions',
+ '-Dfoo=bar',
p.relativeFilePath,
]);
expect(
@@ -173,6 +174,7 @@
'--no-pause-isolates-on-exit',
'--no-pause-isolates-on-unhandled-exceptions',
'--disable-service-auth-codes',
+ '-Dfoo=bar',
p.relativeFilePath,
]);
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index dc92143..ee3f98e 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -180,7 +180,10 @@
defaultsTo: 'amd')
..addFlag('flutter-widget-cache',
help: 'Enable the widget cache to track changes to Widget subtypes',
- defaultsTo: false);
+ defaultsTo: false)
+ ..addFlag('print-incremental-dependencies',
+ help: 'Print list of sources added and removed from compilation',
+ defaultsTo: true);
String usage = '''
Usage: server [options] [input.dart]
@@ -339,6 +342,7 @@
bool incrementalSerialization;
bool useDebuggerModuleNames;
bool emitDebugMetadata;
+ bool _printIncrementalDependencies;
CompilerOptions _compilerOptions;
BytecodeOptions _bytecodeOptions;
@@ -406,6 +410,7 @@
_kernelBinaryFilename = _kernelBinaryFilenameFull;
_initializeFromDill =
_options['initialize-from-dill'] ?? _kernelBinaryFilenameFull;
+ _printIncrementalDependencies = _options['print-incremental-dependencies'];
final String boundaryKey = Uuid().generateV4();
_outputStream.writeln('result $boundaryKey');
final Uri sdkRoot = _ensureFolderPath(options['sdk-root']);
@@ -609,6 +614,9 @@
}
void _outputDependenciesDelta(Iterable<Uri> compiledSources) async {
+ if (!_printIncrementalDependencies) {
+ return;
+ }
Set<Uri> uris = Set<Uri>();
for (Uri uri in compiledSources) {
// Skip empty or corelib dependencies.
diff --git a/runtime/tools/verbose_gc_to_bmu.dart b/runtime/tools/verbose_gc_to_bmu.dart
index 9564e42..6868926 100644
--- a/runtime/tools/verbose_gc_to_bmu.dart
+++ b/runtime/tools/verbose_gc_to_bmu.dart
@@ -10,6 +10,7 @@
// dart --verbose_gc foo.dart 2> foo.gclog
// dart verbose_gc_to_bmu.dart < foo.gclog > foo.bmu
// gnuplot -p -e "set yr [0:1]; set logscale x; plot 'foo.bmu' with linespoints"
+// @dart=2.9
import 'dart:io';
import 'dart:math';
diff --git a/tests/lib/js/extends_test/extends_test.dart b/tests/lib/js/extends_test/extends_test.dart
new file mode 100644
index 0000000..12f8e3f
--- /dev/null
+++ b/tests/lib/js/extends_test/extends_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2020, 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 'extends_test_util.dart';
+
+void main() {
+ // Use the old way to define inheritance between JS objects.
+ eval(r"""
+ function inherits(child, parent) {
+ if (child.prototype.__proto__) {
+ child.prototype.__proto__ = parent.prototype;
+ } else {
+ function tmp() {};
+ tmp.prototype = parent.prototype;
+ child.prototype = new tmp();
+ child.prototype.constructor = child;
+ }
+ }
+ function JSClass(a) {
+ this.a = a;
+ this.getA = function() {
+ return this.a;
+ }
+ this.getAOrB = function() {
+ return this.getA();
+ }
+ }
+ function JSExtendJSClass(a, b) {
+ JSClass.call(this, a);
+ this.b = b;
+ this.getB = function() {
+ return this.b;
+ }
+ this.getAOrB = function() {
+ return this.getB();
+ }
+ }
+ inherits(JSExtendJSClass, JSClass);
+ function JSExtendAnonymousClass(a, b) {
+ this.a = a;
+ this.b = b;
+ this.getA = function() {
+ return this.a;
+ }
+ this.getB = function() {
+ return this.b;
+ }
+ this.getAOrB = function() {
+ return this.getB();
+ }
+ }
+ self.anonExtendAnon = new JSExtendAnonymousClass(1, 2);
+ self.anonExtendJS = new JSExtendJSClass(1, 2);
+ """);
+ testInheritance();
+}
diff --git a/tests/lib/js/extends_test/extends_test_util.dart b/tests/lib/js/extends_test/extends_test_util.dart
new file mode 100644
index 0000000..5185176
--- /dev/null
+++ b/tests/lib/js/extends_test/extends_test_util.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2020, 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.
+
+// Tests inheritance relationships between `JS` and `anonymous` classes/objects.
+
+@JS()
+library extends_test;
+
+import 'package:expect/minitest.dart';
+import 'package:js/js.dart';
+
+@JS()
+external void eval(String code);
+
+@JS()
+class JSClass {
+ external int get a;
+ external int getA();
+ external int getAOrB();
+}
+
+@JS()
+@anonymous
+class AnonymousClass {
+ external int get a;
+ external int getA();
+}
+
+@JS()
+class JSExtendJSClass extends JSClass {
+ external JSExtendJSClass(int a, int b);
+ external int get b;
+ external int getB();
+ external int getAOrB();
+}
+
+@JS()
+class JSExtendAnonymousClass extends AnonymousClass {
+ external JSExtendAnonymousClass(int a, int b);
+ external int get b;
+ external int getB();
+}
+
+@JS()
+@anonymous
+class AnonymousExtendAnonymousClass extends AnonymousClass {
+ external int get b;
+ external int getB();
+}
+
+@JS()
+@anonymous
+class AnonymousExtendJSClass extends JSClass {
+ external int get b;
+ external int getB();
+ external int getAOrB();
+}
+
+external AnonymousExtendAnonymousClass get anonExtendAnon;
+external AnonymousExtendJSClass get anonExtendJS;
+
+void testInheritance() {
+ // Note that for the following, there are no meaningful tests for is checks or
+ // as casts, since the web compilers should return true and succeed for all JS
+ // types.
+
+ var jsExtendJS = JSExtendJSClass(1, 2);
+ expect(jsExtendJS.a, 1);
+ expect(jsExtendJS.b, 2);
+ expect(jsExtendJS.getA(), 1);
+ expect(jsExtendJS.getB(), 2);
+ // Test method overrides.
+ expect(jsExtendJS.getAOrB(), 2);
+ expect((jsExtendJS as JSClass).getAOrB(), 2);
+
+ var jsExtendAnon = JSExtendAnonymousClass(1, 2);
+ expect(jsExtendAnon.a, 1);
+ expect(jsExtendAnon.b, 2);
+ expect(jsExtendAnon.getA(), 1);
+ expect(jsExtendAnon.getB(), 2);
+
+ expect(anonExtendAnon.a, 1);
+ expect(anonExtendAnon.b, 2);
+ expect(anonExtendAnon.getA(), 1);
+ expect(anonExtendAnon.getB(), 2);
+
+ expect(anonExtendJS.a, 1);
+ expect(anonExtendJS.b, 2);
+ expect(anonExtendJS.getA(), 1);
+ expect(anonExtendJS.getB(), 2);
+ expect(anonExtendJS.getAOrB(), 2);
+ expect((anonExtendJS as JSClass).getAOrB(), 2);
+}
diff --git a/tests/lib/js/extends_test/extends_with_es6_test.dart b/tests/lib/js/extends_test/extends_with_es6_test.dart
new file mode 100644
index 0000000..00eb41f
--- /dev/null
+++ b/tests/lib/js/extends_test/extends_with_es6_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2020, 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 'extends_test_util.dart';
+
+void main() {
+ // Use the ES6 syntax for classes to make inheritance easier.
+ eval(r"""
+ class JSClass {
+ constructor(a) {
+ this.a = a;
+ }
+ getA() {
+ return this.a;
+ }
+ getAOrB() {
+ return this.getA();
+ }
+ }
+ class JSExtendJSClass extends JSClass {
+ constructor(a, b) {
+ super(a);
+ this.b = b;
+ }
+ getB() {
+ return this.b;
+ }
+ getAOrB() {
+ return this.getB();
+ }
+ }
+ self.JSExtendJSClass = JSExtendJSClass;
+ class JSExtendAnonymousClass {
+ constructor(a, b) {
+ this.a = a;
+ this.b = b;
+ }
+ getA() {
+ return this.a;
+ }
+ getB() {
+ return this.b;
+ }
+ getAOrB() {
+ return this.getB();
+ }
+ }
+ self.JSExtendAnonymousClass = JSExtendAnonymousClass;
+ self.anonExtendAnon = new JSExtendAnonymousClass(1, 2);
+ self.anonExtendJS = new JSExtendJSClass(1, 2);
+ """);
+ testInheritance();
+}
diff --git a/tools/VERSION b/tools/VERSION
index 70adc94..07cb50e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 11
PATCH 0
-PRERELEASE 225
+PRERELEASE 226
PRERELEASE_PATCH 0
\ No newline at end of file