Version 1.19.0-dev.1.0
Merge 'b78aeee6f20dcad020267443bae6b00017f1eae0' into dev
diff --git a/DEPS b/DEPS
index 3b3ac3b..700ff13 100644
--- a/DEPS
+++ b/DEPS
@@ -56,7 +56,7 @@
"dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
"dart_style_tag": "@0.2.4",
"dartdoc_tag" : "@v0.9.6+2",
- "dev_compiler_rev": "@108f2a2a03b1926e640013f3244df625b42ec380",
+ "dev_compiler_rev": "@d39946fd7af11d02a8831dbd7a2b776c69099ff6",
"fixnum_tag": "@0.10.5",
"func_rev": "@8d4aea75c21be2179cb00dc2b94a71414653094e",
"glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
@@ -71,7 +71,7 @@
"isolate_tag": "@0.2.2",
"jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
"json_rpc_2_tag": "@2.0.0",
- "linter_rev": "@7ca3aab6ca45b988440e425c187993a533fbe27e",
+ "linter_rev": "@0abfb82a7d8c36946a2a9f00c699fa5a925abec3",
"logging_rev": "@85d83e002670545e9039ad3985f0018ab640e597",
"markdown_rev": "@4aaadf3d940bb172e1f6285af4d2b1710d309982",
"matcher_tag": "@0.12.0",
@@ -81,7 +81,7 @@
"oauth2_tag": "@1.0.0",
"observatory_pub_packages_rev": "@e5e1e543bea10d4bed95b22ad3e7aa2b20a23584",
"observe_rev": "@eee2b8ec34236fa46982575fbccff84f61202ac6",
- "package_config_rev": "@0.1.5",
+ "package_config_rev": "@1.0.0",
"path_tag": "@1.3.6",
"plugin_tag": "@0.2.0",
"ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 9b4a4ff..0e3ba01 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -12,6 +12,7 @@
isolate: ^0.2.2
linter: ^0.1.16
logging: any
+ package_config: '>=0.1.5 <2.0.0'
path: any
plugin: ^0.2.0
watcher: any
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 5b2416e..d0a2549 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -9,7 +9,6 @@
import 'package:analysis_server/src/context_manager.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/source/embedder.dart';
import 'package:analyzer/source/error_processor.dart';
diff --git a/pkg/analysis_server/test/services/completion/completion_target_test.dart b/pkg/analysis_server/test/services/completion/completion_target_test.dart
index f7cca21..ce02343 100644
--- a/pkg/analysis_server/test/services/completion/completion_target_test.dart
+++ b/pkg/analysis_server/test/services/completion/completion_target_test.dart
@@ -64,11 +64,7 @@
test_ArgumentList_InstanceCreationExpression2() {
// ArgumentList InstanceCreationExpression Block
addTestSource('main() {new Foo(a,^)}');
- if (context.analysisOptions.enableTrailingCommas) {
- assertTarget(')', '(a)', argIndex: 1);
- } else {
- assertTarget('', '(a, )', argIndex: 1);
- }
+ assertTarget(')', '(a)', argIndex: 1);
}
test_ArgumentList_InstanceCreationExpression_functionArg2() {
@@ -104,11 +100,7 @@
test_ArgumentList_MethodInvocation4() {
// ArgumentList MethodInvocation Block
addTestSource('main() {foo(n,^)}');
- if (context.analysisOptions.enableTrailingCommas) {
- assertTarget(')', '(n)', argIndex: 1);
- } else {
- assertTarget('', '(n, )', argIndex: 1);
- }
+ assertTarget(')', '(n)', argIndex: 1);
}
test_ArgumentList_MethodInvocation_functionArg() {
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index 50207ac..efa8227 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -8,8 +8,6 @@
import 'dart:collection';
import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/dart/element/element.dart'
- show ElementImpl, Modifier;
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -559,7 +557,7 @@
// }
// valueStr = valueStr.replaceAll('\n', '\\n');
// print(
-// 'setValue $descriptor for $target value=$valueStr $dependedOn=$dependedOn');
+// 'setValue $descriptor for $target value=$valueStr dependedOn=$dependedOn');
// }
_validateStateChange(descriptor, CacheState.VALID);
TargetedResult thisResult = new TargetedResult(target, descriptor);
@@ -659,7 +657,7 @@
return;
}
}
-// if (deltaResult != null && deltaResult != DeltaResult.KEEP_CONTINUE) {
+// if (deltaResult != null) {
// String indent = ' ' * level;
// String deltaResultName = deltaResult.toString().split('.').last;
// print('[$id]$indent$deltaResultName $descriptor for $target');
@@ -667,36 +665,43 @@
if (deltaResult == DeltaResult.INVALIDATE_NO_DELTA) {
delta = null;
}
- if (deltaResult == null ||
+ if (deltaResult == DeltaResult.INVALIDATE_KEEP_DEPENDENCIES) {
+ thisData.value = descriptor.defaultValue;
+ thisData.state = CacheState.INVALID;
+ } else if (deltaResult == null ||
deltaResult == DeltaResult.INVALIDATE ||
deltaResult == DeltaResult.INVALIDATE_NO_DELTA) {
_resultMap.remove(descriptor);
-// {
-// String indent = ' ' * level;
-// print('[$id]$indent invalidate $descriptor for $target');
-// }
- }
- // Stop depending on other results.
- if (deltaResult != DeltaResult.KEEP_CONTINUE) {
- TargetedResult thisResult = new TargetedResult(target, descriptor);
- List<AnalysisCache> caches = _partition.containingCaches;
- int cacheLength = caches.length;
- List<TargetedResult> results = thisData.dependedOnResults;
- int resultLength = results.length;
- for (int i = 0; i < resultLength; i++) {
- TargetedResult dependedOnResult = results[i];
- for (int j = 0; j < cacheLength; j++) {
- AnalysisCache cache = caches[j];
- CacheEntry entry = cache.get(dependedOnResult.target);
- if (entry != null) {
- ResultData data =
- entry.getResultDataOrNull(dependedOnResult.result);
- if (data != null) {
- data.dependentResults.remove(thisResult);
+ // Stop depending on other results.
+ if (deltaResult != DeltaResult.KEEP_CONTINUE) {
+ TargetedResult thisResult = new TargetedResult(target, descriptor);
+ List<AnalysisCache> caches = _partition.containingCaches;
+ int cacheLength = caches.length;
+ List<TargetedResult> results = thisData.dependedOnResults;
+ int resultLength = results.length;
+ for (int i = 0; i < resultLength; i++) {
+ TargetedResult dependedOnResult = results[i];
+ for (int j = 0; j < cacheLength; j++) {
+ AnalysisCache cache = caches[j];
+ CacheEntry entry = cache.get(dependedOnResult.target);
+ if (entry != null) {
+ ResultData data =
+ entry.getResultDataOrNull(dependedOnResult.result);
+ if (data != null) {
+ data.dependentResults.remove(thisResult);
+ }
}
}
}
}
+// if (deltaResult == null) {
+// String indent = ' ' * level;
+// print('[$id]$indent invalidate $descriptor for $target');
+// if ('$descriptor for $target' ==
+// 'READY_LIBRARY_ELEMENT2 for /Users/scheglov/tmp/limited-invalidation/async/lib/async.dart') {
+// print('interesting');
+// }
+// }
}
// Invalidate results that depend on this result.
_invalidateDependentResults(id, thisData, delta, level + 1);
@@ -1269,11 +1274,17 @@
enum DeltaResult {
/**
* Invalidate this result and continue visiting dependent results
- * with this [Delta].
+ * with this [Delta]. Remove the result and all its dependencies.
*/
INVALIDATE,
/**
+ * Invalidate this result and continue visiting dependent results
+ * with this [Delta]. Keep the dependencies of this result.
+ */
+ INVALIDATE_KEEP_DEPENDENCIES,
+
+ /**
* Invalidate this result and stop using this [Delta], so unconditionally
* invalidate all the dependent results.
*/
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 7ef0108..ca3eebc 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -298,8 +298,7 @@
options.enableStrictCallChecks ||
this._options.enableGenericMethods != options.enableGenericMethods ||
this._options.enableAsync != options.enableAsync ||
- this._options.enableSuperMixins != options.enableSuperMixins ||
- this._options.enableTrailingCommas != options.enableTrailingCommas;
+ this._options.enableSuperMixins != options.enableSuperMixins;
int cacheSize = options.cacheSize;
if (this._options.cacheSize != cacheSize) {
this._options.cacheSize = cacheSize;
@@ -315,7 +314,6 @@
this._options.enableAsync = options.enableAsync;
this._options.enableSuperMixins = options.enableSuperMixins;
this._options.enableTiming = options.enableTiming;
- this._options.enableTrailingCommas = options.enableTrailingCommas;
this._options.hint = options.hint;
this._options.incremental = options.incremental;
this._options.incrementalApi = options.incrementalApi;
@@ -1859,9 +1857,10 @@
// TODO(scheglov) Incorrect implementation in general.
entry.setState(TOKEN_STREAM, CacheState.FLUSHED);
entry.setState(PARSED_UNIT, CacheState.FLUSHED);
- List<Source> librarySources = getLibrariesContaining(source);
- if (librarySources.length == 1) {
- Source librarySource = librarySources[0];
+ SourceKind sourceKind = getKindOf(source);
+ List<Source> partSources = getResult(source, INCLUDED_PARTS);
+ if (sourceKind == SourceKind.LIBRARY && partSources.isEmpty) {
+ Source librarySource = source;
// Try to find an old unit which has element model.
CacheEntry unitEntry =
getCacheEntry(new LibrarySpecificUnit(librarySource, source));
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 97defa6..6be013c 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -398,7 +398,7 @@
@override
void set correspondingPropagatedParameters(
List<ParameterElement> parameters) {
- if (parameters.length != _arguments.length) {
+ if (parameters != null && parameters.length != _arguments.length) {
throw new IllegalArgumentException(
"Expected ${_arguments.length} parameters, not ${parameters.length}");
}
@@ -410,7 +410,7 @@
@override
void set correspondingStaticParameters(List<ParameterElement> parameters) {
- if (parameters.length != _arguments.length) {
+ if (parameters != null && parameters.length != _arguments.length) {
throw new IllegalArgumentException(
"Expected ${_arguments.length} parameters, not ${parameters.length}");
}
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 6c2cd97..b2c10e2 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -698,16 +698,12 @@
if (staticInvokeType != null) {
List<ParameterElement> parameters =
_computeCorrespondingParameters(argumentList, staticInvokeType);
- if (parameters != null) {
- argumentList.correspondingStaticParameters = parameters;
- }
+ argumentList.correspondingStaticParameters = parameters;
}
if (propagatedInvokeType != null) {
List<ParameterElement> parameters =
_computeCorrespondingParameters(argumentList, propagatedInvokeType);
- if (parameters != null) {
- argumentList.correspondingPropagatedParameters = parameters;
- }
+ argumentList.correspondingPropagatedParameters = parameters;
}
//
// Then check for error conditions.
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 9cd12c7..bd08147 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -1087,12 +1087,6 @@
bool get enableTiming;
/**
- * Return `true` to enable trailing commas in parameter and argument lists
- * (sdk#26647).
- */
- bool get enableTrailingCommas;
-
- /**
* A flag indicating whether finer grained dependencies should be used
* instead of just source level dependencies.
*
@@ -1347,7 +1341,6 @@
enableGenericMethods = options.enableGenericMethods;
enableSuperMixins = options.enableSuperMixins;
enableTiming = options.enableTiming;
- enableTrailingCommas = options.enableTrailingCommas;
generateImplicitErrors = options.generateImplicitErrors;
generateSdkErrors = options.generateSdkErrors;
hint = options.hint;
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index f63bb70..fcf9b01 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -2189,12 +2189,6 @@
bool parseGenericMethodComments = false;
/**
- * A flag indicating whether the parser is to parse trailing commas in
- * parameter and argument lists (sdk#26647).
- */
- bool parseTrailingCommas = false;
-
- /**
* Initialize a newly created parser to parse tokens in the given [_source]
* and to report any errors that are found to the given [_errorListener].
*/
@@ -2330,7 +2324,7 @@
bool foundNamedArgument = argument is NamedExpression;
bool generatedError = false;
while (_optional(TokenType.COMMA)) {
- if (parseTrailingCommas && _matches(TokenType.CLOSE_PAREN)) {
+ if (_matches(TokenType.CLOSE_PAREN)) {
break;
}
argument = parseArgument();
@@ -6146,7 +6140,7 @@
type = _currentToken.type;
// Advance past trailing commas as appropriate.
- if (parseTrailingCommas && type == TokenType.COMMA) {
+ if (type == TokenType.COMMA) {
// Only parse commas trailing normal (non-positional/named) params.
if (rightSquareBracket == null && rightCurlyBracket == null) {
Token next = _peek();
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index b662891..0705295 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2855,10 +2855,12 @@
* The resulting AST must have everything resolved that would have been resolved
* by a [DirectiveElementBuilder].
*/
-class DirectiveResolver extends SimpleAstVisitor with ExistingElementResolver {
+class DirectiveResolver extends SimpleAstVisitor {
+ LibraryElement _enclosingLibrary;
+
@override
void visitCompilationUnit(CompilationUnit node) {
- _enclosingUnit = node.element;
+ _enclosingLibrary = node.element.library;
for (Directive directive in node.directives) {
directive.accept(this);
}
@@ -2866,124 +2868,31 @@
@override
void visitExportDirective(ExportDirective node) {
- String uri = _getStringValue(node.uri);
- if (uri != null) {
- LibraryElement library = _enclosingUnit.library;
- Source source = _enclosingUnit.context.sourceFactory
- .resolveUri(_enclosingUnit.source, uri);
- ExportElement exportElement = _findExport(node, library.exports, source);
- node.element = exportElement;
- } else {
- node.element = null;
+ int nodeOffset = node.offset;
+ node.element = null;
+ for (ExportElement element in _enclosingLibrary.exports) {
+ if (element.nameOffset == nodeOffset) {
+ node.element = element;
+ break;
+ }
}
}
@override
void visitImportDirective(ImportDirective node) {
- String uri = _getStringValue(node.uri);
- if (uri != null) {
- LibraryElement library = _enclosingUnit.library;
- Source source = _enclosingUnit.context.sourceFactory
- .resolveUri(_enclosingUnit.source, uri);
- ImportElement importElement = _findImport(node, library.imports, source);
- node.element = importElement;
- } else {
- node.element = null;
+ int nodeOffset = node.offset;
+ node.element = null;
+ for (ImportElement element in _enclosingLibrary.imports) {
+ if (element.nameOffset == nodeOffset) {
+ node.element = element;
+ break;
+ }
}
}
@override
void visitLibraryDirective(LibraryDirective node) {
- node.element = _enclosingUnit.library;
- }
-
- /**
- * Return the export element from the given list of [exports] whose library
- * has the given [source]. Throw an [ElementMismatchException] if an element
- * corresponding to the identifier cannot be found.
- */
- ExportElement _findExport(
- ExportDirective node, List<ExportElement> exports, Source source) {
- if (source == null) {
- return null;
- }
- int length = exports.length;
- for (int i = 0; i < length; i++) {
- ExportElement export = exports[i];
- if (export.exportedLibrary.source == source) {
- // Must have the same offset.
- if (export.nameOffset != node.offset) {
- continue;
- }
- // In general we should also match combinators.
- // But currently we invalidate element model on any directive change.
- // So, either the combinators are the same, or we build new elements.
- return export;
- }
- }
- if (!_enclosingUnit.context.exists(source)) {
- return null;
- }
- _mismatch("Could not find export element for '$source'", node);
- return null; // Never reached
- }
-
- /**
- * Return the import element from the given list of [imports] whose library
- * has the given [source]. Throw an [ElementMismatchException] if an element
- * corresponding to the [source] cannot be found.
- */
- ImportElement _findImport(
- ImportDirective node, List<ImportElement> imports, Source source) {
- if (source == null) {
- return null;
- }
- SimpleIdentifier prefix = node.prefix;
- bool foundSource = false;
- int length = imports.length;
- for (int i = 0; i < length; i++) {
- ImportElement element = imports[i];
- if (element.importedLibrary.source == source) {
- foundSource = true;
- // Must have the same offset.
- if (element.nameOffset != node.offset) {
- continue;
- }
- // Must have the same prefix.
- if (element.prefix?.displayName != prefix?.name) {
- continue;
- }
- // In general we should also match combinators.
- // But currently we invalidate element model on any directive change.
- // So, either the combinators are the same, or we build new elements.
- return element;
- }
- }
- if (!_enclosingUnit.context.exists(source)) {
- return null;
- }
- if (foundSource) {
- if (prefix == null) {
- _mismatch(
- "Could not find import element for '$source' with no prefix", node);
- }
- _mismatch(
- "Could not find import element for '$source' with prefix ${prefix.name}",
- node);
- }
- _mismatch("Could not find any import element for '$source'", node);
- return null; // Never reached
- }
-
- /**
- * Return the value of the given string [literal], or `null` if the string is
- * not a constant string without any string interpolation.
- */
- String _getStringValue(StringLiteral literal) {
- if (literal is StringInterpolation) {
- return null;
- }
- return literal.stringValue;
+ node.element = _enclosingLibrary;
}
}
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
index 0055866..062ce82 100644
--- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -9,9 +9,11 @@
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/resynthesize.dart';
import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/src/util/fast_uri.dart';
import 'package:analyzer/task/dart.dart';
import 'package:analyzer/task/model.dart';
import 'package:path/path.dart' as pathos;
@@ -182,6 +184,18 @@
return true;
}
return false;
+ } else if (result == CONTAINING_LIBRARIES) {
+ List<String> libraryUriStrings =
+ _dataStore.getContainingLibraryUris(uriString);
+ if (libraryUriStrings != null) {
+ List<Source> librarySources = libraryUriStrings
+ .map((libraryUriString) =>
+ context.sourceFactory.resolveUri(target, libraryUriString))
+ .toList(growable: false);
+ entry.setValue(result, librarySources, TargetedResult.EMPTY_LIST);
+ return true;
+ }
+ return false;
}
} else if (target is LibrarySpecificUnit) {
if (result == CREATED_RESOLVED_UNIT1 ||
@@ -294,6 +308,31 @@
}
}
+ /**
+ * Return a list of absolute URIs of the libraries that contain the unit with
+ * the given [unitUriString], or `null` if no such library is in the store.
+ */
+ List<String> getContainingLibraryUris(String unitUriString) {
+ // The unit is the defining unit of a library.
+ if (linkedMap.containsKey(unitUriString)) {
+ return <String>[unitUriString];
+ }
+ // Check every unlinked unit whether it uses [unitUri] as a part.
+ List<String> libraryUriStrings = <String>[];
+ unlinkedMap.forEach((unlinkedUnitUriString, unlinkedUnit) {
+ Uri libraryUri = FastUri.parse(unlinkedUnitUriString);
+ for (String partUriString in unlinkedUnit.publicNamespace.parts) {
+ Uri partUri = FastUri.parse(partUriString);
+ String partAbsoluteUriString =
+ resolveRelativeUri(libraryUri, partUri).toString();
+ if (partAbsoluteUriString == unitUriString) {
+ libraryUriStrings.add(unlinkedUnitUriString);
+ }
+ }
+ });
+ return libraryUriStrings.isNotEmpty ? libraryUriStrings : null;
+ }
+
void _fillMaps(String path) {
io.File file = new io.File(path);
List<int> buffer = file.readAsBytesSync();
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 6860903..0d3981f 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -2656,6 +2656,15 @@
}
}
}
+ for (String name in references.extendedUsedUnnamedConstructorNames) {
+ for (ClassElementDelta classDelta in changedClasses.values) {
+ if (classDelta.name == name && classDelta.hasUnnamedConstructorChange) {
+ _log(() =>
+ '$refLibrary is affected by the default constructor of $name');
+ return true;
+ }
+ }
+ }
return false;
}
@@ -2717,6 +2726,12 @@
@override
DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
ResultDescriptor descriptor, Object value) {
+ // Always invalidate compounding results.
+ if (descriptor == LIBRARY_ELEMENT4 ||
+ descriptor == READY_LIBRARY_ELEMENT6 ||
+ descriptor == READY_LIBRARY_ELEMENT7) {
+ return DeltaResult.INVALIDATE_KEEP_DEPENDENCIES;
+ }
// Prepare target source.
Source targetUnit = target.source;
Source targetLibrary = target.librarySource;
@@ -2759,7 +2774,7 @@
return DeltaResult.INVALIDATE;
}
if (librariesWithAllValidResults.contains(targetLibrary)) {
- return DeltaResult.STOP;
+ return DeltaResult.KEEP_CONTINUE;
}
// The library is almost, but not completely valid.
// Some error results are invalid.
@@ -2784,7 +2799,7 @@
return DeltaResult.KEEP_CONTINUE;
}
librariesWithAllValidResults.add(targetLibrary);
- return DeltaResult.STOP;
+ return DeltaResult.KEEP_CONTINUE;
}
// We don't know what to do with the given target, invalidate it.
return DeltaResult.INVALIDATE;
@@ -4047,7 +4062,6 @@
parser.parseFunctionBodies = options.analyzeFunctionBodiesPredicate(source);
parser.parseGenericMethods = options.enableGenericMethods;
parser.parseGenericMethodComments = options.strongMode;
- parser.parseTrailingCommas = options.enableTrailingCommas;
CompilationUnit unit = parser.parseCompilationUnit(tokenStream);
unit.lineInfo = lineInfo;
@@ -4783,6 +4797,13 @@
final Map<String, Set<String>> superToSubs = <String, Set<String>>{};
/**
+ * The names of extended classes for which the unnamed constructor is
+ * invoked. Because we cannot use the name of the constructor to identify
+ * whether the unit is affected, we need to use the class name.
+ */
+ final Set<String> extendedUsedUnnamedConstructorNames = new Set<String>();
+
+ /**
* The names of instantiated classes.
*
* If one of these classes changes its set of members, it might change
@@ -4818,6 +4839,7 @@
final Set<String> importPrefixNames = new Set<String>();
final ReferencedNames names;
+ String enclosingSuperClassName;
ReferencedNamesScope scope = new ReferencedNamesScope(null);
int localLevel = 0;
@@ -4847,6 +4869,8 @@
try {
scope = new ReferencedNamesScope.forClass(scope, node);
dependsOn = new Set<String>();
+ enclosingSuperClassName =
+ _getSimpleName(node.extendsClause?.superclass?.name);
super.visitClassDeclaration(node);
String className = node.name.name;
names.userToDependsOn[className] = dependsOn;
@@ -4854,11 +4878,22 @@
_addSuperNames(className, node.withClause?.mixinTypes);
_addSuperNames(className, node.implementsClause?.interfaces);
} finally {
+ enclosingSuperClassName = null;
dependsOn = null;
scope = outerScope;
}
}
+ static String _getSimpleName(Identifier identifier) {
+ if (identifier is SimpleIdentifier) {
+ return identifier.name;
+ }
+ if (identifier is PrefixedIdentifier) {
+ return identifier.identifier.name;
+ }
+ return null;
+ }
+
@override
visitClassTypeAlias(ClassTypeAlias node) {
ReferencedNamesScope outerScope = scope;
@@ -4888,6 +4923,14 @@
}
@override
+ visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ if (node.constructorName == null && enclosingSuperClassName != null) {
+ names.extendedUsedUnnamedConstructorNames.add(enclosingSuperClassName);
+ }
+ super.visitSuperConstructorInvocation(node);
+ }
+
+ @override
visitConstructorName(ConstructorName node) {
if (node.parent is! ConstructorDeclaration) {
super.visitConstructorName(node);
diff --git a/pkg/analyzer/lib/src/task/dart_work_manager.dart b/pkg/analyzer/lib/src/task/dart_work_manager.dart
index 6b2a96e..f3dd0b6 100644
--- a/pkg/analyzer/lib/src/task/dart_work_manager.dart
+++ b/pkg/analyzer/lib/src/task/dart_work_manager.dart
@@ -202,6 +202,7 @@
}
}
List<Source> libraries = partLibrariesMap[part];
+ libraries ??= _getLibrariesContainingPartFromResultProvider(part);
return libraries?.toList() ?? Source.EMPTY_LIST;
}
@@ -350,11 +351,28 @@
}
}
+ /**
+ * The given unit was incrementally resolved. Some of its error results might
+ * have been invalidated, so we schedule it for computing errors.
+ */
void unitIncrementallyResolved(Source librarySource, Source unitSource) {
librarySourceQueue.add(librarySource);
}
/**
+ * Ask the [context]'s result provider for [CONTAINING_LIBRARIES].
+ * Return the list of containing libraries, or `null` if unknown.
+ */
+ List<Source> _getLibrariesContainingPartFromResultProvider(Source part) {
+ CacheEntry cacheEntry = context.getCacheEntry(part);
+ bool knows = context.aboutToComputeResult(cacheEntry, CONTAINING_LIBRARIES);
+ if (knows) {
+ return cacheEntry.getValue(CONTAINING_LIBRARIES);
+ }
+ return null;
+ }
+
+ /**
* Return the SDK [DartWorkManager] or this one.
*/
DartWorkManager _getSdkDartWorkManager() {
diff --git a/pkg/analyzer/lib/src/task/incremental_element_builder.dart b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
index 7e5444d..f3247b6 100644
--- a/pkg/analyzer/lib/src/task/incremental_element_builder.dart
+++ b/pkg/analyzer/lib/src/task/incremental_element_builder.dart
@@ -686,9 +686,6 @@
_UpdateElementOffsetsVisitor(this.map);
void visitElement(Element element) {
- if (element is LibraryElement) {
- return;
- }
if (element is ElementImpl) {
// name offset
{
@@ -703,6 +700,10 @@
}
element.nameOffset = newOffset;
}
+ // stop here for LibraryElement
+ if (element is LibraryElementImpl) {
+ return;
+ }
// code range
{
int oldOffset = element.codeOffset;
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index a101147..6cf5585 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -49,7 +49,6 @@
static const String enableGenericMethods = 'enableGenericMethods';
static const String enableStrictCallChecks = 'enableStrictCallChecks';
static const String enableSuperMixins = 'enableSuperMixins';
- static const String enableTrailingCommas = 'enableTrailingCommas';
static const String errors = 'errors';
static const String exclude = 'exclude';
@@ -88,8 +87,7 @@
enableAsync,
enableGenericMethods,
enableStrictCallChecks,
- enableSuperMixins,
- enableTrailingCommas
+ enableSuperMixins
];
}
@@ -504,14 +502,6 @@
context.analysisOptions = options;
}
}
- if (feature == AnalyzerOptions.enableTrailingCommas) {
- if (isTrue(value)) {
- AnalysisOptionsImpl options =
- new AnalysisOptionsImpl.from(context.analysisOptions);
- options.enableTrailingCommas = true;
- context.analysisOptions = options;
- }
- }
if (feature == AnalyzerOptions.enableGenericMethods) {
if (isTrue(value)) {
AnalysisOptionsImpl options =
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 1eccd93..42691d9 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -11,7 +11,7 @@
glob: ^1.0.3
isolate: ^0.2.2
html: ^0.12.0
- package_config: ^0.1.5
+ package_config: '>=0.1.5 <2.0.0'
path: '>=0.9.0 <2.0.0'
plugin: ^0.2.0
watcher: '>=0.9.6 <0.10.0'
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index e74309d..ee61b20 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -1197,21 +1197,11 @@
}
void test_extraCommaInParameterList() {
- parseTrailingCommas = true;
- parse4("parseFormalParameterList", "(int a, , int b)",
- [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN]);
- parseTrailingCommas = false;
parse4("parseFormalParameterList", "(int a, , int b)",
[ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN]);
}
void test_extraCommaTrailingNamedParameterGroup() {
- parseTrailingCommas = true;
- parse4("parseFormalParameterList", "({int b},)", [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS
- ]);
- parseTrailingCommas = false;
parse4("parseFormalParameterList", "({int b},)", [
ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS
@@ -1219,12 +1209,6 @@
}
void test_extraCommaTrailingPositionalParameterGroup() {
- parseTrailingCommas = true;
- parse4("parseFormalParameterList", "([int b],)", [
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS
- ]);
- parseTrailingCommas = false;
parse4("parseFormalParameterList", "([int b],)", [
ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS
@@ -1232,12 +1216,8 @@
}
void test_extraTrailingCommaInParameterList() {
- parseTrailingCommas = true;
parse4("parseFormalParameterList", "(a,,)",
[ParserErrorCode.MISSING_IDENTIFIER]);
- parseTrailingCommas = false;
- parse4("parseFormalParameterList", "(a,,)",
- [ParserErrorCode.MISSING_IDENTIFIER, ParserErrorCode.EXPECTED_TOKEN]);
}
void test_factoryTopLevelDeclaration_class() {
@@ -1740,7 +1720,6 @@
}
void test_missingIdentifierForParameterGroup() {
- parseTrailingCommas = true;
parse4("parseFormalParameterList", "(,)",
[ParserErrorCode.MISSING_IDENTIFIER]);
}
@@ -2807,12 +2786,6 @@
bool enableGenericMethodComments = false;
/**
- * A flag indicating whether parsing trailing commas in parameter and argument
- * lists should be enabled for this test.
- */
- bool parseTrailingCommas = false;
-
- /**
* Return a CommentAndMetadata object with the given values that can be used for testing.
*
* @param comment the comment to be wrapped in the object
@@ -2866,7 +2839,6 @@
parser.parseGenericMethods = enableGenericMethods;
parser.parseGenericMethodComments = enableGenericMethodComments;
parser.parseFunctionBodies = parseFunctionBodies;
- parser.parseTrailingCommas = parseTrailingCommas;
Object result =
invokeParserMethodImpl(parser, methodName, objects, tokenStream);
//
@@ -4793,7 +4765,6 @@
}
void test_parseArgumentList_trailing_comma() {
- parseTrailingCommas = true;
ArgumentList argumentList = parse4("parseArgumentList", "(x, y, z,)");
NodeList<Expression> arguments = argumentList.arguments;
expect(arguments, hasLength(3));
@@ -5982,7 +5953,6 @@
}
void test_parseClassMember_method_trailing_commas() {
- parseTrailingCommas = true;
MethodDeclaration method =
parse("parseClassMember", <Object>["C"], "void f(int x, int y,) {}");
expect(method.documentationComment, isNull);
@@ -7899,7 +7869,6 @@
}
void test_parseFormalParameterList_named_trailing_comma() {
- parseTrailingCommas = true;
FormalParameterList parameterList =
parse4("parseFormalParameterList", "(A a, {B b,})");
expect(parameterList.leftParenthesis, isNotNull);
@@ -7950,7 +7919,6 @@
}
void test_parseFormalParameterList_normal_single_trailing_comma() {
- parseTrailingCommas = true;
FormalParameterList parameterList =
parse4("parseFormalParameterList", "(A a,)");
expect(parameterList.leftParenthesis, isNotNull);
@@ -7981,7 +7949,6 @@
}
void test_parseFormalParameterList_positional_trailing_comma() {
- parseTrailingCommas = true;
FormalParameterList parameterList =
parse4("parseFormalParameterList", "(A a, [B b,])");
expect(parameterList.leftParenthesis, isNotNull);
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index 28dceb7..0030f98 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -2850,6 +2850,28 @@
''');
}
+ void test_class_constructor_named_parameters_change_usedSuper() {
+ // Update a.dart: change A.named().
+ // b.dart is invalid, because it references A.named().
+ _verifyTwoLibrariesInvalidatesResolution(
+ r'''
+class A {
+ A.named(int a);
+}
+''',
+ r'''
+class A {
+ A.named(String a);
+}
+''',
+ r'''
+import 'a.dart';
+class B extends A {
+ B() : super.named(42);
+}
+''');
+ }
+
void test_class_constructor_named_parameters_remove() {
// Update a.dart: remove a new parameter of A.named().
// b.dart is invalid, because it references A.named().
@@ -2916,6 +2938,56 @@
''');
}
+ void test_class_constructor_unnamed_parameters_change_notUsedSuper() {
+ // Update a.dart: change A().
+ // Resolution of b.dart is valid, because it does not reference A().
+ // Hints and verify errors are invalid, because it extends A.
+ // TODO(scheglov) we could keep valid hints and verify errors,
+ // because only constructor is changed - this cannot add/remove
+ // inherited unimplemented members.
+ _verifyTwoLibrariesInvalidHintsVerifyErrors(
+ r'''
+class A {
+ A(int a);
+ A.named(int a);
+}
+''',
+ r'''
+class A {
+ A(String a);
+ A.named(int a);
+}
+''',
+ r'''
+import 'a.dart';
+class B extends A {
+ B() : super.named(42);
+}
+''');
+ }
+
+ void test_class_constructor_unnamed_parameters_change_usedSuper() {
+ // Update a.dart: change A().
+ // b.dart is invalid, because it references A().
+ _verifyTwoLibrariesInvalidatesResolution(
+ r'''
+class A {
+ A(int a);
+}
+''',
+ r'''
+class A {
+ A(String a);
+}
+''',
+ r'''
+import 'a.dart';
+class B extends A {
+ B() : super(42);
+}
+''');
+ }
+
void test_class_constructor_unnamed_parameters_remove() {
// Update a.dart: change A().
// b.dart is invalid, because it references A().
@@ -2962,8 +3034,8 @@
}
void test_class_constructor_unnamed_remove_used() {
- // Update a.dart: remove A.named().
- // b.dart is invalid, because it references A.named().
+ // Update a.dart: remove A().
+ // b.dart is invalid, because it references A().
_verifyTwoLibrariesInvalidatesResolution(
r'''
class A {
@@ -3493,6 +3565,72 @@
expect(context.getErrors(b).errors, hasLength(1));
}
+ void test_sequence_clearParameterElements() {
+ Source a = addSource(
+ '/a.dart',
+ r'''
+class A {
+ foo(int p) {}
+}
+final a = new A();
+main() {
+ a.foo(42);
+}
+''');
+ _performPendingAnalysisTasks();
+ Expression find42() {
+ CompilationUnit unit =
+ context.getResult(new LibrarySpecificUnit(a, a), RESOLVED_UNIT);
+ ExpressionStatement statement =
+ AstFinder.getStatementsInTopLevelFunction(unit, 'main').single;
+ MethodInvocation invocation = statement.expression;
+ return invocation.argumentList.arguments[0];
+ }
+ {
+ Expression argument = find42();
+ expect(argument.staticParameterElement, isNull);
+ expect(argument.propagatedParameterElement, isNotNull);
+ }
+ // Update a.dart: add type annotation for 'a'.
+ // '42' has 'staticParameterElement', but not 'propagatedParameterElement'.
+ context.setContents(
+ a,
+ r'''
+class A {
+ foo(int p) {}
+}
+final A a = new A();
+main() {
+ a.foo(42);
+}
+''');
+ _performPendingAnalysisTasks();
+ {
+ Expression argument = find42();
+ expect(argument.staticParameterElement, isNotNull);
+ expect(argument.propagatedParameterElement, isNull);
+ }
+ // Update a.dart: remove type annotation for 'a'.
+ // '42' has 'propagatedParameterElement', but not 'staticParameterElement'.
+ context.setContents(
+ a,
+ r'''
+class A {
+ foo(int p) {}
+}
+final a = new A();
+main() {
+ a.foo(42);
+}
+''');
+ _performPendingAnalysisTasks();
+ {
+ Expression argument = find42();
+ expect(argument.staticParameterElement, isNull);
+ expect(argument.propagatedParameterElement, isNotNull);
+ }
+ }
+
void test_sequence_closureParameterTypesPropagation() {
Source a = addSource(
'/a.dart',
@@ -3522,6 +3660,175 @@
expect(parameterName.propagatedType, context.typeProvider.intType);
}
+ void test_sequence_compoundingResults_exportNamespace() {
+ Source a = addSource(
+ '/a.dart',
+ r'''
+class A<T> {}
+''');
+ Source b = addSource(
+ '/b.dart',
+ r'''
+export 'a.dart';
+''');
+ Source c = addSource(
+ '/c.dart',
+ r'''
+import 'b.dart';
+main() {
+ new A<int>();
+}
+''');
+ _performPendingAnalysisTasks();
+ expect(context.getErrors(c).errors, isEmpty);
+ // Update a.dart, so that `A<T>` has a type bound.
+ // This should invalidate export namespace for b.dart.
+ // Currently we invalidate the whole LIBRARY_ELEMENT4.
+ // So, c.dart will see the new `A<T extends B>` and report an error.
+ context.setContents(
+ a,
+ r'''
+class A<T extends B> {}
+class B {}
+''');
+ _assertInvalid(b, LIBRARY_ELEMENT4);
+ // Analyze and validate that a new error is reported.
+ _performPendingAnalysisTasks();
+ expect(context.getErrors(c).errors, hasLength(1));
+ _assertValid(a, LIBRARY_ERRORS_READY);
+ _assertValid(b, LIBRARY_ERRORS_READY);
+ _assertValid(c, LIBRARY_ERRORS_READY);
+ }
+
+ void test_sequence_compoundingResults_invalidateButKeepDependency() {
+ Source a = addSource(
+ '/a.dart',
+ r'''
+import 'b.dart';
+class A {}
+''');
+ Source b = addSource(
+ '/b.dart',
+ r'''
+import 'a.dart';
+import 'c.dart';
+class B {}
+''');
+ Source c = addSource(
+ '/c.dart',
+ r'''
+class C {}
+''');
+ Source d = addSource(
+ '/d.dart',
+ r'''
+export 'b.dart';
+''');
+ _performPendingAnalysisTasks();
+ expect(context.getErrors(c).errors, isEmpty);
+ // Update: a.dart (limited) and b.dart (limited).
+ // This should invalidate LIBRARY_ELEMENT4 in d.dart, but it should be
+ // done in a way that keep dependency of other results od d.dart on
+ // LIBRARY_ELEMENT4 of d.dart, so that when we perform unlimited
+ // invalidation of c.dart, this makes d.dart invalid.
+ context.setContents(
+ a,
+ r'''
+import 'b.dart';
+class A2 {}
+''');
+ context.setContents(
+ b,
+ r'''
+import 'a.dart';
+import 'c.dart';
+class B2 {}
+''');
+ context.setContents(
+ c,
+ r'''
+import 'dart:async';
+class C {}
+''');
+ _assertInvalid(d, LIBRARY_ELEMENT4);
+ _assertInvalid(d, LIBRARY_ERRORS_READY);
+ // Analyze and validate that a new error is reported.
+ _performPendingAnalysisTasks();
+ _assertValid(a, EXPORT_SOURCE_CLOSURE);
+ _assertValid(b, EXPORT_SOURCE_CLOSURE);
+ _assertValid(c, EXPORT_SOURCE_CLOSURE);
+ _assertValid(d, EXPORT_SOURCE_CLOSURE);
+ _assertValid(a, LIBRARY_ERRORS_READY);
+ _assertValid(b, LIBRARY_ERRORS_READY);
+ _assertValid(c, LIBRARY_ERRORS_READY);
+ _assertValid(d, LIBRARY_ERRORS_READY);
+ }
+
+ void test_sequence_compoundingResults_resolvedTypeNames() {
+ Source a = addSource(
+ '/a.dart',
+ r'''
+class A {}
+''');
+ Source b = addSource(
+ '/b.dart',
+ r'''
+class B<T> {
+ B(p);
+}
+''');
+ Source c = addSource(
+ '/c.dart',
+ r'''
+export 'a.dart';
+export 'b.dart';
+''');
+ Source d = addSource(
+ '/d.dart',
+ r'''
+import 'c.dart';
+main() {
+ new B<int>(null);
+}
+''');
+ _performPendingAnalysisTasks();
+ // Update a.dart and b.dart
+ // This should invalidate most results in a.dart and b.dart
+ //
+ // This should also invalidate "compounding" results in c.dart, such as
+ // READY_LIBRARY_ELEMENT6, which represent a state of the whole source
+ // closure, not a result of this single unit or a library.
+ //
+ // The reason is that although type names (RESOLVED_UNIT5) b.dart will be
+ // eventually resolved and set into b.dart elements, it may happen
+ // after we attempted to re-resolve c.dart, which created Member(s), and
+ // attempts to use elements without types set.
+ context.setContents(
+ a,
+ r'''
+class A2 {}
+''');
+ context.setContents(
+ b,
+ r'''
+class B<T> {
+ B(T p);
+}
+''');
+ _assertValidForChangedLibrary(a);
+ _assertInvalid(a, LIBRARY_ERRORS_READY);
+ _assertValidForChangedLibrary(b);
+ _assertInvalid(b, LIBRARY_ERRORS_READY);
+ _assertInvalid(c, READY_LIBRARY_ELEMENT6);
+ _assertInvalid(c, READY_LIBRARY_ELEMENT7);
+ // Analyze and validate that all results are valid.
+ _performPendingAnalysisTasks();
+ _assertValid(a, LIBRARY_ERRORS_READY);
+ _assertValid(b, LIBRARY_ERRORS_READY);
+ _assertValid(c, LIBRARY_ERRORS_READY);
+ _assertValid(d, LIBRARY_ERRORS_READY);
+ }
+
void test_sequence_dependenciesWithCycles() {
Source a = addSource(
'/a.dart',
@@ -3795,6 +4102,64 @@
expect(context.getErrors(b).errors, hasLength(0));
}
+ void test_sequence_parts_disableForPart() {
+ Source a = addSource(
+ '/a.dart',
+ r'''
+library my_lib;
+part 'b.dart';
+''');
+ Source b = addSource(
+ '/b.dart',
+ r'''
+part of my_lib;
+class A {}
+''');
+ _performPendingAnalysisTasks();
+ // Update b.dart - it is a part, which we don't support.
+ // So, invalidate everything.
+ context.setContents(
+ b,
+ r'''
+part of my_lib;
+class A {}
+class B {}
+''');
+ _assertInvalid(a, LIBRARY_ERRORS_READY);
+ _assertInvalid(b, LIBRARY_ERRORS_READY);
+ _assertInvalidUnits(a, RESOLVED_UNIT2);
+ _assertInvalidUnits(b, RESOLVED_UNIT1);
+ }
+
+ void test_sequence_parts_disableWithPart() {
+ Source a = addSource(
+ '/a.dart',
+ r'''
+library my_lib;
+part 'b.dart';
+''');
+ Source b = addSource(
+ '/b.dart',
+ r'''
+part of my_lib;
+class B {}
+''');
+ _performPendingAnalysisTasks();
+ // Update a.dart - it is a library with a part, which we don't support.
+ // So, invalidate everything.
+ context.setContents(
+ a,
+ r'''
+library my_lib;
+part 'b.dart';
+class A {}
+''');
+ _assertInvalid(a, LIBRARY_ERRORS_READY);
+ _assertInvalid(b, LIBRARY_ERRORS_READY);
+ _assertInvalidUnits(a, RESOLVED_UNIT1);
+ _assertInvalidUnits(b, RESOLVED_UNIT1);
+ }
+
void test_sequence_reorder_localFunctions() {
Source a = addSource(
'/a.dart',
@@ -4338,10 +4703,13 @@
}
void _assertValidAllLibraryUnitResults(Source source, {Source library}) {
- for (ResultDescriptor<LibraryElement> result in LIBRARY_ELEMENT_RESULTS) {
- _assertValid(source, result);
- }
library ??= source;
+ for (ResultDescriptor<LibraryElement> result in LIBRARY_ELEMENT_RESULTS) {
+ if (result == LIBRARY_ELEMENT4) {
+ continue;
+ }
+ _assertValid(library, result);
+ }
LibrarySpecificUnit target = new LibrarySpecificUnit(library, source);
for (ResultDescriptor<CompilationUnit> result in RESOLVED_UNIT_RESULTS) {
_assertValid(target, result);
@@ -4441,6 +4809,20 @@
_assertInvalid(b, LIBRARY_ERRORS_READY);
_assertInvalidUnits(b, RESOLVED_UNIT4);
}
+
+ void _verifyTwoLibrariesInvalidHintsVerifyErrors(
+ String firstCodeA, String secondCodeA, String codeB) {
+ Source a = addSource('/a.dart', firstCodeA);
+ Source b = addSource('/b.dart', codeB);
+ _performPendingAnalysisTasks();
+ context.setContents(a, secondCodeA);
+ _assertValidForChangedLibrary(a);
+ _assertInvalid(a, LIBRARY_ERRORS_READY);
+ _assertValidForDependentLibrary(b);
+ _assertValidAllResolution(b);
+ _assertUnitValid(b, RESOLVE_UNIT_ERRORS);
+ _assertInvalidHintsVerifyErrors(b);
+ }
}
class _AnalysisContextImplTest_Source_exists_true extends TestSource {
diff --git a/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart b/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
new file mode 100644
index 0000000..e446d19
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
@@ -0,0 +1,229 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/context/cache.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/src/util/fast_uri.dart';
+import 'package:analyzer/task/dart.dart';
+import 'package:typed_mock/typed_mock.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../reflective_tests.dart';
+
+main() {
+ groupSep = ' | ';
+ runReflectiveTests(ResynthesizerResultProviderTest);
+ runReflectiveTests(SummaryDataStoreTest);
+}
+
+UnlinkedPublicNamespace _namespaceWithParts(List<String> parts) {
+ UnlinkedPublicNamespace namespace = new _UnlinkedPublicNamespaceMock();
+ when(namespace.parts).thenReturn(parts);
+ return namespace;
+}
+
+@reflectiveTest
+class ResynthesizerResultProviderTest {
+ SourceFactory sourceFactory = new _SourceFactoryMock();
+ InternalAnalysisContext context = new _InternalAnalysisContextMock();
+ UniversalCachePartition cachePartition;
+
+ Source source1 = new _SourceMock('package:p1/u1.dart', '/p1/lib/u1.dart');
+ Source source2 = new _SourceMock('package:p1/u2.dart', '/p1/lib/u2.dart');
+ Source source3 = new _SourceMock('package:p2/u1.dart', '/p2/lib/u1.dart');
+ CacheEntry entry1;
+ CacheEntry entry2;
+ CacheEntry entry3;
+
+ PackageBundle bundle = new _PackageBundleMock();
+ UnlinkedUnit unlinkedUnit1 = new _UnlinkedUnitMock();
+ UnlinkedUnit unlinkedUnit2 = new _UnlinkedUnitMock();
+ LinkedLibrary linkedLibrary = new _LinkedLibraryMock();
+
+ SummaryDataStore dataStore = new SummaryDataStore(<String>[]);
+ _TestResynthesizerResultProvider provider;
+
+ void setUp() {
+ cachePartition = new UniversalCachePartition(context);
+ entry1 = new CacheEntry(source1);
+ entry2 = new CacheEntry(source2);
+ entry3 = new CacheEntry(source3);
+ cachePartition.put(entry1);
+ cachePartition.put(entry2);
+ cachePartition.put(entry3);
+
+ when(sourceFactory.resolveUri(anyObject, 'package:p1/u1.dart'))
+ .thenReturn(source1);
+ when(sourceFactory.resolveUri(anyObject, 'package:p1/u2.dart'))
+ .thenReturn(source2);
+ when(context.sourceFactory).thenReturn(sourceFactory);
+
+ when(bundle.unlinkedUnitUris)
+ .thenReturn(<String>['package:p1/u1.dart', 'package:p1/u2.dart']);
+ when(bundle.unlinkedUnits)
+ .thenReturn(<UnlinkedUnit>[unlinkedUnit1, unlinkedUnit2]);
+ when(bundle.linkedLibraryUris).thenReturn(<String>['package:p1/u1.dart']);
+ when(bundle.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary]);
+ dataStore.addBundle('/p1.ds', bundle);
+
+ when(unlinkedUnit1.publicNamespace)
+ .thenReturn(_namespaceWithParts(['package:p1/u2.dart']));
+ when(unlinkedUnit2.publicNamespace).thenReturn(_namespaceWithParts([]));
+
+ provider = new _TestResynthesizerResultProvider(context, dataStore);
+ provider.sourcesWithResults.add(source1);
+ provider.sourcesWithResults.add(source2);
+ }
+
+ test_compute_CONTAINING_LIBRARIES_librarySource() {
+ bool success = provider.compute(entry1, CONTAINING_LIBRARIES);
+ expect(success, isTrue);
+ expect(entry1.getValue(CONTAINING_LIBRARIES), unorderedEquals([source1]));
+ }
+
+ test_compute_CONTAINING_LIBRARIES_partSource() {
+ bool success = provider.compute(entry2, CONTAINING_LIBRARIES);
+ expect(success, isTrue);
+ expect(entry2.getValue(CONTAINING_LIBRARIES), unorderedEquals([source1]));
+ }
+
+ test_compute_SOURCE_KIND_librarySource() {
+ bool success = provider.compute(entry1, SOURCE_KIND);
+ expect(success, isTrue);
+ expect(entry1.getValue(SOURCE_KIND), SourceKind.LIBRARY);
+ }
+
+ test_compute_SOURCE_KIND_noResults() {
+ bool success = provider.compute(entry3, SOURCE_KIND);
+ expect(success, isFalse);
+ expect(entry3.getState(SOURCE_KIND), CacheState.INVALID);
+ }
+
+ test_compute_SOURCE_KIND_partSource() {
+ bool success = provider.compute(entry2, SOURCE_KIND);
+ expect(success, isTrue);
+ expect(entry2.getValue(SOURCE_KIND), SourceKind.PART);
+ }
+}
+
+@reflectiveTest
+class SummaryDataStoreTest {
+ SummaryDataStore dataStore = new SummaryDataStore(<String>[]);
+
+ PackageBundle bundle1 = new _PackageBundleMock();
+ PackageBundle bundle2 = new _PackageBundleMock();
+ UnlinkedUnit unlinkedUnit11 = new _UnlinkedUnitMock();
+ UnlinkedUnit unlinkedUnit12 = new _UnlinkedUnitMock();
+ UnlinkedUnit unlinkedUnit21 = new _UnlinkedUnitMock();
+ LinkedLibrary linkedLibrary1 = new _LinkedLibraryMock();
+ LinkedLibrary linkedLibrary2 = new _LinkedLibraryMock();
+
+ void setUp() {
+ // bundle1
+ when(unlinkedUnit11.publicNamespace)
+ .thenReturn(_namespaceWithParts(['package:p1/u2.dart']));
+ when(unlinkedUnit12.publicNamespace).thenReturn(_namespaceWithParts([]));
+ when(bundle1.unlinkedUnitUris)
+ .thenReturn(<String>['package:p1/u1.dart', 'package:p1/u2.dart']);
+ when(bundle1.unlinkedUnits)
+ .thenReturn(<UnlinkedUnit>[unlinkedUnit11, unlinkedUnit12]);
+ when(bundle1.linkedLibraryUris).thenReturn(<String>['package:p1/u1.dart']);
+ when(bundle1.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary1]);
+ dataStore.addBundle('/p1.ds', bundle1);
+ // bundle2
+ when(unlinkedUnit21.publicNamespace).thenReturn(_namespaceWithParts([]));
+ when(bundle2.unlinkedUnitUris).thenReturn(<String>['package:p2/u1.dart']);
+ when(bundle2.unlinkedUnits).thenReturn(<UnlinkedUnit>[unlinkedUnit21]);
+ when(bundle2.linkedLibraryUris).thenReturn(<String>['package:p2/u1.dart']);
+ when(bundle2.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary2]);
+ dataStore.addBundle('/p2.ds', bundle2);
+ }
+
+ test_addBundle() {
+ expect(dataStore.bundles, unorderedEquals([bundle1, bundle2]));
+ expect(dataStore.uriToSummaryPath,
+ containsPair('package:p1/u1.dart', '/p1.ds'));
+ // unlinkedMap
+ expect(dataStore.unlinkedMap, hasLength(3));
+ expect(dataStore.unlinkedMap,
+ containsPair('package:p1/u1.dart', unlinkedUnit11));
+ expect(dataStore.unlinkedMap,
+ containsPair('package:p1/u2.dart', unlinkedUnit12));
+ expect(dataStore.unlinkedMap,
+ containsPair('package:p2/u1.dart', unlinkedUnit21));
+ // linkedMap
+ expect(dataStore.linkedMap, hasLength(2));
+ expect(dataStore.linkedMap,
+ containsPair('package:p1/u1.dart', linkedLibrary1));
+ expect(dataStore.linkedMap,
+ containsPair('package:p2/u1.dart', linkedLibrary2));
+ }
+
+ test_getContainingLibraryUris_libraryUri() {
+ String partUri = 'package:p1/u1.dart';
+ List<String> uris = dataStore.getContainingLibraryUris(partUri);
+ expect(uris, unorderedEquals([partUri]));
+ }
+
+ test_getContainingLibraryUris_partUri() {
+ String partUri = 'package:p1/u2.dart';
+ List<String> uris = dataStore.getContainingLibraryUris(partUri);
+ expect(uris, unorderedEquals(['package:p1/u1.dart']));
+ }
+
+ test_getContainingLibraryUris_unknownUri() {
+ String partUri = 'package:notInStore/foo.dart';
+ List<String> uris = dataStore.getContainingLibraryUris(partUri);
+ expect(uris, isNull);
+ }
+}
+
+class _InternalAnalysisContextMock extends TypedMock
+ implements InternalAnalysisContext {}
+
+class _LinkedLibraryMock extends TypedMock implements LinkedLibrary {}
+
+class _PackageBundleMock extends TypedMock implements PackageBundle {}
+
+class _SourceFactoryMock extends TypedMock implements SourceFactory {}
+
+class _SourceMock implements Source {
+ final Uri uri;
+ final String fullName;
+
+ _SourceMock(String uriStr, this.fullName) : uri = FastUri.parse(uriStr);
+
+ @override
+ Source get librarySource => null;
+
+ @override
+ Source get source => this;
+
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+
+ @override
+ String toString() => '$uri ($fullName)';
+}
+
+class _TestResynthesizerResultProvider extends ResynthesizerResultProvider {
+ final Set<Source> sourcesWithResults = new Set<Source>();
+
+ _TestResynthesizerResultProvider(
+ InternalAnalysisContext context, SummaryDataStore dataStore)
+ : super(context, dataStore);
+
+ @override
+ bool hasResultsForSource(Source source) {
+ return sourcesWithResults.contains(source);
+ }
+}
+
+class _UnlinkedPublicNamespaceMock extends TypedMock
+ implements UnlinkedPublicNamespace {}
+
+class _UnlinkedUnitMock extends TypedMock implements UnlinkedUnit {}
diff --git a/pkg/analyzer/test/src/summary/test_all.dart b/pkg/analyzer/test/src/summary/test_all.dart
index 2f9202b..b3a0467 100644
--- a/pkg/analyzer/test/src/summary/test_all.dart
+++ b/pkg/analyzer/test/src/summary/test_all.dart
@@ -13,6 +13,7 @@
import 'index_unit_test.dart' as index_unit_test;
import 'linker_test.dart' as linker_test;
import 'name_filter_test.dart' as name_filter_test;
+import 'package_bundle_reader_test.dart' as package_bundle_reader_test;
import 'prelinker_test.dart' as prelinker_test;
import 'resynthesize_ast_test.dart' as resynthesize_ast_test;
import 'resynthesize_strong_test.dart' as resynthesize_strong_test;
@@ -32,6 +33,7 @@
index_unit_test.main();
linker_test.main();
name_filter_test.main();
+ package_bundle_reader_test.main();
prelinker_test.main();
resynthesize_ast_test.main();
resynthesize_strong_test.main();
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index 8c081f7..cedcb9b 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -3695,6 +3695,22 @@
expect(info.userToDependsOn['U'], unorderedEquals(['A', 'B']));
}
+ test_class_extendedUsedUnnamedConstructorNames() {
+ ReferencedNames info = _computeReferencedNames('''
+class U1 extends A {
+ U1() : super();
+}
+class U2 extends p.B {
+ U2() : super();
+}
+class U3 extends p.C {
+ U3() : super.named();
+}
+''');
+ expect(
+ info.extendedUsedUnnamedConstructorNames, unorderedEquals(['A', 'B']));
+ }
+
test_class_field() {
ReferencedNames info = _computeReferencedNames('''
class U {
diff --git a/pkg/analyzer/test/src/task/dart_work_manager_test.dart b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
index 31ee542..79f3071 100644
--- a/pkg/analyzer/test/src/task/dart_work_manager_test.dart
+++ b/pkg/analyzer/test/src/task/dart_work_manager_test.dart
@@ -329,6 +329,7 @@
}
void test_getLibrariesContainingPart() {
+ when(context.aboutToComputeResult(anyObject, anyObject)).thenReturn(false);
Source part1 = new TestSource('part1.dart');
Source part2 = new TestSource('part2.dart');
Source part3 = new TestSource('part3.dart');
@@ -346,6 +347,33 @@
expect(manager.getLibrariesContainingPart(part3), isEmpty);
}
+ void test_getLibrariesContainingPart_askResultProvider() {
+ Source part1 = new TestSource('part1.dart');
+ Source part2 = new TestSource('part2.dart');
+ Source part3 = new TestSource('part3.dart');
+ Source library1 = new TestSource('library1.dart');
+ Source library2 = new TestSource('library2.dart');
+ // configure AnalysisContext mock
+ when(context.aboutToComputeResult(anyObject, CONTAINING_LIBRARIES))
+ .thenInvoke((CacheEntry entry, ResultDescriptor result) {
+ if (entry.target == part1) {
+ entry.setValue(result, <Source>[library1, library2], []);
+ return true;
+ }
+ if (entry.target == part2) {
+ entry.setValue(result, <Source>[library2], []);
+ return true;
+ }
+ return false;
+ });
+ // getLibrariesContainingPart
+ expect(manager.getLibrariesContainingPart(part1),
+ unorderedEquals([library1, library2]));
+ expect(
+ manager.getLibrariesContainingPart(part2), unorderedEquals([library2]));
+ expect(manager.getLibrariesContainingPart(part3), isEmpty);
+ }
+
void test_getLibrariesContainingPart_inSDK() {
Source part = new _SourceMock('part.dart');
when(part.isInSystemLibrary).thenReturn(true);
@@ -764,6 +792,11 @@
expect(manager.libraryPartsMap, isEmpty);
}
+ void test_unitIncrementallyResolved() {
+ manager.unitIncrementallyResolved(source1, source2);
+ expect_librarySourceQueue([source1]);
+ }
+
CacheEntry _getOrCreateEntry(Source source, [bool explicit = true]) {
CacheEntry entry = cache.get(source);
if (entry == null) {
diff --git a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
index ecd98cb..cdca3b4 100644
--- a/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
+++ b/pkg/analyzer/test/src/task/incremental_element_builder_test.dart
@@ -1065,6 +1065,27 @@
}
}
+ test_directives_library_updateOffset() {
+ _buildOldUnit(r'''
+#!/bin/sh
+library my_lib;
+class A {}
+''');
+ LibraryDirective libraryDirective = oldUnit.directives.single;
+ // Set the LibraryElement and check that its nameOffset is correct.
+ libraryDirective.element =
+ new LibraryElementImpl.forNode(context, libraryDirective.name);
+ expect(libraryDirective.element.nameOffset, libraryDirective.name.offset);
+ // Update and check again that the nameOffset is correct.
+ _buildNewUnit(r'''
+#!/bin/sh
+
+library my_lib;
+class A {}
+''');
+ expect(libraryDirective.element.nameOffset, libraryDirective.name.offset);
+ }
+
test_directives_remove() {
_buildOldUnit(r'''
library test;
diff --git a/pkg/analyzer_cli/pubspec.yaml b/pkg/analyzer_cli/pubspec.yaml
index 4e45320..a19fecb 100644
--- a/pkg/analyzer_cli/pubspec.yaml
+++ b/pkg/analyzer_cli/pubspec.yaml
@@ -11,7 +11,7 @@
bazel_worker: ^0.1.0
cli_util: ^0.0.1
linter: ^0.1.16
- package_config: ^0.1.5
+ package_config: '>=0.1.5 <2.0.0'
plugin: '>=0.1.0 <0.3.0'
protobuf: ^0.5.0
yaml: ^2.1.2
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
index 65e7439..8286b33 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
@@ -314,10 +314,6 @@
bool hasNoArguments() => positional.isEmpty && named.isEmpty;
- bool hasOnePositionalArgumentThatMatches(bool f(T type)) {
- return named.isEmpty && positional.length == 1 && f(positional[0]);
- }
-
void forEach(void f(T type)) {
positional.forEach(f);
named.values.forEach(f);
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index d5492f1..dedb4e2 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -856,10 +856,13 @@
}
/**
- * We optimize certain operations on the [int] class because we know
- * more about their return type than the actual Dart code. For
- * example, we know int + int returns an int. The Dart code for
- * [int.operator+] only says it returns a [num].
+ * We optimize certain operations on the [int] class because we know more
+ * about their return type than the actual Dart code. For example, we know int
+ * + int returns an int. The Dart library code for [int.operator+] only says
+ * it returns a [num].
+ *
+ * Returns the more precise TypeInformation, or `null` to defer to the library
+ * code.
*/
TypeInformation handleIntrisifiedSelector(
Selector selector, TypeMask mask, TypeGraphInferrerEngine inferrer) {
@@ -883,63 +886,78 @@
return info.type
.satisfies(classWorld.backend.positiveIntImplementation, classWorld);
}
+ TypeInformation tryLater() => inferrer.types.nonNullEmptyType;
+
+ TypeInformation argument =
+ arguments.isEmpty ? null : arguments.positional.first;
String name = selector.name;
- // We are optimizing for the cases that are not expressed in the
- // Dart code, for example:
- // int + int -> int
- // uint31 | uint31 -> uint31
- if (name == '*' ||
- name == '+' ||
- name == '%' ||
- name == 'remainder' ||
- name == '~/') {
- if (isPositiveInt(receiver) &&
- arguments.hasOnePositionalArgumentThatMatches(isPositiveInt)) {
- // uint31 + uint31 -> uint32
- if (name == '+' &&
- isUInt31(receiver) &&
- arguments.hasOnePositionalArgumentThatMatches(isUInt31)) {
- return inferrer.types.uint32Type;
- } else {
+ // These are type inference rules only for useful cases that are not
+ // expressed in the library code, for example:
+ //
+ // int + int -> int
+ // uint31 | uint31 -> uint31
+ //
+ switch (name) {
+ case '*':
+ case '+':
+ case '%':
+ case 'remainder':
+ case '~/':
+ if (isEmpty(argument)) return tryLater();
+ if (isPositiveInt(receiver) && isPositiveInt(argument)) {
+ // uint31 + uint31 -> uint32
+ if (name == '+' && isUInt31(receiver) && isUInt31(argument)) {
+ return inferrer.types.uint32Type;
+ }
return inferrer.types.positiveIntType;
}
- } else if (arguments.hasOnePositionalArgumentThatMatches(isInt)) {
- return inferrer.types.intType;
- } else if (arguments.hasOnePositionalArgumentThatMatches(isEmpty)) {
- return inferrer.types.nonNullEmptyType;
- } else {
+ if (isInt(argument)) {
+ return inferrer.types.intType;
+ }
return null;
- }
- } else if (name == '|' || name == '^') {
- if (isUInt31(receiver) &&
- arguments.hasOnePositionalArgumentThatMatches(isUInt31)) {
- return inferrer.types.uint31Type;
- }
- } else if (name == '>>') {
- if (isUInt31(receiver)) {
- return inferrer.types.uint31Type;
- }
- } else if (name == '&') {
- if (isUInt31(receiver) ||
- arguments.hasOnePositionalArgumentThatMatches(isUInt31)) {
- return inferrer.types.uint31Type;
- }
- } else if (name == 'unary-') {
- // The receiver being an int, the return value will also be an
- // int.
- return inferrer.types.intType;
- } else if (name == '-') {
- if (arguments.hasOnePositionalArgumentThatMatches(isInt)) {
+
+ case '|':
+ case '^':
+ if (isEmpty(argument)) return tryLater();
+ if (isUInt31(receiver) && isUInt31(argument)) {
+ return inferrer.types.uint31Type;
+ }
+ return null;
+
+ case '>>':
+ if (isEmpty(argument)) return tryLater();
+ if (isUInt31(receiver)) {
+ return inferrer.types.uint31Type;
+ }
+ return null;
+
+ case '&':
+ if (isEmpty(argument)) return tryLater();
+ if (isUInt31(receiver) || isUInt31(argument)) {
+ return inferrer.types.uint31Type;
+ }
+ return null;
+
+ case '-':
+ if (isEmpty(argument)) return tryLater();
+ if (isInt(argument)) {
+ return inferrer.types.intType;
+ }
+ return null;
+
+ case 'unary-':
+ // The receiver being an int, the return value will also be an int.
return inferrer.types.intType;
- } else if (arguments.hasOnePositionalArgumentThatMatches(isEmpty)) {
- return inferrer.types.nonNullEmptyType;
- }
- return null;
- } else if (name == 'abs') {
- return arguments.hasNoArguments() ? inferrer.types.positiveIntType : null;
+
+ case 'abs':
+ return arguments.hasNoArguments()
+ ? inferrer.types.positiveIntType
+ : null;
+
+ default:
+ return null;
}
- return null;
}
TypeMask computeType(TypeGraphInferrerEngine inferrer) {
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index c4a86ef..aeea76e 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -644,7 +644,9 @@
String _jsNameHelper(Element e) {
String jsInteropName = backend.nativeData.getJsInteropName(e);
if (jsInteropName != null && jsInteropName.isNotEmpty) return jsInteropName;
- return e.isLibrary ? 'self' : e.name;
+ return e.isLibrary
+ ? 'self'
+ : backend.nativeData.getUnescapedJSInteropName(e.name);
}
/// Returns a JavaScript path specifying the context in which
diff --git a/pkg/compiler/pubspec.yaml b/pkg/compiler/pubspec.yaml
index 922f69a..d8998ef 100644
--- a/pkg/compiler/pubspec.yaml
+++ b/pkg/compiler/pubspec.yaml
@@ -3,7 +3,7 @@
name: compiler
#version: do-not-upload
dependencies:
- package_config: ^0.1.1
+ package_config: '>=0.1.1 <2.0.0'
pub_semver: ^1.2.1
js:
path: ../js
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 610115a..fb91ab7 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -504,4 +504,88 @@
"//third_party",
]
}
+
+ action("generate_snapshot_test_dat_file") {
+ snapshot_test_dat_file = "$root_gen_dir/snapshot_test.dat"
+ snapshot_test_in_dat_file = "../vm/snapshot_test_in.dat"
+ snapshot_test_dart_file = "../vm/snapshot_test.dart"
+ inputs = [
+ "../tools/create_string_literal.py",
+ snapshot_test_in_dat_file,
+ snapshot_test_dart_file,
+ ]
+
+ outputs = [
+ snapshot_test_dat_file,
+ ]
+
+ script = "../tools/create_string_literal.py"
+ args = [
+ "--output",
+ rebase_path(snapshot_test_dat_file),
+ "--input_cc",
+ rebase_path(snapshot_test_in_dat_file),
+ "--include",
+ "INTENTIONALLY_LEFT_BLANK",
+ "--var_name",
+ "INTENTIONALLY_LEFT_BLANK_TOO",
+ rebase_path(snapshot_test_dart_file),
+ ]
+ }
+
+ executable("run_vm_tests") {
+ testonly = true
+ configs += ["..:dart_config",
+ "..:dart_product_config",
+ "..:dart_precompiled_runtime_config",]
+ deps = [
+ "..:libdart",
+ ":libdart_builtin",
+ ":embedded_dart_io",
+ ":dart_snapshot_cc",
+ ":generate_snapshot_test_dat_file",
+ "../vm:libdart_platform",
+ "//third_party/zlib",
+ ]
+ include_dirs = [
+ "..",
+ "$target_gen_dir",
+ ]
+ defines = [
+ "TESTING",
+ ]
+
+ vm_tests_list = exec_script("../../tools/gypi_to_gn.py",
+ [rebase_path("../vm/vm_sources.gypi"),
+ "--keep_only=_test.cc",
+ "--keep_only=_test.h",],
+ "scope",
+ ["../vm/vm_sources.gypi"])
+ vm_tests = rebase_path(vm_tests_list.sources, ".", "../vm")
+
+ builtin_impl_tests_list =
+ exec_script("../../tools/gypi_to_gn.py",
+ [rebase_path("builtin_impl_sources.gypi"),
+ "--keep_only=_test.cc",
+ "--keep_only=_test.h",],
+ "scope",
+ ["builtin_impl_sources.gypi"])
+
+ sources = [
+ "run_vm_tests.cc",
+ ] + builtin_impl_tests_list.sources + vm_tests
+ }
+
+ copy("fuchsia_vm_tests") {
+ sources = [ "fuchsia_vm_tests.txt" ]
+ outputs = [ "$root_out_dir/fuchsia_vm_tests.txt" ]
+ }
+
+ executable("run_vm_tests_fuchsia") {
+ testonly = true
+ configs += ["..:dart_config"]
+ sources = [
+ "run_vm_tests_fuchsia.cc"
+ ]
+ }
} # defined(is_fuchsia) && is_fuchsia
diff --git a/runtime/bin/fuchsia_vm_tests.txt b/runtime/bin/fuchsia_vm_tests.txt
new file mode 100644
index 0000000..665cf38
--- /dev/null
+++ b/runtime/bin/fuchsia_vm_tests.txt
@@ -0,0 +1,915 @@
+CircularLinkedList
+Read
+FileLength
+FilePosition
+Set
+StackAllocatedDestruction
+StackAllocatedLongJump
+StackResourceDestruction
+StackResourceLongJump
+StoreIntoObject
+ReadArgument
+AddressingModes
+JumpAroundCrash
+SimpleLoop
+Cmpb
+Testb
+Increment
+IncrementLong
+Decrement
+DecrementLong
+SignedMultiply
+UnsignedMultiply
+SignedMultiply64
+SignedMultiplyLong
+OverflowSignedMultiply
+SignedMultiply1
+SignedMultiply2
+UnsignedMultiplyLong
+SignedDivide
+UnsignedDivide
+SignedDivideLong
+UnsignedDivideLong
+Negate
+BitScanReverse
+MoveExtend
+MoveExtend32
+MoveExtendMemory
+MoveExtend32Memory
+MoveWord
+MoveWordRex
+LongAddReg
+LongAddImmediate
+LongAddAddress
+LongSubReg
+LongSubImmediate
+LongSubAddress
+AddReg
+AddImmediate
+AddAddress
+SubReg
+SubImmediate
+SubAddress
+Bitwise
+Bitwise64
+LogicalOps
+LogicalOps64
+LogicalTestL
+LogicalTestQ
+CompareSwapEQ
+CompareSwapNEQ
+Exchange
+LargeConstant
+CallSimpleLeaf
+JumpSimpleLeaf
+JumpIndirect
+SingleFPMoves
+SingleFPMoves2
+PackedDoubleAdd
+PackedDoubleSub
+PackedDoubleNegate
+PackedDoubleAbsolute
+PackedDoubleMul
+PackedDoubleDiv
+PackedDoubleSqrt
+PackedDoubleMin
+PackedDoubleMax
+PackedDoubleShuffle
+PackedDoubleToSingle
+PackedSingleToDouble
+SingleFPOperations
+PackedFPOperations
+PackedIntOperations
+PackedIntOperations2
+PackedFPOperations2
+PackedCompareEQ
+PackedCompareNEQ
+PackedCompareLT
+PackedCompareLE
+PackedCompareNLT
+PackedCompareNLE
+PackedNegate
+PackedAbsolute
+PackedSetWZero
+PackedMin
+PackedMax
+PackedLogicalOr
+PackedLogicalAnd
+PackedLogicalNot
+PackedMoveHighLow
+PackedMoveLowHigh
+PackedUnpackLow
+PackedUnpackHigh
+PackedUnpackLowPair
+PackedUnpackHighPair
+DoubleFPMoves
+DoubleFPOperations
+Int32ToDoubleConversion
+Int64ToDoubleConversion
+DoubleToInt64Conversion
+TestObjectCompare
+TestNop
+TestAlign0
+TestAlign1
+TestAlign1Offset1
+TestAlignLarge
+TestAdds
+TestNot
+TestNotInt32
+XorpdZeroing
+XorpdZeroing2
+Pxor
+SquareRootDouble
+DoubleFPUStackMoves
+Sine
+Cosine
+IntToDoubleConversion
+DoubleToDoubleTrunc
+DoubleAbs
+ExtractSignBits
+TestSetCC
+TestRepMovsBytes
+ConditionalMovesCompare
+BitTest
+ConditionalMovesEqual
+ConditionalMovesNoOverflow
+Assert
+Expect
+Fail0
+Fail1
+Fail2
+AstPrinter
+Ast
+FetchAndIncrement
+FetchAndDecrement
+IncrementBy
+DecrementBy
+LoadRelaxed
+CompareAndSwapWord
+CompareAndSwapUint32
+BigintSmi
+BigintInt64
+BigintUint64
+BigintDouble
+BigintHexStrings
+BigintDecStrings
+BigintCompare
+BigintDecimalStrings
+BitSetBasic
+BitVector
+BitFields
+BitmapBuilder
+BoolField
+ClassHierarchyAnalysis
+ClassFinalizer
+ClassFinalize_Cycles
+ClassFinalize_Resolve
+StackmapCodegen
+StackmapGC
+DescriptorList_TokenPositions
+CodeSourceMap_TokenPositions
+SimpleReturnCodegen
+SmiReturnCodegen
+SimpleStaticCallCodegen
+StaticCallReturnParameterCodegen
+StaticCallSmiParamSumCodegen
+SmiAddCodegen
+GenericAddCodegen
+SmiBinaryOpCodegen
+BoolNotCodegen
+BoolAndCodegen
+BinaryOpCodegen
+SmiUnaryOpCodegen
+DoubleUnaryOpCodegen
+StaticCallCodegen
+InstanceCallCodegen
+AllocateNewObjectCodegen
+IcDataAccess
+CompileScript
+CompileFunction
+CompileFunctionOnHelperThread
+RegenerateAllocStubs
+EvalExpression
+EvalExpressionWithLazyCompile
+EvalExpressionExhaustCIDs
+Id
+GetCpuModelTest
+CustomIsolates
+ErrorHandleBasics
+StacktraceInfo
+DeepStacktraceInfo
+StackOverflowStacktraceInfo
+OutOfMemoryStacktraceInfo
+CurrentStacktraceInfo
+ErrorHandleTypes
+UnhandleExceptionError
+Dart_PropagateError
+Dart_Error
+Null
+EmptyString
+IdentityEquals
+IdentityHash
+ObjectEquals
+InstanceValues
+InstanceGetType
+BooleanValues
+BooleanConstants
+DoubleValues
+NumberValues
+IntegerValues
+IntegerFitsIntoInt64
+IntegerFitsIntoUint64
+ArrayValues
+IsString
+NewString
+MalformedStringToUTF8
+ExternalStringCallback
+ExternalStringPretenure
+ExternalTypedDataPretenure
+ListAccess
+MapAccess
+IsFuture
+TypedDataViewListGetAsBytes
+TypedDataViewListIsTypedData
+TypedDataAccess
+ByteBufferAccess
+ByteDataAccess
+ExternalByteDataAccess
+OptimizedExternalByteDataAccess
+TypedDataDirectAccessUnverified
+TypedDataDirectAccessVerified
+TypedDataDirectAccess1Unverified
+TypedDataDirectAccess1Verified
+TypedDataViewDirectAccessUnverified
+TypedDataViewDirectAccessVerified
+ByteDataDirectAccessUnverified
+ByteDataDirectAccessVerified
+ExternalTypedDataAccess
+ExternalClampedTypedDataAccess
+ExternalUint8ClampedArrayAccess
+ExternalTypedDataCallback
+SlowFinalizer
+Float32x4List
+EnterExitScope
+PersistentHandles
+NewPersistentHandle_FromPersistentHandle
+AssignToPersistentHandle
+WeakPersistentHandle
+WeakPersistentHandleCallback
+WeakPersistentHandleNoCallback
+WeakPersistentHandlesCallbackShutdown
+WeakPersistentHandleExternalAllocationSize
+WeakPersistentHandleExternalAllocationSizeNewspaceGC
+WeakPersistentHandleExternalAllocationSizeOldspaceGC
+WeakPersistentHandleExternalAllocationSizeOddReferents
+ImplicitReferencesOldSpace
+ImplicitReferencesNewSpace
+SetGarbageCollectionCallbacks
+SingleGarbageCollectionCallback
+LocalHandles
+LocalZoneMemory
+Isolates
+CurrentIsolateData
+IsolateSetCheckedMode
+DebugName
+SetMessageCallbacks
+TypeGetNonParamtericTypes
+TypeGetParameterizedTypes
+FieldAccess
+SetField_FunnyValue
+InjectNativeFields1
+InjectNativeFields2
+InjectNativeFields3
+InjectNativeFields4
+TestNativeFieldsAccess
+InjectNativeFieldsSuperClass
+NativeFieldAccess
+ImplicitNativeFieldAccess
+NegativeNativeFieldAccess
+NegativeNativeFieldInIsolateMessage
+GetStaticField_RunsInitializer
+GetField_CheckIsolate
+SetField_CheckIsolate
+New
+New_Issue2971
+Invoke
+Invoke_PrivateStatic
+Invoke_FunnyArgs
+Invoke_Null
+InvokeNoSuchMethod
+Invoke_CrossLibrary
+InvokeClosure
+ThrowException
+GetNativeArguments
+GetNativeArgumentCount
+GetType
+InstanceOf
+LoadScript
+RootLibrary
+LoadScript_CompileError
+LookupLibrary
+LibraryName
+LibraryId
+LibraryUrl
+LibraryGetClassNames
+GetFunctionNames
+LibraryImportLibrary
+ImportLibraryWithPrefix
+LoadLibrary
+LoadLibrary_CompileError
+LoadSource
+LoadSource_LateLoad
+LoadPatch
+LoadPatchSignatureMismatch
+ParsePatchLibrary
+SetNativeResolver
+ImportLibrary2
+ImportLibrary3
+ImportLibrary4
+ImportLibrary5
+IllegalNewSendPort
+IllegalPost
+NewNativePort
+NativePortPostInteger
+NativePortReceiveNull
+NativePortReceiveInteger
+RunLoop_Success
+RunLoop_Exception
+IsolateShutdown
+IsolateShutdownRunDartCode
+NativeFunctionClosure
+NativeStaticFunctionClosure
+RangeLimits
+NewString_Null
+InvalidGetSetPeer
+OneNewSpacePeer
+CollectOneNewSpacePeer
+TwoNewSpacePeers
+CollectTwoNewSpacePeers
+CopyNewSpacePeers
+OnePromotedPeer
+OneOldSpacePeer
+CollectOneOldSpacePeer
+TwoOldSpacePeers
+CollectTwoOldSpacePeers
+MakeExternalString
+ExternalizeConstantStrings
+LazyLoadDeoptimizes
+GuardExternalizedString
+ExternalStringDeoptimize
+ExternalStringPolymorphicDeoptimize
+ExternalStringLoadElimination
+ExternalStringGuardFieldDeoptimize
+ExternalStringStaticFieldDeoptimize
+ExternalStringTrimDoubleParse
+ExternalStringDoubleParse
+ExternalStringIndexOf
+StringFromExternalTypedData
+Timeline_Dart_TimelineDuration
+Timeline_Dart_TimelineInstant
+Timeline_Dart_TimelineAsyncDisabled
+Timeline_Dart_TimelineAsync
+Timeline_Dart_TimelineGetTrace
+Timeline_Dart_TimelineGetTraceOnlyDartEvents
+Timeline_Dart_TimelineGetTraceWithDartEvents
+Timeline_Dart_TimelineGetTraceGlobalOverride
+Timeline_Dart_GlobalTimelineGetTrace
+Timeline_Dart_GlobalTimelineGetTrace_Threaded
+Timeline_Dart_EmbedderTimelineStartStopRecording
+Dart_LoadLibraryPatch_1
+Dart_LoadLibraryPatch_Error1
+Dart_LoadLibraryPatch_Error2
+Dart_LoadLibraryPatch_Error3
+DartEntry
+InvokeStatic_CompileError
+InvokeDynamic_CompileError
+Debugger_PrintBreakpointsToJSONArray
+Debugger_PauseEvent
+Debug_Breakpoint
+Debug_InspectStack_NotOptimized
+Debug_InspectStack_Optimized
+Debug_InspectStackWithClosure_NotOptimized
+Debug_InspectStackWithClosure_Optimized
+Debug_StepOut
+Debug_StepInto
+Debug_IgnoreBP
+Debug_DeoptimizeFunction
+Debug_SingleStep
+Debug_ClosureBreakpoint
+Debug_ExprClosureBreakpoint
+Debug_BreakpointStubPatching
+Debug_DeleteBreakpoint
+Debug_InspectStaticField
+Debug_InspectObject
+Debug_IsolateID
+Debug_InterruptIsolate
+Debug_StackTraceDump1
+Debug_StackTraceDump2
+Debug_EvaluateExpr
+Debug_EvaluateInActivationOfEvaluate
+Debug_BreakOnUnhandledException
+Debug_GetClosureInfo
+Debug_GetSupertype
+Debug_ListSuperType
+Debug_ScriptGetTokenInfo_Basic
+Debug_ScriptGetTokenInfo_MultiLineInterpolation
+Disassembler
+UnhandledExceptions
+FindCodeObject
+BasicFlags
+ParseFlags
+SourcePosition_InstanceCalls
+SourcePosition_If
+SourcePosition_ForLoop
+SourcePosition_While
+SourcePosition_WhileContinueBreak
+SourcePosition_LoadIndexed
+SourcePosition_StoreIndexed
+SourcePosition_BitwiseOperations
+SourcePosition_IfElse
+SourcePosition_Switch
+SourcePosition_TryCatchFinally
+SourcePosition_InstanceFields
+SourcePosition_Async
+SourcePosition_SyntheticTokens
+RangeTests
+RangeTestsInfinity
+RangeUtils
+RangeBinaryOp
+RangeAdd
+RangeSub
+RangeAnd
+RangeIntersectionMinMax
+RangeJoinMinMax
+FreeList
+FreeListProtected
+FreeListProtectedTinyObjects
+FreeListProtectedVariableSizeObjects
+GrowableArray
+MallocGrowableArray
+GrowableArraySort
+GrowableHandlePtr
+GuardFieldSimpleTest
+GuardFieldFinalListTest
+GuardFieldFinalVariableLengthListTest
+GuardFieldConstructorTest
+GuardFieldConstructor2Test
+AllocateZoneHandle
+AllocateScopeHandle
+DirectChainedHashMap
+MallocDirectChainedHashMap
+DirectChainedHashMapIterator
+HashTable
+Sets
+Maps
+OldGC
+OldGC_Unsync
+LargeSweep
+ClassHeapStats
+ArrayHeapStats
+FindObject
+IterateReadOnly
+BecomeFowardOldToOld
+BecomeFowardNewToNew
+BecomeFowardOldToNew
+BecomeFowardNewToOld
+BecomeForwardRememberedObject
+InstructionTests
+OptimizationTests
+IsolateReload_FunctionReplacement
+IsolateReload_BadClass
+IsolateReload_StaticValuePreserved
+IsolateReload_SavedClosure
+IsolateReload_TopLevelFieldAdded
+IsolateReload_ClassFieldAdded
+IsolateReload_ClassFieldAdded2
+IsolateReload_ClassFieldRemoved
+IsolateReload_ClassAdded
+IsolateReload_LibraryImportAdded
+IsolateReload_LibraryImportRemoved
+IsolateReload_LibraryDebuggable
+IsolateReload_ImplicitConstructorChanged
+IsolateReload_ConstructorChanged
+IsolateReload_SuperClassChanged
+IsolateReload_Generics
+IsolateReload_TypeIdentity
+IsolateReload_TypeIdentityGeneric
+IsolateReload_TypeIdentityParameter
+IsolateReload_MixinChanged
+IsolateReload_ComplexInheritanceChange
+IsolateReload_LiveStack
+IsolateReload_LibraryLookup
+IsolateReload_LibraryHide
+IsolateReload_LibraryShow
+IsolateReload_SmiFastPathStubs
+IsolateReload_ImportedMixinFunction
+IsolateReload_TopLevelParseError
+IsolateReload_PendingUnqualifiedCall_StaticToInstance
+IsolateReload_PendingUnqualifiedCall_InstanceToStatic
+IsolateReload_PendingConstructorCall_AbstractToConcrete
+IsolateReload_PendingConstructorCall_ConcreteToAbstract
+IsolateReload_PendingStaticCall_DefinedToNSM
+IsolateReload_PendingStaticCall_NSMToDefined
+IsolateReload_PendingSuperCall
+IsolateReload_EnumEquality
+IsolateReload_EnumIdentical
+IsolateReload_EnumReorderIdentical
+IsolateReload_EnumAddition
+IsolateReload_EnumToNotEnum
+IsolateReload_NotEnumToEnum
+IsolateReload_EnumDelete
+IsolateReload_EnumIdentityReload
+IsolateReload_ConstantIdentical
+IsolateReload_EnumValuesToString
+IsolateReload_DirectSubclasses_Success
+IsolateReload_DirectSubclasses_GhostSubclass
+IsolateReload_DirectSubclasses_Failure
+IsolateCurrent
+IsolateSpawn
+StackLimitInterrupts
+NoOOBMessageScope
+JSON_TextBuffer
+JSON_JSONStream_Primitives
+JSON_JSONStream_Array
+JSON_JSONStream_Object
+JSON_JSONStream_NestedObject
+JSON_JSONStream_ObjectArray
+JSON_JSONStream_ArrayArray
+JSON_JSONStream_Printf
+JSON_JSONStream_ObjectPrintf
+JSON_JSONStream_DartObject
+JSON_JSONStream_EscapedString
+JSON_JSONStream_DartString
+JSON_JSONStream_Params
+JSON_JSONStream_AppendJSONStreamConsumer
+Log_Macro
+Log_Basic
+Log_Block
+LongJump
+NullRegion
+NewRegion
+Subregion
+ExtendedRegion
+MessageHandler_PostMessage
+MessageHandler_HasOOBMessages
+MessageHandler_ClosePort
+MessageHandler_CloseAllPorts
+MessageHandler_HandleNextMessage
+MessageHandler_HandleNextMessage_ProcessOOBAfterError
+MessageHandler_HandleNextMessage_Shutdown
+MessageHandler_HandleOOBMessages
+MessageHandler_Run
+MessageQueue_BasicOperations
+MessageQueue_Clear
+Metric_Simple
+Metric_OnDemand
+ObjectGraph
+ObjectIdRingSerialWrapTest
+ObjectIdRingScavengeMoveTest
+ObjectIdRingOldGCTest
+ObjectIdRingExpiredEntryTest
+Class
+TypeArguments
+TokenStream
+GenerateExactSource
+Class_ComputeEndTokenPos
+InstanceClass
+Smi
+StringCompareTo
+StringEncodeIRI
+StringDecodeIRI
+StringDecodeIRIInvalid
+StringIRITwoByte
+Mint
+Double
+Bigint
+Integer
+String
+StringFormat
+StringConcat
+StringHashConcat
+StringSubStringDifferentWidth
+StringFromUtf8Literal
+StringEqualsUtf8
+StringEqualsUTF32
+ExternalOneByteString
+EscapeSpecialCharactersOneByteString
+EscapeSpecialCharactersExternalOneByteString
+EscapeSpecialCharactersTwoByteString
+EscapeSpecialCharactersExternalTwoByteString
+ExternalTwoByteString
+Symbol
+SymbolUnicode
+Bool
+Array
+ArrayLengthNegativeOne
+ArrayLengthSmiMin
+ArrayLengthOneTooMany
+ArrayLengthMaxElements
+Int8ListLengthNegativeOne
+Int8ListLengthSmiMin
+Int8ListLengthOneTooMany
+Int8ListLengthMaxElements
+StringCodePointIterator
+StringCodePointIteratorRange
+GrowableObjectArray
+InternalTypedData
+ExternalTypedData
+Script
+EmbeddedScript
+Context
+ContextScope
+Closure
+ObjectPrinting
+CheckedHandle
+Code
+CodeImmutability
+EmbedStringInCode
+EmbedSmiInCode
+EmbedSmiIn64BitCode
+ExceptionHandlers
+PcDescriptors
+PcDescriptorsLargeDeltas
+ClassDictionaryIterator
+ICData
+SubtypeTestCache
+FieldTests
+EqualsIgnoringPrivate
+ArrayNew_Overflow_Crash
+StackTraceFormat
+WeakProperty_PreserveCrossGen
+WeakProperty_PreserveRecurse
+WeakProperty_PreserveOne_NewSpace
+WeakProperty_PreserveTwo_NewSpace
+WeakProperty_PreserveTwoShared_NewSpace
+WeakProperty_PreserveOne_OldSpace
+WeakProperty_PreserveTwo_OldSpace
+WeakProperty_PreserveTwoShared_OldSpace
+WeakProperty_ClearOne_NewSpace
+WeakProperty_ClearTwoShared_NewSpace
+WeakProperty_ClearOne_OldSpace
+WeakProperty_ClearTwoShared_OldSpace
+MirrorReference
+FindClosureIndex
+FindInvocationDispatcherFunctionIndex
+Metadata
+FunctionSourceFingerprint
+FunctionWithBreakpointNotInlined
+SpecialClassesHaveEmptyArrays
+PrintJSON
+PrintJSONPrimitives
+InstanceEquality
+HashCode
+LinkedHashMap
+LinkedHashMap_iteration
+Symbols_FromConcatAll
+String_ScrubName
+Sleep
+SNPrint
+SNPrint_BadArgs
+OsFuncs
+OSAlignedAllocate
+Pages
+ParseClassDefinition
+Parser_TopLevel
+Parser_AllocateVariables_CapturedVar
+Parser_AllocateVariables_NestedCapturedVar
+Parser_AllocateVariables_TwoChains
+Parser_AllocateVariables_Issue7681
+Parser_AllocateVariables_CaptureLoopVar
+Parser_AllocateVariables_MiddleChain
+PortMap_CreateAndCloseOnePort
+PortMap_CreateAndCloseTwoPorts
+PortMap_ClosePorts
+PortMap_CreateManyPorts
+PortMap_SetPortState
+PortMap_PostMessage
+PortMap_PostIntegerMessage
+PortMap_PostNullMessage
+PortMap_PostMessageClosedPort
+Profiler_SampleBufferWrapTest
+Profiler_SampleBufferIterateTest
+Profiler_AllocationSampleTest
+Profiler_TrivialRecordAllocation
+Profiler_ToggleRecordAllocation
+Profiler_CodeTicks
+Profiler_FunctionTicks
+Profiler_IntrinsicAllocation
+Profiler_ArrayAllocation
+Profiler_ContextAllocation
+Profiler_ClosureAllocation
+Profiler_TypedArrayAllocation
+Profiler_StringAllocation
+Profiler_StringInterpolation
+Profiler_FunctionInline
+Profiler_InliningIntervalBoundry
+Profiler_ChainedSamples
+Profiler_BasicSourcePosition
+Profiler_BasicSourcePositionOptimized
+Profiler_SourcePosition
+Profiler_SourcePositionOptimized
+Profiler_BinaryOperatorSourcePosition
+Profiler_BinaryOperatorSourcePositionOptimized
+Profiler_GetSourceReport
+RegExp_OneByteString
+RegExp_TwoByteString
+RegExp_ExternalOneByteString
+RegExp_ExternalTwoByteString
+DartStaticResolve
+DartDynamicResolve
+RingBuffer
+Scanner_Test
+ZeroSizeScavenger
+LocalScope
+Service_IdZones
+Service_Code
+Service_TokenStream
+Service_PcDescriptors
+Service_LocalVarDescriptors
+Service_PersistentHandles
+Service_Address
+Service_EmbedderRootHandler
+Service_EmbedderIsolateHandler
+Service_Profile
+SerializeNull
+SerializeSmi1
+SerializeSmi2
+SerializeMints
+SerializeDouble
+SerializeTrue
+SerializeFalse
+SerializeCapability
+SerializeBigint
+SerializeBigint2
+SerializeSingletons
+SerializeString
+SerializeArray
+FailSerializeLargeArray
+FailSerializeLargeNestedArray
+FailSerializeLargeTypedDataInt8
+FailSerializeLargeTypedDataUint8
+FailSerializeLargeExternalTypedData
+SerializeEmptyArray
+SerializeByteArray
+SerializeTypedArray
+SerializeExternalTypedArray
+SerializeEmptyByteArray
+SerializeScript
+CanonicalizationInScriptSnapshots
+GenerateSource
+FullSnapshot
+FullSnapshot1
+ScriptSnapshot
+ScriptSnapshot1
+ScriptSnapshot2
+IntArrayMessage
+DartGeneratedMessages
+DartGeneratedListMessages
+DartGeneratedArrayLiteralMessages
+DartGeneratedListMessagesWithBackref
+DartGeneratedArrayLiteralMessagesWithBackref
+DartGeneratedListMessagesWithTypedData
+PostCObject
+OmittedObjectEncodingLength
+SourceReport_Coverage_NoCalls
+SourceReport_Coverage_SimpleCall
+SourceReport_Coverage_ForceCompile
+SourceReport_Coverage_UnusedClass_NoForceCompile
+SourceReport_Coverage_UnusedClass_ForceCompile
+SourceReport_Coverage_UnusedClass_ForceCompileError
+SourceReport_Coverage_NestedFunctions
+SourceReport_Coverage_RestrictedRange
+SourceReport_Coverage_AllFunctions
+SourceReport_Coverage_AllFunctions_ForceCompile
+SourceReport_CallSites_SimpleCall
+SourceReport_CallSites_PolymorphicCall
+SourceReport_MultipleReports
+SourceReport_PossibleBreakpoints_Simple
+EmptyStackFrameIteration
+EmptyDartStackFrameIteration
+ValidateStackFrameIteration
+ValidateNoSuchMethodStackFrameIteration
+CallRuntimeStubCode
+CallLeafRuntimeStubCode
+ThreadBarrier
+ThreadPool_Create
+ThreadPool_RunOne
+ThreadPool_RunMany
+ThreadPool_WorkerShutdown
+ThreadPool_WorkerTimeout
+ThreadPool_RecursiveSpawn
+Mutex
+Monitor
+ManyTasksWithZones
+ThreadRegistry
+SafepointTestDart
+SafepointTestVM
+RecursiveSafepointTest1
+ThreadIterator_Count
+ThreadIterator_FindSelf
+ThreadIterator_AddFindRemove
+SafepointTestVM2
+RecursiveSafepointTest2
+HelperAllocAndGC
+TimelineEventIsValid
+TimelineEventDuration
+TimelineEventDurationPrintJSON
+TimelineEventArguments
+TimelineEventArgumentsPrintJSON
+TimelineEventBufferPrintJSON
+TimelineEventCallbackRecorderBasic
+TimelineAnalysis_ThreadBlockCount
+TimelineRingRecorderJSONOrder
+TimelinePauses_Basic
+TimelinePauses_BeginEnd
+Utf8Decode
+ParseUri_WithScheme_NoQueryNoUser
+ParseUri_WithScheme_WithQuery
+ParseUri_WithScheme_WithFragment
+ParseUri_WithScheme_WithQueryWithFragment
+ParseUri_WithScheme_WithUser
+ParseUri_WithScheme_ShortPath
+ParseUri_WithScheme_EmptyPath
+ParseUri_WithScheme_Rootless1
+ParseUri_WithScheme_Rootless2
+ParseUri_NoScheme_AbsPath_WithAuthority
+ParseUri_NoScheme_AbsPath_NoAuthority
+ParseUri_NoScheme_AbsPath_StrayColon
+ParseUri_NoScheme_Rootless1
+ParseUri_NoScheme_Rootless2
+ParseUri_NoScheme_Empty
+ParseUri_NoScheme_QueryOnly
+ParseUri_NoScheme_FragmentOnly
+ParseUri_LowerCaseScheme
+ParseUri_NormalizeEscapes_PathQueryFragment
+ParseUri_NormalizeEscapes_UppercaseEscapesPreferred
+ParseUri_NormalizeEscapes_Authority
+ParseUri_NormalizeEscapes_UppercaseEscapeInHost
+ParseUri_BrokenEscapeSequence
+ResolveUri_WithScheme_NoAuthorityNoQuery
+ResolveUri_WithScheme_WithAuthorityWithQuery
+ResolveUri_NoScheme_WithAuthority
+ResolveUri_NoSchemeNoAuthority_AbsolutePath
+ResolveUri_NoSchemeNoAuthority_RelativePath
+ResolveUri_NoSchemeNoAuthority_RelativePathEmptyBasePath
+ResolveUri_NoSchemeNoAuthority_RelativePathWeirdBasePath
+ResolveUri_NoSchemeNoAuthority_EmptyPath
+ResolveUri_NoSchemeNoAuthority_EmptyPathWithQuery
+ResolveUri_NoSchemeNoAuthority_EmptyPathWithFragment
+ResolveUri_RemoveDots_RemoveOneDotSegment
+ResolveUri_RemoveDots_RemoveTwoDotSegments
+ResolveUri_RemoveDots_RemoveOneDotDotSegment
+ResolveUri_RemoveDots_RemoveTwoDotDotSegments
+ResolveUri_RemoveDots_RemoveTooManyDotDotSegments
+ResolveUri_RemoveDots_RemoveDotSegmentsNothingLeft1
+ResolveUri_RemoveDots_RemoveDotSegmentsNothingLeft2
+ResolveUri_RemoveDots_RemoveDotSegmentsInitialPrefix
+ResolveUri_RemoveDots_RemoveDotSegmentsMixed
+ResolveUri_NormalizeEscapes_PathQueryFragment
+ResolveUri_NormalizeEscapes_UppercaseHexPreferred
+ResolveUri_NormalizeEscapes_Authority
+ResolveUri_NormalizeEscapes_BrokenEscapeSequence
+ResolveUri_DataUri
+ResolveUri_RelativeBase_NotImplemented
+ResolveUri_TestUriPerRFCs
+ResolveUri_MoreDotSegmentTests
+Minimum
+Maximum
+IsPowerOfTwo
+ShiftForPowerOfTwo
+IsAligned
+RoundDown
+RoundUp
+RoundUpToPowerOfTwo
+CountOneBits
+CountZeros
+IsInt
+IsUint
+IsAbsoluteUint
+LowBits
+Endianity
+DoublesBitEqual
+AllocateVirtualMemory
+FreeVirtualMemory
+VirtualMemoryCommitPartial
+AllocateZone
+AllocGeneric_Success
+AllocGeneric_Overflow
+ZoneAllocated
+PrintToString
+CorelibCompileAll
+CorelibCompilerStats
+Dart2JSCompilerStats
+CorelibIsolateStartup
+UseDartApi
+DartStringAccess
+Dart2JSCompileAll
+FrameLookup
+CoreSnapshotSize
+StandaloneSnapshotSize
+CreateMirrorSystem
+EnterExitIsolate
+SerializeNull
+SerializeSmi
+SimpleMessage
+LargeMap
diff --git a/runtime/bin/run_vm_tests_fuchsia.cc b/runtime/bin/run_vm_tests_fuchsia.cc
new file mode 100644
index 0000000..3e7430a
--- /dev/null
+++ b/runtime/bin/run_vm_tests_fuchsia.cc
@@ -0,0 +1,255 @@
+// Copyright (c) 2016, 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.
+
+#include <fcntl.h>
+#include <magenta/syscalls.h>
+#include <mxio/util.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+// This program runs Dart VM unit tests. The Dart VM unit tests are contained
+// in a separate binary whose location is defined in kRunVmTestsPath below.
+// That program accepts a command line argument --list to list all the available
+// tests, or the name of a single test to run. This program accepts a single
+// command line argument which is the path to a file containing a list of tests
+// to run, one per line.
+
+const char* kRunVmTestsPath = "/boot/bin/dart_vm_tests";
+
+// Tests that are invalid, wedge, or cause panics.
+const char* kSkip[] = {
+ // These expect a file to exist that we aren't putting in the image.
+ "Read",
+ "FileLength",
+ "FilePosition",
+ // Hangs.
+ "ArrayLengthMaxElements",
+ "Int8ListLengthMaxElements",
+ "ThreadPool_WorkerShutdown",
+ "LargeMap",
+ "CompileFunctionOnHelperThread",
+ // Kernel panic.
+ "ThreadBarrier",
+ // The profiler is turned off.
+ "Profiler_AllocationSampleTest",
+ "Profiler_ArrayAllocation",
+ "Profiler_BasicSourcePosition",
+ "Profiler_BasicSourcePositionOptimized",
+ "Profiler_BinaryOperatorSourcePosition",
+ "Profiler_BinaryOperatorSourcePositionOptimized",
+ "Profiler_ChainedSamples",
+ "Profiler_ClosureAllocation",
+ "Profiler_CodeTicks",
+ "Profiler_ContextAllocation",
+ "Profiler_FunctionInline",
+ "Profiler_FunctionTicks",
+ "Profiler_InliningIntervalBoundry",
+ "Profiler_IntrinsicAllocation",
+ "Profiler_SampleBufferIterateTest",
+ "Profiler_SampleBufferWrapTest",
+ "Profiler_SourcePosition",
+ "Profiler_SourcePositionOptimized",
+ "Profiler_StringAllocation",
+ "Profiler_StringInterpolation",
+ "Profiler_ToggleRecordAllocation",
+ "Profiler_TrivialRecordAllocation",
+ "Profiler_TypedArrayAllocation",
+ "Profiler_GetSourceReport",
+ "Service_Profile",
+ // No realpath.
+ "Dart2JSCompilerStats",
+ "Dart2JSCompileAll",
+};
+
+// Expected to fail/crash.
+const char* kExpectFail[] = {
+ "Fail0",
+ "Fail1",
+ "Fail2",
+ "IsolateReload_PendingUnqualifiedCall_InstanceToStatic",
+ "IsolateReload_PendingUnqualifiedCall_StaticToInstance",
+ "IsolateReload_PendingConstructorCall_AbstractToConcrete",
+ "IsolateReload_PendingConstructorCall_ConcreteToAbstract",
+ "IsolateReload_PendingStaticCall_DefinedToNSM",
+ "IsolateReload_PendingStaticCall_NSMToDefined",
+ "ArrayNew_Overflow_Crash",
+ "AllocGeneric_Overflow",
+ "CodeImmutability",
+ "SNPrint_BadArgs",
+};
+
+// Bugs to fix, or things that are not yet impelemnted.
+const char* kBugs[] = {
+ // pthreads not using specified stack size.
+ "StackOverflowStacktraceInfo",
+ // Needs OS::GetCurrentThreadCPUMicros.
+ "Timeline_Dart_TimelineDuration",
+ "Timeline_Dart_TimelineInstant"
+ "Timeline_Dart_TimelineAsyncDisabled",
+ "Timeline_Dart_TimelineAsync",
+ "Timeline_Dart_TimelineGetTrace",
+ "Timeline_Dart_TimelineGetTraceOnlyDartEvents",
+ "Timeline_Dart_TimelineGetTraceWithDartEvents",
+ "Timeline_Dart_TimelineGetTraceGlobalOverride",
+ "Timeline_Dart_GlobalTimelineGetTrace",
+ "Timeline_Dart_GlobalTimelineGetTrace_Threaded",
+ "TimelineEventDuration",
+ "TimelineEventDurationPrintJSON",
+ "TimelineEventArguments",
+ "TimelineEventArgumentsPrintJSON",
+ "TimelineEventBufferPrintJSON",
+ "TimelineEventCallbackRecorderBasic",
+ "TimelineAnalysis_ThreadBlockCount",
+ "TimelineRingRecorderJSONOrder",
+ "TimelinePauses_BeginEnd",
+ // Crash.
+ "FindCodeObject",
+ // Needs OS::Sleep.
+ "MessageHandler_Run",
+ "Sleep",
+ // Calls VirtualMemory::FreeSubSegment.
+ "GrowableObjectArray",
+ "PrintJSON",
+ "GenerateSource",
+ "FreeVirtualMemory",
+ // Several missing calls.
+ "OsFuncs",
+ // OS::AlignedAllocate.
+ "OSAlignedAllocate",
+ // Needs NativeSymbolResolver
+ "Service_PersistentHandles",
+ // Need to investigate:
+ "ThreadPool_RunOne",
+ "ThreadPool_WorkerTimeout",
+ "Monitor",
+ "ThreadIterator_AddFindRemove",
+ // Needs Utils::HostToBigEndian16
+ "Endianity",
+};
+
+
+static bool contains(const char** list, intptr_t len, const char* str) {
+ for (intptr_t i = 0; i < len; i++) {
+ if (strcmp(list[i], str) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+static bool isSkip(const char* test) {
+ return contains(
+ kSkip, sizeof(kSkip) / sizeof(kSkip[0]), test);
+}
+
+
+static bool isExpectFail(const char* test) {
+ return contains(
+ kExpectFail, sizeof(kExpectFail) / sizeof(kExpectFail[0]), test);
+}
+
+
+static bool isBug(const char* test) {
+ return contains(kBugs, sizeof(kBugs) / sizeof(kBugs[0]), test);
+}
+
+
+static int run_test(const char* test_name) {
+ const intptr_t kArgc = 2;
+ const char* argv[3];
+ argv[0] = kRunVmTestsPath;
+ argv[1] = test_name;
+
+ mx_handle_t p = mxio_start_process(argv[0], kArgc, argv);
+ if (p < 0) {
+ printf("process failed to start\n");
+ return -1;
+ }
+
+ mx_signals_state_t state;
+ mx_status_t r = mx_handle_wait_one(
+ p, MX_SIGNAL_SIGNALED, MX_TIME_INFINITE, &state);
+ if (r != NO_ERROR) {
+ printf("[process(%x): wait failed? %d]\n", p, r);
+ return -1;
+ }
+
+ mx_process_info_t proc_info;
+ mx_ssize_t ret = mx_handle_get_info(
+ p, MX_INFO_PROCESS, &proc_info, sizeof(proc_info));
+ if (ret != sizeof(proc_info)) {
+ printf("[process(%x): handle_get_info failed? %ld]\n", p, ret);
+ return -1;
+ }
+
+ mx_handle_close(p);
+ return proc_info.return_code;
+}
+
+
+static void trim(char* line) {
+ const intptr_t line_len = strlen(line);
+ if (line[line_len - 1] == '\n') {
+ line[line_len - 1] = '\0';
+ }
+}
+
+
+static bool should_run(const char* test) {
+ return !(test[0] == '#') && !isSkip(test);
+}
+
+
+static void handle_result(intptr_t result, const char* test) {
+ if (result != 0) {
+ if (!isExpectFail(test) && !isBug(test)) {
+ printf("******** Test %s FAILED\n", test);
+ }
+ } else {
+ if (isExpectFail(test)) {
+ printf("******** Test %s is expected to fail, but PASSED\n", test);
+ }
+ if (isBug(test)) {
+ printf("******** Test %s is marked as a bug, but PASSED\n", test);
+ }
+ }
+}
+
+
+int main(int argc, char** argv) {
+ if (argc <= 1) {
+ fprintf(stderr, "Pass the path to a file containing the list of tests\n");
+ return -1;
+ }
+ const char* tests_path = argv[1];
+
+ FILE* fp = fopen(tests_path, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "Failed to read the file: %s\n", tests_path);
+ return -1;
+ }
+
+ char* test = NULL;
+ size_t len = 0;
+ ssize_t read;
+ while ((read = getline(&test, &len, fp)) != -1) {
+ trim(test);
+ if (!should_run(test)) {
+ continue;
+ }
+ intptr_t result = run_test(test);
+ handle_result(result, test);
+ }
+
+ fclose(fp);
+ if (test != NULL) {
+ free(test);
+ }
+ return 0;
+}
+
diff --git a/runtime/lib/function.cc b/runtime/lib/function.cc
index b7424f5..4241762 100644
--- a/runtime/lib/function.cc
+++ b/runtime/lib/function.cc
@@ -47,6 +47,19 @@
const Object& receiver_b = Object::Handle(context_b.At(0));
if (receiver_a.raw() == receiver_b.raw()) return Bool::True().raw();
}
+ } else if (func_a.IsImplicitInstanceClosureFunction() &&
+ func_b.IsImplicitInstanceClosureFunction()) {
+ // TODO(rmacnak): Patch existing tears off during reload instead.
+ const Context& context_a = Context::Handle(receiver.context());
+ const Context& context_b = Context::Handle(
+ Closure::Cast(other).context());
+ const Object& receiver_a = Object::Handle(context_a.At(0));
+ const Object& receiver_b = Object::Handle(context_b.At(0));
+ if ((receiver_a.raw() == receiver_b.raw()) &&
+ (func_a.name() == func_b.name()) &&
+ (func_a.Owner() == func_b.Owner())) {
+ return Bool::True().raw();
+ }
}
}
return Bool::False().raw();
diff --git a/runtime/observatory/lib/app.dart b/runtime/observatory/lib/app.dart
index 6212eb3..371c266 100644
--- a/runtime/observatory/lib/app.dart
+++ b/runtime/observatory/lib/app.dart
@@ -27,6 +27,5 @@
part 'src/app/notification.dart';
part 'src/app/page.dart';
part 'src/app/settings.dart';
-part 'src/app/target_manager.dart';
part 'src/app/view_model.dart';
part 'src/app/analytics.dart';
diff --git a/runtime/observatory/lib/elements.dart b/runtime/observatory/lib/elements.dart
index e1889ac..4d9786e 100644
--- a/runtime/observatory/lib/elements.dart
+++ b/runtime/observatory/lib/elements.dart
@@ -83,7 +83,7 @@
import 'package:observatory/src/elements/nav/vm_menu_wrapper.dart';
import 'package:observatory/src/elements/view_footer.dart';
import 'package:observatory/src/elements/vm_connect_target.dart';
-import 'package:observatory/src/elements/vm_connect_target_wrapper.dart';
+import 'package:observatory/src/elements/vm_connect.dart';
export 'package:observatory/src/elements/helpers/rendering_queue.dart';
@@ -103,6 +103,7 @@
export 'package:observatory/src/elements/nav/vm_menu.dart';
export 'package:observatory/src/elements/view_footer.dart';
export 'package:observatory/src/elements/vm_connect_target.dart';
+export 'package:observatory/src/elements/vm_connect.dart';
// Even though this function does not invoke any asynchronous operation
// it is marked as async to allow future backward compatible changes.
@@ -133,6 +134,6 @@
NavVMMenuElement.tag.ensureRegistration();
NavVMMenuElementWrapper.tag.ensureRegistration();
ViewFooterElement.tag.ensureRegistration();
+ VMConnectElement.tag.ensureRegistration();
VMConnectTargetElement.tag.ensureRegistration();
- VMConnectTargetElementWrapper.tag.ensureRegistration();
}
diff --git a/runtime/observatory/lib/elements.html b/runtime/observatory/lib/elements.html
index b1d51fa..731c907 100644
--- a/runtime/observatory/lib/elements.html
+++ b/runtime/observatory/lib/elements.html
@@ -42,5 +42,4 @@
<link rel="import" href="src/elements/script_view.html">
<link rel="import" href="src/elements/service_ref.html">
<link rel="import" href="src/elements/timeline_page.html">
-<link rel="import" href="src/elements/vm_connect.html">
<link rel="import" href="src/elements/vm_view.html">
diff --git a/runtime/observatory/lib/mocks.dart b/runtime/observatory/lib/mocks.dart
index 18d8805..facf17f 100644
--- a/runtime/observatory/lib/mocks.dart
+++ b/runtime/observatory/lib/mocks.dart
@@ -21,4 +21,6 @@
part 'src/mocks/objects/target.dart';
part 'src/mocks/objects/vm.dart';
+part 'src/mocks/repositories/crash_dump.dart';
part 'src/mocks/repositories/notification.dart';
+part 'src/mocks/repositories/target.dart';
diff --git a/runtime/observatory/lib/models.dart b/runtime/observatory/lib/models.dart
index c047e9c..878a72c 100644
--- a/runtime/observatory/lib/models.dart
+++ b/runtime/observatory/lib/models.dart
@@ -25,4 +25,6 @@
part 'src/models/objects/timeline_event.dart';
part 'src/models/objects/vm.dart';
+part 'src/models/repositories/crash_dump.dart';
part 'src/models/repositories/notification.dart';
+part 'src/models/repositories/target.dart';
diff --git a/runtime/observatory/lib/repositories.dart b/runtime/observatory/lib/repositories.dart
index 5e333ad..4e7cd44 100644
--- a/runtime/observatory/lib/repositories.dart
+++ b/runtime/observatory/lib/repositories.dart
@@ -5,6 +5,12 @@
library repositories;
import 'dart:async';
+import 'dart:convert';
+import 'dart:html';
import 'package:observatory/models.dart' as M;
+import 'package:observatory/service_common.dart' as SC;
+import 'package:observatory/utils.dart';
part 'src/repositories/notification.dart';
+part 'src/repositories/settings.dart';
+part 'src/repositories/target.dart';
diff --git a/runtime/observatory/lib/src/app/application.dart b/runtime/observatory/lib/src/app/application.dart
index b37eda2..a8bfabb 100644
--- a/runtime/observatory/lib/src/app/application.dart
+++ b/runtime/observatory/lib/src/app/application.dart
@@ -9,6 +9,7 @@
class ObservatoryApplication extends Observable {
static ObservatoryApplication app;
final RenderingQueue queue = new RenderingQueue();
+ final TargetRepository targets = new TargetRepository();
final NotificationRepository notifications = new NotificationRepository();
final _pageRegistry = new List<Page>();
LocationManager _locationManager;
@@ -17,7 +18,7 @@
VM _vm;
VM get vm => _vm;
- set vm(VM vm) {
+ _setVM(VM vm) {
if (_vm == vm) {
// Do nothing.
return;
@@ -31,9 +32,6 @@
Logger.root.info('Registering new VM callbacks');
vm.onConnect.then((_) {
- if (vm is WebSocketVM) {
- targets.add(vm.target);
- }
notifications.deleteDisconnectEvents();
});
@@ -52,7 +50,6 @@
}
_vm = vm;
}
- final TargetManager targets;
@reflectable final ObservatoryApplicationElement rootElement;
TraceViewElement _traceView = null;
@@ -194,15 +191,20 @@
currentPage = page;
}
- ObservatoryApplication(this.rootElement) :
- targets = new TargetManager() {
+ ObservatoryApplication(this.rootElement) {
_locationManager = new LocationManager(this);
- vm = new WebSocketVM(targets.defaultTarget);
+ targets.onChange.listen((e) {
+ if (targets.current == null) return _setVM(null);
+ if ((_vm as WebSocketVM)?.target != targets.current) {
+ _setVM(new WebSocketVM(targets.current));
+ }
+ });
+ _setVM(new WebSocketVM(targets.current));
_initOnce();
}
loadCrashDump(Map crashDump) {
- this.vm = new FakeVM(crashDump['result']);
+ _setVM(new FakeVM(crashDump['result']));
app.locationManager.go('#/vm');
}
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index 7f51a8e..0129c34 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -18,7 +18,7 @@
final ObservatoryApplication app;
final ObservableMap<String, String> internalArguments =
new ObservableMap<String, String>();
- @observable ObservatoryElement element;
+ @observable HtmlElement element;
Page(this.app);
@@ -370,7 +370,12 @@
void onInstall() {
if (element == null) {
- element = new Element.tag('vm-connect');
+ element = new VMConnectElement(
+ ObservatoryApplication.app.targets,
+ new CrashDumpRepositoryMock(
+ load: ObservatoryApplication.app.loadCrashDump),
+ ObservatoryApplication.app.notifications,
+ queue: ObservatoryApplication.app.queue);
}
assert(element != null);
}
diff --git a/runtime/observatory/lib/src/app/target_manager.dart b/runtime/observatory/lib/src/app/target_manager.dart
deleted file mode 100644
index 6620db0..0000000
--- a/runtime/observatory/lib/src/app/target_manager.dart
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (c) 2014, 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.
-
-part of app;
-
-class ChromiumTargetLister {
- /// Fetch the list of chromium [NetworkVMTargets].
- static Future<List<WebSocketVMTarget>> fetch(String networkAddress) {
- if (networkAddress == null) {
- return new Future.error(null);
- }
- var encoded = Uri.encodeComponent(networkAddress);
- var url = '/crdptargets/$encoded';
- return HttpRequest.getString(url).then((String responseText) {
- var list = JSON.decode(responseText);
- if (list == null) {
- return list;
- }
- for (var i = 0; i < list.length; i++) {
- list[i] = new WebSocketVMTarget.fromMap(list[i]);
- }
- return list;
- }).catchError((e) {
- // An error occured while getting the list of Chrome targets.
- // We eagerly request the list of targets, meaning this error can occur
- // regularly. By catching it and dropping it, we avoid spamming errors
- // on the console.
- });
- }
-}
-
-class TargetManager extends Observable {
- static const _historyKey = 'history';
- final SettingsGroup _settings = new SettingsGroup('targetManager');
- final List history = new ObservableList();
- WebSocketVMTarget defaultTarget;
-
- String _networkAddressOfDefaultTarget() {
- if (Utils.runningInJavaScript()) {
- // We are running as JavaScript, use the same host that Observatory has
- // been loaded from.
- return 'ws://${window.location.host}/ws';
- } else {
- // Otherwise, assume we are running from Dart Editor and want to connect
- // to the default host.
- return 'ws://localhost:8181/ws';
- }
- }
- TargetManager() {
- _restore();
- // Add a default standalone VM target.
- defaultTarget = findOrMake(_networkAddressOfDefaultTarget());
- assert(defaultTarget != null);
- add(defaultTarget);
- }
-
- void clearHistory() {
- history.clear();
- _store();
- }
-
- WebSocketVMTarget findOrMake(String networkAddress) {
- var target;
- target = _find(networkAddress);
- if (target != null) {
- return target;
- }
- target = new WebSocketVMTarget(networkAddress);
- return target;
- }
-
- /// Find by networkAddress.
- WebSocketVMTarget _find(String networkAddress) {
- var r;
- history.forEach((item) {
- if ((item.networkAddress == networkAddress) && (item.chrome == false)) {
- r = item;
- }
- });
- return r;
- }
-
- void add(WebSocketVMTarget item) {
- if (item.chrome) {
- // We don't store chrome tabs.
- return;
- }
- if (history.contains(item)) {
- return;
- }
- // Not inserting duplicates.
- assert(_find(item.networkAddress) == null);
- history.add(item);
- _sort();
- _store();
- }
-
- void remove(WebSocketVMTarget target) {
- history.remove(target);
- _sort();
- _store();
- }
-
- void _sort() {
- this.history.sort((WebSocketVMTarget a, WebSocketVMTarget b) {
- return b.lastConnectionTime.compareTo(a.lastConnectionTime);
- });
- }
-
- /// After making a change, update settings.
- void _store() {
- _sort();
- _settings.set(_historyKey, history);
- }
-
- /// Read settings from data store.
- void _restore() {
- this.history.clear();
- var loaded = _settings.get(_historyKey);
- if (loaded == null) {
- return;
- }
- for (var i = 0; i < loaded.length; i++) {
- loaded[i] = new WebSocketVMTarget.fromMap(loaded[i]);
- }
- this.history.addAll(loaded);
- _sort();
- }
-}
diff --git a/runtime/observatory/lib/src/elements/css/shared.css b/runtime/observatory/lib/src/elements/css/shared.css
index 75b35ce..1f32ad4 100644
--- a/runtime/observatory/lib/src/elements/css/shared.css
+++ b/runtime/observatory/lib/src/elements/css/shared.css
@@ -302,6 +302,11 @@
0 2px 5px 0 rgba(0, 0, 0, 0.26);
}
+input.textbox {
+ width: 20em;
+ font: 400 16px 'Montserrat', sans-serif;
+}
+
@-webkit-keyframes fadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
@@ -473,16 +478,14 @@
}
/* vm-connect-target */
-/* TODO(cbernaschina) fix vm-connect-target-wrapped to vm-connect-target
-+when wrapper removed */
-vm-connect-target-wrapped > button.delete-button {
+vm-connect-target > button.delete-button {
margin-left: 0.28em;
padding: 4px;
background: transparent;
border: none !important;
}
-vm-connect-target-wrapped > button.delete-button:hover {
+vm-connect-target > button.delete-button:hover {
background: #ff0000;
}
diff --git a/runtime/observatory/lib/src/elements/curly_block_wrapper.dart b/runtime/observatory/lib/src/elements/curly_block_wrapper.dart
index 2a141b5..4e2519a 100644
--- a/runtime/observatory/lib/src/elements/curly_block_wrapper.dart
+++ b/runtime/observatory/lib/src/elements/curly_block_wrapper.dart
@@ -12,11 +12,13 @@
typedef _callback();
typedef CurlyBlockToggleCallback(bool a, _callback b);
+@bindable
class CurlyBlockElementWrapper extends HtmlElement {
- static final binder = new Binder<CurlyBlockElementWrapper>(
- const [const Binding('expand'), const Binding('busy'),
- const Binding('expandKey'), const Binding('callback')]);
+ static const binder = const Binder<CurlyBlockElementWrapper>(const {
+ 'expand': #expand, 'busy': #busy, 'expandKey': #expandKey,
+ 'callback': #callback
+ });
static const tag = const Tag<CurlyBlockElementWrapper>('curly-block');
diff --git a/runtime/observatory/lib/src/elements/helpers/rendering_queue.dart b/runtime/observatory/lib/src/elements/helpers/rendering_queue.dart
index a6062c3..707de23 100644
--- a/runtime/observatory/lib/src/elements/helpers/rendering_queue.dart
+++ b/runtime/observatory/lib/src/elements/helpers/rendering_queue.dart
@@ -66,7 +66,8 @@
Future _render() async {
await _barrier.next;
while (_queue.isNotEmpty) {
- _queue.removeFirst().render();
+ _queue.first.render();
+ _queue.removeFirst();
}
}
}
diff --git a/runtime/observatory/lib/src/elements/isolate_ref_wrapper.dart b/runtime/observatory/lib/src/elements/isolate_ref_wrapper.dart
index dc78739..93978c5 100644
--- a/runtime/observatory/lib/src/elements/isolate_ref_wrapper.dart
+++ b/runtime/observatory/lib/src/elements/isolate_ref_wrapper.dart
@@ -13,10 +13,12 @@
import 'package:observatory/src/elements/helpers/tag.dart';
import 'package:observatory/src/elements/shims/binding.dart';
+@bindable
class IsolateRefElementWrapper extends HtmlElement {
- static final binder = new Binder<IsolateRefElementWrapper>(
- const [const Binding('ref')]);
+ static const binder = const Binder<IsolateRefElementWrapper>(const {
+ 'ref': #ref
+ });
static const tag = const Tag<IsolateRefElementWrapper>('isolate-ref');
diff --git a/runtime/observatory/lib/src/elements/nav/class_menu_wrapper.dart b/runtime/observatory/lib/src/elements/nav/class_menu_wrapper.dart
index d1e56ac..35fc448 100644
--- a/runtime/observatory/lib/src/elements/nav/class_menu_wrapper.dart
+++ b/runtime/observatory/lib/src/elements/nav/class_menu_wrapper.dart
@@ -10,9 +10,11 @@
import 'package:observatory/src/elements/shims/binding.dart';
import 'package:observatory/src/elements/nav/class_menu.dart';
+@bindable
class NavClassMenuElementWrapper extends HtmlElement {
- static final binder = new Binder<NavClassMenuElementWrapper>(
- const [const Binding('last'), const Binding('cls')]);
+ static const binder = const Binder<NavClassMenuElementWrapper>(const {
+ 'last': #last, 'cls': #cls
+ });
static const tag =
const Tag<NavClassMenuElementWrapper>('class-nav-menu');
diff --git a/runtime/observatory/lib/src/elements/nav/isolate_menu_wrapper.dart b/runtime/observatory/lib/src/elements/nav/isolate_menu_wrapper.dart
index c2cf8f3..3af85d2 100644
--- a/runtime/observatory/lib/src/elements/nav/isolate_menu_wrapper.dart
+++ b/runtime/observatory/lib/src/elements/nav/isolate_menu_wrapper.dart
@@ -13,9 +13,11 @@
import 'package:observatory/src/elements/shims/binding.dart';
import 'package:observatory/src/elements/nav/isolate_menu.dart';
+@bindable
class NavIsolateMenuElementWrapper extends HtmlElement {
- static final binder = new Binder<NavIsolateMenuElementWrapper>(
- const [const Binding('last'), const Binding('isolate')]);
+ static const binder = const Binder<NavIsolateMenuElementWrapper>(const {
+ 'last': #last, 'isolate': #isolate
+ });
static const tag =
const Tag<NavIsolateMenuElementWrapper>('isolate-nav-menu');
diff --git a/runtime/observatory/lib/src/elements/nav/library_menu_wrapper.dart b/runtime/observatory/lib/src/elements/nav/library_menu_wrapper.dart
index 6e48155..1097bdc 100644
--- a/runtime/observatory/lib/src/elements/nav/library_menu_wrapper.dart
+++ b/runtime/observatory/lib/src/elements/nav/library_menu_wrapper.dart
@@ -10,9 +10,11 @@
import 'package:observatory/src/elements/shims/binding.dart';
import 'package:observatory/src/elements/nav/library_menu.dart';
+@bindable
class NavLibraryMenuElementWrapper extends HtmlElement {
- static final binder = new Binder<NavLibraryMenuElementWrapper>(
- const [const Binding('last'), const Binding('library')]);
+ static const binder = const Binder<NavLibraryMenuElementWrapper>(const {
+ 'last': #last, 'library': #library
+ });
static const tag =
const Tag<NavLibraryMenuElementWrapper>('library-nav-menu');
diff --git a/runtime/observatory/lib/src/elements/nav/menu_item_wrapper.dart b/runtime/observatory/lib/src/elements/nav/menu_item_wrapper.dart
index 045d67a..7888745 100644
--- a/runtime/observatory/lib/src/elements/nav/menu_item_wrapper.dart
+++ b/runtime/observatory/lib/src/elements/nav/menu_item_wrapper.dart
@@ -9,9 +9,11 @@
import 'package:observatory/src/elements/shims/binding.dart';
import 'package:observatory/src/elements/nav/menu_item.dart';
+@bindable
class NavMenuItemElementWrapper extends HtmlElement {
- static final binder = new Binder<NavMenuItemElementWrapper>(
- const [const Binding('anchor'), const Binding('link')]);
+ static const binder = const Binder<NavMenuItemElementWrapper>(const {
+ 'anchor': #anchor, 'link': #link
+ });
static const tag =
const Tag<NavMenuItemElementWrapper>('nav-menu-item');
diff --git a/runtime/observatory/lib/src/elements/nav/menu_wrapper.dart b/runtime/observatory/lib/src/elements/nav/menu_wrapper.dart
index c237fed..04577c6 100644
--- a/runtime/observatory/lib/src/elements/nav/menu_wrapper.dart
+++ b/runtime/observatory/lib/src/elements/nav/menu_wrapper.dart
@@ -9,10 +9,11 @@
import 'package:observatory/src/elements/shims/binding.dart';
import 'package:observatory/src/elements/nav/menu.dart';
+@bindable
class NavMenuElementWrapper extends HtmlElement {
- static final binder = new Binder<NavMenuElementWrapper>(
- const [const Binding('anchor'), const Binding('link'),
- const Binding('last')]);
+ static const binder = const Binder<NavMenuElementWrapper>(const {
+ 'anchor': #anchor, 'link': #link, 'last': #last
+ });
static const tag =
const Tag<NavMenuElementWrapper>('nav-menu');
diff --git a/runtime/observatory/lib/src/elements/nav/notify_wrapper.dart b/runtime/observatory/lib/src/elements/nav/notify_wrapper.dart
index 97f4ded..7676727 100644
--- a/runtime/observatory/lib/src/elements/nav/notify_wrapper.dart
+++ b/runtime/observatory/lib/src/elements/nav/notify_wrapper.dart
@@ -10,9 +10,11 @@
import 'package:observatory/src/elements/shims/binding.dart';
import 'package:observatory/src/elements/nav/notify.dart';
+@bindable
class NavNotifyElementWrapper extends HtmlElement {
- static final binder = new Binder<NavNotifyElementWrapper>(
- const [const Binding('notifications'), const Binding('notifyOnPause')]);
+ static const binder = const Binder<NavNotifyElementWrapper>(const {
+ 'notifications': #notifications, 'notifyOnPause': #notifyOnPause
+ });
static const tag = const Tag<NavNotifyElementWrapper>('nav-notify');
diff --git a/runtime/observatory/lib/src/elements/nav/refresh_wrapper.dart b/runtime/observatory/lib/src/elements/nav/refresh_wrapper.dart
index dcd1696..19e7cce 100644
--- a/runtime/observatory/lib/src/elements/nav/refresh_wrapper.dart
+++ b/runtime/observatory/lib/src/elements/nav/refresh_wrapper.dart
@@ -10,9 +10,11 @@
import 'package:observatory/src/elements/shims/binding.dart';
import 'package:observatory/src/elements/nav/refresh.dart';
+@bindable
class NavRefreshElementWrapper extends HtmlElement {
- static final binder = new Binder<NavRefreshElementWrapper>(
- const [const Binding('callback'), const Binding('label')]);
+ static const binder = const Binder<NavRefreshElementWrapper>(const {
+ 'callback': #callback, 'label': #label
+ });
static const tag = const Tag<NavRefreshElementWrapper>('nav-refresh');
diff --git a/runtime/observatory/lib/src/elements/nav/top_menu_wrapper.dart b/runtime/observatory/lib/src/elements/nav/top_menu_wrapper.dart
index fbfebff..edc5e27 100644
--- a/runtime/observatory/lib/src/elements/nav/top_menu_wrapper.dart
+++ b/runtime/observatory/lib/src/elements/nav/top_menu_wrapper.dart
@@ -9,9 +9,11 @@
import 'package:observatory/src/elements/shims/binding.dart';
import 'package:observatory/src/elements/nav/top_menu.dart';
+@bindable
class NavTopMenuElementWrapper extends HtmlElement {
- static final binder = new Binder<NavTopMenuElementWrapper>(
- const [const Binding('last')]);
+ static const binder = const Binder<NavTopMenuElementWrapper>(const {
+ 'last': #last
+ });
static const tag = const Tag<NavTopMenuElementWrapper>('top-nav-menu');
diff --git a/runtime/observatory/lib/src/elements/nav/vm_menu_wrapper.dart b/runtime/observatory/lib/src/elements/nav/vm_menu_wrapper.dart
index ef71b2d..9327e19 100644
--- a/runtime/observatory/lib/src/elements/nav/vm_menu_wrapper.dart
+++ b/runtime/observatory/lib/src/elements/nav/vm_menu_wrapper.dart
@@ -14,9 +14,11 @@
import 'package:observatory/src/elements/shims/binding.dart';
import 'package:observatory/src/elements/nav/vm_menu.dart';
+@bindable
class NavVMMenuElementWrapper extends HtmlElement {
- static final binder = new Binder<NavVMMenuElementWrapper>(
- const [const Binding('last'), const Binding('vm')]);
+ static const binder = const Binder<NavVMMenuElementWrapper>(const {
+ 'last': #last, 'vm': #vm
+ });
static const tag = const Tag<NavVMMenuElementWrapper>('vm-nav-menu');
diff --git a/runtime/observatory/lib/src/elements/shims/binding.dart b/runtime/observatory/lib/src/elements/shims/binding.dart
index 5e37609..c5425c4 100644
--- a/runtime/observatory/lib/src/elements/shims/binding.dart
+++ b/runtime/observatory/lib/src/elements/shims/binding.dart
@@ -5,57 +5,43 @@
import 'dart:core';
import 'dart:html';
import 'dart:js';
+@MirrorsUsed(metaTargets: const [BindableAnnotation])
import 'dart:mirrors';
import 'package:js/js.dart';
import 'package:js_util/js_util.dart';
import 'package:polymer/polymer.dart';
-class Binding {
- final String attribute;
- final String property;
- const Binding (attribute, [String property])
- : attribute = attribute,
- property = property == null ? attribute : property;
+const BindableAnnotation bindable = const BindableAnnotation();
+class BindableAnnotation {
+ const BindableAnnotation();
}
+
///This is a temporary bridge between Polymer Bindings and the wrapper entities.
class Binder<T extends HtmlElement> {
- final List<Binding> attributes;
- final callback;
+ final Map<String, Symbol> attributes;
- Binder(List<Binding> attributes)
- : attributes = attributes,
- callback = _createCallback(T, attributes);
+ const Binder(Map<String, Symbol> attributes)
+ : attributes = attributes;
registerCallback(T element) {
assert(element != null);
- setValue(element, 'bind', callback);
+ setValue(element, 'bind', allowInteropCaptureThis(_callback));
}
- static _createCallback(Type T, List<Binding> attributes){
- final target = reflectClass(T);
- final setters = <String, Symbol>{};
- for (Binding binding in attributes){
- var member = target.instanceMembers[new Symbol(binding.property + '=')];
- if (!member.isSetter)
- throw new ArgumentError(
- '${binding.property} is not a Setter for class $T');
- setters[binding.attribute] = new Symbol(binding.property);
+ void _callback(_this, name, value, [other]) {
+ final setter = attributes[name];
+ if (setter == null) return;
+ Bindable bindable;
+ if (identical(1, 1.0)) { // dart2js
+ bindable = getValue(getValue(value, '__dartBindable'), 'o') as Bindable;
+ } else { // vm
+ bindable = getValue(value, '__dartBindable');
}
- return allowInteropCaptureThis((_this, name, value, [other]) {
- final setter = setters[name];
- if (setter == null) return;
- Bindable bindable;
- if (identical(1, 1.0)) { // dart2js
- bindable = getValue(getValue(value, '__dartBindable'), 'o') as Bindable;
- } else { // vm
- bindable = getValue(value, '__dartBindable');
- }
- var obj = reflect(_this);
- obj.setField(setter, bindable.value);
- bindable.open((value) {
- obj.setField(setter, value);
- });
+ var obj = reflect(_this);
+ obj.setField(setter, bindable.value);
+ bindable.open((value) {
+ obj.setField(setter, value);
});
}
}
diff --git a/runtime/observatory/lib/src/elements/vm_connect.dart b/runtime/observatory/lib/src/elements/vm_connect.dart
index 37cc2a2..8539921 100644
--- a/runtime/observatory/lib/src/elements/vm_connect.dart
+++ b/runtime/observatory/lib/src/elements/vm_connect.dart
@@ -4,61 +4,174 @@
library vm_connect_element;
-import 'dart:convert';
import 'dart:html';
+import 'dart:async';
+import 'dart:convert';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/nav/bar.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+import 'package:observatory/src/elements/nav/top_menu.dart';
+import 'package:observatory/src/elements/view_footer.dart';
+import 'package:observatory/src/elements/vm_connect_target.dart';
-import 'observatory_element.dart';
-import 'package:observatory/elements.dart';
-import 'package:observatory/service_html.dart';
-import 'package:polymer/polymer.dart';
+class VMConnectElement extends HtmlElement implements Renderable{
+ static const tag = const Tag<VMConnectElement>('vm-connect',
+ dependencies: const [NavBarElement.tag,
+ NavTopMenuElement.tag,
+ NavNotifyElement.tag,
+ ViewFooterElement.tag,
+ VMConnectTargetElement.tag]);
-@CustomTag('vm-connect')
-class VMConnectElement extends ObservatoryElement {
- @published String standaloneVmAddress = '';
+ RenderingScheduler _r;
- VMConnectElement.created() : super.created() {
+ Stream<RenderedEvent<VMConnectElement>> get onRendered => _r.onRendered;
+
+ M.CrashDumpRepository _dump;
+ M.NotificationRepository _notifications;
+ M.TargetRepository _targets;
+ StreamSubscription _targetsSubscription;
+
+ String _address;
+
+ factory VMConnectElement(M.TargetRepository targets,
+ M.CrashDumpRepository dump,
+ M.NotificationRepository notifications,
+ {String address: '', RenderingQueue queue}) {
+ assert(address != null);
+ assert(dump != null);
+ assert(notifications != null);
+ assert(targets != null);
+ VMConnectElement e = document.createElement(tag.name);
+ e._r = new RenderingScheduler(e, queue: queue);
+ e._address = address;
+ e._dump = dump;
+ e._notifications = notifications;
+ e._targets = targets;
+ return e;
}
- void _connect(WebSocketVMTarget target) {
- app.vm = new WebSocketVM(target);
- app.locationManager.goForwardingParameters('/vm');
- }
+ VMConnectElement.created() : super.created();
@override
void attached() {
- super.attached();
- var fileInput = shadowRoot.querySelector('#crashDumpFile');
- fileInput.onChange.listen(_onCrashDumpFileChange);
+ super.attached(); _r.enable();
+ _targetsSubscription = _targets.onChange.listen((_) => _r.dirty());
}
- String _normalizeStandaloneAddress(String networkAddress) {
+ @override
+ void detached() {
+ super.detached(); children = []; _r.disable(notify: true);
+ _targetsSubscription.cancel(); _targetsSubscription = null;
+ }
+
+ void render() {
+ children = [
+ new NavBarElement(queue: _r.queue)
+ ..children = [
+ new NavTopMenuElement(last: true, queue: _r.queue),
+ new NavNotifyElement(_notifications, queue: _r.queue)
+ ],
+ new DivElement()
+ ..classes = ['content-centered']
+ ..children = [
+ new HeadingElement.h1()..text = 'Connect to a Dart VM',
+ new BRElement(), new HRElement(),
+ new DivElement()
+ ..classes = ['flex-row']
+ ..children = [
+ new DivElement()
+ ..classes = ['flex-item-40-percent']
+ ..children = [
+ new HeadingElement.h2()..text = 'WebSocket',
+ new BRElement(),
+ new UListElement()
+ ..children = _targets.list().map((target) {
+ return new LIElement()
+ ..children = [new VMConnectTargetElement(target,
+ current: target == _targets.current, queue: _r.queue)
+ ..onConnect.listen(_connect)
+ ..onDelete.listen(_delete)
+ ];
+ }).toList(),
+ new HRElement(),
+ new FormElement()
+ ..autocomplete = 'on'
+ ..children = [
+ _createAddressBox(),
+ new SpanElement()..text = ' ',
+ new ButtonElement()
+ ..classes = ['vm_connect']
+ ..text = 'Connect'
+ ..onClick.listen((e) {
+ e.preventDefault(); _create(); }),
+ ],
+ new BRElement(),
+ new PreElement()
+ ..classes = ['well']
+ ..text = 'Run Standalone with: \'--observe\'',
+ new HRElement()
+ ],
+ new DivElement()
+ ..classes = ['flex-item-20-percent'],
+ new DivElement()
+ ..classes = ['flex-item-40-percent']
+ ..children = [
+ new HeadingElement.h2()..text = 'Crash dump',
+ new BRElement(),
+ _createCrushDumpLoader(),
+ new BRElement(), new BRElement(),
+ new PreElement()
+ ..classes = ['well']
+ ..text = 'Request a crash dump with:\n'
+ '\'curl localhost:8181/_getCrashDump > dump.json\'',
+ new HRElement()
+ ]
+ ],
+ ],
+ new ViewFooterElement(queue: _r.queue)
+ ];
+ }
+
+ TextInputElement _createAddressBox() {
+ var textbox = new TextInputElement()
+ ..classes = ['textbox']
+ ..placeholder = 'localhost:8181'
+ ..value = _address
+ ..onKeyUp
+ .where((e) => e.key == '\n')
+ .listen((e) { e.preventDefault(); _create(); });
+ textbox.onInput.listen((e) {
+ _address = textbox.value;
+ });
+ return textbox;
+ }
+
+ FileUploadInputElement _createCrushDumpLoader() {
+ FileUploadInputElement e = new FileUploadInputElement()
+ ..id = 'crashDumpFile';
+ e.onChange.listen((_) {
+ var reader = new FileReader();
+ reader.readAsText(e.files[0]);
+ reader.onLoad.listen((_) {
+ var crashDump = JSON.decode(reader.result);
+ _dump.load(crashDump);
+ });
+ });
+ return e;
+ }
+ void _create() {
+ if (_address == null || _address.isEmpty) return;
+ _targets.add(_normalizeStandaloneAddress(_address));
+ }
+ void _connect(TargetEvent e) => _targets.setCurrent(e.target);
+ void _delete(TargetEvent e) => _targets.delete(e.target);
+
+ static String _normalizeStandaloneAddress(String networkAddress) {
if (networkAddress.startsWith('ws://')) {
return networkAddress;
}
return 'ws://${networkAddress}/ws';
}
-
- void connectStandalone(Event e, var detail, Node target) {
- // Prevent any form action.
- e.preventDefault();
- if (standaloneVmAddress == null) {
- return;
- }
- if (standaloneVmAddress.isEmpty) {
- return;
- }
- var targetAddress = _normalizeStandaloneAddress(standaloneVmAddress);
- var target = app.targets.findOrMake(targetAddress);
- _connect(target);
- }
-
- _onCrashDumpFileChange(e) {
- var fileInput = shadowRoot.querySelector('#crashDumpFile');
- var reader = new FileReader();
- reader.readAsText(fileInput.files[0]);
- reader.onLoad.listen((_) {
- var crashDump = JSON.decode(reader.result);
- app.loadCrashDump(crashDump);
- });
- }
}
diff --git a/runtime/observatory/lib/src/elements/vm_connect.html b/runtime/observatory/lib/src/elements/vm_connect.html
deleted file mode 100644
index 53be73d..0000000
--- a/runtime/observatory/lib/src/elements/vm_connect.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<polymer-element name="vm-connect">
- <template>
- <link rel="stylesheet" href="css/shared.css">
- <style>
- .textbox {
- width: 20em;
- font: 400 16px 'Montserrat', sans-serif;
- }
- </style>
-
- <nav-bar>
- <top-nav-menu last="{{ true }}"></top-nav-menu>
- <nav-notify notifications="{{ app.notifications }}"></nav-notify>
- </nav-bar>
-
- <div class="content-centered">
- <h1>Connect to a Dart VM</h1>
- <br>
- <hr>
- <div class="flex-row">
- <div class="flex-item-40-percent">
- <h2>WebSocket</h2>
- <br>
- <ul>
- <template repeat="{{ target in app.targets.history }}">
- <template if="{{ target.standalone }}">
- <li><vm-connect-target target="{{ target }}"></vm-connect-target></li>
- </template>
- </template>
- </ul>
- <hr>
- <form autocomplete="on">
- <input class="textbox" placeholder="localhost:8181" type="text" value="{{ standaloneVmAddress }}">
- <input class="button" type="submit" value="Connect" on-click="{{ connectStandalone }}">
- </form>
- <br>
- <pre class="well">Run Standalone with: '--observe'</pre>
- <hr>
- </div>
-
- <div class="flex-item-20-percent"></div>
- <div class="flex-item-40-percent">
- <h2>Crash dump</h2>
- <br>
- <input type="file" id="crashDumpFile">
- <br>
- <br>
- <pre class="well">Request a crash dump with:
-'curl localhost:8181/_getCrashDump > dump.json'</pre>
- <hr>
- </div>
- </div>
- </div>
- <view-footer></view-footer>
- </template>
-</polymer-element>
-
-<script type="application/dart" src="vm_connect.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/vm_connect_target.dart b/runtime/observatory/lib/src/elements/vm_connect_target.dart
index befe6dd..3fa7d12 100644
--- a/runtime/observatory/lib/src/elements/vm_connect_target.dart
+++ b/runtime/observatory/lib/src/elements/vm_connect_target.dart
@@ -18,7 +18,7 @@
class VMConnectTargetElement extends HtmlElement implements Renderable{
static const tag =
- const Tag<VMConnectTargetElement>('vm-connect-target-wrapped');
+ const Tag<VMConnectTargetElement>('vm-connect-target');
RenderingScheduler<VMConnectTargetElement> _r;
diff --git a/runtime/observatory/lib/src/elements/vm_connect_target_wrapper.dart b/runtime/observatory/lib/src/elements/vm_connect_target_wrapper.dart
deleted file mode 100644
index 1034061..0000000
--- a/runtime/observatory/lib/src/elements/vm_connect_target_wrapper.dart
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2016, 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:html';
-import 'package:observatory/app.dart';
-import 'package:observatory/service_html.dart';
-import 'package:observatory/src/elements/helpers/tag.dart';
-import 'package:observatory/src/elements/shims/binding.dart';
-import 'package:observatory/src/elements/vm_connect_target.dart';
-
-class VMConnectTargetElementWrapper extends HtmlElement {
- static final binder = new Binder<VMConnectTargetElementWrapper>(
- const [const Binding('target')]);
-
- static const tag =
- const Tag<VMConnectTargetElementWrapper>('vm-connect-target');
-
- WebSocketVMTarget _target;
- WebSocketVMTarget get target => _target;
- void set target(WebSocketVMTarget target) { _target = target; render(); }
-
- VMConnectTargetElementWrapper.created() : super.created() {
- binder.registerCallback(this);
- createShadowRoot();
- render();
- }
-
- @override
- void attached() {
- super.attached();
- render();
- }
-
- void render() {
- if (target == null) return;
-
- shadowRoot.children = [
- new StyleElement()
- ..text = '''
- vm-connect-target-wrapped > button.delete-button {
- margin-left: 0.28em;
- padding: 4px;
- background: transparent;
- border: none !important;
- }
-
- vm-connect-target-wrapped > button.delete-button:hover {
- background: #ff0000;
- }''',
- new VMConnectTargetElement(target, current: current,
- queue: application.queue)
- ..onConnect.listen(connectToVm)
- ..onDelete.listen(deleteVm)
- ];
- }
-
- static ObservatoryApplication get application => ObservatoryApplication.app;
-
- bool get current {
- if (application.vm == null) { return false; }
- return (application.vm as WebSocketVM).target == target;
- }
-
- static void connectToVm(TargetEvent event) {
- WebSocketVM currentVM = application.vm;
- if ((currentVM == null) ||
- currentVM.isDisconnected ||
- (currentVM.target != event.target)) {
- application.vm = new WebSocketVM(event.target);
- }
- }
-
- static void deleteVm(TargetEvent event) {
- application.targets.remove(event.target);
- }
-}
diff --git a/runtime/observatory/lib/src/mocks/repositories/crash_dump.dart b/runtime/observatory/lib/src/mocks/repositories/crash_dump.dart
new file mode 100644
index 0000000..68488e9
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/repositories/crash_dump.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2016, 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
+
+part of mocks;
+
+typedef void CrashDumpRepositoryMockCallback(Map);
+
+class CrashDumpRepositoryMock implements M.CrashDumpRepository {
+ final CrashDumpRepositoryMockCallback _load;
+
+ bool loadInvoked = false;
+
+ void load(Map dump) {
+ loadInvoked = true;
+ if (_load != null) {
+ _load(dump);
+ }
+ }
+
+ CrashDumpRepositoryMock({CrashDumpRepositoryMockCallback load})
+ : _load = load;
+}
diff --git a/runtime/observatory/lib/src/mocks/repositories/target.dart b/runtime/observatory/lib/src/mocks/repositories/target.dart
new file mode 100644
index 0000000..8321f86
--- /dev/null
+++ b/runtime/observatory/lib/src/mocks/repositories/target.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2016, 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
+
+part of mocks;
+
+class TargetChangeEventMock implements M.TargetChangeEvent {
+ final TargetRepositoryMock repository;
+ const TargetChangeEventMock({this.repository});
+}
+
+typedef void TargetRepositoryMockStringCallback(String notification);
+typedef void TargetRepositoryMockTargetCallback(M.Target notification);
+
+class TargetRepositoryMock implements M.TargetRepository {
+ final StreamController<M.TargetChangeEvent> _onChange =
+ new StreamController<M.TargetChangeEvent>.broadcast();
+ Stream<M.TargetChangeEvent> get onChange => _onChange.stream;
+
+ bool get hasListeners => _onChange.hasListener;
+
+ final M.Target _current;
+ final Iterable<M.Target> _list;
+ final TargetRepositoryMockStringCallback _add;
+ final TargetRepositoryMockTargetCallback _setCurrent;
+ final TargetRepositoryMockTargetCallback _delete;
+
+ bool currentInvoked = false;
+ bool addInvoked = false;
+ bool listInvoked = false;
+ bool setCurrentInvoked = false;
+ bool deleteInvoked = false;
+
+ M.Target get current {
+ currentInvoked = true;
+ return _current;
+ }
+
+ void add(String val) {
+ addInvoked = true;
+ if (_add != null) _add(val);
+ }
+
+ Iterable<M.Target> list() {
+ listInvoked = true;
+ return _list;
+ }
+
+ void setCurrent(M.Target target) {
+ setCurrentInvoked = true;
+ if (_setCurrent != null) _setCurrent(target);
+ }
+
+ void delete(M.Target target) {
+ deleteInvoked = true;
+ if (_delete != null) _delete(target);
+ }
+
+ void triggerChangeEvent() {
+ _onChange.add(new TargetChangeEventMock(repository: this));
+ }
+
+ TargetRepositoryMock({M.Target current, Iterable<M.Target> list : const [],
+ TargetRepositoryMockStringCallback add,
+ TargetRepositoryMockTargetCallback setCurrent,
+ TargetRepositoryMockTargetCallback delete})
+ : _current = current,
+ _list = list,
+ _add = add,
+ _setCurrent = setCurrent,
+ _delete = delete;
+}
diff --git a/runtime/observatory/lib/src/models/repositories/crash_dump.dart b/runtime/observatory/lib/src/models/repositories/crash_dump.dart
new file mode 100644
index 0000000..8eb64c1
--- /dev/null
+++ b/runtime/observatory/lib/src/models/repositories/crash_dump.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, 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
+
+part of models;
+
+abstract class CrashDumpRepository {
+ void load(Map);
+}
diff --git a/runtime/observatory/lib/src/models/repositories/target.dart b/runtime/observatory/lib/src/models/repositories/target.dart
new file mode 100644
index 0000000..8df29ca
--- /dev/null
+++ b/runtime/observatory/lib/src/models/repositories/target.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2016, 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
+
+part of models;
+
+abstract class TargetChangeEvent {
+ TargetRepository get repository;
+}
+
+abstract class TargetRepository {
+ Stream<TargetChangeEvent> get onChange;
+
+ Target get current;
+ Iterable<Target> list();
+ void add(String);
+ void setCurrent(Target);
+ void delete(Target);
+}
diff --git a/runtime/observatory/lib/src/repositories/settings.dart b/runtime/observatory/lib/src/repositories/settings.dart
new file mode 100644
index 0000000..771c48e
--- /dev/null
+++ b/runtime/observatory/lib/src/repositories/settings.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2016, 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
+
+part of repositories;
+
+/// Static settings database.
+class _Settings {
+ static Storage _storage = window.localStorage;
+
+ /// Associated [value] with [key]. [value] must be JSON encodable.
+ static void set(String key, dynamic value) {
+ _storage[key] = JSON.encode(value);
+ }
+
+ /// Get value associated with [key]. Return value will be a JSON encodable
+ /// object.
+ static dynamic get(String key) {
+ var value = _storage[key];
+ if (value == null) {
+ return null;
+ }
+ return JSON.decode(value);
+ }
+}
+
+/// A group of settings each prefixed with group name and a dot.
+class SettingsRepository {
+ /// Group name
+ final String group;
+
+ SettingsRepository(this.group);
+
+ String _fullKey(String key) => '$group.$key';
+
+ void set(String key, dynamic value) {
+ var fullKey = _fullKey(key);
+ _Settings.set(fullKey, value);
+ }
+
+ dynamic get(String key) {
+ var fullKey = _fullKey(key);
+ return _Settings.get(fullKey);
+ }
+}
diff --git a/runtime/observatory/lib/src/repositories/target.dart b/runtime/observatory/lib/src/repositories/target.dart
new file mode 100644
index 0000000..69ba8c8
--- /dev/null
+++ b/runtime/observatory/lib/src/repositories/target.dart
@@ -0,0 +1,102 @@
+// Copyright (c) 2016, 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
+
+part of repositories;
+
+class TargetChangeEvent implements M.TargetChangeEvent {
+ final TargetRepository repository;
+ TargetChangeEvent(this.repository);
+}
+
+class TargetRepository implements M.TargetRepository {
+
+ static const _historyKey = 'history';
+
+ final StreamController<TargetChangeEvent> _onChange;
+ final Stream<TargetChangeEvent> onChange;
+ final SettingsRepository _settings = new SettingsRepository('targetManager');
+
+ final List<SC.WebSocketVMTarget> _list = <SC.WebSocketVMTarget>[];
+ SC.WebSocketVMTarget current;
+
+ factory TargetRepository() {
+ var controller = new StreamController<TargetChangeEvent>();
+ var stream = controller.stream.asBroadcastStream();
+ return new TargetRepository._(controller, stream);
+ }
+
+ TargetRepository._(this._onChange, this.onChange) {
+ _restore();
+ if (_list.isEmpty) {
+ _list.add(new SC.WebSocketVMTarget(_networkAddressOfDefaultTarget()));
+ }
+ current = _list.first;
+ }
+
+ void add(String address) {
+ if (_find(address) != null) return;
+ _list.insert(0, new SC.WebSocketVMTarget(address));
+ _onChange.add(new TargetChangeEvent(this));
+ _store();
+ }
+
+ Iterable<SC.WebSocketVMTarget> list() => _list;
+
+ void setCurrent(M.Target t) {
+ SC.WebSocketVMTarget target = t as SC.WebSocketVMTarget;
+ if (!_list.contains(target)) return;
+ current = target;
+ _onChange.add(new TargetChangeEvent(this));
+ }
+
+ void delete(o) {
+ if (_list.remove(o)) {
+ if (o == current) {
+ current = null;
+ }
+ _onChange.add(new TargetChangeEvent(this));
+ _store();
+ }
+ }
+
+ /// Read settings from data store.
+ void _restore() {
+ _list.clear();
+ var loaded = _settings.get(_historyKey);
+ if (loaded == null) {
+ return;
+ }
+ _list.addAll(loaded.map((i) => new SC.WebSocketVMTarget.fromMap(i)));
+ _list.sort((SC.WebSocketVMTarget a, SC.WebSocketVMTarget b) {
+ return b.lastConnectionTime.compareTo(a.lastConnectionTime);
+ });
+ }
+
+ /// After making a change, update settings.
+ void _store() {
+ _settings.set(_historyKey, _list);
+ }
+
+ /// Find by networkAddress.
+ SC.WebSocketVMTarget _find(String networkAddress) {
+ for (SC.WebSocketVMTarget item in _list) {
+ if (item.networkAddress == networkAddress) {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ static String _networkAddressOfDefaultTarget() {
+ if (Utils.runningInJavaScript()) {
+ // We are running as JavaScript, use the same host that Observatory has
+ // been loaded from.
+ return 'ws://${window.location.host}/ws';
+ } else {
+ // Otherwise, assume we are running from Dart Editor and want to connect
+ // to the default host.
+ return 'ws://localhost:8181/ws';
+ }
+ }
+}
diff --git a/runtime/observatory/observatory_sources.gypi b/runtime/observatory/observatory_sources.gypi
index 30659e0..43099f1 100644
--- a/runtime/observatory/observatory_sources.gypi
+++ b/runtime/observatory/observatory_sources.gypi
@@ -25,7 +25,6 @@
'lib/src/app/notification.dart',
'lib/src/app/page.dart',
'lib/src/app/settings.dart',
- 'lib/src/app/target_manager.dart',
'lib/src/app/view_model.dart',
'lib/src/cli/command.dart',
'lib/src/cpu_profile/cpu_profile.dart',
@@ -170,9 +169,7 @@
'lib/src/elements/timeline_page.html',
'lib/src/elements/view_footer.dart',
'lib/src/elements/vm_connect_target.dart',
- 'lib/src/elements/vm_connect_target_wrapper.dart',
'lib/src/elements/vm_connect.dart',
- 'lib/src/elements/vm_connect.html',
'lib/src/elements/vm_view.dart',
'lib/src/elements/vm_view.html',
'lib/src/mocks/exceptions/connection_exception.dart',
@@ -186,7 +183,9 @@
'lib/src/mocks/objects/source_location.dart',
'lib/src/mocks/objects/target.dart',
'lib/src/mocks/objects/vm.dart',
+ 'lib/src/mocks/repositories/crash_dump.dart',
'lib/src/mocks/repositories/notification.dart',
+ 'lib/src/mocks/repositories/target.dart',
'lib/src/models/exceptions.dart',
'lib/src/models/objects/breakpoint.dart',
'lib/src/models/objects/class.dart',
@@ -204,8 +203,12 @@
'lib/src/models/objects/target.dart',
'lib/src/models/objects/timeline_event.dart',
'lib/src/models/objects/vm.dart',
+ 'lib/src/models/repositories/crash_dump.dart',
'lib/src/models/repositories/notification.dart',
+ 'lib/src/models/repositories/target.dart',
'lib/src/repositories/notification.dart',
+ 'lib/src/repositories/settings.dart',
+ 'lib/src/repositories/target.dart',
'lib/src/service/object.dart',
'lib/tracer.dart',
'lib/utils.dart',
diff --git a/runtime/observatory/tests/observatory_ui/vm_connect/element_test.dart b/runtime/observatory/tests/observatory_ui/vm_connect/element_test.dart
new file mode 100644
index 0000000..15a853ca
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/vm_connect/element_test.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2016, 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:html';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/mocks.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/nav/notify.dart';
+import 'package:observatory/src/elements/vm_connect_target.dart';
+import 'package:observatory/src/elements/vm_connect.dart';
+
+main() {
+ VMConnectElement.tag.ensureRegistration();
+
+ final String nTag = NavNotifyElement.tag.name;
+ final String tTag = VMConnectTargetElement.tag.name;
+
+ group('instantiation', () {
+ test('default', () {
+ final VMConnectElement e = new VMConnectElement(
+ new TargetRepositoryMock(),
+ new CrashDumpRepositoryMock(),
+ new NotificationRepositoryMock());
+ expect(e, isNotNull, reason: 'element correctly created');
+ });
+ });
+ test('is correctly listening', () async {
+ final targets = new TargetRepositoryMock();
+ final VMConnectElement e = new VMConnectElement(targets,
+ new CrashDumpRepositoryMock(), new NotificationRepositoryMock());
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(targets.hasListeners, isTrue, reason: 'is listening');
+ e.remove();
+ await e.onRendered.first;
+ expect(targets.hasListeners, isFalse, reason: 'is no more listening');
+ });
+ group('elements', () {
+ test('created after attachment', () async {
+ final targets = new TargetRepositoryMock(list: const [
+ const TargetMock(name: 't-1'), const TargetMock(name: 't-2'),
+ ]);
+ final VMConnectElement e = new VMConnectElement(targets,
+ new CrashDumpRepositoryMock(), new NotificationRepositoryMock());
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(targets.listInvoked, isTrue, reason: 'should invoke list()');
+ expect(targets.currentInvoked, isTrue, reason: 'should invoke current');
+ expect(e.children.length, isNonZero, reason: 'has elements');
+ expect(e.querySelectorAll(nTag).length, equals(1));
+ expect(e.querySelectorAll(tTag).length, equals(2));
+ e.remove();
+ await e.onRendered.first;
+ expect(e.children.length, isZero, reason: 'is empty');
+ });
+ test('react to update event', () async {
+ final list = <M.Target>[const TargetMock(name: 't-1')];
+ final targets = new TargetRepositoryMock(list: list);
+ final VMConnectElement e = new VMConnectElement(targets,
+ new CrashDumpRepositoryMock(), new NotificationRepositoryMock());
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.querySelectorAll(tTag).length, equals(1));
+ list.add(const TargetMock(name: 't-2'));
+ targets.triggerChangeEvent();
+ await e.onRendered.first;
+ expect(e.querySelectorAll(tTag).length, equals(2));
+ e.remove();
+ await e.onRendered.first;
+ expect(e.children.length, isZero, reason: 'is empty');
+ });
+ });
+ group('invokes', () {
+ test('add on click', () async {
+ final address = 'ws://host:1234';
+ final list = <M.Target>[const TargetMock(name: 't-1')];
+ final targets = new TargetRepositoryMock(list: list,
+ add: expectAsync((String val) {
+ expect(val, equals(address));
+ }, count: 1, reason: 'should be invoked'));
+ final VMConnectElement e = new VMConnectElement(targets,
+ new CrashDumpRepositoryMock(), new NotificationRepositoryMock(),
+ address: address);
+ document.body.append(e);
+ await e.onRendered.first;
+ (e.querySelector('button.vm_connect') as ButtonElement).click();
+ e.remove();
+ await e.onRendered.first;
+ });
+ test('connect', () async {
+ final list = <M.Target>[const TargetMock(name: 't-1')];
+ final targets = new TargetRepositoryMock(list: list,
+ setCurrent: expectAsync((M.Target t) {
+ expect(t, equals(list[0]));
+ }, count: 1, reason: 'should be invoked'));
+ final VMConnectElement e = new VMConnectElement(targets,
+ new CrashDumpRepositoryMock(), new NotificationRepositoryMock());
+ document.body.append(e);
+ await e.onRendered.first;
+ (e.querySelector(tTag) as VMConnectTargetElement).connect();
+ e.remove();
+ await e.onRendered.first;
+ });
+ test('delete', () async {
+ final list = <M.Target>[const TargetMock(name: 't-1')];
+ final targets = new TargetRepositoryMock(list: list,
+ delete: expectAsync((M.Target t) {
+ expect(t, equals(list[0]));
+ }, count: 1, reason: 'should be invoked'));
+ final VMConnectElement e = new VMConnectElement(targets,
+ new CrashDumpRepositoryMock(), new NotificationRepositoryMock());
+ document.body.append(e);
+ await e.onRendered.first;
+ (e.querySelector(tTag) as VMConnectTargetElement).delete();
+ e.remove();
+ await e.onRendered.first;
+ });
+ });
+}
diff --git a/runtime/observatory/tests/observatory_ui/vm_connect/element_test.html b/runtime/observatory/tests/observatory_ui/vm_connect/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/vm_connect/element_test.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="dart.unittest" content="full-stack-traces">
+ <style>
+ .unittest-table { font-family:monospace; border:1px; }
+ .unittest-pass { background: #6b3;}
+ .unittest-fail { background: #d55;}
+ .unittest-error { background: #a11;}
+ </style>
+ <script src="/packages/web_components/webcomponents.js"></script>
+ <script src="/packages/web_components/dart_support.js"></script>
+</head>
+<body>
+ <script type="text/javascript"
+ src="/root_dart/tools/testing/dart/test_controller.js"></script>
+ %TEST_SCRIPTS%
+</body>
+</html>
diff --git a/runtime/observatory/tests/service/breakpoint_two_args_checked_test.dart b/runtime/observatory/tests/service/breakpoint_two_args_checked_test.dart
new file mode 100644
index 0000000..610af92
--- /dev/null
+++ b/runtime/observatory/tests/service/breakpoint_two_args_checked_test.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--error_on_bad_type --error_on_bad_override --verbose_debug
+
+// This test is mostly interesting for DBC, which needs to patch two bytecodes
+// to create a breakpoint for fast Smi ops.
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:developer';
+
+const int LINE_A = 26;
+const int LINE_B = 27;
+const int LINE_C = 28;
+
+class NotGeneric { }
+
+testeeMain() {
+ var x = new List(1);
+ var y = 7;
+ debugger();
+ print("Statement");
+ x[0] = 3; // Line A.
+ x is NotGeneric; // Line B.
+ y & 4; // Line C.
+}
+
+var tests = [
+
+hasStoppedAtBreakpoint,
+
+// Add breakpoints.
+(Isolate isolate) async {
+ var rootLib = await isolate.rootLibrary.load();
+ var script = rootLib.scripts[0];
+
+ var bpt1 = await isolate.addBreakpoint(script, LINE_A);
+ print(bpt1);
+ expect(bpt1.resolved, isTrue);
+ expect(await bpt1.location.getLine(), equals(LINE_A));
+
+ var bpt2 = await isolate.addBreakpoint(script, LINE_B);
+ print(bpt2);
+ expect(bpt2.resolved, isTrue);
+ expect(await bpt2.location.getLine(), equals(LINE_B));
+
+ var bpt3 = await isolate.addBreakpoint(script, LINE_C);
+ print(bpt3);
+ expect(bpt3.resolved, isTrue);
+ expect(await bpt3.location.getLine(), equals(LINE_C));
+},
+
+resumeIsolate,
+
+hasStoppedAtBreakpoint,
+stoppedAtLine(LINE_A),
+resumeIsolate,
+
+hasStoppedAtBreakpoint,
+stoppedAtLine(LINE_B),
+resumeIsolate,
+
+hasStoppedAtBreakpoint,
+stoppedAtLine(LINE_C),
+resumeIsolate,
+
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testeeMain);
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index 6318dfa..1233d18 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -14,7 +14,7 @@
isolate_lifecycle_test: Pass, RuntimeError # Issue 24174
# Disable on simulators.
-[ $arch == simarm || $arch == simmips || $arch == simarm64]
+[ $arch == simarm || $arch == simmips || $arch == simarm64 ]
*: SkipSlow
# All tests use dart:io
@@ -51,9 +51,12 @@
evaluate_activation_in_method_class_test: CompileTimeError # Issue 24478
[ $arch == simdbc || $arch == simdbc64 ]
-# TODO(vegorov) re-enable when debugger, coverage and profiling is completely
-# fixed for SIMDBC.
-*: Skip
+get_allocation_samples_test: RuntimeError # Profiling unimplemented.
+get_cpu_profile_timeline_rpc_test: RuntimeError # Profiling unimplemented.
+implicit_getter_setter_test: RuntimeError # Field guards unimplemented.
+get_stack_rpc_test: RuntimeError # Missing single stepping check at fast Smi op
+vm_restart_test: RuntimeError # Missing single stepping check at fast Smi op
+debugging_test: RuntimeError # Missing single stepping check at fast Smi op
[ $hot_reload ]
# Skip all service tests because random reloads interfere.
diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart
index df140c5..15b1de4 100644
--- a/runtime/observatory/tests/service/test_helper.dart
+++ b/runtime/observatory/tests/service/test_helper.dart
@@ -191,8 +191,11 @@
}
Future<Process> _spawnCommon(String executable, List<String> arguments) {
- print('** Launching $executable ${arguments.join(' ')}');
- return Process.start(executable, arguments, environment: _TESTEE_SPAWN_ENV);
+ var environment = _TESTEE_SPAWN_ENV;
+ var bashEnvironment = new StringBuffer();
+ environment.forEach((k, v) => bashEnvironment.write("$k=$v "));
+ print('** Launching $bashEnvironment$executable ${arguments.join(' ')}');
+ return Process.start(executable, arguments, environment: environment);
}
Future<int> launch(bool pause_on_start,
@@ -327,7 +330,9 @@
pause_on_unhandled_exceptions,
trace_service, trace_compiler).then((port) async {
if (mainArgs.contains("--gdb")) {
- port = 8181;
+ var pid = process.process.pid;
+ var wait = new Duration(seconds: 10);
+ print("Testee has pid $pid, waiting $wait before continuing");
}
serviceWebsocketAddress = 'ws://localhost:$port/ws';
serviceHttpAddress = 'http://localhost:$port';
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 7053458..f91c0bc 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -139,22 +139,6 @@
cc/Profiler_TypedArrayAllocation: Skip
cc/Profiler_GetSourceReport: Skip
-# TODO(vegorov) These tests are crashing because ICData objects can't be found
-cc/SourceReport_CallSites_PolymorphicCall: Skip
-cc/SourceReport_CallSites_SimpleCall: Skip
-cc/SourceReport_Coverage_AllFunctions: Skip
-cc/SourceReport_Coverage_ForceCompile: Skip
-cc/SourceReport_Coverage_AllFunctions_ForceCompile: Skip
-cc/SourceReport_Coverage_NestedFunctions: Skip
-cc/SourceReport_Coverage_SimpleCall: Skip
-cc/SourceReport_Coverage_UnusedClass_NoForceCompile: Skip
-cc/SourceReport_Coverage_UnusedClass_ForceCompile: Skip
-cc/SourceReport_Coverage_UnusedClass_ForceCompileError: Skip
-cc/SourceReport_MultipleReports: Skip
-cc/Coverage_Empty: Skip
-cc/Coverage_FilterFunction: Skip
-cc/Coverage_MainWithClass: Skip
-
# TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp
# is switched on by default because they attempt to call regexp functions
# directly instead of going through JSSyntaxRegExp_ExecuteMatch.
@@ -170,15 +154,7 @@
cc/GuardFieldFinalVariableLengthListTest: Skip
cc/GuardFieldSimpleTest: Skip
-# TODO(vegorov) Not all bytecodes have appropriate debug breaks.
-cc/Debug_BreakpointStubPatching: Skip
-cc/Debug_ExprClosureBreakpoint: Skip
-cc/Debug_StackTraceDump1: Skip
-cc/Debug_StepInto: Skip
-
-# TODO(vegorov) These parser tests rely on debugger.
-cc/Parser_AllocateVariables_CapturedVar: Skip
-cc/Parser_AllocateVariables_MiddleChain: Skip
+cc/Debug_StepInto: Fail # Missing single stepping check at fast Smi op
# This test is meaningless for DBC as allocation stubs are not used.
cc/RegenerateAllocStubs: Skip
diff --git a/runtime/tools/create_string_literal.py b/runtime/tools/create_string_literal.py
old mode 100644
new mode 100755
index 7b4b2ec..52a9b10
--- a/runtime/tools/create_string_literal.py
+++ b/runtime/tools/create_string_literal.py
@@ -1,3 +1,5 @@
+#!/usr/bin/env python
+#
# Copyright (c) 2011, 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.
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index b22a9d5..bb56889 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -45,17 +45,18 @@
]
}
+
+vm_sources_list = exec_script("../../tools/gypi_to_gn.py",
+ [rebase_path("vm_sources.gypi")],
+ "scope",
+ ["vm_sources.gypi"])
+
+
static_library("libdart_vm") {
configs += ["..:dart_config",
"..:dart_product_config",
"..:dart_precompiled_runtime_config"]
public_configs = [":libdart_vm_config"]
-
- vm_sources_list = exec_script("../../tools/gypi_to_gn.py",
- [rebase_path("vm_sources.gypi")],
- "scope",
- ["vm_sources.gypi"])
-
set_sources_assignment_filter(["*_test.cc", "*_test.h"])
sources = vm_sources_list.sources
include_dirs = [
@@ -70,11 +71,6 @@
"..:dart_precompiled_runtime_config"]
public_configs = [":libdart_vm_config"]
defines = [ "DART_NO_SNAPSHOT" ]
- vm_sources_list = exec_script("../../tools/gypi_to_gn.py",
- [rebase_path("vm_sources.gypi")],
- "scope",
- ["vm_sources.gypi"])
-
set_sources_assignment_filter(["*_test.cc", "*_test.h"])
sources = vm_sources_list.sources
include_dirs = [
@@ -89,11 +85,6 @@
"..:dart_precompiler_config"]
public_configs = [":libdart_vm_config"]
defines = [ "DART_NO_SNAPSHOT" ]
- vm_sources_list = exec_script("../../tools/gypi_to_gn.py",
- [rebase_path("vm_sources.gypi")],
- "scope",
- ["vm_sources.gypi"])
-
set_sources_assignment_filter(["*_test.cc", "*_test.h"])
sources = vm_sources_list.sources
include_dirs = [
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 1bc179c..ca099b5 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -1874,10 +1874,7 @@
ASSERT(error.IsNull());
#ifndef PRODUCT
Isolate* isolate = thread->isolate();
- // We cannot aggregate stats if isolate is shutting down.
- if (isolate->HasMutatorThread()) {
- isolate->aggregate_compiler_stats()->Add(*thread->compiler_stats());
- }
+ isolate->aggregate_compiler_stats()->Add(*thread->compiler_stats());
thread->compiler_stats()->Clear();
#endif // PRODUCT
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
index e84ae57..564e963 100644
--- a/runtime/vm/constants_dbc.h
+++ b/runtime/vm/constants_dbc.h
@@ -754,6 +754,23 @@
}
}
+ DART_FORCE_INLINE static bool IsFastSmiOpcode(Instr instr) {
+ switch (DecodeOpcode(instr)) {
+ case Bytecode::kAddTOS:
+ case Bytecode::kSubTOS:
+ case Bytecode::kMulTOS:
+ case Bytecode::kBitOrTOS:
+ case Bytecode::kBitAndTOS:
+ case Bytecode::kEqualTOS:
+ case Bytecode::kLessThanTOS:
+ case Bytecode::kGreaterThanTOS:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
DART_FORCE_INLINE static uint8_t DecodeArgc(Instr call) {
ASSERT(IsCallOpcode(call));
return (call >> 8) & 0xFF;
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 34a8d33..66894b5 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1344,11 +1344,10 @@
CHECK_NO_ISOLATE(Isolate::Current());
// TODO(16615): Validate isolate parameter.
Isolate* iso = reinterpret_cast<Isolate*>(isolate);
- if (iso->HasMutatorThread()) {
- FATAL("Multiple mutators within one isolate is not supported.");
- }
if (!Thread::EnterIsolate(iso)) {
- FATAL("Unable to Enter Isolate as Dart VM is shutting down");
+ FATAL("Unable to Enter Isolate : "
+ "Multiple mutators entering an isolate / "
+ "Dart VM is shutting down");
}
// A Thread structure has been associated to the thread, we do the
// safepoint transition explicity here instead of using the
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index a52cf4a..6b50583 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -1108,7 +1108,8 @@
#if !defined(TARGET_ARCH_DBC)
saved_value_(Code::null())
#else
- saved_value_(Bytecode::kTrap)
+ saved_value_(Bytecode::kTrap),
+ saved_value_fastsmi_(Bytecode::kTrap)
#endif
{
ASSERT(!code.IsNull());
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index 1d7e1ce..e78e839 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -235,6 +235,7 @@
// DebugBreak. This is an instruction that was replaced. DebugBreak
// will execute it after the breakpoint.
Instr saved_value_;
+ Instr saved_value_fastsmi_;
#endif
friend class Debugger;
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index 957bd6f..18fb194 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -54,12 +54,17 @@
CURRENT_FUNC, #param); \
}
+#define CHECK_DEBUGGER(isolate) \
+ if (isolate->debugger() == NULL) { \
+ return Api::NewError("%s requires debugger support.", CURRENT_FUNC); \
+ }
+
DART_EXPORT intptr_t Dart_CacheObject(Dart_Handle object_in) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object_in));
- if (obj.IsApiError()) {
+ if (obj.IsApiError() || (I->debugger() == NULL)) {
return -1;
}
return I->debugger()->CacheObject(obj);
@@ -69,6 +74,7 @@
DART_EXPORT Dart_Handle Dart_GetCachedObject(intptr_t obj_id) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
if (!I->debugger()->IsValidObjectId(obj_id)) {
return Api::NewError("%s: object id %" Pd " is invalid",
CURRENT_FUNC, obj_id);
@@ -208,6 +214,7 @@
Dart_ExceptionPauseInfo pause_info) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
I->debugger()->SetExceptionPauseInfo(pause_info);
return Api::Success();
}
@@ -216,6 +223,9 @@
DART_EXPORT Dart_ExceptionPauseInfo Dart_GetExceptionPauseInfo() {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ if (I->debugger() == NULL) {
+ return kNoPauseOnExceptions;
+ }
return I->debugger()->GetExceptionPauseInfo();
}
@@ -223,6 +233,7 @@
DART_EXPORT Dart_Handle Dart_GetStackTrace(Dart_StackTrace* trace) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
CHECK_NOT_NULL(trace);
*trace = reinterpret_cast<Dart_StackTrace>(
I->debugger()->CurrentStackTrace());
@@ -233,6 +244,7 @@
DART_EXPORT Dart_Handle Dart_GetStackTraceFromError(Dart_Handle handle,
Dart_StackTrace* trace) {
DARTSCOPE(Thread::Current());
+ CHECK_DEBUGGER(T->isolate());
CHECK_NOT_NULL(trace);
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
if (obj.IsUnhandledException()) {
@@ -341,6 +353,7 @@
intptr_t line_number) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
Debugger* debugger = I->debugger();
@@ -357,6 +370,7 @@
DART_EXPORT Dart_Handle Dart_GetBreakpointURL(intptr_t bp_id) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
Debugger* debugger = I->debugger();
Breakpoint* bpt = debugger->GetBreakpointById(bp_id);
@@ -371,6 +385,7 @@
DART_EXPORT Dart_Handle Dart_GetBreakpointLine(intptr_t bp_id) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
Debugger* debugger = I->debugger();
Breakpoint* bpt = debugger->GetBreakpointById(bp_id);
@@ -392,6 +407,7 @@
Dart_Handle function_name_in) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
UNWRAP_AND_CHECK_PARAM(Library, library, library_in);
UNWRAP_AND_CHECK_PARAM(String, class_name, class_name_in);
UNWRAP_AND_CHECK_PARAM(String, function_name, function_name_in);
@@ -432,6 +448,7 @@
Dart_Handle function_name_in) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
UNWRAP_AND_CHECK_PARAM(Library, library, library_in);
UNWRAP_AND_CHECK_PARAM(String, class_name, class_name_in);
UNWRAP_AND_CHECK_PARAM(String, function_name, function_name_in);
@@ -468,6 +485,7 @@
DART_EXPORT Dart_Handle Dart_RemoveBreakpoint(intptr_t bp_id) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
I->debugger()->RemoveBreakpoint(bp_id);
return Api::Success();
}
@@ -476,6 +494,7 @@
DART_EXPORT Dart_Handle Dart_SetStepOver() {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
I->debugger()->SetStepOver();
return Api::Success();
}
@@ -484,6 +503,7 @@
DART_EXPORT Dart_Handle Dart_SetStepInto() {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
I->debugger()->SetSingleStep();
return Api::Success();
}
@@ -492,6 +512,7 @@
DART_EXPORT Dart_Handle Dart_SetStepOut() {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
I->debugger()->SetStepOut();
return Api::Success();
}
@@ -500,6 +521,7 @@
DART_EXPORT Dart_Handle Dart_GetInstanceFields(Dart_Handle object_in) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
UNWRAP_AND_CHECK_PARAM(Instance, obj, object_in);
return Api::NewHandle(T, I->debugger()->GetInstanceFields(obj));
}
@@ -508,6 +530,7 @@
DART_EXPORT Dart_Handle Dart_GetStaticFields(Dart_Handle target) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
const Type& type_obj = Api::UnwrapTypeHandle(Z, target);
if (type_obj.IsNull()) {
return Api::NewError("%s expects argument 'target' to be a type",
@@ -521,6 +544,7 @@
DART_EXPORT Dart_Handle Dart_GetLibraryFields(intptr_t library_id) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
const Library& lib =
Library::Handle(Z, Library::GetLibrary(library_id));
if (lib.IsNull()) {
@@ -534,6 +558,7 @@
DART_EXPORT Dart_Handle Dart_GetGlobalVariables(intptr_t library_id) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
const Library& lib = Library::Handle(Z, Library::GetLibrary(library_id));
if (lib.IsNull()) {
@@ -548,6 +573,7 @@
Dart_ActivationFrame activation_frame,
Dart_Handle expr_in) {
DARTSCOPE(Thread::Current());
+ CHECK_DEBUGGER(T->isolate());
CHECK_AND_CAST(ActivationFrame, frame, activation_frame);
UNWRAP_AND_CHECK_PARAM(String, expr, expr_in);
return Api::NewHandle(T, frame->Evaluate(expr));
@@ -557,6 +583,7 @@
DART_EXPORT Dart_Handle Dart_EvaluateExpr(Dart_Handle target_in,
Dart_Handle expr_in) {
DARTSCOPE(Thread::Current());
+ CHECK_DEBUGGER(T->isolate());
const Object& target = Object::Handle(Z, Api::UnwrapHandle(target_in));
if (target.IsError()) return target_in;
@@ -718,6 +745,7 @@
Dart_Handle* static_fields) {
DARTSCOPE(Thread::Current());
Isolate* I = T->isolate();
+ CHECK_DEBUGGER(I);
if (!I->class_table()->IsValidIndex(cls_id)) {
return Api::NewError("%s: %" Pd " is not a valid class id",
CURRENT_FUNC, cls_id);
@@ -967,6 +995,9 @@
DART_EXPORT Dart_IsolateId Dart_GetIsolateId(Dart_Isolate dart_isolate) {
Isolate* isolate = reinterpret_cast<Isolate*>(dart_isolate);
+ if (isolate->debugger() == NULL) {
+ return ILLEGAL_ISOLATE_ID;
+ }
return isolate->debugger()->GetIsolateId();
}
diff --git a/runtime/vm/debugger_dbc.cc b/runtime/vm/debugger_dbc.cc
index 5f82cd5..b4b6c1f 100644
--- a/runtime/vm/debugger_dbc.cc
+++ b/runtime/vm/debugger_dbc.cc
@@ -25,6 +25,11 @@
}
+static Instr* FastSmiInstructionFromReturnAddress(uword pc) {
+ return reinterpret_cast<Instr*>(pc) - 2;
+}
+
+
void CodeBreakpoint::PatchCode() {
ASSERT(!is_enabled_);
const Code& code = Code::Handle(code_);
@@ -54,6 +59,17 @@
default:
UNREACHABLE();
}
+
+ // If this call is the fall-through for a fast Smi op, also disable the fast
+ // Smi op.
+ if ((Bytecode::DecodeOpcode(saved_value_) == Bytecode::kInstanceCall2) &&
+ Bytecode::IsFastSmiOpcode(*FastSmiInstructionFromReturnAddress(pc_))) {
+ saved_value_fastsmi_ = *FastSmiInstructionFromReturnAddress(pc_);
+ *FastSmiInstructionFromReturnAddress(pc_) =
+ Bytecode::Encode(Bytecode::kNop, 0, 0, 0);
+ } else {
+ saved_value_fastsmi_ = Bytecode::kTrap;
+ }
}
is_enabled_ = true;
}
@@ -75,6 +91,12 @@
default:
UNREACHABLE();
}
+
+ if (saved_value_fastsmi_ != Bytecode::kTrap) {
+ Instr current_instr = *FastSmiInstructionFromReturnAddress(pc_);
+ ASSERT(Bytecode::DecodeOpcode(current_instr) == Bytecode::kNop);
+ *FastSmiInstructionFromReturnAddress(pc_) = saved_value_fastsmi_;
+ }
}
is_enabled_ = false;
}
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index ae38a71..e658740 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -7,6 +7,7 @@
#include "vm/assembler.h"
#include "vm/code_patcher.h"
#include "vm/compiler.h"
+#include "vm/disassembler.h"
#include "vm/intermediate_language.h"
#include "vm/locations.h"
#include "vm/parser.h"
@@ -52,6 +53,13 @@
deoptimizing_code_(deoptimizing_code) {
const TypedData& deopt_info = TypedData::Handle(
code.GetDeoptInfoAtPc(frame->pc(), &deopt_reason_, &deopt_flags_));
+#if defined(DEBUG)
+ if (deopt_info.IsNull()) {
+ OS::PrintErr("Missing deopt info for pc %" Px "\n", frame->pc());
+ DisassembleToStdout formatter;
+ code.Disassemble(&formatter);
+ }
+#endif
ASSERT(!deopt_info.IsNull());
deopt_info_ = deopt_info.raw();
diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc
index 0dda8e1..f1be32d 100644
--- a/runtime/vm/intermediate_language_dbc.cc
+++ b/runtime/vm/intermediate_language_dbc.cc
@@ -273,10 +273,10 @@
0, Location::NoLocation(),
LocationSummary::kCall) {
__ CheckStack();
- compiler->RecordSafepoint(locs());
- compiler->AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall,
- Thread::kNoDeoptId,
+ compiler->AddCurrentDescriptor(RawPcDescriptors::kOther,
+ deopt_id(),
token_pos());
+ compiler->RecordAfterCall(this);
}
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 697aef8..15091b5 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -989,6 +989,12 @@
}
+Thread* Isolate::mutator_thread() const {
+ ASSERT(thread_registry() != NULL);
+ return thread_registry()->mutator_thread();
+}
+
+
void Isolate::SetupInstructionsSnapshotPage(
const uint8_t* instructions_snapshot_buffer) {
InstructionsSnapshot snapshot(instructions_snapshot_buffer);
@@ -2585,6 +2591,11 @@
// no_safepoint_scope_depth increments/decrements.
MonitorLocker ml(threads_lock(), false);
+ // Check to make sure we don't already have a mutator thread.
+ if (is_mutator && mutator_thread_ != NULL) {
+ return NULL;
+ }
+
// If a safepoint operation is in progress wait for it
// to finish before scheduling this thread in.
while (!bypass_safepoint && safepoint_handler()->SafepointInProgress()) {
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index b49d59b..9761071 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -177,15 +177,7 @@
message_notify_callback_ = value;
}
- // Limited public access to BaseIsolate::mutator_thread_ for code that
- // must treat the mutator as the default or a special case. Prefer code
- // that works uniformly across all threads.
- bool HasMutatorThread() {
- return mutator_thread_ != NULL;
- }
- Thread* mutator_thread() const {
- return mutator_thread_;
- }
+ Thread* mutator_thread() const;
const char* name() const { return name_; }
const char* debugger_name() const { return debugger_name_; }
@@ -466,8 +458,7 @@
// Mutator thread is used to aggregate compiler stats.
CompilerStats* aggregate_compiler_stats() {
- ASSERT(HasMutatorThread());
- return mutator_thread_->compiler_stats();
+ return mutator_thread()->compiler_stats();
}
VMTagCounters* vm_tag_counters() {
@@ -693,8 +684,8 @@
// DEPRECATED: Use Thread's methods instead. During migration, these default
// to using the mutator thread (which must also be the current thread).
Zone* current_zone() const {
- ASSERT(Thread::Current() == mutator_thread_);
- return mutator_thread_->zone();
+ ASSERT(Thread::Current() == mutator_thread());
+ return mutator_thread()->zone();
}
// Accessed from generated code:
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 158f655..b23dd3b 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -162,6 +162,20 @@
}
+void InstanceMorpher::AppendTo(JSONArray* array) {
+ JSONObject jsobj(array);
+ jsobj.AddProperty("type", "Morpher");
+ jsobj.AddProperty("class", to_);
+ jsobj.AddProperty("instances", before()->length());
+ JSONArray map(&jsobj, "mapping");
+ for (int i = 0; i < mapping_.length(); i += 2) {
+ JSONArray pair(&map);
+ pair.AddValue(mapping_.At(i));
+ pair.AddValue(mapping_.At(i+1));
+ }
+}
+
+
void ReasonForCancelling::Report(IsolateReloadContext* context) {
const Error& error = Error::Handle(ToError());
context->ReportError(error);
@@ -181,6 +195,22 @@
}
+void ReasonForCancelling::AppendTo(JSONArray* array) {
+ JSONObject jsobj(array);
+ jsobj.AddProperty("type", "ReasonForCancelling");
+ const String& message = String::Handle(ToString());
+ jsobj.AddProperty("message", message);
+}
+
+
+void ClassReasonForCancelling::AppendTo(JSONArray* array) {
+ JSONObject jsobj(array);
+ jsobj.AddProperty("type", "ReasonForCancelling");
+ jsobj.AddProperty("class", from_);
+ const String& message = String::Handle(ToString());
+ jsobj.AddProperty("message", message);
+}
+
RawError* IsolateReloadContext::error() const {
ASSERT(has_error());
// Report the first error to the surroundings.
@@ -190,6 +220,7 @@
return error.raw();
}
+
class ScriptUrlSetTraits {
public:
static bool ReportStats() { return false; }
@@ -490,6 +521,31 @@
}
BackgroundCompiler::Enable();
+
+ if (FLAG_trace_reload) {
+ JSONStream stream;
+ ReportOnJSON(&stream);
+ OS::Print("\nJSON report:\n %s\n", stream.ToCString());
+ }
+}
+
+
+void IsolateReloadContext::ReportOnJSON(JSONStream* stream) {
+ JSONObject jsobj(stream);
+ jsobj.AddProperty("type", "Reload");
+ jsobj.AddProperty("succeeded", !HasReasonsForCancelling());
+ if (HasReasonsForCancelling()) {
+ JSONArray array(&jsobj, "reasons");
+ for (intptr_t i = 0; i < reasons_to_cancel_reload_.length(); i++) {
+ ReasonForCancelling* reason = reasons_to_cancel_reload_.At(i);
+ reason->AppendTo(&array);
+ }
+ } else {
+ JSONArray array(&jsobj, "changes");
+ for (intptr_t i = 0; i < instance_morphers_.length(); i++) {
+ instance_morphers_.At(i)->AppendTo(&array);
+ }
+ }
}
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index ce316f6..0a3b591 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -63,6 +63,9 @@
// Dump the state of the morpher.
void Dump() const;
+ // Append the morper info to JSON array.
+ void AppendTo(JSONArray* array);
+
// Returns the list of objects that need to be morphed.
ZoneGrowableArray<const Instance*>* before() const { return before_; }
// Returns the list of morphed objects (matches order in before()).
@@ -100,6 +103,9 @@
// Default implementation calls ToError.
virtual RawString* ToString();
+ // Append the reason to JSON array.
+ virtual void AppendTo(JSONArray* array);
+
// Concrete subclasses must override either ToError or ToString.
};
@@ -110,6 +116,8 @@
ClassReasonForCancelling(const Class& from, const Class& to)
: from_(from), to_(to) { }
+ void AppendTo(JSONArray* array);
+
protected:
const Class& from_;
const Class& to_;
@@ -163,9 +171,12 @@
// Record problem for this reload.
void AddReasonForCancelling(ReasonForCancelling* reason);
- // Report all reasons for cancelling reload.
+ // Reports all reasons for cancelling reload.
void ReportReasonsForCancelling();
+ // Reports the deails of a reload operation.
+ void ReportOnJSON(JSONStream* stream);
+
// Store morphing operation.
void AddInstanceMorpher(InstanceMorpher* morpher);
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index d060680..49672f6 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -1003,11 +1003,11 @@
TestCase::SetReloadTestScript(kReloadScript);
- EXPECT_EQ("instance", SimpleInvokeStr(lib, "main"));
+ EXPECT_STREQ("instance", SimpleInvokeStr(lib, "main"));
lib = TestCase::GetReloadErrorOrRootLibrary();
EXPECT_VALID(lib);
- EXPECT_EQ("instance", SimpleInvokeStr(lib, "main"));
+ EXPECT_STREQ("instance", SimpleInvokeStr(lib, "main"));
}
@@ -1043,11 +1043,11 @@
TestCase::SetReloadTestScript(kReloadScript);
- EXPECT_EQ("static", SimpleInvokeStr(lib, "main"));
+ EXPECT_STREQ("static", SimpleInvokeStr(lib, "main"));
lib = TestCase::GetReloadErrorOrRootLibrary();
EXPECT_VALID(lib);
- EXPECT_EQ("static", SimpleInvokeStr(lib, "main"));
+ EXPECT_STREQ("static", SimpleInvokeStr(lib, "main"));
}
@@ -1093,11 +1093,11 @@
TestCase::SetReloadTestScript(kReloadScript);
- EXPECT_EQ("okay", SimpleInvokeStr(lib, "main"));
+ EXPECT_STREQ("okay", SimpleInvokeStr(lib, "main"));
lib = TestCase::GetReloadErrorOrRootLibrary();
EXPECT_VALID(lib);
- EXPECT_EQ("okay", SimpleInvokeStr(lib, "main"));
+ EXPECT_STREQ("okay", SimpleInvokeStr(lib, "main"));
}
@@ -1143,11 +1143,11 @@
TestCase::SetReloadTestScript(kReloadScript);
- EXPECT_EQ("exception", SimpleInvokeStr(lib, "main"));
+ EXPECT_STREQ("exception", SimpleInvokeStr(lib, "main"));
lib = TestCase::GetReloadErrorOrRootLibrary();
EXPECT_VALID(lib);
- EXPECT_EQ("exception", SimpleInvokeStr(lib, "main"));
+ EXPECT_STREQ("exception", SimpleInvokeStr(lib, "main"));
}
@@ -1190,11 +1190,11 @@
TestCase::SetReloadTestScript(kReloadScript);
- EXPECT_EQ("exception", SimpleInvokeStr(lib, "main"));
+ EXPECT_STREQ("exception", SimpleInvokeStr(lib, "main"));
lib = TestCase::GetReloadErrorOrRootLibrary();
EXPECT_VALID(lib);
- EXPECT_EQ("exception", SimpleInvokeStr(lib, "main"));
+ EXPECT_STREQ("exception", SimpleInvokeStr(lib, "main"));
}
@@ -1237,11 +1237,11 @@
TestCase::SetReloadTestScript(kReloadScript);
- EXPECT_EQ("static", SimpleInvokeStr(lib, "main"));
+ EXPECT_STREQ("static", SimpleInvokeStr(lib, "main"));
lib = TestCase::GetReloadErrorOrRootLibrary();
EXPECT_VALID(lib);
- EXPECT_EQ("static", SimpleInvokeStr(lib, "main"));
+ EXPECT_STREQ("static", SimpleInvokeStr(lib, "main"));
}
@@ -1289,6 +1289,109 @@
}
+TEST_CASE(IsolateReload_TearOff_Equality) {
+ const char* kScript =
+ "import 'test:isolate_reload_helper';\n"
+ "class C {\n"
+ " foo() => 'old';\n"
+ "}\n"
+ "main() {\n"
+ " var c = new C();\n"
+ " var f1 = c.foo;\n"
+ " reloadTest();\n"
+ " var f2 = c.foo;\n"
+ " return '${f1()} ${f2()} ${f1 == f2} ${identical(f1, f2)}';\n"
+ "}\n";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+
+ const char* kReloadScript =
+ "import 'test:isolate_reload_helper';\n"
+ "class C {\n"
+ " foo() => 'new';\n"
+ "}\n"
+ "main() {\n"
+ " var c = new C();\n"
+ " var f1 = c.foo;\n"
+ " reloadTest();\n"
+ " var f2 = c.foo;\n"
+ " return '${f1()} ${f2()} ${f1 == f2} ${identical(f1, f2)}';\n"
+ "}\n";
+
+ TestCase::SetReloadTestScript(kReloadScript);
+
+ EXPECT_STREQ("new new true false", SimpleInvokeStr(lib, "main"));
+
+ lib = TestCase::GetReloadErrorOrRootLibrary();
+ EXPECT_VALID(lib);
+}
+
+
+TEST_CASE(IsolateReload_TearOff_List_Set) {
+ const char* kScript =
+ "import 'test:isolate_reload_helper';\n"
+ "class C {\n"
+ " foo() => 'old';\n"
+ "}\n"
+ "List list = new List(2);\n"
+ "Set set = new Set();\n"
+ "main() {\n"
+ " var c = new C();\n"
+ " list[0] = c.foo;\n"
+ " list[1] = c#foo;\n"
+ " set.add(c.foo);\n"
+ " set.add(c#foo);\n"
+ " int countBefore = set.length;\n"
+ " reloadTest();\n"
+ " list[1] = c.foo;\n"
+ " set.add(c.foo);\n"
+ " set.add(c#foo);\n"
+ " int countAfter = set.length;\n"
+ " return '${list[0]()} ${list[1]()} ${list[0] == list[1]} '\n"
+ " '${countBefore == 1} ${countAfter == 1} ${(set.first)()} '\n"
+ " '${set.first == c.foo} ${set.first == c#foo} '\n"
+ " '${set.remove(c#foo)}';\n"
+ "}\n";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+
+ const char* kReloadScript =
+ "import 'test:isolate_reload_helper';\n"
+ "class C {\n"
+ " foo() => 'new';\n"
+ "}\n"
+ "List list = new List(2);\n"
+ "Set set = new Set();\n"
+ "main() {\n"
+ " var c = new C();\n"
+ " list[0] = c.foo;\n"
+ " list[1] = c#foo;\n"
+ " set.add(c.foo);\n"
+ " set.add(c#foo);\n"
+ " int countBefore = set.length;\n"
+ " reloadTest();\n"
+ " list[1] = c.foo;\n"
+ " set.add(c.foo);\n"
+ " set.add(c#foo);\n"
+ " int countAfter = set.length;\n"
+ " return '${list[0]()} ${list[1]()} ${list[0] == list[1]} '\n"
+ " '${countBefore == 1} ${countAfter == 1} ${(set.first)()} '\n"
+ " '${set.first == c.foo} ${set.first == c#foo} '\n"
+ " '${set.remove(c#foo)}';\n"
+ "}\n";
+
+ TestCase::SetReloadTestScript(kReloadScript);
+
+ EXPECT_STREQ("new new true true true new true true true",
+ SimpleInvokeStr(lib, "main"));
+
+ lib = TestCase::GetReloadErrorOrRootLibrary();
+ EXPECT_VALID(lib);
+}
+
+
TEST_CASE(IsolateReload_EnumEquality) {
const char* kScript =
"enum Fruit {\n"
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 577cb91..c646dd6 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -412,6 +412,16 @@
return String::NewFormatted(
"Limitation: type parameters have changed for %s", from_.ToCString());
}
+
+ void AppendTo(JSONArray* array) {
+ JSONObject jsobj(array);
+ jsobj.AddProperty("type", "ReasonForCancellingReload");
+ jsobj.AddProperty("kind", "TypeParametersChanged");
+ jsobj.AddProperty("class", to_);
+ jsobj.AddProperty("message",
+ "Limitation: changing type parameters "
+ "does not work with hot reload.");
+ }
};
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 9e7dcbd..1b7cec3 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -1547,12 +1547,25 @@
&Symbols::ClosureParameter(),
&Object::dynamic_type());
- const Function& parent = Function::ZoneHandle(func.parent_function());
- if (parent.IsImplicitSetterFunction()) {
+ const Function& parent = Function::Handle(func.parent_function());
+ const String& target_name = String::Handle(parent.name());
+ const Class& owner = Class::Handle(parent.Owner());
+ Function& target = Function::ZoneHandle(owner.LookupFunction(target_name));
+ if (target.raw() != parent.raw()) {
+ ASSERT(Isolate::Current()->HasAttemptedReload());
+ if (target.IsNull() ||
+ (target.is_static() != parent.is_static()) ||
+ (target.kind() != parent.kind())) {
+ // TODO(26977): call noSuchMethod/throw NSME instead.
+ target = parent.raw();
+ }
+ }
+
+ if (target.IsImplicitSetterFunction()) {
const TokenPosition ident_pos = func.token_pos();
ASSERT(IsIdentifier());
const String& field_name = *CurrentLiteral();
- const Class& field_class = Class::ZoneHandle(Z, parent.Owner());
+ const Class& field_class = Class::ZoneHandle(Z, target.Owner());
const Field& field =
Field::ZoneHandle(Z, field_class.LookupInstanceField(field_name));
const AbstractType& field_type = AbstractType::ZoneHandle(Z, field.type());
@@ -1560,7 +1573,7 @@
&Symbols::Value(),
&field_type);
ASSERT(func.num_fixed_parameters() == 2); // closure, value.
- } else if (!parent.IsGetterFunction() && !parent.IsImplicitGetterFunction()) {
+ } else if (!target.IsGetterFunction() && !target.IsImplicitGetterFunction()) {
const bool allow_explicit_default_values = true;
SkipFunctionPreamble();
ParseFormalParameterList(allow_explicit_default_values, false, ¶ms);
@@ -1591,7 +1604,7 @@
}
func_args->set_names(arg_names);
}
- StaticCallNode* call = new StaticCallNode(token_pos, parent, func_args);
+ StaticCallNode* call = new StaticCallNode(token_pos, target, func_args);
ReturnNode* return_node = new ReturnNode(token_pos, call);
current_block_->statements->Add(return_node);
return CloseBlock();
@@ -9293,7 +9306,16 @@
LocalVariable* rethrow_stack_trace_var) {
TRACE_PARSER("EnsureFinallyClause");
ASSERT(parse || (is_async && (try_stack_ != NULL)));
- OpenBlock();
+ // Increasing the loop level prevents the reuse of a parent context and forces
+ // the allocation of a local context to hold captured variables declared
+ // inside the finally clause. Otherwise, a captured variable gets allocated at
+ // different slots in the parent context each time the finally clause is
+ // reparsed, which is done to duplicate the ast. Since only one closure is
+ // kept due to canonicalization, it will access the correct slot in only one
+ // copy of the finally clause and the wrong slot in all others. By allocating
+ // a local context, all copies use the same slot in different local contexts.
+ // See issue #26948. This is a temporary fix until we eliminate reparsing.
+ OpenLoopBlock();
if (parse) {
ExpectToken(Token::kLBRACE);
}
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 394d795..6e3527a 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -53,7 +53,7 @@
bool Profiler::initialized_ = false;
SampleBuffer* Profiler::sample_buffer_ = NULL;
-
+ProfilerCounters Profiler::counters_;
void Profiler::InitOnce() {
// Place some sane restrictions on user controlled flags.
@@ -68,6 +68,8 @@
NativeSymbolResolver::InitOnce();
ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period);
ThreadInterrupter::Startup();
+ // Zero counters.
+ memset(&counters_, 0, sizeof(counters_));
initialized_ = true;
}
@@ -769,7 +771,9 @@
ProfilerDartStackWalker* dart_stack_walker,
uword pc,
uword fp,
- uword sp) {
+ uword sp,
+ ProfilerCounters* counters) {
+ ASSERT(counters != NULL);
#if defined(TARGET_OS_WINDOWS)
// Use structured exception handling to trap guard page access on Windows.
__try {
@@ -783,14 +787,18 @@
if (FLAG_profile_vm) {
// Always walk the native stack collecting both native and Dart frames.
+ counters->stack_walker_native++;
native_stack_walker->walk();
} else if (StubCode::HasBeenInitialized() && exited_dart_code) {
+ counters->stack_walker_dart_exit++;
// We have a valid exit frame info, use the Dart stack walker.
dart_exit_stack_walker->walk();
} else if (StubCode::HasBeenInitialized() && in_dart_code) {
+ counters->stack_walker_dart++;
// We are executing Dart code. We have frame pointers.
dart_stack_walker->walk();
} else {
+ counters->stack_walker_none++;
sample->SetAt(0, pc);
}
@@ -1119,6 +1127,7 @@
// Thread is not doing VM work.
if (thread->task_kind() == Thread::kUnknownTask) {
+ counters_.bail_out_unknown_task++;
return;
}
@@ -1127,6 +1136,7 @@
// The JumpToExceptionHandler stub manually adjusts the stack pointer,
// frame pointer, and some isolate state before jumping to a catch entry.
// It is not safe to walk the stack when executing this stub.
+ counters_.bail_out_jump_to_exception_handler++;
return;
}
@@ -1157,15 +1167,18 @@
}
if (!CheckIsolate(isolate)) {
+ counters_.bail_out_check_isolate++;
return;
}
if (thread->IsMutatorThread() && isolate->IsDeoptimizing()) {
+ counters_.single_frame_sample_deoptimizing++;
SampleThreadSingleFrame(thread, pc);
return;
}
if (!InitialRegisterCheck(pc, fp, sp)) {
+ counters_.single_frame_sample_register_check++;
SampleThreadSingleFrame(thread, pc);
return;
}
@@ -1177,6 +1190,7 @@
sp,
&stack_lower,
&stack_upper)) {
+ counters_.single_frame_sample_get_and_validate_stack_bounds++;
// Could not get stack boundary.
SampleThreadSingleFrame(thread, pc);
return;
@@ -1234,7 +1248,8 @@
&dart_stack_walker,
pc,
fp,
- sp);
+ sp,
+ &counters_);
}
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index b6b2417..dcea1d4 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -27,6 +27,23 @@
class SampleBuffer;
class ProfileTrieNode;
+struct ProfilerCounters {
+ // Count of bail out reasons:
+ int64_t bail_out_unknown_task;
+ int64_t bail_out_jump_to_exception_handler;
+ int64_t bail_out_check_isolate;
+ // Count of single frame sampling reasons:
+ int64_t single_frame_sample_deoptimizing;
+ int64_t single_frame_sample_register_check;
+ int64_t single_frame_sample_get_and_validate_stack_bounds;
+ // Count of stack walkers used:
+ int64_t stack_walker_native;
+ int64_t stack_walker_dart_exit;
+ int64_t stack_walker_dart;
+ int64_t stack_walker_none;
+};
+
+
class Profiler : public AllStatic {
public:
static void InitOnce();
@@ -54,6 +71,11 @@
static void SampleThread(Thread* thread,
const InterruptedThreadState& state);
+ static ProfilerCounters counters() {
+ // Copies the counter values.
+ return counters_;
+ }
+
private:
// Does not walk the thread's stack.
static void SampleThreadSingleFrame(Thread* thread, uintptr_t pc);
@@ -61,6 +83,8 @@
static SampleBuffer* sample_buffer_;
+ static ProfilerCounters counters_;
+
friend class Thread;
};
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 6b3d839..f17f38f 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -2448,6 +2448,41 @@
obj->AddProperty("timeSpan", MicrosecondsToSeconds(GetTimeSpan()));
obj->AddPropertyTimeMicros("timeOriginMicros", min_time());
obj->AddPropertyTimeMicros("timeExtentMicros", GetTimeSpan());
+
+ ProfilerCounters counters = Profiler::counters();
+ {
+ JSONObject counts(obj, "counters");
+ counts.AddProperty64(
+ "bail_out_unknown_task",
+ counters.bail_out_unknown_task);
+ counts.AddProperty64(
+ "bail_out_jump_to_exception_handler",
+ counters.bail_out_jump_to_exception_handler);
+ counts.AddProperty64(
+ "bail_out_check_isolate",
+ counters.bail_out_check_isolate);
+ counts.AddProperty64(
+ "single_frame_sample_deoptimizing",
+ counters.single_frame_sample_deoptimizing);
+ counts.AddProperty64(
+ "single_frame_sample_register_check",
+ counters.single_frame_sample_register_check);
+ counts.AddProperty64(
+ "single_frame_sample_get_and_validate_stack_bounds",
+ counters.single_frame_sample_get_and_validate_stack_bounds);
+ counts.AddProperty64(
+ "stack_walker_native",
+ counters.stack_walker_native);
+ counts.AddProperty64(
+ "stack_walker_dart_exit",
+ counters.stack_walker_dart_exit);
+ counts.AddProperty64(
+ "stack_walker_dart",
+ counters.stack_walker_dart);
+ counts.AddProperty64(
+ "stack_walker_none",
+ counters.stack_walker_none);
+ }
}
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 416dda5..de12ec7 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -122,6 +122,17 @@
f->ptr()->usage_counter_++;
}
+ DART_FORCE_INLINE static void IncrementICUsageCount(RawObject** entries,
+ intptr_t offset,
+ intptr_t args_tested) {
+ const intptr_t count_offset = ICData::CountIndexFor(args_tested);
+ const intptr_t raw_smi_old =
+ reinterpret_cast<intptr_t>(entries[offset + count_offset]);
+ const intptr_t raw_smi_new = raw_smi_old + Smi::RawValue(1);
+ *reinterpret_cast<intptr_t*>(&entries[offset + count_offset]) =
+ raw_smi_new;
+ }
+
DART_FORCE_INLINE static bool IsStrictEqualWithNumberCheck(RawObject* lhs,
RawObject* rhs) {
if (lhs == rhs) {
@@ -588,7 +599,8 @@
RawObjectPool** pp,
uint32_t** pc,
RawObject*** FP,
- RawObject*** SP) {
+ RawObject*** SP,
+ bool optimized) {
ASSERT(icdata->GetClassId() == kICDataCid);
const intptr_t kCheckedArgs = 1;
@@ -599,7 +611,8 @@
bool found = false;
const intptr_t length = Smi::Value(cache->length_);
- for (intptr_t i = 0;
+ intptr_t i;
+ for (i = 0;
i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
if (cache->data()[i + 0] == receiver_cid) {
top[0] = cache->data()[i + kCheckedArgs];
@@ -608,7 +621,11 @@
}
}
- if (!found) {
+ if (found) {
+ if (!optimized) {
+ SimulatorHelpers::IncrementICUsageCount(cache->data(), i, kCheckedArgs);
+ }
+ } else {
InlineCacheMiss(
kCheckedArgs, thread, icdata, call_base, top, *pc, *FP, *SP);
}
@@ -626,7 +643,8 @@
RawObjectPool** pp,
uint32_t** pc,
RawObject*** FP,
- RawObject*** SP) {
+ RawObject*** SP,
+ bool optimized) {
ASSERT(icdata->GetClassId() == kICDataCid);
const intptr_t kCheckedArgs = 2;
@@ -638,7 +656,8 @@
bool found = false;
const intptr_t length = Smi::Value(cache->length_);
- for (intptr_t i = 0;
+ intptr_t i;
+ for (i = 0;
i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
if ((cache->data()[i + 0] == receiver_cid) &&
(cache->data()[i + 1] == arg0_cid)) {
@@ -648,7 +667,11 @@
}
}
- if (!found) {
+ if (found) {
+ if (!optimized) {
+ SimulatorHelpers::IncrementICUsageCount(cache->data(), i, kCheckedArgs);
+ }
+ } else {
InlineCacheMiss(
kCheckedArgs, thread, icdata, call_base, top, *pc, *FP, *SP);
}
@@ -762,12 +785,8 @@
ASSERT(Bytecode::IsCallOpcode(*pc)); \
const uint16_t kidx = Bytecode::DecodeD(*pc); \
const RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); \
- RawObject** data = icdata->ptr()->ic_data_->ptr()->data(); \
- const intptr_t count_offset = ICData::CountIndexFor(2); \
- const intptr_t raw_smi_old = \
- reinterpret_cast<intptr_t>(data[count_offset]); \
- const intptr_t raw_smi_new = raw_smi_old + Smi::RawValue(1); \
- *reinterpret_cast<intptr_t*>(&data[count_offset]) = raw_smi_new; \
+ RawObject** entries = icdata->ptr()->ic_data_->ptr()->data(); \
+ SimulatorHelpers::IncrementICUsageCount(entries, 0, 2); \
} while (0); \
// Declare bytecode handler for a smi operation (e.g. AddTOS) with the
@@ -1389,8 +1408,9 @@
// Lookup the funciton in the ICData.
RawObject* ic_data_obj = SP[0];
RawICData* ic_data = RAW_CAST(ICData, ic_data_obj);
- RawArray* cache = ic_data->ptr()->ic_data_->ptr();
- SP[0] = cache->data()[ICData::TargetIndexFor(
+ RawObject** data = ic_data->ptr()->ic_data_->ptr()->data();
+ SimulatorHelpers::IncrementICUsageCount(data, 0, 0);
+ SP[0] = data[ICData::TargetIndexFor(
ic_data->ptr()->state_bits_ & 0x3)];
RawObject** call_base = SP - argc;
RawObject** call_top = SP; // *SP contains function
@@ -1431,8 +1451,9 @@
RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx));
SimulatorHelpers::IncrementUsageCounter(
RAW_CAST(Function, icdata->ptr()->owner_));
- InstanceCall1(
- thread, icdata, call_base, call_top, &argdesc, &pp, &pc, &FP, &SP);
+ InstanceCall1(thread, icdata, call_base, call_top,
+ &argdesc, &pp, &pc, &FP, &SP,
+ false /* optimized */);
}
DISPATCH();
@@ -1456,8 +1477,9 @@
RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx));
SimulatorHelpers::IncrementUsageCounter(
RAW_CAST(Function, icdata->ptr()->owner_));
- InstanceCall2(
- thread, icdata, call_base, call_top, &argdesc, &pp, &pc, &FP, &SP);
+ InstanceCall2(thread, icdata, call_base, call_top,
+ &argdesc, &pp, &pc, &FP, &SP,
+ false /* optimized */);
}
DISPATCH();
@@ -1475,8 +1497,9 @@
RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx));
SimulatorHelpers::IncrementUsageCounter(FrameFunction(FP));
- InstanceCall1(
- thread, icdata, call_base, call_top, &argdesc, &pp, &pc, &FP, &SP);
+ InstanceCall1(thread, icdata, call_base, call_top,
+ &argdesc, &pp, &pc, &FP, &SP,
+ true /* optimized */);
}
DISPATCH();
@@ -1494,8 +1517,9 @@
RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx));
SimulatorHelpers::IncrementUsageCounter(FrameFunction(FP));
- InstanceCall2(
- thread, icdata, call_base, call_top, &argdesc, &pp, &pc, &FP, &SP);
+ InstanceCall2(thread, icdata, call_base, call_top,
+ &argdesc, &pp, &pc, &FP, &SP,
+ true /* optimized */);
}
DISPATCH();
diff --git a/runtime/vm/simulator_dbc.h b/runtime/vm/simulator_dbc.h
index 7172bbe..2cbadce 100644
--- a/runtime/vm/simulator_dbc.h
+++ b/runtime/vm/simulator_dbc.h
@@ -127,7 +127,7 @@
RawObject** call_top,
RawObjectPool** pp,
uint32_t** pc,
- RawObject*** B,
+ RawObject*** FP,
RawObject*** SP);
void InlineCacheMiss(int checked_args,
@@ -136,7 +136,7 @@
RawObject** call_base,
RawObject** top,
uint32_t* pc,
- RawObject** B, RawObject** SP);
+ RawObject** FP, RawObject** SP);
void InstanceCall1(Thread* thread,
RawICData* icdata,
@@ -145,7 +145,8 @@
RawArray** argdesc,
RawObjectPool** pp,
uint32_t** pc,
- RawObject*** B, RawObject*** SP);
+ RawObject*** FP, RawObject*** SP,
+ bool optimized);
void InstanceCall2(Thread* thread,
RawICData* icdata,
@@ -154,7 +155,8 @@
RawArray** argdesc,
RawObjectPool** pp,
uint32_t** pc,
- RawObject*** B, RawObject*** SP);
+ RawObject*** FP, RawObject*** SP,
+ bool optimized);
// Longjmp support for exceptions.
SimulatorSetjmpBuffer* last_setjmp_buffer() {
diff --git a/runtime/vm/thread_registry.h b/runtime/vm/thread_registry.h
index adf2a34..dd2c6df 100644
--- a/runtime/vm/thread_registry.h
+++ b/runtime/vm/thread_registry.h
@@ -26,6 +26,7 @@
void VisitObjectPointers(ObjectPointerVisitor* visitor, bool validate_frames);
void PrepareForGC();
+ Thread* mutator_thread() const { return mutator_thread_; }
private:
Thread* active_list() const { return active_list_; }
diff --git a/runtime/vm/virtual_memory_android.cc b/runtime/vm/virtual_memory_android.cc
index f84e2ef..16aa834 100644
--- a/runtime/vm/virtual_memory_android.cc
+++ b/runtime/vm/virtual_memory_android.cc
@@ -83,7 +83,6 @@
bool VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
ASSERT(Thread::Current()->IsMutatorThread() ||
- !Isolate::Current()->HasMutatorThread() ||
Isolate::Current()->mutator_thread()->IsAtSafepoint());
uword start_address = reinterpret_cast<uword>(address);
uword end_address = start_address + size;
diff --git a/runtime/vm/virtual_memory_linux.cc b/runtime/vm/virtual_memory_linux.cc
index 8973345..0228f68 100644
--- a/runtime/vm/virtual_memory_linux.cc
+++ b/runtime/vm/virtual_memory_linux.cc
@@ -82,7 +82,6 @@
bool VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
ASSERT(Thread::Current()->IsMutatorThread() ||
- !Isolate::Current()->HasMutatorThread() ||
Isolate::Current()->mutator_thread()->IsAtSafepoint());
uword start_address = reinterpret_cast<uword>(address);
uword end_address = start_address + size;
diff --git a/runtime/vm/virtual_memory_macos.cc b/runtime/vm/virtual_memory_macos.cc
index 1d23ead..484ad78 100644
--- a/runtime/vm/virtual_memory_macos.cc
+++ b/runtime/vm/virtual_memory_macos.cc
@@ -83,7 +83,6 @@
bool VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
ASSERT(Thread::Current()->IsMutatorThread() ||
- !Isolate::Current()->HasMutatorThread() ||
Isolate::Current()->mutator_thread()->IsAtSafepoint());
uword start_address = reinterpret_cast<uword>(address);
uword end_address = start_address + size;
diff --git a/runtime/vm/virtual_memory_win.cc b/runtime/vm/virtual_memory_win.cc
index 8ea8fa5..2584613 100644
--- a/runtime/vm/virtual_memory_win.cc
+++ b/runtime/vm/virtual_memory_win.cc
@@ -66,7 +66,6 @@
bool VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
ASSERT(Thread::Current()->IsMutatorThread() ||
- !Isolate::Current()->HasMutatorThread() ||
Isolate::Current()->mutator_thread()->IsAtSafepoint());
uword start_address = reinterpret_cast<uword>(address);
uword end_address = start_address + size;
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 79bfaa5..d61835c 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -400,7 +400,7 @@
* To set the value of a header use the `set()` method:
*
* request.headers.set(HttpHeaders.CACHE_CONTROL,
- 'max-age=3600, must-revalidate');
+ * 'max-age=3600, must-revalidate');
*
* To retrieve the value of a header use the `value()` method:
*
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 1af71e5..efbfd7a 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -194,9 +194,6 @@
LibTest/typed_data/Float32x4/operator_division_A01_t02: RuntimeError # Issue #26675
[ $hot_reload ]
-Language/Expressions/Property_Extraction/Ordinary_Member_Closurization/getter_closurization_t08: Pass, Fail # Closure identity
-Language/Expressions/Property_Extraction/Ordinary_Member_Closurization/method_identical_t03: Pass, Fail # Closure identity
-Language/Expressions/Property_Extraction/conditional_t05: Pass, Fail # Closure identity
Language/Expressions/Assignment/prefix_object_t02: Crash # Requires deferred libraries
Language/Expressions/Constants/constant_constructor_t03: Crash # Requires deferred libraries
Language/Expressions/Constants/identifier_denotes_a_constant_t06: Crash # Requires deferred libraries
diff --git a/tests/html/html.status b/tests/html/html.status
index c7afa75..ed15788 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -147,6 +147,7 @@
text_event_test: RuntimeError # Issue 23437
transition_event_test/functional: Skip # Times out. Issue 22167
request_animation_frame_test: Skip # Times out. Issue 22167
+js_util_test/callConstructor: RuntimeError # Issue 26978
[$runtime == ie10 ]
# IE10 Feature support statuses-
@@ -170,6 +171,8 @@
input_element_test/supported_month: Fail
input_element_test/supported_time: Fail
input_element_test/supported_week: Fail
+js_util_test/hasProperty: RuntimeError # Issue 26978
+js_util_test/getProperty: RuntimeError # Issue 26978
media_stream_test/supported_MediaStreamEvent: Fail
media_stream_test/supported_MediaStreamTrackEvent: Fail
media_stream_test/supported_media: Fail
diff --git a/tests/language/language.status b/tests/language/language.status
index 61b35c9..34798b6 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -152,6 +152,7 @@
stacktrace_rethrow_error_test: Pass, RuntimeError
stacktrace_rethrow_nonerror_test: Pass, RuntimeError
stacktrace_test: Pass, RuntimeError
+regress_26948_test: Skip # Crashes, regis investigating
[ $noopt || $compiler == precompiler || $mode == product ]
# Imports dart:mirrors
@@ -237,9 +238,6 @@
library_env_test/has_mirror_support: RuntimeError, OK
[ $arch == simdbc || $arch == simdbc64 ]
-# TODO(vegorov) StopInstr is unimplemented.
-vm/debug_break_enabled_vm_test/none: Skip
-
# TODO(vegorov) Encoding limitation: StoreField bytecode only supports 256
# fields in an object.
large_class_declaration_test: Skip
@@ -249,7 +247,6 @@
issue23244_test: Skip # Issue #26373
[ $hot_reload ]
-bound_closure_equality_test: Pass, Fail # Closure identity
static_closure_identical_test: Pass, Fail # Closure identity
cha_deopt1_test: Crash # Requires deferred libraries
cha_deopt2_test: Crash # Requires deferred libraries
diff --git a/tests/language/regress_26948_test.dart b/tests/language/regress_26948_test.dart
new file mode 100644
index 0000000..7e323f7
--- /dev/null
+++ b/tests/language/regress_26948_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+import 'dart:async';
+import "package:expect/expect.dart";
+
+void check(Function f) {
+ Expect.isTrue(f());
+}
+
+Future doSync() async {
+ try {
+ await 123;
+ } finally {
+ var next = 5.0;
+ check(() => next == 5.0);
+ }
+}
+
+main() async {
+ for (int i = 0; i < 20; i++) {
+ await doSync();
+ }
+}
diff --git a/tools/VERSION b/tools/VERSION
index 8dbdf92..2092cfe 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 1
MINOR 19
PATCH 0
-PRERELEASE 0
+PRERELEASE 1
PRERELEASE_PATCH 0
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 9c2c9a4..19f4e04 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -9,7 +9,7 @@
vars.update({
"dartium_chromium_commit": "67a7ba9669f7bb0300ef35085d4e6bb98b1966cc",
- "dartium_webkit_commit": "6d435325ef16ceb54f23f5ec6414650ce5ef79ef",
+ "dartium_webkit_commit": "241a4a90dd2aa42490243c2efcc8732ff8aa0a59",
"chromium_base_revision": "338390",
# We use mirrors of all github repos to guarantee reproducibility and
diff --git a/tools/gypi_to_gn.py b/tools/gypi_to_gn.py
index 1aa092c..ca62a12 100755
--- a/tools/gypi_to_gn.py
+++ b/tools/gypi_to_gn.py
@@ -129,10 +129,28 @@
# Assume everything else is unchanged.
return values
+def KeepOnly(values, filters):
+ """Recursively filters out strings not ending in "f" from "values"""
+
+ if isinstance(values, list):
+ return [v for v in values if v.endswith(tuple(filters))]
+
+ if isinstance(values, dict):
+ result = {}
+ for key, value in values.items():
+ new_key = KeepOnly(key, filters)
+ new_value = KeepOnly(value, filters)
+ result[new_key] = new_value
+ return result
+
+ return values
+
def main():
parser = OptionParser()
parser.add_option("-r", "--replace", action="append",
help="Replaces substrings. If passed a=b, replaces all substrs a with b.")
+ parser.add_option("-k", "--keep_only", default = [], action="append",
+ help="Keeps only files ending with the listed strings.")
(options, args) = parser.parse_args()
if len(args) != 1:
@@ -149,6 +167,9 @@
assert len(split) == 2, "Replacement must be of the form 'key=value'."
data = ReplaceSubstrings(data, split[0], split[1])
+ if options.keep_only != []:
+ data = KeepOnly(data, options.keep_only)
+
# Sometimes .gypi files use the GYP syntax with percents at the end of the
# variable name (to indicate not to overwrite a previously-defined value):
# 'foo%': 'bar',