Version 1.19.0-dev.5.0
Merge 9d2ab4d0163ba031580e9315e02f84d7a1b0612b into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 64a30df..35da026 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,20 @@
## 1.19.0
+### Language changes
+
+* The language now allows a trailing comma after the last argument of a call and
+ the last parameter of a function declaration. This can make long argument or
+ parameter lists easier to maintain, as commas can be left as-is when
+ reordering lines. For details, see SDK issue
+ [26644](https://github.com/dart-lang/sdk/issues/26644).
+
### Core library changes
* `dart:io`
* `Socket.connect` with source-address argument is now non-blocking
on Mac. Was already non-blocking on all other platforms.
* Report a better error when a bind fails because of a bad source address.
+ * Handle HTTP header `charset` parameter with empty value.
### Strong Mode
@@ -58,8 +67,9 @@
### Dart VM
* The dependency on BoringSSL has been rolled forward. Going forward, builds
- of the Dart VM including secure sockets will require a compiler with C11
- support, and to link against glib 2.16 or newer.
+ of the Dart VM including secure sockets will require a compiler with C++11
+ support, and to link against glibc 2.16 or newer. For details, see the
+ [Building wiki page](https://github.com/dart-lang/sdk/wiki/Building).
### Tool Changes
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index f72e512..3b41a24 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -40,6 +40,7 @@
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
+import 'package:analyzer/src/summary/pub_summary.dart';
import 'package:analyzer/src/task/dart.dart';
import 'package:analyzer/src/util/glob.dart';
import 'package:analyzer/task/dart.dart';
@@ -299,6 +300,11 @@
ResolverProvider fileResolverProvider;
/**
+ * The manager of pub package summaries.
+ */
+ PubSummaryManager pubSummaryManager;
+
+ /**
* Initialize a newly created server to receive requests from and send
* responses to the given [channel].
*
@@ -363,6 +369,8 @@
});
});
_setupIndexInvalidation();
+ pubSummaryManager =
+ new PubSummaryManager(resourceProvider, '${io.pid}.temp');
Notification notification =
new ServerConnectedParams(VERSION, io.pid).toNotification();
channel.sendNotification(notification);
@@ -1594,6 +1602,10 @@
context.sourceFactory =
_createSourceFactory(context, options, disposition, folder);
context.analysisOptions = options;
+
+ // TODO(scheglov) use linked bundles
+// analysisServer.pubSummaryManager.getLinkedBundles(context);
+
analysisServer._onContextsChangedController
.add(new ContextsChangedEvent(added: [context]));
analysisServer.schedulePerformAnalysisOperation(context);
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index 138c20f..864f04f 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -17,6 +17,7 @@
import 'package:analyzer/src/dart/ast/utilities.dart' as engine;
import 'package:analyzer/src/generated/engine.dart' as engine;
import 'package:analyzer/src/generated/error.dart' as engine;
+import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/source.dart' as engine;
import 'package:analyzer/src/generated/utilities_dart.dart' as engine;
@@ -254,15 +255,15 @@
engine.SourceRange range) {
int startLine = 0;
int startColumn = 0;
- {
- engine.LineInfo lineInfo = context.getLineInfo(source);
+ try {
+ engine.LineInfo lineInfo = context.computeLineInfo(source);
if (lineInfo != null) {
engine.LineInfo_Location offsetLocation =
lineInfo.getLocation(range.offset);
startLine = offsetLocation.lineNumber;
startColumn = offsetLocation.columnNumber;
}
- }
+ } on AnalysisException {}
return new Location(
source.fullName, range.offset, range.length, startLine, startColumn);
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index e582d37..f05284d 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -286,7 +286,7 @@
}
_resolvedImports = <ImportElement>[];
for (ImportElement importElem in libElem.imports) {
- if (importElem.importedLibrary.exportNamespace == null) {
+ if (importElem.importedLibrary?.exportNamespace == null) {
await _computeAsync(this, importElem.importedLibrary.source,
LIBRARY_ELEMENT4, performance, 'resolve imported library');
checkAborted();
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 4daa06e..27f33c8 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -624,13 +624,16 @@
} else {
for (ImportElement import in unitLibraryElement.imports) {
if (prefixElement is PrefixElement && import.prefix == prefixElement) {
- targetUnit = import.importedLibrary.definingCompilationUnit;
- Source targetSource = targetUnit.source;
- int offset = targetSource.contents.data.length;
- sb = new SourceBuilder(targetSource.fullName, offset);
- prefix = '$eol';
- suffix = '$eol';
- break;
+ LibraryElement library = import.importedLibrary;
+ if (library != null) {
+ targetUnit = library.definingCompilationUnit;
+ Source targetSource = targetUnit.source;
+ int offset = targetSource.contents.data.length;
+ sb = new SourceBuilder(targetSource.fullName, offset);
+ prefix = '$eol';
+ suffix = '$eol';
+ break;
+ }
}
}
if (sb == null) {
@@ -1283,6 +1286,7 @@
}
isFirst = false;
}
+
// merge getter/setter pairs into fields
String prefix = utils.getIndent(1);
for (int i = 0; i < elements.length; i++) {
diff --git a/pkg/analysis_server/lib/src/services/correction/namespace.dart b/pkg/analysis_server/lib/src/services/correction/namespace.dart
index 0aa0b8d..87c38dd 100644
--- a/pkg/analysis_server/lib/src/services/correction/namespace.dart
+++ b/pkg/analysis_server/lib/src/services/correction/namespace.dart
@@ -37,13 +37,14 @@
}
/**
- * Returns the [ImportElement] that is referenced by [prefixNode] with
- * an [PrefixElement], maybe `null`.
+ * Return the [ImportElement] that is referenced by [prefixNode], or `null` if
+ * the node does not reference a prefix or if we cannot determine which import
+ * is being referenced.
*/
ImportElement getImportElement(SimpleIdentifier prefixNode) {
- if (prefixNode.parent is ImportDirective) {
- ImportDirective importDirective = prefixNode.parent;
- return importDirective.element;
+ AstNode parent = prefixNode.parent;
+ if (parent is ImportDirective) {
+ return parent.element;
}
ImportElementInfo info = internal_getImportElementInfo(prefixNode);
return info?.element;
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index b829bee..57fcdea 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1156,6 +1156,11 @@
* directive.
*/
LibraryElement get exportedLibrary;
+
+ /**
+ * Return `true` if the file referenced by the import's URI exists.
+ */
+ bool get uriExists;
}
/**
@@ -1341,6 +1346,11 @@
* prefix, or otherwise does not have an offset.
*/
int get prefixOffset;
+
+ /**
+ * Return `true` if the file referenced by the import's URI exists.
+ */
+ bool get uriExists;
}
/**
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index 6eaaedb..668d4fc 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -154,6 +154,7 @@
ImportElementImpl importElement = new ImportElementImpl(-1);
importElement.importedLibrary = importLibraryMap[coreLibrarySource];
importElement.synthetic = true;
+ importElement.uriExists = true;
imports.add(importElement);
}
//
@@ -170,38 +171,38 @@
node.element = null;
Source exportedSource = node.source;
int exportedTime = sourceModificationTimeMap[exportedSource] ?? -1;
- if (exportedTime != -1) {
- // The exported source will be null if the URI in the export
- // directive was invalid.
- LibraryElement exportedLibrary = exportLibraryMap[exportedSource];
- if (exportedLibrary != null) {
- ExportElementImpl exportElement = new ExportElementImpl(node.offset);
- exportElement.metadata = _getElementAnnotations(node.metadata);
- StringLiteral uriLiteral = node.uri;
+ // The exported source will be null if the URI in the export
+ // directive was invalid.
+ LibraryElement exportedLibrary = exportLibraryMap[exportedSource];
+ if (exportedLibrary != null) {
+ ExportElementImpl exportElement = new ExportElementImpl(node.offset);
+ exportElement.metadata = _getElementAnnotations(node.metadata);
+ StringLiteral uriLiteral = node.uri;
+ if (uriLiteral != null) {
+ exportElement.uriOffset = uriLiteral.offset;
+ exportElement.uriEnd = uriLiteral.end;
+ }
+ exportElement.uri = node.uriContent;
+ exportElement.uriExists = exportedTime >= 0;
+ exportElement.combinators = _buildCombinators(node);
+ exportElement.exportedLibrary = exportedLibrary;
+ setElementDocumentationComment(exportElement, node);
+ node.element = exportElement;
+ exports.add(exportElement);
+ if (exportedTime >= 0 &&
+ exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) {
+ int offset = node.offset;
+ int length = node.length;
if (uriLiteral != null) {
- exportElement.uriOffset = uriLiteral.offset;
- exportElement.uriEnd = uriLiteral.end;
+ offset = uriLiteral.offset;
+ length = uriLiteral.length;
}
- exportElement.uri = node.uriContent;
- exportElement.combinators = _buildCombinators(node);
- exportElement.exportedLibrary = exportedLibrary;
- setElementDocumentationComment(exportElement, node);
- node.element = exportElement;
- exports.add(exportElement);
- if (exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) {
- int offset = node.offset;
- int length = node.length;
- if (uriLiteral != null) {
- offset = uriLiteral.offset;
- length = uriLiteral.length;
- }
- errors.add(new AnalysisError(
- libraryElement.source,
- offset,
- length,
- CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
- [uriLiteral.toSource()]));
- }
+ errors.add(new AnalysisError(
+ libraryElement.source,
+ offset,
+ length,
+ CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
+ [uriLiteral.toSource()]));
}
}
return null;
@@ -213,53 +214,53 @@
node.element = null;
Source importedSource = node.source;
int importedTime = sourceModificationTimeMap[importedSource] ?? -1;
- if (importedTime != -1) {
- // The imported source will be null if the URI in the import
- // directive was invalid.
- LibraryElement importedLibrary = importLibraryMap[importedSource];
- if (importedLibrary != null) {
- if (importedLibrary.isDartCore) {
- explicitlyImportsCore = true;
+ // The imported source will be null if the URI in the import
+ // directive was invalid.
+ LibraryElement importedLibrary = importLibraryMap[importedSource];
+ if (importedLibrary != null) {
+ if (importedLibrary.isDartCore) {
+ explicitlyImportsCore = true;
+ }
+ ImportElementImpl importElement = new ImportElementImpl(node.offset);
+ importElement.metadata = _getElementAnnotations(node.metadata);
+ StringLiteral uriLiteral = node.uri;
+ if (uriLiteral != null) {
+ importElement.uriOffset = uriLiteral.offset;
+ importElement.uriEnd = uriLiteral.end;
+ }
+ importElement.uri = node.uriContent;
+ importElement.uriExists = importedTime >= 0;
+ importElement.deferred = node.deferredKeyword != null;
+ importElement.combinators = _buildCombinators(node);
+ importElement.importedLibrary = importedLibrary;
+ setElementDocumentationComment(importElement, node);
+ SimpleIdentifier prefixNode = node.prefix;
+ if (prefixNode != null) {
+ importElement.prefixOffset = prefixNode.offset;
+ String prefixName = prefixNode.name;
+ PrefixElementImpl prefix = nameToPrefixMap[prefixName];
+ if (prefix == null) {
+ prefix = new PrefixElementImpl.forNode(prefixNode);
+ nameToPrefixMap[prefixName] = prefix;
}
- ImportElementImpl importElement = new ImportElementImpl(node.offset);
- importElement.metadata = _getElementAnnotations(node.metadata);
- StringLiteral uriLiteral = node.uri;
+ importElement.prefix = prefix;
+ prefixNode.staticElement = prefix;
+ }
+ node.element = importElement;
+ imports.add(importElement);
+ if (importedTime >= 0 &&
+ importSourceKindMap[importedSource] != SourceKind.LIBRARY) {
+ int offset = node.offset;
+ int length = node.length;
if (uriLiteral != null) {
- importElement.uriOffset = uriLiteral.offset;
- importElement.uriEnd = uriLiteral.end;
+ offset = uriLiteral.offset;
+ length = uriLiteral.length;
}
- importElement.uri = node.uriContent;
- importElement.deferred = node.deferredKeyword != null;
- importElement.combinators = _buildCombinators(node);
- importElement.importedLibrary = importedLibrary;
- setElementDocumentationComment(importElement, node);
- SimpleIdentifier prefixNode = node.prefix;
- if (prefixNode != null) {
- importElement.prefixOffset = prefixNode.offset;
- String prefixName = prefixNode.name;
- PrefixElementImpl prefix = nameToPrefixMap[prefixName];
- if (prefix == null) {
- prefix = new PrefixElementImpl.forNode(prefixNode);
- nameToPrefixMap[prefixName] = prefix;
- }
- importElement.prefix = prefix;
- prefixNode.staticElement = prefix;
- }
- node.element = importElement;
- imports.add(importElement);
- if (importSourceKindMap[importedSource] != SourceKind.LIBRARY) {
- int offset = node.offset;
- int length = node.length;
- if (uriLiteral != null) {
- offset = uriLiteral.offset;
- length = uriLiteral.length;
- }
- ErrorCode errorCode = (importElement.isDeferred
- ? StaticWarningCode.IMPORT_OF_NON_LIBRARY
- : CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY);
- errors.add(new AnalysisError(libraryElement.source, offset, length,
- errorCode, [uriLiteral.toSource()]));
- }
+ ErrorCode errorCode = importElement.isDeferred
+ ? StaticWarningCode.IMPORT_OF_NON_LIBRARY
+ : CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY;
+ errors.add(new AnalysisError(libraryElement.source, offset, length,
+ errorCode, [uriLiteral.toSource()]));
}
}
return null;
@@ -975,8 +976,8 @@
} else {
SimpleIdentifier propertyNameNode = node.name;
String propertyName = propertyNameNode.name;
- FieldElementImpl field =
- _currentHolder.getField(propertyName, synthetic: true) as FieldElementImpl;
+ FieldElementImpl field = _currentHolder.getField(propertyName,
+ synthetic: true) as FieldElementImpl;
if (field == null) {
field = new FieldElementImpl(node.name.name, -1);
field.final2 = true;
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 6f1ec8d..0ac63cf 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -4157,6 +4157,23 @@
}
@override
+ bool get uriExists {
+ if (_unlinkedExportNonPublic != null) {
+ return true;
+ }
+ return hasModifier(Modifier.URI_EXISTS);
+ }
+
+ /**
+ * Set whether the file referenced by the import's URI exists to match the
+ * given flag.
+ */
+ void set uriExists(bool exists) {
+ assert(_unlinkedExportNonPublic == null);
+ setModifier(Modifier.URI_EXISTS, exists);
+ }
+
+ @override
int get uriOffset {
if (_unlinkedExportNonPublic != null) {
return _unlinkedExportNonPublic.uriOffset;
@@ -5100,6 +5117,23 @@
}
@override
+ bool get uriExists {
+ if (_unlinkedImport != null) {
+ return true;
+ }
+ return hasModifier(Modifier.URI_EXISTS);
+ }
+
+ /**
+ * Set whether the file referenced by the import's URI exists to match the
+ * given flag.
+ */
+ void set uriExists(bool exists) {
+ assert(_unlinkedImport == null);
+ setModifier(Modifier.URI_EXISTS, exists);
+ }
+
+ @override
int get uriOffset {
if (_unlinkedImport != null) {
if (_unlinkedImport.isImplicit) {
@@ -5668,6 +5702,7 @@
return lib;
}
}
+
void recurse(LibraryElementImpl child) {
if (!indices.containsKey(child)) {
// We haven't visited this child yet, so recurse on the child,
@@ -5682,6 +5717,7 @@
root = min(root, indices[child]);
}
}
+
// Recurse on all of the children in the import/export graph, filtering
// out those for which library cycles have already been computed.
library.exportedLibraries
@@ -5708,6 +5744,7 @@
}
return root;
}
+
scc(library);
return _libraryCycle;
}
@@ -5907,6 +5944,7 @@
library.importedLibraries.forEach(invalidate);
}
}
+
invalidate(this);
}
@@ -6395,6 +6433,12 @@
*/
static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 16);
+ /**
+ * A flag used for import and export elements that indicates whether the URI
+ * in the corresponding directive referenced a file that exists.
+ */
+ static const Modifier URI_EXISTS = const Modifier('URI_EXISTS', 17);
+
static const List<Modifier> values = const [
ABSTRACT,
ASYNCHRONOUS,
@@ -6412,7 +6456,8 @@
REFERENCES_SUPER,
SETTER,
STATIC,
- SYNTHETIC
+ SYNTHETIC,
+ URI_EXISTS
];
const Modifier(String name, int ordinal) : super(name, ordinal);
diff --git a/pkg/analyzer/lib/src/dart/element/handle.dart b/pkg/analyzer/lib/src/dart/element/handle.dart
index 6823b99..dae8fa2 100644
--- a/pkg/analyzer/lib/src/dart/element/handle.dart
+++ b/pkg/analyzer/lib/src/dart/element/handle.dart
@@ -562,6 +562,9 @@
int get uriEnd => actualElement.uriEnd;
@override
+ bool get uriExists => actualElement.uriExists;
+
+ @override
int get uriOffset => actualElement.uriOffset;
}
@@ -707,6 +710,9 @@
int get uriEnd => actualElement.uriEnd;
@override
+ bool get uriExists => actualElement.uriExists;
+
+ @override
int get uriOffset => actualElement.uriOffset;
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
index 0e0229c..476334b 100644
--- a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
@@ -28,6 +28,12 @@
LibraryElement _library;
/**
+ * A flag indicating whether abstract methods should be included when looking
+ * up the superclass chain.
+ */
+ bool _includeAbstractFromSuperclasses;
+
+ /**
* This is a mapping between each [ClassElement] and a map between the [String] member
* names and the associated [ExecutableElement] in the mixin and superclass chain.
*/
@@ -51,8 +57,10 @@
*
* @param library the library element context that the inheritance mappings are being generated
*/
- InheritanceManager(LibraryElement library) {
+ InheritanceManager(LibraryElement library,
+ {bool includeAbstractFromSuperclasses: false}) {
this._library = library;
+ _includeAbstractFromSuperclasses = includeAbstractFromSuperclasses;
_classLookup = new HashMap<ClassElement, Map<String, ExecutableElement>>();
_interfaceLookup =
new HashMap<ClassElement, Map<String, ExecutableElement>>();
@@ -282,7 +290,8 @@
//
// Include the members from the superclass in the resultMap.
//
- _recordMapWithClassMembers(resultMap, supertype, false);
+ _recordMapWithClassMembers(
+ resultMap, supertype, _includeAbstractFromSuperclasses);
} finally {
visitedClasses.remove(superclassElt);
}
@@ -311,7 +320,8 @@
//
// Include the members from the mixin in the resultMap.
//
- _recordMapWithClassMembers(map, mixin, false);
+ _recordMapWithClassMembers(
+ map, mixin, _includeAbstractFromSuperclasses);
//
// Add the members from map into result map.
//
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index 9211f8a..0537269 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -125,7 +125,8 @@
getSource(identifier),
identifier.offset,
identifier.length,
- CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, [name]));
+ CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION,
+ [name]));
return hiddenElement;
}
}
@@ -438,6 +439,51 @@
return foundElement;
}
+ @override
+ bool shouldIgnoreUndefined(Identifier node) {
+ Iterable<NamespaceCombinator> getShowCombinators(
+ ImportElement importElement) =>
+ importElement.combinators.where((NamespaceCombinator combinator) =>
+ combinator is ShowElementCombinator);
+ if (node is PrefixedIdentifier) {
+ String prefix = node.prefix.name;
+ String name = node.identifier.name;
+ List<ImportElement> imports = _definingLibrary.imports;
+ int count = imports.length;
+ for (int i = 0; i < count; i++) {
+ ImportElement importElement = imports[i];
+ if (importElement.prefix?.name == prefix && !importElement.uriExists) {
+ Iterable<NamespaceCombinator> showCombinators =
+ getShowCombinators(importElement);
+ if (showCombinators.isEmpty) {
+ return true;
+ }
+ for (ShowElementCombinator combinator in showCombinators) {
+ if (combinator.shownNames.contains(name)) {
+ return true;
+ }
+ }
+ }
+ }
+ } else if (node is SimpleIdentifier) {
+ String name = node.name;
+ List<ImportElement> imports = _definingLibrary.imports;
+ int count = imports.length;
+ for (int i = 0; i < count; i++) {
+ ImportElement importElement = imports[i];
+ if (importElement.prefix == null && !importElement.uriExists) {
+ for (ShowElementCombinator combinator
+ in getShowCombinators(importElement)) {
+ if (combinator.shownNames.contains(name)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
/**
* Create all of the namespaces associated with the libraries imported into
* this library. The names are not added to this scope, but are stored for
@@ -521,8 +567,7 @@
return foundElement;
}
for (int i = 0; i < _importedNamespaces.length; i++) {
- Namespace nameSpace = _importedNamespaces[i];
- Element element = nameSpace.getPrefixed(prefix, name);
+ Element element = _importedNamespaces[i].getPrefixed(prefix, name);
if (element != null) {
if (foundElement == null) {
foundElement = element;
@@ -1161,6 +1206,20 @@
}
/**
+ * Return `true` if the fact that the given [node] is not defined should be
+ * ignored (from the perspective of error reporting). This will be the case if
+ * there is at least one import that defines the node's prefix, and if that
+ * import either has no show combinators or has a show combinator that
+ * explicitly lists the node's name.
+ */
+ bool shouldIgnoreUndefined(Identifier node) {
+ if (enclosingScope != null) {
+ return enclosingScope.shouldIgnoreUndefined(node);
+ }
+ return false;
+ }
+
+ /**
* Return the name that will be used to look up the given [element].
*/
String _getName(Element element) {
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 029b5c6..87d3fd2 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -711,6 +711,15 @@
// Then check for error conditions.
//
ErrorCode errorCode = _checkForInvocationError(target, true, staticElement);
+ if (errorCode != null &&
+ target is SimpleIdentifier &&
+ target.staticElement is PrefixElement) {
+ Identifier functionName =
+ new PrefixedIdentifierImpl.temp(target, methodName);
+ if (_resolver.nameScope.shouldIgnoreUndefined(functionName)) {
+ return null;
+ }
+ }
bool generatedWithTypePropagation = false;
if (_enableHints && errorCode == null && staticElement == null) {
// The method lookup may have failed because there were multiple
@@ -750,8 +759,10 @@
identical(errorCode,
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT) ||
identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) {
- _resolver.errorReporter
- .reportErrorForNode(errorCode, methodName, [methodName.name]);
+ if (!_resolver.nameScope.shouldIgnoreUndefined(methodName)) {
+ _resolver.errorReporter
+ .reportErrorForNode(errorCode, methodName, [methodName.name]);
+ }
} else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) {
String targetTypeName;
if (target == null) {
@@ -817,6 +828,7 @@
}
return type;
}
+
DartType targetType = getSuperType(_getStaticType(target));
String targetTypeName = targetType?.name;
_resolver.errorReporter.reportErrorForNode(
@@ -894,6 +906,9 @@
"${node.identifier.name}=", node.identifier.offset - 1)));
element = _resolver.nameScope.lookup(setterName, _definingLibrary);
}
+ if (element == null && _resolver.nameScope.shouldIgnoreUndefined(node)) {
+ return null;
+ }
if (element == null) {
if (identifier.inSetterContext()) {
_resolver.errorReporter.reportErrorForNode(
@@ -1112,7 +1127,7 @@
StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT,
node,
[_resolver.enclosingFunction.displayName]);
- } else {
+ } else if (!_resolver.nameScope.shouldIgnoreUndefined(node)) {
_recordUndefinedNode(_resolver.enclosingClass,
StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]);
}
@@ -1177,6 +1192,15 @@
name.staticElement = element;
}
node.staticElement = element;
+ // TODO(brianwilkerson) Defer this check until we know there's an error (by
+ // in-lining _resolveArgumentsToFunction below).
+ ClassDeclaration declaration =
+ node.getAncestor((AstNode node) => node is ClassDeclaration);
+ Identifier superclassName = declaration.extendsClause?.superclass?.name;
+ if (superclassName != null &&
+ _resolver.nameScope.shouldIgnoreUndefined(superclassName)) {
+ return null;
+ }
ArgumentList argumentList = node.argumentList;
List<ParameterElement> parameters = _resolveArgumentsToFunction(
isInConstConstructor, argumentList, element);
@@ -1212,7 +1236,7 @@
* error code that should be reported, or `null` if no error should be
* reported. The [target] is the target of the invocation, or `null` if there
* was no target. The flag [useStaticContext] should be `true` if the
- * invocation is in a static constant (does not have access to instance state.
+ * invocation is in a static constant (does not have access to instance state).
*/
ErrorCode _checkForInvocationError(
Expression target, bool useStaticContext, Element element) {
@@ -1283,6 +1307,10 @@
targetType = _getBestType(target);
}
if (targetType == null) {
+ if (target is Identifier &&
+ _resolver.nameScope.shouldIgnoreUndefined(target)) {
+ return null;
+ }
return StaticTypeWarningCode.UNDEFINED_FUNCTION;
} else if (!targetType.isDynamic && !targetType.isBottom) {
// Proxy-conditional warning, based on state of
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index db9ad7ec..bedfdd8 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -3317,6 +3317,7 @@
}
return type.displayName;
}
+
if (_hasEqualTypeNames(arguments)) {
int count = arguments.length;
for (int i = 0; i < count; i++) {
@@ -5338,6 +5339,26 @@
false);
/**
+ * 17.9 Switch: It is a static warning if all of the following conditions
+ * hold:
+ * * The switch statement does not have a 'default' clause.
+ * * The static type of <i>e</i> is an enumerated typed with elements
+ * <i>id<sub>1</sub></i>, …, <i>id<sub>n</sub></i>.
+ * * The sets {<i>e<sub>1</sub></i>, …, <i>e<sub>k</sub></i>} and
+ * {<i>id<sub>1</sub></i>, …, <i>id<sub>n</sub></i>} are not the
+ * same.
+ *
+ * Parameters:
+ * 0: the name of the constant that is missing
+ */
+ static const StaticWarningCode MISSING_ENUM_CONSTANT_IN_SWITCH =
+ const StaticWarningCode(
+ 'MISSING_ENUM_CONSTANT_IN_SWITCH',
+ "Missing case clause for '{0}'",
+ "Add a case clause for the missing constant or add a default clause.",
+ false);
+
+ /**
* 13.12 Return: It is a static warning if a function contains both one or
* more return statements of the form <i>return;</i> and one or more return
* statements of the form <i>return e;</i>.
@@ -5861,26 +5882,6 @@
"The return type of the getter must not be 'void'", null, false);
/**
- * 17.9 Switch: It is a static warning if all of the following conditions
- * hold:
- * * The switch statement does not have a 'default' clause.
- * * The static type of <i>e</i> is an enumerated typed with elements
- * <i>id<sub>1</sub></i>, …, <i>id<sub>n</sub></i>.
- * * The sets {<i>e<sub>1</sub></i>, …, <i>e<sub>k</sub></i>} and
- * {<i>id<sub>1</sub></i>, …, <i>id<sub>n</sub></i>} are not the
- * same.
- *
- * Parameters:
- * 0: the name of the constant that is missing
- */
- static const StaticWarningCode MISSING_ENUM_CONSTANT_IN_SWITCH =
- const StaticWarningCode(
- 'MISSING_ENUM_CONSTANT_IN_SWITCH',
- "Missing case clause for '{0}'",
- "Add a case clause for the missing constant or add a default clause.",
- false);
-
- /**
* A flag indicating whether this warning is an error when running with strong
* mode enabled.
*/
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 4a70c66..3f9d3d8 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -562,6 +562,7 @@
}
return element.isDeprecated;
}
+
if (!inDeprecatedMember && isDeprecated(element)) {
String displayName = element.displayName;
if (element is ConstructorElement) {
@@ -971,6 +972,7 @@
}
return false;
}
+
FunctionBody body = node.body;
if (body is ExpressionFunctionBody) {
if (isNonObjectNoSuchMethodInvocation(body.expression)) {
@@ -1916,7 +1918,7 @@
@override
Object visitExportDirective(ExportDirective node) {
ExportElement exportElement = node.element;
- if (exportElement != null) {
+ if (exportElement != null && exportElement.uriExists) {
// The element is null when the URI is invalid
LibraryElement library = exportElement.exportedLibrary;
if (library != null) {
@@ -1960,8 +1962,9 @@
@override
Object visitImportDirective(ImportDirective node) {
ImportElement importElement = node.element;
- if (importElement != null) {
- // The element is null when the URI is invalid
+ if (importElement != null && importElement.uriExists) {
+ // The element is null when the URI is invalid, but not when the URI is
+ // valid but refers to a non-existent file.
LibraryElement library = importElement.importedLibrary;
if (library != null) {
for (Combinator combinator in node.combinators) {
@@ -2547,8 +2550,10 @@
String nameOfMethod = methodName.name;
if (property == null) {
String elementName = nameOfMethod == '-' &&
- node.parameters != null &&
- node.parameters.parameters.isEmpty ? 'unary-' : nameOfMethod;
+ node.parameters != null &&
+ node.parameters.parameters.isEmpty
+ ? 'unary-'
+ : nameOfMethod;
_enclosingExecutable = _findWithNameAndOffset(_enclosingClass.methods,
methodName, elementName, methodName.offset);
_expectedElements.remove(_enclosingExecutable);
@@ -3963,6 +3968,7 @@
}
return false;
}
+
AstNode parent = identifier.parent;
if (parent is MethodInvocation && parent.methodName == identifier) {
return recordIfTargetIsPrefixElement(parent.target);
@@ -4211,7 +4217,8 @@
_usedImportedElementsVisitor =
new GatherUsedImportedElementsVisitor(_library);
_enableDart2JSHints = _context.analysisOptions.dart2jsHint;
- _manager = new InheritanceManager(_library);
+ _manager =
+ new InheritanceManager(_library, includeAbstractFromSuperclasses: true);
_usedLocalElementsVisitor = new GatherUsedLocalElementsVisitor(_library);
}
@@ -4439,11 +4446,13 @@
int length = _unusedImports.length;
for (int i = 0; i < length; i++) {
ImportDirective unusedImport = _unusedImports[i];
- // Check that the import isn't dart:core
+ // Check that the imported URI exists and isn't dart:core
ImportElement importElement = unusedImport.element;
if (importElement != null) {
LibraryElement libraryElement = importElement.importedLibrary;
- if (libraryElement != null && libraryElement.isDartCore) {
+ if (libraryElement == null ||
+ libraryElement.isDartCore ||
+ !importElement.uriExists) {
continue;
}
}
@@ -4689,8 +4698,6 @@
* A stack of return types for all of the enclosing
* functions and methods.
*/
- // TODO(leafp) Handle the implicit union type for Futures
- // https://github.com/dart-lang/sdk/issues/25322
final List<DartType> _returnStack = <DartType>[];
InferenceContext._(this._errorReporter, TypeProvider typeProvider,
@@ -4720,7 +4727,7 @@
return;
}
DartType context = _returnStack.last;
- if (context == null || context.isDynamic) {
+ if (context is! FutureUnionType) {
DartType inferred = _inferredReturn.last;
inferred = _typeSystem.getLeastUpperBound(_typeProvider, type, inferred);
_inferredReturn[_inferredReturn.length - 1] = inferred;
@@ -4746,15 +4753,14 @@
* bound of all types added with [addReturnOrYieldType].
*/
void popReturnContext(BlockFunctionBody node) {
- assert(_returnStack.isNotEmpty && _inferredReturn.isNotEmpty);
- if (_returnStack.isNotEmpty) {
- _returnStack.removeLast();
- }
- if (_inferredReturn.isNotEmpty) {
+ if (_returnStack.isNotEmpty && _inferredReturn.isNotEmpty) {
+ DartType context = _returnStack.removeLast() ?? DynamicTypeImpl.instance;
DartType inferred = _inferredReturn.removeLast();
- if (!inferred.isBottom) {
+ if (!inferred.isBottom && _typeSystem.isSubtypeOf(inferred, context)) {
setType(node, inferred);
}
+ } else {
+ assert(false);
}
}
@@ -4762,8 +4768,7 @@
* Push a block function body's return type onto the return stack.
*/
void pushReturnContext(BlockFunctionBody node) {
- DartType returnType = getType(node);
- _returnStack.add(returnType);
+ _returnStack.add(getContext(node));
_inferredReturn.add(BottomTypeImpl.instance);
}
@@ -4905,18 +4910,49 @@
}
/**
+ * Look for a single contextual type attached to [node], and returns the type
+ * if found, otherwise null.
+ *
+ * If [node] has a contextual union type like `T | Future<T>` this will
+ * simplify it to only return `T`. If the caller can handle a union type,
+ * [getContext] should be used instead.
+ */
+ static DartType getType(AstNode node) {
+ DartType t = getContext(node);
+ if (t is FutureUnionType) {
+ return t.type;
+ }
+ return t;
+ }
+
+ /**
* Look for contextual type information attached to [node]. Returns
* the type if found, otherwise null.
+ *
+ * If [node] has a contextual union type like `T | Future<T>` this will be
+ * returned. You can use [getType] if you prefer to only get the `T`.
*/
- static DartType getType(AstNode node) => node?.getProperty(_typeProperty);
+ static DartType getContext(AstNode node) => node?.getProperty(_typeProperty);
+
+ /**
+ * Like [getContext] but expands a union type into a list of types.
+ */
+ static Iterable<DartType> getTypes(AstNode node) {
+ DartType t = getContext(node);
+ if (t == null) {
+ return DartType.EMPTY_LIST;
+ }
+ if (t is FutureUnionType) {
+ return t.types;
+ }
+ return <DartType>[t];
+ }
/**
* Attach contextual type information [type] to [node] for use during
* inference.
*/
static void setType(AstNode node, DartType type) {
- // TODO(jmesserly): this sets the type even when it's dynamic.
- // Can we skip that?
node?.setProperty(_typeProperty, type);
}
@@ -4925,7 +4961,7 @@
* inference.
*/
static void setTypeFromNode(AstNode innerNode, AstNode outerNode) {
- setType(innerNode, getType(outerNode));
+ setType(innerNode, getContext(outerNode));
}
}
@@ -6009,13 +6045,11 @@
@override
Object visitAwaitExpression(AwaitExpression node) {
- // TODO(leafp): Handle the implicit union type here
- // https://github.com/dart-lang/sdk/issues/25322
- DartType contextType = InferenceContext.getType(node);
+ DartType contextType = InferenceContext.getContext(node);
if (contextType != null) {
- InterfaceType futureT = typeProvider.futureType
- .instantiate([contextType.flattenFutures(typeSystem)]);
- InferenceContext.setType(node.expression, futureT);
+ var futureUnion =
+ FutureUnionType.from(contextType, typeProvider, typeSystem);
+ InferenceContext.setType(node.expression, futureUnion);
}
return super.visitAwaitExpression(node);
}
@@ -6069,7 +6103,7 @@
if (operatorType == TokenType.QUESTION_QUESTION) {
// Set the right side, either from the context, or using the information
// from the left side if it is more precise.
- DartType contextType = InferenceContext.getType(node);
+ DartType contextType = InferenceContext.getContext(node);
DartType leftType = leftOperand?.staticType;
if (contextType == null || contextType.isDynamic) {
contextType = leftType;
@@ -6547,8 +6581,24 @@
matchFunctionTypeParameters(node.typeParameters, functionType);
if (functionType is FunctionType) {
_inferFormalParameterList(node.parameters, functionType);
- DartType returnType =
- _computeReturnOrYieldType(functionType.returnType);
+
+ DartType returnType;
+ if (_isFutureThenLambda(node)) {
+ var futureThenType =
+ InferenceContext.getContext(node.parent) as FunctionType;
+
+ // Pretend the return type of Future<T>.then<S> first parameter is
+ //
+ // T -> (S | Future<S>)
+ //
+ // We can't represent this in Dart so we populate it here during
+ // inference.
+ returnType = FutureUnionType.from(
+ futureThenType.returnType, typeProvider, typeSystem);
+ } else {
+ returnType = _computeReturnOrYieldType(functionType.returnType);
+ }
+
InferenceContext.setType(node.body, returnType);
}
}
@@ -6664,30 +6714,37 @@
Object visitInstanceCreationExpression(InstanceCreationExpression node) {
TypeName classTypeName = node.constructorName.type;
if (classTypeName.typeArguments == null) {
- DartType contextType = InferenceContext.getType(node);
- if (contextType is InterfaceType &&
- contextType.typeArguments != null &&
- contextType.typeArguments.length > 0) {
- // TODO(jmesserly): for generic methods we use the
- // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to
- // be a tad more powerful than matchTypes.
- //
- // For example it can infer this case:
- //
- // class E<S, T> extends A<C<S>, T> { ... }
- // A<C<int>, String> a0 = /*infer<int, String>*/new E("hello");
- //
- // See _inferArgumentTypesFromContext in this file for use of it.
- List<DartType> targs =
- inferenceContext.matchTypes(classTypeName.type, contextType);
- if (targs != null && targs.any((t) => !t.isDynamic)) {
- ClassElement classElement = classTypeName.type.element;
- InterfaceType rawType = classElement.type;
- InterfaceType fullType =
- rawType.substitute2(targs, rawType.typeArguments);
- // The element resolver uses the type on the constructor name, so
- // infer it first
- typeAnalyzer.inferConstructorName(node.constructorName, fullType);
+ // Given a union of context types ` T0 | T1 | ... | Tn`, find the first
+ // valid instantiation `new C<Ti>`, if it exists.
+ // TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>`
+ // will become a valid possibility. Right now the only allowed union is
+ // `T | Future<T>` so we can take a simple approach.
+ for (var contextType in InferenceContext.getTypes(node)) {
+ if (contextType is InterfaceType &&
+ contextType.typeArguments != null &&
+ contextType.typeArguments.isNotEmpty) {
+ // TODO(jmesserly): for generic methods we use the
+ // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to
+ // be a tad more powerful than matchTypes.
+ //
+ // For example it can infer this case:
+ //
+ // class E<S, T> extends A<C<S>, T> { ... }
+ // A<C<int>, String> a0 = /*infer<int, String>*/new E("hello");
+ //
+ // See _inferArgumentTypesFromContext in this file for use of it.
+ List<DartType> targs =
+ inferenceContext.matchTypes(classTypeName.type, contextType);
+ if (targs != null && targs.any((t) => !t.isDynamic)) {
+ ClassElement classElement = classTypeName.type.element;
+ InterfaceType rawType = classElement.type;
+ InterfaceType fullType =
+ rawType.substitute2(targs, rawType.typeArguments);
+ // The element resolver uses the type on the constructor name, so
+ // infer it first
+ typeAnalyzer.inferConstructorName(node.constructorName, fullType);
+ break;
+ }
}
}
}
@@ -6801,7 +6858,7 @@
@override
Object visitNamedExpression(NamedExpression node) {
- InferenceContext.setType(node.expression, InferenceContext.getType(node));
+ InferenceContext.setTypeFromNode(node.expression, node);
return super.visitNamedExpression(node);
}
@@ -6815,7 +6872,7 @@
@override
Object visitParenthesizedExpression(ParenthesizedExpression node) {
- InferenceContext.setType(node.expression, InferenceContext.getType(node));
+ InferenceContext.setTypeFromNode(node.expression, node);
return super.visitParenthesizedExpression(node);
}
@@ -6933,7 +6990,7 @@
@override
Object visitVariableDeclaration(VariableDeclaration node) {
- InferenceContext.setType(node.initializer, InferenceContext.getType(node));
+ InferenceContext.setTypeFromNode(node.initializer, node);
super.visitVariableDeclaration(node);
VariableElement element = node.element;
if (element.initializer != null && node.initializer != null) {
@@ -7077,21 +7134,22 @@
if (!isGenerator && !isAsynchronous) {
return declaredType;
}
- if (isGenerator) {
- if (declaredType is! InterfaceType) {
- return null;
+ if (declaredType is InterfaceType) {
+ if (isGenerator) {
+ // If it's sync* we expect Iterable<T>
+ // If it's async* we expect Stream<T>
+ InterfaceType rawType = isAsynchronous
+ ? typeProvider.streamDynamicType
+ : typeProvider.iterableDynamicType;
+ // Match the types to instantiate the type arguments if possible
+ List<DartType> typeArgs =
+ inferenceContext.matchTypes(rawType, declaredType);
+ return (typeArgs?.length == 1) ? typeArgs[0] : null;
}
- // If it's synchronous, we expect Iterable<T>, otherwise Stream<T>
- InterfaceType rawType = isAsynchronous
- ? typeProvider.streamDynamicType
- : typeProvider.iterableDynamicType;
- // Match the types to instantiate the type arguments if possible
- List<DartType> typeArgs =
- inferenceContext.matchTypes(rawType, declaredType);
- return (typeArgs?.length == 1) ? typeArgs[0] : null;
+ // async functions expect `Future<T> | T`
+ return new FutureUnionType(declaredType, typeProvider, typeSystem);
}
- // Must be asynchronous to reach here, so strip off any layers of Future
- return declaredType.flattenFutures(typeSystem);
+ return declaredType;
}
/**
@@ -7183,6 +7241,20 @@
if (typeAnalyzer.inferFormalParameterList(node, type)) {
// TODO(leafp): This gets dropped on the floor if we're in the field
// inference task. We should probably keep these infos.
+ //
+ // TODO(jmesserly): this is reporting the context type, and therefore not
+ // necessarily the correct inferred type for the lambda.
+ //
+ // For example, `([x]) {}` could be passed to `int -> void` but its type
+ // will really be `([int]) -> void`. Similar issue for named arguments.
+ // It can also happen if the return type is inferred later on to be
+ // more precise.
+ //
+ // This reporting bug defeats the deduplication of error messages and
+ // results in the same inference message being reported twice.
+ //
+ // To get this right, we'd have to delay reporting until we have the
+ // complete type including return type.
inferenceContext.recordInference(node.parent, type);
}
}
@@ -7322,6 +7394,19 @@
}
/**
+ * Returns true if this expression is being passed to `Future.then`.
+ *
+ * If so we will apply special typing rules in strong mode, to handle the
+ * implicit union of `S | Future<S>`
+ */
+ bool _isFutureThenLambda(FunctionExpression node) {
+ Element element = node.staticParameterElement?.enclosingElement;
+ return element is MethodElement &&
+ element.name == 'then' &&
+ element.enclosingElement.type.isDartAsyncFuture;
+ }
+
+ /**
* Return `true` if the given variable is accessed within a closure in the given
* [AstNode] and also mutated somewhere in variable scope. This information is only
* available for local variables (including parameters).
@@ -8542,6 +8627,11 @@
node.type = voidType;
return;
}
+ if (nameScope.shouldIgnoreUndefined(typeName)) {
+ typeName.staticType = undefinedType;
+ node.type = undefinedType;
+ return;
+ }
//
// If not, the look to see whether we might have created the wrong AST
// structure for a constructor name. If so, fix the AST structure and then
@@ -8558,6 +8648,11 @@
SimpleIdentifier prefix = prefixedIdentifier.prefix;
element = nameScope.lookup(prefix, definingLibrary);
if (element is PrefixElement) {
+ if (nameScope.shouldIgnoreUndefined(typeName)) {
+ typeName.staticType = undefinedType;
+ node.type = undefinedType;
+ return;
+ }
AstNode grandParent = parent.parent;
if (grandParent is InstanceCreationExpression &&
grandParent.isConst) {
@@ -8592,6 +8687,11 @@
}
}
}
+ if (nameScope.shouldIgnoreUndefined(typeName)) {
+ typeName.staticType = undefinedType;
+ node.type = undefinedType;
+ return;
+ }
}
// check element
bool elementValid = element is! MultiplyDefinedElement;
@@ -10413,7 +10513,7 @@
Identifier name = typeName.name;
if (name.name == Keyword.DYNAMIC.syntax) {
errorReporter.reportErrorForNode(dynamicTypeError, name, [name.name]);
- } else {
+ } else if (!nameScope.shouldIgnoreUndefined(name)) {
errorReporter.reportErrorForNode(nonTypeError, name, [name.name]);
}
return null;
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index bdaf9d9..2d0acf5d 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -184,19 +184,19 @@
* A list containing the offsets of the first character of each line in the
* source code.
*/
- final List<int> _lineStarts;
+ final List<int> lineStarts;
/**
- * The zero-based [_lineStarts] index resulting from the last call to
+ * The zero-based [lineStarts] index resulting from the last call to
* [getLocation].
*/
int _previousLine = 0;
/**
* Initialize a newly created set of line information to represent the data
- * encoded in the given list of [_lineStarts].
+ * encoded in the given list of [lineStarts].
*/
- factory LineInfo(List<int> _lineStarts) => new LineInfoWithCount(_lineStarts);
+ factory LineInfo(List<int> lineStarts) => new LineInfoWithCount(lineStarts);
/**
* Initialize a newly created set of line information corresponding to the
@@ -207,12 +207,12 @@
/**
* Initialize a newly created set of line information to represent the data
- * encoded in the given list of [_lineStarts].
+ * encoded in the given list of [lineStarts].
*/
- LineInfo._(this._lineStarts) {
- if (_lineStarts == null) {
+ LineInfo._(this.lineStarts) {
+ if (lineStarts == null) {
throw new IllegalArgumentException("lineStarts must be non-null");
- } else if (_lineStarts.length < 1) {
+ } else if (lineStarts.length < 1) {
throw new IllegalArgumentException("lineStarts must be non-empty");
}
}
@@ -220,26 +220,26 @@
/**
* The number of lines.
*/
- int get lineCount => _lineStarts.length;
+ int get lineCount => lineStarts.length;
/**
* Return the location information for the character at the given [offset].
*/
LineInfo_Location getLocation(int offset) {
var min = 0;
- var max = _lineStarts.length - 1;
+ var max = lineStarts.length - 1;
// Subsequent calls to [getLocation] are often for offsets near each other.
// To take advantage of that, we cache the index of the line start we found
// when this was last called. If the current offset is on that line or
// later, we'll skip those early indices completely when searching.
- if (offset >= _lineStarts[_previousLine]) {
+ if (offset >= lineStarts[_previousLine]) {
min = _previousLine;
// Before kicking off a full binary search, do a quick check here to see
// if the new offset is on that exact line.
- if (min == _lineStarts.length - 1 || offset < _lineStarts[min + 1]) {
- return new LineInfo_Location(min + 1, offset - _lineStarts[min] + 1);
+ if (min == lineStarts.length - 1 || offset < lineStarts[min + 1]) {
+ return new LineInfo_Location(min + 1, offset - lineStarts[min] + 1);
}
}
@@ -247,7 +247,7 @@
while (min < max) {
var midpoint = (max - min + 1) ~/ 2 + min;
- if (_lineStarts[midpoint] > offset) {
+ if (lineStarts[midpoint] > offset) {
max = midpoint - 1;
} else {
min = midpoint;
@@ -256,7 +256,7 @@
_previousLine = min;
- return new LineInfo_Location(min + 1, offset - _lineStarts[min] + 1);
+ return new LineInfo_Location(min + 1, offset - lineStarts[min] + 1);
}
/**
@@ -268,7 +268,7 @@
throw new ArgumentError(
'Invalid line number: $lineNumber; must be between 0 and ${lineCount - 1}');
}
- return _lineStarts[lineNumber];
+ return lineStarts[lineNumber];
}
}
@@ -310,14 +310,9 @@
class LineInfoWithCount extends LineInfo {
/**
* Initialize a newly created set of line information to represent the data
- * encoded in the given list of [_lineStarts].
+ * encoded in the given list of [lineStarts].
*/
- LineInfoWithCount(List<int> _lineStarts) : super._(_lineStarts);
-
- /**
- * Return the number of lines in the file.
- */
- int get lineCount => _lineStarts.length;
+ LineInfoWithCount(List<int> lineStarts) : super._(lineStarts);
}
/**
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index fa82560..6875c97 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -131,29 +131,15 @@
}
List<ParameterElement> parameters = node.parameterElements;
-
{
- List<DartType> normalParameterTypes = functionType.normalParameterTypes;
- int normalCount = normalParameterTypes.length;
- Iterable<ParameterElement> required = parameters
- .where((p) => p.parameterKind == ParameterKind.REQUIRED)
- .take(normalCount);
- int index = 0;
- for (ParameterElementImpl p in required) {
- inferType(p, normalParameterTypes[index++]);
- }
- }
-
- {
- List<DartType> optionalParameterTypes =
- functionType.optionalParameterTypes;
- int optionalCount = optionalParameterTypes.length;
- Iterable<ParameterElement> optional = parameters
- .where((p) => p.parameterKind == ParameterKind.POSITIONAL)
- .take(optionalCount);
- int index = 0;
- for (ParameterElementImpl p in optional) {
- inferType(p, optionalParameterTypes[index++]);
+ Iterator<ParameterElement> positional = parameters
+ .where((p) => p.parameterKind != ParameterKind.NAMED)
+ .iterator;
+ Iterator<ParameterElement> fnPositional = functionType.parameters
+ .where((p) => p.parameterKind != ParameterKind.NAMED)
+ .iterator;
+ while (positional.moveNext() && fnPositional.moveNext()) {
+ inferType(positional.current, fnPositional.current.type);
}
}
@@ -518,7 +504,13 @@
// * BlockFunctionBody, if we inferred a type from yield/return.
// * we also normalize bottom to dynamic here.
if (_strongMode && (computedType.isBottom || computedType.isDynamic)) {
- computedType = InferenceContext.getType(body) ?? _dynamicType;
+ DartType contextType = InferenceContext.getContext(body);
+ if (contextType is FutureUnionType) {
+ // TODO(jmesserly): can we do something better here?
+ computedType = body.isAsynchronous ? contextType.type : _dynamicType;
+ } else {
+ computedType = contextType ?? _dynamicType;
+ }
recordInference = !computedType.isDynamic;
}
@@ -1697,6 +1689,7 @@
visitedClasses.remove(element);
}
}
+
if (type is InterfaceType) {
_find(type);
}
@@ -1983,8 +1976,17 @@
}
}
- return ts.inferGenericFunctionCall(_typeProvider, fnType, paramTypes,
- argTypes, InferenceContext.getType(node));
+ DartType returnContext = InferenceContext.getContext(node);
+ DartType returnType;
+ if (returnContext is FutureUnionType) {
+ returnType = fnType.returnType.isDartAsyncFuture
+ ? returnContext.futureOfType
+ : returnContext.type;
+ } else {
+ returnType = returnContext as DartType;
+ }
+ return ts.inferGenericFunctionCall(
+ _typeProvider, fnType, paramTypes, argTypes, returnType);
}
return null;
}
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 78d246f..6fcb63b 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -15,7 +15,9 @@
import 'package:analyzer/src/generated/engine.dart'
show AnalysisContext, AnalysisOptionsImpl;
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
+import 'package:analyzer/src/generated/utilities_general.dart'
+ show JenkinsSmiHash;
typedef bool _GuardedSubtypeChecker<T>(T t1, T t2, Set<Element> visited);
@@ -282,23 +284,6 @@
var inferringTypeSystem =
new _StrongInferenceTypeSystem(typeProvider, this, fnType.typeFormals);
- // Special case inference for Future.then.
- //
- // We don't have union types, so Future<T>.then<S> is typed to take a
- // callback `T -> S`. However, the lambda might actually return a
- // Future<S>. So we handle that special case here.
- if (argumentTypes.isNotEmpty && argumentTypes[0] is FunctionType) {
- Element element = fnType?.element;
- bool isFutureThen = element is MethodElement &&
- element.name == 'then' &&
- element.enclosingElement.type.isDartAsyncFuture;
- if (isFutureThen) {
- // Ignore return context. We'll let the onValue function's return type
- // drive inference.
- returnContextType = null;
- }
- }
-
if (returnContextType != null) {
inferringTypeSystem.isSubtypeOf(fnType.returnType, returnContextType);
}
@@ -751,8 +736,8 @@
return true;
}
- // The types are void, dynamic, bottom, interface types, function types
- // and type parameters. We proceed by eliminating these different classes
+ // The types are void, dynamic, bottom, interface types, function types,
+ // and type parameters. We proceed by eliminating these different classes
// from consideration.
// Trivially true.
@@ -1340,6 +1325,28 @@
}
/// Tracks upper and lower type bounds for a set of type parameters.
+///
+/// This class is used by calling [isSubtypeOf]. When it encounters one of
+/// the type parameters it is inferring, it will record the constraint, and
+/// optimistically assume the constraint will be satisfied.
+///
+/// For example if we are inferring type parameter A, and we ask if
+/// `A <: num`, this will record that A must be a subytpe of `num`. It also
+/// handles cases when A appears as part of the structure of another type, for
+/// example `Iterable<A> <: Iterable<num>` would infer the same constraint
+/// (due to covariant generic types) as would `() -> A <: () -> num`. In
+/// contrast `(A) -> void <: (num) -> void`.
+///
+/// Once the lower/upper bounds are determined, [_infer] should be called to
+/// finish the inference. It will instantiate a generic function type with the
+/// inferred types for each type parameter.
+///
+/// It can also optionally compute a partial solution, in case some of the type
+/// parameters could not be inferred (because the constraints cannot be
+/// satisfied), or bail on the inference when this happens.
+///
+/// As currently designed, an instance of this class should only be used to
+/// infer a single call and discarded immediately afterwards.
class _StrongInferenceTypeSystem extends StrongTypeSystemImpl {
final TypeProvider _typeProvider;
@@ -1578,6 +1585,100 @@
}
}
+/**
+ * A special union type of `Future<T> | T` used for Strong Mode inference.
+ */
+class FutureUnionType extends TypeImpl {
+ // TODO(jmesserly): a Set would be better.
+ //
+ // For now we know `Future<T> | T` is the only valid use, so we can rely on
+ // the order, which simplifies some things.
+ //
+ // This will need clean up before this can function as a real union type.
+ final List<DartType> _types;
+
+ /**
+ * Creates a union of `Future< flatten(T) > | flatten(T)`.
+ */
+ factory FutureUnionType(
+ DartType type, TypeProvider provider, TypeSystem system) {
+ type = type.flattenFutures(system);
+
+ // The order of these types is important: T could be a type variable, so
+ // we want to try and match `Future<T>` before we try and match `T`.
+ return new FutureUnionType._([
+ provider.futureType.instantiate([type]),
+ type
+ ]);
+ }
+
+ FutureUnionType._(this._types) : super(null, null);
+
+ DartType get futureOfType => _types[0];
+
+ DartType get type => _types[1];
+
+ Iterable<DartType> get types => _types;
+
+ @override
+ void appendTo(StringBuffer buffer) {
+ buffer.write('(');
+ for (int i = 0; i < _types.length; i++) {
+ if (i != 0) {
+ buffer.write(' | ');
+ }
+ (_types[i] as TypeImpl).appendTo(buffer);
+ }
+ buffer.write(')');
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ for (var t in types) {
+ hash = JenkinsSmiHash.combine(hash, t.hashCode);
+ }
+ return JenkinsSmiHash.finish(hash);
+ }
+
+ @override
+ bool operator ==(Object obj) {
+ if (obj is FutureUnionType) {
+ if (identical(obj, this)) return true;
+ return types.length == obj.types.length &&
+ types.toSet().containsAll(obj.types);
+ }
+ return false;
+ }
+
+ @override
+ bool isMoreSpecificThan(DartType type,
+ [bool withDynamic = false, Set<Element> visitedElements]) =>
+ throw new UnsupportedError(
+ 'Future unions are not part of the Dart 1 type system');
+
+ @override
+ TypeImpl pruned(List<FunctionTypeAliasElement> prune) =>
+ throw new UnsupportedError('Future unions are not substituted');
+
+ @override
+ DartType substitute2(List<DartType> args, List<DartType> params,
+ [List<FunctionTypeAliasElement> prune]) =>
+ throw new UnsupportedError('Future unions are not used in typedefs');
+
+ /**
+ * Creates a union of `T | Future<T>`, unless `T` is already a future-union,
+ * in which case it simply returns `T`
+ */
+ static DartType from(
+ DartType type, TypeProvider provider, TypeSystem system) {
+ if (type is FutureUnionType) {
+ return type;
+ }
+ return new FutureUnionType(type, provider, system);
+ }
+}
+
bool _isBottom(DartType t, {bool dynamicIsBottom: false}) {
return (t.isDynamic && dynamicIsBottom) || t.isBottom;
}
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index bc4d0ab..626f443 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -2099,6 +2099,7 @@
class PackageBundleBuilder extends Object with _PackageBundleMixin implements idl.PackageBundle {
String _apiSignature;
+ List<PackageDependencyInfoBuilder> _dependencies;
List<LinkedLibraryBuilder> _linkedLibraries;
List<String> _linkedLibraryUris;
int _majorVersion;
@@ -2120,6 +2121,16 @@
}
@override
+ List<PackageDependencyInfoBuilder> get dependencies => _dependencies ??= <PackageDependencyInfoBuilder>[];
+
+ /**
+ * Information about the packages this package depends on, if known.
+ */
+ void set dependencies(List<PackageDependencyInfoBuilder> _value) {
+ _dependencies = _value;
+ }
+
+ @override
List<LinkedLibraryBuilder> get linkedLibraries => _linkedLibraries ??= <LinkedLibraryBuilder>[];
/**
@@ -2195,8 +2206,9 @@
_unlinkedUnitUris = _value;
}
- PackageBundleBuilder({String apiSignature, List<LinkedLibraryBuilder> linkedLibraries, List<String> linkedLibraryUris, int majorVersion, int minorVersion, List<String> unlinkedUnitHashes, List<UnlinkedUnitBuilder> unlinkedUnits, List<String> unlinkedUnitUris})
+ PackageBundleBuilder({String apiSignature, List<PackageDependencyInfoBuilder> dependencies, List<LinkedLibraryBuilder> linkedLibraries, List<String> linkedLibraryUris, int majorVersion, int minorVersion, List<String> unlinkedUnitHashes, List<UnlinkedUnitBuilder> unlinkedUnits, List<String> unlinkedUnitUris})
: _apiSignature = apiSignature,
+ _dependencies = dependencies,
_linkedLibraries = linkedLibraries,
_linkedLibraryUris = linkedLibraryUris,
_majorVersion = majorVersion,
@@ -2209,6 +2221,7 @@
* Flush [informative] data recursively.
*/
void flushInformative() {
+ _dependencies = null;
_linkedLibraries?.forEach((b) => b.flushInformative());
_unlinkedUnitHashes = null;
_unlinkedUnits?.forEach((b) => b.flushInformative());
@@ -2262,6 +2275,7 @@
fb.Offset finish(fb.Builder fbBuilder) {
fb.Offset offset_apiSignature;
+ fb.Offset offset_dependencies;
fb.Offset offset_linkedLibraries;
fb.Offset offset_linkedLibraryUris;
fb.Offset offset_unlinkedUnitHashes;
@@ -2270,6 +2284,9 @@
if (_apiSignature != null) {
offset_apiSignature = fbBuilder.writeString(_apiSignature);
}
+ if (!(_dependencies == null || _dependencies.isEmpty)) {
+ offset_dependencies = fbBuilder.writeList(_dependencies.map((b) => b.finish(fbBuilder)).toList());
+ }
if (!(_linkedLibraries == null || _linkedLibraries.isEmpty)) {
offset_linkedLibraries = fbBuilder.writeList(_linkedLibraries.map((b) => b.finish(fbBuilder)).toList());
}
@@ -2289,6 +2306,9 @@
if (offset_apiSignature != null) {
fbBuilder.addOffset(7, offset_apiSignature);
}
+ if (offset_dependencies != null) {
+ fbBuilder.addOffset(8, offset_dependencies);
+ }
if (offset_linkedLibraries != null) {
fbBuilder.addOffset(0, offset_linkedLibraries);
}
@@ -2333,6 +2353,7 @@
_PackageBundleImpl(this._bc, this._bcOffset);
String _apiSignature;
+ List<idl.PackageDependencyInfo> _dependencies;
List<idl.LinkedLibrary> _linkedLibraries;
List<String> _linkedLibraryUris;
int _majorVersion;
@@ -2348,6 +2369,12 @@
}
@override
+ List<idl.PackageDependencyInfo> get dependencies {
+ _dependencies ??= const fb.ListReader<idl.PackageDependencyInfo>(const _PackageDependencyInfoReader()).vTableGet(_bc, _bcOffset, 8, const <idl.PackageDependencyInfo>[]);
+ return _dependencies;
+ }
+
+ @override
List<idl.LinkedLibrary> get linkedLibraries {
_linkedLibraries ??= const fb.ListReader<idl.LinkedLibrary>(const _LinkedLibraryReader()).vTableGet(_bc, _bcOffset, 0, const <idl.LinkedLibrary>[]);
return _linkedLibraries;
@@ -2395,6 +2422,7 @@
Map<String, Object> toJson() {
Map<String, Object> _result = <String, Object>{};
if (apiSignature != '') _result["apiSignature"] = apiSignature;
+ if (dependencies.isNotEmpty) _result["dependencies"] = dependencies.map((_value) => _value.toJson()).toList();
if (linkedLibraries.isNotEmpty) _result["linkedLibraries"] = linkedLibraries.map((_value) => _value.toJson()).toList();
if (linkedLibraryUris.isNotEmpty) _result["linkedLibraryUris"] = linkedLibraryUris;
if (majorVersion != 0) _result["majorVersion"] = majorVersion;
@@ -2408,6 +2436,7 @@
@override
Map<String, Object> toMap() => {
"apiSignature": apiSignature,
+ "dependencies": dependencies,
"linkedLibraries": linkedLibraries,
"linkedLibraryUris": linkedLibraryUris,
"majorVersion": majorVersion,
@@ -2421,6 +2450,212 @@
String toString() => convert.JSON.encode(toJson());
}
+class PackageDependencyInfoBuilder extends Object with _PackageDependencyInfoMixin implements idl.PackageDependencyInfo {
+ String _apiSignature;
+ List<String> _includedPackageNames;
+ bool _includesDartUris;
+ bool _includesFileUris;
+ String _summaryPath;
+
+ @override
+ String get apiSignature => _apiSignature ??= '';
+
+ /**
+ * API signature of this dependency.
+ */
+ void set apiSignature(String _value) {
+ _apiSignature = _value;
+ }
+
+ @override
+ List<String> get includedPackageNames => _includedPackageNames ??= <String>[];
+
+ /**
+ * If this dependency summarizes any files whose URI takes the form
+ * "package:<package_name>/...", a list of all such package names, sorted
+ * lexicographically. Otherwise empty.
+ */
+ void set includedPackageNames(List<String> _value) {
+ _includedPackageNames = _value;
+ }
+
+ @override
+ bool get includesDartUris => _includesDartUris ??= false;
+
+ /**
+ * Indicates whether this dependency summarizes any files whose URI takes the
+ * form "dart:...".
+ */
+ void set includesDartUris(bool _value) {
+ _includesDartUris = _value;
+ }
+
+ @override
+ bool get includesFileUris => _includesFileUris ??= false;
+
+ /**
+ * Indicates whether this dependency summarizes any files whose URI takes the
+ * form "file:...".
+ */
+ void set includesFileUris(bool _value) {
+ _includesFileUris = _value;
+ }
+
+ @override
+ String get summaryPath => _summaryPath ??= '';
+
+ /**
+ * Relative path to the summary file for this dependency. This is intended as
+ * a hint to help the analysis server locate summaries of dependencies. We
+ * don't specify precisely what this path is relative to, but we expect it to
+ * be relative to a directory the analysis server can find (e.g. for projects
+ * built using Bazel, it would be relative to the "bazel-bin" directory).
+ *
+ * Absent if the path is not known.
+ */
+ void set summaryPath(String _value) {
+ _summaryPath = _value;
+ }
+
+ PackageDependencyInfoBuilder({String apiSignature, List<String> includedPackageNames, bool includesDartUris, bool includesFileUris, String summaryPath})
+ : _apiSignature = apiSignature,
+ _includedPackageNames = includedPackageNames,
+ _includesDartUris = includesDartUris,
+ _includesFileUris = includesFileUris,
+ _summaryPath = summaryPath;
+
+ /**
+ * Flush [informative] data recursively.
+ */
+ void flushInformative() {
+ }
+
+ /**
+ * Accumulate non-[informative] data into [signature].
+ */
+ void collectApiSignature(api_sig.ApiSignature signature) {
+ signature.addString(this._apiSignature ?? '');
+ signature.addString(this._summaryPath ?? '');
+ if (this._includedPackageNames == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this._includedPackageNames.length);
+ for (var x in this._includedPackageNames) {
+ signature.addString(x);
+ }
+ }
+ signature.addBool(this._includesFileUris == true);
+ signature.addBool(this._includesDartUris == true);
+ }
+
+ fb.Offset finish(fb.Builder fbBuilder) {
+ fb.Offset offset_apiSignature;
+ fb.Offset offset_includedPackageNames;
+ fb.Offset offset_summaryPath;
+ if (_apiSignature != null) {
+ offset_apiSignature = fbBuilder.writeString(_apiSignature);
+ }
+ if (!(_includedPackageNames == null || _includedPackageNames.isEmpty)) {
+ offset_includedPackageNames = fbBuilder.writeList(_includedPackageNames.map((b) => fbBuilder.writeString(b)).toList());
+ }
+ if (_summaryPath != null) {
+ offset_summaryPath = fbBuilder.writeString(_summaryPath);
+ }
+ fbBuilder.startTable();
+ if (offset_apiSignature != null) {
+ fbBuilder.addOffset(0, offset_apiSignature);
+ }
+ if (offset_includedPackageNames != null) {
+ fbBuilder.addOffset(2, offset_includedPackageNames);
+ }
+ if (_includesDartUris == true) {
+ fbBuilder.addBool(4, true);
+ }
+ if (_includesFileUris == true) {
+ fbBuilder.addBool(3, true);
+ }
+ if (offset_summaryPath != null) {
+ fbBuilder.addOffset(1, offset_summaryPath);
+ }
+ return fbBuilder.endTable();
+ }
+}
+
+class _PackageDependencyInfoReader extends fb.TableReader<_PackageDependencyInfoImpl> {
+ const _PackageDependencyInfoReader();
+
+ @override
+ _PackageDependencyInfoImpl createObject(fb.BufferContext bc, int offset) => new _PackageDependencyInfoImpl(bc, offset);
+}
+
+class _PackageDependencyInfoImpl extends Object with _PackageDependencyInfoMixin implements idl.PackageDependencyInfo {
+ final fb.BufferContext _bc;
+ final int _bcOffset;
+
+ _PackageDependencyInfoImpl(this._bc, this._bcOffset);
+
+ String _apiSignature;
+ List<String> _includedPackageNames;
+ bool _includesDartUris;
+ bool _includesFileUris;
+ String _summaryPath;
+
+ @override
+ String get apiSignature {
+ _apiSignature ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
+ return _apiSignature;
+ }
+
+ @override
+ List<String> get includedPackageNames {
+ _includedPackageNames ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bc, _bcOffset, 2, const <String>[]);
+ return _includedPackageNames;
+ }
+
+ @override
+ bool get includesDartUris {
+ _includesDartUris ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 4, false);
+ return _includesDartUris;
+ }
+
+ @override
+ bool get includesFileUris {
+ _includesFileUris ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
+ return _includesFileUris;
+ }
+
+ @override
+ String get summaryPath {
+ _summaryPath ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
+ return _summaryPath;
+ }
+}
+
+abstract class _PackageDependencyInfoMixin implements idl.PackageDependencyInfo {
+ @override
+ Map<String, Object> toJson() {
+ Map<String, Object> _result = <String, Object>{};
+ if (apiSignature != '') _result["apiSignature"] = apiSignature;
+ if (includedPackageNames.isNotEmpty) _result["includedPackageNames"] = includedPackageNames;
+ if (includesDartUris != false) _result["includesDartUris"] = includesDartUris;
+ if (includesFileUris != false) _result["includesFileUris"] = includesFileUris;
+ if (summaryPath != '') _result["summaryPath"] = summaryPath;
+ return _result;
+ }
+
+ @override
+ Map<String, Object> toMap() => {
+ "apiSignature": apiSignature,
+ "includedPackageNames": includedPackageNames,
+ "includesDartUris": includesDartUris,
+ "includesFileUris": includesFileUris,
+ "summaryPath": summaryPath,
+ };
+
+ @override
+ String toString() => convert.JSON.encode(toJson());
+}
+
class PackageIndexBuilder extends Object with _PackageIndexMixin implements idl.PackageIndex {
List<idl.IndexSyntheticElementKind> _elementKinds;
List<int> _elementNameClassMemberIds;
@@ -8406,6 +8641,7 @@
String _libraryName;
int _libraryNameLength;
int _libraryNameOffset;
+ List<int> _lineStarts;
List<UnlinkedPartBuilder> _parts;
UnlinkedPublicNamespaceBuilder _publicNamespace;
List<UnlinkedReferenceBuilder> _references;
@@ -8544,6 +8780,17 @@
}
@override
+ List<int> get lineStarts => _lineStarts ??= <int>[];
+
+ /**
+ * Offsets of the first character of each line in the source code.
+ */
+ void set lineStarts(List<int> _value) {
+ assert(_value == null || _value.every((e) => e >= 0));
+ _lineStarts = _value;
+ }
+
+ @override
List<UnlinkedPartBuilder> get parts => _parts ??= <UnlinkedPartBuilder>[];
/**
@@ -8597,7 +8844,7 @@
_variables = _value;
}
- UnlinkedUnitBuilder({List<UnlinkedClassBuilder> classes, CodeRangeBuilder codeRange, List<UnlinkedEnumBuilder> enums, List<UnlinkedExecutableBuilder> executables, List<UnlinkedExportNonPublicBuilder> exports, String fallbackModePath, List<UnlinkedImportBuilder> imports, List<UnlinkedConstBuilder> libraryAnnotations, UnlinkedDocumentationCommentBuilder libraryDocumentationComment, String libraryName, int libraryNameLength, int libraryNameOffset, List<UnlinkedPartBuilder> parts, UnlinkedPublicNamespaceBuilder publicNamespace, List<UnlinkedReferenceBuilder> references, List<UnlinkedTypedefBuilder> typedefs, List<UnlinkedVariableBuilder> variables})
+ UnlinkedUnitBuilder({List<UnlinkedClassBuilder> classes, CodeRangeBuilder codeRange, List<UnlinkedEnumBuilder> enums, List<UnlinkedExecutableBuilder> executables, List<UnlinkedExportNonPublicBuilder> exports, String fallbackModePath, List<UnlinkedImportBuilder> imports, List<UnlinkedConstBuilder> libraryAnnotations, UnlinkedDocumentationCommentBuilder libraryDocumentationComment, String libraryName, int libraryNameLength, int libraryNameOffset, List<int> lineStarts, List<UnlinkedPartBuilder> parts, UnlinkedPublicNamespaceBuilder publicNamespace, List<UnlinkedReferenceBuilder> references, List<UnlinkedTypedefBuilder> typedefs, List<UnlinkedVariableBuilder> variables})
: _classes = classes,
_codeRange = codeRange,
_enums = enums,
@@ -8610,6 +8857,7 @@
_libraryName = libraryName,
_libraryNameLength = libraryNameLength,
_libraryNameOffset = libraryNameOffset,
+ _lineStarts = lineStarts,
_parts = parts,
_publicNamespace = publicNamespace,
_references = references,
@@ -8630,6 +8878,7 @@
_libraryDocumentationComment = null;
_libraryNameLength = null;
_libraryNameOffset = null;
+ _lineStarts = null;
_parts?.forEach((b) => b.flushInformative());
_publicNamespace?.flushInformative();
_references?.forEach((b) => b.flushInformative());
@@ -8743,6 +8992,7 @@
fb.Offset offset_libraryAnnotations;
fb.Offset offset_libraryDocumentationComment;
fb.Offset offset_libraryName;
+ fb.Offset offset_lineStarts;
fb.Offset offset_parts;
fb.Offset offset_publicNamespace;
fb.Offset offset_references;
@@ -8778,6 +9028,9 @@
if (_libraryName != null) {
offset_libraryName = fbBuilder.writeString(_libraryName);
}
+ if (!(_lineStarts == null || _lineStarts.isEmpty)) {
+ offset_lineStarts = fbBuilder.writeListUint32(_lineStarts);
+ }
if (!(_parts == null || _parts.isEmpty)) {
offset_parts = fbBuilder.writeList(_parts.map((b) => b.finish(fbBuilder)).toList());
}
@@ -8830,6 +9083,9 @@
if (_libraryNameOffset != null && _libraryNameOffset != 0) {
fbBuilder.addUint32(8, _libraryNameOffset);
}
+ if (offset_lineStarts != null) {
+ fbBuilder.addOffset(17, offset_lineStarts);
+ }
if (offset_parts != null) {
fbBuilder.addOffset(11, offset_parts);
}
@@ -8879,6 +9135,7 @@
String _libraryName;
int _libraryNameLength;
int _libraryNameOffset;
+ List<int> _lineStarts;
List<idl.UnlinkedPart> _parts;
idl.UnlinkedPublicNamespace _publicNamespace;
List<idl.UnlinkedReference> _references;
@@ -8958,6 +9215,12 @@
}
@override
+ List<int> get lineStarts {
+ _lineStarts ??= const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 17, const <int>[]);
+ return _lineStarts;
+ }
+
+ @override
List<idl.UnlinkedPart> get parts {
_parts ??= const fb.ListReader<idl.UnlinkedPart>(const _UnlinkedPartReader()).vTableGet(_bc, _bcOffset, 11, const <idl.UnlinkedPart>[]);
return _parts;
@@ -9004,6 +9267,7 @@
if (libraryName != '') _result["libraryName"] = libraryName;
if (libraryNameLength != 0) _result["libraryNameLength"] = libraryNameLength;
if (libraryNameOffset != 0) _result["libraryNameOffset"] = libraryNameOffset;
+ if (lineStarts.isNotEmpty) _result["lineStarts"] = lineStarts;
if (parts.isNotEmpty) _result["parts"] = parts.map((_value) => _value.toJson()).toList();
if (publicNamespace != null) _result["publicNamespace"] = publicNamespace.toJson();
if (references.isNotEmpty) _result["references"] = references.map((_value) => _value.toJson()).toList();
@@ -9026,6 +9290,7 @@
"libraryName": libraryName,
"libraryNameLength": libraryNameLength,
"libraryNameOffset": libraryNameOffset,
+ "lineStarts": lineStarts,
"parts": parts,
"publicNamespace": publicNamespace,
"references": references,
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 1449743..ba46f01 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1188,6 +1188,11 @@
apiSignature:string (id: 7);
/**
+ * Information about the packages this package depends on, if known.
+ */
+ dependencies:[PackageDependencyInfo] (id: 8);
+
+ /**
* Linked libraries.
*/
linkedLibraries:[LinkedLibrary] (id: 0);
@@ -1228,6 +1233,46 @@
}
/**
+ * Information about a single dependency of a summary package.
+ */
+table PackageDependencyInfo {
+ /**
+ * API signature of this dependency.
+ */
+ apiSignature:string (id: 0);
+
+ /**
+ * If this dependency summarizes any files whose URI takes the form
+ * "package:<package_name>/...", a list of all such package names, sorted
+ * lexicographically. Otherwise empty.
+ */
+ includedPackageNames:[string] (id: 2);
+
+ /**
+ * Indicates whether this dependency summarizes any files whose URI takes the
+ * form "dart:...".
+ */
+ includesDartUris:bool (id: 4);
+
+ /**
+ * Indicates whether this dependency summarizes any files whose URI takes the
+ * form "file:...".
+ */
+ includesFileUris:bool (id: 3);
+
+ /**
+ * Relative path to the summary file for this dependency. This is intended as
+ * a hint to help the analysis server locate summaries of dependencies. We
+ * don't specify precisely what this path is relative to, but we expect it to
+ * be relative to a directory the analysis server can find (e.g. for projects
+ * built using Bazel, it would be relative to the "bazel-bin" directory).
+ *
+ * Absent if the path is not known.
+ */
+ summaryPath:string (id: 1);
+}
+
+/**
* Index information about a package.
*/
table PackageIndex {
@@ -2329,6 +2374,11 @@
libraryNameOffset:uint (id: 8);
/**
+ * Offsets of the first character of each line in the source code.
+ */
+ lineStarts:[uint] (id: 17);
+
+ /**
* Part declarations in the compilation unit.
*/
parts:[UnlinkedPart] (id: 11);
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 15f81a7..70b329b 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -658,6 +658,13 @@
String get apiSignature;
/**
+ * Information about the packages this package depends on, if known.
+ */
+ @Id(8)
+ @informative
+ List<PackageDependencyInfo> get dependencies;
+
+ /**
* Linked libraries.
*/
@Id(0)
@@ -706,6 +713,51 @@
}
/**
+ * Information about a single dependency of a summary package.
+ */
+abstract class PackageDependencyInfo extends base.SummaryClass {
+ /**
+ * API signature of this dependency.
+ */
+ @Id(0)
+ String get apiSignature;
+
+ /**
+ * If this dependency summarizes any files whose URI takes the form
+ * "package:<package_name>/...", a list of all such package names, sorted
+ * lexicographically. Otherwise empty.
+ */
+ @Id(2)
+ List<String> get includedPackageNames;
+
+ /**
+ * Indicates whether this dependency summarizes any files whose URI takes the
+ * form "dart:...".
+ */
+ @Id(4)
+ bool get includesDartUris;
+
+ /**
+ * Indicates whether this dependency summarizes any files whose URI takes the
+ * form "file:...".
+ */
+ @Id(3)
+ bool get includesFileUris;
+
+ /**
+ * Relative path to the summary file for this dependency. This is intended as
+ * a hint to help the analysis server locate summaries of dependencies. We
+ * don't specify precisely what this path is relative to, but we expect it to
+ * be relative to a directory the analysis server can find (e.g. for projects
+ * built using Bazel, it would be relative to the "bazel-bin" directory).
+ *
+ * Absent if the path is not known.
+ */
+ @Id(1)
+ String get summaryPath;
+}
+
+/**
* Index information about a package.
*/
@TopLevel('Indx')
@@ -2660,6 +2712,13 @@
int get libraryNameOffset;
/**
+ * Offsets of the first character of each line in the source code.
+ */
+ @informative
+ @Id(17)
+ List<int> get lineStarts;
+
+ /**
* Part declarations in the compilation unit.
*/
@Id(11)
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
index 062ce82..7ea1c1b 100644
--- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -10,11 +10,13 @@
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/format.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/general.dart';
import 'package:analyzer/task/model.dart';
import 'package:path/path.dart' as pathos;
@@ -196,6 +198,15 @@
return true;
}
return false;
+ } else if (result == LINE_INFO) {
+ UnlinkedUnit unlinkedUnit = _dataStore.unlinkedMap[uriString];
+ List<int> lineStarts = unlinkedUnit.lineStarts;
+ if (lineStarts.isNotEmpty) {
+ LineInfo lineInfo = new LineInfo(lineStarts);
+ entry.setValue(result, lineInfo, TargetedResult.EMPTY_LIST);
+ return true;
+ }
+ return false;
}
} else if (target is LibrarySpecificUnit) {
if (result == CREATED_RESOLVED_UNIT1 ||
@@ -273,6 +284,15 @@
final List<PackageBundle> bundles = <PackageBundle>[];
/**
+ * List of dependency information for the package bundles in this
+ * [SummaryDataStore], in a form that is ready to store in a newly generated
+ * summary. Computing this information has nonzero cost, so it is only
+ * recorded if the [SummaryDataStore] is constructed with the argument
+ * `recordDependencies`. Otherwise `null`.
+ */
+ final List<PackageDependencyInfoBuilder> dependencies;
+
+ /**
* Map from the URI of a compilation unit to the unlinked summary of that
* compilation unit.
*/
@@ -288,7 +308,16 @@
*/
final Map<String, String> uriToSummaryPath = <String, String>{};
- SummaryDataStore(Iterable<String> summaryPaths) {
+ /**
+ * Create a [SummaryDataStore] and populate it with the summaries in
+ * [summaryPaths]. If [recordDependencyInfo] is `true`, record
+ * [PackageDependencyInfo] for each summary, for later access via
+ * [dependencies].
+ */
+ SummaryDataStore(Iterable<String> summaryPaths,
+ {bool recordDependencyInfo: false})
+ : dependencies =
+ recordDependencyInfo ? <PackageDependencyInfoBuilder>[] : null {
summaryPaths.forEach(_fillMaps);
}
@@ -297,6 +326,29 @@
*/
void addBundle(String path, PackageBundle bundle) {
bundles.add(bundle);
+ if (dependencies != null) {
+ Set<String> includedPackageNames = new Set<String>();
+ bool includesDartUris = false;
+ bool includesFileUris = false;
+ for (String uriString in bundle.unlinkedUnitUris) {
+ Uri uri = FastUri.parse(uriString);
+ String scheme = uri.scheme;
+ if (scheme == 'package') {
+ List<String> pathSegments = uri.pathSegments;
+ includedPackageNames.add(pathSegments.isEmpty ? '' : pathSegments[0]);
+ } else if (scheme == 'file') {
+ includesFileUris = true;
+ } else if (scheme == 'dart') {
+ includesDartUris = true;
+ }
+ }
+ dependencies.add(new PackageDependencyInfoBuilder(
+ includedPackageNames: includedPackageNames.toList()..sort(),
+ includesDartUris: includesDartUris,
+ includesFileUris: includesFileUris,
+ apiSignature: bundle.apiSignature,
+ summaryPath: path));
+ }
for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
String uri = bundle.unlinkedUnitUris[i];
uriToSummaryPath[uri] = path;
diff --git a/pkg/analyzer/lib/src/summary/pub_summary.dart b/pkg/analyzer/lib/src/summary/pub_summary.dart
new file mode 100644
index 0000000..21c074d
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/pub_summary.dart
@@ -0,0 +1,456 @@
+// 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:async';
+import 'dart:collection';
+import 'dart:core' hide Resource;
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/format.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/link.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart'
+ show ResynthesizerResultProvider, SummaryDataStore;
+import 'package:analyzer/src/summary/summarize_ast.dart'
+ show serializeAstUnlinked;
+import 'package:analyzer/src/summary/summarize_elements.dart'
+ show PackageBundleAssembler;
+import 'package:analyzer/src/util/fast_uri.dart';
+import 'package:path/path.dart' as pathos;
+
+/**
+ * A package in the pub cache.
+ */
+class PubPackage {
+ final String name;
+ final Folder libFolder;
+
+ PubPackage(this.name, this.libFolder);
+
+ Folder get folder => libFolder.parent;
+
+ @override
+ int get hashCode => libFolder.hashCode;
+
+ @override
+ bool operator ==(other) {
+ return other is PubPackage && other.libFolder == libFolder;
+ }
+
+ @override
+ String toString() => '($name in $folder)';
+}
+
+/**
+ * Unlinked and linked information about a [PubPackage].
+ */
+class LinkedPubPackage {
+ final PubPackage package;
+ final PackageBundle unlinked;
+ final PackageBundle linked;
+ LinkedPubPackage(this.package, this.unlinked, this.linked);
+}
+
+/**
+ * Class that manages summaries for pub packages.
+ *
+ * The client should call [getLinkedBundles] after creating a new
+ * [AnalysisContext] and configuring its source factory, but before computing
+ * any analysis results. The returned linked bundles can be used to create and
+ * configure [ResynthesizerResultProvider] for the context.
+ */
+class PubSummaryManager {
+ static const UNLINKED_BUNDLE_FILE_NAME = 'unlinked.ds';
+
+ final ResourceProvider resourceProvider;
+
+ /**
+ * The name of the temporary file that is used for atomic writes.
+ */
+ final String tempFileName;
+
+ /**
+ * The map from [PubPackage]s to their unlinked [PackageBundle]s in the pub
+ * cache.
+ */
+ final Map<PubPackage, PackageBundle> unlinkedBundleMap =
+ new HashMap<PubPackage, PackageBundle>();
+
+ /**
+ * The set of packages to compute unlinked summaries for.
+ */
+ final Set<PubPackage> packagesToComputeUnlinked = new Set<PubPackage>();
+
+ /**
+ * The set of already processed packages, which we have already checked
+ * for their unlinked bundle existence, or scheduled its computing.
+ */
+ final Set<PubPackage> seenPackages = new Set<PubPackage>();
+
+ /**
+ * The [Completer] that completes when computing of all scheduled unlinked
+ * bundles is complete.
+ */
+ Completer _onUnlinkedCompleteCompleter;
+
+ PubSummaryManager(this.resourceProvider, this.tempFileName);
+
+ /**
+ * The [Future] that completes when computing of all scheduled unlinked
+ * bundles is complete.
+ */
+ Future get onUnlinkedComplete {
+ if (packagesToComputeUnlinked.isEmpty) {
+ return new Future.value();
+ }
+ _onUnlinkedCompleteCompleter ??= new Completer();
+ return _onUnlinkedCompleteCompleter.future;
+ }
+
+ /**
+ * Return the [pathos.Context] corresponding to the [resourceProvider].
+ */
+ pathos.Context get pathContext => resourceProvider.pathContext;
+
+ /**
+ * Return the list of linked [LinkedPubPackage]s that can be provided at this
+ * time for a subset of the packages used by the given [context]. If
+ * information about some of the used packages is not available yet, schedule
+ * its computation, so that it might be available later for other contexts
+ * referencing the same packages.
+ */
+ List<LinkedPubPackage> getLinkedBundles(
+ AnalysisContext context, PackageBundle sdkBundle) {
+ Map<PubPackage, PackageBundle> unlinkedBundles =
+ getUnlinkedBundles(context);
+
+ // If no unlinked bundles, there is nothing we can try to link.
+ if (unlinkedBundles.isEmpty) {
+ return <LinkedPubPackage>[];
+ }
+
+ // Create graph nodes for packages.
+ List<_LinkedNode> nodes = <_LinkedNode>[];
+ Map<String, _LinkedNode> uriToNode = <String, _LinkedNode>{};
+ unlinkedBundles.forEach((package, unlinked) {
+ _LinkedNode node = new _LinkedNode(package, unlinked, uriToNode);
+ nodes.add(node);
+ for (String uri in unlinked.unlinkedUnitUris) {
+ uriToNode[uri] = node;
+ }
+ });
+
+ // Fill the store with unlinked bundles.
+ SummaryDataStore store = new SummaryDataStore(const <String>[]);
+ store.addBundle(null, sdkBundle);
+ for (PackageBundle unlinked in unlinkedBundles.values) {
+ store.addBundle(null, unlinked);
+ }
+
+ // Link each package node.
+ for (_LinkedNode node in nodes) {
+ if (!node.isEvaluated) {
+ new _LinkedWalker(store).walk(node);
+ }
+ }
+
+ // Create successfully linked packages.
+ List<LinkedPubPackage> linkedPackages = <LinkedPubPackage>[];
+ for (_LinkedNode node in nodes) {
+ if (node.linkedBuilder != null) {
+ List<int> bytes = node.linkedBuilder.toBuffer();
+ PackageBundle linkedBundle = new PackageBundle.fromBuffer(bytes);
+ linkedPackages.add(
+ new LinkedPubPackage(node.package, node.unlinked, linkedBundle));
+ }
+ }
+
+ // TODO(scheglov) compute dependency hashes and write linked bundles.
+
+ // Done.
+ return linkedPackages;
+ }
+
+ /**
+ * Return all available unlinked [PackageBundle]s for the given [context],
+ * maybe an empty map, but not `null`.
+ */
+ Map<PubPackage, PackageBundle> getUnlinkedBundles(AnalysisContext context) {
+ Map<PubPackage, PackageBundle> unlinkedBundles =
+ new HashMap<PubPackage, PackageBundle>();
+ Map<String, List<Folder>> packageMap = context.sourceFactory.packageMap;
+ if (packageMap != null) {
+ packageMap.forEach((String packageName, List<Folder> libFolders) {
+ if (libFolders.length == 1) {
+ Folder libFolder = libFolders.first;
+ if (isPathInPubCache(pathContext, libFolder.path)) {
+ PubPackage package = new PubPackage(packageName, libFolder);
+ PackageBundle unlinkedBundle = _getUnlinkedOrSchedule(package);
+ if (unlinkedBundle != null) {
+ unlinkedBundles[package] = unlinkedBundle;
+ }
+ }
+ }
+ });
+ }
+ return unlinkedBundles;
+ }
+
+ /**
+ * Compute unlinked bundle for a package from [packagesToComputeUnlinked],
+ * and schedule delayed computation for the next package, if any.
+ */
+ void _computeNextUnlinked() {
+ if (packagesToComputeUnlinked.isNotEmpty) {
+ PubPackage package = packagesToComputeUnlinked.first;
+ _computeUnlinked(package);
+ packagesToComputeUnlinked.remove(package);
+ _scheduleNextUnlinked();
+ } else {
+ if (_onUnlinkedCompleteCompleter != null) {
+ _onUnlinkedCompleteCompleter.complete(true);
+ _onUnlinkedCompleteCompleter = null;
+ }
+ }
+ }
+
+ /**
+ * Compute the unlinked bundle for the package with the given path, put
+ * it in the [unlinkedBundleMap] and store into the [resourceProvider].
+ *
+ * TODO(scheglov) Consider moving into separate isolate(s).
+ */
+ void _computeUnlinked(PubPackage package) {
+ Folder libFolder = package.libFolder;
+ String libPath = libFolder.path + pathContext.separator;
+ PackageBundleAssembler assembler = new PackageBundleAssembler();
+
+ /**
+ * Return the `package` [Uri] for the given [path] in the `lib` folder
+ * of the current package.
+ */
+ Uri getUri(String path) {
+ String pathInLib = path.substring(libPath.length);
+ String uriPath = pathos.posix.joinAll(pathContext.split(pathInLib));
+ String uriStr = 'package:${package.name}/$uriPath';
+ return FastUri.parse(uriStr);
+ }
+
+ /**
+ * If the given [file] is a Dart file, add its unlinked unit.
+ */
+ void addDartFile(File file) {
+ String path = file.path;
+ if (AnalysisEngine.isDartFileName(path)) {
+ Uri uri = getUri(path);
+ Source source = file.createSource(uri);
+ CompilationUnit unit = _parse(source);
+ UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
+ assembler.addUnlinkedUnit(source, unlinkedUnit);
+ }
+ }
+
+ /**
+ * Visit the [folder] recursively.
+ */
+ void addDartFiles(Folder folder) {
+ List<Resource> children = folder.getChildren();
+ for (Resource child in children) {
+ if (child is File) {
+ addDartFile(child);
+ }
+ }
+ for (Resource child in children) {
+ if (child is Folder) {
+ addDartFiles(child);
+ }
+ }
+ }
+
+ try {
+ addDartFiles(libFolder);
+ List<int> bytes = assembler.assemble().toBuffer();
+ _writeAtomic(package.folder, UNLINKED_BUNDLE_FILE_NAME, bytes);
+ } on FileSystemException {
+ // Ignore file system exceptions.
+ }
+ }
+
+ /**
+ * Return the unlinked [PackageBundle] for the given [package]. If the bundle
+ * has not been compute yet, return `null` and schedule its computation.
+ */
+ PackageBundle _getUnlinkedOrSchedule(PubPackage package) {
+ // Try to find in the cache.
+ PackageBundle bundle = unlinkedBundleMap[package];
+ if (bundle != null) {
+ return bundle;
+ }
+ // Try to read from the file system.
+ File unlinkedFile =
+ package.folder.getChildAssumingFile(UNLINKED_BUNDLE_FILE_NAME);
+ if (unlinkedFile.exists) {
+ try {
+ List<int> bytes = unlinkedFile.readAsBytesSync();
+ bundle = new PackageBundle.fromBuffer(bytes);
+ unlinkedBundleMap[package] = bundle;
+ return bundle;
+ } on FileSystemException {
+ // Ignore file system exceptions.
+ }
+ }
+ // Schedule computation in the background.
+ if (package != null && seenPackages.add(package)) {
+ if (packagesToComputeUnlinked.isEmpty) {
+ _scheduleNextUnlinked();
+ }
+ packagesToComputeUnlinked.add(package);
+ }
+ // The bundle is for available.
+ return null;
+ }
+
+ /**
+ * Parse the given [source] into AST.
+ */
+ CompilationUnit _parse(Source source) {
+ String code = source.contents.data;
+ AnalysisErrorListener errorListener = AnalysisErrorListener.NULL_LISTENER;
+ CharSequenceReader reader = new CharSequenceReader(code);
+ Scanner scanner = new Scanner(source, reader, errorListener);
+ Token token = scanner.tokenize();
+ LineInfo lineInfo = new LineInfo(scanner.lineStarts);
+ Parser parser = new Parser(source, errorListener);
+ CompilationUnit unit = parser.parseCompilationUnit(token);
+ unit.lineInfo = lineInfo;
+ return unit;
+ }
+
+ /**
+ * Schedule delayed computation of the next package unlinked bundle from the
+ * set of [packagesToComputeUnlinked]. We delay each computation because we
+ * want operations in analysis server to proceed, and computing bundles of
+ * packages is a background task.
+ */
+ void _scheduleNextUnlinked() {
+ new Future.delayed(new Duration(milliseconds: 10), _computeNextUnlinked);
+ }
+
+ /**
+ * Atomically write the given [bytes] into the file in the [folder].
+ */
+ void _writeAtomic(Folder folder, String fileName, List<int> bytes) {
+ String filePath = folder.getChildAssumingFile(fileName).path;
+ File tempFile = folder.getChildAssumingFile(tempFileName);
+ tempFile.writeAsBytesSync(bytes);
+ tempFile.renameSync(filePath);
+ }
+
+ /**
+ * Return `true` if the given absolute [path] is in the pub cache.
+ */
+ static bool isPathInPubCache(pathos.Context pathContext, String path) {
+ List<String> parts = pathContext.split(path);
+ for (int i = 0; i < parts.length - 1; i++) {
+ if (parts[i] == '.pub-cache') {
+ return true;
+ }
+ if (parts[i] == 'Pub' && parts[i + 1] == 'Cache') {
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+/**
+ * Specialization of [Node] for linking packages in proper dependency order.
+ */
+class _LinkedNode extends Node<_LinkedNode> {
+ final PubPackage package;
+ final PackageBundle unlinked;
+ final Map<String, _LinkedNode> uriToNode;
+
+ PackageBundleBuilder linkedBuilder;
+ bool failed = false;
+
+ _LinkedNode(this.package, this.unlinked, this.uriToNode);
+
+ @override
+ bool get isEvaluated => linkedBuilder != null || failed;
+
+ @override
+ List<_LinkedNode> computeDependencies() {
+ Set<String> referencedUris = new Set<String>();
+ for (UnlinkedUnit unit in unlinked.unlinkedUnits) {
+ for (UnlinkedImport import in unit.imports) {
+ String uri = import.isImplicit ? 'dart:core' : import.uri;
+ if (uri.startsWith('dart:')) {
+ // Ignore SDK imports.
+ } else if (uri.startsWith('package:')) {
+ referencedUris.add(uri);
+ } else {
+ failed = true;
+ return const <_LinkedNode>[];
+ }
+ }
+ }
+ // TODO(scheglov) fail if no corresponding node
+ return referencedUris.map((uri) => uriToNode[uri]).toSet().toList();
+ }
+
+ @override
+ String toString() => package.toString();
+}
+
+/**
+ * Specialization of [DependencyWalker] for linking packages.
+ */
+class _LinkedWalker extends DependencyWalker<_LinkedNode> {
+ final SummaryDataStore store;
+
+ _LinkedWalker(this.store);
+
+ @override
+ void evaluate(_LinkedNode v) {
+ Set<String> libraryUris = v.unlinked.unlinkedUnitUris.toSet();
+ Map<String, LinkedLibraryBuilder> map = link(libraryUris, (String absUri) {
+ LinkedLibrary dependencyLibrary = store.linkedMap[absUri];
+ if (dependencyLibrary == null) {
+ // TODO(scheglov) add test
+ v.failed = true;
+ }
+ return dependencyLibrary;
+ }, (String absUri) {
+ UnlinkedUnit unlinkedUnit = store.unlinkedMap[absUri];
+ if (unlinkedUnit == null) {
+ // TODO(scheglov) add test
+ v.failed = true;
+ }
+ return unlinkedUnit;
+ }, false);
+ if (!v.failed) {
+ PackageBundleAssembler assembler = new PackageBundleAssembler();
+ map.forEach((uri, linkedLibrary) {
+ assembler.addLinkedLibrary(uri, linkedLibrary);
+ });
+ v.linkedBuilder = assembler.assemble();
+ store.addBundle(null, v.linkedBuilder);
+ }
+ }
+
+ @override
+ void evaluateScc(List<_LinkedNode> scc) {
+ print('evaluateScc: $scc');
+ // TODO(scheglov): implement evaluateScc
+ }
+}
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
index eeaef9d..ec4f609 100644
--- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -511,6 +511,7 @@
}
compilationUnit.declarations.accept(this);
UnlinkedUnitBuilder b = new UnlinkedUnitBuilder();
+ b.lineStarts = compilationUnit.lineInfo?.lineStarts;
b.libraryName = libraryName;
b.libraryNameOffset = libraryNameOffset;
b.libraryNameLength = libraryNameLength;
diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart
index e25da27..e62f408 100644
--- a/pkg/analyzer/lib/src/summary/summarize_elements.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
@@ -19,6 +19,7 @@
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/name_filter.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/summary/summarize_const_expr.dart';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
@@ -138,7 +139,11 @@
final List<LinkedLibraryBuilder> _linkedLibraries = <LinkedLibraryBuilder>[];
final List<String> _unlinkedUnitUris = <String>[];
final List<UnlinkedUnitBuilder> _unlinkedUnits = <UnlinkedUnitBuilder>[];
+ final Map<String, UnlinkedUnitBuilder> _unlinkedUnitMap =
+ <String, UnlinkedUnitBuilder>{};
final List<String> _unlinkedUnitHashes;
+ final List<PackageDependencyInfoBuilder> _dependencies =
+ <PackageDependencyInfoBuilder>[];
final bool _excludeHashes;
/**
@@ -167,9 +172,11 @@
*/
void addFallbackUnit(Source source) {
String uri = source.uri.toString();
+ UnlinkedUnitBuilder unit = new UnlinkedUnitBuilder(
+ fallbackModePath: path.relative(source.fullName));
_unlinkedUnitUris.add(uri);
- _unlinkedUnits.add(new UnlinkedUnitBuilder(
- fallbackModePath: path.relative(source.fullName)));
+ _unlinkedUnits.add(unit);
+ _unlinkedUnitMap[uri] = unit;
}
void addLinkedLibrary(String uri, LinkedLibraryBuilder library) {
@@ -186,6 +193,7 @@
String uri, UnlinkedUnitBuilder unit, String hash) {
_unlinkedUnitUris.add(uri);
_unlinkedUnits.add(unit);
+ _unlinkedUnitMap[uri] = unit;
_unlinkedUnitHashes?.add(hash);
}
@@ -193,18 +201,24 @@
* Assemble a new [PackageBundleBuilder] using the gathered information.
*/
PackageBundleBuilder assemble() {
- PackageBundleBuilder packageBundle = new PackageBundleBuilder(
+ return new PackageBundleBuilder(
linkedLibraryUris: _linkedLibraryUris,
linkedLibraries: _linkedLibraries,
unlinkedUnitUris: _unlinkedUnitUris,
unlinkedUnits: _unlinkedUnits,
unlinkedUnitHashes: _unlinkedUnitHashes,
majorVersion: currentMajorVersion,
- minorVersion: currentMinorVersion);
- ApiSignature apiSignature = new ApiSignature();
- packageBundle.collectApiSignature(apiSignature);
- packageBundle.apiSignature = apiSignature.toHex();
- return packageBundle;
+ minorVersion: currentMinorVersion,
+ dependencies: _dependencies,
+ apiSignature: _computeApiSignature());
+ }
+
+ /**
+ * Use the dependency information in [summaryDataStore] to populate the
+ * dependencies in the package bundle being assembled.
+ */
+ void recordDependencies(SummaryDataStore summaryDataStore) {
+ _dependencies.addAll(summaryDataStore.dependencies);
}
/**
@@ -220,12 +234,28 @@
_linkedLibraries.add(libraryResult.linked);
_unlinkedUnitUris.addAll(libraryResult.unitUris);
_unlinkedUnits.addAll(libraryResult.unlinkedUnits);
+ for (int i = 0; i < libraryResult.unitUris.length; i++) {
+ _unlinkedUnitMap[libraryResult.unitUris[i]] =
+ libraryResult.unlinkedUnits[i];
+ }
for (Source source in libraryResult.unitSources) {
_unlinkedUnitHashes?.add(_hash(source.contents.data));
}
}
/**
+ * Compute the API signature for this package bundle.
+ */
+ String _computeApiSignature() {
+ ApiSignature apiSignature = new ApiSignature();
+ for (String unitUri in _unlinkedUnitMap.keys.toList()..sort()) {
+ apiSignature.addString(unitUri);
+ _unlinkedUnitMap[unitUri].collectApiSignature(apiSignature);
+ }
+ return apiSignature.toHex();
+ }
+
+ /**
* Compute a hash of the given file contents.
*/
String _hash(String contents) {
@@ -450,6 +480,8 @@
}
unlinkedUnit.variables = variables;
unlinkedUnit.references = unlinkedReferences;
+ unlinkedUnit.lineStarts =
+ compilationUnit.context?.computeLineInfo(unitSource)?.lineStarts;
linkedUnit.references = linkedReferences;
unitUri = compilationUnit.source.uri.toString();
}
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 4ff2448..c8b108b 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -3248,8 +3248,9 @@
unit.accept(new Dart2JSVerifier(errorReporter));
}
// Dart best practices.
- InheritanceManager inheritanceManager =
- new InheritanceManager(libraryElement);
+ InheritanceManager inheritanceManager = new InheritanceManager(
+ libraryElement,
+ includeAbstractFromSuperclasses: true);
TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
unit.accept(new BestPracticesVerifier(
@@ -6545,8 +6546,10 @@
int length = imports.length;
for (int i = 0; i < length; i++) {
ImportElement importElement = imports[i];
- Source importedSource = importElement.importedLibrary.source;
- _newSources.add(importedSource);
+ Source importedSource = importElement.importedLibrary?.source;
+ if (importedSource != null) {
+ _newSources.add(importedSource);
+ }
}
}
if (kind == _SourceClosureKind.EXPORT ||
@@ -6555,8 +6558,10 @@
int length = exports.length;
for (int i = 0; i < length; i++) {
ExportElement exportElement = exports[i];
- Source exportedSource = exportElement.exportedLibrary.source;
- _newSources.add(exportedSource);
+ Source exportedSource = exportElement.exportedLibrary?.source;
+ if (exportedSource != null) {
+ _newSources.add(exportedSource);
+ }
}
}
}
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index b20d702..ab1922f 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -21,22 +21,31 @@
import 'ast_properties.dart';
-bool isKnownFunction(Expression expression, {bool instanceMethods: false}) {
- Element element = null;
+bool isKnownFunction(Expression expression) {
+ var element = _getKnownElement(expression);
+ // First class functions and static methods, where we know the original
+ // declaration, will have an exact type, so we know a downcast will fail.
+ return element is FunctionElement ||
+ element is MethodElement && element.isStatic;
+}
+
+bool _hasStrictArrow(Expression expression) {
+ var element = _getKnownElement(expression);
+ return element is FunctionElement || element is MethodElement;
+}
+
+Element _getKnownElement(Expression expression) {
if (expression is ParenthesizedExpression) {
expression = (expression as ParenthesizedExpression).expression;
}
if (expression is FunctionExpression) {
- return true;
+ return expression.element;
} else if (expression is PropertyAccess) {
- element = expression.propertyName.staticElement;
+ return expression.propertyName.staticElement;
} else if (expression is Identifier) {
- element = expression.staticElement;
+ return expression.staticElement;
}
- // First class functions and static methods, where we know the original
- // declaration, will have an exact type, so we know a downcast will fail.
- return element is FunctionElement ||
- element is MethodElement && (instanceMethods || element.isStatic);
+ return null;
}
DartType _elementType(Element e) {
@@ -111,6 +120,7 @@
if (baseMethod == null || baseMethod.isStatic) return null;
return baseMethod.type;
}
+
return f;
}
@@ -226,14 +236,14 @@
void visitBinaryExpression(BinaryExpression node) {
var op = node.operator;
if (op.isUserDefinableOperator) {
- if (_isDynamicTarget(node.leftOperand)) {
+ var element = node.staticElement;
+ if (element == null) {
// Dynamic invocation
// TODO(vsm): Move this logic to the resolver?
if (op.type != TokenType.EQ_EQ && op.type != TokenType.BANG_EQ) {
_recordDynamicInvoke(node, node.leftOperand);
}
} else {
- var element = node.staticElement;
// Method invocation.
if (element is MethodElement) {
var type = element.type;
@@ -426,20 +436,18 @@
@override
void visitIndexExpression(IndexExpression node) {
var target = node.realTarget;
- if (_isDynamicTarget(target)) {
+ var element = node.staticElement;
+ if (element == null) {
_recordDynamicInvoke(node, target);
- } else {
- var element = node.staticElement;
- if (element is MethodElement) {
- var type = element.type;
- // Analyzer should enforce number of parameter types, but check in
- // case we have erroneous input.
- if (type.normalParameterTypes.isNotEmpty) {
- checkArgument(node.index, type.normalParameterTypes[0]);
- }
- } else {
- // TODO(vsm): Assert that the analyzer found an error here?
+ } else if (element is MethodElement) {
+ var type = element.type;
+ // Analyzer should enforce number of parameter types, but check in
+ // case we have erroneous input.
+ if (type.normalParameterTypes.isNotEmpty) {
+ checkArgument(node.index, type.normalParameterTypes[0]);
}
+ } else {
+ // TODO(vsm): Assert that the analyzer found an error here?
}
node.visitChildren(this);
}
@@ -523,7 +531,8 @@
@override
visitMethodInvocation(MethodInvocation node) {
var target = node.realTarget;
- if (_isDynamicTarget(target) && !_isObjectMethod(node, node.methodName)) {
+ var element = node.methodName.staticElement;
+ if (element == null && !_isObjectMethod(node, node.methodName)) {
_recordDynamicInvoke(node, target);
// Mark the tear-off as being dynamic, too. This lets us distinguish
@@ -548,7 +557,7 @@
@override
void visitPostfixExpression(PostfixExpression node) {
- _checkUnary(node);
+ _checkUnary(node, node.staticElement);
node.visitChildren(this);
}
@@ -562,7 +571,7 @@
if (node.operator.type == TokenType.BANG) {
checkBoolean(node.operand);
} else {
- _checkUnary(node);
+ _checkUnary(node, node.staticElement);
}
node.visitChildren(this);
}
@@ -751,8 +760,7 @@
}
void _checkFieldAccess(AstNode node, AstNode target, SimpleIdentifier field) {
- if ((_isDynamicTarget(target) || field.staticElement == null) &&
- !_isObjectProperty(target, field)) {
+ if (field.staticElement == null && !_isObjectProperty(target, field)) {
_recordDynamicInvoke(node, target);
}
node.visitChildren(this);
@@ -891,12 +899,13 @@
}
}
- void _checkUnary(/*PrefixExpression|PostfixExpression*/ node) {
+ void _checkUnary(
+ /*PrefixExpression|PostfixExpression*/ node, Element element) {
var op = node.operator;
if (op.isUserDefinableOperator ||
op.type == TokenType.PLUS_PLUS ||
op.type == TokenType.MINUS_MINUS) {
- if (_isDynamicTarget(node.operand)) {
+ if (element == null) {
_recordDynamicInvoke(node, node.operand);
}
// For ++ and --, even if it is not dynamic, we still need to check
@@ -963,7 +972,7 @@
DartType t = expr.staticType ?? DynamicTypeImpl.instance;
// Remove fuzzy arrow if possible.
- if (t is FunctionType && isKnownFunction(expr)) {
+ if (t is FunctionType && _hasStrictArrow(expr)) {
t = rules.functionTypeToConcreteType(typeProvider, t);
}
@@ -975,7 +984,7 @@
/// for the possibility of a call method). Returns null
/// if expression is not statically callable.
FunctionType _getTypeAsCaller(Expression node) {
- DartType t = node.staticType;
+ DartType t = _getStaticType(node);
if (node is SimpleIdentifier) {
Expression parent = node.parent;
if (parent is MethodInvocation) {
@@ -1004,27 +1013,12 @@
// a dynamic parameter type requires a dynamic call in general.
// However, as an optimization, if we have an original definition, we know
// dynamic is reified as Object - in this case a regular call is fine.
- if (isKnownFunction(call, instanceMethods: true)) {
+ if (_hasStrictArrow(call)) {
return false;
}
return rules.anyParameterType(ft, (pt) => pt.isDynamic);
}
- /// Returns `true` if the target expression is dynamic.
- bool _isDynamicTarget(Expression node) {
- if (node == null) return false;
-
- if (_isLibraryPrefix(node)) return false;
-
- // Null type happens when we have unknown identifiers, like a dart: import
- // that doesn't resolve.
- var type = node.staticType;
- return type == null || type.isDynamic;
- }
-
- bool _isLibraryPrefix(Expression node) =>
- node is SimpleIdentifier && node.staticElement is PrefixElement;
-
bool _isObjectGetter(Expression target, SimpleIdentifier id) {
PropertyAccessorElement element =
typeProvider.objectType.element.getGetter(id.name);
@@ -1045,7 +1039,7 @@
// TODO(jmesserly): we may eventually want to record if the whole operation
// (node) was dynamic, rather than the target, but this is an easier fit
// with what we used to do.
- setIsDynamicInvoke(target, true);
+ if (target != null) setIsDynamicInvoke(target, true);
}
/// Records an implicit cast for the [expression] from [fromType] to [toType].
@@ -1288,6 +1282,7 @@
seen.add(e.name);
}
}
+
subType.methods.forEach(checkHelper);
subType.accessors.forEach(checkHelper);
}
diff --git a/pkg/analyzer/test/generated/analysis_context_factory.dart b/pkg/analyzer/test/generated/analysis_context_factory.dart
index cca5d3b..f311756 100644
--- a/pkg/analyzer/test/generated/analysis_context_factory.dart
+++ b/pkg/analyzer/test/generated/analysis_context_factory.dart
@@ -97,6 +97,8 @@
Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
coreContext.setContents(coreSource, "");
coreUnit.librarySource = coreUnit.source = coreSource;
+ ClassElementImpl overrideClassElement =
+ ElementFactory.classElement2("_Override");
ClassElementImpl proxyClassElement = ElementFactory.classElement2("_Proxy");
proxyClassElement.constructors = <ConstructorElement>[
ElementFactory.constructorElement(proxyClassElement, '', true)
@@ -117,6 +119,7 @@
provider.nullType.element,
provider.numType.element,
objectClassElement,
+ overrideClassElement,
proxyClassElement,
provider.stackTraceType.element,
provider.stringType.element,
@@ -134,6 +137,9 @@
ConstTopLevelVariableElementImpl deprecatedTopLevelVariableElt =
ElementFactory.topLevelVariableElement3(
"deprecated", true, false, provider.deprecatedType);
+ TopLevelVariableElement overrideTopLevelVariableElt =
+ ElementFactory.topLevelVariableElement3(
+ "override", true, false, overrideClassElement.type);
{
ClassElement deprecatedElement = provider.deprecatedType.element;
InstanceCreationExpression initializer = AstFactory
@@ -147,12 +153,14 @@
deprecatedTopLevelVariableElt.constantInitializer = initializer;
}
coreUnit.accessors = <PropertyAccessorElement>[
- proxyTopLevelVariableElt.getter,
- deprecatedTopLevelVariableElt.getter
+ deprecatedTopLevelVariableElt.getter,
+ overrideTopLevelVariableElt.getter,
+ proxyTopLevelVariableElt.getter
];
coreUnit.topLevelVariables = <TopLevelVariableElement>[
- proxyTopLevelVariableElt,
- deprecatedTopLevelVariableElt
+ deprecatedTopLevelVariableElt,
+ overrideTopLevelVariableElt,
+ proxyTopLevelVariableElt
];
LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode(
coreContext, AstFactory.libraryIdentifier2(["dart", "core"]));
@@ -233,7 +241,9 @@
<TypeDefiningElement>[streamElement.typeParameters[0]],
null);
listenOnData.synthetic = true;
- List<DartType> parameterTypes = <DartType>[listenOnData.type,];
+ List<DartType> parameterTypes = <DartType>[
+ listenOnData.type,
+ ];
// TODO(brianwilkerson) This is missing the optional parameters.
MethodElementImpl listenMethod =
ElementFactory.methodElement('listen', returnType, parameterTypes);
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index 7ddd33b..aaefc2a 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -12,6 +12,7 @@
import 'package:analyzer/src/generated/element_resolver.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/java_engine_io.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source_io.dart';
@@ -827,6 +828,9 @@
subclass.constructors = <ConstructorElement>[subConstructor];
SuperConstructorInvocation invocation =
AstFactory.superConstructorInvocation();
+ AstFactory.classDeclaration(null, 'C', null, null, null, null, [
+ AstFactory.constructorDeclaration(null, 'C', null, [invocation])
+ ]);
_resolveInClass(invocation, subclass);
expect(invocation.staticElement, superConstructor);
_listener.assertNoErrors();
@@ -849,6 +853,9 @@
.superConstructorInvocation([
AstFactory.namedExpression2(parameterName, AstFactory.integer(0))
]);
+ AstFactory.classDeclaration(null, 'C', null, null, null, null, [
+ AstFactory.constructorDeclaration(null, 'C', null, [invocation])
+ ]);
_resolveInClass(invocation, subclass);
expect(invocation.staticElement, superConstructor);
expect(
@@ -949,8 +956,9 @@
_visitor.enclosingClass = null;
_visitor.nameScope = outerScope;
}
- } catch (exception) {
- throw new IllegalArgumentException("Could not resolve node", exception);
+ } catch (exception, stackTrace) {
+ throw new IllegalArgumentException(
+ "Could not resolve node", new CaughtException(exception, stackTrace));
}
}
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 3ff98f7..e14df67 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -31,7 +31,6 @@
const _Factory factory = const _Factory();
const _Literal literal = const _Literal();
const _MustCallSuper mustCallSuper = const _MustCallSuper();
-const _Override override = const _Override();
const _Protected protected = const _Protected();
const Required required = const Required();
class Required {
@@ -48,9 +47,6 @@
class _MustCallSuper {
const _MustCallSuper();
}
-class _Override {
- const _Override();
-}
class _Protected {
const _Protected();
}
@@ -2055,8 +2051,6 @@
void test_overrideOnNonOverridingField_invalid() {
Source source = addSource(r'''
-library dart.core;
-const override = null;
class A {
}
class B extends A {
@@ -2070,8 +2064,6 @@
void test_overrideOnNonOverridingGetter_invalid() {
Source source = addSource(r'''
-library dart.core;
-const override = null;
class A {
}
class B extends A {
@@ -2085,8 +2077,6 @@
void test_overrideOnNonOverridingMethod_invalid() {
Source source = addSource(r'''
-library dart.core;
-const override = null;
class A {
}
class B extends A {
@@ -2100,8 +2090,6 @@
void test_overrideOnNonOverridingSetter_invalid() {
Source source = addSource(r'''
-library dart.core;
-const override = null;
class A {
}
class B extends A {
diff --git a/pkg/analyzer/test/generated/non_hint_code_test.dart b/pkg/analyzer/test/generated/non_hint_code_test.dart
index 4ec1640..16ba3a9 100644
--- a/pkg/analyzer/test/generated/non_hint_code_test.dart
+++ b/pkg/analyzer/test/generated/non_hint_code_test.dart
@@ -488,8 +488,6 @@
void test_overrideOnNonOverridingField_inInterface() {
Source source = addSource(r'''
-library dart.core;
-const override = null;
class A {
int get a => 0;
void set b(_) {}
@@ -510,8 +508,6 @@
void test_overrideOnNonOverridingField_inSuperclass() {
Source source = addSource(r'''
-library dart.core;
-const override = null;
class A {
int get a => 0;
void set b(_) {}
@@ -532,8 +528,6 @@
void test_overrideOnNonOverridingGetter_inInterface() {
Source source = addSource(r'''
-library dart.core;
-const override = null;
class A {
int get m => 0;
}
@@ -548,8 +542,6 @@
void test_overrideOnNonOverridingGetter_inSuperclass() {
Source source = addSource(r'''
-library dart.core;
-const override = null;
class A {
int get m => 0;
}
@@ -564,8 +556,6 @@
void test_overrideOnNonOverridingMethod_inInterface() {
Source source = addSource(r'''
-library dart.core;
-const override = null;
class A {
int m() => 0;
}
@@ -580,8 +570,6 @@
void test_overrideOnNonOverridingMethod_inSuperclass() {
Source source = addSource(r'''
-library dart.core;
-const override = null;
class A {
int m() => 0;
}
@@ -594,10 +582,22 @@
verify([source]);
}
+ void test_overrideOnNonOverridingMethod_inSuperclass_abstract() {
+ Source source = addSource(r'''
+abstract class A {
+ int m();
+}
+class B extends A {
+ @override
+ int m() => 1;
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
void test_overrideOnNonOverridingSetter_inInterface() {
Source source = addSource(r'''
-library dart.core;
-const override = null;
class A {
set m(int x) {}
}
@@ -612,8 +612,6 @@
void test_overrideOnNonOverridingSetter_inSuperclass() {
Source source = addSource(r'''
-library dart.core;
-const override = null;
class A {
set m(int x) {}
}
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index fcd3a5f..dedab71 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -26,59 +26,6 @@
@reflectiveTest
class SimpleResolverTest extends ResolverTestCase {
- void fail_getter_and_setter_fromMixins_property_access() {
- // TODO(paulberry): it appears that auxiliaryElements isn't properly set on
- // a SimpleIdentifier that's inside a property access. This bug should be
- // fixed.
- Source source = addSource('''
-class B {}
-class M1 {
- get x => null;
- set x(value) {}
-}
-class M2 {
- get x => null;
- set x(value) {}
-}
-class C extends B with M1, M2 {}
-void main() {
- new C().x += 1;
-}
-''');
- LibraryElement library = resolve2(source);
- assertNoErrors(source);
- verify([source]);
- // Verify that both the getter and setter for "x" in "new C().x" refer to
- // the accessors defined in M2.
- FunctionDeclaration main =
- library.definingCompilationUnit.functions[0].computeNode();
- BlockFunctionBody body = main.functionExpression.body;
- ExpressionStatement stmt = body.block.statements[0];
- AssignmentExpression assignment = stmt.expression;
- PropertyAccess propertyAccess = assignment.leftHandSide;
- expect(
- propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2');
- expect(
- propertyAccess
- .propertyName.auxiliaryElements.staticElement.enclosingElement.name,
- 'M2');
- }
-
- void fail_staticInvocation() {
- Source source = addSource(r'''
-class A {
- static int get g => (a,b) => 0;
-}
-class B {
- f() {
- A.g(1,0);
- }
-}''');
- computeLibrarySourceErrors(source);
- assertNoErrors(source);
- verify([source]);
- }
-
void test_argumentResolution_required_matching() {
Source source = addSource(r'''
class A {
@@ -791,6 +738,45 @@
'M2');
}
+ @failingTest
+ void test_getter_and_setter_fromMixins_property_access() {
+ // TODO(paulberry): it appears that auxiliaryElements isn't properly set on
+ // a SimpleIdentifier that's inside a property access. This bug should be
+ // fixed.
+ Source source = addSource('''
+class B {}
+class M1 {
+ get x => null;
+ set x(value) {}
+}
+class M2 {
+ get x => null;
+ set x(value) {}
+}
+class C extends B with M1, M2 {}
+void main() {
+ new C().x += 1;
+}
+''');
+ LibraryElement library = resolve2(source);
+ assertNoErrors(source);
+ verify([source]);
+ // Verify that both the getter and setter for "x" in "new C().x" refer to
+ // the accessors defined in M2.
+ FunctionDeclaration main =
+ library.definingCompilationUnit.functions[0].computeNode();
+ BlockFunctionBody body = main.functionExpression.body;
+ ExpressionStatement stmt = body.block.statements[0];
+ AssignmentExpression assignment = stmt.expression;
+ PropertyAccess propertyAccess = assignment.leftHandSide;
+ expect(
+ propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2');
+ expect(
+ propertyAccess
+ .propertyName.auxiliaryElements.staticElement.enclosingElement.name,
+ 'M2');
+ }
+
void test_getter_fromMixins_bare_identifier() {
Source source = addSource('''
class B {}
@@ -926,6 +912,66 @@
verify([source]);
}
+ void test_import_prefix_doesNotExist() {
+ //
+ // The primary purpose of this test is to ensure that we are only getting a
+ // single error generated when the only problem is that an imported file
+ // does not exist.
+ //
+ Source source = addNamedSource(
+ "/a.dart",
+ r'''
+import 'missing.dart' as p;
+int a = p.q + p.r.s;
+String b = p.t(a) + p.u(v: 0);
+p.T c = new p.T();
+class D<E> extends p.T {
+ D(int i) : super(i);
+ p.U f = new p.V();
+}
+class F implements p.T {
+ p.T m(p.U u) => null;
+}
+class G extends Object with p.V {}
+class H extends D<p.W> {
+ H(int i) : super(i);
+}
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
+ verify([source]);
+ }
+
+ void test_import_show_doesNotExist() {
+ //
+ // The primary purpose of this test is to ensure that we are only getting a
+ // single error generated when the only problem is that an imported file
+ // does not exist.
+ //
+ Source source = addNamedSource(
+ "/a.dart",
+ r'''
+import 'missing.dart' show q, r, t, u, T, U, V, W;
+int a = q + r.s;
+String b = t(a) + u(v: 0);
+T c = new T();
+class D<E> extends T {
+ D(int i) : super(i);
+ U f = new V();
+}
+class F implements T {
+ T m(U u) => null;
+}
+class G extends Object with V {}
+class H extends D<W> {
+ H(int i) : super(i);
+}
+''');
+ computeLibrarySourceErrors(source);
+ assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
+ verify([source]);
+ }
+
void test_import_spaceInUri() {
addNamedSource(
"/sub folder/lib.dart",
@@ -1679,6 +1725,22 @@
verify([source]);
}
+ @failingTest
+ void test_staticInvocation() {
+ Source source = addSource(r'''
+class A {
+ static int get g => (a,b) => 0;
+}
+class B {
+ f() {
+ A.g(1,0);
+ }
+}''');
+ computeLibrarySourceErrors(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
/**
* Resolve the given source and verify that the arguments in a specific method invocation were
* correctly resolved.
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 6c5879f..2949909 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -121,9 +121,7 @@
check("f2", _isFutureOfDynamic);
check("f3", _isFutureOfInt);
- // This should be int when we handle the implicit Future<T> | T union
- // https://github.com/dart-lang/sdk/issues/25322
- check("f4", _isFutureOfDynamic);
+ check("f4", _isFutureOfInt);
check("f5", _isFutureOfInt);
check("g0", _isFutureOfDynamic);
@@ -131,9 +129,7 @@
check("g2", _isFutureOfDynamic);
check("g3", _isFutureOfInt);
- // This should be int when we handle the implicit Future<T> | T union
- // https://github.com/dart-lang/sdk/issues/25322
- check("g4", _isFutureOfDynamic);
+ check("g4", _isFutureOfInt);
check("g5", _isFutureOfInt);
}
@@ -181,9 +177,7 @@
check("f2", _isFutureOfDynamic);
check("f3", _isFutureOfInt);
- // This should be int when we handle the implicit Future<T> | T union
- // https://github.com/dart-lang/sdk/issues/25322
- check("f4", _isFutureOfDynamic);
+ check("f4", _isFutureOfInt);
check("f5", _isFutureOfInt);
check("g0", _isFutureOfDynamic);
@@ -191,9 +185,7 @@
check("g2", _isFutureOfDynamic);
check("g3", _isFutureOfInt);
- // This should be int when we handle the implicit Future<T> | T union
- // https://github.com/dart-lang/sdk/issues/25322
- check("g4", _isFutureOfDynamic);
+ check("g4", _isFutureOfInt);
check("g5", _isFutureOfInt);
}
diff --git a/pkg/analyzer/test/src/context/abstract_context.dart b/pkg/analyzer/test/src/context/abstract_context.dart
index be85eff..ba11f84 100644
--- a/pkg/analyzer/test/src/context/abstract_context.dart
+++ b/pkg/analyzer/test/src/context/abstract_context.dart
@@ -123,7 +123,7 @@
return new AnalysisContextImpl();
}
- DartSdk createDartSdk() => new MockSdk();
+ DartSdk createDartSdk() => new MockSdk(resourceProvider: resourceProvider);
Source newSource(String path, [String content = '']) {
File file = resourceProvider.newFile(path, content);
@@ -143,8 +143,8 @@
sdk = createDartSdk();
sdkResolver = new DartUriResolver(sdk);
resourceResolver = new ResourceUriResolver(resourceProvider);
- sourceFactory =
- new SourceFactory(<UriResolver>[sdkResolver, resourceResolver]);
+ sourceFactory = new SourceFactory(
+ <UriResolver>[sdkResolver, resourceResolver], null, resourceProvider);
context = createAnalysisContext();
if (options != null) {
context.analysisOptions = options;
diff --git a/pkg/analyzer/test/src/context/context_test.dart b/pkg/analyzer/test/src/context/context_test.dart
index 988db56..b005734 100644
--- a/pkg/analyzer/test/src/context/context_test.dart
+++ b/pkg/analyzer/test/src/context/context_test.dart
@@ -155,6 +155,43 @@
expect(entry.explicitlyAdded, isTrue);
}
+ void test_applyChanges_addNewImport_invalidateLibraryCycle() {
+ context.analysisOptions =
+ new AnalysisOptionsImpl.from(context.analysisOptions)
+ ..strongMode = true;
+ Source embedder = addSource(
+ '/a.dart',
+ r'''
+library a;
+import 'b.dart';
+//import 'c.dart';
+''');
+ addSource(
+ '/b.dart',
+ r'''
+library b;
+import 'a.dart';
+''');
+ addSource(
+ '/c.dart',
+ r'''
+library c;
+import 'b.dart';
+''');
+ _performPendingAnalysisTasks();
+ // Add a new import into a.dart, this should invalidate its library cycle.
+ // If it doesn't, we will get a task cycle exception.
+ context.setContents(
+ embedder,
+ r'''
+library a;
+import 'b.dart';
+import 'c.dart';
+''');
+ _performPendingAnalysisTasks();
+ expect(context.getCacheEntry(embedder).exception, isNull);
+ }
+
Future test_applyChanges_change() {
SourcesChangedListener listener = new SourcesChangedListener();
context.onSourcesChanged.listen(listener.onData);
@@ -378,7 +415,7 @@
expect(sources[0], same(libA));
libAElement = context.computeLibraryElement(libA);
importedLibraries = libAElement.importedLibraries;
- expect(importedLibraries, hasLength(1));
+ expect(importedLibraries, hasLength(2));
return pumpEventQueue().then((_) {
listener.assertEvent(wereSourcesAdded: true);
listener.assertEvent(wereSourcesAdded: true);
@@ -487,43 +524,6 @@
expect(context.getErrors(a).errors, hasLength(0));
}
- void test_applyChanges_addNewImport_invalidateLibraryCycle() {
- context.analysisOptions =
- new AnalysisOptionsImpl.from(context.analysisOptions)
- ..strongMode = true;
- Source embedder = addSource(
- '/a.dart',
- r'''
-library a;
-import 'b.dart';
-//import 'c.dart';
-''');
- addSource(
- '/b.dart',
- r'''
-library b;
-import 'a.dart';
-''');
- addSource(
- '/c.dart',
- r'''
-library c;
-import 'b.dart';
-''');
- _performPendingAnalysisTasks();
- // Add a new import into a.dart, this should invalidate its library cycle.
- // If it doesn't, we will get a task cycle exception.
- context.setContents(
- embedder,
- r'''
-library a;
-import 'b.dart';
-import 'c.dart';
-''');
- _performPendingAnalysisTasks();
- expect(context.getCacheEntry(embedder).exception, isNull);
- }
-
void test_cacheConsistencyValidator_computed_deleted() {
CacheConsistencyValidator validator = context.cacheConsistencyValidator;
var stat = PerformanceStatistics.cacheConsistencyValidationStatistics;
@@ -3750,6 +3750,7 @@
MethodInvocation invocation = statement.expression;
return invocation.argumentList.arguments[0];
}
+
{
Expression argument = find42();
expect(argument.staticParameterElement, isNull);
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index 6539e67..0ebc01f 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -29,7 +29,7 @@
static Future<List/*<T>*/> wait/*<T>*/(
Iterable<Future/*<T>*/> futures) => null;
- Future/*<R>*/ then/*<R>*/(/*=R*/ onValue(T value)) => null;
+ Future/*<R>*/ then/*<R>*/(onValue(T value)) => null;
}
abstract class Completer<T> {
@@ -194,6 +194,10 @@
/*=R*/ fold/*<R>*/(/*=R*/ initialValue,
/*=R*/ combine(/*=R*/ previousValue, E element));
+
+ Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(E element));
+
+ List<E> toList();
}
class List<E> implements Iterable<E> {
@@ -224,6 +228,9 @@
void print(Object object) {}
+const proxy = const _Proxy();
+class _Proxy { const _Proxy(); }
+
class _Override {
const _Override();
}
@@ -298,8 +305,7 @@
"dart:core": "/lib/core/core.dart",
};
- final resource.MemoryResourceProvider provider =
- new resource.MemoryResourceProvider();
+ final resource.MemoryResourceProvider provider;
final Map<String, String> uriMap;
@@ -311,8 +317,9 @@
@override
final List<SdkLibrary> sdkLibraries;
- MockSdk({bool dartAsync: true})
- : sdkLibraries = dartAsync ? _LIBRARIES : [_LIB_CORE],
+ MockSdk({bool dartAsync: true, resource.ResourceProvider resourceProvider})
+ : provider = resourceProvider ?? new resource.MemoryResourceProvider(),
+ sdkLibraries = dartAsync ? _LIBRARIES : [_LIB_CORE],
uriMap = dartAsync ? FULL_URI_MAP : NO_ASYNC_URI_MAP {
for (_MockSdkLibrary library in sdkLibraries) {
provider.newFile(library.path, library.content);
diff --git a/pkg/analyzer/test/src/summary/linker_test.dart b/pkg/analyzer/test/src/summary/linker_test.dart
index 196fb04..eb9e407 100644
--- a/pkg/analyzer/test/src/summary/linker_test.dart
+++ b/pkg/analyzer/test/src/summary/linker_test.dart
@@ -61,6 +61,42 @@
expect(bundle0.apiSignature, bundle1.apiSignature);
}
+ void test_apiSignature_orderChange() {
+ // A change to the order in which files are processed should not affect the
+ // API signature.
+ addNamedSource('/a.dart', 'class A {}');
+ var bundle0 = createPackageBundle('class B {}', path: '/b.dart');
+ addNamedSource('/b.dart', 'class B {}');
+ var bundle1 = createPackageBundle('class A {}', path: '/a.dart');
+ expect(bundle0.apiSignature, isNotEmpty);
+ expect(bundle1.apiSignature, isNotEmpty);
+ expect(bundle0.apiSignature, bundle1.apiSignature);
+ }
+
+ void test_apiSignature_unlinkedOnly() {
+ // The API signature of a package bundle should only contain unlinked
+ // information. In this test, the linked information for bundle2 and
+ // bundle3 refer to class C as existing in different files. But the
+ // unlinked information for bundle2 and bundle3 should be the same, so their
+ // API signatures should be the same.
+ addNamedSource('/a.dart', 'class C {}');
+ var bundle0 = createPackageBundle('', path: '/b.dart');
+ addNamedSource('/a.dart', '');
+ var bundle1 = createPackageBundle('class C {}', path: '/b.dart');
+ var text = '''
+import 'a.dart';
+import 'b.dart';
+class D extends C {}
+''';
+ addBundle('/bundle0.ds', bundle0);
+ var bundle2 = createPackageBundle(text, path: '/c.dart');
+ addBundle('/bundle1.ds', bundle1);
+ var bundle3 = createPackageBundle(text, path: '/c.dart');
+ expect(bundle2.apiSignature, isNotEmpty);
+ expect(bundle3.apiSignature, isNotEmpty);
+ expect(bundle2.apiSignature, bundle3.apiSignature);
+ }
+
void test_baseClass_genericWithAccessor() {
createLinker('''
class B<T> {
@@ -159,6 +195,33 @@
// No assertions--just make sure it doesn't crash.
}
+ void test_bundle_refers_to_bundle() {
+ var bundle1 = createPackageBundle(
+ '''
+var x = 0;
+''',
+ path: '/a.dart');
+ addBundle('/a.ds', bundle1);
+ var bundle2 = createPackageBundle(
+ '''
+import "a.dart";
+var y = x;
+''',
+ path: '/b.dart');
+ expect(bundle2.dependencies, hasLength(1));
+ expect(bundle2.dependencies[0].summaryPath, '/a.ds');
+ expect(bundle2.dependencies[0].apiSignature, bundle1.apiSignature);
+ addBundle('/a.ds', bundle1);
+ addBundle('/b.ds', bundle2);
+ createLinker('''
+import "b.dart";
+var z = y;
+''');
+ LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+ expect(_getVariable(library.getContainedName('z')).inferredType.toString(),
+ 'int');
+ }
+
void test_constCycle_viaLength() {
createLinker('''
class C {
@@ -206,7 +269,7 @@
var x = () {};
''',
path: '/a.dart');
- addBundle(bundle);
+ addBundle('/a.ds', bundle);
createLinker('''
import 'a.dart';
var y = x;
@@ -228,7 +291,7 @@
class E {}
''',
path: '/a.dart');
- addBundle(bundle);
+ addBundle('/a.ds', bundle);
createLinker('''
import 'a.dart';
var y = C.x;
@@ -341,7 +404,7 @@
var y = x; // Inferred type: dynamic
''',
path: '/a.dart');
- addBundle(bundle);
+ addBundle('/a.ds', bundle);
createLinker('''
import 'a.dart';
var z = y; // Inferred type: dynamic
@@ -359,7 +422,7 @@
}
''',
path: '/a.dart');
- addBundle(bundle);
+ addBundle('/a.ds', bundle);
createLinker('''
import 'a.dart';
var x = new C().f; // Inferred type: int
@@ -377,7 +440,7 @@
}
''',
path: '/a.dart');
- addBundle(bundle);
+ addBundle('/a.ds', bundle);
createLinker('''
import 'a.dart';
class D {
@@ -400,7 +463,7 @@
}
''',
path: '/a.dart');
- addBundle(bundle);
+ addBundle('/a.ds', bundle);
createLinker('''
import 'a.dart';
var x = new C().f(0); // Inferred type: int
@@ -421,7 +484,7 @@
}
''',
path: '/a.dart');
- addBundle(bundle);
+ addBundle('/a.ds', bundle);
createLinker('''
import 'a.dart';
class D extends C {
@@ -448,7 +511,7 @@
}
''',
path: '/a.dart');
- addBundle(bundle);
+ addBundle('/a.ds', bundle);
createLinker('''
import 'a.dart';
var x = new C().f(); // Inferred type: int
@@ -469,7 +532,7 @@
}
''',
path: '/a.dart');
- addBundle(bundle);
+ addBundle('/a.ds', bundle);
createLinker('''
import 'a.dart';
class D extends C {
@@ -486,7 +549,7 @@
void test_inferredTypeFromOutsideBuildUnit_staticField() {
var bundle =
createPackageBundle('class C { static var f = 0; }', path: '/a.dart');
- addBundle(bundle);
+ addBundle('/a.ds', bundle);
createLinker('import "a.dart"; var x = C.f;', path: '/b.dart');
expect(
_getVariable(linker
@@ -499,7 +562,7 @@
void test_inferredTypeFromOutsideBuildUnit_topLevelVariable() {
var bundle = createPackageBundle('var a = 0;', path: '/a.dart');
- addBundle(bundle);
+ addBundle('/a.ds', bundle);
createLinker('import "a.dart"; var b = a;', path: '/b.dart');
expect(
_getVariable(linker
@@ -670,7 +733,7 @@
ref.localIndex = 1234;
}
}
- addBundle(bundle);
+ addBundle('/a.ds', bundle);
createLinker('''
import 'a.dart';
var y = x;
diff --git a/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart b/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
index e446d19..07ce00f 100644
--- a/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
+++ b/pkg/analyzer/test/src/summary/package_bundle_reader_test.dart
@@ -10,6 +10,7 @@
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/general.dart';
import 'package:typed_mock/typed_mock.dart';
import 'package:unittest/unittest.dart';
@@ -92,6 +93,19 @@
expect(entry2.getValue(CONTAINING_LIBRARIES), unorderedEquals([source1]));
}
+ test_compute_LINE_INFO_hasLineStarts() {
+ when(unlinkedUnit1.lineStarts).thenReturn(<int>[10, 20, 30]);
+ bool success = provider.compute(entry1, LINE_INFO);
+ expect(success, isTrue);
+ expect(entry1.getValue(LINE_INFO).lineStarts, <int>[10, 20, 30]);
+ }
+
+ test_compute_LINE_INFO_emptyLineStarts() {
+ when(unlinkedUnit1.lineStarts).thenReturn(<int>[]);
+ bool success = provider.compute(entry1, LINE_INFO);
+ expect(success, isFalse);
+ }
+
test_compute_SOURCE_KIND_librarySource() {
bool success = provider.compute(entry1, SOURCE_KIND);
expect(success, isTrue);
@@ -113,7 +127,8 @@
@reflectiveTest
class SummaryDataStoreTest {
- SummaryDataStore dataStore = new SummaryDataStore(<String>[]);
+ SummaryDataStore dataStore =
+ new SummaryDataStore(<String>[], recordDependencyInfo: true);
PackageBundle bundle1 = new _PackageBundleMock();
PackageBundle bundle2 = new _PackageBundleMock();
@@ -134,6 +149,7 @@
.thenReturn(<UnlinkedUnit>[unlinkedUnit11, unlinkedUnit12]);
when(bundle1.linkedLibraryUris).thenReturn(<String>['package:p1/u1.dart']);
when(bundle1.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary1]);
+ when(bundle1.apiSignature).thenReturn('signature1');
dataStore.addBundle('/p1.ds', bundle1);
// bundle2
when(unlinkedUnit21.publicNamespace).thenReturn(_namespaceWithParts([]));
@@ -141,11 +157,22 @@
when(bundle2.unlinkedUnits).thenReturn(<UnlinkedUnit>[unlinkedUnit21]);
when(bundle2.linkedLibraryUris).thenReturn(<String>['package:p2/u1.dart']);
when(bundle2.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary2]);
+ when(bundle2.apiSignature).thenReturn('signature2');
dataStore.addBundle('/p2.ds', bundle2);
}
test_addBundle() {
expect(dataStore.bundles, unorderedEquals([bundle1, bundle2]));
+ expect(dataStore.dependencies[0].summaryPath, '/p1.ds');
+ expect(dataStore.dependencies[0].apiSignature, 'signature1');
+ expect(dataStore.dependencies[0].includedPackageNames, ['p1']);
+ expect(dataStore.dependencies[0].includesFileUris, false);
+ expect(dataStore.dependencies[0].includesDartUris, false);
+ expect(dataStore.dependencies[1].summaryPath, '/p2.ds');
+ expect(dataStore.dependencies[1].apiSignature, 'signature2');
+ expect(dataStore.dependencies[1].includedPackageNames, ['p2']);
+ expect(dataStore.dependencies[1].includesFileUris, false);
+ expect(dataStore.dependencies[1].includesDartUris, false);
expect(dataStore.uriToSummaryPath,
containsPair('package:p1/u1.dart', '/p1.ds'));
// unlinkedMap
@@ -164,6 +191,47 @@
containsPair('package:p2/u1.dart', linkedLibrary2));
}
+ test_addBundle_dartUris() {
+ PackageBundle bundle = new _PackageBundleMock();
+ when(bundle.unlinkedUnitUris).thenReturn(<String>['dart:core']);
+ when(bundle.unlinkedUnits).thenReturn(<UnlinkedUnit>[unlinkedUnit11]);
+ when(bundle.linkedLibraryUris).thenReturn(<String>['dart:core']);
+ when(bundle.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary1]);
+ when(bundle.apiSignature).thenReturn('signature');
+ dataStore.addBundle('/p3.ds', bundle);
+ expect(dataStore.dependencies.last.includedPackageNames, []);
+ expect(dataStore.dependencies.last.includesFileUris, false);
+ expect(dataStore.dependencies.last.includesDartUris, true);
+ }
+
+ test_addBundle_fileUris() {
+ PackageBundle bundle = new _PackageBundleMock();
+ when(bundle.unlinkedUnitUris).thenReturn(<String>['file:/foo.dart']);
+ when(bundle.unlinkedUnits).thenReturn(<UnlinkedUnit>[unlinkedUnit11]);
+ when(bundle.linkedLibraryUris).thenReturn(<String>['file:/foo.dart']);
+ when(bundle.linkedLibraries).thenReturn(<LinkedLibrary>[linkedLibrary1]);
+ when(bundle.apiSignature).thenReturn('signature');
+ dataStore.addBundle('/p3.ds', bundle);
+ expect(dataStore.dependencies.last.includedPackageNames, []);
+ expect(dataStore.dependencies.last.includesFileUris, true);
+ expect(dataStore.dependencies.last.includesDartUris, false);
+ }
+
+ test_addBundle_multiProject() {
+ PackageBundle bundle = new _PackageBundleMock();
+ when(bundle.unlinkedUnitUris)
+ .thenReturn(<String>['package:p2/u1.dart', 'package:p1/u1.dart']);
+ when(bundle.unlinkedUnits)
+ .thenReturn(<UnlinkedUnit>[unlinkedUnit21, unlinkedUnit11]);
+ when(bundle.linkedLibraryUris)
+ .thenReturn(<String>['package:p2/u1.dart', 'package:p1/u1.dart']);
+ when(bundle.linkedLibraries)
+ .thenReturn(<LinkedLibrary>[linkedLibrary2, linkedLibrary1]);
+ when(bundle.apiSignature).thenReturn('signature');
+ dataStore.addBundle('/p3.ds', bundle);
+ expect(dataStore.dependencies.last.includedPackageNames, ['p1', 'p2']);
+ }
+
test_getContainingLibraryUris_libraryUri() {
String partUri = 'package:p1/u1.dart';
List<String> uris = dataStore.getContainingLibraryUris(partUri);
diff --git a/pkg/analyzer/test/src/summary/pub_summary_test.dart b/pkg/analyzer/test/src/summary/pub_summary_test.dart
new file mode 100644
index 0000000..acc22cc
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/pub_summary_test.dart
@@ -0,0 +1,261 @@
+// 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/dart/element/element.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/source/package_map_resolver.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/summary/idl.dart';
+import 'package:analyzer/src/summary/pub_summary.dart';
+import 'package:analyzer/src/summary/summarize_elements.dart';
+import 'package:path/path.dart' as pathos;
+import 'package:unittest/unittest.dart' hide ERROR;
+
+import '../../reflective_tests.dart';
+import '../../utils.dart';
+import '../context/abstract_context.dart';
+
+main() {
+ initializeTestEnvironment();
+ runReflectiveTests(PubSummaryManagerTest);
+}
+
+@reflectiveTest
+class PubSummaryManagerTest extends AbstractContextTest {
+ static const String CACHE = '/home/.pub-cache/hosted/pub.dartlang.org';
+
+ static Map<DartSdk, PackageBundle> sdkBundleMap = <DartSdk, PackageBundle>{};
+
+ PubSummaryManager manager;
+
+ void setUp() {
+ super.setUp();
+ manager = new PubSummaryManager(resourceProvider, '_.temp');
+ }
+
+ test_getLinkedBundles_noCycles() async {
+ resourceProvider.newFile(
+ '$CACHE/aaa/lib/a.dart',
+ '''
+class A {}
+int a;
+''');
+ resourceProvider.newFile(
+ '$CACHE/bbb/lib/b.dart',
+ '''
+import 'package:aaa/a.dart';
+A b;
+''');
+
+ // Configure packages resolution.
+ Folder libFolderA = resourceProvider.newFolder('$CACHE/aaa/lib');
+ Folder libFolderB = resourceProvider.newFolder('$CACHE/bbb/lib');
+ context.sourceFactory = new SourceFactory(<UriResolver>[
+ sdkResolver,
+ resourceResolver,
+ new PackageMapUriResolver(resourceProvider, {
+ 'aaa': [libFolderA],
+ 'bbb': [libFolderB],
+ })
+ ]);
+
+ // Ensure unlinked bundles.
+ manager.getUnlinkedBundles(context);
+ await manager.onUnlinkedComplete;
+
+ // Now we should be able to get linked bundles.
+ PackageBundle sdkBundle = getSdkBundle(sdk);
+ List<LinkedPubPackage> linkedPackages =
+ manager.getLinkedBundles(context, sdkBundle);
+ expect(linkedPackages, hasLength(2));
+
+ // package:aaa
+ {
+ LinkedPubPackage linkedPackage = linkedPackages
+ .singleWhere((linkedPackage) => linkedPackage.package.name == 'aaa');
+ PackageBundle unlinked = linkedPackage.unlinked;
+ PackageBundle linked = linkedPackage.linked;
+ expect(unlinked, isNotNull);
+ expect(linked, isNotNull);
+ expect(unlinked.unlinkedUnitUris, ['package:aaa/a.dart']);
+ expect(linked.linkedLibraryUris, ['package:aaa/a.dart']);
+ // Prepare linked `package:aaa/a.dart`.
+ UnlinkedUnit unlinkedUnitA = unlinked.unlinkedUnits[0];
+ LinkedLibrary linkedLibraryA = linked.linkedLibraries[0];
+ LinkedUnit linkedUnitA = linkedLibraryA.units[0];
+ // int a;
+ {
+ UnlinkedVariable a = unlinkedUnitA.variables[0];
+ expect(a.name, 'a');
+ _assertLinkedNameReference(unlinkedUnitA, linkedLibraryA, linkedUnitA,
+ a.type.reference, 'int', 'dart:core');
+ }
+ }
+
+ // package:bbb
+ {
+ LinkedPubPackage linkedPackage = linkedPackages
+ .singleWhere((linkedPackage) => linkedPackage.package.name == 'bbb');
+ PackageBundle unlinked = linkedPackage.unlinked;
+ PackageBundle linked = linkedPackage.linked;
+ expect(unlinked, isNotNull);
+ expect(linked, isNotNull);
+ expect(unlinked.unlinkedUnitUris, ['package:bbb/b.dart']);
+ expect(linked.linkedLibraryUris, ['package:bbb/b.dart']);
+ // Prepare linked `package:bbb/b.dart`.
+ UnlinkedUnit unlinkedUnit = unlinked.unlinkedUnits[0];
+ LinkedLibrary linkedLibrary = linked.linkedLibraries[0];
+ LinkedUnit linkedUnit = linkedLibrary.units[0];
+ // A b;
+ {
+ UnlinkedVariable b = unlinkedUnit.variables[0];
+ expect(b.name, 'b');
+ _assertLinkedNameReference(unlinkedUnit, linkedLibrary, linkedUnit,
+ b.type.reference, 'A', 'package:aaa/a.dart');
+ }
+ }
+ }
+
+ test_getUnlinkedBundles() async {
+ // Create package files.
+ resourceProvider.newFile(
+ '$CACHE/aaa/lib/a.dart',
+ '''
+class A {}
+''');
+ resourceProvider.newFile(
+ '$CACHE/aaa/lib/src/a2.dart',
+ '''
+class A2 {}
+''');
+ resourceProvider.newFile(
+ '$CACHE/bbb/lib/b.dart',
+ '''
+class B {}
+''');
+
+ // Configure packages resolution.
+ Folder libFolderA = resourceProvider.newFolder('$CACHE/aaa/lib');
+ Folder libFolderB = resourceProvider.newFolder('$CACHE/bbb/lib');
+ context.sourceFactory = new SourceFactory(<UriResolver>[
+ sdkResolver,
+ resourceResolver,
+ new PackageMapUriResolver(resourceProvider, {
+ 'aaa': [libFolderA],
+ 'bbb': [libFolderB],
+ })
+ ]);
+
+ // No unlinked bundles yet.
+ {
+ Map<PubPackage, PackageBundle> bundles =
+ manager.getUnlinkedBundles(context);
+ expect(bundles, isEmpty);
+ }
+
+ // The requested unlinked bundles must be available after the wait.
+ await manager.onUnlinkedComplete;
+ {
+ Map<PubPackage, PackageBundle> bundles =
+ manager.getUnlinkedBundles(context);
+ expect(bundles, hasLength(2));
+ {
+ PackageBundle bundle = _getBundleByPackageName(bundles, 'aaa');
+ expect(bundle.linkedLibraryUris, isEmpty);
+ expect(bundle.unlinkedUnitUris,
+ ['package:aaa/a.dart', 'package:aaa/src/a2.dart']);
+ expect(bundle.unlinkedUnits, hasLength(2));
+ expect(bundle.unlinkedUnits[0].classes.map((c) => c.name), ['A']);
+ expect(bundle.unlinkedUnits[1].classes.map((c) => c.name), ['A2']);
+ }
+ {
+ PackageBundle bundle = _getBundleByPackageName(bundles, 'bbb');
+ expect(bundle.linkedLibraryUris, isEmpty);
+ expect(bundle.unlinkedUnitUris, ['package:bbb/b.dart']);
+ expect(bundle.unlinkedUnits, hasLength(1));
+ expect(bundle.unlinkedUnits[0].classes.map((c) => c.name), ['B']);
+ }
+ }
+
+ // The files must be created.
+ File fileA = libFolderA.parent.getChildAssumingFile('unlinked.ds');
+ File fileB = libFolderB.parent.getChildAssumingFile('unlinked.ds');
+ expect(fileA.exists, isTrue);
+ expect(fileB.exists, isTrue);
+ }
+
+ test_getUnlinkedBundles_nullPackageMap() async {
+ context.sourceFactory =
+ new SourceFactory(<UriResolver>[sdkResolver, resourceResolver]);
+ Map<PubPackage, PackageBundle> bundles =
+ manager.getUnlinkedBundles(context);
+ expect(bundles, isEmpty);
+ }
+
+ test_isPathInPubCache_posix() {
+ expect(
+ PubSummaryManager.isPathInPubCache(pathos.posix,
+ '/home/.pub-cache/hosted/pub.dartlang.org/foo/lib/bar.dart'),
+ isTrue);
+ expect(
+ PubSummaryManager.isPathInPubCache(
+ pathos.posix, '/home/.pub-cache/foo/lib/bar.dart'),
+ isTrue);
+ expect(
+ PubSummaryManager.isPathInPubCache(
+ pathos.posix, '/home/sources/dart/foo/lib/bar.dart'),
+ isFalse);
+ }
+
+ test_isPathInPubCache_windows() {
+ expect(
+ PubSummaryManager.isPathInPubCache(pathos.windows,
+ r'C:\Users\user\Setters\Pub\Cache\hosted\foo\lib\bar.dart'),
+ isTrue);
+ expect(
+ PubSummaryManager.isPathInPubCache(
+ pathos.windows, r'C:\Users\user\Sources\Dart\foo\lib\bar.dart'),
+ isFalse);
+ }
+
+ void _assertLinkedNameReference(
+ UnlinkedUnit unlinkedUnit,
+ LinkedLibrary linkedLibrary,
+ LinkedUnit linkedUnit,
+ int typeNameReference,
+ String expectedName,
+ String expectedDependencyUri) {
+ expect(unlinkedUnit.references[typeNameReference].name, expectedName);
+ int typeNameDependency =
+ linkedUnit.references[typeNameReference].dependency;
+ expect(linkedLibrary.dependencies[typeNameDependency].uri,
+ expectedDependencyUri);
+ }
+
+ /**
+ * Compute element based summary bundle for the given [sdk].
+ */
+ static PackageBundle getSdkBundle(DartSdk sdk) {
+ return sdkBundleMap.putIfAbsent(sdk, () {
+ PackageBundleAssembler assembler = new PackageBundleAssembler();
+ for (SdkLibrary sdkLibrary in sdk.sdkLibraries) {
+ String uriStr = sdkLibrary.shortName;
+ Source source = sdk.mapDartUri(uriStr);
+ LibraryElement libraryElement =
+ sdk.context.computeLibraryElement(source);
+ assembler.serializeLibraryElement(libraryElement);
+ }
+ List<int> bytes = assembler.assemble().toBuffer();
+ return new PackageBundle.fromBuffer(bytes);
+ });
+ }
+
+ static PackageBundle _getBundleByPackageName(
+ Map<PubPackage, PackageBundle> bundles, String name) {
+ PubPackage package =
+ bundles.keys.singleWhere((package) => package.name == name);
+ return bundles[package];
+ }
+}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_test.dart b/pkg/analyzer/test/src/summary/resynthesize_test.dart
index b6e8b30..679741d 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_test.dart
@@ -107,14 +107,16 @@
expect(resynthesized.imports.length, original.imports.length,
reason: 'imports');
for (int i = 0; i < resynthesized.imports.length; i++) {
- compareImportElements(resynthesized.imports[i], original.imports[i],
- 'import ${original.imports[i].uri}');
+ ImportElement originalImport = original.imports[i];
+ compareImportElements(
+ resynthesized.imports[i], originalImport, originalImport.toString());
}
expect(resynthesized.exports.length, original.exports.length,
reason: 'exports');
for (int i = 0; i < resynthesized.exports.length; i++) {
- compareExportElements(resynthesized.exports[i], original.exports[i],
- 'export ${original.exports[i].uri}');
+ ExportElement originalExport = original.exports[i];
+ compareExportElements(
+ resynthesized.exports[i], originalExport, originalExport.toString());
}
expect(resynthesized.nameLength, original.nameLength);
compareNamespaces(resynthesized.publicNamespace, original.publicNamespace,
@@ -1164,6 +1166,7 @@
}
return new LinkedLibrary.fromBuffer(serialized.linked.toBuffer());
}
+
Map<String, LinkedLibrary> linkedSummaries = <String, LinkedLibrary>{
library.source.uri.toString(): getLinkedSummaryFor(library)
};
@@ -1328,6 +1331,13 @@
return false;
} else if (modifier == Modifier.SYNTHETIC) {
return element.isSynthetic;
+ } else if (modifier == Modifier.URI_EXISTS) {
+ if (element is ExportElement) {
+ return element.uriExists;
+ } else if (element is ImportElement) {
+ return element.uriExists;
+ }
+ return false;
}
throw new UnimplementedError(
'Modifier $modifier for ${element?.runtimeType}');
@@ -1394,6 +1404,7 @@
}
return new LinkedLibrary.fromBuffer(serialized.linked.toBuffer());
}
+
Map<String, LinkedLibrary> linkedSummaries = <String, LinkedLibrary>{
library.source.uri.toString(): getLinkedSummaryFor(library)
};
diff --git a/pkg/analyzer/test/src/summary/summarize_ast_test.dart b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
index 0ac5099..e3c7f52 100644
--- a/pkg/analyzer/test/src/summary/summarize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
@@ -15,6 +15,7 @@
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/link.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/summary/summarize_ast.dart';
import 'package:analyzer/src/summary/summarize_elements.dart';
import 'package:unittest/unittest.dart';
@@ -204,7 +205,7 @@
@override
void serializeLibraryText(String text, {bool allowErrors: false}) {
- Map<String, UnlinkedUnitBuilder> uriToUnit = this.uriToUnit;
+ Map<String, UnlinkedUnitBuilder> uriToUnit = this._filesToLink.uriToUnit;
LinkerInputs linkerInputs = createLinkerInputs(text);
linked = link(linkerInputs.linkedLibraries, linkerInputs.getDependency,
linkerInputs.getUnit, strongMode)[linkerInputs.testDartUri.toString()];
@@ -287,23 +288,9 @@
*/
abstract class SummaryLinkerTest {
/**
- * Map from absolute URI to the [UnlinkedUnit] for each compilation unit
- * passed to [addNamedSource].
+ * Information about the files to be linked.
*/
- Map<String, UnlinkedUnitBuilder> uriToUnit = <String, UnlinkedUnitBuilder>{};
-
- /**
- * Map from absolute URI to the [LinkedLibrary] for each compilation unit in a
- * package bundle passed to [addBundle].
- */
- Map<String, LinkedLibrary> _dependentLinkedLibraries =
- <String, LinkedLibrary>{};
-
- /**
- * Map from absolute URI to the [UnlinkedUnit] for each compilation unit in a
- * package bundle passed to [addBundle].
- */
- Map<String, UnlinkedUnit> _dependentUnlinkedUnits = <String, UnlinkedUnit>{};
+ _FilesToLink _filesToLink = new _FilesToLink();
/**
* A test will set this to `true` if it contains `import`, `export`, or
@@ -315,15 +302,8 @@
* Add the given package bundle as a dependency so that it may be referenced
* by the files under test.
*/
- void addBundle(PackageBundle bundle) {
- for (int i = 0; i < bundle.linkedLibraryUris.length; i++) {
- _dependentLinkedLibraries[bundle.linkedLibraryUris[i]] =
- bundle.linkedLibraries[i];
- }
- for (int i = 0; i < bundle.unlinkedUnitUris.length; i++) {
- _dependentUnlinkedUnits[bundle.unlinkedUnitUris[i]] =
- bundle.unlinkedUnits[i];
- }
+ void addBundle(String path, PackageBundle bundle) {
+ _filesToLink.summaryDataStore.addBundle(path, bundle);
}
/**
@@ -333,7 +313,7 @@
Source addNamedSource(String filePath, String contents) {
CompilationUnit unit = _parseText(contents);
UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
- uriToUnit[absUri(filePath)] = unlinkedUnit;
+ _filesToLink.uriToUnit[absUri(filePath)] = unlinkedUnit;
// Tests using SummaryLinkerTest don't actually need the returned
// Source, so we can safely return `null`.
return null;
@@ -343,19 +323,16 @@
Uri testDartUri = Uri.parse(absUri(path));
CompilationUnit unit = _parseText(text);
UnlinkedUnitBuilder unlinkedDefiningUnit = serializeAstUnlinked(unit);
- uriToUnit[testDartUri.toString()] = unlinkedDefiningUnit;
+ _filesToLink.uriToUnit[testDartUri.toString()] = unlinkedDefiningUnit;
LinkerInputs linkerInputs = new LinkerInputs(
allowMissingFiles,
- uriToUnit,
+ _filesToLink.uriToUnit,
testDartUri,
unlinkedDefiningUnit,
- _dependentLinkedLibraries,
- _dependentUnlinkedUnits);
- // Reset uriToUnit, _dependentLinkedLibraries, and _dependentUnlinkedUnits
- // in case the test needs to start a new package bundle.
- uriToUnit = <String, UnlinkedUnitBuilder>{};
- _dependentLinkedLibraries = <String, LinkedLibrary>{};
- _dependentUnlinkedUnits = <String, UnlinkedUnit>{};
+ _filesToLink.summaryDataStore.linkedMap,
+ _filesToLink.summaryDataStore.unlinkedMap);
+ // Reset _filesToLink in case the test needs to start a new package bundle.
+ _filesToLink = new _FilesToLink();
return linkerInputs;
}
@@ -368,6 +345,7 @@
PackageBundleBuilder createPackageBundle(String text,
{String path: '/test.dart'}) {
PackageBundleAssembler assembler = new PackageBundleAssembler();
+ assembler.recordDependencies(_filesToLink.summaryDataStore);
LinkerInputs linkerInputs = createLinkerInputs(text, path: path);
Map<String, LinkedLibraryBuilder> linkedLibraries = link(
linkerInputs.linkedLibraries,
@@ -390,6 +368,27 @@
Token token = scanner.tokenize();
Parser parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER);
parser.parseGenericMethods = true;
- return parser.parseCompilationUnit(token);
+ CompilationUnit unit = parser.parseCompilationUnit(token);
+ unit.lineInfo = new LineInfo(scanner.lineStarts);
+ return unit;
}
}
+
+/**
+ * [_FilesToLink] stores information about a set of files to be linked together.
+ * This information is grouped into a class to allow it to be reset easily when
+ * [SummaryLinkerTest.createLinkerInputs] is called.
+ */
+class _FilesToLink {
+ /**
+ * Map from absolute URI to the [UnlinkedUnit] for each compilation unit
+ * passed to [addNamedSource].
+ */
+ Map<String, UnlinkedUnitBuilder> uriToUnit = <String, UnlinkedUnitBuilder>{};
+
+ /**
+ * Information about summaries to be included in the link process.
+ */
+ SummaryDataStore summaryDataStore =
+ new SummaryDataStore([], recordDependencyInfo: true);
+}
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index d3e94d3..d5f2876 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -8659,6 +8659,17 @@
expectedTargetUnit: 2);
}
+ test_lineStarts() {
+ String text = '''
+int foo;
+class Test {}
+
+int bar;'''
+ .replaceAll('\r\n', '\n');
+ serializeLibraryText(text);
+ expect(unlinkedUnits[0].lineStarts, [0, 9, 23, 24]);
+ }
+
test_linked_reference_reuse() {
if (skipFullyLinkedData) {
return;
diff --git a/pkg/analyzer/test/src/summary/test_all.dart b/pkg/analyzer/test/src/summary/test_all.dart
index 6ad0f2f..d669d0e 100644
--- a/pkg/analyzer/test/src/summary/test_all.dart
+++ b/pkg/analyzer/test/src/summary/test_all.dart
@@ -16,6 +16,7 @@
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 'pub_summary_test.dart' as pub_summary_test;
import 'resynthesize_ast_test.dart' as resynthesize_ast_test;
import 'resynthesize_strong_test.dart' as resynthesize_strong_test;
import 'resynthesize_test.dart' as resynthesize_test;
@@ -37,6 +38,7 @@
name_filter_test.main();
package_bundle_reader_test.main();
prelinker_test.main();
+ pub_summary_test.main();
resynthesize_ast_test.main();
resynthesize_strong_test.main();
resynthesize_test.main();
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index f7ce4b2..ab82982 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -2687,6 +2687,18 @@
''');
}
+ void test_methodTearoffStrictArrow() {
+ // Regression test for https://github.com/dart-lang/sdk/issues/26393
+ checkFile(r'''
+class A {
+ void foo(dynamic x) {}
+ void test(void f(int x)) {
+ test(foo);
+ }
+}
+ ''');
+ }
+
void test_mixinOverrideOfGrandInterface_interfaceOfAbstractSuperclass() {
checkFile('''
class A {}
@@ -2965,6 +2977,16 @@
''');
}
+ void test_optionalParams() {
+ // Regression test for https://github.com/dart-lang/sdk/issues/26155
+ checkFile(r'''
+void takesF(void f(int x)) {
+ takesF(/*info:INFERRED_TYPE_CLOSURE,info:INFERRED_TYPE_CLOSURE*/([x]) { bool z = x.isEven; });
+ takesF(/*info:INFERRED_TYPE_CLOSURE*/(y) { bool z = y.isEven; });
+}
+ ''');
+ }
+
void test_privateOverride() {
addFile(
'''
@@ -3002,6 +3024,44 @@
''');
}
+ void test_proxy() {
+ checkFile(r'''
+@proxy class C {}
+@proxy class D {
+ var f;
+ m() => null;
+ operator -() => null;
+ operator +(int other) => null;
+ operator [](int index) => null;
+ call() => null;
+}
+@proxy class F implements Function { noSuchMethod(i) => 42; }
+
+
+m() {
+ D d = new D();
+ d.m();
+ d.m;
+ d.f;
+ -d;
+ d + 7;
+ d[7];
+ d();
+
+ C c = new C();
+ /*info:DYNAMIC_INVOKE*/c.m();
+ /*info:DYNAMIC_INVOKE*/c.m;
+ /*info:DYNAMIC_INVOKE*/-c;
+ /*info:DYNAMIC_INVOKE*/c + 7;
+ /*info:DYNAMIC_INVOKE*/c[7];
+ /*error:INVOCATION_OF_NON_FUNCTION,info:DYNAMIC_INVOKE*/c();
+
+ F f = new F();
+ /*info:DYNAMIC_INVOKE*/f();
+}
+ ''');
+ }
+
void test_redirectingConstructor() {
checkFile('''
class A {
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 4dbcbfe..816d2d6 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -900,7 +900,7 @@
import 'dart:async';
Future test() async {
dynamic d;
- List<int> l0 = /*warning:DOWN_CAST_COMPOSITE should be pass*/await /*pass should be info:INFERRED_TYPE_LITERAL*/[d];
+ List<int> l0 = await /*info:INFERRED_TYPE_LITERAL*/[/*info:DYNAMIC_CAST*/d];
List<int> l1 = await /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(/*info:INFERRED_TYPE_LITERAL*/[/*info:DYNAMIC_CAST*/d]);
}
''');
@@ -1523,7 +1523,53 @@
checkFile('''
import 'dart:async';
Future f;
-Future<int> t1 = f.then((_) => new Future<int>.value(42));
+Future<int> t1 = f.then((_) async => await new Future<int>.value(3));
+Future<int> t2 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) async {return await new Future<int>.value(3);});
+Future<int> t3 = f.then((_) async => 3);
+Future<int> t4 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) async {return 3;});
+Future<int> t5 = f.then((_) => new Future<int>.value(3));
+Future<int> t6 = f.then((_) {return new Future<int>.value(3);});
+Future<int> t7 = f.then((_) async => new Future<int>.value(3));
+Future<int> t8 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(_) async {return new Future<int>.value(3);});
+''');
+ }
+
+ void test_futureThen_conditional() {
+ checkFile('''
+import 'dart:async';
+Future<bool> f;
+Future<int> t1 = f.then((x) async => x ? 2 : await new Future<int>.value(3));
+Future<int> t2 = f.then(/*info:INFERRED_TYPE_CLOSURE*/(x) async {return await x ? 2 : new Future<int>.value(3);});
+Future<int> t5 = f.then((x) => x ? 2 : new Future<int>.value(3));
+Future<int> t6 = f.then((x) {return x ? 2 : new Future<int>.value(3);});
+''');
+ }
+
+ void test_futureUnion_asyncConditional() {
+ checkFile('''
+import 'dart:async';
+
+Future<int> g1(bool x) async { return x ? 42 : /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(42); }
+Future<int> g2(bool x) async => x ? 42 : /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(42);
+
+Future<int> g3(bool x) async {
+ var y = x ? 42 : /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(42);
+ return y;
+}
+ ''');
+ }
+
+ void test_futureUnion_downwards() {
+ checkFile('''
+import 'dart:async';
+Future f;
+// Instantiates Future<int>
+Future<int> t1 = f.then((_) => /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(/*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/'hi'));
+
+// Instantiates List<int>
+Future<List<int>> t2 = f.then((_) => /*info:INFERRED_TYPE_LITERAL*/[3]);
+Future<List<int>> g2() async { return /*info:INFERRED_TYPE_LITERAL*/[3]; }
+Future<List<int>> g3() async { return /*info:INFERRED_TYPE_ALLOCATION*/new Future.value(/*info:INFERRED_TYPE_LITERAL*/[3]); }
''');
}
@@ -2280,7 +2326,7 @@
// conected component.
var g = -3;
var h = new A() + 3;
-var i = /*error:UNDEFINED_OPERATOR*/- new A();
+var i = /*error:UNDEFINED_OPERATOR,info:DYNAMIC_INVOKE*/- new A();
var j = null as B;
test1() {
@@ -2554,6 +2600,18 @@
expect(fns[9].type.toString(), '() → Stream<int>');
}
+ void test_inferReturnOfStatementLambda() {
+ // Regression test for https://github.com/dart-lang/sdk/issues/26139
+ checkFile(r'''
+List<String> strings() {
+ var stuff = [].expand(/*info:INFERRED_TYPE_CLOSURE*/(i) {
+ return <String>[];
+ });
+ return stuff.toList();
+}
+ ''');
+ }
+
void test_inferred_nonstatic_field_depends_on_static_field_complex() {
var mainUnit = checkFile('''
class C {
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index 6d3555f..5b9ec2c 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -137,9 +137,14 @@
PackageBundleAssembler assembler;
final Set<Source> processedSources = new Set<Source>();
final Map<Uri, UnlinkedUnit> uriToUnit = <Uri, UnlinkedUnit>{};
+ PackageBundle sdkBundle;
BuildMode(this.resourceProvider, this.options, this.stats);
+ bool get _shouldOutputSummary =>
+ options.buildSummaryOutput != null ||
+ options.buildSummaryOutputSemantic != null;
+
/**
* Perform package analysis according to the given [options].
*/
@@ -188,8 +193,7 @@
assembler = new PackageBundleAssembler(
excludeHashes: options.buildSummaryExcludeInformative &&
options.buildSummaryOutputSemantic == null);
- if (options.buildSummaryOutput != null ||
- options.buildSummaryOutputSemantic != null) {
+ if (_shouldOutputSummary) {
if (options.buildSummaryOnlyAst && !options.buildSummaryFallback) {
_serializeAstBasedSummary(explicitSources);
} else {
@@ -208,21 +212,26 @@
}
}
}
+ if (!options.buildSummaryOnlyAst) {
+ // In non-AST mode, the SDK bundle wasn't added to the summaryDataStore
+ // because it is automatically loaded during analysis. However we still
+ // want the SDK bundle to be noted as a dependency, so add it now.
+ summaryDataStore.addBundle(null, sdkBundle);
+ }
// Write the whole package bundle.
- PackageBundleBuilder sdkBundle = assembler.assemble();
+ assembler.recordDependencies(summaryDataStore);
+ PackageBundleBuilder bundle = assembler.assemble();
if (options.buildSummaryExcludeInformative) {
- sdkBundle.flushInformative();
+ bundle.flushInformative();
}
if (options.buildSummaryOutput != null) {
io.File file = new io.File(options.buildSummaryOutput);
- file.writeAsBytesSync(sdkBundle.toBuffer(),
- mode: io.FileMode.WRITE_ONLY);
+ file.writeAsBytesSync(bundle.toBuffer(), mode: io.FileMode.WRITE_ONLY);
}
if (options.buildSummaryOutputSemantic != null) {
- sdkBundle.flushInformative();
+ bundle.flushInformative();
io.File file = new io.File(options.buildSummaryOutputSemantic);
- file.writeAsBytesSync(sdkBundle.toBuffer(),
- mode: io.FileMode.WRITE_ONLY);
+ file.writeAsBytesSync(bundle.toBuffer(), mode: io.FileMode.WRITE_ONLY);
}
}
@@ -254,10 +263,10 @@
void _createContext() {
// Read the summaries.
- summaryDataStore = new SummaryDataStore(options.buildSummaryInputs);
+ summaryDataStore = new SummaryDataStore(options.buildSummaryInputs,
+ recordDependencyInfo: _shouldOutputSummary);
DartSdk sdk;
- PackageBundle sdkBundle;
if (options.dartSdkSummaryPath != null) {
SummaryBasedDartSdk summarySdk = new SummaryBasedDartSdk(
options.dartSdkSummaryPath, options.strongMode);
diff --git a/pkg/compiler/bin/resolver.dart b/pkg/compiler/bin/resolver.dart
index aa70e4d..054ba50 100644
--- a/pkg/compiler/bin/resolver.dart
+++ b/pkg/compiler/bin/resolver.dart
@@ -6,12 +6,11 @@
import 'package:args/args.dart';
import 'package:compiler/src/apiimpl.dart';
-import 'package:compiler/src/dart2js.dart';
import 'package:compiler/src/filenames.dart';
import 'package:compiler/src/null_compiler_output.dart';
-import 'package:compiler/src/source_file_provider.dart';
import 'package:compiler/src/options.dart';
import 'package:compiler/src/serialization/json_serializer.dart';
+import 'package:compiler/src/source_file_provider.dart';
import 'package:package_config/discovery.dart';
main(var argv) async {
@@ -19,6 +18,8 @@
parser.addOption('deps', abbr: 'd', allowMultiple: true);
parser.addOption('out', abbr: 'o');
parser.addOption('library-root', abbr: 'l');
+ parser.addOption('packages', abbr: 'p');
+ parser.addOption('bazel-config');
var args = parser.parse(argv);
var resolutionInputs = args['deps']
@@ -28,18 +29,31 @@
var libraryRoot = root == null
? Platform.script.resolve('../../../sdk/')
: currentDirectory.resolve(nativeToUriPath(root));
+
var options = new CompilerOptions(
libraryRoot: libraryRoot,
+ packageConfig: args['packages'] == null
+ ? null
+ : currentDirectory.resolve(args['packages']),
resolveOnly: true,
resolutionInputs: resolutionInputs,
packagesDiscoveryProvider: findPackages);
- var inputProvider = new CompilerSourceFileProvider();
+
+ var bazelConfigPath = args['bazel-config'];
+ var inputProvider = bazelConfigPath != null
+ ? new BazelInputProvider(bazelConfigPath)
+ : new CompilerSourceFileProvider();
+
var outputProvider = const NullCompilerOutput();
var diagnostics = new FormattingDiagnosticHandler(inputProvider);
-
var compiler =
new CompilerImpl(inputProvider, outputProvider, diagnostics, options);
+ if (args.rest.isEmpty) {
+ print('missing input files');
+ exit(1);
+ }
+
var inputs = args.rest
.map((uri) => currentDirectory.resolve(nativeToUriPath(uri)))
.toList();
diff --git a/pkg/compiler/lib/compiler.dart b/pkg/compiler/lib/compiler.dart
index 11e99b3..e030673 100644
--- a/pkg/compiler/lib/compiler.dart
+++ b/pkg/compiler/lib/compiler.dart
@@ -5,10 +5,12 @@
library compiler;
import 'dart:async';
+
import 'package:package_config/packages.dart';
+
import 'compiler_new.dart' as new_api;
-import 'src/options.dart' show CompilerOptions;
import 'src/old_to_new_api.dart';
+import 'src/options.dart' show CompilerOptions;
// Unless explicitly allowed, passing [:null:] for any argument to the
// methods of library will result in an Error being thrown.
diff --git a/pkg/compiler/lib/compiler_new.dart b/pkg/compiler/lib/compiler_new.dart
index 51de3810..5ba94cb 100644
--- a/pkg/compiler/lib/compiler_new.dart
+++ b/pkg/compiler/lib/compiler_new.dart
@@ -8,10 +8,11 @@
library compiler_new;
import 'dart:async';
+
+import 'compiler.dart' show Diagnostic;
import 'src/apiimpl.dart';
import 'src/options.dart' show CompilerOptions;
-import 'compiler.dart' show Diagnostic;
export 'compiler.dart' show Diagnostic, PackagesDiscoveryProvider;
// Unless explicitly allowed, passing `null` for any argument to the
@@ -39,9 +40,9 @@
/// files, source map files, dump info files, etc.
abstract class CompilerOutput {
/// Returns an [EventSink] that will serve as compiler output for the given
- /// component.
+ /// component.
///
- /// Components are identified by [name] and [extension]. By convention,
+ /// Components are identified by [name] and [extension]. By convention,
/// the empty string [:"":] will represent the main script
/// (corresponding to the script parameter of [compile]) even if the
/// main script is a library. For libraries that are compiled
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index 98d931a..3bddb9b 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -5,7 +5,6 @@
library leg_apiimpl;
import 'dart:async';
-import 'dart:convert';
import 'package:package_config/packages.dart';
import 'package:package_config/packages_file.dart' as pkgs;
@@ -16,7 +15,6 @@
import '../compiler_new.dart' as api;
import 'common/tasks.dart' show GenericTask, Measurer;
import 'common.dart';
-import 'common/backend_api.dart' show Backend;
import 'compiler.dart';
import 'diagnostics/messages.dart' show Message;
import 'elements/elements.dart' as elements;
@@ -26,7 +24,6 @@
import 'platform_configuration.dart' as platform_configuration;
import 'resolved_uri_translator.dart';
import 'script.dart';
-import 'serialization/system.dart';
/// Implements the [Compiler] using a [api.CompilerInput] for supplying the
/// sources.
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 0cffc40..7b71e69 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -4,23 +4,23 @@
library closureToClassMapper;
-import 'common.dart';
import 'common/names.dart' show Identifiers;
import 'common/resolution.dart' show ParsingContext, Resolution;
import 'common/tasks.dart' show CompilerTask;
+import 'common.dart';
import 'compiler.dart' show Compiler;
import 'constants/expressions.dart';
import 'dart_types.dart';
import 'elements/elements.dart';
import 'elements/modelx.dart'
- show BaseFunctionElementX, ClassElementX, ElementX, LocalFunctionElementX;
+ show BaseFunctionElementX, ClassElementX, ElementX;
import 'elements/visitor.dart' show ElementVisitor;
import 'js_backend/js_backend.dart' show JavaScriptBackend;
import 'resolution/tree_elements.dart' show TreeElements;
import 'tokens/token.dart' show Token;
import 'tree/tree.dart';
-import 'util/util.dart';
import 'universe/universe.dart' show Universe;
+import 'util/util.dart';
class ClosureTask extends CompilerTask {
Map<Node, ClosureClassMap> closureMappingCache;
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 8a26860..cee2fcb 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -4,7 +4,6 @@
library dart2js.common.codegen;
-import '../closure.dart' show SynthesizedCallMethodElementX;
import '../common.dart';
import '../compiler.dart' show Compiler;
import '../constants/values.dart' show ConstantValue;
diff --git a/pkg/compiler/lib/src/common/resolution.dart b/pkg/compiler/lib/src/common/resolution.dart
index d48603d..841e77c 100644
--- a/pkg/compiler/lib/src/common/resolution.dart
+++ b/pkg/compiler/lib/src/common/resolution.dart
@@ -5,8 +5,8 @@
library dart2js.common.resolution;
import '../common.dart';
-import '../compiler.dart' show Compiler;
import '../compile_time_constants.dart';
+import '../compiler.dart' show Compiler;
import '../constants/expressions.dart' show ConstantExpression;
import '../constants/values.dart' show ConstantValue;
import '../core_types.dart' show CoreClasses, CoreTypes;
diff --git a/pkg/compiler/lib/src/common/tasks.dart b/pkg/compiler/lib/src/common/tasks.dart
index 100181c..2c5d62c 100644
--- a/pkg/compiler/lib/src/common/tasks.dart
+++ b/pkg/compiler/lib/src/common/tasks.dart
@@ -20,6 +20,11 @@
int asyncCount = 0;
+ // Each task has a fixed, lazily computed, ZoneSpecification and zoneValues
+ // for [_measureZoned].
+ ZoneSpecification _zoneSpecification;
+ Map _zoneValues;
+
CompilerTask(Measurer measurer)
: measurer = measurer,
_watch = measurer.enableTaskMeasurements ? new Stopwatch() : null;
@@ -97,49 +102,49 @@
// The current zone is already measuring `this` task.
if (Zone.current[measurer] == this) return action();
- /// Run [f] in [zone]. Running must be delegated to [parent] to ensure that
- /// various state is set up correctly (in particular that `Zone.current`
- /// has the right value). Since [_measureZoned] can be called recursively
- /// (synchronously), some of the measuring zones we create will be parents
- /// of other measuring zones, but we still need to call through the parent
- /// chain. Consequently, we use a zone value keyed by [measurer] to see if
- /// we should measure or not when delegating.
- run(Zone self, ZoneDelegate parent, Zone zone, f()) {
- if (zone[measurer] != this) return parent.run(zone, f);
- CompilerTask previous = _start();
- try {
- return parent.run(zone, f);
- } finally {
- _stop(previous);
- }
- }
-
- /// Same as [run] except that [f] takes one argument, [arg].
- runUnary(Zone self, ZoneDelegate parent, Zone zone, f(arg), arg) {
- if (zone[measurer] != this) return parent.runUnary(zone, f, arg);
- CompilerTask previous = _start();
- try {
- return parent.runUnary(zone, f, arg);
- } finally {
- _stop(previous);
- }
- }
-
- /// Same as [run] except that [f] takes two arguments ([a1] and [a2]).
- runBinary(Zone self, ZoneDelegate parent, Zone zone, f(a1, a2), a1, a2) {
- if (zone[measurer] != this) return parent.runBinary(zone, f, a1, a2);
- CompilerTask previous = _start();
- try {
- return parent.runBinary(zone, f, a1, a2);
- } finally {
- _stop(previous);
- }
- }
-
return runZoned(action,
- zoneValues: {measurer: this},
- zoneSpecification: new ZoneSpecification(
- run: run, runUnary: runUnary, runBinary: runBinary));
+ zoneValues: _zoneValues ??= {measurer: this},
+ zoneSpecification: _zoneSpecification ??= new ZoneSpecification(
+ run: _run, runUnary: _runUnary, runBinary: _runBinary));
+ }
+
+ /// Run [f] in [zone]. Running must be delegated to [parent] to ensure that
+ /// various state is set up correctly (in particular that `Zone.current`
+ /// has the right value). Since [_measureZoned] can be called recursively
+ /// (synchronously), some of the measuring zones we create will be parents
+ /// of other measuring zones, but we still need to call through the parent
+ /// chain. Consequently, we use a zone value keyed by [measurer] to see if
+ /// we should measure or not when delegating.
+ _run(Zone self, ZoneDelegate parent, Zone zone, f()) {
+ if (zone[measurer] != this) return parent.run(zone, f);
+ CompilerTask previous = _start();
+ try {
+ return parent.run(zone, f);
+ } finally {
+ _stop(previous);
+ }
+ }
+
+ /// Same as [run] except that [f] takes one argument, [arg].
+ _runUnary(Zone self, ZoneDelegate parent, Zone zone, f(arg), arg) {
+ if (zone[measurer] != this) return parent.runUnary(zone, f, arg);
+ CompilerTask previous = _start();
+ try {
+ return parent.runUnary(zone, f, arg);
+ } finally {
+ _stop(previous);
+ }
+ }
+
+ /// Same as [run] except that [f] takes two arguments ([a1] and [a2]).
+ _runBinary(Zone self, ZoneDelegate parent, Zone zone, f(a1, a2), a1, a2) {
+ if (zone[measurer] != this) return parent.runBinary(zone, f, a1, a2);
+ CompilerTask previous = _start();
+ try {
+ return parent.runBinary(zone, f, a1, a2);
+ } finally {
+ _stop(previous);
+ }
}
/// Asynchronous version of [measure]. Use this when action returns a future
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index 1c066ed..8853b2f 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -4,9 +4,9 @@
library dart2js.compile_time_constant_evaluator;
-import 'common.dart';
import 'common/resolution.dart' show Resolution;
import 'common/tasks.dart' show CompilerTask, Measurer;
+import 'common.dart';
import 'compiler.dart' show Compiler;
import 'constant_system_dart.dart';
import 'constants/constant_system.dart';
@@ -16,13 +16,12 @@
import 'core_types.dart' show CoreTypes;
import 'dart_types.dart';
import 'elements/elements.dart';
-import 'elements/modelx.dart'
- show FieldElementX, FunctionElementX, ConstantVariableMixin;
-import 'resolution/tree_elements.dart' show TreeElements;
+import 'elements/modelx.dart' show ConstantVariableMixin;
import 'resolution/operators.dart';
+import 'resolution/tree_elements.dart' show TreeElements;
import 'tree/tree.dart';
-import 'util/util.dart' show Link;
import 'universe/call_structure.dart' show CallStructure;
+import 'util/util.dart' show Link;
/// A [ConstantEnvironment] provides access for constants compiled for variable
/// initializers.
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index bdda974..762e315 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -1992,6 +1992,9 @@
message: "Element $element must be the declaration."));
assert(invariant(element, hasResolvedAst(element),
message: "ResolvedAst not available for $element."));
+ if (compiler.serialization.isDeserialized(element)) {
+ return compiler.serialization.getResolvedAst(element);
+ }
return element.resolvedAst;
}
diff --git a/pkg/compiler/lib/src/constants/constant_constructors.dart b/pkg/compiler/lib/src/constants/constant_constructors.dart
index 4628f28..996f8b1 100644
--- a/pkg/compiler/lib/src/constants/constant_constructors.dart
+++ b/pkg/compiler/lib/src/constants/constant_constructors.dart
@@ -16,7 +16,6 @@
import '../resolution/tree_elements.dart' show TreeElements;
import '../tree/tree.dart';
import '../universe/call_structure.dart' show CallStructure;
-
import 'constructors.dart';
import 'expressions.dart';
diff --git a/pkg/compiler/lib/src/constants/constant_system.dart b/pkg/compiler/lib/src/constants/constant_system.dart
index 07787fd..1a0da6a 100644
--- a/pkg/compiler/lib/src/constants/constant_system.dart
+++ b/pkg/compiler/lib/src/constants/constant_system.dart
@@ -4,8 +4,8 @@
library dart2js.constant_system;
-import '../dart_types.dart';
import '../compiler.dart' show Compiler;
+import '../dart_types.dart';
import '../resolution/operators.dart';
import '../tree/dartstring.dart' show DartString;
import 'values.dart';
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index 2ea05a8..6fc55de 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -133,7 +133,7 @@
/// if it contains positional or named references, used to define constant
/// constructors.
// TODO(johnniwinther): Maybe make this final if we use it outside assertions.
- bool get isPotential => true;
+ bool get isPotential => false;
}
/// A synthetic constant used to recover from errors.
@@ -195,9 +195,6 @@
ConstantExpressionKind get kind => ConstantExpressionKind.SYNTHETIC;
@override
- bool get isPotential => false;
-
- @override
bool get isImplicit => false;
}
@@ -1270,9 +1267,7 @@
}
@override
- bool get isPotential {
- return true;
- }
+ bool get isPotential => true;
}
/// A reference to a named parameter.
@@ -1311,9 +1306,7 @@
}
@override
- bool get isPotential {
- return true;
- }
+ bool get isPotential => true;
}
abstract class FromEnvironmentConstantExpression extends ConstantExpression {
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index fbda202..cba4e69 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -12,6 +12,23 @@
import '../tree/dartstring.dart';
import '../util/util.dart' show Hashing;
+enum ConstantValueKind {
+ FUNCTION,
+ NULL,
+ INT,
+ DOUBLE,
+ BOOL,
+ STRING,
+ LIST,
+ MAP,
+ CONSTRUCTED,
+ TYPE,
+ INTERCEPTOR,
+ SYNTHETIC,
+ DEFERRED,
+ NON_CONSTANT,
+}
+
abstract class ConstantValueVisitor<R, A> {
const ConstantValueVisitor();
@@ -84,6 +101,8 @@
/// Returns a structured representation of this constant suited for debugging.
String toStructuredText();
+ ConstantValueKind get kind;
+
String toString() {
assertDebugMode("Use ConstantValue.toDartText() or "
"ConstantValue.toStructuredText() "
@@ -118,6 +137,8 @@
accept(ConstantValueVisitor visitor, arg) => visitor.visitFunction(this, arg);
+ ConstantValueKind get kind => ConstantValueKind.FUNCTION;
+
String toDartText() {
if (element.isStatic) {
return '${element.enclosingClass.name}.${element.name}';
@@ -177,6 +198,8 @@
accept(ConstantValueVisitor visitor, arg) => visitor.visitNull(this, arg);
+ ConstantValueKind get kind => ConstantValueKind.NULL;
+
String toStructuredText() => 'NullConstant';
}
@@ -258,6 +281,8 @@
accept(ConstantValueVisitor visitor, arg) => visitor.visitInt(this, arg);
+ ConstantValueKind get kind => ConstantValueKind.INT;
+
String toStructuredText() => 'IntConstant(${toDartText()})';
}
@@ -320,6 +345,8 @@
accept(ConstantValueVisitor visitor, arg) => visitor.visitDouble(this, arg);
+ ConstantValueKind get kind => ConstantValueKind.DOUBLE;
+
String toStructuredText() => 'DoubleConstant(${toDartText()})';
}
@@ -338,6 +365,8 @@
accept(ConstantValueVisitor visitor, arg) => visitor.visitBool(this, arg);
+ ConstantValueKind get kind => ConstantValueKind.BOOL;
+
String toStructuredText() => 'BoolConstant(${toDartText()})';
}
@@ -414,6 +443,8 @@
accept(ConstantValueVisitor visitor, arg) => visitor.visitString(this, arg);
+ ConstantValueKind get kind => ConstantValueKind.STRING;
+
// TODO(johnniwinther): Ensure correct escaping.
String toDartText() => '"${primitiveValue.slowToString()}"';
@@ -457,6 +488,8 @@
accept(ConstantValueVisitor visitor, arg) => visitor.visitType(this, arg);
+ ConstantValueKind get kind => ConstantValueKind.TYPE;
+
String toDartText() => '$representedType';
String toStructuredText() => 'TypeConstant(${representedType})';
@@ -492,6 +525,8 @@
accept(ConstantValueVisitor visitor, arg) => visitor.visitList(this, arg);
+ ConstantValueKind get kind => ConstantValueKind.LIST;
+
String toDartText() {
StringBuffer sb = new StringBuffer();
_unparseTypeArguments(sb);
@@ -567,6 +602,8 @@
accept(ConstantValueVisitor visitor, arg) => visitor.visitMap(this, arg);
+ ConstantValueKind get kind => ConstantValueKind.MAP;
+
String toDartText() {
StringBuffer sb = new StringBuffer();
_unparseTypeArguments(sb);
@@ -621,6 +658,8 @@
DartType getType(CoreTypes types) => const DynamicType();
+ ConstantValueKind get kind => ConstantValueKind.INTERCEPTOR;
+
String toDartText() {
return 'interceptor($dispatchedType)';
}
@@ -632,9 +671,9 @@
class SyntheticConstantValue extends ConstantValue {
final payload;
- final kind;
+ final valueKind;
- SyntheticConstantValue(this.kind, this.payload);
+ SyntheticConstantValue(this.valueKind, this.payload);
bool get isDummy => true;
@@ -642,7 +681,7 @@
return other is SyntheticConstantValue && payload == other.payload;
}
- get hashCode => payload.hashCode * 17 + kind.hashCode;
+ get hashCode => payload.hashCode * 17 + valueKind.hashCode;
List<ConstantValue> getDependencies() => const <ConstantValue>[];
@@ -652,9 +691,11 @@
DartType getType(CoreTypes types) => const DynamicType();
- String toDartText() => 'synthetic($kind, $payload)';
+ ConstantValueKind get kind => ConstantValueKind.SYNTHETIC;
- String toStructuredText() => 'SyntheticConstant($kind, $payload)';
+ String toDartText() => 'synthetic($valueKind, $payload)';
+
+ String toStructuredText() => 'SyntheticConstant($valueKind, $payload)';
}
class ConstructedConstantValue extends ObjectConstantValue {
@@ -693,6 +734,8 @@
return visitor.visitConstructed(this, arg);
}
+ ConstantValueKind get kind => ConstantValueKind.CONSTRUCTED;
+
String toDartText() {
StringBuffer sb = new StringBuffer();
sb.write(type.name);
@@ -752,6 +795,8 @@
DartType getType(CoreTypes types) => referenced.getType(types);
+ ConstantValueKind get kind => ConstantValueKind.DEFERRED;
+
String toDartText() => 'deferred(${referenced.toDartText()})';
String toStructuredText() {
@@ -776,6 +821,8 @@
@override
DartType getType(CoreTypes types) => const DynamicType();
+ ConstantValueKind get kind => ConstantValueKind.NON_CONSTANT;
+
@override
String toStructuredText() => 'NonConstant';
diff --git a/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart b/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart
index 5bdfc6c..57621fb 100644
--- a/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart
+++ b/pkg/compiler/lib/src/cps_ir/backward_null_check_remover.dart
@@ -1,9 +1,9 @@
library dart2js.cps_ir.backward_null_check_remover;
+import 'cps_fragment.dart';
import 'cps_ir_nodes.dart';
import 'optimizers.dart';
import 'type_mask_system.dart';
-import 'cps_fragment.dart';
/// Removes null checks that are follwed by another instruction that will
/// perform the same check.
diff --git a/pkg/compiler/lib/src/cps_ir/bounds_checker.dart b/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
index b4ca8e1..ee5adec 100644
--- a/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
+++ b/pkg/compiler/lib/src/cps_ir/bounds_checker.dart
@@ -4,16 +4,16 @@
library dart2js.cps_ir.bounds_checker;
-import 'cps_ir_nodes.dart';
-import 'optimizers.dart' show Pass;
-import 'octagon.dart';
import '../constants/values.dart';
-import 'cps_fragment.dart';
-import 'type_mask_system.dart';
import '../types/types.dart';
import '../world.dart';
-import 'loop_effects.dart';
+import 'cps_fragment.dart';
+import 'cps_ir_nodes.dart';
import 'effects.dart';
+import 'loop_effects.dart';
+import 'octagon.dart';
+import 'optimizers.dart' show Pass;
+import 'type_mask_system.dart';
/// Eliminates bounds checks when they can be proven safe.
///
diff --git a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
index 4e22d0e..b7c7b9b 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
@@ -4,12 +4,12 @@
library cps_ir.cps_fragment;
-import 'cps_ir_nodes.dart';
import '../constants/values.dart';
-import '../universe/selector.dart' show Selector;
-import '../types/types.dart' show TypeMask;
-import '../io/source_information.dart';
import '../elements/elements.dart';
+import '../io/source_information.dart';
+import '../types/types.dart' show TypeMask;
+import '../universe/selector.dart' show Selector;
+import 'cps_ir_nodes.dart';
/// Builds a CPS fragment that can be plugged into another CPS term.
///
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart
index cee7a1e..6363c88 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart
@@ -1,8 +1,8 @@
library dart2js.cps_ir_integrity;
+import '../tracer.dart' as tracer;
import 'cps_ir_nodes.dart';
import 'cps_ir_nodes_sexpr.dart';
-import '../tracer.dart' as tracer;
/// Dump S-expressions on error if the tracer is enabled.
///
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
index d788549..8d32d04 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
@@ -5,9 +5,9 @@
library dart2js.ir_nodes_sexpr;
import '../constants/values.dart';
+import '../universe/call_structure.dart' show CallStructure;
import '../util/util.dart';
import 'cps_ir_nodes.dart';
-import '../universe/call_structure.dart' show CallStructure;
/// A [Decorator] is a function used by [SExpressionStringifier] to augment the
/// output produced for a node or reference. It can be provided to the
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
index f70c586..3f13ee7 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
@@ -5,8 +5,9 @@
library dart2js.ir_tracer;
import 'dart:async' show EventSink;
-import 'cps_ir_nodes.dart' as cps_ir;
+
import '../tracer.dart';
+import 'cps_ir_nodes.dart' as cps_ir;
/**
* If true, show LetCont expressions in output.
diff --git a/pkg/compiler/lib/src/cps_ir/eagerly_load_statics.dart b/pkg/compiler/lib/src/cps_ir/eagerly_load_statics.dart
index 60a7977..b936885 100644
--- a/pkg/compiler/lib/src/cps_ir/eagerly_load_statics.dart
+++ b/pkg/compiler/lib/src/cps_ir/eagerly_load_statics.dart
@@ -4,10 +4,10 @@
library dart2js.cps_ir.eagerly_load_statics;
-import 'cps_ir_nodes.dart';
-import 'optimizers.dart' show Pass;
import '../elements/elements.dart';
import 'cps_fragment.dart';
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart' show Pass;
/// Replaces [GetLazyStatic] with [GetStatic] when the static field is known
/// to have been initialized.
diff --git a/pkg/compiler/lib/src/cps_ir/effects.dart b/pkg/compiler/lib/src/cps_ir/effects.dart
index 29d3172..2a28785 100644
--- a/pkg/compiler/lib/src/cps_ir/effects.dart
+++ b/pkg/compiler/lib/src/cps_ir/effects.dart
@@ -4,6 +4,7 @@
library dart2js.cps_ir.effects;
import 'dart:typed_data';
+
import '../universe/side_effects.dart' show SideEffects;
/// Bitmasks for tracking non-local side effects and dependencies.
diff --git a/pkg/compiler/lib/src/cps_ir/finalize.dart b/pkg/compiler/lib/src/cps_ir/finalize.dart
index e583f49..7f0e7e0 100644
--- a/pkg/compiler/lib/src/cps_ir/finalize.dart
+++ b/pkg/compiler/lib/src/cps_ir/finalize.dart
@@ -1,11 +1,11 @@
library dart2js.cps_ir.finalize;
-import 'cps_ir_nodes.dart';
-import 'cps_fragment.dart';
-import 'optimizers.dart' show Pass;
-import '../js_backend/js_backend.dart' show JavaScriptBackend;
-import '../js_backend/backend_helpers.dart';
import '../js/js.dart' as js;
+import '../js_backend/backend_helpers.dart';
+import '../js_backend/js_backend.dart' show JavaScriptBackend;
+import 'cps_fragment.dart';
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart' show Pass;
/// A transformation pass that must run immediately before the tree IR builder.
///
diff --git a/pkg/compiler/lib/src/cps_ir/gvn.dart b/pkg/compiler/lib/src/cps_ir/gvn.dart
index 8970f5c..4c49d7a 100644
--- a/pkg/compiler/lib/src/cps_ir/gvn.dart
+++ b/pkg/compiler/lib/src/cps_ir/gvn.dart
@@ -4,16 +4,16 @@
library dart2js.cps_ir.gvn;
-import 'cps_ir_nodes.dart';
-import '../elements/elements.dart';
-import 'optimizers.dart' show Pass;
-import 'loop_hierarchy.dart';
-import 'loop_effects.dart';
-import '../world.dart';
import '../compiler.dart' show Compiler;
+import '../elements/elements.dart';
import '../js_backend/js_backend.dart' show JavaScriptBackend;
-import 'type_mask_system.dart';
+import '../world.dart';
+import 'cps_ir_nodes.dart';
import 'effects.dart';
+import 'loop_effects.dart';
+import 'loop_hierarchy.dart';
+import 'optimizers.dart' show Pass;
+import 'type_mask_system.dart';
/// Eliminates redundant primitives by reusing the value of another primitive
/// that is known to have the same result. Primitives are also hoisted out of
diff --git a/pkg/compiler/lib/src/cps_ir/insert_refinements.dart b/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
index 28d013f..e57f43f 100644
--- a/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
+++ b/pkg/compiler/lib/src/cps_ir/insert_refinements.dart
@@ -5,12 +5,13 @@
library cps_ir.optimization.insert_refinements;
import 'dart:math' show min;
-import 'optimizers.dart' show Pass;
-import 'cps_ir_nodes.dart';
-import '../elements/elements.dart';
+
import '../common/names.dart';
+import '../elements/elements.dart';
import '../types/types.dart' show TypeMask;
import '../universe/selector.dart';
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart' show Pass;
import 'type_mask_system.dart';
/// Inserts [Refinement] nodes in the IR to allow for sparse path-sensitive
diff --git a/pkg/compiler/lib/src/cps_ir/loop_effects.dart b/pkg/compiler/lib/src/cps_ir/loop_effects.dart
index d7c3c6f..e2f5e22 100644
--- a/pkg/compiler/lib/src/cps_ir/loop_effects.dart
+++ b/pkg/compiler/lib/src/cps_ir/loop_effects.dart
@@ -1,9 +1,9 @@
library dart2js.cps_ir.loop_effects;
-import 'cps_ir_nodes.dart';
-import 'loop_hierarchy.dart';
import '../world.dart';
+import 'cps_ir_nodes.dart';
import 'effects.dart';
+import 'loop_hierarchy.dart';
/// Determines the side effects that may occur in each loop.
class LoopSideEffects extends TrampolineRecursiveVisitor {
diff --git a/pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart b/pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart
index 60129af..4433510 100644
--- a/pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart
+++ b/pkg/compiler/lib/src/cps_ir/loop_hierarchy.dart
@@ -4,8 +4,8 @@
library dart2js.cps_ir.loop_hierarchy;
-import 'cps_ir_nodes.dart';
import 'cps_fragment.dart';
+import 'cps_ir_nodes.dart';
/// Determines the effective nesting of loops.
///
diff --git a/pkg/compiler/lib/src/cps_ir/loop_invariant_branch.dart b/pkg/compiler/lib/src/cps_ir/loop_invariant_branch.dart
index 95ee597..8d84f0f 100644
--- a/pkg/compiler/lib/src/cps_ir/loop_invariant_branch.dart
+++ b/pkg/compiler/lib/src/cps_ir/loop_invariant_branch.dart
@@ -1,9 +1,9 @@
library dart2js.cps_ir.loop_invariant_branch;
-import 'cps_ir_nodes.dart';
-import 'optimizers.dart';
-import 'loop_hierarchy.dart';
import 'cps_fragment.dart';
+import 'cps_ir_nodes.dart';
+import 'loop_hierarchy.dart';
+import 'optimizers.dart';
import 'redundant_join.dart' show AlphaRenamer;
/// Hoists branches out of loops, where:
diff --git a/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart b/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart
index 65500a5..59ef662 100644
--- a/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimize_interceptors.dart
@@ -4,17 +4,17 @@
library dart2js.cps_ir.optimize_interceptors;
-import 'optimizers.dart';
-import 'cps_ir_nodes.dart';
-import 'loop_hierarchy.dart';
-import 'cps_fragment.dart';
import '../constants/values.dart';
import '../elements/elements.dart';
+import '../io/source_information.dart' show SourceInformation;
import '../js_backend/backend_helpers.dart' show BackendHelpers;
import '../js_backend/js_backend.dart' show JavaScriptBackend;
import '../types/types.dart' show TypeMask;
-import '../io/source_information.dart' show SourceInformation;
import '../world.dart';
+import 'cps_fragment.dart';
+import 'cps_ir_nodes.dart';
+import 'loop_hierarchy.dart';
+import 'optimizers.dart';
import 'type_mask_system.dart';
/// Replaces `getInterceptor` calls with interceptor constants when possible,
diff --git a/pkg/compiler/lib/src/cps_ir/optimizers.dart b/pkg/compiler/lib/src/cps_ir/optimizers.dart
index 8af5154..3e22e10 100644
--- a/pkg/compiler/lib/src/cps_ir/optimizers.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimizers.dart
@@ -4,30 +4,30 @@
library dart2js.cps_ir.optimizers;
-import 'cps_ir_nodes.dart';
-import '../constants/values.dart';
import '../common/names.dart';
+import '../constants/values.dart';
import '../universe/selector.dart';
+import 'cps_ir_nodes.dart';
-export 'type_propagation.dart' show TypePropagator;
-export 'scalar_replacement.dart' show ScalarReplacer;
-export 'redundant_phi.dart' show RedundantPhiEliminator;
-export 'redundant_join.dart' show RedundantJoinEliminator;
-export 'shrinking_reductions.dart' show ShrinkingReducer;
-export 'mutable_ssa.dart' show MutableVariableEliminator;
-export 'insert_refinements.dart' show InsertRefinements;
-export 'update_refinements.dart' show UpdateRefinements;
-export 'redundant_refinement.dart' show RedundantRefinementEliminator;
-export 'optimize_interceptors.dart' show OptimizeInterceptors;
-export 'bounds_checker.dart' show BoundsChecker;
export 'backward_null_check_remover.dart' show BackwardNullCheckRemover;
+export 'bounds_checker.dart' show BoundsChecker;
+export 'eagerly_load_statics.dart' show EagerlyLoadStatics;
export 'gvn.dart' show GVN;
export 'inline.dart' show Inliner;
-export 'eagerly_load_statics.dart' show EagerlyLoadStatics;
+export 'insert_refinements.dart' show InsertRefinements;
export 'loop_invariant_branch.dart' show LoopInvariantBranchMotion;
-export 'path_based_optimizer.dart' show PathBasedOptimizer;
-export 'use_field_initializers.dart' show UseFieldInitializers;
+export 'mutable_ssa.dart' show MutableVariableEliminator;
+export 'optimize_interceptors.dart' show OptimizeInterceptors;
export 'parent_visitor.dart' show ParentVisitor;
+export 'path_based_optimizer.dart' show PathBasedOptimizer;
+export 'redundant_join.dart' show RedundantJoinEliminator;
+export 'redundant_phi.dart' show RedundantPhiEliminator;
+export 'redundant_refinement.dart' show RedundantRefinementEliminator;
+export 'scalar_replacement.dart' show ScalarReplacer;
+export 'shrinking_reductions.dart' show ShrinkingReducer;
+export 'type_propagation.dart' show TypePropagator;
+export 'update_refinements.dart' show UpdateRefinements;
+export 'use_field_initializers.dart' show UseFieldInitializers;
/// An optimization pass over the CPS IR.
abstract class Pass {
diff --git a/pkg/compiler/lib/src/cps_ir/path_based_optimizer.dart b/pkg/compiler/lib/src/cps_ir/path_based_optimizer.dart
index 933111e..d7f4acc 100644
--- a/pkg/compiler/lib/src/cps_ir/path_based_optimizer.dart
+++ b/pkg/compiler/lib/src/cps_ir/path_based_optimizer.dart
@@ -3,10 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
library dart2js.cps_ir.path_based_optimizer;
+import '../js_backend/js_backend.dart';
+import 'cps_fragment.dart';
import 'cps_ir_nodes.dart';
import 'optimizers.dart';
-import 'cps_fragment.dart';
-import '../js_backend/js_backend.dart';
import 'type_mask_system.dart';
/// Optimizations based on intraprocedural forward dataflow analysis, taking
diff --git a/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart b/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart
index a913f08..b66f88f 100644
--- a/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart
+++ b/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart
@@ -3,8 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
library dart2js.cps_ir.scalar_replacement;
-import 'optimizers.dart';
-
import 'dart:collection' show Queue;
import '../common.dart';
@@ -14,6 +12,7 @@
import '../types/types.dart';
import '../world.dart' show World;
import 'cps_ir_nodes.dart';
+import 'optimizers.dart';
/**
* Replaces aggregates with a set of local values. Performs inlining of
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index 4ee963c..75ede1f 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -3,8 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
library dart2js.cps_ir.type_propagation;
-import 'optimizers.dart';
-
import '../closure.dart' show ClosureClassElement;
import '../common.dart';
import '../common/names.dart' show Identifiers, Selectors;
@@ -15,18 +13,19 @@
import '../elements/elements.dart';
import '../io/source_information.dart' show SourceInformation;
import '../js_backend/backend_helpers.dart' show BackendHelpers;
-import '../js_backend/js_backend.dart' show JavaScriptBackend;
import '../js_backend/codegen/task.dart' show CpsFunctionCompiler;
+import '../js_backend/js_backend.dart' show JavaScriptBackend;
import '../resolution/operators.dart';
import '../tree/tree.dart' as ast;
-import '../types/types.dart';
import '../types/abstract_value_domain.dart' show AbstractBool;
+import '../types/types.dart';
import '../universe/selector.dart' show Selector;
import '../world.dart' show World;
import 'cps_fragment.dart';
import 'cps_ir_nodes.dart';
-import 'type_mask_system.dart';
import 'effects.dart';
+import 'optimizers.dart';
+import 'type_mask_system.dart';
class ConstantPropagationLattice {
final TypeMaskSystem typeSystem;
diff --git a/pkg/compiler/lib/src/cps_ir/update_refinements.dart b/pkg/compiler/lib/src/cps_ir/update_refinements.dart
index 09f5d7a..20d333f 100644
--- a/pkg/compiler/lib/src/cps_ir/update_refinements.dart
+++ b/pkg/compiler/lib/src/cps_ir/update_refinements.dart
@@ -1,9 +1,9 @@
library dart2js.cps_ir.update_refinements;
+import '../world.dart';
import 'cps_ir_nodes.dart';
import 'optimizers.dart' show Pass;
import 'type_mask_system.dart';
-import '../world.dart';
/// Updates all references to use the most refined version in scope.
///
diff --git a/pkg/compiler/lib/src/cps_ir/use_field_initializers.dart b/pkg/compiler/lib/src/cps_ir/use_field_initializers.dart
index 1b218af..6019742 100644
--- a/pkg/compiler/lib/src/cps_ir/use_field_initializers.dart
+++ b/pkg/compiler/lib/src/cps_ir/use_field_initializers.dart
@@ -3,10 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
library dart2js.cps_ir.use_field_initializers;
-import 'cps_ir_nodes.dart';
-import 'optimizers.dart';
import '../elements/elements.dart';
import '../js_backend/js_backend.dart';
+import 'cps_ir_nodes.dart';
+import 'optimizers.dart';
/// Eliminates [SetField] instructions when the value can instead be passed into
/// the field initializer of a [CreateInstance] instruction.
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index c4ab29f..5efe438 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -11,9 +11,8 @@
import 'package:package_config/discovery.dart' show findPackages;
import '../compiler_new.dart' as api;
-import 'apiimpl.dart';
-import 'common/names.dart' show Uris;
import 'commandline_options.dart';
+import 'common/names.dart' show Uris;
import 'filenames.dart';
import 'io/source_file.dart';
import 'null_compiler_output.dart';
diff --git a/pkg/compiler/lib/src/dart2js_profile_many.dart b/pkg/compiler/lib/src/dart2js_profile_many.dart
index e29ec46..8288a9a 100644
--- a/pkg/compiler/lib/src/dart2js_profile_many.dart
+++ b/pkg/compiler/lib/src/dart2js_profile_many.dart
@@ -4,9 +4,10 @@
library dart2js.profile_many;
-import 'dart2js.dart' as cmdline;
import 'dart:async';
+import 'dart2js.dart' as cmdline;
+
const String USAGE = """
Usage: dart2js_profile_many.dart [OPTIONS] [FILES]
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index b3668c1..449a434 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -8,8 +8,7 @@
import 'common/tasks.dart' show CompilerTask;
import 'common.dart';
import 'compiler.dart' show Compiler;
-import 'constants/expressions.dart'
- show ConstantExpression, ConstantExpressionKind;
+import 'constants/expressions.dart' show ConstantExpression;
import 'constants/values.dart'
show
ConstantValue,
@@ -180,12 +179,22 @@
return _elementToOutputUnit[element];
}
+ /// Direct access to the output-unit to element relation used for testing.
+ OutputUnit getOutputUnitForElementForTesting(Element element) {
+ return _elementToOutputUnit[element];
+ }
+
/// Returns the [OutputUnit] where [constant] belongs.
OutputUnit outputUnitForConstant(ConstantValue constant) {
if (!isProgramSplit) return mainOutputUnit;
return _constantToOutputUnit[constant];
}
+ /// Direct access to the output-unit to constants map used for testing.
+ Map<ConstantValue, OutputUnit> get outputUnitForConstantsForTesting {
+ return _constantToOutputUnit;
+ }
+
bool isDeferred(Element element) {
return outputUnitForElement(element) != mainOutputUnit;
}
@@ -348,7 +357,7 @@
treeElements.forEachConstantNode(
(ast.Node node, ConstantExpression expression) {
if (compiler.serialization.isDeserialized(analyzableElement)) {
- if (!expression.isImplicit && !expression.isPotential) {
+ if (!expression.isPotential) {
// Enforce evaluation of [expression].
backend.constants.getConstantValue(expression);
}
@@ -926,7 +935,8 @@
StringBuffer sb = new StringBuffer();
for (OutputUnit outputUnit in allOutputUnits) {
- sb.write(outputUnit.name);
+ sb.write('\n-------------------------------\n');
+ sb.write('Output unit: ${outputUnit.name}');
List<String> elements = elementMap[outputUnit];
if (elements != null) {
sb.write('\n elements:');
diff --git a/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart b/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
index 0a9c5f5..e12c09c 100644
--- a/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
+++ b/pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart
@@ -4,11 +4,11 @@
library dart2js.diagnostic_listener;
+import '../elements/elements.dart' show Element;
import '../options.dart' show DiagnosticOptions;
+import 'messages.dart';
import 'source_span.dart' show SourceSpan;
import 'spannable.dart' show Spannable;
-import '../elements/elements.dart' show Element;
-import 'messages.dart';
// TODO(johnniwinther): Rename and cleanup this interface. Add severity enum.
abstract class DiagnosticReporter {
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index 472e016..8baffd6 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -63,12 +63,10 @@
library dart2js.messages;
import '../tokens/token.dart' show ErrorToken, Token;
-
+import 'generated/shared_messages.dart' as shared_messages;
import 'invariant.dart' show invariant;
import 'spannable.dart' show CURRENT_ELEMENT_SPANNABLE;
-import 'generated/shared_messages.dart' as shared_messages;
-
const DONT_KNOW_HOW_TO_FIX = "Computer says no!";
/// Keys for the [MessageTemplate]s.
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index a8c39fa..93f1312 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -16,7 +16,6 @@
import 'deferred_load.dart' show OutputUnit;
import 'elements/elements.dart';
import 'elements/visitor.dart';
-import 'info/send_info.dart' show collectSendMeasurements;
import 'js/js.dart' as jsAst;
import 'js_backend/js_backend.dart' show JavaScriptBackend;
import 'js_emitter/full_emitter/emitter.dart' as full show Emitter;
@@ -313,9 +312,6 @@
}
info.closures = nestedClosures;
result.functions.add(info);
- if (const bool.fromEnvironment('send_stats')) {
- info.measurements = collectSendMeasurements(element, compiler);
- }
return info;
}
diff --git a/pkg/compiler/lib/src/elements/common.dart b/pkg/compiler/lib/src/elements/common.dart
index 0eb92a6..b3a43ca 100644
--- a/pkg/compiler/lib/src/elements/common.dart
+++ b/pkg/compiler/lib/src/elements/common.dart
@@ -10,7 +10,6 @@
import '../core_types.dart' show CoreClasses;
import '../dart_types.dart' show DartType, InterfaceType, FunctionType;
import '../util/util.dart' show Link;
-
import 'elements.dart';
abstract class ElementCommon implements Element {
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index aac0b0d..67cdd60 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -11,16 +11,15 @@
import '../constants/expressions.dart';
import '../core_types.dart' show CoreClasses;
import '../dart_types.dart';
+import '../ordered_typeset.dart' show OrderedTypeSet;
import '../resolution/scope.dart' show Scope;
import '../resolution/tree_elements.dart' show TreeElements;
-import '../ordered_typeset.dart' show OrderedTypeSet;
import '../script.dart';
import '../tokens/token.dart'
show Token, isUserDefinableOperator, isMinusOperator;
import '../tree/tree.dart';
import '../util/characters.dart' show $_;
import '../util/util.dart';
-
import 'visitor.dart' show ElementVisitor;
part 'names.dart';
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 265eb2e..b8a2987 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -15,9 +15,9 @@
import '../diagnostics/messages.dart' show MessageTemplate;
import '../ordered_typeset.dart' show OrderedTypeSet;
import '../resolution/class_members.dart' show ClassMemberMixin;
+import '../resolution/resolution.dart' show AnalyzableElementX;
import '../resolution/scope.dart'
show ClassScope, LibraryScope, Scope, TypeDeclarationScope;
-import '../resolution/resolution.dart' show AnalyzableElementX;
import '../resolution/tree_elements.dart' show TreeElements;
import '../resolution/typedefs.dart' show TypedefCyclicVisitor;
import '../script.dart';
@@ -25,7 +25,6 @@
import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
import '../tree/tree.dart';
import '../util/util.dart';
-
import 'common.dart';
import 'elements.dart';
import 'visitor.dart' show ElementVisitor;
diff --git a/pkg/compiler/lib/src/elements/visitor.dart b/pkg/compiler/lib/src/elements/visitor.dart
index 2a1c917..0779288 100644
--- a/pkg/compiler/lib/src/elements/visitor.dart
+++ b/pkg/compiler/lib/src/elements/visitor.dart
@@ -4,9 +4,9 @@
library visitor;
-import 'elements.dart';
import '../closure.dart'
show BoxFieldElement, ClosureClassElement, ClosureFieldElement;
+import 'elements.dart';
abstract class ElementVisitor<R, A> {
const ElementVisitor();
diff --git a/pkg/compiler/lib/src/hash/sha1.dart b/pkg/compiler/lib/src/hash/sha1.dart
index 8e5eec2..56ae8b9 100644
--- a/pkg/compiler/lib/src/hash/sha1.dart
+++ b/pkg/compiler/lib/src/hash/sha1.dart
@@ -8,8 +8,8 @@
*/
library sha1;
-import 'dart:math' show pow;
import 'dart:convert';
+import 'dart:math' show pow;
import '../io/code_output.dart' show CodeOutputListener;
diff --git a/pkg/compiler/lib/src/helpers/helpers.dart b/pkg/compiler/lib/src/helpers/helpers.dart
index 6c4cc63..14a7887 100644
--- a/pkg/compiler/lib/src/helpers/helpers.dart
+++ b/pkg/compiler/lib/src/helpers/helpers.dart
@@ -10,14 +10,13 @@
import '../common.dart';
import '../diagnostics/invariant.dart' show DEBUG_MODE;
import '../util/util.dart';
-
import 'trace.dart';
export 'debug_collection.dart';
-export 'trace.dart';
export 'expensive_map.dart';
export 'expensive_set.dart';
export 'stats.dart';
+export 'trace.dart';
export 'track_map.dart';
/// Global flag to enable [debugPrint]. This should always be `true` by default
diff --git a/pkg/compiler/lib/src/inferrer/closure_tracer.dart b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
index ed2d198..80b7e3d 100644
--- a/pkg/compiler/lib/src/inferrer/closure_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
@@ -4,13 +4,13 @@
library compiler.src.inferrer.closure_tracer;
-import '../types/types.dart' show TypeMask;
import '../common/names.dart' show Names;
import '../elements/elements.dart';
+import '../types/types.dart' show TypeMask;
import '../universe/selector.dart' show Selector;
+import 'debug.dart' as debug;
import 'node_tracer.dart';
import 'type_graph_nodes.dart';
-import 'debug.dart' as debug;
class ClosureTracerVisitor extends TracerVisitor<ApplyableTypeInformation> {
final Iterable<FunctionElement> tracedElements;
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
index 8286b33..eebe56f 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
@@ -16,8 +16,8 @@
import '../resolution/semantic_visitor.dart';
import '../resolution/tree_elements.dart' show TreeElements;
import '../tree/tree.dart';
-import '../types/types.dart' show TypeMask;
import '../types/constants.dart' show computeTypeMask;
+import '../types/types.dart' show TypeMask;
import '../universe/call_structure.dart' show CallStructure;
import '../universe/selector.dart' show Selector;
import '../util/util.dart';
diff --git a/pkg/compiler/lib/src/inferrer/list_tracer.dart b/pkg/compiler/lib/src/inferrer/list_tracer.dart
index 83f2e8b..d0985e0 100644
--- a/pkg/compiler/lib/src/inferrer/list_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/list_tracer.dart
@@ -7,7 +7,6 @@
import '../elements/elements.dart';
import '../universe/selector.dart' show Selector;
import '../util/util.dart' show Setlet;
-
import 'node_tracer.dart';
import 'type_graph_nodes.dart';
diff --git a/pkg/compiler/lib/src/inferrer/map_tracer.dart b/pkg/compiler/lib/src/inferrer/map_tracer.dart
index 3bd0e41..22a9f0f 100644
--- a/pkg/compiler/lib/src/inferrer/map_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/map_tracer.dart
@@ -6,7 +6,6 @@
import '../elements/elements.dart';
import '../universe/selector.dart' show Selector;
-
import 'node_tracer.dart';
import 'type_graph_nodes.dart';
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index dca18a5..cc890bf 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -9,10 +9,9 @@
import '../elements/elements.dart';
import '../types/types.dart' show ContainerTypeMask, MapTypeMask;
import '../util/util.dart' show Setlet;
-
+import 'debug.dart' as debug;
import 'type_graph_inferrer.dart' show TypeGraphInferrerEngine;
import 'type_graph_nodes.dart';
-import 'debug.dart' as debug;
// A set of selectors we know do not escape the elements inside the
// list.
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
index 3e68725..8024e52 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_dump.dart
@@ -4,10 +4,11 @@
library dart2js.inferrer.type_graph_dump;
import 'dart:async';
-import 'type_graph_nodes.dart';
-import 'type_graph_inferrer.dart';
+
import '../elements/elements.dart';
import '../types/types.dart';
+import 'type_graph_inferrer.dart';
+import 'type_graph_nodes.dart';
/// Dumps the type inference graph in Graphviz Dot format into the `typegraph`
/// subfolder of the current working directory. Each function body is dumped in
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index 4f185c2..d610c54 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -15,8 +15,8 @@
import '../elements/elements.dart';
import '../js_backend/js_backend.dart' show Annotations, JavaScriptBackend;
import '../resolution/tree_elements.dart' show TreeElementMapping;
-import '../tree/tree.dart' as ast show Node, LiteralBool, TryStatement;
import '../tree/dartstring.dart' show DartString;
+import '../tree/tree.dart' as ast show Node, LiteralBool, TryStatement;
import '../types/constants.dart' show computeTypeMask;
import '../types/types.dart'
show ContainerTypeMask, MapTypeMask, TypeMask, TypesInferrer;
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 1a6842f..c21b118 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -13,9 +13,8 @@
import '../cps_ir/cps_ir_nodes.dart' as cps_ir show Node;
import '../dart_types.dart' show DartType, FunctionType, TypeKind;
import '../elements/elements.dart';
-import '../native/native.dart' as native;
-import '../tree/tree.dart' as ast show Node, LiteralBool, Send;
import '../tree/dartstring.dart' show DartString;
+import '../tree/tree.dart' as ast show Node, LiteralBool, Send;
import '../types/types.dart'
show
ContainerTypeMask,
diff --git a/pkg/compiler/lib/src/info/analysis_result.dart b/pkg/compiler/lib/src/info/analysis_result.dart
deleted file mode 100644
index 5266a01..0000000
--- a/pkg/compiler/lib/src/info/analysis_result.dart
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2015, 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.
-
-/// API to get results from a static analysis of the source program.
-library compiler.src.stats.analysis_result;
-
-import '../tree/tree.dart' show Node;
-import '../universe/selector.dart' show Selector;
-
-/// A three-value logic bool (yes, no, maybe). We say that `yes` and `maybe` are
-/// "truthy", while `no` and `maybe` are "falsy".
-// TODO(sigmund): is it worth using an enum? or switch to true/false/null?
-enum Boolish { yes, no, maybe }
-
-/// Specifies results of some kind of static analysis on a source program.
-abstract class AnalysisResult {
- /// Information computed about a specific [receiver].
- ReceiverInfo infoForReceiver(Node receiver);
-
- /// Information computed about a specific [selector] applied to a specific
- /// [receiver].
- SelectorInfo infoForSelector(Node receiver, Selector selector);
-}
-
-/// Analysis information about a receiver of a send.
-abstract class ReceiverInfo {
- /// Receiver node for which this information is computed.
- Node get receiver;
-
- /// Return whether [receiver] resolves to a value that implements no such
- /// method. The answer is `yes` if all values that [receiver] could evaluate
- /// to at runtime contain it, or `no` if none of them does. Maybe if it
- /// depends on some context or we can't determine this information precisely.
- Boolish get hasNoSuchMethod;
-
- /// When [hasNoSuchMethod] is yes, the precise number of possible noSuchMethod
- /// handlers for this receiver.
- int get possibleNsmTargets;
-
- /// Return whether [receiver] may ever be null.
- Boolish get isNull;
-}
-
-/// Information about a specific selector applied to a specific receiver.
-abstract class SelectorInfo {
- /// Receiver node of the [selector].
- Node get receiver;
-
- /// Specific selector on [receiver] for which this information is computed.
- Selector get selector;
-
- /// Whether a member matching [selector] exists in [receiver].
- Boolish get exists;
-
- /// Whether [receiver] needs an interceptor to implement [selector].
- Boolish get usesInterceptor;
-
- /// Possible total number of methods that could be the target of the selector.
- /// This needs to be combined with [isAccurate] to correctly understand the
- /// value. Some invariants:
- ///
- /// * If [exists] is `no`, the value here should be 0, regardless of
- /// accuracy.
- /// * If [exists] is `yes`, the value is always considered 1 or more.
- /// If [isAccurate] is false, we treat it as there may be many possible
- /// targets.
- /// * If [exists] is `maybe`, the value is considered 0 or more.
- int get possibleTargets;
-
- /// Whether the information about [possibleTargets] is accurate.
- bool get isAccurate;
-}
diff --git a/pkg/compiler/lib/src/info/naive_analysis_result.dart b/pkg/compiler/lib/src/info/naive_analysis_result.dart
deleted file mode 100644
index d18dc91..0000000
--- a/pkg/compiler/lib/src/info/naive_analysis_result.dart
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2015, 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.
-
-/// API to get results from a static analysis of the source program.
-// TODO(sigmund): split out implementations out of this file.
-library compiler.src.stats.naive_analysis_result;
-
-import 'analysis_result.dart';
-import '../tree/tree.dart' show Node;
-import '../universe/selector.dart' show Selector;
-
-/// A naive [AnalysisResult] that tells us very little. This is the most
-/// conservative we can be when we only use information from the AST structure
-/// and from resolution, but no type information.
-class NaiveAnalysisResult implements AnalysisResult {
- NaiveAnalysisResult();
-
- ReceiverInfo infoForReceiver(Node receiver) =>
- new NaiveReceiverInfo(receiver);
- SelectorInfo infoForSelector(Node receiver, Selector selector) =>
- new NaiveSelectorInfo(receiver, selector);
-}
-
-class NaiveReceiverInfo implements ReceiverInfo {
- final Node receiver;
-
- NaiveReceiverInfo(this.receiver);
- Boolish get hasNoSuchMethod => Boolish.maybe;
- Boolish get isNull => Boolish.maybe;
- int get possibleNsmTargets => -1;
-}
-
-class NaiveSelectorInfo implements SelectorInfo {
- final Node receiver;
- final Selector selector;
-
- NaiveSelectorInfo(this.receiver, this.selector);
-
- Boolish get exists => Boolish.maybe;
- Boolish get usesInterceptor => Boolish.maybe;
- int get possibleTargets => -1;
- bool get isAccurate => false;
-}
diff --git a/pkg/compiler/lib/src/info/send_info.dart b/pkg/compiler/lib/src/info/send_info.dart
deleted file mode 100644
index 86f3845..0000000
--- a/pkg/compiler/lib/src/info/send_info.dart
+++ /dev/null
@@ -1,2415 +0,0 @@
-// Copyright (c) 2015, 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.
-
-/// Computes measurements about sends in a function.
-library compiler.src.info.send_info;
-
-import 'package:dart2js_info/src/measurements.dart';
-import 'package:dart2js_info/src/util.dart' show recursiveDiagnosticString;
-
-import '../closure.dart';
-import '../common.dart';
-import '../compiler.dart' show Compiler;
-import '../constants/expressions.dart';
-import '../dart_types.dart';
-import '../elements/elements.dart';
-import '../elements/visitor.dart' show ElementVisitor;
-import '../parser/partial_elements.dart' show PartialElement;
-import '../resolution/operators.dart';
-import '../resolution/semantic_visitor.dart';
-import '../resolution/tree_elements.dart';
-import '../tree/tree.dart';
-import '../universe/call_structure.dart' show CallStructure;
-import '../universe/selector.dart' show Selector;
-import 'analysis_result.dart';
-import 'naive_analysis_result.dart';
-import 'trusted_types_analysis_result.dart';
-
-/// Collects a set of [Measurements] about send expressions in the function [f].
-// TODO(sigmund): collect information on initializers too.
-Measurements collectSendMeasurements(FunctionElement f, Compiler compiler) {
- DiagnosticReporter reporter = compiler.reporter;
- return reporter.withCurrentElement(f, () {
- // TODO(sigmund): enable for platform too.
- if (f.library.isPlatformLibrary) return null;
- if (!f.hasNode) {
- if (f is PartialElement) return const Measurements.unreachableFunction();
- assert(f is ConstructorElement && f.isSynthesized);
- // TODO(sigmund): measure synthethic forwarding sends, measure
- // initializers
- return new Measurements.reachableFunction();
- }
- if (!f.hasResolvedAst) {
- _debug('no resolved ast ${f.runtimeType}');
- return null;
- }
- var resolvedAst = f.resolvedAst;
- if (resolvedAst.node == null) {
- _debug('no node ${f.runtimeType}');
- return null;
- }
- var def = resolvedAst.elements.getFunctionDefinition(resolvedAst.node);
- if (def == null) {
- assert(f is PartialElement);
- return const Measurements.unreachableFunction();
- }
-
- var visitor = new _StatsTraversalVisitor(compiler, resolvedAst.elements,
- reporter.spanFromSpannable(resolvedAst.node).uri);
- resolvedAst.node.accept(visitor);
- return visitor.measurements;
- });
-}
-
-/// Visitor that categorizes data about an individual send.
-class _StatsVisitor<T> extends Visitor
- with SemanticSendResolvedMixin<dynamic, T>
- implements SemanticSendVisitor<dynamic, T> {
- // TODO(sigmund): consider passing in several AnalysisResults at once, so we
- // can compute the different metrics together.
- /// Information we know about the program from static analysis.
- final AnalysisResult info;
-
- /// Results from this function.
- final Measurements measurements;
-
- final DiagnosticReporter reporter;
- final TreeElements elements;
-
- SemanticSendVisitor<dynamic, T> get sendVisitor => this;
-
- _StatsVisitor(this.reporter, this.elements, this.info, Uri sourceUri)
- : measurements = new Measurements.reachableFunction(sourceUri);
-
- visitNode(Node node) => throw "unhandled ${node.runtimeType}: $node";
- apply(Node node, T arg) => throw "missing apply ${node.runtimeType}: $node";
- internalError(Node node, String arg) => throw "internal error on $node";
-
- visitSend(Send node) {
- _checkInvariant(node, 'before');
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.send, span.begin, span.end);
- if (node is SendSet) {
- if ((node.assignmentOperator != null &&
- node.assignmentOperator.source != '=') ||
- node.isPrefix ||
- node.isPostfix) {
- assert(!node.isIfNullAssignment);
- // We count get and set separately in case one of them is defined by the
- // other could be a nSM error.
- measurements.record(Metric.send, span.begin, span.end);
- measurements.record(Metric.send, span.begin, span.end);
- } else if (node.isIfNullAssignment) {
- measurements.record(Metric.send, span.begin, span.end);
- }
- }
- super.visitSend(node);
- _checkInvariant(node, 'after ');
- }
-
- visitNewExpression(NewExpression node) {
- _checkInvariant(node, 'before');
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.send, span.begin, span.end);
- super.visitNewExpression(node);
- _checkInvariant(node, 'after ');
- }
-
- /// A monomorphic local variable read.
- ///
- /// See [Metric.send] for a full categorization of sends.
- handleLocal(Node node) {
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.monomorphicSend, span.begin, span.end);
- measurements.record(Metric.localSend, span.begin, span.end);
- }
-
- /// A monomorphic virual call on [node], where we know which function is the
- /// target of the call (for example, because only one type in a class
- /// hierarchy implements a function with a given name).
- ///
- /// See [Metric.send] for a full categorization of sends.
- handleSingleInstance(Node node) {
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.monomorphicSend, span.begin, span.end);
- measurements.record(Metric.instanceSend, span.begin, span.end);
- }
-
- /// A monomorphic call that goes through an interceptor. This is equivalent in
- /// terms of what the compiler knows as we do with [handleSignleInstance], and
- /// because we know the target of the call, we also know that it doesn't live
- /// in the object instance, but on an interceptor on the side.
- ///
- /// See [Metric.send] for a full categorization of sends.
- handleSingleInterceptor(Node node) {
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.monomorphicSend, span.begin, span.end);
- measurements.record(Metric.interceptorSend, span.begin, span.end);
- }
-
- /// A polymorphic call that goes through an interceptor.
- ///
- /// See [Metric.send] for a full categorization of sends.
- handleMultiInterceptor(Node node) {
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.polymorphicSend, span.begin, span.end);
- measurements.record(Metric.multiInterceptorSend, span.begin, span.end);
- }
-
- handleConstructor(Node node) {
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.monomorphicSend, span.begin, span.end);
- measurements.record(Metric.constructorSend, span.begin, span.end);
- }
-
- handleDynamic(Node node) {
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.polymorphicSend, span.begin, span.end);
- measurements.record(Metric.dynamicSend, span.begin, span.end);
- }
-
- handleVirtual(Node node) {
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.polymorphicSend, span.begin, span.end);
- measurements.record(Metric.virtualSend, span.begin, span.end);
- }
-
- handleNSMError(Node node) {
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.monomorphicSend, span.begin, span.end);
- measurements.record(Metric.nsmErrorSend, span.begin, span.end);
- }
-
- handleNSMSingle(Node node) {
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.monomorphicSend, span.begin, span.end);
- measurements.record(Metric.singleNsmCallSend, span.begin, span.end);
- }
-
- handleNSMSuper(Node node, ClassElement type) {
- var superclass = type.superclass;
- var member = superclass.lookupMember('noSuchMethod');
- if (!member.enclosingClass.isObject) {
- handleNSMSingle(node);
- } else {
- handleNSMError(node);
- }
- }
-
- handleNSMAny(Node node) {
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.polymorphicSend, span.begin, span.end);
- measurements.record(Metric.multiNsmCallSend, span.begin, span.end);
- }
-
- handleSuper(Node node) {
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.monomorphicSend, span.begin, span.end);
- measurements.record(Metric.superSend, span.begin, span.end);
- }
-
- handleTypeVariable(Node node) {
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.monomorphicSend, span.begin, span.end);
- measurements.record(Metric.typeVariableSend, span.begin, span.end);
- }
-
- handleStatic(Node node) {
- var span = reporter.spanFromSpannable(node);
- measurements.record(Metric.monomorphicSend, span.begin, span.end);
- measurements.record(Metric.staticSend, span.begin, span.end);
- }
-
- handleNoSend(Node node) {
- measurements.popLast(Metric.send);
- }
-
- void handleDynamicProperty(Node node, Node receiver, Selector selector) {
- // staticSend: no (automatically)
- // superSend: no (automatically)
- // localSend: no (automatically)
- // constructorSend: no (automatically)
- // typeVariableSend: no (automatically)
-
- // nsmErrorSend: receiver has no `selector` nor nSM.
- // singleNsmCallSend: receiver has no `selector`, but definitely has `nSM`
- // instanceSend: receiver has `selector`, no need to use an interceptor
- // interceptorSend: receiver has `selector`, but we know we need an
- // interceptor to get it
-
- // multiNsmCallSend: receiver has no `selector`, not sure if receiver has
- // nSM, or not sure which nSM is called (does this one
- // matter, or does nSM is treated like an instance method
- // call)?
- // virtualSend: receiver has `selector`, we know we do not need an
- // interceptor, not sure which specific type implements
- // the selector.
- // multiInterceptorSend: multiple possible receiver types, all using an
- // interceptor to get the `selector`, might be
- // possbile to pick a special selector logic for this
- // combination?
- // dynamicSend: any combination of the above.
-
- ReceiverInfo receiverInfo = info.infoForReceiver(receiver);
- SelectorInfo selectorInfo = info.infoForSelector(receiver, selector);
- Boolish hasSelector = selectorInfo.exists;
- Boolish hasNsm = receiverInfo.hasNoSuchMethod;
-
- if (hasSelector == Boolish.no) {
- if (hasNsm == Boolish.no) {
- handleNSMError(node);
- } else if (hasNsm == Boolish.yes) {
- if (receiverInfo.possibleNsmTargets == 1) {
- handleNSMSingle(node);
- } else {
- handleNSMAny(node);
- }
- } else {
- handleDynamic(node);
- }
- return;
- }
-
- Boolish usesInterceptor = selectorInfo.usesInterceptor;
- if (hasSelector == Boolish.yes) {
- if (selectorInfo.isAccurate && selectorInfo.possibleTargets == 1) {
- assert(usesInterceptor != Boolish.maybe);
- if (usesInterceptor == Boolish.yes) {
- handleSingleInterceptor(node);
- } else {
- handleSingleInstance(node);
- }
- } else {
- if (usesInterceptor == Boolish.no) {
- handleVirtual(node);
- } else if (usesInterceptor == Boolish.yes) {
- handleMultiInterceptor(node);
- } else {
- handleDynamic(node);
- }
- }
- return;
- }
- handleDynamic(node);
- }
-
- void handleThisProperty(Send node, Selector selector) {
- handleDynamicProperty(node, node.receiver, selector);
- }
-
- void handleIndex(Node node) {
- handleDynamic(node);
- }
-
- void handleOperator(Node node) {
- handleDynamic(node);
- }
-
- void handleInvoke(Node node) {
- handleDynamic(node);
- }
-
- void handleEquals(Node node) {
- handleDynamic(node);
- }
-
- // Constructors
-
- void visitAbstractClassConstructorInvoke(
- NewExpression node,
- ConstructorElement element,
- InterfaceType type,
- NodeList arguments,
- CallStructure callStructure,
- T arg) {
- handleConstructor(node);
- }
-
- void visitBoolFromEnvironmentConstructorInvoke(NewExpression node,
- BoolFromEnvironmentConstantExpression constant, T arg) {
- handleConstructor(node);
- }
-
- void visitConstConstructorInvoke(
- NewExpression node, ConstructedConstantExpression constant, T arg) {
- handleConstructor(node);
- }
-
- void visitGenerativeConstructorInvoke(
- NewExpression node,
- ConstructorElement constructor,
- InterfaceType type,
- NodeList arguments,
- CallStructure callStructure,
- T arg) {
- handleConstructor(node);
- }
-
- void visitIntFromEnvironmentConstructorInvoke(NewExpression node,
- IntFromEnvironmentConstantExpression constant, T arg) {
- handleConstructor(node);
- }
-
- void visitRedirectingFactoryConstructorInvoke(
- NewExpression node,
- ConstructorElement constructor,
- InterfaceType type,
- ConstructorElement effectiveTarget,
- InterfaceType effectiveTargetType,
- NodeList arguments,
- CallStructure callStructure,
- T arg) {
- handleConstructor(node);
- }
-
- void visitRedirectingGenerativeConstructorInvoke(
- NewExpression node,
- ConstructorElement constructor,
- InterfaceType type,
- NodeList arguments,
- CallStructure callStructure,
- T arg) {
- handleConstructor(node);
- }
-
- void visitStringFromEnvironmentConstructorInvoke(NewExpression node,
- StringFromEnvironmentConstantExpression constant, T arg) {
- handleConstructor(node);
- }
-
- // Dynamic sends
-
- // TODO(sigmund): many many things to add:
- // -- support for operators, indexers, etc.
- // -- logic about nullables
- // -- int, JSArray
- // -- all interceptors
-
- void visitBinary(
- Send node, Node left, BinaryOperator operator, Node right, T arg) {
- handleOperator(node);
- }
-
- void visitCompoundIndexSet(SendSet node, Node receiver, Node index,
- AssignmentOperator operator, Node rhs, T arg) {
- handleIndex(node); // t1 = receiver[index]
- handleOperator(node); // t2 = t1 op rhs
- handleIndex(node); // receiver[index] = t2
- }
-
- void visitDynamicPropertyCompound(Send node, Node receiver, Name name,
- AssignmentOperator operator, Node rhs, T arg) {
- handleDynamicProperty(node, receiver, new Selector.getter(name));
- handleOperator(node);
- handleDynamicProperty(node, receiver, new Selector.setter(name));
- }
-
- void visitDynamicPropertyGet(Send node, Node receiver, Name name, T arg) {
- handleDynamicProperty(node, receiver, new Selector.getter(name));
- }
-
- void visitDynamicPropertyInvoke(
- Send node, Node receiver, NodeList arguments, Selector selector, T arg) {
- handleDynamicProperty(node, receiver, selector);
- }
-
- void visitDynamicPropertyPostfix(
- Send node, Node receiver, Name name, IncDecOperator operator, T arg) {
- handleDynamicProperty(node, receiver, new Selector.getter(name));
- handleOperator(node);
- handleDynamicProperty(node, receiver, new Selector.setter(name));
- }
-
- void visitDynamicPropertyPrefix(
- Send node, Node receiver, Name name, IncDecOperator operator, T arg) {
- handleDynamicProperty(node, receiver, new Selector.getter(name));
- handleOperator(node);
- handleDynamicProperty(node, receiver, new Selector.setter(name));
- }
-
- void visitDynamicPropertySet(
- SendSet node, Node receiver, Name name, Node rhs, T arg) {
- handleDynamicProperty(node, receiver, new Selector.setter(name));
- }
-
- void visitDynamicPropertySetIfNull(
- Send node, Node receiver, Name name, Node rhs, T arg) {
- // read to check for null?
- handleDynamicProperty(node, receiver, new Selector.getter(name));
- handleDynamicProperty(node, receiver, new Selector.setter(name));
- }
-
- void visitEquals(Send node, Node left, Node right, T arg) {
- handleEquals(node);
- }
-
- void visitExpressionInvoke(Send node, Node expression, NodeList arguments,
- CallStructure callStructure, T arg) {
- handleInvoke(node);
- }
-
- void visitIfNotNullDynamicPropertyCompound(Send node, Node receiver,
- Name name, AssignmentOperator operator, Node rhs, T arg) {
- handleDynamicProperty(node, receiver, new Selector.getter(name));
- handleOperator(node);
- handleDynamicProperty(node, receiver, new Selector.setter(name));
- }
-
- void visitIfNotNullDynamicPropertyGet(
- Send node, Node receiver, Name name, T arg) {
- handleDynamicProperty(node, receiver, new Selector.getter(name));
- }
-
- void visitIfNotNullDynamicPropertyInvoke(
- Send node, Node receiver, NodeList arguments, Selector selector, T arg) {
- handleDynamicProperty(node, receiver, selector);
- }
-
- void visitIfNotNullDynamicPropertyPostfix(
- Send node, Node receiver, Name name, IncDecOperator operator, T arg) {
- handleDynamicProperty(node, receiver, new Selector.getter(name));
- handleOperator(node);
- handleDynamicProperty(node, receiver, new Selector.setter(name));
- }
-
- void visitIfNotNullDynamicPropertyPrefix(
- Send node, Node receiver, Name name, IncDecOperator operator, T arg) {
- handleDynamicProperty(node, receiver, new Selector.getter(name));
- handleOperator(node);
- handleDynamicProperty(node, receiver, new Selector.setter(name));
- }
-
- void visitIfNotNullDynamicPropertySet(
- SendSet node, Node receiver, Name name, Node rhs, T arg) {
- handleDynamicProperty(node, receiver, new Selector.setter(name));
- }
-
- void visitIfNotNullDynamicPropertySetIfNull(
- Send node, Node receiver, Name name, Node rhs, T arg) {
- handleDynamicProperty(node, receiver, new Selector.getter(name));
- handleDynamicProperty(node, receiver, new Selector.setter(name));
- }
-
- void visitIndex(Send node, Node receiver, Node index, T arg) {
- handleIndex(node);
- }
-
- void visitIndexPostfix(
- Send node, Node receiver, Node index, IncDecOperator operator, T arg) {
- handleIndex(node);
- handleOperator(node);
- handleIndex(node);
- }
-
- void visitIndexPrefix(
- Send node, Node receiver, Node index, IncDecOperator operator, T arg) {
- handleIndex(node);
- handleOperator(node);
- handleIndex(node);
- }
-
- void visitIndexSet(SendSet node, Node receiver, Node index, Node rhs, T arg) {
- handleIndex(node);
- }
-
- void visitLocalVariableCompound(Send node, LocalVariableElement variable,
- AssignmentOperator operator, Node rhs, T arg) {
- handleLocal(node);
- handleOperator(node);
- handleLocal(node);
- }
-
- void visitLocalVariableInvoke(Send node, LocalVariableElement variable,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleInvoke(node);
- }
-
- void visitLocalVariablePostfix(Send node, LocalVariableElement variable,
- IncDecOperator operator, T arg) {
- handleLocal(node);
- handleOperator(node);
- handleLocal(node);
- }
-
- void visitLocalVariablePrefix(Send node, LocalVariableElement variable,
- IncDecOperator operator, T arg) {
- handleLocal(node);
- handleOperator(node);
- handleLocal(node);
- }
-
- void visitNotEquals(Send node, Node left, Node right, T arg) {
- handleEquals(node);
- }
-
- void visitParameterCompound(Send node, ParameterElement parameter,
- AssignmentOperator operator, Node rhs, T arg) {
- handleLocal(node);
- handleOperator(node);
- handleLocal(node);
- }
-
- void visitParameterInvoke(Send node, ParameterElement parameter,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleInvoke(node);
- }
-
- void visitParameterPostfix(
- Send node, ParameterElement parameter, IncDecOperator operator, T arg) {
- handleLocal(node);
- handleOperator(node);
- handleLocal(node);
- }
-
- void visitParameterPrefix(
- Send node, ParameterElement parameter, IncDecOperator operator, T arg) {
- handleLocal(node);
- handleOperator(node);
- handleLocal(node);
- }
-
- void visitStaticFieldCompound(Send node, FieldElement field,
- AssignmentOperator operator, Node rhs, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleStatic(node);
- }
-
- void visitStaticFieldInvoke(Send node, FieldElement field, NodeList arguments,
- CallStructure callStructure, T arg) {
- handleInvoke(node);
- }
-
- void visitStaticFieldPostfix(
- Send node, FieldElement field, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleStatic(node);
- }
-
- void visitStaticFieldPrefix(
- Send node, FieldElement field, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleStatic(node);
- }
-
- void visitStaticGetterInvoke(Send node, FunctionElement getter,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleInvoke(node);
- }
-
- void visitStaticGetterSetterCompound(Send node, FunctionElement getter,
- FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleStatic(node);
- }
-
- void visitStaticGetterSetterPostfix(Send node, FunctionElement getter,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleStatic(node);
- }
-
- void visitStaticGetterSetterPrefix(Send node, FunctionElement getter,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleStatic(node);
- }
-
- void visitSuperFieldCompound(Send node, FieldElement field,
- AssignmentOperator operator, Node rhs, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperFieldFieldCompound(Send node, FieldElement readField,
- FieldElement writtenField, AssignmentOperator operator, Node rhs, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperFieldFieldPostfix(Send node, FieldElement readField,
- FieldElement writtenField, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperFieldFieldPrefix(Send node, FieldElement readField,
- FieldElement writtenField, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperFieldFieldSetIfNull(Send node, FieldElement readField,
- FieldElement writtenField, Node rhs, T arg) {
- handleSuper(node);
- handleNSMSuper(node, readField.enclosingClass);
- }
-
- void visitSuperFieldInvoke(Send node, FieldElement field, NodeList arguments,
- CallStructure callStructure, T arg) {
- handleInvoke(node);
- }
-
- void visitSuperFieldPostfix(
- Send node, FieldElement field, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperFieldPrefix(
- Send node, FieldElement field, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperFieldSetterCompound(Send node, FieldElement field,
- FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperFieldSetterPostfix(Send node, FieldElement field,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperFieldSetterPrefix(Send node, FieldElement field,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperFieldSetterSetIfNull(
- Send node, FieldElement field, FunctionElement setter, Node rhs, T arg) {
- handleSuper(node);
- handleSuper(node);
- }
-
- void visitSuperGetterFieldCompound(Send node, FunctionElement getter,
- FieldElement field, AssignmentOperator operator, Node rhs, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperGetterFieldPostfix(Send node, FunctionElement getter,
- FieldElement field, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperGetterFieldPrefix(Send node, FunctionElement getter,
- FieldElement field, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperGetterFieldSetIfNull(
- Send node, FunctionElement getter, FieldElement field, Node rhs, T arg) {
- handleSuper(node);
- handleSuper(node);
- }
-
- void visitSuperGetterInvoke(Send node, FunctionElement getter,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleInvoke(node);
- }
-
- void visitSuperGetterSetterCompound(Send node, FunctionElement getter,
- FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperGetterSetterPostfix(Send node, FunctionElement getter,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperGetterSetterPrefix(Send node, FunctionElement getter,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperGetterSetterSetIfNull(Send node, FunctionElement getter,
- FunctionElement setter, Node rhs, T arg) {
- handleSuper(node);
- handleSuper(node);
- }
-
- void visitSuperIndexPostfix(
- Send node,
- MethodElement indexFunction,
- MethodElement indexSetFunction,
- Node index,
- IncDecOperator operator,
- T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperIndexPrefix(
- Send node,
- MethodElement indexFunction,
- MethodElement indexSetFunction,
- Node index,
- IncDecOperator operator,
- T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitSuperMethodSetterCompound(Send node, FunctionElement method,
- FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
- handleSuper(node);
- handleNSMSuper(node, method.enclosingClass);
- handleSuper(node);
- }
-
- void visitSuperMethodSetterPostfix(Send node, FunctionElement method,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleNSMSuper(node, method.enclosingClass);
- handleSuper(node);
- }
-
- void visitSuperMethodSetterPrefix(Send node, FunctionElement method,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleNSMSuper(node, method.enclosingClass);
- handleSuper(node);
- }
-
- void visitSuperMethodSetterSetIfNull(Send node, FunctionElement method,
- FunctionElement setter, Node rhs, T arg) {
- handleSuper(node);
- handleSuper(node);
- }
-
- void visitThisPropertyCompound(
- Send node, Name name, AssignmentOperator operator, Node rhs, T arg) {
- handleThisProperty(node, new Selector.getter(name));
- handleOperator(node);
- handleThisProperty(node, new Selector.setter(name));
- }
-
- void visitThisPropertyInvoke(
- Send node, NodeList arguments, Selector selector, T arg) {
- handleThisProperty(node, selector);
- }
-
- void visitThisPropertyPostfix(
- Send node, Name name, IncDecOperator operator, T arg) {
- handleThisProperty(node, new Selector.getter(name));
- handleOperator(node);
- handleThisProperty(node, new Selector.setter(name));
- }
-
- void visitThisPropertyPrefix(
- Send node, Name name, IncDecOperator operator, T arg) {
- handleThisProperty(node, new Selector.getter(name));
- handleOperator(node);
- handleThisProperty(node, new Selector.setter(name));
- }
-
- void visitTopLevelFieldCompound(Send node, FieldElement field,
- AssignmentOperator operator, Node rhs, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleStatic(node);
- }
-
- void visitTopLevelFieldInvoke(Send node, FieldElement field,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleInvoke(node);
- }
-
- void visitTopLevelFieldPostfix(
- Send node, FieldElement field, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleStatic(node);
- }
-
- void visitTopLevelFieldPrefix(
- Send node, FieldElement field, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleStatic(node);
- }
-
- void visitTopLevelGetterInvoke(Send node, FunctionElement getter,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleInvoke(node);
- }
-
- void visitTopLevelGetterSetterCompound(Send node, FunctionElement getter,
- FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleStatic(node);
- }
-
- void visitTopLevelGetterSetterPostfix(Send node, FunctionElement getter,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleStatic(node);
- }
-
- void visitTopLevelGetterSetterPrefix(Send node, FunctionElement getter,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleStatic(node);
- }
-
- void visitUnary(Send node, UnaryOperator operator, Node expression, T arg) {
- handleDynamic(node);
- }
-
- // Local variable sends
-
- void visitLocalFunctionGet(Send node, LocalFunctionElement function, T arg) {
- handleLocal(node);
- }
-
- void visitLocalFunctionInvoke(Send node, LocalFunctionElement function,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleLocal(node);
- }
-
- void visitLocalVariableGet(Send node, LocalVariableElement variable, T arg) {
- handleLocal(node);
- }
-
- void visitLocalVariableSet(
- SendSet node, LocalVariableElement variable, Node rhs, T arg) {
- handleLocal(node);
- }
-
- void visitLocalVariableSetIfNull(
- SendSet node, LocalVariableElement variable, Node rhs, T arg) {
- handleLocal(node);
- handleLocal(node);
- }
-
- void visitParameterGet(Send node, ParameterElement parameter, T arg) {
- handleLocal(node);
- }
-
- void visitParameterSet(
- SendSet node, ParameterElement parameter, Node rhs, T arg) {
- handleLocal(node);
- }
-
- void visitParameterSetIfNull(
- Send node, ParameterElement parameter, Node rhs, T arg) {
- handleLocal(node);
- handleLocal(node);
- }
-
- // Super monomorphic sends
-
- void visitSuperBinary(Send node, FunctionElement function,
- BinaryOperator operator, Node argument, T arg) {
- handleSuper(node);
- }
-
- void visitSuperEquals(
- Send node, FunctionElement function, Node argument, T arg) {
- handleSuper(node);
- }
-
- void visitSuperFieldGet(Send node, FieldElement field, T arg) {
- handleSuper(node);
- }
-
- void visitSuperFieldSet(SendSet node, FieldElement field, Node rhs, T arg) {
- handleSuper(node);
- }
-
- void visitSuperFieldSetIfNull(
- SendSet node, FieldElement field, Node rhs, T arg) {
- handleSuper(node);
- handleSuper(node);
- }
-
- void visitSuperGetterGet(Send node, FunctionElement getter, T arg) {
- handleSuper(node);
- }
-
- void visitSuperGetterSet(
- SendSet node, FunctionElement getter, Node rhs, T arg) {
- handleSuper(node);
- }
-
- void visitSuperIndex(Send node, FunctionElement function, Node index, T arg) {
- handleSuper(node);
- }
-
- void visitSuperIndexSet(
- SendSet node, FunctionElement function, Node index, Node rhs, T arg) {
- handleSuper(node);
- }
-
- void visitSuperMethodGet(Send node, MethodElement method, T arg) {
- handleSuper(node);
- }
-
- void visitSuperMethodInvoke(Send node, MethodElement method,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleSuper(node);
- }
-
- void visitSuperNotEquals(
- Send node, FunctionElement function, Node argument, T arg) {
- handleSuper(node);
- }
-
- void visitSuperSetterSet(
- SendSet node, FunctionElement setter, Node rhs, T arg) {
- handleSuper(node);
- }
-
- void visitSuperUnary(
- Send node, UnaryOperator operator, FunctionElement function, T arg) {
- handleSuper(node);
- }
-
- // Statically known "no such method" sends
-
- void visitConstructorIncompatibleInvoke(
- NewExpression node,
- ConstructorElement constructor,
- InterfaceType type,
- NodeList arguments,
- CallStructure callStructure,
- T arg) {
- handleNSMError(node);
- }
-
- void visitFinalLocalVariableCompound(Send node, LocalVariableElement variable,
- AssignmentOperator operator, Node rhs, T arg) {
- handleLocal(node);
- handleOperator(node);
- handleNSMError(node);
- }
-
- void visitFinalLocalVariablePostfix(Send node, LocalVariableElement variable,
- IncDecOperator operator, T arg) {
- handleLocal(node);
- handleOperator(node);
- handleNSMError(node);
- }
-
- void visitFinalLocalVariablePrefix(Send node, LocalVariableElement variable,
- IncDecOperator operator, T arg) {
- handleLocal(node);
- handleOperator(node);
- handleNSMError(node);
- }
-
- void visitFinalLocalVariableSet(
- SendSet node, LocalVariableElement variable, Node rhs, T arg) {
- handleNSMError(node);
- }
-
- void visitFinalLocalVariableSetIfNull(
- SendSet node, LocalVariableElement variable, Node rhs, T arg) {
- handleLocal(node); // read for null
- handleNSMError(node); // set fails
- }
-
- void visitFinalParameterCompound(Send node, ParameterElement parameter,
- AssignmentOperator operator, Node rhs, T arg) {
- handleLocal(node);
- handleOperator(node);
- handleNSMError(node);
- }
-
- void visitFinalParameterPostfix(
- Send node, ParameterElement parameter, IncDecOperator operator, T arg) {
- handleLocal(node);
- handleOperator(node);
- handleNSMError(node);
- }
-
- void visitFinalParameterPrefix(
- Send node, ParameterElement parameter, IncDecOperator operator, T arg) {
- handleLocal(node);
- handleOperator(node);
- handleNSMError(node);
- }
-
- void visitFinalParameterSet(
- SendSet node, ParameterElement parameter, Node rhs, T arg) {
- handleNSMError(node);
- }
-
- void visitFinalParameterSetIfNull(
- SendSet node, ParameterElement parameter, Node rhs, T arg) {
- handleLocal(node);
- handleNSMError(node);
- }
-
- void visitFinalStaticFieldCompound(Send node, FieldElement field,
- AssignmentOperator operator, Node rhs, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleNSMError(node);
- }
-
- void visitFinalStaticFieldPostfix(
- Send node, FieldElement field, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleNSMError(node);
- }
-
- void visitFinalStaticFieldPrefix(
- Send node, FieldElement field, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleNSMError(node);
- }
-
- void visitFinalStaticFieldSet(
- SendSet node, FieldElement field, Node rhs, T arg) {
- handleNSMError(node);
- }
-
- void visitFinalStaticFieldSetIfNull(
- SendSet node, FieldElement field, Node rhs, T arg) {
- handleStatic(node);
- handleNSMError(node);
- }
-
- void visitFinalSuperFieldSetIfNull(
- Send node, FieldElement field, Node rhs, T arg) {
- handleSuper(node);
- handleNSMSuper(node, field.enclosingClass);
- }
-
- void visitFinalSuperFieldCompound(Send node, FieldElement field,
- AssignmentOperator operator, Node rhs, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleNSMSuper(node, field.enclosingClass);
- }
-
- void visitFinalSuperFieldPostfix(
- Send node, FieldElement field, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleNSMSuper(node, field.enclosingClass);
- }
-
- void visitFinalSuperFieldPrefix(
- Send node, FieldElement field, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleNSMSuper(node, field.enclosingClass);
- }
-
- void visitFinalSuperFieldSet(
- SendSet node, FieldElement field, Node rhs, T arg) {
- handleNSMSuper(node, field.enclosingClass);
- }
-
- void visitFinalTopLevelFieldCompound(Send node, FieldElement field,
- AssignmentOperator operator, Node rhs, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleNSMError(node);
- }
-
- void visitFinalTopLevelFieldPostfix(
- Send node, FieldElement field, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleNSMError(node);
- }
-
- void visitFinalTopLevelFieldPrefix(
- Send node, FieldElement field, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleOperator(node);
- handleNSMError(node);
- }
-
- void visitFinalTopLevelFieldSet(
- SendSet node, FieldElement field, Node rhs, T arg) {
- handleNSMError(node);
- }
-
- void visitFinalTopLevelFieldSetIfNull(
- SendSet node, FieldElement field, Node rhs, T arg) {
- handleStatic(node);
- handleNSMError(node);
- }
-
- void visitTopLevelGetterSetterSetIfNull(Send node, FunctionElement getter,
- FunctionElement setter, Node rhs, T arg) {
- handleStatic(node);
- handleStatic(node);
- }
-
- void visitTopLevelMethodSetterSetIfNull(Send node, FunctionElement method,
- FunctionElement setter, Node rhs, T arg) {
- handleStatic(node);
- handleStatic(node);
- }
-
- void visitTopLevelMethodSetIfNull(
- Send node, FunctionElement method, Node rhs, T arg) {
- handleStatic(node);
- handleNSMError(node);
- }
-
- void visitLocalFunctionIncompatibleInvoke(
- Send node,
- LocalFunctionElement function,
- NodeList arguments,
- CallStructure callStructure,
- T arg) {
- handleNSMError(node);
- }
-
- void visitLocalFunctionCompound(Send node, LocalFunctionElement function,
- AssignmentOperator operator, Node rhs, T arg) {
- handleLocal(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitLocalFunctionPostfix(Send node, LocalFunctionElement function,
- IncDecOperator operator, T arg) {
- handleLocal(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitLocalFunctionPrefix(Send node, LocalFunctionElement function,
- IncDecOperator operator, T arg) {
- handleLocal(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitLocalFunctionSet(
- SendSet node, LocalFunctionElement function, Node rhs, T arg) {
- handleNSMError(node);
- }
-
- void visitLocalFunctionSetIfNull(
- SendSet node, LocalFunctionElement function, Node rhs, T arg) {
- handleLocal(node);
- handleNSMError(node);
- }
-
- void visitStaticFunctionIncompatibleInvoke(Send node, MethodElement function,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleNSMError(node);
- }
-
- void visitStaticFunctionSet(
- Send node, MethodElement function, Node rhs, T arg) {
- handleNSMError(node);
- }
-
- void visitStaticMethodCompound(Send node, MethodElement method,
- AssignmentOperator operator, Node rhs, T arg) {
- handleStatic(node);
- handleNSMError(node); // operator on a method closure yields nSM
- handleNoSend(node); // setter is not invoked, don't count it.
- }
-
- void visitStaticMethodPostfix(
- Send node, MethodElement method, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitStaticMethodPrefix(
- Send node, MethodElement method, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitStaticMethodSetterCompound(Send node, MethodElement method,
- MethodElement setter, AssignmentOperator operator, Node rhs, T arg) {
- handleStatic(node);
- handleNSMError(node); // operator on a method closure yields nSM
- handleNoSend(node); // setter is not invoked, don't count it.
- }
-
- void visitStaticMethodSetterPostfix(Send node, FunctionElement getter,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitStaticMethodSetterPrefix(Send node, FunctionElement getter,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitStaticSetterGet(Send node, FunctionElement setter, T arg) {
- handleNSMError(node);
- }
-
- void visitStaticSetterInvoke(Send node, FunctionElement setter,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleNSMError(node);
- }
-
- void visitSuperMethodCompound(Send node, FunctionElement method,
- AssignmentOperator operator, Node rhs, T arg) {
- handleSuper(node);
-
- // An operator send on a method closure yields nSM
- handleNSMSuper(node, method.enclosingClass);
-
- handleNoSend(node); // setter is not invoked, don't count it.
- }
-
- void visitSuperMethodIncompatibleInvoke(Send node, MethodElement method,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleNSMSuper(node, method.enclosingClass);
- }
-
- void visitSuperMethodPostfix(
- Send node, FunctionElement method, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleNSMSuper(node, method.enclosingClass);
- handleNoSend(node);
- }
-
- void visitSuperMethodPrefix(
- Send node, FunctionElement method, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleNSMSuper(node, method.enclosingClass);
- handleNoSend(node);
- }
-
- void visitSuperMethodSet(Send node, MethodElement method, Node rhs, T arg) {
- handleNSMSuper(node, method.enclosingClass);
- }
-
- void visitSuperMethodSetIfNull(
- Send node, MethodElement method, Node rhs, T arg) {
- handleNSMSuper(node, method.enclosingClass);
- }
-
- void visitSuperSetterGet(Send node, FunctionElement setter, T arg) {
- handleNSMSuper(node, setter.enclosingClass);
- }
-
- void visitSuperSetterInvoke(Send node, FunctionElement setter,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleNSMSuper(node, setter.enclosingClass);
- }
-
- void visitTopLevelFunctionIncompatibleInvoke(
- Send node,
- MethodElement function,
- NodeList arguments,
- CallStructure callStructure,
- T arg) {
- handleNSMError(node);
- }
-
- void visitTopLevelFunctionSet(
- Send node, MethodElement function, Node rhs, T arg) {
- handleNSMError(node);
- }
-
- void visitTopLevelGetterSet(
- SendSet node, FunctionElement getter, Node rhs, T arg) {
- handleNSMError(node);
- }
-
- void visitTopLevelMethodCompound(Send node, FunctionElement method,
- AssignmentOperator operator, Node rhs, T arg) {
- handleStatic(node);
- handleNSMError(node); // operator on a method closure yields nSM
- handleNoSend(node); // setter is not invoked, don't count it.
- }
-
- void visitTopLevelMethodPostfix(
- Send node, MethodElement method, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitTopLevelMethodPrefix(
- Send node, MethodElement method, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitTopLevelMethodSetterCompound(Send node, FunctionElement method,
- FunctionElement setter, AssignmentOperator operator, Node rhs, T arg) {
- handleStatic(node);
- handleNSMError(node); // operator on a method closure yields nSM
- handleNoSend(node); // setter is not invoked, don't count it.
- }
-
- void visitTopLevelMethodSetterPostfix(Send node, FunctionElement method,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitTopLevelMethodSetterPrefix(Send node, FunctionElement method,
- FunctionElement setter, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitTopLevelSetterGet(Send node, FunctionElement setter, T arg) {
- handleNSMError(node);
- }
-
- void visitTopLevelSetterInvoke(Send node, FunctionElement setter,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleNSMError(node);
- }
-
- void visitTypeVariableTypeLiteralCompound(
- Send node,
- TypeVariableElement element,
- AssignmentOperator operator,
- Node rhs,
- T arg) {
- handleTypeVariable(node);
- handleNSMError(node); // operator on a method closure yields nSM
- handleNoSend(node); // setter is not invoked, don't count it.
- }
-
- void visitTypeVariableTypeLiteralGet(
- Send node, TypeVariableElement element, T arg) {
- handleTypeVariable(node);
- }
-
- void visitTypeVariableTypeLiteralInvoke(
- Send node,
- TypeVariableElement element,
- NodeList arguments,
- CallStructure callStructure,
- T arg) {
- handleNSMError(node);
- }
-
- void visitTypeVariableTypeLiteralPostfix(
- Send node, TypeVariableElement element, IncDecOperator operator, T arg) {
- handleTypeVariable(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitTypeVariableTypeLiteralPrefix(
- Send node, TypeVariableElement element, IncDecOperator operator, T arg) {
- handleTypeVariable(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitTypeVariableTypeLiteralSet(
- SendSet node, TypeVariableElement element, Node rhs, T arg) {
- handleNSMError(node);
- }
-
- void visitTypeVariableTypeLiteralSetIfNull(
- SendSet node, TypeVariableElement element, Node rhs, T arg) {
- handleTypeVariable(node);
- handleNSMError(node);
- }
-
- void visitTypedefTypeLiteralCompound(Send node, ConstantExpression constant,
- AssignmentOperator operator, Node rhs, T arg) {
- handleTypeVariable(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitTypedefTypeLiteralGet(
- Send node, ConstantExpression constant, T arg) {
- handleTypeVariable(node);
- }
-
- void visitTypedefTypeLiteralInvoke(Send node, ConstantExpression constant,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleNSMError(node);
- }
-
- void visitTypedefTypeLiteralPostfix(
- Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
- handleTypeVariable(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitTypedefTypeLiteralPrefix(
- Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
- handleTypeVariable(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitTypedefTypeLiteralSet(
- SendSet node, ConstantExpression constant, Node rhs, T arg) {
- handleNSMError(node);
- }
-
- void visitTypedefTypeLiteralSetIfNull(
- SendSet node, ConstantExpression constant, Node rhs, T arg) {
- handleStatic(node);
- handleNSMError(node);
- }
-
- void visitUnresolvedClassConstructorInvoke(
- NewExpression node,
- Element element,
- DartType type,
- NodeList arguments,
- Selector selector,
- T arg) {
- handleNSMError(node);
- }
-
- void visitUnresolvedCompound(Send node, Element element,
- AssignmentOperator operator, Node rhs, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedConstructorInvoke(NewExpression node, Element constructor,
- DartType type, NodeList arguments, Selector selector, T arg) {
- handleNSMError(node);
- }
-
- void visitUnresolvedGet(Send node, Element element, T arg) {
- handleNSMError(node);
- }
-
- void visitUnresolvedInvoke(Send node, Element element, NodeList arguments,
- Selector selector, T arg) {
- handleNSMError(node);
- }
-
- void visitUnresolvedPostfix(
- Send node, Element element, IncDecOperator operator, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedPrefix(
- Send node, Element element, IncDecOperator operator, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedRedirectingFactoryConstructorInvoke(
- NewExpression node,
- ConstructorElement constructor,
- InterfaceType type,
- NodeList arguments,
- CallStructure callStructure,
- T arg) {
- handleNSMError(node);
- }
-
- void visitUnresolvedSet(Send node, Element element, Node rhs, T arg) {
- handleNSMError(node);
- }
-
- void visitUnresolvedSetIfNull(Send node, Element element, Node rhs, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedStaticGetterCompound(Send node, Element element,
- MethodElement setter, AssignmentOperator operator, Node rhs, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedStaticGetterPostfix(Send node, Element element,
- MethodElement setter, IncDecOperator operator, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedStaticGetterPrefix(Send node, Element element,
- MethodElement setter, IncDecOperator operator, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedStaticGetterSetIfNull(
- Send node, Element element, MethodElement setter, Node rhs, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedStaticSetterCompound(Send node, MethodElement getter,
- Element element, AssignmentOperator operator, Node rhs, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedStaticSetterPostfix(Send node, MethodElement getter,
- Element element, IncDecOperator operator, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedStaticSetterPrefix(Send node, MethodElement getter,
- Element element, IncDecOperator operator, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedStaticSetterSetIfNull(
- Send node, MethodElement getter, Element element, Node rhs, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedSuperBinary(Send node, Element element,
- BinaryOperator operator, Node argument, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperCompound(Send node, Element element,
- AssignmentOperator operator, Node rhs, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- // TODO(sigmund): we should only count the next 2 if we know that the
- // superclass has a nSM method.
- handleOperator(node);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperCompoundIndexSet(Send node, Element element,
- Node index, AssignmentOperator operator, Node rhs, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleNoSend(node);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperGet(Send node, Element element, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperSet(Send node, Element element, Node rhs, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperSetIfNull(
- Send node, Element element, Node rhs, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleNoSend(node);
- }
-
- void visitUnresolvedSuperGetterCompound(Send node, Element element,
- MethodElement setter, AssignmentOperator operator, Node rhs, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitUnresolvedSuperGetterCompoundIndexSet(
- Send node,
- Element element,
- MethodElement setter,
- Node index,
- AssignmentOperator operator,
- Node rhs,
- T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitUnresolvedSuperGetterIndexPostfix(Send node, Element element,
- MethodElement setter, Node index, IncDecOperator operator, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitUnresolvedSuperGetterIndexPrefix(Send node, Element element,
- MethodElement setter, Node index, IncDecOperator operator, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitUnresolvedSuperGetterPostfix(Send node, Element element,
- MethodElement setter, IncDecOperator operator, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitUnresolvedSuperGetterPrefix(Send node, Element element,
- MethodElement setter, IncDecOperator operator, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitUnresolvedSuperGetterSetIfNull(
- Send node, Element element, MethodElement setter, Node rhs, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleSuper(node);
- }
-
- void visitUnresolvedSuperIndex(
- Send node, Element element, Node index, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperIndexPostfix(
- Send node, Element element, Node index, IncDecOperator operator, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleOperator(node);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperIndexPrefix(
- Send node, Element element, Node index, IncDecOperator operator, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleOperator(node);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperIndexSet(
- Send node, Element element, Node index, Node rhs, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperInvoke(Send node, Element element,
- NodeList arguments, Selector selector, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperPostfix(
- Send node, Element element, IncDecOperator operator, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleOperator(node);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperPrefix(
- Send node, Element element, IncDecOperator operator, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleOperator(node);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperSetterCompound(Send node, MethodElement getter,
- Element element, AssignmentOperator operator, Node rhs, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperSetterCompoundIndexSet(
- Send node,
- MethodElement getter,
- Element element,
- Node index,
- AssignmentOperator operator,
- Node rhs,
- T arg) {
- handleSuper(node);
- handleOperator(node);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperSetterIndexPostfix(
- Send node,
- MethodElement indexFunction,
- Element element,
- Node index,
- IncDecOperator operator,
- T arg) {
- handleSuper(node);
- handleOperator(node);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperSetterIndexPrefix(
- Send node,
- MethodElement indexFunction,
- Element element,
- Node index,
- IncDecOperator operator,
- T arg) {
- handleSuper(node);
- handleOperator(node);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperSetterPostfix(Send node, MethodElement getter,
- Element element, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperSetterPrefix(Send node, MethodElement getter,
- Element element, IncDecOperator operator, T arg) {
- handleSuper(node);
- handleOperator(node);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperSetterSetIfNull(
- Send node, MethodElement getter, Element element, Node rhs, T arg) {
- handleSuper(node);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedSuperUnary(
- Send node, UnaryOperator operator, Element element, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitUnresolvedTopLevelGetterCompound(Send node, Element element,
- MethodElement setter, AssignmentOperator operator, Node rhs, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedTopLevelGetterPostfix(Send node, Element element,
- MethodElement setter, IncDecOperator operator, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedTopLevelGetterPrefix(Send node, Element element,
- MethodElement setter, IncDecOperator operator, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedTopLevelGetterSetIfNull(
- Send node, Element element, MethodElement setter, Node rhs, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedTopLevelSetterCompound(Send node, MethodElement getter,
- Element element, AssignmentOperator operator, Node rhs, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedTopLevelSetterPostfix(Send node, MethodElement getter,
- Element element, IncDecOperator operator, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedTopLevelSetterPrefix(Send node, MethodElement getter,
- Element element, IncDecOperator operator, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void visitUnresolvedTopLevelSetterSetIfNull(
- Send node, MethodElement getter, Element element, Node rhs, T arg) {
- handleNSMError(node);
- handleNoSend(node);
- }
-
- // Static
-
- void visitConstantGet(Send node, ConstantExpression constant, T arg) {
- handleStatic(node);
- }
-
- void visitConstantInvoke(Send node, ConstantExpression constant,
- NodeList arguments, CallStructure callStreucture, T arg) {
- handleStatic(node);
- }
-
- void visitFactoryConstructorInvoke(
- NewExpression node,
- ConstructorElement constructor,
- InterfaceType type,
- NodeList arguments,
- CallStructure callStructure,
- T arg) {
- handleStatic(node);
- }
-
- void visitStaticFieldGet(Send node, FieldElement field, T arg) {
- handleStatic(node);
- }
-
- void visitStaticFieldSet(SendSet node, FieldElement field, Node rhs, T arg) {
- handleStatic(node);
- }
-
- void visitStaticFieldSetIfNull(
- SendSet node, FieldElement field, Node rhs, T arg) {
- handleStatic(node);
- handleStatic(node);
- }
-
- void visitStaticFunctionGet(Send node, MethodElement function, T arg) {
- handleStatic(node);
- }
-
- void visitStaticFunctionInvoke(Send node, MethodElement function,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleStatic(node);
- }
-
- void visitStaticGetterGet(Send node, FunctionElement getter, T arg) {
- handleStatic(node);
- }
-
- void visitStaticGetterSet(
- SendSet node, FunctionElement getter, Node rhs, T arg) {
- handleStatic(node);
- }
-
- void visitStaticSetterSet(
- SendSet node, FunctionElement setter, Node rhs, T arg) {
- handleStatic(node);
- }
-
- void visitStaticGetterSetterSetIfNull(Send node, FunctionElement getter,
- FunctionElement setter, Node rhs, T arg) {
- handleStatic(node);
- handleStatic(node);
- }
-
- void visitStaticMethodSetterSetIfNull(
- Send node, MethodElement method, MethodElement setter, Node rhs, T arg) {
- handleStatic(node);
- handleStatic(node);
- }
-
- void visitStaticMethodSetIfNull(
- Send node, FunctionElement method, Node rhs, T arg) {
- handleStatic(node);
- handleNSMError(node);
- }
-
- void visitTopLevelFieldGet(Send node, FieldElement field, T arg) {
- handleStatic(node);
- }
-
- void visitTopLevelFieldSet(
- SendSet node, FieldElement field, Node rhs, T arg) {
- handleStatic(node);
- }
-
- void visitTopLevelFieldSetIfNull(
- SendSet node, FieldElement field, Node rhs, T arg) {
- handleStatic(node);
- handleStatic(node);
- }
-
- void visitTopLevelFunctionGet(Send node, MethodElement function, T arg) {
- handleStatic(node);
- }
-
- void visitTopLevelFunctionInvoke(Send node, MethodElement function,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleStatic(node);
- }
-
- void visitTopLevelGetterGet(Send node, FunctionElement getter, T arg) {
- handleStatic(node);
- }
-
- void visitTopLevelSetterSet(
- SendSet node, FunctionElement setter, Node rhs, T arg) {
- handleStatic(node);
- }
-
- // Virtual
-
- void visitSuperCompoundIndexSet(
- SendSet node,
- MethodElement getter,
- MethodElement setter,
- Node index,
- AssignmentOperator operator,
- Node rhs,
- T arg) {
- handleSuper(node);
- handleOperator(node);
- handleSuper(node);
- }
-
- void visitThisGet(Identifier node, T arg) {
- handleLocal(node); // TODO(sigmund): should we add a metric for "this"?
- }
-
- void visitThisInvoke(
- Send node, NodeList arguments, CallStructure callStructure, T arg) {
- // TODO(sigmund): implement (treat like this.call())
- handleDynamic(node);
- }
-
- void visitThisPropertyGet(Send node, Name name, T arg) {
- handleThisProperty(node, new Selector.getter(name));
- }
-
- void visitThisPropertySet(SendSet node, Name name, Node rhs, T arg) {
- handleThisProperty(node, new Selector.setter(name));
- }
-
- void visitThisPropertySetIfNull(Send node, Name name, Node rhs, T arg) {
- handleThisProperty(node, new Selector.getter(name));
- handleThisProperty(node, new Selector.setter(name));
- }
-
- // Not count
-
- void errorNonConstantConstructorInvoke(NewExpression node, Element element,
- DartType type, NodeList arguments, CallStructure callStructure, T arg) {
- handleNoSend(node);
- }
-
- void errorUndefinedBinaryExpression(
- Send node, Node left, Operator operator, Node right, T arg) {
- handleNoSend(node);
- }
-
- void errorUndefinedUnaryExpression(
- Send node, Operator operator, Node expression, T arg) {
- handleNoSend(node);
- }
-
- void errorInvalidGet(Send node, ErroneousElement error, T arg) {
- handleNoSend(node);
- }
-
- void errorInvalidInvoke(Send node, ErroneousElement error, NodeList arguments,
- Selector selector, T arg) {
- handleNoSend(node);
- }
-
- void errorInvalidSet(Send node, ErroneousElement error, Node rhs, T arg) {
- handleNoSend(node);
- }
-
- void errorInvalidSetIfNull(
- Send node, ErroneousElement error, Node rhs, T arg) {
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void errorInvalidPrefix(
- Send node, ErroneousElement error, IncDecOperator operator, T arg) {
- handleNoSend(node);
- }
-
- void errorInvalidPostfix(
- Send node, ErroneousElement error, IncDecOperator operator, T arg) {
- handleNoSend(node);
- }
-
- void errorInvalidCompound(Send node, ErroneousElement error,
- AssignmentOperator operator, Node rhs, T arg) {
- handleNoSend(node);
- }
-
- void errorInvalidUnary(
- Send node, UnaryOperator operator, ErroneousElement error, T arg) {
- handleNoSend(node);
- }
-
- void errorInvalidEquals(
- Send node, ErroneousElement error, Node right, T arg) {
- handleNoSend(node);
- }
-
- void errorInvalidNotEquals(
- Send node, ErroneousElement error, Node right, T arg) {
- handleNoSend(node);
- }
-
- void errorInvalidBinary(Send node, ErroneousElement error,
- BinaryOperator operator, Node right, T arg) {
- handleNoSend(node);
- }
-
- void errorInvalidIndex(Send node, ErroneousElement error, Node index, T arg) {
- handleNoSend(node);
- }
-
- void errorInvalidIndexSet(
- Send node, ErroneousElement error, Node index, Node rhs, T arg) {
- handleNoSend(node);
- }
-
- void errorInvalidCompoundIndexSet(Send node, ErroneousElement error,
- Node index, AssignmentOperator operator, Node rhs, T arg) {
- handleNoSend(node);
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void errorInvalidIndexPrefix(Send node, ErroneousElement error, Node index,
- IncDecOperator operator, T arg) {
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void errorInvalidIndexPostfix(Send node, ErroneousElement error, Node index,
- IncDecOperator operator, T arg) {
- handleNoSend(node);
- handleNoSend(node);
- }
-
- void previsitDeferredAccess(Send node, PrefixElement prefix, T arg) {}
-
- void visitAs(Send node, Node expression, DartType type, T arg) {
- handleNoSend(node);
- }
-
- void visitClassTypeLiteralCompound(Send node, ConstantExpression constant,
- AssignmentOperator operator, Node rhs, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitClassTypeLiteralGet(Send node, ConstantExpression constant, T arg) {
- handleStatic(node);
- }
-
- void visitClassTypeLiteralInvoke(Send node, ConstantExpression constant,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleNSMError(node);
- }
-
- void visitClassTypeLiteralPostfix(
- Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitClassTypeLiteralPrefix(
- Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitClassTypeLiteralSet(
- SendSet node, ConstantExpression constant, Node rhs, T arg) {
- handleNSMError(node);
- }
-
- void visitClassTypeLiteralSetIfNull(
- SendSet node, ConstantExpression constant, Node rhs, T arg) {
- handleStatic(node);
- handleNSMError(node);
- }
-
- void visitDynamicTypeLiteralCompound(Send node, ConstantExpression constant,
- AssignmentOperator operator, Node rhs, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitDynamicTypeLiteralGet(
- Send node, ConstantExpression constant, T arg) {
- handleNSMError(node);
- }
-
- void visitDynamicTypeLiteralInvoke(Send node, ConstantExpression constant,
- NodeList arguments, CallStructure callStructure, T arg) {
- handleNSMError(node);
- }
-
- void visitDynamicTypeLiteralPostfix(
- Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitDynamicTypeLiteralPrefix(
- Send node, ConstantExpression constant, IncDecOperator operator, T arg) {
- handleStatic(node);
- handleNSMError(node);
- handleNoSend(node);
- }
-
- void visitDynamicTypeLiteralSet(
- SendSet node, ConstantExpression constant, Node rhs, T arg) {
- handleNSMError(node);
- }
-
- void visitDynamicTypeLiteralSetIfNull(
- SendSet node, ConstantExpression constant, Node rhs, T arg) {
- handleStatic(node);
- handleNSMError(node);
- }
-
- @override
- errorInvalidIndexSetIfNull(
- SendSet node, ErroneousElement error, Node index, Node rhs, T arg) {
- handleNoSend(node);
- }
-
- @override
- visitIndexSetIfNull(
- SendSet node, Node receiver, Node index, Node rhs, T arg) {
- handleIndex(node); // t1 = receiver[index]
- handleIndex(node); // receiver[index] = t2
- }
-
- @override
- visitSuperIndexSetIfNull(SendSet node, MethodElement getter,
- MethodElement setter, Node index, Node rhs, T arg) {
- handleSuper(node); // t1 = super[index]
- handleSuper(node); // super[index] = t2
- }
-
- @override
- visitUnresolvedSuperGetterIndexSetIfNull(Send node, Element element,
- MethodElement setter, Node index, Node rhs, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- @override
- visitUnresolvedSuperIndexSetIfNull(
- Send node, Element element, Node index, Node rhs, T arg) {
- handleNSMSuper(node, element.enclosingClass);
- handleNSMSuper(node, element.enclosingClass);
- }
-
- @override
- visitUnresolvedSuperSetterIndexSetIfNull(Send node, MethodElement getter,
- Element element, Node index, Node rhs, T arg) {
- handleSuper(node); // t1 = super[index]
- handleNSMSuper(node, element.enclosingClass);
- }
-
- void visitIfNull(Send node, Node left, Node right, T arg) {
- handleNoSend(node);
- }
-
- void visitIs(Send node, Node expression, DartType type, T arg) {
- handleNoSend(node);
- }
-
- void visitIsNot(Send node, Node expression, DartType type, T arg) {
- handleNoSend(node);
- }
-
- void visitLogicalAnd(Send node, Node left, Node right, T arg) {
- handleNoSend(node);
- }
-
- void visitLogicalOr(Send node, Node left, Node right, T arg) {
- handleNoSend(node);
- }
-
- void visitNot(Send node, Node expression, T arg) {
- handleNoSend(node);
- }
-
- String last;
- _checkInvariant(node, String msg) {
- msg = '$msg ${recursiveDiagnosticString(measurements, Metric.send)}';
- if (!measurements.checkInvariant(Metric.send) ||
- !measurements.checkInvariant(Metric.monomorphicSend) ||
- !measurements.checkInvariant(Metric.polymorphicSend)) {
- reporter.reportErrorMessage(node, MessageKind.GENERIC,
- {'text': 'bad\n-- $msg\nlast:\n-- $last\n'});
- last = msg;
- } else {
- last = msg;
- }
- }
-}
-
-/// Visitor that collects statistics for a single function.
-class _StatsTraversalVisitor<T> extends TraversalVisitor<dynamic, T>
- implements SemanticSendVisitor<dynamic, T> {
- final DiagnosticReporter reporter;
- final _StatsVisitor statsVisitor;
- Measurements get measurements => statsVisitor.measurements;
- _StatsTraversalVisitor(
- Compiler compiler, TreeElements elements, Uri sourceUri)
- : reporter = compiler.reporter,
- statsVisitor = new _StatsVisitor(
- compiler.reporter,
- elements,
- // TODO(sigmund): accept a list of analyses, so we can compare them
- // together.
- true
- ? new TrustTypesAnalysisResult(elements, compiler.world)
- : new NaiveAnalysisResult(),
- sourceUri),
- super(elements);
-
- void visitSend(Send node) {
- try {
- node.accept(statsVisitor);
- } catch (e, t) {
- reporter
- .reportErrorMessage(node, MessageKind.GENERIC, {'text': '$e\n$t'});
- }
- super.visitSend(node);
- }
-
- void visitNewExpression(NewExpression node) {
- try {
- node.accept(statsVisitor);
- } catch (e, t) {
- reporter
- .reportErrorMessage(node, MessageKind.GENERIC, {'text': '$e\n$t'});
- }
- super.visitNewExpression(node);
- }
-}
-
-/// Helper to visit elements recursively
-// TODO(sigmund): maybe generalize and move to elements/visitor.dart?
-abstract class RecursiveElementVisitor<R, A> extends ElementVisitor<R, A> {
- @override
- R visitWarnOnUseElement(WarnOnUseElement e, A arg) =>
- e.wrappedElement.accept(this, arg);
-
- R visitScopeContainerElement(ScopeContainerElement e, A arg) {
- e.forEachLocalMember((l) => l.accept(this, arg));
- return null;
- }
-
- @override
- R visitCompilationUnitElement(CompilationUnitElement e, A arg) {
- e.forEachLocalMember((l) => l.accept(this, arg));
- return null;
- }
-
- @override
- R visitLibraryElement(LibraryElement e, A arg) {
- e.implementation.compilationUnits.forEach((u) => u.accept(this, arg));
- return null;
- }
-
- R visitVariableElement(VariableElement e, A arg) => null;
-
- @override
- R visitParameterElement(ParameterElement e, A arg) => null;
-
- @override
- R visitFormalElement(FormalElement e, A arg) => null;
-
- @override
- R visitFieldElement(FieldElement e, A arg) => null;
-
- @override
- R visitFieldParameterElement(InitializingFormalElement e, A arg) => null;
-
- @override
- R visitAbstractFieldElement(AbstractFieldElement e, A arg) => null;
-
- R visitFunctionElement(FunctionElement e, A arg) => null;
-
- @override
- R visitConstructorElement(ConstructorElement e, A arg) {
- return visitFunctionElement(e, arg);
- }
-
- @override
- R visitConstructorBodyElement(ConstructorBodyElement e, A arg) {
- return visitFunctionElement(e.constructor, arg);
- }
-
- @override
- R visitClassElement(ClassElement e, A arg) {
- return visitScopeContainerElement(e, arg);
- }
-
- @override
- R visitEnumClassElement(EnumClassElement e, A arg) {
- return visitClassElement(e, arg);
- }
-
- @override
- R visitBoxFieldElement(BoxFieldElement e, A arg) => null;
-
- @override
- R visitClosureClassElement(ClosureClassElement e, A arg) {
- return visitClassElement(e, arg);
- }
-
- @override
- R visitClosureFieldElement(ClosureFieldElement e, A arg) {
- return visitVariableElement(e, arg);
- }
-}
-
-// TODO(sigmund): get rid of debug messages.
-_debug(String message) {
- print('[33mdebug:[0m $message');
-}
diff --git a/pkg/compiler/lib/src/info/trusted_types_analysis_result.dart b/pkg/compiler/lib/src/info/trusted_types_analysis_result.dart
deleted file mode 100644
index 5653f2e..0000000
--- a/pkg/compiler/lib/src/info/trusted_types_analysis_result.dart
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (c) 2015, 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.
-
-/// API to get results from a static analysis of the source program.
-// TODO(sigmund): split out implementations out of this file.
-library compiler.src.stats.trusted_types_analysis_result;
-
-import 'analysis_result.dart';
-import '../tree/tree.dart' show Node;
-import '../universe/selector.dart' show Selector;
-import '../resolution/tree_elements.dart' show TreeElements;
-import '../world.dart' show ClassWorld;
-import '../dart_types.dart' show InterfaceType;
-
-/// An [AnalysisResult] produced by using type-propagation based on
-/// trusted type annotations.
-class TrustTypesAnalysisResult implements AnalysisResult {
- final ClassWorld world;
- final TreeElements elements;
-
- TrustTypesAnalysisResult(this.elements, this.world);
-
- ReceiverInfo infoForReceiver(Node receiver) => new TrustTypesReceiverInfo(
- receiver, elements.typesCache[receiver], world);
- SelectorInfo infoForSelector(Node receiver, Selector selector) =>
- new TrustTypesSelectorInfo(
- receiver, elements.typesCache[receiver], selector, world);
-}
-
-class _SelectorLookupResult {
- final Boolish exists;
- // TODO(sigmund): implement
- final Boolish usesInterceptor = Boolish.no;
- final int possibleTargets;
-
- _SelectorLookupResult(this.exists, this.possibleTargets);
-
- const _SelectorLookupResult.dontKnow()
- : exists = Boolish.maybe,
- possibleTargets = -1;
-}
-
-_SelectorLookupResult _lookupSelector(
- String selectorName, InterfaceType type, ClassWorld world) {
- if (type == null) return const _SelectorLookupResult.dontKnow();
- bool isNsm = selectorName == 'noSuchMethod';
- bool notFound = false;
- var uniqueTargets = new Set();
- for (var cls in world.subtypesOf(type.element)) {
- var member = cls.lookupMember(selectorName);
- if (member != null &&
- !member.isAbstract
- // Don't match nsm in Object
- &&
- (!isNsm || !member.enclosingClass.isObject)) {
- uniqueTargets.add(member);
- } else {
- notFound = true;
- }
- }
- Boolish exists = uniqueTargets.length > 0
- ? (notFound ? Boolish.maybe : Boolish.yes)
- : Boolish.no;
- return new _SelectorLookupResult(exists, uniqueTargets.length);
-}
-
-class TrustTypesReceiverInfo implements ReceiverInfo {
- final Node receiver;
- final Boolish hasNoSuchMethod;
- final int possibleNsmTargets;
- final Boolish isNull = Boolish.maybe;
-
- factory TrustTypesReceiverInfo(
- Node receiver, InterfaceType type, ClassWorld world) {
- // TODO(sigmund): refactor, maybe just store nsm as a SelectorInfo
- var res = _lookupSelector('noSuchMethod', type, world);
- return new TrustTypesReceiverInfo._(
- receiver, res.exists, res.possibleTargets);
- }
-
- TrustTypesReceiverInfo._(
- this.receiver, this.hasNoSuchMethod, this.possibleNsmTargets);
-}
-
-class TrustTypesSelectorInfo implements SelectorInfo {
- final Node receiver;
- final Selector selector;
-
- final Boolish exists;
- final Boolish usesInterceptor;
- final int possibleTargets;
- final bool isAccurate;
-
- factory TrustTypesSelectorInfo(
- Node receiver, InterfaceType type, Selector selector, ClassWorld world) {
- var res =
- _lookupSelector(selector != null ? selector.name : null, type, world);
- return new TrustTypesSelectorInfo._(receiver, selector, res.exists,
- res.usesInterceptor, res.possibleTargets, res.exists != Boolish.maybe);
- }
- TrustTypesSelectorInfo._(this.receiver, this.selector, this.exists,
- this.usesInterceptor, this.possibleTargets, this.isAccurate);
-}
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index 321943f..b4a764f 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -9,11 +9,11 @@
import '../common.dart';
import '../elements/elements.dart'
- show AstElement, FieldElement, ResolvedAst, ResolvedAstKind;
+ show AstElement, ResolvedAst, ResolvedAstKind;
import '../js/js.dart' as js;
import '../js/js_debug.dart';
import '../js/js_source_mapping.dart';
-import '../tree/tree.dart' show FunctionExpression, Node, Send;
+import '../tree/tree.dart' show Node, Send;
import 'code_output.dart' show CodeBuffer;
import 'source_file.dart';
import 'source_information.dart';
diff --git a/pkg/compiler/lib/src/io/source_file.dart b/pkg/compiler/lib/src/io/source_file.dart
index 93e6189..8b137c0 100644
--- a/pkg/compiler/lib/src/io/source_file.dart
+++ b/pkg/compiler/lib/src/io/source_file.dart
@@ -4,8 +4,8 @@
library dart2js.io.source_file;
-import 'dart:math';
import 'dart:convert' show UTF8;
+import 'dart:math';
import 'dart:typed_data' show Uint8List;
import 'line_column_provider.dart';
diff --git a/pkg/compiler/lib/src/io/source_map_builder.dart b/pkg/compiler/lib/src/io/source_map_builder.dart
index f6fa478..c3e6f5f 100644
--- a/pkg/compiler/lib/src/io/source_map_builder.dart
+++ b/pkg/compiler/lib/src/io/source_map_builder.dart
@@ -4,8 +4,8 @@
library dart2js.source_map_builder;
-import '../util/util.dart';
import '../util/uri_extras.dart' show relativize;
+import '../util/util.dart';
import 'line_column_provider.dart';
import 'source_information.dart' show SourceLocation;
diff --git a/pkg/compiler/lib/src/io/start_end_information.dart b/pkg/compiler/lib/src/io/start_end_information.dart
index 1734aa9..b246958 100644
--- a/pkg/compiler/lib/src/io/start_end_information.dart
+++ b/pkg/compiler/lib/src/io/start_end_information.dart
@@ -9,8 +9,7 @@
import '../common.dart';
import '../diagnostics/messages.dart' show MessageTemplate;
-import '../elements/elements.dart'
- show AstElement, ResolvedAst, ResolvedAstKind;
+import '../elements/elements.dart' show ResolvedAst, ResolvedAstKind;
import '../js/js.dart' as js;
import '../js/js_source_mapping.dart';
import '../tokens/token.dart' show Token;
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 9578f3f..a70b5d3 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -4,15 +4,14 @@
library rewrite_async;
-import "dart:math" show max;
import 'dart:collection';
+import "dart:math" show max;
import 'package:js_runtime/shared/async_await_error_codes.dart' as error_codes;
-import "js.dart" as js;
-
import '../common.dart';
import '../util/util.dart' show Pair;
+import "js.dart" as js;
/// Rewrites a [js.Fun] with async/sync*/async* functions and await and yield
/// (with dart-like semantics) to an equivalent function without these.
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 4bf0d1e..0ab92e4 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -2,7 +2,84 @@
// 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 js_backend;
+library js_backend.backend;
+
+import 'dart:async' show Future;
+
+import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
+
+import '../closure.dart';
+import '../common.dart';
+import '../common/backend_api.dart'
+ show Backend, ImpactTransformer, ForeignResolver, NativeRegistry;
+import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem;
+import '../common/names.dart' show Identifiers, Selectors, Uris;
+import '../common/registry.dart' show EagerRegistry, Registry;
+import '../common/resolution.dart'
+ show
+ Feature,
+ Frontend,
+ ListLiteralUse,
+ MapLiteralUse,
+ Resolution,
+ ResolutionImpact;
+import '../common/tasks.dart' show CompilerTask;
+import '../common/work.dart' show ItemCompilationContext;
+import '../compiler.dart' show Compiler;
+import '../constants/constant_system.dart';
+import '../constants/expressions.dart';
+import '../constants/values.dart';
+import '../core_types.dart' show CoreClasses, CoreTypes;
+import '../dart_types.dart';
+import '../deferred_load.dart' show DeferredLoadTask;
+import '../dump_info.dart' show DumpInfoTask;
+import '../elements/elements.dart';
+import '../enqueue.dart' show Enqueuer, ResolutionEnqueuer;
+import '../io/position_information.dart' show PositionSourceInformationStrategy;
+import '../io/source_information.dart' show SourceInformationStrategy;
+import '../io/start_end_information.dart'
+ show StartEndSourceInformationStrategy;
+import '../js/js.dart' as jsAst;
+import '../js/js.dart' show js;
+import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy;
+import '../js/rewrite_async.dart';
+import '../js_emitter/js_emitter.dart' show CodeEmitterTask;
+import '../library_loader.dart' show LibraryLoader, LoadedLibraries;
+import '../native/native.dart' as native;
+import '../ssa/builder.dart' show SsaFunctionCompiler;
+import '../ssa/nodes.dart' show HInstruction;
+import '../tree/tree.dart';
+import '../types/types.dart';
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/selector.dart' show Selector, SelectorKind;
+import '../universe/universe.dart';
+import '../universe/use.dart'
+ show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind;
+import '../universe/world_impact.dart'
+ show
+ ImpactStrategy,
+ ImpactUseCase,
+ TransformedWorldImpact,
+ WorldImpact,
+ WorldImpactVisitor;
+import '../util/util.dart';
+import '../world.dart' show ClassWorld;
+import 'backend_helpers.dart';
+import 'backend_impact.dart';
+import 'backend_serialization.dart' show JavaScriptBackendSerialization;
+import 'checked_mode_helpers.dart';
+import 'codegen/task.dart';
+import 'constant_handler_javascript.dart';
+import 'custom_elements_analysis.dart';
+import 'js_interop_analysis.dart' show JsInteropAnalysis;
+import 'lookup_map_analysis.dart' show LookupMapAnalysis;
+import 'namer.dart';
+import 'native_data.dart' show NativeData;
+import 'no_such_method_registry.dart';
+import 'patch_resolver.dart';
+import 'type_variable_handler.dart';
+
+part 'runtime_types.dart';
const VERBOSE_OPTIMIZER_HINTS = false;
diff --git a/pkg/compiler/lib/src/js_backend/backend_helpers.dart b/pkg/compiler/lib/src/js_backend/backend_helpers.dart
index 7613305..b9e011d 100644
--- a/pkg/compiler/lib/src/js_backend/backend_helpers.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_helpers.dart
@@ -23,7 +23,6 @@
import '../library_loader.dart' show LoadedLibraries;
import '../universe/call_structure.dart' show CallStructure;
import '../universe/selector.dart' show Selector;
-
import 'js_backend.dart';
/// Helper classes and functions for the JavaScript backend.
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index ee1dab9..7606e4d 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -8,7 +8,6 @@
import '../core_types.dart' show CoreClasses;
import '../dart_types.dart' show InterfaceType;
import '../elements/elements.dart' show ClassElement, Element;
-
import 'backend_helpers.dart';
import 'constant_system_javascript.dart';
import 'js_backend.dart';
diff --git a/pkg/compiler/lib/src/js_backend/backend_serialization.dart b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
index 471456cb..523f188 100644
--- a/pkg/compiler/lib/src/js_backend/backend_serialization.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
@@ -4,15 +4,14 @@
library js_backend.serialization;
-import '../common.dart';
import '../common/backend_api.dart' show BackendSerialization;
import '../dart_types.dart';
import '../elements/elements.dart';
import '../js/js.dart' as js;
import '../native/native.dart';
+import '../serialization/keys.dart';
import '../serialization/serialization.dart'
show DeserializerPlugin, ObjectDecoder, ObjectEncoder, SerializerPlugin;
-import '../serialization/keys.dart';
import '../universe/side_effects.dart';
import 'js_backend.dart';
diff --git a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
index 409c44d..38e0070 100644
--- a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
+++ b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
@@ -2,7 +2,16 @@
// 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 js_backend;
+import '../compiler.dart' show Compiler;
+import '../dart_types.dart';
+import '../elements/elements.dart';
+import '../js/js.dart' as jsAst;
+import '../js/js.dart' show js;
+import '../ssa/codegen.dart' show SsaCodeGenerator;
+import '../ssa/nodes.dart' show HTypeConversion;
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/use.dart' show StaticUse;
+import 'backend.dart';
class CheckedModeHelper {
final String name;
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
index d2c539d..add58ce 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -4,8 +4,6 @@
library code_generator;
-import 'glue.dart';
-
import '../../closure.dart' show ClosureClassElement;
import '../../common/codegen.dart' show CodegenRegistry;
import '../../constants/values.dart';
@@ -21,6 +19,7 @@
import '../../universe/selector.dart' show Selector;
import '../../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
import '../../util/maplet.dart';
+import 'glue.dart';
class CodegenBailout {
final tree_ir.Node node;
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index 69b13f3..859647a 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -5,39 +5,37 @@
/// Generate code using the cps-based IR pipeline.
library code_generator_task;
-import 'glue.dart';
-import 'codegen.dart';
-import 'unsugar.dart';
-
-import '../js_backend.dart';
-
import '../../common.dart';
import '../../common/codegen.dart' show CodegenWorkItem;
import '../../common/tasks.dart' show CompilerTask, GenericTask;
import '../../compiler.dart' show Compiler;
import '../../constants/constant_system.dart';
import '../../cps_ir/cps_ir_builder_task.dart';
+import '../../cps_ir/cps_ir_integrity.dart';
import '../../cps_ir/cps_ir_nodes.dart' as cps;
import '../../cps_ir/cps_ir_nodes_sexpr.dart';
-import '../../cps_ir/cps_ir_integrity.dart';
+import '../../cps_ir/finalize.dart' show Finalize;
import '../../cps_ir/optimizers.dart';
import '../../cps_ir/optimizers.dart' as cps_opt;
import '../../cps_ir/type_mask_system.dart';
-import '../../cps_ir/finalize.dart' show Finalize;
import '../../diagnostics/invariant.dart' show DEBUG_MODE;
import '../../elements/elements.dart';
+import '../../io/source_information.dart' show SourceInformationStrategy;
import '../../js/js.dart' as js;
import '../../js_backend/codegen/codegen.dart';
-import '../../io/source_information.dart' show SourceInformationStrategy;
-import '../../tree_ir/tree_ir_builder.dart' as tree_builder;
-import '../../tracer.dart';
import '../../ssa/ssa.dart' as ssa;
+import '../../tracer.dart';
import '../../tree_ir/optimization/optimization.dart';
import '../../tree_ir/optimization/optimization.dart' as tree_opt;
+import '../../tree_ir/tree_ir_builder.dart' as tree_builder;
import '../../tree_ir/tree_ir_integrity.dart';
import '../../tree_ir/tree_ir_nodes.dart' as tree_ir;
import '../../types/types.dart'
show FlatTypeMask, ForwardingTypeMask, TypeMask, UnionTypeMask;
+import '../js_backend.dart';
+import 'codegen.dart';
+import 'glue.dart';
+import 'unsugar.dart';
class CpsFunctionCompiler implements FunctionCompiler {
final ConstantSystem constantSystem;
diff --git a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
index 3c0f485..02db2c4 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
@@ -1,14 +1,13 @@
library dart2js.unsugar_cps;
-import '../../cps_ir/cps_ir_nodes.dart';
-
-import '../../cps_ir/optimizers.dart' show Pass;
+import '../../common/names.dart';
import '../../constants/values.dart';
+import '../../cps_ir/cps_fragment.dart';
+import '../../cps_ir/cps_ir_nodes.dart';
+import '../../cps_ir/optimizers.dart' show Pass;
import '../../elements/elements.dart';
import '../../js_backend/codegen/glue.dart';
import '../../universe/selector.dart' show Selector;
-import '../../cps_ir/cps_fragment.dart';
-import '../../common/names.dart';
class ExplicitReceiverParameterEntity implements Local {
String get name => 'receiver';
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index eba60d9..391a35c 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -2,7 +2,17 @@
// 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 js_backend;
+import '../common.dart';
+import '../compiler.dart' show Compiler;
+import '../constants/values.dart';
+import '../dart_types.dart';
+import '../elements/elements.dart';
+import '../io/code_output.dart';
+import '../js/js.dart' as jsAst;
+import '../js/js.dart' show js;
+import 'backend.dart';
+import 'constant_system_javascript.dart';
+import 'namer.dart';
typedef jsAst.Expression _ConstantReferenceGenerator(ConstantValue constant);
@@ -269,7 +279,7 @@
@override
jsAst.Expression visitSynthetic(SyntheticConstantValue constant, [_]) {
- switch (constant.kind) {
+ switch (constant.valueKind) {
case SyntheticConstantKind.DUMMY_INTERCEPTOR:
case SyntheticConstantKind.EMPTY_VALUE:
return new jsAst.LiteralNumber('0');
diff --git a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
index 8e6de54..2ab684e 100644
--- a/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart
@@ -2,7 +2,16 @@
// 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 js_backend;
+import '../compile_time_constants.dart';
+import '../compiler.dart' show Compiler;
+import '../constants/constant_system.dart';
+import '../constants/expressions.dart';
+import '../constants/values.dart';
+import '../elements/elements.dart';
+import '../elements/visitor.dart' show BaseElementVisitor;
+import '../resolution/tree_elements.dart' show TreeElements;
+import '../tree/tree.dart';
+import 'constant_system_javascript.dart';
/// [ConstantCompilerTask] for compilation of constants for the JavaScript
/// backend.
diff --git a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
index 4bbf530..e717466 100644
--- a/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_system_javascript.dart
@@ -5,9 +5,9 @@
library dart2js.constant_system.js;
import '../compiler.dart' show Compiler;
+import '../constant_system_dart.dart';
import '../constants/constant_system.dart';
import '../constants/values.dart';
-import '../constant_system_dart.dart';
import '../core_types.dart' show CoreTypes;
import '../dart_types.dart';
import '../elements/elements.dart' show ClassElement, FieldElement;
diff --git a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
index 450b826..b496a14 100644
--- a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
@@ -2,7 +2,13 @@
// 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 js_backend;
+import '../compiler.dart' show Compiler;
+import '../constants/values.dart';
+import '../dart_types.dart';
+import '../elements/elements.dart';
+import '../enqueue.dart' show Enqueuer;
+import '../universe/use.dart' show StaticUse;
+import 'backend.dart';
/**
* Support for Custom Elements.
diff --git a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
index cfc0136..7ac77d5 100644
--- a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
+++ b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
@@ -2,7 +2,7 @@
// 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 js_backend;
+part of js_backend.namer;
abstract class _MinifiedFieldNamer implements Namer {
_FieldNamingRegistry get fieldRegistry;
diff --git a/pkg/compiler/lib/src/js_backend/frequency_namer.dart b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
index 7698c3d..9636e67 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -2,7 +2,7 @@
// 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 js_backend;
+part of js_backend.namer;
class FrequencyBasedNamer extends Namer
with _MinifiedFieldNamer, _MinifiedOneShotInterceptorNamer
diff --git a/pkg/compiler/lib/src/js_backend/js_backend.dart b/pkg/compiler/lib/src/js_backend/js_backend.dart
index 5e5424f..aa31961 100644
--- a/pkg/compiler/lib/src/js_backend/js_backend.dart
+++ b/pkg/compiler/lib/src/js_backend/js_backend.dart
@@ -4,96 +4,11 @@
library js_backend;
-import 'dart:async' show Future;
-import 'dart:collection' show HashMap;
-
-import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
-import 'package:js_runtime/shared/embedded_names.dart' show JsGetName;
-
-import '../closure.dart';
-import '../common.dart';
-import '../common/backend_api.dart'
- show Backend, ImpactTransformer, ForeignResolver, NativeRegistry;
-import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem;
-import '../common/names.dart' show Identifiers, Names, Selectors, Uris;
-import '../common/registry.dart' show EagerRegistry, Registry;
-import '../common/resolution.dart'
- show
- Feature,
- Frontend,
- ListLiteralUse,
- MapLiteralUse,
- Resolution,
- ResolutionImpact;
-import '../common/tasks.dart' show CompilerTask;
-import '../common/work.dart' show ItemCompilationContext;
-import '../compile_time_constants.dart';
-import '../compiler.dart' show Compiler;
-import '../constants/constant_system.dart';
-import '../constants/expressions.dart';
-import '../constants/values.dart';
-import '../core_types.dart' show CoreClasses, CoreTypes;
-import '../dart_types.dart';
-import '../deferred_load.dart' show DeferredLoadTask;
-import '../diagnostics/invariant.dart' show DEBUG_MODE;
-import '../dump_info.dart' show DumpInfoTask;
-import '../elements/elements.dart';
-import '../elements/visitor.dart' show BaseElementVisitor;
-import '../enqueue.dart' show Enqueuer, ResolutionEnqueuer;
-import '../io/code_output.dart';
-import '../io/position_information.dart' show PositionSourceInformationStrategy;
-import '../io/source_information.dart' show SourceInformationStrategy;
-import '../io/start_end_information.dart'
- show StartEndSourceInformationStrategy;
-import '../js/js.dart' as jsAst;
-import '../js/js.dart' show js;
-import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy;
-import '../js/rewrite_async.dart';
-import '../js_emitter/js_emitter.dart'
- show CodeEmitterTask, MetadataCollector, Placeholder;
-import '../library_loader.dart' show LibraryLoader, LoadedLibraries;
-import '../native/native.dart' as native;
-import '../resolution/tree_elements.dart' show TreeElements;
-import '../ssa/builder.dart' show SsaFunctionCompiler;
-import '../ssa/codegen.dart' show SsaCodeGenerator;
-import '../ssa/nodes.dart' show HTypeConversion, HInstruction;
-import '../tree/tree.dart';
-import '../types/types.dart';
-import '../universe/call_structure.dart' show CallStructure;
-import '../universe/selector.dart' show Selector, SelectorKind;
-import '../universe/universe.dart';
-import '../universe/use.dart'
- show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind;
-import '../universe/world_impact.dart'
- show
- ImpactStrategy,
- ImpactUseCase,
- TransformedWorldImpact,
- WorldImpact,
- WorldImpactVisitor;
-import '../util/characters.dart';
-import '../util/util.dart';
-import '../world.dart' show ClassWorld;
-import 'backend_helpers.dart';
-import 'backend_impact.dart';
-import 'backend_serialization.dart' show JavaScriptBackendSerialization;
-import 'codegen/task.dart';
-import 'constant_system_javascript.dart';
-import 'js_interop_analysis.dart' show JsInteropAnalysis;
-import 'lookup_map_analysis.dart' show LookupMapAnalysis;
-import 'native_data.dart' show NativeData;
-import 'patch_resolver.dart';
-
-part 'backend.dart';
-part 'checked_mode_helpers.dart';
-part 'constant_emitter.dart';
-part 'constant_handler_javascript.dart';
-part 'custom_elements_analysis.dart';
-part 'field_naming_mixin.dart';
-part 'frequency_namer.dart';
-part 'minify_namer.dart';
-part 'namer.dart';
-part 'namer_names.dart';
-part 'no_such_method_registry.dart';
-part 'runtime_types.dart';
-part 'type_variable_handler.dart';
+export 'backend.dart';
+export 'checked_mode_helpers.dart';
+export 'constant_emitter.dart';
+export 'constant_handler_javascript.dart';
+export 'custom_elements_analysis.dart';
+export 'namer.dart';
+export 'no_such_method_registry.dart';
+export 'type_variable_handler.dart';
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index ff76d87..3e689d4 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -2,7 +2,7 @@
// 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 js_backend;
+part of js_backend.namer;
/**
* Assigns JavaScript identifiers to Dart variables, class-names and members.
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index aeea76e..7cc4621 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -2,7 +2,37 @@
// 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 js_backend;
+library js_backend.namer;
+
+import 'dart:collection' show HashMap;
+
+import 'package:js_runtime/shared/embedded_names.dart' show JsGetName;
+
+import '../closure.dart';
+import '../common.dart';
+import '../common/names.dart' show Identifiers, Selectors;
+import '../compiler.dart' show Compiler;
+import '../constants/values.dart';
+import '../core_types.dart' show CoreClasses;
+import '../dart_types.dart';
+import '../diagnostics/invariant.dart' show DEBUG_MODE;
+import '../elements/elements.dart';
+import '../js/js.dart' as jsAst;
+import '../js/js.dart' show js;
+import '../tree/tree.dart';
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/selector.dart' show Selector, SelectorKind;
+import '../util/characters.dart';
+import '../util/util.dart';
+import '../world.dart' show ClassWorld;
+import 'backend.dart';
+import 'backend_helpers.dart';
+import 'constant_system_javascript.dart';
+
+part 'field_naming_mixin.dart';
+part 'frequency_namer.dart';
+part 'minify_namer.dart';
+part 'namer_names.dart';
/**
* Assigns JavaScript identifiers to Dart variables, class-names and members.
@@ -1768,7 +1798,7 @@
@override
void visitSynthetic(SyntheticConstantValue constant, [_]) {
- switch (constant.kind) {
+ switch (constant.valueKind) {
case SyntheticConstantKind.DUMMY_INTERCEPTOR:
add('dummy_receiver');
break;
@@ -1888,7 +1918,7 @@
@override
int visitSynthetic(SyntheticConstantValue constant, [_]) {
- switch (constant.kind) {
+ switch (constant.valueKind) {
case SyntheticConstantKind.TYPEVARIABLE_REFERENCE:
// These contain a deferred opaque index into metadata. There is nothing
// we can access that is stable between compiles. Luckily, since they
diff --git a/pkg/compiler/lib/src/js_backend/namer_names.dart b/pkg/compiler/lib/src/js_backend/namer_names.dart
index 4baffb5..7e8e76f 100644
--- a/pkg/compiler/lib/src/js_backend/namer_names.dart
+++ b/pkg/compiler/lib/src/js_backend/namer_names.dart
@@ -2,7 +2,7 @@
// 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 js_backend;
+part of js_backend.namer;
abstract class _NamerName extends jsAst.Name {
int get _kind;
diff --git a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
index d9e8681..4464214 100644
--- a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
+++ b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
@@ -2,7 +2,13 @@
// 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 js_backend;
+import '../common.dart';
+import '../common/names.dart' show Identifiers, Names, Selectors;
+import '../compiler.dart' show Compiler;
+import '../elements/elements.dart';
+import '../tree/tree.dart';
+import '../types/types.dart';
+import 'backend.dart';
/**
* Categorizes `noSuchMethod` implementations.
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index e3f74b7..1e8cc1c 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -2,7 +2,7 @@
// 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 js_backend;
+part of js_backend.backend;
/// For each class, stores the possible class subtype tests that could succeed.
abstract class TypeChecks {
diff --git a/pkg/compiler/lib/src/js_backend/type_variable_handler.dart b/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
index faf8539..ada9d16 100644
--- a/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
+++ b/pkg/compiler/lib/src/js_backend/type_variable_handler.dart
@@ -2,7 +2,21 @@
// 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 js_backend;
+import '../common.dart';
+import '../common/registry.dart' show Registry;
+import '../compiler.dart' show Compiler;
+import '../constants/expressions.dart';
+import '../constants/values.dart';
+import '../dart_types.dart';
+import '../elements/elements.dart';
+import '../enqueue.dart' show Enqueuer;
+import '../js/js.dart' as jsAst;
+import '../js_emitter/js_emitter.dart'
+ show CodeEmitterTask, MetadataCollector, Placeholder;
+import '../universe/call_structure.dart' show CallStructure;
+import '../universe/use.dart' show StaticUse;
+import '../util/util.dart';
+import 'backend.dart';
/**
* Handles construction of TypeVariable constants needed at runtime.
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index 57ce762..6baa377 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -5,11 +5,10 @@
library dart2js.js_emitter.constant_ordering;
import '../constants/values.dart';
-
import '../dart_types.dart';
import '../elements/elements.dart' show Element, Elements, FieldElement;
-import '../tree/dartstring.dart' show DartString;
import '../js_backend/js_backend.dart' show SyntheticConstantKind;
+import '../tree/dartstring.dart' show DartString;
/// A canonical but arbrary ordering of constants. The ordering is 'stable'
/// under perturbation of the source.
@@ -148,11 +147,11 @@
// as elements of a few constants. If this becomes a source of instability,
// we will need to add a total ordering on JavaScript ASTs including
// deferred elements.
- SyntheticConstantKind aKind = a.kind;
- SyntheticConstantKind bKind = b.kind;
+ SyntheticConstantKind aKind = a.valueKind;
+ SyntheticConstantKind bKind = b.valueKind;
int r = aKind.index - bKind.index;
if (r != 0) return r;
- switch (a.kind) {
+ switch (aKind) {
case SyntheticConstantKind.DUMMY_INTERCEPTOR:
case SyntheticConstantKind.EMPTY_VALUE:
// Never emitted.
diff --git a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
index 138062e..352d7f7 100644
--- a/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/lazy_emitter/model_emitter.dart
@@ -4,17 +4,6 @@
library dart2js.js_emitter.lazy_emitter.model_emitter;
-import '../../compiler.dart' show Compiler;
-import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
-import '../../core_types.dart' show CoreClasses;
-import '../../elements/elements.dart' show ClassElement, FunctionElement;
-import '../../js/js.dart' as js;
-import '../../js_backend/js_backend.dart'
- show JavaScriptBackend, Namer, ConstantEmitter;
-
-import '../js_emitter.dart' show NativeEmitter;
-import '../constant_ordering.dart' show deepCompareConstants;
-
import 'package:js_runtime/shared/embedded_names.dart'
show
CREATE_NEW_ISOLATE,
@@ -31,6 +20,15 @@
TYPE_TO_INTERCEPTOR_MAP,
TYPES;
+import '../../compiler.dart' show Compiler;
+import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
+import '../../core_types.dart' show CoreClasses;
+import '../../elements/elements.dart' show ClassElement, FunctionElement;
+import '../../js/js.dart' as js;
+import '../../js_backend/js_backend.dart'
+ show JavaScriptBackend, Namer, ConstantEmitter;
+import '../constant_ordering.dart' show deepCompareConstants;
+import '../js_emitter.dart' show NativeEmitter;
import '../js_emitter.dart' show NativeGenerator, buildTearOffCode;
import '../model.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index 072e8cb..07be9d6 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -14,12 +14,10 @@
show ClassElement, Element, FieldElement, FunctionElement;
import '../../js/js.dart' as js;
import '../../js_backend/js_backend.dart' show JavaScriptBackend, Namer;
-
import '../js_emitter.dart' show NativeEmitter;
import '../js_emitter.dart' as emitterTask show Emitter;
-import '../program_builder/program_builder.dart' show ProgramBuilder;
import '../model.dart';
-
+import '../program_builder/program_builder.dart' show ProgramBuilder;
import 'model_emitter.dart';
class Emitter implements emitterTask.Emitter {
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index b3be363..046fa6f 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -31,8 +31,8 @@
TYPES;
import '../../common.dart';
-import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
import '../../compiler.dart' show Compiler;
+import '../../constants/values.dart' show ConstantValue, FunctionConstantValue;
import '../../core_types.dart' show CoreClasses;
import '../../elements/elements.dart' show ClassElement, FunctionElement;
import '../../hash/sha1.dart' show Hasher;
@@ -44,11 +44,9 @@
import '../../js_backend/js_backend.dart'
show JavaScriptBackend, Namer, ConstantEmitter;
import '../../util/uri_extras.dart' show relativize;
-
import '../constant_ordering.dart' show deepCompareConstants;
import '../headers.dart';
import '../js_emitter.dart' show NativeEmitter;
-
import '../js_emitter.dart' show buildTearOffCode, NativeGenerator;
import '../model.dart';
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index a4e2922..57ef61a 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -15,7 +15,6 @@
import '../tree/tree.dart';
import '../universe/side_effects.dart' show SideEffects;
import '../util/util.dart';
-
import 'enqueue.dart';
import 'js.dart';
diff --git a/pkg/compiler/lib/src/native/js.dart b/pkg/compiler/lib/src/native/js.dart
index 1251fe5..e7c7079 100644
--- a/pkg/compiler/lib/src/native/js.dart
+++ b/pkg/compiler/lib/src/native/js.dart
@@ -4,7 +4,6 @@
import '../js/js.dart' as js;
import '../universe/side_effects.dart' show SideEffects;
-
import 'behavior.dart';
class HasCapturedPlaceholders extends js.BaseVisitor {
diff --git a/pkg/compiler/lib/src/native/scanner.dart b/pkg/compiler/lib/src/native/scanner.dart
index f22b866..c1bc40d 100644
--- a/pkg/compiler/lib/src/native/scanner.dart
+++ b/pkg/compiler/lib/src/native/scanner.dart
@@ -4,7 +4,6 @@
import '../common.dart';
import '../parser/element_listener.dart' show ElementListener;
-import '../parser/listener.dart' show Listener;
import '../tokens/token.dart' show BeginGroupToken, Token;
import '../tokens/token_constants.dart' as Tokens show STRING_TOKEN;
diff --git a/pkg/compiler/lib/src/null_compiler_output.dart b/pkg/compiler/lib/src/null_compiler_output.dart
index acc323f..ed5a186 100644
--- a/pkg/compiler/lib/src/null_compiler_output.dart
+++ b/pkg/compiler/lib/src/null_compiler_output.dart
@@ -6,9 +6,10 @@
library compiler.null_api;
-import '../compiler_new.dart';
import 'dart:async';
+import '../compiler_new.dart';
+
/// Null pattern implementation of the [CompilerOutput] interface.
class NullCompilerOutput implements CompilerOutput {
const NullCompilerOutput();
diff --git a/pkg/compiler/lib/src/old_to_new_api.dart b/pkg/compiler/lib/src/old_to_new_api.dart
index 7954091..d79b5f9 100644
--- a/pkg/compiler/lib/src/old_to_new_api.dart
+++ b/pkg/compiler/lib/src/old_to_new_api.dart
@@ -8,9 +8,10 @@
library compiler.api.legacy;
import 'dart:async' show EventSink, Future;
-import 'null_compiler_output.dart' show NullSink;
+
import '../compiler.dart';
import '../compiler_new.dart';
+import 'null_compiler_output.dart' show NullSink;
/// Implementation of [CompilerInput] using a [CompilerInputProvider].
class LegacyCompilerInput implements CompilerInput {
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 98b88e0..b1aaeb0 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -4,8 +4,8 @@
library dart2js.src.options;
-import 'commandline_options.dart' show Flags;
import '../compiler.dart' show PackagesDiscoveryProvider;
+import 'commandline_options.dart' show Flags;
/// Options used for parsing.
///
diff --git a/pkg/compiler/lib/src/parser/class_element_parser.dart b/pkg/compiler/lib/src/parser/class_element_parser.dart
index b85114d..3d3cd27 100644
--- a/pkg/compiler/lib/src/parser/class_element_parser.dart
+++ b/pkg/compiler/lib/src/parser/class_element_parser.dart
@@ -4,10 +4,9 @@
library dart2js.parser.classes;
-import '../tokens/token.dart' show Token;
-
-import 'listener.dart' show Listener;
import '../options.dart' show ParserOptions;
+import '../tokens/token.dart' show Token;
+import 'listener.dart' show Listener;
import 'partial_parser.dart' show PartialParser;
class ClassElementParser extends PartialParser {
diff --git a/pkg/compiler/lib/src/parser/diet_parser_task.dart b/pkg/compiler/lib/src/parser/diet_parser_task.dart
index 3c48a31..002bba0 100644
--- a/pkg/compiler/lib/src/parser/diet_parser_task.dart
+++ b/pkg/compiler/lib/src/parser/diet_parser_task.dart
@@ -9,11 +9,10 @@
import '../common/tasks.dart' show CompilerTask, Measurer;
import '../elements/elements.dart' show CompilationUnitElement;
import '../id_generator.dart';
-import '../tokens/token.dart' show Token;
-
-import 'listener.dart' show ParserError;
-import 'element_listener.dart' show ElementListener, ScannerOptions;
import '../options.dart' show ParserOptions;
+import '../tokens/token.dart' show Token;
+import 'element_listener.dart' show ElementListener, ScannerOptions;
+import 'listener.dart' show ParserError;
import 'partial_parser.dart' show PartialParser;
class DietParserTask extends CompilerTask {
diff --git a/pkg/compiler/lib/src/parser/element_listener.dart b/pkg/compiler/lib/src/parser/element_listener.dart
index 6d9bd82..ae1c592 100644
--- a/pkg/compiler/lib/src/parser/element_listener.dart
+++ b/pkg/compiler/lib/src/parser/element_listener.dart
@@ -4,7 +4,6 @@
library dart2js.parser.element_listener;
-import '../compiler.dart' show Compiler;
import '../common.dart';
import '../diagnostics/messages.dart' show MessageTemplate;
import '../elements/elements.dart'
@@ -30,7 +29,7 @@
import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
import '../tree/tree.dart';
import '../util/util.dart' show Link, LinkBuilder;
-
+import 'listener.dart' show closeBraceFor, Listener, ParserError, VERBOSE;
import 'partial_elements.dart'
show
PartialClassElement,
@@ -39,7 +38,6 @@
PartialFunctionElement,
PartialMetadataAnnotation,
PartialTypedefElement;
-import 'listener.dart' show closeBraceFor, Listener, ParserError, VERBOSE;
/// Options used for scanning.
///
diff --git a/pkg/compiler/lib/src/parser/parser.dart b/pkg/compiler/lib/src/parser/parser.dart
index 3ac4900..f9998ca 100644
--- a/pkg/compiler/lib/src/parser/parser.dart
+++ b/pkg/compiler/lib/src/parser/parser.dart
@@ -4,8 +4,8 @@
library dart2js.parser;
-import '../options.dart' show ParserOptions;
import '../common.dart';
+import '../options.dart' show ParserOptions;
import '../tokens/keyword.dart' show Keyword;
import '../tokens/precedence.dart' show PrecedenceInfo;
import '../tokens/precedence_constants.dart'
@@ -58,7 +58,6 @@
STRING_TOKEN;
import '../util/characters.dart' as Characters show $CLOSE_CURLY_BRACKET;
import '../util/util.dart' show Link;
-
import 'listener.dart' show Listener;
class FormalParameterType {
diff --git a/pkg/compiler/lib/src/parser/parser_task.dart b/pkg/compiler/lib/src/parser/parser_task.dart
index 02c3719..07734b9 100644
--- a/pkg/compiler/lib/src/parser/parser_task.dart
+++ b/pkg/compiler/lib/src/parser/parser_task.dart
@@ -11,7 +11,6 @@
import '../options.dart' show ParserOptions;
import '../tokens/token.dart' show Token;
import '../tree/tree.dart' show Node;
-
import 'element_listener.dart' show ScannerOptions;
import 'listener.dart' show ParserError;
import 'node_listener.dart' show NodeListener;
diff --git a/pkg/compiler/lib/src/parser/partial_parser.dart b/pkg/compiler/lib/src/parser/partial_parser.dart
index 514a058..0868265 100644
--- a/pkg/compiler/lib/src/parser/partial_parser.dart
+++ b/pkg/compiler/lib/src/parser/partial_parser.dart
@@ -6,10 +6,9 @@
import '../common.dart';
import '../options.dart' show ParserOptions;
-import '../util/characters.dart' as Characters show $CLOSE_CURLY_BRACKET;
import '../tokens/token.dart' show BeginGroupToken, ErrorToken, Token;
import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
-
+import '../util/characters.dart' as Characters show $CLOSE_CURLY_BRACKET;
import 'listener.dart' show Listener;
import 'parser.dart' show Parser;
diff --git a/pkg/compiler/lib/src/platform_configuration.dart b/pkg/compiler/lib/src/platform_configuration.dart
index 56a48df..e721001 100644
--- a/pkg/compiler/lib/src/platform_configuration.dart
+++ b/pkg/compiler/lib/src/platform_configuration.dart
@@ -6,7 +6,9 @@
library plaform_configuration;
import "dart:async";
+
import "package:charcode/ascii.dart";
+
import "../compiler_new.dart" as api;
/// Parses an Ini-like format.
diff --git a/pkg/compiler/lib/src/resolution/access_semantics.dart b/pkg/compiler/lib/src/resolution/access_semantics.dart
index fdd8410..ffb71f9 100644
--- a/pkg/compiler/lib/src/resolution/access_semantics.dart
+++ b/pkg/compiler/lib/src/resolution/access_semantics.dart
@@ -8,8 +8,8 @@
library dart2js.access_semantics;
import '../constants/expressions.dart';
-import '../elements/elements.dart';
import '../dart_types.dart';
+import '../elements/elements.dart';
/// Enum representing the different kinds of destinations which a property
/// access or method or function invocation might refer to.
diff --git a/pkg/compiler/lib/src/resolution/class_hierarchy.dart b/pkg/compiler/lib/src/resolution/class_hierarchy.dart
index 39fe5e1..cdc5c02 100644
--- a/pkg/compiler/lib/src/resolution/class_hierarchy.dart
+++ b/pkg/compiler/lib/src/resolution/class_hierarchy.dart
@@ -19,9 +19,8 @@
UnnamedMixinApplicationElementX;
import '../ordered_typeset.dart' show OrderedTypeSet, OrderedTypeSetBuilder;
import '../tree/tree.dart';
-import '../util/util.dart' show Link, Setlet;
import '../universe/call_structure.dart' show CallStructure;
-
+import '../util/util.dart' show Link, Setlet;
import 'enum_creator.dart';
import 'members.dart' show lookupInScope;
import 'registry.dart' show ResolutionRegistry;
diff --git a/pkg/compiler/lib/src/resolution/class_members.dart b/pkg/compiler/lib/src/resolution/class_members.dart
index 7c28777..b4ae169 100644
--- a/pkg/compiler/lib/src/resolution/class_members.dart
+++ b/pkg/compiler/lib/src/resolution/class_members.dart
@@ -7,7 +7,6 @@
import '../common.dart';
import '../common/names.dart' show Identifiers, Names;
import '../common/resolution.dart' show Resolution;
-import '../compiler.dart' show Compiler;
import '../dart_types.dart';
import '../elements/elements.dart'
show
diff --git a/pkg/compiler/lib/src/resolution/constructors.dart b/pkg/compiler/lib/src/resolution/constructors.dart
index 50f51d1..1d2ac2f 100644
--- a/pkg/compiler/lib/src/resolution/constructors.dart
+++ b/pkg/compiler/lib/src/resolution/constructors.dart
@@ -23,10 +23,9 @@
InitializingFormalElementX,
ParameterElementX;
import '../tree/tree.dart';
-import '../util/util.dart' show Link;
import '../universe/call_structure.dart' show CallStructure;
import '../universe/use.dart' show StaticUse;
-
+import '../util/util.dart' show Link;
import 'members.dart' show lookupInScope, ResolverVisitor;
import 'registry.dart' show ResolutionRegistry;
import 'resolution_common.dart' show CommonResolverVisitor;
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 97f59bc..8ef45c0 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -20,7 +20,6 @@
ConstructorElementX,
ErroneousElementX,
FunctionElementX,
- InitializingFormalElementX,
JumpTargetX,
LocalFunctionElementX,
LocalParameterElementX,
diff --git a/pkg/compiler/lib/src/resolution/registry.dart b/pkg/compiler/lib/src/resolution/registry.dart
index 753d9a7..4d9606b 100644
--- a/pkg/compiler/lib/src/resolution/registry.dart
+++ b/pkg/compiler/lib/src/resolution/registry.dart
@@ -7,26 +7,22 @@
import '../common.dart';
import '../common/backend_api.dart'
show Backend, ForeignResolver, NativeRegistry;
+import '../common/registry.dart' show Registry;
import '../common/resolution.dart'
show Feature, ListLiteralUse, MapLiteralUse, ResolutionImpact, Target;
-import '../common/registry.dart' show Registry;
-import '../compiler.dart' show Compiler;
import '../constants/expressions.dart';
import '../dart_types.dart';
import '../diagnostics/source_span.dart';
-import '../enqueue.dart' show ResolutionEnqueuer;
import '../elements/elements.dart';
import '../tree/tree.dart';
-import '../util/util.dart' show Setlet;
import '../universe/call_structure.dart' show CallStructure;
import '../universe/selector.dart' show Selector;
import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
import '../universe/world_impact.dart' show WorldImpact, WorldImpactBuilder;
import '../util/enumset.dart' show EnumSet;
-
-import 'send_structure.dart';
-
+import '../util/util.dart' show Setlet;
import 'members.dart' show ResolverVisitor;
+import 'send_structure.dart';
import 'tree_elements.dart' show TreeElementMapping;
class _ResolutionWorldImpact extends ResolutionImpact
diff --git a/pkg/compiler/lib/src/resolution/semantic_visitor.dart b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
index 6f0005e..c4fe79a 100644
--- a/pkg/compiler/lib/src/resolution/semantic_visitor.dart
+++ b/pkg/compiler/lib/src/resolution/semantic_visitor.dart
@@ -7,11 +7,10 @@
import '../common.dart';
import '../constants/expressions.dart';
import '../dart_types.dart';
-import '../tree/tree.dart';
import '../elements/elements.dart';
+import '../tree/tree.dart';
import '../universe/call_structure.dart' show CallStructure;
import '../universe/selector.dart' show Selector;
-
import 'operators.dart';
import 'send_resolver.dart';
import 'send_structure.dart';
diff --git a/pkg/compiler/lib/src/resolution/send_resolver.dart b/pkg/compiler/lib/src/resolution/send_resolver.dart
index 7ef2a86..d53d4ec 100644
--- a/pkg/compiler/lib/src/resolution/send_resolver.dart
+++ b/pkg/compiler/lib/src/resolution/send_resolver.dart
@@ -9,7 +9,6 @@
import '../dart_types.dart';
import '../elements/elements.dart';
import '../tree/tree.dart';
-
import 'semantic_visitor.dart';
import 'send_structure.dart';
import 'tree_elements.dart';
diff --git a/pkg/compiler/lib/src/resolution/send_structure.dart b/pkg/compiler/lib/src/resolution/send_structure.dart
index b26087e..52bf4dd 100644
--- a/pkg/compiler/lib/src/resolution/send_structure.dart
+++ b/pkg/compiler/lib/src/resolution/send_structure.dart
@@ -12,7 +12,6 @@
import '../tree/tree.dart';
import '../universe/call_structure.dart' show CallStructure;
import '../universe/selector.dart' show Selector;
-
import 'access_semantics.dart';
import 'operators.dart';
import 'semantic_visitor.dart';
diff --git a/pkg/compiler/lib/src/resolution/tree_elements.dart b/pkg/compiler/lib/src/resolution/tree_elements.dart
index 974981c..bae0857 100644
--- a/pkg/compiler/lib/src/resolution/tree_elements.dart
+++ b/pkg/compiler/lib/src/resolution/tree_elements.dart
@@ -9,11 +9,10 @@
import '../dart_types.dart';
import '../diagnostics/source_span.dart';
import '../elements/elements.dart';
-import '../types/types.dart' show TypeMask;
import '../tree/tree.dart';
-import '../util/util.dart';
+import '../types/types.dart' show TypeMask;
import '../universe/selector.dart' show Selector;
-
+import '../util/util.dart';
import 'secret_tree_element.dart' show getTreeElement, setTreeElement;
import 'send_structure.dart';
diff --git a/pkg/compiler/lib/src/resolution/typedefs.dart b/pkg/compiler/lib/src/resolution/typedefs.dart
index 7f18141..eed801b 100644
--- a/pkg/compiler/lib/src/resolution/typedefs.dart
+++ b/pkg/compiler/lib/src/resolution/typedefs.dart
@@ -4,8 +4,6 @@
library dart2js.resolution.typedefs;
-import 'dart:developer';
-
import '../common.dart';
import '../common/resolution.dart';
import '../dart_types.dart';
@@ -14,7 +12,6 @@
import '../elements/modelx.dart' show ErroneousElementX, TypedefElementX;
import '../tree/tree.dart';
import '../util/util.dart' show Link;
-
import 'class_hierarchy.dart' show TypeDefinitionVisitor;
import 'registry.dart' show ResolutionRegistry;
import 'scope.dart' show MethodScope, TypeDeclarationScope;
diff --git a/pkg/compiler/lib/src/resolution/variables.dart b/pkg/compiler/lib/src/resolution/variables.dart
index 28d5372..77a8f4e 100644
--- a/pkg/compiler/lib/src/resolution/variables.dart
+++ b/pkg/compiler/lib/src/resolution/variables.dart
@@ -10,7 +10,6 @@
import '../tree/tree.dart';
import '../universe/use.dart' show TypeUse;
import '../util/util.dart' show Link;
-
import 'members.dart' show ResolverVisitor;
import 'registry.dart' show ResolutionRegistry;
import 'resolution_common.dart' show CommonResolverVisitor;
diff --git a/pkg/compiler/lib/src/scanner/array_based_scanner.dart b/pkg/compiler/lib/src/scanner/array_based_scanner.dart
index 2496daa..edd22ae 100644
--- a/pkg/compiler/lib/src/scanner/array_based_scanner.dart
+++ b/pkg/compiler/lib/src/scanner/array_based_scanner.dart
@@ -15,7 +15,6 @@
show LT_TOKEN, OPEN_CURLY_BRACKET_TOKEN, STRING_INTERPOLATION_TOKEN;
import '../util/characters.dart' show $LF, $STX;
import '../util/util.dart' show Link;
-
import 'scanner.dart' show AbstractScanner;
abstract class ArrayBasedScanner extends AbstractScanner {
diff --git a/pkg/compiler/lib/src/scanner/scanner.dart b/pkg/compiler/lib/src/scanner/scanner.dart
index 30d5caf..63f4bd0 100644
--- a/pkg/compiler/lib/src/scanner/scanner.dart
+++ b/pkg/compiler/lib/src/scanner/scanner.dart
@@ -11,7 +11,6 @@
import '../tokens/token.dart';
import '../tokens/token_constants.dart';
import '../util/characters.dart';
-
import 'string_scanner.dart' show StringScanner;
import 'utf8_bytes_scanner.dart' show Utf8BytesScanner;
diff --git a/pkg/compiler/lib/src/scanner/scanner_task.dart b/pkg/compiler/lib/src/scanner/scanner_task.dart
index 6b25efd..1977248 100644
--- a/pkg/compiler/lib/src/scanner/scanner_task.dart
+++ b/pkg/compiler/lib/src/scanner/scanner_task.dart
@@ -7,12 +7,11 @@
import '../common/tasks.dart' show CompilerTask, Measurer;
import '../diagnostics/diagnostic_listener.dart' show DiagnosticReporter;
import '../elements/elements.dart' show CompilationUnitElement, LibraryElement;
-import '../script.dart' show Script;
import '../parser/diet_parser_task.dart' show DietParserTask;
+import '../script.dart' show Script;
import '../tokens/token.dart' show Token;
import '../tokens/token_constants.dart' as Tokens show COMMENT_TOKEN, EOF_TOKEN;
import '../tokens/token_map.dart' show TokenMap;
-
import 'scanner.dart' show Scanner;
import 'string_scanner.dart' show StringScanner;
diff --git a/pkg/compiler/lib/src/scanner/string_scanner.dart b/pkg/compiler/lib/src/scanner/string_scanner.dart
index 5c6604e..7e1f995d 100644
--- a/pkg/compiler/lib/src/scanner/string_scanner.dart
+++ b/pkg/compiler/lib/src/scanner/string_scanner.dart
@@ -7,7 +7,6 @@
import '../io/source_file.dart' show SourceFile;
import '../tokens/precedence.dart' show PrecedenceInfo;
import '../tokens/token.dart' show StringToken, Token;
-
import 'array_based_scanner.dart' show ArrayBasedScanner;
/**
diff --git a/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart b/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart
index c4b87ed..ea46e35 100644
--- a/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart
+++ b/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart
@@ -9,7 +9,6 @@
import '../io/source_file.dart' show SourceFile;
import '../tokens/precedence.dart' show PrecedenceInfo;
import '../tokens/token.dart' show StringToken, Token;
-
import 'array_based_scanner.dart' show ArrayBasedScanner;
/**
diff --git a/pkg/compiler/lib/src/serialization/constant_serialization.dart b/pkg/compiler/lib/src/serialization/constant_serialization.dart
index ae3040a..fae3d2f 100644
--- a/pkg/compiler/lib/src/serialization/constant_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/constant_serialization.dart
@@ -10,8 +10,8 @@
import '../elements/elements.dart' show FieldElement;
import '../resolution/operators.dart';
import '../universe/call_structure.dart' show CallStructure;
-import 'serialization.dart';
import 'keys.dart';
+import 'serialization.dart';
/// Visitor that serializes a [ConstantExpression] by encoding it into an
/// [ObjectEncoder].
diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart
index 3a63bbc..3b14778 100644
--- a/pkg/compiler/lib/src/serialization/element_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/element_serialization.dart
@@ -5,7 +5,6 @@
library dart2js.serialization.elements;
import '../common.dart';
-import '../common/names.dart';
import '../constants/constructors.dart';
import '../constants/expressions.dart';
import '../dart_types.dart';
diff --git a/pkg/compiler/lib/src/serialization/equivalence.dart b/pkg/compiler/lib/src/serialization/equivalence.dart
index 6cb175c..fccc44e 100644
--- a/pkg/compiler/lib/src/serialization/equivalence.dart
+++ b/pkg/compiler/lib/src/serialization/equivalence.dart
@@ -7,9 +7,9 @@
library dart2js.serialization.equivalence;
import '../closure.dart';
-import '../common.dart';
import '../common/resolution.dart';
import '../constants/expressions.dart';
+import '../constants/values.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
import '../elements/visitor.dart';
@@ -63,6 +63,31 @@
return remaining.isEmpty;
}
+/// Returns `true` if the content of [map1] and [map2] is equivalent using
+/// [keyEquivalence] and [valueEquivalence] to determine key/value equivalence.
+bool areMapsEquivalent(Map map1, Map map2,
+ [bool keyEquivalence(a, b) = equality,
+ bool valueEquivalence(a, b) = equality]) {
+ Set remaining = map2.keys.toSet();
+ for (var key1 in map1.keys) {
+ bool found = false;
+ for (var key2 in map2.keys) {
+ if (keyEquivalence(key2, key2)) {
+ found = true;
+ remaining.remove(key2);
+ if (!valueEquivalence(map1[key1], map2[key2])) {
+ return false;
+ }
+ break;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+ return remaining.isEmpty;
+}
+
/// Returns `true` if elements [a] and [b] are equivalent.
bool areElementsEquivalent(Element a, Element b) {
if (identical(a, b)) return true;
@@ -77,13 +102,20 @@
return const TypeEquivalence().visit(a, b);
}
-/// Returns `true` if constants [a] and [b] are equivalent.
+/// Returns `true` if constants [exp1] and [exp2] are equivalent.
bool areConstantsEquivalent(ConstantExpression exp1, ConstantExpression exp2) {
if (identical(exp1, exp2)) return true;
if (exp1 == null || exp2 == null) return false;
return const ConstantEquivalence().visit(exp1, exp2);
}
+/// Returns `true` if constant values [value1] and [value2] are equivalent.
+bool areConstantValuesEquivalent(ConstantValue value1, ConstantValue value2) {
+ if (identical(value1, value2)) return true;
+ if (value1 == null || value2 == null) return false;
+ return const ConstantValueEquivalence().visit(value1, value2);
+}
+
/// Returns `true` if the lists of elements, [a] and [b], are equivalent.
bool areElementListsEquivalent(List<Element> a, List<Element> b) {
return areListsEquivalent(a, b, areElementsEquivalent);
@@ -100,6 +132,12 @@
return areListsEquivalent(a, b, areConstantsEquivalent);
}
+/// Returns `true` if the lists of constant values, [a] and [b], are equivalent.
+bool areConstantValueListsEquivalent(
+ List<ConstantValue> a, List<ConstantValue> b) {
+ return areListsEquivalent(a, b, areConstantValuesEquivalent);
+}
+
/// Returns `true` if the selectors [a] and [b] are equivalent.
bool areSelectorsEquivalent(Selector a, Selector b) {
if (identical(a, b)) return true;
@@ -307,6 +345,12 @@
return areSetsEquivalent(set1, set2, elementEquivalence);
}
+ bool testMaps(var object1, var object2, String property, Map map1, Map map2,
+ [bool keyEquivalence(a, b) = equality,
+ bool valueEquivalence(a, b) = equality]) {
+ return areMapsEquivalent(map1, map2, keyEquivalence, valueEquivalence);
+ }
+
bool testElements(Object object1, Object object2, String property,
Element element1, Element element2) {
return areElementsEquivalent(element1, element2);
@@ -322,6 +366,11 @@
return areConstantsEquivalent(exp1, exp2);
}
+ bool testConstantValues(Object object1, Object object2, String property,
+ ConstantValue value1, ConstantValue value2) {
+ return areConstantValuesEquivalent(value1, value2);
+ }
+
bool testTypeLists(Object object1, Object object2, String property,
List<DartType> list1, List<DartType> list2) {
return areTypeListsEquivalent(list1, list2);
@@ -332,6 +381,11 @@
return areConstantListsEquivalent(list1, list2);
}
+ bool testConstantValueLists(Object object1, Object object2, String property,
+ List<ConstantValue> list1, List<ConstantValue> list2) {
+ return areConstantValueListsEquivalent(list1, list2);
+ }
+
bool testNodes(
Object object1, Object object2, String property, Node node1, Node node2) {
return areNodesEquivalent(node1, node2);
@@ -780,9 +834,130 @@
@override
bool visitDeferred(
DeferredConstantExpression exp1, DeferredConstantExpression exp2) {
- // TODO(johnniwinther): Implement this.
+ return strategy.testElements(
+ exp1, exp2, 'prefix', exp1.prefix, exp2.prefix) &&
+ strategy.testConstants(
+ exp1, exp2, 'expression', exp1.expression, exp2.expression);
+ }
+}
+
+/// Visitor that checks for structural equivalence of [ConstantValue]s.
+class ConstantValueEquivalence
+ implements ConstantValueVisitor<bool, ConstantValue> {
+ final TestStrategy strategy;
+
+ const ConstantValueEquivalence([this.strategy = const TestStrategy()]);
+
+ bool visit(ConstantValue value1, ConstantValue value2) {
+ if (identical(value1, value2)) return true;
+ return strategy.test(value1, value2, 'kind', value1.kind, value2.kind) &&
+ value1.accept(this, value2);
+ }
+
+ @override
+ bool visitConstructed(
+ ConstructedConstantValue value1, ConstructedConstantValue value2) {
+ return strategy.testTypes(
+ value1, value2, 'type', value1.type, value2.type) &&
+ strategy.testMaps(
+ value1,
+ value2,
+ 'fields',
+ value1.fields,
+ value2.fields,
+ areElementsEquivalent,
+ (a, b) => strategy.testConstantValues(
+ value1, value2, 'fields.values', a, b));
+ }
+
+ @override
+ bool visitFunction(
+ FunctionConstantValue value1, FunctionConstantValue value2) {
+ return strategy.testElements(
+ value1, value2, 'element', value1.element, value2.element);
+ }
+
+ @override
+ bool visitList(ListConstantValue value1, ListConstantValue value2) {
+ return strategy.testTypes(
+ value1, value2, 'type', value1.type, value2.type) &&
+ strategy.testConstantValueLists(
+ value1, value2, 'entries', value1.entries, value2.entries);
+ }
+
+ @override
+ bool visitMap(MapConstantValue value1, MapConstantValue value2) {
+ return strategy.testTypes(
+ value1, value2, 'type', value1.type, value2.type) &&
+ strategy.testConstantValueLists(
+ value1, value2, 'keys', value1.keys, value2.keys) &&
+ strategy.testConstantValueLists(
+ value1, value2, 'values', value1.values, value2.values);
+ }
+
+ @override
+ bool visitType(TypeConstantValue value1, TypeConstantValue value2) {
+ return strategy.testTypes(value1, value2, 'type', value1.type, value2.type);
+ }
+
+ @override
+ bool visitBool(BoolConstantValue value1, BoolConstantValue value2) {
+ return strategy.test(value1, value2, 'primitiveValue',
+ value1.primitiveValue, value2.primitiveValue);
+ }
+
+ @override
+ bool visitDouble(DoubleConstantValue value1, DoubleConstantValue value2) {
+ return strategy.test(value1, value2, 'primitiveValue',
+ value1.primitiveValue, value2.primitiveValue);
+ }
+
+ @override
+ bool visitInt(IntConstantValue value1, IntConstantValue value2) {
+ return strategy.test(value1, value2, 'primitiveValue',
+ value1.primitiveValue, value2.primitiveValue);
+ }
+
+ @override
+ bool visitNull(NullConstantValue value1, NullConstantValue value2) {
return true;
}
+
+ @override
+ bool visitString(StringConstantValue value1, StringConstantValue value2) {
+ return strategy.test(value1, value2, 'primitiveValue',
+ value1.primitiveValue, value2.primitiveValue);
+ }
+
+ @override
+ bool visitDeferred(
+ DeferredConstantValue value1, DeferredConstantValue value2) {
+ return strategy.testElements(
+ value1, value2, 'prefix', value1.prefix, value2.prefix) &&
+ strategy.testConstantValues(
+ value1, value2, 'referenced', value1.referenced, value2.referenced);
+ }
+
+ @override
+ bool visitNonConstant(NonConstantValue value1, NonConstantValue value2) {
+ return true;
+ }
+
+ @override
+ bool visitSynthetic(
+ SyntheticConstantValue value1, SyntheticConstantValue value2) {
+ return strategy.test(
+ value1, value2, 'payload', value1.payload, value2.payload) &&
+ strategy.test(
+ value1, value2, 'valueKind', value1.valueKind, value2.valueKind);
+ }
+
+ @override
+ bool visitInterceptor(
+ InterceptorConstantValue value1, InterceptorConstantValue value2) {
+ return strategy.testTypes(value1, value2, 'dispatchedType',
+ value1.dispatchedType, value2.dispatchedType);
+ }
}
/// Tests the equivalence of [impact1] and [impact2] using [strategy].
diff --git a/pkg/compiler/lib/src/serialization/impact_serialization.dart b/pkg/compiler/lib/src/serialization/impact_serialization.dart
index b2aa0455..62671e2 100644
--- a/pkg/compiler/lib/src/serialization/impact_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/impact_serialization.dart
@@ -4,7 +4,6 @@
library dart2js.serialization.impact;
-import '../common.dart';
import '../common/resolution.dart';
import '../constants/expressions.dart';
import '../dart_types.dart';
diff --git a/pkg/compiler/lib/src/serialization/json_serializer.dart b/pkg/compiler/lib/src/serialization/json_serializer.dart
index 32c6500..52e9f96 100644
--- a/pkg/compiler/lib/src/serialization/json_serializer.dart
+++ b/pkg/compiler/lib/src/serialization/json_serializer.dart
@@ -5,6 +5,7 @@
library dart2js.serialization.json;
import 'dart:convert';
+
import 'keys.dart';
import 'serialization.dart';
import 'values.dart';
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index 55ab23e..a6ba195 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -10,7 +10,6 @@
library dart2js.serialization.modelz;
import '../common.dart';
-import '../common/names.dart';
import '../common/resolution.dart' show Resolution;
import '../constants/constructors.dart';
import '../constants/expressions.dart';
@@ -31,7 +30,6 @@
import '../util/util.dart' show Link, LinkBuilder;
import 'keys.dart';
import 'serialization.dart';
-import 'serialization_util.dart';
/// Compute a [Link] from an [Iterable].
Link toLink(Iterable iterable) {
diff --git a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
index bce66ac..c3ef366 100644
--- a/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/resolved_ast_serialization.dart
@@ -25,7 +25,6 @@
import 'modelz.dart';
import 'serialization.dart';
import 'serialization_util.dart';
-import 'modelz.dart';
/// Visitor that computes a node-index mapping.
class AstIndexComputer extends Visitor {
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 4230ca0..b1418f6 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -11,7 +11,6 @@
import '../elements/elements.dart';
import '../library_loader.dart' show LibraryProvider;
import '../util/enumset.dart';
-
import 'constant_serialization.dart';
import 'element_serialization.dart';
import 'json_serializer.dart';
diff --git a/pkg/compiler/lib/src/serialization/system.dart b/pkg/compiler/lib/src/serialization/system.dart
index 5e2a24b..9be7d6d 100644
--- a/pkg/compiler/lib/src/serialization/system.dart
+++ b/pkg/compiler/lib/src/serialization/system.dart
@@ -5,22 +5,18 @@
library dart2js.serialization_system;
import 'dart:async';
-import '../commandline_options.dart';
+
import '../common.dart';
-import '../common/backend_api.dart';
-import '../common/names.dart';
import '../common/resolution.dart';
import '../compiler.dart';
import '../elements/elements.dart';
-import '../io/source_file.dart';
import '../scanner/scanner.dart';
import '../script.dart';
import '../serialization/impact_serialization.dart';
import '../tokens/token.dart';
import '../universe/call_structure.dart';
-import '../universe/world_impact.dart';
import '../universe/use.dart';
-import 'json_serializer.dart';
+import '../universe/world_impact.dart';
import 'modelz.dart';
import 'resolved_ast_serialization.dart';
import 'serialization.dart';
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index f57ade6..bfcd950 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -5,7 +5,7 @@
library dart2js.serialization.task;
import 'dart:async' show EventSink, Future;
-import '../common.dart';
+
import '../common/resolution.dart' show ResolutionImpact, ResolutionWorkItem;
import '../common/tasks.dart' show CompilerTask;
import '../common/work.dart' show ItemCompilationContext;
diff --git a/pkg/compiler/lib/src/serialization/type_serialization.dart b/pkg/compiler/lib/src/serialization/type_serialization.dart
index ed94ade..96f659e 100644
--- a/pkg/compiler/lib/src/serialization/type_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/type_serialization.dart
@@ -6,8 +6,8 @@
import '../dart_types.dart';
import '../elements/elements.dart';
-import 'serialization.dart';
import 'keys.dart';
+import 'serialization.dart';
/// Visitor that serializes a [DartType] by encoding it into an [ObjectEncoder].
///
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index 2e2c7aa..22273d4 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -19,16 +19,6 @@
import 'io/source_file.dart';
import 'util/uri_extras.dart';
-List<int> readAll(String filename) {
- var file = (new File(filename)).openSync();
- var length = file.lengthSync();
- // +1 to have a 0 terminated list, see [Scanner].
- var buffer = new Uint8List(length + 1);
- file.readIntoSync(buffer, 0, length);
- file.closeSync();
- return buffer;
-}
-
abstract class SourceFileProvider implements CompilerInput {
bool isWindows = (Platform.operatingSystem == 'windows');
Uri cwd = currentDirectory;
@@ -55,12 +45,10 @@
try {
source = readAll(resourceUri.toFilePath());
} on FileSystemException catch (ex) {
- OSError ose = ex.osError;
- String detail =
- (ose != null && ose.message != null) ? ' (${ose.message})' : '';
+ String message = ex.osError?.message;
+ String detail = message != null ? ' ($message)' : '';
return new Future.error(
- "Error reading '${relativize(cwd, resourceUri, isWindows)}'"
- "$detail");
+ "Error reading '${relativizeUri(resourceUri)}' $detail");
}
dartCharactersRead += source.length;
sourceFiles[resourceUri] = new CachingUtf8BytesSourceFile(
@@ -100,7 +88,7 @@
// TODO(johnniwinther): Remove this when no longer needed for the old compiler
// API.
- Future/*<List<int> | String>*/ call(Uri resourceUri);
+ Future/*<List<int> | String>*/ call(Uri resourceUri) => throw "unimplemented";
relativizeUri(Uri uri) => relativize(cwd, uri, isWindows);
@@ -109,6 +97,16 @@
}
}
+List<int> readAll(String filename) {
+ var file = (new File(filename)).openSync();
+ var length = file.lengthSync();
+ // +1 to have a 0 terminated list, see [Scanner].
+ var buffer = new Uint8List(length + 1);
+ file.readIntoSync(buffer, 0, length);
+ file.closeSync();
+ return buffer;
+}
+
class CompilerSourceFileProvider extends SourceFileProvider {
// TODO(johnniwinther): Remove this when no longer needed for the old compiler
// API.
@@ -330,14 +328,14 @@
}
}
- return new EventSinkWrapper(writeStringSync, onDone);
+ return new _EventSinkWrapper(writeStringSync, onDone);
}
}
-class EventSinkWrapper extends EventSink<String> {
+class _EventSinkWrapper extends EventSink<String> {
var onAdd, onClose;
- EventSinkWrapper(this.onAdd, this.onClose);
+ _EventSinkWrapper(this.onAdd, this.onClose);
void add(String data) => onAdd(data);
@@ -345,3 +343,79 @@
void close() => onClose();
}
+
+/// Adapter to integrate dart2js in bazel.
+///
+/// To handle bazel's special layout:
+///
+/// * We specify a .packages configuration file that expands packages to their
+/// corresponding bazel location. This way there is no need to create a pub
+/// cache prior to invoking dart2js.
+///
+/// * We provide a mapping that can make all urls relative to the bazel root.
+/// To the compiler, URIs look like:
+/// file:///bazel-root/a/b/c.dart
+///
+/// even though in the file system the file is located at:
+/// file:///path/to/the/actual/bazel/root/a/b/c.dart
+///
+/// This mapping serves two purposes:
+/// - It makes compiler results independent of the machine layout, which
+/// enables us to share results across bazel runs and across machines.
+///
+/// - It hides the distinction between generated and source files. That way
+/// we can use the standard package-resolution mechanism and ignore the
+/// internals of how files are organized within bazel.
+///
+/// This class is initialized using a dart2js-bazel configuration file. The file
+/// follows the following custom format:
+///
+/// <generated-path-prefix>
+/// <file1-bazel-root-relative-path>
+/// <file2-bazel-root-relative-path>
+/// ...
+/// <fileN-bazel-root-relative-path>
+///
+/// For example:
+///
+/// bazel-bin/123/
+/// a/b/c.dart
+/// bazel-bin/123/a/b/d.dart
+/// a/b/e.dart
+///
+/// The current working directory will be used to resolve the bazel-root and
+/// when invoking the compiler, bazel will use `package:` and
+/// `file:///bazel-root/` URIs to specify entrypoints.
+class BazelInputProvider extends SourceFileProvider {
+ /// Anything above this root is treated as machine specific and will only be
+ /// used to locate files on disk, but otherwise it's abstracted away in the
+ /// representation of canonical uris in the compiler.
+ final Uri bazelRoot;
+
+ /// Path prefix where generated files are located.
+ final String genPath;
+
+ /// Mapping from bazel-root uris to relative paths on top of [bazelRoot].
+ final Map<Uri, Uri> mappings = <Uri, Uri>{};
+
+ factory BazelInputProvider(String configPath) {
+ var config = new File(configPath).readAsLinesSync();
+ var bazelRoot = currentDirectory;
+ var outPrefix = config[0];
+ var files = config.skip(1);
+ return new BazelInputProvider._(bazelRoot, outPrefix, files);
+ }
+
+ BazelInputProvider._(this.bazelRoot, this.genPath, Iterable<String> files) {
+ var fakeBazelRoot = Uri.parse('file:///bazel-root/');
+ for (var path in files) {
+ var absolute = currentDirectory.resolve(path);
+ var bazelRelativeUri = fakeBazelRoot.resolve(
+ path.startsWith(genPath) ? path.substring(genPath.length) : path);
+ mappings[bazelRelativeUri] = absolute;
+ }
+ }
+
+ @override
+ Future readFromUri(Uri uri) => readUtf8BytesFromUri(mappings[uri] ?? uri);
+}
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index 681056f..5a0f558 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -8,7 +8,6 @@
import '../js_backend/js_backend.dart';
import '../types/types.dart';
import '../universe/selector.dart' show Selector;
-
import 'nodes.dart';
/**
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index 9a6f6c6..5591851 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -10,7 +10,6 @@
import '../diagnostics/invariant.dart' show DEBUG_MODE;
import '../js_backend/js_backend.dart';
import '../tracer.dart';
-
import 'nodes.dart';
/**
diff --git a/pkg/compiler/lib/src/ssa/value_set.dart b/pkg/compiler/lib/src/ssa/value_set.dart
index c990014..89dbeca 100644
--- a/pkg/compiler/lib/src/ssa/value_set.dart
+++ b/pkg/compiler/lib/src/ssa/value_set.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import '../universe/side_effects.dart' show SideEffects;
-
import 'nodes.dart';
class ValueSet {
diff --git a/pkg/compiler/lib/src/ssa/variable_allocator.dart b/pkg/compiler/lib/src/ssa/variable_allocator.dart
index 2145d6d..5ea597d 100644
--- a/pkg/compiler/lib/src/ssa/variable_allocator.dart
+++ b/pkg/compiler/lib/src/ssa/variable_allocator.dart
@@ -5,7 +5,6 @@
import '../common.dart';
import '../compiler.dart' show Compiler;
import '../js_backend/js_backend.dart';
-
import 'nodes.dart';
/**
diff --git a/pkg/compiler/lib/src/string_validator.dart b/pkg/compiler/lib/src/string_validator.dart
index 866d0f0..60c3c78 100644
--- a/pkg/compiler/lib/src/string_validator.dart
+++ b/pkg/compiler/lib/src/string_validator.dart
@@ -10,8 +10,8 @@
import 'common.dart';
import 'tokens/token.dart' show Token;
-import 'tree/nodes.dart' show StringQuoting;
import 'tree/dartstring.dart' show DartString;
+import 'tree/nodes.dart' show StringQuoting;
import 'util/characters.dart';
class StringValidator {
diff --git a/pkg/compiler/lib/src/tokens/keyword.dart b/pkg/compiler/lib/src/tokens/keyword.dart
index ad22ee6..4d914bc 100644
--- a/pkg/compiler/lib/src/tokens/keyword.dart
+++ b/pkg/compiler/lib/src/tokens/keyword.dart
@@ -5,7 +5,6 @@
library dart2js.tokens.keywords;
import '../util/characters.dart' as Characters show $a;
-
import 'precedence.dart' show PrecedenceInfo;
import 'precedence_constants.dart' as Precedence
show AS_INFO, IS_INFO, KEYWORD_INFO;
diff --git a/pkg/compiler/lib/src/tokens/token.dart b/pkg/compiler/lib/src/tokens/token.dart
index df66bd9..af31142 100644
--- a/pkg/compiler/lib/src/tokens/token.dart
+++ b/pkg/compiler/lib/src/tokens/token.dart
@@ -4,12 +4,11 @@
library dart2js.tokens;
-import 'dart:convert' show UTF8;
import 'dart:collection' show HashSet;
+import 'dart:convert' show UTF8;
import '../common.dart';
import '../util/util.dart' show computeHashCode;
-
import 'keyword.dart' show Keyword;
import 'precedence.dart' show PrecedenceInfo;
import 'precedence_constants.dart' as Precedence show BAD_INPUT_INFO;
diff --git a/pkg/compiler/lib/src/tracer.dart b/pkg/compiler/lib/src/tracer.dart
index 359ea77..09b8b98 100644
--- a/pkg/compiler/lib/src/tracer.dart
+++ b/pkg/compiler/lib/src/tracer.dart
@@ -5,13 +5,14 @@
library tracer;
import 'dart:async' show EventSink;
+
import '../compiler.dart' as api;
import 'common/work.dart' show ItemCompilationContext;
import 'compiler.dart' show Compiler;
-import 'ssa/nodes.dart' as ssa show HGraph;
-import 'ssa/ssa_tracer.dart' show HTracer;
import 'cps_ir/cps_ir_nodes.dart' as cps_ir;
import 'cps_ir/cps_ir_tracer.dart' show IRTracer;
+import 'ssa/nodes.dart' as ssa show HGraph;
+import 'ssa/ssa_tracer.dart' show HTracer;
import 'tree_ir/tree_ir_nodes.dart' as tree_ir;
import 'tree_ir/tree_ir_tracer.dart' show TreeTracer;
import 'util/util.dart' show Indentation;
diff --git a/pkg/compiler/lib/src/tree/dartstring.dart b/pkg/compiler/lib/src/tree/dartstring.dart
index 684f55b..4ec773c 100644
--- a/pkg/compiler/lib/src/tree/dartstring.dart
+++ b/pkg/compiler/lib/src/tree/dartstring.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:collection';
+
import '../util/characters.dart';
/**
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
index bfed37d..bdfadae 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/logical_rewriter.dart
@@ -4,9 +4,9 @@
library tree_ir.optimization.logical_rewriter;
+import '../../constants/values.dart' as values;
import '../tree_ir_nodes.dart';
import 'optimization.dart' show Pass;
-import '../../constants/values.dart' as values;
/// Rewrites logical expressions to be more compact in the Tree IR.
///
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart
index e57c938..847d0ca 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/loop_rewriter.dart
@@ -4,8 +4,8 @@
library tree_ir.optimization.loop_rewriter;
-import 'optimization.dart' show Pass;
import '../tree_ir_nodes.dart';
+import 'optimization.dart' show Pass;
/// Rewrites [WhileTrue] statements into [For] statements.
///
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/optimization.dart b/pkg/compiler/lib/src/tree_ir/optimization/optimization.dart
index 130e5e3..ebf201a 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/optimization.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/optimization.dart
@@ -2,11 +2,11 @@
import '../tree_ir_nodes.dart';
+export 'logical_rewriter.dart' show LogicalRewriter;
+export 'loop_rewriter.dart' show LoopRewriter;
+export 'pull_into_initializers.dart' show PullIntoInitializers;
export 'statement_rewriter.dart' show StatementRewriter;
export 'variable_merger.dart' show VariableMerger;
-export 'loop_rewriter.dart' show LoopRewriter;
-export 'logical_rewriter.dart' show LogicalRewriter;
-export 'pull_into_initializers.dart' show PullIntoInitializers;
/// An optimization pass over the Tree IR.
abstract class Pass {
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
index 931368d..722230a 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/pull_into_initializers.dart
@@ -4,8 +4,8 @@
library tree_ir.optimization.pull_into_initializers;
-import 'optimization.dart' show Pass;
import '../tree_ir_nodes.dart';
+import 'optimization.dart' show Pass;
/// Where a variable has been assigned.
enum AssignArea {
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
index 5db310a..cc2786e 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart
@@ -4,11 +4,11 @@
library tree_ir.optimization.statement_rewriter;
-import 'optimization.dart' show Pass;
-import '../tree_ir_nodes.dart';
-import '../../io/source_information.dart';
import '../../elements/elements.dart';
+import '../../io/source_information.dart';
import '../../js/placeholder_safety.dart';
+import '../tree_ir_nodes.dart';
+import 'optimization.dart' show Pass;
/**
* Translates to direct-style.
diff --git a/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart b/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
index 273d7a4..d76bb31 100644
--- a/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
+++ b/pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart
@@ -4,8 +4,8 @@
library tree_ir.optimization.variable_merger;
-import 'optimization.dart' show Pass;
import '../tree_ir_nodes.dart';
+import 'optimization.dart' show Pass;
/// Merges variables based on liveness and source variable information.
///
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
index 000f610..a152f3b 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
@@ -10,7 +10,6 @@
import '../elements/elements.dart';
import '../io/source_information.dart';
import '../js_backend/codegen/glue.dart';
-
import 'tree_ir_nodes.dart';
typedef Statement NodeCallback(Statement next);
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
index 486ee13..e93ae0c 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart
@@ -5,6 +5,7 @@
library tree_ir_tracer;
import 'dart:async' show EventSink;
+
import '../tracer.dart';
import 'tree_ir_nodes.dart';
diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart
index be25edf..b4ad1f8 100644
--- a/pkg/compiler/lib/src/typechecker.dart
+++ b/pkg/compiler/lib/src/typechecker.dart
@@ -443,7 +443,7 @@
if (result == null) {
reporter.internalError(node, 'Type is null.');
}
- return _record(node, result);
+ return result;
}
void checkTypePromotion(Node node, TypePromotion typePromotion,
@@ -1151,24 +1151,6 @@
return null;
}
- static bool _fyiShown = false;
- DartType _record(Node node, DartType type) {
- if (node is! Expression) return type;
- if (const bool.fromEnvironment('send_stats') &&
- executableContext != null &&
- // TODO(sigmund): enable also in core libs.
- !executableContext.library.isPlatformLibrary &&
- !type.isDynamic) {
- if (!_fyiShown) {
- print('FYI experiment to collect send stats is on: '
- 'caching types of expressions');
- _fyiShown = true;
- }
- elements.typesCache[node] = type;
- }
- return type;
- }
-
DartType visitSend(Send node) {
Element element = elements[node];
diff --git a/pkg/compiler/lib/src/types/constants.dart b/pkg/compiler/lib/src/types/constants.dart
index d66a31c..219e6b1 100644
--- a/pkg/compiler/lib/src/types/constants.dart
+++ b/pkg/compiler/lib/src/types/constants.dart
@@ -48,7 +48,7 @@
@override
TypeMask visitSynthetic(SyntheticConstantValue constant, Compiler compiler) {
- switch (constant.kind) {
+ switch (constant.valueKind) {
case SyntheticConstantKind.DUMMY_INTERCEPTOR:
return constant.payload;
case SyntheticConstantKind.EMPTY_VALUE:
diff --git a/pkg/compiler/lib/src/types/types.dart b/pkg/compiler/lib/src/types/types.dart
index 61dbabf..d12b2bd 100644
--- a/pkg/compiler/lib/src/types/types.dart
+++ b/pkg/compiler/lib/src/types/types.dart
@@ -12,15 +12,14 @@
import '../elements/elements.dart';
import '../inferrer/type_graph_inferrer.dart' show TypeGraphInferrer;
import '../tree/tree.dart';
-import '../util/util.dart';
import '../universe/selector.dart' show Selector;
import '../universe/universe.dart'
show
ReceiverConstraint,
UniverseSelectorConstraints,
SelectorConstraintsStrategy;
+import '../util/util.dart';
import '../world.dart' show ClassWorld, World;
-
import 'abstract_value_domain.dart' show AbstractValue;
part 'container_type_mask.dart';
diff --git a/pkg/compiler/lib/src/universe/class_set.dart b/pkg/compiler/lib/src/universe/class_set.dart
index 038d757..4a7a035 100644
--- a/pkg/compiler/lib/src/universe/class_set.dart
+++ b/pkg/compiler/lib/src/universe/class_set.dart
@@ -5,6 +5,7 @@
library dart2js.world.class_set;
import 'dart:collection' show IterableBase;
+
import '../elements/elements.dart' show ClassElement;
import '../util/enumset.dart' show EnumSet;
import '../util/util.dart' show Link;
diff --git a/pkg/compiler/lib/src/universe/function_set.dart b/pkg/compiler/lib/src/universe/function_set.dart
index c225b15..afa0951 100644
--- a/pkg/compiler/lib/src/universe/function_set.dart
+++ b/pkg/compiler/lib/src/universe/function_set.dart
@@ -10,7 +10,6 @@
import '../types/types.dart';
import '../util/util.dart' show Hashing, Setlet;
import '../world.dart' show ClassWorld;
-
import 'selector.dart' show Selector;
import 'universe.dart' show ReceiverConstraint;
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index a76db34..19ce7c6 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -17,7 +17,6 @@
PublicName;
import '../util/util.dart' show Hashing;
import '../world.dart' show World;
-
import 'call_structure.dart' show CallStructure;
class SelectorKind {
diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart
index 8f08f6f..e2bba01 100644
--- a/pkg/compiler/lib/src/universe/universe.dart
+++ b/pkg/compiler/lib/src/universe/universe.dart
@@ -8,11 +8,10 @@
import '../common.dart';
import '../compiler.dart' show Compiler;
-import '../elements/elements.dart';
import '../dart_types.dart';
+import '../elements/elements.dart';
import '../util/util.dart';
import '../world.dart' show ClassWorld, World;
-
import 'selector.dart' show Selector;
import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind;
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index bb6b153..e795f02 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -11,9 +11,8 @@
import '../common.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
-import '../world.dart' show ClassWorld;
import '../util/util.dart' show Hashing;
-
+import '../world.dart' show ClassWorld;
import 'call_structure.dart' show CallStructure;
import 'selector.dart' show Selector;
import 'universe.dart' show ReceiverConstraint;
diff --git a/pkg/compiler/lib/src/use_unused_api.dart b/pkg/compiler/lib/src/use_unused_api.dart
index d3578f7..468fae3 100644
--- a/pkg/compiler/lib/src/use_unused_api.dart
+++ b/pkg/compiler/lib/src/use_unused_api.dart
@@ -9,7 +9,6 @@
library dart2js.use_unused_api;
import '../compiler.dart' as api;
-
import 'colors.dart' as colors;
import 'compiler.dart' as compiler;
import 'constants/constant_system.dart' as constants;
@@ -19,9 +18,8 @@
import 'constants/values.dart' as constants;
import 'cps_ir/cps_ir_builder.dart' as ir_builder;
import 'cps_ir/cps_ir_builder_task.dart' as ir_builder;
-import 'tree_ir/tree_ir_nodes.dart' as tree_ir;
-import 'dart_types.dart' as dart_types;
import 'dart2js.dart' as dart2js;
+import 'dart_types.dart' as dart_types;
import 'deferred_load.dart' as deferred;
import 'diagnostics/source_span.dart' as diagnostics;
import 'elements/elements.dart' as elements;
@@ -33,21 +31,21 @@
import 'io/source_map_builder.dart' as io;
import 'js/js.dart' as js;
import 'js_backend/js_backend.dart' as js_backend;
-import 'js_emitter/js_emitter.dart' as js_emitter;
import 'js_emitter/full_emitter/emitter.dart' as full;
+import 'js_emitter/js_emitter.dart' as js_emitter;
import 'js_emitter/program_builder/program_builder.dart' as program_builder;
-import 'resolution/semantic_visitor.dart' as semantic_visitor;
+import 'parser/partial_elements.dart'
+ show PartialClassElement, PartialFunctionElement;
import 'resolution/operators.dart' as operators;
+import 'resolution/semantic_visitor.dart' as semantic_visitor;
import 'script.dart';
import 'source_file_provider.dart' as source_file_provider;
import 'ssa/nodes.dart' as ssa;
import 'tree/tree.dart' as tree;
+import 'tree_ir/tree_ir_nodes.dart' as tree_ir;
import 'util/util.dart' as util;
import 'world.dart';
-import 'parser/partial_elements.dart'
- show PartialClassElement, PartialFunctionElement;
-
class ElementVisitor extends elements_visitor.BaseElementVisitor {
visitElement(e, a) {}
}
diff --git a/pkg/compiler/lib/src/util/util.dart b/pkg/compiler/lib/src/util/util.dart
index d9cc16c..397bd6c 100644
--- a/pkg/compiler/lib/src/util/util.dart
+++ b/pkg/compiler/lib/src/util/util.dart
@@ -4,12 +4,12 @@
library dart2js.util;
-import 'util_implementation.dart';
import 'characters.dart';
+import 'util_implementation.dart';
-export 'setlet.dart';
-export 'maplet.dart';
export 'emptyset.dart';
+export 'maplet.dart';
+export 'setlet.dart';
part 'indentation.dart';
part 'link.dart';
diff --git a/pkg/compiler/lib/src/util/util_implementation.dart b/pkg/compiler/lib/src/util/util_implementation.dart
index c28b63f..bdb6b90 100644
--- a/pkg/compiler/lib/src/util/util_implementation.dart
+++ b/pkg/compiler/lib/src/util/util_implementation.dart
@@ -4,7 +4,8 @@
library util_implementation;
-import 'util.dart';
import 'dart:collection';
+import 'util.dart';
+
part 'link_implementation.dart';
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index bfa2100..5bb3f52 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -5,8 +5,8 @@
library dart2js.world;
import 'closure.dart' show SynthesizedCallMethodElementX;
-import 'common.dart';
import 'common/backend_api.dart' show Backend;
+import 'common.dart';
import 'compiler.dart' show Compiler;
import 'core_types.dart' show CoreClasses;
import 'dart_types.dart';
diff --git a/pkg/compiler/samples/compile_loop/compile_loop.dart b/pkg/compiler/samples/compile_loop/compile_loop.dart
deleted file mode 100644
index 097d046..0000000
--- a/pkg/compiler/samples/compile_loop/compile_loop.dart
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// This sample demonstrates how to run the compiler in a loop reading
-// all sources from memory, instead of using dart:io.
-library sample.compile_loop;
-
-import 'dart:async';
-
-import '../../lib/compiler.dart' as compiler;
-
-// If this file is missing, generate it using ../jsonify/jsonify.dart.
-import 'sdk.dart';
-
-Future<String> compile(source) {
- Future<String> inputProvider(Uri uri) {
- if (uri.scheme == 'sdk') {
- var value = SDK_SOURCES['$uri'];
- if (value == null) {
- // TODO(ahe): Use new Future.error.
- throw new Exception('Error: Cannot read: $uri');
- }
- return new Future.value(value);
- } else if ('$uri' == 'memory:/main.dart') {
- return new Future.value(source);
- }
- // TODO(ahe): Use new Future.error.
- throw new Exception('Error: Cannot read: $uri');
- }
- void handler(
- Uri uri, int begin, int end, String message, compiler.Diagnostic kind) {
- // TODO(ahe): Remove dart:io import from
- // ../../lib/src/source_file_provider.dart and use
- // FormattingDiagnosticHandler instead.
- print({
- 'uri': '$uri',
- 'begin': begin,
- 'end': end,
- 'message': message,
- 'kind': kind.name
- });
- if (kind == compiler.Diagnostic.ERROR) {
- throw new Exception('Unexpected error occurred.');
- }
- }
- return compiler.compile(Uri.parse('memory:/main.dart'),
- Uri.parse('sdk:/sdk/'), null, inputProvider, handler, []);
-}
-
-int iterations = 10;
-
-main() {
- compile(EXAMPLE_HELLO_HTML).then((jsResult) {
- if (jsResult == null) throw 'Compilation failed';
- if (--iterations > 0) main();
- });
-}
-
-const String EXAMPLE_HELLO_HTML = r'''
-// Go ahead and modify this example.
-
-import "dart:html";
-
-var greeting = "Hello, World!";
-
-// Displays a greeting.
-void main() {
- // This example uses HTML to display the greeting and it will appear
- // in a nested HTML frame (an iframe).
- document.body.append(new HeadingElement.h1()..appendText(greeting));
-}
-''';
diff --git a/pkg/compiler/samples/darttags/darttags.dart b/pkg/compiler/samples/darttags/darttags.dart
deleted file mode 100644
index d77966d..0000000
--- a/pkg/compiler/samples/darttags/darttags.dart
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Usage: Add the following to your .gclient file (found in the parent
-// of the "dart" in a gclient checkout of the Dart repositor).
-//
-// hooks = [
-// {
-// "pattern": ".",
-// "action": [
-// "dart/sdk/bin/dart",
-// # Replace "xcodebuild" with "out" on Linux, and "build" on Windows.
-// "-pdart/xcodebuild/ReleaseIA32/packages/",
-// "dart/pkg/compiler/samples/darttags/darttags.dart",
-// "dart/TAGS",
-// # Modify the following list to your preferences:
-// "dart/tests/try/web/incremental_compilation_update_test.dart",
-// "package:compiler/src/dart2js.dart",
-// ],
-// },
-// ]
-//
-// Modify .emacs to contain:
-//
-// (setq tags-table-list
-// '("DART_LOCATION/dart"))
-//
-// Where DART_LOCATION is the gclient directory where you found .gclient.
-
-import 'dart:io';
-import 'dart:mirrors';
-
-import 'package:compiler/src/filenames.dart';
-import 'package:compiler/src/io/source_file.dart';
-import 'package:compiler/src/mirrors/analyze.dart' show analyze;
-import 'package:compiler/src/mirrors/dart2js_mirrors.dart' show BackDoor;
-import 'package:compiler/src/mirrors/mirrors_util.dart' show nameOf;
-import 'package:compiler/src/source_file_provider.dart';
-import 'package:compiler/src/util/uri_extras.dart';
-import 'package:sdk_library_metadata/libraries.dart' show libraries;
-
-const DART2JS = 'package:compiler/src/dart2js.dart';
-const DART2JS_MIRROR = 'package:compiler/src/mirrors/dart2js_mirrors.dart';
-const SDK_ROOT = '../../../../sdk/';
-
-bool isPublicDart2jsLibrary(String name) {
- return !name.startsWith('_') && libraries[name].isDart2jsLibrary;
-}
-
-var handler;
-RandomAccessFile output;
-Uri outputUri;
-
-main(List<String> arguments) {
- handler = new FormattingDiagnosticHandler()..throwOnError = true;
-
- outputUri = handler.provider.cwd.resolve(nativeToUriPath(arguments.first));
- output = new File(arguments.first).openSync(mode: FileMode.WRITE);
-
- Uri myLocation = handler.provider.cwd.resolveUri(Platform.script);
-
- List<Uri> uris = <Uri>[];
-
- if (arguments.length > 1) {
- // Compute tags for libraries requested by the user.
- uris.addAll(
- arguments.skip(1).map((argument) => Uri.base.resolve(argument)));
- } else {
- // Compute tags for dart2js itself.
- uris.add(myLocation.resolve(DART2JS));
- uris.add(myLocation.resolve(DART2JS_MIRROR));
- }
-
- // Get the names of public dart2js libraries.
- Iterable<String> names = libraries.keys.where(isPublicDart2jsLibrary);
-
- // Prepend "dart:" to the names.
- uris.addAll(names.map((String name) => Uri.parse('dart:$name')));
-
- Uri platformConfigUri =
- myLocation.resolve(SDK_ROOT).resolve("lib/dart2js_shared_sdk");
- Uri packageRoot = Uri.base.resolve(Platform.packageRoot);
-
- analyze(uris, platformConfigUri, packageRoot, handler.provider, handler)
- .then(processMirrors);
-}
-
-processMirrors(MirrorSystem mirrors) {
- mirrors.libraries.forEach((_, LibraryMirror library) {
- BackDoor.compilationUnitsOf(library).forEach(emitTagsForCompilationUnit);
- });
-
- output.closeSync();
-}
-
-/**
- * From http://en.wikipedia.org/wiki/Ctags#Etags_2
- *
- * A section starts with a two line header, one line containing a
- * single <\x0c> character, followed by a line which consists of:
- *
- * {src_file},{size_of_tag_definition_data_in_bytes}
- *
- * The header is followed by tag definitions, one definition per line,
- * with the format:
- *
- * {tag_definition_text}<\x7f>{tagname}<\x01>{line_number},{byte_offset}
- */
-emitTagsForCompilationUnit(compilationUnit) {
- // Certain variables in this method do not follow Dart naming
- // conventions. This is because the format as written on Wikipedia
- // looks very similar to Dart string interpolation that the author
- // felt it would make sense to keep the names.
- Uri uri = compilationUnit.uri;
- var buffer = new StringBuffer();
- SourceFile file = handler.provider.sourceFiles[uri];
- String src_file = relativize(outputUri, uri, false);
-
- compilationUnit.declarations.forEach((_, DeclarationMirror mirror) {
- Definition definition = new Definition.from(mirror, file);
- String name = nameOf(mirror);
- definition.writeOn(buffer, name);
-
- if (mirror is ClassMirror) {
- emitTagsForClass(mirror, file, buffer);
- }
- });
-
- var tag_definition_data = '$buffer';
- var size_of_tag_definition_data_in_bytes = tag_definition_data.length;
-
- // The header.
- output.writeStringSync(
- '\x0c\n${src_file},${size_of_tag_definition_data_in_bytes}\n');
- output.writeStringSync(tag_definition_data);
-}
-
-void emitTagsForClass(ClassMirror cls, SourceFile file, StringBuffer buffer) {
- String className = nameOf(cls);
-
- cls.declarations.forEach((_, DeclarationMirror mirror) {
- Definition definition = new Definition.from(mirror, file);
- String name = nameOf(mirror);
- if (mirror is MethodMirror && mirror.isConstructor) {
- if (name == '') {
- name = className;
- definition.writeOn(buffer, 'new $className');
- } else {
- definition.writeOn(buffer, 'new $className.$name');
- }
- } else {
- definition.writeOn(buffer, '$className.$name');
- }
- definition.writeOn(buffer, name);
- });
-}
-
-class Definition {
- final int byte_offset;
- final int line_number;
- final String tag_definition_text;
-
- Definition(this.byte_offset, this.line_number, this.tag_definition_text);
-
- factory Definition.from(DeclarationMirror mirror, SourceFile file) {
- var location = mirror.location;
- int byte_offset = location.offset;
- int line_number = file.getLine(byte_offset) + 1;
-
- int lineStart = file.lineStarts[line_number - 1];
-
- int lineEnd = file.lineStarts.length > line_number
- // Subract 1 to remove trailing newline.
- ? file.lineStarts[line_number] - 1
- : null;
- String tag_definition_text = file.slowText().substring(lineStart, lineEnd);
-
- return new Definition(byte_offset, line_number, tag_definition_text);
- }
-
- void writeOn(StringBuffer buffer, String tagname) {
- buffer.write('${tag_definition_text}\x7f${tagname}'
- '\x01${line_number},${byte_offset}\n');
- }
-}
diff --git a/pkg/pkg.gyp b/pkg/pkg.gyp
index 771152c..047607f 100644
--- a/pkg/pkg.gyp
+++ b/pkg/pkg.gyp
@@ -22,6 +22,7 @@
'../sdk/lib/_internal/js_runtime/lib',
'../sdk/lib/_internal/sdk_library_metadata/lib',
'../site/try',
+ '../third_party/observatory_pub_packages/packages/charted/lib',
],
'outputs': [
'<(SHARED_INTERMEDIATE_DIR)/packages.stamp',
diff --git a/runtime/bin/common_patch.dart b/runtime/bin/common_patch.dart
index feaf552..aa6e1aa 100644
--- a/runtime/bin/common_patch.dart
+++ b/runtime/bin/common_patch.dart
@@ -2,8 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-patch class _IOCrypto {
- /* patch */ static Uint8List getRandomBytes(int count)
+@patch class _IOCrypto {
+ /* @patch */ static Uint8List getRandomBytes(int count)
native "Crypto_GetRandomBytes";
}
diff --git a/runtime/bin/directory_patch.dart b/runtime/bin/directory_patch.dart
index 9f4a265..c503161 100644
--- a/runtime/bin/directory_patch.dart
+++ b/runtime/bin/directory_patch.dart
@@ -2,25 +2,25 @@
// 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.
-patch class _Directory {
- /* patch */ static _current() native "Directory_Current";
- /* patch */ static _setCurrent(path) native "Directory_SetCurrent";
- /* patch */ static _createTemp(String path) native "Directory_CreateTemp";
- /* patch */ static String _systemTemp() native "Directory_SystemTemp";
- /* patch */ static _exists(String path) native "Directory_Exists";
- /* patch */ static _create(String path) native "Directory_Create";
- /* patch */ static _deleteNative(String path, bool recursive)
+@patch class _Directory {
+ /* @patch */ static _current() native "Directory_Current";
+ /* @patch */ static _setCurrent(path) native "Directory_SetCurrent";
+ /* @patch */ static _createTemp(String path) native "Directory_CreateTemp";
+ /* @patch */ static String _systemTemp() native "Directory_SystemTemp";
+ /* @patch */ static _exists(String path) native "Directory_Exists";
+ /* @patch */ static _create(String path) native "Directory_Create";
+ /* @patch */ static _deleteNative(String path, bool recursive)
native "Directory_Delete";
- /* patch */ static _rename(String path, String newPath)
+ /* @patch */ static _rename(String path, String newPath)
native "Directory_Rename";
- /* patch */ static void _fillWithDirectoryListing(
+ /* @patch */ static void _fillWithDirectoryListing(
List<FileSystemEntity> list, String path, bool recursive,
bool followLinks)
native "Directory_FillWithDirectoryListing";
}
-patch class _AsyncDirectoryListerOps {
- /* patch */ factory _AsyncDirectoryListerOps(int pointer) =>
+@patch class _AsyncDirectoryListerOps {
+ /* @patch */ factory _AsyncDirectoryListerOps(int pointer) =>
new _AsyncDirectoryListerOpsImpl(pointer);
}
diff --git a/runtime/bin/eventhandler_patch.dart b/runtime/bin/eventhandler_patch.dart
index d92271b..60be5e5 100644
--- a/runtime/bin/eventhandler_patch.dart
+++ b/runtime/bin/eventhandler_patch.dart
@@ -4,8 +4,8 @@
import 'dart:nativewrappers';
-patch class _EventHandler {
- /* patch */ static void _sendData(Object sender,
+@patch class _EventHandler {
+ /* @patch */ static void _sendData(Object sender,
SendPort sendPort,
int data)
native "EventHandler_SendData";
diff --git a/runtime/bin/file_patch.dart b/runtime/bin/file_patch.dart
index a3d42e8..8795b9c 100644
--- a/runtime/bin/file_patch.dart
+++ b/runtime/bin/file_patch.dart
@@ -2,28 +2,28 @@
// 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.
-patch class _File {
- /* patch */ static _exists(String path) native "File_Exists";
- /* patch */ static _create(String path) native "File_Create";
- /* patch */ static _createLink(String path, String target)
+@patch class _File {
+ /* @patch */ static _exists(String path) native "File_Exists";
+ /* @patch */ static _create(String path) native "File_Create";
+ /* @patch */ static _createLink(String path, String target)
native "File_CreateLink";
- /* patch */ static _linkTarget(String path) native "File_LinkTarget";
- /* patch */ static _deleteNative(String path) native "File_Delete";
- /* patch */ static _deleteLinkNative(String path) native "File_DeleteLink";
- /* patch */ static _rename(String oldPath, String newPath)
+ /* @patch */ static _linkTarget(String path) native "File_LinkTarget";
+ /* @patch */ static _deleteNative(String path) native "File_Delete";
+ /* @patch */ static _deleteLinkNative(String path) native "File_DeleteLink";
+ /* @patch */ static _rename(String oldPath, String newPath)
native "File_Rename";
- /* patch */ static _renameLink(String oldPath, String newPath)
+ /* @patch */ static _renameLink(String oldPath, String newPath)
native "File_RenameLink";
- /* patch */ static _copy(String oldPath, String newPath) native "File_Copy";
- /* patch */ static _lengthFromPath(String path) native "File_LengthFromPath";
- /* patch */ static _lastModified(String path) native "File_LastModified";
- /* patch */ static _open(String path, int mode) native "File_Open";
- /* patch */ static int _openStdio(int fd) native "File_OpenStdio";
+ /* @patch */ static _copy(String oldPath, String newPath) native "File_Copy";
+ /* @patch */ static _lengthFromPath(String path) native "File_LengthFromPath";
+ /* @patch */ static _lastModified(String path) native "File_LastModified";
+ /* @patch */ static _open(String path, int mode) native "File_Open";
+ /* @patch */ static int _openStdio(int fd) native "File_OpenStdio";
}
-patch class _RandomAccessFileOps {
- /* patch */ factory _RandomAccessFileOps(int pointer)
+@patch class _RandomAccessFileOps {
+ /* @patch */ factory _RandomAccessFileOps(int pointer)
=> new _RandomAccessFileOpsImpl(pointer);
}
@@ -62,7 +62,7 @@
}
-patch class _FileSystemWatcher {
+@patch class _FileSystemWatcher {
static int _id;
static final Map<int, _WatcherPath> _idMap = {};
@@ -74,7 +74,7 @@
StreamController _broadcastController;
- /* patch */ static Stream<FileSystemEvent> _watch(
+ /* @patch */ static Stream<FileSystemEvent> _watch(
String path, int events, bool recursive) {
if (Platform.isLinux) {
return new _InotifyFileSystemWatcher(path, events, recursive).stream;
@@ -262,7 +262,7 @@
});
}
- /* patch */ static bool get isSupported
+ /* @patch */ static bool get isSupported
native "FileSystemWatcher_IsSupported";
static int _initWatcher() native "FileSystemWatcher_InitWatcher";
diff --git a/runtime/bin/file_system_entity_patch.dart b/runtime/bin/file_system_entity_patch.dart
index 24782aa..dc2b346 100644
--- a/runtime/bin/file_system_entity_patch.dart
+++ b/runtime/bin/file_system_entity_patch.dart
@@ -2,16 +2,16 @@
// 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.
-patch class FileStat {
- /* patch */ static _statSync(String path) native "File_Stat";
+@patch class FileStat {
+ /* @patch */ static _statSync(String path) native "File_Stat";
}
-patch class FileSystemEntity {
- /* patch */ static _getType(String path, bool followLinks)
+@patch class FileSystemEntity {
+ /* @patch */ static _getType(String path, bool followLinks)
native "File_GetType";
- /* patch */ static _identical(String path1, String path2)
+ /* @patch */ static _identical(String path1, String path2)
native "File_AreIdentical";
- /* patch */ static _resolveSymbolicLinks(String path)
+ /* @patch */ static _resolveSymbolicLinks(String path)
native "File_ResolveSymbolicLinks";
}
diff --git a/runtime/bin/filter_patch.dart b/runtime/bin/filter_patch.dart
index a5626bb..11691e8 100644
--- a/runtime/bin/filter_patch.dart
+++ b/runtime/bin/filter_patch.dart
@@ -28,16 +28,16 @@
native "Filter_CreateZLibDeflate";
}
-patch class _Filter {
- /* patch */ static _Filter _newZLibDeflateFilter(bool gzip, int level,
- int windowBits, int memLevel,
- int strategy,
- List<int> dictionary,
- bool raw) =>
+@patch class _Filter {
+ /* @patch */ static _Filter _newZLibDeflateFilter(bool gzip, int level,
+ int windowBits, int memLevel,
+ int strategy,
+ List<int> dictionary,
+ bool raw) =>
new _ZLibDeflateFilter(gzip, level, windowBits, memLevel, strategy,
dictionary, raw);
- /* patch */ static _Filter _newZLibInflateFilter(int windowBits,
- List<int> dictionary,
- bool raw) =>
+ /* @patch */ static _Filter _newZLibInflateFilter(int windowBits,
+ List<int> dictionary,
+ bool raw) =>
new _ZLibInflateFilter(windowBits, dictionary, raw);
}
diff --git a/runtime/bin/fuchsia_test.cc b/runtime/bin/fuchsia_test.cc
index 341f9c7..fef899a 100644
--- a/runtime/bin/fuchsia_test.cc
+++ b/runtime/bin/fuchsia_test.cc
@@ -148,16 +148,11 @@
FATAL("Failed to set flags\n");
}
Log::Print("Calling Dart_Initialize\n");
- char* error = Dart_Initialize(
- vm_isolate_snapshot_buffer, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL);
+ Dart_InitializeParams init_params;
+ memset(&init_params, 0, sizeof(init_params));
+ init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
+ init_params.vm_isolate_snapshot = vm_isolate_snapshot_buffer;
+ char* error = Dart_Initialize(&init_params);
if (error != NULL) {
FATAL1("VM initialization failed: %s\n", error);
}
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 8654e28..319a322 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -1231,21 +1231,20 @@
// core library snapshot generation. However for the case when a full
// snasphot is generated from a script (app_script_name != NULL) we will
// need the service isolate to resolve URI and load code.
- char* error = Dart_Initialize(
- NULL,
- NULL,
- NULL,
- (app_script_name != NULL) ? CreateServiceIsolate : NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- DartUtils::OpenFile,
- DartUtils::ReadFile,
- DartUtils::WriteFile,
- DartUtils::CloseFile,
- DartUtils::EntropySource,
- NULL);
+
+ Dart_InitializeParams init_params;
+ memset(&init_params, 0, sizeof(init_params));
+ init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
+ if (app_script_name != NULL) {
+ init_params.create = CreateServiceIsolate;
+ }
+ init_params.file_open = DartUtils::OpenFile;
+ init_params.file_read = DartUtils::ReadFile;
+ init_params.file_write = DartUtils::WriteFile;
+ init_params.file_close = DartUtils::CloseFile;
+ init_params.entropy_source = DartUtils::EntropySource;
+
+ char* error = Dart_Initialize(&init_params);
if (error != NULL) {
Log::PrintErr("VM initialization failed: %s\n", error);
free(error);
diff --git a/runtime/bin/io_service_patch.dart b/runtime/bin/io_service_patch.dart
index add622f..94b6346 100644
--- a/runtime/bin/io_service_patch.dart
+++ b/runtime/bin/io_service_patch.dart
@@ -2,7 +2,7 @@
// 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.
-patch class _IOService {
+@patch class _IOService {
// Lazy initialize service ports, 32 per isolate.
static const int _SERVICE_PORT_COUNT = 32;
static List<SendPort> _servicePort = new List(_SERVICE_PORT_COUNT);
@@ -11,7 +11,7 @@
static Map<int, Completer> _messageMap = {};
static int _id = 0;
- /* patch */ static Future _dispatch(int request, List data) {
+ /* @patch */ static Future _dispatch(int request, List data) {
int id;
do {
id = _getNextId();
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index a90c1a4..216b919 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -282,28 +282,32 @@
environment = new HashMap(&HashMap::SameStringValue, 4);
}
// Split the name=value part of the -Dname=value argument.
- char* name;
- char* value = NULL;
const char* equals_pos = strchr(arg, '=');
if (equals_pos == NULL) {
// No equal sign (name without value) currently not supported.
Log::PrintErr("No value given to -D option\n");
return false;
- } else {
- int name_len = equals_pos - arg;
- if (name_len == 0) {
- Log::PrintErr("No name given to -D option\n");
- return false;
- }
- // Split name=value into name and value.
- name = reinterpret_cast<char*>(malloc(name_len + 1));
- strncpy(name, arg, name_len);
- name[name_len] = '\0';
- value = strdup(equals_pos + 1);
}
+
+ char* name;
+ char* value = NULL;
+ int name_len = equals_pos - arg;
+ if (name_len == 0) {
+ Log::PrintErr("No name given to -D option\n");
+ return false;
+ }
+ // Split name=value into name and value.
+ name = reinterpret_cast<char*>(malloc(name_len + 1));
+ strncpy(name, arg, name_len);
+ name[name_len] = '\0';
+ value = strdup(equals_pos + 1);
HashMap::Entry* entry = environment->Lookup(
GetHashmapKeyFromString(name), HashMap::StringHash(name), true);
ASSERT(entry != NULL); // Lookup adds an entry if key not found.
+ if (entry->value != NULL) {
+ free(name);
+ free(entry->value);
+ }
entry->value = value;
return true;
}
@@ -1727,16 +1731,22 @@
}
// Initialize the Dart VM.
- char* error = Dart_Initialize(
- vm_isolate_snapshot_buffer, instructions_snapshot, data_snapshot,
- CreateIsolateAndSetup, NULL, NULL, ShutdownIsolate,
- NULL,
- DartUtils::OpenFile,
- DartUtils::ReadFile,
- DartUtils::WriteFile,
- DartUtils::CloseFile,
- DartUtils::EntropySource,
- GetVMServiceAssetsArchiveCallback);
+ Dart_InitializeParams init_params;
+ memset(&init_params, 0, sizeof(init_params));
+ init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
+ init_params.vm_isolate_snapshot = vm_isolate_snapshot_buffer;
+ init_params.instructions_snapshot = instructions_snapshot;
+ init_params.data_snapshot = data_snapshot;
+ init_params.create = CreateIsolateAndSetup;
+ init_params.shutdown = ShutdownIsolate;
+ init_params.file_open = DartUtils::OpenFile;
+ init_params.file_read = DartUtils::ReadFile;
+ init_params.file_write = DartUtils::WriteFile;
+ init_params.file_close = DartUtils::CloseFile;
+ init_params.entropy_source = DartUtils::EntropySource;
+ init_params.get_service_assets = GetVMServiceAssetsArchiveCallback;
+
+ char* error = Dart_Initialize(&init_params);
if (error != NULL) {
EventHandler::Stop();
fprintf(stderr, "VM initialization failed: %s\n", error);
diff --git a/runtime/bin/platform_patch.dart b/runtime/bin/platform_patch.dart
index 577bbb6..bbd353b 100644
--- a/runtime/bin/platform_patch.dart
+++ b/runtime/bin/platform_patch.dart
@@ -2,33 +2,33 @@
// 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.
-patch class _Platform {
- /* patch */ static int _numberOfProcessors()
+@patch class _Platform {
+ /* @patch */ static int _numberOfProcessors()
native "Platform_NumberOfProcessors";
- /* patch */ static String _pathSeparator()
+ /* @patch */ static String _pathSeparator()
native "Platform_PathSeparator";
- /* patch */ static String _operatingSystem()
+ /* @patch */ static String _operatingSystem()
native "Platform_OperatingSystem";
- /* patch */ static _localHostname()
+ /* @patch */ static _localHostname()
native "Platform_LocalHostname";
- /* patch */ static _executable()
+ /* @patch */ static _executable()
native "Platform_ExecutableName";
- /* patch */ static _resolvedExecutable()
+ /* @patch */ static _resolvedExecutable()
native "Platform_ResolvedExecutableName";
- /* patch */ static _environment()
+ /* @patch */ static _environment()
native "Platform_Environment";
- /* patch */ static List<String> _executableArguments()
+ /* @patch */ static List<String> _executableArguments()
native "Platform_ExecutableArguments";
- /* patch */ static String _version()
+ /* @patch */ static String _version()
native "Platform_GetVersion";
- /* patch */ static String _packageRoot()
+ /* @patch */ static String _packageRoot()
=> VMLibraryHooks.packageRootString;
- /* patch */ static String _packageConfig()
+ /* @patch */ static String _packageConfig()
=> VMLibraryHooks.packageConfigString;
// This script singleton is written to by the embedder if applicable.
- /* patch */ static void set _nativeScript(String path) {
+ /* @patch */ static void set _nativeScript(String path) {
if (path.startsWith('http:') ||
path.startsWith('https:') ||
path.startsWith('package:') ||
diff --git a/runtime/bin/process_patch.dart b/runtime/bin/process_patch.dart
index 60fb2b5..2e3d2fb 100644
--- a/runtime/bin/process_patch.dart
+++ b/runtime/bin/process_patch.dart
@@ -2,20 +2,20 @@
// 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.
-patch class _WindowsCodePageDecoder {
- /* patch */ static String _decodeBytes(List<int> bytes)
+@patch class _WindowsCodePageDecoder {
+ /* @patch */ static String _decodeBytes(List<int> bytes)
native "SystemEncodingToString";
}
-patch class _WindowsCodePageEncoder {
- /* patch */ static List<int> _encodeString(String string)
+@patch class _WindowsCodePageEncoder {
+ /* @patch */ static List<int> _encodeString(String string)
native "StringToSystemEncoding";
}
-patch class Process {
- /* patch */ static Future<Process> start(
+@patch class Process {
+ /* @patch */ static Future<Process> start(
String executable,
List<String> arguments,
{String workingDirectory,
@@ -33,7 +33,7 @@
return process._start();
}
- /* patch */ static Future<ProcessResult> run(
+ /* @patch */ static Future<ProcessResult> run(
String executable,
List<String> arguments,
{String workingDirectory,
@@ -52,7 +52,7 @@
stderrEncoding);
}
- /* patch */ static ProcessResult runSync(
+ /* @patch */ static ProcessResult runSync(
String executable,
List<String> arguments,
{String workingDirectory,
@@ -71,7 +71,7 @@
stderrEncoding);
}
- /* patch */ static bool killPid(
+ /* @patch */ static bool killPid(
int pid, [ProcessSignal signal = ProcessSignal.SIGTERM]) {
if (signal is! ProcessSignal) {
throw new ArgumentError(
@@ -125,25 +125,25 @@
}
}
- /* patch */ static _setSignalHandler(int signal)
+ /* @patch */ static _setSignalHandler(int signal)
native "Process_SetSignalHandler";
- /* patch */ static int _clearSignalHandler(int signal)
+ /* @patch */ static int _clearSignalHandler(int signal)
native "Process_ClearSignalHandler";
}
Function _getWatchSignalInternal() => _ProcessUtils._watchSignalInternal;
-patch class _ProcessUtils {
- /* patch */ static void _exit(int status) native "Process_Exit";
- /* patch */ static void _setExitCode(int status)
+@patch class _ProcessUtils {
+ /* @patch */ static void _exit(int status) native "Process_Exit";
+ /* @patch */ static void _setExitCode(int status)
native "Process_SetExitCode";
- /* patch */ static int _getExitCode() native "Process_GetExitCode";
- /* patch */ static void _sleep(int millis) native "Process_Sleep";
- /* patch */ static int _pid(Process process) native "Process_Pid";
+ /* @patch */ static int _getExitCode() native "Process_GetExitCode";
+ /* @patch */ static void _sleep(int millis) native "Process_Sleep";
+ /* @patch */ static int _pid(Process process) native "Process_Pid";
static bool _killPid(int pid, int signal)
native "Process_KillPid";
- /* patch */ static Stream<ProcessSignal> _watchSignal(ProcessSignal signal) {
+ /* @patch */ static Stream<ProcessSignal> _watchSignal(ProcessSignal signal) {
if (signal != ProcessSignal.SIGHUP &&
signal != ProcessSignal.SIGINT &&
signal != ProcessSignal.SIGTERM &&
diff --git a/runtime/bin/run_vm_tests_fuchsia.cc b/runtime/bin/run_vm_tests_fuchsia.cc
index 43185ac..a7839a9 100644
--- a/runtime/bin/run_vm_tests_fuchsia.cc
+++ b/runtime/bin/run_vm_tests_fuchsia.cc
@@ -33,11 +33,11 @@
"Read",
"FileLength",
"FilePosition",
- // Hangs.
+ // Crash and then Hang.
"ArrayLengthMaxElements",
"Int8ListLengthMaxElements",
+ // Crashes in realloc.
"LargeMap",
- "CompileFunctionOnHelperThread",
// The profiler is turned off.
"Profiler_AllocationSampleTest",
"Profiler_ArrayAllocation",
diff --git a/runtime/bin/secure_socket_patch.dart b/runtime/bin/secure_socket_patch.dart
index c47c941..b3fde05 100644
--- a/runtime/bin/secure_socket_patch.dart
+++ b/runtime/bin/secure_socket_patch.dart
@@ -2,18 +2,18 @@
// 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.
-patch class SecureSocket {
- /* patch */ factory SecureSocket._(RawSecureSocket rawSocket) =>
+@patch class SecureSocket {
+ /* @patch */ factory SecureSocket._(RawSecureSocket rawSocket) =>
new _SecureSocket(rawSocket);
}
-patch class _SecureFilter {
- /* patch */ factory _SecureFilter() => new _SecureFilterImpl();
+@patch class _SecureFilter {
+ /* @patch */ factory _SecureFilter() => new _SecureFilterImpl();
}
-patch class X509Certificate {
- /* patch */ factory X509Certificate._() => new _X509CertificateImpl();
+@patch class X509Certificate {
+ /* @patch */ factory X509Certificate._() => new _X509CertificateImpl();
}
class _SecureSocket extends _Socket implements SecureSocket {
@@ -115,16 +115,16 @@
List<_ExternalBuffer> buffers;
}
-patch class SecurityContext {
- /* patch */ factory SecurityContext() {
+@patch class SecurityContext {
+ /* @patch */ factory SecurityContext() {
return new _SecurityContext();
}
- /* patch */ static SecurityContext get defaultContext {
+ /* @patch */ static SecurityContext get defaultContext {
return _SecurityContext.defaultContext;
}
- /* patch */ static bool get alpnSupported {
+ /* @patch */ static bool get alpnSupported {
return _SecurityContext.alpnSupported;
}
}
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index a8b60c3..e4bcb9f 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -2,8 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-patch class RawServerSocket {
- /* patch */ static Future<RawServerSocket> bind(address,
+@patch class RawServerSocket {
+ /* @patch */ static Future<RawServerSocket> bind(address,
int port,
{int backlog: 0,
bool v6Only: false,
@@ -13,52 +13,52 @@
}
-patch class RawSocket {
- /* patch */ static Future<RawSocket> connect(
+@patch class RawSocket {
+ /* @patch */ static Future<RawSocket> connect(
host, int port, {sourceAddress}) {
return _RawSocket.connect(host, port, sourceAddress);
}
}
-patch class InternetAddress {
- /* patch */ static InternetAddress get LOOPBACK_IP_V4 {
+@patch class InternetAddress {
+ /* @patch */ static InternetAddress get LOOPBACK_IP_V4 {
return _InternetAddress.LOOPBACK_IP_V4;
}
- /* patch */ static InternetAddress get LOOPBACK_IP_V6 {
+ /* @patch */ static InternetAddress get LOOPBACK_IP_V6 {
return _InternetAddress.LOOPBACK_IP_V6;
}
- /* patch */ static InternetAddress get ANY_IP_V4 {
+ /* @patch */ static InternetAddress get ANY_IP_V4 {
return _InternetAddress.ANY_IP_V4;
}
- /* patch */ static InternetAddress get ANY_IP_V6 {
+ /* @patch */ static InternetAddress get ANY_IP_V6 {
return _InternetAddress.ANY_IP_V6;
}
- /* patch */ factory InternetAddress(String address) {
+ /* @patch */ factory InternetAddress(String address) {
return new _InternetAddress.parse(address);
}
- /* patch */ static Future<List<InternetAddress>> lookup(
+ /* @patch */ static Future<List<InternetAddress>> lookup(
String host, {InternetAddressType type: InternetAddressType.ANY}) {
return _NativeSocket.lookup(host, type: type);
}
- /* patch */ static InternetAddress _cloneWithNewHost(
+ /* @patch */ static InternetAddress _cloneWithNewHost(
InternetAddress address, String host) {
return (address as _InternetAddress)._cloneWithNewHost(host);
}
}
-patch class NetworkInterface {
- /* patch */ static bool get listSupported {
+@patch class NetworkInterface {
+ /* @patch */ static bool get listSupported {
return _listSupported();
}
- /* patch */ static Future<List<NetworkInterface>> list({
+ /* @patch */ static Future<List<NetworkInterface>> list({
bool includeLoopback: false,
bool includeLinkLocal: false,
InternetAddressType type: InternetAddressType.ANY}) {
@@ -1095,7 +1095,7 @@
nativeGetOption(int option, int protocol) native "Socket_GetOption";
bool nativeSetOption(int option, int protocol, value)
native "Socket_SetOption";
- bool nativeJoinMulticast(
+ OSError nativeJoinMulticast(
List<int> addr, List<int> interfaceAddr, int interfaceIndex)
native "Socket_JoinMulticast";
bool nativeLeaveMulticast(
@@ -1360,8 +1360,8 @@
}
-patch class ServerSocket {
- /* patch */ static Future<ServerSocket> bind(address,
+@patch class ServerSocket {
+ /* @patch */ static Future<ServerSocket> bind(address,
int port,
{int backlog: 0,
bool v6Only: false,
@@ -1407,8 +1407,8 @@
}
-patch class Socket {
- /* patch */ static Future<Socket> connect(host, int port, {sourceAddress}) {
+@patch class Socket {
+ /* @patch */ static Future<Socket> connect(host, int port, {sourceAddress}) {
return RawSocket.connect(host, port, sourceAddress: sourceAddress).then(
(socket) => new _Socket(socket));
}
@@ -1720,8 +1720,8 @@
}
-patch class RawDatagramSocket {
- /* patch */ static Future<RawDatagramSocket> bind(
+@patch class RawDatagramSocket {
+ /* @patch */ static Future<RawDatagramSocket> bind(
host, int port, {bool reuseAddress: true}) {
return _RawDatagramSocket.bind(host, port, reuseAddress);
}
diff --git a/runtime/bin/stdio_patch.dart b/runtime/bin/stdio_patch.dart
index cf02819..3c258c5 100644
--- a/runtime/bin/stdio_patch.dart
+++ b/runtime/bin/stdio_patch.dart
@@ -2,7 +2,7 @@
// 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.
-patch class _StdIOUtils {
+@patch class _StdIOUtils {
static Stdin _getStdioInputStream() {
switch (_getStdioHandleType(0)) {
case _STDIO_HANDLE_TYPE_TERMINAL:
@@ -46,14 +46,14 @@
static _getStdioHandleType(int fd) native "File_GetStdioHandleType";
}
-patch class Stdin {
- /* patch */ int readByteSync() native "Stdin_ReadByte";
+@patch class Stdin {
+ /* @patch */ int readByteSync() native "Stdin_ReadByte";
- /* patch */ bool get echoMode => _echoMode;
- /* patch */ void set echoMode(bool enabled) { _echoMode = enabled; }
+ /* @patch */ bool get echoMode => _echoMode;
+ /* @patch */ void set echoMode(bool enabled) { _echoMode = enabled; }
- /* patch */ bool get lineMode => _lineMode;
- /* patch */ void set lineMode(bool enabled) { _lineMode = enabled; }
+ /* @patch */ bool get lineMode => _lineMode;
+ /* @patch */ void set lineMode(bool enabled) { _lineMode = enabled; }
static bool get _echoMode native "Stdin_GetEchoMode";
static void set _echoMode(bool enabled) native "Stdin_SetEchoMode";
@@ -61,8 +61,8 @@
static void set _lineMode(bool enabled) native "Stdin_SetLineMode";
}
-patch class Stdout {
- /* patch */ bool _hasTerminal(int fd) {
+@patch class Stdout {
+ /* @patch */ bool _hasTerminal(int fd) {
try {
_terminalSize(fd);
return true;
@@ -71,8 +71,8 @@
}
}
- /* patch */ int _terminalColumns(int fd) => _terminalSize(fd)[0];
- /* patch */ int _terminalLines(int fd) => _terminalSize(fd)[1];
+ /* @patch */ int _terminalColumns(int fd) => _terminalSize(fd)[0];
+ /* @patch */ int _terminalLines(int fd) => _terminalSize(fd)[1];
static List _terminalSize(int fd) {
var size = _getTerminalSize(fd);
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index 4e4c54a..4075e8d 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -157,12 +157,44 @@
return false;
}
- void _requestHandler(HttpRequest request) {
+ Future _requestHandler(HttpRequest request) async {
if (!_originCheck(request)) {
// This is a cross origin attempt to connect
request.response.close();
return;
}
+ if (request.method == 'PUT') {
+ // PUT requests are forwarded to DevFS for processing.
+
+ List fsNameList;
+ List fsPathList;
+ Object fsName;
+ Object fsPath;
+
+ try {
+ // Extract the fs name and fs path from the request headers.
+ fsNameList = request.headers['dev_fs_name'];
+ fsPathList = request.headers['dev_fs_path'];
+ fsName = fsNameList[0];
+ fsPath = fsPathList[0];
+ } catch (e) { /* ignore */ }
+
+ String result;
+ try {
+ result = await _service.devfs.handlePutStream(
+ fsName,
+ fsPath,
+ request.transform(GZIP.decoder));
+ } catch (e) { /* ignore */ }
+
+ if (result != null) {
+ request.response.headers.contentType =
+ HttpRequestClient.jsonContentType;
+ request.response.write(result);
+ }
+ request.response.close();
+ return;
+ }
if (request.method != 'GET') {
// Not a GET request. Do nothing.
request.response.close();
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/runtime/bin/vmservice/vmservice_io.dart
index 4e5ccab..49e8ad7 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/runtime/bin/vmservice/vmservice_io.dart
@@ -127,6 +127,15 @@
return WriteLimiter.scheduleWrite(path, bytes);
}
+Future writeStreamFileCallback(Uri path, Stream<List<int>> bytes) async {
+ var file = new File.fromUri(path);
+ var parent_directory = file.parent;
+ await parent_directory.create(recursive: true);
+ IOSink sink = await file.openWrite();
+ await sink.addStream(bytes);
+ await sink.close();
+}
+
Future<List<int>> readFileCallback(Uri path) async {
var file = new File.fromUri(path);
return await file.readAsBytes();
@@ -191,6 +200,7 @@
VMServiceEmbedderHooks.createTempDir = createTempDirCallback;
VMServiceEmbedderHooks.deleteDir = deleteDirCallback;
VMServiceEmbedderHooks.writeFile = writeFileCallback;
+ VMServiceEmbedderHooks.writeStreamFile = writeStreamFileCallback;
VMServiceEmbedderHooks.readFile = readFileCallback;
VMServiceEmbedderHooks.listFiles = listFilesCallback;
// Always instantiate the vmservice object so that the exit message
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 627e80f..3291dd0 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -784,41 +784,54 @@
typedef Dart_Handle (*Dart_GetVMServiceAssetsArchive)();
/**
- * Initializes the VM.
+ * The current version of the Dart_InitializeFlags. Should be incremented every
+ * time Dart_InitializeFlags changes in a binary incompatible way.
+ */
+#define DART_INITIALIZE_PARAMS_CURRENT_VERSION (0x00000001)
+
+/**
+ * Describes how to initialize the VM. Used with Dart_Initialize.
*
+ * \param version Identifies the version of the struct used by the client.
+ * should be initialized to DART_INITIALIZE_PARAMS_CURRENT_VERSION.
* \param vm_isolate_snapshot A buffer containing a snapshot of the VM isolate
* or NULL if no snapshot is provided.
* \param instructions_snapshot A buffer containing a snapshot of precompiled
* instructions, or NULL if no snapshot is provided.
* \param create A function to be called during isolate creation.
* See Dart_IsolateCreateCallback.
- * \param interrupt This parameter has been DEPRECATED.
- * \param unhandled_exception This parameter has been DEPRECATED.
* \param shutdown A function to be called when an isolate is shutdown.
* See Dart_IsolateShutdownCallback.
- *
* \param get_service_assets A function to be called by the service isolate when
* it requires the vmservice assets archive.
* See Dart_GetVMServiceAssetsArchive.
+ */
+typedef struct {
+ int32_t version;
+ const uint8_t* vm_isolate_snapshot;
+ const uint8_t* instructions_snapshot;
+ const uint8_t* data_snapshot;
+ Dart_IsolateCreateCallback create;
+ Dart_IsolateShutdownCallback shutdown;
+ Dart_ThreadExitCallback thread_exit;
+ Dart_FileOpenCallback file_open;
+ Dart_FileReadCallback file_read;
+ Dart_FileWriteCallback file_write;
+ Dart_FileCloseCallback file_close;
+ Dart_EntropySource entropy_source;
+ Dart_GetVMServiceAssetsArchive get_service_assets;
+} Dart_InitializeParams;
+
+/**
+ * Initializes the VM.
+ *
+ * \param flags A struct containing initialization information. The version
+ * field of the struct must be DART_INITIALIZE_PARAMS_CURRENT_VERSION.
*
* \return NULL if initialization is successful. Returns an error message
* otherwise. The caller is responsible for freeing the error message.
*/
-DART_EXPORT char* Dart_Initialize(
- const uint8_t* vm_isolate_snapshot,
- const uint8_t* instructions_snapshot,
- const uint8_t* data_snapshot,
- Dart_IsolateCreateCallback create,
- Dart_IsolateInterruptCallback interrupt,
- Dart_IsolateUnhandledExceptionCallback unhandled_exception,
- Dart_IsolateShutdownCallback shutdown,
- Dart_ThreadExitCallback thread_exit,
- Dart_FileOpenCallback file_open,
- Dart_FileReadCallback file_read,
- Dart_FileWriteCallback file_write,
- Dart_FileCloseCallback file_close,
- Dart_EntropySource entropy_source,
- Dart_GetVMServiceAssetsArchive get_service_assets);
+DART_EXPORT char* Dart_Initialize(Dart_InitializeParams* params);
/**
* Cleanup state in the VM before process termination.
@@ -1178,6 +1191,23 @@
/**
+ * Called when the embedder has caught a top level unhandled exception error
+ * in the current isolate. Also marks the isolate as paused at exit.
+ *
+ * NOTE: It is illegal to call this twice on the same isolate.
+ *
+ * \param error The unhandled exception error.
+ */
+DART_EXPORT void Dart_SetStickyError(Dart_Handle error);
+
+
+/**
+ * Does the current isolate have a sticky error?
+ */
+DART_EXPORT bool Dart_HasStickyError();
+
+
+/**
* Handles the next pending message for the current isolate.
*
* May generate an unhandled exception error.
diff --git a/runtime/lib/array_patch.dart b/runtime/lib/array_patch.dart
index 94f29f1..95eeaa8 100644
--- a/runtime/lib/array_patch.dart
+++ b/runtime/lib/array_patch.dart
@@ -10,8 +10,8 @@
const _GROWABLE_ARRAY_MARKER = const _GrowableArrayMarker();
-patch class List<E> {
- /* patch */ factory List([int length = _GROWABLE_ARRAY_MARKER]) {
+@patch class List<E> {
+ /* @patch */ factory List([int length = _GROWABLE_ARRAY_MARKER]) {
if (identical(length, _GROWABLE_ARRAY_MARKER)) {
return new _GrowableList<E>(0);
}
@@ -20,7 +20,7 @@
return new _List<E>(length);
}
- /* patch */ factory List.filled(int length, E fill, {bool growable: false}) {
+ /* @patch */ factory List.filled(int length, E fill, {bool growable: false}) {
// All error handling on the length parameter is done at the implementation
// of new _List.
var result = growable ? new _GrowableList<E>(length) : new _List<E>(length);
@@ -32,7 +32,7 @@
return result;
}
- /* patch */ factory List.from(Iterable elements, { bool growable: true }) {
+ /* @patch */ factory List.from(Iterable elements, { bool growable: true }) {
if (elements is EfficientLength) {
int length = elements.length;
var list = growable ? new _GrowableList<E>(length) : new _List<E>(length);
@@ -54,7 +54,7 @@
return makeListFixedLength(list);
}
- /* patch */ factory List.unmodifiable(Iterable elements) {
+ /* @patch */ factory List.unmodifiable(Iterable elements) {
List result = new List<E>.from(elements, growable: false);
return makeFixedListUnmodifiable(result);
}
diff --git a/runtime/lib/async_patch.dart b/runtime/lib/async_patch.dart
index 346e50d..c048ce8 100644
--- a/runtime/lib/async_patch.dart
+++ b/runtime/lib/async_patch.dart
@@ -188,4 +188,4 @@
}
}
-patch void _rethrow(Object error, StackTrace stackTrace) native "Async_rethrow";
+@patch void _rethrow(Object error, StackTrace stackTrace) native "Async_rethrow";
diff --git a/runtime/lib/bool_patch.dart b/runtime/lib/bool_patch.dart
index bbcbdb4..1a5eb6c 100644
--- a/runtime/lib/bool_patch.dart
+++ b/runtime/lib/bool_patch.dart
@@ -4,9 +4,9 @@
// Dart core library.
-patch class bool {
+@patch class bool {
- /* patch */ const factory bool.fromEnvironment(String name,
+ /* @patch */ const factory bool.fromEnvironment(String name,
{bool defaultValue: false})
native "Bool_fromEnvironment";
diff --git a/runtime/lib/collection_patch.dart b/runtime/lib/collection_patch.dart
index ccb4190..000e0bc 100644
--- a/runtime/lib/collection_patch.dart
+++ b/runtime/lib/collection_patch.dart
@@ -2,10 +2,10 @@
// 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.
-patch class HashMap<K, V> {
- /* patch */ factory HashMap({ bool equals(K key1, K key2),
- int hashCode(K key),
- bool isValidKey(potentialKey) }) {
+@patch class HashMap<K, V> {
+ /* @patch */ factory HashMap({ bool equals(K key1, K key2),
+ int hashCode(K key),
+ bool isValidKey(potentialKey) }) {
if (isValidKey == null) {
if (hashCode == null) {
if (equals == null) {
@@ -518,10 +518,10 @@
}
}
-patch class HashSet<E> {
- /* patch */ factory HashSet({ bool equals(E e1, E e2),
- int hashCode(E e),
- bool isValidKey(potentialKey) }) {
+@patch class HashSet<E> {
+ /* @patch */ factory HashSet({ bool equals(E e1, E e2),
+ int hashCode(E e),
+ bool isValidKey(potentialKey) }) {
if (isValidKey == null) {
if (hashCode == null) {
if (equals == null) {
@@ -548,7 +548,7 @@
return new _CustomHashSet<E>(equals, hashCode, isValidKey);
}
- /* patch */ factory HashSet.identity() = _IdentityHashSet<E>;
+ /* @patch */ factory HashSet.identity() = _IdentityHashSet<E>;
}
class _HashSet<E> extends _HashSetBase<E> implements HashSet<E> {
@@ -901,7 +901,7 @@
/**
* A hash-based map that iterates keys and values in key insertion order.
*/
-patch class LinkedHashMap<K, V> {
+@patch class LinkedHashMap<K, V> {
/// Holds a double-linked list of entries in insertion order.
/// The fields have the same name as the ones in [_LinkedHashMapEntry],
/// and this map is itself used as the head entry of the list.
@@ -910,9 +910,9 @@
var _nextEntry;
var _previousEntry;
- /* patch */ factory LinkedHashMap({ bool equals(K key1, K key2),
- int hashCode(K key),
- bool isValidKey(potentialKey) }) {
+ /* @patch */ factory LinkedHashMap({ bool equals(K key1, K key2),
+ int hashCode(K key),
+ bool isValidKey(potentialKey) }) {
if (isValidKey == null) {
if (hashCode == null) {
if (equals == null) {
@@ -939,14 +939,14 @@
return new _CompactLinkedCustomHashMap<K, V>(equals, hashCode, isValidKey);
}
- /* patch */ factory LinkedHashMap.identity() =
+ /* @patch */ factory LinkedHashMap.identity() =
_CompactLinkedIdentityHashMap<K, V>;
}
-patch class LinkedHashSet<E> {
- /* patch */ factory LinkedHashSet({ bool equals(E e1, E e2),
- int hashCode(E e),
- bool isValidKey(potentialKey) }) {
+@patch class LinkedHashSet<E> {
+ /* @patch */ factory LinkedHashSet({ bool equals(E e1, E e2),
+ int hashCode(E e),
+ bool isValidKey(potentialKey) }) {
if (isValidKey == null) {
if (hashCode == null) {
if (equals == null) {
@@ -973,6 +973,6 @@
return new _CompactLinkedCustomHashSet<E>(equals, hashCode, isValidKey);
}
- /* patch */ factory LinkedHashSet.identity() =
+ /* @patch */ factory LinkedHashSet.identity() =
_CompactLinkedIdentityHashSet<E>;
}
diff --git a/runtime/lib/convert_patch.dart b/runtime/lib/convert_patch.dart
index d4acc18a..6bf0a2c 100644
--- a/runtime/lib/convert_patch.dart
+++ b/runtime/lib/convert_patch.dart
@@ -6,7 +6,7 @@
// JSON conversion.
-patch _parseJson(String json, reviver(var key, var value)) {
+@patch _parseJson(String json, reviver(var key, var value)) {
_BuildJsonListener listener;
if (reviver == null) {
listener = new _BuildJsonListener();
@@ -21,8 +21,8 @@
return listener.result;
}
-patch class Utf8Decoder {
- /* patch */
+@patch class Utf8Decoder {
+ /* @patch */
Converter<List<int>, dynamic/*=T*/> fuse/*<T>*/(
Converter<String, dynamic/*=T*/> next) {
if (next is JsonDecoder) {
@@ -34,7 +34,7 @@
}
// Allow intercepting of UTF-8 decoding when built-in lists are passed.
- /* patch */
+ /* @patch */
static String _convertIntercepted(
bool allowMalformed, List<int> codeUnits, int start, int end) {
return null; // This call was not intercepted.
@@ -1376,8 +1376,8 @@
}
}
-patch class JsonDecoder {
- /* patch */ StringConversionSink startChunkedConversion(Sink<Object> sink) {
+@patch class JsonDecoder {
+ /* @patch */ StringConversionSink startChunkedConversion(Sink<Object> sink) {
return new _JsonStringDecoderSink(this._reviver, sink);
}
}
diff --git a/runtime/lib/core_patch.dart b/runtime/lib/core_patch.dart
index 6c792d2..5fd883e 100644
--- a/runtime/lib/core_patch.dart
+++ b/runtime/lib/core_patch.dart
@@ -75,6 +75,6 @@
}
}
-patch class StackTrace {
- /* patch */ static StackTrace get current native "StackTrace_current";
+@patch class StackTrace {
+ /* @patch */ static StackTrace get current native "StackTrace_current";
}
diff --git a/runtime/lib/date_patch.dart b/runtime/lib/date_patch.dart
index 1ecf812..0f7837e 100644
--- a/runtime/lib/date_patch.dart
+++ b/runtime/lib/date_patch.dart
@@ -4,7 +4,7 @@
// Dart core library.
// VM implementation of DateTime.
-patch class DateTime {
+@patch class DateTime {
// Natives.
// The natives have been moved up here to work around Issue 10401.
static int _getCurrentMicros() native "DateTime_currentTimeMicros";
@@ -30,17 +30,17 @@
List __parts;
- /* patch */ DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
+ /* @patch */ DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
{bool isUtc: false})
: this._withValue(
millisecondsSinceEpoch * Duration.MICROSECONDS_PER_MILLISECOND,
isUtc: isUtc);
- /* patch */ DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
+ /* @patch */ DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
{bool isUtc: false})
: this._withValue(microsecondsSinceEpoch, isUtc: isUtc);
- /* patch */ DateTime._internal(int year,
+ /* @patch */ DateTime._internal(int year,
int month,
int day,
int hour,
@@ -57,17 +57,17 @@
if (isUtc == null) throw new ArgumentError();
}
- /* patch */ DateTime._now()
+ /* @patch */ DateTime._now()
: isUtc = false,
_value = _getCurrentMicros() {
}
- /* patch */ String get timeZoneName {
+ /* @patch */ String get timeZoneName {
if (isUtc) return "UTC";
return _timeZoneName(microsecondsSinceEpoch);
}
- /* patch */ Duration get timeZoneOffset {
+ /* @patch */ Duration get timeZoneOffset {
if (isUtc) return new Duration();
int offsetInSeconds = _timeZoneOffsetInSeconds(microsecondsSinceEpoch);
return new Duration(seconds: offsetInSeconds);
@@ -165,42 +165,42 @@
return __parts;
}
- /* patch */ DateTime add(Duration duration) {
+ /* @patch */ DateTime add(Duration duration) {
return new DateTime._withValue(
_value + duration.inMicroseconds, isUtc: isUtc);
}
- /* patch */ DateTime subtract(Duration duration) {
+ /* @patch */ DateTime subtract(Duration duration) {
return new DateTime._withValue(
_value - duration.inMicroseconds, isUtc: isUtc);
}
- /* patch */ Duration difference(DateTime other) {
+ /* @patch */ Duration difference(DateTime other) {
return new Duration(microseconds: _value - other._value);
}
- /* patch */ int get millisecondsSinceEpoch =>
+ /* @patch */ int get millisecondsSinceEpoch =>
_value ~/ Duration.MICROSECONDS_PER_MILLISECOND;
- /* patch */ int get microsecondsSinceEpoch => _value;
+ /* @patch */ int get microsecondsSinceEpoch => _value;
- /* patch */ int get microsecond => _parts[_MICROSECOND_INDEX];
+ /* @patch */ int get microsecond => _parts[_MICROSECOND_INDEX];
- /* patch */ int get millisecond => _parts[_MILLISECOND_INDEX];
+ /* @patch */ int get millisecond => _parts[_MILLISECOND_INDEX];
- /* patch */ int get second => _parts[_SECOND_INDEX];
+ /* @patch */ int get second => _parts[_SECOND_INDEX];
- /* patch */ int get minute => _parts[_MINUTE_INDEX];
+ /* @patch */ int get minute => _parts[_MINUTE_INDEX];
- /* patch */ int get hour => _parts[_HOUR_INDEX];
+ /* @patch */ int get hour => _parts[_HOUR_INDEX];
- /* patch */ int get day => _parts[_DAY_INDEX];
+ /* @patch */ int get day => _parts[_DAY_INDEX];
- /* patch */ int get weekday => _parts[_WEEKDAY_INDEX];
+ /* @patch */ int get weekday => _parts[_WEEKDAY_INDEX];
- /* patch */ int get month => _parts[_MONTH_INDEX];
+ /* @patch */ int get month => _parts[_MONTH_INDEX];
- /* patch */ int get year => _parts[_YEAR_INDEX];
+ /* @patch */ int get year => _parts[_YEAR_INDEX];
/**
* Returns the amount of microseconds in UTC that represent the same values
@@ -244,7 +244,7 @@
}
/// Converts the given broken down date to microseconds.
- /* patch */ static int _brokenDownDateToValue(
+ /* @patch */ static int _brokenDownDateToValue(
int year, int month, int day,
int hour, int minute, int second, int millisecond, int microsecond,
bool isUtc) {
diff --git a/runtime/lib/deferred_load_patch.dart b/runtime/lib/deferred_load_patch.dart
index 800fdef..32f233b 100644
--- a/runtime/lib/deferred_load_patch.dart
+++ b/runtime/lib/deferred_load_patch.dart
@@ -4,8 +4,8 @@
final Set<String> _loadedLibraries = new Set<String>();
-patch class DeferredLibrary {
- /* patch */ Future<Null> load() {
+@patch class DeferredLibrary {
+ /* @patch */ Future<Null> load() {
// Dummy implementation that should eventually be replaced by real
// implementation.
Future future =
diff --git a/runtime/lib/developer.dart b/runtime/lib/developer.dart
index f7b45f0..ec3d38b 100644
--- a/runtime/lib/developer.dart
+++ b/runtime/lib/developer.dart
@@ -4,19 +4,19 @@
import 'dart:isolate';
-patch bool debugger({bool when: true,
+@patch bool debugger({bool when: true,
String message}) native "Developer_debugger";
-patch Object inspect(Object object) native "Developer_inspect";
+@patch Object inspect(Object object) native "Developer_inspect";
-patch void log(String message,
- {DateTime time,
- int sequenceNumber,
- int level: 0,
- String name: '',
- Zone zone,
- Object error,
- StackTrace stackTrace}) {
+@patch void log(String message,
+ {DateTime time,
+ int sequenceNumber,
+ int level: 0,
+ String name: '',
+ Zone zone,
+ Object error,
+ StackTrace stackTrace}) {
if (message is! String) {
throw new ArgumentError(message, "message", "Must be a String");
}
@@ -52,13 +52,13 @@
Object error,
StackTrace stackTrace) native "Developer_log";
-patch void _postEvent(String eventKind, String eventData)
+@patch void _postEvent(String eventKind, String eventData)
native "Developer_postEvent";
-patch ServiceExtensionHandler _lookupExtension(String method)
+@patch ServiceExtensionHandler _lookupExtension(String method)
native "Developer_lookupExtension";
-patch _registerExtension(String method, ServiceExtensionHandler handler)
+@patch _registerExtension(String method, ServiceExtensionHandler handler)
native "Developer_registerExtension";
// This code is only invoked when there is no other Dart code on the stack.
diff --git a/runtime/lib/double_patch.dart b/runtime/lib/double_patch.dart
index f33122a..cc3c605 100644
--- a/runtime/lib/double_patch.dart
+++ b/runtime/lib/double_patch.dart
@@ -5,7 +5,7 @@
// VM implementation of double.
-patch class double {
+@patch class double {
static double _nativeParse(String str,
int start, int end) native "Double_parse";
@@ -101,8 +101,8 @@
return _nativeParse(str, start, end);
}
- /* patch */ static double parse(String str,
- [double onError(String str)]) {
+ /* @patch */ static double parse(String str,
+ [double onError(String str)]) {
var result = _parse(str);
if (result == null) {
if (onError == null) throw new FormatException("Invalid double", str);
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index faf342b..2deb7f9 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -5,16 +5,16 @@
import 'dart:_internal' as internal;
import 'dart:convert' show JSON;
-patch class Error {
- /* patch */ static String _objectToString(Object object) {
+@patch class Error {
+ /* @patch */ static String _objectToString(Object object) {
return Object._toString(object);
}
- /* patch */ static String _stringToSafeString(String string) {
+ /* @patch */ static String _stringToSafeString(String string) {
return JSON.encode(string);
}
- /* patch */ StackTrace get stackTrace => _stackTrace;
+ /* @patch */ StackTrace get stackTrace => _stackTrace;
StackTrace _stackTrace;
}
@@ -95,12 +95,12 @@
final String _errorMsg;
}
-patch class FallThroughError {
+@patch class FallThroughError {
FallThroughError._create(this._url, this._line);
static _throwNew(int case_clause_pos) native "FallThroughError_throwNew";
- /* patch */ String toString() {
+ /* @patch */ String toString() {
return "'$_url': Switch case fall-through at line $_line.";
}
@@ -116,26 +116,26 @@
final String _msg;
}
-patch class UnsupportedError {
+@patch class UnsupportedError {
static _throwNew(String msg) {
throw new UnsupportedError(msg);
}
}
-patch class CyclicInitializationError {
+@patch class CyclicInitializationError {
static _throwNew(String variableName) {
throw new CyclicInitializationError(variableName);
}
}
-patch class AbstractClassInstantiationError {
+@patch class AbstractClassInstantiationError {
AbstractClassInstantiationError._create(
this._className, this._url, this._line);
static _throwNew(int case_clause_pos, String className)
native "AbstractClassInstantiationError_throwNew";
- /* patch */ String toString() {
+ /* @patch */ String toString() {
return "Cannot instantiate abstract class $_className: "
"_url '$_url' line $_line";
}
@@ -146,7 +146,7 @@
int _line;
}
-patch class NoSuchMethodError {
+@patch class NoSuchMethodError {
// The compiler emits a call to _throwNew when it cannot resolve a static
// method at compile time. The receiver is actually the literal class of the
// unresolved method.
@@ -284,7 +284,7 @@
return "$msg\n\n";
}
- /* patch */ String toString() {
+ /* @patch */ String toString() {
StringBuffer actual_buf = new StringBuffer();
int i = 0;
if (_arguments == null) {
diff --git a/runtime/lib/expando_patch.dart b/runtime/lib/expando_patch.dart
index df0234d..abdefab 100644
--- a/runtime/lib/expando_patch.dart
+++ b/runtime/lib/expando_patch.dart
@@ -2,15 +2,15 @@
// 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.
-patch class Expando<T> {
- /* patch */ Expando([String this.name])
+@patch class Expando<T> {
+ /* @patch */ Expando([String this.name])
: _data = new List(_minSize),
_used = 0;
static const _minSize = 8;
static final _deletedEntry = new _WeakProperty(null, null);
- /* patch */ T operator[](Object object) {
+ /* @patch */ T operator[](Object object) {
_checkType(object);
var mask = _size - 1;
@@ -31,7 +31,7 @@
return null;
}
- /* patch */ void operator[]=(Object object, T value) {
+ /* @patch */ void operator[]=(Object object, T value) {
_checkType(object);
var mask = _size - 1;
diff --git a/runtime/lib/function_patch.dart b/runtime/lib/function_patch.dart
index c94c78b..7ed74c8 100644
--- a/runtime/lib/function_patch.dart
+++ b/runtime/lib/function_patch.dart
@@ -2,13 +2,13 @@
// 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.
-patch class Function {
+@patch class Function {
static _apply(List arguments, List names)
native "Function_apply";
- /* patch */ static apply(Function function,
- List positionalArguments,
- [Map<Symbol, dynamic> namedArguments]) {
+ /* @patch */ static apply(Function function,
+ List positionalArguments,
+ [Map<Symbol, dynamic> namedArguments]) {
int numPositionalArguments = 1 + // Function is first implicit argument.
(positionalArguments != null ? positionalArguments.length : 0);
int numNamedArguments = namedArguments != null ? namedArguments.length : 0;
diff --git a/runtime/lib/identical_patch.dart b/runtime/lib/identical_patch.dart
index 172478f..6aaa1fc 100644
--- a/runtime/lib/identical_patch.dart
+++ b/runtime/lib/identical_patch.dart
@@ -2,6 +2,6 @@
// 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.
-patch bool identical(Object a, Object b) native "Identical_comparison";
+@patch bool identical(Object a, Object b) native "Identical_comparison";
-patch int identityHashCode(Object object) => object._identityHashCode;
+@patch int identityHashCode(Object object) => object._identityHashCode;
diff --git a/runtime/lib/integers_patch.dart b/runtime/lib/integers_patch.dart
index 19cc787..6aa072b 100644
--- a/runtime/lib/integers_patch.dart
+++ b/runtime/lib/integers_patch.dart
@@ -7,9 +7,9 @@
import 'dart:_internal' as internal;
-patch class int {
+@patch class int {
- /* patch */ const factory int.fromEnvironment(String name,
+ /* @patch */ const factory int.fromEnvironment(String name,
{int defaultValue})
native "Integer_fromEnvironment";
@@ -42,7 +42,7 @@
return sign * result;
}
- /* patch */ static int parse(String source,
+ /* @patch */ static int parse(String source,
{ int radix,
int onError(String str) }) {
if (source == null) throw new ArgumentError("The source must not be null");
diff --git a/runtime/lib/internal_patch.dart b/runtime/lib/internal_patch.dart
index 3089830..24f31de 100644
--- a/runtime/lib/internal_patch.dart
+++ b/runtime/lib/internal_patch.dart
@@ -2,10 +2,10 @@
// 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.
-patch List makeListFixedLength(List growableList)
+@patch List makeListFixedLength(List growableList)
native "Internal_makeListFixedLength";
-patch List makeFixedListUnmodifiable(List fixedLengthList)
+@patch List makeFixedListUnmodifiable(List fixedLengthList)
native "Internal_makeFixedListUnmodifiable";
class VMLibraryHooks {
@@ -32,7 +32,7 @@
static var platformScript;
}
-patch class CodeUnits {
+@patch class CodeUnits {
static final int cid = ClassID.getID(new CodeUnits(""));
}
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index 4dd89c0..6ea2ef5 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -5,15 +5,15 @@
import "dart:collection" show HashMap;
import "dart:_internal";
-patch class ReceivePort {
- /* patch */ factory ReceivePort() = _ReceivePortImpl;
+@patch class ReceivePort {
+ /* @patch */ factory ReceivePort() = _ReceivePortImpl;
- /* patch */ factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) =
+ /* @patch */ factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) =
_ReceivePortImpl.fromRawReceivePort;
}
-patch class Capability {
- /* patch */ factory Capability() = _CapabilityImpl;
+@patch class Capability {
+ /* @patch */ factory Capability() = _CapabilityImpl;
}
class _CapabilityImpl implements Capability {
@@ -31,7 +31,7 @@
_get_hashcode() native "CapabilityImpl_get_hashcode";
}
-patch class RawReceivePort {
+@patch class RawReceivePort {
/**
* Opens a long-lived port for receiving messages.
*
@@ -39,7 +39,7 @@
* can not be paused. The data-handler must be set before the first
* event is received.
*/
- /* patch */ factory RawReceivePort([void handler(event)]) {
+ /* @patch */ factory RawReceivePort([void handler(event)]) {
_RawReceivePortImpl result = new _RawReceivePortImpl();
result.handler = handler;
return result;
@@ -268,13 +268,13 @@
port.sendPort.send(null);
}
-patch class Isolate {
+@patch class Isolate {
static final _currentIsolate = _getCurrentIsolate();
static final _rootUri = _getCurrentRootUri();
- /* patch */ static Isolate get current => _currentIsolate;
+ /* @patch */ static Isolate get current => _currentIsolate;
- /* patch */ static Future<Uri> get packageRoot {
+ /* @patch */ static Future<Uri> get packageRoot {
var hook = VMLibraryHooks.packageRootUriFuture;
if (hook == null) {
throw new UnsupportedError("Isolate.packageRoot");
@@ -282,7 +282,7 @@
return hook();
}
- /* patch */ static Future<Uri> get packageConfig {
+ /* @patch */ static Future<Uri> get packageConfig {
var hook = VMLibraryHooks.packageConfigUriFuture;
if (hook == null) {
throw new UnsupportedError("Isolate.packageConfig");
@@ -290,7 +290,7 @@
return hook();
}
- /* patch */ static Future<Uri> resolvePackageUri(Uri packageUri) {
+ /* @patch */ static Future<Uri> resolvePackageUri(Uri packageUri) {
var hook = VMLibraryHooks.resolvePackageUriFuture;
if (hook == null) {
throw new UnsupportedError("Isolate.resolvePackageUri");
@@ -303,7 +303,7 @@
(VMLibraryHooks.packageConfigUriFuture != null) &&
(VMLibraryHooks.resolvePackageUriFuture != null);
- /* patch */ static Future<Isolate> spawn(
+ /* @patch */ static Future<Isolate> spawn(
void entryPoint(message), var message,
{bool paused: false, bool errorsAreFatal,
SendPort onExit, SendPort onError}) async {
@@ -340,7 +340,7 @@
}
}
- /* patch */ static Future<Isolate> spawnUri(
+ /* @patch */ static Future<Isolate> spawnUri(
Uri uri, List<String> args, var message,
{bool paused: false,
SendPort onExit,
@@ -478,7 +478,7 @@
static void _sendOOB(port, msg) native "Isolate_sendOOB";
- /* patch */ void _pause(Capability resumeCapability) {
+ /* @patch */ void _pause(Capability resumeCapability) {
var msg = new List(4)
..[0] = 0 // Make room for OOB message type.
..[1] = _PAUSE
@@ -487,7 +487,7 @@
_sendOOB(controlPort, msg);
}
- /* patch */ void resume(Capability resumeCapability) {
+ /* @patch */ void resume(Capability resumeCapability) {
var msg = new List(4)
..[0] = 0 // Make room for OOB message type.
..[1] = _RESUME
@@ -496,7 +496,7 @@
_sendOOB(controlPort, msg);
}
- /* patch */ void addOnExitListener(SendPort responsePort,
+ /* @patch */ void addOnExitListener(SendPort responsePort,
{Object response}) {
var msg = new List(4)
..[0] = 0 // Make room for OOB message type.
@@ -506,7 +506,7 @@
_sendOOB(controlPort, msg);
}
- /* patch */ void removeOnExitListener(SendPort responsePort) {
+ /* @patch */ void removeOnExitListener(SendPort responsePort) {
var msg = new List(3)
..[0] = 0 // Make room for OOB message type.
..[1] = _DEL_EXIT
@@ -514,7 +514,7 @@
_sendOOB(controlPort, msg);
}
- /* patch */ void setErrorsFatal(bool errorsAreFatal) {
+ /* @patch */ void setErrorsFatal(bool errorsAreFatal) {
var msg = new List(4)
..[0] = 0 // Make room for OOB message type.
..[1] = _ERROR_FATAL
@@ -523,7 +523,7 @@
_sendOOB(controlPort, msg);
}
- /* patch */ void kill({int priority: BEFORE_NEXT_EVENT}) {
+ /* @patch */ void kill({int priority: BEFORE_NEXT_EVENT}) {
var msg = new List(4)
..[0] = 0 // Make room for OOB message type.
..[1] = _KILL
@@ -532,7 +532,7 @@
_sendOOB(controlPort, msg);
}
- /* patch */ void ping(SendPort responsePort, {Object response,
+ /* @patch */ void ping(SendPort responsePort, {Object response,
int priority: IMMEDIATE}) {
var msg = new List(5)
..[0] = 0 // Make room for OOM message type.
@@ -543,7 +543,7 @@
_sendOOB(controlPort, msg);
}
- /* patch */ void addErrorListener(SendPort port) {
+ /* @patch */ void addErrorListener(SendPort port) {
var msg = new List(3)
..[0] = 0 // Make room for OOB message type.
..[1] = _ADD_ERROR
@@ -551,7 +551,7 @@
_sendOOB(controlPort, msg);
}
- /* patch */ void removeErrorListener(SendPort port) {
+ /* @patch */ void removeErrorListener(SendPort port) {
var msg = new List(3)
..[0] = 0 // Make room for OOB message type.
..[1] = _DEL_ERROR
diff --git a/runtime/lib/map_patch.dart b/runtime/lib/map_patch.dart
index 8a8359a..333f62a 100644
--- a/runtime/lib/map_patch.dart
+++ b/runtime/lib/map_patch.dart
@@ -2,7 +2,7 @@
// 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.
-patch class Map<K, V> {
+@patch class Map<K, V> {
// Factory constructing a Map from a parser generated Map literal.
// [elements] contains n key-value pairs.
// The keys are at position 2*n and are already type checked by the parser
@@ -17,9 +17,9 @@
return map;
}
- /* patch */ factory Map.unmodifiable(Map other) {
+ /* @patch */ factory Map.unmodifiable(Map other) {
return new UnmodifiableMapView<K, V>(new Map.from(other));
}
- /* patch */ factory Map() = LinkedHashMap<K, V>;
+ /* @patch */ factory Map() = LinkedHashMap<K, V>;
}
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index 4f0b852..5cf80c9 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.dart
@@ -8,7 +8,7 @@
// If [x] is an [int] and [exponent] is a non-negative [int], the result is
// an [int], otherwise the result is a [double].
-patch num pow(num x, num exponent) {
+@patch num pow(num x, num exponent) {
if ((x is int) && (exponent is int) && (exponent >= 0)) {
return _intPow(x, exponent);
}
@@ -23,7 +23,7 @@
if (exponent == 1.0) return base;
if (exponent == 2.0) return base * base;
if (exponent == 3.0) return base * base * base;
-
+
if (base == 1.0) return 1.0;
if (base.isNaN || exponent.isNaN) {
@@ -56,16 +56,16 @@
return result;
}
-patch double atan2(num a, num b) => _atan2(a.toDouble(), b.toDouble());
-patch double sin(num value) => _sin(value.toDouble());
-patch double cos(num value) => _cos(value.toDouble());
-patch double tan(num value) => _tan(value.toDouble());
-patch double acos(num value) => _acos(value.toDouble());
-patch double asin(num value) => _asin(value.toDouble());
-patch double atan(num value) => _atan(value.toDouble());
-patch double sqrt(num value) => _sqrt(value.toDouble());
-patch double exp(num value) => _exp(value.toDouble());
-patch double log(num value) => _log(value.toDouble());
+@patch double atan2(num a, num b) => _atan2(a.toDouble(), b.toDouble());
+@patch double sin(num value) => _sin(value.toDouble());
+@patch double cos(num value) => _cos(value.toDouble());
+@patch double tan(num value) => _tan(value.toDouble());
+@patch double acos(num value) => _acos(value.toDouble());
+@patch double asin(num value) => _asin(value.toDouble());
+@patch double atan(num value) => _atan(value.toDouble());
+@patch double sqrt(num value) => _sqrt(value.toDouble());
+@patch double exp(num value) => _exp(value.toDouble());
+@patch double log(num value) => _log(value.toDouble());
double _atan2(double a, double b) native "Math_atan2";
double _sin(double x) native "Math_sin";
@@ -80,9 +80,9 @@
// TODO(iposva): Handle patch methods within a patch class correctly.
-patch class Random {
+@patch class Random {
- /*patch*/ factory Random([int seed]) {
+ /*@patch*/ factory Random([int seed]) {
var state = _Random._setupSeed((seed == null) ? _Random._nextSeed() : seed);
// Crank a couple of times to distribute the seed bits a bit further.
return new _Random._withState(state).._nextState()
@@ -91,7 +91,7 @@
.._nextState();
}
- /*patch*/ factory Random.secure() {
+ /*@patch*/ factory Random.secure() {
return new _SecureRandom();
}
}
diff --git a/runtime/lib/mirrors_patch.dart b/runtime/lib/mirrors_patch.dart
index e80dd47..d66ce82 100644
--- a/runtime/lib/mirrors_patch.dart
+++ b/runtime/lib/mirrors_patch.dart
@@ -7,7 +7,7 @@
/**
* Returns a [MirrorSystem] for the current isolate.
*/
-patch MirrorSystem currentMirrorSystem() {
+@patch MirrorSystem currentMirrorSystem() {
return _Mirrors.currentMirrorSystem();
}
@@ -17,7 +17,7 @@
* This only works if this mirror system is associated with the
* current running isolate.
*/
-patch InstanceMirror reflect(Object reflectee) {
+@patch InstanceMirror reflect(Object reflectee) {
return _Mirrors.reflect(reflectee);
}
@@ -27,16 +27,16 @@
*
* This only works with objects local to the current isolate.
*/
-patch ClassMirror reflectClass(Type key) {
+@patch ClassMirror reflectClass(Type key) {
return _Mirrors.reflectClass(key);
}
-patch TypeMirror reflectType(Type key) {
+@patch TypeMirror reflectType(Type key) {
return _Mirrors.reflectType(key);
}
-patch class MirrorSystem {
- /* patch */ LibraryMirror findLibrary(Symbol libraryName) {
+@patch class MirrorSystem {
+ /* @patch */ LibraryMirror findLibrary(Symbol libraryName) {
var candidates =
libraries.values.where((lib) => lib.simpleName == libraryName);
if (candidates.length == 1) {
@@ -50,11 +50,11 @@
throw new Exception("There is no library named '${getName(libraryName)}'");
}
- /* patch */ static String getName(Symbol symbol) {
+ /* @patch */ static String getName(Symbol symbol) {
return internal.Symbol.getUnmangledName(symbol);
}
- /* patch */ static Symbol getSymbol(String name, [LibraryMirror library]) {
+ /* @patch */ static Symbol getSymbol(String name, [LibraryMirror library]) {
if ((library != null && library is! _LocalLibraryMirror) ||
((name.length > 0) && (name[0] == '_') && (library == null))) {
throw new ArgumentError(library);
diff --git a/runtime/lib/null_patch.dart b/runtime/lib/null_patch.dart
index 047039b..312804e 100644
--- a/runtime/lib/null_patch.dart
+++ b/runtime/lib/null_patch.dart
@@ -4,7 +4,7 @@
// Dart core library.
-patch class Null {
+@patch class Null {
factory Null._uninstantiable() {
throw new UnsupportedError("class Null cannot be instantiated");
diff --git a/runtime/lib/object_patch.dart b/runtime/lib/object_patch.dart
index 719e592..7de335b 100644
--- a/runtime/lib/object_patch.dart
+++ b/runtime/lib/object_patch.dart
@@ -2,7 +2,7 @@
// 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.
-patch class Object {
+@patch class Object {
// The VM has its own implementation of equals.
bool operator ==(other) native "Object_equals";
@@ -29,10 +29,10 @@
return result;
}
- /* patch */ int get hashCode => _objectHashCode(this);
+ /* @patch */ int get hashCode => _objectHashCode(this);
int get _identityHashCode => _objectHashCode(this);
- /* patch */ String toString() native "Object_toString";
+ /* @patch */ String toString() native "Object_toString";
// A statically dispatched version of Object.toString.
static String _toString(obj) native "Object_toString";
@@ -43,7 +43,7 @@
Map<String, dynamic> namedArguments)
native "Object_noSuchMethod";
- /* patch */ noSuchMethod(Invocation invocation) {
+ /* @patch */ noSuchMethod(Invocation invocation) {
return _noSuchMethod(invocation.isMethod,
internal.Symbol.getName(invocation.memberName),
invocation._type,
@@ -51,7 +51,7 @@
_symbolMapToStringMap(invocation.namedArguments));
}
- /* patch */ Type get runtimeType native "Object_runtimeType";
+ /* @patch */ Type get runtimeType native "Object_runtimeType";
// Call this function instead of inlining instanceof, thus collecting
// type feedback and reducing code size of unoptimized code.
@@ -62,7 +62,7 @@
bool _simpleInstanceOf(type) native "Object_simpleInstanceOf";
bool _simpleInstanceOfTrue(type) => true;
bool _simpleInstanceOfFalse(type) => false;
-
+
bool _instanceOfDouble(bool negate) native "Object_instanceOfDouble";
bool _instanceOfNum(bool negate) native "Object_instanceOfNum";
bool _instanceOfInt(bool negate) native "Object_instanceOfInt";
diff --git a/runtime/lib/print_patch.dart b/runtime/lib/print_patch.dart
index 539294a..3df38d1 100644
--- a/runtime/lib/print_patch.dart
+++ b/runtime/lib/print_patch.dart
@@ -6,7 +6,7 @@
// string is a line, but it may contain "\n" characters.
typedef void _PrintClosure(String line);
-patch void printToConsole(String line) {
+@patch void printToConsole(String line) {
_printClosure(line);
}
diff --git a/runtime/lib/profiler.dart b/runtime/lib/profiler.dart
index 94d11ef..9b4ce97 100644
--- a/runtime/lib/profiler.dart
+++ b/runtime/lib/profiler.dart
@@ -4,11 +4,11 @@
import 'dart:_internal';
-patch class UserTag {
- /* patch */ factory UserTag(String label) {
+@patch class UserTag {
+ /* @patch */ factory UserTag(String label) {
return new _UserTag(label);
}
- /* patch */ static UserTag get defaultTag => _getDefaultTag();
+ /* @patch */ static UserTag get defaultTag => _getDefaultTag();
}
@@ -18,7 +18,7 @@
UserTag makeCurrent() native "UserTag_makeCurrent";
}
-patch UserTag getCurrentTag() => _getCurrentTag();
+@patch UserTag getCurrentTag() => _getCurrentTag();
UserTag _getCurrentTag() native "Profiler_getCurrentTag";
UserTag _getDefaultTag() native "UserTag_defaultTag";
diff --git a/runtime/lib/regexp_patch.dart b/runtime/lib/regexp_patch.dart
index d8e622a..9b23430 100644
--- a/runtime/lib/regexp_patch.dart
+++ b/runtime/lib/regexp_patch.dart
@@ -4,10 +4,10 @@
import "dart:collection" show LinkedList, LinkedListEntry;
-patch class RegExp {
- /* patch */ factory RegExp(String source,
- {bool multiLine: false,
- bool caseSensitive: true}) {
+@patch class RegExp {
+ /* @patch */ factory RegExp(String source,
+ {bool multiLine: false,
+ bool caseSensitive: true}) {
_RegExpHashKey key = new _RegExpHashKey(
source, multiLine, caseSensitive);
_RegExpHashValue value = _cache[key];
diff --git a/runtime/lib/resource_patch.dart b/runtime/lib/resource_patch.dart
index 0643516..e0db212 100644
--- a/runtime/lib/resource_patch.dart
+++ b/runtime/lib/resource_patch.dart
@@ -2,8 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-patch class Resource {
- /* patch */ const factory Resource(String uri) = _Resource;
+@patch class Resource {
+ /* @patch */ const factory Resource(String uri) = _Resource;
}
class _Resource implements Resource {
diff --git a/runtime/lib/schedule_microtask_patch.dart b/runtime/lib/schedule_microtask_patch.dart
index f08de2b..9384c1e 100644
--- a/runtime/lib/schedule_microtask_patch.dart
+++ b/runtime/lib/schedule_microtask_patch.dart
@@ -2,8 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-patch class _AsyncRun {
- /* patch */ static void _scheduleImmediate(void callback()) {
+@patch class _AsyncRun {
+ /* @patch */ static void _scheduleImmediate(void callback()) {
if (_ScheduleImmediate._closure == null) {
throw new UnsupportedError("Microtasks are not supported");
}
diff --git a/runtime/lib/stopwatch_patch.dart b/runtime/lib/stopwatch_patch.dart
index e16005c..e3749e8 100644
--- a/runtime/lib/stopwatch_patch.dart
+++ b/runtime/lib/stopwatch_patch.dart
@@ -4,15 +4,15 @@
// A VM patch of the stopwatch part of dart:core.
-patch class Stopwatch {
- /* patch */ static void _initTicker() {
+@patch class Stopwatch {
+ /* @patch */ static void _initTicker() {
if (_frequency == null) {
_frequency = _computeFrequency();
}
}
// Returns the current clock tick.
- /* patch */ static int _now() native "Stopwatch_now";
+ /* @patch */ static int _now() native "Stopwatch_now";
// Returns the frequency of clock ticks in Hz.
static int _computeFrequency() native "Stopwatch_frequency";
diff --git a/runtime/lib/string_buffer_patch.dart b/runtime/lib/string_buffer_patch.dart
index 401d258..c4fab5c 100644
--- a/runtime/lib/string_buffer_patch.dart
+++ b/runtime/lib/string_buffer_patch.dart
@@ -2,7 +2,7 @@
// 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.
-patch class StringBuffer {
+@patch class StringBuffer {
static const int _BUFFER_SIZE = 64;
static const int _PARTS_TO_COMPACT = 128;
static const int _PARTS_TO_COMPACT_SIZE_LIMIT = _PARTS_TO_COMPACT * 8;
@@ -48,20 +48,20 @@
int _bufferCodeUnitMagnitude = 0;
/// Creates the string buffer with an initial content.
- /* patch */ StringBuffer([Object content = ""]) {
+ /* @patch */ StringBuffer([Object content = ""]) {
write(content);
}
- /* patch */ int get length => _partsCodeUnits + _bufferPosition;
+ /* @patch */ int get length => _partsCodeUnits + _bufferPosition;
- /* patch */ void write(Object obj) {
+ /* @patch */ void write(Object obj) {
String str = '$obj';
if (str.isEmpty) return;
_consumeBuffer();
_addPart(str);
}
- /* patch */ void writeCharCode(int charCode) {
+ /* @patch */ void writeCharCode(int charCode) {
if (charCode <= 0xFFFF) {
if (charCode < 0) {
throw new RangeError.range(charCode, 0, 0x10FFFF);
@@ -81,7 +81,7 @@
}
}
- /* patch */ void writeAll(Iterable objects, [String separator = ""]) {
+ /* @patch */ void writeAll(Iterable objects, [String separator = ""]) {
Iterator iterator = objects.iterator;
if (!iterator.moveNext()) return;
if (separator.isEmpty) {
@@ -97,19 +97,19 @@
}
}
- /* patch */ void writeln([Object obj = ""]) {
+ /* @patch */ void writeln([Object obj = ""]) {
write(obj);
write("\n");
}
/** Makes the buffer empty. */
- /* patch */ void clear() {
+ /* @patch */ void clear() {
_parts = null;
_partsCodeUnits = _bufferPosition = _bufferCodeUnitMagnitude = 0;
}
/** Returns the contents of buffer as a string. */
- /* patch */ String toString() {
+ /* @patch */ String toString() {
_consumeBuffer();
return (_partsCodeUnits == 0) ?
"" :
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index 4352245..e8b3642 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -7,16 +7,16 @@
const int _maxUtf16 = 0xffff;
const int _maxUnicode = 0x10ffff;
-patch class String {
- /* patch */ factory String.fromCharCodes(Iterable<int> charCodes,
- [int start = 0, int end]) {
+@patch class String {
+ /* @patch */ factory String.fromCharCodes(Iterable<int> charCodes,
+ [int start = 0, int end]) {
if (charCodes is! Iterable) throw new ArgumentError.value(charCodes, "charCodes");
if (start is! int) throw new ArgumentError.value(start, "start");
if (end != null && end is! int) throw new ArgumentError.value(end, "end");
return _StringBase.createFromCharCodes(charCodes, start, end, null);
}
- /* patch */ factory String.fromCharCode(int charCode) {
+ /* @patch */ factory String.fromCharCode(int charCode) {
if (charCode >= 0) {
if (charCode <= 0xff) {
return _OneByteString._allocate(1).._setAt(0, charCode);
@@ -37,8 +37,8 @@
throw new RangeError.range(charCode, 0, 0x10ffff);
}
- /* patch */ const factory String.fromEnvironment(String name,
- {String defaultValue})
+ /* @patch */ const factory String.fromEnvironment(String name,
+ {String defaultValue})
native "String_fromEnvironment";
}
diff --git a/runtime/lib/symbol_patch.dart b/runtime/lib/symbol_patch.dart
index 1a1b2bc..4c70daa 100644
--- a/runtime/lib/symbol_patch.dart
+++ b/runtime/lib/symbol_patch.dart
@@ -2,11 +2,11 @@
// 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.
-patch class Symbol {
- /* patch */ const Symbol(String name)
+@patch class Symbol {
+ /* @patch */ const Symbol(String name)
: this._name = name;
- /* patch */ toString() => 'Symbol("${getUnmangledName(this)}")';
+ /* @patch */ toString() => 'Symbol("${getUnmangledName(this)}")';
static getUnmangledName(Symbol symbol) {
String string = Symbol.getName(symbol);
@@ -52,7 +52,7 @@
return result.toString();
}
- /* patch */ int get hashCode {
+ /* @patch */ int get hashCode {
const arbitraryPrime = 664597;
return 0x1fffffff & (arbitraryPrime * _name.hashCode);
}
diff --git a/runtime/lib/timeline.dart b/runtime/lib/timeline.dart
index df43dec..da5760e 100644
--- a/runtime/lib/timeline.dart
+++ b/runtime/lib/timeline.dart
@@ -4,33 +4,33 @@
import 'dart:_internal';
-patch bool _isDartStreamEnabled() native "Timeline_isDartStreamEnabled";
+@patch bool _isDartStreamEnabled() native "Timeline_isDartStreamEnabled";
-patch int _getTraceClock() native "Timeline_getTraceClock";
+@patch int _getTraceClock() native "Timeline_getTraceClock";
-patch int _getThreadCpuClock() native "Timeline_getThreadCpuClock";
+@patch int _getThreadCpuClock() native "Timeline_getThreadCpuClock";
-patch int _getNextAsyncId() native "Timeline_getNextAsyncId";
+@patch int _getNextAsyncId() native "Timeline_getNextAsyncId";
-patch int _getIsolateNum() native "Timeline_getIsolateNum";
+@patch int _getIsolateNum() native "Timeline_getIsolateNum";
-patch void _reportTaskEvent(
- int start,
- int taskId,
- String phase,
- String category,
- String name,
- String argumentsAsJson) native "Timeline_reportTaskEvent";
+@patch void _reportTaskEvent(
+ int start,
+ int taskId,
+ String phase,
+ String category,
+ String name,
+ String argumentsAsJson) native "Timeline_reportTaskEvent";
-patch void _reportCompleteEvent(
- int start,
- int end,
- String category,
- String name,
- String argumentsAsJson) native "Timeline_reportCompleteEvent";
+@patch void _reportCompleteEvent(
+ int start,
+ int end,
+ String category,
+ String name,
+ String argumentsAsJson) native "Timeline_reportCompleteEvent";
-patch void _reportInstantEvent(
- int start,
- String category,
- String name,
- String argumentsAsJson) native "Timeline_reportInstantEvent";
+@patch void _reportInstantEvent(
+ int start,
+ String category,
+ String name,
+ String argumentsAsJson) native "Timeline_reportInstantEvent";
diff --git a/runtime/lib/timer_patch.dart b/runtime/lib/timer_patch.dart
index f975daa..a92db40 100644
--- a/runtime/lib/timer_patch.dart
+++ b/runtime/lib/timer_patch.dart
@@ -2,8 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-patch class Timer {
- /*patch*/ static Timer _createTimer(Duration duration, void callback()) {
+@patch class Timer {
+ /*@patch*/ static Timer _createTimer(Duration duration, void callback()) {
// TODO(iposva): Remove _TimerFactory and use VMLibraryHooks exclusively.
if (_TimerFactory._factory == null) {
_TimerFactory._factory = VMLibraryHooks.timerFactory;
@@ -16,7 +16,7 @@
return _TimerFactory._factory(milliseconds, (_) { callback(); }, false);
}
- /*patch*/ static Timer _createPeriodicTimer(Duration duration,
+ /*@patch*/ static Timer _createPeriodicTimer(Duration duration,
void callback(Timer timer)) {
// TODO(iposva): Remove _TimerFactory and use VMLibraryHooks exclusively.
if (_TimerFactory._factory == null) {
diff --git a/runtime/lib/uri_patch.dart b/runtime/lib/uri_patch.dart
index 2664b9b..d4eb712 100644
--- a/runtime/lib/uri_patch.dart
+++ b/runtime/lib/uri_patch.dart
@@ -15,19 +15,19 @@
// value for Uri.base.
_UriBaseClosure _uriBaseClosure = _unsupportedUriBase;
-patch class Uri {
+@patch class Uri {
static final bool _isWindowsCached = _isWindowsPlatform;
- /* patch */ static bool get _isWindows => _isWindowsCached;
+ /* @patch */ static bool get _isWindows => _isWindowsCached;
- /* patch */ static Uri get base => _uriBaseClosure();
+ /* @patch */ static Uri get base => _uriBaseClosure();
static bool get _isWindowsPlatform native "Uri_isWindowsPlatform";
- /* patch */ static String _uriEncode(List<int> canonicalTable,
- String text,
- Encoding encoding,
- bool spaceToPlus) {
+ /* @patch */ static String _uriEncode(List<int> canonicalTable,
+ String text,
+ Encoding encoding,
+ bool spaceToPlus) {
// First check if the text will be changed by encoding.
int i = 0;
if (identical(encoding, UTF8) ||
diff --git a/runtime/lib/vmservice_patch.dart b/runtime/lib/vmservice_patch.dart
index 498bda2..e0a2e02 100644
--- a/runtime/lib/vmservice_patch.dart
+++ b/runtime/lib/vmservice_patch.dart
@@ -2,9 +2,9 @@
// 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.
-patch class Asset {
+@patch class Asset {
/// Call to request assets from the embedder.
- /* patch */ static HashMap<String, Asset> request() {
+ /* @patch */ static HashMap<String, Asset> request() {
HashMap<String, Asset> assets = new HashMap<String, Asset>();
Uint8List tarBytes = _requestAssets();
if (tarBytes == null) {
@@ -21,18 +21,18 @@
List _decodeAssets(Uint8List data) native "VMService_DecodeAssets";
-patch bool sendIsolateServiceMessage(SendPort sp, List m)
+@patch bool sendIsolateServiceMessage(SendPort sp, List m)
native "VMService_SendIsolateServiceMessage";
-patch void sendRootServiceMessage(List m)
+@patch void sendRootServiceMessage(List m)
native "VMService_SendRootServiceMessage";
-patch void sendObjectRootServiceMessage(List m)
+@patch void sendObjectRootServiceMessage(List m)
native "VMService_SendObjectRootServiceMessage";
-patch void _onStart() native "VMService_OnStart";
-patch void _onExit() native "VMService_OnExit";
-patch void onServerAddressChange(String address)
+@patch void _onStart() native "VMService_OnStart";
+@patch void _onExit() native "VMService_OnExit";
+@patch void onServerAddressChange(String address)
native "VMService_OnServerAddressChange";
-patch bool _vmListenStream(String streamId) native "VMService_ListenStream";
-patch void _vmCancelStream(String streamId) native "VMService_CancelStream";
-patch Uint8List _requestAssets() native "VMService_RequestAssets";
-patch void _spawnUriNotify(obj, String token)
+@patch bool _vmListenStream(String streamId) native "VMService_ListenStream";
+@patch void _vmCancelStream(String streamId) native "VMService_CancelStream";
+@patch Uint8List _requestAssets() native "VMService_RequestAssets";
+@patch void _spawnUriNotify(obj, String token)
native "VMService_spawnUriNotify";
diff --git a/runtime/observatory/lib/app.dart b/runtime/observatory/lib/app.dart
index 4856448..0b85c8b 100644
--- a/runtime/observatory/lib/app.dart
+++ b/runtime/observatory/lib/app.dart
@@ -7,7 +7,6 @@
import 'dart:async';
import 'dart:convert';
import 'dart:html';
-import 'dart:math' as math;
import 'package:logging/logging.dart';
import 'package:observatory/service_html.dart';
diff --git a/runtime/observatory/lib/cpu_profile.dart b/runtime/observatory/lib/cpu_profile.dart
index 5ebd9a5..ccc53c5 100644
--- a/runtime/observatory/lib/cpu_profile.dart
+++ b/runtime/observatory/lib/cpu_profile.dart
@@ -4,6 +4,7 @@
library cpu_profiler;
+import 'dart:async';
import 'dart:typed_data';
import 'package:observatory/models.dart' as M;
import 'package:observatory/service.dart';
diff --git a/runtime/observatory/lib/elements.dart b/runtime/observatory/lib/elements.dart
index ecc32ac..8f72b4d 100644
--- a/runtime/observatory/lib/elements.dart
+++ b/runtime/observatory/lib/elements.dart
@@ -7,7 +7,7 @@
export 'package:observatory/src/elements/code_view.dart';
export 'package:observatory/src/elements/context_ref.dart';
export 'package:observatory/src/elements/context_view.dart';
-export 'package:observatory/src/elements/cpu_profile.dart';
+export 'package:observatory/src/elements/cpu_profile_table.dart';
export 'package:observatory/src/elements/debugger.dart';
export 'package:observatory/src/elements/error_view.dart';
export 'package:observatory/src/elements/eval_box.dart';
@@ -36,7 +36,6 @@
export 'package:observatory/src/elements/object_view.dart';
export 'package:observatory/src/elements/objectpool_view.dart';
export 'package:observatory/src/elements/objectstore_view.dart';
-export 'package:observatory/src/elements/observatory_application.dart';
export 'package:observatory/src/elements/observatory_element.dart';
export 'package:observatory/src/elements/persistent_handles.dart';
export 'package:observatory/src/elements/ports.dart';
@@ -57,6 +56,8 @@
import 'package:observatory/src/elements/code_ref_wrapper.dart';
import 'package:observatory/src/elements/containers/virtual_collection.dart';
import 'package:observatory/src/elements/containers/virtual_tree.dart';
+import 'package:observatory/src/elements/cpu_profile.dart';
+import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
import 'package:observatory/src/elements/curly_block.dart';
import 'package:observatory/src/elements/curly_block_wrapper.dart';
import 'package:observatory/src/elements/error_ref.dart';
@@ -65,8 +66,12 @@
import 'package:observatory/src/elements/function_ref.dart';
import 'package:observatory/src/elements/function_ref_wrapper.dart';
import 'package:observatory/src/elements/general_error.dart';
+import 'package:observatory/src/elements/isolate_reconnect.dart';
import 'package:observatory/src/elements/isolate_ref.dart';
import 'package:observatory/src/elements/isolate_ref_wrapper.dart';
+import 'package:observatory/src/elements/isolate/counter_chart.dart';
+import 'package:observatory/src/elements/isolate/shared_summary.dart';
+import 'package:observatory/src/elements/isolate/shared_summary_wrapper.dart';
import 'package:observatory/src/elements/library_ref.dart';
import 'package:observatory/src/elements/library_ref_wrapper.dart';
import 'package:observatory/src/elements/nav/bar.dart';
@@ -90,10 +95,13 @@
import 'package:observatory/src/elements/nav/top_menu_wrapper.dart';
import 'package:observatory/src/elements/nav/vm_menu.dart';
import 'package:observatory/src/elements/nav/vm_menu_wrapper.dart';
+import 'package:observatory/src/elements/observatory_application.dart';
+import 'package:observatory/src/elements/sample_buffer_control.dart';
import 'package:observatory/src/elements/script_ref.dart';
import 'package:observatory/src/elements/script_ref_wrapper.dart';
import 'package:observatory/src/elements/source_link.dart';
import 'package:observatory/src/elements/source_link_wrapper.dart';
+import 'package:observatory/src/elements/stack_trace_tree_config.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.dart';
@@ -105,12 +113,17 @@
export 'package:observatory/src/elements/code_ref.dart';
export 'package:observatory/src/elements/containers/virtual_collection.dart';
export 'package:observatory/src/elements/containers/virtual_tree.dart';
+export 'package:observatory/src/elements/cpu_profile.dart';
+export 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
export 'package:observatory/src/elements/curly_block.dart';
export 'package:observatory/src/elements/error_ref.dart';
export 'package:observatory/src/elements/flag_list.dart';
export 'package:observatory/src/elements/function_ref.dart';
export 'package:observatory/src/elements/general_error.dart';
+export 'package:observatory/src/elements/isolate_reconnect.dart';
export 'package:observatory/src/elements/isolate_ref.dart';
+export 'package:observatory/src/elements/isolate/counter_chart.dart';
+export 'package:observatory/src/elements/isolate/shared_summary.dart';
export 'package:observatory/src/elements/library_ref.dart';
export 'package:observatory/src/elements/nav/bar.dart';
export 'package:observatory/src/elements/nav/class_menu.dart';
@@ -124,8 +137,11 @@
export 'package:observatory/src/elements/nav/refresh.dart';
export 'package:observatory/src/elements/nav/top_menu.dart';
export 'package:observatory/src/elements/nav/vm_menu.dart';
+export 'package:observatory/src/elements/observatory_application.dart';
+export 'package:observatory/src/elements/sample_buffer_control.dart';
export 'package:observatory/src/elements/script_ref.dart';
export 'package:observatory/src/elements/source_link.dart';
+export 'package:observatory/src/elements/stack_trace_tree_config.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';
@@ -138,6 +154,8 @@
ClassTreeElement.tag.ensureRegistration();
CodeRefElement.tag.ensureRegistration();
CodeRefElementWrapper.tag.ensureRegistration();
+ CpuProfileElement.tag.ensureRegistration();
+ CpuProfileVirtualTreeElement.tag.ensureRegistration();
CurlyBlockElement.tag.ensureRegistration();
CurlyBlockElementWrapper.tag.ensureRegistration();
ErrorRefElement.tag.ensureRegistration();
@@ -146,8 +164,12 @@
FunctionRefElement.tag.ensureRegistration();
FunctionRefElementWrapper.tag.ensureRegistration();
GeneralErrorElement.tag.ensureRegistration();
+ IsolateCounterChartElement.tag.ensureRegistration();
+ IsolateReconnectElement.tag.ensureRegistration();
IsolateRefElement.tag.ensureRegistration();
IsolateRefElementWrapper.tag.ensureRegistration();
+ IsolateSharedSummaryElement.tag.ensureRegistration();
+ IsolateSharedSummaryElementWrapper.tag.ensureRegistration();
LibraryRefElement.tag.ensureRegistration();
LibraryRefElementWrapper.tag.ensureRegistration();
NavBarElement.tag.ensureRegistration();
@@ -171,13 +193,19 @@
NavTopMenuElementWrapper.tag.ensureRegistration();
NavVMMenuElement.tag.ensureRegistration();
NavVMMenuElementWrapper.tag.ensureRegistration();
+ ObservatoryApplicationElement.tag.ensureRegistration();
+ ScriptRefElement.tag.ensureRegistration();
+ SampleBufferControlElement.tag.ensureRegistration();
ScriptRefElement.tag.ensureRegistration();
ScriptRefElementWrapper.tag.ensureRegistration();
SourceLinkElement.tag.ensureRegistration();
SourceLinkElementWrapper.tag.ensureRegistration();
+ StackTraceTreeConfigElement.tag.ensureRegistration();
ViewFooterElement.tag.ensureRegistration();
VirtualCollectionElement.tag.ensureRegistration();
VirtualTreeElement.tag.ensureRegistration();
VMConnectElement.tag.ensureRegistration();
+ VirtualCollectionElement.tag.ensureRegistration();
+ VirtualTreeElement.tag.ensureRegistration();
VMConnectTargetElement.tag.ensureRegistration();
}
diff --git a/runtime/observatory/lib/elements.html b/runtime/observatory/lib/elements.html
index 2b42d47..5c34c60 100644
--- a/runtime/observatory/lib/elements.html
+++ b/runtime/observatory/lib/elements.html
@@ -2,7 +2,7 @@
<link rel="import" href="src/elements/class_ref_as_value.html">
<link rel="import" href="src/elements/class_view.html">
<link rel="import" href="src/elements/code_view.html">
-<link rel="import" href="src/elements/cpu_profile.html">
+<link rel="import" href="src/elements/cpu_profile_table.html">
<link rel="import" href="src/elements/debugger.html">
<link rel="import" href="src/elements/error_view.html">
<link rel="import" href="src/elements/eval_box.html">
@@ -16,7 +16,6 @@
<link rel="import" href="src/elements/io_view.html">
<link rel="import" href="src/elements/icdata_view.html">
<link rel="import" href="src/elements/instructions_view.html">
-<link rel="import" href="src/elements/isolate_reconnect.html">
<link rel="import" href="src/elements/isolate_summary.html">
<link rel="import" href="src/elements/isolate_view.html">
<link rel="import" href="src/elements/json_view.html">
@@ -29,11 +28,11 @@
<link rel="import" href="src/elements/object_view.html">
<link rel="import" href="src/elements/objectpool_view.html">
<link rel="import" href="src/elements/objectstore_view.html">
-<link rel="import" href="src/elements/observatory_application.html">
<link rel="import" href="src/elements/persistent_handles.html">
<link rel="import" href="src/elements/ports.html">
<link rel="import" href="src/elements/script_inset.html">
<link rel="import" href="src/elements/script_view.html">
<link rel="import" href="src/elements/service_ref.html">
+<link rel="import" href="src/elements/service_view.html">
<link rel="import" href="src/elements/timeline_page.html">
<link rel="import" href="src/elements/vm_view.html">
diff --git a/runtime/observatory/lib/models.dart b/runtime/observatory/lib/models.dart
index ded6d78..943592f 100644
--- a/runtime/observatory/lib/models.dart
+++ b/runtime/observatory/lib/models.dart
@@ -17,11 +17,13 @@
part 'src/models/objects/flag.dart';
part 'src/models/objects/frame.dart';
part 'src/models/objects/function.dart';
+part 'src/models/objects/heap_space.dart';
part 'src/models/objects/instance.dart';
part 'src/models/objects/isolate.dart';
part 'src/models/objects/library.dart';
part 'src/models/objects/notification.dart';
part 'src/models/objects/object.dart';
+part 'src/models/objects/sample_profile.dart';
part 'src/models/objects/script.dart';
part 'src/models/objects/source_location.dart';
part 'src/models/objects/target.dart';
@@ -33,5 +35,6 @@
part 'src/models/repositories/flag.dart';
part 'src/models/repositories/instance.dart';
part 'src/models/repositories/notification.dart';
+part 'src/models/repositories/sample_profile.dart';
part 'src/models/repositories/script.dart';
part 'src/models/repositories/target.dart';
diff --git a/runtime/observatory/lib/repositories.dart b/runtime/observatory/lib/repositories.dart
index 9f3c340..b3938b1 100644
--- a/runtime/observatory/lib/repositories.dart
+++ b/runtime/observatory/lib/repositories.dart
@@ -7,6 +7,7 @@
import 'dart:async';
import 'dart:convert';
import 'dart:html';
+import 'package:observatory/cpu_profile.dart';
import 'package:observatory/models.dart' as M;
import 'package:observatory/service.dart' as S;
import 'package:observatory/service_common.dart' as SC;
@@ -17,6 +18,7 @@
part 'src/repositories/flag.dart';
part 'src/repositories/instance.dart';
part 'src/repositories/notification.dart';
+part 'src/repositories/sample_profile.dart';
part 'src/repositories/script.dart';
part 'src/repositories/settings.dart';
part 'src/repositories/target.dart';
diff --git a/runtime/observatory/lib/src/app/location_manager.dart b/runtime/observatory/lib/src/app/location_manager.dart
index 64ea764..aadf653 100644
--- a/runtime/observatory/lib/src/app/location_manager.dart
+++ b/runtime/observatory/lib/src/app/location_manager.dart
@@ -98,8 +98,8 @@
? '/vm-connect' : '/isolate-reconnect');
var parameters = {};
parameters.addAll(_uri.queryParameters);
- parameters['originalPath'] = _uri.path;
- parameters['originalIsolateId'] = parameters['isolateId'];
+ parameters['originalUri'] = _uri.toString();
+ parameters['isolateId'] = parameters['isolateId'];
var generatedUri = new Uri(path: newPath, queryParameters: parameters);
go(makeLink(generatedUri.toString()), true);
return;
diff --git a/runtime/observatory/lib/src/app/page.dart b/runtime/observatory/lib/src/app/page.dart
index 9d624c1..e5d0b1f 100644
--- a/runtime/observatory/lib/src/app/page.dart
+++ b/runtime/observatory/lib/src/app/page.dart
@@ -4,6 +4,9 @@
part of app;
+IsolateSampleProfileRepository _isolateSampleProfileRepository
+ = new IsolateSampleProfileRepository();
+
class IsolateNotFound implements Exception {
String isolateId;
IsolateNotFound(this.isolateId);
@@ -47,17 +50,10 @@
bool canVisit(Uri uri);
}
-/// A [SimplePage] matches a single uri path and displays a single element.
-class SimplePage extends Page {
+/// A [MatchingPage] matches a single uri path.
+abstract class MatchingPage extends Page {
final String path;
- final String elementTagName;
- SimplePage(this.path, this.elementTagName, app) : super(app);
-
- void onInstall() {
- if (element == null) {
- element = new Element.tag(elementTagName);
- }
- }
+ MatchingPage(this.path, app) : super(app);
void _visit(Uri uri) {
assert(uri != null);
@@ -77,6 +73,18 @@
bool canVisit(Uri uri) => uri.path == path;
}
+/// A [SimplePage] matches a single uri path and displays a single element.
+class SimplePage extends MatchingPage {
+ final String elementTagName;
+ SimplePage(String path, this.elementTagName, app) : super(path, app);
+
+ void onInstall() {
+ if (element == null) {
+ element = new Element.tag(elementTagName);
+ }
+ }
+}
+
/// Error page for unrecognized paths.
class ErrorPage extends Page {
ErrorPage(app) : super(app);
@@ -216,19 +224,28 @@
}
}
-class CpuProfilerPage extends SimplePage {
- CpuProfilerPage(app) : super('profiler', 'cpu-profile', app);
+class CpuProfilerPage extends MatchingPage {
+ CpuProfilerPage(app) : super('profiler', app);
+
+ DivElement container = new DivElement();
void _visit(Uri uri) {
super._visit(uri);
getIsolate(uri).then((isolate) {
- if (element != null) {
- /// Update the page.
- CpuProfileElement page = element;
- page.isolate = isolate;
- }
+ container.children = [
+ new CpuProfileElement(isolate.vm, isolate, app.events,
+ app.notifications,
+ _isolateSampleProfileRepository)
+ ];
});
}
+
+ void onInstall() {
+ if (element == null) {
+ element = container;
+ }
+ assert(element != null);
+ }
}
class TableCpuProfilerPage extends SimplePage {
@@ -389,15 +406,19 @@
class IsolateReconnectPage extends Page {
IsolateReconnectPage(app) : super(app);
+ DivElement container = new DivElement();
+
void onInstall() {
- if (element == null) {
- element = new Element.tag('isolate-reconnect');
- }
- assert(element != null);
+ element = container;
}
void _visit(Uri uri) {
app.vm.reload();
+ container.children = [
+ new IsolateReconnectElement(app.vm, app.events, app.notifications,
+ uri.queryParameters['isolateId'],
+ Uri.parse(uri.queryParameters['originalUri']))
+ ];
assert(element != null);
assert(canVisit(uri));
}
diff --git a/runtime/observatory/lib/src/app/view_model.dart b/runtime/observatory/lib/src/app/view_model.dart
index 76033eb..94edb49 100644
--- a/runtime/observatory/lib/src/app/view_model.dart
+++ b/runtime/observatory/lib/src/app/view_model.dart
@@ -4,389 +4,6 @@
part of app;
-abstract class VirtualTreeRow {
- // Number of ems each subtree is indented.
- static const subtreeIndent = 2.0;
-
- static const redColor = '#F44336';
- static const blueColor = '#3F51B5';
- static const purpleColor = '#673AB7';
- static const greenColor = '#4CAF50';
- static const orangeColor = '#FF9800';
- static const lightGrayColor = '#FAFAFA';
-
- List backgroundColors = const [
- purpleColor,
- redColor,
- greenColor,
- blueColor,
- orangeColor,
- ];
-
- final VirtualTree tree;
- final List<VirtualTreeRow> children = [];
- final List<StreamSubscription> _listeners = [];
- final int depth;
- bool _expanded = false;
-
- VirtualTreeRow(this.tree, this.depth);
-
- bool get expanded => _expanded;
-
- set expanded(bool expanded) {
- var changed = _expanded != expanded;
- _expanded = expanded;
- if (!changed) {
- return;
- }
- if (_expanded) {
- _expand();
- } else {
- _collapse();
- }
- }
-
- Element makeColorBar(int depth) {
- var element = new SpanElement();
- element.style.paddingLeft = '2px';
- element.style.paddingRight = '2px';
- element.style.flexBasis = '2px';
- element.style.height = '${tree.rowHeight}px';
- element.style.minHeight = '${tree.rowHeight}px';
- if (depth > 0) {
- var colorIndex = (depth - 1) % backgroundColors.length;
- element.style.backgroundColor = backgroundColors[colorIndex];
- }
- return element;
- }
-
- Element makeExpander() {
- SpanElement element = new SpanElement();
- element.style.flexBasis = '2em';
- if (!hasChildren()) {
- element.style.visibility = 'hidden';
- } else {
- element.style.visibility = 'visible';
- element.children.add(expanded ?
- new Element.tag('icon-expand-more') :
- new Element.tag('icon-chevron-right'));
- }
- _listeners.add(element.onClick.listen((e) {
- e.stopPropagation();
- toggle();
- }));
- return element;
- }
-
- Element makeIndenter(int depth, {colored: true}) {
- SpanElement element = new SpanElement();
- element.style.paddingLeft = '${subtreeIndent * depth}em';
- element.style.flexBasis = '${subtreeIndent * depth}em';
- element.style.height = '${tree.rowHeight}px';
- element.style.minHeight = '${tree.rowHeight}px';
- if (colored) {
- if (depth > 0) {
- var colorIndex = (depth - 1) % backgroundColors.length;
- element.style.backgroundColor = backgroundColors[colorIndex];
- }
- }
- return element;
- }
-
- Element makeText(String text, {String toolTip,
- String flexBasis: '4.5em',
- String cssClass}) {
- SpanElement element = new SpanElement();
- element.text = text;
- if (toolTip != null) {
- element.title = toolTip;
- }
- if (flexBasis != null) {
- element.style.flexBasis = flexBasis;
- }
- if (cssClass != null) {
- element.classes.add(cssClass);
- }
- return element;
- }
-
- Element makeGap({double ems: 0.5}) {
- SpanElement element = new SpanElement();
- var flexBasis = '${ems}em';
- element.style.flexBasis = flexBasis;
- return element;
- }
-
- void _cleanupListeners() {
- for (var listener in _listeners) {
- listener.cancel();
- }
- _listeners.clear();
- }
-
- void _expand() {
- onShow();
- tree._onExpand(this);
- if (children.length == 1) {
- children[0]._expand();
- }
- _expanded = true;
- }
-
- void _collapse() {
- _expanded = false;
- for (var i = 0; i < children.length; i++) {
- if (children[i].expanded) {
- children[i]._collapse();
- }
- }
- tree._onCollapse(this);
- }
-
- void toggle() {
- expanded = !expanded;
- }
-
- void _render(DivElement rowDiv) {
- rowDiv.style.display = 'flex';
- rowDiv.style.alignItems = 'center';
- _cleanupListeners();
- onShow();
- onRender(rowDiv);
- }
-
- /// Called when you should render into [rowDiv].
- void onRender(DivElement rowDiv);
-
- // Called when this row is visible.
- void onShow();
-
- // Return the number of children this node has.
- int get childCount => 0;
-
- // Return true if this node can be expanded.
- bool hasChildren() => childCount > 0;
-
- // Called when this row is not visible.
- void onHide() {
- _cleanupListeners();
- }
-}
-
-class VirtualTree {
- final int rowHeight;
- final List<VirtualTreeRow> rows = [];
- final DivElement root;
- final Stopwatch _clock = new Stopwatch();
-
- DivElement _treeHeightElement;
- DivElement _tree;
-
- StreamSubscription _scrollSubscription;
- StreamSubscription _resizeSubscription;
-
- // Height of [root] in pixels.
- int viewHeight;
-
- // Number of pixels view can be scrolled before a redraw occurs.
- int redrawThresholdPixels;
-
- // Number of rows visible at any given time.
- int numVisibleRows;
- // Number of rows above the current view that are in the dom.
- int extraRowsAbove;
- // Number of rows below the current view that are in the dom.
- int extraRowsBelow;
-
- // The scroll top of the last scroll event.
- int lastPaintScrollTop;
-
- // The starting row of the last paint.
- int lastPaintStartingRow = 0;
-
- bool paintScheduled = false;
-
- bool scrolled = false;
-
- static const scrollStopThresholdMilliseconds = 100;
-
- VirtualTree(this.rowHeight, this.root) {
- _clock.start();
- _install();
- _resize();
- _schedulePaint(0);
- }
-
- void uninstall() => _uninstall();
-
- void refresh() {
- _resize();
- _schedulePaint(lastPaintStartingRow);
- }
-
- // Clear the tree.
- void clear() {
- rows.clear();
- _resize();
- }
-
- void _onExpand(VirtualTreeRow parent) {
- int index = rows.indexOf(parent);
- if (index == -1) {
- return;
- }
- rows.insertAll(index + 1, parent.children);
- refresh();
- }
-
- void _onCollapse(VirtualTreeRow parent) {
- int index = rows.indexOf(parent);
- if (index == -1) {
- return;
- }
- int start = index + 1;
- int end = start + parent.children.length;
- rows.removeRange(start, end);
- refresh();
- }
-
- void _resize() {
- if (viewHeight != root.offsetHeight) {
- viewHeight = root.offsetHeight;
- numVisibleRows = (viewHeight ~/ rowHeight) + 1;
- extraRowsAbove = numVisibleRows ~/ 2;
- extraRowsBelow = numVisibleRows - extraRowsAbove;
- redrawThresholdPixels =
- math.min(extraRowsAbove, extraRowsBelow) * rowHeight;
- }
- _treeHeightElement.style.height = '${_treeHeight()}px';
- }
-
- int _treeHeight() {
- return rows.length * rowHeight;
- }
-
- int _pixelsFromLastScroll(int currentScrollTop) {
- if (lastPaintScrollTop == null) {
- return currentScrollTop;
- }
-
- return (currentScrollTop - lastPaintScrollTop).abs();
- }
-
- int _pixelToRow(int pixelY) {
- int result = pixelY ~/ rowHeight;
- return result;
- }
-
- void _install() {
- // This element controls the height of the tree's scrollable region.
- // It is one pixel wide and the height is set to rowHeight * numRows.
- _treeHeightElement = new DivElement();
- _treeHeightElement.style.position = 'absolute';
- _treeHeightElement.style.top = '0';
- _treeHeightElement.style.left = '0';
- _treeHeightElement.style.width = '1px';
-
- // This element holds the visible tree rows and the height controlling
- // element. It takes the full width and height of its parent element.
- _tree = new DivElement();
- _tree.children.add(_treeHeightElement);
- _tree.style.width = '100%';
- _tree.style.height = '100%';
- _tree.style.position = 'relative';
- _tree.style.overflow = 'auto';
-
- // Listen for scroll events on the tree.
- _scrollSubscription = _tree.onScroll.listen(_onScroll);
-
- root.children.add(_tree);
-
- // Listen for resize events.
- _resizeSubscription = window.onResize.listen((_) {
- _resize();
- _schedulePaint(lastPaintStartingRow);
- });
- }
-
- void _uninstall() {
- root.children.clear();
- _scrollSubscription?.cancel();
- _scrollSubscription = null;
- _resizeSubscription?.cancel();
- _resizeSubscription = null;
- }
-
- void _onScroll(Event scrollEvent) {
- Element target = scrollEvent.target;
- int scrollTop = target.scrollTop;
- if (_pixelsFromLastScroll(scrollTop) > redrawThresholdPixels) {
- _schedulePaint(lastPaintStartingRow);
- scrolled = true;
- }
- scrollEvent.preventDefault();
- }
-
- void _schedulePaint(int startingRow) {
- if (paintScheduled) {
- return;
- }
- paintScheduled = true;
- window.requestAnimationFrame(
- (timestamp) => _onRenderFrame(timestamp, startingRow));
- }
-
- void _onRenderFrame(int timestamp, int startingRow) {
- paintScheduled = false;
- _paint(startingRow);
- }
-
- void _paint(int startingRow) {
- if (scrolled) {
- startingRow = math.max(_pixelToRow(_tree.scrollTop), 0);
- scrolled = false;
- }
- lastPaintScrollTop = _tree.scrollTop;
- lastPaintStartingRow = startingRow;
-
- int endingRow =
- math.min(rows.length, startingRow + numVisibleRows + extraRowsBelow);
-
- startingRow =
- math.max(0, startingRow - extraRowsAbove);
-
- print('PAINT $startingRow $endingRow');
-
- for (int i = startingRow; i < endingRow; i++) {
- // We add 1 because _tree.children[0] contains the height control element.
- int cacheIndex = (i - startingRow) + 1;
- DivElement row;
- if (cacheIndex < _tree.children.length) {
- // re-use existing row.
- row = _tree.children[cacheIndex];
- row.children.clear();
- } else {
- // Allocate a new row.
- row = new DivElement();
- row.style.position = 'absolute';
- row.style.height = '${rowHeight}px';
- row.style.maxHeight = '${rowHeight}px';
- row.style.margin = '0';
- row.style.width = '100%';
- row.style.left = '0';
- _tree.children.add(row);
- }
- row.style.top = '${(i * rowHeight)}px';
- // Render the row.
- rows[i]._render(row);
- }
- int necessaryChildren = (endingRow - startingRow) + 1;
- while (_tree.children.length > necessaryChildren) {
- _tree.children.removeLast();
- }
- }
-}
-
abstract class TableTreeRow extends Observable {
static const arrowRight = '\u2192';
static const arrowDownRight = '\u21b3';
diff --git a/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart b/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart
index a572279..f96f5db 100644
--- a/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart
+++ b/runtime/observatory/lib/src/cpu_profile/cpu_profile.dart
@@ -4,8 +4,9 @@
part of cpu_profiler;
-abstract class CallTreeNode {
- final List<CallTreeNode> children;
+abstract class CallTreeNode<NodeT extends M.CallTreeNode>
+ implements M.CallTreeNode {
+ final List<NodeT> children;
final int count;
double get percentage => _percentage;
double _percentage = 0.0;
@@ -18,7 +19,8 @@
CallTreeNode(this.children, this.count);
}
-class CodeCallTreeNode extends CallTreeNode {
+class CodeCallTreeNode extends CallTreeNode<CodeCallTreeNode>
+ implements M.CodeCallTreeNode {
final ProfileCode profileCode;
Object get profileData => profileCode;
@@ -32,14 +34,15 @@
}
}
-class CallTree {
+class CallTree<NodeT extends CallTreeNode> {
final bool inclusive;
- final CallTreeNode root;
+ final NodeT root;
CallTree(this.inclusive, this.root);
}
-class CodeCallTree extends CallTree {
+class CodeCallTree extends CallTree<CodeCallTreeNode>
+ implements M.CodeCallTree {
CodeCallTree(bool inclusive, CodeCallTreeNode root)
: super(inclusive, root) {
_setCodePercentage(null, root);
@@ -305,7 +308,7 @@
}
}
-class FunctionCallTree extends CallTree {
+class FunctionCallTree extends CallTree implements M.FunctionCallTree {
FunctionCallTree(bool inclusive, FunctionCallTreeNode root)
: super(inclusive, root) {
_setFunctionPercentage(null, root);
@@ -370,7 +373,7 @@
InlineIntervalTick(this.startAddress);
}
-class ProfileCode {
+class ProfileCode implements M.ProfileCode {
final CpuProfile profile;
final Code code;
int exclusiveTicks;
@@ -488,7 +491,7 @@
}
}
-class ProfileFunction {
+class ProfileFunction implements M.ProfileFunction {
final CpuProfile profile;
final ServiceFunction function;
// List of compiled code objects containing this function.
@@ -640,9 +643,7 @@
// TODO(johnmccutchan): Rename to SampleProfile
-class CpuProfile {
- final double MICROSECONDS_PER_SECOND = 1000000.0;
- final double displayThreshold = 0.0002; // 0.02%.
+class CpuProfile extends M.SampleProfile {
Isolate isolate;
@@ -660,20 +661,24 @@
final List<ProfileFunction> functions = new List<ProfileFunction>();
bool _builtFunctionCalls = false;
- CodeCallTree loadCodeTree(String name) {
- if (name == 'inclusive') {
- return _loadCodeTree(true, tries['inclusiveCodeTrie']);
- } else {
- return _loadCodeTree(false, tries['exclusiveCodeTrie']);
+ CodeCallTree loadCodeTree(M.ProfileTreeDirection direction) {
+ switch (direction) {
+ case M.ProfileTreeDirection.inclusive:
+ return _loadCodeTree(true, tries['inclusiveCodeTrie']);
+ case M.ProfileTreeDirection.exclusive:
+ return _loadCodeTree(false, tries['exclusiveCodeTrie']);
}
+ throw new Exception('Unknown ProfileTreeDirection');
}
- FunctionCallTree loadFunctionTree(String name) {
- if (name == 'inclusive') {
- return _loadFunctionTree(true, tries['inclusiveFunctionTrie']);
- } else {
- return _loadFunctionTree(false, tries['exclusiveFunctionTrie']);
+ FunctionCallTree loadFunctionTree(M.ProfileTreeDirection direction) {
+ switch (direction) {
+ case M.ProfileTreeDirection.inclusive:
+ return _loadFunctionTree(true, tries['inclusiveFunctionTrie']);
+ case M.ProfileTreeDirection.exclusive:
+ return _loadFunctionTree(false, tries['exclusiveFunctionTrie']);
}
+ throw new Exception('Unknown ProfileTreeDirection');
}
buildCodeCallerAndCallees() {
@@ -681,7 +686,7 @@
return;
}
_builtCodeCalls = true;
- var tree = loadCodeTree('inclusive');
+ var tree = loadCodeTree(M.ProfileTreeDirection.inclusive);
tree._recordCallerAndCallees();
}
@@ -690,7 +695,7 @@
return;
}
_builtFunctionCalls = true;
- var tree = loadFunctionTree('inclusive');
+ var tree = loadFunctionTree(M.ProfileTreeDirection.inclusive);
tree._markFunctionCalls();
}
@@ -707,44 +712,87 @@
_builtFunctionCalls = false;
}
- load(Isolate isolate, ServiceMap profile) {
- clear();
- if ((isolate == null) || (profile == null)) {
- return;
- }
+ Future load(Isolate isolate, ServiceMap profile) async {
+ await loadProgress(isolate, profile).last;
+ }
- this.isolate = isolate;
- isolate.resetCachedProfileData();
+ static Future sleep([Duration duration = const Duration(microseconds: 0)]) {
+ final Completer completer = new Completer();
+ new Timer(duration, () => completer.complete() );
+ return completer.future;
+ }
- sampleCount = profile['sampleCount'];
- samplePeriod = profile['samplePeriod'];
- sampleRate = (MICROSECONDS_PER_SECOND / samplePeriod);
- stackDepth = profile['stackDepth'];
- timeSpan = profile['timeSpan'];
+ Stream<double> loadProgress(Isolate isolate, ServiceMap profile) {
+ var progress = new StreamController<double>.broadcast();
- // Process code table.
- for (var codeRegion in profile['codes']) {
- Code code = codeRegion['code'];
- assert(code != null);
- codes.add(new ProfileCode.fromMap(this, code, codeRegion));
- }
+ (() async {
+ final Stopwatch watch = new Stopwatch();
+ watch.start();
+ int count = 0;
+ var needToUpdate = () {
+ count++;
+ if (((count % 256) == 0) && (watch.elapsedMilliseconds > 16)) {
+ watch.reset();
+ return true;
+ }
+ return false;
+ };
+ var signal = (double p) {
+ progress.add(p);
+ return sleep();
+ };
+ try {
+ clear();
+ progress.add(0.0);
+ if ((isolate == null) || (profile == null)) {
+ return;
+ }
- // Process function table.
- for (var profileFunction in profile['functions']) {
- ServiceFunction function = profileFunction['function'];
- assert(function != null);
- functions.add(
- new ProfileFunction.fromMap(this, function, profileFunction));
- }
+ this.isolate = isolate;
+ isolate.resetCachedProfileData();
- tries['exclusiveCodeTrie'] =
- new Uint32List.fromList(profile['exclusiveCodeTrie']);
- tries['inclusiveCodeTrie'] =
- new Uint32List.fromList(profile['inclusiveCodeTrie']);
- tries['exclusiveFunctionTrie'] =
- new Uint32List.fromList(profile['exclusiveFunctionTrie']);
- tries['inclusiveFunctionTrie'] =
- new Uint32List.fromList(profile['inclusiveFunctionTrie']);
+ sampleCount = profile['sampleCount'];
+ samplePeriod = profile['samplePeriod'];
+ sampleRate = (Duration.MICROSECONDS_PER_SECOND / samplePeriod);
+ stackDepth = profile['stackDepth'];
+ timeSpan = profile['timeSpan'];
+
+ num length = profile['codes'].length +
+ profile['functions'].length;
+
+ // Process code table.
+ for (var codeRegion in profile['codes']) {
+ if (needToUpdate()) {
+ await signal(count * 100.0 / length);
+ }
+ Code code = codeRegion['code'];
+ assert(code != null);
+ codes.add(new ProfileCode.fromMap(this, code, codeRegion));
+ }
+ // Process function table.
+ for (var profileFunction in profile['functions']) {
+ if (needToUpdate()) {
+ await signal(count * 100 / length);
+ }
+ ServiceFunction function = profileFunction['function'];
+ assert(function != null);
+ functions.add(
+ new ProfileFunction.fromMap(this, function, profileFunction));
+ }
+
+ tries['exclusiveCodeTrie'] =
+ new Uint32List.fromList(profile['exclusiveCodeTrie']);
+ tries['inclusiveCodeTrie'] =
+ new Uint32List.fromList(profile['inclusiveCodeTrie']);
+ tries['exclusiveFunctionTrie'] =
+ new Uint32List.fromList(profile['exclusiveFunctionTrie']);
+ tries['inclusiveFunctionTrie'] =
+ new Uint32List.fromList(profile['inclusiveFunctionTrie']);
+ } finally {
+ progress.close();
+ }
+ }());
+ return progress.stream;
}
// Data shared across calls to _read*TrieNode.
@@ -918,12 +966,10 @@
}
int approximateMillisecondsForCount(count) {
- var MICROSECONDS_PER_MILLISECOND = 1000.0;
- return (count * samplePeriod) ~/ MICROSECONDS_PER_MILLISECOND;
+ return (count * samplePeriod) ~/ Duration.MICROSECONDS_PER_MILLISECOND;
}
double approximateSecondsForCount(count) {
- var MICROSECONDS_PER_SECOND = 1000000.0;
- return (count * samplePeriod) / MICROSECONDS_PER_SECOND;
+ return (count * samplePeriod) / Duration.MICROSECONDS_PER_SECOND;
}
}
diff --git a/runtime/observatory/lib/src/elements/class_tree.dart b/runtime/observatory/lib/src/elements/class_tree.dart
index f17f27b..6fefdfd 100644
--- a/runtime/observatory/lib/src/elements/class_tree.dart
+++ b/runtime/observatory/lib/src/elements/class_tree.dart
@@ -147,7 +147,7 @@
return new DivElement()..classes = ['class-tree-item']
..children = [
new SpanElement()..classes = ['lines'],
- new SpanElement()..classes = ['expander']
+ new ButtonElement()..classes = ['expander']
..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
new SpanElement()..classes = ['name']
];
diff --git a/runtime/observatory/lib/src/elements/class_view.dart b/runtime/observatory/lib/src/elements/class_view.dart
index b1ac3fc..9f860a9 100644
--- a/runtime/observatory/lib/src/elements/class_view.dart
+++ b/runtime/observatory/lib/src/elements/class_view.dart
@@ -6,9 +6,13 @@
import 'dart:async';
import 'observatory_element.dart';
-import 'package:observatory/cpu_profile.dart';
+import 'sample_buffer_control.dart';
+import 'stack_trace_tree_config.dart';
+import 'cpu_profile/virtual_tree.dart';
import 'package:observatory/elements.dart';
+import 'package:observatory/models.dart' as M;
import 'package:observatory/service.dart';
+import 'package:observatory/repositories.dart';
import 'package:polymer/polymer.dart';
@CustomTag('class-view')
@@ -21,6 +25,8 @@
SampleBufferControlElement sampleBufferControlElement;
StackTraceTreeConfigElement stackTraceTreeConfigElement;
CpuProfileVirtualTreeElement cpuProfileTreeElement;
+ ClassSampleProfileRepository repository = new ClassSampleProfileRepository();
+
ClassViewElement.created() : super.created();
@@ -59,66 +65,62 @@
void attached() {
super.attached();
- sampleBufferControlElement =
- shadowRoot.querySelector('#sampleBufferControl');
- assert(sampleBufferControlElement != null);
- sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange;
- sampleBufferControlElement.state =
- SampleBufferControlElement.kNotLoadedState;
- stackTraceTreeConfigElement =
- shadowRoot.querySelector('#stackTraceTreeConfig');
- assert(stackTraceTreeConfigElement != null);
- stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange;
- stackTraceTreeConfigElement.show = false;
- stackTraceTreeConfigElement.showFilter = false;
- cpuProfileTreeElement = shadowRoot.querySelector('#cpuProfileTree');
- assert(cpuProfileTreeElement != null);
- cpuProfileTreeElement.profile = sampleBufferControlElement.profile;
- cpuProfileTreeElement.show = false;
cls.fields.forEach((field) => field.reload());
- sampleBufferControlElement.allocationProfileClass = cls;
}
- Future refresh() {
+ Future refresh() async {
instances = null;
retainedBytes = null;
mostRetained = null;
- var loads = [];
- loads.add(cls.reload());
- cls.fields.forEach((field) => loads.add(field.reload()));
- return Future.wait(loads);
+ await cls.reload();
+ await Future.wait(cls.fields.map((field) => field.reload()));
}
- onSampleBufferChange(CpuProfile sampleBuffer) {
- stackTraceTreeConfigElement.show = sampleBuffer.sampleCount > 0;
- cpuProfileTreeElement.show = sampleBuffer.sampleCount > 0;
- cpuProfileTreeElement.render();
- }
-
- onTreeConfigChange(String modeSelector,
- String directionSelector,
- String filter) {
- ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
- if (directionSelector != 'Up') {
- direction = ProfileTreeDirection.Inclusive;
- }
- ProfileTreeMode mode = ProfileTreeMode.Function;
- if (modeSelector == 'Code') {
- mode = ProfileTreeMode.Code;
- }
- cpuProfileTreeElement.direction = direction;
- cpuProfileTreeElement.mode = mode;
- cpuProfileTreeElement.render();
- }
+ M.SampleProfileTag _tag = M.SampleProfileTag.none;
Future refreshAllocationProfile() async {
- return sampleBufferControlElement.reload(cls.isolate);
+ shadowRoot.querySelector('#sampleBufferControl').children = const [];
+ shadowRoot.querySelector('#stackTraceTreeConfig').children = const [];
+ shadowRoot.querySelector('#cpuProfileTree').children = const [];
+ final stream = repository.get(cls, _tag);
+ var progress = (await stream.first).progress;
+ shadowRoot.querySelector('#sampleBufferControl')..children = [
+ new SampleBufferControlElement(progress, stream, queue: app.queue,
+ selectedTag: _tag)
+ ..onTagChange.listen((e) {
+ _tag = e.element.selectedTag;
+ refreshAllocationProfile();
+ })
+ ];
+ if (M.isSampleProcessRunning(progress.status)) {
+ progress = await stream.last;
+ }
+ if (progress.status == M.SampleProfileLoadingStatus.loaded) {
+ shadowRoot.querySelector('#stackTraceTreeConfig')..children = [
+ new StackTraceTreeConfigElement(
+ queue: app.queue)
+ ..showFilter = false
+ ..onModeChange.listen((e) {
+ cpuProfileTreeElement.mode = e.element.mode;
+ })
+ ..onDirectionChange.listen((e) {
+ cpuProfileTreeElement.direction = e.element.direction;
+ })
+ ];
+ shadowRoot.querySelector('#cpuProfileTree')..children = [
+ cpuProfileTreeElement = new CpuProfileVirtualTreeElement(cls.isolate,
+ progress.profile, queue: app.queue)
+ ];
+ }
}
Future toggleAllocationTrace() {
if (cls == null) {
return new Future(refresh);
}
+ if (cls.traceAllocations) {
+ refreshAllocationProfile();
+ }
return cls.setTraceAllocations(!cls.traceAllocations).whenComplete(refresh);
}
}
diff --git a/runtime/observatory/lib/src/elements/class_view.html b/runtime/observatory/lib/src/elements/class_view.html
index 94efab1..60e9e3e 100644
--- a/runtime/observatory/lib/src/elements/class_view.html
+++ b/runtime/observatory/lib/src/elements/class_view.html
@@ -1,6 +1,5 @@
<link rel="import" href="../../../../packages/polymer/polymer.html">
<link rel="import" href="action_link.html">
-<link rel="import" href="cpu_profile.html">
<link rel="import" href="eval_box.html">
<link rel="import" href="eval_link.html">
<link rel="import" href="field_ref.html">
@@ -258,15 +257,11 @@
</div>
</template>
</div>
- <sample-buffer-control id="sampleBufferControl"></sample-buffer-control>
+ <div id="sampleBufferControl"></div>
<br>
- <stack-trace-tree-config id="stackTraceTreeConfig"></stack-trace-tree-config>
+ <div id="stackTraceTreeConfig"></div>
<br>
- <div class="flex-row centered">
- <div class="flex-item-90-percent outlined" style="margin: 16px; margin-left: 8px; margin-right: 8px">
- <cpu-profile-virtual-tree id="cpuProfileTree"></cpu-profile-virtual-tree>
- </div>
- </div>
+ <div id="cpuProfileTree"></div>
</div>
<div class="content-centered-big">
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.dart b/runtime/observatory/lib/src/elements/cpu_profile.dart
index 82f479d..0b24b07 100644
--- a/runtime/observatory/lib/src/elements/cpu_profile.dart
+++ b/runtime/observatory/lib/src/elements/cpu_profile.dart
@@ -6,1571 +6,168 @@
import 'dart:async';
import 'dart:html';
-import 'observatory_element.dart';
import 'package:observatory/models.dart' as M;
-import 'package:observatory/service.dart';
-import 'package:observatory/app.dart';
-import 'package:observatory/cpu_profile.dart';
-import 'package:observatory/elements.dart';
-import 'package:polymer/polymer.dart';
+import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/src/elements/nav/bar.dart';
+import 'package:observatory/src/elements/nav/isolate_menu.dart';
+import 'package:observatory/src/elements/nav/menu.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+import 'package:observatory/src/elements/nav/refresh.dart';
+import 'package:observatory/src/elements/nav/top_menu.dart';
+import 'package:observatory/src/elements/nav/vm_menu.dart';
+import 'package:observatory/src/elements/sample_buffer_control.dart';
+import 'package:observatory/src/elements/stack_trace_tree_config.dart';
-List<String> sorted(Set<String> attributes) {
- var list = attributes.toList();
- list.sort();
- return list;
-}
+class CpuProfileElement extends HtmlElement implements Renderable {
+ static const tag = const Tag<CpuProfileElement>('cpu-profile',
+ dependencies: const [
+ NavBarElement.tag,
+ NavTopMenuElement.tag,
+ NavVMMenuElement.tag,
+ NavIsolateMenuElement.tag,
+ NavMenuElement.tag,
+ NavMenuElement.tag,
+ NavRefreshElement.tag,
+ NavNotifyElement.tag,
+ SampleBufferControlElement.tag,
+ StackTraceTreeConfigElement.tag,
+ CpuProfileVirtualTreeElement.tag,
+ ]);
-abstract class ProfileTreeRow<T> extends TableTreeRow {
- final CpuProfile profile;
- final T node;
- final String selfPercent;
- final String percent;
- bool _infoBoxShown = false;
- HtmlElement infoBox;
- HtmlElement infoButton;
+ RenderingScheduler<CpuProfileElement> _r;
- ProfileTreeRow(TableTree tree, TableTreeRow parent,
- this.profile, this.node, double selfPercent, double percent)
- : super(tree, parent),
- selfPercent = Utils.formatPercentNormalized(selfPercent),
- percent = Utils.formatPercentNormalized(percent);
+ Stream<RenderedEvent<CpuProfileElement>> get onRendered => _r.onRendered;
- static _addToMemberList(DivElement memberList, Map<String, String> items) {
- items.forEach((k, v) {
- var item = new DivElement();
- item.classes.add('memberItem');
- var name = new DivElement();
- name.classes.add('memberName');
- name.text = k;
- var value = new DivElement();
- value.classes.add('memberValue');
- value.text = v;
- item.children.add(name);
- item.children.add(value);
- memberList.children.add(item);
- });
+ M.VM _vm;
+ M.IsolateRef _isolate;
+ M.EventRepository _events;
+ M.NotificationRepository _notifications;
+ M.IsolateSampleProfileRepository _profiles;
+ Stream<M.SampleProfileLoadingProgressEvent> _progressStream;
+ M.SampleProfileLoadingProgress _progress;
+ M.SampleProfileTag _tag = M.SampleProfileTag.none;
+ ProfileTreeMode _mode = ProfileTreeMode.function;
+ M.ProfileTreeDirection _direction = M.ProfileTreeDirection.exclusive;
+ String _filter = '';
+
+
+ M.IsolateRef get isolate => _isolate;
+ M.NotificationRepository get notifications => _notifications;
+ M.IsolateSampleProfileRepository get profiles => _profiles;
+ M.VMRef get vm => _vm;
+
+ factory CpuProfileElement(M.VM vm, M.IsolateRef isolate,
+ M.EventRepository events,
+ M.NotificationRepository notifications,
+ M.IsolateSampleProfileRepository profiles,
+ {RenderingQueue queue}) {
+ assert(vm != null);
+ assert(isolate != null);
+ assert(events != null);
+ assert(notifications != null);
+ assert(profiles != null);
+ CpuProfileElement e = document.createElement(tag.name);
+ e._r = new RenderingScheduler(e, queue: queue);
+ e._vm = vm;
+ e._isolate = isolate;
+ e._events = events;
+ e._notifications = notifications;
+ e._profiles = profiles;
+ return e;
}
- makeInfoBox() {
- if (infoBox != null) {
- return;
- }
- infoBox = new DivElement();
- infoBox.classes.add('infoBox');
- infoBox.classes.add('shadow');
- infoBox.style.display = 'none';
- listeners.add(infoBox.onClick.listen((e) => e.stopPropagation()));
- }
-
- makeInfoButton() {
- infoButton = new SpanElement();
- infoButton.style.marginLeft = 'auto';
- infoButton.style.marginRight = '1em';
- infoButton.children.add(new Element.tag('icon-info-outline'));
- listeners.add(infoButton.onClick.listen((event) {
- event.stopPropagation();
- toggleInfoBox();
- }));
- }
-
- static const attributes = const {
- 'optimized' : const ['O', null, 'Optimized'],
- 'unoptimized' : const ['U', null, 'Unoptimized'],
- 'inlined' : const ['I', null, 'Inlined'],
- 'intrinsic' : const ['It', null, 'Intrinsic'],
- 'ffi' : const ['F', null, 'FFI'],
- 'dart' : const ['D', null, 'Dart'],
- 'tag' : const ['T', null, 'Tag'],
- 'native' : const ['N', null, 'Native'],
- 'stub': const ['S', null, 'Stub'],
- 'synthetic' : const ['?', null, 'Synthetic'],
- };
-
- HtmlElement newAttributeBox(String attribute) {
- List attributeDetails = attributes[attribute];
- if (attributeDetails == null) {
- print('could not find attribute $attribute');
- return null;
- }
- var element = new SpanElement();
- element.style.border = 'solid 2px #ECECEC';
- element.style.height = '100%';
- element.style.display = 'inline-block';
- element.style.textAlign = 'center';
- element.style.minWidth = '1.5em';
- element.style.fontWeight = 'bold';
- if (attributeDetails[1] != null) {
- element.style.backgroundColor = attributeDetails[1];
- }
- element.text = attributeDetails[0];
- element.title = attributeDetails[2];
- return element;
- }
-
- onHide() {
- super.onHide();
- infoBox = null;
- infoButton = null;
- }
-
- showInfoBox() {
- if ((infoButton == null) || (infoBox == null)) {
- return;
- }
- _infoBoxShown = true;
- infoBox.style.display = 'block';
- infoButton.children.clear();
- infoButton.children.add(new Element.tag('icon-info'));
- }
-
- hideInfoBox() {
- _infoBoxShown = false;
- if ((infoButton == null) || (infoBox == null)) {
- return;
- }
- infoBox.style.display = 'none';
- infoButton.children.clear();
- infoButton.children.add(new Element.tag('icon-info-outline'));
- }
-
- toggleInfoBox() {
- if (_infoBoxShown) {
- hideInfoBox();
- } else {
- showInfoBox();
- }
- }
-
- hideAllInfoBoxes() {
- final List<ProfileTreeRow> rows = tree.rows;
- for (var row in rows) {
- row.hideInfoBox();
- }
- }
-
- onClick(MouseEvent e) {
- e.stopPropagation();
- if (e.altKey) {
- bool show = !_infoBoxShown;
- hideAllInfoBoxes();
- if (show) {
- showInfoBox();
- }
- return;
- }
- super.onClick(e);
- }
-
- HtmlElement newCodeRef(ProfileCode code) {
- var codeRef = new Element.tag('code-ref');
- codeRef.ref = code.code;
- return codeRef;
- }
-
- HtmlElement newFunctionRef(ProfileFunction function) {
- var ref = new Element.tag('function-ref');
- ref.ref = function.function;
- return ref;
- }
-
- HtmlElement hr() {
- var element = new HRElement();
- return element;
- }
-
- HtmlElement div(String text) {
- var element = new DivElement();
- element.text = text;
- return element;
- }
-
- HtmlElement br() {
- return new BRElement();
- }
-
- HtmlElement span(String text) {
- var element = new SpanElement();
- element.style.minWidth = '1em';
- element.text = text;
- return element;
- }
-}
-
-class CodeProfileTreeRow extends ProfileTreeRow<CodeCallTreeNode> {
- CodeProfileTreeRow(TableTree tree, CodeProfileTreeRow parent,
- CpuProfile profile, CodeCallTreeNode node)
- : super(tree, parent, profile, node,
- node.profileCode.normalizedExclusiveTicks,
- node.percentage) {
- // fill out attributes.
- }
-
- bool hasChildren() => node.children.length > 0;
-
- void onShow() {
- super.onShow();
-
- if (children.length == 0) {
- for (var childNode in node.children) {
- var row = new CodeProfileTreeRow(tree, this, profile, childNode);
- children.add(row);
- }
- }
-
- // Fill in method column.
- var methodColumn = flexColumns[0];
- methodColumn.style.justifyContent = 'flex-start';
- methodColumn.style.position = 'relative';
-
- // Percent.
- var percentNode = new DivElement();
- percentNode.text = percent;
- percentNode.style.minWidth = '5em';
- percentNode.style.textAlign = 'right';
- percentNode.title = 'Executing: $selfPercent';
- methodColumn.children.add(percentNode);
-
- // Gap.
- var gap = new SpanElement();
- gap.style.minWidth = '1em';
- methodColumn.children.add(gap);
-
- // Code link.
- var codeRef = newCodeRef(node.profileCode);
- codeRef.style.alignSelf = 'center';
- methodColumn.children.add(codeRef);
-
- gap = new SpanElement();
- gap.style.minWidth = '1em';
- methodColumn.children.add(gap);
-
- for (var attribute in sorted(node.attributes)) {
- methodColumn.children.add(newAttributeBox(attribute));
- }
-
- makeInfoBox();
- methodColumn.children.add(infoBox);
-
- infoBox.children.add(span('Code '));
- infoBox.children.add(newCodeRef(node.profileCode));
- infoBox.children.add(span(' '));
- for (var attribute in sorted(node.profileCode.attributes)) {
- infoBox.children.add(newAttributeBox(attribute));
- }
- infoBox.children.add(br());
- infoBox.children.add(br());
- var memberList = new DivElement();
- memberList.classes.add('memberList');
- infoBox.children.add(br());
- infoBox.children.add(memberList);
- ProfileTreeRow._addToMemberList(memberList, {
- 'Exclusive ticks' : node.profileCode.formattedExclusiveTicks,
- 'Cpu time' : node.profileCode.formattedCpuTime,
- 'Inclusive ticks' : node.profileCode.formattedInclusiveTicks,
- 'Call stack time' : node.profileCode.formattedOnStackTime,
- });
-
- makeInfoButton();
- methodColumn.children.add(infoButton);
-
- // Fill in self column.
- var selfColumn = flexColumns[1];
- selfColumn.style.position = 'relative';
- selfColumn.style.alignItems = 'center';
- selfColumn.text = selfPercent;
- }
-}
-
-class FunctionProfileTreeRow extends ProfileTreeRow<FunctionCallTreeNode> {
- FunctionProfileTreeRow(TableTree tree, FunctionProfileTreeRow parent,
- CpuProfile profile, FunctionCallTreeNode node)
- : super(tree, parent, profile, node,
- node.profileFunction.normalizedExclusiveTicks,
- node.percentage) {
- // fill out attributes.
- }
-
- bool hasChildren() => node.children.length > 0;
-
- onShow() {
- super.onShow();
- if (children.length == 0) {
- for (var childNode in node.children) {
- var row = new FunctionProfileTreeRow(tree, this, profile, childNode);
- children.add(row);
- }
- }
-
- var methodColumn = flexColumns[0];
- methodColumn.style.justifyContent = 'flex-start';
-
- var codeAndFunctionColumn = new DivElement();
- codeAndFunctionColumn.classes.add('flex-column');
- codeAndFunctionColumn.style.justifyContent = 'center';
- codeAndFunctionColumn.style.width = '100%';
- methodColumn.children.add(codeAndFunctionColumn);
-
- var functionRow = new DivElement();
- functionRow.classes.add('flex-row');
- functionRow.style.position = 'relative';
- functionRow.style.justifyContent = 'flex-start';
- codeAndFunctionColumn.children.add(functionRow);
-
- // Insert the parent percentage
- var parentPercent = new SpanElement();
- parentPercent.text = percent;
- parentPercent.style.minWidth = '4em';
- parentPercent.style.alignSelf = 'center';
- parentPercent.style.textAlign = 'right';
- parentPercent.title = 'Executing: $selfPercent';
- functionRow.children.add(parentPercent);
-
- // Gap.
- var gap = new SpanElement();
- gap.style.minWidth = '1em';
- gap.text = ' ';
- functionRow.children.add(gap);
-
- var functionRef = new Element.tag('function-ref');
- functionRef.ref = node.profileFunction.function;
- functionRef.style.alignSelf = 'center';
- functionRow.children.add(functionRef);
-
- gap = new SpanElement();
- gap.style.minWidth = '1em';
- gap.text = ' ';
- functionRow.children.add(gap);
-
- for (var attribute in sorted(node.attributes)) {
- functionRow.children.add(newAttributeBox(attribute));
- }
-
- makeInfoBox();
- functionRow.children.add(infoBox);
-
- if (M.hasDartCode(node.profileFunction.function.kind)) {
- infoBox.children.add(div('Code for current node'));
- infoBox.children.add(br());
- var totalTicks = node.totalCodesTicks;
- var numCodes = node.codes.length;
- for (var i = 0; i < numCodes; i++) {
- var codeRowSpan = new DivElement();
- codeRowSpan.style.paddingLeft = '1em';
- infoBox.children.add(codeRowSpan);
- var nodeCode = node.codes[i];
- var ticks = nodeCode.ticks;
- var percentage = Utils.formatPercent(ticks, totalTicks);
- var percentageSpan = new SpanElement();
- percentageSpan.style.display = 'inline-block';
- percentageSpan.text = '$percentage';
- percentageSpan.style.minWidth = '5em';
- percentageSpan.style.textAlign = 'right';
- codeRowSpan.children.add(percentageSpan);
- var codeRef = new Element.tag('code-ref');
- codeRef.ref = nodeCode.code.code;
- codeRef.style.marginLeft = '1em';
- codeRef.style.marginRight = 'auto';
- codeRef.style.width = '100%';
- codeRowSpan.children.add(codeRef);
- }
- infoBox.children.add(hr());
- }
- infoBox.children.add(span('Function '));
- infoBox.children.add(newFunctionRef(node.profileFunction));
- infoBox.children.add(span(' '));
- for (var attribute in sorted(node.profileFunction.attributes)) {
- infoBox.children.add(newAttributeBox(attribute));
- }
- var memberList = new DivElement();
- memberList.classes.add('memberList');
- infoBox.children.add(br());
- infoBox.children.add(br());
- infoBox.children.add(memberList);
- infoBox.children.add(br());
- ProfileTreeRow._addToMemberList(memberList, {
- 'Exclusive ticks' : node.profileFunction.formattedExclusiveTicks,
- 'Cpu time' : node.profileFunction.formattedCpuTime,
- 'Inclusive ticks' : node.profileFunction.formattedInclusiveTicks,
- 'Call stack time' : node.profileFunction.formattedOnStackTime,
- });
-
- if (M.hasDartCode(node.profileFunction.function.kind)) {
- infoBox.children.add(div('Code containing function'));
- infoBox.children.add(br());
- var totalTicks = profile.sampleCount;
- var codes = node.profileFunction.profileCodes;
- var numCodes = codes.length;
- for (var i = 0; i < numCodes; i++) {
- var codeRowSpan = new DivElement();
- codeRowSpan.style.paddingLeft = '1em';
- infoBox.children.add(codeRowSpan);
- var profileCode = codes[i];
- var code = profileCode.code;
- var ticks = profileCode.inclusiveTicks;
- var percentage = Utils.formatPercent(ticks, totalTicks);
- var percentageSpan = new SpanElement();
- percentageSpan.style.display = 'inline-block';
- percentageSpan.text = '$percentage';
- percentageSpan.style.minWidth = '5em';
- percentageSpan.style.textAlign = 'right';
- percentageSpan.title = 'Inclusive ticks';
- codeRowSpan.children.add(percentageSpan);
- var codeRef = new Element.tag('code-ref');
- codeRef.ref = code;
- codeRef.style.marginLeft = '1em';
- codeRef.style.marginRight = 'auto';
- codeRef.style.width = '100%';
- codeRowSpan.children.add(codeRef);
- }
- }
-
- makeInfoButton();
- methodColumn.children.add(infoButton);
-
- // Fill in self column.
- var selfColumn = flexColumns[1];
- selfColumn.style.position = 'relative';
- selfColumn.style.alignItems = 'center';
- selfColumn.text = selfPercent;
- }
-}
-
-@CustomTag('sample-buffer-control')
-class SampleBufferControlElement extends ObservatoryElement {
- SampleBufferControlElement.created() : super.created() {
- _stopWatch.start();
- }
-
- Future<CpuProfile> reload(Isolate isolate) async {
- profile.clear();
- if (isolate == null) {
- _update(profile);
- // Notify listener.
- onSampleBufferUpdate(profile);
- return profile;
- }
- profileVM = isolate.vm.profileVM;
- if (tagSelector == null) {
- // Set default value.
- tagSelector = profileVM ? 'UserVM' : 'None';
- }
- await _changeState(kFetchingState);
- try {
- var response;
- if (allocationProfileClass != null) {
- response =
- await allocationProfileClass.getAllocationSamples(tagSelector);
- } else {
- var params = { 'tags': tagSelector };
- response = await isolate.invokeRpc('_getCpuProfile', params);
- }
- await _changeState(kLoadingState);
- profile.load(isolate, response);
- profile.buildFunctionCallerAndCallees();
- _update(profile);
- await _changeState(kLoadedState);
- // Notify listener.
- onSampleBufferUpdate(profile);
- return profile;
- } catch (e, st) {
- if (e is ServerRpcException) {
- ServerRpcException se = e;
- if (se.code == ServerRpcException.kFeatureDisabled) {
- await _changeState(kDisabledState);
- return profile;
- }
- }
- await _changeState(kExceptionState, e, st);
- rethrow;
- }
- }
-
- Future _changeState(String newState, [exception, stackTrace]) {
- if ((newState == kDisabledState) ||
- (newState == kFetchingState) ||
- (newState == kExceptionState)) {
- loadTime = '';
- fetchTime = '';
- } else if (newState == kLoadingState) {
- fetchTime = formatTimeMilliseconds(_stopWatch.elapsedMilliseconds);
- loadTime = '';
- } else if (newState == kLoadedState) {
- loadTime = formatTimeMilliseconds(_stopWatch.elapsedMilliseconds);
- }
- state = newState;
- this.exception = exception;
- this.stackTrace = stackTrace;
- _stopWatch.reset();
- return window.animationFrame;
- }
-
- _update(CpuProfile sampleBuffer) {
- sampleCount = profile.sampleCount.toString();
- refreshTime = new DateTime.now().toString();
- stackDepth = profile.stackDepth.toString();
- sampleRate = profile.sampleRate.toStringAsFixed(0);
- if (profile.sampleCount == 0) {
- timeSpan = '0s';
- } else {
- timeSpan = formatTime(profile.timeSpan);
- }
- }
-
- void tagSelectorChanged(oldValue) {
- reload(profile.isolate);
- }
-
- Function onSampleBufferUpdate;
- @observable bool showTagSelector = true;
- @observable bool profileVM = false;
- @observable String sampleCount = '';
- @observable String refreshTime = '';
- @observable String sampleRate = '';
- @observable String stackDepth = '';
- @observable String timeSpan = '';
- @observable String fetchTime = '';
- @observable String loadTime = '';
- @observable String tagSelector;
- @observable String state = kFetchingState;
- @observable var exception;
- @observable var stackTrace;
-
- static const kDisabledState = 'kDisabled';
- static const kExceptionState = 'Exception';
- static const kFetchingState = 'kFetching';
- static const kLoadedState = 'kLoaded';
- static const kLoadingState = 'kLoading';
- static const kNotLoadedState = 'kNotLoaded';
-
- Isolate isolate;
- Class allocationProfileClass;
-
- final CpuProfile profile = new CpuProfile();
- final Stopwatch _stopWatch = new Stopwatch();
-}
-
-@CustomTag('stack-trace-tree-config')
-class StackTraceTreeConfigElement extends ObservatoryElement {
- StackTraceTreeConfigElement.created() : super.created();
-
- attached() {
- super.attached();
- var filterElement = shadowRoot.querySelector('#filterInput');
- keyDownSubscription = filterElement.onKeyDown.listen(_onKeyDown);
- blurSubscription = filterElement.onBlur.listen(_onBlur);
- }
-
- detached() {
- super.detached();
- keyDownSubscription?.cancel();
- blurSubscription?.cancel();
- }
-
- void _onKeyDown(KeyboardEvent keyEvent) {
- if (keyEvent.keyCode == 13) {
- // On enter, update the filter string.
- filterString =
- (shadowRoot.querySelector('#filterInput') as InputElement).value;
- if (onTreeConfigChange == null) {
- return;
- }
- onTreeConfigChange(modeSelector, directionSelector, filterString);
- }
- }
-
- void _onBlur(Event event) {
- // Input box has lost focus, update the display to match the active
- // filter string.
- (shadowRoot.querySelector('#filterInput') as InputElement).value =
- filterString;
- }
-
- void modeSelectorChanged(oldValue) {
- if (onTreeConfigChange == null) {
- return;
- }
- onTreeConfigChange(modeSelector, directionSelector, filterString);
- }
-
- void directionSelectorChanged(oldValue) {
- if (onTreeConfigChange == null) {
- return;
- }
- onTreeConfigChange(modeSelector, directionSelector, filterString);
- }
-
- Function onTreeConfigChange;
- StreamSubscription keyDownSubscription;
- StreamSubscription blurSubscription;
- @observable bool show = true;
- @observable bool showModeSelector = true;
- @observable bool showDirectionSelector = true;
- @observable bool showFilter = true;
- @observable String modeSelector = 'Function';
- @observable String directionSelector = 'Up';
- @observable String filterString;
-}
-
-class FunctionCallTreeNodeRow extends VirtualTreeRow {
- final CpuProfile profile;
- final FunctionCallTreeNode node;
- String selfPercent;
- String totalPercent;
- String percent;
-
- static const kHotThreshold = 0.05; // 5%.
- static const kMediumThreshold = 0.02; // 2%.
-
- double _percent(bool self) {
- if (self) {
- return node.profileFunction.normalizedExclusiveTicks;
- } else {
- return node.profileFunction.normalizedInclusiveTicks;
- }
- }
-
- bool isHot(bool self) => _percent(self) > kHotThreshold;
- bool isMedium(bool self) => _percent(self) > kMediumThreshold;
-
- String rowClass(bool self) {
- if (isHot(self)) {
- return 'hotProfile';
- } else if (isMedium(self)) {
- return 'mediumProfile';
- } else {
- return 'coldProfile';
- }
- }
-
- FunctionCallTreeNodeRow(VirtualTree tree,
- int depth,
- this.profile,
- FunctionCallTreeNode node)
- : node = node,
- super(tree, depth) {
- if ((node.profileFunction.function.kind == M.FunctionKind.tag) &&
- (node.profileFunction.normalizedExclusiveTicks == 0) &&
- (node.profileFunction.normalizedInclusiveTicks == 0)) {
- selfPercent = '';
- totalPercent = '';
- } else {
- selfPercent = Utils.formatPercentNormalized(
- node.profileFunction.normalizedExclusiveTicks);
- totalPercent = Utils.formatPercentNormalized(
- node.profileFunction.normalizedInclusiveTicks);
- }
- percent = Utils.formatPercentNormalized(node.percentage);
- }
-
- void onRender(DivElement rowDiv) {
- rowDiv.children.add(makeGap(ems:0.1));
- rowDiv.children.add(
- makeText(totalPercent,
- toolTip: 'global % on stack'));
- rowDiv.children.add(makeGap());
- rowDiv.children.add(
- makeText(selfPercent,
- toolTip: 'global % executing'));
- rowDiv.children.add(makeGap());
- rowDiv.children.add(makeIndenter(depth, colored: false));
- rowDiv.children.add(makeColorBar(depth));
- rowDiv.children.add(makeGap(ems: 1.0));
- rowDiv.children.add(makeExpander());
- rowDiv.children.add(
- makeText(percent, toolTip: 'tree node %', flexBasis: null));
- rowDiv.children.add(makeGap(ems: 0.5));
- functionRef.ref = node.profileFunction.function;
- rowDiv.children.add(functionRef);
- }
-
- var functionRef = new Element.tag('function-ref');
-
- int get childCount => node.children.length;
-
- void onShow() {
- if (children.length > 0) {
- return;
- }
- for (var childNode in node.children) {
- var row = new FunctionCallTreeNodeRow(tree, depth + 1, profile, childNode);
- children.add(row);
- }
- }
-}
-
-
-class CodeCallTreeNodeRow extends VirtualTreeRow {
- final CpuProfile profile;
- final CodeCallTreeNode node;
- String selfPercent;
- String totalPercent;
- String percent;
-
- static const kHotThreshold = 0.05; // 5%.
- static const kMediumThreshold = 0.02; // 2%.
-
- double _percent(bool self) {
- if (self) {
- return node.profileCode.normalizedExclusiveTicks;
- } else {
- return node.profileCode.normalizedInclusiveTicks;
- }
- }
-
- bool isHot(bool self) => _percent(self) > kHotThreshold;
- bool isMedium(bool self) => _percent(self) > kMediumThreshold;
-
- String rowClass(bool self) {
- if (isHot(self)) {
- return 'hotProfile';
- } else if (isMedium(self)) {
- return 'mediumProfile';
- } else {
- return 'coldProfile';
- }
- }
-
- CodeCallTreeNodeRow(VirtualTree tree,
- int depth,
- this.profile,
- CodeCallTreeNode node)
- : node = node,
- super(tree, depth) {
- if ((node.profileCode.code.kind == M.CodeKind.tag) &&
- (node.profileCode.normalizedExclusiveTicks == 0) &&
- (node.profileCode.normalizedInclusiveTicks == 0)) {
- selfPercent = '';
- totalPercent = '';
- } else {
- selfPercent = Utils.formatPercentNormalized(
- node.profileCode.normalizedExclusiveTicks);
- totalPercent = Utils.formatPercentNormalized(
- node.profileCode.normalizedInclusiveTicks);
- }
- percent = Utils.formatPercentNormalized(node.percentage);
- }
-
- void onRender(DivElement rowDiv) {
- rowDiv.children.add(makeGap(ems:0.1));
- rowDiv.children.add(
- makeText(totalPercent,
- toolTip: 'global % on stack'));
- rowDiv.children.add(makeGap());
- rowDiv.children.add(
- makeText(selfPercent,
- toolTip: 'global % executing'));
- rowDiv.children.add(makeGap());
- rowDiv.children.add(makeIndenter(depth, colored: false));
- rowDiv.children.add(makeColorBar(depth));
- rowDiv.children.add(makeGap(ems: 1.0));
- rowDiv.children.add(makeExpander());
- rowDiv.children.add(
- makeText(percent, toolTip: 'tree node %', flexBasis: null));
- rowDiv.children.add(makeGap(ems: 0.5));
- codeRef.ref = node.profileCode.code;
- rowDiv.children.add(codeRef);
- }
-
- var codeRef = new Element.tag('code-ref');
-
- int get childCount => node.children.length;
-
- void onShow() {
- if (children.length > 0) {
- return;
- }
- for (var childNode in node.children) {
- var row = new CodeCallTreeNodeRow(tree, depth + 1, profile, childNode);
- children.add(row);
- }
- }
-}
-
-/// Displays a CpuProfile
-@CustomTag('cpu-profile')
-class CpuProfileElement extends ObservatoryElement {
- CpuProfileElement.created() : super.created() {
- _updateTask = new Task(update);
- _renderTask = new Task(render);
- }
-
- attached() {
- super.attached();
- sampleBufferControlElement =
- shadowRoot.querySelector('#sampleBufferControl');
- assert(sampleBufferControlElement != null);
- sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange;
- stackTraceTreeConfigElement =
- shadowRoot.querySelector('#stackTraceTreeConfig');
- assert(stackTraceTreeConfigElement != null);
- stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange;
- cpuProfileVirtualTreeElement = shadowRoot.querySelector('#cpuProfileVirtualTree');
- assert(cpuProfileVirtualTreeElement != null);
- cpuProfileVirtualTreeElement.profile = sampleBufferControlElement.profile;
- _resizeSubscription = window.onResize.listen((_) => _updateSize());
- _updateTask.queue();
- _updateSize();
- }
-
- detached() {
- super.detached();
- if (_resizeSubscription != null) {
- _resizeSubscription.cancel();
- }
- }
-
- _updateSize() {
- var applySize = (e) {
- Rectangle rect = e.getBoundingClientRect();
- final totalHeight = window.innerHeight;
- final bottomMargin = 200;
- final mainHeight = totalHeight - bottomMargin;
- e.style.setProperty('height', '${mainHeight}px');
- };
- HtmlElement e2 = $['cpuProfileVirtualTree'];
- applySize(e2);
- }
-
- isolateChanged(oldValue) {
- _updateTask.queue();
- }
-
- update() {
- if (sampleBufferControlElement != null) {
- sampleBufferControlElement.reload(isolate);
- }
- }
-
- onSampleBufferChange(CpuProfile sampleBuffer) {
- _renderTask.queue();
- }
-
- onTreeConfigChange(String modeSelector,
- String directionSelector,
- String filterString) {
- ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
- if (directionSelector != 'Up') {
- direction = ProfileTreeDirection.Inclusive;
- }
- ProfileTreeMode mode = ProfileTreeMode.Function;
- if (modeSelector == 'Code') {
- mode = ProfileTreeMode.Code;
- }
- // Clear the filter.
- cpuProfileVirtualTreeElement.filter = null;
- if (filterString != null) {
- filterString = filterString.trim();
- if (filterString.isNotEmpty) {
- cpuProfileVirtualTreeElement.filter = (CallTreeNode node) {
- return node.name.contains(filterString);
- };
- }
- }
- cpuProfileVirtualTreeElement.direction = direction;
- cpuProfileVirtualTreeElement.mode = mode;
- _renderTask.queue();
- }
-
- Future clearCpuProfile() async {
- await isolate.invokeRpc('_clearCpuProfile', { });
- _updateTask.queue();
- return new Future.value(null);
- }
-
- Future refresh() {
- _updateTask.queue();
- return new Future.value(null);
- }
-
- render() {
- cpuProfileVirtualTreeElement.render();
- }
-
- @published Isolate isolate;
-
- StreamSubscription _resizeSubscription;
- Task _updateTask;
- Task _renderTask;
- SampleBufferControlElement sampleBufferControlElement;
- StackTraceTreeConfigElement stackTraceTreeConfigElement;
- CpuProfileVirtualTreeElement cpuProfileVirtualTreeElement;
-}
+ CpuProfileElement.created() : super.created();
-class NameSortedTable extends SortedTable {
- NameSortedTable(columns) : super(columns);
@override
- dynamic getSortKeyFor(int row, int col) {
- if (col == FUNCTION_COLUMN) {
- // Use name as sort key.
- return rows[row].values[col].name;
- }
- return super.getSortKeyFor(row, col);
- }
-
- SortedTableRow rowFromIndex(int tableIndex) {
- final modelIndex = sortedRows[tableIndex];
- return rows[modelIndex];
- }
-
- static const FUNCTION_SPACER_COLUMNS = const [];
- static const FUNCTION_COLUMN = 2;
- TableRowElement _makeFunctionRow() {
- var tr = new TableRowElement();
- var cell;
-
- // Add percentage.
- cell = tr.insertCell(-1);
- cell = tr.insertCell(-1);
-
- // Add function ref.
- cell = tr.insertCell(-1);
- var functionRef = new Element.tag('function-ref');
- cell.children.add(functionRef);
-
- return tr;
- }
-
- static const CALL_SPACER_COLUMNS = const [];
- static const CALL_FUNCTION_COLUMN = 1;
- TableRowElement _makeCallRow() {
- var tr = new TableRowElement();
- var cell;
-
- // Add percentage.
- cell = tr.insertCell(-1);
- // Add function ref.
- cell = tr.insertCell(-1);
- var functionRef = new Element.tag('function-ref');
- cell.children.add(functionRef);
- return tr;
- }
-
- _updateRow(TableRowElement tr,
- int rowIndex,
- List spacerColumns,
- int refColumn) {
- var row = rows[rowIndex];
- // Set reference
- var ref = tr.children[refColumn].children[0];
- ref.ref = row.values[refColumn];
-
- for (var i = 0; i < row.values.length; i++) {
- if (spacerColumns.contains(i) || (i == refColumn)) {
- // Skip spacer columns.
- continue;
- }
- var cell = tr.children[i];
- cell.title = row.values[i].toString();
- cell.text = getFormattedValue(rowIndex, i);
- }
- }
-
- _updateTableView(HtmlElement table,
- HtmlElement makeEmptyRow(),
- void onRowClick(TableRowElement tr),
- List spacerColumns,
- int refColumn) {
- assert(table != null);
-
- // Resize DOM table.
- if (table.children.length > sortedRows.length) {
- // Shrink the table.
- var deadRows = table.children.length - sortedRows.length;
- for (var i = 0; i < deadRows; i++) {
- table.children.removeLast();
- }
- } else if (table.children.length < sortedRows.length) {
- // Grow table.
- var newRows = sortedRows.length - table.children.length;
- for (var i = 0; i < newRows; i++) {
- var row = makeEmptyRow();
- row.onClick.listen((e) {
- e.stopPropagation();
- e.preventDefault();
- onRowClick(row);
- });
- table.children.add(row);
- }
- }
-
- assert(table.children.length == sortedRows.length);
-
- // Fill table.
- for (var i = 0; i < sortedRows.length; i++) {
- var rowIndex = sortedRows[i];
- var tr = table.children[i];
- _updateRow(tr, rowIndex, spacerColumns, refColumn);
- }
- }
-}
-
-@CustomTag('cpu-profile-table')
-class CpuProfileTableElement extends ObservatoryElement {
- CpuProfileTableElement.created() : super.created() {
- _updateTask = new Task(update);
- _renderTask = new Task(render);
- var columns = [
- new SortedTableColumn.withFormatter('Executing (%)',
- Utils.formatPercentNormalized),
- new SortedTableColumn.withFormatter('In stack (%)',
- Utils.formatPercentNormalized),
- new SortedTableColumn('Method'),
- ];
- profileTable = new NameSortedTable(columns);
- profileTable.sortColumnIndex = 0;
-
- columns = [
- new SortedTableColumn.withFormatter('Callees (%)',
- Utils.formatPercentNormalized),
- new SortedTableColumn('Method')
- ];
- profileCalleesTable = new NameSortedTable(columns);
- profileCalleesTable.sortColumnIndex = 0;
-
- columns = [
- new SortedTableColumn.withFormatter('Callers (%)',
- Utils.formatPercentNormalized),
- new SortedTableColumn('Method')
- ];
- profileCallersTable = new NameSortedTable(columns);
- profileCallersTable.sortColumnIndex = 0;
- }
-
attached() {
super.attached();
- sampleBufferControlElement =
- shadowRoot.querySelector('#sampleBufferControl');
- assert(sampleBufferControlElement != null);
- sampleBufferControlElement.onSampleBufferUpdate = onSampleBufferChange;
- // Disable the tag selector- we always want no tags.
- sampleBufferControlElement.tagSelector = 'None';
- sampleBufferControlElement.showTagSelector = false;
- stackTraceTreeConfigElement =
- shadowRoot.querySelector('#stackTraceTreeConfig');
- assert(stackTraceTreeConfigElement != null);
- stackTraceTreeConfigElement.onTreeConfigChange = onTreeConfigChange;
- stackTraceTreeConfigElement.modeSelector = 'Function';
- stackTraceTreeConfigElement.showModeSelector = false;
- stackTraceTreeConfigElement.directionSelector = 'Down';
- stackTraceTreeConfigElement.showDirectionSelector = false;
- cpuProfileTreeElement = shadowRoot.querySelector('#cpuProfileTree');
- assert(cpuProfileTreeElement != null);
- cpuProfileTreeElement.profile = sampleBufferControlElement.profile;
- _updateTask.queue();
- _resizeSubscription = window.onResize.listen((_) => _updateSize());
- _updateSize();
+ _r.enable();
+ _request();
}
+ @override
detached() {
- super.detached();
- if (_resizeSubscription != null) {
- _resizeSubscription.cancel();
- }
- }
-
- _updateSize() {
- HtmlElement e = $['main'];
- final totalHeight = window.innerHeight;
- final top = e.offset.top;
- final bottomMargin = 32;
- final mainHeight = totalHeight - top - bottomMargin;
- e.style.setProperty('height', '${mainHeight}px');
- }
-
- isolateChanged(oldValue) {
- _updateTask.queue();
- }
-
- update() {
- _clearView();
- if (sampleBufferControlElement != null) {
- sampleBufferControlElement.reload(isolate).whenComplete(checkParameters);
- }
- }
-
- onSampleBufferChange(CpuProfile sampleBuffer) {
- _renderTask.queue();
- }
-
- onTreeConfigChange(String modeSelector,
- String directionSelector,
- String filterString) {
- ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
- if (directionSelector != 'Up') {
- direction = ProfileTreeDirection.Inclusive;
- }
- ProfileTreeMode mode = ProfileTreeMode.Function;
- if (modeSelector == 'Code') {
- mode = ProfileTreeMode.Code;
- }
- cpuProfileTreeElement.direction = direction;
- cpuProfileTreeElement.mode = mode;
- _renderTask.queue();
- }
-
- Future clearCpuProfile() async {
- await isolate.invokeRpc('_clearCpuProfile', { });
- _updateTask.queue();
- return new Future.value(null);
- }
-
- Future refresh() {
- _updateTask.queue();
- return new Future.value(null);
- }
-
- render() {
- _updateView();
- }
-
- checkParameters() {
- if (isolate == null) {
- return;
- }
- var functionId = app.locationManager.uri.queryParameters['functionId'];
- var functionName =
- app.locationManager.uri.queryParameters['functionName'];
- if (functionId == '') {
- // Fallback to searching by name.
- _focusOnFunction(_findFunction(functionName));
- } else {
- if (functionId == null) {
- _focusOnFunction(null);
- return;
- }
- isolate.getObject(functionId).then((func) => _focusOnFunction(func));
- }
- }
-
- _clearView() {
- profileTable.clearRows();
- _renderTable();
- }
-
- _updateView() {
- _buildFunctionTable();
- _renderTable();
- _updateFunctionTreeView();
- }
-
- int _findFunctionRow(ServiceFunction function) {
- for (var i = 0; i < profileTable.sortedRows.length; i++) {
- var rowIndex = profileTable.sortedRows[i];
- var row = profileTable.rows[rowIndex];
- if (row.values[NameSortedTable.FUNCTION_COLUMN] == function) {
- return i;
- }
- }
- return -1;
- }
-
- _scrollToFunction(ServiceFunction function) {
- TableSectionElement tableBody = $['profile-table'];
- var row = _findFunctionRow(function);
- if (row == -1) {
- return;
- }
- tableBody.children[row].classes.remove('shake');
- // trigger reflow.
- tableBody.children[row].offsetHeight;
- tableBody.children[row].scrollIntoView(ScrollAlignment.CENTER);
- tableBody.children[row].classes.add('shake');
- // Focus on clicked function.
- _focusOnFunction(function);
- }
-
- _clearFocusedFunction() {
- TableSectionElement tableBody = $['profile-table'];
- // Clear current focus.
- if (focusedRow != null) {
- tableBody.children[focusedRow].classes.remove('focused');
- }
- focusedRow = null;
- focusedFunction = null;
- }
-
- ServiceFunction _findFunction(String functionName) {
- for (var func in profile.functions) {
- if (func.function.name == functionName) {
- return func.function;
- }
- }
- return null;
- }
-
- _focusOnFunction(ServiceFunction function) {
- if (focusedFunction == function) {
- // Do nothing.
- return;
- }
-
- _clearFocusedFunction();
-
- if (function == null) {
- _updateFunctionTreeView();
- _clearCallTables();
- return;
- }
-
- var row = _findFunctionRow(function);
- if (row == -1) {
- _updateFunctionTreeView();
- _clearCallTables();
- return;
- }
-
- focusedRow = row;
- focusedFunction = function;
-
- TableSectionElement tableBody = $['profile-table'];
- tableBody.children[focusedRow].classes.add('focused');
- _updateFunctionTreeView();
- _buildCallersTable(focusedFunction);
- _buildCalleesTable(focusedFunction);
- }
-
- _onRowClick(TableRowElement tr) {
- var tableBody = $['profile-table'];
- var row = profileTable.rowFromIndex(tableBody.children.indexOf(tr));
- var function = row.values[NameSortedTable.FUNCTION_COLUMN];
- app.locationManager.goReplacingParameters(
- {
- 'functionId': function.id,
- 'functionName': function.vmName
- }
- );
- }
-
- _renderTable() {
- profileTable._updateTableView($['profile-table'],
- profileTable._makeFunctionRow,
- _onRowClick,
- NameSortedTable.FUNCTION_SPACER_COLUMNS,
- NameSortedTable.FUNCTION_COLUMN);
- }
-
- _buildFunctionTable() {
- for (var func in profile.functions) {
- if ((func.exclusiveTicks == 0) && (func.inclusiveTicks == 0)) {
- // Skip.
- continue;
- }
- var row = [
- func.normalizedExclusiveTicks,
- func.normalizedInclusiveTicks,
- func.function,
- ];
- profileTable.addRow(new SortedTableRow(row));
- }
- profileTable.sort();
- }
-
- _renderCallTable(TableSectionElement view,
- NameSortedTable model,
- void onRowClick(TableRowElement tr)) {
- model._updateTableView(view,
- model._makeCallRow,
- onRowClick,
- NameSortedTable.CALL_SPACER_COLUMNS,
- NameSortedTable.CALL_FUNCTION_COLUMN);
- }
-
- _buildCallTable(Map<ProfileFunction, int> calls,
- NameSortedTable model) {
- model.clearRows();
- if (calls == null) {
- return;
- }
- var sum = 0;
- calls.values.forEach((i) => sum += i);
- calls.forEach((func, count) {
- var row = [
- count / sum,
- func.function,
- ];
- model.addRow(new SortedTableRow(row));
- });
- model.sort();
- }
-
- _clearCallTables() {
- _buildCallersTable(null);
- _buildCalleesTable(null);
- }
-
- _onCallersClick(TableRowElement tr) {
- var table = $['callers-table'];
- final row = profileCallersTable.rowFromIndex(table.children.indexOf(tr));
- var function = row.values[NameSortedTable.CALL_FUNCTION_COLUMN];
- _scrollToFunction(function);
- }
-
- _buildCallersTable(ServiceFunction function) {
- var calls = (function != null) ? function.profile.callers : null;
- var table = $['callers-table'];
- _buildCallTable(calls, profileCallersTable);
- _renderCallTable(table, profileCallersTable, _onCallersClick);
- }
-
- _onCalleesClick(TableRowElement tr) {
- var table = $['callees-table'];
- final row = profileCalleesTable.rowFromIndex(table.children.indexOf(tr));
- var function = row.values[NameSortedTable.CALL_FUNCTION_COLUMN];
- _scrollToFunction(function);
- }
-
- _buildCalleesTable(ServiceFunction function) {
- var calls = (function != null) ? function.profile.callees : null;
- var table = $['callees-table'];
- _buildCallTable(calls, profileCalleesTable);
- _renderCallTable(table, profileCalleesTable, _onCalleesClick);
- }
-
- _changeSort(Element target, NameSortedTable table) {
- if (target is TableCellElement) {
- if (table.sortColumnIndex != target.cellIndex) {
- table.sortColumnIndex = target.cellIndex;
- table.sortDescending = true;
- } else {
- table.sortDescending = !profileTable.sortDescending;
- }
- table.sort();
- }
- }
-
- changeSortProfile(Event e, var detail, Element target) {
- _changeSort(target, profileTable);
- _renderTable();
- }
-
- changeSortCallers(Event e, var detail, Element target) {
- _changeSort(target, profileCallersTable);
- _renderCallTable($['callers-table'], profileCallersTable, _onCallersClick);
- }
-
- changeSortCallees(Event e, var detail, Element target) {
- _changeSort(target, profileCalleesTable);
- _renderCallTable($['callees-table'], profileCalleesTable, _onCalleesClick);
- }
-
- //////
- ///
- /// Function tree.
- ///
- TableTree functionTree;
- _updateFunctionTreeView() {
- cpuProfileTreeElement.filter = (FunctionCallTreeNode node) {
- return node.profileFunction.function == focusedFunction;
- };
- cpuProfileTreeElement.render();
- }
-
- @published Isolate isolate;
- @observable NameSortedTable profileTable;
- @observable NameSortedTable profileCallersTable;
- @observable NameSortedTable profileCalleesTable;
- @observable ServiceFunction focusedFunction;
- @observable int focusedRow;
-
-
- StreamSubscription _resizeSubscription;
- Task _updateTask;
- Task _renderTask;
-
- CpuProfile get profile => sampleBufferControlElement.profile;
- SampleBufferControlElement sampleBufferControlElement;
- StackTraceTreeConfigElement stackTraceTreeConfigElement;
- CpuProfileVirtualTreeElement cpuProfileTreeElement;
-}
-
-enum ProfileTreeDirection {
- Exclusive,
- Inclusive
-}
-
-enum ProfileTreeMode {
- Code,
- Function,
-}
-
-@CustomTag('cpu-profile-virtual-tree')
-class CpuProfileVirtualTreeElement extends ObservatoryElement {
- ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
- ProfileTreeMode mode = ProfileTreeMode.Function;
- CpuProfile profile;
- VirtualTree virtualTree;
- CallTreeNodeFilter filter;
- StreamSubscription _resizeSubscription;
- @observable bool show = true;
-
- CpuProfileVirtualTreeElement.created() : super.created();
-
- attached() {
- super.attached();
- _resizeSubscription = window.onResize.listen((_) => _updateSize());
- }
-
- detached() {
- super.detached();
- _resizeSubscription?.cancel();
+ super.detached(); _r.disable(notify: true);
+ children = [];
}
void render() {
- _updateView();
- }
-
- showChanged(oldValue) {
- if (show) {
- virtualTree?.root?.style?.display = 'block';
- } else {
- virtualTree?.root?.style?.display = 'none';
- }
- }
-
- void _updateView() {
- _updateSize();
- virtualTree?.clear();
- virtualTree?.uninstall();
- virtualTree = null;
- bool exclusive = direction == ProfileTreeDirection.Exclusive;
- if (mode == ProfileTreeMode.Code) {
- _buildCodeTree(exclusive);
- } else {
- assert(mode == ProfileTreeMode.Function);
- _buildFunctionTree(exclusive);
- }
- virtualTree?.refresh();
- }
-
- void _updateSize() {
- var treeBody = shadowRoot.querySelector('#tree');
- assert(treeBody != null);
- int windowHeight = window.innerHeight - 32;
- treeBody.style.height = '${windowHeight}px';
- }
-
- void _buildFunctionTree(bool exclusive) {
- var treeBody = shadowRoot.querySelector('#tree');
- assert(treeBody != null);
- virtualTree = new VirtualTree(32, treeBody);
- if (profile == null) {
+ var content = [
+ new NavBarElement(queue: _r.queue)
+ ..children = [
+ new NavTopMenuElement(queue: _r.queue),
+ new NavVMMenuElement(_vm, _events, queue: _r.queue),
+ new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
+ new NavMenuElement('cpu profile', link: Uris.profiler(_isolate),
+ last: true, queue: _r.queue),
+ new NavRefreshElement(queue: _r.queue)
+ ..onRefresh.listen(_refresh),
+ new NavRefreshElement(label: 'Clear', queue: _r.queue)
+ ..onRefresh.listen(_clearCpuProfile),
+ new NavNotifyElement(_notifications, queue: _r.queue)
+ ],
+ ];
+ if (_progress == null) {
+ children = content;
return;
}
- var tree = profile.loadFunctionTree(exclusive ? 'exclusive' : 'inclusive');
- if (tree == null) {
- return;
+ content.add(new SampleBufferControlElement(_progress, _progressStream,
+ selectedTag: _tag, queue: _r.queue)
+ ..onTagChange.listen((e) {
+ _tag = e.element.selectedTag;
+ _request();
+ }));
+ if (_progress.status == M.SampleProfileLoadingStatus.loaded) {
+ CpuProfileVirtualTreeElement tree;
+ content.addAll([
+ new BRElement(),
+ new StackTraceTreeConfigElement(mode: _mode, direction: _direction,
+ filter: _filter, queue: _r.queue)
+ ..onModeChange.listen((e) {
+ _mode = tree.mode = e.element.mode;
+ })
+ ..onFilterChange.listen((e) {
+ _filter = e.element.filter.trim();
+ tree.filter = _filter.isNotEmpty
+ ? (node) { return node.name.contains(_filter); }
+ : null;
+ })
+ ..onDirectionChange.listen((e) {
+ _direction = tree.direction = e.element.direction;
+ }),
+ new BRElement(),
+ tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
+ queue: _r.queue)
+ ]);
}
- if (filter != null) {
- tree = tree.filtered(filter);
- }
- for (var child in tree.root.children) {
- virtualTree.rows.add(
- new FunctionCallTreeNodeRow(virtualTree, 0, profile, child));
- }
- if (virtualTree.rows.length == 1) {
- virtualTree.rows[0].expanded = true;
+ children = content;
+ }
+
+ Future _request({bool clear: false, bool forceFetch: false}) async {
+ _progress = null;
+ _progressStream = _profiles.get(isolate, _tag, clear: clear,
+ forceFetch: forceFetch);
+ _r.dirty();
+ _progress = (await _progressStream.first).progress;
+ _r.dirty();
+ if (M.isSampleProcessRunning(_progress.status)) {
+ _progress = (await _progressStream.last).progress;
+ _r.dirty();
}
}
- void _buildCodeTree(bool exclusive) {
- var treeBody = shadowRoot.querySelector('#tree');
- assert(treeBody != null);
- virtualTree = new VirtualTree(32, treeBody);
- if (profile == null) {
- return;
- }
- var tree = profile.loadCodeTree(exclusive ? 'exclusive' : 'inclusive');
- if (tree == null) {
- return;
- }
- if (filter != null) {
- tree = tree.filtered(filter);
- }
- for (var child in tree.root.children) {
- virtualTree.rows.add(
- new CodeCallTreeNodeRow(virtualTree, 0, profile, child));
- }
- if (virtualTree.rows.length == 1) {
- virtualTree.rows[0].expanded = true;
- }
- }
-}
-
-@CustomTag('cpu-profile-tree')
-class CpuProfileTreeElement extends ObservatoryElement {
- ProfileTreeDirection direction = ProfileTreeDirection.Exclusive;
- ProfileTreeMode mode = ProfileTreeMode.Function;
- CpuProfile profile;
- TableTree codeTree;
- TableTree functionTree;
- CallTreeNodeFilter functionFilter;
- @observable bool show = true;
-
- CpuProfileTreeElement.created() : super.created();
-
- void render() {
- _updateView();
+ Future _clearCpuProfile(RefreshEvent e) async {
+ e.element.disabled = true;
+ await _request(clear: true);
+ e.element.disabled = false;
}
- showChanged(oldValue) {
- var treeTable = shadowRoot.querySelector('#treeTable');
- assert(treeTable != null);
- treeTable.style.display = show ? 'table' : 'none';
- }
-
- void _updateView() {
- if (functionTree != null) {
- functionTree.clear();
- functionTree = null;
- }
- if (codeTree != null) {
- codeTree.clear();
- codeTree = null;
- }
- bool exclusive = direction == ProfileTreeDirection.Exclusive;
- if (mode == ProfileTreeMode.Code) {
- _buildCodeTree(exclusive);
- } else {
- assert(mode == ProfileTreeMode.Function);
- _buildFunctionTree(exclusive);
- }
- }
-
- void _buildFunctionTree(bool exclusive) {
- if (functionTree == null) {
- var tableBody = shadowRoot.querySelector('#treeBody');
- assert(tableBody != null);
- functionTree = new TableTree(tableBody, 2);
- }
- if (profile == null) {
- return;
- }
- var tree = profile.loadFunctionTree(exclusive ? 'exclusive' : 'inclusive');
- if (tree == null) {
- return;
- }
- if (functionFilter != null) {
- tree = tree.filtered(functionFilter);
- }
- var rootRow =
- new FunctionProfileTreeRow(functionTree, null, profile, tree.root);
- functionTree.initialize(rootRow);
- }
-
- void _buildCodeTree(bool exclusive) {
- if (codeTree == null) {
- var tableBody = shadowRoot.querySelector('#treeBody');
- assert(tableBody != null);
- codeTree = new TableTree(tableBody, 2);
- }
- if (profile == null) {
- return;
- }
- var tree = profile.loadCodeTree(exclusive ? 'exclusive' : 'inclusive');
- if (tree == null) {
- return;
- }
- var rootRow = new CodeProfileTreeRow(codeTree, null, profile, tree.root);
- codeTree.initialize(rootRow);
+ Future _refresh(e) async {
+ e.element.disabled = true;
+ await _request(forceFetch: true);
+ e.element.disabled = false;
}
}
diff --git a/runtime/observatory/lib/src/elements/cpu_profile.html b/runtime/observatory/lib/src/elements/cpu_profile.html
deleted file mode 100644
index 32363c7..0000000
--- a/runtime/observatory/lib/src/elements/cpu_profile.html
+++ /dev/null
@@ -1,515 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<polymer-element name="sample-buffer-control">
- <template>
- <link rel="stylesheet" href="css/shared.css">
- <style>
- .statusMessage {
- font-size: 150%;
- font-weight: bold;
- }
-
- .statusBox {
- height: 100%;
- padding: 1em;
- }
-
- .center {
- align-items: center;
- justify-content: center;
- }
-
- .notice {
- background-color: #fcf8e3;
- }
-
- .red {
- background-color: #f2dede;
- }
- </style>
- <div class="content-centered-big">
- <template if="{{ state != 'kNotLoaded' }}">
- <h2>Sample buffer</h2>
- <hr>
- </template>
- <template if="{{ state == 'kFetching' }}">
- <div class="statusBox shadow center">
- <div class="statusMessage">Fetching profile from VM...</div>
- </div>
- </template>
- <template if="{{ state == 'kLoading' }}">
- <div class="statusBox shadow center">
- <div class="statusMessage">Loading profile...</div>
- </div>
- </template>
- <template if="{{ state == 'kDisabled' }}">
- <div class="statusBox shadow center">
- <div>
- <h1>Profiling is disabled</h1>
- <br>
- Perhaps the <b>profile</b> flag has been disabled for this VM.
- <br><br>
- See all
- <a on-click="{{ goto }}" _href="{{ gotoLink('/flags') }}">vm flags</a>
- </div>
- </div>
- </template>
- <template if="{{ state == 'kException' }}">
- <div class="statusBox shadow center">
- <div class="statusMessage">
- <h1>Profiling is disabled due to unexpected exception:</h1>
- <br>
- <pre>{{ exception.toString() }}</pre>
- <br>
- <h1>Stack trace:</h1>
- <br>
- <pre>{{ stackTrace.toString() }}</pre>
- </div>
- </div>
- </template>
- <template if="{{ state == 'kLoaded' }}">
- <div class="memberList">
- <div class="memberItem">
- <div class="memberName">Refreshed at </div>
- <div class="memberValue">{{ refreshTime }} (fetched in {{ fetchTime }}) (loaded in {{ loadTime }})</div>
- </div>
- <div class="memberItem">
- <div class="memberName">Profile contains</div>
- <div class="memberValue">{{ sampleCount }} samples (spanning {{ timeSpan }})</div>
- </div>
- <div class="memberItem">
- <div class="memberName">Sampling</div>
- <div class="memberValue">{{ stackDepth }} stack frames @ {{ sampleRate }} Hz</div>
- </div>
- <template if="{{ showTagSelector }}">
- <div class="memberItem">
- <div class="memberName">Tag Order</div>
- <div class="memberValue">
- <template if="{{ profileVM }}">
- <select value="{{tagSelector}}">
- <option value="UserVM">User > VM</option>
- <option value="UserOnly">User</option>
- <option value="VMUser">VM > User</option>
- <option value="VMOnly">VM</option>
- <option value="None">None</option>
- </select>
- </template>
- <template if="{{ !profileVM }}">
- <select value="{{tagSelector}}">
- <option value="UserOnly">User</option>
- <option value="None">None</option>
- </select>
- </template>
- </div>
- </div>
- </template>
- </div>
- </template>
- </div>
- </template>
-</polymer-element>
-
-<polymer-element name="stack-trace-tree-config">
- <template>
- <link rel="stylesheet" href="css/shared.css">
- <style>
- .statusBox {
- height: 100%;
- padding: 0.5em;
- }
- .row {
- display: flex;
- }
- </style>
- <div class="content-centered-big">
- <template if="{{ show }}">
- <h2>Tree display</h2>
- <hr>
- <div class="row">
- <div>
- <div class="memberList">
- <template if="{{ showModeSelector }}">
- <div class="memberItem">
- <div class="memberName">Mode</div>
- <div class="memberValue">
- <select value="{{modeSelector}}">
- <option value="Code">Code</option>
- <option value="Function">Function</option>
- </select>
- </div>
- </div>
- </template>
- <template if="{{ showDirectionSelector }}">
- <div class="memberItem">
- <div class="memberName">Call Tree Direction</div>
- <span class="memberValue">
- <select value="{{directionSelector}}">
- <option value="Down">Top down</option>
- <option value="Up">Bottom up</option>
- </select>
- <template if="{{ directionSelector == 'Down' }}">
- <span>
- Tree is rooted at "main". Child nodes are callees.
- </span>
- </template>
- <template if="{{ directionSelector == 'Up' }}">
- <span>
- Tree is rooted at executing function / code. Child nodes are callers.
- </span>
- </template>
- </span>
- </div>
- </template>
- <template if="{{ showFilter }}">
- <div class="memberItem">
- <div title="case-sensitive substring match" class="memberName">Call Tree Filter</div>
- <span class="memberValue">
- <input type="text" placeholder="Search filter" id="filterInput">
- </span>
- </div>
- </template>
- </div>
- </div>
- </div>
- </template>
- </div>
- </template>
-</polymer-element>
-
-<polymer-element name="cpu-profile-tree">
- <template>
- <link rel="stylesheet" href="css/shared.css">
- <style>
- .infoBox {
- position: absolute;
- top: 100%;
- left: 0%;
- z-index: 999;
- opacity: 1;
- padding: 1em;
- background-color: #ffffff;
- border-left: solid 2px #ECECEC;
- border-bottom: solid 2px #ECECEC;
- border-right: solid 2px #ECECEC;
- }
- .full-width {
- width: 100%;
- }
- .tree {
- border-spacing: 0px;
- width: 100%;
- margin-bottom: 20px
- vertical-align: middle;
- }
- .tree tbody tr {
- animation: fadeIn 0.5s;
- -moz-animation: fadeIn 0.5s;
- -webkit-animation: fadeIn 0.5s;
- }
- .tree tbody tr:hover {
- background-color: #FAFAFA;
- }
- .tree tr td:first-child,
- .tree tr th:first-child {
- width: 100%;
- }
- .tree thead > tr > th {
- padding: 8px;
- vertical-align: bottom;
- text-align: left;
- border-bottom: 1px solid #ddd;
- }
- tr {
- background-color: #FFFFFF;
- }
- tbody tr {
- animation: fadeIn 0.5s;
- -moz-animation: fadeIn 0.5s;
- -webkit-animation: fadeIn 0.5s;
- }
- tbody tr:hover {
- background-color: #FAFAFA;
- }
- tr td:first-child,
- tr th:first-child {
- width: 100%;
- }
- </style>
- <table id="treeTable" class="full-width tree">
- <thead id="treeHeader">
- <tr>
- <th>Method</th>
- <th>Executing</th>
- </tr>
- </thead>
- <tbody id="treeBody">
- </tbody>
- </table>
- </template>
-</polymer-element>
-
-<polymer-element name="cpu-profile-virtual-tree">
- <template>
- <link rel="stylesheet" href="css/shared.css">
- <style>
- .full {
- height: 50%;
- width: 100%;
- }
- .coldProfile {
- background-color: #aea;
- }
- .mediumProfile {
- background-color: #fe9;
- }
- .hotProfile {
- background-color: #faa;
- }
- </style>
- <div id="tree" class="full"></div>
- </template>
-</polymer-element>
-
-
-<polymer-element name="cpu-profile-table">
- <template>
- <link rel="stylesheet" href="css/shared.css">
- <nav-bar>
- <top-nav-menu></top-nav-menu>
- <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
- <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
- <nav-menu link="{{ makeLink('/profiler-table', isolate) }}" anchor="cpu profile (table)" last="{{ true }}"></nav-menu>
- <nav-refresh callback="{{ refresh }}"></nav-refresh>
- <nav-refresh callback="{{ clearCpuProfile }}" label="Clear"></nav-refresh>
- <nav-notify notifications="{{ app.notifications }}"></nav-notify>
- </nav-bar>
- <style>
- /* general */
- .well {
- background-color: #ECECEC;
- padding: 0.2em;
- }
- .center {
- align-items: center;
- justify-content: center;
- }
-
- /* status messages */
- .statusMessage {
- font-size: 150%;
- font-weight: bold;
- }
- .statusBox {
- height: 100%;
- padding: 1em;
- }
-
- /* tables */
- .table {
- border-collapse: collapse!important;
- table-layout: fixed;
- height: 100%;
- }
- .th, .td {
- padding: 8px;
- vertical-align: top;
- }
- .table thead > tr > th {
- vertical-align: bottom;
- text-align: left;
- border-bottom:2px solid #ddd;
- }
- .spacer {
- width: 16px;
- }
- .left-border-spacer {
- width: 16px;
- border-left: 1px solid;
- }
- .clickable {
- color: #0489c3;
- text-decoration: none;
- cursor: pointer;
- min-width: 8em;
- }
- .clickable:hover {
- text-decoration: underline;
- cursor: pointer;
- }
- tr:hover:not(.focused) > td {
- background-color: #FAFAFA;
- }
- .focused {
- background-color: #F4C7C3;
- }
- .scroll {
- overflow: scroll;
- }
- .outlined {
- -webkit-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
- -moz-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
- box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
- margin: 4px;
- }
- .centered {
- margin-left: auto;
- margin-right: auto;
- justify-content: center;
- }
- .full-height {
- height: 100%;
- }
- .mostly-full-height {
- height: 80%;
- }
- .full-width {
- width: 100%;
- }
- .focused-function-label {
- flex: 0 1 auto;
- margin-left: auto;
- margin-right: auto;
- justify-content: center;
- }
- .call-table {
- flex: 1 1 auto;
- }
-
- .tree {
- border-spacing: 0px;
- width: 100%;
- margin-bottom: 20px
- vertical-align: middle;
- }
-
- .tree tbody tr {
- animation: fadeIn 0.5s;
- -moz-animation: fadeIn 0.5s;
- -webkit-animation: fadeIn 0.5s;
- }
-
- .tree tbody tr:hover {
- background-color: #FAFAFA;
- }
-
- .tree tr td:first-child,
- .tree tr th:first-child {
- width: 100%;
- }
-
- .tree thead > tr > th {
- padding: 8px;
- vertical-align: bottom;
- text-align: left;
- border-bottom: 1px solid #ddd;
- }
-
- </style>
- <sample-buffer-control id="sampleBufferControl"></sample-buffer-control>
- <br>
- <hr>
- <div id="main" class="flex-row centered">
- <div class="flex-item-45-percent full-height outlined scroll">
- <table id="main-table" class="flex-item-100-percent table">
- <thead>
- <tr>
- <th on-click="{{changeSortProfile}}" class="clickable" title="Executing (%)">{{ profileTable.getColumnLabel(0) }}</th>
- <th on-click="{{changeSortProfile}}" class="clickable" title="In stack (%)">{{ profileTable.getColumnLabel(1) }}</th>
- <th on-click="{{changeSortProfile}}" class="clickable" title="Method">{{ profileTable.getColumnLabel(2) }}</th>
- </tr>
- </thead>
- <tbody id="profile-table">
- </tbody>
- </table>
- </div>
- <div class="flex-item-45-percent full-height outlined">
- <div class="flex-column full-height">
- <div class="focused-function-label">
- <template if="{{ focusedFunction != null }}">
- <span>Focused on: </span>
- <function-ref ref="{{ focusedFunction }}"></function-ref>
- </template>
- <template if="{{ focusedFunction == null }}">
- <span>No focused function</span>
- </template>
- </div>
- <hr>
- <div class="call-table scroll">
- <table class="full-width table">
- <thead>
- <tr>
- <th on-click="{{changeSortCallers}}" class="clickable" title="Callers (%)">{{ profileCallersTable.getColumnLabel(0) }}</th>
- <th on-click="{{changeSortCallers}}" class="clickable" title="Method">{{ profileCallersTable.getColumnLabel(1) }}</th>
- </tr>
- </thead>
- <tbody id="callers-table">
- </tbody>
- </table>
- </div>
- <hr>
- <div class="call-table scroll">
- <table class="full-width table">
- <thead>
- <tr>
- <th on-click="{{changeSortCallees}}" class="clickable" title="Callees (%)">{{ profileCalleesTable.getColumnLabel(0) }}</th>
- <th on-click="{{changeSortCallees}}" class="clickable" title="Method">{{ profileCalleesTable.getColumnLabel(1) }}</th>
- </tr>
- </thead>
- <tbody id="callees-table">
- </tbody>
- </table>
- </div>
- </div>
- </div>
- </div>
- <br>
- <stack-trace-tree-config id="stackTraceTreeConfig"></stack-trace-tree-config>
- <br>
- <div class="content-centered-big">
- <div class="focused-function-label">
- <template if="{{ focusedFunction != null }}">
- <span>Filtered tree: </span>
- <function-ref ref="{{ focusedFunction }}"></function-ref>
- </template>
- <template if="{{ focusedFunction == null }}">
- <span>No focused function</span>
- </template>
- </div>
- </div>
- <br>
- <br>
- <div class="flex-row centered">
- <div class="flex-item-90-percent outlined" style="margin: 16px; margin-left: 8px; margin-right: 8px">
- <cpu-profile-virtual-tree id="cpuProfileTree"></cpu-profile-virtual-tree>
- </div>
- </div>
- </template>
-</polymer-element>
-
-<polymer-element name="cpu-profile">
- <template>
- <link rel="stylesheet" href="css/shared.css">
- <nav-bar>
- <top-nav-menu></top-nav-menu>
- <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
- <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
- <nav-menu link="{{ makeLink('/profiler', isolate) }}" anchor="cpu profile" last="{{ true }}"></nav-menu>
- <nav-refresh callback="{{ refresh }}"></nav-refresh>
- <nav-refresh callback="{{ clearCpuProfile }}" label="Clear"></nav-refresh>
- <nav-notify notifications="{{ app.notifications }}"></nav-notify>
- </nav-bar>
- <style>
- .tableWell {
- background-color: #ECECEC;
- padding: 0.2em;
- }
- </style>
- <sample-buffer-control id="sampleBufferControl"></sample-buffer-control>
- <br>
- <stack-trace-tree-config id="stackTraceTreeConfig"></stack-trace-tree-config>
- <br>
- <cpu-profile-virtual-tree id="cpuProfileVirtualTree"></cpu-profile-virtual-tree>
- </template>
-</polymer-element>
-
-<script type="application/dart" src="cpu_profile.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart b/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart
new file mode 100644
index 0000000..236b395
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/cpu_profile/virtual_tree.dart
@@ -0,0 +1,179 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:math' as Math;
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/stack_trace_tree_config.dart'
+ show ProfileTreeMode;
+import 'package:observatory/src/elements/code_ref.dart';
+import 'package:observatory/src/elements/containers/virtual_tree.dart';
+import 'package:observatory/src/elements/function_ref.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/utils.dart';
+
+export 'package:observatory/src/elements/stack_trace_tree_config.dart'
+ show ProfileTreeMode;
+
+class CpuProfileVirtualTreeElement extends HtmlElement implements Renderable {
+ static const tag =
+ const Tag<CpuProfileVirtualTreeElement>('cpu-profile-virtual-tree');
+
+ RenderingScheduler<CpuProfileVirtualTreeElement> _r;
+
+ Stream<RenderedEvent<CpuProfileVirtualTreeElement>> get onRendered =>
+ _r.onRendered;
+
+ M.ProfileTreeDirection _direction;
+ ProfileTreeMode _mode;
+ M.IsolateRef _isolate;
+ M.SampleProfile _profile;
+ M.CallTreeNodeFilter _filter;
+
+ M.ProfileTreeDirection get direction => _direction;
+ ProfileTreeMode get mode => _mode;
+ M.IsolateRef get isolate => _isolate;
+ M.SampleProfile get profile => _profile;
+ M.CallTreeNodeFilter get filter => _filter;
+
+ set direction(M.ProfileTreeDirection value) =>
+ _direction = _r.checkAndReact(_direction, value);
+ set mode(ProfileTreeMode value) => _mode = _r.checkAndReact(_mode, value);
+ set filter(M.CallTreeNodeFilter value) =>
+ _filter = _r.checkAndReact(_filter, value);
+
+ factory CpuProfileVirtualTreeElement(M.IsolateRef isolate,
+ M.SampleProfile profile, {ProfileTreeMode mode: ProfileTreeMode.function,
+ M.ProfileTreeDirection direction: M.ProfileTreeDirection.exclusive,
+ RenderingQueue queue}) {
+ assert(isolate != null);
+ assert(profile != null);
+ assert(mode != null);
+ assert(direction != null);
+ CpuProfileVirtualTreeElement e = document.createElement(tag.name);
+ e._r = new RenderingScheduler(e, queue: queue);
+ e._isolate = isolate;
+ e._profile = profile;
+ e._mode = mode;
+ e._direction = direction;
+ return e;
+ }
+
+ CpuProfileVirtualTreeElement.created() : super.created();
+
+ @override
+ attached() {
+ super.attached();
+ _r.enable();
+ }
+
+ @override
+ detached() {
+ super.detached();
+ _r.disable(notify: true);
+ children = [];
+ }
+
+ VirtualTreeElement _tree;
+
+ void render() {
+ var tree;
+ var update;
+ switch (mode) {
+ case ProfileTreeMode.code:
+ tree = _profile.loadCodeTree(_direction);
+ update = _updateCodeRow;
+ break;
+ case ProfileTreeMode.function:
+ tree = _profile.loadFunctionTree(_direction);
+ update = _updateFunctionRow;
+ break;
+ default:
+ throw new Exception('Unknown ProfileTreeMode: $mode');
+ }
+ if (tree == null) {
+ children = [
+ new HeadingElement.h1()..text = 'No Results'
+ ];
+ return;
+ }
+ if (filter != null) {
+ tree = tree.filtered(filter);
+ }
+ _tree = new VirtualTreeElement(_createRow, update, _getChildren,
+ items: tree.root.children, queue: _r.queue);
+ if (tree.root.children.length == 1) {
+ _tree.expand(tree.root.children.first, autoExpandSingleChildNodes: true);
+ }
+ children = [_tree];
+ }
+
+ static Element _createRow(toggle) {
+ return new DivElement()
+ ..classes = const ['tree-item']
+ ..children = [
+ new SpanElement()..classes = const ['inclusive']
+ ..title = 'global % on stack',
+ new SpanElement()..classes = const ['exclusive']
+ ..title = 'global % executing',
+ new SpanElement()..classes = const ['lines'],
+ new ButtonElement()..classes = const ['expander']
+ ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
+ new SpanElement()..classes = const ['percentage']
+ ..title = 'tree node %',
+ new SpanElement()..classes = const ['name']
+ ];
+ }
+
+ static _getChildren(M.CallTreeNode node) => node.children;
+
+ void _updateFunctionRow(HtmlElement element, M.FunctionCallTreeNode item,
+ int depth) {
+ element.children[0].text = Utils.formatPercentNormalized(
+ item.profileFunction.normalizedInclusiveTicks);
+ element.children[1].text = Utils.formatPercentNormalized(
+ item.profileFunction.normalizedExclusiveTicks);
+ _updateLines(element.children[2].children, depth);
+ if (item.children.isNotEmpty) {
+ element.children[3].text = _tree.isExpanded(item) ? 'â–¼' : 'â–º';
+ } else {
+ element.children[3].text = '';
+ }
+ element.children[4].text = Utils.formatPercentNormalized(
+ item.percentage);
+ element.children[5] = new FunctionRefElement(_isolate,
+ item.profileFunction.function, queue: _r.queue)
+ ..classes = const ['name'];
+ }
+
+ void _updateCodeRow(HtmlElement element, M.CodeCallTreeNode item, int depth) {
+ element.children[0].text = Utils.formatPercentNormalized(
+ item.profileCode.normalizedInclusiveTicks);
+ element.children[1].text = Utils.formatPercentNormalized(
+ item.profileCode.normalizedExclusiveTicks);
+ _updateLines(element.children[2].children, depth);
+ if (item.children.isNotEmpty) {
+ element.children[3].text = _tree.isExpanded(item) ? 'â–¼' : 'â–º';
+ } else {
+ element.children[3].text = '';
+ }
+ element.children[4].text = Utils.formatPercentNormalized(
+ item.percentage);
+ element.children[5] = new CodeRefElement(_isolate,
+ item.profileCode.code, queue: _r.queue)
+ ..classes = const ['name'];
+ }
+
+ static _updateLines(List<Element> lines, int n) {
+ n = Math.max(0, n);
+ while (lines.length > n) {
+ lines.removeLast();
+ }
+ while (lines.length < n) {
+ lines.add(new SpanElement());
+ }
+ }
+}
diff --git a/runtime/observatory/lib/src/elements/cpu_profile_table.dart b/runtime/observatory/lib/src/elements/cpu_profile_table.dart
new file mode 100644
index 0000000..2a76e17
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/cpu_profile_table.dart
@@ -0,0 +1,929 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library cpu_profile_table_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'observatory_element.dart';
+import 'sample_buffer_control.dart';
+import 'stack_trace_tree_config.dart';
+import 'cpu_profile/virtual_tree.dart';
+import 'package:observatory/service.dart';
+import 'package:observatory/app.dart';
+import 'package:observatory/cpu_profile.dart';
+import 'package:observatory/elements.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/repositories.dart';
+import 'package:polymer/polymer.dart';
+
+List<String> sorted(Set<String> attributes) {
+ var list = attributes.toList();
+ list.sort();
+ return list;
+}
+
+abstract class ProfileTreeRow<T> extends TableTreeRow {
+ final CpuProfile profile;
+ final T node;
+ final String selfPercent;
+ final String percent;
+ bool _infoBoxShown = false;
+ HtmlElement infoBox;
+ HtmlElement infoButton;
+
+ ProfileTreeRow(TableTree tree, TableTreeRow parent,
+ this.profile, this.node, double selfPercent, double percent)
+ : super(tree, parent),
+ selfPercent = Utils.formatPercentNormalized(selfPercent),
+ percent = Utils.formatPercentNormalized(percent);
+
+ static _addToMemberList(DivElement memberList, Map<String, String> items) {
+ items.forEach((k, v) {
+ var item = new DivElement();
+ item.classes.add('memberItem');
+ var name = new DivElement();
+ name.classes.add('memberName');
+ name.text = k;
+ var value = new DivElement();
+ value.classes.add('memberValue');
+ value.text = v;
+ item.children.add(name);
+ item.children.add(value);
+ memberList.children.add(item);
+ });
+ }
+
+ makeInfoBox() {
+ if (infoBox != null) {
+ return;
+ }
+ infoBox = new DivElement();
+ infoBox.classes.add('infoBox');
+ infoBox.classes.add('shadow');
+ infoBox.style.display = 'none';
+ listeners.add(infoBox.onClick.listen((e) => e.stopPropagation()));
+ }
+
+ makeInfoButton() {
+ infoButton = new SpanElement();
+ infoButton.style.marginLeft = 'auto';
+ infoButton.style.marginRight = '1em';
+ infoButton.children.add(new Element.tag('icon-info-outline'));
+ listeners.add(infoButton.onClick.listen((event) {
+ event.stopPropagation();
+ toggleInfoBox();
+ }));
+ }
+
+ static const attributes = const {
+ 'optimized' : const ['O', null, 'Optimized'],
+ 'unoptimized' : const ['U', null, 'Unoptimized'],
+ 'inlined' : const ['I', null, 'Inlined'],
+ 'intrinsic' : const ['It', null, 'Intrinsic'],
+ 'ffi' : const ['F', null, 'FFI'],
+ 'dart' : const ['D', null, 'Dart'],
+ 'tag' : const ['T', null, 'Tag'],
+ 'native' : const ['N', null, 'Native'],
+ 'stub': const ['S', null, 'Stub'],
+ 'synthetic' : const ['?', null, 'Synthetic'],
+ };
+
+ HtmlElement newAttributeBox(String attribute) {
+ List attributeDetails = attributes[attribute];
+ if (attributeDetails == null) {
+ print('could not find attribute $attribute');
+ return null;
+ }
+ var element = new SpanElement();
+ element.style.border = 'solid 2px #ECECEC';
+ element.style.height = '100%';
+ element.style.display = 'inline-block';
+ element.style.textAlign = 'center';
+ element.style.minWidth = '1.5em';
+ element.style.fontWeight = 'bold';
+ if (attributeDetails[1] != null) {
+ element.style.backgroundColor = attributeDetails[1];
+ }
+ element.text = attributeDetails[0];
+ element.title = attributeDetails[2];
+ return element;
+ }
+
+ onHide() {
+ super.onHide();
+ infoBox = null;
+ infoButton = null;
+ }
+
+ showInfoBox() {
+ if ((infoButton == null) || (infoBox == null)) {
+ return;
+ }
+ _infoBoxShown = true;
+ infoBox.style.display = 'block';
+ infoButton.children.clear();
+ infoButton.children.add(new Element.tag('icon-info'));
+ }
+
+ hideInfoBox() {
+ _infoBoxShown = false;
+ if ((infoButton == null) || (infoBox == null)) {
+ return;
+ }
+ infoBox.style.display = 'none';
+ infoButton.children.clear();
+ infoButton.children.add(new Element.tag('icon-info-outline'));
+ }
+
+ toggleInfoBox() {
+ if (_infoBoxShown) {
+ hideInfoBox();
+ } else {
+ showInfoBox();
+ }
+ }
+
+ hideAllInfoBoxes() {
+ final List<ProfileTreeRow> rows = tree.rows;
+ for (var row in rows) {
+ row.hideInfoBox();
+ }
+ }
+
+ onClick(MouseEvent e) {
+ e.stopPropagation();
+ if (e.altKey) {
+ bool show = !_infoBoxShown;
+ hideAllInfoBoxes();
+ if (show) {
+ showInfoBox();
+ }
+ return;
+ }
+ super.onClick(e);
+ }
+
+ HtmlElement newCodeRef(ProfileCode code) {
+ var codeRef = new Element.tag('code-ref');
+ codeRef.ref = code.code;
+ return codeRef;
+ }
+
+ HtmlElement newFunctionRef(ProfileFunction function) {
+ var ref = new Element.tag('function-ref');
+ ref.ref = function.function;
+ return ref;
+ }
+
+ HtmlElement hr() {
+ var element = new HRElement();
+ return element;
+ }
+
+ HtmlElement div(String text) {
+ var element = new DivElement();
+ element.text = text;
+ return element;
+ }
+
+ HtmlElement br() {
+ return new BRElement();
+ }
+
+ HtmlElement span(String text) {
+ var element = new SpanElement();
+ element.style.minWidth = '1em';
+ element.text = text;
+ return element;
+ }
+}
+
+class CodeProfileTreeRow extends ProfileTreeRow<CodeCallTreeNode> {
+ CodeProfileTreeRow(TableTree tree, CodeProfileTreeRow parent,
+ CpuProfile profile, CodeCallTreeNode node)
+ : super(tree, parent, profile, node,
+ node.profileCode.normalizedExclusiveTicks,
+ node.percentage) {
+ // fill out attributes.
+ }
+
+ bool hasChildren() => node.children.length > 0;
+
+ void onShow() {
+ super.onShow();
+
+ if (children.length == 0) {
+ for (var childNode in node.children) {
+ var row = new CodeProfileTreeRow(tree, this, profile, childNode);
+ children.add(row);
+ }
+ }
+
+ // Fill in method column.
+ var methodColumn = flexColumns[0];
+ methodColumn.style.justifyContent = 'flex-start';
+ methodColumn.style.position = 'relative';
+
+ // Percent.
+ var percentNode = new DivElement();
+ percentNode.text = percent;
+ percentNode.style.minWidth = '5em';
+ percentNode.style.textAlign = 'right';
+ percentNode.title = 'Executing: $selfPercent';
+ methodColumn.children.add(percentNode);
+
+ // Gap.
+ var gap = new SpanElement();
+ gap.style.minWidth = '1em';
+ methodColumn.children.add(gap);
+
+ // Code link.
+ var codeRef = newCodeRef(node.profileCode);
+ codeRef.style.alignSelf = 'center';
+ methodColumn.children.add(codeRef);
+
+ gap = new SpanElement();
+ gap.style.minWidth = '1em';
+ methodColumn.children.add(gap);
+
+ for (var attribute in sorted(node.attributes)) {
+ methodColumn.children.add(newAttributeBox(attribute));
+ }
+
+ makeInfoBox();
+ methodColumn.children.add(infoBox);
+
+ infoBox.children.add(span('Code '));
+ infoBox.children.add(newCodeRef(node.profileCode));
+ infoBox.children.add(span(' '));
+ for (var attribute in sorted(node.profileCode.attributes)) {
+ infoBox.children.add(newAttributeBox(attribute));
+ }
+ infoBox.children.add(br());
+ infoBox.children.add(br());
+ var memberList = new DivElement();
+ memberList.classes.add('memberList');
+ infoBox.children.add(br());
+ infoBox.children.add(memberList);
+ ProfileTreeRow._addToMemberList(memberList, {
+ 'Exclusive ticks' : node.profileCode.formattedExclusiveTicks,
+ 'Cpu time' : node.profileCode.formattedCpuTime,
+ 'Inclusive ticks' : node.profileCode.formattedInclusiveTicks,
+ 'Call stack time' : node.profileCode.formattedOnStackTime,
+ });
+
+ makeInfoButton();
+ methodColumn.children.add(infoButton);
+
+ // Fill in self column.
+ var selfColumn = flexColumns[1];
+ selfColumn.style.position = 'relative';
+ selfColumn.style.alignItems = 'center';
+ selfColumn.text = selfPercent;
+ }
+}
+
+class FunctionProfileTreeRow extends ProfileTreeRow<FunctionCallTreeNode> {
+ FunctionProfileTreeRow(TableTree tree, FunctionProfileTreeRow parent,
+ CpuProfile profile, FunctionCallTreeNode node)
+ : super(tree, parent, profile, node,
+ node.profileFunction.normalizedExclusiveTicks,
+ node.percentage) {
+ // fill out attributes.
+ }
+
+ bool hasChildren() => node.children.length > 0;
+
+ onShow() {
+ super.onShow();
+ if (children.length == 0) {
+ for (var childNode in node.children) {
+ var row = new FunctionProfileTreeRow(tree, this, profile, childNode);
+ children.add(row);
+ }
+ }
+
+ var methodColumn = flexColumns[0];
+ methodColumn.style.justifyContent = 'flex-start';
+
+ var codeAndFunctionColumn = new DivElement();
+ codeAndFunctionColumn.classes.add('flex-column');
+ codeAndFunctionColumn.style.justifyContent = 'center';
+ codeAndFunctionColumn.style.width = '100%';
+ methodColumn.children.add(codeAndFunctionColumn);
+
+ var functionRow = new DivElement();
+ functionRow.classes.add('flex-row');
+ functionRow.style.position = 'relative';
+ functionRow.style.justifyContent = 'flex-start';
+ codeAndFunctionColumn.children.add(functionRow);
+
+ // Insert the parent percentage
+ var parentPercent = new SpanElement();
+ parentPercent.text = percent;
+ parentPercent.style.minWidth = '4em';
+ parentPercent.style.alignSelf = 'center';
+ parentPercent.style.textAlign = 'right';
+ parentPercent.title = 'Executing: $selfPercent';
+ functionRow.children.add(parentPercent);
+
+ // Gap.
+ var gap = new SpanElement();
+ gap.style.minWidth = '1em';
+ gap.text = ' ';
+ functionRow.children.add(gap);
+
+ var functionRef = new Element.tag('function-ref');
+ functionRef.ref = node.profileFunction.function;
+ functionRef.style.alignSelf = 'center';
+ functionRow.children.add(functionRef);
+
+ gap = new SpanElement();
+ gap.style.minWidth = '1em';
+ gap.text = ' ';
+ functionRow.children.add(gap);
+
+ for (var attribute in sorted(node.attributes)) {
+ functionRow.children.add(newAttributeBox(attribute));
+ }
+
+ makeInfoBox();
+ functionRow.children.add(infoBox);
+
+ if (M.hasDartCode(node.profileFunction.function.kind)) {
+ infoBox.children.add(div('Code for current node'));
+ infoBox.children.add(br());
+ var totalTicks = node.totalCodesTicks;
+ var numCodes = node.codes.length;
+ for (var i = 0; i < numCodes; i++) {
+ var codeRowSpan = new DivElement();
+ codeRowSpan.style.paddingLeft = '1em';
+ infoBox.children.add(codeRowSpan);
+ var nodeCode = node.codes[i];
+ var ticks = nodeCode.ticks;
+ var percentage = Utils.formatPercent(ticks, totalTicks);
+ var percentageSpan = new SpanElement();
+ percentageSpan.style.display = 'inline-block';
+ percentageSpan.text = '$percentage';
+ percentageSpan.style.minWidth = '5em';
+ percentageSpan.style.textAlign = 'right';
+ codeRowSpan.children.add(percentageSpan);
+ var codeRef = new Element.tag('code-ref');
+ codeRef.ref = nodeCode.code.code;
+ codeRef.style.marginLeft = '1em';
+ codeRef.style.marginRight = 'auto';
+ codeRef.style.width = '100%';
+ codeRowSpan.children.add(codeRef);
+ }
+ infoBox.children.add(hr());
+ }
+ infoBox.children.add(span('Function '));
+ infoBox.children.add(newFunctionRef(node.profileFunction));
+ infoBox.children.add(span(' '));
+ for (var attribute in sorted(node.profileFunction.attributes)) {
+ infoBox.children.add(newAttributeBox(attribute));
+ }
+ var memberList = new DivElement();
+ memberList.classes.add('memberList');
+ infoBox.children.add(br());
+ infoBox.children.add(br());
+ infoBox.children.add(memberList);
+ infoBox.children.add(br());
+ ProfileTreeRow._addToMemberList(memberList, {
+ 'Exclusive ticks' : node.profileFunction.formattedExclusiveTicks,
+ 'Cpu time' : node.profileFunction.formattedCpuTime,
+ 'Inclusive ticks' : node.profileFunction.formattedInclusiveTicks,
+ 'Call stack time' : node.profileFunction.formattedOnStackTime,
+ });
+
+ if (M.hasDartCode(node.profileFunction.function.kind)) {
+ infoBox.children.add(div('Code containing function'));
+ infoBox.children.add(br());
+ var totalTicks = profile.sampleCount;
+ var codes = node.profileFunction.profileCodes;
+ var numCodes = codes.length;
+ for (var i = 0; i < numCodes; i++) {
+ var codeRowSpan = new DivElement();
+ codeRowSpan.style.paddingLeft = '1em';
+ infoBox.children.add(codeRowSpan);
+ var profileCode = codes[i];
+ var code = profileCode.code;
+ var ticks = profileCode.inclusiveTicks;
+ var percentage = Utils.formatPercent(ticks, totalTicks);
+ var percentageSpan = new SpanElement();
+ percentageSpan.style.display = 'inline-block';
+ percentageSpan.text = '$percentage';
+ percentageSpan.style.minWidth = '5em';
+ percentageSpan.style.textAlign = 'right';
+ percentageSpan.title = 'Inclusive ticks';
+ codeRowSpan.children.add(percentageSpan);
+ var codeRef = new Element.tag('code-ref');
+ codeRef.ref = code;
+ codeRef.style.marginLeft = '1em';
+ codeRef.style.marginRight = 'auto';
+ codeRef.style.width = '100%';
+ codeRowSpan.children.add(codeRef);
+ }
+ }
+
+ makeInfoButton();
+ methodColumn.children.add(infoButton);
+
+ // Fill in self column.
+ var selfColumn = flexColumns[1];
+ selfColumn.style.position = 'relative';
+ selfColumn.style.alignItems = 'center';
+ selfColumn.text = selfPercent;
+ }
+}
+
+class NameSortedTable extends SortedTable {
+ NameSortedTable(columns) : super(columns);
+ @override
+ dynamic getSortKeyFor(int row, int col) {
+ if (col == FUNCTION_COLUMN) {
+ // Use name as sort key.
+ return rows[row].values[col].name;
+ }
+ return super.getSortKeyFor(row, col);
+ }
+
+ SortedTableRow rowFromIndex(int tableIndex) {
+ final modelIndex = sortedRows[tableIndex];
+ return rows[modelIndex];
+ }
+
+ static const FUNCTION_SPACER_COLUMNS = const [];
+ static const FUNCTION_COLUMN = 2;
+ TableRowElement _makeFunctionRow() {
+ var tr = new TableRowElement();
+ var cell;
+
+ // Add percentage.
+ cell = tr.insertCell(-1);
+ cell = tr.insertCell(-1);
+
+ // Add function ref.
+ cell = tr.insertCell(-1);
+ var functionRef = new Element.tag('function-ref');
+ cell.children.add(functionRef);
+
+ return tr;
+ }
+
+ static const CALL_SPACER_COLUMNS = const [];
+ static const CALL_FUNCTION_COLUMN = 1;
+ TableRowElement _makeCallRow() {
+ var tr = new TableRowElement();
+ var cell;
+
+ // Add percentage.
+ cell = tr.insertCell(-1);
+ // Add function ref.
+ cell = tr.insertCell(-1);
+ var functionRef = new Element.tag('function-ref');
+ cell.children.add(functionRef);
+ return tr;
+ }
+
+ _updateRow(TableRowElement tr,
+ int rowIndex,
+ List spacerColumns,
+ int refColumn) {
+ var row = rows[rowIndex];
+ // Set reference
+ var ref = tr.children[refColumn].children[0];
+ ref.ref = row.values[refColumn];
+
+ for (var i = 0; i < row.values.length; i++) {
+ if (spacerColumns.contains(i) || (i == refColumn)) {
+ // Skip spacer columns.
+ continue;
+ }
+ var cell = tr.children[i];
+ cell.title = row.values[i].toString();
+ cell.text = getFormattedValue(rowIndex, i);
+ }
+ }
+
+ _updateTableView(HtmlElement table,
+ HtmlElement makeEmptyRow(),
+ void onRowClick(TableRowElement tr),
+ List spacerColumns,
+ int refColumn) {
+ assert(table != null);
+
+ // Resize DOM table.
+ if (table.children.length > sortedRows.length) {
+ // Shrink the table.
+ var deadRows = table.children.length - sortedRows.length;
+ for (var i = 0; i < deadRows; i++) {
+ table.children.removeLast();
+ }
+ } else if (table.children.length < sortedRows.length) {
+ // Grow table.
+ var newRows = sortedRows.length - table.children.length;
+ for (var i = 0; i < newRows; i++) {
+ var row = makeEmptyRow();
+ row.onClick.listen((e) {
+ e.stopPropagation();
+ e.preventDefault();
+ onRowClick(row);
+ });
+ table.children.add(row);
+ }
+ }
+
+ assert(table.children.length == sortedRows.length);
+
+ // Fill table.
+ for (var i = 0; i < sortedRows.length; i++) {
+ var rowIndex = sortedRows[i];
+ var tr = table.children[i];
+ _updateRow(tr, rowIndex, spacerColumns, refColumn);
+ }
+ }
+}
+
+@CustomTag('cpu-profile-table')
+class CpuProfileTableElement extends ObservatoryElement {
+
+
+ CpuProfileTableElement.created() : super.created() {
+ _updateTask = new Task(update);
+ _renderTask = new Task(render);
+ var columns = [
+ new SortedTableColumn.withFormatter('Executing (%)',
+ Utils.formatPercentNormalized),
+ new SortedTableColumn.withFormatter('In stack (%)',
+ Utils.formatPercentNormalized),
+ new SortedTableColumn('Method'),
+ ];
+ profileTable = new NameSortedTable(columns);
+ profileTable.sortColumnIndex = 0;
+
+ columns = [
+ new SortedTableColumn.withFormatter('Callees (%)',
+ Utils.formatPercentNormalized),
+ new SortedTableColumn('Method')
+ ];
+ profileCalleesTable = new NameSortedTable(columns);
+ profileCalleesTable.sortColumnIndex = 0;
+
+ columns = [
+ new SortedTableColumn.withFormatter('Callers (%)',
+ Utils.formatPercentNormalized),
+ new SortedTableColumn('Method')
+ ];
+ profileCallersTable = new NameSortedTable(columns);
+ profileCallersTable.sortColumnIndex = 0;
+ }
+
+ attached() {
+ super.attached();
+ _updateTask.queue();
+ _resizeSubscription = window.onResize.listen((_) => _updateSize());
+ _updateSize();
+ }
+
+ detached() {
+ super.detached();
+ if (_resizeSubscription != null) {
+ _resizeSubscription.cancel();
+ }
+ }
+
+ _updateSize() {
+ HtmlElement e = $['main'];
+ final totalHeight = window.innerHeight;
+ final top = e.offset.top;
+ final bottomMargin = 32;
+ final mainHeight = totalHeight - top - bottomMargin;
+ e.style.setProperty('height', '${mainHeight}px');
+ }
+
+ isolateChanged(oldValue) {
+ _updateTask.queue();
+ }
+
+ update() async {
+ _clearView();
+ if (isolate == null) {
+ return;
+ }
+ final stream = _repository.get(isolate, M.SampleProfileTag.none);
+ var progress = (await stream.first).progress;
+ shadowRoot.querySelector('#sampleBufferControl').children = [
+ sampleBufferControlElement =
+ new SampleBufferControlElement(progress, stream, showTag: false,
+ selectedTag: M.SampleProfileTag.none, queue: app.queue)
+ ];
+ if (M.isSampleProcessRunning(progress.status)) {
+ progress = (await stream.last).progress;
+ }
+ if (progress.status == M.SampleProfileLoadingStatus.loaded) {
+ _profile = progress.profile;
+ shadowRoot.querySelector('#stackTraceTreeConfig').children = [
+ stackTraceTreeConfigElement =
+ new StackTraceTreeConfigElement(showMode: false,
+ showDirection: false, mode: ProfileTreeMode.function,
+ direction: M.ProfileTreeDirection.exclusive, queue: app.queue)
+ ..onModeChange.listen((e) {
+ cpuProfileTreeElement.mode = e.element.mode;
+ _renderTask.queue();
+ })
+ ..onDirectionChange.listen((e) {
+ cpuProfileTreeElement.direction = e.element.direction;
+ _renderTask.queue();
+ })
+ ..onFilterChange.listen((e) =>_renderTask.queue())
+ ];
+ shadowRoot.querySelector('#cpuProfileTree').children = [
+ cpuProfileTreeElement =
+ new CpuProfileVirtualTreeElement(isolate, _profile,
+ queue: app.queue)
+ ];
+ }
+ _renderTask.queue();
+ }
+
+ Future clearCpuProfile() async {
+ await isolate.invokeRpc('_clearCpuProfile', { });
+ _updateTask.queue();
+ return new Future.value(null);
+ }
+
+ Future refresh() {
+ _updateTask.queue();
+ return new Future.value(null);
+ }
+
+ render() {
+ _updateView();
+ }
+
+ checkParameters() {
+ if (isolate == null) {
+ return;
+ }
+ var functionId = app.locationManager.uri.queryParameters['functionId'];
+ var functionName =
+ app.locationManager.uri.queryParameters['functionName'];
+ if (functionId == '') {
+ // Fallback to searching by name.
+ _focusOnFunction(_findFunction(functionName));
+ } else {
+ if (functionId == null) {
+ _focusOnFunction(null);
+ return;
+ }
+ isolate.getObject(functionId).then((func) => _focusOnFunction(func));
+ }
+ }
+
+ _clearView() {
+ profileTable.clearRows();
+ _renderTable();
+ }
+
+ _updateView() {
+ _buildFunctionTable();
+ _renderTable();
+ _updateFunctionTreeView();
+ }
+
+ int _findFunctionRow(ServiceFunction function) {
+ for (var i = 0; i < profileTable.sortedRows.length; i++) {
+ var rowIndex = profileTable.sortedRows[i];
+ var row = profileTable.rows[rowIndex];
+ if (row.values[NameSortedTable.FUNCTION_COLUMN] == function) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ _scrollToFunction(ServiceFunction function) {
+ TableSectionElement tableBody = $['profile-table'];
+ var row = _findFunctionRow(function);
+ if (row == -1) {
+ return;
+ }
+ tableBody.children[row].classes.remove('shake');
+ // trigger reflow.
+ tableBody.children[row].offsetHeight;
+ tableBody.children[row].scrollIntoView(ScrollAlignment.CENTER);
+ tableBody.children[row].classes.add('shake');
+ // Focus on clicked function.
+ _focusOnFunction(function);
+ }
+
+ _clearFocusedFunction() {
+ TableSectionElement tableBody = $['profile-table'];
+ // Clear current focus.
+ if (focusedRow != null) {
+ tableBody.children[focusedRow].classes.remove('focused');
+ }
+ focusedRow = null;
+ focusedFunction = null;
+ }
+
+ ServiceFunction _findFunction(String functionName) {
+ for (var func in _profile.functions) {
+ if (func.function.name == functionName) {
+ return func.function;
+ }
+ }
+ return null;
+ }
+
+ _focusOnFunction(ServiceFunction function) {
+ if (focusedFunction == function) {
+ // Do nothing.
+ return;
+ }
+
+ _clearFocusedFunction();
+
+ if (function == null) {
+ _updateFunctionTreeView();
+ _clearCallTables();
+ return;
+ }
+
+ var row = _findFunctionRow(function);
+ if (row == -1) {
+ _updateFunctionTreeView();
+ _clearCallTables();
+ return;
+ }
+
+ focusedRow = row;
+ focusedFunction = function;
+
+ TableSectionElement tableBody = $['profile-table'];
+ tableBody.children[focusedRow].classes.add('focused');
+ _updateFunctionTreeView();
+ _buildCallersTable(focusedFunction);
+ _buildCalleesTable(focusedFunction);
+ }
+
+ _onRowClick(TableRowElement tr) {
+ var tableBody = $['profile-table'];
+ var row = profileTable.rowFromIndex(tableBody.children.indexOf(tr));
+ var function = row.values[NameSortedTable.FUNCTION_COLUMN];
+ app.locationManager.goReplacingParameters(
+ {
+ 'functionId': function.id,
+ 'functionName': function.vmName
+ }
+ );
+ }
+
+ _renderTable() {
+ profileTable._updateTableView($['profile-table'],
+ profileTable._makeFunctionRow,
+ _onRowClick,
+ NameSortedTable.FUNCTION_SPACER_COLUMNS,
+ NameSortedTable.FUNCTION_COLUMN);
+ }
+
+ _buildFunctionTable() {
+ for (var func in _profile.functions) {
+ if ((func.exclusiveTicks == 0) && (func.inclusiveTicks == 0)) {
+ // Skip.
+ continue;
+ }
+ var row = [
+ func.normalizedExclusiveTicks,
+ func.normalizedInclusiveTicks,
+ func.function,
+ ];
+ profileTable.addRow(new SortedTableRow(row));
+ }
+ profileTable.sort();
+ }
+
+ _renderCallTable(TableSectionElement view,
+ NameSortedTable model,
+ void onRowClick(TableRowElement tr)) {
+ model._updateTableView(view,
+ model._makeCallRow,
+ onRowClick,
+ NameSortedTable.CALL_SPACER_COLUMNS,
+ NameSortedTable.CALL_FUNCTION_COLUMN);
+ }
+
+ _buildCallTable(Map<ProfileFunction, int> calls,
+ NameSortedTable model) {
+ model.clearRows();
+ if (calls == null) {
+ return;
+ }
+ var sum = 0;
+ calls.values.forEach((i) => sum += i);
+ calls.forEach((func, count) {
+ var row = [
+ count / sum,
+ func.function,
+ ];
+ model.addRow(new SortedTableRow(row));
+ });
+ model.sort();
+ }
+
+ _clearCallTables() {
+ _buildCallersTable(null);
+ _buildCalleesTable(null);
+ }
+
+ _onCallersClick(TableRowElement tr) {
+ var table = $['callers-table'];
+ final row = profileCallersTable.rowFromIndex(table.children.indexOf(tr));
+ var function = row.values[NameSortedTable.CALL_FUNCTION_COLUMN];
+ _scrollToFunction(function);
+ }
+
+ _buildCallersTable(ServiceFunction function) {
+ var calls = (function != null) ? function.profile.callers : null;
+ var table = $['callers-table'];
+ _buildCallTable(calls, profileCallersTable);
+ _renderCallTable(table, profileCallersTable, _onCallersClick);
+ }
+
+ _onCalleesClick(TableRowElement tr) {
+ var table = $['callees-table'];
+ final row = profileCalleesTable.rowFromIndex(table.children.indexOf(tr));
+ var function = row.values[NameSortedTable.CALL_FUNCTION_COLUMN];
+ _scrollToFunction(function);
+ }
+
+ _buildCalleesTable(ServiceFunction function) {
+ var calls = (function != null) ? function.profile.callees : null;
+ var table = $['callees-table'];
+ _buildCallTable(calls, profileCalleesTable);
+ _renderCallTable(table, profileCalleesTable, _onCalleesClick);
+ }
+
+ _changeSort(Element target, NameSortedTable table) {
+ if (target is TableCellElement) {
+ if (table.sortColumnIndex != target.cellIndex) {
+ table.sortColumnIndex = target.cellIndex;
+ table.sortDescending = true;
+ } else {
+ table.sortDescending = !profileTable.sortDescending;
+ }
+ table.sort();
+ }
+ }
+
+ changeSortProfile(Event e, var detail, Element target) {
+ _changeSort(target, profileTable);
+ _renderTable();
+ }
+
+ changeSortCallers(Event e, var detail, Element target) {
+ _changeSort(target, profileCallersTable);
+ _renderCallTable($['callers-table'], profileCallersTable, _onCallersClick);
+ }
+
+ changeSortCallees(Event e, var detail, Element target) {
+ _changeSort(target, profileCalleesTable);
+ _renderCallTable($['callees-table'], profileCalleesTable, _onCalleesClick);
+ }
+
+ //////
+ ///
+ /// Function tree.
+ ///
+ TableTree functionTree;
+ _updateFunctionTreeView() {
+ if (cpuProfileTreeElement == null) {
+ return;
+ }
+ cpuProfileTreeElement.filter = (FunctionCallTreeNode node) {
+ return node.profileFunction.function == focusedFunction;
+ };
+ }
+
+ @published Isolate isolate;
+ @observable NameSortedTable profileTable;
+ @observable NameSortedTable profileCallersTable;
+ @observable NameSortedTable profileCalleesTable;
+ @observable ServiceFunction focusedFunction;
+ @observable int focusedRow;
+
+
+ StreamSubscription _resizeSubscription;
+ Task _updateTask;
+ Task _renderTask;
+
+ IsolateSampleProfileRepository _repository =
+ new IsolateSampleProfileRepository();
+ CpuProfile _profile;
+ SampleBufferControlElement sampleBufferControlElement;
+ StackTraceTreeConfigElement stackTraceTreeConfigElement;
+ CpuProfileVirtualTreeElement cpuProfileTreeElement;
+}
diff --git a/runtime/observatory/lib/src/elements/cpu_profile_table.html b/runtime/observatory/lib/src/elements/cpu_profile_table.html
new file mode 100644
index 0000000..b95c0bc
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/cpu_profile_table.html
@@ -0,0 +1,218 @@
+<link rel="import" href="../../../../packages/polymer/polymer.html">
+
+<polymer-element name="cpu-profile-table">
+ <template>
+ <link rel="stylesheet" href="css/shared.css">
+ <nav-bar>
+ <top-nav-menu></top-nav-menu>
+ <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu>
+ <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu>
+ <nav-menu link="{{ makeLink('/profiler-table', isolate) }}" anchor="cpu profile (table)" last="{{ true }}"></nav-menu>
+ <nav-refresh callback="{{ refresh }}"></nav-refresh>
+ <nav-refresh callback="{{ clearCpuProfile }}" label="Clear"></nav-refresh>
+ <nav-notify notifications="{{ app.notifications }}"></nav-notify>
+ </nav-bar>
+ <style>
+ /* general */
+ .well {
+ background-color: #ECECEC;
+ padding: 0.2em;
+ }
+ .center {
+ align-items: center;
+ justify-content: center;
+ }
+
+ /* status messages */
+ .statusMessage {
+ font-size: 150%;
+ font-weight: bold;
+ }
+ .statusBox {
+ height: 100%;
+ padding: 1em;
+ }
+
+ /* tables */
+ .table {
+ border-collapse: collapse!important;
+ table-layout: fixed;
+ height: 100%;
+ }
+ .th, .td {
+ padding: 8px;
+ vertical-align: top;
+ }
+ .table thead > tr > th {
+ vertical-align: bottom;
+ text-align: left;
+ border-bottom:2px solid #ddd;
+ }
+ .spacer {
+ width: 16px;
+ }
+ .left-border-spacer {
+ width: 16px;
+ border-left: 1px solid;
+ }
+ .clickable {
+ color: #0489c3;
+ text-decoration: none;
+ cursor: pointer;
+ min-width: 8em;
+ }
+ .clickable:hover {
+ text-decoration: underline;
+ cursor: pointer;
+ }
+ tr:hover:not(.focused) > td {
+ background-color: #FAFAFA;
+ }
+ .focused {
+ background-color: #F4C7C3;
+ }
+ .scroll {
+ overflow: scroll;
+ }
+ .outlined {
+ -webkit-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
+ -moz-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
+ box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
+ margin: 4px;
+ }
+ .centered {
+ margin-left: auto;
+ margin-right: auto;
+ justify-content: center;
+ }
+ .full-height {
+ height: 100%;
+ }
+ .mostly-full-height {
+ height: 80%;
+ }
+ .full-width {
+ width: 100%;
+ }
+ .focused-function-label {
+ flex: 0 1 auto;
+ margin-left: auto;
+ margin-right: auto;
+ justify-content: center;
+ }
+ .call-table {
+ flex: 1 1 auto;
+ }
+
+ .tree {
+ border-spacing: 0px;
+ width: 100%;
+ margin-bottom: 20px
+ vertical-align: middle;
+ }
+
+ .tree tbody tr {
+ animation: fadeIn 0.5s;
+ -moz-animation: fadeIn 0.5s;
+ -webkit-animation: fadeIn 0.5s;
+ }
+
+ .tree tbody tr:hover {
+ background-color: #FAFAFA;
+ }
+
+ .tree tr td:first-child,
+ .tree tr th:first-child {
+ width: 100%;
+ }
+
+ .tree thead > tr > th {
+ padding: 8px;
+ vertical-align: bottom;
+ text-align: left;
+ border-bottom: 1px solid #ddd;
+ }
+
+ </style>
+ <div id="sampleBufferControl"></div>
+ <br>
+ <hr>
+ <div id="main" class="flex-row centered">
+ <div class="flex-item-45-percent full-height outlined scroll">
+ <table id="main-table" class="flex-item-100-percent table">
+ <thead>
+ <tr>
+ <th on-click="{{changeSortProfile}}" class="clickable" title="Executing (%)">{{ profileTable.getColumnLabel(0) }}</th>
+ <th on-click="{{changeSortProfile}}" class="clickable" title="In stack (%)">{{ profileTable.getColumnLabel(1) }}</th>
+ <th on-click="{{changeSortProfile}}" class="clickable" title="Method">{{ profileTable.getColumnLabel(2) }}</th>
+ </tr>
+ </thead>
+ <tbody id="profile-table">
+ </tbody>
+ </table>
+ </div>
+ <div class="flex-item-45-percent full-height outlined">
+ <div class="flex-column full-height">
+ <div class="focused-function-label">
+ <template if="{{ focusedFunction != null }}">
+ <span>Focused on: </span>
+ <function-ref ref="{{ focusedFunction }}"></function-ref>
+ </template>
+ <template if="{{ focusedFunction == null }}">
+ <span>No focused function</span>
+ </template>
+ </div>
+ <hr>
+ <div class="call-table scroll">
+ <table class="full-width table">
+ <thead>
+ <tr>
+ <th on-click="{{changeSortCallers}}" class="clickable" title="Callers (%)">{{ profileCallersTable.getColumnLabel(0) }}</th>
+ <th on-click="{{changeSortCallers}}" class="clickable" title="Method">{{ profileCallersTable.getColumnLabel(1) }}</th>
+ </tr>
+ </thead>
+ <tbody id="callers-table">
+ </tbody>
+ </table>
+ </div>
+ <hr>
+ <div class="call-table scroll">
+ <table class="full-width table">
+ <thead>
+ <tr>
+ <th on-click="{{changeSortCallees}}" class="clickable" title="Callees (%)">{{ profileCalleesTable.getColumnLabel(0) }}</th>
+ <th on-click="{{changeSortCallees}}" class="clickable" title="Method">{{ profileCalleesTable.getColumnLabel(1) }}</th>
+ </tr>
+ </thead>
+ <tbody id="callees-table">
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+ <br>
+ <div id="stackTraceTreeConfig"></div>
+ <br>
+ <div class="content-centered-big">
+ <div class="focused-function-label">
+ <template if="{{ focusedFunction != null }}">
+ <span>Filtered tree: </span>
+ <function-ref ref="{{ focusedFunction }}"></function-ref>
+ </template>
+ <template if="{{ focusedFunction == null }}">
+ <span>No focused function</span>
+ </template>
+ </div>
+ </div>
+ <br>
+ <br>
+ <div class="flex-row centered">
+ <div class="flex-item-90-percent outlined" style="margin: 16px; margin-left: 8px; margin-right: 8px">
+ <div id="cpuProfileTree"></div>
+ </div>
+ </div>
+ </template>
+</polymer-element>
+
+<script type="application/dart" src="cpu_profile.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/css/shared.css b/runtime/observatory/lib/src/elements/css/shared.css
index e468fc8..9e4a0f5 100644
--- a/runtime/observatory/lib/src/elements/css/shared.css
+++ b/runtime/observatory/lib/src/elements/css/shared.css
@@ -61,12 +61,12 @@
white-space: nowrap;
}
-a {
+a[href] {
color: #0489c3;
text-decoration: none;
}
-a:hover {
+a[href]:hover {
text-decoration: underline;
}
@@ -307,6 +307,12 @@
font: 400 16px 'Montserrat', sans-serif;
}
+select, button, input {
+ border-radius: 0px;
+ border-style: solid;
+ border-width: 1px;
+}
+
@-webkit-keyframes fadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
@@ -416,6 +422,56 @@
margin-left: 0.5em;
}
+/* cpu-profile */
+
+cpu-profile {
+ position: relative;
+ display: block;
+ height: 100%;
+}
+
+cpu-profile > cpu-profile-virtual-tree {
+ position: absolute;
+ height: auto;
+ top: 320px;
+ bottom: 0;
+ left: 0;
+ right: 0;
+}
+
+/* cpu-profile-virtual-tree */
+
+cpu-profile-virtual-tree {
+ display: block;
+ height: 600px;
+}
+
+cpu-profile-virtual-tree .tree-item {
+ line-height: 30px;
+ height: 30px;
+ padding-left: 5%;
+ padding-right: 5%;
+}
+
+cpu-profile-virtual-tree .tree-item > .inclusive,
+cpu-profile-virtual-tree .tree-item > .exclusive,
+cpu-profile-virtual-tree .tree-item > .percentage {
+ display: inline-block;
+ text-align: right;
+ width: 4em;
+ margin-left: 0.25em;
+ margin-right: 0.25em;
+}
+
+cpu-profile-virtual-tree .tree-item > .exclusive {
+ margin-right: 1.5em;
+}
+
+cpu-profile-virtual-tree .tree-item > .name {
+ display: inline;
+ margin-left: 0.5em;
+}
+
/* error-ref */
/* TODO(cbernaschina) fix error-ref-wrapped to error-ref when wrapper
removed */
@@ -461,6 +517,36 @@
text-decoration: none;
}
+/* isolate-counter-chart */
+
+isolate-counter-chart {
+ display: block;
+ position: relative;
+ height: 300px;
+ min-width: 350px;
+}
+isolate-counter-chart > div.host {
+ position: absolute;
+ left: 0;
+ bottom: 20px;
+ top: 5px;
+ right: 250px;
+}
+isolate-counter-chart > div.legend {
+ position: absolute;
+ width: 250px;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ overflow-y: auto;
+}
+
+/* isolate-reconnect */
+
+isolate-reconnect div.doubleSpaced {
+ line-height: 2em;
+}
+
/* isolate-ref */
/* TODO(cbernaschina) fix isolate-ref-wrapped to isolate-ref when wrapper
removed */
@@ -473,6 +559,38 @@
text-decoration: none;
}
+/* isolate-shared-summary */
+/* TODO(cbernaschina) fix isolate-shared-summary-wrapped
+to isolate-shared-summary when wrapper removed */
+
+isolate-shared-summary,
+isolate-shared-summary-wrapped {
+ display: block;
+ height: 300px;
+ position: relative;
+}
+isolate-shared-summary-wrapped > .menu {
+ float: right;
+ top: 0;
+ right: 0;
+}
+isolate-shared-summary-wrapped > isolate-counter-chart {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 230px;
+ clear: both;
+}
+isolate-shared-summary-wrapped .errorBox {
+ background-color: #f5f5f5;
+ border: 1px solid #ccc;
+ padding: 2em;
+ font-family: consolas, courier, monospace;
+ font-size: 1em;
+ line-height: 1.2em;
+ white-space: pre;
+}
+
/* library-ref */
/* TODO(cbernaschina) fix library-ref-wrapped to library-ref when wrapper
removed */
@@ -621,6 +739,47 @@
}
+/* observatory-application */
+
+observatory-application {
+ display: block;
+ height: 100%;
+}
+
+observatory-application > div {
+ display: block;
+ height: 100%;
+}
+
+/* sample-buffer-control */
+
+sample-buffer-control .statusMessage {
+ font-size: 150%;
+ font-weight: bold;
+}
+
+sample-buffer-control .statusBox {
+ height: 100%;
+ padding: 1em;
+}
+
+sample-buffer-control .center {
+ align-items: center;
+ justify-content: center;
+}
+
+sample-buffer-control .notice {
+ background-color: #fcf8e3;
+}
+
+sample-buffer-control .red {
+ background-color: #f2dede;
+}
+
+sample-buffer-control .shadow {
+ box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.16),
+ 0 2px 5px 0 rgba(0, 0, 0, 0.26);
+}
/* view-footer */
@@ -681,6 +840,12 @@
font-weight: bold;
font-size: 18px;
width: 19px;
+ border: none;
+ background-color: transparent;
+}
+
+virtual-tree .expander:focus {
+ outline: none;
}
virtual-tree .lines,
diff --git a/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart b/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart
index a2ab155..d5ba83d 100644
--- a/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart
+++ b/runtime/observatory/lib/src/elements/helpers/rendering_scheduler.dart
@@ -13,7 +13,7 @@
}
/// Event related to a Renderable rendering phase.
-class RenderedEvent<T extends Renderable> {
+class RenderedEvent<T> {
/// Renderable to which the event is related
final T element;
/// Is another rendering scheduled for this element.
diff --git a/runtime/observatory/lib/src/elements/helpers/uris.dart b/runtime/observatory/lib/src/elements/helpers/uris.dart
index a099bbf..b243f78 100644
--- a/runtime/observatory/lib/src/elements/helpers/uris.dart
+++ b/runtime/observatory/lib/src/elements/helpers/uris.dart
@@ -13,35 +13,37 @@
return '#' + new Uri(path: path, queryParameters: parameters).toString();
}
- static String inspect(M.IsolateRef isolate, {M.ObjectRef object, int pos}) {
- if (pos == null) {
- return _isolatePage('/inspect', isolate, object: object);
- }
- return _isolatePage('/inspect', isolate, object: object) + '---pos=${pos}';
- }
- static String debugger(M.IsolateRef isolate)
- => _isolatePage('/debugger', isolate);
+ static String allocationProfiler(M.IsolateRef isolate)
+ => _isolatePage('/allocation-profiler', isolate);
static String classTree(M.IsolateRef isolate)
=> _isolatePage('/class-tree', isolate);
static String cpuProfiler(M.IsolateRef isolate)
=> _isolatePage('/profiler', isolate);
static String cpuProfilerTable(M.IsolateRef isolate)
=> _isolatePage('/profiler-table', isolate);
- static String allocationProfiler(M.IsolateRef isolate)
- => _isolatePage('/allocation-profiler', isolate);
+ static String debugger(M.IsolateRef isolate)
+ => _isolatePage('/debugger', isolate);
+ static String flags() => '#/flags';
static String heapMap(M.IsolateRef isolate)
=> _isolatePage('/heap-map', isolate);
- static String metrics(M.IsolateRef isolate)
- => _isolatePage('/metrics', isolate);
static String heapSnapshot(M.IsolateRef isolate)
=> _isolatePage('/heap-snapshot', isolate);
+ static String inspect(M.IsolateRef isolate, {M.ObjectRef object, int pos}) {
+ if (pos == null) {
+ return _isolatePage('/inspect', isolate, object: object);
+ }
+ return _isolatePage('/inspect', isolate, object: object) + '---pos=${pos}';
+ }
+ static String logging(M.IsolateRef isolate)
+ => _isolatePage('/logging', isolate);
+ static String metrics(M.IsolateRef isolate)
+ => _isolatePage('/metrics', isolate);
static String persistentHandles(M.IsolateRef isolate)
=> _isolatePage('/persistent-handles', isolate);
static String ports(M.IsolateRef isolate)
=> _isolatePage('/ports', isolate);
- static String logging(M.IsolateRef isolate)
- => _isolatePage('/logging', isolate);
+ static String profiler(M.IsolateRef isolate)
+ => _isolatePage('/profiler', isolate);
static String vm() => '#/vm';
static String vmConnect() => '#/vm-connect';
- static String flags() => '#/flags';
}
diff --git a/runtime/observatory/lib/src/elements/isolate/counter_chart.dart b/runtime/observatory/lib/src/elements/isolate/counter_chart.dart
new file mode 100644
index 0000000..3c7b3bc
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/isolate/counter_chart.dart
@@ -0,0 +1,77 @@
+// 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 'dart:async';
+import 'package:charted/charted.dart';
+import "package:charted/charts/charts.dart";
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+
+class IsolateCounterChartElement extends HtmlElement implements Renderable {
+ static const tag =
+ const Tag<IsolateCounterChartElement>('isolate-counter-chart');
+
+ RenderingScheduler<IsolateCounterChartElement> _r;
+
+ Stream<RenderedEvent<IsolateCounterChartElement>> get onRendered =>
+ _r.onRendered;
+
+ Map _counters;
+ StreamSubscription _subscription;
+
+ factory IsolateCounterChartElement(Map counters, {RenderingQueue queue}) {
+ assert(counters != null);
+ IsolateCounterChartElement e = document.createElement(tag.name);
+ e._r = new RenderingScheduler(e, queue: queue);
+ e._counters = counters;
+ return e;
+ }
+
+ IsolateCounterChartElement.created() : super.created();
+
+ @override
+ void attached() {
+ super.attached();
+ _r.enable();
+ _subscription = window.onResize.listen((_) => _r.dirty());
+ }
+
+ @override
+ void detached() {
+ super.detached();
+ children = [];
+ _r.disable(notify: true);
+ _subscription.cancel();
+ }
+
+ void render() {
+ var areaHost;
+ var legendHost;
+ children = [
+ areaHost = new DivElement()..classes = ['host'],
+ legendHost = new DivElement()..classes = ['legend']
+ ];
+ final series = new ChartSeries("Work", [1], new PieChartRenderer(
+ sortDataByValue: false
+ ));
+ var rect = areaHost.getBoundingClientRect();
+ var minSize = new Rect.size(rect.width, rect.height);
+ final config = new ChartConfig([series], [0])
+ ..minimumSize = minSize
+ ..legend = new ChartLegend(legendHost, showValues: true);
+ final data = new ChartData([
+ new ChartColumnSpec(label: 'Type', type: ChartColumnSpec.TYPE_STRING),
+ new ChartColumnSpec(label: 'Percent', formatter: (v) => v.toString())
+ ], _counters.keys
+ .map((key) => [key, double.parse(_counters[key].split('%')[0])])
+ .toList());
+
+ new LayoutArea(areaHost, data, config, state: new ChartState(),
+ autoUpdate: true)
+ ..addChartBehavior(new Hovercard())
+ ..addChartBehavior(new AxisLabelTooltip())
+ ..draw();
+ }
+}
diff --git a/runtime/observatory/lib/src/elements/isolate/shared_summary.dart b/runtime/observatory/lib/src/elements/isolate/shared_summary.dart
new file mode 100644
index 0000000..51fdc28
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/isolate/shared_summary.dart
@@ -0,0 +1,155 @@
+// 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 'dart:async';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/utils.dart';
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/src/elements/isolate/counter_chart.dart';
+
+class IsolateSharedSummaryElement extends HtmlElement implements Renderable {
+ static const tag =
+ const Tag<IsolateSharedSummaryElement>('isolate-shared-summary-wrapped',
+ dependencies: const [
+ IsolateCounterChartElement.tag
+ ]);
+
+ RenderingScheduler<IsolateSharedSummaryElement> _r;
+
+ Stream<RenderedEvent<IsolateSharedSummaryElement>> get onRendered =>
+ _r.onRendered;
+
+ M.Isolate _isolate;
+
+ factory IsolateSharedSummaryElement(M.Isolate isolate,
+ {RenderingQueue queue}) {
+ assert(isolate != null);
+ IsolateSharedSummaryElement e = document.createElement(tag.name);
+ e._r = new RenderingScheduler(e, queue: queue);
+ e._isolate = isolate;
+ return e;
+ }
+
+ IsolateSharedSummaryElement.created() : super.created();
+
+ @override
+ void attached() {
+ super.attached();
+ _r.enable();
+ }
+
+ @override
+ void detached() {
+ super.detached();
+ children = [];
+ _r.disable(notify: true);
+ }
+
+ void render() {
+ children = [];
+ if (_isolate.error != null) {
+ children = [
+ new PreElement()..classes = const ["errorBox"]
+ ..text = _isolate.error.message
+ ];
+ }
+ final newHeapUsed = Utils.formatSize(_isolate.newSpace.used);
+ final newHeapCapacity = Utils.formatSize(_isolate.newSpace.capacity);
+ final oldHeapUsed = Utils.formatSize(_isolate.oldSpace.used);
+ final oldHeapCapacity = Utils.formatSize(_isolate.oldSpace.capacity);
+ children.addAll([
+ new DivElement()..classes = ['menu']
+ ..children = [
+ new DivElement()..classes = const ['memberList']
+ ..children = [
+ new DivElement()..classes = const ['memberItem']
+ ..children = [
+ new DivElement()..classes = const ['memberName']
+ ..text = 'new heap',
+ new DivElement()..classes = const ['memberValue']
+ ..text = '$newHeapUsed of $newHeapCapacity',
+ ],
+ new DivElement()..classes = const ['memberItem']
+ ..children = [
+ new DivElement()..classes = const ['memberName']
+ ..text = 'old heap',
+ new DivElement()..classes = const ['memberValue']
+ ..text = '$oldHeapUsed of $oldHeapCapacity',
+ ]
+ ],
+ new BRElement(),
+ new DivElement()
+ ..children = [
+ new SpanElement()..text = 'see ',
+ new AnchorElement(href: Uris.debugger(_isolate))
+ ..text = 'debug'
+ ],
+ new DivElement()
+ ..children = [
+ new SpanElement()..text = 'see ',
+ new AnchorElement(href: Uris.classTree(_isolate))
+ ..text = 'class hierarchy'
+ ],
+ new DivElement()
+ ..children = [
+ new SpanElement()..text = 'see ',
+ new AnchorElement(href: Uris.cpuProfiler(_isolate))
+ ..text = 'cpu profile'
+ ],
+ new DivElement()
+ ..children = [
+ new SpanElement()..text = 'see ',
+ new AnchorElement(href: Uris.cpuProfilerTable(_isolate))
+ ..text = 'cpu profile (table)'
+ ],
+ new DivElement()
+ ..children = [
+ new SpanElement()..text = 'see ',
+ new AnchorElement(href: Uris.allocationProfiler(_isolate))
+ ..text = 'allocation profile'
+ ],
+ new DivElement()
+ ..children = [
+ new SpanElement()..text = 'see ',
+ new AnchorElement(href: Uris.heapMap(_isolate))
+ ..text = 'heap map'
+ ],
+ new DivElement()
+ ..children = [
+ new SpanElement()..text = 'see ',
+ new AnchorElement(href: Uris.metrics(_isolate))
+ ..text = 'metrics'
+ ],
+ new DivElement()
+ ..children = [
+ new SpanElement()..text = 'see ',
+ new AnchorElement(href: Uris.heapSnapshot(_isolate))
+ ..text = 'heap snapshot'
+ ],
+ new DivElement()
+ ..children = [
+ new SpanElement()..text = 'see ',
+ new AnchorElement(href: Uris.persistentHandles(_isolate))
+ ..text = 'persistent handles'
+ ],
+ new DivElement()
+ ..children = [
+ new SpanElement()..text = 'see ',
+ new AnchorElement(href: Uris.ports(_isolate))
+ ..text = 'ports'
+ ],
+ new DivElement()
+ ..children = [
+ new SpanElement()..text = 'see ',
+ new AnchorElement(href: Uris.logging(_isolate))
+ ..text = 'logging'
+ ]
+ ],
+ new IsolateCounterChartElement(_isolate.counters, queue: _r.queue)
+ ]);
+ }
+}
diff --git a/runtime/observatory/lib/src/elements/isolate/shared_summary_wrapper.dart b/runtime/observatory/lib/src/elements/isolate/shared_summary_wrapper.dart
new file mode 100644
index 0000000..72b86c2
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/isolate/shared_summary_wrapper.dart
@@ -0,0 +1,167 @@
+// 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 'dart:async';
+import 'package:observatory/app.dart';
+import 'package:observatory/service.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/shims/binding.dart';
+import 'package:observatory/src/elements/isolate/shared_summary.dart';
+
+@bindable
+class IsolateSharedSummaryElementWrapper extends HtmlElement {
+ static const binder = const Binder<IsolateSharedSummaryElementWrapper>(const {
+ 'isolate': #isolate
+ });
+
+ static const tag =
+ const Tag<IsolateSharedSummaryElementWrapper>('isolate-shared-summary');
+
+ IsolateSharedSummaryElementWrapper.created() : super.created() {
+ binder.registerCallback(this);
+ createShadowRoot();
+ render();
+ }
+
+ Isolate _isolate;
+ StreamSubscription _subscription;
+
+ Isolate get isolate => _isolate;
+
+ void set isolate(Isolate value) {
+ _isolate = value;
+ _detached();
+ _attached();
+ }
+
+ @override
+ void attached() {
+ super.attached();
+ _attached();
+ }
+
+ @override
+ void detached() {
+ super.detached();
+ _detached();
+ }
+
+ void _attached() {
+ if (_isolate != null) {
+ _subscription = _isolate.changes.listen((_) { render(); });
+ }
+ render();
+ }
+
+ void _detached() {
+ _subscription?.cancel();
+ _subscription = null;
+ }
+
+ void render() {
+ if (_isolate == null) {
+ return;
+ }
+ shadowRoot.children = [
+ new StyleElement()
+ ..text = '''
+ a[href] {
+ color: #0489c3;
+ text-decoration: none;
+ }
+ a[href]:hover {
+ text-decoration: underline;
+ }
+ .memberList {
+ display: table;
+ }
+ .memberItem {
+ display: table-row;
+ }
+ .memberName, .memberValue {
+ display: table-cell;
+ vertical-align: top;
+ padding: 3px 0 3px 1em;
+ font: 400 14px 'Montserrat', sans-serif;
+ }
+ isolate-shared-summary-wrapped {
+ display: block;
+ height: 300px;
+ position: relative;
+ }
+ isolate-shared-summary-wrapped > .menu {
+ float: right;
+ top: 0;
+ right: 0;
+ }
+ isolate-shared-summary-wrapped > isolate-counter-chart {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 230px;
+ clear: both;
+ }
+ isolate-shared-summary-wrapped .errorBox {
+ background-color: #f5f5f5;
+ border: 1px solid #ccc;
+ padding: 2em;
+ font-family: consolas, courier, monospace;
+ font-size: 1em;
+ line-height: 1.2em;
+ white-space: pre;
+ }
+ isolate-counter-chart {
+ display: block;
+ position: relative;
+ height: 300px;
+ min-width: 350px;
+ }
+ isolate-counter-chart > div.host {
+ position: absolute;
+ left: 0;
+ bottom: 20px;
+ top: 5px;
+ right: 250px;
+ }
+ isolate-counter-chart > div.legend {
+ position: absolute;
+ width: 250px;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ overflow-y: auto;
+ }
+ .type-pie-rdr > .chart-legend-color {
+ border-radius: 6px;
+ }
+ .chart-legend-row, .chart-legend-more {
+ width: 100%;
+ display: flex;
+ font-size: 14px;
+ margin-bottom: 16px;
+ position: relative;
+ cursor: default;
+ }
+ .chart-legend-row:hover, .chart-legend-more:hover {
+ font-weight: bold;
+ }
+ .chart-legend-color, .chart-legend-more-color {
+ width: 12px;
+ height: 12px;
+ margin: auto 8px;
+ border-radius: 2px;
+ }
+ .chart-legend-label {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 120px;
+ flex: 1;
+ }
+ ''',
+ new IsolateSharedSummaryElement(_isolate,
+ queue: ObservatoryApplication.app.queue)
+ ];
+ }
+}
diff --git a/runtime/observatory/lib/src/elements/isolate_reconnect.dart b/runtime/observatory/lib/src/elements/isolate_reconnect.dart
index 01edf8f..465bc0c 100644
--- a/runtime/observatory/lib/src/elements/isolate_reconnect.dart
+++ b/runtime/observatory/lib/src/elements/isolate_reconnect.dart
@@ -4,24 +4,111 @@
library isolate_reconnect_element;
-import 'package:polymer/polymer.dart';
-import 'observatory_element.dart';
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.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';
-@CustomTag('isolate-reconnect')
-class IsolateReconnectElement extends ObservatoryElement {
- IsolateReconnectElement.created() : super.created();
+class IsolateReconnectElement extends HtmlElement implements Renderable{
+ static const tag = const Tag<IsolateReconnectElement>('isolate-reconnect',
+ dependencies: const [NavBarElement.tag,
+ NavTopMenuElement.tag,
+ NavNotifyElement.tag,
+ ViewFooterElement.tag]);
- get missingIsolateId {
- return app.locationManager.uri.queryParameters['originalIsolateId'];
+ RenderingScheduler _r;
+
+ Stream<RenderedEvent<IsolateReconnectElement>> get onRendered =>
+ _r.onRendered;
+
+ M.VM _vm;
+ String _missing;
+ Uri _uri;
+ M.EventRepository _events;
+ StreamSubscription _subscription;
+
+ M.VM get vm => _vm;
+ String get missing => _missing;
+ Uri get uri => _uri;
+
+ M.NotificationRepository _notifications;
+ factory IsolateReconnectElement(M.VM vm, M.EventRepository events,
+ M.NotificationRepository notifications, String missing, Uri uri,
+ {RenderingQueue queue}) {
+ assert(vm != null);
+ assert(events != null);
+ assert(missing != null);
+ assert(uri != null);
+ assert(notifications != null);
+ IsolateReconnectElement e = document.createElement(tag.name);
+ e._r = new RenderingScheduler(e, queue: queue);
+ e._vm = vm;
+ e._events = events;
+ e._missing = missing;
+ e._uri = uri;
+ e._notifications = notifications;
+ return e;
}
- linkToContinueIn(isolate) {
- var parameters = new Map.from(app.locationManager.uri.queryParameters);
- parameters['isolateId'] = isolate.id;
- parameters.remove('originalIsolateId');
- var path = parameters.remove('originalPath');
- path = "/$path";
- var generatedUri = new Uri(path: path, queryParameters: parameters);
- return app.locationManager.makeLink(generatedUri.toString());
+ IsolateReconnectElement.created() : super.created();
+
+ @override
+ void attached() {
+ super.attached();
+ _subscription = _events.onVMUpdate.listen((e) {
+ _vm = e.vm;
+ _r.dirty();
+ });
+ _r.enable();
+ }
+
+ @override
+ void detached() {
+ super.detached();
+ children = [];
+ _r.disable(notify: true);
+ _subscription.cancel();
+ }
+
+ 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 = 'Isolate $_missing no longer exists',
+ new BRElement(), new HRElement(),
+ new DivElement()..classes = ['memberList']
+ ..children = (_vm.isolates.map((isolate) {
+ final query = new Map.from(_uri.queryParameters);
+ query['isolateId'] = isolate.id;
+ final href = new Uri(path: _uri.path, queryParameters: query);
+ return new DivElement()..classes = ['memberItem', 'doubleSpaced']
+ ..children = [
+ new SpanElement()..text = 'Continue in ',
+ new AnchorElement(href: '#$href')..classes = ['isolate-link']
+ ..text = '${isolate.id} (${isolate.name})'
+ ];
+ }).toList()..add(
+ new DivElement()..classes = ['memberItem', 'doubleSpaced']
+ ..children = [
+ new SpanElement()..text = 'Go to ',
+ new AnchorElement(href: Uris.vm())
+ ..text = 'isolates summary',
+ ]
+ ))
+ ],
+ new ViewFooterElement(queue: _r.queue)
+ ];
}
}
diff --git a/runtime/observatory/lib/src/elements/isolate_reconnect.html b/runtime/observatory/lib/src/elements/isolate_reconnect.html
deleted file mode 100644
index 1f678f5..0000000
--- a/runtime/observatory/lib/src/elements/isolate_reconnect.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<polymer-element name="isolate-reconnect">
- <template>
- <link rel="stylesheet" href="css/shared.css">
- <style>
- .doubleSpaced {
- line-height: 2em;
- }
- </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 class="doubleSpaced">Isolate {{ missingIsolateId }} no longer exists</h1>
- <div class="memberList">
- <template repeat="{{ i in app.vm.isolates }}">
- <div class="memberItem doubleSpaced">
- Continue in <a _href="{{ linkToContinueIn(i) }}">{{ i.id }} ({{ i.name }})</a>
- </div>
- </template>
- <div class="memberItem doubleSpaced">
- Go to <a _href="{{ gotoLink('/vm') }}">isolates summary</a>
- </div>
- </div>
- </div>
- </template>
-</polymer-element>
-
-<script type="application/dart" src="isolate_reconnect.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/isolate_summary.dart b/runtime/observatory/lib/src/elements/isolate_summary.dart
index b0b2e06..b41befd 100644
--- a/runtime/observatory/lib/src/elements/isolate_summary.dart
+++ b/runtime/observatory/lib/src/elements/isolate_summary.dart
@@ -4,10 +4,7 @@
library isolate_summary_element;
-import 'dart:html';
import 'observatory_element.dart';
-import 'package:charted/charted.dart';
-import "package:charted/charts/charts.dart";
import 'package:observatory/service.dart';
import 'package:polymer/polymer.dart';
@@ -31,88 +28,3 @@
@published Isolate isolate;
}
-
-@CustomTag('isolate-shared-summary')
-class IsolateSharedSummaryElement extends ObservatoryElement {
- IsolateSharedSummaryElement.created() : super.created();
-
- @published Isolate isolate;
-}
-
-class CounterChart {
- final HtmlElement _wrapper;
- HtmlElement _areaHost;
- HtmlElement _legendHost;
- LayoutArea _area;
- ChartData _data;
- final _columns = [
- new ChartColumnSpec(label: 'Type', type: ChartColumnSpec.TYPE_STRING),
- new ChartColumnSpec(label: 'Percent', formatter: (v) => v.toString())
- ];
-
- CounterChart(this._wrapper) {
- assert(_wrapper != null);
- _areaHost = _wrapper.querySelector('.chart-host');
- assert(_areaHost != null);
- _areaHost.clientWidth;
- _legendHost = _wrapper.querySelector('.chart-legend-host');
- assert(_legendHost != null);
- var series = new ChartSeries("Work", [1], new PieChartRenderer(
- sortDataByValue: false
- ));
- var config = new ChartConfig([series], [0]);
- config.minimumSize = new Rect(200, 200);
- config.legend = new ChartLegend(_legendHost, showValues: true);
- _data = new ChartData(_columns, []);
- _area = new LayoutArea(_areaHost,
- _data,
- config,
- state: new ChartState(),
- autoUpdate: false);
- _area.addChartBehavior(new Hovercard());
- _area.addChartBehavior(new AxisLabelTooltip());
- }
-
- void update(Map counters) {
- var rows = [];
- for (var key in counters.keys) {
- var value = double.parse(counters[key].split('%')[0]);
- rows.add([key, value]);
- }
- _area.data = new ChartData(_columns, rows);
- _area.draw();
- }
-}
-
-@CustomTag('isolate-counter-chart')
-class IsolateCounterChartElement extends ObservatoryElement {
- IsolateCounterChartElement.created() : super.created();
-
- @published ObservableMap counters;
- CounterChart chart;
-
- attached() {
- super.attached();
- chart =
- new CounterChart(shadowRoot.querySelector('#isolate-counter-chart'));
- }
-
- detached() {
- super.detached();
- var host = shadowRoot.querySelector('#isolate-counter-chart-host');
- host.children.clear();
- var legendHost =
- shadowRoot.querySelector('#isolate-counter-chart-legend-host');
- legendHost.children.clear();
- }
-
- void countersChanged(oldValue) {
- if (counters == null) {
- return;
- }
- if (chart == null) {
- return;
- }
- chart.update(counters);
- }
-}
diff --git a/runtime/observatory/lib/src/elements/isolate_summary.html b/runtime/observatory/lib/src/elements/isolate_summary.html
index 1a0c0a1..3c4924d 100644
--- a/runtime/observatory/lib/src/elements/isolate_summary.html
+++ b/runtime/observatory/lib/src/elements/isolate_summary.html
@@ -85,146 +85,4 @@
</template>
</polymer-element>
-<polymer-element name="isolate-shared-summary">
- <template>
- <style>
- .errorBox {
- background-color: #f5f5f5;
- border: 1px solid #ccc;
- padding: 2em;
- font-family: consolas, courier, monospace;
- font-size: 1em;
- line-height: 1.2em;
- white-space: pre;
- }
- </style>
- <link rel="stylesheet" href="css/shared.css">
- <template if="{{ isolate.error != null }}">
- <div class="content-centered">
- <pre class="errorBox">{{ isolate.error.message }}</pre>
- <br>
- </div>
- </template>
- <div class="flex-row">
- <div style="flex:2">
- <isolate-counter-chart counters="{{ isolate.counters }}"></isolate-counter-chart>
- </div>
- <div style="flex:1">
- <div class="memberList">
- <div class="memberItem">
- <div class="memberName">new heap</div>
- <div class="memberValue">
- {{ isolate.newSpace.used | formatSize }}
- of
- {{ isolate.newSpace.capacity | formatSize }}
- </div>
- </div>
- <div class="memberItem">
- <div class="memberName">old heap</div>
- <div class="memberValue">
- {{ isolate.oldSpace.used | formatSize }}
- of
- {{ isolate.oldSpace.capacity | formatSize }}
- </div>
- </div>
- </div>
- <br>
- <div class="memberItem">
- <div class="memberValue">
- See <a on-click="{{ goto }}" _href="{{ gotoLink('/debugger', isolate) }}">debugger</a>
- </div>
- </div>
- <div class="memberItem">
- <div class="memberValue">
- See <a on-click="{{ goto }}" _href="{{ gotoLink('/class-tree', isolate) }}">class hierarchy</a>
- </div>
- </div>
- <div class="memberItem">
- <div class="memberValue">
- See <a on-click="{{ goto }}" _href="{{ gotoLink('/profiler', isolate) }}">cpu profile</a>
- </div>
- </div>
- <div class="memberItem">
- <div class="memberValue">
- See <a on-click="{{ goto }}" _href="{{ gotoLink('/profiler-table', isolate) }}">cpu profile (table)</a>
- </div>
- </div>
- <div class="memberItem">
- <div class="memberValue">
- See <a on-click="{{ goto }}" _href="{{ gotoLink('/allocation-profiler', isolate) }}">allocation profile</a>
- </div>
- </div>
- <div class="memberItem">
- <div class="memberValue">
- See <a on-click="{{ goto }}" _href="{{ gotoLink('/heap-map', isolate) }}">heap map</a>
- </div>
- </div>
- <div class="memberItem">
- <div class="memberValue">
- See <a on-click="{{ goto }}" _href="{{ gotoLink('/metrics', isolate) }}">metrics</a>
- </div>
- </div>
- <div class="memberItem">
- <div class="memberValue">
- See <a on-click="{{ goto }}" _href="{{ gotoLink('/heap-snapshot', isolate) }}">heap snapshot</a>
- </div>
- </div>
- <div class="memberItem">
- <div class="memberValue">
- See <a on-click="{{ goto }}" _href="{{ gotoLink('/persistent-handles', isolate) }}">persistent handles</a>
- </div>
- </div>
- <div class="memberItem">
- <div class="memberValue">
- See <a on-click="{{ goto }}" _href="{{ gotoLink('/ports', isolate) }}">ports</a>
- </div>
- </div>
- <div class="memberItem">
- <div class="memberValue">
- See <a on-click="{{ goto }}" _href="{{ gotoLink('/logging', isolate) }}">logging</a>
- </div>
- </div>
- <!-- Temporarily disabled until UI for dart:io is acceptable.
- <template if="{{ isolate.ioEnabled }}">
- <div class="memberItem">
- <div class="memberValue">
- See <a on-click="{{ goto }}" href="{{ gotoLink('/io', isolate) }}">dart:io</a>
- </div>
- </div>
- </template>
- -->
- </div>
- </div>
- </template>
-</polymer-element>
-
-<polymer-element name="isolate-counter-chart">
- <template>
- <link rel="stylesheet" href="../../../../packages/charted/charts/themes/quantum_theme.css">
- <style>
-.chart-wrapper {
-}
-.chart-host-wrapper {
- display: flex;
- flex-direction: row;
- max-height: 250px;
-}
-.chart-host {
- flex: 1;
-}
-.chart-legend-host {
- flex: 1;
- overflow-x: auto;
- overflow-y: auto;
-}
- </style>
- <div class="chart-wrapper" id="isolate-counter-chart">
- <div class="chart-host-wrapper">
- <div class="chart-host" id="isolate-counter-chart-host"></div>
- <div class="chart-legend-host" id="isolate-counter-chart-legend-host"></div>
- </div>
- </div>
- </template>
-</polymer-element>
-
<script type="application/dart" src="isolate_summary.dart"></script>
diff --git a/runtime/observatory/lib/src/elements/observatory_application.dart b/runtime/observatory/lib/src/elements/observatory_application.dart
index 4acdc65..0e85692 100644
--- a/runtime/observatory/lib/src/elements/observatory_application.dart
+++ b/runtime/observatory/lib/src/elements/observatory_application.dart
@@ -4,22 +4,24 @@
library observatory_application_element;
-import 'observatory_element.dart';
+import 'dart:html';
import 'package:observatory/app.dart';
-import 'package:polymer/polymer.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
/// Main application tag. Responsible for instantiating an instance of
/// [ObservatoryApplication] which is passed declaratively to all child
/// elements.
-@CustomTag('observatory-application')
-class ObservatoryApplicationElement extends ObservatoryElement {
+class ObservatoryApplicationElement extends HtmlElement {
+ static const tag =
+ const Tag<ObservatoryApplicationElement>('observatory-application');
+
ObservatoryApplication app;
ObservatoryApplicationElement.created() : super.created();
@override
- void domReady() {
- super.domReady();
+ void attached() {
+ super.attached();
app = new ObservatoryApplication(this);
}
}
diff --git a/runtime/observatory/lib/src/elements/observatory_application.html b/runtime/observatory/lib/src/elements/observatory_application.html
deleted file mode 100644
index d91819f..0000000
--- a/runtime/observatory/lib/src/elements/observatory_application.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<link rel="import" href="../../../../packages/polymer/polymer.html">
-
-<link rel="import" href="service_view.html">
-<polymer-element name="observatory-application">
- <!-- This element explicitly manages its child elements -->
-</polymer-element>
-
-<script type="application/dart" src="observatory_application.dart"></script>
\ No newline at end of file
diff --git a/runtime/observatory/lib/src/elements/sample_buffer_control.dart b/runtime/observatory/lib/src/elements/sample_buffer_control.dart
new file mode 100644
index 0000000..dde5eb8
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/sample_buffer_control.dart
@@ -0,0 +1,232 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+import 'package:observatory/src/elements/helpers/uris.dart';
+import 'package:observatory/utils.dart';
+
+class SampleBufferControlChangedElement {
+ final SampleBufferControlElement element;
+ SampleBufferControlChangedElement(this.element);
+}
+
+class SampleBufferControlElement extends HtmlElement implements Renderable {
+ static const tag =
+ const Tag<SampleBufferControlElement>('sample-buffer-control');
+
+ RenderingScheduler<SampleBufferControlElement> _r;
+
+ Stream<RenderedEvent<SampleBufferControlElement>> get onRendered =>
+ _r.onRendered;
+
+ StreamController<SampleBufferControlChangedElement> _onTagChange =
+ new StreamController<SampleBufferControlChangedElement>.broadcast();
+ Stream<SampleBufferControlChangedElement> get onTagChange =>
+ _onTagChange.stream;
+
+ Stream<M.SampleProfileLoadingProgressEvent> _progressStream;
+ M.SampleProfileLoadingProgress _progress;
+ M.SampleProfileTag _tag;
+ bool _showTag = false;
+ bool _profileVM = false;
+ StreamSubscription _subscription;
+
+ M.SampleProfileLoadingProgress get progress => _progress;
+ M.SampleProfileTag get selectedTag => _tag;
+ bool get showTag => _showTag;
+ bool get profileVM => _profileVM;
+
+ set selectedTag(M.SampleProfileTag value) =>
+ _tag = _r.checkAndReact(_tag, value);
+ set showTag(bool value) => _showTag = _r.checkAndReact(_showTag, value);
+ set profileVM(bool value) => _profileVM = _r.checkAndReact(_profileVM, value);
+
+
+ factory SampleBufferControlElement(M.SampleProfileLoadingProgress progress,
+ Stream<M.SampleProfileLoadingProgressEvent> progressStream,
+ {M.SampleProfileTag selectedTag: M.SampleProfileTag.none,
+ bool showTag: true, RenderingQueue queue}) {
+ assert(progress != null);
+ assert(progressStream != null);
+ assert(selectedTag != null);
+ assert(showTag != null);
+ SampleBufferControlElement e = document.createElement(tag.name);
+ e._r = new RenderingScheduler(e, queue: queue);
+ e._progress = progress;
+ e._progressStream = progressStream;
+ e._tag = selectedTag;
+ e._showTag = showTag;
+ return e;
+ }
+
+ SampleBufferControlElement.created() : super.created();
+
+ @override
+ void attached() {
+ super.attached();
+ _r.enable();
+ _subscription = _progressStream.listen((e) {
+ _progress = e.progress;
+ _r.dirty();
+ });
+ }
+
+ @override
+ void detached() {
+ super.detached(); _r.disable(notify: true);
+ children = const [];
+ _subscription.cancel();
+ }
+
+ void render() {
+ var content = <Element>[
+ new HeadingElement.h2()..text = 'Sample buffer',
+ new HRElement()
+ ];
+ switch (_progress.status) {
+ case M.SampleProfileLoadingStatus.fetching :
+ content.addAll(_createStatusMessage('Fetching profile from VM...'));
+ break;
+ case M.SampleProfileLoadingStatus.loading :
+ content.addAll(_createStatusMessage('Loading profile...',
+ progress: _progress.progress));
+ break;
+ case M.SampleProfileLoadingStatus.disabled :
+ content.addAll(_createDisabledMessage());
+ break;
+ case M.SampleProfileLoadingStatus.loaded:
+ content.addAll(_createStatusReport());
+ break;
+ }
+ children = [
+ new DivElement()..classes = ['content-centered-big']
+ ..children = content
+ ];
+ }
+
+ static List<Element> _createStatusMessage(String message,
+ {double progress: 0.0}) {
+ return [new DivElement()..classes = ['statusBox', 'shadow', 'center']
+ ..children = [
+ new DivElement()..classes = ['statusMessage']
+ ..text = message,
+ new DivElement()..style.background = '#0489c3'
+ ..style.width = '$progress%'
+ ..style.height = '15px'
+ ..style.borderRadius = '4px'
+ ]
+ ];
+ }
+
+ static List<Element> _createDisabledMessage() {
+ return [new DivElement()..classes = ['statusBox' 'shadow' 'center']
+ ..children = [
+ new DivElement()
+ ..children = [
+ new HeadingElement.h1()
+ ..text = 'Profiling is disabled',
+ new BRElement(),
+ new DivElement()
+ ..innerHtml = 'Perhaps the <b>profile</b> '
+ 'flag has been disabled for this VM.',
+ new BRElement(),
+ new SpanElement()..text = 'See all',
+ new AnchorElement(href: Uris.flags())..text = 'vm flags'
+ ]
+ ]
+ ];
+ }
+
+ List<Element> _createStatusReport() {
+ final fetchT = Utils.formatDurationInSeconds(_progress.fetchingTime);
+ final loadT = Utils.formatDurationInSeconds(_progress.loadingTime);
+ final sampleCount = _progress.profile.sampleCount;
+ final refreshT = new DateTime.now();
+ final stackDepth = _progress.profile.stackDepth;
+ final sampleRate = _progress.profile.sampleRate.toStringAsFixed(0);
+ final timeSpan = _progress.profile.sampleCount == 0 ? '0s'
+ : Utils.formatTimePrecise(_progress.profile.timeSpan);
+
+ var content = <Element>[
+ new DivElement()..classes = ['memberItem']
+ ..children = [
+ new DivElement()..classes = ['memberName']
+ ..text = 'Refreshed at',
+ new DivElement()..classes = ['memberValue']
+ ..text = '$refreshT (fetched in ${fetchT}s) (loaded in ${loadT}s)'
+ ],
+ new DivElement()..classes = ['memberItem']
+ ..children = [
+ new DivElement()..classes = ['memberName']
+ ..text = 'Profile contains ',
+ new DivElement()..classes = ['memberValue']
+ ..text = '$sampleCount samples (spanning $timeSpan)'
+ ],
+ new DivElement()..classes = ['memberItem']
+ ..children = [
+ new DivElement()..classes = ['memberName']
+ ..text = 'Sampling',
+ new DivElement()..classes = ['memberValue']
+ ..text = '$stackDepth stack frames @ ${sampleRate}Hz'
+ ],
+ ];
+ if (_showTag) {
+ content.add(
+ new DivElement()..classes = ['memberItem']
+ ..children = [
+ new DivElement()..classes = ['memberName']
+ ..text = 'Tag Order',
+ new DivElement()..classes = ['memberValue']
+ ..children = _createTagSelect()
+ ]
+ );
+ }
+ return [
+ new DivElement()..classes = ['memberList']
+ ..children = content
+ ];
+ }
+
+ List<Element> _createTagSelect() {
+ var values = M.SampleProfileTag.values;
+ if (!_profileVM) {
+ values = const [M.SampleProfileTag.userOnly, M.SampleProfileTag.none];
+ }
+ var s;
+ return [
+ s = new SelectElement()..classes = ['tag-select']
+ ..value = tagToString(_tag)
+ ..children = values.map((tag) {
+ return new OptionElement(value : tagToString(tag),
+ selected: _tag == tag)
+ ..text = tagToString(tag);
+ }).toList(growable: false)
+ ..onChange.listen((_) {
+ _tag = values[s.selectedIndex];
+ })
+ ..onChange.map(_toEvent).listen(_triggerModeChange),
+ ];
+ }
+
+ static String tagToString(M.SampleProfileTag tag) {
+ switch (tag) {
+ case M.SampleProfileTag.userVM: return 'User > VM';
+ case M.SampleProfileTag.userOnly: return 'User';
+ case M.SampleProfileTag.vmUser: return 'VM > User';
+ case M.SampleProfileTag.vmOnly: return 'VM';
+ case M.SampleProfileTag.none: return 'None';
+ }
+ throw new Exception('Unknown tagToString');
+ }
+
+ SampleBufferControlChangedElement _toEvent(_) {
+ return new SampleBufferControlChangedElement(this);
+ }
+
+ void _triggerModeChange(e) => _onTagChange.add(e);
+}
diff --git a/runtime/observatory/lib/src/elements/service_view.html b/runtime/observatory/lib/src/elements/service_view.html
index 3ddbbe4..52f6d07 100644
--- a/runtime/observatory/lib/src/elements/service_view.html
+++ b/runtime/observatory/lib/src/elements/service_view.html
@@ -2,7 +2,6 @@
<link rel="import" href="class_view.html">
<link rel="import" href="code_view.html">
<link rel="import" href="context_view.html">
-<link rel="import" href="cpu_profile.html">
<link rel="import" href="error_view.html">
<link rel="import" href="field_view.html">
<link rel="import" href="function_view.html">
diff --git a/runtime/observatory/lib/src/elements/stack_trace_tree_config.dart b/runtime/observatory/lib/src/elements/stack_trace_tree_config.dart
new file mode 100644
index 0000000..b1f2f4e
--- /dev/null
+++ b/runtime/observatory/lib/src/elements/stack_trace_tree_config.dart
@@ -0,0 +1,228 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory/src/elements/helpers/tag.dart';
+
+enum ProfileTreeMode {
+ code,
+ function,
+}
+
+class StackTraceTreeConfigChangedEvent {
+ final StackTraceTreeConfigElement element;
+ StackTraceTreeConfigChangedEvent(this.element);
+}
+
+class StackTraceTreeConfigElement extends HtmlElement implements Renderable {
+ static const tag =
+ const Tag<StackTraceTreeConfigElement>('stack-trace-tree-config');
+
+ RenderingScheduler<StackTraceTreeConfigElement> _r;
+
+ Stream<RenderedEvent<StackTraceTreeConfigElement>> get onRendered =>
+ _r.onRendered;
+
+ StreamController<StackTraceTreeConfigChangedEvent> _onModeChange =
+ new StreamController<StackTraceTreeConfigChangedEvent>.broadcast();
+ StreamController<StackTraceTreeConfigChangedEvent> _onDirectionChange =
+ new StreamController<StackTraceTreeConfigChangedEvent>.broadcast();
+ StreamController<StackTraceTreeConfigChangedEvent> _onFilterChange =
+ new StreamController<StackTraceTreeConfigChangedEvent>.broadcast();
+ Stream<StackTraceTreeConfigChangedEvent> get onModeChange =>
+ _onModeChange.stream;
+ Stream<StackTraceTreeConfigChangedEvent> get onDirectionChange =>
+ _onDirectionChange.stream;
+ Stream<StackTraceTreeConfigChangedEvent> get onFilterChange =>
+ _onFilterChange.stream;
+
+ bool _showMode;
+ bool _showDirection;
+ bool _showFilter;
+ ProfileTreeMode _mode;
+ M.ProfileTreeDirection _direction;
+ String _filter;
+
+ bool get showMode => _showMode;
+ bool get showDirection => _showDirection;
+ bool get showFilter => _showFilter;
+ ProfileTreeMode get mode => _mode;
+ M.ProfileTreeDirection get direction => _direction;
+ String get filter => _filter;
+
+ set showMode(bool value) => _showMode = _r.checkAndReact(_showMode, value);
+ set showDirection(bool value) =>
+ _showDirection = _r.checkAndReact(_showDirection, value);
+ set showFilter(bool value) =>
+ _showFilter = _r.checkAndReact(_showFilter, value);
+ set mode(ProfileTreeMode value) => _mode = _r.checkAndReact(_mode, value);
+ set direction(M.ProfileTreeDirection value) =>
+ _direction = _r.checkAndReact(_direction, value);
+ set filter(String value) => _filter = _r.checkAndReact(_filter, value);
+
+ factory StackTraceTreeConfigElement({bool showMode: true,
+ bool showDirection: true, bool showFilter: true, String filter: '',
+ ProfileTreeMode mode: ProfileTreeMode.function,
+ M.ProfileTreeDirection direction: M.ProfileTreeDirection.exclusive,
+ RenderingQueue queue}) {
+ assert(showMode != null);
+ assert(showDirection != null);
+ assert(showFilter != null);
+ assert(mode != null);
+ assert(direction != null);
+ assert(filter != null);
+ StackTraceTreeConfigElement e = document.createElement(tag.name);
+ e._r = new RenderingScheduler(e, queue: queue);
+ e._showMode = showMode;
+ e._showDirection = showDirection;
+ e._showFilter = showFilter;
+ e._mode = mode;
+ e._direction = direction;
+ e._filter = filter;
+ return e;
+ }
+
+ StackTraceTreeConfigElement.created() : super.created();
+
+ @override
+ void attached() {
+ super.attached();
+ _r.enable();
+ }
+
+ @override
+ void detached() {
+ super.detached(); _r.disable(notify: true);
+ children = const [];
+ }
+
+ void render() {
+ children = [
+ new DivElement()..classes = ['content-centered-big']
+ ..children = [
+ new HeadingElement.h2()..text = 'Tree display',
+ new HRElement(),
+ new DivElement()..classes = ['row']
+ ..children = [
+ new DivElement()..classes = ['memberList']
+ ..children = _createMembers()
+ ]
+ ]
+ ];
+ }
+
+ List<Element> _createMembers() {
+ var members = <Element>[];
+ if (_showMode) {
+ members.add(
+ new DivElement()..classes = ['memberItem']
+ ..children = [
+ new DivElement()..classes = ['memberName']..text = 'Mode',
+ new DivElement()..classes = ['memberValue']
+ ..children = _createModeSelect()
+ ]
+ );
+ }
+ if (_showDirection) {
+ members.add(
+ new DivElement()..classes = ['memberItem']
+ ..children = [
+ new DivElement()..classes = ['memberName']
+ ..text = 'Call Tree Direction',
+ new SpanElement()..classes = ['memberValue']
+ ..children = _createDirectionSelect()
+ ]
+ );
+ }
+ if (showFilter) {
+ members.add(
+ new DivElement()..classes = ['memberItem']
+ ..children = [
+ new DivElement()..classes = ['memberName']
+ ..text = 'Call Tree Filter'
+ ..title = 'case-sensitive substring match',
+ new SpanElement()..classes = ['memberValue']
+ ..children = _createFilter()
+ ]
+ );
+ }
+ return members;
+ }
+
+ List<Element> _createModeSelect() {
+ var s;
+ return [
+ s = new SelectElement()..classes = ['mode-select']
+ ..value = modeToString(_mode)
+ ..children = ProfileTreeMode.values.map((mode) {
+ return new OptionElement(value : modeToString(mode),
+ selected: _mode == mode)
+ ..text = modeToString(mode);
+ }).toList(growable: false)
+ ..onChange.listen((_) {
+ _mode = ProfileTreeMode.values[s.selectedIndex];
+ })
+ ..onChange.map(_toEvent).listen(_triggerModeChange),
+ ];
+ }
+
+ List<Element> _createDirectionSelect() {
+ var s;
+ return [
+ s = new SelectElement()..classes = ['direction-select']
+ ..value = directionToString(_direction)
+ ..children = M.ProfileTreeDirection.values.map((direction) {
+ return new OptionElement(value: directionToString(direction),
+ selected: _direction == direction)
+ ..text = directionToString(direction);
+ }).toList(growable: false)
+ ..onChange.listen((_) {
+ _direction = M.ProfileTreeDirection.values[s.selectedIndex];
+ })
+ ..onChange.map(_toEvent).listen(_triggerDirectionChange),
+ new SpanElement()..text = 'Tree is rooted at ' +
+ (_direction == 'Down' ? '"main"' : 'function / code') +
+ '. Child nodes are callers.'
+ ];
+ }
+
+ List<Element> _createFilter(){
+ var t;
+ return [
+ t = new TextInputElement()..placeholder = 'Search filter'
+ ..value = filter
+ ..onChange.listen((_) { _filter = t.value; })
+ ..onChange.map(_toEvent).listen(_triggerFilterChange)
+ ];
+ }
+
+ static String modeToString(ProfileTreeMode mode) {
+ switch (mode) {
+ case ProfileTreeMode.code: return 'Code';
+ case ProfileTreeMode.function: return 'Function';
+ }
+ throw new Exception('Unknown ProfileTreeMode');
+ }
+
+ static String directionToString(M.ProfileTreeDirection direction) {
+ switch (direction) {
+ case M.ProfileTreeDirection.inclusive: return 'Top down';
+ case M.ProfileTreeDirection.exclusive: return 'Bottom up';
+ }
+ throw new Exception('Unknown ProfileTreeDirection');
+ }
+
+ StackTraceTreeConfigChangedEvent _toEvent(_) {
+ return new StackTraceTreeConfigChangedEvent(this);
+ }
+
+ void _triggerModeChange(e) => _onModeChange.add(e);
+ void _triggerDirectionChange(e) => _onDirectionChange.add(e);
+ void _triggerFilterChange(e) => _onFilterChange.add(e);
+
+
+}
diff --git a/runtime/observatory/lib/src/models/objects/error.dart b/runtime/observatory/lib/src/models/objects/error.dart
index 23de456..8b36aed 100644
--- a/runtime/observatory/lib/src/models/objects/error.dart
+++ b/runtime/observatory/lib/src/models/objects/error.dart
@@ -6,14 +6,14 @@
enum ErrorKind {
/// The isolate has encountered an unhandled Dart exception.
- UnhandledException,
+ unhandledException,
/// The isolate has encountered a Dart language error in the program.
- LanguageError,
+ languageError,
/// The isolate has encounted an internal error. These errors should be
/// reported as bugs.
- InternalError,
+ internalError,
/// The isolate has been terminated by an external source.
- TerminationError
+ terminationError
}
abstract class ErrorRef extends ObjectRef {
diff --git a/runtime/observatory/lib/src/models/objects/heap_space.dart b/runtime/observatory/lib/src/models/objects/heap_space.dart
new file mode 100644
index 0000000..29c55ce
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/heap_space.dart
@@ -0,0 +1,10 @@
+// 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 HeapSpace {
+ int get used;
+ int get capacity;
+}
diff --git a/runtime/observatory/lib/src/models/objects/isolate.dart b/runtime/observatory/lib/src/models/objects/isolate.dart
index 81d54c5..45f5524 100644
--- a/runtime/observatory/lib/src/models/objects/isolate.dart
+++ b/runtime/observatory/lib/src/models/objects/isolate.dart
@@ -5,12 +5,58 @@
part of models;
abstract class IsolateRef {
+ /// The id which is passed to the getIsolate RPC to reload this
+ /// isolate.
String get id;
+
+ /// A numeric id for this isolate, represented as a string. Unique.
int get number;
+
+ /// A name identifying this isolate. Not guaranteed to be unique.
String get name;
}
abstract class Isolate extends IsolateRef {
+ /// The time that the VM started in milliseconds since the epoch.
DateTime get startTime;
+
+ /// Is the isolate in a runnable state?
bool get runnable;
+
+ /// The number of live ports for this isolate.
+ //int get livePorts;
+
+ /// Will this isolate pause when exiting?
+ //bool get pauseOnExit;
+
+ /// The last pause event delivered to the isolate. If the isolate is
+ /// running, this will be a resume event.
+ //Event get pauseEvent;
+
+ /// [optional] The root library for this isolate.
+ ///
+ /// Guaranteed to be initialized when the IsolateRunnable event fires.
+ //LibraryRef get rootLib;
+
+ /// A list of all libraries for this isolate.
+ ///
+ /// Guaranteed to be initialized when the IsolateRunnable event fires.
+ Iterable<LibraryRef> get libraries;
+
+ /// A list of all breakpoints for this isolate.
+ //Iterable<Breakpoint> get breakpoints;
+
+ /// [optional] The error that is causing this isolate to exit, if applicable.
+ Error get error;
+
+ /// The current pause on exception mode for this isolate.
+ //ExceptionPauseMode get exceptionPauseMode;
+
+ /// [optional]The list of service extension RPCs that are registered for this
+ /// isolate, if any.
+ Iterable<String> get extensionRPCs;
+
+ Map get counters;
+ HeapSpace get newSpace;
+ HeapSpace get oldSpace;
}
diff --git a/runtime/observatory/lib/src/models/objects/sample_profile.dart b/runtime/observatory/lib/src/models/objects/sample_profile.dart
new file mode 100644
index 0000000..5c5a983
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/sample_profile.dart
@@ -0,0 +1,64 @@
+// 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;
+
+enum ProfileTreeDirection {
+ inclusive,
+ exclusive
+}
+
+abstract class SampleProfile {
+ int get sampleCount;
+ int get stackDepth;
+ double get sampleRate;
+ double get timeSpan;
+
+ FunctionCallTree loadFunctionTree(ProfileTreeDirection direction);
+ CodeCallTree loadCodeTree(ProfileTreeDirection direction);
+}
+
+abstract class Profile {
+ double get normalizedExclusiveTicks;
+ double get normalizedInclusiveTicks;
+}
+
+abstract class ProfileCode extends Profile {
+ CodeRef get code;
+}
+
+abstract class ProfileFunction extends Profile {
+ FunctionRef get function;
+}
+
+typedef bool CallTreeNodeFilter(CallTreeNode);
+
+abstract class CallTree {
+ CallTree filtered(CallTreeNodeFilter filter);
+}
+
+abstract class CodeCallTree extends CallTree {
+ CodeCallTreeNode get root;
+ CodeCallTree filtered(CallTreeNodeFilter filter);
+}
+
+abstract class FunctionCallTree extends CallTree {
+ FunctionCallTreeNode get root;
+ FunctionCallTree filtered(CallTreeNodeFilter filter);
+}
+
+abstract class CallTreeNode {
+ double get percentage;
+ Iterable<CallTreeNode> get children;
+}
+
+abstract class CodeCallTreeNode extends CallTreeNode {
+ ProfileCode get profileCode;
+ Iterable<CodeCallTreeNode> get children;
+}
+
+abstract class FunctionCallTreeNode extends CallTreeNode {
+ ProfileFunction get profileFunction;
+ Iterable<FunctionCallTreeNode> get children;
+}
diff --git a/runtime/observatory/lib/src/models/repositories/sample_profile.dart b/runtime/observatory/lib/src/models/repositories/sample_profile.dart
new file mode 100644
index 0000000..3ec7cfd
--- /dev/null
+++ b/runtime/observatory/lib/src/models/repositories/sample_profile.dart
@@ -0,0 +1,52 @@
+// 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;
+
+enum SampleProfileTag {
+ userVM,
+ userOnly,
+ vmUser,
+ vmOnly,
+ none
+}
+
+enum SampleProfileLoadingStatus {
+ disabled,
+ fetching,
+ loading,
+ loaded
+}
+
+bool isSampleProcessRunning(SampleProfileLoadingStatus status) {
+ switch (status) {
+ case SampleProfileLoadingStatus.fetching:
+ case SampleProfileLoadingStatus.loading:
+ return true;
+ default:
+ return false;
+ }
+}
+
+abstract class SampleProfileLoadingProgressEvent {
+ SampleProfileLoadingProgress get progress;
+}
+
+abstract class SampleProfileLoadingProgress {
+ SampleProfileLoadingStatus get status;
+ double get progress;
+ Duration get fetchingTime;
+ Duration get loadingTime;
+ SampleProfile get profile;
+}
+
+abstract class ClassSampleProfileRepository {
+ Stream<SampleProfileLoadingProgressEvent> get(ClassRef cls,
+ SampleProfileTag tag, {bool clear: false});
+}
+
+abstract class IsolateSampleProfileRepository {
+ Stream<SampleProfileLoadingProgressEvent> get(IsolateRef cls,
+ SampleProfileTag tag, {bool clear: false, bool forceFetch: false});
+}
diff --git a/runtime/observatory/lib/src/repositories/sample_profile.dart b/runtime/observatory/lib/src/repositories/sample_profile.dart
new file mode 100644
index 0000000..5752139
--- /dev/null
+++ b/runtime/observatory/lib/src/repositories/sample_profile.dart
@@ -0,0 +1,137 @@
+// 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;
+
+String _tagToString(M.SampleProfileTag tag) {
+ switch (tag) {
+ case M.SampleProfileTag.userVM: return 'UserVM';
+ case M.SampleProfileTag.userOnly: return 'UserOnly';
+ case M.SampleProfileTag.vmUser: return 'VMUser';
+ case M.SampleProfileTag.vmOnly: return 'VMOnly';
+ case M.SampleProfileTag.none: return 'None';
+ }
+ throw new Exception('Unknown SampleProfileTag: $tag');
+}
+
+class SampleProfileLoadingProgressEvent
+ implements M.SampleProfileLoadingProgressEvent {
+ final SampleProfileLoadingProgress progress;
+ SampleProfileLoadingProgressEvent(this.progress);
+}
+
+class SampleProfileLoadingProgress extends M.SampleProfileLoadingProgress {
+ StreamController<SampleProfileLoadingProgressEvent> _onProgress =
+ new StreamController<SampleProfileLoadingProgressEvent>.broadcast();
+ Stream<SampleProfileLoadingProgressEvent> get onProgress =>
+ _onProgress.stream;
+
+ final S.Isolate isolate;
+ final S.Class cls;
+ final M.SampleProfileTag tag;
+ final bool clear;
+
+ M.SampleProfileLoadingStatus _status = M.SampleProfileLoadingStatus.fetching;
+ double _progress = 0.0;
+ final Stopwatch _fetchingTime = new Stopwatch();
+ final Stopwatch _loadingTime = new Stopwatch();
+ CpuProfile _profile;
+
+ M.SampleProfileLoadingStatus get status => _status;
+ double get progress => _progress;
+ Duration get fetchingTime => _fetchingTime.elapsed;
+ Duration get loadingTime => _loadingTime.elapsed;
+ CpuProfile get profile => _profile;
+
+ SampleProfileLoadingProgress(this.isolate, this.tag,
+ this.clear, {this.cls}) {
+ _run();
+ }
+
+ Future _run() async {
+ _fetchingTime.start();
+ try {
+ if (clear) {
+ await isolate.invokeRpc('_clearCpuProfile', { });
+ }
+
+ final response = cls != null
+ ? await cls.getAllocationSamples(_tagToString(tag))
+ : await isolate.invokeRpc('_getCpuProfile',
+ { 'tags': _tagToString(tag) });
+
+ _fetchingTime.stop();
+ _loadingTime.start();
+ _status = M.SampleProfileLoadingStatus.loading;
+ _triggerOnProgress();
+
+ CpuProfile profile = new CpuProfile();
+
+ Stream<double> progress = profile.loadProgress(isolate, response);
+ progress.listen((value) { _progress = value; _triggerOnProgress(); });
+
+ await progress.drain();
+
+ profile.buildFunctionCallerAndCallees();
+ _profile = profile;
+
+ _loadingTime.stop();
+ _status = M.SampleProfileLoadingStatus.loaded;
+ _triggerOnProgress();
+ } catch (e) {
+ if (e is S.ServerRpcException) {
+ if (e.code == S.ServerRpcException.kFeatureDisabled) {
+ _status = M.SampleProfileLoadingStatus.disabled;
+ _triggerOnProgress();
+ }
+ }
+ rethrow;
+ } finally {
+ _onProgress.close();
+ }
+ }
+
+ void _triggerOnProgress() {
+ _onProgress.add(new SampleProfileLoadingProgressEvent(this));
+ }
+
+ void reuse() {
+ _onProgress =
+ new StreamController<SampleProfileLoadingProgressEvent>.broadcast();
+ (() async {
+ _triggerOnProgress();
+ _onProgress.close();
+ }());
+ }
+}
+
+class IsolateSampleProfileRepository
+ implements M.IsolateSampleProfileRepository {
+ SampleProfileLoadingProgress _last;
+
+ Stream<SampleProfileLoadingProgressEvent> get(M.IsolateRef i,
+ M.SampleProfileTag t, {bool clear: false, bool forceFetch: false}) {
+ assert(clear != null);
+ assert(forceFetch != null);
+ S.Isolate isolate = i as S.Isolate;
+ assert(isolate != null);
+ if (_last != null && !clear && !forceFetch && _last.isolate == isolate) {
+ _last.reuse();
+ } else {
+ _last = new SampleProfileLoadingProgress(isolate, t, clear);
+ }
+ return _last.onProgress;
+ }
+}
+
+class ClassSampleProfileRepository
+ implements M.ClassSampleProfileRepository {
+ Stream<SampleProfileLoadingProgressEvent> get(M.ClassRef c,
+ M.SampleProfileTag t, {bool clear: false}) {
+ S.Class cls = c as S.Class;
+ assert(cls != null);
+ return new SampleProfileLoadingProgress(cls.isolate, t,
+ clear, cls: cls).onProgress;
+ }
+}
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index afd9240..525b1b7 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1077,7 +1077,7 @@
}
}
-class HeapSpace extends Observable {
+class HeapSpace extends Observable implements M.HeapSpace {
@observable int used = 0;
@observable int capacity = 0;
@observable int external = 0;
@@ -1139,7 +1139,7 @@
return (new DateTime.now().difference(startTime));
}
- @observable ObservableMap counters = new ObservableMap();
+ @observable Map counters = {};
void _updateRunState() {
topFrame = (pauseEvent != null ? pauseEvent.topFrame : null);
@@ -1441,18 +1441,18 @@
for (var i = 0; i < counts.length; i++) {
sum += counts[i];
}
- // TODO: Why does this not work without this?
- counters = toObservable({});
+ var _counters = {};
if (sum == 0) {
for (var i = 0; i < names.length; i++) {
- counters[names[i]] = '0.0%';
+ _counters[names[i]] = '0.0%';
}
} else {
for (var i = 0; i < names.length; i++) {
- counters[names[i]] =
+ _counters[names[i]] =
(counts[i] / sum * 100.0).toStringAsFixed(2) + '%';
}
}
+ counters = _counters;
}
updateHeapsFromMap(map['_heaps']);
@@ -1855,10 +1855,10 @@
M.ErrorKind stringToErrorKind(String value) {
switch(value) {
- case 'UnhandledException': return M.ErrorKind.UnhandledException;
- case 'LanguageError': return M.ErrorKind.UnhandledException;
- case 'InternalError': return M.ErrorKind.InternalError;
- case 'TerminationError': return M.ErrorKind.TerminationError;
+ case 'UnhandledException': return M.ErrorKind.unhandledException;
+ case 'LanguageError': return M.ErrorKind.unhandledException;
+ case 'InternalError': return M.ErrorKind.internalError;
+ case 'TerminationError': return M.ErrorKind.terminationError;
}
Logger.root.severe('Unrecognized error kind: $value');
throw new FallThroughError();
diff --git a/runtime/observatory/lib/utils.dart b/runtime/observatory/lib/utils.dart
index cfc447c..a69af52 100644
--- a/runtime/observatory/lib/utils.dart
+++ b/runtime/observatory/lib/utils.dart
@@ -146,6 +146,10 @@
return x.toStringAsFixed(2);
}
+ static String formatDurationInSeconds(Duration x) {
+ return formatSeconds(x.inMilliseconds / Duration.MILLISECONDS_PER_SECOND);
+ }
+
static bool runningInJavaScript() => identical(1.0, 1);
}
diff --git a/runtime/observatory/observatory_sources.gypi b/runtime/observatory/observatory_sources.gypi
index fe89855..4e2ec39 100644
--- a/runtime/observatory/observatory_sources.gypi
+++ b/runtime/observatory/observatory_sources.gypi
@@ -49,8 +49,10 @@
'lib/src/elements/context_view.html',
'lib/src/elements/containers/virtual_collection.dart',
'lib/src/elements/containers/virtual_tree.dart',
+ 'lib/src/elements/cpu_profile_table.dart',
+ 'lib/src/elements/cpu_profile_table.html',
'lib/src/elements/cpu_profile.dart',
- 'lib/src/elements/cpu_profile.html',
+ 'lib/src/elements/cpu_profile/virtual_tree.dart',
'lib/src/elements/css/shared.css',
'lib/src/elements/curly_block.dart',
'lib/src/elements/curly_block_wrapper.dart',
@@ -100,9 +102,11 @@
'lib/src/elements/io_view.dart',
'lib/src/elements/io_view.html',
'lib/src/elements/isolate_reconnect.dart',
- 'lib/src/elements/isolate_reconnect.html',
'lib/src/elements/isolate_ref.dart',
'lib/src/elements/isolate_ref_wrapper.dart',
+ 'lib/src/elements/isolate/counter_chart.dart',
+ 'lib/src/elements/isolate/shared_summary_wrapper.dart',
+ 'lib/src/elements/isolate/shared_summary.dart',
'lib/src/elements/isolate_summary.dart',
'lib/src/elements/isolate_summary.html',
'lib/src/elements/isolate_view.dart',
@@ -151,12 +155,12 @@
'lib/src/elements/objectpool_view.dart',
'lib/src/elements/objectpool_view.html',
'lib/src/elements/observatory_application.dart',
- 'lib/src/elements/observatory_application.html',
'lib/src/elements/observatory_element.dart',
'lib/src/elements/persistent_handles.dart',
'lib/src/elements/persistent_handles.html',
'lib/src/elements/ports.dart',
'lib/src/elements/ports.html',
+ 'lib/src/elements/sample_buffer_control.dart',
'lib/src/elements/script_inset.dart',
'lib/src/elements/script_inset.html',
'lib/src/elements/script_ref_wrapper.dart',
@@ -170,6 +174,7 @@
'lib/src/elements/source_link_wrapper.dart',
'lib/src/elements/source_link.dart',
'lib/src/elements/shims/binding.dart',
+ 'lib/src/elements/stack_trace_tree_config.dart',
'lib/src/elements/timeline_page.dart',
'lib/src/elements/timeline_page.html',
'lib/src/elements/view_footer.dart',
@@ -187,11 +192,13 @@
'lib/src/models/objects/flag.dart',
'lib/src/models/objects/frame.dart',
'lib/src/models/objects/function.dart',
+ 'lib/src/models/objects/heap_space.dart',
'lib/src/models/objects/instance.dart',
'lib/src/models/objects/isolate.dart',
'lib/src/models/objects/library.dart',
'lib/src/models/objects/notification.dart',
'lib/src/models/objects/object.dart',
+ 'lib/src/models/objects/sample_profile.dart',
'lib/src/models/objects/script.dart',
'lib/src/models/objects/source_location.dart',
'lib/src/models/objects/target.dart',
@@ -202,6 +209,7 @@
'lib/src/models/repositories/flag.dart',
'lib/src/models/repositories/instance.dart',
'lib/src/models/repositories/notification.dart',
+ 'lib/src/models/repositories/sample_profile.dart',
'lib/src/models/repositories/script.dart',
'lib/src/models/repositories/target.dart',
'lib/src/repositories/class.dart',
@@ -209,6 +217,7 @@
'lib/src/repositories/flag.dart',
'lib/src/repositories/instance.dart',
'lib/src/repositories/notification.dart',
+ 'lib/src/repositories/sample_profile.dart',
'lib/src/repositories/script.dart',
'lib/src/repositories/settings.dart',
'lib/src/repositories/target.dart',
diff --git a/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart
index 0f0eed2..41aeb10 100644
--- a/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/class_ref/element_test.dart
@@ -1,24 +1,25 @@
// 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/src/elements/class_ref.dart';
import '../mocks.dart';
-main(){
+main() {
ClassRefElement.tag.ensureRegistration();
- final IsolateRefMock isolate = new IsolateRefMock(id: 'i-id', name: 'i-name');
- final ClassRefMock cls = new ClassRefMock(id: 'c-id', name: 'c-name');
+ const isolate = const IsolateRefMock();
+ const cls = const ClassRefMock();
test('instantiation', () {
- final ClassRefElement e = new ClassRefElement(isolate, cls);
+ final e = new ClassRefElement(isolate, cls);
expect(e, isNotNull, reason: 'element correctly created');
expect(e.isolate, equals(isolate));
expect(e.cls, equals(cls));
});
test('elements created after attachment', () async {
- final ClassRefElement e = new ClassRefElement(isolate, cls);
+ final e = new ClassRefElement(isolate, cls);
document.body.append(e);
await e.onRendered.first;
expect(e.children.length, isNonZero, reason: 'has elements');
diff --git a/runtime/observatory/tests/observatory_ui/class_tree/element_test.dart b/runtime/observatory/tests/observatory_ui/class_tree/element_test.dart
index 518613f..5d20331 100644
--- a/runtime/observatory/tests/observatory_ui/class_tree/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/class_tree/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/class_tree.dart';
diff --git a/runtime/observatory/tests/observatory_ui/code_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/code_ref/element_test.dart
index 694d81b..7a65c84 100644
--- a/runtime/observatory/tests/observatory_ui/code_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/code_ref/element_test.dart
@@ -1,12 +1,13 @@
// 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/src/elements/code_ref.dart';
import '../mocks.dart';
-main(){
+main() {
CodeRefElement.tag.ensureRegistration();
final isolate = new IsolateRefMock(id: 'i-id', name: 'i-name');
diff --git a/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.dart b/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.dart
new file mode 100644
index 0000000..249d465
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.dart
@@ -0,0 +1,80 @@
+// 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 'dart:async';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/cpu_profile.dart';
+import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
+import 'package:observatory/src/elements/stack_trace_tree_config.dart';
+import 'package:observatory/src/elements/sample_buffer_control.dart';
+import '../mocks.dart';
+
+main() {
+ CpuProfileElement.tag.ensureRegistration();
+
+ final sTag = SampleBufferControlElement.tag.name;
+ final cTag = StackTraceTreeConfigElement.tag.name;
+ final tTag = CpuProfileVirtualTreeElement.tag.name;
+
+ const vm = const VMMock();
+ const isolate = const IsolateRefMock();
+ final events = new EventRepositoryMock();
+ final notifs = new NotificationRepositoryMock();
+ test('instantiation', () {
+ final profiles = new IsolateSampleProfileRepositoryMock();
+ final e = new CpuProfileElement(vm, isolate, events, notifs, profiles);
+ expect(e, isNotNull, reason: 'element correctly created');
+ });
+ test('elements created', () async {
+ final controller
+ = new StreamController<M.SampleProfileLoadingProgressEvent>.broadcast();
+ final profiles = new IsolateSampleProfileRepositoryMock(
+ getter: (M.IsolateRef i, M.SampleProfileTag t, bool clear,
+ bool forceFetch) {
+ expect(i, equals(isolate));
+ expect(t, isNotNull);
+ expect(clear, isFalse);
+ expect(forceFetch, isFalse);
+ return controller.stream;
+ }
+ );
+ final e = new CpuProfileElement(vm, isolate, events, notifs, profiles);
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.children.length, isNonZero, reason: 'has elements');
+ expect(e.querySelectorAll(sTag).length, isZero);
+ expect(e.querySelectorAll(cTag).length, isZero);
+ expect(e.querySelectorAll(tTag).length, isZero);
+ controller.add(new SampleProfileLoadingProgressEventMock(
+ progress: new SampleProfileLoadingProgressMock(
+ status: M.SampleProfileLoadingStatus.fetching
+ )
+ ));
+ await e.onRendered.first;
+ expect(e.querySelectorAll(sTag).length, equals(1));
+ expect(e.querySelectorAll(cTag).length, isZero);
+ expect(e.querySelectorAll(tTag).length, isZero);
+ controller.add(new SampleProfileLoadingProgressEventMock(
+ progress: new SampleProfileLoadingProgressMock(
+ status: M.SampleProfileLoadingStatus.loading
+ )
+ ));
+ controller.add(new SampleProfileLoadingProgressEventMock(
+ progress: new SampleProfileLoadingProgressMock(
+ status: M.SampleProfileLoadingStatus.loaded,
+ profile: new SampleProfileMock()
+ )
+ ));
+ controller.close();
+ await e.onRendered.first;
+ expect(e.querySelectorAll(sTag).length, equals(1));
+ expect(e.querySelectorAll(cTag).length, equals(1));
+ expect(e.querySelectorAll(tTag).length, equals(1));
+ e.remove();
+ await e.onRendered.first;
+ expect(e.children.length, isZero, reason: 'is empty');
+ });
+}
diff --git a/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.html b/runtime/observatory/tests/observatory_ui/cpu_profile/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/cpu_profile/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/observatory_ui/cpu_profile/virtual-tree/element_test.dart b/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.dart
new file mode 100644
index 0000000..cb93e56
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.dart
@@ -0,0 +1,53 @@
+// 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/models.dart' as M;
+import 'package:observatory/src/elements/cpu_profile/virtual_tree.dart';
+import '../../mocks.dart';
+
+main() {
+ CpuProfileVirtualTreeElement.tag.ensureRegistration();
+ const isolate = const IsolateRefMock();
+ group('instantiation', () {
+ final profile = new SampleProfileMock();
+ test('default', () {
+ final e = new CpuProfileVirtualTreeElement(isolate, profile);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.isolate, equals(isolate));
+ expect(e.profile, equals(profile));
+ expect(e.mode, equals(ProfileTreeMode.function));
+ expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+ });
+ test('mode', () {
+ final e = new CpuProfileVirtualTreeElement(isolate, profile,
+ mode: ProfileTreeMode.code);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.isolate, equals(isolate));
+ expect(e.profile, equals(profile));
+ expect(e.mode, equals(ProfileTreeMode.code));
+ expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+ });
+ test('direction', () {
+ final e = new CpuProfileVirtualTreeElement(isolate, profile,
+ direction: M.ProfileTreeDirection.inclusive);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.isolate, equals(isolate));
+ expect(e.profile, equals(profile));
+ expect(e.mode, equals(ProfileTreeMode.function));
+ expect(e.direction, equals(M.ProfileTreeDirection.inclusive));
+ });
+ });
+ test('elements created after attachment', () async {
+ final profile = new SampleProfileMock();
+ final e = new CpuProfileVirtualTreeElement(isolate, profile);
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.children.length, isNonZero, reason: 'has elements');
+ e.remove();
+ await e.onRendered.first;
+ expect(e.children.length, isZero, reason: 'is empty');
+ });
+}
diff --git a/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.html b/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/cpu_profile/virtual-tree/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/observatory_ui/curly_block/element_test.dart b/runtime/observatory/tests/observatory_ui/curly_block/element_test.dart
index 6010bc6..139e235 100644
--- a/runtime/observatory/tests/observatory_ui/curly_block/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/curly_block/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/curly_block.dart';
diff --git a/runtime/observatory/tests/observatory_ui/error_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/error_ref/element_test.dart
index b131472..878f90a 100644
--- a/runtime/observatory/tests/observatory_ui/error_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/error_ref/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/error_ref.dart';
diff --git a/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart b/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart
index d23fffa..327daa1 100644
--- a/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/flag_list/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/flag_list.dart';
diff --git a/runtime/observatory/tests/observatory_ui/function_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/function_ref/element_test.dart
index cd6b8af..4068493 100644
--- a/runtime/observatory/tests/observatory_ui/function_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/function_ref/element_test.dart
@@ -1,12 +1,13 @@
// 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/src/elements/function_ref.dart';
import '../mocks.dart';
-main(){
+main() {
FunctionRefElement.tag.ensureRegistration();
final isolate = new IsolateRefMock(id: 'i-id', name: 'i-name');
diff --git a/runtime/observatory/tests/observatory_ui/general_error/element_test.dart b/runtime/observatory/tests/observatory_ui/general_error/element_test.dart
index e056bac..71ba186 100644
--- a/runtime/observatory/tests/observatory_ui/general_error/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/general_error/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/general_error.dart';
diff --git a/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.dart b/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.dart
new file mode 100644
index 0000000..8aef7df
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.dart
@@ -0,0 +1,25 @@
+// 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/src/elements/isolate/counter_chart.dart';
+
+main() {
+ IsolateCounterChartElement.tag.ensureRegistration();
+
+ test('instantiation', () {
+ final e = new IsolateCounterChartElement({});
+ expect(e, isNotNull, reason: 'element correctly created');
+ });
+ test('elements created', () async {
+ final e = new IsolateCounterChartElement({});
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.children.length, isNonZero, reason: 'has elements');
+ e.remove();
+ await e.onRendered.first;
+ expect(e.children.length, isZero, reason: 'is empty');
+ });
+}
diff --git a/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.html b/runtime/observatory/tests/observatory_ui/isolate/counter_chart/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate/counter_chart/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/observatory_ui/isolate/isolate-shared-summary/element_test.dart b/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.dart
new file mode 100644
index 0000000..14aeeed
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.dart
@@ -0,0 +1,31 @@
+// 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/src/elements/isolate/counter_chart.dart';
+import 'package:observatory/src/elements/isolate/shared_summary.dart';
+import '../../mocks.dart';
+
+main() {
+ IsolateSharedSummaryElement.tag.ensureRegistration();
+
+ final cTag = IsolateCounterChartElement.tag.name;
+
+ const isolate = const IsolateMock();
+ test('instantiation', () {
+ final e = new IsolateSharedSummaryElement(isolate);
+ expect(e, isNotNull, reason: 'element correctly created');
+ });
+ test('elements created', () async {
+ final e = new IsolateSharedSummaryElement(isolate);
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.children.length, isNonZero, reason: 'has elements');
+ expect(e.querySelectorAll(cTag).length, equals(1));
+ e.remove();
+ await e.onRendered.first;
+ expect(e.children.length, isZero, reason: 'is empty');
+ });
+}
diff --git a/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.html b/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate/isolate-shared-summary/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/observatory_ui/isolate_reconnect/element_test.dart b/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.dart
new file mode 100644
index 0000000..9b2a782
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.dart
@@ -0,0 +1,80 @@
+// 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/src/elements/isolate_reconnect.dart';
+import 'package:observatory/src/elements/nav/notify.dart';
+import '../mocks.dart';
+
+main() {
+ IsolateReconnectElement.tag.ensureRegistration();
+
+ final nTag = NavNotifyElement.tag.name;
+
+ EventRepositoryMock events;
+ NotificationRepositoryMock notifications;
+ Uri uri;
+ const vm = const VMMock(isolates: const [
+ const IsolateMock(id: 'i-1-id'), const IsolateMock(id: 'i-2-id')
+ ]);
+ const missing = 'missing-id';
+ setUp(() {
+ events = new EventRepositoryMock();
+ notifications = new NotificationRepositoryMock();
+ uri = new Uri(path: 'path');
+ });
+ test('instantiation', () {
+ final e = new IsolateReconnectElement(vm, events, notifications, missing,
+ uri);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.vm, equals(vm));
+ expect(e.missing, equals(missing));
+ expect(e.uri, equals(uri));
+ });
+ test('elements created after attachment', () async {
+ final e = new IsolateReconnectElement(vm, events, notifications, missing,
+ uri);
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.children.length, isNonZero, reason: 'has elements');
+ expect(e.querySelector(nTag), isNotNull, reason: 'has notifications');
+ expect(e.querySelectorAll('.isolate-link').length,
+ equals(vm.isolates.length), reason: 'has links');
+ e.remove();
+ await e.onRendered.first;
+ expect(e.children.length, isZero, reason: 'is empty');
+ });
+ group('updates', () {
+ test('are correctly listen', () async {
+ final e = new IsolateReconnectElement(vm, events, notifications, missing,
+ uri);
+ expect(events.onVMUpdateHasListener, isFalse);
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(events.onVMUpdateHasListener, isTrue);
+ e.remove();
+ await e.onRendered.first;
+ expect(events.onVMUpdateHasListener, isFalse);
+ });
+ test('have effects', () async {
+ final e = new IsolateReconnectElement(vm, events, notifications, missing,
+ uri);
+ const vm2 = const VMMock(isolates: const [
+ const IsolateMock(id: 'i-1-id'), const IsolateMock(id: 'i-2-id'),
+ const IsolateMock(id: 'i-3-id')
+ ]);
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.querySelectorAll('.isolate-link').length,
+ equals(vm.isolates.length));
+ events.add(new VMUpdateEventMock(vm: vm2));
+ await e.onRendered.first;
+ expect(e.querySelectorAll('.isolate-link').length,
+ equals(vm2.isolates.length));
+ e.remove();
+ await e.onRendered.first;
+ });
+ });
+}
diff --git a/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.html b/runtime/observatory/tests/observatory_ui/isolate_reconnect/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/isolate_reconnect/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/observatory_ui/isolate_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.dart
index 2cfaafc..6d4e25b 100644
--- a/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/isolate_ref/element_test.dart
@@ -1,12 +1,13 @@
// 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/src/elements/isolate_ref.dart';
import '../mocks.dart';
-main(){
+main() {
IsolateRefElement.tag.ensureRegistration();
final ref = new IsolateRefMock(id: 'id', name: 'old-name');
diff --git a/runtime/observatory/tests/observatory_ui/library_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/library_ref/element_test.dart
index 48291b5..f1e2dda 100644
--- a/runtime/observatory/tests/observatory_ui/library_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/library_ref/element_test.dart
@@ -1,12 +1,13 @@
// 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/src/elements/library_ref.dart';
import '../mocks.dart';
-main(){
+main() {
LibraryRefElement.tag.ensureRegistration();
const isolate = const IsolateRefMock(id: 'i-id', name: 'i-name');
diff --git a/runtime/observatory/tests/observatory_ui/mocks.dart b/runtime/observatory/tests/observatory_ui/mocks.dart
index b52b93b..dbe6645 100644
--- a/runtime/observatory/tests/observatory_ui/mocks.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks.dart
@@ -16,9 +16,11 @@
part 'mocks/objects/class.dart';
part 'mocks/objects/flag.dart';
part 'mocks/objects/function.dart';
+part 'mocks/objects/heap_space.dart';
part 'mocks/objects/isolate.dart';
part 'mocks/objects/library.dart';
part 'mocks/objects/notification.dart';
+part 'mocks/objects/sample_profile.dart';
part 'mocks/objects/script.dart';
part 'mocks/objects/source_location.dart';
part 'mocks/objects/target.dart';
@@ -29,5 +31,6 @@
part 'mocks/repositories/flag.dart';
part 'mocks/repositories/instance.dart';
part 'mocks/repositories/notification.dart';
+part 'mocks/repositories/sample_profile.dart';
part 'mocks/repositories/script.dart';
part 'mocks/repositories/target.dart';
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/heap_space.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/heap_space.dart
new file mode 100644
index 0000000..022414c
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/mocks/objects/heap_space.dart
@@ -0,0 +1,11 @@
+// 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 HeapSpaceMock implements M.HeapSpace {
+ final int used;
+ final int capacity;
+ const HeapSpaceMock({this.used: 0, this.capacity: 1});
+}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/isolate.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/isolate.dart
index d65b840..055b84e 100644
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/isolate.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks/objects/isolate.dart
@@ -18,8 +18,18 @@
final String name;
final DateTime startTime;
final bool runnable;
+ final Iterable<M.LibraryRef> libraries;
+ final M.Error error;
+ final Iterable<String> extensionRPCs;
+ final Map counters;
+ final M.HeapSpace newSpace;
+ final M.HeapSpace oldSpace;
const IsolateMock({this.id: 'i-id', this.number, this.name: 'i-name',
- this.startTime, this.runnable: true});
+ this.startTime, this.runnable: true,
+ this.libraries: const [], this.error,
+ this.extensionRPCs: const [], this.counters: const {},
+ this.newSpace: const HeapSpaceMock(),
+ this.oldSpace: const HeapSpaceMock()});
// TODO(cbernaschina) add other properties.
}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/sample_profile.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/sample_profile.dart
new file mode 100644
index 0000000..4e8441c
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/mocks/objects/sample_profile.dart
@@ -0,0 +1,41 @@
+// 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 M.FunctionCallTree SampleProfileMockLoadFunctionTreeCallback(
+ M.ProfileTreeDirection direction);
+typedef M.CodeCallTree SampleProfileMockLoadCodeTreeCallback(
+ M.ProfileTreeDirection direction);
+
+class SampleProfileMock implements M.SampleProfile {
+ final SampleProfileMockLoadFunctionTreeCallback _loadFunctionTree;
+ final SampleProfileMockLoadCodeTreeCallback _loadCodeTree;
+
+
+ final int sampleCount;
+ final int stackDepth;
+ final double sampleRate;
+ final double timeSpan;
+
+ M.FunctionCallTree loadFunctionTree(M.ProfileTreeDirection direction) {
+ if (_loadFunctionTree != null) {
+ return _loadFunctionTree(direction);
+ }
+ return null;
+ }
+ M.CodeCallTree loadCodeTree(M.ProfileTreeDirection direction) {
+ if (_loadCodeTree != null) {
+ return _loadCodeTree(direction);
+ }
+ return null;
+ }
+
+ SampleProfileMock({this.sampleCount: 0, this.stackDepth: 0,
+ this.sampleRate: 1.0, this.timeSpan: 1.0,
+ SampleProfileMockLoadFunctionTreeCallback loadFunctionTree,
+ SampleProfileMockLoadCodeTreeCallback loadCodeTree})
+ : _loadFunctionTree = loadFunctionTree,
+ _loadCodeTree = loadCodeTree;
+}
diff --git a/runtime/observatory/tests/observatory_ui/mocks/repositories/sample_profile.dart b/runtime/observatory/tests/observatory_ui/mocks/repositories/sample_profile.dart
new file mode 100644
index 0000000..ffbf3bf
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/mocks/repositories/sample_profile.dart
@@ -0,0 +1,70 @@
+// 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 SampleProfileLoadingProgressEventMock
+ implements M.SampleProfileLoadingProgressEvent {
+ final M.SampleProfileLoadingProgress progress;
+ SampleProfileLoadingProgressEventMock({this.progress});
+}
+
+class SampleProfileLoadingProgressMock
+ implements M.SampleProfileLoadingProgress {
+ final M.SampleProfileLoadingStatus status;
+ final double progress;
+ final Duration fetchingTime;
+ final Duration loadingTime;
+ final M.SampleProfile profile;
+
+ const SampleProfileLoadingProgressMock({
+ this.status: M.SampleProfileLoadingStatus.disabled,
+ this.progress: 0.0,
+ this.fetchingTime: const Duration(),
+ this.loadingTime: const Duration(),
+ this.profile
+ });
+}
+
+typedef Stream<M.SampleProfileLoadingProgressEvent>
+ ClassSampleProfileRepositoryMockCallback(M.ClassRef cls,
+ M.SampleProfileTag tag, bool clear);
+
+class ClassSampleProfileRepositoryMock
+ implements M.ClassSampleProfileRepository {
+ final ClassSampleProfileRepositoryMockCallback _get;
+
+ Stream<M.SampleProfileLoadingProgressEvent> get(M.ClassRef cls,
+ M.SampleProfileTag tag, {bool clear: false}) {
+ if (_get != null) {
+ return _get(cls, tag, clear);
+ }
+ return null;
+ }
+
+ ClassSampleProfileRepositoryMock(
+ {ClassSampleProfileRepositoryMockCallback getter})
+ : _get = getter;
+}
+
+typedef Stream<M.SampleProfileLoadingProgressEvent>
+ IsolateampleProfileRepositoryMockCallback(M.IsolateRef cls,
+ M.SampleProfileTag tag, bool clear, bool forceFetch);
+
+class IsolateSampleProfileRepositoryMock
+ implements M.IsolateSampleProfileRepository {
+ final IsolateampleProfileRepositoryMockCallback _get;
+
+ Stream<M.SampleProfileLoadingProgressEvent> get(M.IsolateRef isolate,
+ M.SampleProfileTag tag, {bool clear: false, bool forceFetch: false}) {
+ if (_get != null) {
+ return _get(isolate, tag, clear, forceFetch);
+ }
+ return null;
+ }
+
+ IsolateSampleProfileRepositoryMock(
+ {IsolateampleProfileRepositoryMockCallback getter})
+ : _get = getter;
+}
diff --git a/runtime/observatory/tests/observatory_ui/nav/bar/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/bar/element_test.dart
index 98b9653..e450d3e 100644
--- a/runtime/observatory/tests/observatory_ui/nav/bar/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/bar/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/nav/bar.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.dart
index 1b3766d..32fb9f0 100644
--- a/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/class-menu/element_test.dart
@@ -1,12 +1,13 @@
// 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/src/elements/nav/class_menu.dart';
import '../../mocks.dart';
-main(){
+main() {
NavClassMenuElement.tag.ensureRegistration();
final i_ref = const IsolateRefMock(id: 'i-id', name: 'i-name');
diff --git a/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.dart
index 235975f..3241c45 100644
--- a/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/isolate-menu/element_test.dart
@@ -1,13 +1,14 @@
// 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/src/elements/nav/menu.dart';
import 'package:observatory/src/elements/nav/isolate_menu.dart';
import '../../mocks.dart';
-main(){
+main() {
NavIsolateMenuElement.tag.ensureRegistration();
final tag = NavMenuElement.tag.name;
diff --git a/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.dart
index 2144520..86fecea 100644
--- a/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/library-menu/element_test.dart
@@ -1,12 +1,13 @@
// 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/src/elements/nav/library_menu.dart';
import '../../mocks.dart';
-main(){
+main() {
NavLibraryMenuElement.tag.ensureRegistration();
final i_ref = const IsolateRefMock(id: 'i-id', name: 'i-name');
diff --git a/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.dart
index d439a60..5ab71f1 100644
--- a/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/menu-item/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/nav/menu_item.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/menu/element_test.dart
index 7e32086..5b35836 100644
--- a/runtime/observatory/tests/observatory_ui/nav/menu/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/menu/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/nav/menu.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/notify/element_test.dart
index 9cee6cf..cbdebba 100644
--- a/runtime/observatory/tests/observatory_ui/nav/notify/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/notify/element_test.dart
@@ -1,6 +1,7 @@
// 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' hide Notification, NotificationEvent;
import 'package:unittest/unittest.dart';
import 'package:observatory/models.dart' as M;
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.dart
index 9cea3f5..7c621bb 100644
--- a/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/notify_event/element_test.dart
@@ -1,6 +1,7 @@
// 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 'dart:async';
import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.dart b/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.dart
index f09ed32..426828d 100644
--- a/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/notify_exception/connection_exception_test.dart
@@ -1,6 +1,7 @@
// 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 'dart:async';
import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.dart b/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.dart
index 4696ee8..e809b82 100644
--- a/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/notify_exception/exception_test.dart
@@ -1,6 +1,7 @@
// 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 'dart:async';
import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.dart
index 05b3370..6752929 100644
--- a/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/refresh/element_test.dart
@@ -1,6 +1,7 @@
// 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 'dart:async';
import 'package:unittest/unittest.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.dart
index 5e62069..8a161b6 100644
--- a/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/top-menu/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/nav/menu.dart';
diff --git a/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.dart b/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.dart
index 7aba8ed..a5596a7 100644
--- a/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/nav/vm_menu/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/nav/menu.dart';
diff --git a/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.dart b/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.dart
new file mode 100644
index 0000000..aa82df1
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.dart
@@ -0,0 +1,172 @@
+// 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 'dart:async';
+import 'package:unittest/unittest.dart';
+import 'package:observatory/models.dart' as M;
+import 'package:observatory/src/elements/sample_buffer_control.dart';
+import '../mocks.dart';
+
+main() {
+ SampleBufferControlElement.tag.ensureRegistration();
+
+ group('instantiation', () {
+ SampleProfileLoadingProgressMock progress;
+ StreamController<SampleProfileLoadingProgressEventMock> events;
+ setUp(() {
+ progress = new SampleProfileLoadingProgressMock();
+ events = new StreamController<SampleProfileLoadingProgressEventMock>();
+ });
+ test('no additional parameters', () {
+ final e = new SampleBufferControlElement(progress, events.stream);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.progress, equals(progress));
+ expect(e.selectedTag, equals(M.SampleProfileTag.none));
+ expect(e.showTag, isTrue);
+ });
+ test('selected tag', () {
+ const tag = M.SampleProfileTag.userOnly;
+ final e = new SampleBufferControlElement(progress, events.stream,
+ selectedTag: tag);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.progress, equals(progress));
+ expect(e.selectedTag, equals(tag));
+ expect(e.showTag, isTrue);
+ });
+ test('show tag (true)', () {
+ final e = new SampleBufferControlElement(progress, events.stream,
+ showTag: true);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.progress, equals(progress));
+ expect(e.selectedTag, equals(M.SampleProfileTag.none));
+ expect(e.showTag, isTrue);
+ });
+ test('show tag (false)', () {
+ final e = new SampleBufferControlElement(progress, events.stream,
+ showTag: false);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.progress, equals(progress));
+ expect(e.selectedTag, equals(M.SampleProfileTag.none));
+ expect(e.showTag, isFalse);
+ });
+ });
+ group('elements', () {
+ SampleProfileLoadingProgressMock progress;
+ StreamController<SampleProfileLoadingProgressEventMock> events;
+ setUp(() {
+ progress = new SampleProfileLoadingProgressMock();
+ events = new StreamController<SampleProfileLoadingProgressEventMock>();
+ });
+ test('created after attachment', () async {
+ final e = new SampleBufferControlElement(progress, events.stream);
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.children.length, isNonZero, reason: 'has elements');
+ e.remove();
+ await e.onRendered.first;
+ expect(e.children.length, isZero,
+ reason: 'is empty');
+ });
+ test('listen for status changes', () async {
+ final e = new SampleBufferControlElement(progress, events.stream);
+ expect(events.hasListener, isFalse);
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(events.hasListener, isTrue);
+ events.add(new SampleProfileLoadingProgressEventMock(progress: progress));
+ events.close();
+ await e.onRendered.first;
+ e.remove();
+ await e.onRendered.first;
+ });
+ test('follow updates changes', () async {
+ final e = new SampleBufferControlElement(progress, events.stream);
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.querySelector('select'), isNull);
+ events.add(new SampleProfileLoadingProgressEventMock(
+ progress: new SampleProfileLoadingProgressMock(
+ status: M.SampleProfileLoadingStatus.fetching
+ )));
+ await e.onRendered.first;
+ expect(e.querySelector('select'), isNull);
+ events.add(new SampleProfileLoadingProgressEventMock(
+ progress: new SampleProfileLoadingProgressMock(
+ status: M.SampleProfileLoadingStatus.loading
+ )));
+ await e.onRendered.first;
+ expect(e.querySelector('select'), isNull);
+ events.add(new SampleProfileLoadingProgressEventMock(
+ progress: new SampleProfileLoadingProgressMock(
+ status: M.SampleProfileLoadingStatus.loaded,
+ profile: new SampleProfileMock()
+ )));
+ events.close();
+ await e.onRendered.first;
+ expect(e.querySelector('select'), isNotNull);
+ e.remove();
+ await e.onRendered.first;
+ });
+ test('follow updates changes (no tag)', () async {
+ final e = new SampleBufferControlElement(progress, events.stream,
+ showTag: false);
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.querySelector('select'), isNull);
+ events.add(new SampleProfileLoadingProgressEventMock(
+ progress: new SampleProfileLoadingProgressMock(
+ status: M.SampleProfileLoadingStatus.fetching
+ )));
+ await e.onRendered.first;
+ expect(e.querySelector('select'), isNull);
+ events.add(new SampleProfileLoadingProgressEventMock(
+ progress: new SampleProfileLoadingProgressMock(
+ status: M.SampleProfileLoadingStatus.loading
+ )));
+ await e.onRendered.first;
+ expect(e.querySelector('select'), isNull);
+ events.add(new SampleProfileLoadingProgressEventMock(
+ progress: new SampleProfileLoadingProgressMock(
+ status: M.SampleProfileLoadingStatus.loaded,
+ profile: new SampleProfileMock()
+ )));
+ await e.onRendered.first;
+ expect(e.querySelector('select'), isNull);
+ e.remove();
+ await e.onRendered.first;
+ });
+ });
+ group('events', () {
+ SampleProfileLoadingProgressMock progress;
+ StreamController<SampleProfileLoadingProgressEventMock> events;
+ setUp(() {
+ progress = new SampleProfileLoadingProgressMock();
+ events = new StreamController<SampleProfileLoadingProgressEventMock>();
+ });
+ test('onModeChange', () async {
+ final e = new SampleBufferControlElement(progress, events.stream);
+ document.body.append(e);
+ await e.onRendered.first;
+ events.add(new SampleProfileLoadingProgressEventMock(
+ progress: new SampleProfileLoadingProgressMock(
+ status: M.SampleProfileLoadingStatus.loaded,
+ profile: new SampleProfileMock()
+ )));
+ await e.onRendered.first;
+ expect(e.selectedTag, equals(M.SampleProfileTag.none));
+ e.onTagChange.listen(expectAsync((_) {
+ expect(e.selectedTag, equals(M.SampleProfileTag.userOnly));
+ }, count: 1));
+ final select = (e.querySelector('.tag-select') as SelectElement);
+ select.selectedIndex = select.options.indexOf(
+ (select.options.toSet()
+ ..removeAll(select.selectedOptions)).toList().first
+ );
+ select.dispatchEvent(new Event("change"));
+ e.remove();
+ await e.onRendered.first;
+ });
+ });
+}
diff --git a/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.html b/runtime/observatory/tests/observatory_ui/sample_buffer_control/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/sample_buffer_control/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/observatory_ui/script_ref/element_test.dart b/runtime/observatory/tests/observatory_ui/script_ref/element_test.dart
index 6dc2b84..b6c6e93 100644
--- a/runtime/observatory/tests/observatory_ui/script_ref/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/script_ref/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/script_ref.dart';
diff --git a/runtime/observatory/tests/observatory_ui/source_link/element_test.dart b/runtime/observatory/tests/observatory_ui/source_link/element_test.dart
index 3dcb5dd..bd096b8 100644
--- a/runtime/observatory/tests/observatory_ui/source_link/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/source_link/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/source_link.dart';
diff --git a/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.dart b/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.dart
new file mode 100644
index 0000000..f8c0f00
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.dart
@@ -0,0 +1,185 @@
+// 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/models.dart' as M;
+import 'package:observatory/src/elements/stack_trace_tree_config.dart';
+
+main() {
+ StackTraceTreeConfigElement.tag.ensureRegistration();
+
+ group('instantiation', () {
+ test('default', () {
+ final e = new StackTraceTreeConfigElement();
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.showMode, isTrue);
+ expect(e.showDirection, isTrue);
+ expect(e.showFilter, isTrue);
+ expect(e.filter, equals(''));
+ expect(e.mode, equals(ProfileTreeMode.function));
+ expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+ });
+ test('showMode', () {
+ final e = new StackTraceTreeConfigElement(showMode: false);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.showMode, isFalse);
+ expect(e.showDirection, isTrue);
+ expect(e.showFilter, isTrue);
+ expect(e.filter, equals(''));
+ expect(e.mode, equals(ProfileTreeMode.function));
+ expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+ });
+ test('showDirection', () {
+ final e = new StackTraceTreeConfigElement(showDirection: false);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.showMode, isTrue);
+ expect(e.showDirection, isFalse);
+ expect(e.showFilter, isTrue);
+ expect(e.filter, equals(''));
+ expect(e.mode, equals(ProfileTreeMode.function));
+ expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+ });
+ test('showFilter', () {
+ final e = new StackTraceTreeConfigElement(showFilter: false);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.showMode, isTrue);
+ expect(e.showDirection, isTrue);
+ expect(e.showFilter, isFalse);
+ expect(e.filter, equals(''));
+ expect(e.mode, equals(ProfileTreeMode.function));
+ expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+ });
+ test('filter', () {
+ final filter = 'filter-string';
+ final e = new StackTraceTreeConfigElement(filter: filter);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.showMode, isTrue);
+ expect(e.showDirection, isTrue);
+ expect(e.showFilter, isTrue);
+ expect(e.filter, equals(filter));
+ expect(e.mode, equals(ProfileTreeMode.function));
+ expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+ });
+ test('mode', () {
+ final e = new StackTraceTreeConfigElement(mode: ProfileTreeMode.code);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.showMode, isTrue);
+ expect(e.showDirection, isTrue);
+ expect(e.showFilter, isTrue);
+ expect(e.filter, equals(''));
+ expect(e.mode, equals(ProfileTreeMode.code));
+ expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+ });
+ test('default', () {
+ final e = new StackTraceTreeConfigElement(
+ direction: M.ProfileTreeDirection.inclusive);
+ expect(e, isNotNull, reason: 'element correctly created');
+ expect(e.showMode, isTrue);
+ expect(e.showDirection, isTrue);
+ expect(e.showFilter, isTrue);
+ expect(e.filter, equals(''));
+ expect(e.mode, equals(ProfileTreeMode.function));
+ expect(e.direction, equals(M.ProfileTreeDirection.inclusive));
+ });
+ });
+ group('elements', () {
+ test('created after attachment', () async {
+ final e = new StackTraceTreeConfigElement();
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.children.length, isNonZero, reason: 'has elements');
+ e.remove();
+ await e.onRendered.first;
+ expect(e.children.length, isZero, reason: 'is empty');
+ });
+ test('react to mode change', () async {
+ final e = new StackTraceTreeConfigElement();
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.mode, equals(ProfileTreeMode.function));
+ e.mode = ProfileTreeMode.code;
+ await e.onRendered.first;
+ expect(e.mode, equals(ProfileTreeMode.code));
+ e.remove();
+ await e.onRendered.first;
+ expect(e.children.length, isZero, reason: 'is empty');
+ });
+ test('react to direction change', () async {
+ final e = new StackTraceTreeConfigElement();
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+ e.direction = M.ProfileTreeDirection.inclusive;
+ await e.onRendered.first;
+ expect(e.direction, equals(M.ProfileTreeDirection.inclusive));
+ e.remove();
+ await e.onRendered.first;
+ expect(e.children.length, isZero, reason: 'is empty');
+ });
+ test('react to filter change', () async {
+ final filter = 'filter-string';
+ final e = new StackTraceTreeConfigElement();
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.filter, equals(''));
+ e.filter = filter;
+ await e.onRendered.first;
+ expect(e.filter, equals(filter));
+ e.remove();
+ await e.onRendered.first;
+ expect(e.children.length, isZero, reason: 'is empty');
+ });
+ });
+ group('events', () {
+ test('onModeChange', () async {
+ final e = new StackTraceTreeConfigElement();
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.mode, equals(ProfileTreeMode.function));
+ e.onModeChange.listen(expectAsync((_) {
+ expect(e.mode, equals(ProfileTreeMode.code));
+ }, count: 1));
+ final select = (e.querySelector('.mode-select') as SelectElement);
+ select.selectedIndex = select.options.indexOf(
+ (select.options.toSet()
+ ..removeAll(select.selectedOptions)).toList().first
+ );
+ select.dispatchEvent(new Event("change"));
+ e.remove();
+ await e.onRendered.first;
+ });
+ test('onDirectionChange', () async {
+ final e = new StackTraceTreeConfigElement();
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+ e.onDirectionChange.listen(expectAsync((_) {
+ expect(e.direction, equals(M.ProfileTreeDirection.inclusive));
+ }, count: 1));
+ final select = (e.querySelector('.direction-select') as SelectElement);
+ select.selectedIndex = select.options.indexOf(
+ (select.options.toSet()
+ ..removeAll(select.selectedOptions)).toList().first
+ );
+ select.dispatchEvent(new Event("change"));
+ e.remove();
+ await e.onRendered.first;
+ });
+ test('onFilterChange', () async {
+ final e = new StackTraceTreeConfigElement();
+ document.body.append(e);
+ await e.onRendered.first;
+ expect(e.direction, equals(M.ProfileTreeDirection.exclusive));
+ e.onFilterChange.listen(expectAsync((_) {
+ expect(e.filter, equals('value'));
+ }, count: 1));
+ var input = (e.querySelector('input') as TextInputElement);
+ input.value = 'value';
+ input.dispatchEvent(new Event("change"));
+ e.remove();
+ await e.onRendered.first;
+ });
+ });
+}
diff --git a/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.html b/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/element_test.html
new file mode 100644
index 0000000..f0e956d
--- /dev/null
+++ b/runtime/observatory/tests/observatory_ui/stack_trace_tree_config/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/observatory_ui/view_footer/element_test.dart b/runtime/observatory/tests/observatory_ui/view_footer/element_test.dart
index 143464e..77cb4cc 100644
--- a/runtime/observatory/tests/observatory_ui/view_footer/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/view_footer/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/view_footer.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
index 270e0d5..84026e5 100644
--- a/runtime/observatory/tests/observatory_ui/vm_connect/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/vm_connect/element_test.dart
@@ -1,6 +1,7 @@
// 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/src/elements/nav/notify.dart';
diff --git a/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.dart b/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.dart
index 45efab6..b4011f9 100644
--- a/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.dart
+++ b/runtime/observatory/tests/observatory_ui/vm_connect_target/element_test.dart
@@ -1,6 +1,7 @@
// Copyright (c) 2015, 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/src/elements/vm_connect_target.dart';
diff --git a/runtime/observatory/tests/service/dev_fs_http_put_test.dart b/runtime/observatory/tests/service/dev_fs_http_put_test.dart
new file mode 100644
index 0000000..c5639a8
--- /dev/null
+++ b/runtime/observatory/tests/service/dev_fs_http_put_test.dart
@@ -0,0 +1,101 @@
+// 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
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+Future<String> readResponse(HttpClientResponse response) {
+ var completer = new Completer();
+ var contents = new StringBuffer();
+ response.transform(UTF8.decoder).listen((String data) {
+ contents.write(data);
+ }, onDone: () => completer.complete(contents.toString()));
+ return completer.future;
+}
+
+
+var tests = [
+ // Write a file with the ? character in the filename.
+ (VM vm) async {
+ var fsId = 'test';
+ var filePath = '/foo/bar.dat';
+ var fileContents = [0, 1, 2, 3, 4, 5, 6, 255];
+ var fileContentsBase64 = BASE64.encode(fileContents);
+
+ var result;
+ // Create DevFS.
+ result = await vm.invokeRpcNoUpgrade('_createDevFS', { 'fsName': fsId });
+ expect(result['type'], equals('FileSystem'));
+ expect(result['name'], equals(fsId));
+ expect(result['uri'], new isInstanceOf<String>());
+
+ // Write the file by issuing an HTTP PUT.
+ HttpClient client = new HttpClient();
+ HttpClientRequest request =
+ await client.putUrl(Uri.parse(serviceHttpAddress));
+ request.headers.add('dev_fs_name', fsId);
+ request.headers.add('dev_fs_path', filePath);
+ request.add(GZIP.encode([9]));
+ HttpClientResponse response = await request.close();
+ String responseBody = await readResponse(response);
+ result = JSON.decode(responseBody);
+ expect(result['result']['type'], equals('Success'));
+
+ // Trigger an error by issuing an HTTP PUT.
+ request = await client.putUrl(Uri.parse(serviceHttpAddress));
+ request.headers.add('dev_fs_name', fsId);
+ // omit the 'dev_fs_path' parameter.
+ request.write(GZIP.encode(fileContents));
+ response = await request.close();
+ responseBody = await readResponse(response);
+ result = JSON.decode(responseBody);
+ Map error = result['error']['data'];
+ expect(error, isNotNull);
+ expect(error['details'].contains("expects the 'path' parameter"), isTrue);
+
+ // Write the file again but this time with the true file contents.
+ client = new HttpClient();
+ request =
+ await client.putUrl(Uri.parse(serviceHttpAddress));
+ request.headers.add('dev_fs_name', fsId);
+ request.headers.add('dev_fs_path', filePath);
+ request.add(GZIP.encode(fileContents));
+ response = await request.close();
+ responseBody = await readResponse(response);
+ result = JSON.decode(responseBody);
+ expect(result['result']['type'], equals('Success'));
+
+ // Close the HTTP client.
+ client.close();
+
+ // Read the file back.
+ result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+ 'fsName': fsId,
+ 'path': filePath,
+ });
+ expect(result['type'], equals('FSFile'));
+ expect(result['fileContents'], equals(fileContentsBase64));
+
+ // List all the files in the file system.
+ result = await vm.invokeRpcNoUpgrade('_listDevFSFiles', {
+ 'fsName': fsId,
+ });
+ expect(result['type'], equals('FSFileList'));
+ expect(result['files'].length, equals(1));
+ expect(result['files'][0]['name'], equals(filePath));
+
+ // Delete DevFS.
+ result = await vm.invokeRpcNoUpgrade('_deleteDevFS', {
+ 'fsName': fsId,
+ });
+ expect(result['type'], equals('Success'));
+ },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory/tests/service/get_allocation_samples_test.dart b/runtime/observatory/tests/service/get_allocation_samples_test.dart
index 85626ee..d26c75f 100644
--- a/runtime/observatory/tests/service/get_allocation_samples_test.dart
+++ b/runtime/observatory/tests/service/get_allocation_samples_test.dart
@@ -4,6 +4,7 @@
// VMOptions=--error_on_bad_type --error_on_bad_override
import 'dart:developer';
+import 'package:observatory/models.dart' as M;
import 'package:observatory/service_io.dart';
import 'package:observatory/cpu_profile.dart';
import 'package:unittest/unittest.dart';
@@ -61,10 +62,10 @@
await fooClass.reload();
expect(fooClass.traceAllocations, isFalse);
CpuProfile cpuProfile = new CpuProfile();
- cpuProfile.load(isolate, profileResponse);
+ await cpuProfile.load(isolate, profileResponse);
cpuProfile.buildCodeCallerAndCallees();
cpuProfile.buildFunctionCallerAndCallees();
- var tree = cpuProfile.loadCodeTree('exclusive');
+ var tree = cpuProfile.loadCodeTree(M.ProfileTreeDirection.exclusive);
var node = tree.root;
var expected =
['Root', 'DRT_AllocateObject', 'test', 'test', '_Closure.call'];
diff --git a/runtime/observatory/web/index.html b/runtime/observatory/web/index.html
index 0659525..ccd9bfc 100644
--- a/runtime/observatory/web/index.html
+++ b/runtime/observatory/web/index.html
@@ -4,6 +4,7 @@
<meta charset="utf-8">
<title>Dart VM Observatory</title>
<link rel="import" href="packages/polymer/polymer.html">
+ <link rel="stylesheet" href="packages/charted/charts/themes/quantum_theme.css">
<link rel="stylesheet" href="packages/observatory/src/elements/css/shared.css">
<link rel="import" href="packages/observatory/elements.html">
<script src="packages/js_util/dist/js_util.js"></script>
@@ -11,6 +12,5 @@
<script src="packages/browser/dart.js"></script>
</head>
<body style="height: 100%">
- <observatory-application></observatory-application>
</body>
</html>
diff --git a/runtime/observatory/web/main.dart b/runtime/observatory/web/main.dart
index 41f3dc7..36c03ab 100644
--- a/runtime/observatory/web/main.dart
+++ b/runtime/observatory/web/main.dart
@@ -2,6 +2,7 @@
// 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:logging/logging.dart';
import 'package:polymer/polymer.dart';
import 'package:observatory/elements.dart';
@@ -24,4 +25,6 @@
Logger.root.info('Polymer initialized');
await Polymer.onReady;
Logger.root.info('Polymer elements have been upgraded');
+ document.body.children
+ .insert(0, document.createElement('observatory-application'));
}
diff --git a/runtime/vm/assembler_arm64.cc b/runtime/vm/assembler_arm64.cc
index 54dcabb..705d8c8 100644
--- a/runtime/vm/assembler_arm64.cc
+++ b/runtime/vm/assembler_arm64.cc
@@ -13,12 +13,6 @@
#include "vm/stack_frame.h"
#include "vm/stub_code.h"
-// An extra check since we are assuming the existence of /proc/cpuinfo below.
-#if !defined(USING_SIMULATOR) && !defined(__linux__) && !defined(ANDROID) && \
- !TARGET_OS_IOS
-#error ARM64 cross-compile only supported on Linux
-#endif
-
namespace dart {
DECLARE_FLAG(bool, check_code_pointer);
diff --git a/runtime/vm/assembler_arm64_test.cc b/runtime/vm/assembler_arm64_test.cc
index 329466a..3d95b7c 100644
--- a/runtime/vm/assembler_arm64_test.cc
+++ b/runtime/vm/assembler_arm64_test.cc
@@ -13,8 +13,6 @@
namespace dart {
-static const intptr_t kTestStackSpace = 512 * kWordSize;
-
#define __ assembler->
ASSEMBLER_TEST_GENERATE(Simple, assembler) {
diff --git a/runtime/vm/cpu_arm64.cc b/runtime/vm/cpu_arm64.cc
index 881aebc..e612cce 100644
--- a/runtime/vm/cpu_arm64.cc
+++ b/runtime/vm/cpu_arm64.cc
@@ -3,10 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
#include "vm/globals.h"
-
#if defined(TARGET_ARCH_ARM64)
#include "vm/cpu.h"
+#include "vm/cpu_arm64.h"
+
#include "vm/cpuinfo.h"
#include "vm/simulator.h"
@@ -31,13 +32,15 @@
// ARM recommends using the gcc intrinsic __clear_cache on Linux and Android.
// blogs.arm.com/software-enablement/141-caches-and-self-modifying-code/
- #if defined(__linux__) || defined(ANDROID)
+ #if defined(TARGET_OS_ANDROID) || \
+ defined(TARGET_OS_FUCHSIA) || \
+ defined(TARGET_OS_LINUX)
extern void __clear_cache(char*, char*);
char* beg = reinterpret_cast<char*>(start);
char* end = reinterpret_cast<char*>(start + size);
::__clear_cache(beg, end);
#else
- #error FlushICache only tested/supported on Linux and Android
+ #error FlushICache only tested/supported on Android, Fuchsia, and Linux
#endif
#endif
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index aff9955..61bd28f 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1142,37 +1142,29 @@
return Version::String();
}
-DART_EXPORT char* Dart_Initialize(
- const uint8_t* vm_isolate_snapshot,
- const uint8_t* instructions_snapshot,
- const uint8_t* data_snapshot,
- Dart_IsolateCreateCallback create,
- Dart_IsolateInterruptCallback interrupt,
- Dart_IsolateUnhandledExceptionCallback unhandled,
- Dart_IsolateShutdownCallback shutdown,
- Dart_ThreadExitCallback thread_exit,
- Dart_FileOpenCallback file_open,
- Dart_FileReadCallback file_read,
- Dart_FileWriteCallback file_write,
- Dart_FileCloseCallback file_close,
- Dart_EntropySource entropy_source,
- Dart_GetVMServiceAssetsArchive get_service_assets) {
- if (interrupt != NULL) {
+DART_EXPORT char* Dart_Initialize(Dart_InitializeParams* params) {
+ if (params == NULL) {
return strdup("Dart_Initialize: "
- "Setting of interrupt callback is not supported.");
+ "Dart_InitializeParams is null.");
}
- if (unhandled != NULL) {
+
+ if (params->version != DART_INITIALIZE_PARAMS_CURRENT_VERSION) {
return strdup("Dart_Initialize: "
- "Setting of unhandled exception callback is not supported.");
+ "Invalid Dart_InitializeParams version.");
}
- return Dart::InitOnce(vm_isolate_snapshot,
- instructions_snapshot,
- data_snapshot,
- create, shutdown,
- thread_exit,
- file_open, file_read, file_write, file_close,
- entropy_source,
- get_service_assets);
+
+ return Dart::InitOnce(params->vm_isolate_snapshot,
+ params->instructions_snapshot,
+ params->data_snapshot,
+ params->create,
+ params->shutdown,
+ params->thread_exit,
+ params->file_open,
+ params->file_read,
+ params->file_write,
+ params->file_close,
+ params->entropy_source,
+ params->get_service_assets);
}
@@ -1450,6 +1442,32 @@
}
+DART_EXPORT void Dart_SetStickyError(Dart_Handle error) {
+ Thread* thread = Thread::Current();
+ DARTSCOPE(thread);
+ Isolate* isolate = thread->isolate();
+ CHECK_ISOLATE(isolate);
+ NoSafepointScope no_safepoint_scope;
+ if (isolate->sticky_error() != Error::null()) {
+ FATAL1("%s expects there to be no sticky error.", CURRENT_FUNC);
+ }
+ if (!::Dart_IsUnhandledExceptionError(error)) {
+ FATAL1("%s expects the error to be an unhandled exception error.",
+ CURRENT_FUNC);
+ }
+ isolate->SetStickyError(
+ Api::UnwrapErrorHandle(Z, error).raw());
+}
+
+
+DART_EXPORT bool Dart_HasStickyError() {
+ Isolate* isolate = Isolate::Current();
+ CHECK_ISOLATE(isolate);
+ NoSafepointScope no_safepoint_scope;
+ return isolate->sticky_error() != Error::null();
+}
+
+
DART_EXPORT void Dart_ExitIsolate() {
Thread* T = Thread::Current();
CHECK_ISOLATE(T->isolate());
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 3dbf3f6..b7348e4 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3618,6 +3618,19 @@
}
+TEST_CASE(SetStickyError) {
+ const char* kScriptChars =
+ "main() => throw 'HI';";
+ Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+ Dart_Handle retobj = Dart_Invoke(lib, NewString("main"), 0, NULL);
+ EXPECT(Dart_IsError(retobj));
+ EXPECT(Dart_IsUnhandledExceptionError(retobj));
+ EXPECT(!Dart_HasStickyError());
+ Dart_SetStickyError(retobj);
+ EXPECT(Dart_HasStickyError());
+}
+
+
TEST_CASE(TypeGetNonParamtericTypes) {
const char* kScriptChars =
"class MyClass0 {\n"
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index a8e27c0..8ee6739 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -2102,86 +2102,6 @@
}
-static intptr_t MethodKindToCid(MethodRecognizer::Kind kind) {
- switch (kind) {
- case MethodRecognizer::kImmutableArrayGetIndexed:
- return kImmutableArrayCid;
-
- case MethodRecognizer::kObjectArrayGetIndexed:
- case MethodRecognizer::kObjectArraySetIndexed:
- return kArrayCid;
-
- case MethodRecognizer::kGrowableArrayGetIndexed:
- case MethodRecognizer::kGrowableArraySetIndexed:
- return kGrowableObjectArrayCid;
-
- case MethodRecognizer::kFloat32ArrayGetIndexed:
- case MethodRecognizer::kFloat32ArraySetIndexed:
- return kTypedDataFloat32ArrayCid;
-
- case MethodRecognizer::kFloat64ArrayGetIndexed:
- case MethodRecognizer::kFloat64ArraySetIndexed:
- return kTypedDataFloat64ArrayCid;
-
- case MethodRecognizer::kInt8ArrayGetIndexed:
- case MethodRecognizer::kInt8ArraySetIndexed:
- return kTypedDataInt8ArrayCid;
-
- case MethodRecognizer::kUint8ArrayGetIndexed:
- case MethodRecognizer::kUint8ArraySetIndexed:
- return kTypedDataUint8ArrayCid;
-
- case MethodRecognizer::kUint8ClampedArrayGetIndexed:
- case MethodRecognizer::kUint8ClampedArraySetIndexed:
- return kTypedDataUint8ClampedArrayCid;
-
- case MethodRecognizer::kExternalUint8ArrayGetIndexed:
- case MethodRecognizer::kExternalUint8ArraySetIndexed:
- return kExternalTypedDataUint8ArrayCid;
-
- case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
- case MethodRecognizer::kExternalUint8ClampedArraySetIndexed:
- return kExternalTypedDataUint8ClampedArrayCid;
-
- case MethodRecognizer::kInt16ArrayGetIndexed:
- case MethodRecognizer::kInt16ArraySetIndexed:
- return kTypedDataInt16ArrayCid;
-
- case MethodRecognizer::kUint16ArrayGetIndexed:
- case MethodRecognizer::kUint16ArraySetIndexed:
- return kTypedDataUint16ArrayCid;
-
- case MethodRecognizer::kInt32ArrayGetIndexed:
- case MethodRecognizer::kInt32ArraySetIndexed:
- return kTypedDataInt32ArrayCid;
-
- case MethodRecognizer::kUint32ArrayGetIndexed:
- case MethodRecognizer::kUint32ArraySetIndexed:
- return kTypedDataUint32ArrayCid;
-
- case MethodRecognizer::kInt64ArrayGetIndexed:
- case MethodRecognizer::kInt64ArraySetIndexed:
- return kTypedDataInt64ArrayCid;
-
- case MethodRecognizer::kFloat32x4ArrayGetIndexed:
- case MethodRecognizer::kFloat32x4ArraySetIndexed:
- return kTypedDataFloat32x4ArrayCid;
-
- case MethodRecognizer::kInt32x4ArrayGetIndexed:
- case MethodRecognizer::kInt32x4ArraySetIndexed:
- return kTypedDataInt32x4ArrayCid;
-
- case MethodRecognizer::kFloat64x2ArrayGetIndexed:
- case MethodRecognizer::kFloat64x2ArraySetIndexed:
- return kTypedDataFloat64x2ArrayCid;
-
- default:
- break;
- }
- return kIllegalCid;
-}
-
-
static Instruction* GetCheckClass(FlowGraph* flow_graph,
Definition* to_check,
const ICData& unary_checks,
@@ -2204,8 +2124,7 @@
Definition* receiver,
TargetEntryInstr** entry,
Definition** last) {
- intptr_t array_cid = MethodKindToCid(kind);
- ASSERT(array_cid != kIllegalCid);
+ intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind);
Definition* array = receiver;
Definition* index = call->ArgumentAt(1);
@@ -2262,8 +2181,7 @@
const ICData& value_check,
TargetEntryInstr** entry,
Definition** last) {
- intptr_t array_cid = MethodKindToCid(kind);
- ASSERT(array_cid != kIllegalCid);
+ intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind);
Definition* array = receiver;
Definition* index = call->ArgumentAt(1);
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index 15a0fa9..93478fc 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -384,8 +384,8 @@
Thread::kNoDeoptId));
}
-
-bool Intrinsifier::Build_ObjectArrayGetIndexed(FlowGraph* flow_graph) {
+static bool IntrinsifyArrayGetIndexed(FlowGraph* flow_graph,
+ intptr_t array_cid) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
TargetEntryInstr* normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
@@ -393,199 +393,70 @@
Definition* index = builder.AddParameter(1);
Definition* array = builder.AddParameter(2);
- PrepareIndexedOp(&builder, array, index, Array::length_offset());
-
- Definition* result = builder.AddDefinition(
- new LoadIndexedInstr(new Value(array),
- new Value(index),
- Instance::ElementSizeFor(kArrayCid), // index scale
- kArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- builder.AddIntrinsicReturn(new Value(result));
- return true;
-}
-
-
-bool Intrinsifier::Build_ImmutableArrayGetIndexed(FlowGraph* flow_graph) {
- return Build_ObjectArrayGetIndexed(flow_graph);
-}
-
-
-bool Intrinsifier::Build_Uint8ArrayGetIndexed(FlowGraph* flow_graph) {
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
-
- Definition* index = builder.AddParameter(1);
- Definition* array = builder.AddParameter(2);
-
- PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
- Definition* result = builder.AddDefinition(
- new LoadIndexedInstr(new Value(array),
- new Value(index),
- 1, // index scale
- kTypedDataUint8ArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- builder.AddIntrinsicReturn(new Value(result));
- return true;
-}
-
-
-bool Intrinsifier::Build_ExternalUint8ArrayGetIndexed(FlowGraph* flow_graph) {
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
-
- Definition* index = builder.AddParameter(1);
- Definition* array = builder.AddParameter(2);
-
- PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset());
-
- Definition* elements = builder.AddDefinition(
- new LoadUntaggedInstr(new Value(array),
- ExternalTypedData::data_offset()));
- Definition* result = builder.AddDefinition(
- new LoadIndexedInstr(new Value(elements),
- new Value(index),
- 1, // index scale
- kExternalTypedDataUint8ArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- builder.AddIntrinsicReturn(new Value(result));
- return true;
-}
-
-
-bool Intrinsifier::Build_Uint8ArraySetIndexed(FlowGraph* flow_graph) {
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
-
- Definition* value = builder.AddParameter(1);
- Definition* index = builder.AddParameter(2);
- Definition* array = builder.AddParameter(3);
-
- PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
- builder.AddInstruction(
- new CheckSmiInstr(new Value(value),
- Thread::kNoDeoptId,
- builder.TokenPos()));
-
- builder.AddInstruction(
- new StoreIndexedInstr(new Value(array),
- new Value(index),
- new Value(value),
- kNoStoreBarrier,
- 1, // index scale
- kTypedDataUint8ArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- // Return null.
- Definition* null_def = builder.AddNullDefinition();
- builder.AddIntrinsicReturn(new Value(null_def));
- return true;
-}
-
-
-bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) {
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
-
- Definition* value = builder.AddParameter(1);
- Definition* index = builder.AddParameter(2);
- Definition* array = builder.AddParameter(3);
-
- PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset());
-
- builder.AddInstruction(
- new CheckSmiInstr(new Value(value),
- Thread::kNoDeoptId,
- builder.TokenPos()));
- Definition* elements = builder.AddDefinition(
- new LoadUntaggedInstr(new Value(array),
- ExternalTypedData::data_offset()));
- builder.AddInstruction(
- new StoreIndexedInstr(new Value(elements),
- new Value(index),
- new Value(value),
- kNoStoreBarrier,
- 1, // index scale
- kExternalTypedDataUint8ArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- // Return null.
- Definition* null_def = builder.AddNullDefinition();
- builder.AddIntrinsicReturn(new Value(null_def));
- return true;
-}
-
-
-bool Intrinsifier::Build_Uint32ArraySetIndexed(FlowGraph* flow_graph) {
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
-
- Definition* value = builder.AddParameter(1);
- Definition* index = builder.AddParameter(2);
- Definition* array = builder.AddParameter(3);
-
- PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
- Definition* unboxed_value =
- builder.AddUnboxInstr(kUnboxedUint32,
- new Value(value),
- /* is_checked = */ true);
-
- builder.AddInstruction(
- new StoreIndexedInstr(new Value(array),
- new Value(index),
- new Value(unboxed_value),
- kNoStoreBarrier,
- 4, // index scale
- kTypedDataUint32ArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- // Return null.
- Definition* null_def = builder.AddNullDefinition();
- builder.AddIntrinsicReturn(new Value(null_def));
- return true;
-}
-
-
-bool Intrinsifier::Build_Uint32ArrayGetIndexed(FlowGraph* flow_graph) {
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
-
- Definition* index = builder.AddParameter(1);
- Definition* array = builder.AddParameter(2);
-
- PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
- Definition* unboxed_value = builder.AddDefinition(
- new LoadIndexedInstr(new Value(array),
- new Value(index),
- 4, // index scale
- kTypedDataUint32ArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- Definition* result = builder.AddDefinition(
- BoxInstr::Create(kUnboxedUint32, new Value(unboxed_value)));
- builder.AddIntrinsicReturn(new Value(result));
- return true;
-}
-
-
-bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) {
- if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
- return false;
+ intptr_t length_offset = Array::length_offset();
+ if (RawObject::IsTypedDataClassId(array_cid)) {
+ length_offset = TypedData::length_offset();
+ } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ length_offset = ExternalTypedData::length_offset();
}
+ PrepareIndexedOp(&builder, array, index, length_offset);
+
+ if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ array = builder.AddDefinition(
+ new LoadUntaggedInstr(new Value(array),
+ ExternalTypedData::data_offset()));
+ }
+
+ Definition* result = builder.AddDefinition(
+ new LoadIndexedInstr(new Value(array),
+ new Value(index),
+ Instance::ElementSizeFor(array_cid), // index scale
+ array_cid,
+ Thread::kNoDeoptId,
+ builder.TokenPos()));
+ // Box and/or convert result if necessary.
+ switch (array_cid) {
+ case kTypedDataInt32ArrayCid:
+ case kExternalTypedDataInt32ArrayCid:
+ result = builder.AddDefinition(
+ BoxInstr::Create(kUnboxedInt32, new Value(result)));
+ break;
+ case kTypedDataUint32ArrayCid:
+ case kExternalTypedDataUint32ArrayCid:
+ result = builder.AddDefinition(
+ BoxInstr::Create(kUnboxedUint32, new Value(result)));
+ break;
+ case kTypedDataFloat32ArrayCid:
+ result = builder.AddDefinition(
+ new FloatToDoubleInstr(new Value(result), Thread::kNoDeoptId));
+ // Fall through.
+ case kTypedDataFloat64ArrayCid:
+ result = builder.AddDefinition(
+ BoxInstr::Create(kUnboxedDouble, new Value(result)));
+ break;
+ case kArrayCid:
+ case kImmutableArrayCid:
+ case kTypedDataInt8ArrayCid:
+ case kTypedDataUint8ArrayCid:
+ case kExternalTypedDataUint8ArrayCid:
+ case kTypedDataUint8ClampedArrayCid:
+ case kExternalTypedDataUint8ClampedArrayCid:
+ case kTypedDataInt16ArrayCid:
+ case kTypedDataUint16ArrayCid:
+ // Nothing to do.
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ builder.AddIntrinsicReturn(new Value(result));
+ return true;
+}
+
+
+static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph,
+ intptr_t array_cid) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
TargetEntryInstr* normal_entry = graph_entry->normal_entry();
BlockBuilder builder(flow_graph, normal_entry);
@@ -594,33 +465,82 @@
Definition* index = builder.AddParameter(2);
Definition* array = builder.AddParameter(3);
- PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
+ intptr_t length_offset = Array::length_offset();
+ if (RawObject::IsTypedDataClassId(array_cid)) {
+ length_offset = TypedData::length_offset();
+ } else if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ length_offset = ExternalTypedData::length_offset();
+ }
- const ICData& value_check = ICData::ZoneHandle(ICData::New(
- flow_graph->function(),
- String::Handle(flow_graph->function().name()),
- Object::empty_array(), // Dummy args. descr.
- Thread::kNoDeoptId,
- 1,
- false));
- value_check.AddReceiverCheck(kDoubleCid, flow_graph->function());
- builder.AddInstruction(
- new CheckClassInstr(new Value(value),
- Thread::kNoDeoptId,
- value_check,
- builder.TokenPos()));
- Definition* double_value =
- builder.AddUnboxInstr(kUnboxedDouble,
- new Value(value),
- /* is_checked = */ true);
+ PrepareIndexedOp(&builder, array, index, length_offset);
+ // Value check/conversion.
+ switch (array_cid) {
+ case kTypedDataInt8ArrayCid:
+ case kTypedDataUint8ArrayCid:
+ case kExternalTypedDataUint8ArrayCid:
+ case kTypedDataUint8ClampedArrayCid:
+ case kExternalTypedDataUint8ClampedArrayCid:
+ case kTypedDataInt16ArrayCid:
+ case kTypedDataUint16ArrayCid:
+ builder.AddInstruction(new CheckSmiInstr(new Value(value),
+ Thread::kNoDeoptId,
+ builder.TokenPos()));
+ break;
+ case kTypedDataInt32ArrayCid:
+ case kExternalTypedDataInt32ArrayCid:
+ // Use same truncating unbox-instruction for int32 and uint32.
+ // Fall-through.
+ case kTypedDataUint32ArrayCid:
+ case kExternalTypedDataUint32ArrayCid:
+ // Supports smi and mint, slow-case for bigints.
+ value = builder.AddUnboxInstr(kUnboxedUint32,
+ new Value(value),
+ /* is_checked = */ false);
+ break;
+ case kTypedDataFloat32ArrayCid:
+ case kTypedDataFloat64ArrayCid: {
+ const ICData& value_check = ICData::ZoneHandle(ICData::New(
+ flow_graph->function(),
+ Symbols::Empty(), // Dummy function name.
+ Object::empty_array(), // Dummy args. descr.
+ Thread::kNoDeoptId,
+ 1,
+ false));
+ value_check.AddReceiverCheck(kDoubleCid, flow_graph->function());
+ builder.AddInstruction(
+ new CheckClassInstr(new Value(value),
+ Thread::kNoDeoptId,
+ value_check,
+ builder.TokenPos()));
+ value = builder.AddUnboxInstr(kUnboxedDouble,
+ new Value(value),
+ /* is_checked = */ true);
+ if (array_cid == kTypedDataFloat32ArrayCid) {
+ value = builder.AddDefinition(
+ new DoubleToFloatInstr(new Value(value), Thread::kNoDeoptId));
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+ array = builder.AddDefinition(
+ new LoadUntaggedInstr(new Value(array),
+ ExternalTypedData::data_offset()));
+ }
+ // No store barrier.
+ ASSERT(RawObject::IsExternalTypedDataClassId(array_cid) ||
+ RawObject::IsTypedDataClassId(array_cid));
builder.AddInstruction(
new StoreIndexedInstr(new Value(array),
new Value(index),
- new Value(double_value),
+ new Value(value),
kNoStoreBarrier,
- 8, // index scale
- kTypedDataFloat64ArrayCid,
+ Instance::ElementSizeFor(array_cid), // index scale
+ array_cid,
Thread::kNoDeoptId,
builder.TokenPos()));
// Return null.
@@ -630,34 +550,80 @@
}
-bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) {
- if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
- return false;
- }
-
- GraphEntryInstr* graph_entry = flow_graph->graph_entry();
- TargetEntryInstr* normal_entry = graph_entry->normal_entry();
- BlockBuilder builder(flow_graph, normal_entry);
-
- Definition* index = builder.AddParameter(1);
- Definition* array = builder.AddParameter(2);
-
- PrepareIndexedOp(&builder, array, index, TypedData::length_offset());
-
- Definition* unboxed_value = builder.AddDefinition(
- new LoadIndexedInstr(new Value(array),
- new Value(index),
- 8, // index scale
- kTypedDataFloat64ArrayCid,
- Thread::kNoDeoptId,
- builder.TokenPos()));
- Definition* result = builder.AddDefinition(
- BoxInstr::Create(kUnboxedDouble, new Value(unboxed_value)));
- builder.AddIntrinsicReturn(new Value(result));
- return true;
+#define DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \
+bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \
+ return IntrinsifyArrayGetIndexed( \
+ flow_graph, \
+ MethodRecognizer::MethodKindToReceiverCid( \
+ MethodRecognizer::k##enum_name##GetIndexed)); \
}
+#define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) \
+bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \
+ return IntrinsifyArraySetIndexed( \
+ flow_graph, \
+ MethodRecognizer::MethodKindToReceiverCid( \
+ MethodRecognizer::k##enum_name##SetIndexed)); \
+}
+
+DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray) // Setter in intrinsifier_<arch>.cc.
+DEFINE_ARRAY_GETTER_INTRINSIC(ImmutableArray)
+
+#define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \
+DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \
+DEFINE_ARRAY_SETTER_INTRINSIC(enum_name)
+
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int8Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8ClampedArray)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8ClampedArray)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int16Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint16Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int32Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint32Array)
+
+#undef DEFINE_ARRAY_GETTER_SETTER_INTRINSICS
+#undef DEFINE_ARRAY_GETTER_INTRINSIC
+#undef DEFINE_ARRAY_SETTER_INTRINSIC
+
+
+#define DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \
+bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \
+ if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \
+ return false; \
+ } \
+ return IntrinsifyArrayGetIndexed( \
+ flow_graph, \
+ MethodRecognizer::MethodKindToReceiverCid( \
+ MethodRecognizer::k##enum_name##GetIndexed)); \
+}
+
+
+#define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) \
+bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \
+ if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \
+ return false; \
+ } \
+ return IntrinsifyArraySetIndexed( \
+ flow_graph, \
+ MethodRecognizer::MethodKindToReceiverCid( \
+ MethodRecognizer::k##enum_name##SetIndexed)); \
+}
+
+#define DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \
+DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \
+DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name)
+
+DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float64Array)
+DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array)
+
+#undef DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS
+#undef DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC
+#undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC
+
+
static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) {
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
TargetEntryInstr* normal_entry = graph_entry->normal_entry();
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 52aaa44..028a130 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -1513,6 +1513,13 @@
}
+void Isolate::SetStickyError(RawError* sticky_error) {
+ ASSERT(sticky_error_ == Error::null());
+ sticky_error_ = sticky_error;
+ message_handler()->PausedOnExit(true);
+}
+
+
void Isolate::Run() {
message_handler()->Run(Dart::thread_pool(),
RunIsolate,
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 2e603f1..9401e85 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -535,6 +535,9 @@
void set_deoptimized_code_array(const GrowableObjectArray& value);
void TrackDeoptimizedCode(const Code& code);
+ // Also sends a paused at exit event over the service protocol.
+ void SetStickyError(RawError* sticky_error);
+
RawError* sticky_error() const { return sticky_error_; }
void clear_sticky_error();
diff --git a/runtime/vm/method_recognizer.cc b/runtime/vm/method_recognizer.cc
index 03014ac..649a1fe 100644
--- a/runtime/vm/method_recognizer.cc
+++ b/runtime/vm/method_recognizer.cc
@@ -37,6 +37,87 @@
}
+intptr_t MethodRecognizer::MethodKindToReceiverCid(Kind kind) {
+ switch (kind) {
+ case kImmutableArrayGetIndexed:
+ return kImmutableArrayCid;
+
+ case kObjectArrayGetIndexed:
+ case kObjectArraySetIndexed:
+ return kArrayCid;
+
+ case kGrowableArrayGetIndexed:
+ case kGrowableArraySetIndexed:
+ return kGrowableObjectArrayCid;
+
+ case kFloat32ArrayGetIndexed:
+ case kFloat32ArraySetIndexed:
+ return kTypedDataFloat32ArrayCid;
+
+ case kFloat64ArrayGetIndexed:
+ case kFloat64ArraySetIndexed:
+ return kTypedDataFloat64ArrayCid;
+
+ case kInt8ArrayGetIndexed:
+ case kInt8ArraySetIndexed:
+ return kTypedDataInt8ArrayCid;
+
+ case kUint8ArrayGetIndexed:
+ case kUint8ArraySetIndexed:
+ return kTypedDataUint8ArrayCid;
+
+ case kUint8ClampedArrayGetIndexed:
+ case kUint8ClampedArraySetIndexed:
+ return kTypedDataUint8ClampedArrayCid;
+
+ case kExternalUint8ArrayGetIndexed:
+ case kExternalUint8ArraySetIndexed:
+ return kExternalTypedDataUint8ArrayCid;
+
+ case kExternalUint8ClampedArrayGetIndexed:
+ case kExternalUint8ClampedArraySetIndexed:
+ return kExternalTypedDataUint8ClampedArrayCid;
+
+ case kInt16ArrayGetIndexed:
+ case kInt16ArraySetIndexed:
+ return kTypedDataInt16ArrayCid;
+
+ case kUint16ArrayGetIndexed:
+ case kUint16ArraySetIndexed:
+ return kTypedDataUint16ArrayCid;
+
+ case kInt32ArrayGetIndexed:
+ case kInt32ArraySetIndexed:
+ return kTypedDataInt32ArrayCid;
+
+ case kUint32ArrayGetIndexed:
+ case kUint32ArraySetIndexed:
+ return kTypedDataUint32ArrayCid;
+
+ case kInt64ArrayGetIndexed:
+ case kInt64ArraySetIndexed:
+ return kTypedDataInt64ArrayCid;
+
+ case kFloat32x4ArrayGetIndexed:
+ case kFloat32x4ArraySetIndexed:
+ return kTypedDataFloat32x4ArrayCid;
+
+ case kInt32x4ArrayGetIndexed:
+ case kInt32x4ArraySetIndexed:
+ return kTypedDataInt32x4ArrayCid;
+
+ case kFloat64x2ArrayGetIndexed:
+ case kFloat64x2ArraySetIndexed:
+ return kTypedDataFloat64x2ArrayCid;
+
+ default:
+ break;
+ }
+ UNREACHABLE();
+ return kIllegalCid;
+}
+
+
#define KIND_TO_STRING(class_name, function_name, enum_name, type, fp) \
#enum_name,
static const char* recognized_list_method_name[] = {
diff --git a/runtime/vm/method_recognizer.h b/runtime/vm/method_recognizer.h
index 08226f8..cf185cf 100644
--- a/runtime/vm/method_recognizer.h
+++ b/runtime/vm/method_recognizer.h
@@ -13,7 +13,7 @@
// When adding a new function add a 0 as fingerprint, build and run to get the
// correct fingerprint from the mismatch error.
#define OTHER_RECOGNIZED_LIST(V) \
- V(::, identical, ObjectIdentical, Bool, 0x12e69c8c) \
+ V(::, identical, ObjectIdentical, Bool, 0x49c6e96a) \
V(ClassID, getID, ClassIDgetID, Smi, 0x528fd455) \
V(Object, Object., ObjectConstructor, Dynamic, 0x681617fe) \
V(_List, ., ObjectArrayAllocate, Array, 0x63078b15) \
@@ -111,22 +111,6 @@
V(Int32x4, withFlagY, Int32x4WithFlagY, Int32x4, 0x6485a9c4) \
V(Int32x4, withFlagZ, Int32x4WithFlagZ, Int32x4, 0x267acdfa) \
V(Int32x4, withFlagW, Int32x4WithFlagW, Int32x4, 0x345ac675) \
- V(Float32List, [], Float32ArrayGetIndexed, Double, 0x5686528f) \
- V(Float32List, []=, Float32ArraySetIndexed, Dynamic, 0x1b0d90df) \
- V(Int8List, [], Int8ArrayGetIndexed, Smi, 0x069af8b3) \
- V(Int8List, []=, Int8ArraySetIndexed, Dynamic, 0x33994cd7) \
- V(Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, Smi, 0x027603ed) \
- V(Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, Dynamic, 0x28f5f058) \
- V(_ExternalUint8ClampedArray, [], ExternalUint8ClampedArrayGetIndexed, \
- Smi, 0x027603ed) \
- V(_ExternalUint8ClampedArray, []=, ExternalUint8ClampedArraySetIndexed, \
- Dynamic, 0x28f5f058) \
- V(Int16List, [], Int16ArrayGetIndexed, Smi, 0x173cd6a1) \
- V(Int16List, []=, Int16ArraySetIndexed, Dynamic, 0x32f84e3c) \
- V(Uint16List, [], Uint16ArrayGetIndexed, Smi, 0x3ececa2f) \
- V(Uint16List, []=, Uint16ArraySetIndexed, Dynamic, 0x5c3a0bb9) \
- V(Int32List, [], Int32ArrayGetIndexed, Dynamic, 0x262eef09) \
- V(Int32List, []=, Int32ArraySetIndexed, Dynamic, 0x1b05b471) \
V(Int64List, [], Int64ArrayGetIndexed, Dynamic, 0x0c0c939a) \
V(Int64List, []=, Int64ArraySetIndexed, Dynamic, 0x3714d004) \
V(Float32x4List, [], Float32x4ArrayGetIndexed, Float32x4, 0x01c7017b) \
@@ -239,17 +223,17 @@
#define MATH_LIB_INTRINSIC_LIST(V) \
- V(::, sqrt, MathSqrt, Double, 0x18e8d5f6) \
+ V(::, sqrt, MathSqrt, Double, 0x1afb83d4) \
V(_Random, _nextState, Random_nextState, Dynamic, 0x1e4b0103) \
#define GRAPH_MATH_LIB_INTRINSIC_LIST(V) \
- V(::, sin, MathSin, Double, 0x0000fe08) \
- V(::, cos, MathCos, Double, 0x7794b33e) \
- V(::, tan, MathTan, Double, 0x4c1b72fd) \
- V(::, asin, MathAsin, Double, 0x640d48ad) \
- V(::, acos, MathAcos, Double, 0x42d46f81) \
- V(::, atan, MathAtan, Double, 0x4223f879) \
- V(::, atan2, MathAtan2, Double, 0x3553fb61) \
+ V(::, sin, MathSin, Double, 0x0213abe6) \
+ V(::, cos, MathCos, Double, 0x79a7611c) \
+ V(::, tan, MathTan, Double, 0x4e2e20db) \
+ V(::, asin, MathAsin, Double, 0x661ff68b) \
+ V(::, acos, MathAcos, Double, 0x44e71d5f) \
+ V(::, atan, MathAtan, Double, 0x4436a657) \
+ V(::, atan2, MathAtan2, Double, 0x60a40743) \
#define TYPED_DATA_LIB_INTRINSIC_LIST(V) \
V(Int8List, ., TypedData_Int8Array_factory, TypedDataInt8Array, 0x2e7749e3) \
@@ -281,15 +265,31 @@
TypedDataFloat64x2Array, 0x18cbf4d9) \
#define GRAPH_TYPED_DATA_INTRINSICS_LIST(V) \
+ V(Int8List, [], Int8ArrayGetIndexed, Smi, 0x069af8b3) \
+ V(Int8List, []=, Int8ArraySetIndexed, Dynamic, 0x33994cd7) \
V(Uint8List, [], Uint8ArrayGetIndexed, Smi, 0x027603ed) \
V(Uint8List, []=, Uint8ArraySetIndexed, Dynamic, 0x060d5256) \
V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, Smi, 0x027603ed) \
V(_ExternalUint8Array, []=, ExternalUint8ArraySetIndexed, Dynamic, \
0x060d5256) \
+ V(Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, Smi, 0x027603ed) \
+ V(Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, Dynamic, 0x28f5f058) \
+ V(_ExternalUint8ClampedArray, [], ExternalUint8ClampedArrayGetIndexed, \
+ Smi, 0x027603ed) \
+ V(_ExternalUint8ClampedArray, []=, ExternalUint8ClampedArraySetIndexed, \
+ Dynamic, 0x28f5f058) \
+ V(Int16List, [], Int16ArrayGetIndexed, Smi, 0x173cd6a1) \
+ V(Int16List, []=, Int16ArraySetIndexed, Dynamic, 0x32f84e3c) \
+ V(Uint16List, [], Uint16ArrayGetIndexed, Smi, 0x3ececa2f) \
+ V(Uint16List, []=, Uint16ArraySetIndexed, Dynamic, 0x5c3a0bb9) \
+ V(Int32List, [], Int32ArrayGetIndexed, Dynamic, 0x262eef09) \
+ V(Int32List, []=, Int32ArraySetIndexed, Dynamic, 0x1b05b471) \
V(Uint32List, [], Uint32ArrayGetIndexed, Dynamic, 0x6040f7fb) \
V(Uint32List, []=, Uint32ArraySetIndexed, Dynamic, 0x3a4e1119) \
V(Float64List, [], Float64ArrayGetIndexed, Double, 0x7a27098d) \
V(Float64List, []=, Float64ArraySetIndexed, Dynamic, 0x139b2465) \
+ V(Float32List, [], Float32ArrayGetIndexed, Double, 0x5686528f) \
+ V(Float32List, []=, Float32ArraySetIndexed, Dynamic, 0x1b0d90df) \
V(_TypedList, get:length, TypedDataLength, Smi, 0x2090dc1a) \
V(Float32x4, get:x, Float32x4ShuffleX, Double, 0x63d0c13f) \
V(Float32x4, get:y, Float32x4ShuffleY, Double, 0x20343b1b) \
@@ -335,7 +335,7 @@
V(::, _getDefaultTag, UserTag_defaultTag, Dynamic, 0x14ddc3b7) \
V(::, _getCurrentTag, Profiler_getCurrentTag, Dynamic, 0x486ee02d) \
V(::, _isDartStreamEnabled, Timeline_isDartStreamEnabled, Dynamic, \
- 0x3fe92e14) \
+ 0x1667ce76) \
#define ALL_INTRINSICS_NO_INTEGER_LIB_LIST(V) \
CORE_LIB_INTRINSIC_LIST(V) \
@@ -421,19 +421,19 @@
V(_ByteDataView, getUint64, ByteDataViewGetUint64, 0x2fab992e) \
V(_ByteDataView, getFloat32, ByteDataViewGetFloat32, 0x387e9fc6) \
V(_ByteDataView, getFloat64, ByteDataViewGetFloat64, 0x5396432d) \
- V(::, asin, MathAsin, 0x640d48ad) \
- V(::, acos, MathAcos, 0x42d46f81) \
- V(::, atan, MathAtan, 0x4223f879) \
- V(::, atan2, MathAtan2, 0x3553fb61) \
- V(::, cos, MathCos, 0x7794b33e) \
- V(::, exp, MathExp, 0x59769f9d) \
- V(::, log, MathLog, 0x2c12654e) \
+ V(::, asin, MathAsin, 0x661ff68b) \
+ V(::, acos, MathAcos, 0x44e71d5f) \
+ V(::, atan, MathAtan, 0x4436a657) \
+ V(::, atan2, MathAtan2, 0x60a40743) \
+ V(::, cos, MathCos, 0x79a7611c) \
+ V(::, exp, MathExp, 0x5b894d7b) \
+ V(::, log, MathLog, 0x2e25132c) \
V(::, max, MathMax, 0x54121d6a) \
V(::, min, MathMin, 0x4276561c) \
- V(::, pow, MathPow, 0x7ab62ca7) \
- V(::, sin, MathSin, 0x0000fe08) \
- V(::, sqrt, MathSqrt, 0x18e8d5f6) \
- V(::, tan, MathTan, 0x4c1b72fd) \
+ V(::, pow, MathPow, 0x438e3089) \
+ V(::, sin, MathSin, 0x0213abe6) \
+ V(::, sqrt, MathSqrt, 0x1afb83d4) \
+ V(::, tan, MathTan, 0x4e2e20db) \
V(Lists, copy, ListsCopy, 0x21a194fa) \
V(_Bigint, get:_neg, Bigint_getNeg, 0x7bf17a57) \
V(_Bigint, get:_used, Bigint_getUsed, 0x55041013) \
@@ -529,6 +529,7 @@
static bool AlwaysInline(const Function& function);
static bool PolymorphicTarget(const Function& function);
static intptr_t ResultCid(const Function& function);
+ static intptr_t MethodKindToReceiverCid(Kind kind);
static const char* KindToCString(Kind kind);
#if defined(DART_NO_SNAPSHOT)
static void InitializeState();
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 8626a5f..0543a07 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -52,6 +52,7 @@
"Make initializing formal parameters visible in initializer list.");
DEFINE_FLAG(bool, warn_super, false,
"Warning if super initializer not last in initializer list.");
+DEFINE_FLAG(bool, warn_patch, false, "Warn on old-style patch syntax.");
DEFINE_FLAG(bool, await_is_keyword, false,
"await and yield are treated as proper keywords in synchronous code.");
@@ -4545,10 +4546,17 @@
bool is_patch = false;
bool is_abstract = false;
TokenPosition declaration_pos =
- metadata_pos.IsReal() ? metadata_pos : TokenPos();
- if (is_patch_source() &&
+ metadata_pos.IsReal() ? metadata_pos : TokenPos();
+ if (is_patch_source() && IsPatchAnnotation(metadata_pos)) {
+ is_patch = true;
+ metadata_pos = TokenPosition::kNoSource;
+ declaration_pos = TokenPos();
+ } else if (is_patch_source() &&
(CurrentToken() == Token::kIDENT) &&
CurrentLiteral()->Equals("patch")) {
+ if (FLAG_warn_patch) {
+ ReportWarning("deprecated use of patch 'keyword'");
+ }
ConsumeToken();
is_patch = true;
} else if (CurrentToken() == Token::kABSTRACT) {
@@ -5264,6 +5272,19 @@
}
+bool Parser::IsPatchAnnotation(TokenPosition pos) {
+ if (pos == TokenPosition::kNoSource) {
+ return false;
+ }
+ TokenPosition saved_pos = TokenPos();
+ SetPosition(pos);
+ ExpectToken(Token::kAT);
+ bool is_patch = IsSymbol(Symbols::Patch());
+ SetPosition(saved_pos);
+ return is_patch;
+}
+
+
TokenPosition Parser::SkipMetadata() {
if (CurrentToken() != Token::kAT) {
return TokenPosition::kNoSource;
@@ -5606,10 +5627,16 @@
const bool is_static = true;
bool is_external = false;
bool is_patch = false;
- if (is_patch_source() &&
+ if (is_patch_source() && IsPatchAnnotation(metadata_pos)) {
+ is_patch = true;
+ metadata_pos = TokenPosition::kNoSource;
+ } else if (is_patch_source() &&
(CurrentToken() == Token::kIDENT) &&
CurrentLiteral()->Equals("patch") &&
(LookaheadToken(1) != Token::kLPAREN)) {
+ if (FLAG_warn_patch) {
+ ReportWarning("deprecated use of patch 'keyword'");
+ }
ConsumeToken();
is_patch = true;
} else if (CurrentToken() == Token::kEXTERNAL) {
@@ -5729,9 +5756,15 @@
bool is_external = false;
bool is_patch = false;
AbstractType& result_type = AbstractType::Handle(Z);
- if (is_patch_source() &&
+ if (is_patch_source() && IsPatchAnnotation(metadata_pos)) {
+ is_patch = true;
+ metadata_pos = TokenPosition::kNoSource;
+ } else if (is_patch_source() &&
(CurrentToken() == Token::kIDENT) &&
CurrentLiteral()->Equals("patch")) {
+ if (FLAG_warn_patch) {
+ ReportWarning("deprecated use of patch 'keyword'");
+ }
ConsumeToken();
is_patch = true;
} else if (CurrentToken() == Token::kEXTERNAL) {
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index e29f86e..d2644b7 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -401,6 +401,7 @@
void SkipToMatchingParenthesis();
void SkipBlock();
TokenPosition SkipMetadata();
+ bool IsPatchAnnotation(TokenPosition pos);
void SkipTypeArguments();
void SkipType(bool allow_void);
void SkipInitializers();
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index c272b4c..4ec886d 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -115,6 +115,50 @@
}
+TEST_CASE(Service_IsolateStickyError) {
+ const char* kScript =
+ "main() => throw 'HI THERE STICKY';\n";
+
+ Isolate* isolate = thread->isolate();
+ isolate->set_is_runnable(true);
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ Library& vmlib = Library::Handle();
+ vmlib ^= Api::UnwrapHandle(lib);
+ EXPECT(!vmlib.IsNull());
+ Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
+ EXPECT(Dart_IsUnhandledExceptionError(result));
+ EXPECT(!Dart_HasStickyError());
+ EXPECT(Thread::Current()->sticky_error() == Error::null());
+
+ {
+ TransitionNativeToVM transition(thread);
+
+ JSONStream js;
+ isolate->PrintJSON(&js, false);
+ // No error property and no PauseExit state.
+ EXPECT_NOTSUBSTRING("\"error\":", js.ToCString());
+ EXPECT_NOTSUBSTRING("HI THERE STICKY", js.ToCString());
+ EXPECT_NOTSUBSTRING("PauseExit", js.ToCString());
+ }
+
+ // Set the sticky error.
+ Dart_SetStickyError(result);
+ EXPECT(Dart_HasStickyError());
+
+ {
+ TransitionNativeToVM transition(thread);
+
+ JSONStream js;
+ isolate->PrintJSON(&js, false);
+ // Error and PauseExit set.
+ EXPECT_SUBSTRING("\"error\":", js.ToCString());
+ EXPECT_SUBSTRING("HI THERE STICKY", js.ToCString());
+ EXPECT_SUBSTRING("PauseExit", js.ToCString());
+ }
+}
+
+
TEST_CASE(Service_IdZones) {
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 24c934b..0ef9308 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -1531,7 +1531,7 @@
Redirection* redirection = Redirection::FromSvcInstruction(instr);
uword external = redirection->external_function();
if (IsTracingExecution()) {
- OS::Print("Call to host function at 0x%" Pd "\n", external);
+ THR_Print("Call to host function at 0x%" Pd "\n", external);
}
if ((redirection->call_kind() == kRuntimeCall) ||
@@ -3607,13 +3607,13 @@
void Simulator::InstructionDecode(Instr* instr) {
pc_modified_ = false;
if (IsTracingExecution()) {
- OS::Print("%" Pu64 " ", icount_);
+ THR_Print("%" Pu64 " ", icount_);
const uword start = reinterpret_cast<uword>(instr);
const uword end = start + Instr::kInstrSize;
if (FLAG_support_disassembler) {
Disassembler::Disassemble(start, end);
} else {
- OS::Print("Disassembler not supported in this mode.\n");
+ THR_Print("Disassembler not supported in this mode.\n");
}
}
if (instr->ConditionField() == kSpecialCondition) {
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index b3cac8b..e517fa4 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -1603,7 +1603,7 @@
Redirection* redirection = Redirection::FromHltInstruction(instr);
uword external = redirection->external_function();
if (IsTracingExecution()) {
- OS::Print("Call to host function at 0x%" Pd "\n", external);
+ THR_Print("Call to host function at 0x%" Pd "\n", external);
}
if ((redirection->call_kind() == kRuntimeCall) ||
@@ -3406,13 +3406,13 @@
void Simulator::InstructionDecode(Instr* instr) {
pc_modified_ = false;
if (IsTracingExecution()) {
- OS::Print("%" Pu64 " ", icount_);
+ THR_Print("%" Pu64 " ", icount_);
const uword start = reinterpret_cast<uword>(instr);
const uword end = start + Instr::kInstrSize;
if (FLAG_support_disassembler) {
Disassembler::Disassemble(start, end);
} else {
- OS::Print("Disassembler not supported in this mode.\n");
+ THR_Print("Disassembler not supported in this mode.\n");
}
}
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index d980ca1..8eff9ed 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -1242,7 +1242,7 @@
Redirection* redirection = Redirection::FromBreakInstruction(instr);
uword external = redirection->external_function();
if (IsTracingExecution()) {
- OS::Print("Call to host function at 0x%" Pd "\n", external);
+ THR_Print("Call to host function at 0x%" Pd "\n", external);
}
if ((redirection->call_kind() == kRuntimeCall) ||
@@ -1994,13 +1994,13 @@
void Simulator::InstructionDecode(Instr* instr) {
if (IsTracingExecution()) {
- OS::Print("%" Pu64 " ", icount_);
+ THR_Print("%" Pu64 " ", icount_);
const uword start = reinterpret_cast<uword>(instr);
const uword end = start + Instr::kInstrSize;
if (FLAG_support_disassembler) {
Disassembler::Disassemble(start, end);
} else {
- OS::Print("Disassembler not supported in this mode.\n");
+ THR_Print("Disassembler not supported in this mode.\n");
}
}
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 406f0bc..5115963 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -642,6 +642,12 @@
bool Thread::ObjectAtOffset(intptr_t offset, Object* object) {
+ if (Isolate::Current() == Dart::vm_isolate()) {
+ // --disassemble-stubs runs before all the references through
+ // thread have targets
+ return false;
+ }
+
#define COMPUTE_OFFSET(type_name, member_name, expr, default_init_value) \
if (Thread::member_name##offset() == offset) { \
*object = expr; \
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index e0e0617..b4d9c24 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -433,7 +433,7 @@
* with a `test` parameter, instead of handling both value and error in a
* single [then] call.
*/
- Future/*<S>*/ then/*<S>*/(/*=S*/ onValue(T value), { Function onError });
+ Future/*<S>*/ then/*<S>*/(onValue(T value), { Function onError });
/**
* Handles errors emitted by this [Future].
diff --git a/sdk/lib/io/http_headers.dart b/sdk/lib/io/http_headers.dart
index 6b14ae2..3769b3f 100644
--- a/sdk/lib/io/http_headers.dart
+++ b/sdk/lib/io/http_headers.dart
@@ -760,12 +760,12 @@
}
maybeExpect("=");
skipWS();
- if(done()) {
+ if (done()) {
parameters[name] = null;
return;
}
String value = parseParameterValue();
- if (name == 'charset' && this is _ContentType) {
+ if (name == 'charset' && this is _ContentType && value != null) {
// Charset parameter of ContentTypes are always lower-case.
value = value.toLowerCase();
}
diff --git a/sdk/lib/vmservice/devfs.dart b/sdk/lib/vmservice/devfs.dart
index 4735512..7f940b9 100644
--- a/sdk/lib/vmservice/devfs.dart
+++ b/sdk/lib/vmservice/devfs.dart
@@ -121,6 +121,39 @@
}
}
+ Future<String> handlePutStream(Object fsName,
+ Object path,
+ Stream<List<int>> bytes) async {
+ // A dummy Message for error message construction.
+ Message message = new Message.forMethod('_writeDevFSFile');
+ var writeStreamFile = VMServiceEmbedderHooks.writeStreamFile;
+ if (writeStreamFile == null) {
+ return _encodeDevFSDisabledError(message);
+ }
+ if (fsName == null) {
+ return encodeMissingParamError(message, 'fsName');
+ }
+ if (fsName is! String) {
+ return encodeInvalidParamError(message, 'fsName');
+ }
+ var fs = _fsMap[fsName];
+ if (fs == null) {
+ return _encodeFileSystemDoesNotExistError(message, fsName);
+ }
+ if (path == null) {
+ return encodeMissingParamError(message, 'path');
+ }
+ if (path is! String) {
+ return encodeInvalidParamError(message, 'path');
+ }
+ Uri uri = fs.resolvePath(path);
+ if (uri == null) {
+ return encodeInvalidParamError(message, 'path');
+ }
+ await writeStreamFile(uri, bytes);
+ return encodeSuccess(message);
+ }
+
Future<String> _listDevFS(Message message) async {
var result = {};
result['type'] = 'FileSystemList';
diff --git a/sdk/lib/vmservice/message.dart b/sdk/lib/vmservice/message.dart
index 295214c..0c02171 100644
--- a/sdk/lib/vmservice/message.dart
+++ b/sdk/lib/vmservice/message.dart
@@ -51,6 +51,9 @@
return uri.pathSegments[0];
}
+ Message.forMethod(String method)
+ : client = null, method = method, serial = '';
+
Message.fromUri(this.client, Uri uri)
: serial = '', method = _methodNameFromUri(uri) {
params.addAll(uri.queryParameters);
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index df5642b..25ceb6a 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -116,6 +116,9 @@
/// Called to write a file.
typedef Future WriteFileCallback(Uri path, List<int> bytes);
+/// Called to write a stream into a file.
+typedef Future WriteStreamFileCallback(Uri path, Stream<List<int>> bytes);
+
/// Called to read a file.
typedef Future<List<int>> ReadFileCallback(Uri path);
@@ -130,6 +133,7 @@
static CreateTempDirCallback createTempDir;
static DeleteDirCallback deleteDir;
static WriteFileCallback writeFile;
+ static WriteStreamFileCallback writeStreamFile;
static ReadFileCallback readFile;
static ListFilesCallback listFiles;
}
@@ -146,7 +150,7 @@
/// A port used to receive events from the VM.
final RawReceivePort eventPort;
- final _devfs = new DevFS();
+ final devfs = new DevFS();
void _addClient(Client client) {
assert(client.streams.isEmpty);
@@ -206,7 +210,7 @@
for (var client in clientsList) {
client.disconnect();
}
- _devfs.cleanup();
+ devfs.cleanup();
if (VMServiceEmbedderHooks.cleanup != null) {
await VMServiceEmbedderHooks.cleanup();
}
@@ -401,8 +405,8 @@
if (message.method == '_spawnUri') {
return _spawnUri(message);
}
- if (_devfs.shouldHandleMessage(message)) {
- return _devfs.handleMessage(message);
+ if (devfs.shouldHandleMessage(message)) {
+ return devfs.handleMessage(message);
}
if (message.params['isolateId'] != null) {
return runningIsolates.route(message);
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 7b4c8f9..0bb4d7d 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -37,7 +37,6 @@
patch_test/bug: RuntimeError # Issue 21132
quarantined/http_test: Pass, Slow
-inference_stats_test: Pass, Slow
# These tests are for the now-deleted dart2dart variant of the CPS IR.
# We want to adapt them to test the JS variant of the CPS IR instead,
diff --git a/tests/compiler/dart2js/inference_stats_test.dart b/tests/compiler/dart2js/inference_stats_test.dart
deleted file mode 100644
index a85ca39..0000000
--- a/tests/compiler/dart2js/inference_stats_test.dart
+++ /dev/null
@@ -1,340 +0,0 @@
-// Copyright (c) 2015, 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.
-// SharedOptions=-Dsend_stats=true
-
-/// Tests that we compute send metrics correctly in many simple scenarios.
-library dart2js.test.send_measurements_test;
-
-import 'dart:async';
-import 'package:test/test.dart';
-import 'package:dart2js_info/info.dart';
-import 'package:dart2js_info/src/util.dart' show
- recursiveDiagnosticString;
-import 'memory_compiler.dart';
-
-main() {
- test('nothing is reachable, nothing to count', () {
- return _check('''
- main() {}
- test() { int x = 3; }
- ''');
- });
-
- test('local variable read', () {
- return _check('''
- main() => test();
- test() { int x = 3; int y = x; }
- ''',
- localSend: 1); // from `int y = x`;
- });
-
- test('generative constructor call', () {
- return _check('''
- class A {
- get f => 1;
- }
- main() => test();
- test() { new A(); }
- ''',
- constructorSend: 1); // from new A()
- });
-
- group('instance call', () {
- test('monomorphic only one implementor', () {
- return _check('''
- class A {
- get f => 1;
- }
- main() => test();
- test() { new A().f; }
- ''',
- constructorSend: 1, // new A()
- instanceSend: 1); // f resolved to A.f
- });
-
- test('monomorphic only one type possible from types', () {
- return _check('''
- class A {
- get f => 1;
- }
- class B extends A {
- get f => 1;
- }
- main() => test();
- test() { new B().f; }
- ''',
- constructorSend: 1,
- instanceSend: 1); // f resolved to B.f
- });
-
- test('monomorphic only one type possible from liveness', () {
- return _check('''
- class A {
- get f => 1;
- }
- class B extends A {
- get f => 1;
- }
- main() => test();
- test() { A x = new B(); x.f; }
- ''',
- constructorSend: 1, // new B()
- localSend: 1, // x in x.f
- instanceSend: 1); // x.f known to resolve to B.f
- });
-
- test('monomorphic one possible, more than one live', () {
- return _check('''
- class A {
- get f => 1;
- }
- class B extends A {
- get f => 1;
- }
- main() { new A(); test(); }
- test() { B x = new B(); x.f; }
- ''',
- constructorSend: 1, // new B()
- localSend: 1, // x in x.f
- instanceSend: 1); // x.f resolves to B.f
- });
-
- test('polymorphic-virtual couple possible types from liveness', () {
- // Note: this would be an instanceSend if we used the inferrer.
- return _check('''
- class A {
- get f => 1;
- }
- class B extends A {
- get f => 1;
- }
- main() { new A(); test(); }
- test() { A x = new B(); x.f; }
- ''',
- constructorSend: 1, // new B()
- localSend: 1, // x in x.f
- virtualSend: 1); // x.f may be A.f or B.f (types alone is not enough)
- });
-
- test("polymorphic-dynamic: type annotations don't help", () {
- return _check('''
- class A {
- get f => 1;
- }
- class B extends A {
- get f => 1;
- }
- main() { new A(); test(); }
- test() { var x = new B(); x.f; }
- ''',
- constructorSend: 1, // new B()
- localSend: 1, // x in x.f
- dynamicSend: 1); // x.f could be any `f` or no `f`
- });
- });
-
- group('instance this call', () {
- test('monomorphic only one implementor', () {
- return _check('''
- class A {
- get f => 1;
- test() => this.f;
- }
- main() => new A().test();
- ''',
- instanceSend: 1); // this.f resolved to A.f
- });
-
- test('monomorphic only one type possible from types & liveness', () {
- return _check('''
- class A {
- get f => 1;
- test() => this.f;
- }
- class B extends A {
- get f => 1;
- }
- main() => new B().test();
- ''',
- instanceSend: 1); // this.f resolved to B.f
- });
-
- test('polymorphic-virtual couple possible types from liveness', () {
- // Note: this would be an instanceSend if we used the inferrer.
- return _check('''
- class A {
- get f => 1;
- test() => this.f;
- }
- class B extends A {
- get f => 1;
- }
- main() { new A(); new B().test(); }
- ''',
- virtualSend: 1); // this.f may be A.f or B.f
- });
- });
-
- group('noSuchMethod', () {
- test('error will be thrown', () {
- return _check('''
- class A {
- }
- main() { test(); }
- test() { new A().f; }
- ''',
- constructorSend: 1, // new B()
- nsmErrorSend: 1); // f not there, A has no nSM
- });
-
- test('nSM will be called - one option', () {
- return _check('''
- class A {
- noSuchMethod(i) => null;
- }
- main() { test(); }
- test() { new A().f; }
- ''',
- constructorSend: 1, // new B()
- singleNsmCallSend: 1); // f not there, A has nSM
- });
-
- // TODO(sigmund): is it worth splitting multiNSMvirtual?
- test('nSM will be called - multiple options', () {
- return _check('''
- class A {
- noSuchMethod(i) => null;
- }
- class B extends A {
- noSuchMethod(i) => null;
- }
- main() { new A(); test(); }
- test() { A x = new B(); x.f; }
- ''',
- constructorSend: 1, // new B()
- localSend: 1, // x in x.f
- multiNsmCallSend: 1); // f not there, A has nSM
- });
-
- // TODO(sigmund): is it worth splitting multiNSMvirtual?
- test('nSM will be called - multiple options', () {
- return _check('''
- class A {
- noSuchMethod(i) => null;
- }
- class B extends A {
- // don't count A's nsm as distinct
- }
- main() { new A(); test(); }
- test() { A x = new B(); x.f; }
- ''',
- constructorSend: 1, // new B()
- localSend: 1, // x in x.f
- singleNsmCallSend: 1); // f not there, A has nSM
- });
-
- test('nSM will be called - multiple options', () {
- return _check('''
- class A {
- noSuchMethod(i) => null;
- }
- class B extends A {
- get f => null;
- }
- main() { new A(); test(); }
- test() { A x = new B(); x.f; }
- ''',
- constructorSend: 1, // new B()
- localSend: 1, // x in x.f
- dynamicSend: 1); // f not known to be there there, A has nSM
- });
-
- test('nSM in super', () {
- return _check('''
- class A {
- noSuchMethod(i) => null;
- }
- class B extends A {
- get f => super.f;
- }
- main() { new A(); test(); }
- test() { A x = new B(); x.f; }
- ''',
- singleNsmCallSend: 1, // super.f
- testMethod: 'f');
- });
- });
-}
-
-
-/// Checks that the `test` function in [code] produces the given distribution of
-/// sends.
-_check(String code, {int staticSend: 0, int superSend: 0, int localSend: 0,
- int constructorSend: 0, int typeVariableSend: 0, int nsmErrorSend: 0,
- int singleNsmCallSend: 0, int instanceSend: 0, int interceptorSend: 0,
- int multiNsmCallSend: 0, int virtualSend: 0, int multiInterceptorSend: 0,
- int dynamicSend: 0, String testMethod: 'test'}) async {
-
- // Set up the expectation.
- var expected = new Measurements();
- int monomorphic = staticSend + superSend + localSend + constructorSend +
- typeVariableSend + nsmErrorSend + singleNsmCallSend + instanceSend +
- interceptorSend;
- int polymorphic = multiNsmCallSend + virtualSend + multiInterceptorSend +
- dynamicSend;
-
- expected.counters[Metric.monomorphicSend] = monomorphic;
- expected.counters[Metric.staticSend] = staticSend;
- expected.counters[Metric.superSend] = superSend;
- expected.counters[Metric.localSend] = localSend;
- expected.counters[Metric.constructorSend] = constructorSend;
- expected.counters[Metric.typeVariableSend] = typeVariableSend;
- expected.counters[Metric.nsmErrorSend] = nsmErrorSend;
- expected.counters[Metric.singleNsmCallSend] = singleNsmCallSend;
- expected.counters[Metric.instanceSend] = instanceSend;
- expected.counters[Metric.interceptorSend] = interceptorSend;
-
- expected.counters[Metric.polymorphicSend] = polymorphic;
- expected.counters[Metric.multiNsmCallSend] = multiNsmCallSend;
- expected.counters[Metric.virtualSend] = virtualSend;
- expected.counters[Metric.multiInterceptorSend] = multiInterceptorSend;
- expected.counters[Metric.dynamicSend] = dynamicSend;
-
- expected.counters[Metric.send] = monomorphic + polymorphic;
-
- // Run the compiler to get the results.
- var all = await _compileAndGetStats(code);
- var function = all.functions.firstWhere((f) => f.name == testMethod,
- orElse: () => null);
- var result = function?.measurements;
- if (function == null) {
- expect(expected.counters[Metric.send], 0);
- return;
- }
-
- expect(result, isNotNull);
-
- _compareMetric(Metric key) {
- var expectedValue = expected.counters[key];
- var value = result.counters[key];
- if (value == null) value = 0;
- if (value == expectedValue) return;
- expect(expectedValue, value,
- reason: "count for `$key` didn't match:\n"
- "expected measurements:\n${recursiveDiagnosticString(expected, key)}\n"
- "actual measurements:\n${recursiveDiagnosticString(result, key)}");
- }
-
- _compareMetric(Metric.send);
- expected.counters.keys.forEach(_compareMetric);
-}
-
-/// Helper that runs the compiler and returns the [GlobalResult] computed for
-/// it.
-Future<AllInfo> _compileAndGetStats(String program) async {
- var result = await runCompiler(
- memorySourceFiles: {'main.dart': program}, options: ['--dump-info']);
- expect(result.compiler.compilationFailed, isFalse);
- return result.compiler.dumpInfoTask.infoCollector.result;
-}
diff --git a/tests/compiler/dart2js/serialization/analysis3_test.dart b/tests/compiler/dart2js/serialization/analysis3_test.dart
new file mode 100644
index 0000000..84da9d9
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/analysis3_test.dart
@@ -0,0 +1,12 @@
+// 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.
+
+library dart2js.serialization.analysis3_test;
+
+import 'analysis_test_helper.dart' as test;
+import 'test_helper.dart';
+
+main() {
+ test.main(testSegment(3, test.SPLIT_COUNT, test.SKIP_COUNT));
+}
diff --git a/tests/compiler/dart2js/serialization/analysis4_test.dart b/tests/compiler/dart2js/serialization/analysis4_test.dart
new file mode 100644
index 0000000..ff5c1ac
--- /dev/null
+++ b/tests/compiler/dart2js/serialization/analysis4_test.dart
@@ -0,0 +1,12 @@
+// 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.
+
+library dart2js.serialization.analysis4_test;
+
+import 'analysis_test_helper.dart' as test;
+import 'test_helper.dart';
+
+main() {
+ test.main(testSegment(4, test.SPLIT_COUNT, test.SKIP_COUNT));
+}
diff --git a/tests/compiler/dart2js/serialization/analysis_test_helper.dart b/tests/compiler/dart2js/serialization/analysis_test_helper.dart
index 52b0271..17926c6 100644
--- a/tests/compiler/dart2js/serialization/analysis_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/analysis_test_helper.dart
@@ -18,7 +18,7 @@
int SKIP_COUNT = 0;
/// Number of groups that the [TESTS] are split into.
-int SPLIT_COUNT = 2;
+int SPLIT_COUNT = 4;
main(List<String> args) {
asyncTest(() async {
diff --git a/tests/compiler/dart2js/serialization/model_test_helper.dart b/tests/compiler/dart2js/serialization/model_test_helper.dart
index daf68663..18fd88c 100644
--- a/tests/compiler/dart2js/serialization/model_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/model_test_helper.dart
@@ -11,6 +11,7 @@
import 'package:compiler/src/closure.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/common.dart';
+import 'package:compiler/src/constants/values.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/deferred_load.dart';
import 'package:compiler/src/elements/elements.dart';
@@ -161,6 +162,38 @@
compilerNormal.deferredLoadTask.isProgramSplit,
compilerDeserialized.deferredLoadTask.isProgramSplit,
"isProgramSplit mismatch");
+
+ Map<ConstantValue, OutputUnit> constants1 =
+ compilerNormal.deferredLoadTask.outputUnitForConstantsForTesting;
+ Map<ConstantValue, OutputUnit> constants2 =
+ compilerDeserialized.deferredLoadTask.outputUnitForConstantsForTesting;
+ checkSets(
+ constants1.keys,
+ constants2.keys,
+ 'deferredLoadTask._outputUnitForConstants.keys',
+ areConstantValuesEquivalent,
+ failOnUnfound: false,
+ failOnExtra: false,
+ onSameElement: (ConstantValue value1, ConstantValue value2) {
+ OutputUnit outputUnit1 = constants1[value1];
+ OutputUnit outputUnit2 = constants2[value2];
+ checkOutputUnits(outputUnit1, outputUnit2,
+ 'for ${value1.toStructuredText()} '
+ 'vs ${value2.toStructuredText()}');
+ },
+ onUnfoundElement: (ConstantValue value1) {
+ OutputUnit outputUnit1 = constants1[value1];
+ Expect.isTrue(outputUnit1.isMainOutput,
+ "Missing deferred constant: ${value1.toStructuredText()}");
+ },
+ onExtraElement: (ConstantValue value2) {
+ OutputUnit outputUnit2 = constants2[value2];
+ Expect.isTrue(outputUnit2.isMainOutput,
+ "Extra deferred constant: ${value2.toStructuredText()}");
+ },
+ elementToString: (a) {
+ return '${a.toStructuredText()} -> ${constants1[a]}/${constants2[a]}';
+ });
});
}
@@ -244,7 +277,7 @@
backend2.inlineCache.getCurrentCacheDecisionForTesting(element2),
"Inline cache decision mismatch for $element1 vs $element2");
- checkOutputUnits(compiler1, compiler2, element1, element2);
+ checkElementOutputUnits(compiler1, compiler2, element1, element2);
}
void checkMixinUses(
@@ -360,17 +393,24 @@
return '(${node.runtimeType}) $text';
}
-void checkOutputUnits(Compiler compiler1, Compiler compiler2, Element element1,
- Element element2) {
+void checkElementOutputUnits(
+ Compiler compiler1, Compiler compiler2,
+ Element element1, Element element2) {
OutputUnit outputUnit1 =
- compiler1.deferredLoadTask.outputUnitForElement(element1);
+ compiler1.deferredLoadTask.getOutputUnitForElementForTesting(element1);
OutputUnit outputUnit2 =
- compiler2.deferredLoadTask.outputUnitForElement(element2);
+ compiler2.deferredLoadTask.getOutputUnitForElementForTesting(element2);
+ checkOutputUnits(outputUnit1, outputUnit2, 'for $element1 vs $element2');
+}
+
+void checkOutputUnits(
+ OutputUnit outputUnit1, OutputUnit outputUnit2, String message) {
+ if (outputUnit1 == null && outputUnit2 == null) return;
check(outputUnit1, outputUnit2,
- 'OutputUnit.isMainOutput for $element1 vs $element2',
+ 'OutputUnit.isMainOutput $message',
outputUnit1.isMainOutput, outputUnit2.isMainOutput);
checkSetEquivalence(outputUnit1, outputUnit2,
- 'OutputUnit.imports for $element1 vs $element2',
+ 'OutputUnit.imports $message',
outputUnit1.imports, outputUnit2.imports,
(a, b) => areElementsEquivalent(a.declaration, b.declaration));
}
\ No newline at end of file
diff --git a/tests/compiler/dart2js/serialization/test_data.dart b/tests/compiler/dart2js/serialization/test_data.dart
index 568b453..9fbd223 100644
--- a/tests/compiler/dart2js/serialization/test_data.dart
+++ b/tests/compiler/dart2js/serialization/test_data.dart
@@ -644,6 +644,35 @@
}
''',
}),
+
+ const Test('Use of dart:indexed_db', const {
+ 'main.dart': '''
+import 'a.dart';
+
+main() {}
+''',
+ }, preserializedSourceFiles: const {
+ 'a.dart': '''
+import 'dart:indexed_db';
+''',
+ }),
+
+ const Test('Deferred static access', const {},
+ preserializedSourceFiles: const {
+ 'main.dart': '''
+import 'b.dart' deferred as prefix;
+
+main() => prefix.loadLibrary().then((_) => prefix.test2());
+''',
+ 'b.dart': '''
+test2() => x;
+var x = const ConstClass(const ConstClass(1));
+class ConstClass {
+ final x;
+ const ConstClass(this.x);
+}
+''',
+ }),
];
class Test {
diff --git a/tests/compiler/dart2js/serialization/test_helper.dart b/tests/compiler/dart2js/serialization/test_helper.dart
index 2c74a07..f5d986d 100644
--- a/tests/compiler/dart2js/serialization/test_helper.dart
+++ b/tests/compiler/dart2js/serialization/test_helper.dart
@@ -7,6 +7,7 @@
import 'dart:collection';
import 'package:compiler/src/common/resolution.dart';
import 'package:compiler/src/constants/expressions.dart';
+import 'package:compiler/src/constants/values.dart';
import 'package:compiler/src/dart_types.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/elements.dart';
@@ -88,6 +89,15 @@
}
@override
+ bool testMaps(
+ var object1, var object2, String property, Map map1, Map map2,
+ [bool keyEquivalence(a, b) = equality,
+ bool valueEquivalence(a, b) = equality]) {
+ return checkMapEquivalence(object1, object2, property,
+ map1, map2, keyEquivalence, valueEquivalence);
+ }
+
+ @override
bool testElements(
Object object1, Object object2, String property,
Element element1, Element element2) {
@@ -110,6 +120,12 @@
}
@override
+ bool testConstantValues(Object object1, Object object2, String property,
+ ConstantValue value1, ConstantValue value2) {
+ return areConstantValuesEquivalent(value1, value2);
+ }
+
+ @override
bool testTypeLists(
Object object1, Object object2, String property,
List<DartType> list1, List<DartType> list2) {
@@ -125,6 +141,12 @@
}
@override
+ bool testConstantValueLists(Object object1, Object object2, String property,
+ List<ConstantValue> list1, List<ConstantValue> list2) {
+ return checkConstantValueLists(object1, object2, property, list1, list2);
+ }
+
+ @override
bool testNodes(Object object1, Object object2, String property,
Node node1, Node node2) {
return new NodeEquivalenceVisitor(this).testNodes(
@@ -247,6 +269,38 @@
return true;
}
+/// Check equivalence of the two iterables, [set1] and [set1], as sets using
+/// [elementEquivalence] to compute the pair-wise equivalence.
+///
+/// Uses [object1], [object2] and [property] to provide context for failures.
+bool checkMapEquivalence(
+ var object1,
+ var object2,
+ String property,
+ Map map1,
+ Map map2,
+ bool sameKey(a, b),
+ bool sameValue(a, b)) {
+ List<List> common = <List>[];
+ List unfound = [];
+ Set remaining =
+ computeSetDifference(map1.keys, map2.keys, common, unfound,
+ sameElement: sameKey);
+ if (unfound.isNotEmpty || remaining.isNotEmpty) {
+ String message =
+ "Map key mismatch for `$property` on $object1 vs $object2: \n"
+ "Common:\n ${common.join('\n ')}\n"
+ "Unfound:\n ${unfound.join('\n ')}\n"
+ "Extra: \n ${remaining.join('\n ')}";
+ throw message;
+ }
+ for (List pair in common) {
+ check(object1, object2, 'Map value for `$property`',
+ map1[pair[0]], map2[pair[1]], sameValue);
+ }
+ return true;
+}
+
/// Checks the equivalence of the identity (but not properties) of [element1]
/// and [element2].
///
@@ -311,7 +365,23 @@
}
}
-/// Checks the pair-wise equivalence of the contants in [list1] and [list2].
+/// Checks the equivalence of [value1] and [value2].
+///
+/// Uses [object1], [object2] and [property] to provide context for failures.
+bool checkConstantValues(
+ Object object1, Object object2, String property,
+ ConstantValue value1, ConstantValue value2) {
+ if (identical(value1, value2)) return true;
+ if (value1 == null || value2 == null) {
+ return check(object1, object2, property, value1, value2);
+ } else {
+ return check(object1, object2, property, value1, value2,
+ (a, b) => const ConstantValueEquivalence(
+ const CheckStrategy()).visit(a, b));
+ }
+}
+
+/// Checks the pair-wise equivalence of the constants in [list1] and [list2].
///
/// Uses [object1], [object2] and [property] to provide context for failures.
bool checkConstantLists(
@@ -323,6 +393,18 @@
list1, list2, checkConstants);
}
+/// Checks the pair-wise equivalence of the constants values in [list1] and
+/// [list2].
+///
+/// Uses [object1], [object2] and [property] to provide context for failures.
+bool checkConstantValueLists(
+ Object object1, Object object2, String property,
+ List<ConstantValue> list1,
+ List<ConstantValue> list2) {
+ return checkListEquivalence(
+ object1, object2, property,
+ list1, list2, checkConstantValues);
+}
/// Check member property equivalence between all members common to [compiler1]
/// and [compiler2].
@@ -439,27 +521,41 @@
{bool failOnUnfound: true,
bool failOnExtra: true,
bool verbose: false,
- void onSameElement(a, b)}) {
+ void onSameElement(a, b),
+ void onUnfoundElement(a),
+ void onExtraElement(b),
+ String elementToString(key): defaultToString}) {
List<List> common = <List>[];
List unfound = [];
Set remaining = computeSetDifference(
set1, set2, common, unfound,
sameElement: sameElement,
checkElements: onSameElement);
+ if (onUnfoundElement != null) {
+ unfound.forEach(onUnfoundElement);
+ }
+ if (onExtraElement != null) {
+ remaining.forEach(onExtraElement);
+ }
StringBuffer sb = new StringBuffer();
sb.write("$messagePrefix:");
if (verbose) {
- sb.write("\n Common:\n ${common.join('\n ')}");
+ sb.write("\n Common: \n");
+ for (List pair in common) {
+ var element1 = pair[0];
+ var element2 = pair[1];
+ sb.write(" [${elementToString(element1)},"
+ "${elementToString(element2)}]\n");
+ }
}
if (unfound.isNotEmpty || verbose) {
- sb.write("\n Unfound:\n ${unfound.join('\n ')}");
+ sb.write("\n Unfound:\n ${unfound.map(elementToString).join('\n ')}");
}
if (remaining.isNotEmpty || verbose) {
- sb.write("\n Extra: \n ${remaining.join('\n ')}");
+ sb.write("\n Extra: \n ${remaining.map(elementToString).join('\n ')}");
}
String message = sb.toString();
if (unfound.isNotEmpty || remaining.isNotEmpty) {
-
if ((failOnUnfound && unfound.isNotEmpty) ||
(failOnExtra && remaining.isNotEmpty)) {
Expect.fail(message);
diff --git a/tests/language/string_interpolation1_negative_test.dart b/tests/language/string_interpolation1_test.dart
similarity index 79%
rename from tests/language/string_interpolation1_negative_test.dart
rename to tests/language/string_interpolation1_test.dart
index 15ccfe4..4555dd0 100644
--- a/tests/language/string_interpolation1_negative_test.dart
+++ b/tests/language/string_interpolation1_test.dart
@@ -11,8 +11,9 @@
class StringInterpolation1NegativeTest {
// Dollar not followed by "{" or identifier.
- static const DOLLAR = const A("$");
- testMain() {
+ static const DOLLAR = const A("$"); /// 01: compile-time error
+ static testMain() {
+ print(DOLLAR); /// 01: continued
}
}
diff --git a/tests/language/string_interpolation2_negative_test.dart b/tests/language/string_interpolation2_test.dart
similarity index 76%
rename from tests/language/string_interpolation2_negative_test.dart
rename to tests/language/string_interpolation2_test.dart
index ca5e269..55aa734 100644
--- a/tests/language/string_interpolation2_negative_test.dart
+++ b/tests/language/string_interpolation2_test.dart
@@ -5,8 +5,9 @@
// A dollar must be followed by a "{" or an identifier.
class StringInterpolation2NegativeTest {
- testMain() {
- print('C;Y1;X4;K"$/Month"'); // Dollar followed by "/".
+ static testMain() {
+ // Dollar followed by "/".
+ print('C;Y1;X4;K"$/Month"'); /// 01: compile-time error
}
}
diff --git a/tests/language/string_interpolation3_negative_test.dart b/tests/language/string_interpolation3_test.dart
similarity index 81%
rename from tests/language/string_interpolation3_negative_test.dart
rename to tests/language/string_interpolation3_test.dart
index 14e2525..4ccf8d5 100644
--- a/tests/language/string_interpolation3_negative_test.dart
+++ b/tests/language/string_interpolation3_test.dart
@@ -6,7 +6,8 @@
class StringInterpolation3NegativeTest {
static testMain() {
- print('F;P4;F$2R'); // Dollar followed by a number.
+ // Dollar followed by a number.
+ print('F;P4;F$2R'); /// 01: compile-time error
}
}
diff --git a/tests/language/string_interpolation4_negative_test.dart b/tests/language/string_interpolation4_test.dart
similarity index 84%
rename from tests/language/string_interpolation4_negative_test.dart
rename to tests/language/string_interpolation4_test.dart
index bc7db6f..ab26160 100644
--- a/tests/language/string_interpolation4_negative_test.dart
+++ b/tests/language/string_interpolation4_test.dart
@@ -5,9 +5,9 @@
// A dollar must be followed by a "{" or an identifier.
class StringInterpolation4NegativeTest {
- testMain() {
+ static testMain() {
// Dollar not followed by "{" or identifier.
- print("-" + "$" + "foo");
+ print("-" + "$" + "foo"); /// 01: compile-time error
}
}
diff --git a/tests/language/string_interpolation5_negative_test.dart b/tests/language/string_interpolation5_test.dart
similarity index 78%
rename from tests/language/string_interpolation5_negative_test.dart
rename to tests/language/string_interpolation5_test.dart
index 9d6197d..13cf3d3 100644
--- a/tests/language/string_interpolation5_negative_test.dart
+++ b/tests/language/string_interpolation5_test.dart
@@ -5,8 +5,9 @@
// A dollar must be followed by a "{" or an identifier.
class StringInterpolation5NegativeTest {
- testMain() {
- print("$1,000"); // Dollar followed by a number.
+ static testMain() {
+ // Dollar followed by a number.
+ print("$1,000"); /// 01: compile-time error
}
}
diff --git a/tests/language/string_interpolation6_negative_test.dart b/tests/language/string_interpolation6_test.dart
similarity index 80%
rename from tests/language/string_interpolation6_negative_test.dart
rename to tests/language/string_interpolation6_test.dart
index e90545f..155f9fb 100644
--- a/tests/language/string_interpolation6_negative_test.dart
+++ b/tests/language/string_interpolation6_test.dart
@@ -5,9 +5,10 @@
// A dollar must be followed by a "{" or an identifier.
class StringInterpolation6NegativeTest {
- testMain() {
+ static testMain() {
// Dollar not followed by "{" or identifier.
- String regexp = "^(\\d\\d?)[-/](\\d\\d?)$";
+ String regexp;
+ regexp = "^(\\d\\d?)[-/](\\d\\d?)$"; /// 01: compile-time error
print(regexp);
}
}
diff --git a/tests/standalone/io/http_headers_test.dart b/tests/standalone/io/http_headers_test.dart
index 1c84cd5..26edb5f 100644
--- a/tests/standalone/io/http_headers_test.dart
+++ b/tests/standalone/io/http_headers_test.dart
@@ -380,6 +380,11 @@
" text/html ; charset = utf-8 ; xxx=yyy ");
check(contentType, "text", "html", {"charset": "utf-8", "xxx": "yyy"});
+ contentType = ContentType.parse("text/html; charset=;");
+ check(contentType, "text", "html", {"charset": null});
+ contentType = ContentType.parse("text/html; charset;");
+ check(contentType, "text", "html", {"charset": null});
+
// Test builtin content types.
check(ContentType.TEXT, "text", "plain", {"charset": "utf-8"});
check(ContentType.HTML, "text", "html", {"charset": "utf-8"});
@@ -387,6 +392,20 @@
check(ContentType.BINARY, "application", "octet-stream");
}
+void testKnownContentTypes() {
+ // Well known content types used by the VM service.
+ ContentType.parse('text/html; charset=UTF-8');
+ ContentType.parse('application/dart; charset=UTF-8');
+ ContentType.parse('application/javascript; charset=UTF-8');
+ ContentType.parse('text/css; charset=UTF-8');
+ ContentType.parse('image/gif');
+ ContentType.parse('image/png');
+ ContentType.parse('image/jpeg');
+ ContentType.parse('image/jpeg');
+ ContentType.parse('image/svg+xml');
+ ContentType.parse('text/plain');
+}
+
void testContentTypeCache() {
_HttpHeaders headers = new _HttpHeaders("1.1");
headers.set(HttpHeaders.CONTENT_TYPE, "text/html");
@@ -570,6 +589,7 @@
testEnumeration();
testHeaderValue();
testContentType();
+ testKnownContentTypes();
testContentTypeCache();
testCookie();
testInvalidCookie();
diff --git a/tests/standalone/io/raw_datagram_socket_test.dart b/tests/standalone/io/raw_datagram_socket_test.dart
index 20d841e..f3168fb 100644
--- a/tests/standalone/io/raw_datagram_socket_test.dart
+++ b/tests/standalone/io/raw_datagram_socket_test.dart
@@ -195,6 +195,25 @@
}
}
+testLoopbackMulticastError() {
+ var bindAddress = InternetAddress.ANY_IP_V4;
+ var multicastAddress = new InternetAddress("228.0.0.4");
+ asyncStart();
+ Future.wait([
+ RawDatagramSocket.bind(bindAddress, 0, reuseAddress: false),
+ RawDatagramSocket.bind(bindAddress, 0, reuseAddress: false)])
+ .then((values) {
+ var sender = values[0];
+ var receiver = values[1];
+ Expect.throws(
+ () { sender.joinMulticast(new InternetAddress("127.0.0.1")); },
+ (e) => e is! TypeError);
+ sender.close();
+ receiver.close();
+ asyncEnd();
+ });
+}
+
testSendReceive(InternetAddress bindAddress, int dataSize) {
asyncStart();
@@ -320,6 +339,7 @@
}
testBroadcast();
testLoopbackMulticast();
+ testLoopbackMulticastError();
testSendReceive(InternetAddress.LOOPBACK_IP_V4, 1000);
testSendReceive(InternetAddress.LOOPBACK_IP_V6, 1000);
if (!Platform.isMacOS) {
diff --git a/tools/FAKE_COMMITS b/tools/FAKE_COMMITS
index 63b6b4b..65dee12 100644
--- a/tools/FAKE_COMMITS
+++ b/tools/FAKE_COMMITS
@@ -17,3 +17,4 @@
googlecode back up
CIT outage - all slaves rebooted
Authentication failure flake - rerun all bots
+Trigger bots after master restart - switch dart2js bots to use downloaded sdk.
\ No newline at end of file
diff --git a/tools/VERSION b/tools/VERSION
index 8bec38a..020fe18 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 1
MINOR 19
PATCH 0
-PRERELEASE 4
+PRERELEASE 5
PRERELEASE_PATCH 0
diff --git a/tools/bots/bot.py b/tools/bots/bot.py
index cfd9076..b24fe74 100644
--- a/tools/bots/bot.py
+++ b/tools/bots/bot.py
@@ -271,14 +271,17 @@
RunProcess(args)
-def RunProcess(command):
+def RunProcess(command, env=None):
"""
Runs command.
If a non-zero exit code is returned, raises an OSError with errno as the exit
code.
"""
- no_color_env = dict(os.environ)
+ if env is None:
+ no_color_env = dict(os.environ)
+ else:
+ no_color_env = env
no_color_env['TERM'] = 'nocolor'
exit_code = subprocess.call(command, env=no_color_env)
diff --git a/tools/bots/dart_sdk.py b/tools/bots/dart_sdk.py
index 92f89f8..ce8b5c9 100644
--- a/tools/bots/dart_sdk.py
+++ b/tools/bots/dart_sdk.py
@@ -4,6 +4,7 @@
# 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 os
import os.path
import shutil
import sys
@@ -21,8 +22,26 @@
def BuildSDK():
with bot.BuildStep('Build SDK'):
+ sysroot_env = dict(os.environ)
+ if BUILD_OS == 'linux':
+ ia32root = os.path.join(bot_utils.DART_DIR, '..', 'sysroots',
+ 'build', 'linux', 'debian_wheezy_i386-sysroot')
+ sysroot_env['CXXFLAGS'] = ("--sysroot=%s -I=/usr/include/c++/4.6 "
+ "-I=/usr/include/c++/4.6/i486-linux-gnu") % ia32root
+ sysroot_env['LDFLAGS'] = '--sysroot=%s' % ia32root
+ sysroot_env['CFLAGS'] = '--sysroot=%s' % ia32root
Run([sys.executable, './tools/build.py', '--mode=release',
- '--arch=ia32,x64', 'create_sdk'])
+ '--arch=ia32', 'create_sdk'], env=sysroot_env)
+
+ x64root = os.path.join(bot_utils.DART_DIR, '..', 'sysroots', 'build',
+ 'linux', 'debian_wheezy_amd64-sysroot')
+ if BUILD_OS == 'linux':
+ sysroot_env['CXXFLAGS'] = ("--sysroot=%s -I=/usr/include/c++/4.6 "
+ "-I=/usr/include/c++/4.6/x86_64-linux-gnu") % x64root
+ sysroot_env['LDFLAGS'] = '--sysroot=%s' % x64root
+ sysroot_env['CFLAGS'] = '--sysroot=%s' % x64root
+ Run([sys.executable, './tools/build.py', '--mode=release',
+ '--arch=x64', 'create_sdk'], env=sysroot_env)
def BuildDartdocAPIDocs(dirname):
dart_sdk = os.path.join(bot_utils.DART_DIR,
@@ -214,9 +233,10 @@
mangled_filename)
gsutil.upload(local_sha256, remote_path + '.sha256sum', public=True)
-def Run(command):
+def Run(command, env=None):
print "Running %s" % ' '.join(command)
- return bot.RunProcess(command)
+ print "Environment %s" % env
+ return bot.RunProcess(command, env=env)
if __name__ == '__main__':
# We always clobber the bot, to make sure releases are build from scratch
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 9457e56..00ba641 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": "006cf3ee53f37973d2db812a62fc8f5f83b52948",
+ "dartium_webkit_commit": "522da5fa29843cb44afdc20328be356f693685d6",
"chromium_base_revision": "338390",
# We use mirrors of all github repos to guarantee reproducibility and
diff --git a/tools/download_chromium_sysroot.sh b/tools/download_chromium_sysroot.sh
new file mode 100755
index 0000000..75b3744
--- /dev/null
+++ b/tools/download_chromium_sysroot.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+#
+# 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.
+
+# Downloads the ia32 and x64 Debian wheezy sysroot that chromium uses,
+# Only tested and used on Ubuntu trusty linux. Used to keep glibc version low.
+# Creates directories called "build" and "tools" in the current directory.
+# After running this, source set_ia32_sysroot.sh or set_x64_sysroot.sh, in
+# the same working directory, to set the compilation environment variables.
+# Sourcing a script means running the script with a '.', so that it runs
+# in the current shell, not a subshell, as in:
+# . sdk/tools/set_ia32_sysroot.sh
+
+git clone https://chromium.googlesource.com/chromium/src/build
+mkdir tools
+cd tools
+git clone https://chromium.googlesource.com/external/gyp
+cd ..
+
+build/linux/sysroot_scripts/install-sysroot.py --arch i386
+build/linux/sysroot_scripts/install-sysroot.py --arch amd64
diff --git a/tools/set_ia32_sysroot.sh b/tools/set_ia32_sysroot.sh
new file mode 100755
index 0000000..c7156ce
--- /dev/null
+++ b/tools/set_ia32_sysroot.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+#
+# 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.
+
+# Sets the compiler environment variables to use a downloaded wheezy sysroot
+# when building Dart with architecture ia32.
+# Run this in the same working directory that you have run
+# sdk/tools/download_chromium_sysroot.sh in.
+# Must be sourced, not run in a subshell, to modify the environment.
+# Run with the command ". sdk/tools/set_ia32_sysroot.sh"
+# Only tested and used on Ubuntu trusty linux. Used to build dart with
+# no requirement for glibc greater than version 2.14.
+
+export CXXFLAGS="--sysroot=$PWD/build/linux/debian_wheezy_i386-sysroot -I=/usr/include/c++/4.6 -I=/usr/include/c++/4.6/i486-linux-gnu"
+
+export LDFLAGS=--sysroot=$PWD/build/linux/debian_wheezy_i386-sysroot
+export CFLAGS=--sysroot=$PWD/build/linux/debian_wheezy_i386-sysroot
diff --git a/tools/set_x64_sysroot.sh b/tools/set_x64_sysroot.sh
new file mode 100755
index 0000000..bc28961
--- /dev/null
+++ b/tools/set_x64_sysroot.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+#
+# 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.
+
+# Sets the compiler environment variables to use a downloaded wheezy sysroot
+# when building Dart with architecture x64.
+# Run this in the same working directory that you have run
+# sdk/tools/download_chromium_sysroot.sh in.
+# Must be sourced, not run in a subshell, to modify the environment.
+# Run with the command ". sdk/tools/set_x64_sysroot.sh"
+# Only tested and used on Ubuntu trusty linux. Used to build dart with
+# no requirement for glibc greater than version 2.14.
+
+export CXXFLAGS="--sysroot=$PWD/build/linux/debian_wheezy_amd64-sysroot -I=/usr/include/c++/4.6 -I=/usr/include/c++/4.6/x86_64-linux-gnu"
+
+export LDFLAGS=--sysroot=$PWD/build/linux/debian_wheezy_amd64-sysroot
+export CFLAGS=--sysroot=$PWD/build/linux/debian_wheezy_amd64-sysroot
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index bf6db43..f6ac871 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -34,6 +34,7 @@
abstract class CompilerConfiguration {
final bool isDebug;
final bool isChecked;
+ final bool isStrong;
final bool isHostChecked;
final bool useSdk;
@@ -48,6 +49,7 @@
// object.
bool isDebug = configuration['mode'] == 'debug';
bool isChecked = configuration['checked'];
+ bool isStrong = configuration['strong'];
bool isHostChecked = configuration['host_checked'];
bool useSdk = configuration['use_sdk'];
bool isCsp = configuration['csp'];
@@ -61,6 +63,7 @@
return new AnalyzerCompilerConfiguration(
isDebug: isDebug,
isChecked: isChecked,
+ isStrong: isStrong,
isHostChecked: isHostChecked,
useSdk: useSdk);
case 'dart2js':
@@ -102,6 +105,7 @@
CompilerConfiguration._subclass(
{this.isDebug: false,
this.isChecked: false,
+ this.isStrong: false,
this.isHostChecked: false,
this.useSdk: false});
@@ -604,10 +608,12 @@
class AnalyzerCompilerConfiguration extends CompilerConfiguration {
AnalyzerCompilerConfiguration(
- {bool isDebug, bool isChecked, bool isHostChecked, bool useSdk})
+ {bool isDebug, bool isChecked, bool isStrong, bool isHostChecked, bool
+ useSdk})
: super._subclass(
isDebug: isDebug,
isChecked: isChecked,
+ isStrong: isStrong,
isHostChecked: isHostChecked,
useSdk: useSdk);
@@ -640,9 +646,12 @@
List arguments,
Map<String, String> environmentOverrides) {
arguments = new List.from(arguments);
- if (isChecked) {
+ if (isChecked || isStrong) {
arguments.add('--enable_type_checks');
}
+ if (isStrong){
+ arguments.add('--strong');
+ }
return new CommandArtifact(<Command>[
commandBuilder.getAnalysisCommand('dart2analyzer',
computeCompilerPath(buildDir), arguments, environmentOverrides,
diff --git a/tools/testing/dart/test_configurations.dart b/tools/testing/dart/test_configurations.dart
index ca3bfbe..84cbbb4 100644
--- a/tools/testing/dart/test_configurations.dart
+++ b/tools/testing/dart/test_configurations.dart
@@ -103,6 +103,7 @@
.map((name) => conf[name])
.toList();
if (conf['checked']) settings.add('checked');
+ if (conf['strong']) settings.add('strong');
if (conf['noopt']) settings.add('noopt');
output_words.add(settings.join('_'));
}
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index 6f76125..c685988 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -163,6 +163,9 @@
new _TestOptionSpecification(
'checked', 'Run tests in checked mode', ['--checked'], [], false,
type: 'bool'),
+ new _TestOptionSpecification(
+ 'strong', 'Run tests in strong mode', ['--strong'], [], false,
+ type: 'bool'),
new _TestOptionSpecification('host_checked',
'Run compiler in checked mode', ['--host-checked'], [], false,
type: 'bool'),
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index b93294b..14910fa 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -255,6 +255,7 @@
'compiler',
'runtime',
'checked',
+ 'strong',
'host_checked',
'minified',
'csp',
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 2c4b541..abdde58 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -377,25 +377,27 @@
String createOutputDirectory(Path testPath, String optionsName) {
var checked = configuration['checked'] ? '-checked' : '';
+ var strong = configuration['strong'] ? '-strong' : '';
var minified = configuration['minified'] ? '-minified' : '';
var sdk = configuration['use_sdk'] ? '-sdk' : '';
var packages =
configuration['use_public_packages'] ? '-public_packages' : '';
var dirName = "${configuration['compiler']}-${configuration['runtime']}"
- "$checked$minified$packages$sdk";
+ "$checked$strong$minified$packages$sdk";
return createGeneratedTestDirectoryHelper(
"tests", dirName, testPath, optionsName);
}
String createCompilationOutputDirectory(Path testPath) {
var checked = configuration['checked'] ? '-checked' : '';
+ var strong = configuration['strong'] ? '-strong' : '';
var minified = configuration['minified'] ? '-minified' : '';
var csp = configuration['csp'] ? '-csp' : '';
var sdk = configuration['use_sdk'] ? '-sdk' : '';
var packages =
configuration['use_public_packages'] ? '-public_packages' : '';
var dirName = "${configuration['compiler']}"
- "$checked$minified$csp$packages$sdk";
+ "$checked$strong$minified$csp$packages$sdk";
return createGeneratedTestDirectoryHelper(
"compilations", dirName, testPath, "");
}
@@ -2211,13 +2213,14 @@
configuration['compiler'] == 'dart2appjit' ||
configuration['compiler'] == 'precompiler') {
var checked = configuration['checked'] ? '-checked' : '';
+ var strong = configuration['strong'] ? '-strong' : '';
var minified = configuration['minified'] ? '-minified' : '';
var csp = configuration['csp'] ? '-csp' : '';
var sdk = configuration['use_sdk'] ? '-sdk' : '';
var packages =
configuration['use_public_packages'] ? '-public_packages' : '';
var dirName = "${configuration['compiler']}"
- "$checked$minified$csp$packages$sdk";
+ "$checked$strong$minified$csp$packages$sdk";
String generatedPath = "${TestUtils.buildDir(configuration)}"
"/generated_compilations/$dirName";
TestUtils.deleteDirectory(generatedPath);