Version 1.16.0-dev.2.0
Merge commit '3b2a695d71057f3a538f79f48a96f6bdca2474bb' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 863e8d6..10c8136 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,15 @@
for (int n in <String>["a", "b"]) { ... }
```
+### Tool Changes
+
+* Pub
+ * `pub serve` now provides caching headers that should improve the performance
+ of requesting large files multiple times.
+
+ * Both `pub get` and `pub upgrade` now have a `--no-precompile` flag that
+ disables precompilation of executables and transformed dependencies.
+
## 1.15.0 - 2016-03-09
### Core library changes
diff --git a/DEPS b/DEPS
index 9ed1e3a..8e35a96 100644
--- a/DEPS
+++ b/DEPS
@@ -21,14 +21,18 @@
"github_mirror":
"https://chromium.googlesource.com/external/github.com/dart-lang/%s.git",
+ # Only use this temporarily while waiting for a mirror for a new package.
+ "github_dartlang": "https://github.com/dart-lang/%s.git",
+
"gyp_rev": "@6ee91ad8659871916f9aa840d42e1513befdf638",
"co19_rev": "@3ed795ea02e022ef19c77cf1b6095b7c8f5584d0",
"chromium_git": "https://chromium.googlesource.com",
# Revisions of /third_party/* dependencies.
- "args_tag": "@0.13.0",
- "async_tag": "@1.4.0",
+ "args_tag": "@0.13.4",
+ "async_tag": "@1.9.0",
"barback_tag" : "@0.15.2+7",
+ "boolean_selector_tag" : "@1.0.0",
"boringssl_rev" : "@daeafc22c66ad48f6b32fc8d3362eb9ba31b774e",
"charcode_tag": "@1.1.0",
"chrome_rev" : "@19997",
@@ -41,7 +45,7 @@
"dartdoc_tag" : "@v0.9.0",
"dart_services_rev" : "@7aea2574e6f3924bf409a80afb8ad52aa2be4f97",
"dart_style_tag": "@0.2.4",
- "dev_compiler_rev": "@0.1.9",
+ "dev_compiler_rev": "@0c5dd2d1e999c421d978a478e267aac6279e087a",
"glob_rev": "@704cf75e4f26b417505c5c611bdaacd8808467dd",
"html_tag" : "@0.12.1+1",
"http_tag" : "@0.11.3+3",
@@ -51,7 +55,7 @@
"idl_parser_rev": "@7fbe68cab90c38147dee4f48c30ad0d496c17915",
"intl_rev": "@a8b480b9c436f6c0ec16730804c914bdb4e30d53",
"jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
- "json_rpc_2_tag": "@1.1.1",
+ "json_rpc_2_tag": "@2.0.0",
"linter_rev": "@a60289545b34ab1f047a0a3f0673a4c5abde0eaf",
"logging_rev": "@85d83e002670545e9039ad3985f0018ab640e597",
"markdown_rev": "@4aaadf3d940bb172e1f6285af4d2b1710d309982",
@@ -67,31 +71,34 @@
"ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
"plugin_tag": "@0.1.0",
"pool_tag": "@1.2.1",
- "pub_rev": "@bd5c77abcb609d95340632b96344b59035e70376",
+ "pub_rev": "@c1405b945c6d818c8cfe78334e8d4b11fd913103",
"pub_cache_tag": "@v0.1.0",
"pub_semver_tag": "@1.2.1",
"quiver_tag": "@0.21.4",
"resource_rev":"@a49101ba2deb29c728acba6fb86000a8f730f4b1",
"root_certificates_rev": "@c3a41df63afacec62fcb8135196177e35fe72f71",
- "scheduled_test_tag": "@0.12.4+2",
- "shelf_tag": "@0.6.4+3",
+ "scheduled_test_tag": "@0.12.5+2",
+ "shelf_tag": "@0.6.5",
"smoke_rev" : "@f3361191cc2a85ebc1e4d4c33aec672d7915aba9",
"source_maps_tag": "@0.10.1",
"shelf_static_tag": "@0.2.3+1",
- "shelf_web_socket_tag": "@0.0.1+4",
+ "shelf_web_socket_tag": "@0.2.0",
"source_map_stack_trace_tag": "@1.0.4",
"source_span_tag": "@1.2.0",
"stack_trace_tag": "@1.4.2",
+ "stream_channel_tag": "@1.3.1",
"string_scanner_tag": "@0.1.4",
"sunflower_rev": "@879b704933413414679396b129f5dfa96f7a0b1e",
- "test_tag": "@0.12.6+1",
+ "test_tag": "@0.12.12",
"test_reflective_loader_tag": "@0.0.3",
+ "typed_data_tag": "@1.1.2",
"utf_rev": "@1f55027068759e2d52f2c12de6a57cce5f3c5ee6",
"usage_rev": "@b5080dac0d26a5609b266f8fdb0d053bc4c1c638",
"watcher_tag": "@0.9.7",
"when_tag": "@0.2.0+2",
"which_tag": "@0.1.3+1",
"web_components_rev": "@0e636b534d9b12c9e96f841e6679398e91a986ec",
+ "web_socket_channel_tag": "@1.0.0",
"WebCore_rev": "@a86fe28efadcfc781f836037a80f27e22a5dad17",
"yaml_tag": "@2.1.5",
"zlib_rev": "@c3d0a6190f2f8c924a05ab6cc97b8f975bddd33f",
@@ -142,6 +149,9 @@
(Var("github_mirror") % "async") + Var("async_tag"),
Var("dart_root") + "/third_party/pkg/barback":
(Var("github_mirror") % "barback") + Var("barback_tag"),
+ Var("dart_root") + "/third_party/pkg/boolean_selector":
+ (Var("github_dartlang") % "boolean_selector") +
+ Var("boolean_selector_tag"),
Var("dart_root") + "/third_party/pkg/charcode":
(Var("github_mirror") % "charcode") + Var("charcode_tag"),
Var("dart_root") + "/third_party/pkg/cli_util":
@@ -247,6 +257,9 @@
Var("source_map_stack_trace_tag"),
Var("dart_root") + "/third_party/pkg/stack_trace":
(Var("github_mirror") % "stack_trace") + Var("stack_trace_tag"),
+ Var("dart_root") + "/third_party/pkg/stream_channel":
+ (Var("github_dartlang") % "stream_channel") +
+ Var("stream_channel_tag"),
Var("dart_root") + "/third_party/pkg/string_scanner":
(Var("github_mirror") % "string_scanner") +
Var("string_scanner_tag"),
@@ -258,6 +271,8 @@
Var("dart_root") + "/third_party/pkg/test_reflective_loader":
(Var("github_mirror") % "test_reflective_loader") +
Var("test_reflective_loader_tag"),
+ Var("dart_root") + "/third_party/pkg/typed_data":
+ (Var("github_dartlang") % "typed_data") + Var("typed_data_tag"),
Var("dart_root") + "/third_party/pkg/usage":
(Var("github_mirror") % "usage") + Var("usage_rev"),
Var("dart_root") + "/third_party/pkg/utf":
@@ -267,6 +282,9 @@
Var("dart_root") + "/third_party/pkg/web_components":
(Var("github_mirror") % "web-components") +
Var("web_components_rev"),
+ Var("dart_root") + "/third_party/pkg/web_socket_channel":
+ (Var("github_dartlang") % "web_socket_channel") +
+ Var("web_socket_channel_tag"),
Var("dart_root") + "/third_party/pkg/when":
(Var("github_mirror") % "when") + Var("when_tag"),
Var("dart_root") + "/third_party/pkg/which":
diff --git a/create_sdk.gyp b/create_sdk.gyp
index b13adda..83ddc47 100644
--- a/create_sdk.gyp
+++ b/create_sdk.gyp
@@ -15,6 +15,7 @@
'utils/dartdoc/dartdoc.gyp:dartdoc',
'utils/analysis_server/analysis_server.gyp:analysis_server',
'utils/dartanalyzer/dartanalyzer.gyp:dartanalyzer',
+ 'utils/dartdevc/dartdevc.gyp:dartdevc',
],
'actions': [
{
@@ -38,6 +39,7 @@
'<(SHARED_INTERMEDIATE_DIR)/utils_wrapper.dart.snapshot',
'<(SHARED_INTERMEDIATE_DIR)/pub.dart.snapshot',
'<(SHARED_INTERMEDIATE_DIR)/dartanalyzer.dart.snapshot',
+ '<(SHARED_INTERMEDIATE_DIR)/dartdevc.dart.snapshot',
'<(SHARED_INTERMEDIATE_DIR)/dartfmt.dart.snapshot',
'<(SHARED_INTERMEDIATE_DIR)/analysis_server.dart.snapshot',
'<(SHARED_INTERMEDIATE_DIR)/dartdoc.dart.snapshot',
diff --git a/dart.gyp b/dart.gyp
index 9ac4105..b8d3e43f 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -12,6 +12,7 @@
'create_sdk',
'dart2js',
'dartanalyzer',
+ 'dartdevc',
'packages',
'runtime',
'samples',
@@ -58,6 +59,13 @@
],
},
{
+ 'target_name': 'dartdevc',
+ 'type': 'none',
+ 'dependencies': [
+ 'utils/dartdevc/dartdevc.gyp:dartdevc',
+ ],
+ },
+ {
'target_name': 'dartfmt',
'type': 'none',
'dependencies': [
diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart
index 19ae943..33b5941 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -10,6 +10,7 @@
import 'package:analysis_server/src/utilities/documentation.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
/**
@@ -76,10 +77,26 @@
// parameter
hover.parameter = _safeToString(expression.bestParameterElement);
// types
- if (element == null || element is VariableElement) {
- hover.staticType = _safeToString(expression.staticType);
+ {
+ AstNode parent = expression.parent;
+ DartType staticType = null;
+ DartType propagatedType = expression.propagatedType;
+ if (element == null || element is VariableElement) {
+ staticType = expression.staticType;
+ }
+ if (parent is MethodInvocation && parent.methodName == expression) {
+ staticType = parent.staticInvokeType;
+ propagatedType = parent.propagatedInvokeType;
+ if (staticType != null && staticType.isDynamic) {
+ staticType = null;
+ }
+ if (propagatedType != null && propagatedType.isDynamic) {
+ propagatedType = null;
+ }
+ }
+ hover.staticType = _safeToString(staticType);
+ hover.propagatedType = _safeToString(propagatedType);
}
- hover.propagatedType = _safeToString(expression.propagatedType);
// done
return hover;
}
diff --git a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
index e978eb4..7a7a870 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
@@ -127,21 +127,21 @@
}
computer._addRegionForNode(node.constructorName, element);
// arguments
- _safelyVisit(node.arguments);
+ node.arguments?.accept(this);
}
@override
visitAssignmentExpression(AssignmentExpression node) {
- _safelyVisit(node.leftHandSide);
+ node.leftHandSide?.accept(this);
computer._addRegionForToken(node.operator, node.bestElement);
- _safelyVisit(node.rightHandSide);
+ node.rightHandSide?.accept(this);
}
@override
visitBinaryExpression(BinaryExpression node) {
- _safelyVisit(node.leftOperand);
+ node.leftOperand?.accept(this);
computer._addRegionForToken(node.operator, node.bestElement);
- _safelyVisit(node.rightOperand);
+ node.rightOperand?.accept(this);
}
@override
@@ -255,7 +255,7 @@
computer._addRegionForToken(node.thisKeyword, element);
computer._addRegionForNode(node.constructorName, element);
// process arguments
- _safelyVisit(node.argumentList);
+ node.argumentList?.accept(this);
}
@override
@@ -277,7 +277,7 @@
computer._addRegionForToken(node.superKeyword, element);
computer._addRegionForNode(node.constructorName, element);
// process arguments
- _safelyVisit(node.argumentList);
+ node.argumentList?.accept(this);
}
void _addConstructorName(AstNode parent, ConstructorName node) {
@@ -324,10 +324,4 @@
}
}
}
-
- void _safelyVisit(AstNode node) {
- if (node != null) {
- node.accept(this);
- }
- }
}
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 7db68b6..c053754 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -375,6 +375,22 @@
_initIncrementalLogger(results[INCREMENTAL_RESOLUTION_LOG]);
+ //
+ // Process all of the plugins so that extensions are registered.
+ //
+ ServerPlugin serverPlugin = new ServerPlugin();
+ List<Plugin> plugins = <Plugin>[];
+ plugins.addAll(AnalysisEngine.instance.requiredPlugins);
+ plugins.add(AnalysisEngine.instance.commandLinePlugin);
+ plugins.add(AnalysisEngine.instance.optionsPlugin);
+ plugins.add(serverPlugin);
+ plugins.add(linterPlugin);
+ plugins.add(linterServerPlugin);
+ plugins.add(dartCompletionPlugin);
+ plugins.addAll(_userDefinedPlugins);
+ ExtensionManager manager = new ExtensionManager();
+ manager.processPlugins(plugins);
+
JavaFile defaultSdkDirectory;
if (results[SDK_OPTION] != null) {
defaultSdkDirectory = new JavaFile(results[SDK_OPTION]);
@@ -383,8 +399,12 @@
// Use DirectoryBasedDartSdk.defaultSdkDirectory, which will make a guess.
defaultSdkDirectory = DirectoryBasedDartSdk.defaultSdkDirectory;
}
- SdkCreator defaultSdkCreator =
- () => new DirectoryBasedDartSdk(defaultSdkDirectory);
+ SdkCreator defaultSdkCreator = () {
+ DirectoryBasedDartSdk sdk =
+ new DirectoryBasedDartSdk(defaultSdkDirectory);
+ sdk.useSummary = true;
+ return sdk;
+ };
// TODO(brianwilkerson) It would be nice to avoid creating an SDK that
// cannot be re-used, but the SDK is needed to create a package map provider
// in the case where we need to run `pub` in order to get the package map.
@@ -408,22 +428,6 @@
results[CLIENT_VERSION], AnalysisServer.VERSION, defaultSdk.sdkVersion);
AnalysisEngine.instance.instrumentationService = service;
//
- // Process all of the plugins so that extensions are registered.
- //
- ServerPlugin serverPlugin = new ServerPlugin();
- List<Plugin> plugins = <Plugin>[];
- plugins.addAll(AnalysisEngine.instance.requiredPlugins);
- plugins.add(AnalysisEngine.instance.commandLinePlugin);
- plugins.add(AnalysisEngine.instance.optionsPlugin);
- plugins.add(serverPlugin);
- plugins.add(linterPlugin);
- plugins.add(linterServerPlugin);
- plugins.add(dartCompletionPlugin);
- plugins.addAll(_userDefinedPlugins);
-
- ExtensionManager manager = new ExtensionManager();
- manager.processPlugins(plugins);
- //
// Create the sockets and start listening for requests.
//
socketServer = new SocketServer(
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
index 6071fae..1a1352f 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
@@ -79,6 +79,44 @@
}
/**
+ * Determine if the completion target is in the middle or beginning of the list
+ * of named parameters and is not preceded by a comma. This method assumes that
+ * _isAppendingToArgList has been called and is false.
+ */
+bool _isInsertingToArgListWithNoSynthetic(DartCompletionRequest request) {
+ AstNode node = request.target.containingNode;
+ if (node is ArgumentList) {
+ var entity = request.target.entity;
+ return entity is NamedExpression;
+ }
+ return false;
+}
+
+/**
+ * Determine if the completion target is in the middle or beginning of the list
+ * of named parameters and is preceded by a comma. This method assumes that
+ * _isAppendingToArgList and _isInsertingToArgListWithNoSynthetic have been
+ * called and both return false.
+ */
+bool _isInsertingToArgListWithSynthetic(DartCompletionRequest request) {
+ AstNode node = request.target.containingNode;
+ if (node is ArgumentList) {
+ var entity = request.target.entity;
+ if (entity is SimpleIdentifier) {
+ int argIndex = request.target.argIndex;
+ // if the next argument is a NamedExpression, then we are in the named
+ // parameter list, guard first against end of list
+ if (node.arguments.length == argIndex + 1 ||
+ node.arguments.getRange(argIndex + 1, argIndex + 2).first
+ is NamedExpression) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/**
* Determine if the completion target is the label for a named argument.
*/
bool _isEditingNamedArgLabel(DartCompletionRequest request) {
@@ -87,7 +125,7 @@
var entity = request.target.entity;
if (entity is NamedExpression) {
int offset = request.offset;
- if (entity.offset <= offset && offset < entity.end) {
+ if (entity.offset < offset && offset < entity.end) {
return true;
}
}
@@ -219,23 +257,29 @@
// suggestions.add(suggestion);
}
- void _addDefaultParamSuggestions(Iterable<ParameterElement> parameters) {
+ void _addDefaultParamSuggestions(Iterable<ParameterElement> parameters,
+ [bool appendComma = false]) {
Iterable<String> namedArgs = _namedArgs(request);
for (ParameterElement param in parameters) {
if (param.parameterKind == ParameterKind.NAMED) {
- _addNamedParameterSuggestion(request, namedArgs, param.name);
+ _addNamedParameterSuggestion(
+ request, namedArgs, param.name, appendComma);
}
}
}
- void _addNamedParameterSuggestion(
- DartCompletionRequest request, List<String> namedArgs, String name) {
+ void _addNamedParameterSuggestion(DartCompletionRequest request,
+ List<String> namedArgs, String name, bool appendComma) {
if (name != null && name.length > 0 && !namedArgs.contains(name)) {
+ String completion = '$name: ';
+ if (appendComma) {
+ completion += ',';
+ }
suggestions.add(new CompletionSuggestion(
CompletionSuggestionKind.NAMED_ARGUMENT,
DART_RELEVANCE_NAMED_PARAMETER,
- '$name: ',
- name.length + 2,
+ completion,
+ completion.length,
0,
false,
false));
@@ -253,10 +297,19 @@
_addArgListSuggestion(requiredParam);
return;
}
+ // TODO (jwren) _isAppendingToArgList can be split into two cases (with and
+ // without preceded), then _isAppendingToArgList,
+ // _isInsertingToArgListWithNoSynthetic and
+ // _isInsertingToArgListWithSynthetic could be formatted into a single
+ // method which returns some enum with 5+ cases.
if (_isEditingNamedArgLabel(request) || _isAppendingToArgList(request)) {
if (requiredCount == 0 || requiredCount < _argCount(request)) {
_addDefaultParamSuggestions(parameters);
}
+ } else if (_isInsertingToArgListWithNoSynthetic(request)) {
+ _addDefaultParamSuggestions(parameters, true);
+ } else if (_isInsertingToArgListWithSynthetic(request)) {
+ _addDefaultParamSuggestions(parameters);
}
}
}
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 dbf0da7..6c3a1e6 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -1494,6 +1494,10 @@
String libraryUri = sdkLibrary.shortName;
Source librarySource =
sdkSourceFactory.resolveUri(unitSource, libraryUri);
+ // maybe already imported
+ if (alreadyImportedWithPrefix.contains(librarySource)) {
+ continue;
+ }
// prepare LibraryElement
LibraryElement libraryElement =
context.getResult(librarySource, LIBRARY_ELEMENT1);
@@ -1523,7 +1527,7 @@
if (librarySource.isInSystemLibrary) {
continue;
}
- // maybe already imported with a prefix
+ // maybe already imported
if (alreadyImportedWithPrefix.contains(librarySource)) {
continue;
}
diff --git a/pkg/analysis_server/lib/src/status/get_handler.dart b/pkg/analysis_server/lib/src/status/get_handler.dart
index c466669..47cbcbd 100644
--- a/pkg/analysis_server/lib/src/status/get_handler.dart
+++ b/pkg/analysis_server/lib/src/status/get_handler.dart
@@ -1289,6 +1289,36 @@
buffer.write('</table></p>');
}
}
+ void writeOptions(StringBuffer buffer, AnalysisOptionsImpl options) {
+ if (options == null) {
+ buffer.write('<p>No option information available.</p>');
+ return;
+ }
+ buffer.write('<p>');
+ _writeOption(
+ buffer, 'Analyze functon bodies', options.analyzeFunctionBodies);
+ _writeOption(buffer, 'Cache size', options.cacheSize);
+ _writeOption(buffer, 'Enable async support', options.enableAsync);
+ _writeOption(
+ buffer, 'Enable generic methods', options.enableGenericMethods);
+ _writeOption(
+ buffer, 'Enable strict call checks', options.enableStrictCallChecks);
+ _writeOption(buffer, 'Enable super mixins', options.enableSuperMixins);
+ _writeOption(buffer, 'Generate dart2js hints', options.dart2jsHint);
+ _writeOption(buffer, 'Generate errors in implicit files',
+ options.generateImplicitErrors);
+ _writeOption(
+ buffer, 'Generate errors in SDK files', options.generateSdkErrors);
+ _writeOption(buffer, 'Generate hints', options.hint);
+ _writeOption(buffer, 'Incremental resolution', options.incremental);
+ _writeOption(buffer, 'Incremental resolution with API changes',
+ options.incrementalApi);
+ _writeOption(buffer, 'Preserve comments', options.preserveComments);
+ _writeOption(buffer, 'Strong mode', options.strongMode);
+ _writeOption(buffer, 'Strong mode hints', options.strongModeHints,
+ last: true);
+ buffer.write('</p>');
+ }
_writeResponse(request, (StringBuffer buffer) {
_writePage(
@@ -1296,53 +1326,37 @@
(StringBuffer buffer) {
buffer.write('<h3>Configuration</h3>');
- _writeTwoColumns(buffer, (StringBuffer buffer) {
- AnalysisOptionsImpl options = context.analysisOptions;
- buffer.write('<p><b>Options</b></p>');
- buffer.write('<p>');
- _writeOption(
- buffer, 'Analyze functon bodies', options.analyzeFunctionBodies);
- _writeOption(buffer, 'Cache size', options.cacheSize);
- _writeOption(buffer, 'Enable async support', options.enableAsync);
- _writeOption(
- buffer, 'Enable generic methods', options.enableGenericMethods);
- _writeOption(buffer, 'Enable strict call checks',
- options.enableStrictCallChecks);
- _writeOption(
- buffer, 'Enable super mixins', options.enableSuperMixins);
- _writeOption(buffer, 'Generate dart2js hints', options.dart2jsHint);
- _writeOption(buffer, 'Generate errors in implicit files',
- options.generateImplicitErrors);
- _writeOption(buffer, 'Generate errors in SDK files',
- options.generateSdkErrors);
- _writeOption(buffer, 'Generate hints', options.hint);
- _writeOption(buffer, 'Incremental resolution', options.incremental);
- _writeOption(buffer, 'Incremental resolution with API changes',
- options.incrementalApi);
- _writeOption(buffer, 'Preserve comments', options.preserveComments);
- _writeOption(buffer, 'Strong mode', options.strongMode);
- _writeOption(buffer, 'Strong mode hints', options.strongModeHints,
- last: true);
- buffer.write('</p>');
- }, (StringBuffer buffer) {
- List<Linter> lints =
- context.getConfigurationData(CONFIGURED_LINTS_KEY);
- buffer.write('<p><b>Lints</b></p>');
- if (lints.isEmpty) {
- buffer.write('<p>none</p>');
- } else {
- for (Linter lint in lints) {
- buffer.write('<p>');
- buffer.write(lint.runtimeType);
- buffer.write('</p>');
+ _writeColumns(buffer, <HtmlGenerator>[
+ (StringBuffer buffer) {
+ buffer.write('<p><b>Context Options</b></p>');
+ writeOptions(buffer, context.analysisOptions);
+ },
+ (StringBuffer buffer) {
+ buffer.write('<p><b>SDK Context Options</b></p>');
+ writeOptions(buffer,
+ context?.sourceFactory?.dartSdk?.context?.analysisOptions);
+ },
+ (StringBuffer buffer) {
+ List<Linter> lints =
+ context.getConfigurationData(CONFIGURED_LINTS_KEY);
+ buffer.write('<p><b>Lints</b></p>');
+ if (lints.isEmpty) {
+ buffer.write('<p>none</p>');
+ } else {
+ for (Linter lint in lints) {
+ buffer.write('<p>');
+ buffer.write(lint.runtimeType);
+ buffer.write('</p>');
+ }
}
- }
- List<ErrorProcessor> errorProcessors =
- context.getConfigurationData(CONFIGURED_ERROR_PROCESSORS);
- int processorCount = errorProcessors?.length ?? 0;
- buffer.write('<p><b>Error Processor count</b>: $processorCount</p>');
- });
+ List<ErrorProcessor> errorProcessors =
+ context.getConfigurationData(CONFIGURED_ERROR_PROCESSORS);
+ int processorCount = errorProcessors?.length ?? 0;
+ buffer
+ .write('<p><b>Error Processor count</b>: $processorCount</p>');
+ }
+ ]);
SourceFactory sourceFactory = context.sourceFactory;
if (sourceFactory is SourceFactoryImpl) {
@@ -1666,6 +1680,23 @@
}
/**
+ * Write multiple columns of information to the given [buffer], where the list
+ * of [columns] functions are used to generate the content of those columns.
+ */
+ void _writeColumns(StringBuffer buffer, List<HtmlGenerator> columns) {
+ buffer
+ .write('<table class="column"><tr class="column"><td class="column">');
+ int count = columns.length;
+ for (int i = 0; i < count; i++) {
+ if (i > 0) {
+ buffer.write('</td><td class="column">');
+ }
+ columns[i](buffer);
+ }
+ buffer.write('</td></tr></table>');
+ }
+
+ /**
* Write performance information about a specific completion request
* to the given [buffer] object.
*/
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index 672e9f2..9d5436b 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -259,7 +259,7 @@
expect(hover.elementDescription, 'mmm(int a, String b) → List<String>');
expect(hover.elementKind, 'method');
// types
- expect(hover.staticType, isNull);
+ expect(hover.staticType, '(int, String) → List<String>');
expect(hover.propagatedType, isNull);
// no parameter
expect(hover.parameter, isNull);
diff --git a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
index 076ae9d..7ed2989 100644
--- a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
@@ -173,13 +173,14 @@
isLocal: true,
docRegexp: 'Documentation for func',
parameterRegexps: ['.*']));
- tests.add(checkHover('add(', 3, ['List', 'add'], 'method', null,
+ tests.add(checkHover(
+ 'add(', 3, ['List', 'add'], 'method', ['dynamic', 'void'],
isCore: true, docRegexp: '.*'));
tests.add(checkHover(
'localVar)', 8, ['num', 'localVar'], 'local variable', ['num'],
isLocal: true, parameterRegexps: ['.*'], propagatedType: 'int'));
tests.add(checkHover(
- 'func(35', 4, ['func', 'int', 'param'], 'function', null,
+ 'func(35', 4, ['func', 'int', 'param'], 'function', ['int', 'void'],
docRegexp: 'Documentation for func'));
tests.add(checkHover('35', 2, null, null, ['int'],
isLiteral: true, parameterRegexps: ['int', 'param']));
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index 0a14ef1..e7f4fea 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -79,6 +79,20 @@
/**
* Assert that the specified suggestions are the only suggestions.
*/
+ void assertSuggestions(List<String> suggestions) {
+ List<CompletionSuggestion> expected = new List<CompletionSuggestion>();
+ for (String suggestion in suggestions) {
+ expected.add(assertSuggest('$suggestion',
+ csKind: CompletionSuggestionKind.NAMED_ARGUMENT,
+ relevance: DART_RELEVANCE_NAMED_PARAMETER));
+ }
+ assertNoOtherSuggestions(expected);
+ }
+
+ /**
+ * Assert that the specified named argument suggestions are the only
+ * suggestions.
+ */
void assertSuggestArguments({List<String> namedArguments}) {
List<CompletionSuggestion> expected = new List<CompletionSuggestion>();
for (String name in namedArguments) {
@@ -94,19 +108,108 @@
return new ArgListContributor();
}
+ test_Annotation_local_constructor_named_param_negative() async {
+ addTestSource('''
+class A { const A(int one, int two, int three, {int four, String five:
+ 'defaultValue'}); }
+@A(1, ^, 3) main() { }''');
+ await computeSuggestions();
+ assertNoSuggestions();
+ }
+
test_Annotation_local_constructor_named_param() async {
addTestSource('''
-class A { A({int one, String two: 'defaultValue'}) { } }
+class A { const A({int one, String two: 'defaultValue'}); }
@A(^) main() { }''');
await computeSuggestions();
assertSuggestArguments(namedArguments: ['one', 'two']);
}
+ test_Annotation_local_constructor_named_param_2() async {
+ addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(^ two: '2') main() { }''');
+ await computeSuggestions();
+ assertSuggestions(['one: ,']);
+ }
+
+ test_Annotation_local_constructor_named_param_3() async {
+ addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(^two: '2') main() { }''');
+ await computeSuggestions();
+ assertSuggestions(['one: ,']);
+ }
+
+ test_Annotation_local_constructor_named_param_4() async {
+ addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(^, two: '2') main() { }''');
+ await computeSuggestions();
+ assertSuggestArguments(namedArguments: ['one']);
+ }
+
+ test_Annotation_local_constructor_named_param_5() async {
+ addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(^ , two: '2') main() { }''');
+ await computeSuggestions();
+ assertSuggestArguments(namedArguments: ['one']);
+ }
+
+ test_Annotation_local_constructor_named_param_6() async {
+ addTestSource('''
+class A { const A(int zero, {int one, String two: 'defaultValue'}); }
+@A(0, ^, two: '2') main() { }''');
+ await computeSuggestions();
+ assertSuggestArguments(namedArguments: ['one']);
+ }
+
+ test_Annotation_local_constructor_named_param_7() async {
+ addTestSource('''
+class A { const A(int zero, {int one, String two: 'defaultValue'}); }
+@A(0, ^ two: '2') main() { }''');
+ await computeSuggestions();
+ assertSuggestions(['one: ,']);
+ }
+
+ test_Annotation_local_constructor_named_param_8() async {
+ addTestSource('''
+class A { const A(int zero, {int one, String two: 'defaultValue'}); }
+@A(0, ^two: '2') main() { }''');
+ await computeSuggestions();
+ assertSuggestions(['one: ,']);
+ }
+
+ fail_test_Annotation_local_constructor_named_param_9() async {
+ addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(two: '2'^) main() { }''');
+ await computeSuggestions();
+ assertSuggestions([', one: ']);
+ }
+
+ fail_test_Annotation_local_constructor_named_param_10() async {
+ addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(two: '2' ^) main() { }''');
+ await computeSuggestions();
+ assertSuggestions([', one: ']);
+ }
+
+ test_Annotation_local_constructor_named_param_11() async {
+ addTestSource('''
+class A { const A({int one, String two: 'defaultValue'}); }
+@A(two: '2', ^) main() { }''');
+ await computeSuggestions();
+ assertSuggestArguments(namedArguments: ['one']);
+ }
+
test_Annotation_imported_constructor_named_param() async {
addSource(
'/libA.dart',
'''
-library libA; class A { A({int one, String two: 'defaultValue'}) { } }''');
+library libA; class A { const A({int one, String two: 'defaultValue'}); }''');
addTestSource('import "/libA.dart"; @A(^) main() { }');
await computeSuggestions();
assertSuggestArguments(namedArguments: ['one', 'two']);
@@ -120,7 +223,7 @@
test_ArgumentList_imported_constructor_named_param() async {
//
- addSource('/libA.dart', 'library libA; class A{A({int one}){}}');
+ addSource('/libA.dart', 'library libA; class A{A({int one}); }');
addTestSource('import "/libA.dart"; main() { new A(^);}');
await computeSuggestions();
assertSuggestArguments(namedArguments: ['one']);
@@ -128,7 +231,7 @@
test_ArgumentList_imported_constructor_named_param2() async {
//
- addSource('/libA.dart', 'library libA; class A{A.foo({int one}){}}');
+ addSource('/libA.dart', 'library libA; class A{A.foo({int one}); }');
addTestSource('import "/libA.dart"; main() { new A.foo(^);}');
await computeSuggestions();
assertSuggestArguments(namedArguments: ['one']);
@@ -317,7 +420,7 @@
//
addTestSource('main() { int.parse("16", ^r: 16);}');
await computeSuggestions();
- assertSuggestArguments(namedArguments: ['radix', 'onError']);
+ assertSuggestions(['radix: ,', 'onError: ,']);
}
test_ArgumentList_imported_function_named_param_label3() async {
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index b059279..d793539 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -3460,7 +3460,35 @@
''');
}
- test_importLibraryShow() async {
+ test_importLibraryShow_project() async {
+ testFile = '/project/bin/test.dart';
+ addSource(
+ '/project/bin/lib.dart',
+ '''
+class A {}
+class B {}
+''');
+ resolveTestUnit('''
+import 'lib.dart' show A;
+main() {
+ A a;
+ B b;
+}
+''');
+ performAllAnalysisTasks();
+ await assertNoFix(DartFixKind.IMPORT_LIBRARY_PROJECT);
+ await assertHasFix(
+ DartFixKind.IMPORT_LIBRARY_SHOW,
+ '''
+import 'lib.dart' show A, B;
+main() {
+ A a;
+ B b;
+}
+''');
+ }
+
+ test_importLibraryShow_sdk() async {
resolveTestUnit('''
import 'dart:async' show Stream;
main() {
@@ -3468,6 +3496,7 @@
Future f = null;
}
''');
+ await assertNoFix(DartFixKind.IMPORT_LIBRARY_SDK);
await assertHasFix(
DartFixKind.IMPORT_LIBRARY_SHOW,
'''
diff --git a/pkg/analysis_server/test/services/correction/sort_members_test.dart b/pkg/analysis_server/test/services/correction/sort_members_test.dart
index b32f502..bcc9c0c 100644
--- a/pkg/analysis_server/test/services/correction/sort_members_test.dart
+++ b/pkg/analysis_server/test/services/correction/sort_members_test.dart
@@ -83,6 +83,22 @@
''');
}
+ void test_classMembers_external_constructorMethod() {
+ _parseTestUnit(r'''
+class Chart {
+ external Pie();
+ external Chart();
+}
+''');
+ // validate change
+ _assertSort(r'''
+class Chart {
+ external Chart();
+ external Pie();
+}
+''');
+ }
+
void test_classMembers_field() {
_parseTestUnit(r'''
class A {
diff --git a/pkg/analyzer/lib/context/declared_variables.dart b/pkg/analyzer/lib/context/declared_variables.dart
new file mode 100644
index 0000000..9a0322c
--- /dev/null
+++ b/pkg/analyzer/lib/context/declared_variables.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.context.declared_variables;
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/constant/value.dart';
+import 'package:analyzer/src/dart/constant/value.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+
+/**
+ * An object used to provide access to the values of variables that have been
+ * defined on the command line using the `-D` option.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class DeclaredVariables {
+ /**
+ * A table mapping the names of declared variables to their values.
+ */
+ HashMap<String, String> _declaredVariables = new HashMap<String, String>();
+
+ /**
+ * Define a variable with the given [name] to have the given [value].
+ */
+ void define(String name, String value) {
+ _declaredVariables[name] = value;
+ }
+
+ /**
+ * Return the value of the variable with the given [name] interpreted as a
+ * 'boolean' value. If the variable is not defined (or [name] is `null`), a
+ * DartObject representing "unknown" is returned. If the value cannot be
+ * parsed as a boolean, a DartObject representing 'null' is returned. The
+ * [typeProvider] is the type provider used to find the type 'bool'.
+ */
+ DartObject getBool(TypeProvider typeProvider, String name) {
+ String value = _declaredVariables[name];
+ if (value == null) {
+ return new DartObjectImpl(typeProvider.boolType, BoolState.UNKNOWN_VALUE);
+ }
+ if (value == "true") {
+ return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE);
+ } else if (value == "false") {
+ return new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE);
+ }
+ return new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE);
+ }
+
+ /**
+ * Return the value of the variable with the given [name] interpreted as an
+ * integer value. If the variable is not defined (or [name] is `null`), a
+ * DartObject representing "unknown" is returned. If the value cannot be
+ * parsed as an integer, a DartObject representing 'null' is returned.
+ */
+ DartObject getInt(TypeProvider typeProvider, String name) {
+ String value = _declaredVariables[name];
+ if (value == null) {
+ return new DartObjectImpl(typeProvider.intType, IntState.UNKNOWN_VALUE);
+ }
+ int bigInteger;
+ try {
+ bigInteger = int.parse(value);
+ } on FormatException {
+ return new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE);
+ }
+ return new DartObjectImpl(typeProvider.intType, new IntState(bigInteger));
+ }
+
+ /**
+ * Return the value of the variable with the given [name] interpreted as a
+ * String value, or `null` if the variable is not defined. Return the value of
+ * the variable with the given name interpreted as a String value. If the
+ * variable is not defined (or [name] is `null`), a DartObject representing
+ * "unknown" is returned. The [typeProvider] is the type provider used to find
+ * the type 'String'.
+ */
+ DartObject getString(TypeProvider typeProvider, String name) {
+ String value = _declaredVariables[name];
+ if (value == null) {
+ return new DartObjectImpl(
+ typeProvider.stringType, StringState.UNKNOWN_VALUE);
+ }
+ return new DartObjectImpl(typeProvider.stringType, new StringState(value));
+ }
+}
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index d0680c4..e53a204 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -536,7 +536,7 @@
* (either AST nodes or tokens) that make up the contents of this node,
* including doc comments but excluding other comments.
*/
- Iterable/*<AstNode | Token>*/ get childEntities;
+ Iterable /* AstNode | Token */ get childEntities;
/**
* Return the offset of the character immediately following the last character
@@ -591,7 +591,7 @@
* Use the given [visitor] to visit this node. Return the value returned by
* the visitor as a result of visiting this node.
*/
- dynamic /* =E */ accept/*<E>*/(AstVisitor/*<E>*/ visitor);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor);
/**
* Return the most immediate ancestor of this node for which the [predicate]
@@ -5899,7 +5899,8 @@
* are added to the list will have their parent set to the given [owner]. The
* list will initially be populated with the given [elements].
*/
- factory NodeList(AstNode owner, [List<E> elements]) = NodeListImpl;
+ factory NodeList(AstNode owner, [List<E> elements]) =>
+ new NodeListImpl<E>(owner as AstNodeImpl, elements);
/**
* Return the first token included in this node list's source range, or `null`
diff --git a/pkg/analyzer/lib/dart/constant/value.dart b/pkg/analyzer/lib/dart/constant/value.dart
new file mode 100644
index 0000000..e268345
--- /dev/null
+++ b/pkg/analyzer/lib/dart/constant/value.dart
@@ -0,0 +1,159 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * The interface used to access the result of constant evaluation.
+ *
+ * Because the analyzer does not have any of the code under analysis loaded, it
+ * does not do real evaluation. Instead it performs a symbolic computation and
+ * presents those results through this interface.
+ *
+ * Instances of these constant values are accessed through the
+ * [element model](../element/element.dart).
+ */
+library analyzer.dart.constant.value;
+
+import 'package:analyzer/dart/element/type.dart';
+
+/**
+ * A representation of the value of a compile-time constant expression.
+ *
+ * Note that, unlike the mirrors system, the object being represented does *not*
+ * exist. This interface allows static analysis tools to determine something
+ * about the state of the object that would exist if the code that creates the
+ * object were executed, but none of the code being analyzed is actually
+ * executed.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class DartObject {
+ /**
+ * Return `true` if the value of the object being represented is known.
+ *
+ * This method will return `false` if
+ * * the value being represented is the value of a declared variable (a
+ * variable whose value is provided at run-time using a `-D` command-line
+ * option), or
+ * * the value is a function.
+ *
+ * The result of this method does not imply anything about the state of
+ * object representations returned by the method [getField], those that are
+ * elements of the list returned by [toListValue], or the keys or values in
+ * the map returned by [toMapValue]. For example, a representation of a list
+ * can return `true` even if one or more of the elements of that list would
+ * return `false`.
+ */
+ bool get hasKnownValue;
+
+ /**
+ * Return `true` if the object being represented represents the value 'null'.
+ */
+ bool get isNull;
+
+ /**
+ * Return a representation of the type of the object being represented.
+ *
+ * For values resulting from the invocation of a 'const' constructor, this
+ * will be a representation of the run-time type of the object.
+ *
+ * For values resulting from a literal expression, this will be a
+ * representation of the static type of the value -- `int` for integer
+ * literals, `List` for list literals, etc. -- even when the static type is an
+ * abstract type (such as `List`) and hence will never be the run-time type of
+ * the represented object.
+ *
+ * For values resulting from any other kind of expression, this will be a
+ * representation of the result of evaluating the expression.
+ *
+ * Return `null` if the expression cannot be evaluated, either because it is
+ * not a valid constant expression or because one or more of the values used
+ * in the expression does not have a known value.
+ *
+ * This method can return a representation of the type, even if this object
+ * would return `false` from [hasKnownValue].
+ */
+ ParameterizedType get type;
+
+ /**
+ * Return a representation of the value of the field with the given [name].
+ *
+ * Return `null` if either the object being represented does not have a field
+ * with the given name or if the implementation of the class of the object is
+ * invalid, making it impossible to determine that value of the field.
+ *
+ * Note that, unlike the mirrors API, this method does *not* invoke a getter;
+ * it simply returns a representation of the known state of a field.
+ */
+ DartObject getField(String name);
+
+ /**
+ * Return a boolean corresponding to the value of the object being
+ * represented, or `null` if
+ * * this object is not of type 'bool',
+ * * the value of the object being represented is not known, or
+ * * the value of the object being represented is `null`.
+ */
+ bool toBoolValue();
+
+ /**
+ * Return a double corresponding to the value of the object being represented,
+ * or `null`
+ * if
+ * * this object is not of type 'double',
+ * * the value of the object being represented is not known, or
+ * * the value of the object being represented is `null`.
+ */
+ double toDoubleValue();
+
+ /**
+ * Return an integer corresponding to the value of the object being
+ * represented, or `null` if
+ * * this object is not of type 'int',
+ * * the value of the object being represented is not known, or
+ * * the value of the object being represented is `null`.
+ */
+ int toIntValue();
+
+ /**
+ * Return a list corresponding to the value of the object being represented,
+ * or `null` if
+ * * this object is not of type 'List', or
+ * * the value of the object being represented is `null`.
+ */
+ List<DartObject> toListValue();
+
+ /**
+ * Return a map corresponding to the value of the object being represented, or
+ * `null` if
+ * * this object is not of type 'Map', or
+ * * the value of the object being represented is `null`.
+ */
+ Map<DartObject, DartObject> toMapValue();
+
+ /**
+ * Return a string corresponding to the value of the object being represented,
+ * or `null` if
+ * * this object is not of type 'String',
+ * * the value of the object being represented is not known, or
+ * * the value of the object being represented is `null`.
+ */
+ String toStringValue();
+
+ /**
+ * Return a string corresponding to the value of the object being represented,
+ * or `null` if
+ * * this object is not of type 'Symbol', or
+ * * the value of the object being represented is `null`.
+ * (We return the string
+ */
+ String toSymbolValue();
+
+ /**
+ * Return the representation of the type corresponding to the value of the
+ * object being represented, or `null` if
+ * * this object is not of type 'Type', or
+ * * the value of the object being represented is `null`.
+ */
+ DartType toTypeValue();
+}
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 17e2f54..385849f 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -37,8 +37,8 @@
library analyzer.dart.element.element;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/generated/constant.dart' show DartObject;
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/java_engine.dart';
@@ -808,18 +808,18 @@
bool get isDeprecated;
/**
- * Return `true` if this annotation marks the associated method as being
- * expected to override an inherited method.
- */
- bool get isOverride;
-
- /**
* Return `true` if this annotation marks the associated member as requiring
* overriding methods to call super.
*/
bool get isMustCallSuper;
/**
+ * Return `true` if this annotation marks the associated method as being
+ * expected to override an inherited method.
+ */
+ bool get isOverride;
+
+ /**
* Return `true` if this annotation marks the associated member as being
* protected.
*/
@@ -1330,12 +1330,6 @@
static const List<LibraryElement> EMPTY_LIST = const <LibraryElement>[];
/**
- * Return a list containing the strongly connected component in the
- * import/export graph in which the current library resides.
- */
- List<LibraryElement> get libraryCycle;
-
- /**
* Return the compilation unit that defines this library.
*/
CompilationUnitElement get definingCompilationUnit;
@@ -1417,6 +1411,12 @@
bool get isInSdk;
/**
+ * Return a list containing the strongly connected component in the
+ * import/export graph in which the current library resides.
+ */
+ List<LibraryElement> get libraryCycle;
+
+ /**
* Return the element representing the synthetic function `loadLibrary` that
* is implicitly defined for this library if the library is imported using a
* deferred import.
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index c9b3e96..ba2bf4b 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -32,10 +32,33 @@
Source createSource([Uri uri]);
/**
+ * Synchronously read the entire file contents as a list of bytes.
+ * Throws a [FileSystemException] if the operation fails.
+ */
+ List<int> readAsBytesSync();
+
+ /**
* Synchronously read the entire file contents as a [String].
* Throws [FileSystemException] if the file does not exist.
*/
String readAsStringSync();
+
+ /**
+ * Synchronously rename this file.
+ * Return a [File] instance for the renamed file.
+ *
+ * If [newPath] identifies an existing file, that file is replaced.
+ * If [newPath] identifies an existing resource the operation might fail and
+ * an exception is thrown.
+ */
+ File renameSync(String newPath);
+
+ /**
+ * Synchronously write a list of bytes to the file.
+ *
+ * Throws a [FileSystemException] if the operation fails.
+ */
+ void writeAsBytesSync(List<int> bytes);
}
/**
@@ -63,7 +86,7 @@
/**
* If the path [path] is a relative path, convert it to an absolute path
- * by interpreting it relative to this folder. If it is already an aboslute
+ * by interpreting it relative to this folder. If it is already an absolute
* path, then don't change it.
*
* However, regardless of whether [path] is relative or absolute, normalize
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index fd26eb1..22d1b81 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -23,6 +23,7 @@
final Map<String, _MemoryResource> _pathToResource =
new HashMap<String, _MemoryResource>();
final Map<String, String> _pathToContent = new HashMap<String, String>();
+ final Map<String, List<int>> _pathToBytes = new HashMap<String, List<int>>();
final Map<String, int> _pathToTimestamp = new HashMap<String, int>();
final Map<String, List<StreamController<WatchEvent>>> _pathToWatchers =
new HashMap<String, List<StreamController<WatchEvent>>>();
@@ -116,16 +117,18 @@
File newFile(String path, String content, [int stamp]) {
path = pathContext.normalize(path);
- _MemoryResource folder = _pathToResource[pathContext.dirname(path)];
- if (folder == null) {
- newFolder(pathContext.dirname(path));
- } else if (folder is! Folder) {
- throw new ArgumentError('Cannot create file ($path) as child of file');
- }
- _MemoryFile file = new _MemoryFile(this, path);
- _pathToResource[path] = file;
+ _MemoryFile file = _newFile(path);
_pathToContent[path] = content;
- _pathToTimestamp[path] = stamp != null ? stamp : nextStamp++;
+ _pathToTimestamp[path] = stamp ?? nextStamp++;
+ _notifyWatchers(path, ChangeType.ADD);
+ return file;
+ }
+
+ File newFileWithBytes(String path, List<int> bytes, [int stamp]) {
+ path = pathContext.normalize(path);
+ _MemoryFile file = _newFile(path);
+ _pathToBytes[path] = bytes;
+ _pathToTimestamp[path] = stamp ?? nextStamp++;
_notifyWatchers(path, ChangeType.ADD);
return file;
}
@@ -156,6 +159,29 @@
}
}
+ _MemoryFile renameFileSync(_MemoryFile file, String newPath) {
+ String path = file.path;
+ if (newPath == path) {
+ return file;
+ }
+ _MemoryResource existingNewResource = _pathToResource[newPath];
+ if (existingNewResource is _MemoryFolder) {
+ throw new FileSystemException(
+ path, 'Could not be renamed: $newPath is a folder.');
+ }
+ _MemoryFile newFile = _newFile(newPath);
+ _pathToResource.remove(path);
+ _pathToContent[newPath] = _pathToContent.remove(path);
+ _pathToBytes[newPath] = _pathToBytes.remove(path);
+ _pathToTimestamp[newPath] = _pathToTimestamp.remove(path);
+ if (existingNewResource != null) {
+ _notifyWatchers(newPath, ChangeType.REMOVE);
+ }
+ _notifyWatchers(path, ChangeType.REMOVE);
+ _notifyWatchers(newPath, ChangeType.ADD);
+ return newFile;
+ }
+
File updateFile(String path, String content, [int stamp]) {
path = pathContext.normalize(path);
newFolder(pathContext.dirname(path));
@@ -183,6 +209,22 @@
}
}
+ /**
+ * Create a new [_MemoryFile] without any content.
+ */
+ _MemoryFile _newFile(String path) {
+ String folderPath = pathContext.dirname(path);
+ _MemoryResource folder = _pathToResource[folderPath];
+ if (folder == null) {
+ newFolder(folderPath);
+ } else if (folder is! Folder) {
+ throw new ArgumentError('Cannot create file ($path) as child of file');
+ }
+ _MemoryFile file = new _MemoryFile(this, path);
+ _pathToResource[path] = file;
+ return file;
+ }
+
void _notifyWatchers(String path, ChangeType changeType) {
_pathToWatchers.forEach((String watcherPath,
List<StreamController<WatchEvent>> streamControllers) {
@@ -194,6 +236,14 @@
}
});
}
+
+ void _setFileBytes(_MemoryFile file, List<int> bytes) {
+ String path = file.path;
+ _pathToResource[path] = file;
+ _pathToBytes[path] = bytes;
+ _pathToTimestamp[path] = nextStamp++;
+ _notifyWatchers(path, ChangeType.MODIFY);
+ }
}
/**
@@ -236,9 +286,24 @@
}
@override
+ List<int> readAsBytesSync() {
+ throw new FileSystemException(path, 'File could not be read');
+ }
+
+ @override
String readAsStringSync() {
throw new FileSystemException(path, 'File could not be read');
}
+
+ @override
+ Resource renameSync(String newPath) {
+ throw new FileSystemException(path, 'File could not be renamed');
+ }
+
+ @override
+ void writeAsBytesSync(List<int> bytes) {
+ throw new FileSystemException(path, 'File could not be written');
+ }
}
/**
@@ -282,6 +347,15 @@
}
@override
+ List<int> readAsBytesSync() {
+ List<int> bytes = _provider._pathToBytes[path];
+ if (bytes == null) {
+ throw new FileSystemException(path, 'File "$path" is not binary.');
+ }
+ return bytes;
+ }
+
+ @override
String readAsStringSync() {
String content = _provider._pathToContent[path];
if (content == null) {
@@ -289,6 +363,16 @@
}
return content;
}
+
+ @override
+ File renameSync(String newPath) {
+ return _provider.renameFileSync(this, newPath);
+ }
+
+ @override
+ void writeAsBytesSync(List<int> bytes) {
+ _provider._setFileBytes(this, bytes);
+ }
}
/**
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index cdfa9a6..66125a6 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -19,8 +19,8 @@
* A `dart:io` based implementation of [ResourceProvider].
*/
class PhysicalResourceProvider implements ResourceProvider {
- static final NORMALIZE_EOL_ALWAYS = (String string) =>
- string.replaceAll(new RegExp('\r\n?'), '\n');
+ static final NORMALIZE_EOL_ALWAYS =
+ (String string) => string.replaceAll(new RegExp('\r\n?'), '\n');
static final PhysicalResourceProvider INSTANCE =
new PhysicalResourceProvider(null);
@@ -112,6 +112,16 @@
}
@override
+ List<int> readAsBytesSync() {
+ try {
+ io.File file = _entry as io.File;
+ return file.readAsBytesSync();
+ } on io.FileSystemException catch (exception) {
+ throw new FileSystemException(exception.path, exception.message);
+ }
+ }
+
+ @override
String readAsStringSync() {
try {
io.File file = _entry as io.File;
@@ -120,6 +130,27 @@
throw new FileSystemException(exception.path, exception.message);
}
}
+
+ @override
+ void writeAsBytesSync(List<int> bytes) {
+ try {
+ io.File file = _entry as io.File;
+ file.writeAsBytesSync(bytes);
+ } on io.FileSystemException catch (exception) {
+ throw new FileSystemException(exception.path, exception.message);
+ }
+ }
+
+ @override
+ Resource renameSync(String newPath) {
+ try {
+ io.File file = _entry as io.File;
+ io.File newFile = file.renameSync(newPath);
+ return new _PhysicalFile(newFile);
+ } on io.FileSystemException catch (exception) {
+ throw new FileSystemException(exception.path, exception.message);
+ }
+ }
}
/**
diff --git a/pkg/analyzer/lib/source/analysis_options_provider.dart b/pkg/analyzer/lib/source/analysis_options_provider.dart
index c53bbad..b96ba5c 100644
--- a/pkg/analyzer/lib/source/analysis_options_provider.dart
+++ b/pkg/analyzer/lib/source/analysis_options_provider.dart
@@ -68,7 +68,7 @@
if (v != null && v is! YamlNode) {
throw new OptionsFormatException(
'Bad options file format (expected Node value, '
- 'got ${v.runtimeType}: `${v.toString()}`)',
+ 'got ${v.runtimeType}: `${v.toString()}`)',
doc.span);
}
options[key] = v;
@@ -91,7 +91,7 @@
///
Map<String, YamlNode> merge(
Map<String, YamlNode> defaults, Map<String, YamlNode> overrides) =>
- new Merger().merge(defaults, overrides);
+ new Merger().merge(defaults, overrides) as Map<String, YamlNode>;
/// Read the contents of [file] as a string.
/// Returns null if file does not exist.
diff --git a/pkg/analyzer/lib/source/error_processor.dart b/pkg/analyzer/lib/source/error_processor.dart
index 6b69cb7..ddd0679 100644
--- a/pkg/analyzer/lib/source/error_processor.dart
+++ b/pkg/analyzer/lib/source/error_processor.dart
@@ -10,6 +10,13 @@
import 'package:analyzer/src/task/options.dart';
import 'package:yaml/yaml.dart';
+/// String identifiers mapped to associated severities.
+const Map<String, ErrorSeverity> severityMap = const {
+ 'error': ErrorSeverity.ERROR,
+ 'info': ErrorSeverity.INFO,
+ 'warning': ErrorSeverity.WARNING
+};
+
/// Error processor configuration derived from analysis (or embedder) options.
class ErrorConfig {
/// The processors in this config.
@@ -57,13 +64,6 @@
ErrorSeverity _toSeverity(String severity) => severityMap[severity];
}
-/// String identifiers mapped to associated severities.
-const Map<String, ErrorSeverity> severityMap = const {
- 'error': ErrorSeverity.ERROR,
- 'info': ErrorSeverity.INFO,
- 'warning': ErrorSeverity.WARNING
-};
-
/// Process errors by filtering or changing associated [ErrorSeverity].
class ErrorProcessor {
/// The code name of the associated error.
@@ -94,20 +94,18 @@
return null;
}
- // By default, the error is not processed.
- ErrorProcessor processor;
+ // Let the user configure how specific errors are processed.
+ List<ErrorProcessor> processors =
+ context.getConfigurationData(CONFIGURED_ERROR_PROCESSORS)
+ as List<ErrorProcessor>;
// Give strong mode a chance to upgrade it.
if (context.analysisOptions.strongMode) {
- processor = _StrongModeTypeErrorProcessor.instance;
+ processors = processors.toList();
+ processors.add(_StrongModeTypeErrorProcessor.instance);
}
-
- // Let the user configure how specific errors are processed.
- List<ErrorProcessor> processors =
- context.getConfigurationData(CONFIGURED_ERROR_PROCESSORS);
-
return processors.firstWhere((ErrorProcessor p) => p.appliesTo(error),
- orElse: () => processor);
+ orElse: () => null);
}
}
diff --git a/pkg/analyzer/lib/source/sdk_ext.dart b/pkg/analyzer/lib/source/sdk_ext.dart
index fc7155a..126d3b6 100644
--- a/pkg/analyzer/lib/source/sdk_ext.dart
+++ b/pkg/analyzer/lib/source/sdk_ext.dart
@@ -155,7 +155,7 @@
/// Read the contents of [libDir]/[SDK_EXT_NAME] as a string.
/// Returns null if the file doesn't exist.
String _readDotSdkExt(Folder libDir) {
- var file = libDir.getChild(SDK_EXT_NAME);
+ File file = libDir.getChild(SDK_EXT_NAME);
try {
return file.readAsStringSync();
} on FileSystemException {
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index de913f3..98e0451 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -405,7 +405,7 @@
if (_partition != null) {
_partition.resultAccessed(target, descriptor);
}
- return data.value;
+ return data.value as Object/*=V*/;
}
/**
@@ -565,7 +565,8 @@
// Ask the delta to validate.
DeltaResult deltaResult = null;
if (delta != null) {
- deltaResult = delta.validate(_partition.context, target, descriptor);
+ deltaResult = delta.validate(
+ _partition.context, target, descriptor, thisData.value);
if (deltaResult == DeltaResult.STOP) {
return;
}
@@ -1056,10 +1057,10 @@
/**
* Check whether this delta affects the result described by the given
- * [descriptor] and [target].
+ * [descriptor] and [target]. The current [value] of the result is provided.
*/
DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
- ResultDescriptor descriptor) {
+ ResultDescriptor descriptor, Object value) {
return DeltaResult.INVALIDATE;
}
}
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 2c4ef43..90d5ffc 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -288,6 +288,7 @@
this._options.enableConditionalDirectives =
options.enableConditionalDirectives;
this._options.enableSuperMixins = options.enableSuperMixins;
+ this._options.enableTiming = options.enableTiming;
this._options.hint = options.hint;
this._options.incremental = options.incremental;
this._options.incrementalApi = options.incrementalApi;
@@ -1019,8 +1020,9 @@
}
@override
- Object getResult(AnalysisTarget target, ResultDescriptor result) {
- return _cache.getValue(target, result);
+ Object/*=V*/ getResult/*<V>*/(
+ AnalysisTarget target, ResultDescriptor/*<V>*/ result) {
+ return _cache.getValue(target, result) as Object/*=V*/;
}
@override
@@ -2009,7 +2011,7 @@
return new CancelableFuture.error(new AnalysisNotScheduledError());
}
CacheEntry entry = _context.getCacheEntry(_target);
- PendingFuture pendingFuture =
+ PendingFuture<T> pendingFuture =
new PendingFuture<T>(_context, _target, (CacheEntry entry) {
CacheState state = entry.getState(_descriptor);
if (state == CacheState.ERROR) {
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index d2e09de..3f398ac 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -59,7 +59,8 @@
NodeList<StringLiteral> get strings => _strings;
@override
- accept(AstVisitor visitor) => visitor.visitAdjacentStrings(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitAdjacentStrings(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -155,7 +156,7 @@
@override
void visitChildren(AstVisitor visitor) {
if (_commentIsBeforeAnnotations()) {
- _safelyVisitChild(_comment, visitor);
+ _comment?.accept(visitor);
_metadata.accept(visitor);
} else {
for (AstNode child in sortedCommentAndAnnotations) {
@@ -305,13 +306,14 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitAnnotation(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitAnnotation(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_name, visitor);
- _safelyVisitChild(_constructorName, visitor);
- _safelyVisitChild(_arguments, visitor);
+ _name?.accept(visitor);
+ _constructorName?.accept(visitor);
+ _arguments?.accept(visitor);
}
}
@@ -409,7 +411,8 @@
Token get endToken => rightParenthesis;
@override
- accept(AstVisitor visitor) => visitor.visitArgumentList(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitArgumentList(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -531,12 +534,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitAsExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitAsExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_expression, visitor);
- _safelyVisitChild(_type, visitor);
+ _expression?.accept(visitor);
+ _type?.accept(visitor);
}
}
@@ -636,12 +640,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitAssertStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitAssertStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_condition, visitor);
- _safelyVisitChild(message, visitor);
+ _condition?.accept(visitor);
+ message?.accept(visitor);
}
}
@@ -823,12 +828,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitAssignmentExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitAssignmentExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_leftHandSide, visitor);
- _safelyVisitChild(_rightHandSide, visitor);
+ _leftHandSide?.accept(visitor);
+ _rightHandSide?.accept(visitor);
}
}
@@ -941,15 +947,6 @@
}
return child;
}
-
- /**
- * If the given [child] is not `null`, use the given [visitor] to visit it.
- */
- void _safelyVisitChild(AstNode child, AstVisitor visitor) {
- if (child != null) {
- child.accept(visitor);
- }
- }
}
/**
@@ -1004,11 +1001,12 @@
int get precedence => 0;
@override
- accept(AstVisitor visitor) => visitor.visitAwaitExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitAwaitExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_expression, visitor);
+ _expression?.accept(visitor);
}
}
@@ -1134,12 +1132,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitBinaryExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitBinaryExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_leftOperand, visitor);
- _safelyVisitChild(_rightOperand, visitor);
+ _leftOperand?.accept(visitor);
+ _rightOperand?.accept(visitor);
}
}
@@ -1213,11 +1212,12 @@
bool get isSynchronous => keyword == null || keyword.lexeme != Parser.ASYNC;
@override
- accept(AstVisitor visitor) => visitor.visitBlockFunctionBody(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitBlockFunctionBody(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_block, visitor);
+ _block?.accept(visitor);
}
}
@@ -1268,7 +1268,8 @@
NodeList<Statement> get statements => _statements;
@override
- accept(AstVisitor visitor) => visitor.visitBlock(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitBlock(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -1313,7 +1314,8 @@
bool get isSynthetic => literal.isSynthetic;
@override
- accept(AstVisitor visitor) => visitor.visitBooleanLiteral(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitBooleanLiteral(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -1385,11 +1387,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitBreakStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitBreakStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_label, visitor);
+ _label?.accept(visitor);
}
}
@@ -1456,11 +1459,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitCascadeExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitCascadeExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_target, visitor);
+ _target?.accept(visitor);
_cascadeSections.accept(visitor);
}
}
@@ -1610,14 +1614,15 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitCatchClause(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitCatchClause(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_exceptionType, visitor);
- _safelyVisitChild(_exceptionParameter, visitor);
- _safelyVisitChild(_stackTraceParameter, visitor);
- _safelyVisitChild(_body, visitor);
+ _exceptionType?.accept(visitor);
+ _exceptionParameter?.accept(visitor);
+ _stackTraceParameter?.accept(visitor);
+ _body?.accept(visitor);
}
}
@@ -1830,7 +1835,8 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitClassDeclaration(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitClassDeclaration(this);
@override
ConstructorDeclaration getConstructor(String name) {
@@ -1884,12 +1890,12 @@
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_name, visitor);
- _safelyVisitChild(_typeParameters, visitor);
- _safelyVisitChild(_extendsClause, visitor);
- _safelyVisitChild(_withClause, visitor);
- _safelyVisitChild(_implementsClause, visitor);
- _safelyVisitChild(_nativeClause, visitor);
+ _name?.accept(visitor);
+ _typeParameters?.accept(visitor);
+ _extendsClause?.accept(visitor);
+ _withClause?.accept(visitor);
+ _implementsClause?.accept(visitor);
+ _nativeClause?.accept(visitor);
members.accept(visitor);
}
}
@@ -2039,16 +2045,17 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitClassTypeAlias(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitClassTypeAlias(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_name, visitor);
- _safelyVisitChild(_typeParameters, visitor);
- _safelyVisitChild(_superclass, visitor);
- _safelyVisitChild(_withClause, visitor);
- _safelyVisitChild(_implementsClause, visitor);
+ _name?.accept(visitor);
+ _typeParameters?.accept(visitor);
+ _superclass?.accept(visitor);
+ _withClause?.accept(visitor);
+ _implementsClause?.accept(visitor);
}
}
@@ -2145,7 +2152,8 @@
NodeList<CommentReference> get references => _references;
@override
- accept(AstVisitor visitor) => visitor.visitComment(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitComment(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -2226,11 +2234,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitCommentReference(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitCommentReference(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_identifier, visitor);
+ _identifier?.accept(visitor);
}
}
@@ -2411,11 +2420,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitCompilationUnit(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitCompilationUnit(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_scriptTag, visitor);
+ _scriptTag?.accept(visitor);
if (_directivesAreBeforeDeclarations) {
_directives.accept(visitor);
_declarations.accept(visitor);
@@ -2537,13 +2547,14 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitConditionalExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitConditionalExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_condition, visitor);
- _safelyVisitChild(_thenExpression, visitor);
- _safelyVisitChild(_elseExpression, visitor);
+ _condition?.accept(visitor);
+ _thenExpression?.accept(visitor);
+ _elseExpression?.accept(visitor);
}
}
@@ -2626,13 +2637,14 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitConfiguration(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitConfiguration(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_name, visitor);
- _safelyVisitChild(_value, visitor);
- _safelyVisitChild(_libraryUri, visitor);
+ _name?.accept(visitor);
+ _value?.accept(visitor);
+ _libraryUri?.accept(visitor);
}
}
@@ -2853,17 +2865,18 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitConstructorDeclaration(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitConstructorDeclaration(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_returnType, visitor);
- _safelyVisitChild(_name, visitor);
- _safelyVisitChild(_parameters, visitor);
+ _returnType?.accept(visitor);
+ _name?.accept(visitor);
+ _parameters?.accept(visitor);
_initializers.accept(visitor);
- _safelyVisitChild(_redirectedConstructor, visitor);
- _safelyVisitChild(_body, visitor);
+ _redirectedConstructor?.accept(visitor);
+ _body?.accept(visitor);
}
}
@@ -2951,12 +2964,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitConstructorFieldInitializer(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitConstructorFieldInitializer(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_fieldName, visitor);
- _safelyVisitChild(_expression, visitor);
+ _fieldName?.accept(visitor);
+ _expression?.accept(visitor);
}
}
@@ -3045,12 +3059,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitConstructorName(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitConstructorName(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_type, visitor);
- _safelyVisitChild(_name, visitor);
+ _type?.accept(visitor);
+ _name?.accept(visitor);
}
}
@@ -3116,11 +3131,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitContinueStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitContinueStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_label, visitor);
+ _label?.accept(visitor);
}
}
@@ -3230,13 +3246,14 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitDeclaredIdentifier(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitDeclaredIdentifier(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_type, visitor);
- _safelyVisitChild(_identifier, visitor);
+ _type?.accept(visitor);
+ _identifier?.accept(visitor);
}
}
@@ -3331,12 +3348,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitDefaultFormalParameter(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitDefaultFormalParameter(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_parameter, visitor);
- _safelyVisitChild(_defaultValue, visitor);
+ _parameter?.accept(visitor);
+ _defaultValue?.accept(visitor);
}
}
@@ -3461,12 +3479,13 @@
Token get endToken => semicolon;
@override
- accept(AstVisitor visitor) => visitor.visitDoStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitDoStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_body, visitor);
- _safelyVisitChild(_condition, visitor);
+ _body?.accept(visitor);
+ _condition?.accept(visitor);
}
}
@@ -3503,7 +3522,8 @@
Token get endToken => _components.endToken;
@override
- accept(AstVisitor visitor) => visitor.visitDottedName(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitDottedName(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -3549,7 +3569,8 @@
Token get endToken => literal;
@override
- accept(AstVisitor visitor) => visitor.visitDoubleLiteral(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitDoubleLiteral(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -3588,7 +3609,8 @@
Token get endToken => semicolon;
@override
- accept(AstVisitor visitor) => visitor.visitEmptyFunctionBody(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitEmptyFunctionBody(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -3623,7 +3645,8 @@
Token get endToken => semicolon;
@override
- accept(AstVisitor visitor) => visitor.visitEmptyStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitEmptyStatement(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -3675,12 +3698,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitEnumConstantDeclaration(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitEnumConstantDeclaration(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_name, visitor);
+ _name?.accept(visitor);
}
}
@@ -3756,12 +3780,13 @@
Token get firstTokenAfterCommentAndMetadata => enumKeyword;
@override
- accept(AstVisitor visitor) => visitor.visitEnumDeclaration(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitEnumDeclaration(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_name, visitor);
+ _name?.accept(visitor);
_constants.accept(visitor);
}
}
@@ -3820,7 +3845,8 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitExportDirective(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitExportDirective(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -3910,11 +3936,12 @@
bool get isSynchronous => keyword == null;
@override
- accept(AstVisitor visitor) => visitor.visitExpressionFunctionBody(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitExpressionFunctionBody(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_expression, visitor);
+ _expression?.accept(visitor);
}
}
@@ -4073,11 +4100,12 @@
bool get isSynthetic => _expression.isSynthetic && semicolon.isSynthetic;
@override
- accept(AstVisitor visitor) => visitor.visitExpressionStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitExpressionStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_expression, visitor);
+ _expression?.accept(visitor);
}
}
@@ -4125,11 +4153,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitExtendsClause(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitExtendsClause(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_superclass, visitor);
+ _superclass?.accept(visitor);
}
}
@@ -4200,12 +4229,13 @@
bool get isStatic => staticKeyword != null;
@override
- accept(AstVisitor visitor) => visitor.visitFieldDeclaration(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitFieldDeclaration(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_fieldList, visitor);
+ _fieldList?.accept(visitor);
}
}
@@ -4342,15 +4372,16 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitFieldFormalParameter(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitFieldFormalParameter(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_type, visitor);
- _safelyVisitChild(identifier, visitor);
- _safelyVisitChild(_typeParameters, visitor);
- _safelyVisitChild(_parameters, visitor);
+ _type?.accept(visitor);
+ identifier?.accept(visitor);
+ _typeParameters?.accept(visitor);
+ _parameters?.accept(visitor);
}
}
@@ -4503,14 +4534,15 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitForEachStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitForEachStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_loopVariable, visitor);
- _safelyVisitChild(_identifier, visitor);
- _safelyVisitChild(_iterable, visitor);
- _safelyVisitChild(_body, visitor);
+ _loopVariable?.accept(visitor);
+ _identifier?.accept(visitor);
+ _iterable?.accept(visitor);
+ _body?.accept(visitor);
}
}
@@ -4643,7 +4675,8 @@
NodeList<FormalParameter> get parameters => _parameters;
@override
- accept(AstVisitor visitor) => visitor.visitFormalParameterList(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitFormalParameterList(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -4804,15 +4837,16 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitForStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitForStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_variableList, visitor);
- _safelyVisitChild(_initialization, visitor);
- _safelyVisitChild(_condition, visitor);
+ _variableList?.accept(visitor);
+ _initialization?.accept(visitor);
+ _condition?.accept(visitor);
_updaters.accept(visitor);
- _safelyVisitChild(_body, visitor);
+ _body?.accept(visitor);
}
}
@@ -4994,14 +5028,15 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitFunctionDeclaration(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitFunctionDeclaration(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_returnType, visitor);
- _safelyVisitChild(_name, visitor);
- _safelyVisitChild(_functionExpression, visitor);
+ _returnType?.accept(visitor);
+ _name?.accept(visitor);
+ _functionExpression?.accept(visitor);
}
}
@@ -5040,11 +5075,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitFunctionDeclarationStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitFunctionDeclarationStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_functionDeclaration, visitor);
+ _functionDeclaration?.accept(visitor);
}
}
@@ -5147,13 +5183,14 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitFunctionExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitFunctionExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_typeParameters, visitor);
- _safelyVisitChild(_parameters, visitor);
- _safelyVisitChild(_body, visitor);
+ _typeParameters?.accept(visitor);
+ _parameters?.accept(visitor);
+ _body?.accept(visitor);
}
}
@@ -5229,13 +5266,14 @@
int get precedence => 15;
@override
- accept(AstVisitor visitor) => visitor.visitFunctionExpressionInvocation(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitFunctionExpressionInvocation(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_function, visitor);
- _safelyVisitChild(_typeArguments, visitor);
- _safelyVisitChild(_argumentList, visitor);
+ _function?.accept(visitor);
+ _typeArguments?.accept(visitor);
+ _argumentList?.accept(visitor);
}
}
@@ -5326,15 +5364,16 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitFunctionTypeAlias(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitFunctionTypeAlias(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_returnType, visitor);
- _safelyVisitChild(_name, visitor);
- _safelyVisitChild(_typeParameters, visitor);
- _safelyVisitChild(_parameters, visitor);
+ _returnType?.accept(visitor);
+ _name?.accept(visitor);
+ _typeParameters?.accept(visitor);
+ _parameters?.accept(visitor);
}
}
@@ -5428,15 +5467,16 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitFunctionTypedFormalParameter(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitFunctionTypedFormalParameter(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_returnType, visitor);
- _safelyVisitChild(identifier, visitor);
- _safelyVisitChild(_typeParameters, visitor);
- _safelyVisitChild(_parameters, visitor);
+ _returnType?.accept(visitor);
+ identifier?.accept(visitor);
+ _typeParameters?.accept(visitor);
+ _parameters?.accept(visitor);
}
}
@@ -5473,7 +5513,8 @@
NodeList<SimpleIdentifier> get hiddenNames => _hiddenNames;
@override
- accept(AstVisitor visitor) => visitor.visitHideCombinator(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitHideCombinator(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -5613,13 +5654,14 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitIfStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitIfStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_condition, visitor);
- _safelyVisitChild(_thenStatement, visitor);
- _safelyVisitChild(_elseStatement, visitor);
+ _condition?.accept(visitor);
+ _thenStatement?.accept(visitor);
+ _elseStatement?.accept(visitor);
}
}
@@ -5664,7 +5706,8 @@
NodeList<TypeName> get interfaces => _interfaces;
@override
- accept(AstVisitor visitor) => visitor.visitImplementsClause(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitImplementsClause(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -5754,12 +5797,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitImportDirective(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitImportDirective(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_prefix, visitor);
+ _prefix?.accept(visitor);
combinators.accept(visitor);
}
}
@@ -5946,7 +5990,8 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitIndexExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitIndexExpression(this);
@override
bool inGetterContext() {
@@ -5978,8 +6023,8 @@
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_target, visitor);
- _safelyVisitChild(_index, visitor);
+ _target?.accept(visitor);
+ _index?.accept(visitor);
}
}
@@ -6062,12 +6107,13 @@
int get precedence => 16;
@override
- accept(AstVisitor visitor) => visitor.visitInstanceCreationExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitInstanceCreationExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_constructorName, visitor);
- _safelyVisitChild(_argumentList, visitor);
+ _constructorName?.accept(visitor);
+ _argumentList?.accept(visitor);
}
}
@@ -6113,7 +6159,8 @@
Token get endToken => literal;
@override
- accept(AstVisitor visitor) => visitor.visitIntegerLiteral(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitIntegerLiteral(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -6194,11 +6241,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitInterpolationExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitInterpolationExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_expression, visitor);
+ _expression?.accept(visitor);
}
}
@@ -6251,7 +6299,8 @@
Token get endToken => contents;
@override
- accept(AstVisitor visitor) => visitor.visitInterpolationString(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitInterpolationString(this);
@override
void visitChildren(AstVisitor visitor) {}
@@ -6376,12 +6425,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitIsExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitIsExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_expression, visitor);
- _safelyVisitChild(_type, visitor);
+ _expression?.accept(visitor);
+ _type?.accept(visitor);
}
}
@@ -6441,12 +6491,13 @@
Statement get unlabeled => _statement.unlabeled;
@override
- accept(AstVisitor visitor) => visitor.visitLabeledStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitLabeledStatement(this);
@override
void visitChildren(AstVisitor visitor) {
_labels.accept(visitor);
- _safelyVisitChild(_statement, visitor);
+ _statement?.accept(visitor);
}
}
@@ -6493,11 +6544,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitLabel(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitLabel(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_label, visitor);
+ _label?.accept(visitor);
}
}
@@ -6558,12 +6610,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitLibraryDirective(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitLibraryDirective(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_name, visitor);
+ _name?.accept(visitor);
}
}
@@ -6628,7 +6681,8 @@
Element get staticElement => null;
@override
- accept(AstVisitor visitor) => visitor.visitLibraryIdentifier(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitLibraryIdentifier(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -6698,7 +6752,8 @@
Token get endToken => rightBracket;
@override
- accept(AstVisitor visitor) => visitor.visitListLiteral(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitListLiteral(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -6802,12 +6857,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitMapLiteralEntry(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitMapLiteralEntry(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_key, visitor);
- _safelyVisitChild(_value, visitor);
+ _key?.accept(visitor);
+ _value?.accept(visitor);
}
}
@@ -6873,7 +6929,8 @@
NodeList<MapLiteralEntry> get entries => _entries;
@override
- accept(AstVisitor visitor) => visitor.visitMapLiteral(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitMapLiteral(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -7019,7 +7076,9 @@
@override
Token get firstTokenAfterCommentAndMetadata {
- if (modifierKeyword != null) {
+ if (externalKeyword != null) {
+ return externalKeyword;
+ } else if (modifierKeyword != null) {
return modifierKeyword;
} else if (_returnType != null) {
return _returnType.beginToken;
@@ -7089,16 +7148,17 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitMethodDeclaration(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitMethodDeclaration(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_returnType, visitor);
- _safelyVisitChild(_name, visitor);
- _safelyVisitChild(_typeParameters, visitor);
- _safelyVisitChild(_parameters, visitor);
- _safelyVisitChild(_body, visitor);
+ _returnType?.accept(visitor);
+ _name?.accept(visitor);
+ _typeParameters?.accept(visitor);
+ _parameters?.accept(visitor);
+ _body?.accept(visitor);
}
}
@@ -7210,14 +7270,15 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitMethodInvocation(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitMethodInvocation(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_target, visitor);
- _safelyVisitChild(_methodName, visitor);
- _safelyVisitChild(_typeArguments, visitor);
- _safelyVisitChild(_argumentList, visitor);
+ _target?.accept(visitor);
+ _methodName?.accept(visitor);
+ _typeArguments?.accept(visitor);
+ _argumentList?.accept(visitor);
}
}
@@ -7316,12 +7377,13 @@
int get precedence => 0;
@override
- accept(AstVisitor visitor) => visitor.visitNamedExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitNamedExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_name, visitor);
- _safelyVisitChild(_expression, visitor);
+ _name?.accept(visitor);
+ _expression?.accept(visitor);
}
}
@@ -7436,11 +7498,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitNativeClause(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitNativeClause(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_name, visitor);
+ _name?.accept(visitor);
}
}
@@ -7501,11 +7564,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitNativeFunctionBody(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitNativeFunctionBody(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_stringLiteral, visitor);
+ _stringLiteral?.accept(visitor);
}
}
@@ -7729,7 +7793,7 @@
// they often need to visit other nodes before visiting the identifier.
//
if (_commentIsBeforeAnnotations()) {
- _safelyVisitChild(_comment, visitor);
+ _comment?.accept(visitor);
_metadata.accept(visitor);
} else {
for (AstNode child in sortedCommentAndAnnotations) {
@@ -7777,7 +7841,8 @@
Token get endToken => literal;
@override
- accept(AstVisitor visitor) => visitor.visitNullLiteral(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitNullLiteral(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -7840,11 +7905,12 @@
int get precedence => 15;
@override
- accept(AstVisitor visitor) => visitor.visitParenthesizedExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitParenthesizedExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_expression, visitor);
+ _expression?.accept(visitor);
}
}
@@ -7893,7 +7959,8 @@
CompilationUnitElement get uriElement => element as CompilationUnitElement;
@override
- accept(AstVisitor visitor) => visitor.visitPartDirective(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitPartDirective(this);
}
/**
@@ -7967,12 +8034,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitPartOfDirective(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitPartOfDirective(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_libraryName, visitor);
+ _libraryName?.accept(visitor);
}
}
@@ -8084,11 +8152,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitPostfixExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitPostfixExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_operand, visitor);
+ _operand?.accept(visitor);
}
}
@@ -8197,12 +8266,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitPrefixedIdentifier(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitPrefixedIdentifier(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_prefix, visitor);
- _safelyVisitChild(_identifier, visitor);
+ _prefix?.accept(visitor);
+ _identifier?.accept(visitor);
}
}
@@ -8309,11 +8379,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitPrefixExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitPrefixExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_operand, visitor);
+ _operand?.accept(visitor);
}
}
@@ -8409,12 +8480,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitPropertyAccess(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitPropertyAccess(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_target, visitor);
- _safelyVisitChild(_propertyName, visitor);
+ _target?.accept(visitor);
+ _propertyName?.accept(visitor);
}
}
@@ -8497,13 +8569,13 @@
Token get endToken => _argumentList.endToken;
@override
- accept(AstVisitor visitor) =>
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
visitor.visitRedirectingConstructorInvocation(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_constructorName, visitor);
- _safelyVisitChild(_argumentList, visitor);
+ _constructorName?.accept(visitor);
+ _argumentList?.accept(visitor);
}
}
@@ -8538,7 +8610,8 @@
int get precedence => 0;
@override
- accept(AstVisitor visitor) => visitor.visitRethrowExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitRethrowExpression(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -8597,11 +8670,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitReturnStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitReturnStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_expression, visitor);
+ _expression?.accept(visitor);
}
}
@@ -8632,7 +8706,8 @@
Token get endToken => scriptTag;
@override
- accept(AstVisitor visitor) => visitor.visitScriptTag(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitScriptTag(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -8673,7 +8748,8 @@
NodeList<SimpleIdentifier> get shownNames => _shownNames;
@override
- accept(AstVisitor visitor) => visitor.visitShowCombinator(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitShowCombinator(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -8752,13 +8828,14 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitSimpleFormalParameter(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitSimpleFormalParameter(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_type, visitor);
- _safelyVisitChild(identifier, visitor);
+ _type?.accept(visitor);
+ identifier?.accept(visitor);
}
}
@@ -8865,7 +8942,8 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitSimpleIdentifier(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitSimpleIdentifier(this);
@override
bool inDeclarationContext() {
@@ -9131,7 +9209,8 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitSimpleStringLiteral(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitSimpleStringLiteral(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -9241,7 +9320,8 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitStringInterpolation(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitStringInterpolation(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -9457,12 +9537,13 @@
Token get endToken => _argumentList.endToken;
@override
- accept(AstVisitor visitor) => visitor.visitSuperConstructorInvocation(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitSuperConstructorInvocation(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_constructorName, visitor);
- _safelyVisitChild(_argumentList, visitor);
+ _constructorName?.accept(visitor);
+ _argumentList?.accept(visitor);
}
}
@@ -9496,7 +9577,8 @@
int get precedence => 16;
@override
- accept(AstVisitor visitor) => visitor.visitSuperExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitSuperExpression(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -9543,12 +9625,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitSwitchCase(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitSwitchCase(this);
@override
void visitChildren(AstVisitor visitor) {
labels.accept(visitor);
- _safelyVisitChild(_expression, visitor);
+ _expression?.accept(visitor);
statements.accept(visitor);
}
}
@@ -9576,7 +9659,8 @@
..addAll(statements);
@override
- accept(AstVisitor visitor) => visitor.visitSwitchDefault(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitSwitchDefault(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -9733,11 +9817,12 @@
NodeList<SwitchMember> get members => _members;
@override
- accept(AstVisitor visitor) => visitor.visitSwitchStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitSwitchStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_expression, visitor);
+ _expression?.accept(visitor);
_members.accept(visitor);
}
}
@@ -9777,7 +9862,8 @@
Token get endToken => components[components.length - 1];
@override
- accept(AstVisitor visitor) => visitor.visitSymbolLiteral(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitSymbolLiteral(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -9815,7 +9901,8 @@
int get precedence => 16;
@override
- accept(AstVisitor visitor) => visitor.visitThisExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitThisExpression(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -9874,11 +9961,12 @@
int get precedence => 0;
@override
- accept(AstVisitor visitor) => visitor.visitThrowExpression(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitThrowExpression(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_expression, visitor);
+ _expression?.accept(visitor);
}
}
@@ -9934,12 +10022,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitTopLevelVariableDeclaration(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitTopLevelVariableDeclaration(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_variableList, visitor);
+ _variableList?.accept(visitor);
}
}
@@ -10035,13 +10124,14 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitTryStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitTryStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_body, visitor);
+ _body?.accept(visitor);
_catchClauses.accept(visitor);
- _safelyVisitChild(_finallyBlock, visitor);
+ _finallyBlock?.accept(visitor);
}
}
@@ -10130,7 +10220,8 @@
Token get endToken => rightBracket;
@override
- accept(AstVisitor visitor) => visitor.visitTypeArgumentList(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitTypeArgumentList(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -10180,7 +10271,7 @@
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_typeArguments, visitor);
+ _typeArguments?.accept(visitor);
}
}
@@ -10260,12 +10351,13 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitTypeName(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitTypeName(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_name, visitor);
- _safelyVisitChild(_typeArguments, visitor);
+ _name?.accept(visitor);
+ _typeArguments?.accept(visitor);
}
}
@@ -10342,13 +10434,14 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitTypeParameter(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitTypeParameter(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_name, visitor);
- _safelyVisitChild(_bound, visitor);
+ _name?.accept(visitor);
+ _bound?.accept(visitor);
}
}
@@ -10398,7 +10491,8 @@
NodeList<TypeParameter> get typeParameters => _typeParameters;
@override
- accept(AstVisitor visitor) => visitor.visitTypeParameterList(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitTypeParameterList(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -10480,7 +10574,7 @@
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_uri, visitor);
+ _uri?.accept(visitor);
}
}
@@ -10620,13 +10714,14 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitVariableDeclaration(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitVariableDeclaration(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_name, visitor);
- _safelyVisitChild(_initializer, visitor);
+ _name?.accept(visitor);
+ _initializer?.accept(visitor);
}
}
@@ -10715,12 +10810,13 @@
NodeList<VariableDeclaration> get variables => _variables;
@override
- accept(AstVisitor visitor) => visitor.visitVariableDeclarationList(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitVariableDeclarationList(this);
@override
void visitChildren(AstVisitor visitor) {
super.visitChildren(visitor);
- _safelyVisitChild(_type, visitor);
+ _type?.accept(visitor);
_variables.accept(visitor);
}
}
@@ -10771,11 +10867,12 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitVariableDeclarationStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitVariableDeclarationStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_variableList, visitor);
+ _variableList?.accept(visitor);
}
}
@@ -10851,12 +10948,13 @@
Token get endToken => _body.endToken;
@override
- accept(AstVisitor visitor) => visitor.visitWhileStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitWhileStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_condition, visitor);
- _safelyVisitChild(_body, visitor);
+ _condition?.accept(visitor);
+ _body?.accept(visitor);
}
}
@@ -10900,7 +10998,8 @@
NodeList<TypeName> get mixinTypes => _mixinTypes;
@override
- accept(AstVisitor visitor) => visitor.visitWithClause(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitWithClause(this);
@override
void visitChildren(AstVisitor visitor) {
@@ -10976,10 +11075,11 @@
}
@override
- accept(AstVisitor visitor) => visitor.visitYieldStatement(this);
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) =>
+ visitor.visitYieldStatement(this);
@override
void visitChildren(AstVisitor visitor) {
- _safelyVisitChild(_expression, visitor);
+ _expression?.accept(visitor);
}
}
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 331d6d9..3628346 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -60,22 +60,23 @@
/**
* Return a clone of the given [node].
*/
- AstNode cloneNode(AstNode node) {
+ AstNode/*=E*/ cloneNode/*<E extends AstNode>*/(AstNode/*=E*/ node) {
if (node == null) {
return null;
}
- return node.accept(this) as AstNode;
+ return node.accept(this) as AstNode/*=E*/;
}
/**
* Return a list containing cloned versions of the nodes in the given list of
* [nodes].
*/
- List<AstNode> cloneNodeList(NodeList nodes) {
+ List<AstNode/*=E*/ > cloneNodeList/*<E extends AstNode>*/(
+ NodeList/*<E>*/ nodes) {
int count = nodes.length;
- List clonedNodes = new List();
+ List/*<E>*/ clonedNodes = new List/*<E>*/();
for (int i = 0; i < count; i++) {
- clonedNodes.add((nodes[i]).accept(this) as AstNode);
+ clonedNodes.add((nodes[i]).accept(this) as AstNode/*=E*/);
}
return clonedNodes;
}
@@ -2588,6 +2589,7 @@
* mapping the old token stream to a new token stream, and preserving resolution
* results.
*/
+@deprecated
class IncrementalAstCloner implements AstVisitor<AstNode> {
/**
* The node to be replaced during the cloning process.
@@ -3101,18 +3103,21 @@
_mapToken(node.implementsKeyword), _cloneNodeList(node.interfaces));
@override
- ImportDirective visitImportDirective(ImportDirective node) =>
- new ImportDirective(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.keyword),
- _cloneNode(node.uri),
- _cloneNodeList(node.configurations),
- _mapToken(node.deferredKeyword),
- _mapToken(node.asKeyword),
- _cloneNode(node.prefix),
- _cloneNodeList(node.combinators),
- _mapToken(node.semicolon));
+ ImportDirective visitImportDirective(ImportDirective node) {
+ ImportDirective copy = new ImportDirective(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.keyword),
+ _cloneNode(node.uri),
+ _cloneNodeList(node.configurations),
+ _mapToken(node.deferredKeyword),
+ _mapToken(node.asKeyword),
+ _cloneNode(node.prefix),
+ _cloneNodeList(node.combinators),
+ _mapToken(node.semicolon));
+ copy.element = node.element;
+ return copy;
+ }
@override
IndexExpression visitIndexExpression(IndexExpression node) {
@@ -3190,13 +3195,16 @@
_cloneNodeList(node.labels), _cloneNode(node.statement));
@override
- LibraryDirective visitLibraryDirective(LibraryDirective node) =>
- new LibraryDirective(
- _cloneNode(node.documentationComment),
- _cloneNodeList(node.metadata),
- _mapToken(node.libraryKeyword),
- _cloneNode(node.name),
- _mapToken(node.semicolon));
+ LibraryDirective visitLibraryDirective(LibraryDirective node) {
+ LibraryDirective copy = new LibraryDirective(
+ _cloneNode(node.documentationComment),
+ _cloneNodeList(node.metadata),
+ _mapToken(node.libraryKeyword),
+ _cloneNode(node.name),
+ _mapToken(node.semicolon));
+ copy.element = node.element;
+ return copy;
+ }
@override
LibraryIdentifier visitLibraryIdentifier(LibraryIdentifier node) {
@@ -3607,19 +3615,19 @@
_cloneNode(node.expression),
_mapToken(node.semicolon));
- AstNode _cloneNode(AstNode node) {
+ AstNode/*=E*/ _cloneNode/*<E extends AstNode>*/(AstNode/*=E*/ node) {
if (node == null) {
return null;
}
if (identical(node, _oldNode)) {
- return _newNode;
+ return _newNode as AstNode/*=E*/;
}
- return node.accept(this) as AstNode;
+ return node.accept(this) as AstNode/*=E*/;
}
- List _cloneNodeList(NodeList nodes) {
- List clonedNodes = new List();
- for (AstNode node in nodes) {
+ List/*<E>*/ _cloneNodeList/*<E extends AstNode>*/(NodeList/*<E>*/ nodes) {
+ List/*<E>*/ clonedNodes = new List/*<E>*/();
+ for (AstNode/*=E*/ node in nodes) {
clonedNodes.add(_cloneNode(node));
}
return clonedNodes;
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
new file mode 100644
index 0000000..5484bba
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -0,0 +1,2003 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.src.dart.constant.evaluation;
+
+import 'dart:collection';
+
+import 'package:analyzer/context/declared_variables.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/constant/value.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/constant/utilities.dart';
+import 'package:analyzer/src/dart/constant/value.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/engine.dart'
+ show AnalysisEngine, RecordingErrorListener;
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+import 'package:analyzer/src/generated/source.dart' show Source;
+import 'package:analyzer/src/generated/type_system.dart'
+ show TypeSystem, TypeSystemImpl;
+import 'package:analyzer/src/generated/utilities_collection.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
+import 'package:analyzer/src/task/dart.dart';
+
+/**
+ * Helper class encapsulating the methods for evaluating constants and
+ * constant instance creation expressions.
+ */
+class ConstantEvaluationEngine {
+ /**
+ * Parameter to "fromEnvironment" methods that denotes the default value.
+ */
+ static String _DEFAULT_VALUE_PARAM = "defaultValue";
+
+ /**
+ * Source of RegExp matching any public identifier.
+ * From sdk/lib/internal/symbol.dart.
+ */
+ static String _PUBLIC_IDENTIFIER_RE =
+ "(?!${ConstantValueComputer._RESERVED_WORD_RE}\\b(?!\\\$))[a-zA-Z\$][\\w\$]*";
+
+ /**
+ * RegExp that validates a non-empty non-private symbol.
+ * From sdk/lib/internal/symbol.dart.
+ */
+ static RegExp _PUBLIC_SYMBOL_PATTERN = new RegExp(
+ "^(?:${ConstantValueComputer._OPERATOR_RE}\$|$_PUBLIC_IDENTIFIER_RE(?:=?\$|[.](?!\$)))+?\$");
+
+ /**
+ * The type provider used to access the known types.
+ */
+ final TypeProvider typeProvider;
+
+ /**
+ * The type system. This is used to guess the types of constants when their
+ * exact value is unknown.
+ */
+ final TypeSystem typeSystem;
+
+ /**
+ * The set of variables declared on the command line using '-D'.
+ */
+ final DeclaredVariables _declaredVariables;
+
+ /**
+ * Validator used to verify correct dependency analysis when running unit
+ * tests.
+ */
+ final ConstantEvaluationValidator validator;
+
+ /**
+ * Initialize a newly created [ConstantEvaluationEngine]. The [typeProvider]
+ * is used to access known types. [_declaredVariables] is the set of
+ * variables declared on the command line using '-D'. The [validator], if
+ * given, is used to verify correct dependency analysis when running unit
+ * tests.
+ */
+ ConstantEvaluationEngine(this.typeProvider, this._declaredVariables,
+ {ConstantEvaluationValidator validator, TypeSystem typeSystem})
+ : validator = validator != null
+ ? validator
+ : new ConstantEvaluationValidator_ForProduction(),
+ typeSystem = typeSystem != null ? typeSystem : new TypeSystemImpl();
+
+ /**
+ * Check that the arguments to a call to fromEnvironment() are correct. The
+ * [arguments] are the AST nodes of the arguments. The [argumentValues] are
+ * the values of the unnamed arguments. The [namedArgumentValues] are the
+ * values of the named arguments. The [expectedDefaultValueType] is the
+ * allowed type of the "defaultValue" parameter (if present). Note:
+ * "defaultValue" is always allowed to be null. Return `true` if the arguments
+ * are correct, `false` if there is an error.
+ */
+ bool checkFromEnvironmentArguments(
+ NodeList<Expression> arguments,
+ List<DartObjectImpl> argumentValues,
+ HashMap<String, DartObjectImpl> namedArgumentValues,
+ InterfaceType expectedDefaultValueType) {
+ int argumentCount = arguments.length;
+ if (argumentCount < 1 || argumentCount > 2) {
+ return false;
+ }
+ if (arguments[0] is NamedExpression) {
+ return false;
+ }
+ if (!identical(argumentValues[0].type, typeProvider.stringType)) {
+ return false;
+ }
+ if (argumentCount == 2) {
+ if (arguments[1] is! NamedExpression) {
+ return false;
+ }
+ if (!((arguments[1] as NamedExpression).name.label.name ==
+ _DEFAULT_VALUE_PARAM)) {
+ return false;
+ }
+ ParameterizedType defaultValueType =
+ namedArgumentValues[_DEFAULT_VALUE_PARAM].type;
+ if (!(identical(defaultValueType, expectedDefaultValueType) ||
+ identical(defaultValueType, typeProvider.nullType))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Check that the arguments to a call to Symbol() are correct. The [arguments]
+ * are the AST nodes of the arguments. The [argumentValues] are the values of
+ * the unnamed arguments. The [namedArgumentValues] are the values of the
+ * named arguments. Return `true` if the arguments are correct, `false` if
+ * there is an error.
+ */
+ bool checkSymbolArguments(
+ NodeList<Expression> arguments,
+ List<DartObjectImpl> argumentValues,
+ HashMap<String, DartObjectImpl> namedArgumentValues) {
+ if (arguments.length != 1) {
+ return false;
+ }
+ if (arguments[0] is NamedExpression) {
+ return false;
+ }
+ if (!identical(argumentValues[0].type, typeProvider.stringType)) {
+ return false;
+ }
+ String name = argumentValues[0].toStringValue();
+ return isValidPublicSymbol(name);
+ }
+
+ /**
+ * Compute the constant value associated with the given [constant].
+ */
+ void computeConstantValue(ConstantEvaluationTarget constant) {
+ validator.beforeComputeValue(constant);
+ if (constant is ParameterElementImpl) {
+ Expression defaultValue = constant.constantInitializer;
+ if (defaultValue != null) {
+ RecordingErrorListener errorListener = new RecordingErrorListener();
+ ErrorReporter errorReporter =
+ new ErrorReporter(errorListener, constant.source);
+ DartObjectImpl dartObject =
+ defaultValue.accept(new ConstantVisitor(this, errorReporter));
+ constant.evaluationResult =
+ new EvaluationResultImpl(dartObject, errorListener.errors);
+ }
+ } else if (constant is VariableElementImpl) {
+ Expression constantInitializer = constant.constantInitializer;
+ if (constantInitializer != null) {
+ RecordingErrorListener errorListener = new RecordingErrorListener();
+ ErrorReporter errorReporter =
+ new ErrorReporter(errorListener, constant.source);
+ DartObjectImpl dartObject = constantInitializer
+ .accept(new ConstantVisitor(this, errorReporter));
+ // Only check the type for truly const declarations (don't check final
+ // fields with initializers, since their types may be generic. The type
+ // of the final field will be checked later, when the constructor is
+ // invoked).
+ if (dartObject != null && constant.isConst) {
+ if (!runtimeTypeMatch(dartObject, constant.type)) {
+ errorReporter.reportErrorForElement(
+ CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
+ constant,
+ [dartObject.type, constant.type]);
+ }
+ }
+ constant.evaluationResult =
+ new EvaluationResultImpl(dartObject, errorListener.errors);
+ }
+ } else if (constant is ConstructorElement) {
+ if (constant.isConst) {
+ // No evaluation needs to be done; constructor declarations are only in
+ // the dependency graph to ensure that any constants referred to in
+ // initializer lists and parameter defaults are evaluated before
+ // invocations of the constructor. However we do need to annotate the
+ // element as being free of constant evaluation cycles so that later
+ // code will know that it is safe to evaluate.
+ (constant as ConstructorElementImpl).isCycleFree = true;
+ }
+ } else if (constant is ElementAnnotationImpl) {
+ Annotation constNode = constant.annotationAst;
+ Element element = constant.element;
+ if (element is PropertyAccessorElement &&
+ element.variable is VariableElementImpl) {
+ // The annotation is a reference to a compile-time constant variable.
+ // Just copy the evaluation result.
+ VariableElementImpl variableElement =
+ element.variable as VariableElementImpl;
+ if (variableElement.evaluationResult != null) {
+ constant.evaluationResult = variableElement.evaluationResult;
+ } else {
+ // This could happen in the event that the annotation refers to a
+ // non-constant. The error is detected elsewhere, so just silently
+ // ignore it here.
+ constant.evaluationResult = new EvaluationResultImpl(null);
+ }
+ } else if (element is ConstructorElementImpl &&
+ element.isConst &&
+ constNode.arguments != null) {
+ RecordingErrorListener errorListener = new RecordingErrorListener();
+ ErrorReporter errorReporter =
+ new ErrorReporter(errorListener, constant.source);
+ ConstantVisitor constantVisitor =
+ new ConstantVisitor(this, errorReporter);
+ DartObjectImpl result = evaluateConstructorCall(
+ constNode,
+ constNode.arguments.arguments,
+ element,
+ constantVisitor,
+ errorReporter);
+ constant.evaluationResult =
+ new EvaluationResultImpl(result, errorListener.errors);
+ } else {
+ // This may happen for invalid code (e.g. failing to pass arguments
+ // to an annotation which references a const constructor). The error
+ // is detected elsewhere, so just silently ignore it here.
+ constant.evaluationResult = new EvaluationResultImpl(null);
+ }
+ } else if (constant is VariableElement) {
+ // constant is a VariableElement but not a VariableElementImpl. This can
+ // happen sometimes in the case of invalid user code (for example, a
+ // constant expression that refers to a non-static field inside a generic
+ // class will wind up referring to a FieldMember). The error is detected
+ // elsewhere, so just silently ignore it here.
+ } else {
+ // Should not happen.
+ assert(false);
+ AnalysisEngine.instance.logger.logError(
+ "Constant value computer trying to compute the value of a node of type ${constant.runtimeType}");
+ return;
+ }
+ }
+
+ /**
+ * Determine which constant elements need to have their values computed
+ * prior to computing the value of [constant], and report them using
+ * [callback].
+ */
+ void computeDependencies(
+ ConstantEvaluationTarget constant, ReferenceFinderCallback callback) {
+ ReferenceFinder referenceFinder = new ReferenceFinder(callback);
+ if (constant is ConstructorElement) {
+ constant = getConstructorImpl(constant);
+ }
+ if (constant is VariableElementImpl) {
+ Expression initializer = constant.constantInitializer;
+ if (initializer != null) {
+ initializer.accept(referenceFinder);
+ }
+ } else if (constant is ConstructorElementImpl) {
+ if (constant.isConst) {
+ constant.isCycleFree = false;
+ ConstructorElement redirectedConstructor =
+ getConstRedirectedConstructor(constant);
+ if (redirectedConstructor != null) {
+ ConstructorElement redirectedConstructorBase =
+ getConstructorImpl(redirectedConstructor);
+ callback(redirectedConstructorBase);
+ return;
+ } else if (constant.isFactory) {
+ // Factory constructor, but getConstRedirectedConstructor returned
+ // null. This can happen if we're visiting one of the special external
+ // const factory constructors in the SDK, or if the code contains
+ // errors (such as delegating to a non-const constructor, or delegating
+ // to a constructor that can't be resolved). In any of these cases,
+ // we'll evaluate calls to this constructor without having to refer to
+ // any other constants. So we don't need to report any dependencies.
+ return;
+ }
+ bool superInvocationFound = false;
+ List<ConstructorInitializer> initializers =
+ constant.constantInitializers;
+ for (ConstructorInitializer initializer in initializers) {
+ if (initializer is SuperConstructorInvocation) {
+ superInvocationFound = true;
+ }
+ initializer.accept(referenceFinder);
+ }
+ if (!superInvocationFound) {
+ // No explicit superconstructor invocation found, so we need to
+ // manually insert a reference to the implicit superconstructor.
+ InterfaceType superclass =
+ (constant.returnType as InterfaceType).superclass;
+ if (superclass != null && !superclass.isObject) {
+ ConstructorElement unnamedConstructor =
+ getConstructorImpl(superclass.element.unnamedConstructor);
+ if (unnamedConstructor != null) {
+ callback(unnamedConstructor);
+ }
+ }
+ }
+ for (FieldElement field in constant.enclosingElement.fields) {
+ // Note: non-static const isn't allowed but we handle it anyway so
+ // that we won't be confused by incorrect code.
+ if ((field.isFinal || field.isConst) &&
+ !field.isStatic &&
+ field.initializer != null) {
+ callback(field);
+ }
+ }
+ for (ParameterElement parameterElement in constant.parameters) {
+ callback(parameterElement);
+ }
+ }
+ } else if (constant is ElementAnnotationImpl) {
+ Annotation constNode = constant.annotationAst;
+ Element element = constant.element;
+ if (element is PropertyAccessorElement &&
+ element.variable is VariableElementImpl) {
+ // The annotation is a reference to a compile-time constant variable,
+ // so it depends on the variable.
+ callback(element.variable);
+ } else if (element is ConstructorElementImpl) {
+ // The annotation is a constructor invocation, so it depends on the
+ // constructor.
+ callback(element);
+ } else {
+ // This could happen in the event of invalid code. The error will be
+ // reported at constant evaluation time.
+ }
+ if (constNode.arguments != null) {
+ constNode.arguments.accept(referenceFinder);
+ }
+ } else if (constant is VariableElement) {
+ // constant is a VariableElement but not a VariableElementImpl. This can
+ // happen sometimes in the case of invalid user code (for example, a
+ // constant expression that refers to a non-static field inside a generic
+ // class will wind up referring to a FieldMember). So just don't bother
+ // computing any dependencies.
+ } else {
+ // Should not happen.
+ assert(false);
+ AnalysisEngine.instance.logger.logError(
+ "Constant value computer trying to compute the value of a node of type ${constant.runtimeType}");
+ }
+ }
+
+ /**
+ * Evaluate a call to fromEnvironment() on the bool, int, or String class. The
+ * [environmentValue] is the value fetched from the environment. The
+ * [builtInDefaultValue] is the value that should be used as the default if no
+ * "defaultValue" argument appears in [namedArgumentValues]. The
+ * [namedArgumentValues] are the values of the named parameters passed to
+ * fromEnvironment(). Return a [DartObjectImpl] object corresponding to the
+ * evaluated result.
+ */
+ DartObjectImpl computeValueFromEnvironment(
+ DartObject environmentValue,
+ DartObjectImpl builtInDefaultValue,
+ HashMap<String, DartObjectImpl> namedArgumentValues) {
+ DartObjectImpl value = environmentValue as DartObjectImpl;
+ if (value.isUnknown || value.isNull) {
+ // The name either doesn't exist in the environment or we couldn't parse
+ // the corresponding value.
+ // If the code supplied an explicit default, use it.
+ if (namedArgumentValues.containsKey(_DEFAULT_VALUE_PARAM)) {
+ value = namedArgumentValues[_DEFAULT_VALUE_PARAM];
+ } else if (value.isNull) {
+ // The code didn't supply an explicit default.
+ // The name exists in the environment but we couldn't parse the
+ // corresponding value.
+ // So use the built-in default value, because this is what the VM does.
+ value = builtInDefaultValue;
+ } else {
+ // The code didn't supply an explicit default.
+ // The name doesn't exist in the environment.
+ // The VM would use the built-in default value, but we don't want to do
+ // that for analysis because it's likely to lead to cascading errors.
+ // So just leave [value] in the unknown state.
+ }
+ }
+ return value;
+ }
+
+ DartObjectImpl evaluateConstructorCall(
+ AstNode node,
+ NodeList<Expression> arguments,
+ ConstructorElement constructor,
+ ConstantVisitor constantVisitor,
+ ErrorReporter errorReporter) {
+ if (!getConstructorImpl(constructor).isCycleFree) {
+ // It's not safe to evaluate this constructor, so bail out.
+ // TODO(paulberry): ensure that a reasonable error message is produced
+ // in this case, as well as other cases involving constant expression
+ // circularities (e.g. "compile-time constant expression depends on
+ // itself")
+ return new DartObjectImpl.validWithUnknownValue(constructor.returnType);
+ }
+ int argumentCount = arguments.length;
+ List<DartObjectImpl> argumentValues =
+ new List<DartObjectImpl>(argumentCount);
+ List<Expression> argumentNodes = new List<Expression>(argumentCount);
+ HashMap<String, DartObjectImpl> namedArgumentValues =
+ new HashMap<String, DartObjectImpl>();
+ HashMap<String, NamedExpression> namedArgumentNodes =
+ new HashMap<String, NamedExpression>();
+ for (int i = 0; i < argumentCount; i++) {
+ Expression argument = arguments[i];
+ if (argument is NamedExpression) {
+ String name = argument.name.label.name;
+ namedArgumentValues[name] =
+ constantVisitor._valueOf(argument.expression);
+ namedArgumentNodes[name] = argument;
+ argumentValues[i] = typeProvider.nullObject;
+ } else {
+ argumentValues[i] = constantVisitor._valueOf(argument);
+ argumentNodes[i] = argument;
+ }
+ }
+ constructor = followConstantRedirectionChain(constructor);
+ InterfaceType definingClass = constructor.returnType as InterfaceType;
+ if (constructor.isFactory) {
+ // We couldn't find a non-factory constructor.
+ // See if it's because we reached an external const factory constructor
+ // that we can emulate.
+ if (constructor.name == "fromEnvironment") {
+ if (!checkFromEnvironmentArguments(
+ arguments, argumentValues, namedArgumentValues, definingClass)) {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
+ return null;
+ }
+ String variableName =
+ argumentCount < 1 ? null : argumentValues[0].toStringValue();
+ if (identical(definingClass, typeProvider.boolType)) {
+ DartObject valueFromEnvironment;
+ valueFromEnvironment =
+ _declaredVariables.getBool(typeProvider, variableName);
+ return computeValueFromEnvironment(
+ valueFromEnvironment,
+ new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE),
+ namedArgumentValues);
+ } else if (identical(definingClass, typeProvider.intType)) {
+ DartObject valueFromEnvironment;
+ valueFromEnvironment =
+ _declaredVariables.getInt(typeProvider, variableName);
+ return computeValueFromEnvironment(
+ valueFromEnvironment,
+ new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
+ namedArgumentValues);
+ } else if (identical(definingClass, typeProvider.stringType)) {
+ DartObject valueFromEnvironment;
+ valueFromEnvironment =
+ _declaredVariables.getString(typeProvider, variableName);
+ return computeValueFromEnvironment(
+ valueFromEnvironment,
+ new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
+ namedArgumentValues);
+ }
+ } else if (constructor.name == "" &&
+ identical(definingClass, typeProvider.symbolType) &&
+ argumentCount == 1) {
+ if (!checkSymbolArguments(
+ arguments, argumentValues, namedArgumentValues)) {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
+ return null;
+ }
+ String argumentValue = argumentValues[0].toStringValue();
+ return new DartObjectImpl(
+ definingClass, new SymbolState(argumentValue));
+ }
+ // Either it's an external const factory constructor that we can't
+ // emulate, or an error occurred (a cycle, or a const constructor trying
+ // to delegate to a non-const constructor).
+ // In the former case, the best we can do is consider it an unknown value.
+ // In the latter case, the error has already been reported, so considering
+ // it an unknown value will suppress further errors.
+ return new DartObjectImpl.validWithUnknownValue(definingClass);
+ }
+ ConstructorElementImpl constructorBase = getConstructorImpl(constructor);
+ validator.beforeGetConstantInitializers(constructorBase);
+ List<ConstructorInitializer> initializers =
+ constructorBase.constantInitializers;
+ if (initializers == null) {
+ // This can happen in some cases where there are compile errors in the
+ // code being analyzed (for example if the code is trying to create a
+ // const instance using a non-const constructor, or the node we're
+ // visiting is involved in a cycle). The error has already been reported,
+ // so consider it an unknown value to suppress further errors.
+ return new DartObjectImpl.validWithUnknownValue(definingClass);
+ }
+ HashMap<String, DartObjectImpl> fieldMap =
+ new HashMap<String, DartObjectImpl>();
+ // Start with final fields that are initialized at their declaration site.
+ for (FieldElement field in constructor.enclosingElement.fields) {
+ if ((field.isFinal || field.isConst) &&
+ !field.isStatic &&
+ field is ConstFieldElementImpl) {
+ validator.beforeGetFieldEvaluationResult(field);
+ EvaluationResultImpl evaluationResult = field.evaluationResult;
+ // It is possible that the evaluation result is null.
+ // This happens for example when we have duplicate fields.
+ // class Test {final x = 1; final x = 2; const Test();}
+ if (evaluationResult == null) {
+ continue;
+ }
+ // Match the value and the type.
+ DartType fieldType =
+ FieldMember.from(field, constructor.returnType).type;
+ DartObjectImpl fieldValue = evaluationResult.value;
+ if (fieldValue != null && !runtimeTypeMatch(fieldValue, fieldType)) {
+ errorReporter.reportErrorForNode(
+ CheckedModeCompileTimeErrorCode
+ .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
+ node,
+ [fieldValue.type, field.name, fieldType]);
+ }
+ fieldMap[field.name] = fieldValue;
+ }
+ }
+ // Now evaluate the constructor declaration.
+ HashMap<String, DartObjectImpl> parameterMap =
+ new HashMap<String, DartObjectImpl>();
+ List<ParameterElement> parameters = constructor.parameters;
+ int parameterCount = parameters.length;
+ for (int i = 0; i < parameterCount; i++) {
+ ParameterElement parameter = parameters[i];
+ ParameterElement baseParameter = parameter;
+ while (baseParameter is ParameterMember) {
+ baseParameter = (baseParameter as ParameterMember).baseElement;
+ }
+ DartObjectImpl argumentValue = null;
+ AstNode errorTarget = null;
+ if (baseParameter.parameterKind == ParameterKind.NAMED) {
+ argumentValue = namedArgumentValues[baseParameter.name];
+ errorTarget = namedArgumentNodes[baseParameter.name];
+ } else if (i < argumentCount) {
+ argumentValue = argumentValues[i];
+ errorTarget = argumentNodes[i];
+ }
+ if (errorTarget == null) {
+ // No argument node that we can direct error messages to, because we
+ // are handling an optional parameter that wasn't specified. So just
+ // direct error messages to the constructor call.
+ errorTarget = node;
+ }
+ if (argumentValue == null && baseParameter is ParameterElementImpl) {
+ // The parameter is an optional positional parameter for which no value
+ // was provided, so use the default value.
+ validator.beforeGetParameterDefault(baseParameter);
+ EvaluationResultImpl evaluationResult = baseParameter.evaluationResult;
+ if (evaluationResult == null) {
+ // No default was provided, so the default value is null.
+ argumentValue = typeProvider.nullObject;
+ } else if (evaluationResult.value != null) {
+ argumentValue = evaluationResult.value;
+ }
+ }
+ if (argumentValue != null) {
+ if (!runtimeTypeMatch(argumentValue, parameter.type)) {
+ errorReporter.reportErrorForNode(
+ CheckedModeCompileTimeErrorCode
+ .CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+ errorTarget,
+ [argumentValue.type, parameter.type]);
+ }
+ if (baseParameter.isInitializingFormal) {
+ FieldElement field = (parameter as FieldFormalParameterElement).field;
+ if (field != null) {
+ DartType fieldType = field.type;
+ if (fieldType != parameter.type) {
+ // We've already checked that the argument can be assigned to the
+ // parameter; we also need to check that it can be assigned to
+ // the field.
+ if (!runtimeTypeMatch(argumentValue, fieldType)) {
+ errorReporter.reportErrorForNode(
+ CheckedModeCompileTimeErrorCode
+ .CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+ errorTarget,
+ [argumentValue.type, fieldType]);
+ }
+ }
+ String fieldName = field.name;
+ if (fieldMap.containsKey(fieldName)) {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
+ }
+ fieldMap[fieldName] = argumentValue;
+ }
+ } else {
+ String name = baseParameter.name;
+ parameterMap[name] = argumentValue;
+ }
+ }
+ }
+ ConstantVisitor initializerVisitor = new ConstantVisitor(
+ this, errorReporter,
+ lexicalEnvironment: parameterMap);
+ String superName = null;
+ NodeList<Expression> superArguments = null;
+ for (ConstructorInitializer initializer in initializers) {
+ if (initializer is ConstructorFieldInitializer) {
+ ConstructorFieldInitializer constructorFieldInitializer = initializer;
+ Expression initializerExpression =
+ constructorFieldInitializer.expression;
+ DartObjectImpl evaluationResult =
+ initializerExpression.accept(initializerVisitor);
+ if (evaluationResult != null) {
+ String fieldName = constructorFieldInitializer.fieldName.name;
+ if (fieldMap.containsKey(fieldName)) {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
+ }
+ fieldMap[fieldName] = evaluationResult;
+ PropertyAccessorElement getter = definingClass.getGetter(fieldName);
+ if (getter != null) {
+ PropertyInducingElement field = getter.variable;
+ if (!runtimeTypeMatch(evaluationResult, field.type)) {
+ errorReporter.reportErrorForNode(
+ CheckedModeCompileTimeErrorCode
+ .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
+ node,
+ [evaluationResult.type, fieldName, field.type]);
+ }
+ }
+ }
+ } else if (initializer is SuperConstructorInvocation) {
+ SuperConstructorInvocation superConstructorInvocation = initializer;
+ SimpleIdentifier name = superConstructorInvocation.constructorName;
+ if (name != null) {
+ superName = name.name;
+ }
+ superArguments = superConstructorInvocation.argumentList.arguments;
+ } else if (initializer is RedirectingConstructorInvocation) {
+ // This is a redirecting constructor, so just evaluate the constructor
+ // it redirects to.
+ ConstructorElement constructor = initializer.staticElement;
+ if (constructor != null && constructor.isConst) {
+ return evaluateConstructorCall(
+ node,
+ initializer.argumentList.arguments,
+ constructor,
+ initializerVisitor,
+ errorReporter);
+ }
+ }
+ }
+ // Evaluate explicit or implicit call to super().
+ InterfaceType superclass = definingClass.superclass;
+ if (superclass != null && !superclass.isObject) {
+ ConstructorElement superConstructor =
+ superclass.lookUpConstructor(superName, constructor.library);
+ if (superConstructor != null) {
+ if (superArguments == null) {
+ superArguments = new NodeList<Expression>(null);
+ }
+ evaluateSuperConstructorCall(node, fieldMap, superConstructor,
+ superArguments, initializerVisitor, errorReporter);
+ }
+ }
+ return new DartObjectImpl(definingClass, new GenericState(fieldMap));
+ }
+
+ void evaluateSuperConstructorCall(
+ AstNode node,
+ HashMap<String, DartObjectImpl> fieldMap,
+ ConstructorElement superConstructor,
+ NodeList<Expression> superArguments,
+ ConstantVisitor initializerVisitor,
+ ErrorReporter errorReporter) {
+ if (superConstructor != null && superConstructor.isConst) {
+ DartObjectImpl evaluationResult = evaluateConstructorCall(node,
+ superArguments, superConstructor, initializerVisitor, errorReporter);
+ if (evaluationResult != null) {
+ fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult;
+ }
+ }
+ }
+
+ /**
+ * Attempt to follow the chain of factory redirections until a constructor is
+ * reached which is not a const factory constructor. Return the constant
+ * constructor which terminates the chain of factory redirections, if the
+ * chain terminates. If there is a problem (e.g. a redirection can't be found,
+ * or a cycle is encountered), the chain will be followed as far as possible
+ * and then a const factory constructor will be returned.
+ */
+ ConstructorElement followConstantRedirectionChain(
+ ConstructorElement constructor) {
+ HashSet<ConstructorElement> constructorsVisited =
+ new HashSet<ConstructorElement>();
+ while (true) {
+ ConstructorElement redirectedConstructor =
+ getConstRedirectedConstructor(constructor);
+ if (redirectedConstructor == null) {
+ break;
+ } else {
+ ConstructorElement constructorBase = getConstructorImpl(constructor);
+ constructorsVisited.add(constructorBase);
+ ConstructorElement redirectedConstructorBase =
+ getConstructorImpl(redirectedConstructor);
+ if (constructorsVisited.contains(redirectedConstructorBase)) {
+ // Cycle in redirecting factory constructors--this is not allowed
+ // and is checked elsewhere--see
+ // [ErrorVerifier.checkForRecursiveFactoryRedirect()]).
+ break;
+ }
+ }
+ constructor = redirectedConstructor;
+ }
+ return constructor;
+ }
+
+ /**
+ * Generate an error indicating that the given [constant] is not a valid
+ * compile-time constant because it references at least one of the constants
+ * in the given [cycle], each of which directly or indirectly references the
+ * constant.
+ */
+ void generateCycleError(Iterable<ConstantEvaluationTarget> cycle,
+ ConstantEvaluationTarget constant) {
+ if (constant is VariableElement) {
+ RecordingErrorListener errorListener = new RecordingErrorListener();
+ ErrorReporter errorReporter =
+ new ErrorReporter(errorListener, constant.source);
+ // TODO(paulberry): It would be really nice if we could extract enough
+ // information from the 'cycle' argument to provide the user with a
+ // description of the cycle.
+ errorReporter.reportErrorForElement(
+ CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT, constant, []);
+ (constant as VariableElementImpl).evaluationResult =
+ new EvaluationResultImpl(null, errorListener.errors);
+ } else if (constant is ConstructorElement) {
+ // We don't report cycle errors on constructor declarations since there
+ // is nowhere to put the error information.
+ } else {
+ // Should not happen. Formal parameter defaults and annotations should
+ // never appear as part of a cycle because they can't be referred to.
+ assert(false);
+ AnalysisEngine.instance.logger.logError(
+ "Constant value computer trying to report a cycle error for a node of type ${constant.runtimeType}");
+ }
+ }
+
+ /**
+ * If [constructor] redirects to another const constructor, return the
+ * const constructor it redirects to. Otherwise return `null`.
+ */
+ ConstructorElement getConstRedirectedConstructor(
+ ConstructorElement constructor) {
+ if (!constructor.isFactory) {
+ return null;
+ }
+ if (identical(constructor.enclosingElement.type, typeProvider.symbolType)) {
+ // The dart:core.Symbol has a const factory constructor that redirects
+ // to dart:_internal.Symbol. That in turn redirects to an external
+ // const constructor, which we won't be able to evaluate.
+ // So stop following the chain of redirections at dart:core.Symbol, and
+ // let [evaluateInstanceCreationExpression] handle it specially.
+ return null;
+ }
+ ConstructorElement redirectedConstructor =
+ constructor.redirectedConstructor;
+ if (redirectedConstructor == null) {
+ // This can happen if constructor is an external factory constructor.
+ return null;
+ }
+ if (!redirectedConstructor.isConst) {
+ // Delegating to a non-const constructor--this is not allowed (and
+ // is checked elsewhere--see
+ // [ErrorVerifier.checkForRedirectToNonConstConstructor()]).
+ return null;
+ }
+ return redirectedConstructor;
+ }
+
+ /**
+ * Check if the object [obj] matches the type [type] according to runtime type
+ * checking rules.
+ */
+ bool runtimeTypeMatch(DartObjectImpl obj, DartType type) {
+ if (obj.isNull) {
+ return true;
+ }
+ if (type.isUndefined) {
+ return false;
+ }
+ return obj.type.isSubtypeOf(type);
+ }
+
+ /**
+ * Determine whether the given string is a valid name for a public symbol
+ * (i.e. whether it is allowed for a call to the Symbol constructor).
+ */
+ static bool isValidPublicSymbol(String name) =>
+ name.isEmpty ||
+ name == "void" ||
+ new JavaPatternMatcher(_PUBLIC_SYMBOL_PATTERN, name).matches();
+}
+
+/**
+ * Interface used by unit tests to verify correct dependency analysis during
+ * constant evaluation.
+ */
+abstract class ConstantEvaluationValidator {
+ /**
+ * This method is called just before computing the constant value associated
+ * with [constant]. Unit tests will override this method to introduce
+ * additional error checking.
+ */
+ void beforeComputeValue(ConstantEvaluationTarget constant);
+
+ /**
+ * This method is called just before getting the constant initializers
+ * associated with the [constructor]. Unit tests will override this method to
+ * introduce additional error checking.
+ */
+ void beforeGetConstantInitializers(ConstructorElement constructor);
+
+ /**
+ * This method is called just before retrieving an evaluation result from an
+ * element. Unit tests will override it to introduce additional error
+ * checking.
+ */
+ void beforeGetEvaluationResult(ConstantEvaluationTarget constant);
+
+ /**
+ * This method is called just before getting the constant value of a field
+ * with an initializer. Unit tests will override this method to introduce
+ * additional error checking.
+ */
+ void beforeGetFieldEvaluationResult(FieldElementImpl field);
+
+ /**
+ * This method is called just before getting a parameter's default value. Unit
+ * tests will override this method to introduce additional error checking.
+ */
+ void beforeGetParameterDefault(ParameterElement parameter);
+}
+
+/**
+ * Implementation of [ConstantEvaluationValidator] used in production; does no
+ * validation.
+ */
+class ConstantEvaluationValidator_ForProduction
+ implements ConstantEvaluationValidator {
+ @override
+ void beforeComputeValue(ConstantEvaluationTarget constant) {}
+
+ @override
+ void beforeGetConstantInitializers(ConstructorElement constructor) {}
+
+ @override
+ void beforeGetEvaluationResult(ConstantEvaluationTarget constant) {}
+
+ @override
+ void beforeGetFieldEvaluationResult(FieldElementImpl field) {}
+
+ @override
+ void beforeGetParameterDefault(ParameterElement parameter) {}
+}
+
+/**
+ * An object used to compute the values of constant variables and constant
+ * constructor invocations in one or more compilation units. The expected usage
+ * pattern is for the compilation units to be added to this computer using the
+ * method [add] and then for the method [computeValues] to be invoked exactly
+ * once. Any use of an instance after invoking the method [computeValues] will
+ * result in unpredictable behavior.
+ */
+class ConstantValueComputer {
+ /**
+ * Source of RegExp matching declarable operator names.
+ * From sdk/lib/internal/symbol.dart.
+ */
+ static String _OPERATOR_RE =
+ "(?:[\\-+*/%&|^]|\\[\\]=?|==|~/?|<[<=]?|>[>=]?|unary-)";
+
+ /**
+ * Source of RegExp matching Dart reserved words.
+ * From sdk/lib/internal/symbol.dart.
+ */
+ static String _RESERVED_WORD_RE =
+ "(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|d(?:efault|o)|e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?:ew|ull)|ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|r(?:ue|y))|v(?:ar|oid)|w(?:hile|ith))";
+
+ /**
+ * A graph in which the nodes are the constants, and the edges are from each
+ * constant to the other constants that are referenced by it.
+ */
+ DirectedGraph<ConstantEvaluationTarget> referenceGraph =
+ new DirectedGraph<ConstantEvaluationTarget>();
+
+ /**
+ * The elements whose constant values need to be computed. Any elements
+ * which appear in [referenceGraph] but not in this set either belong to a
+ * different library cycle (and hence don't need to be recomputed) or were
+ * computed during a previous stage of resolution stage (e.g. constants
+ * associated with enums).
+ */
+ HashSet<ConstantEvaluationTarget> _constantsToCompute =
+ new HashSet<ConstantEvaluationTarget>();
+
+ /**
+ * The evaluation engine that does the work of evaluating instance creation
+ * expressions.
+ */
+ final ConstantEvaluationEngine evaluationEngine;
+
+ final AnalysisContext _context;
+
+ /**
+ * Initialize a newly created constant value computer. The [typeProvider] is
+ * the type provider used to access known types. The [declaredVariables] is
+ * the set of variables declared on the command line using '-D'.
+ */
+ ConstantValueComputer(this._context, TypeProvider typeProvider,
+ DeclaredVariables declaredVariables,
+ [ConstantEvaluationValidator validator, TypeSystem typeSystem])
+ : evaluationEngine = new ConstantEvaluationEngine(
+ typeProvider, declaredVariables,
+ validator: validator, typeSystem: typeSystem);
+
+ /**
+ * Add the constants in the given compilation [unit] to the list of constants
+ * whose value needs to be computed.
+ */
+ void add(CompilationUnit unit, Source source, Source librarySource) {
+ ConstantFinder constantFinder =
+ new ConstantFinder(_context, source, librarySource);
+ unit.accept(constantFinder);
+ _constantsToCompute.addAll(constantFinder.constantsToCompute);
+ }
+
+ /**
+ * Compute values for all of the constants in the compilation units that were
+ * added.
+ */
+ void computeValues() {
+ for (ConstantEvaluationTarget constant in _constantsToCompute) {
+ referenceGraph.addNode(constant);
+ evaluationEngine.computeDependencies(constant,
+ (ConstantEvaluationTarget dependency) {
+ referenceGraph.addEdge(constant, dependency);
+ });
+ }
+ List<List<ConstantEvaluationTarget>> topologicalSort =
+ referenceGraph.computeTopologicalSort();
+ for (List<ConstantEvaluationTarget> constantsInCycle in topologicalSort) {
+ if (constantsInCycle.length == 1) {
+ ConstantEvaluationTarget constant = constantsInCycle[0];
+ if (!referenceGraph.getTails(constant).contains(constant)) {
+ _computeValueFor(constant);
+ continue;
+ }
+ }
+ for (ConstantEvaluationTarget constant in constantsInCycle) {
+ evaluationEngine.generateCycleError(constantsInCycle, constant);
+ }
+ }
+ }
+
+ /**
+ * Compute a value for the given [constant].
+ */
+ void _computeValueFor(ConstantEvaluationTarget constant) {
+ if (!_constantsToCompute.contains(constant)) {
+ // Element is in the dependency graph but should have been computed by
+ // a previous stage of analysis.
+ // TODO(paulberry): once we have moved over to the new task model, this
+ // should only occur for constants associated with enum members. Once
+ // that happens we should add an assertion to verify that it doesn't
+ // occur in any other cases.
+ return;
+ }
+ evaluationEngine.computeConstantValue(constant);
+ }
+}
+
+/**
+ * A visitor used to evaluate constant expressions to produce their compile-time
+ * value. According to the Dart Language Specification: <blockquote> A constant
+ * expression is one of the following:
+ *
+ * * A literal number.
+ * * A literal boolean.
+ * * A literal string where any interpolated expression is a compile-time
+ * constant that evaluates to a numeric, string or boolean value or to
+ * <b>null</b>.
+ * * A literal symbol.
+ * * <b>null</b>.
+ * * A qualified reference to a static constant variable.
+ * * An identifier expression that denotes a constant variable, class or type
+ * alias.
+ * * A constant constructor invocation.
+ * * A constant list literal.
+ * * A constant map literal.
+ * * A simple or qualified identifier denoting a top-level function or a static
+ * method.
+ * * A parenthesized expression <i>(e)</i> where <i>e</i> is a constant
+ * expression.
+ * * An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i>
+ * where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
+ * expressions and <i>identical()</i> is statically bound to the predefined
+ * dart function <i>identical()</i> discussed above.
+ * * An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> or
+ * <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and
+ * <i>e<sub>2</sub></i> are constant expressions that evaluate to a numeric,
+ * string or boolean value.
+ * * An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &&
+ * e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where <i>e</i>,
+ * <i>e1</sub></i> and <i>e2</sub></i> are constant expressions that evaluate
+ * to a boolean value.
+ * * An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^
+ * e<sub>2</sub></i>, <i>e<sub>1</sub> & e<sub>2</sub></i>,
+ * <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> >>
+ * e<sub>2</sub></i> or <i>e<sub>1</sub> << e<sub>2</sub></i>, where
+ * <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
+ * expressions that evaluate to an integer value or to <b>null</b>.
+ * * An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> +
+ * e<sub>2</sub></i>, <i>e<sub>1</sub> - e<sub>2</sub></i>, <i>e<sub>1</sub> *
+ * e<sub>2</sub></i>, <i>e<sub>1</sub> / e<sub>2</sub></i>, <i>e<sub>1</sub>
+ * ~/ e<sub>2</sub></i>, <i>e<sub>1</sub> > e<sub>2</sub></i>,
+ * <i>e<sub>1</sub> < e<sub>2</sub></i>, <i>e<sub>1</sub> >=
+ * e<sub>2</sub></i>, <i>e<sub>1</sub> <= e<sub>2</sub></i> or
+ * <i>e<sub>1</sub> % e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i>
+ * and <i>e<sub>2</sub></i> are constant expressions that evaluate to a
+ * numeric value or to <b>null</b>.
+ * * An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
+ * e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
+ * <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
+ * evaluates to a boolean value.
+ * </blockquote>
+ */
+class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
+ /**
+ * The type provider used to access the known types.
+ */
+ final ConstantEvaluationEngine evaluationEngine;
+
+ final HashMap<String, DartObjectImpl> _lexicalEnvironment;
+
+ /**
+ * Error reporter that we use to report errors accumulated while computing the
+ * constant.
+ */
+ final ErrorReporter _errorReporter;
+
+ /**
+ * Helper class used to compute constant values.
+ */
+ DartObjectComputer _dartObjectComputer;
+
+ /**
+ * Initialize a newly created constant visitor. The [evaluationEngine] is
+ * used to evaluate instance creation expressions. The [lexicalEnvironment]
+ * is a map containing values which should override identifiers, or `null` if
+ * no overriding is necessary. The [_errorReporter] is used to report errors
+ * found during evaluation. The [validator] is used by unit tests to verify
+ * correct dependency analysis.
+ */
+ ConstantVisitor(this.evaluationEngine, this._errorReporter,
+ {HashMap<String, DartObjectImpl> lexicalEnvironment})
+ : _lexicalEnvironment = lexicalEnvironment {
+ this._dartObjectComputer =
+ new DartObjectComputer(_errorReporter, evaluationEngine.typeProvider);
+ }
+
+ /**
+ * Convenience getter to gain access to the [evalationEngine]'s type
+ * provider.
+ */
+ TypeProvider get _typeProvider => evaluationEngine.typeProvider;
+
+ /**
+ * Convenience getter to gain access to the [evaluationEngine]'s type system.
+ */
+ TypeSystem get _typeSystem => evaluationEngine.typeSystem;
+
+ @override
+ DartObjectImpl visitAdjacentStrings(AdjacentStrings node) {
+ DartObjectImpl result = null;
+ for (StringLiteral string in node.strings) {
+ if (result == null) {
+ result = string.accept(this);
+ } else {
+ result =
+ _dartObjectComputer.concatenate(node, result, string.accept(this));
+ }
+ }
+ return result;
+ }
+
+ @override
+ DartObjectImpl visitBinaryExpression(BinaryExpression node) {
+ DartObjectImpl leftResult = node.leftOperand.accept(this);
+ DartObjectImpl rightResult = node.rightOperand.accept(this);
+ TokenType operatorType = node.operator.type;
+ // 'null' is almost never good operand
+ if (operatorType != TokenType.BANG_EQ &&
+ operatorType != TokenType.EQ_EQ &&
+ operatorType != TokenType.QUESTION_QUESTION) {
+ if (leftResult != null && leftResult.isNull ||
+ rightResult != null && rightResult.isNull) {
+ _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ return null;
+ }
+ }
+ // evaluate operator
+ while (true) {
+ if (operatorType == TokenType.AMPERSAND) {
+ return _dartObjectComputer.bitAnd(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
+ return _dartObjectComputer.logicalAnd(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.BANG_EQ) {
+ return _dartObjectComputer.notEqual(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.BAR) {
+ return _dartObjectComputer.bitOr(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.BAR_BAR) {
+ return _dartObjectComputer.logicalOr(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.CARET) {
+ return _dartObjectComputer.bitXor(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.EQ_EQ) {
+ return _dartObjectComputer.equalEqual(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.GT) {
+ return _dartObjectComputer.greaterThan(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.GT_EQ) {
+ return _dartObjectComputer.greaterThanOrEqual(
+ node, leftResult, rightResult);
+ } else if (operatorType == TokenType.GT_GT) {
+ return _dartObjectComputer.shiftRight(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.LT) {
+ return _dartObjectComputer.lessThan(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.LT_EQ) {
+ return _dartObjectComputer.lessThanOrEqual(
+ node, leftResult, rightResult);
+ } else if (operatorType == TokenType.LT_LT) {
+ return _dartObjectComputer.shiftLeft(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.MINUS) {
+ return _dartObjectComputer.minus(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.PERCENT) {
+ return _dartObjectComputer.remainder(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.PLUS) {
+ return _dartObjectComputer.add(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.STAR) {
+ return _dartObjectComputer.times(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.SLASH) {
+ return _dartObjectComputer.divide(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.TILDE_SLASH) {
+ return _dartObjectComputer.integerDivide(node, leftResult, rightResult);
+ } else if (operatorType == TokenType.QUESTION_QUESTION) {
+ return _dartObjectComputer.questionQuestion(
+ node, leftResult, rightResult);
+ } else {
+ // TODO(brianwilkerson) Figure out which error to report.
+ _error(node, null);
+ return null;
+ }
+ break;
+ }
+ }
+
+ @override
+ DartObjectImpl visitBooleanLiteral(BooleanLiteral node) =>
+ new DartObjectImpl(_typeProvider.boolType, BoolState.from(node.value));
+
+ @override
+ DartObjectImpl visitConditionalExpression(ConditionalExpression node) {
+ Expression condition = node.condition;
+ DartObjectImpl conditionResult = condition.accept(this);
+ DartObjectImpl thenResult = node.thenExpression.accept(this);
+ DartObjectImpl elseResult = node.elseExpression.accept(this);
+ if (conditionResult == null) {
+ return conditionResult;
+ } else if (!conditionResult.isBool) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, condition);
+ return null;
+ } else if (thenResult == null) {
+ return thenResult;
+ } else if (elseResult == null) {
+ return elseResult;
+ }
+ conditionResult =
+ _dartObjectComputer.applyBooleanConversion(condition, conditionResult);
+ if (conditionResult == null) {
+ return conditionResult;
+ }
+ if (conditionResult.toBoolValue() == true) {
+ return thenResult;
+ } else if (conditionResult.toBoolValue() == false) {
+ return elseResult;
+ }
+ ParameterizedType thenType = thenResult.type;
+ ParameterizedType elseType = elseResult.type;
+ return new DartObjectImpl.validWithUnknownValue(
+ _typeSystem.getLeastUpperBound(_typeProvider, thenType, elseType)
+ as InterfaceType);
+ }
+
+ @override
+ DartObjectImpl visitDoubleLiteral(DoubleLiteral node) =>
+ new DartObjectImpl(_typeProvider.doubleType, new DoubleState(node.value));
+
+ @override
+ DartObjectImpl visitInstanceCreationExpression(
+ InstanceCreationExpression node) {
+ if (!node.isConst) {
+ // TODO(brianwilkerson) Figure out which error to report.
+ _error(node, null);
+ return null;
+ }
+ ConstructorElement constructor = node.staticElement;
+ if (constructor == null) {
+ // Couldn't resolve the constructor so we can't compute a value. No
+ // problem - the error has already been reported.
+ return null;
+ }
+ return evaluationEngine.evaluateConstructorCall(
+ node, node.argumentList.arguments, constructor, this, _errorReporter);
+ }
+
+ @override
+ DartObjectImpl visitIntegerLiteral(IntegerLiteral node) =>
+ new DartObjectImpl(_typeProvider.intType, new IntState(node.value));
+
+ @override
+ DartObjectImpl visitInterpolationExpression(InterpolationExpression node) {
+ DartObjectImpl result = node.expression.accept(this);
+ if (result != null && !result.isBoolNumStringOrNull) {
+ _error(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
+ return null;
+ }
+ return _dartObjectComputer.performToString(node, result);
+ }
+
+ @override
+ DartObjectImpl visitInterpolationString(InterpolationString node) =>
+ new DartObjectImpl(_typeProvider.stringType, new StringState(node.value));
+
+ @override
+ DartObjectImpl visitListLiteral(ListLiteral node) {
+ if (node.constKeyword == null) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL, node);
+ return null;
+ }
+ bool errorOccurred = false;
+ List<DartObjectImpl> elements = new List<DartObjectImpl>();
+ for (Expression element in node.elements) {
+ DartObjectImpl elementResult = element.accept(this);
+ if (elementResult == null) {
+ errorOccurred = true;
+ } else {
+ elements.add(elementResult);
+ }
+ }
+ if (errorOccurred) {
+ return null;
+ }
+ DartType elementType = _typeProvider.dynamicType;
+ if (node.typeArguments != null &&
+ node.typeArguments.arguments.length == 1) {
+ DartType type = node.typeArguments.arguments[0].type;
+ if (type != null) {
+ elementType = type;
+ }
+ }
+ InterfaceType listType = _typeProvider.listType.instantiate([elementType]);
+ return new DartObjectImpl(listType, new ListState(elements));
+ }
+
+ @override
+ DartObjectImpl visitMapLiteral(MapLiteral node) {
+ if (node.constKeyword == null) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL, node);
+ return null;
+ }
+ bool errorOccurred = false;
+ LinkedHashMap<DartObjectImpl, DartObjectImpl> map =
+ new LinkedHashMap<DartObjectImpl, DartObjectImpl>();
+ for (MapLiteralEntry entry in node.entries) {
+ DartObjectImpl keyResult = entry.key.accept(this);
+ DartObjectImpl valueResult = entry.value.accept(this);
+ if (keyResult == null || valueResult == null) {
+ errorOccurred = true;
+ } else {
+ map[keyResult] = valueResult;
+ }
+ }
+ if (errorOccurred) {
+ return null;
+ }
+ DartType keyType = _typeProvider.dynamicType;
+ DartType valueType = _typeProvider.dynamicType;
+ if (node.typeArguments != null &&
+ node.typeArguments.arguments.length == 2) {
+ DartType keyTypeCandidate = node.typeArguments.arguments[0].type;
+ if (keyTypeCandidate != null) {
+ keyType = keyTypeCandidate;
+ }
+ DartType valueTypeCandidate = node.typeArguments.arguments[1].type;
+ if (valueTypeCandidate != null) {
+ valueType = valueTypeCandidate;
+ }
+ }
+ InterfaceType mapType =
+ _typeProvider.mapType.instantiate([keyType, valueType]);
+ return new DartObjectImpl(mapType, new MapState(map));
+ }
+
+ @override
+ DartObjectImpl visitMethodInvocation(MethodInvocation node) {
+ Element element = node.methodName.staticElement;
+ if (element is FunctionElement) {
+ FunctionElement function = element;
+ if (function.name == "identical") {
+ NodeList<Expression> arguments = node.argumentList.arguments;
+ if (arguments.length == 2) {
+ Element enclosingElement = function.enclosingElement;
+ if (enclosingElement is CompilationUnitElement) {
+ LibraryElement library = enclosingElement.library;
+ if (library.isDartCore) {
+ DartObjectImpl leftArgument = arguments[0].accept(this);
+ DartObjectImpl rightArgument = arguments[1].accept(this);
+ return _dartObjectComputer.isIdentical(
+ node, leftArgument, rightArgument);
+ }
+ }
+ }
+ }
+ }
+ // TODO(brianwilkerson) Figure out which error to report.
+ _error(node, null);
+ return null;
+ }
+
+ @override
+ DartObjectImpl visitNamedExpression(NamedExpression node) =>
+ node.expression.accept(this);
+
+ @override
+ DartObjectImpl visitNode(AstNode node) {
+ // TODO(brianwilkerson) Figure out which error to report.
+ _error(node, null);
+ return null;
+ }
+
+ @override
+ DartObjectImpl visitNullLiteral(NullLiteral node) => _typeProvider.nullObject;
+
+ @override
+ DartObjectImpl visitParenthesizedExpression(ParenthesizedExpression node) =>
+ node.expression.accept(this);
+
+ @override
+ DartObjectImpl visitPrefixedIdentifier(PrefixedIdentifier node) {
+ SimpleIdentifier prefixNode = node.prefix;
+ Element prefixElement = prefixNode.staticElement;
+ // String.length
+ if (prefixElement is! PrefixElement && prefixElement is! ClassElement) {
+ DartObjectImpl prefixResult = node.prefix.accept(this);
+ if (_isStringLength(prefixResult, node.identifier)) {
+ return prefixResult.stringLength(_typeProvider);
+ }
+ }
+ // importPrefix.CONST
+ if (prefixElement is! PrefixElement) {
+ DartObjectImpl prefixResult = prefixNode.accept(this);
+ if (prefixResult == null) {
+ // The error has already been reported.
+ return null;
+ }
+ }
+ // validate prefixed identifier
+ return _getConstantValue(node, node.staticElement);
+ }
+
+ @override
+ DartObjectImpl visitPrefixExpression(PrefixExpression node) {
+ DartObjectImpl operand = node.operand.accept(this);
+ if (operand != null && operand.isNull) {
+ _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ return null;
+ }
+ while (true) {
+ if (node.operator.type == TokenType.BANG) {
+ return _dartObjectComputer.logicalNot(node, operand);
+ } else if (node.operator.type == TokenType.TILDE) {
+ return _dartObjectComputer.bitNot(node, operand);
+ } else if (node.operator.type == TokenType.MINUS) {
+ return _dartObjectComputer.negated(node, operand);
+ } else {
+ // TODO(brianwilkerson) Figure out which error to report.
+ _error(node, null);
+ return null;
+ }
+ break;
+ }
+ }
+
+ @override
+ DartObjectImpl visitPropertyAccess(PropertyAccess node) {
+ if (node.target != null) {
+ DartObjectImpl prefixResult = node.target.accept(this);
+ if (_isStringLength(prefixResult, node.propertyName)) {
+ return prefixResult.stringLength(_typeProvider);
+ }
+ }
+ return _getConstantValue(node, node.propertyName.staticElement);
+ }
+
+ @override
+ DartObjectImpl visitSimpleIdentifier(SimpleIdentifier node) {
+ if (_lexicalEnvironment != null &&
+ _lexicalEnvironment.containsKey(node.name)) {
+ return _lexicalEnvironment[node.name];
+ }
+ return _getConstantValue(node, node.staticElement);
+ }
+
+ @override
+ DartObjectImpl visitSimpleStringLiteral(SimpleStringLiteral node) =>
+ new DartObjectImpl(_typeProvider.stringType, new StringState(node.value));
+
+ @override
+ DartObjectImpl visitStringInterpolation(StringInterpolation node) {
+ DartObjectImpl result = null;
+ bool first = true;
+ for (InterpolationElement element in node.elements) {
+ if (first) {
+ result = element.accept(this);
+ first = false;
+ } else {
+ result =
+ _dartObjectComputer.concatenate(node, result, element.accept(this));
+ }
+ }
+ return result;
+ }
+
+ @override
+ DartObjectImpl visitSymbolLiteral(SymbolLiteral node) {
+ StringBuffer buffer = new StringBuffer();
+ List<Token> components = node.components;
+ for (int i = 0; i < components.length; i++) {
+ if (i > 0) {
+ buffer.writeCharCode(0x2E);
+ }
+ buffer.write(components[i].lexeme);
+ }
+ return new DartObjectImpl(
+ _typeProvider.symbolType, new SymbolState(buffer.toString()));
+ }
+
+ /**
+ * Create an error associated with the given [node]. The error will have the
+ * given error [code].
+ */
+ void _error(AstNode node, ErrorCode code) {
+ _errorReporter.reportErrorForNode(
+ code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code, node);
+ }
+
+ /**
+ * Return the constant value of the static constant represented by the given
+ * [element]. The [node] is the node to be used if an error needs to be
+ * reported.
+ */
+ DartObjectImpl _getConstantValue(AstNode node, Element element) {
+ if (element is PropertyAccessorElement) {
+ element = (element as PropertyAccessorElement).variable;
+ }
+ if (element is VariableElementImpl) {
+ VariableElementImpl variableElementImpl = element;
+ evaluationEngine.validator.beforeGetEvaluationResult(element);
+ EvaluationResultImpl value = variableElementImpl.evaluationResult;
+ if (variableElementImpl.isConst && value != null) {
+ return value.value;
+ }
+ } else if (element is ExecutableElement) {
+ ExecutableElement function = element;
+ if (function.isStatic) {
+ ParameterizedType functionType = function.type;
+ if (functionType == null) {
+ functionType = _typeProvider.functionType;
+ }
+ return new DartObjectImpl(functionType, new FunctionState(function));
+ }
+ } else if (element is ClassElement ||
+ element is FunctionTypeAliasElement ||
+ element is DynamicElementImpl) {
+ return new DartObjectImpl(_typeProvider.typeType, new TypeState(element));
+ }
+ // TODO(brianwilkerson) Figure out which error to report.
+ _error(node, null);
+ return null;
+ }
+
+ /**
+ * Return `true` if the given [targetResult] represents a string and the
+ * [identifier] is "length".
+ */
+ bool _isStringLength(
+ DartObjectImpl targetResult, SimpleIdentifier identifier) {
+ if (targetResult == null || targetResult.type != _typeProvider.stringType) {
+ return false;
+ }
+ return identifier.name == 'length';
+ }
+
+ /**
+ * Return the value of the given [expression], or a representation of 'null'
+ * if the expression cannot be evaluated.
+ */
+ DartObjectImpl _valueOf(Expression expression) {
+ DartObjectImpl expressionValue = expression.accept(this);
+ if (expressionValue != null) {
+ return expressionValue;
+ }
+ return _typeProvider.nullObject;
+ }
+}
+
+/**
+ * A utility class that contains methods for manipulating instances of a Dart
+ * class and for collecting errors during evaluation.
+ */
+class DartObjectComputer {
+ /**
+ * The error reporter that we are using to collect errors.
+ */
+ final ErrorReporter _errorReporter;
+
+ /**
+ * The type provider used to create objects of the appropriate types, and to
+ * identify when an object is of a built-in type.
+ */
+ final TypeProvider _typeProvider;
+
+ DartObjectComputer(this._errorReporter, this._typeProvider);
+
+ DartObjectImpl add(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.add(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ return null;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return the result of applying boolean conversion to the [evaluationResult].
+ * The [node] is the node against which errors should be reported.
+ */
+ DartObjectImpl applyBooleanConversion(
+ AstNode node, DartObjectImpl evaluationResult) {
+ if (evaluationResult != null) {
+ try {
+ return evaluationResult.convertToBool(_typeProvider);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl bitAnd(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.bitAnd(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl bitNot(Expression node, DartObjectImpl evaluationResult) {
+ if (evaluationResult != null) {
+ try {
+ return evaluationResult.bitNot(_typeProvider);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl bitOr(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.bitOr(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl bitXor(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.bitXor(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl concatenate(Expression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.concatenate(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl divide(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.divide(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl equalEqual(Expression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.equalEqual(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl greaterThan(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.greaterThan(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl greaterThanOrEqual(BinaryExpression node,
+ DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.greaterThanOrEqual(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl integerDivide(BinaryExpression node,
+ DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.integerDivide(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl isIdentical(Expression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.isIdentical(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl lessThan(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.lessThan(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl lessThanOrEqual(BinaryExpression node,
+ DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.lessThanOrEqual(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl logicalAnd(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.logicalAnd(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl logicalNot(Expression node, DartObjectImpl evaluationResult) {
+ if (evaluationResult != null) {
+ try {
+ return evaluationResult.logicalNot(_typeProvider);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl logicalOr(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.logicalOr(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl minus(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.minus(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl negated(Expression node, DartObjectImpl evaluationResult) {
+ if (evaluationResult != null) {
+ try {
+ return evaluationResult.negated(_typeProvider);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl notEqual(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.notEqual(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl performToString(
+ AstNode node, DartObjectImpl evaluationResult) {
+ if (evaluationResult != null) {
+ try {
+ return evaluationResult.performToString(_typeProvider);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl questionQuestion(Expression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ if (leftOperand.isNull) {
+ return rightOperand;
+ }
+ return leftOperand;
+ }
+ return null;
+ }
+
+ DartObjectImpl remainder(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.remainder(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl shiftLeft(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.shiftLeft(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ DartObjectImpl shiftRight(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.shiftRight(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return the result of invoking the 'length' getter on the
+ * [evaluationResult]. The [node] is the node against which errors should be
+ * reported.
+ */
+ EvaluationResultImpl stringLength(
+ Expression node, EvaluationResultImpl evaluationResult) {
+ if (evaluationResult.value != null) {
+ try {
+ return new EvaluationResultImpl(
+ evaluationResult.value.stringLength(_typeProvider));
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return new EvaluationResultImpl(null);
+ }
+
+ DartObjectImpl times(BinaryExpression node, DartObjectImpl leftOperand,
+ DartObjectImpl rightOperand) {
+ if (leftOperand != null && rightOperand != null) {
+ try {
+ return leftOperand.times(_typeProvider, rightOperand);
+ } on EvaluationException catch (exception) {
+ _errorReporter.reportErrorForNode(exception.errorCode, node);
+ }
+ }
+ return null;
+ }
+}
+
+/**
+ * The result of attempting to evaluate an expression.
+ */
+class EvaluationResult {
+ // TODO(brianwilkerson) Merge with EvaluationResultImpl
+ /**
+ * The value of the expression.
+ */
+ final DartObject value;
+
+ /**
+ * The errors that should be reported for the expression(s) that were
+ * evaluated.
+ */
+ final List<AnalysisError> _errors;
+
+ /**
+ * Initialize a newly created result object with the given [value] and set of
+ * [_errors]. Clients should use one of the factory methods: [forErrors] and
+ * [forValue].
+ */
+ EvaluationResult(this.value, this._errors);
+
+ /**
+ * Return a list containing the errors that should be reported for the
+ * expression(s) that were evaluated. If there are no such errors, the list
+ * will be empty. The list can be empty even if the expression is not a valid
+ * compile time constant if the errors would have been reported by other parts
+ * of the analysis engine.
+ */
+ List<AnalysisError> get errors =>
+ _errors == null ? AnalysisError.NO_ERRORS : _errors;
+
+ /**
+ * Return `true` if the expression is a compile-time constant expression that
+ * would not throw an exception when evaluated.
+ */
+ bool get isValid => _errors == null;
+
+ /**
+ * Return an evaluation result representing the result of evaluating an
+ * expression that is not a compile-time constant because of the given
+ * [errors].
+ */
+ static EvaluationResult forErrors(List<AnalysisError> errors) =>
+ new EvaluationResult(null, errors);
+
+ /**
+ * Return an evaluation result representing the result of evaluating an
+ * expression that is a compile-time constant that evaluates to the given
+ * [value].
+ */
+ static EvaluationResult forValue(DartObject value) =>
+ new EvaluationResult(value, null);
+}
+
+/**
+ * The result of attempting to evaluate a expression.
+ */
+class EvaluationResultImpl {
+ /**
+ * The errors encountered while trying to evaluate the compile time constant.
+ * These errors may or may not have prevented the expression from being a
+ * valid compile time constant.
+ */
+ List<AnalysisError> _errors;
+
+ /**
+ * The value of the expression, or `null` if the value couldn't be computed
+ * due to errors.
+ */
+ final DartObjectImpl value;
+
+ EvaluationResultImpl(this.value, [List<AnalysisError> errors]) {
+ this._errors = errors == null ? <AnalysisError>[] : errors;
+ }
+
+ List<AnalysisError> get errors => _errors;
+
+ bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result) {
+ if (this.value != null) {
+ if (result.value == null) {
+ return false;
+ }
+ return value == result.value;
+ } else {
+ return false;
+ }
+ }
+
+ @override
+ String toString() {
+ if (value == null) {
+ return "error";
+ }
+ return value.toString();
+ }
+}
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
new file mode 100644
index 0000000..c324d7f
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -0,0 +1,312 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.src.dart.constant.utilities;
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/handle.dart'
+ show ConstructorElementHandle;
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/source.dart' show Source;
+import 'package:analyzer/src/task/dart.dart';
+
+ConstructorElementImpl getConstructorImpl(ConstructorElement constructor) {
+ while (constructor is ConstructorMember) {
+ constructor = (constructor as ConstructorMember).baseElement;
+ }
+ if (constructor is ConstructorElementHandle) {
+ constructor = (constructor as ConstructorElementHandle).actualElement;
+ }
+ return constructor;
+}
+
+/**
+ * Callback used by [ReferenceFinder] to report that a dependency was found.
+ */
+typedef void ReferenceFinderCallback(ConstantEvaluationTarget dependency);
+
+/**
+ * An [AstCloner] that copies the necessary information from the AST to allow
+ * constants to be evaluated.
+ */
+class ConstantAstCloner extends AstCloner {
+ ConstantAstCloner() : super(true);
+
+ @override
+ ConstructorName visitConstructorName(ConstructorName node) {
+ ConstructorName name = super.visitConstructorName(node);
+ name.staticElement = node.staticElement;
+ return name;
+ }
+
+ @override
+ InstanceCreationExpression visitInstanceCreationExpression(
+ InstanceCreationExpression node) {
+ InstanceCreationExpression expression =
+ super.visitInstanceCreationExpression(node);
+ expression.staticElement = node.staticElement;
+ return expression;
+ }
+
+ @override
+ RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) {
+ RedirectingConstructorInvocation invocation =
+ super.visitRedirectingConstructorInvocation(node);
+ invocation.staticElement = node.staticElement;
+ return invocation;
+ }
+
+ @override
+ SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
+ SimpleIdentifier identifier = super.visitSimpleIdentifier(node);
+ identifier.staticElement = node.staticElement;
+ return identifier;
+ }
+
+ @override
+ SuperConstructorInvocation visitSuperConstructorInvocation(
+ SuperConstructorInvocation node) {
+ SuperConstructorInvocation invocation =
+ super.visitSuperConstructorInvocation(node);
+ invocation.staticElement = node.staticElement;
+ return invocation;
+ }
+
+ @override
+ TypeName visitTypeName(TypeName node) {
+ TypeName typeName = super.visitTypeName(node);
+ typeName.type = node.type;
+ return typeName;
+ }
+}
+
+/**
+ * A visitor used to traverse the AST structures of all of the compilation units
+ * being resolved and build the full set of dependencies for all constant
+ * expressions.
+ */
+class ConstantExpressionsDependenciesFinder extends RecursiveAstVisitor {
+ /**
+ * The constants whose values need to be computed.
+ */
+ HashSet<ConstantEvaluationTarget> dependencies =
+ new HashSet<ConstantEvaluationTarget>();
+
+ @override
+ void visitInstanceCreationExpression(InstanceCreationExpression node) {
+ if (node.isConst) {
+ _find(node);
+ } else {
+ super.visitInstanceCreationExpression(node);
+ }
+ }
+
+ @override
+ void visitListLiteral(ListLiteral node) {
+ if (node.constKeyword != null) {
+ _find(node);
+ } else {
+ super.visitListLiteral(node);
+ }
+ }
+
+ @override
+ void visitMapLiteral(MapLiteral node) {
+ if (node.constKeyword != null) {
+ _find(node);
+ } else {
+ super.visitMapLiteral(node);
+ }
+ }
+
+ @override
+ void visitSwitchCase(SwitchCase node) {
+ _find(node.expression);
+ node.statements.accept(this);
+ }
+
+ void _find(Expression node) {
+ if (node != null) {
+ ReferenceFinder referenceFinder = new ReferenceFinder(dependencies.add);
+ node.accept(referenceFinder);
+ }
+ }
+}
+
+/**
+ * A visitor used to traverse the AST structures of all of the compilation units
+ * being resolved and build tables of the constant variables, constant
+ * constructors, constant constructor invocations, and annotations found in
+ * those compilation units.
+ */
+class ConstantFinder extends RecursiveAstVisitor<Object> {
+ final AnalysisContext context;
+ final Source source;
+ final Source librarySource;
+
+ /**
+ * The elements and AST nodes whose constant values need to be computed.
+ */
+ List<ConstantEvaluationTarget> constantsToCompute =
+ <ConstantEvaluationTarget>[];
+
+ /**
+ * A flag indicating whether instance variables marked as "final" should be
+ * treated as "const".
+ */
+ bool treatFinalInstanceVarAsConst = false;
+
+ ConstantFinder(this.context, this.source, this.librarySource);
+
+ @override
+ Object visitAnnotation(Annotation node) {
+ super.visitAnnotation(node);
+ ElementAnnotation elementAnnotation = node.elementAnnotation;
+ if (elementAnnotation == null) {
+ // Analyzer ignores annotations on "part of" directives.
+ assert(node.parent is PartOfDirective);
+ } else {
+ constantsToCompute.add(elementAnnotation);
+ }
+ return null;
+ }
+
+ @override
+ Object visitClassDeclaration(ClassDeclaration node) {
+ bool prevTreatFinalInstanceVarAsConst = treatFinalInstanceVarAsConst;
+ if (node.element.constructors.any((ConstructorElement e) => e.isConst)) {
+ // Instance vars marked "final" need to be included in the dependency
+ // graph, since constant constructors implicitly use the values in their
+ // initializers.
+ treatFinalInstanceVarAsConst = true;
+ }
+ try {
+ return super.visitClassDeclaration(node);
+ } finally {
+ treatFinalInstanceVarAsConst = prevTreatFinalInstanceVarAsConst;
+ }
+ }
+
+ @override
+ Object visitConstructorDeclaration(ConstructorDeclaration node) {
+ super.visitConstructorDeclaration(node);
+ if (node.constKeyword != null) {
+ ConstructorElement element = node.element;
+ if (element != null) {
+ constantsToCompute.add(element);
+ constantsToCompute.addAll(element.parameters);
+ }
+ }
+ return null;
+ }
+
+ @override
+ Object visitDefaultFormalParameter(DefaultFormalParameter node) {
+ super.visitDefaultFormalParameter(node);
+ Expression defaultValue = node.defaultValue;
+ if (defaultValue != null && node.element != null) {
+ constantsToCompute.add(node.element);
+ }
+ return null;
+ }
+
+ @override
+ Object visitVariableDeclaration(VariableDeclaration node) {
+ super.visitVariableDeclaration(node);
+ Expression initializer = node.initializer;
+ VariableElement element = node.element;
+ if (initializer != null &&
+ (node.isConst ||
+ treatFinalInstanceVarAsConst &&
+ element is FieldElement &&
+ node.isFinal &&
+ !element.isStatic)) {
+ if (element != null) {
+ constantsToCompute.add(element);
+ }
+ }
+ return null;
+ }
+}
+
+/**
+ * An object used to add reference information for a given variable to the
+ * bi-directional mapping used to order the evaluation of constants.
+ */
+class ReferenceFinder extends RecursiveAstVisitor<Object> {
+ /**
+ * The callback which should be used to report any dependencies that were
+ * found.
+ */
+ final ReferenceFinderCallback _callback;
+
+ /**
+ * Initialize a newly created reference finder to find references from a given
+ * variable to other variables and to add those references to the given graph.
+ * The [_callback] will be invoked for every dependency found.
+ */
+ ReferenceFinder(this._callback);
+
+ @override
+ Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+ if (node.isConst) {
+ ConstructorElement constructor = getConstructorImpl(node.staticElement);
+ if (constructor != null) {
+ _callback(constructor);
+ }
+ }
+ return super.visitInstanceCreationExpression(node);
+ }
+
+ @override
+ Object visitLabel(Label node) {
+ // We are visiting the "label" part of a named expression in a function
+ // call (presumably a constructor call), e.g. "const C(label: ...)". We
+ // don't want to visit the SimpleIdentifier for the label because that's a
+ // reference to a function parameter that needs to be filled in; it's not a
+ // constant whose value we depend on.
+ return null;
+ }
+
+ @override
+ Object visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) {
+ super.visitRedirectingConstructorInvocation(node);
+ ConstructorElement target = getConstructorImpl(node.staticElement);
+ if (target != null) {
+ _callback(target);
+ }
+ return null;
+ }
+
+ @override
+ Object visitSimpleIdentifier(SimpleIdentifier node) {
+ Element element = node.staticElement;
+ if (element is PropertyAccessorElement) {
+ element = (element as PropertyAccessorElement).variable;
+ }
+ if (element is VariableElement && element.isConst) {
+ _callback(element);
+ }
+ return null;
+ }
+
+ @override
+ Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ super.visitSuperConstructorInvocation(node);
+ ConstructorElement constructor = getConstructorImpl(node.staticElement);
+ if (constructor != null) {
+ _callback(constructor);
+ }
+ return null;
+ }
+}
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
new file mode 100644
index 0000000..6ebb45d
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -0,0 +1,2818 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * The implementation of the class [DartObject].
+ */
+library analyzer.src.dart.constant.value;
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/constant/value.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/java_core.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+import 'package:analyzer/src/generated/utilities_general.dart';
+
+/**
+ * The state of an object representing a boolean value.
+ */
+class BoolState extends InstanceState {
+ /**
+ * An instance representing the boolean value 'false'.
+ */
+ static BoolState FALSE_STATE = new BoolState(false);
+
+ /**
+ * An instance representing the boolean value 'true'.
+ */
+ static BoolState TRUE_STATE = new BoolState(true);
+
+ /**
+ * A state that can be used to represent a boolean whose value is not known.
+ */
+ static BoolState UNKNOWN_VALUE = new BoolState(null);
+
+ /**
+ * The value of this instance.
+ */
+ final bool value;
+
+ /**
+ * Initialize a newly created state to represent the given [value].
+ */
+ BoolState(this.value);
+
+ @override
+ int get hashCode => value == null ? 0 : (value ? 2 : 3);
+
+ @override
+ bool get isBool => true;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ bool get isUnknown => value == null;
+
+ @override
+ String get typeName => "bool";
+
+ @override
+ bool operator ==(Object object) =>
+ object is BoolState && identical(value, object.value);
+
+ @override
+ BoolState convertToBool() => this;
+
+ @override
+ StringState convertToString() {
+ if (value == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(value ? "true" : "false");
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is BoolState) {
+ bool rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return BoolState.from(identical(value, rightValue));
+ } else if (rightOperand is DynamicState) {
+ return UNKNOWN_VALUE;
+ }
+ return FALSE_STATE;
+ }
+
+ @override
+ BoolState logicalAnd(InstanceState rightOperand) {
+ assertBool(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ return value ? rightOperand.convertToBool() : FALSE_STATE;
+ }
+
+ @override
+ BoolState logicalNot() {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ return value ? FALSE_STATE : TRUE_STATE;
+ }
+
+ @override
+ BoolState logicalOr(InstanceState rightOperand) {
+ assertBool(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ return value ? TRUE_STATE : rightOperand.convertToBool();
+ }
+
+ @override
+ String toString() => value == null ? "-unknown-" : (value ? "true" : "false");
+
+ /**
+ * Return the boolean state representing the given boolean [value].
+ */
+ static BoolState from(bool value) =>
+ value ? BoolState.TRUE_STATE : BoolState.FALSE_STATE;
+}
+
+/**
+ * A representation of an instance of a Dart class.
+ */
+class DartObjectImpl implements DartObject {
+ /**
+ * An empty list of objects.
+ */
+ static const List<DartObjectImpl> EMPTY_LIST = const <DartObjectImpl>[];
+
+ /**
+ * The run-time type of this object.
+ */
+ @override
+ final ParameterizedType type;
+
+ /**
+ * The state of the object.
+ */
+ final InstanceState _state;
+
+ /**
+ * Initialize a newly created object to have the given [type] and [_state].
+ */
+ DartObjectImpl(this.type, this._state);
+
+ /**
+ * Create an object to represent an unknown value.
+ */
+ factory DartObjectImpl.validWithUnknownValue(InterfaceType type) {
+ if (type.element.library.isDartCore) {
+ String typeName = type.name;
+ if (typeName == "bool") {
+ return new DartObjectImpl(type, BoolState.UNKNOWN_VALUE);
+ } else if (typeName == "double") {
+ return new DartObjectImpl(type, DoubleState.UNKNOWN_VALUE);
+ } else if (typeName == "int") {
+ return new DartObjectImpl(type, IntState.UNKNOWN_VALUE);
+ } else if (typeName == "String") {
+ return new DartObjectImpl(type, StringState.UNKNOWN_VALUE);
+ }
+ }
+ return new DartObjectImpl(type, GenericState.UNKNOWN_VALUE);
+ }
+
+ HashMap<String, DartObjectImpl> get fields => _state.fields;
+
+ @override
+ int get hashCode => JenkinsSmiHash.hash2(type.hashCode, _state.hashCode);
+
+ @override
+ bool get hasKnownValue => !_state.isUnknown;
+
+ /**
+ * Return `true` if this object represents an object whose type is 'bool'.
+ */
+ bool get isBool => _state.isBool;
+
+ /**
+ * Return `true` if this object represents an object whose type is either
+ * 'bool', 'num', 'String', or 'Null'.
+ */
+ bool get isBoolNumStringOrNull => _state.isBoolNumStringOrNull;
+
+ @override
+ bool get isNull => _state is NullState;
+
+ /**
+ * Return `true` if this object represents an unknown value.
+ */
+ bool get isUnknown => _state.isUnknown;
+
+ /**
+ * Return `true` if this object represents an instance of a user-defined
+ * class.
+ */
+ bool get isUserDefinedObject => _state is GenericState;
+
+ @override
+ bool operator ==(Object object) {
+ if (object is! DartObjectImpl) {
+ return false;
+ }
+ DartObjectImpl dartObject = object as DartObjectImpl;
+ return type == dartObject.type && _state == dartObject._state;
+ }
+
+ /**
+ * Return the result of invoking the '+' operator on this object with the
+ * given [rightOperand]. The [typeProvider] is the type provider used to find
+ * known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl add(TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ InstanceState result = _state.add(rightOperand._state);
+ if (result is IntState) {
+ return new DartObjectImpl(typeProvider.intType, result);
+ } else if (result is DoubleState) {
+ return new DartObjectImpl(typeProvider.doubleType, result);
+ } else if (result is NumState) {
+ return new DartObjectImpl(typeProvider.numType, result);
+ } else if (result is StringState) {
+ return new DartObjectImpl(typeProvider.stringType, result);
+ }
+ // We should never get here.
+ throw new IllegalStateException("add returned a ${result.runtimeType}");
+ }
+
+ /**
+ * Return the result of invoking the '&' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl bitAnd(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.intType, _state.bitAnd(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '~' operator on this object. The
+ * [typeProvider] is the type provider used to find known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl bitNot(TypeProvider typeProvider) =>
+ new DartObjectImpl(typeProvider.intType, _state.bitNot());
+
+ /**
+ * Return the result of invoking the '|' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl bitOr(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.intType, _state.bitOr(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '^' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl bitXor(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.intType, _state.bitXor(rightOperand._state));
+
+ /**
+ * Return the result of invoking the ' ' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl concatenate(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.stringType, _state.concatenate(rightOperand._state));
+
+ /**
+ * Return the result of applying boolean conversion to this object. The
+ * [typeProvider] is the type provider used to find known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl convertToBool(TypeProvider typeProvider) {
+ InterfaceType boolType = typeProvider.boolType;
+ if (identical(type, boolType)) {
+ return this;
+ }
+ return new DartObjectImpl(boolType, _state.convertToBool());
+ }
+
+ /**
+ * Return the result of invoking the '/' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for
+ * an object of this kind.
+ */
+ DartObjectImpl divide(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ InstanceState result = _state.divide(rightOperand._state);
+ if (result is IntState) {
+ return new DartObjectImpl(typeProvider.intType, result);
+ } else if (result is DoubleState) {
+ return new DartObjectImpl(typeProvider.doubleType, result);
+ } else if (result is NumState) {
+ return new DartObjectImpl(typeProvider.numType, result);
+ }
+ // We should never get here.
+ throw new IllegalStateException("divide returned a ${result.runtimeType}");
+ }
+
+ /**
+ * Return the result of invoking the '==' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl equalEqual(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ if (type != rightOperand.type) {
+ String typeName = type.name;
+ if (!(typeName == "bool" ||
+ typeName == "double" ||
+ typeName == "int" ||
+ typeName == "num" ||
+ typeName == "String" ||
+ typeName == "Null" ||
+ type.isDynamic)) {
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
+ }
+ }
+ return new DartObjectImpl(
+ typeProvider.boolType, _state.equalEqual(rightOperand._state));
+ }
+
+ @override
+ DartObject getField(String name) {
+ if (_state is GenericState) {
+ return (_state as GenericState).fields[name];
+ }
+ return null;
+ }
+
+ /**
+ * Return the result of invoking the '>' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl greaterThan(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.boolType, _state.greaterThan(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '>=' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl greaterThanOrEqual(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(typeProvider.boolType,
+ _state.greaterThanOrEqual(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '~/' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl integerDivide(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.intType, _state.integerDivide(rightOperand._state));
+
+ /**
+ * Return the result of invoking the identical function on this object with
+ * the [rightOperand]. The [typeProvider] is the type provider used to find
+ * known types.
+ */
+ DartObjectImpl isIdentical(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ return new DartObjectImpl(
+ typeProvider.boolType, _state.isIdentical(rightOperand._state));
+ }
+
+ /**
+ * Return the result of invoking the '<' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl lessThan(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.boolType, _state.lessThan(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '<=' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl lessThanOrEqual(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.boolType, _state.lessThanOrEqual(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '&&' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl logicalAnd(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.boolType, _state.logicalAnd(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '!' operator on this object. The
+ * [typeProvider] is the type provider used to find known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl logicalNot(TypeProvider typeProvider) =>
+ new DartObjectImpl(typeProvider.boolType, _state.logicalNot());
+
+ /**
+ * Return the result of invoking the '||' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl logicalOr(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.boolType, _state.logicalOr(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '-' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl minus(TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ InstanceState result = _state.minus(rightOperand._state);
+ if (result is IntState) {
+ return new DartObjectImpl(typeProvider.intType, result);
+ } else if (result is DoubleState) {
+ return new DartObjectImpl(typeProvider.doubleType, result);
+ } else if (result is NumState) {
+ return new DartObjectImpl(typeProvider.numType, result);
+ }
+ // We should never get here.
+ throw new IllegalStateException("minus returned a ${result.runtimeType}");
+ }
+
+ /**
+ * Return the result of invoking the '-' operator on this object. The
+ * [typeProvider] is the type provider used to find known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl negated(TypeProvider typeProvider) {
+ InstanceState result = _state.negated();
+ if (result is IntState) {
+ return new DartObjectImpl(typeProvider.intType, result);
+ } else if (result is DoubleState) {
+ return new DartObjectImpl(typeProvider.doubleType, result);
+ } else if (result is NumState) {
+ return new DartObjectImpl(typeProvider.numType, result);
+ }
+ // We should never get here.
+ throw new IllegalStateException("negated returned a ${result.runtimeType}");
+ }
+
+ /**
+ * Return the result of invoking the '!=' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl notEqual(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ if (type != rightOperand.type) {
+ String typeName = type.name;
+ if (typeName != "bool" &&
+ typeName != "double" &&
+ typeName != "int" &&
+ typeName != "num" &&
+ typeName != "String") {
+ return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE);
+ }
+ }
+ return new DartObjectImpl(typeProvider.boolType,
+ _state.equalEqual(rightOperand._state).logicalNot());
+ }
+
+ /**
+ * Return the result of converting this object to a 'String'. The
+ * [typeProvider] is the type provider used to find known types.
+ *
+ * Throws an [EvaluationException] if the object cannot be converted to a
+ * 'String'.
+ */
+ DartObjectImpl performToString(TypeProvider typeProvider) {
+ InterfaceType stringType = typeProvider.stringType;
+ if (identical(type, stringType)) {
+ return this;
+ }
+ return new DartObjectImpl(stringType, _state.convertToString());
+ }
+
+ /**
+ * Return the result of invoking the '%' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl remainder(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ InstanceState result = _state.remainder(rightOperand._state);
+ if (result is IntState) {
+ return new DartObjectImpl(typeProvider.intType, result);
+ } else if (result is DoubleState) {
+ return new DartObjectImpl(typeProvider.doubleType, result);
+ } else if (result is NumState) {
+ return new DartObjectImpl(typeProvider.numType, result);
+ }
+ // We should never get here.
+ throw new IllegalStateException(
+ "remainder returned a ${result.runtimeType}");
+ }
+
+ /**
+ * Return the result of invoking the '<<' operator on this object with
+ * the [rightOperand]. The [typeProvider] is the type provider used to find
+ * known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl shiftLeft(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.intType, _state.shiftLeft(rightOperand._state));
+
+ /**
+ * Return the result of invoking the '>>' operator on this object with
+ * the [rightOperand]. The [typeProvider] is the type provider used to find
+ * known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl shiftRight(
+ TypeProvider typeProvider, DartObjectImpl rightOperand) =>
+ new DartObjectImpl(
+ typeProvider.intType, _state.shiftRight(rightOperand._state));
+
+ /**
+ * Return the result of invoking the 'length' getter on this object. The
+ * [typeProvider] is the type provider used to find known types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl stringLength(TypeProvider typeProvider) =>
+ new DartObjectImpl(typeProvider.intType, _state.stringLength());
+
+ /**
+ * Return the result of invoking the '*' operator on this object with the
+ * [rightOperand]. The [typeProvider] is the type provider used to find known
+ * types.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ DartObjectImpl times(TypeProvider typeProvider, DartObjectImpl rightOperand) {
+ InstanceState result = _state.times(rightOperand._state);
+ if (result is IntState) {
+ return new DartObjectImpl(typeProvider.intType, result);
+ } else if (result is DoubleState) {
+ return new DartObjectImpl(typeProvider.doubleType, result);
+ } else if (result is NumState) {
+ return new DartObjectImpl(typeProvider.numType, result);
+ }
+ // We should never get here.
+ throw new IllegalStateException("times returned a ${result.runtimeType}");
+ }
+
+ @override
+ bool toBoolValue() {
+ if (_state is BoolState) {
+ return (_state as BoolState).value;
+ }
+ return null;
+ }
+
+ @override
+ double toDoubleValue() {
+ if (_state is DoubleState) {
+ return (_state as DoubleState).value;
+ }
+ return null;
+ }
+
+ @override
+ int toIntValue() {
+ if (_state is IntState) {
+ return (_state as IntState).value;
+ }
+ return null;
+ }
+
+ @override
+ List<DartObject> toListValue() {
+ if (_state is ListState) {
+ return (_state as ListState)._elements;
+ }
+ return null;
+ }
+
+ @override
+ Map<DartObject, DartObject> toMapValue() {
+ if (_state is MapState) {
+ return (_state as MapState)._entries;
+ }
+ return null;
+ }
+
+ @override
+ String toString() => "${type.displayName} ($_state)";
+
+ @override
+ String toStringValue() {
+ if (_state is StringState) {
+ return (_state as StringState).value;
+ }
+ return null;
+ }
+
+ @override
+ String toSymbolValue() {
+ if (_state is SymbolState) {
+ return (_state as SymbolState).value;
+ }
+ return null;
+ }
+
+ @override
+ DartType toTypeValue() {
+ if (_state is TypeState) {
+ Element element = (_state as TypeState)._element;
+ if (element is TypeDefiningElement) {
+ return element.type;
+ }
+ }
+ return null;
+ }
+}
+
+/**
+ * The state of an object representing a double.
+ */
+class DoubleState extends NumState {
+ /**
+ * A state that can be used to represent a double whose value is not known.
+ */
+ static DoubleState UNKNOWN_VALUE = new DoubleState(null);
+
+ /**
+ * The value of this instance.
+ */
+ final double value;
+
+ /**
+ * Initialize a newly created state to represent a double with the given
+ * [value].
+ */
+ DoubleState(this.value);
+
+ @override
+ int get hashCode => value == null ? 0 : value.hashCode;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ bool get isUnknown => value == null;
+
+ @override
+ String get typeName => "double";
+
+ @override
+ bool operator ==(Object object) =>
+ object is DoubleState && (value == object.value);
+
+ @override
+ NumState add(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value + rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value + rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ StringState convertToString() {
+ if (value == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(value.toString());
+ }
+
+ @override
+ NumState divide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value / rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value / rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState greaterThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value > rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value > rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState greaterThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value >= rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value >= rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState integerDivide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return IntState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return IntState.UNKNOWN_VALUE;
+ }
+ double result = value / rightValue.toDouble();
+ return new IntState(result.toInt());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return IntState.UNKNOWN_VALUE;
+ }
+ double result = value / rightValue;
+ return new IntState(result.toInt());
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return IntState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value == rightValue);
+ } else if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value == rightValue.toDouble());
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
+ }
+
+ @override
+ BoolState lessThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value < rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value < rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState lessThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value <= rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value <= rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ NumState minus(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value - rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value - rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ NumState negated() {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(-(value));
+ }
+
+ @override
+ NumState remainder(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value % rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value % rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ NumState times(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value * rightValue.toDouble());
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new DoubleState(value * rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ String toString() => value == null ? "-unknown-" : value.toString();
+}
+
+/**
+ * The state of an object representing a Dart object for which there is no type
+ * information.
+ */
+class DynamicState extends InstanceState {
+ /**
+ * The unique instance of this class.
+ */
+ static DynamicState DYNAMIC_STATE = new DynamicState();
+
+ @override
+ bool get isBool => true;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ String get typeName => "dynamic";
+
+ @override
+ NumState add(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return _unknownNum(rightOperand);
+ }
+
+ @override
+ IntState bitAnd(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ IntState bitNot() => IntState.UNKNOWN_VALUE;
+
+ @override
+ IntState bitOr(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ IntState bitXor(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ StringState concatenate(InstanceState rightOperand) {
+ assertString(rightOperand);
+ return StringState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState convertToBool() => BoolState.UNKNOWN_VALUE;
+
+ @override
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+ @override
+ NumState divide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return _unknownNum(rightOperand);
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState greaterThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState greaterThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ IntState integerDivide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState lessThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState lessThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState logicalAnd(InstanceState rightOperand) {
+ assertBool(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState logicalNot() => BoolState.UNKNOWN_VALUE;
+
+ @override
+ BoolState logicalOr(InstanceState rightOperand) {
+ assertBool(rightOperand);
+ return rightOperand.convertToBool();
+ }
+
+ @override
+ NumState minus(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return _unknownNum(rightOperand);
+ }
+
+ @override
+ NumState negated() => NumState.UNKNOWN_VALUE;
+
+ @override
+ NumState remainder(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return _unknownNum(rightOperand);
+ }
+
+ @override
+ IntState shiftLeft(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ IntState shiftRight(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ NumState times(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return _unknownNum(rightOperand);
+ }
+
+ /**
+ * Return an object representing an unknown numeric value whose type is based
+ * on the type of the [rightOperand].
+ */
+ NumState _unknownNum(InstanceState rightOperand) {
+ if (rightOperand is IntState) {
+ return IntState.UNKNOWN_VALUE;
+ } else if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return NumState.UNKNOWN_VALUE;
+ }
+}
+
+/**
+ * A run-time exception that would be thrown during the evaluation of Dart code.
+ */
+class EvaluationException extends JavaException {
+ /**
+ * The error code associated with the exception.
+ */
+ final ErrorCode errorCode;
+
+ /**
+ * Initialize a newly created exception to have the given [errorCode].
+ */
+ EvaluationException(this.errorCode);
+}
+
+/**
+ * The state of an object representing a function.
+ */
+class FunctionState extends InstanceState {
+ /**
+ * The element representing the function being modeled.
+ */
+ final ExecutableElement _element;
+
+ /**
+ * Initialize a newly created state to represent the function with the given
+ * [element].
+ */
+ FunctionState(this._element);
+
+ @override
+ int get hashCode => _element == null ? 0 : _element.hashCode;
+
+ @override
+ String get typeName => "Function";
+
+ @override
+ bool operator ==(Object object) =>
+ object is FunctionState && (_element == object._element);
+
+ @override
+ StringState convertToString() {
+ if (_element == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(_element.name);
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (_element == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is FunctionState) {
+ ExecutableElement rightElement = rightOperand._element;
+ if (rightElement == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(_element == rightElement);
+ } else if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
+ }
+
+ @override
+ String toString() => _element == null ? "-unknown-" : _element.name;
+}
+
+/**
+ * The state of an object representing a Dart object for which there is no more
+ * specific state.
+ */
+class GenericState extends InstanceState {
+ /**
+ * Pseudo-field that we use to represent fields in the superclass.
+ */
+ static String SUPERCLASS_FIELD = "(super)";
+
+ /**
+ * A state that can be used to represent an object whose state is not known.
+ */
+ static GenericState UNKNOWN_VALUE =
+ new GenericState(new HashMap<String, DartObjectImpl>());
+
+ /**
+ * The values of the fields of this instance.
+ */
+ final HashMap<String, DartObjectImpl> _fieldMap;
+
+ /**
+ * Initialize a newly created state to represent a newly created object. The
+ * [fieldMap] contains the values of the fields of the instance.
+ */
+ GenericState(this._fieldMap);
+
+ @override
+ HashMap<String, DartObjectImpl> get fields => _fieldMap;
+
+ @override
+ int get hashCode {
+ int hashCode = 0;
+ for (DartObjectImpl value in _fieldMap.values) {
+ hashCode += value.hashCode;
+ }
+ return hashCode;
+ }
+
+ @override
+ bool get isUnknown => identical(this, UNKNOWN_VALUE);
+
+ @override
+ String get typeName => "user defined type";
+
+ @override
+ bool operator ==(Object object) {
+ if (object is! GenericState) {
+ return false;
+ }
+ GenericState state = object as GenericState;
+ HashSet<String> otherFields =
+ new HashSet<String>.from(state._fieldMap.keys.toSet());
+ for (String fieldName in _fieldMap.keys.toSet()) {
+ if (_fieldMap[fieldName] != state._fieldMap[fieldName]) {
+ return false;
+ }
+ otherFields.remove(fieldName);
+ }
+ for (String fieldName in otherFields) {
+ if (state._fieldMap[fieldName] != _fieldMap[fieldName]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @override
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(this == rightOperand);
+ }
+
+ @override
+ String toString() {
+ StringBuffer buffer = new StringBuffer();
+ List<String> fieldNames = _fieldMap.keys.toList();
+ fieldNames.sort();
+ bool first = true;
+ for (String fieldName in fieldNames) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.write('; ');
+ }
+ buffer.write(fieldName);
+ buffer.write(' = ');
+ buffer.write(_fieldMap[fieldName]);
+ }
+ return buffer.toString();
+ }
+}
+
+/**
+ * The state of an object representing a Dart object.
+ */
+abstract class InstanceState {
+ /**
+ * If this represents a generic dart object, return a map from its field names
+ * to their values. Otherwise return null.
+ */
+ HashMap<String, DartObjectImpl> get fields => null;
+
+ /**
+ * Return `true` if this object represents an object whose type is 'bool'.
+ */
+ bool get isBool => false;
+
+ /**
+ * Return `true` if this object represents an object whose type is either
+ * 'bool', 'num', 'String', or 'Null'.
+ */
+ bool get isBoolNumStringOrNull => false;
+
+ /**
+ * Return `true` if this object represents an unknown value.
+ */
+ bool get isUnknown => false;
+
+ /**
+ * Return the name of the type of this value.
+ */
+ String get typeName;
+
+ /**
+ * Return the result of invoking the '+' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ InstanceState add(InstanceState rightOperand) {
+ if (this is StringState && rightOperand is StringState) {
+ return concatenate(rightOperand);
+ }
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Throw an exception if the given [state] does not represent a boolean value.
+ */
+ void assertBool(InstanceState state) {
+ if (!(state is BoolState || state is DynamicState)) {
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
+ }
+ }
+
+ /**
+ * Throw an exception if the given [state] does not represent a boolean,
+ * numeric, string or null value.
+ */
+ void assertBoolNumStringOrNull(InstanceState state) {
+ if (!(state is BoolState ||
+ state is DoubleState ||
+ state is IntState ||
+ state is NumState ||
+ state is StringState ||
+ state is NullState ||
+ state is DynamicState)) {
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
+ }
+ }
+
+ /**
+ * Throw an exception if the given [state] does not represent an integer or
+ * null value.
+ */
+ void assertIntOrNull(InstanceState state) {
+ if (!(state is IntState ||
+ state is NumState ||
+ state is NullState ||
+ state is DynamicState)) {
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
+ }
+ }
+
+ /**
+ * Throw an exception if the given [state] does not represent a boolean,
+ * numeric, string or null value.
+ */
+ void assertNumOrNull(InstanceState state) {
+ if (!(state is DoubleState ||
+ state is IntState ||
+ state is NumState ||
+ state is NullState ||
+ state is DynamicState)) {
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
+ }
+ }
+
+ /**
+ * Throw an exception if the given [state] does not represent a String value.
+ */
+ void assertString(InstanceState state) {
+ if (!(state is StringState || state is DynamicState)) {
+ throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
+ }
+ }
+
+ /**
+ * Return the result of invoking the '&' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState bitAnd(InstanceState rightOperand) {
+ assertIntOrNull(this);
+ assertIntOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '~' operator on this object.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState bitNot() {
+ assertIntOrNull(this);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '|' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState bitOr(InstanceState rightOperand) {
+ assertIntOrNull(this);
+ assertIntOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '^' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState bitXor(InstanceState rightOperand) {
+ assertIntOrNull(this);
+ assertIntOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the ' ' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ StringState concatenate(InstanceState rightOperand) {
+ assertString(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of applying boolean conversion to this object.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState convertToBool() => BoolState.FALSE_STATE;
+
+ /**
+ * Return the result of converting this object to a String.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ StringState convertToString();
+
+ /**
+ * Return the result of invoking the '/' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ NumState divide(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '==' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState equalEqual(InstanceState rightOperand);
+
+ /**
+ * Return the result of invoking the '>' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState greaterThan(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '>=' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState greaterThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '~/' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState integerDivide(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the identical function on this object with
+ * the [rightOperand].
+ */
+ BoolState isIdentical(InstanceState rightOperand);
+
+ /**
+ * Return the result of invoking the '<' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState lessThan(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '<=' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState lessThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '&&' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState logicalAnd(InstanceState rightOperand) {
+ assertBool(this);
+ assertBool(rightOperand);
+ return BoolState.FALSE_STATE;
+ }
+
+ /**
+ * Return the result of invoking the '!' operator on this object.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState logicalNot() {
+ assertBool(this);
+ return BoolState.TRUE_STATE;
+ }
+
+ /**
+ * Return the result of invoking the '||' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ BoolState logicalOr(InstanceState rightOperand) {
+ assertBool(this);
+ assertBool(rightOperand);
+ return rightOperand.convertToBool();
+ }
+
+ /**
+ * Return the result of invoking the '-' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ NumState minus(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '-' operator on this object.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ NumState negated() {
+ assertNumOrNull(this);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '%' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ NumState remainder(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '<<' operator on this object with
+ * the [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState shiftLeft(InstanceState rightOperand) {
+ assertIntOrNull(this);
+ assertIntOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '>>' operator on this object with
+ * the [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState shiftRight(InstanceState rightOperand) {
+ assertIntOrNull(this);
+ assertIntOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the 'length' getter on this object.
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ IntState stringLength() {
+ assertString(this);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+
+ /**
+ * Return the result of invoking the '*' operator on this object with the
+ * [rightOperand].
+ *
+ * Throws an [EvaluationException] if the operator is not appropriate for an
+ * object of this kind.
+ */
+ NumState times(InstanceState rightOperand) {
+ assertNumOrNull(this);
+ assertNumOrNull(rightOperand);
+ throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
+ }
+}
+
+/**
+ * The state of an object representing an int.
+ */
+class IntState extends NumState {
+ /**
+ * A state that can be used to represent an int whose value is not known.
+ */
+ static IntState UNKNOWN_VALUE = new IntState(null);
+
+ /**
+ * The value of this instance.
+ */
+ final int value;
+
+ /**
+ * Initialize a newly created state to represent an int with the given
+ * [value].
+ */
+ IntState(this.value);
+
+ @override
+ int get hashCode => value == null ? 0 : value.hashCode;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ bool get isUnknown => value == null;
+
+ @override
+ String get typeName => "int";
+
+ @override
+ bool operator ==(Object object) =>
+ object is IntState && (value == object.value);
+
+ @override
+ NumState add(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value + rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() + rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState bitAnd(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value & rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState bitNot() {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(~value);
+ }
+
+ @override
+ IntState bitOr(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value | rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState bitXor(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value ^ rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ StringState convertToString() {
+ if (value == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(value.toString());
+ }
+
+ @override
+ NumState divide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ } else {
+ return new DoubleState(value.toDouble() / rightValue.toDouble());
+ }
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() / rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState greaterThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.compareTo(rightValue) > 0);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.toDouble() > rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState greaterThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.compareTo(rightValue) >= 0);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.toDouble() >= rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState integerDivide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ } else if (rightValue == 0) {
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
+ }
+ return new IntState(value ~/ rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ double result = value.toDouble() / rightValue;
+ return new IntState(result.toInt());
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value == rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(rightValue == value.toDouble());
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
+ }
+
+ @override
+ BoolState lessThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.compareTo(rightValue) < 0);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.toDouble() < rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ BoolState lessThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.compareTo(rightValue) <= 0);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value.toDouble() <= rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ NumState minus(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value - rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() - rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ NumState negated() {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(-value);
+ }
+
+ @override
+ NumState remainder(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ } else if (rightValue == 0) {
+ return new DoubleState(value.toDouble() % rightValue.toDouble());
+ }
+ return new IntState(value.remainder(rightValue));
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() % rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState shiftLeft(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ } else if (rightValue.bitLength > 31) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value << rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ IntState shiftRight(InstanceState rightOperand) {
+ assertIntOrNull(rightOperand);
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ } else if (rightValue.bitLength > 31) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value >> rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ NumState times(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (value == null) {
+ if (rightOperand is DoubleState) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new IntState(value * rightValue);
+ } else if (rightOperand is DoubleState) {
+ double rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return DoubleState.UNKNOWN_VALUE;
+ }
+ return new DoubleState(value.toDouble() * rightValue);
+ } else if (rightOperand is DynamicState || rightOperand is NumState) {
+ return UNKNOWN_VALUE;
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ String toString() => value == null ? "-unknown-" : value.toString();
+}
+
+/**
+ * The state of an object representing a list.
+ */
+class ListState extends InstanceState {
+ /**
+ * The elements of the list.
+ */
+ final List<DartObjectImpl> _elements;
+
+ /**
+ * Initialize a newly created state to represent a list with the given
+ * [elements].
+ */
+ ListState(this._elements);
+
+ @override
+ int get hashCode {
+ int value = 0;
+ int count = _elements.length;
+ for (int i = 0; i < count; i++) {
+ value = (value << 3) ^ _elements[i].hashCode;
+ }
+ return value;
+ }
+
+ @override
+ String get typeName => "List";
+
+ @override
+ bool operator ==(Object object) {
+ if (object is! ListState) {
+ return false;
+ }
+ List<DartObjectImpl> otherElements = (object as ListState)._elements;
+ int count = _elements.length;
+ if (otherElements.length != count) {
+ return false;
+ } else if (count == 0) {
+ return true;
+ }
+ for (int i = 0; i < count; i++) {
+ if (_elements[i] != otherElements[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @override
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(this == rightOperand);
+ }
+
+ @override
+ String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.write('[');
+ bool first = true;
+ _elements.forEach((DartObjectImpl element) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.write(', ');
+ }
+ buffer.write(element);
+ });
+ buffer.write(']');
+ return buffer.toString();
+ }
+}
+
+/**
+ * The state of an object representing a map.
+ */
+class MapState extends InstanceState {
+ /**
+ * The entries in the map.
+ */
+ final HashMap<DartObjectImpl, DartObjectImpl> _entries;
+
+ /**
+ * Initialize a newly created state to represent a map with the given
+ * [entries].
+ */
+ MapState(this._entries);
+
+ @override
+ int get hashCode {
+ int value = 0;
+ for (DartObjectImpl key in _entries.keys.toSet()) {
+ value = (value << 3) ^ key.hashCode;
+ }
+ return value;
+ }
+
+ @override
+ String get typeName => "Map";
+
+ @override
+ bool operator ==(Object object) {
+ if (object is! MapState) {
+ return false;
+ }
+ HashMap<DartObjectImpl, DartObjectImpl> otherElements =
+ (object as MapState)._entries;
+ int count = _entries.length;
+ if (otherElements.length != count) {
+ return false;
+ } else if (count == 0) {
+ return true;
+ }
+ for (DartObjectImpl key in _entries.keys) {
+ DartObjectImpl value = _entries[key];
+ DartObjectImpl otherValue = otherElements[key];
+ if (value != otherValue) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @override
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(this == rightOperand);
+ }
+
+ @override
+ String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.write('{');
+ bool first = true;
+ _entries.forEach((DartObjectImpl key, DartObjectImpl value) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.write(', ');
+ }
+ buffer.write(key);
+ buffer.write(' = ');
+ buffer.write(value);
+ });
+ buffer.write('}');
+ return buffer.toString();
+ }
+}
+
+/**
+ * The state of an object representing the value 'null'.
+ */
+class NullState extends InstanceState {
+ /**
+ * An instance representing the boolean value 'null'.
+ */
+ static NullState NULL_STATE = new NullState();
+
+ @override
+ int get hashCode => 0;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ String get typeName => "Null";
+
+ @override
+ bool operator ==(Object object) => object is NullState;
+
+ @override
+ BoolState convertToBool() {
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ StringState convertToString() => new StringState("null");
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(rightOperand is NullState);
+ }
+
+ @override
+ BoolState logicalNot() {
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
+ }
+
+ @override
+ String toString() => "null";
+}
+
+/**
+ * The state of an object representing a number of an unknown type (a 'num').
+ */
+class NumState extends InstanceState {
+ /**
+ * A state that can be used to represent a number whose value is not known.
+ */
+ static NumState UNKNOWN_VALUE = new NumState();
+
+ @override
+ int get hashCode => 7;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ bool get isUnknown => identical(this, UNKNOWN_VALUE);
+
+ @override
+ String get typeName => "num";
+
+ @override
+ bool operator ==(Object object) => object is NumState;
+
+ @override
+ NumState add(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return UNKNOWN_VALUE;
+ }
+
+ @override
+ StringState convertToString() => StringState.UNKNOWN_VALUE;
+
+ @override
+ NumState divide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return DoubleState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState greaterThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState greaterThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ IntState integerDivide(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ if (rightOperand is IntState) {
+ int rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return IntState.UNKNOWN_VALUE;
+ } else if (rightValue == 0) {
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
+ }
+ } else if (rightOperand is DynamicState) {
+ return IntState.UNKNOWN_VALUE;
+ }
+ return IntState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState lessThan(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ BoolState lessThanOrEqual(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return BoolState.UNKNOWN_VALUE;
+ }
+
+ @override
+ NumState minus(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return UNKNOWN_VALUE;
+ }
+
+ @override
+ NumState negated() => UNKNOWN_VALUE;
+
+ @override
+ NumState remainder(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return UNKNOWN_VALUE;
+ }
+
+ @override
+ NumState times(InstanceState rightOperand) {
+ assertNumOrNull(rightOperand);
+ return UNKNOWN_VALUE;
+ }
+
+ @override
+ String toString() => "-unknown-";
+}
+
+/**
+ * The state of an object representing a string.
+ */
+class StringState extends InstanceState {
+ /**
+ * A state that can be used to represent a double whose value is not known.
+ */
+ static StringState UNKNOWN_VALUE = new StringState(null);
+
+ /**
+ * The value of this instance.
+ */
+ final String value;
+
+ /**
+ * Initialize a newly created state to represent the given [value].
+ */
+ StringState(this.value);
+
+ @override
+ int get hashCode => value == null ? 0 : value.hashCode;
+
+ @override
+ bool get isBoolNumStringOrNull => true;
+
+ @override
+ bool get isUnknown => value == null;
+
+ @override
+ String get typeName => "String";
+
+ @override
+ bool operator ==(Object object) =>
+ object is StringState && (value == object.value);
+
+ @override
+ StringState concatenate(InstanceState rightOperand) {
+ if (value == null) {
+ return UNKNOWN_VALUE;
+ }
+ if (rightOperand is StringState) {
+ String rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return UNKNOWN_VALUE;
+ }
+ return new StringState("$value$rightValue");
+ } else if (rightOperand is DynamicState) {
+ return UNKNOWN_VALUE;
+ }
+ return super.concatenate(rightOperand);
+ }
+
+ @override
+ StringState convertToString() => this;
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is StringState) {
+ String rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value == rightValue);
+ } else if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
+ }
+
+ @override
+ IntState stringLength() {
+ if (value == null) {
+ return IntState.UNKNOWN_VALUE;
+ }
+ return new IntState(value.length);
+ }
+
+ @override
+ String toString() => value == null ? "-unknown-" : "'$value'";
+}
+
+/**
+ * The state of an object representing a symbol.
+ */
+class SymbolState extends InstanceState {
+ /**
+ * The value of this instance.
+ */
+ final String value;
+
+ /**
+ * Initialize a newly created state to represent the given [value].
+ */
+ SymbolState(this.value);
+
+ @override
+ int get hashCode => value == null ? 0 : value.hashCode;
+
+ @override
+ String get typeName => "Symbol";
+
+ @override
+ bool operator ==(Object object) =>
+ object is SymbolState && (value == object.value);
+
+ @override
+ StringState convertToString() {
+ if (value == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(value);
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (value == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is SymbolState) {
+ String rightValue = rightOperand.value;
+ if (rightValue == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(value == rightValue);
+ } else if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
+ }
+
+ @override
+ String toString() => value == null ? "-unknown-" : "#$value";
+}
+
+/**
+ * The state of an object representing a type.
+ */
+class TypeState extends InstanceState {
+ /**
+ * The element representing the type being modeled.
+ */
+ final Element _element;
+
+ /**
+ * Initialize a newly created state to represent the given [value].
+ */
+ TypeState(this._element);
+
+ @override
+ int get hashCode => _element == null ? 0 : _element.hashCode;
+
+ @override
+ String get typeName => "Type";
+
+ @override
+ bool operator ==(Object object) =>
+ object is TypeState && (_element == object._element);
+
+ @override
+ StringState convertToString() {
+ if (_element == null) {
+ return StringState.UNKNOWN_VALUE;
+ }
+ return new StringState(_element.name);
+ }
+
+ @override
+ BoolState equalEqual(InstanceState rightOperand) {
+ assertBoolNumStringOrNull(rightOperand);
+ return isIdentical(rightOperand);
+ }
+
+ @override
+ BoolState isIdentical(InstanceState rightOperand) {
+ if (_element == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ if (rightOperand is TypeState) {
+ Element rightElement = rightOperand._element;
+ if (rightElement == null) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.from(_element == rightElement);
+ } else if (rightOperand is DynamicState) {
+ return BoolState.UNKNOWN_VALUE;
+ }
+ return BoolState.FALSE_STATE;
+ }
+
+ @override
+ String toString() => _element == null ? "-unknown-" : _element.name;
+}
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 24241df..c91582c 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -9,14 +9,14 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/constant.dart'
- show DartObject, EvaluationResultImpl;
+import 'package:analyzer/src/generated/constant.dart' show EvaluationResultImpl;
import 'package:analyzer/src/generated/engine.dart'
show AnalysisContext, AnalysisEngine;
import 'package:analyzer/src/generated/java_core.dart';
@@ -679,9 +679,12 @@
visitedClasses.add(this);
}
try {
- ClassElementImpl superclass = supertype.element;
- constructorsToForward =
- superclass._computeMixinAppConstructors(visitedClasses);
+ ClassElement superclass = supertype.element;
+ if (superclass is ClassElementHandle) {
+ superclass = (superclass as ClassElementHandle).actualElement;
+ }
+ constructorsToForward = (superclass as ClassElementImpl)
+ ._computeMixinAppConstructors(visitedClasses);
} finally {
visitedClasses.removeLast();
}
@@ -2091,15 +2094,6 @@
}
/**
- * If the given [child] is not `null`, use the given [visitor] to visit it.
- */
- void safelyVisitChild(Element child, ElementVisitor visitor) {
- if (child != null) {
- child.accept(visitor);
- }
- }
-
- /**
* Use the given [visitor] to visit all of the [children] in the given array.
*/
void safelyVisitChildren(List<Element> children, ElementVisitor visitor) {
@@ -3048,7 +3042,7 @@
@override
void visitChildren(ElementVisitor visitor) {
super.visitChildren(visitor);
- safelyVisitChild(prefix, visitor);
+ prefix?.accept(visitor);
}
}
@@ -3194,8 +3188,8 @@
* the given [name].
*/
LibraryElementImpl.forNode(this.context, LibraryIdentifier name)
- : super.forNode(name),
- nameLength = name != null ? name.length : 0;
+ : nameLength = name != null ? name.length : 0,
+ super.forNode(name);
@override
int get codeLength {
@@ -3600,14 +3594,19 @@
// are in the case where library cycles have simply never been computed from
// a newly reachable node.
Set<LibraryElementImpl> active = new HashSet();
- void invalidate(LibraryElementImpl library) {
- if (!active.add(library)) return;
- if (library._libraryCycle != null) {
- library._libraryCycle.forEach(invalidate);
- library._libraryCycle = null;
+ void invalidate(LibraryElement library) {
+ if (library is LibraryElementHandle) {
+ library = (library as LibraryElementHandle).actualElement;
}
- library.exportedLibraries.forEach(invalidate);
- library.importedLibraries.forEach(invalidate);
+ LibraryElementImpl libraryImpl = library;
+ if (active.add(libraryImpl)) {
+ if (libraryImpl._libraryCycle != null) {
+ libraryImpl._libraryCycle.forEach(invalidate);
+ libraryImpl._libraryCycle = null;
+ }
+ library.exportedLibraries.forEach(invalidate);
+ library.importedLibraries.forEach(invalidate);
+ }
}
invalidate(this);
}
@@ -3621,7 +3620,7 @@
@override
void visitChildren(ElementVisitor visitor) {
super.visitChildren(visitor);
- safelyVisitChild(_definingCompilationUnit, visitor);
+ _definingCompilationUnit?.accept(visitor);
safelyVisitChildren(_exports, visitor);
safelyVisitChildren(_imports, visitor);
safelyVisitChildren(_parts, visitor);
@@ -4917,7 +4916,7 @@
@override
void visitChildren(ElementVisitor visitor) {
super.visitChildren(visitor);
- safelyVisitChild(_initializer, visitor);
+ _initializer?.accept(visitor);
}
}
diff --git a/pkg/analyzer/lib/src/dart/element/handle.dart b/pkg/analyzer/lib/src/dart/element/handle.dart
index dfecff2..8cde8d0 100644
--- a/pkg/analyzer/lib/src/dart/element/handle.dart
+++ b/pkg/analyzer/lib/src/dart/element/handle.dart
@@ -5,10 +5,10 @@
library analyzer.src.generated.element_handle;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 28bce1e..0ac6d4a 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -5,12 +5,11 @@
library analyzer.src.dart.element.member;
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/constant.dart'
- show DartObject, EvaluationResultImpl;
import 'package:analyzer/src/generated/engine.dart'
show AnalysisContext, AnalysisEngine;
import 'package:analyzer/src/generated/java_core.dart';
@@ -524,6 +523,7 @@
/**
* If the given [child] is not `null`, use the given [visitor] to visit it.
*/
+ @deprecated
void safelyVisitChild(Element child, ElementVisitor visitor) {
// TODO(brianwilkerson) Make this private
if (child != null) {
@@ -1017,10 +1017,12 @@
bool get isFinal => baseElement.isFinal;
@override
+ @deprecated
bool get isPotentiallyMutatedInClosure =>
baseElement.isPotentiallyMutatedInClosure;
@override
+ @deprecated
bool get isPotentiallyMutatedInScope =>
baseElement.isPotentiallyMutatedInScope;
@@ -1032,6 +1034,6 @@
// TODO(brianwilkerson) We need to finish implementing the accessors used
// below so that we can safely invoke them.
super.visitChildren(visitor);
- safelyVisitChild(baseElement.initializer, visitor);
+ baseElement.initializer?.accept(visitor);
}
}
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index 0f1d7e9..16113c5 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -4,1069 +4,24 @@
library analyzer.src.generated.constant;
-import 'dart:collection';
-
+import 'package:analyzer/context/declared_variables.dart';
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/handle.dart'
- show ConstructorElementHandle;
-import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
+import 'package:analyzer/src/dart/constant/value.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/engine.dart'
show AnalysisEngine, RecordingErrorListener;
import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/source.dart' show Source;
import 'package:analyzer/src/generated/type_system.dart'
show TypeSystem, TypeSystemImpl;
-import 'package:analyzer/src/generated/utilities_collection.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
-import 'package:analyzer/src/generated/utilities_general.dart';
-import 'package:analyzer/src/task/dart.dart';
-ConstructorElementImpl _getConstructorImpl(ConstructorElement constructor) {
- while (constructor is ConstructorMember) {
- constructor = (constructor as ConstructorMember).baseElement;
- }
- if (constructor is ConstructorElementHandle) {
- constructor = (constructor as ConstructorElementHandle).actualElement;
- }
- return constructor;
-}
-
-/**
- * Callback used by [ReferenceFinder] to report that a dependency was found.
- */
-typedef void ReferenceFinderCallback(ConstantEvaluationTarget dependency);
-
-/**
- * The state of an object representing a boolean value.
- */
-class BoolState extends InstanceState {
- /**
- * An instance representing the boolean value 'false'.
- */
- static BoolState FALSE_STATE = new BoolState(false);
-
- /**
- * An instance representing the boolean value 'true'.
- */
- static BoolState TRUE_STATE = new BoolState(true);
-
- /**
- * A state that can be used to represent a boolean whose value is not known.
- */
- static BoolState UNKNOWN_VALUE = new BoolState(null);
-
- /**
- * The value of this instance.
- */
- final bool value;
-
- /**
- * Initialize a newly created state to represent the given [value].
- */
- BoolState(this.value);
-
- @override
- int get hashCode => value == null ? 0 : (value ? 2 : 3);
-
- @override
- bool get isBool => true;
-
- @override
- bool get isBoolNumStringOrNull => true;
-
- @override
- bool get isUnknown => value == null;
-
- @override
- String get typeName => "bool";
-
- @override
- bool operator ==(Object object) =>
- object is BoolState && identical(value, object.value);
-
- @override
- BoolState convertToBool() => this;
-
- @override
- StringState convertToString() {
- if (value == null) {
- return StringState.UNKNOWN_VALUE;
- }
- return new StringState(value ? "true" : "false");
- }
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- return isIdentical(rightOperand);
- }
-
- @override
- BoolState isIdentical(InstanceState rightOperand) {
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is BoolState) {
- bool rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return BoolState.from(identical(value, rightValue));
- } else if (rightOperand is DynamicState) {
- return UNKNOWN_VALUE;
- }
- return FALSE_STATE;
- }
-
- @override
- BoolState logicalAnd(InstanceState rightOperand) {
- assertBool(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- return value ? rightOperand.convertToBool() : FALSE_STATE;
- }
-
- @override
- BoolState logicalNot() {
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- return value ? FALSE_STATE : TRUE_STATE;
- }
-
- @override
- BoolState logicalOr(InstanceState rightOperand) {
- assertBool(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- return value ? TRUE_STATE : rightOperand.convertToBool();
- }
-
- @override
- String toString() => value == null ? "-unknown-" : (value ? "true" : "false");
-
- /**
- * Return the boolean state representing the given boolean [value].
- */
- static BoolState from(bool value) =>
- value ? BoolState.TRUE_STATE : BoolState.FALSE_STATE;
-}
-
-/**
- * An [AstCloner] that copies the necessary information from the AST to allow
- * constants to be evaluated.
- */
-class ConstantAstCloner extends AstCloner {
- ConstantAstCloner() : super(true);
-
- @override
- ConstructorName visitConstructorName(ConstructorName node) {
- ConstructorName name = super.visitConstructorName(node);
- name.staticElement = node.staticElement;
- return name;
- }
-
- @override
- InstanceCreationExpression visitInstanceCreationExpression(
- InstanceCreationExpression node) {
- InstanceCreationExpression expression =
- super.visitInstanceCreationExpression(node);
- expression.staticElement = node.staticElement;
- return expression;
- }
-
- @override
- RedirectingConstructorInvocation visitRedirectingConstructorInvocation(
- RedirectingConstructorInvocation node) {
- RedirectingConstructorInvocation invocation =
- super.visitRedirectingConstructorInvocation(node);
- invocation.staticElement = node.staticElement;
- return invocation;
- }
-
- @override
- SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) {
- SimpleIdentifier identifier = super.visitSimpleIdentifier(node);
- identifier.staticElement = node.staticElement;
- return identifier;
- }
-
- @override
- SuperConstructorInvocation visitSuperConstructorInvocation(
- SuperConstructorInvocation node) {
- SuperConstructorInvocation invocation =
- super.visitSuperConstructorInvocation(node);
- invocation.staticElement = node.staticElement;
- return invocation;
- }
-
- @override
- TypeName visitTypeName(TypeName node) {
- TypeName typeName = super.visitTypeName(node);
- typeName.type = node.type;
- return typeName;
- }
-}
-
-/**
- * Helper class encapsulating the methods for evaluating constants and
- * constant instance creation expressions.
- */
-class ConstantEvaluationEngine {
- /**
- * Parameter to "fromEnvironment" methods that denotes the default value.
- */
- static String _DEFAULT_VALUE_PARAM = "defaultValue";
-
- /**
- * Source of RegExp matching any public identifier.
- * From sdk/lib/internal/symbol.dart.
- */
- static String _PUBLIC_IDENTIFIER_RE =
- "(?!${ConstantValueComputer._RESERVED_WORD_RE}\\b(?!\\\$))[a-zA-Z\$][\\w\$]*";
-
- /**
- * RegExp that validates a non-empty non-private symbol.
- * From sdk/lib/internal/symbol.dart.
- */
- static RegExp _PUBLIC_SYMBOL_PATTERN = new RegExp(
- "^(?:${ConstantValueComputer._OPERATOR_RE}\$|$_PUBLIC_IDENTIFIER_RE(?:=?\$|[.](?!\$)))+?\$");
-
- /**
- * The type provider used to access the known types.
- */
- final TypeProvider typeProvider;
-
- /**
- * The type system. This is used to guess the types of constants when their
- * exact value is unknown.
- */
- final TypeSystem typeSystem;
-
- /**
- * The set of variables declared on the command line using '-D'.
- */
- final DeclaredVariables _declaredVariables;
-
- /**
- * Validator used to verify correct dependency analysis when running unit
- * tests.
- */
- final ConstantEvaluationValidator validator;
-
- /**
- * Initialize a newly created [ConstantEvaluationEngine]. The [typeProvider]
- * is used to access known types. [_declaredVariables] is the set of
- * variables declared on the command line using '-D'. The [validator], if
- * given, is used to verify correct dependency analysis when running unit
- * tests.
- */
- ConstantEvaluationEngine(this.typeProvider, this._declaredVariables,
- {ConstantEvaluationValidator validator, TypeSystem typeSystem})
- : validator = validator != null
- ? validator
- : new ConstantEvaluationValidator_ForProduction(),
- typeSystem = typeSystem != null ? typeSystem : new TypeSystemImpl();
-
- /**
- * Check that the arguments to a call to fromEnvironment() are correct. The
- * [arguments] are the AST nodes of the arguments. The [argumentValues] are
- * the values of the unnamed arguments. The [namedArgumentValues] are the
- * values of the named arguments. The [expectedDefaultValueType] is the
- * allowed type of the "defaultValue" parameter (if present). Note:
- * "defaultValue" is always allowed to be null. Return `true` if the arguments
- * are correct, `false` if there is an error.
- */
- bool checkFromEnvironmentArguments(
- NodeList<Expression> arguments,
- List<DartObjectImpl> argumentValues,
- HashMap<String, DartObjectImpl> namedArgumentValues,
- InterfaceType expectedDefaultValueType) {
- int argumentCount = arguments.length;
- if (argumentCount < 1 || argumentCount > 2) {
- return false;
- }
- if (arguments[0] is NamedExpression) {
- return false;
- }
- if (!identical(argumentValues[0].type, typeProvider.stringType)) {
- return false;
- }
- if (argumentCount == 2) {
- if (arguments[1] is! NamedExpression) {
- return false;
- }
- if (!((arguments[1] as NamedExpression).name.label.name ==
- _DEFAULT_VALUE_PARAM)) {
- return false;
- }
- ParameterizedType defaultValueType =
- namedArgumentValues[_DEFAULT_VALUE_PARAM].type;
- if (!(identical(defaultValueType, expectedDefaultValueType) ||
- identical(defaultValueType, typeProvider.nullType))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Check that the arguments to a call to Symbol() are correct. The [arguments]
- * are the AST nodes of the arguments. The [argumentValues] are the values of
- * the unnamed arguments. The [namedArgumentValues] are the values of the
- * named arguments. Return `true` if the arguments are correct, `false` if
- * there is an error.
- */
- bool checkSymbolArguments(
- NodeList<Expression> arguments,
- List<DartObjectImpl> argumentValues,
- HashMap<String, DartObjectImpl> namedArgumentValues) {
- if (arguments.length != 1) {
- return false;
- }
- if (arguments[0] is NamedExpression) {
- return false;
- }
- if (!identical(argumentValues[0].type, typeProvider.stringType)) {
- return false;
- }
- String name = argumentValues[0].toStringValue();
- return isValidPublicSymbol(name);
- }
-
- /**
- * Compute the constant value associated with the given [constant].
- */
- void computeConstantValue(ConstantEvaluationTarget constant) {
- validator.beforeComputeValue(constant);
- if (constant is ParameterElementImpl) {
- Expression defaultValue = constant.constantInitializer;
- if (defaultValue != null) {
- RecordingErrorListener errorListener = new RecordingErrorListener();
- ErrorReporter errorReporter =
- new ErrorReporter(errorListener, constant.source);
- DartObjectImpl dartObject =
- defaultValue.accept(new ConstantVisitor(this, errorReporter));
- constant.evaluationResult =
- new EvaluationResultImpl(dartObject, errorListener.errors);
- }
- } else if (constant is VariableElementImpl) {
- Expression constantInitializer = constant.constantInitializer;
- if (constantInitializer != null) {
- RecordingErrorListener errorListener = new RecordingErrorListener();
- ErrorReporter errorReporter =
- new ErrorReporter(errorListener, constant.source);
- DartObjectImpl dartObject = constantInitializer
- .accept(new ConstantVisitor(this, errorReporter));
- // Only check the type for truly const declarations (don't check final
- // fields with initializers, since their types may be generic. The type
- // of the final field will be checked later, when the constructor is
- // invoked).
- if (dartObject != null && constant.isConst) {
- if (!runtimeTypeMatch(dartObject, constant.type)) {
- errorReporter.reportErrorForElement(
- CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
- constant,
- [dartObject.type, constant.type]);
- }
- }
- constant.evaluationResult =
- new EvaluationResultImpl(dartObject, errorListener.errors);
- }
- } else if (constant is ConstructorElement) {
- if (constant.isConst) {
- // No evaluation needs to be done; constructor declarations are only in
- // the dependency graph to ensure that any constants referred to in
- // initializer lists and parameter defaults are evaluated before
- // invocations of the constructor. However we do need to annotate the
- // element as being free of constant evaluation cycles so that later
- // code will know that it is safe to evaluate.
- (constant as ConstructorElementImpl).isCycleFree = true;
- }
- } else if (constant is ElementAnnotationImpl) {
- Annotation constNode = constant.annotationAst;
- Element element = constant.element;
- if (element is PropertyAccessorElement &&
- element.variable is VariableElementImpl) {
- // The annotation is a reference to a compile-time constant variable.
- // Just copy the evaluation result.
- VariableElementImpl variableElement =
- element.variable as VariableElementImpl;
- if (variableElement.evaluationResult != null) {
- constant.evaluationResult = variableElement.evaluationResult;
- } else {
- // This could happen in the event that the annotation refers to a
- // non-constant. The error is detected elsewhere, so just silently
- // ignore it here.
- constant.evaluationResult = new EvaluationResultImpl(null);
- }
- } else if (element is ConstructorElementImpl &&
- element.isConst &&
- constNode.arguments != null) {
- RecordingErrorListener errorListener = new RecordingErrorListener();
- ErrorReporter errorReporter =
- new ErrorReporter(errorListener, constant.source);
- ConstantVisitor constantVisitor =
- new ConstantVisitor(this, errorReporter);
- DartObjectImpl result = evaluateConstructorCall(
- constNode,
- constNode.arguments.arguments,
- element,
- constantVisitor,
- errorReporter);
- constant.evaluationResult =
- new EvaluationResultImpl(result, errorListener.errors);
- } else {
- // This may happen for invalid code (e.g. failing to pass arguments
- // to an annotation which references a const constructor). The error
- // is detected elsewhere, so just silently ignore it here.
- constant.evaluationResult = new EvaluationResultImpl(null);
- }
- } else if (constant is VariableElement) {
- // constant is a VariableElement but not a VariableElementImpl. This can
- // happen sometimes in the case of invalid user code (for example, a
- // constant expression that refers to a non-static field inside a generic
- // class will wind up referring to a FieldMember). The error is detected
- // elsewhere, so just silently ignore it here.
- } else {
- // Should not happen.
- assert(false);
- AnalysisEngine.instance.logger.logError(
- "Constant value computer trying to compute the value of a node of type ${constant.runtimeType}");
- return;
- }
- }
-
- /**
- * Determine which constant elements need to have their values computed
- * prior to computing the value of [constant], and report them using
- * [callback].
- */
- void computeDependencies(
- ConstantEvaluationTarget constant, ReferenceFinderCallback callback) {
- ReferenceFinder referenceFinder = new ReferenceFinder(callback);
- if (constant is ConstructorElement) {
- constant = _getConstructorImpl(constant);
- }
- if (constant is VariableElementImpl) {
- Expression initializer = constant.constantInitializer;
- if (initializer != null) {
- initializer.accept(referenceFinder);
- }
- } else if (constant is ConstructorElementImpl) {
- if (constant.isConst) {
- constant.isCycleFree = false;
- ConstructorElement redirectedConstructor =
- getConstRedirectedConstructor(constant);
- if (redirectedConstructor != null) {
- ConstructorElement redirectedConstructorBase =
- _getConstructorImpl(redirectedConstructor);
- callback(redirectedConstructorBase);
- return;
- } else if (constant.isFactory) {
- // Factory constructor, but getConstRedirectedConstructor returned
- // null. This can happen if we're visiting one of the special external
- // const factory constructors in the SDK, or if the code contains
- // errors (such as delegating to a non-const constructor, or delegating
- // to a constructor that can't be resolved). In any of these cases,
- // we'll evaluate calls to this constructor without having to refer to
- // any other constants. So we don't need to report any dependencies.
- return;
- }
- bool superInvocationFound = false;
- List<ConstructorInitializer> initializers =
- constant.constantInitializers;
- for (ConstructorInitializer initializer in initializers) {
- if (initializer is SuperConstructorInvocation) {
- superInvocationFound = true;
- }
- initializer.accept(referenceFinder);
- }
- if (!superInvocationFound) {
- // No explicit superconstructor invocation found, so we need to
- // manually insert a reference to the implicit superconstructor.
- InterfaceType superclass =
- (constant.returnType as InterfaceType).superclass;
- if (superclass != null && !superclass.isObject) {
- ConstructorElement unnamedConstructor =
- _getConstructorImpl(superclass.element.unnamedConstructor);
- if (unnamedConstructor != null) {
- callback(unnamedConstructor);
- }
- }
- }
- for (FieldElement field in constant.enclosingElement.fields) {
- // Note: non-static const isn't allowed but we handle it anyway so
- // that we won't be confused by incorrect code.
- if ((field.isFinal || field.isConst) &&
- !field.isStatic &&
- field.initializer != null) {
- callback(field);
- }
- }
- for (ParameterElement parameterElement in constant.parameters) {
- callback(parameterElement);
- }
- }
- } else if (constant is ElementAnnotationImpl) {
- Annotation constNode = constant.annotationAst;
- Element element = constant.element;
- if (element is PropertyAccessorElement &&
- element.variable is VariableElementImpl) {
- // The annotation is a reference to a compile-time constant variable,
- // so it depends on the variable.
- callback(element.variable);
- } else if (element is ConstructorElementImpl) {
- // The annotation is a constructor invocation, so it depends on the
- // constructor.
- callback(element);
- } else {
- // This could happen in the event of invalid code. The error will be
- // reported at constant evaluation time.
- }
- if (constNode.arguments != null) {
- constNode.arguments.accept(referenceFinder);
- }
- } else if (constant is VariableElement) {
- // constant is a VariableElement but not a VariableElementImpl. This can
- // happen sometimes in the case of invalid user code (for example, a
- // constant expression that refers to a non-static field inside a generic
- // class will wind up referring to a FieldMember). So just don't bother
- // computing any dependencies.
- } else {
- // Should not happen.
- assert(false);
- AnalysisEngine.instance.logger.logError(
- "Constant value computer trying to compute the value of a node of type ${constant.runtimeType}");
- }
- }
-
- /**
- * Evaluate a call to fromEnvironment() on the bool, int, or String class. The
- * [environmentValue] is the value fetched from the environment. The
- * [builtInDefaultValue] is the value that should be used as the default if no
- * "defaultValue" argument appears in [namedArgumentValues]. The
- * [namedArgumentValues] are the values of the named parameters passed to
- * fromEnvironment(). Return a [DartObjectImpl] object corresponding to the
- * evaluated result.
- */
- DartObjectImpl computeValueFromEnvironment(
- DartObject environmentValue,
- DartObjectImpl builtInDefaultValue,
- HashMap<String, DartObjectImpl> namedArgumentValues) {
- DartObjectImpl value = environmentValue as DartObjectImpl;
- if (value.isUnknown || value.isNull) {
- // The name either doesn't exist in the environment or we couldn't parse
- // the corresponding value.
- // If the code supplied an explicit default, use it.
- if (namedArgumentValues.containsKey(_DEFAULT_VALUE_PARAM)) {
- value = namedArgumentValues[_DEFAULT_VALUE_PARAM];
- } else if (value.isNull) {
- // The code didn't supply an explicit default.
- // The name exists in the environment but we couldn't parse the
- // corresponding value.
- // So use the built-in default value, because this is what the VM does.
- value = builtInDefaultValue;
- } else {
- // The code didn't supply an explicit default.
- // The name doesn't exist in the environment.
- // The VM would use the built-in default value, but we don't want to do
- // that for analysis because it's likely to lead to cascading errors.
- // So just leave [value] in the unknown state.
- }
- }
- return value;
- }
-
- DartObjectImpl evaluateConstructorCall(
- AstNode node,
- NodeList<Expression> arguments,
- ConstructorElement constructor,
- ConstantVisitor constantVisitor,
- ErrorReporter errorReporter) {
- if (!_getConstructorImpl(constructor).isCycleFree) {
- // It's not safe to evaluate this constructor, so bail out.
- // TODO(paulberry): ensure that a reasonable error message is produced
- // in this case, as well as other cases involving constant expression
- // circularities (e.g. "compile-time constant expression depends on
- // itself")
- return new DartObjectImpl.validWithUnknownValue(constructor.returnType);
- }
- int argumentCount = arguments.length;
- List<DartObjectImpl> argumentValues =
- new List<DartObjectImpl>(argumentCount);
- List<Expression> argumentNodes = new List<Expression>(argumentCount);
- HashMap<String, DartObjectImpl> namedArgumentValues =
- new HashMap<String, DartObjectImpl>();
- HashMap<String, NamedExpression> namedArgumentNodes =
- new HashMap<String, NamedExpression>();
- for (int i = 0; i < argumentCount; i++) {
- Expression argument = arguments[i];
- if (argument is NamedExpression) {
- String name = argument.name.label.name;
- namedArgumentValues[name] =
- constantVisitor._valueOf(argument.expression);
- namedArgumentNodes[name] = argument;
- argumentValues[i] = typeProvider.nullObject;
- } else {
- argumentValues[i] = constantVisitor._valueOf(argument);
- argumentNodes[i] = argument;
- }
- }
- constructor = followConstantRedirectionChain(constructor);
- InterfaceType definingClass = constructor.returnType as InterfaceType;
- if (constructor.isFactory) {
- // We couldn't find a non-factory constructor.
- // See if it's because we reached an external const factory constructor
- // that we can emulate.
- if (constructor.name == "fromEnvironment") {
- if (!checkFromEnvironmentArguments(
- arguments, argumentValues, namedArgumentValues, definingClass)) {
- errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
- return null;
- }
- String variableName =
- argumentCount < 1 ? null : argumentValues[0].toStringValue();
- if (identical(definingClass, typeProvider.boolType)) {
- DartObject valueFromEnvironment;
- valueFromEnvironment =
- _declaredVariables.getBool(typeProvider, variableName);
- return computeValueFromEnvironment(
- valueFromEnvironment,
- new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE),
- namedArgumentValues);
- } else if (identical(definingClass, typeProvider.intType)) {
- DartObject valueFromEnvironment;
- valueFromEnvironment =
- _declaredVariables.getInt(typeProvider, variableName);
- return computeValueFromEnvironment(
- valueFromEnvironment,
- new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
- namedArgumentValues);
- } else if (identical(definingClass, typeProvider.stringType)) {
- DartObject valueFromEnvironment;
- valueFromEnvironment =
- _declaredVariables.getString(typeProvider, variableName);
- return computeValueFromEnvironment(
- valueFromEnvironment,
- new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE),
- namedArgumentValues);
- }
- } else if (constructor.name == "" &&
- identical(definingClass, typeProvider.symbolType) &&
- argumentCount == 1) {
- if (!checkSymbolArguments(
- arguments, argumentValues, namedArgumentValues)) {
- errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
- return null;
- }
- String argumentValue = argumentValues[0].toStringValue();
- return new DartObjectImpl(
- definingClass, new SymbolState(argumentValue));
- }
- // Either it's an external const factory constructor that we can't
- // emulate, or an error occurred (a cycle, or a const constructor trying
- // to delegate to a non-const constructor).
- // In the former case, the best we can do is consider it an unknown value.
- // In the latter case, the error has already been reported, so considering
- // it an unknown value will suppress further errors.
- return new DartObjectImpl.validWithUnknownValue(definingClass);
- }
- ConstructorElementImpl constructorBase = _getConstructorImpl(constructor);
- validator.beforeGetConstantInitializers(constructorBase);
- List<ConstructorInitializer> initializers =
- constructorBase.constantInitializers;
- if (initializers == null) {
- // This can happen in some cases where there are compile errors in the
- // code being analyzed (for example if the code is trying to create a
- // const instance using a non-const constructor, or the node we're
- // visiting is involved in a cycle). The error has already been reported,
- // so consider it an unknown value to suppress further errors.
- return new DartObjectImpl.validWithUnknownValue(definingClass);
- }
- HashMap<String, DartObjectImpl> fieldMap =
- new HashMap<String, DartObjectImpl>();
- // Start with final fields that are initialized at their declaration site.
- for (FieldElement field in constructor.enclosingElement.fields) {
- if ((field.isFinal || field.isConst) &&
- !field.isStatic &&
- field is ConstFieldElementImpl) {
- validator.beforeGetFieldEvaluationResult(field);
- EvaluationResultImpl evaluationResult = field.evaluationResult;
- // It is possible that the evaluation result is null.
- // This happens for example when we have duplicate fields.
- // class Test {final x = 1; final x = 2; const Test();}
- if (evaluationResult == null) {
- continue;
- }
- // Match the value and the type.
- DartType fieldType =
- FieldMember.from(field, constructor.returnType).type;
- DartObjectImpl fieldValue = evaluationResult.value;
- if (fieldValue != null && !runtimeTypeMatch(fieldValue, fieldType)) {
- errorReporter.reportErrorForNode(
- CheckedModeCompileTimeErrorCode
- .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
- node,
- [fieldValue.type, field.name, fieldType]);
- }
- fieldMap[field.name] = fieldValue;
- }
- }
- // Now evaluate the constructor declaration.
- HashMap<String, DartObjectImpl> parameterMap =
- new HashMap<String, DartObjectImpl>();
- List<ParameterElement> parameters = constructor.parameters;
- int parameterCount = parameters.length;
- for (int i = 0; i < parameterCount; i++) {
- ParameterElement parameter = parameters[i];
- ParameterElement baseParameter = parameter;
- while (baseParameter is ParameterMember) {
- baseParameter = (baseParameter as ParameterMember).baseElement;
- }
- DartObjectImpl argumentValue = null;
- AstNode errorTarget = null;
- if (baseParameter.parameterKind == ParameterKind.NAMED) {
- argumentValue = namedArgumentValues[baseParameter.name];
- errorTarget = namedArgumentNodes[baseParameter.name];
- } else if (i < argumentCount) {
- argumentValue = argumentValues[i];
- errorTarget = argumentNodes[i];
- }
- if (errorTarget == null) {
- // No argument node that we can direct error messages to, because we
- // are handling an optional parameter that wasn't specified. So just
- // direct error messages to the constructor call.
- errorTarget = node;
- }
- if (argumentValue == null && baseParameter is ParameterElementImpl) {
- // The parameter is an optional positional parameter for which no value
- // was provided, so use the default value.
- validator.beforeGetParameterDefault(baseParameter);
- EvaluationResultImpl evaluationResult = baseParameter.evaluationResult;
- if (evaluationResult == null) {
- // No default was provided, so the default value is null.
- argumentValue = typeProvider.nullObject;
- } else if (evaluationResult.value != null) {
- argumentValue = evaluationResult.value;
- }
- }
- if (argumentValue != null) {
- if (!runtimeTypeMatch(argumentValue, parameter.type)) {
- errorReporter.reportErrorForNode(
- CheckedModeCompileTimeErrorCode
- .CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
- errorTarget,
- [argumentValue.type, parameter.type]);
- }
- if (baseParameter.isInitializingFormal) {
- FieldElement field = (parameter as FieldFormalParameterElement).field;
- if (field != null) {
- DartType fieldType = field.type;
- if (fieldType != parameter.type) {
- // We've already checked that the argument can be assigned to the
- // parameter; we also need to check that it can be assigned to
- // the field.
- if (!runtimeTypeMatch(argumentValue, fieldType)) {
- errorReporter.reportErrorForNode(
- CheckedModeCompileTimeErrorCode
- .CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
- errorTarget,
- [argumentValue.type, fieldType]);
- }
- }
- String fieldName = field.name;
- if (fieldMap.containsKey(fieldName)) {
- errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
- }
- fieldMap[fieldName] = argumentValue;
- }
- } else {
- String name = baseParameter.name;
- parameterMap[name] = argumentValue;
- }
- }
- }
- ConstantVisitor initializerVisitor = new ConstantVisitor(
- this, errorReporter,
- lexicalEnvironment: parameterMap);
- String superName = null;
- NodeList<Expression> superArguments = null;
- for (ConstructorInitializer initializer in initializers) {
- if (initializer is ConstructorFieldInitializer) {
- ConstructorFieldInitializer constructorFieldInitializer = initializer;
- Expression initializerExpression =
- constructorFieldInitializer.expression;
- DartObjectImpl evaluationResult =
- initializerExpression.accept(initializerVisitor);
- if (evaluationResult != null) {
- String fieldName = constructorFieldInitializer.fieldName.name;
- if (fieldMap.containsKey(fieldName)) {
- errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
- }
- fieldMap[fieldName] = evaluationResult;
- PropertyAccessorElement getter = definingClass.getGetter(fieldName);
- if (getter != null) {
- PropertyInducingElement field = getter.variable;
- if (!runtimeTypeMatch(evaluationResult, field.type)) {
- errorReporter.reportErrorForNode(
- CheckedModeCompileTimeErrorCode
- .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
- node,
- [evaluationResult.type, fieldName, field.type]);
- }
- }
- }
- } else if (initializer is SuperConstructorInvocation) {
- SuperConstructorInvocation superConstructorInvocation = initializer;
- SimpleIdentifier name = superConstructorInvocation.constructorName;
- if (name != null) {
- superName = name.name;
- }
- superArguments = superConstructorInvocation.argumentList.arguments;
- } else if (initializer is RedirectingConstructorInvocation) {
- // This is a redirecting constructor, so just evaluate the constructor
- // it redirects to.
- ConstructorElement constructor = initializer.staticElement;
- if (constructor != null && constructor.isConst) {
- return evaluateConstructorCall(
- node,
- initializer.argumentList.arguments,
- constructor,
- initializerVisitor,
- errorReporter);
- }
- }
- }
- // Evaluate explicit or implicit call to super().
- InterfaceType superclass = definingClass.superclass;
- if (superclass != null && !superclass.isObject) {
- ConstructorElement superConstructor =
- superclass.lookUpConstructor(superName, constructor.library);
- if (superConstructor != null) {
- if (superArguments == null) {
- superArguments = new NodeList<Expression>(null);
- }
- evaluateSuperConstructorCall(node, fieldMap, superConstructor,
- superArguments, initializerVisitor, errorReporter);
- }
- }
- return new DartObjectImpl(definingClass, new GenericState(fieldMap));
- }
-
- void evaluateSuperConstructorCall(
- AstNode node,
- HashMap<String, DartObjectImpl> fieldMap,
- ConstructorElement superConstructor,
- NodeList<Expression> superArguments,
- ConstantVisitor initializerVisitor,
- ErrorReporter errorReporter) {
- if (superConstructor != null && superConstructor.isConst) {
- DartObjectImpl evaluationResult = evaluateConstructorCall(node,
- superArguments, superConstructor, initializerVisitor, errorReporter);
- if (evaluationResult != null) {
- fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult;
- }
- }
- }
-
- /**
- * Attempt to follow the chain of factory redirections until a constructor is
- * reached which is not a const factory constructor. Return the constant
- * constructor which terminates the chain of factory redirections, if the
- * chain terminates. If there is a problem (e.g. a redirection can't be found,
- * or a cycle is encountered), the chain will be followed as far as possible
- * and then a const factory constructor will be returned.
- */
- ConstructorElement followConstantRedirectionChain(
- ConstructorElement constructor) {
- HashSet<ConstructorElement> constructorsVisited =
- new HashSet<ConstructorElement>();
- while (true) {
- ConstructorElement redirectedConstructor =
- getConstRedirectedConstructor(constructor);
- if (redirectedConstructor == null) {
- break;
- } else {
- ConstructorElement constructorBase = _getConstructorImpl(constructor);
- constructorsVisited.add(constructorBase);
- ConstructorElement redirectedConstructorBase =
- _getConstructorImpl(redirectedConstructor);
- if (constructorsVisited.contains(redirectedConstructorBase)) {
- // Cycle in redirecting factory constructors--this is not allowed
- // and is checked elsewhere--see
- // [ErrorVerifier.checkForRecursiveFactoryRedirect()]).
- break;
- }
- }
- constructor = redirectedConstructor;
- }
- return constructor;
- }
-
- /**
- * Generate an error indicating that the given [constant] is not a valid
- * compile-time constant because it references at least one of the constants
- * in the given [cycle], each of which directly or indirectly references the
- * constant.
- */
- void generateCycleError(Iterable<ConstantEvaluationTarget> cycle,
- ConstantEvaluationTarget constant) {
- if (constant is VariableElement) {
- RecordingErrorListener errorListener = new RecordingErrorListener();
- ErrorReporter errorReporter =
- new ErrorReporter(errorListener, constant.source);
- // TODO(paulberry): It would be really nice if we could extract enough
- // information from the 'cycle' argument to provide the user with a
- // description of the cycle.
- errorReporter.reportErrorForElement(
- CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT, constant, []);
- (constant as VariableElementImpl).evaluationResult =
- new EvaluationResultImpl(null, errorListener.errors);
- } else if (constant is ConstructorElement) {
- // We don't report cycle errors on constructor declarations since there
- // is nowhere to put the error information.
- } else {
- // Should not happen. Formal parameter defaults and annotations should
- // never appear as part of a cycle because they can't be referred to.
- assert(false);
- AnalysisEngine.instance.logger.logError(
- "Constant value computer trying to report a cycle error for a node of type ${constant.runtimeType}");
- }
- }
-
- /**
- * If [constructor] redirects to another const constructor, return the
- * const constructor it redirects to. Otherwise return `null`.
- */
- ConstructorElement getConstRedirectedConstructor(
- ConstructorElement constructor) {
- if (!constructor.isFactory) {
- return null;
- }
- if (identical(constructor.enclosingElement.type, typeProvider.symbolType)) {
- // The dart:core.Symbol has a const factory constructor that redirects
- // to dart:_internal.Symbol. That in turn redirects to an external
- // const constructor, which we won't be able to evaluate.
- // So stop following the chain of redirections at dart:core.Symbol, and
- // let [evaluateInstanceCreationExpression] handle it specially.
- return null;
- }
- ConstructorElement redirectedConstructor =
- constructor.redirectedConstructor;
- if (redirectedConstructor == null) {
- // This can happen if constructor is an external factory constructor.
- return null;
- }
- if (!redirectedConstructor.isConst) {
- // Delegating to a non-const constructor--this is not allowed (and
- // is checked elsewhere--see
- // [ErrorVerifier.checkForRedirectToNonConstConstructor()]).
- return null;
- }
- return redirectedConstructor;
- }
-
- /**
- * Check if the object [obj] matches the type [type] according to runtime type
- * checking rules.
- */
- bool runtimeTypeMatch(DartObjectImpl obj, DartType type) {
- if (obj.isNull) {
- return true;
- }
- if (type.isUndefined) {
- return false;
- }
- return obj.type.isSubtypeOf(type);
- }
-
- /**
- * Determine whether the given string is a valid name for a public symbol
- * (i.e. whether it is allowed for a call to the Symbol constructor).
- */
- static bool isValidPublicSymbol(String name) =>
- name.isEmpty ||
- name == "void" ||
- new JavaPatternMatcher(_PUBLIC_SYMBOL_PATTERN, name).matches();
-}
-
-/**
- * Interface used by unit tests to verify correct dependency analysis during
- * constant evaluation.
- */
-abstract class ConstantEvaluationValidator {
- /**
- * This method is called just before computing the constant value associated
- * with [constant]. Unit tests will override this method to introduce
- * additional error checking.
- */
- void beforeComputeValue(ConstantEvaluationTarget constant);
-
- /**
- * This method is called just before getting the constant initializers
- * associated with the [constructor]. Unit tests will override this method to
- * introduce additional error checking.
- */
- void beforeGetConstantInitializers(ConstructorElement constructor);
-
- /**
- * This method is called just before retrieving an evaluation result from an
- * element. Unit tests will override it to introduce additional error
- * checking.
- */
- void beforeGetEvaluationResult(ConstantEvaluationTarget constant);
-
- /**
- * This method is called just before getting the constant value of a field
- * with an initializer. Unit tests will override this method to introduce
- * additional error checking.
- */
- void beforeGetFieldEvaluationResult(FieldElementImpl field);
-
- /**
- * This method is called just before getting a parameter's default value. Unit
- * tests will override this method to introduce additional error checking.
- */
- void beforeGetParameterDefault(ParameterElement parameter);
-}
-
-/**
- * Implementation of [ConstantEvaluationValidator] used in production; does no
- * validation.
- */
-class ConstantEvaluationValidator_ForProduction
- implements ConstantEvaluationValidator {
- @override
- void beforeComputeValue(ConstantEvaluationTarget constant) {}
-
- @override
- void beforeGetConstantInitializers(ConstructorElement constructor) {}
-
- @override
- void beforeGetEvaluationResult(ConstantEvaluationTarget constant) {}
-
- @override
- void beforeGetFieldEvaluationResult(FieldElementImpl field) {}
-
- @override
- void beforeGetParameterDefault(ParameterElement parameter) {}
-}
+export 'package:analyzer/context/declared_variables.dart';
+export 'package:analyzer/dart/constant/value.dart';
+export 'package:analyzer/src/dart/constant/evaluation.dart';
+export 'package:analyzer/src/dart/constant/utilities.dart';
+export 'package:analyzer/src/dart/constant/value.dart';
/// Instances of the class [ConstantEvaluator] evaluate constant expressions to
/// produce their compile-time value.
@@ -1143,6 +98,7 @@
/// In addition, this class defines several values that can be returned to
/// indicate various conditions encountered during evaluation. These are
/// documented with the static fields that define those values.
+@deprecated
class ConstantEvaluator {
/**
* The source containing the expression(s) that will be evaluated.
@@ -1180,4243 +136,3 @@
return EvaluationResult.forErrors(errorListener.errors);
}
}
-
-/**
- * A visitor used to traverse the AST structures of all of the compilation units
- * being resolved and build the full set of dependencies for all constant
- * expressions.
- */
-class ConstantExpressionsDependenciesFinder extends RecursiveAstVisitor {
- /**
- * The constants whose values need to be computed.
- */
- HashSet<ConstantEvaluationTarget> dependencies =
- new HashSet<ConstantEvaluationTarget>();
-
- @override
- void visitInstanceCreationExpression(InstanceCreationExpression node) {
- if (node.isConst) {
- _find(node);
- } else {
- super.visitInstanceCreationExpression(node);
- }
- }
-
- @override
- void visitListLiteral(ListLiteral node) {
- if (node.constKeyword != null) {
- _find(node);
- } else {
- super.visitListLiteral(node);
- }
- }
-
- @override
- void visitMapLiteral(MapLiteral node) {
- if (node.constKeyword != null) {
- _find(node);
- } else {
- super.visitMapLiteral(node);
- }
- }
-
- @override
- void visitSwitchCase(SwitchCase node) {
- _find(node.expression);
- node.statements.accept(this);
- }
-
- void _find(Expression node) {
- if (node != null) {
- ReferenceFinder referenceFinder = new ReferenceFinder(dependencies.add);
- node.accept(referenceFinder);
- }
- }
-}
-
-/**
- * A visitor used to traverse the AST structures of all of the compilation units
- * being resolved and build tables of the constant variables, constant
- * constructors, constant constructor invocations, and annotations found in
- * those compilation units.
- */
-class ConstantFinder extends RecursiveAstVisitor<Object> {
- final AnalysisContext context;
- final Source source;
- final Source librarySource;
-
- /**
- * The elements and AST nodes whose constant values need to be computed.
- */
- List<ConstantEvaluationTarget> constantsToCompute =
- <ConstantEvaluationTarget>[];
-
- /**
- * True if instance variables marked as "final" should be treated as "const".
- */
- bool treatFinalInstanceVarAsConst = false;
-
- ConstantFinder(this.context, this.source, this.librarySource);
-
- @override
- Object visitAnnotation(Annotation node) {
- super.visitAnnotation(node);
- ElementAnnotation elementAnnotation = node.elementAnnotation;
- if (elementAnnotation == null) {
- // Analyzer ignores annotations on "part of" directives.
- assert(node.parent is PartOfDirective);
- } else {
- constantsToCompute.add(elementAnnotation);
- }
- return null;
- }
-
- @override
- Object visitClassDeclaration(ClassDeclaration node) {
- bool prevTreatFinalInstanceVarAsConst = treatFinalInstanceVarAsConst;
- if (node.element.constructors.any((ConstructorElement e) => e.isConst)) {
- // Instance vars marked "final" need to be included in the dependency
- // graph, since constant constructors implicitly use the values in their
- // initializers.
- treatFinalInstanceVarAsConst = true;
- }
- try {
- return super.visitClassDeclaration(node);
- } finally {
- treatFinalInstanceVarAsConst = prevTreatFinalInstanceVarAsConst;
- }
- }
-
- @override
- Object visitConstructorDeclaration(ConstructorDeclaration node) {
- super.visitConstructorDeclaration(node);
- if (node.constKeyword != null) {
- ConstructorElement element = node.element;
- if (element != null) {
- constantsToCompute.add(element);
- constantsToCompute.addAll(element.parameters);
- }
- }
- return null;
- }
-
- @override
- Object visitDefaultFormalParameter(DefaultFormalParameter node) {
- super.visitDefaultFormalParameter(node);
- Expression defaultValue = node.defaultValue;
- if (defaultValue != null && node.element != null) {
- constantsToCompute.add(node.element);
- }
- return null;
- }
-
- @override
- Object visitVariableDeclaration(VariableDeclaration node) {
- super.visitVariableDeclaration(node);
- Expression initializer = node.initializer;
- VariableElement element = node.element;
- if (initializer != null &&
- (node.isConst ||
- treatFinalInstanceVarAsConst &&
- element is FieldElement &&
- node.isFinal &&
- !element.isStatic)) {
- if (element != null) {
- constantsToCompute.add(element);
- }
- }
- return null;
- }
-}
-
-/**
- * An object used to compute the values of constant variables and constant
- * constructor invocations in one or more compilation units. The expected usage
- * pattern is for the compilation units to be added to this computer using the
- * method [add] and then for the method [computeValues] to be invoked exactly
- * once. Any use of an instance after invoking the method [computeValues] will
- * result in unpredictable behavior.
- */
-class ConstantValueComputer {
- /**
- * Source of RegExp matching declarable operator names.
- * From sdk/lib/internal/symbol.dart.
- */
- static String _OPERATOR_RE =
- "(?:[\\-+*/%&|^]|\\[\\]=?|==|~/?|<[<=]?|>[>=]?|unary-)";
-
- /**
- * Source of RegExp matching Dart reserved words.
- * From sdk/lib/internal/symbol.dart.
- */
- static String _RESERVED_WORD_RE =
- "(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|d(?:efault|o)|e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?:ew|ull)|ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|r(?:ue|y))|v(?:ar|oid)|w(?:hile|ith))";
-
- /**
- * A graph in which the nodes are the constants, and the edges are from each
- * constant to the other constants that are referenced by it.
- */
- DirectedGraph<ConstantEvaluationTarget> referenceGraph =
- new DirectedGraph<ConstantEvaluationTarget>();
-
- /**
- * The elements whose constant values need to be computed. Any elements
- * which appear in [referenceGraph] but not in this set either belong to a
- * different library cycle (and hence don't need to be recomputed) or were
- * computed during a previous stage of resolution stage (e.g. constants
- * associated with enums).
- */
- HashSet<ConstantEvaluationTarget> _constantsToCompute =
- new HashSet<ConstantEvaluationTarget>();
-
- /**
- * The evaluation engine that does the work of evaluating instance creation
- * expressions.
- */
- final ConstantEvaluationEngine evaluationEngine;
-
- final AnalysisContext _context;
-
- /**
- * Initialize a newly created constant value computer. The [typeProvider] is
- * the type provider used to access known types. The [declaredVariables] is
- * the set of variables declared on the command line using '-D'.
- */
- ConstantValueComputer(this._context, TypeProvider typeProvider,
- DeclaredVariables declaredVariables,
- [ConstantEvaluationValidator validator, TypeSystem typeSystem])
- : evaluationEngine = new ConstantEvaluationEngine(
- typeProvider, declaredVariables,
- validator: validator, typeSystem: typeSystem);
-
- /**
- * Add the constants in the given compilation [unit] to the list of constants
- * whose value needs to be computed.
- */
- void add(CompilationUnit unit, Source source, Source librarySource) {
- ConstantFinder constantFinder =
- new ConstantFinder(_context, source, librarySource);
- unit.accept(constantFinder);
- _constantsToCompute.addAll(constantFinder.constantsToCompute);
- }
-
- /**
- * Compute values for all of the constants in the compilation units that were
- * added.
- */
- void computeValues() {
- for (ConstantEvaluationTarget constant in _constantsToCompute) {
- referenceGraph.addNode(constant);
- evaluationEngine.computeDependencies(constant,
- (ConstantEvaluationTarget dependency) {
- referenceGraph.addEdge(constant, dependency);
- });
- }
- List<List<ConstantEvaluationTarget>> topologicalSort =
- referenceGraph.computeTopologicalSort();
- for (List<ConstantEvaluationTarget> constantsInCycle in topologicalSort) {
- if (constantsInCycle.length == 1) {
- ConstantEvaluationTarget constant = constantsInCycle[0];
- if (!referenceGraph.getTails(constant).contains(constant)) {
- _computeValueFor(constant);
- continue;
- }
- }
- for (ConstantEvaluationTarget constant in constantsInCycle) {
- evaluationEngine.generateCycleError(constantsInCycle, constant);
- }
- }
- }
-
- /**
- * Compute a value for the given [constant].
- */
- void _computeValueFor(ConstantEvaluationTarget constant) {
- if (!_constantsToCompute.contains(constant)) {
- // Element is in the dependency graph but should have been computed by
- // a previous stage of analysis.
- // TODO(paulberry): once we have moved over to the new task model, this
- // should only occur for constants associated with enum members. Once
- // that happens we should add an assertion to verify that it doesn't
- // occur in any other cases.
- return;
- }
- evaluationEngine.computeConstantValue(constant);
- }
-}
-
-/**
- * A visitor used to evaluate constant expressions to produce their compile-time
- * value. According to the Dart Language Specification: <blockquote> A constant
- * expression is one of the following:
- *
- * * A literal number.
- * * A literal boolean.
- * * A literal string where any interpolated expression is a compile-time
- * constant that evaluates to a numeric, string or boolean value or to
- * <b>null</b>.
- * * A literal symbol.
- * * <b>null</b>.
- * * A qualified reference to a static constant variable.
- * * An identifier expression that denotes a constant variable, class or type
- * alias.
- * * A constant constructor invocation.
- * * A constant list literal.
- * * A constant map literal.
- * * A simple or qualified identifier denoting a top-level function or a static
- * method.
- * * A parenthesized expression <i>(e)</i> where <i>e</i> is a constant
- * expression.
- * * An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i>
- * where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
- * expressions and <i>identical()</i> is statically bound to the predefined
- * dart function <i>identical()</i> discussed above.
- * * An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> or
- * <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and
- * <i>e<sub>2</sub></i> are constant expressions that evaluate to a numeric,
- * string or boolean value.
- * * An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &&
- * e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where <i>e</i>,
- * <i>e1</sub></i> and <i>e2</sub></i> are constant expressions that evaluate
- * to a boolean value.
- * * An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^
- * e<sub>2</sub></i>, <i>e<sub>1</sub> & e<sub>2</sub></i>,
- * <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> >>
- * e<sub>2</sub></i> or <i>e<sub>1</sub> << e<sub>2</sub></i>, where
- * <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
- * expressions that evaluate to an integer value or to <b>null</b>.
- * * An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> +
- * e<sub>2</sub></i>, <i>e<sub>1</sub> - e<sub>2</sub></i>, <i>e<sub>1</sub> *
- * e<sub>2</sub></i>, <i>e<sub>1</sub> / e<sub>2</sub></i>, <i>e<sub>1</sub>
- * ~/ e<sub>2</sub></i>, <i>e<sub>1</sub> > e<sub>2</sub></i>,
- * <i>e<sub>1</sub> < e<sub>2</sub></i>, <i>e<sub>1</sub> >=
- * e<sub>2</sub></i>, <i>e<sub>1</sub> <= e<sub>2</sub></i> or
- * <i>e<sub>1</sub> % e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i>
- * and <i>e<sub>2</sub></i> are constant expressions that evaluate to a
- * numeric value or to <b>null</b>.
- * * An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
- * e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
- * <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
- * evaluates to a boolean value.
- * </blockquote>
- */
-class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
- /**
- * The type provider used to access the known types.
- */
- final ConstantEvaluationEngine evaluationEngine;
-
- final HashMap<String, DartObjectImpl> _lexicalEnvironment;
-
- /**
- * Error reporter that we use to report errors accumulated while computing the
- * constant.
- */
- final ErrorReporter _errorReporter;
-
- /**
- * Helper class used to compute constant values.
- */
- DartObjectComputer _dartObjectComputer;
-
- /**
- * Initialize a newly created constant visitor. The [evaluationEngine] is
- * used to evaluate instance creation expressions. The [lexicalEnvironment]
- * is a map containing values which should override identifiers, or `null` if
- * no overriding is necessary. The [_errorReporter] is used to report errors
- * found during evaluation. The [validator] is used by unit tests to verify
- * correct dependency analysis.
- */
- ConstantVisitor(this.evaluationEngine, this._errorReporter,
- {HashMap<String, DartObjectImpl> lexicalEnvironment})
- : _lexicalEnvironment = lexicalEnvironment {
- this._dartObjectComputer =
- new DartObjectComputer(_errorReporter, evaluationEngine.typeProvider);
- }
-
- /**
- * Convenience getter to gain access to the [evalationEngine]'s type
- * provider.
- */
- TypeProvider get _typeProvider => evaluationEngine.typeProvider;
-
- /**
- * Convenience getter to gain access to the [evaluationEngine]'s type system.
- */
- TypeSystem get _typeSystem => evaluationEngine.typeSystem;
-
- @override
- DartObjectImpl visitAdjacentStrings(AdjacentStrings node) {
- DartObjectImpl result = null;
- for (StringLiteral string in node.strings) {
- if (result == null) {
- result = string.accept(this);
- } else {
- result =
- _dartObjectComputer.concatenate(node, result, string.accept(this));
- }
- }
- return result;
- }
-
- @override
- DartObjectImpl visitBinaryExpression(BinaryExpression node) {
- DartObjectImpl leftResult = node.leftOperand.accept(this);
- DartObjectImpl rightResult = node.rightOperand.accept(this);
- TokenType operatorType = node.operator.type;
- // 'null' is almost never good operand
- if (operatorType != TokenType.BANG_EQ &&
- operatorType != TokenType.EQ_EQ &&
- operatorType != TokenType.QUESTION_QUESTION) {
- if (leftResult != null && leftResult.isNull ||
- rightResult != null && rightResult.isNull) {
- _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- return null;
- }
- }
- // evaluate operator
- while (true) {
- if (operatorType == TokenType.AMPERSAND) {
- return _dartObjectComputer.bitAnd(node, leftResult, rightResult);
- } else if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
- return _dartObjectComputer.logicalAnd(node, leftResult, rightResult);
- } else if (operatorType == TokenType.BANG_EQ) {
- return _dartObjectComputer.notEqual(node, leftResult, rightResult);
- } else if (operatorType == TokenType.BAR) {
- return _dartObjectComputer.bitOr(node, leftResult, rightResult);
- } else if (operatorType == TokenType.BAR_BAR) {
- return _dartObjectComputer.logicalOr(node, leftResult, rightResult);
- } else if (operatorType == TokenType.CARET) {
- return _dartObjectComputer.bitXor(node, leftResult, rightResult);
- } else if (operatorType == TokenType.EQ_EQ) {
- return _dartObjectComputer.equalEqual(node, leftResult, rightResult);
- } else if (operatorType == TokenType.GT) {
- return _dartObjectComputer.greaterThan(node, leftResult, rightResult);
- } else if (operatorType == TokenType.GT_EQ) {
- return _dartObjectComputer.greaterThanOrEqual(
- node, leftResult, rightResult);
- } else if (operatorType == TokenType.GT_GT) {
- return _dartObjectComputer.shiftRight(node, leftResult, rightResult);
- } else if (operatorType == TokenType.LT) {
- return _dartObjectComputer.lessThan(node, leftResult, rightResult);
- } else if (operatorType == TokenType.LT_EQ) {
- return _dartObjectComputer.lessThanOrEqual(
- node, leftResult, rightResult);
- } else if (operatorType == TokenType.LT_LT) {
- return _dartObjectComputer.shiftLeft(node, leftResult, rightResult);
- } else if (operatorType == TokenType.MINUS) {
- return _dartObjectComputer.minus(node, leftResult, rightResult);
- } else if (operatorType == TokenType.PERCENT) {
- return _dartObjectComputer.remainder(node, leftResult, rightResult);
- } else if (operatorType == TokenType.PLUS) {
- return _dartObjectComputer.add(node, leftResult, rightResult);
- } else if (operatorType == TokenType.STAR) {
- return _dartObjectComputer.times(node, leftResult, rightResult);
- } else if (operatorType == TokenType.SLASH) {
- return _dartObjectComputer.divide(node, leftResult, rightResult);
- } else if (operatorType == TokenType.TILDE_SLASH) {
- return _dartObjectComputer.integerDivide(node, leftResult, rightResult);
- } else if (operatorType == TokenType.QUESTION_QUESTION) {
- return _dartObjectComputer.questionQuestion(
- node, leftResult, rightResult);
- } else {
- // TODO(brianwilkerson) Figure out which error to report.
- _error(node, null);
- return null;
- }
- break;
- }
- }
-
- @override
- DartObjectImpl visitBooleanLiteral(BooleanLiteral node) =>
- new DartObjectImpl(_typeProvider.boolType, BoolState.from(node.value));
-
- @override
- DartObjectImpl visitConditionalExpression(ConditionalExpression node) {
- Expression condition = node.condition;
- DartObjectImpl conditionResult = condition.accept(this);
- DartObjectImpl thenResult = node.thenExpression.accept(this);
- DartObjectImpl elseResult = node.elseExpression.accept(this);
- if (conditionResult == null) {
- return conditionResult;
- } else if (!conditionResult.isBool) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL, condition);
- return null;
- } else if (thenResult == null) {
- return thenResult;
- } else if (elseResult == null) {
- return elseResult;
- }
- conditionResult =
- _dartObjectComputer.applyBooleanConversion(condition, conditionResult);
- if (conditionResult == null) {
- return conditionResult;
- }
- if (conditionResult.toBoolValue() == true) {
- return thenResult;
- } else if (conditionResult.toBoolValue() == false) {
- return elseResult;
- }
- ParameterizedType thenType = thenResult.type;
- ParameterizedType elseType = elseResult.type;
- return new DartObjectImpl.validWithUnknownValue(
- _typeSystem.getLeastUpperBound(_typeProvider, thenType, elseType)
- as InterfaceType);
- }
-
- @override
- DartObjectImpl visitDoubleLiteral(DoubleLiteral node) =>
- new DartObjectImpl(_typeProvider.doubleType, new DoubleState(node.value));
-
- @override
- DartObjectImpl visitInstanceCreationExpression(
- InstanceCreationExpression node) {
- if (!node.isConst) {
- // TODO(brianwilkerson) Figure out which error to report.
- _error(node, null);
- return null;
- }
- ConstructorElement constructor = node.staticElement;
- if (constructor == null) {
- // Couldn't resolve the constructor so we can't compute a value. No
- // problem - the error has already been reported.
- return null;
- }
- return evaluationEngine.evaluateConstructorCall(
- node, node.argumentList.arguments, constructor, this, _errorReporter);
- }
-
- @override
- DartObjectImpl visitIntegerLiteral(IntegerLiteral node) =>
- new DartObjectImpl(_typeProvider.intType, new IntState(node.value));
-
- @override
- DartObjectImpl visitInterpolationExpression(InterpolationExpression node) {
- DartObjectImpl result = node.expression.accept(this);
- if (result != null && !result.isBoolNumStringOrNull) {
- _error(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
- return null;
- }
- return _dartObjectComputer.performToString(node, result);
- }
-
- @override
- DartObjectImpl visitInterpolationString(InterpolationString node) =>
- new DartObjectImpl(_typeProvider.stringType, new StringState(node.value));
-
- @override
- DartObjectImpl visitListLiteral(ListLiteral node) {
- if (node.constKeyword == null) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL, node);
- return null;
- }
- bool errorOccurred = false;
- List<DartObjectImpl> elements = new List<DartObjectImpl>();
- for (Expression element in node.elements) {
- DartObjectImpl elementResult = element.accept(this);
- if (elementResult == null) {
- errorOccurred = true;
- } else {
- elements.add(elementResult);
- }
- }
- if (errorOccurred) {
- return null;
- }
- DartType elementType = _typeProvider.dynamicType;
- if (node.typeArguments != null &&
- node.typeArguments.arguments.length == 1) {
- DartType type = node.typeArguments.arguments[0].type;
- if (type != null) {
- elementType = type;
- }
- }
- InterfaceType listType = _typeProvider.listType.instantiate([elementType]);
- return new DartObjectImpl(listType, new ListState(elements));
- }
-
- @override
- DartObjectImpl visitMapLiteral(MapLiteral node) {
- if (node.constKeyword == null) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.MISSING_CONST_IN_MAP_LITERAL, node);
- return null;
- }
- bool errorOccurred = false;
- LinkedHashMap<DartObjectImpl, DartObjectImpl> map =
- new LinkedHashMap<DartObjectImpl, DartObjectImpl>();
- for (MapLiteralEntry entry in node.entries) {
- DartObjectImpl keyResult = entry.key.accept(this);
- DartObjectImpl valueResult = entry.value.accept(this);
- if (keyResult == null || valueResult == null) {
- errorOccurred = true;
- } else {
- map[keyResult] = valueResult;
- }
- }
- if (errorOccurred) {
- return null;
- }
- DartType keyType = _typeProvider.dynamicType;
- DartType valueType = _typeProvider.dynamicType;
- if (node.typeArguments != null &&
- node.typeArguments.arguments.length == 2) {
- DartType keyTypeCandidate = node.typeArguments.arguments[0].type;
- if (keyTypeCandidate != null) {
- keyType = keyTypeCandidate;
- }
- DartType valueTypeCandidate = node.typeArguments.arguments[1].type;
- if (valueTypeCandidate != null) {
- valueType = valueTypeCandidate;
- }
- }
- InterfaceType mapType =
- _typeProvider.mapType.instantiate([keyType, valueType]);
- return new DartObjectImpl(mapType, new MapState(map));
- }
-
- @override
- DartObjectImpl visitMethodInvocation(MethodInvocation node) {
- Element element = node.methodName.staticElement;
- if (element is FunctionElement) {
- FunctionElement function = element;
- if (function.name == "identical") {
- NodeList<Expression> arguments = node.argumentList.arguments;
- if (arguments.length == 2) {
- Element enclosingElement = function.enclosingElement;
- if (enclosingElement is CompilationUnitElement) {
- LibraryElement library = enclosingElement.library;
- if (library.isDartCore) {
- DartObjectImpl leftArgument = arguments[0].accept(this);
- DartObjectImpl rightArgument = arguments[1].accept(this);
- return _dartObjectComputer.isIdentical(
- node, leftArgument, rightArgument);
- }
- }
- }
- }
- }
- // TODO(brianwilkerson) Figure out which error to report.
- _error(node, null);
- return null;
- }
-
- @override
- DartObjectImpl visitNamedExpression(NamedExpression node) =>
- node.expression.accept(this);
-
- @override
- DartObjectImpl visitNode(AstNode node) {
- // TODO(brianwilkerson) Figure out which error to report.
- _error(node, null);
- return null;
- }
-
- @override
- DartObjectImpl visitNullLiteral(NullLiteral node) => _typeProvider.nullObject;
-
- @override
- DartObjectImpl visitParenthesizedExpression(ParenthesizedExpression node) =>
- node.expression.accept(this);
-
- @override
- DartObjectImpl visitPrefixedIdentifier(PrefixedIdentifier node) {
- SimpleIdentifier prefixNode = node.prefix;
- Element prefixElement = prefixNode.staticElement;
- // String.length
- if (prefixElement is! PrefixElement && prefixElement is! ClassElement) {
- DartObjectImpl prefixResult = node.prefix.accept(this);
- if (_isStringLength(prefixResult, node.identifier)) {
- return prefixResult.stringLength(_typeProvider);
- }
- }
- // importPrefix.CONST
- if (prefixElement is! PrefixElement) {
- DartObjectImpl prefixResult = prefixNode.accept(this);
- if (prefixResult == null) {
- // The error has already been reported.
- return null;
- }
- }
- // validate prefixed identifier
- return _getConstantValue(node, node.staticElement);
- }
-
- @override
- DartObjectImpl visitPrefixExpression(PrefixExpression node) {
- DartObjectImpl operand = node.operand.accept(this);
- if (operand != null && operand.isNull) {
- _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- return null;
- }
- while (true) {
- if (node.operator.type == TokenType.BANG) {
- return _dartObjectComputer.logicalNot(node, operand);
- } else if (node.operator.type == TokenType.TILDE) {
- return _dartObjectComputer.bitNot(node, operand);
- } else if (node.operator.type == TokenType.MINUS) {
- return _dartObjectComputer.negated(node, operand);
- } else {
- // TODO(brianwilkerson) Figure out which error to report.
- _error(node, null);
- return null;
- }
- break;
- }
- }
-
- @override
- DartObjectImpl visitPropertyAccess(PropertyAccess node) {
- if (node.target != null) {
- DartObjectImpl prefixResult = node.target.accept(this);
- if (_isStringLength(prefixResult, node.propertyName)) {
- return prefixResult.stringLength(_typeProvider);
- }
- }
- return _getConstantValue(node, node.propertyName.staticElement);
- }
-
- @override
- DartObjectImpl visitSimpleIdentifier(SimpleIdentifier node) {
- if (_lexicalEnvironment != null &&
- _lexicalEnvironment.containsKey(node.name)) {
- return _lexicalEnvironment[node.name];
- }
- return _getConstantValue(node, node.staticElement);
- }
-
- @override
- DartObjectImpl visitSimpleStringLiteral(SimpleStringLiteral node) =>
- new DartObjectImpl(_typeProvider.stringType, new StringState(node.value));
-
- @override
- DartObjectImpl visitStringInterpolation(StringInterpolation node) {
- DartObjectImpl result = null;
- bool first = true;
- for (InterpolationElement element in node.elements) {
- if (first) {
- result = element.accept(this);
- first = false;
- } else {
- result =
- _dartObjectComputer.concatenate(node, result, element.accept(this));
- }
- }
- return result;
- }
-
- @override
- DartObjectImpl visitSymbolLiteral(SymbolLiteral node) {
- StringBuffer buffer = new StringBuffer();
- List<Token> components = node.components;
- for (int i = 0; i < components.length; i++) {
- if (i > 0) {
- buffer.writeCharCode(0x2E);
- }
- buffer.write(components[i].lexeme);
- }
- return new DartObjectImpl(
- _typeProvider.symbolType, new SymbolState(buffer.toString()));
- }
-
- /**
- * Create an error associated with the given [node]. The error will have the
- * given error [code].
- */
- void _error(AstNode node, ErrorCode code) {
- _errorReporter.reportErrorForNode(
- code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code, node);
- }
-
- /**
- * Return the constant value of the static constant represented by the given
- * [element]. The [node] is the node to be used if an error needs to be
- * reported.
- */
- DartObjectImpl _getConstantValue(AstNode node, Element element) {
- if (element is PropertyAccessorElement) {
- element = (element as PropertyAccessorElement).variable;
- }
- if (element is VariableElementImpl) {
- VariableElementImpl variableElementImpl = element;
- evaluationEngine.validator.beforeGetEvaluationResult(element);
- EvaluationResultImpl value = variableElementImpl.evaluationResult;
- if (variableElementImpl.isConst && value != null) {
- return value.value;
- }
- } else if (element is ExecutableElement) {
- ExecutableElement function = element;
- if (function.isStatic) {
- ParameterizedType functionType = function.type;
- if (functionType == null) {
- functionType = _typeProvider.functionType;
- }
- return new DartObjectImpl(functionType, new FunctionState(function));
- }
- } else if (element is ClassElement ||
- element is FunctionTypeAliasElement ||
- element is DynamicElementImpl) {
- return new DartObjectImpl(_typeProvider.typeType, new TypeState(element));
- }
- // TODO(brianwilkerson) Figure out which error to report.
- _error(node, null);
- return null;
- }
-
- /**
- * Return `true` if the given [targetResult] represents a string and the
- * [identifier] is "length".
- */
- bool _isStringLength(
- DartObjectImpl targetResult, SimpleIdentifier identifier) {
- if (targetResult == null || targetResult.type != _typeProvider.stringType) {
- return false;
- }
- return identifier.name == 'length';
- }
-
- /**
- * Return the value of the given [expression], or a representation of 'null'
- * if the expression cannot be evaluated.
- */
- DartObjectImpl _valueOf(Expression expression) {
- DartObjectImpl expressionValue = expression.accept(this);
- if (expressionValue != null) {
- return expressionValue;
- }
- return _typeProvider.nullObject;
- }
-}
-
-/**
- * A representation of the value of a compile-time constant expression.
- *
- * Note that, unlike the mirrors system, the object being represented does *not*
- * exist. This interface allows static analysis tools to determine something
- * about the state of the object that would exist if the code that creates the
- * object were executed, but none of the code being analyzed is actually
- * executed.
- */
-abstract class DartObject {
- /**
- * Return `true` if the value of the object being represented is known.
- *
- * This method will return `false` if
- * * the value being represented is the value of a declared variable (a
- * variable whose value is provided at run-time using a `-D` command-line
- * option), or
- * * the value is a function.
- *
- * The result of this method does not imply anything about the state of
- * object representations returned by the method [getField], those that are
- * elements of the list returned by [toListValue], or the keys or values in
- * the map returned by [toMapValue]. For example, a representation of a list
- * can return `true` even if one or more of the elements of that list would
- * return `false`.
- */
- bool get hasKnownValue;
-
- /**
- * Return `true` if the object being represented represents the value 'null'.
- */
- bool get isNull;
-
- /**
- * Return a representation of the type of the object being represented.
- *
- * For values resulting from the invocation of a 'const' constructor, this
- * will be a representation of the run-time type of the object.
- *
- * For values resulting from a literal expression, this will be a
- * representation of the static type of the value -- `int` for integer
- * literals, `List` for list literals, etc. -- even when the static type is an
- * abstract type (such as `List`) and hence will never be the run-time type of
- * the represented object.
- *
- * For values resulting from any other kind of expression, this will be a
- * representation of the result of evaluating the expression.
- *
- * Return `null` if the expression cannot be evaluated, either because it is
- * not a valid constant expression or because one or more of the values used
- * in the expression does not have a known value.
- *
- * This method can return a representation of the type, even if this object
- * would return `false` from [hasKnownValue].
- */
- ParameterizedType get type;
-
- /**
- * Return a representation of the value of the field with the given [name].
- *
- * Return `null` if either the object being represented does not have a field
- * with the given name or if the implementation of the class of the object is
- * invalid, making it impossible to determine that value of the field.
- *
- * Note that, unlike the mirrors API, this method does *not* invoke a getter;
- * it simply returns a representation of the known state of a field.
- */
- DartObject getField(String name);
-
- /**
- * Return a boolean corresponding to the value of the object being
- * represented, or `null` if
- * * this object is not of type 'bool',
- * * the value of the object being represented is not known, or
- * * the value of the object being represented is `null`.
- */
- bool toBoolValue();
-
- /**
- * Return a double corresponding to the value of the object being represented,
- * or `null`
- * if
- * * this object is not of type 'double',
- * * the value of the object being represented is not known, or
- * * the value of the object being represented is `null`.
- */
- double toDoubleValue();
-
- /**
- * Return an integer corresponding to the value of the object being
- * represented, or `null` if
- * * this object is not of type 'int',
- * * the value of the object being represented is not known, or
- * * the value of the object being represented is `null`.
- */
- int toIntValue();
-
- /**
- * Return a list corresponding to the value of the object being represented,
- * or `null` if
- * * this object is not of type 'List', or
- * * the value of the object being represented is `null`.
- */
- List<DartObject> toListValue();
-
- /**
- * Return a map corresponding to the value of the object being represented, or
- * `null` if
- * * this object is not of type 'Map', or
- * * the value of the object being represented is `null`.
- */
- Map<DartObject, DartObject> toMapValue();
-
- /**
- * Return a string corresponding to the value of the object being represented,
- * or `null` if
- * * this object is not of type 'String',
- * * the value of the object being represented is not known, or
- * * the value of the object being represented is `null`.
- */
- String toStringValue();
-
- /**
- * Return a string corresponding to the value of the object being represented,
- * or `null` if
- * * this object is not of type 'Symbol', or
- * * the value of the object being represented is `null`.
- * (We return the string
- */
- String toSymbolValue();
-
- /**
- * Return the representation of the type corresponding to the value of the
- * object being represented, or `null` if
- * * this object is not of type 'Type', or
- * * the value of the object being represented is `null`.
- */
- DartType toTypeValue();
-}
-
-/**
- * A utility class that contains methods for manipulating instances of a Dart
- * class and for collecting errors during evaluation.
- */
-class DartObjectComputer {
- /**
- * The error reporter that we are using to collect errors.
- */
- final ErrorReporter _errorReporter;
-
- /**
- * The type provider used to create objects of the appropriate types, and to
- * identify when an object is of a built-in type.
- */
- final TypeProvider _typeProvider;
-
- DartObjectComputer(this._errorReporter, this._typeProvider);
-
- DartObjectImpl add(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.add(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- return null;
- }
- }
- return null;
- }
-
- /**
- * Return the result of applying boolean conversion to the [evaluationResult].
- * The [node] is the node against which errors should be reported.
- */
- DartObjectImpl applyBooleanConversion(
- AstNode node, DartObjectImpl evaluationResult) {
- if (evaluationResult != null) {
- try {
- return evaluationResult.convertToBool(_typeProvider);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl bitAnd(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.bitAnd(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl bitNot(Expression node, DartObjectImpl evaluationResult) {
- if (evaluationResult != null) {
- try {
- return evaluationResult.bitNot(_typeProvider);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl bitOr(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.bitOr(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl bitXor(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.bitXor(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl concatenate(Expression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.concatenate(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl divide(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.divide(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl equalEqual(Expression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.equalEqual(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl greaterThan(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.greaterThan(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl greaterThanOrEqual(BinaryExpression node,
- DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.greaterThanOrEqual(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl integerDivide(BinaryExpression node,
- DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.integerDivide(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl isIdentical(Expression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.isIdentical(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl lessThan(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.lessThan(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl lessThanOrEqual(BinaryExpression node,
- DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.lessThanOrEqual(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl logicalAnd(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.logicalAnd(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl logicalNot(Expression node, DartObjectImpl evaluationResult) {
- if (evaluationResult != null) {
- try {
- return evaluationResult.logicalNot(_typeProvider);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl logicalOr(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.logicalOr(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl minus(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.minus(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl negated(Expression node, DartObjectImpl evaluationResult) {
- if (evaluationResult != null) {
- try {
- return evaluationResult.negated(_typeProvider);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl notEqual(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.notEqual(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl performToString(
- AstNode node, DartObjectImpl evaluationResult) {
- if (evaluationResult != null) {
- try {
- return evaluationResult.performToString(_typeProvider);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl questionQuestion(Expression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- if (leftOperand.isNull) {
- return rightOperand;
- }
- return leftOperand;
- }
- return null;
- }
-
- DartObjectImpl remainder(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.remainder(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl shiftLeft(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.shiftLeft(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- DartObjectImpl shiftRight(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.shiftRight(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-
- /**
- * Return the result of invoking the 'length' getter on the
- * [evaluationResult]. The [node] is the node against which errors should be
- * reported.
- */
- EvaluationResultImpl stringLength(
- Expression node, EvaluationResultImpl evaluationResult) {
- if (evaluationResult.value != null) {
- try {
- return new EvaluationResultImpl(
- evaluationResult.value.stringLength(_typeProvider));
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return new EvaluationResultImpl(null);
- }
-
- DartObjectImpl times(BinaryExpression node, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (leftOperand != null && rightOperand != null) {
- try {
- return leftOperand.times(_typeProvider, rightOperand);
- } on EvaluationException catch (exception) {
- _errorReporter.reportErrorForNode(exception.errorCode, node);
- }
- }
- return null;
- }
-}
-
-/**
- * An instance of a Dart class.
- */
-class DartObjectImpl implements DartObject {
- /**
- * An empty list of objects.
- */
- static const List<DartObjectImpl> EMPTY_LIST = const <DartObjectImpl>[];
-
- /**
- * The run-time type of this object.
- */
- @override
- final ParameterizedType type;
-
- /**
- * The state of the object.
- */
- final InstanceState _state;
-
- /**
- * Initialize a newly created object to have the given [type] and [_state].
- */
- DartObjectImpl(this.type, this._state);
-
- /**
- * Create an object to represent an unknown value.
- */
- factory DartObjectImpl.validWithUnknownValue(InterfaceType type) {
- if (type.element.library.isDartCore) {
- String typeName = type.name;
- if (typeName == "bool") {
- return new DartObjectImpl(type, BoolState.UNKNOWN_VALUE);
- } else if (typeName == "double") {
- return new DartObjectImpl(type, DoubleState.UNKNOWN_VALUE);
- } else if (typeName == "int") {
- return new DartObjectImpl(type, IntState.UNKNOWN_VALUE);
- } else if (typeName == "String") {
- return new DartObjectImpl(type, StringState.UNKNOWN_VALUE);
- }
- }
- return new DartObjectImpl(type, GenericState.UNKNOWN_VALUE);
- }
-
- HashMap<String, DartObjectImpl> get fields => _state.fields;
-
- @override
- int get hashCode => JenkinsSmiHash.hash2(type.hashCode, _state.hashCode);
-
- @override
- bool get hasKnownValue => !_state.isUnknown;
-
- /**
- * Return `true` if this object represents an object whose type is 'bool'.
- */
- bool get isBool => _state.isBool;
-
- /**
- * Return `true` if this object represents an object whose type is either
- * 'bool', 'num', 'String', or 'Null'.
- */
- bool get isBoolNumStringOrNull => _state.isBoolNumStringOrNull;
-
- @override
- bool get isNull => _state is NullState;
-
- /**
- * Return `true` if this object represents an unknown value.
- */
- bool get isUnknown => _state.isUnknown;
-
- /**
- * Return `true` if this object represents an instance of a user-defined
- * class.
- */
- bool get isUserDefinedObject => _state is GenericState;
-
- @override
- bool operator ==(Object object) {
- if (object is! DartObjectImpl) {
- return false;
- }
- DartObjectImpl dartObject = object as DartObjectImpl;
- return type == dartObject.type && _state == dartObject._state;
- }
-
- /**
- * Return the result of invoking the '+' operator on this object with the
- * given [rightOperand]. The [typeProvider] is the type provider used to find
- * known types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl add(TypeProvider typeProvider, DartObjectImpl rightOperand) {
- InstanceState result = _state.add(rightOperand._state);
- if (result is IntState) {
- return new DartObjectImpl(typeProvider.intType, result);
- } else if (result is DoubleState) {
- return new DartObjectImpl(typeProvider.doubleType, result);
- } else if (result is NumState) {
- return new DartObjectImpl(typeProvider.numType, result);
- } else if (result is StringState) {
- return new DartObjectImpl(typeProvider.stringType, result);
- }
- // We should never get here.
- throw new IllegalStateException("add returned a ${result.runtimeType}");
- }
-
- /**
- * Return the result of invoking the '&' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl bitAnd(
- TypeProvider typeProvider, DartObjectImpl rightOperand) =>
- new DartObjectImpl(
- typeProvider.intType, _state.bitAnd(rightOperand._state));
-
- /**
- * Return the result of invoking the '~' operator on this object. The
- * [typeProvider] is the type provider used to find known types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl bitNot(TypeProvider typeProvider) =>
- new DartObjectImpl(typeProvider.intType, _state.bitNot());
-
- /**
- * Return the result of invoking the '|' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl bitOr(
- TypeProvider typeProvider, DartObjectImpl rightOperand) =>
- new DartObjectImpl(
- typeProvider.intType, _state.bitOr(rightOperand._state));
-
- /**
- * Return the result of invoking the '^' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl bitXor(
- TypeProvider typeProvider, DartObjectImpl rightOperand) =>
- new DartObjectImpl(
- typeProvider.intType, _state.bitXor(rightOperand._state));
-
- /**
- * Return the result of invoking the ' ' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl concatenate(
- TypeProvider typeProvider, DartObjectImpl rightOperand) =>
- new DartObjectImpl(
- typeProvider.stringType, _state.concatenate(rightOperand._state));
-
- /**
- * Return the result of applying boolean conversion to this object. The
- * [typeProvider] is the type provider used to find known types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl convertToBool(TypeProvider typeProvider) {
- InterfaceType boolType = typeProvider.boolType;
- if (identical(type, boolType)) {
- return this;
- }
- return new DartObjectImpl(boolType, _state.convertToBool());
- }
-
- /**
- * Return the result of invoking the '/' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for
- * an object of this kind.
- */
- DartObjectImpl divide(
- TypeProvider typeProvider, DartObjectImpl rightOperand) {
- InstanceState result = _state.divide(rightOperand._state);
- if (result is IntState) {
- return new DartObjectImpl(typeProvider.intType, result);
- } else if (result is DoubleState) {
- return new DartObjectImpl(typeProvider.doubleType, result);
- } else if (result is NumState) {
- return new DartObjectImpl(typeProvider.numType, result);
- }
- // We should never get here.
- throw new IllegalStateException("divide returned a ${result.runtimeType}");
- }
-
- /**
- * Return the result of invoking the '==' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl equalEqual(
- TypeProvider typeProvider, DartObjectImpl rightOperand) {
- if (type != rightOperand.type) {
- String typeName = type.name;
- if (!(typeName == "bool" ||
- typeName == "double" ||
- typeName == "int" ||
- typeName == "num" ||
- typeName == "String" ||
- typeName == "Null" ||
- type.isDynamic)) {
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
- }
- }
- return new DartObjectImpl(
- typeProvider.boolType, _state.equalEqual(rightOperand._state));
- }
-
- @override
- DartObject getField(String name) {
- if (_state is GenericState) {
- return (_state as GenericState).fields[name];
- }
- return null;
- }
-
- /**
- * Return the result of invoking the '>' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl greaterThan(
- TypeProvider typeProvider, DartObjectImpl rightOperand) =>
- new DartObjectImpl(
- typeProvider.boolType, _state.greaterThan(rightOperand._state));
-
- /**
- * Return the result of invoking the '>=' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl greaterThanOrEqual(
- TypeProvider typeProvider, DartObjectImpl rightOperand) =>
- new DartObjectImpl(typeProvider.boolType,
- _state.greaterThanOrEqual(rightOperand._state));
-
- /**
- * Return the result of invoking the '~/' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl integerDivide(
- TypeProvider typeProvider, DartObjectImpl rightOperand) =>
- new DartObjectImpl(
- typeProvider.intType, _state.integerDivide(rightOperand._state));
-
- /**
- * Return the result of invoking the identical function on this object with
- * the [rightOperand]. The [typeProvider] is the type provider used to find
- * known types.
- */
- DartObjectImpl isIdentical(
- TypeProvider typeProvider, DartObjectImpl rightOperand) {
- return new DartObjectImpl(
- typeProvider.boolType, _state.isIdentical(rightOperand._state));
- }
-
- /**
- * Return the result of invoking the '<' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl lessThan(
- TypeProvider typeProvider, DartObjectImpl rightOperand) =>
- new DartObjectImpl(
- typeProvider.boolType, _state.lessThan(rightOperand._state));
-
- /**
- * Return the result of invoking the '<=' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl lessThanOrEqual(
- TypeProvider typeProvider, DartObjectImpl rightOperand) =>
- new DartObjectImpl(
- typeProvider.boolType, _state.lessThanOrEqual(rightOperand._state));
-
- /**
- * Return the result of invoking the '&&' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl logicalAnd(
- TypeProvider typeProvider, DartObjectImpl rightOperand) =>
- new DartObjectImpl(
- typeProvider.boolType, _state.logicalAnd(rightOperand._state));
-
- /**
- * Return the result of invoking the '!' operator on this object. The
- * [typeProvider] is the type provider used to find known types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl logicalNot(TypeProvider typeProvider) =>
- new DartObjectImpl(typeProvider.boolType, _state.logicalNot());
-
- /**
- * Return the result of invoking the '||' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl logicalOr(
- TypeProvider typeProvider, DartObjectImpl rightOperand) =>
- new DartObjectImpl(
- typeProvider.boolType, _state.logicalOr(rightOperand._state));
-
- /**
- * Return the result of invoking the '-' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl minus(TypeProvider typeProvider, DartObjectImpl rightOperand) {
- InstanceState result = _state.minus(rightOperand._state);
- if (result is IntState) {
- return new DartObjectImpl(typeProvider.intType, result);
- } else if (result is DoubleState) {
- return new DartObjectImpl(typeProvider.doubleType, result);
- } else if (result is NumState) {
- return new DartObjectImpl(typeProvider.numType, result);
- }
- // We should never get here.
- throw new IllegalStateException("minus returned a ${result.runtimeType}");
- }
-
- /**
- * Return the result of invoking the '-' operator on this object. The
- * [typeProvider] is the type provider used to find known types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl negated(TypeProvider typeProvider) {
- InstanceState result = _state.negated();
- if (result is IntState) {
- return new DartObjectImpl(typeProvider.intType, result);
- } else if (result is DoubleState) {
- return new DartObjectImpl(typeProvider.doubleType, result);
- } else if (result is NumState) {
- return new DartObjectImpl(typeProvider.numType, result);
- }
- // We should never get here.
- throw new IllegalStateException("negated returned a ${result.runtimeType}");
- }
-
- /**
- * Return the result of invoking the '!=' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl notEqual(
- TypeProvider typeProvider, DartObjectImpl rightOperand) {
- if (type != rightOperand.type) {
- String typeName = type.name;
- if (typeName != "bool" &&
- typeName != "double" &&
- typeName != "int" &&
- typeName != "num" &&
- typeName != "String") {
- return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE);
- }
- }
- return new DartObjectImpl(typeProvider.boolType,
- _state.equalEqual(rightOperand._state).logicalNot());
- }
-
- /**
- * Return the result of converting this object to a 'String'. The
- * [typeProvider] is the type provider used to find known types.
- *
- * Throws an [EvaluationException] if the object cannot be converted to a
- * 'String'.
- */
- DartObjectImpl performToString(TypeProvider typeProvider) {
- InterfaceType stringType = typeProvider.stringType;
- if (identical(type, stringType)) {
- return this;
- }
- return new DartObjectImpl(stringType, _state.convertToString());
- }
-
- /**
- * Return the result of invoking the '%' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl remainder(
- TypeProvider typeProvider, DartObjectImpl rightOperand) {
- InstanceState result = _state.remainder(rightOperand._state);
- if (result is IntState) {
- return new DartObjectImpl(typeProvider.intType, result);
- } else if (result is DoubleState) {
- return new DartObjectImpl(typeProvider.doubleType, result);
- } else if (result is NumState) {
- return new DartObjectImpl(typeProvider.numType, result);
- }
- // We should never get here.
- throw new IllegalStateException(
- "remainder returned a ${result.runtimeType}");
- }
-
- /**
- * Return the result of invoking the '<<' operator on this object with
- * the [rightOperand]. The [typeProvider] is the type provider used to find
- * known types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl shiftLeft(
- TypeProvider typeProvider, DartObjectImpl rightOperand) =>
- new DartObjectImpl(
- typeProvider.intType, _state.shiftLeft(rightOperand._state));
-
- /**
- * Return the result of invoking the '>>' operator on this object with
- * the [rightOperand]. The [typeProvider] is the type provider used to find
- * known types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl shiftRight(
- TypeProvider typeProvider, DartObjectImpl rightOperand) =>
- new DartObjectImpl(
- typeProvider.intType, _state.shiftRight(rightOperand._state));
-
- /**
- * Return the result of invoking the 'length' getter on this object. The
- * [typeProvider] is the type provider used to find known types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl stringLength(TypeProvider typeProvider) =>
- new DartObjectImpl(typeProvider.intType, _state.stringLength());
-
- /**
- * Return the result of invoking the '*' operator on this object with the
- * [rightOperand]. The [typeProvider] is the type provider used to find known
- * types.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- DartObjectImpl times(TypeProvider typeProvider, DartObjectImpl rightOperand) {
- InstanceState result = _state.times(rightOperand._state);
- if (result is IntState) {
- return new DartObjectImpl(typeProvider.intType, result);
- } else if (result is DoubleState) {
- return new DartObjectImpl(typeProvider.doubleType, result);
- } else if (result is NumState) {
- return new DartObjectImpl(typeProvider.numType, result);
- }
- // We should never get here.
- throw new IllegalStateException("times returned a ${result.runtimeType}");
- }
-
- @override
- bool toBoolValue() {
- if (_state is BoolState) {
- return (_state as BoolState).value;
- }
- return null;
- }
-
- @override
- double toDoubleValue() {
- if (_state is DoubleState) {
- return (_state as DoubleState).value;
- }
- return null;
- }
-
- @override
- int toIntValue() {
- if (_state is IntState) {
- return (_state as IntState).value;
- }
- return null;
- }
-
- @override
- List<DartObject> toListValue() {
- if (_state is ListState) {
- return (_state as ListState)._elements;
- }
- return null;
- }
-
- @override
- Map<DartObject, DartObject> toMapValue() {
- if (_state is MapState) {
- return (_state as MapState)._entries;
- }
- return null;
- }
-
- @override
- String toString() => "${type.displayName} ($_state)";
-
- @override
- String toStringValue() {
- if (_state is StringState) {
- return (_state as StringState).value;
- }
- return null;
- }
-
- @override
- String toSymbolValue() {
- if (_state is SymbolState) {
- return (_state as SymbolState).value;
- }
- return null;
- }
-
- @override
- DartType toTypeValue() {
- if (_state is TypeState) {
- Element element = (_state as TypeState)._element;
- if (element is TypeDefiningElement) {
- return element.type;
- }
- }
- return null;
- }
-}
-
-/**
- * An object used to provide access to the values of variables that have been
- * defined on the command line using the `-D` option.
- */
-class DeclaredVariables {
- /**
- * A table mapping the names of declared variables to their values.
- */
- HashMap<String, String> _declaredVariables = new HashMap<String, String>();
-
- /**
- * Define a variable with the given [name] to have the given [value].
- */
- void define(String name, String value) {
- _declaredVariables[name] = value;
- }
-
- /**
- * Return the value of the variable with the given [name] interpreted as a
- * 'boolean' value. If the variable is not defined (or [name] is `null`), a
- * DartObject representing "unknown" is returned. If the value cannot be
- * parsed as a boolean, a DartObject representing 'null' is returned. The
- * [typeProvider] is the type provider used to find the type 'bool'.
- */
- DartObject getBool(TypeProvider typeProvider, String name) {
- String value = _declaredVariables[name];
- if (value == null) {
- return new DartObjectImpl(typeProvider.boolType, BoolState.UNKNOWN_VALUE);
- }
- if (value == "true") {
- return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE);
- } else if (value == "false") {
- return new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE);
- }
- return new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE);
- }
-
- /**
- * Return the value of the variable with the given [name] interpreted as an
- * integer value. If the variable is not defined (or [name] is `null`), a
- * DartObject representing "unknown" is returned. If the value cannot be
- * parsed as an integer, a DartObject representing 'null' is returned.
- */
- DartObject getInt(TypeProvider typeProvider, String name) {
- String value = _declaredVariables[name];
- if (value == null) {
- return new DartObjectImpl(typeProvider.intType, IntState.UNKNOWN_VALUE);
- }
- int bigInteger;
- try {
- bigInteger = int.parse(value);
- } on FormatException {
- return new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE);
- }
- return new DartObjectImpl(typeProvider.intType, new IntState(bigInteger));
- }
-
- /**
- * Return the value of the variable with the given [name] interpreted as a
- * String value, or `null` if the variable is not defined. Return the value of
- * the variable with the given name interpreted as a String value. If the
- * variable is not defined (or [name] is `null`), a DartObject representing
- * "unknown" is returned. The [typeProvider] is the type provider used to find
- * the type 'String'.
- */
- DartObject getString(TypeProvider typeProvider, String name) {
- String value = _declaredVariables[name];
- if (value == null) {
- return new DartObjectImpl(
- typeProvider.stringType, StringState.UNKNOWN_VALUE);
- }
- return new DartObjectImpl(typeProvider.stringType, new StringState(value));
- }
-}
-
-/**
- * The state of an object representing a double.
- */
-class DoubleState extends NumState {
- /**
- * A state that can be used to represent a double whose value is not known.
- */
- static DoubleState UNKNOWN_VALUE = new DoubleState(null);
-
- /**
- * The value of this instance.
- */
- final double value;
-
- /**
- * Initialize a newly created state to represent a double with the given
- * [value].
- */
- DoubleState(this.value);
-
- @override
- int get hashCode => value == null ? 0 : value.hashCode;
-
- @override
- bool get isBoolNumStringOrNull => true;
-
- @override
- bool get isUnknown => value == null;
-
- @override
- String get typeName => "double";
-
- @override
- bool operator ==(Object object) =>
- object is DoubleState && (value == object.value);
-
- @override
- NumState add(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new DoubleState(value + rightValue.toDouble());
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new DoubleState(value + rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- StringState convertToString() {
- if (value == null) {
- return StringState.UNKNOWN_VALUE;
- }
- return new StringState(value.toString());
- }
-
- @override
- NumState divide(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new DoubleState(value / rightValue.toDouble());
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new DoubleState(value / rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- return isIdentical(rightOperand);
- }
-
- @override
- BoolState greaterThan(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value > rightValue.toDouble());
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value > rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- BoolState greaterThanOrEqual(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value >= rightValue.toDouble());
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value >= rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- IntState integerDivide(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return IntState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return IntState.UNKNOWN_VALUE;
- }
- double result = value / rightValue.toDouble();
- return new IntState(result.toInt());
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return IntState.UNKNOWN_VALUE;
- }
- double result = value / rightValue;
- return new IntState(result.toInt());
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return IntState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- BoolState isIdentical(InstanceState rightOperand) {
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value == rightValue);
- } else if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value == rightValue.toDouble());
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.FALSE_STATE;
- }
-
- @override
- BoolState lessThan(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value < rightValue.toDouble());
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value < rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- BoolState lessThanOrEqual(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value <= rightValue.toDouble());
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value <= rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- NumState minus(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new DoubleState(value - rightValue.toDouble());
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new DoubleState(value - rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- NumState negated() {
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- return new DoubleState(-(value));
- }
-
- @override
- NumState remainder(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new DoubleState(value % rightValue.toDouble());
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new DoubleState(value % rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- NumState times(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new DoubleState(value * rightValue.toDouble());
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new DoubleState(value * rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- String toString() => value == null ? "-unknown-" : value.toString();
-}
-
-/**
- * The state of an object representing a Dart object for which there is no type
- * information.
- */
-class DynamicState extends InstanceState {
- /**
- * The unique instance of this class.
- */
- static DynamicState DYNAMIC_STATE = new DynamicState();
-
- @override
- bool get isBool => true;
-
- @override
- bool get isBoolNumStringOrNull => true;
-
- @override
- String get typeName => "dynamic";
-
- @override
- NumState add(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return _unknownNum(rightOperand);
- }
-
- @override
- IntState bitAnd(InstanceState rightOperand) {
- assertIntOrNull(rightOperand);
- return IntState.UNKNOWN_VALUE;
- }
-
- @override
- IntState bitNot() => IntState.UNKNOWN_VALUE;
-
- @override
- IntState bitOr(InstanceState rightOperand) {
- assertIntOrNull(rightOperand);
- return IntState.UNKNOWN_VALUE;
- }
-
- @override
- IntState bitXor(InstanceState rightOperand) {
- assertIntOrNull(rightOperand);
- return IntState.UNKNOWN_VALUE;
- }
-
- @override
- StringState concatenate(InstanceState rightOperand) {
- assertString(rightOperand);
- return StringState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState convertToBool() => BoolState.UNKNOWN_VALUE;
-
- @override
- StringState convertToString() => StringState.UNKNOWN_VALUE;
-
- @override
- NumState divide(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return _unknownNum(rightOperand);
- }
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState greaterThan(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState greaterThanOrEqual(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
- }
-
- @override
- IntState integerDivide(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return IntState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState isIdentical(InstanceState rightOperand) {
- return BoolState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState lessThan(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState lessThanOrEqual(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState logicalAnd(InstanceState rightOperand) {
- assertBool(rightOperand);
- return BoolState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState logicalNot() => BoolState.UNKNOWN_VALUE;
-
- @override
- BoolState logicalOr(InstanceState rightOperand) {
- assertBool(rightOperand);
- return rightOperand.convertToBool();
- }
-
- @override
- NumState minus(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return _unknownNum(rightOperand);
- }
-
- @override
- NumState negated() => NumState.UNKNOWN_VALUE;
-
- @override
- NumState remainder(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return _unknownNum(rightOperand);
- }
-
- @override
- IntState shiftLeft(InstanceState rightOperand) {
- assertIntOrNull(rightOperand);
- return IntState.UNKNOWN_VALUE;
- }
-
- @override
- IntState shiftRight(InstanceState rightOperand) {
- assertIntOrNull(rightOperand);
- return IntState.UNKNOWN_VALUE;
- }
-
- @override
- NumState times(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return _unknownNum(rightOperand);
- }
-
- /**
- * Return an object representing an unknown numeric value whose type is based
- * on the type of the [rightOperand].
- */
- NumState _unknownNum(InstanceState rightOperand) {
- if (rightOperand is IntState) {
- return IntState.UNKNOWN_VALUE;
- } else if (rightOperand is DoubleState) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return NumState.UNKNOWN_VALUE;
- }
-}
-
-/**
- * A run-time exception that would be thrown during the evaluation of Dart code.
- */
-class EvaluationException extends JavaException {
- /**
- * The error code associated with the exception.
- */
- final ErrorCode errorCode;
-
- /**
- * Initialize a newly created exception to have the given [errorCode].
- */
- EvaluationException(this.errorCode);
-}
-
-/**
- * The result of attempting to evaluate an expression.
- */
-class EvaluationResult {
- /**
- * The value of the expression.
- */
- final DartObject value;
-
- /**
- * The errors that should be reported for the expression(s) that were
- * evaluated.
- */
- final List<AnalysisError> _errors;
-
- /**
- * Initialize a newly created result object with the given [value] and set of
- * [_errors]. Clients should use one of the factory methods: [forErrors] and
- * [forValue].
- */
- EvaluationResult(this.value, this._errors);
-
- /**
- * Return a list containing the errors that should be reported for the
- * expression(s) that were evaluated. If there are no such errors, the list
- * will be empty. The list can be empty even if the expression is not a valid
- * compile time constant if the errors would have been reported by other parts
- * of the analysis engine.
- */
- List<AnalysisError> get errors =>
- _errors == null ? AnalysisError.NO_ERRORS : _errors;
-
- /**
- * Return `true` if the expression is a compile-time constant expression that
- * would not throw an exception when evaluated.
- */
- bool get isValid => _errors == null;
-
- /**
- * Return an evaluation result representing the result of evaluating an
- * expression that is not a compile-time constant because of the given
- * [errors].
- */
- static EvaluationResult forErrors(List<AnalysisError> errors) =>
- new EvaluationResult(null, errors);
-
- /**
- * Return an evaluation result representing the result of evaluating an
- * expression that is a compile-time constant that evaluates to the given
- * [value].
- */
- static EvaluationResult forValue(DartObject value) =>
- new EvaluationResult(value, null);
-}
-
-/**
- * The result of attempting to evaluate a expression.
- */
-class EvaluationResultImpl {
- /**
- * The errors encountered while trying to evaluate the compile time constant.
- * These errors may or may not have prevented the expression from being a
- * valid compile time constant.
- */
- List<AnalysisError> _errors;
-
- /**
- * The value of the expression, or `null` if the value couldn't be computed
- * due to errors.
- */
- final DartObjectImpl value;
-
- EvaluationResultImpl(this.value, [List<AnalysisError> errors]) {
- this._errors = errors == null ? <AnalysisError>[] : errors;
- }
-
- List<AnalysisError> get errors => _errors;
-
- bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result) {
- if (this.value != null) {
- if (result.value == null) {
- return false;
- }
- return value == result.value;
- } else {
- return false;
- }
- }
-
- @override
- String toString() {
- if (value == null) {
- return "error";
- }
- return value.toString();
- }
-}
-
-/**
- * The state of an object representing a function.
- */
-class FunctionState extends InstanceState {
- /**
- * The element representing the function being modeled.
- */
- final ExecutableElement _element;
-
- /**
- * Initialize a newly created state to represent the function with the given
- * [element].
- */
- FunctionState(this._element);
-
- @override
- int get hashCode => _element == null ? 0 : _element.hashCode;
-
- @override
- String get typeName => "Function";
-
- @override
- bool operator ==(Object object) =>
- object is FunctionState && (_element == object._element);
-
- @override
- StringState convertToString() {
- if (_element == null) {
- return StringState.UNKNOWN_VALUE;
- }
- return new StringState(_element.name);
- }
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- return isIdentical(rightOperand);
- }
-
- @override
- BoolState isIdentical(InstanceState rightOperand) {
- if (_element == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is FunctionState) {
- ExecutableElement rightElement = rightOperand._element;
- if (rightElement == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(_element == rightElement);
- } else if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.FALSE_STATE;
- }
-
- @override
- String toString() => _element == null ? "-unknown-" : _element.name;
-}
-
-/**
- * The state of an object representing a Dart object for which there is no more
- * specific state.
- */
-class GenericState extends InstanceState {
- /**
- * Pseudo-field that we use to represent fields in the superclass.
- */
- static String SUPERCLASS_FIELD = "(super)";
-
- /**
- * A state that can be used to represent an object whose state is not known.
- */
- static GenericState UNKNOWN_VALUE =
- new GenericState(new HashMap<String, DartObjectImpl>());
-
- /**
- * The values of the fields of this instance.
- */
- final HashMap<String, DartObjectImpl> _fieldMap;
-
- /**
- * Initialize a newly created state to represent a newly created object. The
- * [fieldMap] contains the values of the fields of the instance.
- */
- GenericState(this._fieldMap);
-
- @override
- HashMap<String, DartObjectImpl> get fields => _fieldMap;
-
- @override
- int get hashCode {
- int hashCode = 0;
- for (DartObjectImpl value in _fieldMap.values) {
- hashCode += value.hashCode;
- }
- return hashCode;
- }
-
- @override
- bool get isUnknown => identical(this, UNKNOWN_VALUE);
-
- @override
- String get typeName => "user defined type";
-
- @override
- bool operator ==(Object object) {
- if (object is! GenericState) {
- return false;
- }
- GenericState state = object as GenericState;
- HashSet<String> otherFields =
- new HashSet<String>.from(state._fieldMap.keys.toSet());
- for (String fieldName in _fieldMap.keys.toSet()) {
- if (_fieldMap[fieldName] != state._fieldMap[fieldName]) {
- return false;
- }
- otherFields.remove(fieldName);
- }
- for (String fieldName in otherFields) {
- if (state._fieldMap[fieldName] != _fieldMap[fieldName]) {
- return false;
- }
- }
- return true;
- }
-
- @override
- StringState convertToString() => StringState.UNKNOWN_VALUE;
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- return isIdentical(rightOperand);
- }
-
- @override
- BoolState isIdentical(InstanceState rightOperand) {
- if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(this == rightOperand);
- }
-
- @override
- String toString() {
- StringBuffer buffer = new StringBuffer();
- List<String> fieldNames = _fieldMap.keys.toList();
- fieldNames.sort();
- bool first = true;
- for (String fieldName in fieldNames) {
- if (first) {
- first = false;
- } else {
- buffer.write('; ');
- }
- buffer.write(fieldName);
- buffer.write(' = ');
- buffer.write(_fieldMap[fieldName]);
- }
- return buffer.toString();
- }
-}
-
-/**
- * The state of an object representing a Dart object.
- */
-abstract class InstanceState {
- /**
- * If this represents a generic dart object, return a map from its field names
- * to their values. Otherwise return null.
- */
- HashMap<String, DartObjectImpl> get fields => null;
-
- /**
- * Return `true` if this object represents an object whose type is 'bool'.
- */
- bool get isBool => false;
-
- /**
- * Return `true` if this object represents an object whose type is either
- * 'bool', 'num', 'String', or 'Null'.
- */
- bool get isBoolNumStringOrNull => false;
-
- /**
- * Return `true` if this object represents an unknown value.
- */
- bool get isUnknown => false;
-
- /**
- * Return the name of the type of this value.
- */
- String get typeName;
-
- /**
- * Return the result of invoking the '+' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- InstanceState add(InstanceState rightOperand) {
- if (this is StringState && rightOperand is StringState) {
- return concatenate(rightOperand);
- }
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Throw an exception if the given [state] does not represent a boolean value.
- */
- void assertBool(InstanceState state) {
- if (!(state is BoolState || state is DynamicState)) {
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
- }
- }
-
- /**
- * Throw an exception if the given [state] does not represent a boolean,
- * numeric, string or null value.
- */
- void assertBoolNumStringOrNull(InstanceState state) {
- if (!(state is BoolState ||
- state is DoubleState ||
- state is IntState ||
- state is NumState ||
- state is StringState ||
- state is NullState ||
- state is DynamicState)) {
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
- }
- }
-
- /**
- * Throw an exception if the given [state] does not represent an integer or
- * null value.
- */
- void assertIntOrNull(InstanceState state) {
- if (!(state is IntState ||
- state is NumState ||
- state is NullState ||
- state is DynamicState)) {
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_INT);
- }
- }
-
- /**
- * Throw an exception if the given [state] does not represent a boolean,
- * numeric, string or null value.
- */
- void assertNumOrNull(InstanceState state) {
- if (!(state is DoubleState ||
- state is IntState ||
- state is NumState ||
- state is NullState ||
- state is DynamicState)) {
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_NUM);
- }
- }
-
- /**
- * Throw an exception if the given [state] does not represent a String value.
- */
- void assertString(InstanceState state) {
- if (!(state is StringState || state is DynamicState)) {
- throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL);
- }
- }
-
- /**
- * Return the result of invoking the '&' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- IntState bitAnd(InstanceState rightOperand) {
- assertIntOrNull(this);
- assertIntOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '~' operator on this object.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- IntState bitNot() {
- assertIntOrNull(this);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '|' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- IntState bitOr(InstanceState rightOperand) {
- assertIntOrNull(this);
- assertIntOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '^' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- IntState bitXor(InstanceState rightOperand) {
- assertIntOrNull(this);
- assertIntOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the ' ' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- StringState concatenate(InstanceState rightOperand) {
- assertString(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of applying boolean conversion to this object.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- BoolState convertToBool() => BoolState.FALSE_STATE;
-
- /**
- * Return the result of converting this object to a String.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- StringState convertToString();
-
- /**
- * Return the result of invoking the '/' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- NumState divide(InstanceState rightOperand) {
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '==' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- BoolState equalEqual(InstanceState rightOperand);
-
- /**
- * Return the result of invoking the '>' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- BoolState greaterThan(InstanceState rightOperand) {
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '>=' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- BoolState greaterThanOrEqual(InstanceState rightOperand) {
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '~/' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- IntState integerDivide(InstanceState rightOperand) {
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the identical function on this object with
- * the [rightOperand].
- */
- BoolState isIdentical(InstanceState rightOperand);
-
- /**
- * Return the result of invoking the '<' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- BoolState lessThan(InstanceState rightOperand) {
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '<=' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- BoolState lessThanOrEqual(InstanceState rightOperand) {
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '&&' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- BoolState logicalAnd(InstanceState rightOperand) {
- assertBool(this);
- assertBool(rightOperand);
- return BoolState.FALSE_STATE;
- }
-
- /**
- * Return the result of invoking the '!' operator on this object.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- BoolState logicalNot() {
- assertBool(this);
- return BoolState.TRUE_STATE;
- }
-
- /**
- * Return the result of invoking the '||' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- BoolState logicalOr(InstanceState rightOperand) {
- assertBool(this);
- assertBool(rightOperand);
- return rightOperand.convertToBool();
- }
-
- /**
- * Return the result of invoking the '-' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- NumState minus(InstanceState rightOperand) {
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '-' operator on this object.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- NumState negated() {
- assertNumOrNull(this);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '%' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- NumState remainder(InstanceState rightOperand) {
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '<<' operator on this object with
- * the [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- IntState shiftLeft(InstanceState rightOperand) {
- assertIntOrNull(this);
- assertIntOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '>>' operator on this object with
- * the [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- IntState shiftRight(InstanceState rightOperand) {
- assertIntOrNull(this);
- assertIntOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the 'length' getter on this object.
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- IntState stringLength() {
- assertString(this);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-
- /**
- * Return the result of invoking the '*' operator on this object with the
- * [rightOperand].
- *
- * Throws an [EvaluationException] if the operator is not appropriate for an
- * object of this kind.
- */
- NumState times(InstanceState rightOperand) {
- assertNumOrNull(this);
- assertNumOrNull(rightOperand);
- throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT);
- }
-}
-
-/**
- * The state of an object representing an int.
- */
-class IntState extends NumState {
- /**
- * A state that can be used to represent an int whose value is not known.
- */
- static IntState UNKNOWN_VALUE = new IntState(null);
-
- /**
- * The value of this instance.
- */
- final int value;
-
- /**
- * Initialize a newly created state to represent an int with the given
- * [value].
- */
- IntState(this.value);
-
- @override
- int get hashCode => value == null ? 0 : value.hashCode;
-
- @override
- bool get isBoolNumStringOrNull => true;
-
- @override
- bool get isUnknown => value == null;
-
- @override
- String get typeName => "int";
-
- @override
- bool operator ==(Object object) =>
- object is IntState && (value == object.value);
-
- @override
- NumState add(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- if (rightOperand is DoubleState) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new IntState(value + rightValue);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return new DoubleState(value.toDouble() + rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- IntState bitAnd(InstanceState rightOperand) {
- assertIntOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new IntState(value & rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- IntState bitNot() {
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- return new IntState(~value);
- }
-
- @override
- IntState bitOr(InstanceState rightOperand) {
- assertIntOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new IntState(value | rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- IntState bitXor(InstanceState rightOperand) {
- assertIntOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new IntState(value ^ rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- StringState convertToString() {
- if (value == null) {
- return StringState.UNKNOWN_VALUE;
- }
- return new StringState(value.toString());
- }
-
- @override
- NumState divide(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return DoubleState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return DoubleState.UNKNOWN_VALUE;
- } else {
- return new DoubleState(value.toDouble() / rightValue.toDouble());
- }
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return new DoubleState(value.toDouble() / rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return DoubleState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- return isIdentical(rightOperand);
- }
-
- @override
- BoolState greaterThan(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.compareTo(rightValue) > 0);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.toDouble() > rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- BoolState greaterThanOrEqual(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.compareTo(rightValue) >= 0);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.toDouble() >= rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- IntState integerDivide(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- } else if (rightValue == 0) {
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
- }
- return new IntState(value ~/ rightValue);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- double result = value.toDouble() / rightValue;
- return new IntState(result.toInt());
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- BoolState isIdentical(InstanceState rightOperand) {
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value == rightValue);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(rightValue == value.toDouble());
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.FALSE_STATE;
- }
-
- @override
- BoolState lessThan(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.compareTo(rightValue) < 0);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.toDouble() < rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- BoolState lessThanOrEqual(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.compareTo(rightValue) <= 0);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value.toDouble() <= rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return BoolState.UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- NumState minus(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- if (rightOperand is DoubleState) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new IntState(value - rightValue);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return new DoubleState(value.toDouble() - rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- NumState negated() {
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- return new IntState(-value);
- }
-
- @override
- NumState remainder(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- if (rightOperand is DoubleState) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- } else if (rightValue == 0) {
- return new DoubleState(value.toDouble() % rightValue.toDouble());
- }
- return new IntState(value.remainder(rightValue));
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return new DoubleState(value.toDouble() % rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- IntState shiftLeft(InstanceState rightOperand) {
- assertIntOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- } else if (rightValue.bitLength > 31) {
- return UNKNOWN_VALUE;
- }
- return new IntState(value << rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- IntState shiftRight(InstanceState rightOperand) {
- assertIntOrNull(rightOperand);
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- } else if (rightValue.bitLength > 31) {
- return UNKNOWN_VALUE;
- }
- return new IntState(value >> rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- NumState times(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (value == null) {
- if (rightOperand is DoubleState) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return UNKNOWN_VALUE;
- }
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new IntState(value * rightValue);
- } else if (rightOperand is DoubleState) {
- double rightValue = rightOperand.value;
- if (rightValue == null) {
- return DoubleState.UNKNOWN_VALUE;
- }
- return new DoubleState(value.toDouble() * rightValue);
- } else if (rightOperand is DynamicState || rightOperand is NumState) {
- return UNKNOWN_VALUE;
- }
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- String toString() => value == null ? "-unknown-" : value.toString();
-}
-
-/**
- * The state of an object representing a list.
- */
-class ListState extends InstanceState {
- /**
- * The elements of the list.
- */
- final List<DartObjectImpl> _elements;
-
- /**
- * Initialize a newly created state to represent a list with the given
- * [elements].
- */
- ListState(this._elements);
-
- @override
- int get hashCode {
- int value = 0;
- int count = _elements.length;
- for (int i = 0; i < count; i++) {
- value = (value << 3) ^ _elements[i].hashCode;
- }
- return value;
- }
-
- @override
- String get typeName => "List";
-
- @override
- bool operator ==(Object object) {
- if (object is! ListState) {
- return false;
- }
- List<DartObjectImpl> otherElements = (object as ListState)._elements;
- int count = _elements.length;
- if (otherElements.length != count) {
- return false;
- } else if (count == 0) {
- return true;
- }
- for (int i = 0; i < count; i++) {
- if (_elements[i] != otherElements[i]) {
- return false;
- }
- }
- return true;
- }
-
- @override
- StringState convertToString() => StringState.UNKNOWN_VALUE;
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- return isIdentical(rightOperand);
- }
-
- @override
- BoolState isIdentical(InstanceState rightOperand) {
- if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(this == rightOperand);
- }
-
- @override
- String toString() {
- StringBuffer buffer = new StringBuffer();
- buffer.write('[');
- bool first = true;
- _elements.forEach((DartObjectImpl element) {
- if (first) {
- first = false;
- } else {
- buffer.write(', ');
- }
- buffer.write(element);
- });
- buffer.write(']');
- return buffer.toString();
- }
-}
-
-/**
- * The state of an object representing a map.
- */
-class MapState extends InstanceState {
- /**
- * The entries in the map.
- */
- final HashMap<DartObjectImpl, DartObjectImpl> _entries;
-
- /**
- * Initialize a newly created state to represent a map with the given
- * [entries].
- */
- MapState(this._entries);
-
- @override
- int get hashCode {
- int value = 0;
- for (DartObjectImpl key in _entries.keys.toSet()) {
- value = (value << 3) ^ key.hashCode;
- }
- return value;
- }
-
- @override
- String get typeName => "Map";
-
- @override
- bool operator ==(Object object) {
- if (object is! MapState) {
- return false;
- }
- HashMap<DartObjectImpl, DartObjectImpl> otherElements =
- (object as MapState)._entries;
- int count = _entries.length;
- if (otherElements.length != count) {
- return false;
- } else if (count == 0) {
- return true;
- }
- for (DartObjectImpl key in _entries.keys) {
- DartObjectImpl value = _entries[key];
- DartObjectImpl otherValue = otherElements[key];
- if (value != otherValue) {
- return false;
- }
- }
- return true;
- }
-
- @override
- StringState convertToString() => StringState.UNKNOWN_VALUE;
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- return isIdentical(rightOperand);
- }
-
- @override
- BoolState isIdentical(InstanceState rightOperand) {
- if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(this == rightOperand);
- }
-
- @override
- String toString() {
- StringBuffer buffer = new StringBuffer();
- buffer.write('{');
- bool first = true;
- _entries.forEach((DartObjectImpl key, DartObjectImpl value) {
- if (first) {
- first = false;
- } else {
- buffer.write(', ');
- }
- buffer.write(key);
- buffer.write(' = ');
- buffer.write(value);
- });
- buffer.write('}');
- return buffer.toString();
- }
-}
-
-/**
- * The state of an object representing the value 'null'.
- */
-class NullState extends InstanceState {
- /**
- * An instance representing the boolean value 'null'.
- */
- static NullState NULL_STATE = new NullState();
-
- @override
- int get hashCode => 0;
-
- @override
- bool get isBoolNumStringOrNull => true;
-
- @override
- String get typeName => "Null";
-
- @override
- bool operator ==(Object object) => object is NullState;
-
- @override
- BoolState convertToBool() {
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- StringState convertToString() => new StringState("null");
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- return isIdentical(rightOperand);
- }
-
- @override
- BoolState isIdentical(InstanceState rightOperand) {
- if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(rightOperand is NullState);
- }
-
- @override
- BoolState logicalNot() {
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION);
- }
-
- @override
- String toString() => "null";
-}
-
-/**
- * The state of an object representing a number of an unknown type (a 'num').
- */
-class NumState extends InstanceState {
- /**
- * A state that can be used to represent a number whose value is not known.
- */
- static NumState UNKNOWN_VALUE = new NumState();
-
- @override
- int get hashCode => 7;
-
- @override
- bool get isBoolNumStringOrNull => true;
-
- @override
- bool get isUnknown => identical(this, UNKNOWN_VALUE);
-
- @override
- String get typeName => "num";
-
- @override
- bool operator ==(Object object) => object is NumState;
-
- @override
- NumState add(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return UNKNOWN_VALUE;
- }
-
- @override
- StringState convertToString() => StringState.UNKNOWN_VALUE;
-
- @override
- NumState divide(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return DoubleState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState greaterThan(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState greaterThanOrEqual(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
- }
-
- @override
- IntState integerDivide(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- if (rightOperand is IntState) {
- int rightValue = rightOperand.value;
- if (rightValue == null) {
- return IntState.UNKNOWN_VALUE;
- } else if (rightValue == 0) {
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE);
- }
- } else if (rightOperand is DynamicState) {
- return IntState.UNKNOWN_VALUE;
- }
- return IntState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState isIdentical(InstanceState rightOperand) {
- return BoolState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState lessThan(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
- }
-
- @override
- BoolState lessThanOrEqual(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return BoolState.UNKNOWN_VALUE;
- }
-
- @override
- NumState minus(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return UNKNOWN_VALUE;
- }
-
- @override
- NumState negated() => UNKNOWN_VALUE;
-
- @override
- NumState remainder(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return UNKNOWN_VALUE;
- }
-
- @override
- NumState times(InstanceState rightOperand) {
- assertNumOrNull(rightOperand);
- return UNKNOWN_VALUE;
- }
-
- @override
- String toString() => "-unknown-";
-}
-
-/**
- * An object used to add reference information for a given variable to the
- * bi-directional mapping used to order the evaluation of constants.
- */
-class ReferenceFinder extends RecursiveAstVisitor<Object> {
- /**
- * The callback which should be used to report any dependencies that were
- * found.
- */
- final ReferenceFinderCallback _callback;
-
- /**
- * Initialize a newly created reference finder to find references from a given
- * variable to other variables and to add those references to the given graph.
- * The [_callback] will be invoked for every dependency found.
- */
- ReferenceFinder(this._callback);
-
- @override
- Object visitInstanceCreationExpression(InstanceCreationExpression node) {
- if (node.isConst) {
- ConstructorElement constructor = _getConstructorImpl(node.staticElement);
- if (constructor != null) {
- _callback(constructor);
- }
- }
- return super.visitInstanceCreationExpression(node);
- }
-
- @override
- Object visitLabel(Label node) {
- // We are visiting the "label" part of a named expression in a function
- // call (presumably a constructor call), e.g. "const C(label: ...)". We
- // don't want to visit the SimpleIdentifier for the label because that's a
- // reference to a function parameter that needs to be filled in; it's not a
- // constant whose value we depend on.
- return null;
- }
-
- @override
- Object visitRedirectingConstructorInvocation(
- RedirectingConstructorInvocation node) {
- super.visitRedirectingConstructorInvocation(node);
- ConstructorElement target = _getConstructorImpl(node.staticElement);
- if (target != null) {
- _callback(target);
- }
- return null;
- }
-
- @override
- Object visitSimpleIdentifier(SimpleIdentifier node) {
- Element element = node.staticElement;
- if (element is PropertyAccessorElement) {
- element = (element as PropertyAccessorElement).variable;
- }
- if (element is VariableElement && element.isConst) {
- _callback(element);
- }
- return null;
- }
-
- @override
- Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
- super.visitSuperConstructorInvocation(node);
- ConstructorElement constructor = _getConstructorImpl(node.staticElement);
- if (constructor != null) {
- _callback(constructor);
- }
- return null;
- }
-}
-
-/**
- * The state of an object representing a string.
- */
-class StringState extends InstanceState {
- /**
- * A state that can be used to represent a double whose value is not known.
- */
- static StringState UNKNOWN_VALUE = new StringState(null);
-
- /**
- * The value of this instance.
- */
- final String value;
-
- /**
- * Initialize a newly created state to represent the given [value].
- */
- StringState(this.value);
-
- @override
- int get hashCode => value == null ? 0 : value.hashCode;
-
- @override
- bool get isBoolNumStringOrNull => true;
-
- @override
- bool get isUnknown => value == null;
-
- @override
- String get typeName => "String";
-
- @override
- bool operator ==(Object object) =>
- object is StringState && (value == object.value);
-
- @override
- StringState concatenate(InstanceState rightOperand) {
- if (value == null) {
- return UNKNOWN_VALUE;
- }
- if (rightOperand is StringState) {
- String rightValue = rightOperand.value;
- if (rightValue == null) {
- return UNKNOWN_VALUE;
- }
- return new StringState("$value$rightValue");
- } else if (rightOperand is DynamicState) {
- return UNKNOWN_VALUE;
- }
- return super.concatenate(rightOperand);
- }
-
- @override
- StringState convertToString() => this;
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- return isIdentical(rightOperand);
- }
-
- @override
- BoolState isIdentical(InstanceState rightOperand) {
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is StringState) {
- String rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value == rightValue);
- } else if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.FALSE_STATE;
- }
-
- @override
- IntState stringLength() {
- if (value == null) {
- return IntState.UNKNOWN_VALUE;
- }
- return new IntState(value.length);
- }
-
- @override
- String toString() => value == null ? "-unknown-" : "'$value'";
-}
-
-/**
- * The state of an object representing a symbol.
- */
-class SymbolState extends InstanceState {
- /**
- * The value of this instance.
- */
- final String value;
-
- /**
- * Initialize a newly created state to represent the given [value].
- */
- SymbolState(this.value);
-
- @override
- int get hashCode => value == null ? 0 : value.hashCode;
-
- @override
- String get typeName => "Symbol";
-
- @override
- bool operator ==(Object object) =>
- object is SymbolState && (value == object.value);
-
- @override
- StringState convertToString() {
- if (value == null) {
- return StringState.UNKNOWN_VALUE;
- }
- return new StringState(value);
- }
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- return isIdentical(rightOperand);
- }
-
- @override
- BoolState isIdentical(InstanceState rightOperand) {
- if (value == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is SymbolState) {
- String rightValue = rightOperand.value;
- if (rightValue == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(value == rightValue);
- } else if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.FALSE_STATE;
- }
-
- @override
- String toString() => value == null ? "-unknown-" : "#$value";
-}
-
-/**
- * The state of an object representing a type.
- */
-class TypeState extends InstanceState {
- /**
- * The element representing the type being modeled.
- */
- final Element _element;
-
- /**
- * Initialize a newly created state to represent the given [value].
- */
- TypeState(this._element);
-
- @override
- int get hashCode => _element == null ? 0 : _element.hashCode;
-
- @override
- String get typeName => "Type";
-
- @override
- bool operator ==(Object object) =>
- object is TypeState && (_element == object._element);
-
- @override
- StringState convertToString() {
- if (_element == null) {
- return StringState.UNKNOWN_VALUE;
- }
- return new StringState(_element.name);
- }
-
- @override
- BoolState equalEqual(InstanceState rightOperand) {
- assertBoolNumStringOrNull(rightOperand);
- return isIdentical(rightOperand);
- }
-
- @override
- BoolState isIdentical(InstanceState rightOperand) {
- if (_element == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- if (rightOperand is TypeState) {
- Element rightElement = rightOperand._element;
- if (rightElement == null) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.from(_element == rightElement);
- } else if (rightOperand is DynamicState) {
- return BoolState.UNKNOWN_VALUE;
- }
- return BoolState.FALSE_STATE;
- }
-
- @override
- String toString() => _element == null ? "-unknown-" : _element.name;
-}
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index a9a3881..9945d4e 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -2586,7 +2586,7 @@
Element get staticElement => null;
@override
- accept(AstVisitor visitor) => null;
+ dynamic/*=E*/ accept/*<E>*/(AstVisitor/*<E>*/ visitor) => null;
@override
void visitChildren(AstVisitor visitor) {}
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 60b1acf..846b27b 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -1082,6 +1082,11 @@
bool get enableSuperMixins;
/**
+ * Return `true` if timing data should be gathered during execution.
+ */
+ bool get enableTiming;
+
+ /**
* Return `true` if errors, warnings and hints should be generated for sources
* that are implicitly being analyzed. The default value is `true`.
*/
@@ -1215,6 +1220,9 @@
*/
bool enableSuperMixins = false;
+ @override
+ bool enableTiming = false;
+
/**
* A flag indicating whether errors, warnings and hints should be generated
* for sources that are implicitly being analyzed.
@@ -1293,6 +1301,7 @@
enableStrictCallChecks = options.enableStrictCallChecks;
enableGenericMethods = options.enableGenericMethods;
enableSuperMixins = options.enableSuperMixins;
+ enableTiming = options.enableTiming;
generateImplicitErrors = options.generateImplicitErrors;
generateSdkErrors = options.generateSdkErrors;
hint = options.hint;
diff --git a/pkg/analyzer/lib/src/generated/error.dart b/pkg/analyzer/lib/src/generated/error.dart
index 0219d7e..4b67db5 100644
--- a/pkg/analyzer/lib/src/generated/error.dart
+++ b/pkg/analyzer/lib/src/generated/error.dart
@@ -26,7 +26,7 @@
* The descriptor used to associate error processors with analysis contexts in
* configuration data.
*/
-final ListResultDescriptor<List<ErrorProcessor>> CONFIGURED_ERROR_PROCESSORS =
+final ListResultDescriptor<ErrorProcessor> CONFIGURED_ERROR_PROCESSORS =
new ListResultDescriptorImpl('configured.errors', const <ErrorProcessor>[]);
/**
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index efd0f93..28d02ec 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -5694,6 +5694,15 @@
iterableType = iterableType.resolveToBound(_typeProvider.objectType);
DartType bestIterableType =
_typeSystem.mostSpecificTypeArgument(iterableType, loopType);
+
+ // Allow it to be a supertype of Iterable<T> (basically just Object) and do
+ // an implicit downcast to Iterable<dynamic>.
+ if (bestIterableType == null) {
+ if (_typeSystem.isSubtypeOf(loopType, iterableType)) {
+ bestIterableType = DynamicTypeImpl.instance;
+ }
+ }
+
if (bestIterableType == null) {
_errorReporter.reportTypeErrorForNode(
StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE,
diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
index 9f4e419..61c8570 100644
--- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart
@@ -878,7 +878,7 @@
@override
DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
- ResultDescriptor descriptor) {
+ ResultDescriptor descriptor, Object value) {
// A body change delta should never leak outside its source.
// It can cause invalidation of results (e.g. hints) in other sources,
// but only when a result in the updated source is INVALIDATE_NO_DELTA.
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index adf9a73..d537f0c 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -128,7 +128,9 @@
'expectKeyword_1': new MethodTrampoline(
1, (Parser target, arg0) => target._expectKeyword(arg0)),
'findRange_2': new MethodTrampoline(
- 2, (Parser target, arg0, arg1) => target._findRange(arg0, arg1)),
+ 2,
+ (Parser target, List<List<int>> arg0, int arg1) =>
+ target._findRange(arg0, arg1)),
'getCodeBlockRanges_1': new MethodTrampoline(
1, (Parser target, arg0) => target._getCodeBlockRanges(arg0)),
'getEndToken_1': new MethodTrampoline(
@@ -202,7 +204,9 @@
'parseCommentReference_2': new MethodTrampoline(2,
(Parser target, arg0, arg1) => target._parseCommentReference(arg0, arg1)),
'parseCommentReferences_1': new MethodTrampoline(
- 1, (Parser target, arg0) => target._parseCommentReferences(arg0)),
+ 1,
+ (Parser target, List<DocumentationCommentToken> arg0) =>
+ target._parseCommentReferences(arg0)),
'parseCompilationUnitMember_1': new MethodTrampoline(
1, (Parser target, arg0) => target._parseCompilationUnitMember(arg0)),
'parseConfiguration_0':
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 92814ba..4849014 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -36,26 +36,6 @@
export 'package:analyzer/src/generated/type_system.dart';
/**
- * Throw an [ElementMismatchException] to report that the element model and the
- * AST do not match. The [message] will have the path to the given [node]
- * appended to it.
- */
-void _mismatch(String message, AstNode node) {
- StringBuffer buffer = new StringBuffer();
- buffer.writeln(message);
- buffer.write('Path to root:');
- String separator = ' ';
- AstNode parent = node;
- while (parent != null) {
- buffer.write(separator);
- buffer.write(parent.runtimeType.toString());
- separator = ', ';
- parent = parent.parent;
- }
- throw new ElementMismatchException(buffer.toString());
-}
-
-/**
* Instances of the class `BestPracticesVerifier` traverse an AST structure looking for
* violations of Dart best practices.
*/
@@ -1877,14 +1857,14 @@
_errorReporter.reportErrorForNode(
HintCode.DEAD_CODE, node.rightOperand);
// only visit the LHS:
- _safelyVisit(lhsCondition);
+ lhsCondition?.accept(this);
return null;
} else if (lhsResult.value.toBoolValue() == false && isAmpAmp) {
// report error on if block: false && !e!
_errorReporter.reportErrorForNode(
HintCode.DEAD_CODE, node.rightOperand);
// only visit the LHS:
- _safelyVisit(lhsCondition);
+ lhsCondition?.accept(this);
return null;
}
}
@@ -1898,13 +1878,13 @@
// // report error on else block: !e! || true
// errorReporter.reportError(HintCode.DEAD_CODE, node.getRightOperand());
// // only visit the RHS:
-// safelyVisit(rhsCondition);
+// rhsCondition?.accept(this);
// return null;
// } else if (rhsResult == ValidResult.RESULT_FALSE && isAmpAmp) {
// // report error on if block: !e! && false
// errorReporter.reportError(HintCode.DEAD_CODE, node.getRightOperand());
// // only visit the RHS:
-// safelyVisit(rhsCondition);
+// rhsCondition?.accept(this);
// return null;
// }
// }
@@ -1928,7 +1908,7 @@
@override
Object visitConditionalExpression(ConditionalExpression node) {
Expression conditionExpression = node.condition;
- _safelyVisit(conditionExpression);
+ conditionExpression?.accept(this);
if (!_isDebugConstant(conditionExpression)) {
EvaluationResultImpl result =
_getConstantBooleanValue(conditionExpression);
@@ -1937,13 +1917,13 @@
// report error on else block: true ? 1 : !2!
_errorReporter.reportErrorForNode(
HintCode.DEAD_CODE, node.elseExpression);
- _safelyVisit(node.thenExpression);
+ node.thenExpression?.accept(this);
return null;
} else {
// report error on if block: false ? !1! : 2
_errorReporter.reportErrorForNode(
HintCode.DEAD_CODE, node.thenExpression);
- _safelyVisit(node.elseExpression);
+ node.elseExpression?.accept(this);
return null;
}
}
@@ -1954,7 +1934,7 @@
@override
Object visitIfStatement(IfStatement node) {
Expression conditionExpression = node.condition;
- _safelyVisit(conditionExpression);
+ conditionExpression?.accept(this);
if (!_isDebugConstant(conditionExpression)) {
EvaluationResultImpl result =
_getConstantBooleanValue(conditionExpression);
@@ -1965,14 +1945,14 @@
if (elseStatement != null) {
_errorReporter.reportErrorForNode(
HintCode.DEAD_CODE, elseStatement);
- _safelyVisit(node.thenStatement);
+ node.thenStatement?.accept(this);
return null;
}
} else {
// report error on if block: if (false) {!} else {}
_errorReporter.reportErrorForNode(
HintCode.DEAD_CODE, node.thenStatement);
- _safelyVisit(node.elseStatement);
+ node.elseStatement?.accept(this);
return null;
}
}
@@ -1994,8 +1974,8 @@
@override
Object visitTryStatement(TryStatement node) {
- _safelyVisit(node.body);
- _safelyVisit(node.finallyBlock);
+ node.body?.accept(this);
+ node.finallyBlock?.accept(this);
NodeList<CatchClause> catchClauses = node.catchClauses;
int numOfCatchClauses = catchClauses.length;
List<DartType> visitedTypes = new List<DartType>();
@@ -2012,7 +1992,7 @@
// this is equivalent to having a catch clause that doesn't have an
// exception type, visit the block, but generate an error on any
// following catch clauses (and don't visit them).
- _safelyVisit(catchClause);
+ catchClause?.accept(this);
if (i + 1 != numOfCatchClauses) {
// this catch clause is not the last in the try statement
CatchClause nextCatchClause = catchClauses[i + 1];
@@ -2039,12 +2019,12 @@
}
visitedTypes.add(currentType);
}
- _safelyVisit(catchClause);
+ catchClause?.accept(this);
} else {
// Found catch clause clause that doesn't have an exception type,
// visit the block, but generate an error on any following catch clauses
// (and don't visit them).
- _safelyVisit(catchClause);
+ catchClause?.accept(this);
if (i + 1 != numOfCatchClauses) {
// this catch clause is not the last in the try statement
CatchClause nextCatchClause = catchClauses[i + 1];
@@ -2063,7 +2043,7 @@
@override
Object visitWhileStatement(WhileStatement node) {
Expression conditionExpression = node.condition;
- _safelyVisit(conditionExpression);
+ conditionExpression?.accept(this);
if (!_isDebugConstant(conditionExpression)) {
EvaluationResultImpl result =
_getConstantBooleanValue(conditionExpression);
@@ -2075,7 +2055,7 @@
}
}
}
- _safelyVisit(node.body);
+ node.body?.accept(this);
return null;
}
@@ -2090,7 +2070,7 @@
int size = statements.length;
for (int i = 0; i < size; i++) {
Statement currentStatement = statements[i];
- _safelyVisit(currentStatement);
+ currentStatement?.accept(this);
bool returnOrBreakingStatement = currentStatement is ReturnStatement ||
(currentStatement is BreakStatement &&
currentStatement.label == null) ||
@@ -2162,17 +2142,6 @@
}
return false;
}
-
- /**
- * If the given node is not `null`, visit this instance of the dead code verifier.
- *
- * @param node the node to be visited
- */
- void _safelyVisit(AstNode node) {
- if (node != null) {
- node.accept(this);
- }
- }
}
/**
@@ -2184,7 +2153,8 @@
* This class must not assume that the [CompilationUnitElement] passed to it is
* any more complete than a [COMPILATION_UNIT_ELEMENT].
*/
-class DeclarationResolver extends RecursiveAstVisitor<Object> {
+class DeclarationResolver extends RecursiveAstVisitor<Object>
+ with ExistingElementResolver {
/**
* The analysis context containing the sources to be analyzed.
*/
@@ -2197,11 +2167,6 @@
Set<Element> _expectedElements;
/**
- * The compilation unit containing the AST nodes being visited.
- */
- CompilationUnitElementImpl _enclosingUnit;
-
- /**
* The function type alias containing the AST nodes being visited, or `null`
* if we are not in the scope of a function type alias.
*/
@@ -2833,9 +2798,7 @@
* The resulting AST must have everything resolved that would have been resolved
* by a [DirectiveElementBuilder].
*/
-class DirectiveResolver extends SimpleAstVisitor {
- CompilationUnitElementImpl _enclosingUnit;
-
+class DirectiveResolver extends SimpleAstVisitor with ExistingElementResolver {
@override
void visitCompilationUnit(CompilationUnit node) {
_enclosingUnit = node.element;
@@ -3494,6 +3457,41 @@
}
/**
+ * A mixin for classes that use an existing element model to resolve a portion
+ * of an AST structure.
+ */
+class ExistingElementResolver {
+ /**
+ * The compilation unit containing the AST nodes being visited.
+ */
+ CompilationUnitElementImpl _enclosingUnit;
+
+ /**
+ * Throw an [ElementMismatchException] to report that the element model and the
+ * AST do not match. The [message] will have the path to the given [node]
+ * appended to it.
+ */
+ void _mismatch(String message, AstNode node) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.write('Mismatch in ');
+ buffer.write(runtimeType);
+ buffer.write(' while resolving ');
+ buffer.writeln(_enclosingUnit?.source?.fullName);
+ buffer.writeln(message);
+ buffer.write('Path to root:');
+ String separator = ' ';
+ AstNode parent = node;
+ while (parent != null) {
+ buffer.write(separator);
+ buffer.write(parent.runtimeType.toString());
+ separator = ', ';
+ parent = parent.parent;
+ }
+ throw new ElementMismatchException(buffer.toString());
+ }
+}
+
+/**
* Instances of the class `ExitDetector` determine whether the visited AST node is guaranteed
* to terminate by executing a `return` statement, `throw` expression, `rethrow`
* expression, or simple infinite loop such as `while(true)`.
@@ -6611,10 +6609,9 @@
//
return Namespace.EMPTY;
}
- HashMap<String, Element> definedNames =
- _createExportMapping(exportedLibrary, new HashSet<LibraryElement>());
- definedNames = _applyCombinators(definedNames, element.combinators);
- return new Namespace(definedNames);
+ HashMap<String, Element> exportedNames = _getExportMapping(exportedLibrary);
+ exportedNames = _applyCombinators(exportedNames, element.combinators);
+ return new Namespace(exportedNames);
}
/**
@@ -6623,9 +6620,10 @@
* @param library the library whose export namespace is to be created
* @return the export namespace that was created
*/
- Namespace createExportNamespaceForLibrary(LibraryElement library) =>
- new Namespace(
- _createExportMapping(library, new HashSet<LibraryElement>()));
+ Namespace createExportNamespaceForLibrary(LibraryElement library) {
+ HashMap<String, Element> exportedNames = _getExportMapping(library);
+ return new Namespace(exportedNames);
+ }
/**
* Create a namespace representing the import namespace of the given library.
@@ -6642,11 +6640,10 @@
//
return Namespace.EMPTY;
}
- HashMap<String, Element> definedNames =
- _createExportMapping(importedLibrary, new HashSet<LibraryElement>());
- definedNames = _applyCombinators(definedNames, element.combinators);
- definedNames = _applyPrefix(definedNames, element.prefix);
- return new Namespace(definedNames);
+ HashMap<String, Element> exportedNames = _getExportMapping(importedLibrary);
+ exportedNames = _applyCombinators(exportedNames, element.combinators);
+ exportedNames = _applyPrefix(exportedNames, element.prefix);
+ return new Namespace(exportedNames);
}
/**
@@ -6770,7 +6767,7 @@
* be added by another library
* @return the mapping table that was created
*/
- HashMap<String, Element> _createExportMapping(
+ HashMap<String, Element> _computeExportMapping(
LibraryElement library, HashSet<LibraryElement> visitedElements) {
visitedElements.add(library);
try {
@@ -6784,7 +6781,7 @@
// valid library.
//
HashMap<String, Element> exportedNames =
- _createExportMapping(exportedLibrary, visitedElements);
+ _computeExportMapping(exportedLibrary, visitedElements);
exportedNames = _applyCombinators(exportedNames, element.combinators);
definedNames.addAll(exportedNames);
}
@@ -6799,6 +6796,20 @@
}
}
+ HashMap<String, Element> _getExportMapping(LibraryElement library) {
+ if (library is LibraryElementImpl) {
+ if (library.exportNamespace != null) {
+ return library.exportNamespace.definedNames;
+ } else {
+ HashMap<String, Element> exportMapping =
+ _computeExportMapping(library, new HashSet<LibraryElement>());
+ library.exportNamespace = new Namespace(exportMapping);
+ return exportMapping;
+ }
+ }
+ return _computeExportMapping(library, new HashSet<LibraryElement>());
+ }
+
/**
* Return a new map of names which has all the names from [definedNames]
* with exception of [hiddenNames].
@@ -7682,13 +7693,13 @@
identical(parent, _enclosingFunctionTypeAlias)) {
return null;
}
- safelyVisit(node.name);
- safelyVisit(node.constructorName);
+ node.name?.accept(this);
+ node.constructorName?.accept(this);
Element element = node.element;
if (element is ExecutableElement) {
InferenceContext.setType(node.arguments, element.type);
}
- safelyVisit(node.arguments);
+ node.arguments?.accept(this);
node.accept(elementResolver);
node.accept(typeAnalyzer);
ElementAnnotationImpl elementAnnotationImpl = node.elementAnnotation;
@@ -7766,14 +7777,14 @@
@override
Object visitAssignmentExpression(AssignmentExpression node) {
- safelyVisit(node.leftHandSide);
+ node.leftHandSide?.accept(this);
TokenType operator = node.operator.type;
if (operator == TokenType.EQ ||
operator == TokenType.QUESTION_QUESTION_EQ) {
InferenceContext.setType(
node.rightHandSide, node.leftHandSide.staticType);
}
- safelyVisit(node.rightHandSide);
+ node.rightHandSide?.accept(this);
node.accept(elementResolver);
node.accept(typeAnalyzer);
return null;
@@ -7798,7 +7809,7 @@
Expression leftOperand = node.leftOperand;
Expression rightOperand = node.rightOperand;
if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
- safelyVisit(leftOperand);
+ leftOperand?.accept(this);
if (rightOperand != null) {
_overrideManager.enterScope();
try {
@@ -7821,7 +7832,7 @@
}
}
} else if (operatorType == TokenType.BAR_BAR) {
- safelyVisit(leftOperand);
+ leftOperand?.accept(this);
if (rightOperand != null) {
_overrideManager.enterScope();
try {
@@ -7838,8 +7849,8 @@
InferenceContext.setTypeFromNode(leftOperand, node);
InferenceContext.setTypeFromNode(rightOperand, node);
}
- safelyVisit(leftOperand);
- safelyVisit(rightOperand);
+ leftOperand?.accept(this);
+ rightOperand?.accept(this);
}
node.accept(elementResolver);
node.accept(typeAnalyzer);
@@ -7993,7 +8004,7 @@
@override
Object visitConditionalExpression(ConditionalExpression node) {
Expression condition = node.condition;
- safelyVisit(condition);
+ condition?.accept(this);
Expression thenExpression = node.thenExpression;
if (thenExpression != null) {
_overrideManager.enterScope();
@@ -8075,7 +8086,7 @@
//
FieldElement fieldElement = enclosingClass.getField(node.fieldName.name);
InferenceContext.setType(node.expression, fieldElement?.type);
- safelyVisit(node.expression);
+ node.expression?.accept(this);
node.accept(elementResolver);
node.accept(typeAnalyzer);
return null;
@@ -8226,9 +8237,9 @@
InferenceContext.setType(
iterable, targetType.instantiate([loopVariable.type.type]));
}
- safelyVisit(iterable);
- safelyVisit(loopVariable);
- safelyVisit(identifier);
+ iterable?.accept(this);
+ loopVariable?.accept(this);
+ identifier?.accept(this);
Statement body = node.body;
if (body != null) {
_overrideManager.enterScope();
@@ -8278,9 +8289,9 @@
@override
void visitForStatementInScope(ForStatement node) {
- safelyVisit(node.variables);
- safelyVisit(node.initialization);
- safelyVisit(node.condition);
+ node.variables?.accept(this);
+ node.initialization?.accept(this);
+ node.condition?.accept(this);
_overrideManager.enterScope();
try {
_propagateTrueState(node.condition);
@@ -8350,11 +8361,11 @@
@override
Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
- safelyVisit(node.function);
+ node.function?.accept(this);
node.accept(elementResolver);
_inferFunctionExpressionsParametersTypes(node.argumentList);
_inferArgumentTypesFromContext(node);
- safelyVisit(node.argumentList);
+ node.argumentList?.accept(this);
node.accept(typeAnalyzer);
return null;
}
@@ -8387,7 +8398,7 @@
@override
Object visitIfStatement(IfStatement node) {
Expression condition = node.condition;
- safelyVisit(condition);
+ condition?.accept(this);
Map<VariableElement, DartType> thenOverrides =
new HashMap<VariableElement, DartType>();
Statement thenStatement = node.thenStatement;
@@ -8467,12 +8478,12 @@
}
}
}
- safelyVisit(node.constructorName);
+ node.constructorName?.accept(this);
FunctionType constructorType = node.constructorName.staticElement?.type;
if (constructorType != null) {
InferenceContext.setType(node.argumentList, constructorType);
}
- safelyVisit(node.argumentList);
+ node.argumentList?.accept(this);
node.accept(elementResolver);
node.accept(typeAnalyzer);
return null;
@@ -8566,12 +8577,12 @@
// We visit the target and argument list, but do not visit the method name
// because it needs to be visited in the context of the invocation.
//
- safelyVisit(node.target);
- safelyVisit(node.typeArguments);
+ node.target?.accept(this);
+ node.typeArguments?.accept(this);
node.accept(elementResolver);
_inferFunctionExpressionsParametersTypes(node.argumentList);
_inferArgumentTypesFromContext(node);
- safelyVisit(node.argumentList);
+ node.argumentList?.accept(this);
node.accept(typeAnalyzer);
return null;
}
@@ -8602,7 +8613,7 @@
// We visit the prefix, but do not visit the identifier because it needs to
// be visited in the context of the prefix.
//
- safelyVisit(node.prefix);
+ node.prefix?.accept(this);
node.accept(elementResolver);
node.accept(typeAnalyzer);
return null;
@@ -8614,7 +8625,7 @@
// We visit the target, but do not visit the property name because it needs
// to be visited in the context of the property access node.
//
- safelyVisit(node.target);
+ node.target?.accept(this);
node.accept(elementResolver);
node.accept(typeAnalyzer);
return null;
@@ -8629,7 +8640,7 @@
// invocation.
//
InferenceContext.setType(node.argumentList, node.staticElement?.type);
- safelyVisit(node.argumentList);
+ node.argumentList?.accept(this);
node.accept(elementResolver);
node.accept(typeAnalyzer);
return null;
@@ -8663,7 +8674,7 @@
// invocation.
//
InferenceContext.setType(node.argumentList, node.staticElement?.type);
- safelyVisit(node.argumentList);
+ node.argumentList?.accept(this);
node.accept(elementResolver);
node.accept(typeAnalyzer);
return null;
@@ -8748,7 +8759,7 @@
try {
_implicitLabelScope = _implicitLabelScope.nest(node);
Expression condition = node.condition;
- safelyVisit(condition);
+ condition?.accept(this);
Statement body = node.body;
if (body != null) {
_overrideManager.enterScope();
@@ -9680,17 +9691,6 @@
source, token.offset, token.length, errorCode, arguments));
}
- /**
- * Visit the given AST node if it is not null.
- *
- * @param node the node to be visited
- */
- void safelyVisit(AstNode node) {
- if (node != null) {
- node.accept(this);
- }
- }
-
@override
Object visitBlock(Block node) {
Scope outerScope = nameScope;
@@ -9768,16 +9768,16 @@
}
void visitClassDeclarationInScope(ClassDeclaration node) {
- safelyVisit(node.name);
- safelyVisit(node.typeParameters);
- safelyVisit(node.extendsClause);
- safelyVisit(node.withClause);
- safelyVisit(node.implementsClause);
- safelyVisit(node.nativeClause);
+ node.name?.accept(this);
+ node.typeParameters?.accept(this);
+ node.extendsClause?.accept(this);
+ node.withClause?.accept(this);
+ node.implementsClause?.accept(this);
+ node.nativeClause?.accept(this);
}
void visitClassMembersInScope(ClassDeclaration node) {
- safelyVisit(node.documentationComment);
+ node.documentationComment?.accept(this);
node.metadata.accept(this);
node.members.accept(this);
}
@@ -9843,7 +9843,7 @@
try {
_implicitLabelScope = _implicitLabelScope.nest(node);
visitStatementInScope(node.body);
- safelyVisit(node.condition);
+ node.condition?.accept(this);
} finally {
_implicitLabelScope = outerImplicitScope;
}
@@ -9877,7 +9877,7 @@
}
void visitEnumMembersInScope(EnumDeclaration node) {
- safelyVisit(node.documentationComment);
+ node.documentationComment?.accept(this);
node.metadata.accept(this);
node.constants.accept(this);
}
@@ -9909,9 +9909,9 @@
// We visit the iterator before the loop variable because the loop variable
// cannot be in scope while visiting the iterator.
//
- safelyVisit(node.identifier);
- safelyVisit(node.iterable);
- safelyVisit(node.loopVariable);
+ node.identifier?.accept(this);
+ node.iterable?.accept(this);
+ node.loopVariable?.accept(this);
visitStatementInScope(node.body);
}
@@ -9955,9 +9955,9 @@
* @param node the statement to be visited
*/
void visitForStatementInScope(ForStatement node) {
- safelyVisit(node.variables);
- safelyVisit(node.initialization);
- safelyVisit(node.condition);
+ node.variables?.accept(this);
+ node.initialization?.accept(this);
+ node.condition?.accept(this);
node.updaters.accept(this);
visitStatementInScope(node.body);
}
@@ -10067,7 +10067,7 @@
@override
Object visitIfStatement(IfStatement node) {
- safelyVisit(node.condition);
+ node.condition?.accept(this);
visitStatementInScope(node.thenStatement);
visitStatementInScope(node.elseStatement);
return null;
@@ -10191,7 +10191,7 @@
@override
Object visitWhileStatement(WhileStatement node) {
- safelyVisit(node.condition);
+ node.condition?.accept(this);
ImplicitLabelScope outerImplicitScope = _implicitLabelScope;
try {
_implicitLabelScope = _implicitLabelScope.nest(node);
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
index d8d44f4..6983cc8 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_factory.dart
@@ -869,6 +869,28 @@
parameters,
body);
+ static MethodDeclaration methodDeclaration4(
+ {bool external: false,
+ Keyword modifier,
+ TypeName returnType,
+ Keyword property,
+ bool operator: false,
+ String name,
+ FormalParameterList parameters,
+ FunctionBody body}) =>
+ new MethodDeclaration(
+ null,
+ null,
+ external ? TokenFactory.tokenFromKeyword(Keyword.EXTERNAL) : null,
+ modifier == null ? null : TokenFactory.tokenFromKeyword(modifier),
+ returnType,
+ property == null ? null : TokenFactory.tokenFromKeyword(property),
+ operator ? TokenFactory.tokenFromKeyword(Keyword.OPERATOR) : null,
+ identifier3(name),
+ null,
+ parameters,
+ body);
+
static MethodInvocation methodInvocation(Expression target, String methodName,
[List<Expression> arguments,
TokenType operator = TokenType.PERIOD]) =>
diff --git a/pkg/analyzer/lib/src/generated/utilities_general.dart b/pkg/analyzer/lib/src/generated/utilities_general.dart
index e0600dc..b9dca93 100644
--- a/pkg/analyzer/lib/src/generated/utilities_general.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_general.dart
@@ -145,7 +145,7 @@
* Make this the current tag for the isolate, run [f], and restore the
* previous tag. Returns the result of invoking [f].
*/
- makeCurrentWhile(f());
+ dynamic/*=E*/ makeCurrentWhile/*<E>*/(dynamic/*=E*/ f());
/**
* Reset the total time tracked by all [PerformanceTag]s to zero.
@@ -206,7 +206,7 @@
return previous;
}
- makeCurrentWhile(f()) {
+ dynamic/*=E*/ makeCurrentWhile/*<E>*/(dynamic/*=E*/ f()) {
PerformanceTag prevTag = makeCurrent();
try {
return f();
diff --git a/pkg/analyzer/lib/src/plugin/options_plugin.dart b/pkg/analyzer/lib/src/plugin/options_plugin.dart
index 6fba649..9a4fc01 100644
--- a/pkg/analyzer/lib/src/plugin/options_plugin.dart
+++ b/pkg/analyzer/lib/src/plugin/options_plugin.dart
@@ -34,11 +34,13 @@
/// All contributed options processors.
List<OptionsProcessor> get optionsProcessors =>
- optionsProcessorExtensionPoint?.extensions ?? const [];
+ optionsProcessorExtensionPoint?.extensions as List<OptionsProcessor> ??
+ const <OptionsProcessor>[];
/// All contributed options validators.
List<OptionsValidator> get optionsValidators =>
- optionsValidatorExtensionPoint?.extensions ?? const [];
+ optionsValidatorExtensionPoint?.extensions as List<OptionsValidator> ??
+ const <OptionsValidator>[];
@override
String get uniqueIdentifier => UNIQUE_IDENTIFIER;
diff --git a/pkg/analyzer/lib/src/services/lint.dart b/pkg/analyzer/lib/src/services/lint.dart
index 3eea1b7..3b36457 100644
--- a/pkg/analyzer/lib/src/services/lint.dart
+++ b/pkg/analyzer/lib/src/services/lint.dart
@@ -25,7 +25,8 @@
/// Return lints associated with this [context], or an empty list if there are
/// none.
List<Linter> getLints(AnalysisContext context) =>
- context.getConfigurationData(CONFIGURED_LINTS_KEY) ?? _noLints;
+ context.getConfigurationData(CONFIGURED_LINTS_KEY) as List<Linter> ??
+ _noLints;
/// Associate these [lints] with the given [context].
void setLints(AnalysisContext context, List<Linter> lints) {
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index bf4a78a..e8f16bf 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -11,6 +11,19 @@
import 'idl.dart' as idl;
import 'dart:convert' as convert;
+class _CacheSourceKindReader extends fb.Reader<idl.CacheSourceKind> {
+ const _CacheSourceKindReader() : super();
+
+ @override
+ int get size => 1;
+
+ @override
+ idl.CacheSourceKind read(fb.BufferPointer bp) {
+ int index = const fb.Uint8Reader().read(bp);
+ return index < idl.CacheSourceKind.values.length ? idl.CacheSourceKind.values[index] : idl.CacheSourceKind.library;
+ }
+}
+
class _IndexNameKindReader extends fb.Reader<idl.IndexNameKind> {
const _IndexNameKindReader() : super();
@@ -115,6 +128,174 @@
}
}
+class CacheSourceContentBuilder extends Object with _CacheSourceContentMixin implements idl.CacheSourceContent {
+ bool _finished = false;
+
+ List<String> _exportedUris;
+ List<String> _importedUris;
+ idl.CacheSourceKind _kind;
+ List<String> _partUris;
+
+ @override
+ List<String> get exportedUris => _exportedUris ??= <String>[];
+
+ /**
+ * The list of exported URIs, e.g. `dart:core`, or `foo/bar.dart`,
+ * or `package:foo/bar.dart`. Empty if [kind] is [CacheSourceKind.part].
+ */
+ void set exportedUris(List<String> _value) {
+ assert(!_finished);
+ _exportedUris = _value;
+ }
+
+ @override
+ List<String> get importedUris => _importedUris ??= <String>[];
+
+ /**
+ * The list of explicitly imported URIs, e.g. `dart:core`, or `foo/bar.dart`,
+ * or `package:foo/bar.dart`. Empty if [kind] is [CacheSourceKind.part].
+ */
+ void set importedUris(List<String> _value) {
+ assert(!_finished);
+ _importedUris = _value;
+ }
+
+ @override
+ idl.CacheSourceKind get kind => _kind ??= idl.CacheSourceKind.library;
+
+ /**
+ * The kind of the source.
+ */
+ void set kind(idl.CacheSourceKind _value) {
+ assert(!_finished);
+ _kind = _value;
+ }
+
+ @override
+ List<String> get partUris => _partUris ??= <String>[];
+
+ /**
+ * The list of part URIs, e.g. `foo/bar.dart`. Empty if [kind] is
+ * [CacheSourceKind.part].
+ */
+ void set partUris(List<String> _value) {
+ assert(!_finished);
+ _partUris = _value;
+ }
+
+ CacheSourceContentBuilder({List<String> exportedUris, List<String> importedUris, idl.CacheSourceKind kind, List<String> partUris})
+ : _exportedUris = exportedUris,
+ _importedUris = importedUris,
+ _kind = kind,
+ _partUris = partUris;
+
+ List<int> toBuffer() {
+ fb.Builder fbBuilder = new fb.Builder();
+ return fbBuilder.finish(finish(fbBuilder), "CaSS");
+ }
+
+ fb.Offset finish(fb.Builder fbBuilder) {
+ assert(!_finished);
+ _finished = true;
+ fb.Offset offset_exportedUris;
+ fb.Offset offset_importedUris;
+ fb.Offset offset_partUris;
+ if (!(_exportedUris == null || _exportedUris.isEmpty)) {
+ offset_exportedUris = fbBuilder.writeList(_exportedUris.map((b) => fbBuilder.writeString(b)).toList());
+ }
+ if (!(_importedUris == null || _importedUris.isEmpty)) {
+ offset_importedUris = fbBuilder.writeList(_importedUris.map((b) => fbBuilder.writeString(b)).toList());
+ }
+ if (!(_partUris == null || _partUris.isEmpty)) {
+ offset_partUris = fbBuilder.writeList(_partUris.map((b) => fbBuilder.writeString(b)).toList());
+ }
+ fbBuilder.startTable();
+ if (offset_exportedUris != null) {
+ fbBuilder.addOffset(2, offset_exportedUris);
+ }
+ if (offset_importedUris != null) {
+ fbBuilder.addOffset(1, offset_importedUris);
+ }
+ if (_kind != null && _kind != idl.CacheSourceKind.library) {
+ fbBuilder.addUint8(0, _kind.index);
+ }
+ if (offset_partUris != null) {
+ fbBuilder.addOffset(3, offset_partUris);
+ }
+ return fbBuilder.endTable();
+ }
+}
+
+idl.CacheSourceContent readCacheSourceContent(List<int> buffer) {
+ fb.BufferPointer rootRef = new fb.BufferPointer.fromBytes(buffer);
+ return const _CacheSourceContentReader().read(rootRef);
+}
+
+class _CacheSourceContentReader extends fb.TableReader<_CacheSourceContentImpl> {
+ const _CacheSourceContentReader();
+
+ @override
+ _CacheSourceContentImpl createObject(fb.BufferPointer bp) => new _CacheSourceContentImpl(bp);
+}
+
+class _CacheSourceContentImpl extends Object with _CacheSourceContentMixin implements idl.CacheSourceContent {
+ final fb.BufferPointer _bp;
+
+ _CacheSourceContentImpl(this._bp);
+
+ List<String> _exportedUris;
+ List<String> _importedUris;
+ idl.CacheSourceKind _kind;
+ List<String> _partUris;
+
+ @override
+ List<String> get exportedUris {
+ _exportedUris ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 2, const <String>[]);
+ return _exportedUris;
+ }
+
+ @override
+ List<String> get importedUris {
+ _importedUris ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 1, const <String>[]);
+ return _importedUris;
+ }
+
+ @override
+ idl.CacheSourceKind get kind {
+ _kind ??= const _CacheSourceKindReader().vTableGet(_bp, 0, idl.CacheSourceKind.library);
+ return _kind;
+ }
+
+ @override
+ List<String> get partUris {
+ _partUris ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bp, 3, const <String>[]);
+ return _partUris;
+ }
+}
+
+abstract class _CacheSourceContentMixin implements idl.CacheSourceContent {
+ @override
+ Map<String, Object> toJson() {
+ Map<String, Object> _result = <String, Object>{};
+ if (exportedUris.isNotEmpty) _result["exportedUris"] = exportedUris;
+ if (importedUris.isNotEmpty) _result["importedUris"] = importedUris;
+ if (kind != idl.CacheSourceKind.library) _result["kind"] = kind.toString().split('.')[1];
+ if (partUris.isNotEmpty) _result["partUris"] = partUris;
+ return _result;
+ }
+
+ @override
+ Map<String, Object> toMap() => {
+ "exportedUris": exportedUris,
+ "importedUris": importedUris,
+ "kind": kind,
+ "partUris": partUris,
+ };
+
+ @override
+ String toString() => convert.JSON.encode(toJson());
+}
+
class CodeRangeBuilder extends Object with _CodeRangeMixin implements idl.CodeRange {
bool _finished = false;
@@ -1905,10 +2086,10 @@
List<int> _usedElementLengths;
List<int> _usedElementOffsets;
List<int> _usedElements;
+ List<bool> _usedNameIsQualifiedFlags;
List<idl.IndexRelationKind> _usedNameKinds;
List<int> _usedNameOffsets;
List<int> _usedNames;
- List<bool> _usedNameIsQualifiedFlags;
@override
List<idl.IndexNameKind> get definedNameKinds => _definedNameKinds ??= <idl.IndexNameKind>[];
@@ -2025,6 +2206,18 @@
}
@override
+ List<bool> get usedNameIsQualifiedFlags => _usedNameIsQualifiedFlags ??= <bool>[];
+
+ /**
+ * Each item of this list is the `true` if the corresponding name usage
+ * is qualified with some prefix.
+ */
+ void set usedNameIsQualifiedFlags(List<bool> _value) {
+ assert(!_finished);
+ _usedNameIsQualifiedFlags = _value;
+ }
+
+ @override
List<idl.IndexRelationKind> get usedNameKinds => _usedNameKinds ??= <idl.IndexRelationKind>[];
/**
@@ -2062,19 +2255,7 @@
_usedNames = _value;
}
- @override
- List<bool> get usedNameIsQualifiedFlags => _usedNameIsQualifiedFlags ??= <bool>[];
-
- /**
- * Each item of this list is the `true` if the corresponding name usage
- * is qualified with some prefix.
- */
- void set usedNameIsQualifiedFlags(List<bool> _value) {
- assert(!_finished);
- _usedNameIsQualifiedFlags = _value;
- }
-
- UnitIndexBuilder({List<idl.IndexNameKind> definedNameKinds, List<int> definedNameOffsets, List<int> definedNames, int unit, List<bool> usedElementIsQualifiedFlags, List<idl.IndexRelationKind> usedElementKinds, List<int> usedElementLengths, List<int> usedElementOffsets, List<int> usedElements, List<idl.IndexRelationKind> usedNameKinds, List<int> usedNameOffsets, List<int> usedNames, List<bool> usedNameIsQualifiedFlags})
+ UnitIndexBuilder({List<idl.IndexNameKind> definedNameKinds, List<int> definedNameOffsets, List<int> definedNames, int unit, List<bool> usedElementIsQualifiedFlags, List<idl.IndexRelationKind> usedElementKinds, List<int> usedElementLengths, List<int> usedElementOffsets, List<int> usedElements, List<bool> usedNameIsQualifiedFlags, List<idl.IndexRelationKind> usedNameKinds, List<int> usedNameOffsets, List<int> usedNames})
: _definedNameKinds = definedNameKinds,
_definedNameOffsets = definedNameOffsets,
_definedNames = definedNames,
@@ -2084,10 +2265,10 @@
_usedElementLengths = usedElementLengths,
_usedElementOffsets = usedElementOffsets,
_usedElements = usedElements,
+ _usedNameIsQualifiedFlags = usedNameIsQualifiedFlags,
_usedNameKinds = usedNameKinds,
_usedNameOffsets = usedNameOffsets,
- _usedNames = usedNames,
- _usedNameIsQualifiedFlags = usedNameIsQualifiedFlags;
+ _usedNames = usedNames;
fb.Offset finish(fb.Builder fbBuilder) {
assert(!_finished);
@@ -2100,10 +2281,10 @@
fb.Offset offset_usedElementLengths;
fb.Offset offset_usedElementOffsets;
fb.Offset offset_usedElements;
+ fb.Offset offset_usedNameIsQualifiedFlags;
fb.Offset offset_usedNameKinds;
fb.Offset offset_usedNameOffsets;
fb.Offset offset_usedNames;
- fb.Offset offset_usedNameIsQualifiedFlags;
if (!(_definedNameKinds == null || _definedNameKinds.isEmpty)) {
offset_definedNameKinds = fbBuilder.writeListUint8(_definedNameKinds.map((b) => b.index).toList());
}
@@ -2128,6 +2309,9 @@
if (!(_usedElements == null || _usedElements.isEmpty)) {
offset_usedElements = fbBuilder.writeListUint32(_usedElements);
}
+ if (!(_usedNameIsQualifiedFlags == null || _usedNameIsQualifiedFlags.isEmpty)) {
+ offset_usedNameIsQualifiedFlags = fbBuilder.writeListBool(_usedNameIsQualifiedFlags);
+ }
if (!(_usedNameKinds == null || _usedNameKinds.isEmpty)) {
offset_usedNameKinds = fbBuilder.writeListUint8(_usedNameKinds.map((b) => b.index).toList());
}
@@ -2137,9 +2321,6 @@
if (!(_usedNames == null || _usedNames.isEmpty)) {
offset_usedNames = fbBuilder.writeListUint32(_usedNames);
}
- if (!(_usedNameIsQualifiedFlags == null || _usedNameIsQualifiedFlags.isEmpty)) {
- offset_usedNameIsQualifiedFlags = fbBuilder.writeListBool(_usedNameIsQualifiedFlags);
- }
fbBuilder.startTable();
if (offset_definedNameKinds != null) {
fbBuilder.addOffset(6, offset_definedNameKinds);
@@ -2168,6 +2349,9 @@
if (offset_usedElements != null) {
fbBuilder.addOffset(3, offset_usedElements);
}
+ if (offset_usedNameIsQualifiedFlags != null) {
+ fbBuilder.addOffset(12, offset_usedNameIsQualifiedFlags);
+ }
if (offset_usedNameKinds != null) {
fbBuilder.addOffset(10, offset_usedNameKinds);
}
@@ -2177,9 +2361,6 @@
if (offset_usedNames != null) {
fbBuilder.addOffset(8, offset_usedNames);
}
- if (offset_usedNameIsQualifiedFlags != null) {
- fbBuilder.addOffset(12, offset_usedNameIsQualifiedFlags);
- }
return fbBuilder.endTable();
}
}
@@ -2205,10 +2386,10 @@
List<int> _usedElementLengths;
List<int> _usedElementOffsets;
List<int> _usedElements;
+ List<bool> _usedNameIsQualifiedFlags;
List<idl.IndexRelationKind> _usedNameKinds;
List<int> _usedNameOffsets;
List<int> _usedNames;
- List<bool> _usedNameIsQualifiedFlags;
@override
List<idl.IndexNameKind> get definedNameKinds {
@@ -2265,6 +2446,12 @@
}
@override
+ List<bool> get usedNameIsQualifiedFlags {
+ _usedNameIsQualifiedFlags ??= const fb.BoolListReader().vTableGet(_bp, 12, const <bool>[]);
+ return _usedNameIsQualifiedFlags;
+ }
+
+ @override
List<idl.IndexRelationKind> get usedNameKinds {
_usedNameKinds ??= const fb.ListReader<idl.IndexRelationKind>(const _IndexRelationKindReader()).vTableGet(_bp, 10, const <idl.IndexRelationKind>[]);
return _usedNameKinds;
@@ -2281,12 +2468,6 @@
_usedNames ??= const fb.Uint32ListReader().vTableGet(_bp, 8, const <int>[]);
return _usedNames;
}
-
- @override
- List<bool> get usedNameIsQualifiedFlags {
- _usedNameIsQualifiedFlags ??= const fb.BoolListReader().vTableGet(_bp, 12, const <bool>[]);
- return _usedNameIsQualifiedFlags;
- }
}
abstract class _UnitIndexMixin implements idl.UnitIndex {
@@ -2302,10 +2483,10 @@
if (usedElementLengths.isNotEmpty) _result["usedElementLengths"] = usedElementLengths;
if (usedElementOffsets.isNotEmpty) _result["usedElementOffsets"] = usedElementOffsets;
if (usedElements.isNotEmpty) _result["usedElements"] = usedElements;
+ if (usedNameIsQualifiedFlags.isNotEmpty) _result["usedNameIsQualifiedFlags"] = usedNameIsQualifiedFlags;
if (usedNameKinds.isNotEmpty) _result["usedNameKinds"] = usedNameKinds.map((_value) => _value.toString().split('.')[1]).toList();
if (usedNameOffsets.isNotEmpty) _result["usedNameOffsets"] = usedNameOffsets;
if (usedNames.isNotEmpty) _result["usedNames"] = usedNames;
- if (usedNameIsQualifiedFlags.isNotEmpty) _result["usedNameIsQualifiedFlags"] = usedNameIsQualifiedFlags;
return _result;
}
@@ -2320,10 +2501,10 @@
"usedElementLengths": usedElementLengths,
"usedElementOffsets": usedElementOffsets,
"usedElements": usedElements,
+ "usedNameIsQualifiedFlags": usedNameIsQualifiedFlags,
"usedNameKinds": usedNameKinds,
"usedNameOffsets": usedNameOffsets,
"usedNames": usedNames,
- "usedNameIsQualifiedFlags": usedNameIsQualifiedFlags,
};
@override
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index a653a52..9c6cf83 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -7,6 +7,15 @@
/**
+ * Kind of a source in the cache.
+ */
+enum CacheSourceKind : byte {
+ library,
+
+ part
+}
+
+/**
* Enum used to indicate the kind of a name in index.
*/
enum IndexNameKind : byte {
@@ -106,6 +115,11 @@
constructor,
/**
+ * The synthetic field element.
+ */
+ field,
+
+ /**
* The synthetic getter of a property introducing element.
*/
getter,
@@ -560,6 +574,34 @@
}
/**
+ * Information about a source that depends only on its content.
+ */
+table CacheSourceContent {
+ /**
+ * The list of exported URIs, e.g. `dart:core`, or `foo/bar.dart`,
+ * or `package:foo/bar.dart`. Empty if [kind] is [CacheSourceKind.part].
+ */
+ exportedUris:[string] (id: 2);
+
+ /**
+ * The list of explicitly imported URIs, e.g. `dart:core`, or `foo/bar.dart`,
+ * or `package:foo/bar.dart`. Empty if [kind] is [CacheSourceKind.part].
+ */
+ importedUris:[string] (id: 1);
+
+ /**
+ * The kind of the source.
+ */
+ kind:CacheSourceKind (id: 0);
+
+ /**
+ * The list of part URIs, e.g. `foo/bar.dart`. Empty if [kind] is
+ * [CacheSourceKind.part].
+ */
+ partUris:[string] (id: 3);
+}
+
+/**
* Information about an element code range.
*/
table CodeRange {
@@ -1017,6 +1059,12 @@
usedElements:[uint] (id: 3);
/**
+ * Each item of this list is the `true` if the corresponding name usage
+ * is qualified with some prefix.
+ */
+ usedNameIsQualifiedFlags:[ubyte] (id: 12);
+
+ /**
* Each item of this list is the kind of the name usage.
*/
usedNameKinds:[IndexRelationKind] (id: 10);
@@ -1033,12 +1081,6 @@
* quickly find name uses in this [UnitIndex].
*/
usedNames:[uint] (id: 8);
-
- /**
- * Each item of this list is the `true` if the corresponding name usage
- * is qualified with some prefix.
- */
- usedNameIsQualifiedFlags:[ubyte] (id: 12);
}
/**
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index f15ba03..4453056 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -53,6 +53,47 @@
const informative = null;
/**
+ * Information about a source that depends only on its content.
+ */
+@TopLevel('CaSS')
+abstract class CacheSourceContent extends base.SummaryClass {
+ factory CacheSourceContent.fromBuffer(List<int> buffer) =>
+ generated.readCacheSourceContent(buffer);
+
+ /**
+ * The list of exported URIs, e.g. `dart:core`, or `foo/bar.dart`,
+ * or `package:foo/bar.dart`. Empty if [kind] is [CacheSourceKind.part].
+ */
+ @Id(2)
+ List<String> get exportedUris;
+
+ /**
+ * The list of explicitly imported URIs, e.g. `dart:core`, or `foo/bar.dart`,
+ * or `package:foo/bar.dart`. Empty if [kind] is [CacheSourceKind.part].
+ */
+ @Id(1)
+ List<String> get importedUris;
+
+ /**
+ * The kind of the source.
+ */
+ @Id(0)
+ CacheSourceKind get kind;
+
+ /**
+ * The list of part URIs, e.g. `foo/bar.dart`. Empty if [kind] is
+ * [CacheSourceKind.part].
+ */
+ @Id(3)
+ List<String> get partUris;
+}
+
+/**
+ * Kind of a source in the cache.
+ */
+enum CacheSourceKind { library, part }
+
+/**
* Information about an element code range.
*/
abstract class CodeRange extends base.SummaryClass {
@@ -265,6 +306,11 @@
constructor,
/**
+ * The synthetic field element.
+ */
+ field,
+
+ /**
* The synthetic getter of a property introducing element.
*/
getter,
@@ -773,6 +819,13 @@
List<int> get usedElements;
/**
+ * Each item of this list is the `true` if the corresponding name usage
+ * is qualified with some prefix.
+ */
+ @Id(12)
+ List<bool> get usedNameIsQualifiedFlags;
+
+ /**
* Each item of this list is the kind of the name usage.
*/
@Id(10)
@@ -792,13 +845,6 @@
*/
@Id(8)
List<int> get usedNames;
-
- /**
- * Each item of this list is the `true` if the corresponding name usage
- * is qualified with some prefix.
- */
- @Id(12)
- List<bool> get usedNameIsQualifiedFlags;
}
/**
diff --git a/pkg/analyzer/lib/src/summary/incremental_cache.dart b/pkg/analyzer/lib/src/summary/incremental_cache.dart
new file mode 100644
index 0000000..9900773
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary/incremental_cache.dart
@@ -0,0 +1,420 @@
+// 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:convert' show UTF8;
+import 'dart:core' hide Resource;
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/generated/engine.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/summarize_elements.dart';
+import 'package:crypto/crypto.dart';
+
+/**
+ * Storage for cache data.
+ */
+abstract class CacheStorage {
+ /**
+ * Return bytes for the given [key], `null` if [key] is not in the storage.
+ */
+ List<int> get(String key);
+
+ /**
+ * Associate the [key] with the given [bytes].
+ *
+ * If the [key] was already in the storage, its associated value is changed.
+ * Otherwise the key-value pair is added to the storage.
+ *
+ * It is not guaranteed that data will always be accessible using [get], in
+ * some implementations association may silently fail or become inaccessible
+ * after some time.
+ */
+ void put(String key, List<int> bytes);
+}
+
+/**
+ * A [Folder] based implementation of [CacheStorage].
+ */
+class FolderCacheStorage implements CacheStorage {
+ /**
+ * The folder to read and write files.
+ */
+ final Folder folder;
+
+ /**
+ * To ensure that operations of writing files are atomic we create a temporary
+ * file with this name in the [folder] and then rename it once we are
+ * done writing.
+ */
+ final String tempFileName;
+
+ FolderCacheStorage(this.folder, this.tempFileName);
+
+ @override
+ List<int> get(String key) {
+ Resource file = folder.getChild(key);
+ if (file is File) {
+ try {
+ return file.readAsBytesSync();
+ } on FileSystemException {}
+ }
+ return null;
+ }
+
+ @override
+ void put(String key, List<int> bytes) {
+ String absPath = folder.getChild(key).path;
+ File tempFile = folder.getChild(tempFileName);
+ tempFile.writeAsBytesSync(bytes);
+ try {
+ tempFile.renameSync(absPath);
+ } catch (e) {}
+ }
+}
+
+/**
+ * Cache of information to support incremental analysis.
+ *
+ * Note that currently this class is not intended for interactive use.
+ */
+class IncrementalCache {
+ /**
+ * The storage for the cache data.
+ */
+ final CacheStorage storage;
+
+ /**
+ * The context in which this cache is used.
+ */
+ final AnalysisContext context;
+
+ /**
+ * Opaque data that reflects the current configuration, such as the [context]
+ * options, and is mixed into the hashes.
+ */
+ final List<int> configSalt;
+
+ final Map<Source, CacheSourceContent> _sourceContentMap =
+ <Source, CacheSourceContent>{};
+ final Map<Source, List<Source>> _libraryClosureMap = <Source, List<Source>>{};
+ final Map<Source, List<int>> _libraryClosureHashMap = <Source, List<int>>{};
+ final Map<Source, List<int>> _sourceContentHashMap = <Source, List<int>>{};
+
+ /**
+ * Mapping from a library closure key to its [PackageBundle].
+ */
+ final Map<String, PackageBundle> _bundleMap = <String, PackageBundle>{};
+
+ final Map<String, Source> _absoluteUriMap = <String, Source>{};
+
+ IncrementalCache(this.storage, this.context, this.configSalt);
+
+ /**
+ * Clear internal caches so that we read from file system again.
+ */
+ void clearInternalCaches() {
+ _sourceContentMap.clear();
+ _libraryClosureMap.clear();
+ _sourceContentHashMap.clear();
+ _bundleMap.clear();
+ }
+
+ /**
+ * Return all summaries that are required to provide results about the library
+ * with the given [librarySource] from its summary. It includes all of the
+ * bundles in the import/export closure of the library. If any of the
+ * bundles are not in the cache, then `null` is returned. If any of the
+ * [LibraryBundleWithId]s were already returned as a part of the closure of
+ * another library, they are still included - it is up to the client to
+ * decide whether a bundle should be used or not, but it is easy to do
+ * using [LibraryBundleWithId.id].
+ */
+ List<LibraryBundleWithId> getLibraryClosureBundles(Source librarySource) {
+ try {
+ List<Source> closureSources = _getLibraryClosure(librarySource);
+ List<LibraryBundleWithId> closureBundles = <LibraryBundleWithId>[];
+ for (Source source in closureSources) {
+ if (source.isInSystemLibrary) {
+ continue;
+ }
+ if (getSourceKind(source) == SourceKind.PART) {
+ continue;
+ }
+ String key = _getLibraryBundleKey(source);
+ PackageBundle bundle = _getLibraryBundle(key);
+ if (bundle == null) {
+ return null;
+ }
+ closureBundles.add(new LibraryBundleWithId(source, key, bundle));
+ }
+ return closureBundles;
+ } catch (e) {
+ return null;
+ }
+ }
+
+ /**
+ * Return the kind of the given [source], or `null` if unknown.
+ */
+ SourceKind getSourceKind(Source source) {
+ try {
+ CacheSourceContent contentSource = _getCacheSourceContent(source);
+ if (contentSource != null) {
+ if (contentSource.kind == CacheSourceKind.library) {
+ return SourceKind.LIBRARY;
+ }
+ if (contentSource.kind == CacheSourceKind.part) {
+ return SourceKind.PART;
+ }
+ }
+ } catch (e) {}
+ return null;
+ }
+
+ /**
+ * Write information about the [libraryElement] into the cache.
+ */
+ void putLibrary(LibraryElement libraryElement) {
+ _writeCacheSourceContents(libraryElement);
+ String key = _getLibraryBundleKey(libraryElement.source);
+ PackageBundleAssembler assembler = new PackageBundleAssembler();
+ assembler.serializeLibraryElement(libraryElement);
+ List<int> bytes = assembler.assemble().toBuffer();
+ storage.put(key, bytes);
+ }
+
+ /**
+ * Fill the whole source closure of the library with the given
+ * [librarySource]. It includes defining units and parts of the library and
+ * all its directly or indirectly imported or exported libraries.
+ */
+ void _appendLibraryClosure(Set<Source> closure, Source librarySource) {
+ if (closure.add(librarySource)) {
+ CacheSourceContent contentSource = _getCacheSourceContent(librarySource);
+ if (contentSource == null) {
+ throw new StateError('No structure for $librarySource');
+ }
+ // Append parts.
+ for (String partUri in contentSource.partUris) {
+ Source partSource = _resolveUri(librarySource, partUri);
+ if (partSource == null) {
+ throw new StateError('Unable to resolve $partUri in $librarySource');
+ }
+ closure.add(partSource);
+ }
+ // Append imports and exports.
+ void appendLibrarySources(String refUri) {
+ Source refSource = _resolveUri(librarySource, refUri);
+ if (refSource == null) {
+ throw new StateError('Unable to resolve $refUri in $librarySource');
+ }
+ _appendLibraryClosure(closure, refSource);
+ }
+ contentSource.importedUris.forEach(appendLibrarySources);
+ contentSource.exportedUris.forEach(appendLibrarySources);
+ }
+ }
+
+ /**
+ * Get the content based information about the given [source], maybe `null`
+ * if the information is not in the cache.
+ */
+ CacheSourceContent _getCacheSourceContent(Source source) {
+ CacheSourceContent content = _sourceContentMap[source];
+ if (content == null) {
+ String key = _getCacheSourceContentKey(source);
+ List<int> bytes = storage.get(key);
+ if (bytes == null) {
+ return null;
+ }
+ content = new CacheSourceContent.fromBuffer(bytes);
+ _sourceContentMap[source] = content;
+ }
+ return content;
+ }
+
+ /**
+ * Return the key of the content based [source] information.
+ */
+ String _getCacheSourceContentKey(Source source) {
+ List<int> hash = _getSourceContentHash(source);
+ String hashStr = CryptoUtils.bytesToHex(hash);
+ return '$hashStr.content';
+ }
+
+ /**
+ * Get the bundle for the given key.
+ */
+ PackageBundle _getLibraryBundle(String key) {
+ PackageBundle bundle = _bundleMap[key];
+ if (bundle == null) {
+ List<int> bytes = storage.get(key);
+ if (bytes == null) {
+ return null;
+ }
+ bundle = new PackageBundle.fromBuffer(bytes);
+ _bundleMap[key] = bundle;
+ }
+ return bundle;
+ }
+
+ /**
+ * Return the key of the bundle of the [librarySource].
+ */
+ String _getLibraryBundleKey(Source librarySource) {
+ List<int> hash = _getLibraryClosureHash(librarySource);
+ String hashStr = CryptoUtils.bytesToHex(hash);
+ return '$hashStr.summary';
+ }
+
+ /**
+ * Return the whole source closure of the library with the given
+ * [librarySource]. It includes defining units and parts of the library and
+ * of all its directly or indirectly imported or exported libraries.
+ */
+ List<Source> _getLibraryClosure(Source librarySource) {
+ return _libraryClosureMap.putIfAbsent(librarySource, () {
+ Set<Source> closure = new Set<Source>();
+ _appendLibraryClosure(closure, librarySource);
+ return closure.toList();
+ });
+ }
+
+ /**
+ * Return the [context]-specific hash of the closure of the library with
+ * the given [librarySource].
+ */
+ List<int> _getLibraryClosureHash(Source librarySource) {
+ return _libraryClosureHashMap.putIfAbsent(librarySource, () {
+ List<Source> closure = _getLibraryClosure(librarySource);
+ MD5 md5 = new MD5();
+ for (Source source in closure) {
+ List<int> sourceHash = _getSourceContentHash(source);
+ md5.add(sourceHash);
+ }
+ md5.add(configSalt);
+ return md5.close();
+ });
+ }
+
+ /**
+ * Compute a hash of the given [source] contents.
+ */
+ List<int> _getSourceContentHash(Source source) {
+ return _sourceContentHashMap.putIfAbsent(source, () {
+ String sourceText = source.contents.data;
+ List<int> sourceBytes = UTF8.encode(sourceText);
+ return (new MD5()..add(sourceBytes)).close();
+ });
+ }
+
+ /**
+ * Return a source representing the URI that results from resolving the given
+ * (possibly relative) [containedUri] against the URI associated with the
+ * [containingSource], whether or not the resulting source exists, or `null`
+ * if either the [containedUri] is invalid or if it cannot be resolved against
+ * the [containingSource]'s URI.
+ */
+ Source _resolveUri(Source containingSource, String containedUri) {
+ // Cache absolute URIs.
+ if (containedUri.startsWith('dart:') ||
+ containedUri.startsWith('package:')) {
+ return _absoluteUriMap.putIfAbsent(containedUri, () {
+ return context.sourceFactory.resolveUri(containingSource, containedUri);
+ });
+ }
+ // Resolve relative URIs without caching.
+ return context.sourceFactory.resolveUri(containingSource, containedUri);
+ }
+
+ /**
+ * Write the content based information about the given [source].
+ */
+ void _writeCacheSourceContent(Source source, CacheSourceContentBuilder b) {
+ String key = _getCacheSourceContentKey(source);
+ List<int> bytes = b.toBuffer();
+ storage.put(key, bytes);
+ // Put into the cache to avoid reading it later.
+ _sourceContentMap[source] = new CacheSourceContent.fromBuffer(bytes);
+ }
+
+ /**
+ * Write [CacheSourceContent] for every unit of the given [library] and its
+ * direct and indirect imports/exports.
+ */
+ void _writeCacheSourceContents(LibraryElement library,
+ [Set<LibraryElement> writtenLibraries]) {
+ Source librarySource = library.source;
+ // Do nothing if already cached.
+ if (_sourceContentMap.containsKey(librarySource)) {
+ return;
+ }
+ // Stop recursion cycle.
+ writtenLibraries ??= new Set<LibraryElement>();
+ if (!writtenLibraries.add(library)) {
+ return;
+ }
+ // Write parts.
+ List<String> partUris = <String>[];
+ for (CompilationUnitElement part in library.parts) {
+ partUris.add(part.uri);
+ Source partSource = part.source;
+ if (context.getKindOf(partSource) == SourceKind.PART) {
+ _writeCacheSourceContent(partSource,
+ new CacheSourceContentBuilder(kind: CacheSourceKind.part));
+ }
+ }
+ // Write imports.
+ List<String> importUris = <String>[];
+ for (ImportElement element in library.imports) {
+ String uri = element.uri;
+ if (uri != null) {
+ importUris.add(uri);
+ _writeCacheSourceContents(element.importedLibrary, writtenLibraries);
+ }
+ }
+ // Write exports.
+ List<String> exportUris = <String>[];
+ for (ExportElement element in library.exports) {
+ String uri = element.uri;
+ if (uri != null) {
+ exportUris.add(uri);
+ _writeCacheSourceContents(element.exportedLibrary, writtenLibraries);
+ }
+ }
+ // Write the library.
+ _writeCacheSourceContent(
+ librarySource,
+ new CacheSourceContentBuilder(
+ kind: CacheSourceKind.library,
+ importedUris: importUris,
+ exportedUris: exportUris,
+ partUris: partUris));
+ }
+}
+
+/**
+ * The bundle for a source in the context.
+ */
+class LibraryBundleWithId {
+ /**
+ * The source of the library this bundle is for.
+ */
+ final Source source;
+
+ /**
+ * The unique ID of the [bundle] of the [source] in the context.
+ */
+ final String id;
+
+ /**
+ * The payload bundle.
+ */
+ final PackageBundle bundle;
+
+ LibraryBundleWithId(this.source, this.id, this.bundle);
+}
diff --git a/pkg/analyzer/lib/src/summary/index_unit.dart b/pkg/analyzer/lib/src/summary/index_unit.dart
index a29c88b..b239d5c 100644
--- a/pkg/analyzer/lib/src/summary/index_unit.dart
+++ b/pkg/analyzer/lib/src/summary/index_unit.dart
@@ -207,6 +207,11 @@
} else if (element is FunctionElement && element.name == 'loadLibrary') {
kind = IndexSyntheticElementKind.loadLibrary;
element = element.library;
+ } else if (element is FieldElement) {
+ FieldElement field = element;
+ kind = IndexSyntheticElementKind.field;
+ element = field.getter;
+ element ??= field.setter;
} else if (element is PropertyAccessorElement) {
PropertyAccessorElement accessor = element;
Element enclosing = element.enclosingElement;
@@ -504,6 +509,9 @@
}
@override
+ visitLibraryIdentifier(LibraryIdentifier node) {}
+
+ @override
visitMethodInvocation(MethodInvocation node) {
SimpleIdentifier name = node.methodName;
Element element = name.bestElement;
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index cd6c52e..6ebb3f4 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -93,6 +93,18 @@
if (target.library == null || !target.library.isInSystemLibrary) {
return false;
}
+ if (result == CREATED_RESOLVED_UNIT1 ||
+ result == CREATED_RESOLVED_UNIT2 ||
+ result == CREATED_RESOLVED_UNIT3 ||
+ result == CREATED_RESOLVED_UNIT4 ||
+ result == CREATED_RESOLVED_UNIT5 ||
+ result == CREATED_RESOLVED_UNIT6 ||
+ result == CREATED_RESOLVED_UNIT7 ||
+ result == CREATED_RESOLVED_UNIT8 ||
+ result == CREATED_RESOLVED_UNIT9) {
+ entry.setValue(result, true, TargetedResult.EMPTY_LIST);
+ return true;
+ }
if (result == COMPILATION_UNIT_ELEMENT) {
String libraryUri = target.library.uri.toString();
String unitUri = target.unit.uri.toString();
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 408db9e..b366e13 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -2231,7 +2231,7 @@
@override
DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
- ResultDescriptor descriptor) {
+ ResultDescriptor descriptor, Object value) {
if (hasDirectiveChange) {
return DeltaResult.INVALIDATE;
}
@@ -2259,6 +2259,10 @@
return DeltaResult.KEEP_CONTINUE;
}
if (BuildLibraryElementTask.DESCRIPTOR.results.contains(descriptor)) {
+ // Invalidate cached results.
+ if (value is LibraryElementImpl) {
+ value.exportNamespace = null;
+ }
return DeltaResult.KEEP_CONTINUE;
}
return DeltaResult.INVALIDATE;
@@ -2815,13 +2819,16 @@
//
List<AstVisitor> visitors = <AstVisitor>[];
+ bool timeVisits = analysisOptions.enableTiming;
List<Linter> linters = getLints(context);
for (Linter linter in linters) {
AstVisitor visitor = linter.getVisitor();
if (visitor != null) {
linter.reporter = errorReporter;
- visitors
- .add(new TimedAstVisitor(visitor, lintRegistry.getTimer(linter)));
+ if (timeVisits) {
+ visitor = new TimedAstVisitor(visitor, lintRegistry.getTimer(linter));
+ }
+ visitors.add(visitor);
}
}
diff --git a/pkg/analyzer/lib/src/task/driver.dart b/pkg/analyzer/lib/src/task/driver.dart
index cb4da98..7ff8287 100644
--- a/pkg/analyzer/lib/src/task/driver.dart
+++ b/pkg/analyzer/lib/src/task/driver.dart
@@ -165,6 +165,9 @@
state == CacheState.IN_PROCESS) {
return null;
}
+ if (context.aboutToComputeResult(entry, result)) {
+ return null;
+ }
TaskDescriptor taskDescriptor = taskManager.findTask(target, result);
if (taskDescriptor == null) {
return null;
diff --git a/pkg/analyzer/lib/src/task/inputs.dart b/pkg/analyzer/lib/src/task/inputs.dart
index 1134a58..7553e15 100644
--- a/pkg/analyzer/lib/src/task/inputs.dart
+++ b/pkg/analyzer/lib/src/task/inputs.dart
@@ -89,29 +89,27 @@
*/
abstract class ListTaskInputMixin<E> implements ListTaskInput<E> {
@override
- ListTaskInput /*<V>*/ toFlattenListOf /*<V>*/ (
- ListResultDescriptor /*<V>*/ subListResult) {
- return new ListToFlattenListTaskInput<E, dynamic /*=V*/ >(
+ ListTaskInput/*<V>*/ toFlattenListOf/*<V>*/(
+ ListResultDescriptor/*<V>*/ subListResult) {
+ return new ListToFlattenListTaskInput<E, dynamic/*=V*/ >(
this, subListResult.of as dynamic);
}
- ListTaskInput /*<V>*/ toList /*<V>*/ (
- UnaryFunction<E, dynamic /*<=V>*/ > mapper) {
- return new ListToListTaskInput<E, dynamic /*=V*/ >(this, mapper);
+ ListTaskInput/*<V>*/ toList/*<V>*/(UnaryFunction<E, dynamic/*=V*/ > mapper) {
+ return new ListToListTaskInput<E, dynamic/*=V*/ >(this, mapper);
}
- ListTaskInput /*<V>*/ toListOf /*<V>*/ (
- ResultDescriptor /*<V>*/ valueResult) {
+ ListTaskInput/*<V>*/ toListOf/*<V>*/(ResultDescriptor/*<V>*/ valueResult) {
return (this as ListTaskInput<AnalysisTarget>).toList(valueResult.of);
}
- MapTaskInput<E, dynamic /*=V*/ > toMap /*<V>*/ (
- UnaryFunction<E, dynamic /*<=V>*/ > mapper) {
- return new ListToMapTaskInput<E, dynamic /*=V*/ >(this, mapper);
+ MapTaskInput<E, dynamic/*=V*/ > toMap/*<V>*/(
+ UnaryFunction<E, dynamic/*=V*/ > mapper) {
+ return new ListToMapTaskInput<E, dynamic/*=V*/ >(this, mapper);
}
- MapTaskInput<AnalysisTarget, dynamic /*=V*/ > toMapOf /*<V>*/ (
- ResultDescriptor /*<V>*/ valueResult) {
+ MapTaskInput<AnalysisTarget, dynamic/*=V*/ > toMapOf/*<V>*/(
+ ResultDescriptor/*<V>*/ valueResult) {
return (this as ListTaskInputImpl<AnalysisTarget>).toMap(valueResult.of);
}
}
@@ -279,10 +277,10 @@
* A mixin-ready implementation of [MapTaskInput].
*/
abstract class MapTaskInputMixin<K, V> implements MapTaskInput<K, V> {
- TaskInput<List /*<E>*/ > toFlattenList /*<E>*/ (
- BinaryFunction<K, dynamic /*element of V*/, dynamic /*<=E>*/ > mapper) {
+ TaskInput<List/*<E>*/ > toFlattenList/*<E>*/(
+ BinaryFunction<K, dynamic /*element of V*/, dynamic/*=E*/ > mapper) {
return new MapToFlattenListTaskInput<K, dynamic /*element of V*/,
- dynamic /*=E*/ >(this as MapTaskInput<K, List /*<element of V>*/ >, mapper);
+ dynamic/*=E*/ >(this as MapTaskInput<K, List /*element of V*/ >, mapper);
}
}
@@ -441,23 +439,22 @@
new ObjectToListTaskInputBuilder<E>(this);
@override
- ListTaskInput /*<V>*/ toFlattenListOf /*<V>*/ (
- ListResultDescriptor /*<V>*/ subListResult) {
- return new ListToFlattenListTaskInput<E, dynamic /*=V*/ >(
+ ListTaskInput/*<V>*/ toFlattenListOf/*<V>*/(
+ ListResultDescriptor/*<V>*/ subListResult) {
+ return new ListToFlattenListTaskInput<E, dynamic/*=V*/ >(
this, subListResult.of as dynamic);
}
@override
- ListTaskInput /*<V>*/ toListOf /*<V>*/ (
- ResultDescriptor /*<V>*/ valueResult) {
- return new ListToListTaskInput<E, dynamic /*=V*/ >(
+ ListTaskInput/*<V>*/ toListOf/*<V>*/(ResultDescriptor/*<V>*/ valueResult) {
+ return new ListToListTaskInput<E, dynamic/*=V*/ >(
this, valueResult.of as dynamic);
}
@override
- MapTaskInput<AnalysisTarget, dynamic /*=V*/ > toMapOf /*<V>*/ (
- ResultDescriptor /*<V>*/ valueResult) {
- return new ListToMapTaskInput<AnalysisTarget, dynamic /*=V*/ >(
+ MapTaskInput<AnalysisTarget, dynamic/*=V*/ > toMapOf/*<V>*/(
+ ResultDescriptor/*<V>*/ valueResult) {
+ return new ListToMapTaskInput<AnalysisTarget, dynamic/*=V*/ >(
this as dynamic, valueResult.of);
}
}
@@ -696,7 +693,7 @@
abstract class TaskInputImpl<V> implements TaskInput<V> {
@override
- ListTaskInput /*<E>*/ mappedToList /*<E>*/ (List /*<E>*/ mapper(V value)) {
+ ListTaskInput/*<E>*/ mappedToList/*<E>*/(List/*<E>*/ mapper(V value)) {
return new ObjectToListTaskInput(this, mapper);
}
}
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 53164a3..79da6a8 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -327,19 +327,43 @@
@override
void visitForEachStatement(ForEachStatement node) {
- // Check that the expression is an Iterable.
- var expr = node.iterable;
- var iterableType = node.awaitKeyword != null
- ? typeProvider.streamType
- : typeProvider.iterableType;
var loopVariable = node.identifier != null
? node.identifier
: node.loopVariable?.identifier;
+
+ // Safely handle malformed statements.
if (loopVariable != null) {
- var iteratorType = loopVariable.staticType;
- var checkedType = iterableType.instantiate([iteratorType]);
- checkAssignment(expr, checkedType);
+ // Find the element type of the sequence.
+ var sequenceInterface = node.awaitKeyword != null
+ ? typeProvider.streamType
+ : typeProvider.iterableType;
+ var iterableType = _getStaticType(node.iterable);
+ var elementType =
+ rules.mostSpecificTypeArgument(iterableType, sequenceInterface);
+
+ // If the sequence is not an Iterable (or Stream for await for) but is a
+ // supertype of it, do an implicit downcast to Iterable<dynamic>. Then
+ // we'll do a separate cast of the dynamic element to the variable's type.
+ if (elementType == null) {
+ var sequenceType = sequenceInterface.instantiate([DynamicTypeImpl.instance]);
+
+ if (rules.isSubtypeOf(sequenceType, iterableType)) {
+ _recordMessage(DownCast.create(
+ rules, node.iterable, iterableType, sequenceType));
+ elementType = DynamicTypeImpl.instance;
+ }
+ }
+
+ // If the sequence doesn't implement the interface at all, [ErrorVerifier]
+ // will report the error, so ignore it here.
+ if (elementType != null) {
+ // Insert a cast from the sequence's element type to the loop variable's
+ // if needed.
+ _checkDowncast(loopVariable, _getStaticType(loopVariable),
+ from: elementType);
+ }
}
+
node.visitChildren(this);
}
@@ -595,8 +619,8 @@
rules.isSubtypeOf(lhsType, rhsType)) {
// This is also slightly different from spec, but allows us to keep
// compound operators in the int += num and num += dynamic cases.
- staticInfo = DownCast.create(
- rules, expr.rightHandSide, rhsType, lhsType);
+ staticInfo =
+ DownCast.create(rules, expr.rightHandSide, rhsType, lhsType);
rhsType = lhsType;
} else {
staticInfo = new StaticTypeError(rules, expr, lhsType);
@@ -663,18 +687,22 @@
}
}
- /// Records a [DownCast] of [expr] to [toT], if there is one.
+ /// Records a [DownCast] of [expr] from [from] to [to], if there is one.
///
- /// If [expr] does not require a downcast because it is not related to [toT]
+ /// If [from] is omitted, uses the static type of [expr].
+ ///
+ /// If [expr] does not require a downcast because it is not related to [to]
/// or is already a subtype of it, does nothing.
- void _checkDowncast(Expression expr, DartType toT) {
- DartType fromT = _getStaticType(expr);
+ void _checkDowncast(Expression expr, DartType to, {DartType from}) {
+ if (from == null) {
+ from = _getStaticType(expr);
+ }
// We can use anything as void.
- if (toT.isVoid) return;
+ if (to.isVoid) return;
// fromT <: toT, no coercion needed.
- if (rules.isSubtypeOf(fromT, toT)) return;
+ if (rules.isSubtypeOf(from, to)) return;
// TODO(vsm): We can get rid of the second clause if we disallow
// all sideways casts - see TODO below.
@@ -682,14 +710,14 @@
// Note: a function type is never assignable to a class per the Dart
// spec - even if it has a compatible call method. We disallow as
// well for consistency.
- if ((fromT is FunctionType && rules.getCallMethodType(toT) != null) ||
- (toT is FunctionType && rules.getCallMethodType(fromT) != null)) {
+ if ((from is FunctionType && rules.getCallMethodType(to) != null) ||
+ (to is FunctionType && rules.getCallMethodType(from) != null)) {
return;
}
// Downcast if toT <: fromT
- if (rules.isSubtypeOf(toT, fromT)) {
- _recordMessage(DownCast.create(rules, expr, fromT, toT));
+ if (rules.isSubtypeOf(to, from)) {
+ _recordMessage(DownCast.create(rules, expr, from, to));
return;
}
@@ -703,8 +731,8 @@
// are likely to succeed. The canonical example is List<dynamic> and
// Iterable<T> for some concrete T (e.g. Object). These are unrelated
// in the restricted system, but List<dynamic> <: Iterable<T> in dart.
- if (fromT.isAssignableTo(toT)) {
- _recordMessage(DownCast.create(rules, expr, fromT, toT));
+ if (from.isAssignableTo(to)) {
+ _recordMessage(DownCast.create(rules, expr, from, to));
}
}
diff --git a/pkg/analyzer/lib/src/task/strong/info.dart b/pkg/analyzer/lib/src/task/strong/info.dart
index 2aaa4c6..b8f09ea 100644
--- a/pkg/analyzer/lib/src/task/strong/info.dart
+++ b/pkg/analyzer/lib/src/task/strong/info.dart
@@ -67,24 +67,24 @@
DownCast._internal(
TypeSystem rules, Expression expression, this._fromType, this._toType)
- : super(rules, expression) {
- assert(_toType != baseType &&
- _fromType == baseType &&
- (baseType.isDynamic ||
- // Call methods make the following non-redundant.
- _toType.isSubtypeOf(baseType) ||
- baseType.isAssignableTo(_toType)));
- }
+ : super(rules, expression);
@override
List<Object> get arguments => [baseType, convertedType];
+ /// The type being cast from.
+ ///
+ /// This is usually the static type of the associated expression, but may not
+ /// be if the cast is attached to a variable in a for-in loop.
+ @override
+ DartType get baseType => _fromType;
+
DartType get convertedType => _toType;
@override
String get message => 'Unsound implicit cast from {0} to {1}';
- // Factory to create correct DownCast variant.
+ /// Factory to create correct DownCast variant.
static StaticInfo create(StrongTypeSystemImpl rules, Expression expression,
DartType fromType, DartType toType) {
// toT <:_R fromT => to <: fromT
diff --git a/pkg/analyzer/lib/task/model.dart b/pkg/analyzer/lib/task/model.dart
index 8144f17..b80cca2 100644
--- a/pkg/analyzer/lib/task/model.dart
+++ b/pkg/analyzer/lib/task/model.dart
@@ -381,7 +381,7 @@
* Return a task input that can be used to compute a list whose elements are
* the result of passing the elements of this input to the [mapper] function.
*/
- ListTaskInput/*<V>*/ toList/*<V>*/(UnaryFunction<E, dynamic/*<=V>*/ > mapper);
+ ListTaskInput/*<V>*/ toList/*<V>*/(UnaryFunction<E, dynamic/*=V*/ > mapper);
/**
* Return a task input that can be used to compute a list whose elements are
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 15dc4c0..e902923 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 0.27.3-alpha.2
+version: 0.27.3-alpha.4
author: Dart Team <misc@dartlang.org>
description: Static analyzer for Dart.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
diff --git a/pkg/analyzer/test/context/declared_variables_test.dart b/pkg/analyzer/test/context/declared_variables_test.dart
new file mode 100644
index 0000000..3a33003
--- /dev/null
+++ b/pkg/analyzer/test/context/declared_variables_test.dart
@@ -0,0 +1,116 @@
+// 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 analyzer.test.context.declared_variables_test;
+
+import 'package:analyzer/context/declared_variables.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:unittest/unittest.dart';
+
+import '../generated/test_support.dart';
+import '../reflective_tests.dart';
+import '../utils.dart';
+
+main() {
+ initializeTestEnvironment();
+ runReflectiveTests(DeclaredVariablesTest);
+}
+
+@reflectiveTest
+class DeclaredVariablesTest extends EngineTestCase {
+ void test_getBool_false() {
+ TestTypeProvider typeProvider = new TestTypeProvider();
+ String variableName = "var";
+ DeclaredVariables variables = new DeclaredVariables();
+ variables.define(variableName, "false");
+ DartObject object = variables.getBool(typeProvider, variableName);
+ expect(object, isNotNull);
+ expect(object.toBoolValue(), false);
+ }
+
+ void test_getBool_invalid() {
+ TestTypeProvider typeProvider = new TestTypeProvider();
+ String variableName = "var";
+ DeclaredVariables variables = new DeclaredVariables();
+ variables.define(variableName, "not true");
+ _assertNullDartObject(
+ typeProvider, variables.getBool(typeProvider, variableName));
+ }
+
+ void test_getBool_true() {
+ TestTypeProvider typeProvider = new TestTypeProvider();
+ String variableName = "var";
+ DeclaredVariables variables = new DeclaredVariables();
+ variables.define(variableName, "true");
+ DartObject object = variables.getBool(typeProvider, variableName);
+ expect(object, isNotNull);
+ expect(object.toBoolValue(), true);
+ }
+
+ void test_getBool_undefined() {
+ TestTypeProvider typeProvider = new TestTypeProvider();
+ String variableName = "var";
+ DeclaredVariables variables = new DeclaredVariables();
+ _assertUnknownDartObject(
+ typeProvider.boolType, variables.getBool(typeProvider, variableName));
+ }
+
+ void test_getInt_invalid() {
+ TestTypeProvider typeProvider = new TestTypeProvider();
+ String variableName = "var";
+ DeclaredVariables variables = new DeclaredVariables();
+ variables.define(variableName, "four score and seven years");
+ _assertNullDartObject(
+ typeProvider, variables.getInt(typeProvider, variableName));
+ }
+
+ void test_getInt_undefined() {
+ TestTypeProvider typeProvider = new TestTypeProvider();
+ String variableName = "var";
+ DeclaredVariables variables = new DeclaredVariables();
+ _assertUnknownDartObject(
+ typeProvider.intType, variables.getInt(typeProvider, variableName));
+ }
+
+ void test_getInt_valid() {
+ TestTypeProvider typeProvider = new TestTypeProvider();
+ String variableName = "var";
+ DeclaredVariables variables = new DeclaredVariables();
+ variables.define(variableName, "23");
+ DartObject object = variables.getInt(typeProvider, variableName);
+ expect(object, isNotNull);
+ expect(object.toIntValue(), 23);
+ }
+
+ void test_getString_defined() {
+ TestTypeProvider typeProvider = new TestTypeProvider();
+ String variableName = "var";
+ String value = "value";
+ DeclaredVariables variables = new DeclaredVariables();
+ variables.define(variableName, value);
+ DartObject object = variables.getString(typeProvider, variableName);
+ expect(object, isNotNull);
+ expect(object.toStringValue(), value);
+ }
+
+ void test_getString_undefined() {
+ TestTypeProvider typeProvider = new TestTypeProvider();
+ String variableName = "var";
+ DeclaredVariables variables = new DeclaredVariables();
+ _assertUnknownDartObject(typeProvider.stringType,
+ variables.getString(typeProvider, variableName));
+ }
+
+ void _assertNullDartObject(TestTypeProvider typeProvider, DartObject result) {
+ expect(result.type, typeProvider.nullType);
+ }
+
+ void _assertUnknownDartObject(
+ ParameterizedType expectedType, DartObject result) {
+ expect((result as DartObjectImpl).isUnknown, isTrue);
+ expect(result.type, expectedType);
+ }
+}
diff --git a/pkg/analyzer/test/context/test_all.dart b/pkg/analyzer/test/context/test_all.dart
new file mode 100644
index 0000000..b5387ba
--- /dev/null
+++ b/pkg/analyzer/test/context/test_all.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.context.test_all;
+
+import 'package:unittest/unittest.dart';
+
+import '../utils.dart';
+import 'declared_variables_test.dart' as declared_variables;
+
+/// Utility for manually running all tests.
+main() {
+ initializeTestEnvironment();
+ group('context tests', () {
+ declared_variables.main();
+ });
+}
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index 7be2b72..6cd446d 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -23,6 +23,7 @@
runReflectiveTests(ConstructorDeclarationTest);
runReflectiveTests(FieldFormalParameterTest);
runReflectiveTests(IndexExpressionTest);
+ runReflectiveTests(MethodDeclarationTest);
runReflectiveTests(NodeListTest);
runReflectiveTests(SimpleIdentifierTest);
runReflectiveTests(SimpleStringLiteralTest);
@@ -305,6 +306,44 @@
}
@reflectiveTest
+class MethodDeclarationTest extends EngineTestCase {
+ void test_firstTokenAfterCommentAndMetadata_external() {
+ MethodDeclaration declaration =
+ AstFactory.methodDeclaration4(external: true, name: 'm');
+ expect(declaration.firstTokenAfterCommentAndMetadata,
+ declaration.externalKeyword);
+ }
+
+ void test_firstTokenAfterCommentAndMetadata_external_getter() {
+ MethodDeclaration declaration = AstFactory.methodDeclaration4(
+ external: true, property: Keyword.GET, name: 'm');
+ expect(declaration.firstTokenAfterCommentAndMetadata,
+ declaration.externalKeyword);
+ }
+
+ void test_firstTokenAfterCommentAndMetadata_external_operator() {
+ MethodDeclaration declaration = AstFactory.methodDeclaration4(
+ external: true, operator: true, name: 'm');
+ expect(declaration.firstTokenAfterCommentAndMetadata,
+ declaration.externalKeyword);
+ }
+
+ void test_firstTokenAfterCommentAndMetadata_getter() {
+ MethodDeclaration declaration =
+ AstFactory.methodDeclaration4(property: Keyword.GET, name: 'm');
+ expect(declaration.firstTokenAfterCommentAndMetadata,
+ declaration.propertyKeyword);
+ }
+
+ void test_firstTokenAfterCommentAndMetadata_operator() {
+ MethodDeclaration declaration =
+ AstFactory.methodDeclaration4(operator: true, name: 'm');
+ expect(declaration.firstTokenAfterCommentAndMetadata,
+ declaration.operatorKeyword);
+ }
+}
+
+@reflectiveTest
class NodeListTest extends EngineTestCase {
void test_add() {
AstNode parent = AstFactory.argumentList();
diff --git a/pkg/analyzer/test/enum_test.dart b/pkg/analyzer/test/enum_test.dart
index 0ba5a98..93f8a4f 100644
--- a/pkg/analyzer/test/enum_test.dart
+++ b/pkg/analyzer/test/enum_test.dart
@@ -136,7 +136,7 @@
if (_ignoreGetters.contains(name)) {
return;
}
- C value = reflectedClass.getField(symbol).reflectee;
+ C value = reflectedClass.getField(symbol).reflectee as C;
result[name] = value;
});
return result;
@@ -148,7 +148,7 @@
*/
void check_explicit_values() {
ClassMirror reflectedClass = reflectClass(C);
- List<C> values = reflectedClass.getField(#values).reflectee;
+ List<C> values = reflectedClass.getField(#values).reflectee as List<C>;
Map<C, int> reverseMap = <C, int>{};
// Check that "values" is a list of values of type C, with no duplicates.
diff --git a/pkg/analyzer/test/file_system/memory_file_system_test.dart b/pkg/analyzer/test/file_system/memory_file_system_test.dart
index d00d2d4..759362b 100644
--- a/pkg/analyzer/test/file_system/memory_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/memory_file_system_test.dart
@@ -123,6 +123,19 @@
expect(parent.path, equals('/foo/bar'));
}
+ void test_readAsBytesSync_doesNotExist() {
+ File file = provider.getResource('/test.bin');
+ expect(() {
+ file.readAsBytesSync();
+ }, throwsA(_isFileSystemException));
+ }
+
+ void test_readAsBytesSync_exists() {
+ List<int> bytes = <int>[1, 2, 3, 4, 5];
+ File file = provider.newFileWithBytes('/file.bin', bytes);
+ expect(file.readAsBytesSync(), bytes);
+ }
+
void test_readAsStringSync_doesNotExist() {
File file = provider.getResource('/test.txt');
expect(() {
@@ -135,6 +148,43 @@
expect(file.readAsStringSync(), 'abc');
}
+ void test_renameSync_newDoesNotExist() {
+ String oldPath = '/foo/bar/file.txt';
+ String newPath = '/foo/bar/new-file.txt';
+ File file = provider.newFile(oldPath, 'text');
+ File newFile = file.renameSync(newPath);
+ expect(file.path, oldPath);
+ expect(file.exists, isFalse);
+ expect(newFile.path, newPath);
+ expect(newFile.exists, isTrue);
+ expect(newFile.readAsStringSync(), 'text');
+ }
+
+ void test_renameSync_newExists_file() {
+ String oldPath = '/foo/bar/file.txt';
+ String newPath = '/foo/bar/new-file.txt';
+ File file = provider.newFile(oldPath, 'text');
+ provider.newFile(newPath, 'new text');
+ File newFile = file.renameSync(newPath);
+ expect(file.path, oldPath);
+ expect(file.exists, isFalse);
+ expect(newFile.path, newPath);
+ expect(newFile.exists, isTrue);
+ expect(newFile.readAsStringSync(), 'text');
+ }
+
+ void test_renameSync_newExists_folder() {
+ String oldPath = '/foo/bar/file.txt';
+ String newPath = '/foo/bar/baz';
+ File file = provider.newFile(oldPath, 'text');
+ provider.newFolder(newPath);
+ expect(() {
+ file.renameSync(newPath);
+ }, throwsA(_isFileSystemException));
+ expect(file.path, oldPath);
+ expect(file.exists, isTrue);
+ }
+
void test_shortName() {
File file = provider.getResource('/foo/bar/file.txt');
expect(file.shortName, 'file.txt');
@@ -144,6 +194,23 @@
File file = provider.getResource('/foo/bar/file.txt');
expect(file.toString(), '/foo/bar/file.txt');
}
+
+ void test_writeAsBytesSync_existing() {
+ File file = provider.newFileWithBytes('/foo/file.bin', <int>[1, 2]);
+ expect(file.readAsBytesSync(), <int>[1, 2]);
+ // write new bytes
+ file.writeAsBytesSync(<int>[10, 20]);
+ expect(file.readAsBytesSync(), <int>[10, 20]);
+ }
+
+ void test_writeAsBytesSync_new() {
+ File file = provider.getFile('/foo/file.bin');
+ expect(file.exists, false);
+ // write new bytes
+ file.writeAsBytesSync(<int>[10, 20]);
+ expect(file.exists, true);
+ expect(file.readAsBytesSync(), <int>[10, 20]);
+ }
}
@reflectiveTest
@@ -467,14 +534,24 @@
expect(source.contents.data, equals('contents 2'));
}
- void test_newFolder_aleadyExists_asFile() {
+ void test_newFileWithBytes() {
+ String path = '/my/file';
+ List<int> bytes = <int>[1, 2, 3, 4, 5];
+ provider.newFileWithBytes(path, bytes);
+ File file = provider.getResource(path);
+ expect(file, isNotNull);
+ expect(file.exists, isTrue);
+ expect(file.readAsBytesSync(), bytes);
+ }
+
+ void test_newFolder_alreadyExists_asFile() {
provider.newFile('/my/file', 'qwerty');
expect(() {
provider.newFolder('/my/file');
}, throwsA(new isInstanceOf<ArgumentError>()));
}
- void test_newFolder_aleadyExists_asFolder() {
+ void test_newFolder_alreadyExists_asFolder() {
Folder folder = provider.newFolder('/my/folder');
Folder newFolder = provider.newFolder('/my/folder');
expect(newFolder, folder);
diff --git a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
index 850bbcf..5bf3256 100644
--- a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
+++ b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
@@ -20,9 +20,11 @@
main() {
initializeTestEnvironment();
- runReflectiveTests(PhysicalResourceProviderTest);
- runReflectiveTests(FileTest);
- runReflectiveTests(FolderTest);
+ if (!new bool.fromEnvironment('skipPhysicalResourceProviderTests')) {
+ runReflectiveTests(PhysicalResourceProviderTest);
+ runReflectiveTests(FileTest);
+ runReflectiveTests(FolderTest);
+ }
}
var _isFile = new isInstanceOf<File>();
@@ -104,6 +106,19 @@
expect(parent.path, equals(tempPath));
}
+ void test_readAsBytesSync_doesNotExist() {
+ File file = PhysicalResourceProvider.INSTANCE.getResource('/test.bin');
+ expect(() {
+ file.readAsBytesSync();
+ }, throwsA(_isFileSystemException));
+ }
+
+ void test_readAsBytesSync_exists() {
+ List<int> bytes = <int>[1, 2, 3, 4, 5];
+ new io.File(path).writeAsBytesSync(bytes);
+ expect(file.readAsBytesSync(), bytes);
+ }
+
void test_readAsStringSync_doesNotExist() {
File file = PhysicalResourceProvider.INSTANCE.getResource(path);
expect(() {
@@ -117,6 +132,46 @@
expect(file.readAsStringSync(), 'abc');
}
+ void test_renameSync_newDoesNotExist() {
+ String oldPath = '$tempPath/file.txt';
+ String newPath = '$tempPath/new-file.txt';
+ new io.File(oldPath).writeAsStringSync('text');
+ File file = PhysicalResourceProvider.INSTANCE.getResource(oldPath);
+ File newFile = file.renameSync(newPath);
+ expect(file.path, oldPath);
+ expect(file.exists, isFalse);
+ expect(newFile.path, newPath);
+ expect(newFile.exists, isTrue);
+ expect(newFile.readAsStringSync(), 'text');
+ }
+
+ test_renameSync_newExists_file() async {
+ String oldPath = '$tempPath/file.txt';
+ String newPath = '$tempPath/new-file.txt';
+ new io.File(oldPath).writeAsStringSync('text');
+ new io.File(newPath).writeAsStringSync('new text');
+ File file = PhysicalResourceProvider.INSTANCE.getResource(oldPath);
+ File newFile = file.renameSync(newPath);
+ expect(file.path, oldPath);
+ expect(file.exists, isFalse);
+ expect(newFile.path, newPath);
+ expect(newFile.exists, isTrue);
+ expect(newFile.readAsStringSync(), 'text');
+ }
+
+ void test_renameSync_newExists_folder() {
+ String oldPath = '$tempPath/file.txt';
+ String newPath = '$tempPath/foo';
+ new io.File(oldPath).writeAsStringSync('text');
+ new io.Directory(newPath).createSync();
+ File file = PhysicalResourceProvider.INSTANCE.getResource(oldPath);
+ expect(() {
+ file.renameSync(newPath);
+ }, throwsA(_isFileSystemException));
+ expect(file.path, oldPath);
+ expect(file.exists, isTrue);
+ }
+
void test_shortName() {
expect(file.shortName, 'file.txt');
}
@@ -124,6 +179,14 @@
void test_toString() {
expect(file.toString(), path);
}
+
+ void test_writeAsBytesSync() {
+ new io.File(path).writeAsBytesSync(<int>[1, 2]);
+ expect(file.readAsBytesSync(), <int>[1, 2]);
+ // write new bytes
+ file.writeAsBytesSync(<int>[10, 20]);
+ expect(file.readAsBytesSync(), <int>[10, 20]);
+ }
}
@reflectiveTest
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index dc95b3a..ac35f08 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -5,96 +5,21 @@
library analyzer.test.constant_test;
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/error.dart';
-import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
-import 'package:analyzer/src/generated/testing/ast_factory.dart';
-import 'package:analyzer/src/generated/testing/element_factory.dart';
-import 'package:analyzer/src/generated/testing/test_type_provider.dart';
-import 'package:analyzer/src/generated/utilities_collection.dart';
-import 'package:analyzer/src/task/dart.dart';
-import 'package:path/path.dart';
import 'package:unittest/unittest.dart';
import '../reflective_tests.dart';
import '../utils.dart';
-import 'engine_test.dart';
import 'resolver_test_case.dart';
import 'test_support.dart';
main() {
initializeTestEnvironment();
runReflectiveTests(ConstantEvaluatorTest);
- runReflectiveTests(ConstantFinderTest);
- runReflectiveTests(ConstantValueComputerTest);
- runReflectiveTests(ConstantVisitorTest);
- runReflectiveTests(DartObjectImplTest);
- runReflectiveTests(DeclaredVariablesTest);
- runReflectiveTests(ReferenceFinderTest);
-}
-
-const int LONG_MAX_VALUE = 0x7fffffffffffffff;
-
-/**
- * Implementation of [ConstantEvaluationValidator] used during unit tests;
- * verifies that any nodes referenced during constant evaluation are present in
- * the dependency graph.
- */
-class ConstantEvaluationValidator_ForTest
- implements ConstantEvaluationValidator {
- final InternalAnalysisContext context;
- ConstantValueComputer computer;
- ConstantEvaluationTarget _nodeBeingEvaluated;
-
- ConstantEvaluationValidator_ForTest(this.context);
-
- @override
- void beforeComputeValue(ConstantEvaluationTarget constant) {
- _nodeBeingEvaluated = constant;
- }
-
- @override
- void beforeGetConstantInitializers(ConstructorElement constructor) =>
- _checkPathTo(constructor);
-
- @override
- void beforeGetEvaluationResult(ConstantEvaluationTarget constant) =>
- _checkPathTo(constant);
-
- @override
- void beforeGetFieldEvaluationResult(FieldElementImpl field) =>
- _checkPathTo(field);
-
- @override
- void beforeGetParameterDefault(ParameterElement parameter) =>
- _checkPathTo(parameter);
-
- void _checkPathTo(ConstantEvaluationTarget target) {
- if (computer.referenceGraph.containsPath(_nodeBeingEvaluated, target)) {
- return; // pass
- }
- // print a nice error message on failure
- StringBuffer out = new StringBuffer();
- out.writeln("missing path in constant dependency graph");
- out.writeln("from $_nodeBeingEvaluated to $target");
- for (var s in context.analysisCache.sources) {
- String text = context.getContents(s).data;
- if (text != "") {
- out.writeln('''
-=== ${s.shortName}
-$text''');
- }
- }
- fail(out.toString());
- }
}
@reflectiveTest
@@ -482,4060 +407,3 @@
return evaluator.evaluate(variables[0].initializer);
}
}
-
-@reflectiveTest
-class ConstantFinderTest {
- AstNode _node;
- TypeProvider _typeProvider;
- AnalysisContext _context;
- Source _source;
-
- void setUp() {
- _typeProvider = new TestTypeProvider();
- _context = new _TestAnalysisContext();
- _source = new TestSource();
- }
-
- /**
- * Test an annotation that consists solely of an identifier (and hence
- * represents a reference to a compile-time constant variable).
- */
- void test_visitAnnotation_constantVariable() {
- CompilationUnitElement compilationUnitElement =
- ElementFactory.compilationUnit('/test.dart', _source)..source = _source;
- ElementFactory.library(_context, 'L').definingCompilationUnit =
- compilationUnitElement;
- ElementAnnotationImpl elementAnnotation =
- new ElementAnnotationImpl(compilationUnitElement);
- _node = elementAnnotation.annotationAst = AstFactory.annotation(
- AstFactory.identifier3('x'))..elementAnnotation = elementAnnotation;
- expect(_findAnnotations(), contains(_node));
- }
-
- /**
- * Test an annotation that represents the invocation of a constant
- * constructor.
- */
- void test_visitAnnotation_invocation() {
- CompilationUnitElement compilationUnitElement =
- ElementFactory.compilationUnit('/test.dart', _source)..source = _source;
- ElementFactory.library(_context, 'L').definingCompilationUnit =
- compilationUnitElement;
- ElementAnnotationImpl elementAnnotation =
- new ElementAnnotationImpl(compilationUnitElement);
- _node = elementAnnotation.annotationAst = AstFactory.annotation2(
- AstFactory.identifier3('A'), null, AstFactory.argumentList())
- ..elementAnnotation = elementAnnotation;
- expect(_findAnnotations(), contains(_node));
- }
-
- void test_visitAnnotation_partOf() {
- // Analyzer ignores annotations on "part of" directives.
- Annotation annotation = AstFactory.annotation2(
- AstFactory.identifier3('A'), null, AstFactory.argumentList());
- _node = AstFactory.partOfDirective2(
- <Annotation>[annotation], AstFactory.libraryIdentifier2(<String>['L']));
- expect(_findConstants(), isEmpty);
- }
-
- void test_visitConstructorDeclaration_const() {
- ConstructorElement element = _setupConstructorDeclaration("A", true);
- expect(_findConstants(), contains(element));
- }
-
- void test_visitConstructorDeclaration_nonConst() {
- _setupConstructorDeclaration("A", false);
- expect(_findConstants(), isEmpty);
- }
-
- void test_visitVariableDeclaration_const() {
- VariableElement element = _setupVariableDeclaration("v", true, true);
- expect(_findConstants(), contains(element));
- }
-
- void test_visitVariableDeclaration_final_inClass() {
- _setupFieldDeclaration('C', 'f', Keyword.FINAL);
- expect(_findConstants(), isEmpty);
- }
-
- void test_visitVariableDeclaration_final_inClassWithConstConstructor() {
- VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
- hasConstConstructor: true);
- expect(_findConstants(), contains(field.element));
- }
-
- void test_visitVariableDeclaration_final_outsideClass() {
- _setupVariableDeclaration('v', false, true, isFinal: true);
- expect(_findConstants(), isEmpty);
- }
-
- void test_visitVariableDeclaration_noInitializer() {
- _setupVariableDeclaration("v", true, false);
- expect(_findConstants(), isEmpty);
- }
-
- void test_visitVariableDeclaration_nonConst() {
- _setupVariableDeclaration("v", false, true);
- expect(_findConstants(), isEmpty);
- }
-
- void test_visitVariableDeclaration_static_const_inClass() {
- VariableDeclaration field =
- _setupFieldDeclaration('C', 'f', Keyword.CONST, isStatic: true);
- expect(_findConstants(), contains(field.element));
- }
-
- void
- test_visitVariableDeclaration_static_const_inClassWithConstConstructor() {
- VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.CONST,
- isStatic: true, hasConstConstructor: true);
- expect(_findConstants(), contains(field.element));
- }
-
- void
- test_visitVariableDeclaration_static_final_inClassWithConstConstructor() {
- VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
- isStatic: true, hasConstConstructor: true);
- expect(_findConstants(), isNot(contains(field.element)));
- }
-
- void
- test_visitVariableDeclaration_uninitialized_final_inClassWithConstConstructor() {
- VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
- isInitialized: false, hasConstConstructor: true);
- expect(_findConstants(), isNot(contains(field.element)));
- }
-
- void test_visitVariableDeclaration_uninitialized_static_const_inClass() {
- _setupFieldDeclaration('C', 'f', Keyword.CONST,
- isStatic: true, isInitialized: false);
- expect(_findConstants(), isEmpty);
- }
-
- List<Annotation> _findAnnotations() {
- Set<Annotation> annotations = new Set<Annotation>();
- for (ConstantEvaluationTarget target in _findConstants()) {
- if (target is ElementAnnotationImpl) {
- expect(target.context, same(_context));
- expect(target.source, same(_source));
- annotations.add(target.annotationAst);
- }
- }
- return new List<Annotation>.from(annotations);
- }
-
- List<ConstantEvaluationTarget> _findConstants() {
- ConstantFinder finder = new ConstantFinder(_context, _source, _source);
- _node.accept(finder);
- List<ConstantEvaluationTarget> constants = finder.constantsToCompute;
- expect(constants, isNotNull);
- return constants;
- }
-
- ConstructorElement _setupConstructorDeclaration(String name, bool isConst) {
- Keyword constKeyword = isConst ? Keyword.CONST : null;
- ConstructorDeclaration constructorDeclaration =
- AstFactory.constructorDeclaration2(
- constKeyword,
- null,
- null,
- name,
- AstFactory.formalParameterList(),
- null,
- AstFactory.blockFunctionBody2());
- ClassElement classElement = ElementFactory.classElement2(name);
- ConstructorElement element =
- ElementFactory.constructorElement(classElement, name, isConst);
- constructorDeclaration.element = element;
- _node = constructorDeclaration;
- return element;
- }
-
- VariableDeclaration _setupFieldDeclaration(
- String className, String fieldName, Keyword keyword,
- {bool isInitialized: true,
- bool isStatic: false,
- bool hasConstConstructor: false}) {
- VariableDeclaration variableDeclaration = isInitialized
- ? AstFactory.variableDeclaration2(fieldName, AstFactory.integer(0))
- : AstFactory.variableDeclaration(fieldName);
- VariableElement fieldElement = ElementFactory.fieldElement(
- fieldName,
- isStatic,
- keyword == Keyword.FINAL,
- keyword == Keyword.CONST,
- _typeProvider.intType);
- variableDeclaration.name.staticElement = fieldElement;
- FieldDeclaration fieldDeclaration = AstFactory.fieldDeclaration2(
- isStatic, keyword, <VariableDeclaration>[variableDeclaration]);
- ClassDeclaration classDeclaration =
- AstFactory.classDeclaration(null, className, null, null, null, null);
- classDeclaration.members.add(fieldDeclaration);
- _node = classDeclaration;
- ClassElementImpl classElement = ElementFactory.classElement2(className);
- classElement.fields = <FieldElement>[fieldElement];
- classDeclaration.name.staticElement = classElement;
- if (hasConstConstructor) {
- ConstructorDeclaration constructorDeclaration =
- AstFactory.constructorDeclaration2(
- Keyword.CONST,
- null,
- AstFactory.identifier3(className),
- null,
- AstFactory.formalParameterList(),
- null,
- AstFactory.blockFunctionBody2());
- classDeclaration.members.add(constructorDeclaration);
- ConstructorElement constructorElement =
- ElementFactory.constructorElement(classElement, '', true);
- constructorDeclaration.element = constructorElement;
- classElement.constructors = <ConstructorElement>[constructorElement];
- } else {
- classElement.constructors = ConstructorElement.EMPTY_LIST;
- }
- return variableDeclaration;
- }
-
- VariableElement _setupVariableDeclaration(
- String name, bool isConst, bool isInitialized,
- {isFinal: false}) {
- VariableDeclaration variableDeclaration = isInitialized
- ? AstFactory.variableDeclaration2(name, AstFactory.integer(0))
- : AstFactory.variableDeclaration(name);
- SimpleIdentifier identifier = variableDeclaration.name;
- VariableElement element = ElementFactory.localVariableElement(identifier);
- identifier.staticElement = element;
- Keyword keyword = isConst ? Keyword.CONST : isFinal ? Keyword.FINAL : null;
- AstFactory.variableDeclarationList2(keyword, [variableDeclaration]);
- _node = variableDeclaration;
- return element;
- }
-}
-
-@reflectiveTest
-class ConstantValueComputerTest extends ResolverTestCase {
- void test_annotation_constConstructor() {
- CompilationUnit compilationUnit = resolveSource(r'''
-class A {
- final int i;
- const A(this.i);
-}
-
-class C {
- @A(5)
- f() {}
-}
-''');
- EvaluationResultImpl result =
- _evaluateAnnotation(compilationUnit, "C", "f");
- Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A');
- _assertIntField(annotationFields, 'i', 5);
- }
-
- void test_annotation_constConstructor_named() {
- CompilationUnit compilationUnit = resolveSource(r'''
-class A {
- final int i;
- const A.named(this.i);
-}
-
-class C {
- @A.named(5)
- f() {}
-}
-''');
- EvaluationResultImpl result =
- _evaluateAnnotation(compilationUnit, "C", "f");
- Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A');
- _assertIntField(annotationFields, 'i', 5);
- }
-
- void test_annotation_constConstructor_noArgs() {
- // Failing to pass arguments to an annotation which is a constant
- // constructor is illegal, but shouldn't crash analysis.
- CompilationUnit compilationUnit = resolveSource(r'''
-class A {
- final int i;
- const A(this.i);
-}
-
-class C {
- @A
- f() {}
-}
-''');
- _evaluateAnnotation(compilationUnit, "C", "f");
- }
-
- void test_annotation_constConstructor_noArgs_named() {
- // Failing to pass arguments to an annotation which is a constant
- // constructor is illegal, but shouldn't crash analysis.
- CompilationUnit compilationUnit = resolveSource(r'''
-class A {
- final int i;
- const A.named(this.i);
-}
-
-class C {
- @A.named
- f() {}
-}
-''');
- _evaluateAnnotation(compilationUnit, "C", "f");
- }
-
- void test_annotation_nonConstConstructor() {
- // Calling a non-const constructor from an annotation that is illegal, but
- // shouldn't crash analysis.
- CompilationUnit compilationUnit = resolveSource(r'''
-class A {
- final int i;
- A(this.i);
-}
-
-class C {
- @A(5)
- f() {}
-}
-''');
- _evaluateAnnotation(compilationUnit, "C", "f");
- }
-
- void test_annotation_staticConst() {
- CompilationUnit compilationUnit = resolveSource(r'''
-class C {
- static const int i = 5;
-
- @i
- f() {}
-}
-''');
- EvaluationResultImpl result =
- _evaluateAnnotation(compilationUnit, "C", "f");
- expect(_assertValidInt(result), 5);
- }
-
- void test_annotation_staticConst_args() {
- // Applying arguments to an annotation that is a static const is
- // illegal, but shouldn't crash analysis.
- CompilationUnit compilationUnit = resolveSource(r'''
-class C {
- static const int i = 5;
-
- @i(1)
- f() {}
-}
-''');
- _evaluateAnnotation(compilationUnit, "C", "f");
- }
-
- void test_annotation_staticConst_otherClass() {
- CompilationUnit compilationUnit = resolveSource(r'''
-class A {
- static const int i = 5;
-}
-
-class C {
- @A.i
- f() {}
-}
-''');
- EvaluationResultImpl result =
- _evaluateAnnotation(compilationUnit, "C", "f");
- expect(_assertValidInt(result), 5);
- }
-
- void test_annotation_staticConst_otherClass_args() {
- // Applying arguments to an annotation that is a static const is
- // illegal, but shouldn't crash analysis.
- CompilationUnit compilationUnit = resolveSource(r'''
-class A {
- static const int i = 5;
-}
-
-class C {
- @A.i(1)
- f() {}
-}
-''');
- _evaluateAnnotation(compilationUnit, "C", "f");
- }
-
- void test_annotation_topLevelVariable() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const int i = 5;
-class C {
- @i
- f() {}
-}
-''');
- EvaluationResultImpl result =
- _evaluateAnnotation(compilationUnit, "C", "f");
- expect(_assertValidInt(result), 5);
- }
-
- void test_annotation_topLevelVariable_args() {
- // Applying arguments to an annotation that is a top-level variable is
- // illegal, but shouldn't crash analysis.
- CompilationUnit compilationUnit = resolveSource(r'''
-const int i = 5;
-class C {
- @i(1)
- f() {}
-}
-''');
- _evaluateAnnotation(compilationUnit, "C", "f");
- }
-
- void test_computeValues_cycle() {
- TestLogger logger = new TestLogger();
- AnalysisEngine.instance.logger = logger;
- try {
- Source source = addSource(r'''
- const int a = c;
- const int b = a;
- const int c = b;''');
- LibraryElement libraryElement = resolve2(source);
- CompilationUnit unit =
- analysisContext.resolveCompilationUnit(source, libraryElement);
- analysisContext.computeErrors(source);
- expect(unit, isNotNull);
- ConstantValueComputer computer = _makeConstantValueComputer();
- computer.add(unit, source, source);
- computer.computeValues();
- NodeList<CompilationUnitMember> members = unit.declarations;
- expect(members, hasLength(3));
- _validate(false, (members[0] as TopLevelVariableDeclaration).variables);
- _validate(false, (members[1] as TopLevelVariableDeclaration).variables);
- _validate(false, (members[2] as TopLevelVariableDeclaration).variables);
- } finally {
- AnalysisEngine.instance.logger = Logger.NULL;
- }
- }
-
- void test_computeValues_dependentVariables() {
- Source source = addSource(r'''
-const int b = a;
-const int a = 0;''');
- LibraryElement libraryElement = resolve2(source);
- CompilationUnit unit =
- analysisContext.resolveCompilationUnit(source, libraryElement);
- expect(unit, isNotNull);
- ConstantValueComputer computer = _makeConstantValueComputer();
- computer.add(unit, source, source);
- computer.computeValues();
- NodeList<CompilationUnitMember> members = unit.declarations;
- expect(members, hasLength(2));
- _validate(true, (members[0] as TopLevelVariableDeclaration).variables);
- _validate(true, (members[1] as TopLevelVariableDeclaration).variables);
- }
-
- void test_computeValues_empty() {
- ConstantValueComputer computer = _makeConstantValueComputer();
- computer.computeValues();
- }
-
- void test_computeValues_multipleSources() {
- Source librarySource = addNamedSource(
- "/lib.dart",
- r'''
-library lib;
-part 'part.dart';
-const int c = b;
-const int a = 0;''');
- Source partSource = addNamedSource(
- "/part.dart",
- r'''
-part of lib;
-const int b = a;
-const int d = c;''');
- LibraryElement libraryElement = resolve2(librarySource);
- CompilationUnit libraryUnit =
- analysisContext.resolveCompilationUnit(librarySource, libraryElement);
- expect(libraryUnit, isNotNull);
- CompilationUnit partUnit =
- analysisContext.resolveCompilationUnit(partSource, libraryElement);
- expect(partUnit, isNotNull);
- ConstantValueComputer computer = _makeConstantValueComputer();
- computer.add(libraryUnit, librarySource, librarySource);
- computer.add(partUnit, partSource, librarySource);
- computer.computeValues();
- NodeList<CompilationUnitMember> libraryMembers = libraryUnit.declarations;
- expect(libraryMembers, hasLength(2));
- _validate(
- true, (libraryMembers[0] as TopLevelVariableDeclaration).variables);
- _validate(
- true, (libraryMembers[1] as TopLevelVariableDeclaration).variables);
- NodeList<CompilationUnitMember> partMembers = libraryUnit.declarations;
- expect(partMembers, hasLength(2));
- _validate(true, (partMembers[0] as TopLevelVariableDeclaration).variables);
- _validate(true, (partMembers[1] as TopLevelVariableDeclaration).variables);
- }
-
- void test_computeValues_singleVariable() {
- Source source = addSource("const int a = 0;");
- LibraryElement libraryElement = resolve2(source);
- CompilationUnit unit =
- analysisContext.resolveCompilationUnit(source, libraryElement);
- expect(unit, isNotNull);
- ConstantValueComputer computer = _makeConstantValueComputer();
- computer.add(unit, source, source);
- computer.computeValues();
- NodeList<CompilationUnitMember> members = unit.declarations;
- expect(members, hasLength(1));
- _validate(true, (members[0] as TopLevelVariableDeclaration).variables);
- }
-
- void test_computeValues_value_depends_on_enum() {
- Source source = addSource('''
-enum E { id0, id1 }
-const E e = E.id0;
-''');
- LibraryElement libraryElement = resolve2(source);
- CompilationUnit unit =
- analysisContext.resolveCompilationUnit(source, libraryElement);
- expect(unit, isNotNull);
- ConstantValueComputer computer = _makeConstantValueComputer();
- computer.add(unit, source, source);
- computer.computeValues();
- TopLevelVariableDeclaration declaration = unit.declarations
- .firstWhere((member) => member is TopLevelVariableDeclaration);
- _validate(true, declaration.variables);
- }
-
- void test_dependencyOnConstructor() {
- // x depends on "const A()"
- _assertProperDependencies(r'''
-class A {
- const A();
-}
-const x = const A();''');
- }
-
- void test_dependencyOnConstructorArgument() {
- // "const A(x)" depends on x
- _assertProperDependencies(r'''
-class A {
- const A(this.next);
- final A next;
-}
-const A x = const A(null);
-const A y = const A(x);''');
- }
-
- void test_dependencyOnConstructorArgument_unresolvedConstructor() {
- // "const A.a(x)" depends on x even if the constructor A.a can't be found.
- _assertProperDependencies(
- r'''
-class A {
-}
-const int x = 1;
-const A y = const A.a(x);''',
- [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR]);
- }
-
- void test_dependencyOnConstructorInitializer() {
- // "const A()" depends on x
- _assertProperDependencies(r'''
-const int x = 1;
-class A {
- const A() : v = x;
- final int v;
-}''');
- }
-
- void test_dependencyOnExplicitSuperConstructor() {
- // b depends on B() depends on A()
- _assertProperDependencies(r'''
-class A {
- const A(this.x);
- final int x;
-}
-class B extends A {
- const B() : super(5);
-}
-const B b = const B();''');
- }
-
- void test_dependencyOnExplicitSuperConstructorParameters() {
- // b depends on B() depends on i
- _assertProperDependencies(r'''
-class A {
- const A(this.x);
- final int x;
-}
-class B extends A {
- const B() : super(i);
-}
-const B b = const B();
-const int i = 5;''');
- }
-
- void test_dependencyOnFactoryRedirect() {
- // a depends on A.foo() depends on A.bar()
- _assertProperDependencies(r'''
-const A a = const A.foo();
-class A {
- factory const A.foo() = A.bar;
- const A.bar();
-}''');
- }
-
- void test_dependencyOnFactoryRedirectWithTypeParams() {
- _assertProperDependencies(r'''
-class A {
- const factory A(var a) = B<int>;
-}
-
-class B<T> implements A {
- final T x;
- const B(this.x);
-}
-
-const A a = const A(10);''');
- }
-
- void test_dependencyOnImplicitSuperConstructor() {
- // b depends on B() depends on A()
- _assertProperDependencies(r'''
-class A {
- const A() : x = 5;
- final int x;
-}
-class B extends A {
- const B();
-}
-const B b = const B();''');
- }
-
- void test_dependencyOnInitializedFinal() {
- // a depends on A() depends on A.x
- _assertProperDependencies('''
-class A {
- const A();
- final int x = 1;
-}
-const A a = const A();
-''');
- }
-
- void test_dependencyOnInitializedNonStaticConst() {
- // Even though non-static consts are not allowed by the language, we need
- // to handle them for error recovery purposes.
- // a depends on A() depends on A.x
- _assertProperDependencies(
- '''
-class A {
- const A();
- const int x = 1;
-}
-const A a = const A();
-''',
- [CompileTimeErrorCode.CONST_INSTANCE_FIELD]);
- }
-
- void test_dependencyOnNonFactoryRedirect() {
- // a depends on A.foo() depends on A.bar()
- _assertProperDependencies(r'''
-const A a = const A.foo();
-class A {
- const A.foo() : this.bar();
- const A.bar();
-}''');
- }
-
- void test_dependencyOnNonFactoryRedirect_arg() {
- // a depends on A.foo() depends on b
- _assertProperDependencies(r'''
-const A a = const A.foo();
-const int b = 1;
-class A {
- const A.foo() : this.bar(b);
- const A.bar(x) : y = x;
- final int y;
-}''');
- }
-
- void test_dependencyOnNonFactoryRedirect_defaultValue() {
- // a depends on A.foo() depends on A.bar() depends on b
- _assertProperDependencies(r'''
-const A a = const A.foo();
-const int b = 1;
-class A {
- const A.foo() : this.bar();
- const A.bar([x = b]) : y = x;
- final int y;
-}''');
- }
-
- void test_dependencyOnNonFactoryRedirect_toMissing() {
- // a depends on A.foo() which depends on nothing, since A.bar() is
- // missing.
- _assertProperDependencies(
- r'''
-const A a = const A.foo();
-class A {
- const A.foo() : this.bar();
-}''',
- [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR]);
- }
-
- void test_dependencyOnNonFactoryRedirect_toNonConst() {
- // a depends on A.foo() which depends on nothing, since A.bar() is
- // non-const.
- _assertProperDependencies(r'''
-const A a = const A.foo();
-class A {
- const A.foo() : this.bar();
- A.bar();
-}''');
- }
-
- void test_dependencyOnNonFactoryRedirect_unnamed() {
- // a depends on A.foo() depends on A()
- _assertProperDependencies(r'''
-const A a = const A.foo();
-class A {
- const A.foo() : this();
- const A();
-}''');
- }
-
- void test_dependencyOnOptionalParameterDefault() {
- // a depends on A() depends on B()
- _assertProperDependencies(r'''
-class A {
- const A([x = const B()]) : b = x;
- final B b;
-}
-class B {
- const B();
-}
-const A a = const A();''');
- }
-
- void test_dependencyOnVariable() {
- // x depends on y
- _assertProperDependencies(r'''
-const x = y + 1;
-const y = 2;''');
- }
-
- void test_final_initialized_at_declaration() {
- CompilationUnit compilationUnit = resolveSource('''
-class A {
- final int i = 123;
- const A();
-}
-
-const A a = const A();
-''');
- EvaluationResultImpl result =
- _evaluateTopLevelVariable(compilationUnit, 'a');
- Map<String, DartObjectImpl> fields = _assertType(result, "A");
- expect(fields, hasLength(1));
- _assertIntField(fields, "i", 123);
- }
-
- void test_fromEnvironment_bool_default_false() {
- expect(_assertValidBool(_check_fromEnvironment_bool(null, "false")), false);
- }
-
- void test_fromEnvironment_bool_default_overridden() {
- expect(
- _assertValidBool(_check_fromEnvironment_bool("false", "true")), false);
- }
-
- void test_fromEnvironment_bool_default_parseError() {
- expect(_assertValidBool(_check_fromEnvironment_bool("parseError", "true")),
- true);
- }
-
- void test_fromEnvironment_bool_default_true() {
- expect(_assertValidBool(_check_fromEnvironment_bool(null, "true")), true);
- }
-
- void test_fromEnvironment_bool_false() {
- expect(_assertValidBool(_check_fromEnvironment_bool("false", null)), false);
- }
-
- void test_fromEnvironment_bool_parseError() {
- expect(_assertValidBool(_check_fromEnvironment_bool("parseError", null)),
- false);
- }
-
- void test_fromEnvironment_bool_true() {
- expect(_assertValidBool(_check_fromEnvironment_bool("true", null)), true);
- }
-
- void test_fromEnvironment_bool_undeclared() {
- _assertValidUnknown(_check_fromEnvironment_bool(null, null));
- }
-
- void test_fromEnvironment_int_default_overridden() {
- expect(_assertValidInt(_check_fromEnvironment_int("234", "123")), 234);
- }
-
- void test_fromEnvironment_int_default_parseError() {
- expect(
- _assertValidInt(_check_fromEnvironment_int("parseError", "123")), 123);
- }
-
- void test_fromEnvironment_int_default_undeclared() {
- expect(_assertValidInt(_check_fromEnvironment_int(null, "123")), 123);
- }
-
- void test_fromEnvironment_int_ok() {
- expect(_assertValidInt(_check_fromEnvironment_int("234", null)), 234);
- }
-
- void test_fromEnvironment_int_parseError() {
- _assertValidNull(_check_fromEnvironment_int("parseError", null));
- }
-
- void test_fromEnvironment_int_parseError_nullDefault() {
- _assertValidNull(_check_fromEnvironment_int("parseError", "null"));
- }
-
- void test_fromEnvironment_int_undeclared() {
- _assertValidUnknown(_check_fromEnvironment_int(null, null));
- }
-
- void test_fromEnvironment_int_undeclared_nullDefault() {
- _assertValidNull(_check_fromEnvironment_int(null, "null"));
- }
-
- void test_fromEnvironment_string_default_overridden() {
- expect(_assertValidString(_check_fromEnvironment_string("abc", "'def'")),
- "abc");
- }
-
- void test_fromEnvironment_string_default_undeclared() {
- expect(_assertValidString(_check_fromEnvironment_string(null, "'def'")),
- "def");
- }
-
- void test_fromEnvironment_string_empty() {
- expect(_assertValidString(_check_fromEnvironment_string("", null)), "");
- }
-
- void test_fromEnvironment_string_ok() {
- expect(
- _assertValidString(_check_fromEnvironment_string("abc", null)), "abc");
- }
-
- void test_fromEnvironment_string_undeclared() {
- _assertValidUnknown(_check_fromEnvironment_string(null, null));
- }
-
- void test_fromEnvironment_string_undeclared_nullDefault() {
- _assertValidNull(_check_fromEnvironment_string(null, "null"));
- }
-
- void test_instanceCreationExpression_computedField() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(4, 5);
-class A {
- const A(int i, int j) : k = 2 * i + j;
- final int k;
-}''');
- EvaluationResultImpl result =
- _evaluateTopLevelVariable(compilationUnit, "foo");
- Map<String, DartObjectImpl> fields = _assertType(result, "A");
- expect(fields, hasLength(1));
- _assertIntField(fields, "k", 13);
- }
-
- void
- test_instanceCreationExpression_computedField_namedOptionalWithDefault() {
- _checkInstanceCreationOptionalParams(false, true, true);
- }
-
- void
- test_instanceCreationExpression_computedField_namedOptionalWithoutDefault() {
- _checkInstanceCreationOptionalParams(false, true, false);
- }
-
- void
- test_instanceCreationExpression_computedField_unnamedOptionalWithDefault() {
- _checkInstanceCreationOptionalParams(false, false, true);
- }
-
- void
- test_instanceCreationExpression_computedField_unnamedOptionalWithoutDefault() {
- _checkInstanceCreationOptionalParams(false, false, false);
- }
-
- void test_instanceCreationExpression_computedField_usesConstConstructor() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(3);
-class A {
- const A(int i) : b = const B(4);
- final int b;
-}
-class B {
- const B(this.k);
- final int k;
-}''');
- EvaluationResultImpl result =
- _evaluateTopLevelVariable(compilationUnit, "foo");
- Map<String, DartObjectImpl> fieldsOfA = _assertType(result, "A");
- expect(fieldsOfA, hasLength(1));
- Map<String, DartObjectImpl> fieldsOfB =
- _assertFieldType(fieldsOfA, "b", "B");
- expect(fieldsOfB, hasLength(1));
- _assertIntField(fieldsOfB, "k", 4);
- }
-
- void test_instanceCreationExpression_computedField_usesStaticConst() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(3);
-class A {
- const A(int i) : k = i + B.bar;
- final int k;
-}
-class B {
- static const bar = 4;
-}''');
- EvaluationResultImpl result =
- _evaluateTopLevelVariable(compilationUnit, "foo");
- Map<String, DartObjectImpl> fields = _assertType(result, "A");
- expect(fields, hasLength(1));
- _assertIntField(fields, "k", 7);
- }
-
- void test_instanceCreationExpression_computedField_usesTopLevelConst() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(3);
-const bar = 4;
-class A {
- const A(int i) : k = i + bar;
- final int k;
-}''');
- EvaluationResultImpl result =
- _evaluateTopLevelVariable(compilationUnit, "foo");
- Map<String, DartObjectImpl> fields = _assertType(result, "A");
- expect(fields, hasLength(1));
- _assertIntField(fields, "k", 7);
- }
-
- void test_instanceCreationExpression_explicitSuper() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const B(4, 5);
-class A {
- const A(this.x);
- final int x;
-}
-class B extends A {
- const B(int x, this.y) : super(x * 2);
- final int y;
-}''');
- EvaluationResultImpl result =
- _evaluateTopLevelVariable(compilationUnit, "foo");
- Map<String, DartObjectImpl> fields = _assertType(result, "B");
- expect(fields, hasLength(2));
- _assertIntField(fields, "y", 5);
- Map<String, DartObjectImpl> superclassFields =
- _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A");
- expect(superclassFields, hasLength(1));
- _assertIntField(superclassFields, "x", 8);
- }
-
- void test_instanceCreationExpression_fieldFormalParameter() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A(42);
-class A {
- int x;
- const A(this.x)
-}''');
- EvaluationResultImpl result =
- _evaluateTopLevelVariable(compilationUnit, "foo");
- Map<String, DartObjectImpl> fields = _assertType(result, "A");
- expect(fields, hasLength(1));
- _assertIntField(fields, "x", 42);
- }
-
- void
- test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithDefault() {
- _checkInstanceCreationOptionalParams(true, true, true);
- }
-
- void
- test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithoutDefault() {
- _checkInstanceCreationOptionalParams(true, true, false);
- }
-
- void
- test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithDefault() {
- _checkInstanceCreationOptionalParams(true, false, true);
- }
-
- void
- test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithoutDefault() {
- _checkInstanceCreationOptionalParams(true, false, false);
- }
-
- void test_instanceCreationExpression_implicitSuper() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const B(4);
-class A {
- const A() : x = 3;
- final int x;
-}
-class B extends A {
- const B(this.y);
- final int y;
-}''');
- EvaluationResultImpl result =
- _evaluateTopLevelVariable(compilationUnit, "foo");
- Map<String, DartObjectImpl> fields = _assertType(result, "B");
- expect(fields, hasLength(2));
- _assertIntField(fields, "y", 4);
- Map<String, DartObjectImpl> superclassFields =
- _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A");
- expect(superclassFields, hasLength(1));
- _assertIntField(superclassFields, "x", 3);
- }
-
- void test_instanceCreationExpression_nonFactoryRedirect() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
- const A.a1() : this.a2();
- const A.a2() : x = 5;
- final int x;
-}''');
- Map<String, DartObjectImpl> aFields =
- _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
- _assertIntField(aFields, 'x', 5);
- }
-
- void test_instanceCreationExpression_nonFactoryRedirect_arg() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1(1);
-class A {
- const A.a1(x) : this.a2(x + 100);
- const A.a2(x) : y = x + 10;
- final int y;
-}''');
- Map<String, DartObjectImpl> aFields =
- _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
- _assertIntField(aFields, 'y', 111);
- }
-
- void test_instanceCreationExpression_nonFactoryRedirect_cycle() {
- // It is an error to have a cycle in non-factory redirects; however, we
- // need to make sure that even if the error occurs, attempting to evaluate
- // the constant will terminate.
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
- const A() : this.b();
- const A.b() : this();
-}''');
- _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
- }
-
- void test_instanceCreationExpression_nonFactoryRedirect_defaultArg() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
- const A.a1() : this.a2();
- const A.a2([x = 100]) : y = x + 10;
- final int y;
-}''');
- Map<String, DartObjectImpl> aFields =
- _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
- _assertIntField(aFields, 'y', 110);
- }
-
- void test_instanceCreationExpression_nonFactoryRedirect_toMissing() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
- const A.a1() : this.a2();
-}''');
- // We don't care what value foo evaluates to (since there is a compile
- // error), but we shouldn't crash, and we should figure
- // out that it evaluates to an instance of class A.
- _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
- }
-
- void test_instanceCreationExpression_nonFactoryRedirect_toNonConst() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
- const A.a1() : this.a2();
- A.a2();
-}''');
- // We don't care what value foo evaluates to (since there is a compile
- // error), but we shouldn't crash, and we should figure
- // out that it evaluates to an instance of class A.
- _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
- }
-
- void test_instanceCreationExpression_nonFactoryRedirect_unnamed() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A.a1();
-class A {
- const A.a1() : this();
- const A() : x = 5;
- final int x;
-}''');
- Map<String, DartObjectImpl> aFields =
- _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
- _assertIntField(aFields, 'x', 5);
- }
-
- void test_instanceCreationExpression_redirect() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
- const factory A() = B;
-}
-class B implements A {
- const B();
-}''');
- _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "B");
- }
-
- void test_instanceCreationExpression_redirect_cycle() {
- // It is an error to have a cycle in factory redirects; however, we need
- // to make sure that even if the error occurs, attempting to evaluate the
- // constant will terminate.
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
- const factory A() = A.b;
- const factory A.b() = A;
-}''');
- _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
- }
-
- void test_instanceCreationExpression_redirect_external() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
- external const factory A();
-}''');
- _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
- }
-
- void test_instanceCreationExpression_redirect_nonConst() {
- // It is an error for a const factory constructor redirect to a non-const
- // constructor; however, we need to make sure that even if the error
- // attempting to evaluate the constant won't cause a crash.
- CompilationUnit compilationUnit = resolveSource(r'''
-const foo = const A();
-class A {
- const factory A() = A.b;
- A.b();
-}''');
- _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
- }
-
- void test_instanceCreationExpression_redirectWithTypeParams() {
- CompilationUnit compilationUnit = resolveSource(r'''
-class A {
- const factory A(var a) = B<int>;
-}
-
-class B<T> implements A {
- final T x;
- const B(this.x);
-}
-
-const A a = const A(10);''');
- EvaluationResultImpl result =
- _evaluateTopLevelVariable(compilationUnit, "a");
- Map<String, DartObjectImpl> fields = _assertType(result, "B<int>");
- expect(fields, hasLength(1));
- _assertIntField(fields, "x", 10);
- }
-
- void test_instanceCreationExpression_redirectWithTypeSubstitution() {
- // To evaluate the redirection of A<int>,
- // A's template argument (T=int) must be substituted
- // into B's template argument (B<U> where U=T) to get B<int>.
- CompilationUnit compilationUnit = resolveSource(r'''
-class A<T> {
- const factory A(var a) = B<T>;
-}
-
-class B<U> implements A {
- final U x;
- const B(this.x);
-}
-
-const A<int> a = const A<int>(10);''');
- EvaluationResultImpl result =
- _evaluateTopLevelVariable(compilationUnit, "a");
- Map<String, DartObjectImpl> fields = _assertType(result, "B<int>");
- expect(fields, hasLength(1));
- _assertIntField(fields, "x", 10);
- }
-
- void test_instanceCreationExpression_symbol() {
- CompilationUnit compilationUnit =
- resolveSource("const foo = const Symbol('a');");
- EvaluationResultImpl evaluationResult =
- _evaluateTopLevelVariable(compilationUnit, "foo");
- expect(evaluationResult.value, isNotNull);
- DartObjectImpl value = evaluationResult.value;
- expect(value.type, typeProvider.symbolType);
- expect(value.toSymbolValue(), "a");
- }
-
- void test_instanceCreationExpression_withSupertypeParams_explicit() {
- _checkInstanceCreation_withSupertypeParams(true);
- }
-
- void test_instanceCreationExpression_withSupertypeParams_implicit() {
- _checkInstanceCreation_withSupertypeParams(false);
- }
-
- void test_instanceCreationExpression_withTypeParams() {
- CompilationUnit compilationUnit = resolveSource(r'''
-class C<E> {
- const C();
-}
-const c_int = const C<int>();
-const c_num = const C<num>();''');
- EvaluationResultImpl c_int =
- _evaluateTopLevelVariable(compilationUnit, "c_int");
- _assertType(c_int, "C<int>");
- DartObjectImpl c_int_value = c_int.value;
- EvaluationResultImpl c_num =
- _evaluateTopLevelVariable(compilationUnit, "c_num");
- _assertType(c_num, "C<num>");
- DartObjectImpl c_num_value = c_num.value;
- expect(c_int_value == c_num_value, isFalse);
- }
-
- void test_isValidSymbol() {
- expect(ConstantEvaluationEngine.isValidPublicSymbol(""), isTrue);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("foo"), isTrue);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar"), isTrue);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$"), isTrue);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$bar"), isTrue);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("iff"), isTrue);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("gif"), isTrue);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("if\$"), isTrue);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("\$if"), isTrue);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("foo="), isTrue);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar="), isTrue);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.+"), isTrue);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("void"), isTrue);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo"), isFalse);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo.bar"), isFalse);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("foo._bar"), isFalse);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("if"), isFalse);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("if.foo"), isFalse);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.if"), isFalse);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("foo=.bar"), isFalse);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("foo."), isFalse);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("+.foo"), isFalse);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("void.foo"), isFalse);
- expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.void"), isFalse);
- }
-
- void test_length_of_improperly_typed_string_expression() {
- // Since type annotations are ignored in unchecked mode, the improper
- // types on s1 and s2 shouldn't prevent us from evaluating i to
- // 'alpha'.length.
- CompilationUnit compilationUnit = resolveSource('''
-const int s1 = 'alpha';
-const int s2 = 'beta';
-const int i = (true ? s1 : s2).length;
-''');
- ConstTopLevelVariableElementImpl element =
- findTopLevelDeclaration(compilationUnit, 'i').element;
- EvaluationResultImpl result = element.evaluationResult;
- expect(_assertValidInt(result), 5);
- }
-
- void test_length_of_improperly_typed_string_identifier() {
- // Since type annotations are ignored in unchecked mode, the improper type
- // on s shouldn't prevent us from evaluating i to 'alpha'.length.
- CompilationUnit compilationUnit = resolveSource('''
-const int s = 'alpha';
-const int i = s.length;
-''');
- ConstTopLevelVariableElementImpl element =
- findTopLevelDeclaration(compilationUnit, 'i').element;
- EvaluationResultImpl result = element.evaluationResult;
- expect(_assertValidInt(result), 5);
- }
-
- void test_non_static_const_initialized_at_declaration() {
- // Even though non-static consts are not allowed by the language, we need
- // to handle them for error recovery purposes.
- CompilationUnit compilationUnit = resolveSource('''
-class A {
- const int i = 123;
- const A();
-}
-
-const A a = const A();
-''');
- EvaluationResultImpl result =
- _evaluateTopLevelVariable(compilationUnit, 'a');
- Map<String, DartObjectImpl> fields = _assertType(result, "A");
- expect(fields, hasLength(1));
- _assertIntField(fields, "i", 123);
- }
-
- void test_symbolLiteral_void() {
- CompilationUnit compilationUnit =
- resolveSource("const voidSymbol = #void;");
- VariableDeclaration voidSymbol =
- findTopLevelDeclaration(compilationUnit, "voidSymbol");
- EvaluationResultImpl voidSymbolResult =
- (voidSymbol.element as VariableElementImpl).evaluationResult;
- DartObjectImpl value = voidSymbolResult.value;
- expect(value.type, typeProvider.symbolType);
- expect(value.toSymbolValue(), "void");
- }
-
- Map<String, DartObjectImpl> _assertFieldType(
- Map<String, DartObjectImpl> fields,
- String fieldName,
- String expectedType) {
- DartObjectImpl field = fields[fieldName];
- expect(field.type.displayName, expectedType);
- return field.fields;
- }
-
- void _assertIntField(
- Map<String, DartObjectImpl> fields, String fieldName, int expectedValue) {
- DartObjectImpl field = fields[fieldName];
- expect(field.type.name, "int");
- expect(field.toIntValue(), expectedValue);
- }
-
- void _assertNullField(Map<String, DartObjectImpl> fields, String fieldName) {
- DartObjectImpl field = fields[fieldName];
- expect(field.isNull, isTrue);
- }
-
- void _assertProperDependencies(String sourceText,
- [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) {
- Source source = addSource(sourceText);
- LibraryElement element = resolve2(source);
- CompilationUnit unit =
- analysisContext.resolveCompilationUnit(source, element);
- expect(unit, isNotNull);
- ConstantValueComputer computer = _makeConstantValueComputer();
- computer.add(unit, source, source);
- computer.computeValues();
- assertErrors(source, expectedErrorCodes);
- }
-
- Map<String, DartObjectImpl> _assertType(
- EvaluationResultImpl result, String typeName) {
- expect(result.value, isNotNull);
- DartObjectImpl value = result.value;
- expect(value.type.displayName, typeName);
- return value.fields;
- }
-
- bool _assertValidBool(EvaluationResultImpl result) {
- expect(result.value, isNotNull);
- DartObjectImpl value = result.value;
- expect(value.type, typeProvider.boolType);
- bool boolValue = value.toBoolValue();
- expect(boolValue, isNotNull);
- return boolValue;
- }
-
- int _assertValidInt(EvaluationResultImpl result) {
- expect(result, isNotNull);
- expect(result.value, isNotNull);
- DartObjectImpl value = result.value;
- expect(value.type, typeProvider.intType);
- return value.toIntValue();
- }
-
- void _assertValidNull(EvaluationResultImpl result) {
- expect(result.value, isNotNull);
- DartObjectImpl value = result.value;
- expect(value.type, typeProvider.nullType);
- }
-
- String _assertValidString(EvaluationResultImpl result) {
- expect(result.value, isNotNull);
- DartObjectImpl value = result.value;
- expect(value.type, typeProvider.stringType);
- return value.toStringValue();
- }
-
- void _assertValidUnknown(EvaluationResultImpl result) {
- expect(result.value, isNotNull);
- DartObjectImpl value = result.value;
- expect(value.isUnknown, isTrue);
- }
-
- EvaluationResultImpl _check_fromEnvironment_bool(
- String valueInEnvironment, String defaultExpr) {
- String envVarName = "x";
- String varName = "foo";
- if (valueInEnvironment != null) {
- analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
- }
- String defaultArg =
- defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
- CompilationUnit compilationUnit = resolveSource(
- "const $varName = const bool.fromEnvironment('$envVarName'$defaultArg);");
- return _evaluateTopLevelVariable(compilationUnit, varName);
- }
-
- EvaluationResultImpl _check_fromEnvironment_int(
- String valueInEnvironment, String defaultExpr) {
- String envVarName = "x";
- String varName = "foo";
- if (valueInEnvironment != null) {
- analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
- }
- String defaultArg =
- defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
- CompilationUnit compilationUnit = resolveSource(
- "const $varName = const int.fromEnvironment('$envVarName'$defaultArg);");
- return _evaluateTopLevelVariable(compilationUnit, varName);
- }
-
- EvaluationResultImpl _check_fromEnvironment_string(
- String valueInEnvironment, String defaultExpr) {
- String envVarName = "x";
- String varName = "foo";
- if (valueInEnvironment != null) {
- analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
- }
- String defaultArg =
- defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
- CompilationUnit compilationUnit = resolveSource(
- "const $varName = const String.fromEnvironment('$envVarName'$defaultArg);");
- return _evaluateTopLevelVariable(compilationUnit, varName);
- }
-
- void _checkInstanceCreation_withSupertypeParams(bool isExplicit) {
- String superCall = isExplicit ? " : super()" : "";
- CompilationUnit compilationUnit = resolveSource("""
-class A<T> {
- const A();
-}
-class B<T, U> extends A<T> {
- const B()$superCall;
-}
-class C<T, U> extends A<U> {
- const C()$superCall;
-}
-const b_int_num = const B<int, num>();
-const c_int_num = const C<int, num>();""");
- EvaluationResultImpl b_int_num =
- _evaluateTopLevelVariable(compilationUnit, "b_int_num");
- Map<String, DartObjectImpl> b_int_num_fields =
- _assertType(b_int_num, "B<int, num>");
- _assertFieldType(b_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<int>");
- EvaluationResultImpl c_int_num =
- _evaluateTopLevelVariable(compilationUnit, "c_int_num");
- Map<String, DartObjectImpl> c_int_num_fields =
- _assertType(c_int_num, "C<int, num>");
- _assertFieldType(c_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<num>");
- }
-
- void _checkInstanceCreationOptionalParams(
- bool isFieldFormal, bool isNamed, bool hasDefault) {
- String fieldName = "j";
- String paramName = isFieldFormal ? fieldName : "i";
- String formalParam =
- "${isFieldFormal ? "this." : "int "}$paramName${hasDefault ? " = 3" : ""}";
- CompilationUnit compilationUnit = resolveSource("""
-const x = const A();
-const y = const A(${isNamed ? '$paramName: ' : ''}10);
-class A {
- const A(${isNamed ? "{$formalParam}" : "[$formalParam]"})${isFieldFormal ? "" : " : $fieldName = $paramName"};
- final int $fieldName;
-}""");
- EvaluationResultImpl x = _evaluateTopLevelVariable(compilationUnit, "x");
- Map<String, DartObjectImpl> fieldsOfX = _assertType(x, "A");
- expect(fieldsOfX, hasLength(1));
- if (hasDefault) {
- _assertIntField(fieldsOfX, fieldName, 3);
- } else {
- _assertNullField(fieldsOfX, fieldName);
- }
- EvaluationResultImpl y = _evaluateTopLevelVariable(compilationUnit, "y");
- Map<String, DartObjectImpl> fieldsOfY = _assertType(y, "A");
- expect(fieldsOfY, hasLength(1));
- _assertIntField(fieldsOfY, fieldName, 10);
- }
-
- /**
- * Search [compilationUnit] for a class named [className], containing a
- * method [methodName], with exactly one annotation. Return the constant
- * value of the annotation.
- */
- EvaluationResultImpl _evaluateAnnotation(
- CompilationUnit compilationUnit, String className, String memberName) {
- for (CompilationUnitMember member in compilationUnit.declarations) {
- if (member is ClassDeclaration && member.name.name == className) {
- for (ClassMember classMember in member.members) {
- if (classMember is MethodDeclaration &&
- classMember.name.name == memberName) {
- expect(classMember.metadata, hasLength(1));
- ElementAnnotationImpl elementAnnotation =
- classMember.metadata[0].elementAnnotation;
- return elementAnnotation.evaluationResult;
- }
- }
- }
- }
- fail('Class member not found');
- return null;
- }
-
- EvaluationResultImpl _evaluateTopLevelVariable(
- CompilationUnit compilationUnit, String name) {
- VariableDeclaration varDecl =
- findTopLevelDeclaration(compilationUnit, name);
- ConstTopLevelVariableElementImpl varElement = varDecl.element;
- return varElement.evaluationResult;
- }
-
- ConstantValueComputer _makeConstantValueComputer() {
- ConstantEvaluationValidator_ForTest validator =
- new ConstantEvaluationValidator_ForTest(analysisContext2);
- validator.computer = new ConstantValueComputer(
- analysisContext2,
- analysisContext2.typeProvider,
- analysisContext2.declaredVariables,
- validator,
- analysisContext2.typeSystem);
- return validator.computer;
- }
-
- void _validate(bool shouldBeValid, VariableDeclarationList declarationList) {
- for (VariableDeclaration declaration in declarationList.variables) {
- VariableElementImpl element = declaration.element as VariableElementImpl;
- expect(element, isNotNull);
- EvaluationResultImpl result = element.evaluationResult;
- if (shouldBeValid) {
- expect(result.value, isNotNull);
- } else {
- expect(result.value, isNull);
- }
- }
- }
-}
-
-@reflectiveTest
-class ConstantVisitorTest extends ResolverTestCase {
- void test_visitBinaryExpression_questionQuestion_notNull_notNull() {
- Expression left = AstFactory.string2('a');
- Expression right = AstFactory.string2('b');
- Expression expression =
- AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
-
- GatheringErrorListener errorListener = new GatheringErrorListener();
- ErrorReporter errorReporter =
- new ErrorReporter(errorListener, _dummySource());
- DartObjectImpl result = _evaluate(expression, errorReporter);
- expect(result, isNotNull);
- expect(result.isNull, isFalse);
- expect(result.toStringValue(), 'a');
- errorListener.assertNoErrors();
- }
-
- void test_visitBinaryExpression_questionQuestion_null_notNull() {
- Expression left = AstFactory.nullLiteral();
- Expression right = AstFactory.string2('b');
- Expression expression =
- AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
-
- GatheringErrorListener errorListener = new GatheringErrorListener();
- ErrorReporter errorReporter =
- new ErrorReporter(errorListener, _dummySource());
- DartObjectImpl result = _evaluate(expression, errorReporter);
- expect(result, isNotNull);
- expect(result.isNull, isFalse);
- expect(result.toStringValue(), 'b');
- errorListener.assertNoErrors();
- }
-
- void test_visitBinaryExpression_questionQuestion_null_null() {
- Expression left = AstFactory.nullLiteral();
- Expression right = AstFactory.nullLiteral();
- Expression expression =
- AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
-
- GatheringErrorListener errorListener = new GatheringErrorListener();
- ErrorReporter errorReporter =
- new ErrorReporter(errorListener, _dummySource());
- DartObjectImpl result = _evaluate(expression, errorReporter);
- expect(result, isNotNull);
- expect(result.isNull, isTrue);
- errorListener.assertNoErrors();
- }
-
- void test_visitConditionalExpression_false() {
- Expression thenExpression = AstFactory.integer(1);
- Expression elseExpression = AstFactory.integer(0);
- ConditionalExpression expression = AstFactory.conditionalExpression(
- AstFactory.booleanLiteral(false), thenExpression, elseExpression);
- GatheringErrorListener errorListener = new GatheringErrorListener();
- ErrorReporter errorReporter =
- new ErrorReporter(errorListener, _dummySource());
- _assertValue(0, _evaluate(expression, errorReporter));
- errorListener.assertNoErrors();
- }
-
- void test_visitConditionalExpression_nonBooleanCondition() {
- Expression thenExpression = AstFactory.integer(1);
- Expression elseExpression = AstFactory.integer(0);
- NullLiteral conditionExpression = AstFactory.nullLiteral();
- ConditionalExpression expression = AstFactory.conditionalExpression(
- conditionExpression, thenExpression, elseExpression);
- GatheringErrorListener errorListener = new GatheringErrorListener();
- ErrorReporter errorReporter =
- new ErrorReporter(errorListener, _dummySource());
- DartObjectImpl result = _evaluate(expression, errorReporter);
- expect(result, isNull);
- errorListener
- .assertErrorsWithCodes([CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL]);
- }
-
- void test_visitConditionalExpression_nonConstantElse() {
- Expression thenExpression = AstFactory.integer(1);
- Expression elseExpression = AstFactory.identifier3("x");
- ConditionalExpression expression = AstFactory.conditionalExpression(
- AstFactory.booleanLiteral(true), thenExpression, elseExpression);
- GatheringErrorListener errorListener = new GatheringErrorListener();
- ErrorReporter errorReporter =
- new ErrorReporter(errorListener, _dummySource());
- DartObjectImpl result = _evaluate(expression, errorReporter);
- expect(result, isNull);
- errorListener
- .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
- }
-
- void test_visitConditionalExpression_nonConstantThen() {
- Expression thenExpression = AstFactory.identifier3("x");
- Expression elseExpression = AstFactory.integer(0);
- ConditionalExpression expression = AstFactory.conditionalExpression(
- AstFactory.booleanLiteral(true), thenExpression, elseExpression);
- GatheringErrorListener errorListener = new GatheringErrorListener();
- ErrorReporter errorReporter =
- new ErrorReporter(errorListener, _dummySource());
- DartObjectImpl result = _evaluate(expression, errorReporter);
- expect(result, isNull);
- errorListener
- .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
- }
-
- void test_visitConditionalExpression_true() {
- Expression thenExpression = AstFactory.integer(1);
- Expression elseExpression = AstFactory.integer(0);
- ConditionalExpression expression = AstFactory.conditionalExpression(
- AstFactory.booleanLiteral(true), thenExpression, elseExpression);
- GatheringErrorListener errorListener = new GatheringErrorListener();
- ErrorReporter errorReporter =
- new ErrorReporter(errorListener, _dummySource());
- _assertValue(1, _evaluate(expression, errorReporter));
- errorListener.assertNoErrors();
- }
-
- void test_visitSimpleIdentifier_className() {
- CompilationUnit compilationUnit = resolveSource('''
-const a = C;
-class C {}
-''');
- DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
- expect(result.type, typeProvider.typeType);
- expect(result.toTypeValue().name, 'C');
- }
-
- void test_visitSimpleIdentifier_dynamic() {
- CompilationUnit compilationUnit = resolveSource('''
-const a = dynamic;
-''');
- DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
- expect(result.type, typeProvider.typeType);
- expect(result.toTypeValue(), typeProvider.dynamicType);
- }
-
- void test_visitSimpleIdentifier_inEnvironment() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const a = b;
-const b = 3;''');
- Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
- DartObjectImpl six =
- new DartObjectImpl(typeProvider.intType, new IntState(6));
- environment["b"] = six;
- _assertValue(6, _evaluateConstant(compilationUnit, "a", environment));
- }
-
- void test_visitSimpleIdentifier_notInEnvironment() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const a = b;
-const b = 3;''');
- Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
- DartObjectImpl six =
- new DartObjectImpl(typeProvider.intType, new IntState(6));
- environment["c"] = six;
- _assertValue(3, _evaluateConstant(compilationUnit, "a", environment));
- }
-
- void test_visitSimpleIdentifier_withoutEnvironment() {
- CompilationUnit compilationUnit = resolveSource(r'''
-const a = b;
-const b = 3;''');
- _assertValue(3, _evaluateConstant(compilationUnit, "a", null));
- }
-
- void _assertValue(int expectedValue, DartObjectImpl result) {
- expect(result, isNotNull);
- expect(result.type.name, "int");
- expect(result.toIntValue(), expectedValue);
- }
-
- NonExistingSource _dummySource() {
- String path = '/test.dart';
- return new NonExistingSource(path, toUri(path), UriKind.FILE_URI);
- }
-
- DartObjectImpl _evaluate(Expression expression, ErrorReporter errorReporter) {
- return expression.accept(new ConstantVisitor(
- new ConstantEvaluationEngine(
- new TestTypeProvider(), new DeclaredVariables(),
- typeSystem: new TypeSystemImpl()),
- errorReporter));
- }
-
- DartObjectImpl _evaluateConstant(CompilationUnit compilationUnit, String name,
- Map<String, DartObjectImpl> lexicalEnvironment) {
- Source source = compilationUnit.element.source;
- Expression expression =
- findTopLevelConstantExpression(compilationUnit, name);
- GatheringErrorListener errorListener = new GatheringErrorListener();
- ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
- DartObjectImpl result = expression.accept(new ConstantVisitor(
- new ConstantEvaluationEngine(typeProvider, new DeclaredVariables(),
- typeSystem: typeSystem),
- errorReporter,
- lexicalEnvironment: lexicalEnvironment));
- errorListener.assertNoErrors();
- return result;
- }
-}
-
-@reflectiveTest
-class DartObjectImplTest extends EngineTestCase {
- TypeProvider _typeProvider = new TestTypeProvider();
-
- void test_add_knownDouble_knownDouble() {
- _assertAdd(_doubleValue(3.0), _doubleValue(1.0), _doubleValue(2.0));
- }
-
- void test_add_knownDouble_knownInt() {
- _assertAdd(_doubleValue(3.0), _doubleValue(1.0), _intValue(2));
- }
-
- void test_add_knownDouble_unknownDouble() {
- _assertAdd(_doubleValue(null), _doubleValue(1.0), _doubleValue(null));
- }
-
- void test_add_knownDouble_unknownInt() {
- _assertAdd(_doubleValue(null), _doubleValue(1.0), _intValue(null));
- }
-
- void test_add_knownInt_knownInt() {
- _assertAdd(_intValue(3), _intValue(1), _intValue(2));
- }
-
- void test_add_knownInt_knownString() {
- _assertAdd(null, _intValue(1), _stringValue("2"));
- }
-
- void test_add_knownInt_unknownDouble() {
- _assertAdd(_doubleValue(null), _intValue(1), _doubleValue(null));
- }
-
- void test_add_knownInt_unknownInt() {
- _assertAdd(_intValue(null), _intValue(1), _intValue(null));
- }
-
- void test_add_knownString_knownInt() {
- _assertAdd(null, _stringValue("1"), _intValue(2));
- }
-
- void test_add_knownString_knownString() {
- _assertAdd(_stringValue("ab"), _stringValue("a"), _stringValue("b"));
- }
-
- void test_add_knownString_unknownString() {
- _assertAdd(_stringValue(null), _stringValue("a"), _stringValue(null));
- }
-
- void test_add_unknownDouble_knownDouble() {
- _assertAdd(_doubleValue(null), _doubleValue(null), _doubleValue(2.0));
- }
-
- void test_add_unknownDouble_knownInt() {
- _assertAdd(_doubleValue(null), _doubleValue(null), _intValue(2));
- }
-
- void test_add_unknownInt_knownDouble() {
- _assertAdd(_doubleValue(null), _intValue(null), _doubleValue(2.0));
- }
-
- void test_add_unknownInt_knownInt() {
- _assertAdd(_intValue(null), _intValue(null), _intValue(2));
- }
-
- void test_add_unknownString_knownString() {
- _assertAdd(_stringValue(null), _stringValue(null), _stringValue("b"));
- }
-
- void test_add_unknownString_unknownString() {
- _assertAdd(_stringValue(null), _stringValue(null), _stringValue(null));
- }
-
- void test_bitAnd_knownInt_knownInt() {
- _assertBitAnd(_intValue(2), _intValue(6), _intValue(3));
- }
-
- void test_bitAnd_knownInt_knownString() {
- _assertBitAnd(null, _intValue(6), _stringValue("3"));
- }
-
- void test_bitAnd_knownInt_unknownInt() {
- _assertBitAnd(_intValue(null), _intValue(6), _intValue(null));
- }
-
- void test_bitAnd_knownString_knownInt() {
- _assertBitAnd(null, _stringValue("6"), _intValue(3));
- }
-
- void test_bitAnd_unknownInt_knownInt() {
- _assertBitAnd(_intValue(null), _intValue(null), _intValue(3));
- }
-
- void test_bitAnd_unknownInt_unknownInt() {
- _assertBitAnd(_intValue(null), _intValue(null), _intValue(null));
- }
-
- void test_bitNot_knownInt() {
- _assertBitNot(_intValue(-4), _intValue(3));
- }
-
- void test_bitNot_knownString() {
- _assertBitNot(null, _stringValue("6"));
- }
-
- void test_bitNot_unknownInt() {
- _assertBitNot(_intValue(null), _intValue(null));
- }
-
- void test_bitOr_knownInt_knownInt() {
- _assertBitOr(_intValue(7), _intValue(6), _intValue(3));
- }
-
- void test_bitOr_knownInt_knownString() {
- _assertBitOr(null, _intValue(6), _stringValue("3"));
- }
-
- void test_bitOr_knownInt_unknownInt() {
- _assertBitOr(_intValue(null), _intValue(6), _intValue(null));
- }
-
- void test_bitOr_knownString_knownInt() {
- _assertBitOr(null, _stringValue("6"), _intValue(3));
- }
-
- void test_bitOr_unknownInt_knownInt() {
- _assertBitOr(_intValue(null), _intValue(null), _intValue(3));
- }
-
- void test_bitOr_unknownInt_unknownInt() {
- _assertBitOr(_intValue(null), _intValue(null), _intValue(null));
- }
-
- void test_bitXor_knownInt_knownInt() {
- _assertBitXor(_intValue(5), _intValue(6), _intValue(3));
- }
-
- void test_bitXor_knownInt_knownString() {
- _assertBitXor(null, _intValue(6), _stringValue("3"));
- }
-
- void test_bitXor_knownInt_unknownInt() {
- _assertBitXor(_intValue(null), _intValue(6), _intValue(null));
- }
-
- void test_bitXor_knownString_knownInt() {
- _assertBitXor(null, _stringValue("6"), _intValue(3));
- }
-
- void test_bitXor_unknownInt_knownInt() {
- _assertBitXor(_intValue(null), _intValue(null), _intValue(3));
- }
-
- void test_bitXor_unknownInt_unknownInt() {
- _assertBitXor(_intValue(null), _intValue(null), _intValue(null));
- }
-
- void test_concatenate_knownInt_knownString() {
- _assertConcatenate(null, _intValue(2), _stringValue("def"));
- }
-
- void test_concatenate_knownString_knownInt() {
- _assertConcatenate(null, _stringValue("abc"), _intValue(3));
- }
-
- void test_concatenate_knownString_knownString() {
- _assertConcatenate(
- _stringValue("abcdef"), _stringValue("abc"), _stringValue("def"));
- }
-
- void test_concatenate_knownString_unknownString() {
- _assertConcatenate(
- _stringValue(null), _stringValue("abc"), _stringValue(null));
- }
-
- void test_concatenate_unknownString_knownString() {
- _assertConcatenate(
- _stringValue(null), _stringValue(null), _stringValue("def"));
- }
-
- void test_divide_knownDouble_knownDouble() {
- _assertDivide(_doubleValue(3.0), _doubleValue(6.0), _doubleValue(2.0));
- }
-
- void test_divide_knownDouble_knownInt() {
- _assertDivide(_doubleValue(3.0), _doubleValue(6.0), _intValue(2));
- }
-
- void test_divide_knownDouble_unknownDouble() {
- _assertDivide(_doubleValue(null), _doubleValue(6.0), _doubleValue(null));
- }
-
- void test_divide_knownDouble_unknownInt() {
- _assertDivide(_doubleValue(null), _doubleValue(6.0), _intValue(null));
- }
-
- void test_divide_knownInt_knownInt() {
- _assertDivide(_doubleValue(3.0), _intValue(6), _intValue(2));
- }
-
- void test_divide_knownInt_knownString() {
- _assertDivide(null, _intValue(6), _stringValue("2"));
- }
-
- void test_divide_knownInt_unknownDouble() {
- _assertDivide(_doubleValue(null), _intValue(6), _doubleValue(null));
- }
-
- void test_divide_knownInt_unknownInt() {
- _assertDivide(_doubleValue(null), _intValue(6), _intValue(null));
- }
-
- void test_divide_knownString_knownInt() {
- _assertDivide(null, _stringValue("6"), _intValue(2));
- }
-
- void test_divide_unknownDouble_knownDouble() {
- _assertDivide(_doubleValue(null), _doubleValue(null), _doubleValue(2.0));
- }
-
- void test_divide_unknownDouble_knownInt() {
- _assertDivide(_doubleValue(null), _doubleValue(null), _intValue(2));
- }
-
- void test_divide_unknownInt_knownDouble() {
- _assertDivide(_doubleValue(null), _intValue(null), _doubleValue(2.0));
- }
-
- void test_divide_unknownInt_knownInt() {
- _assertDivide(_doubleValue(null), _intValue(null), _intValue(2));
- }
-
- void test_equalEqual_bool_false() {
- _assertEqualEqual(_boolValue(false), _boolValue(false), _boolValue(true));
- }
-
- void test_equalEqual_bool_true() {
- _assertEqualEqual(_boolValue(true), _boolValue(true), _boolValue(true));
- }
-
- void test_equalEqual_bool_unknown() {
- _assertEqualEqual(_boolValue(null), _boolValue(null), _boolValue(false));
- }
-
- void test_equalEqual_double_false() {
- _assertEqualEqual(_boolValue(false), _doubleValue(2.0), _doubleValue(4.0));
- }
-
- void test_equalEqual_double_true() {
- _assertEqualEqual(_boolValue(true), _doubleValue(2.0), _doubleValue(2.0));
- }
-
- void test_equalEqual_double_unknown() {
- _assertEqualEqual(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
- }
-
- void test_equalEqual_int_false() {
- _assertEqualEqual(_boolValue(false), _intValue(-5), _intValue(5));
- }
-
- void test_equalEqual_int_true() {
- _assertEqualEqual(_boolValue(true), _intValue(5), _intValue(5));
- }
-
- void test_equalEqual_int_unknown() {
- _assertEqualEqual(_boolValue(null), _intValue(null), _intValue(3));
- }
-
- void test_equalEqual_list_empty() {
- _assertEqualEqual(null, _listValue(), _listValue());
- }
-
- void test_equalEqual_list_false() {
- _assertEqualEqual(null, _listValue(), _listValue());
- }
-
- void test_equalEqual_map_empty() {
- _assertEqualEqual(null, _mapValue(), _mapValue());
- }
-
- void test_equalEqual_map_false() {
- _assertEqualEqual(null, _mapValue(), _mapValue());
- }
-
- void test_equalEqual_null() {
- _assertEqualEqual(_boolValue(true), _nullValue(), _nullValue());
- }
-
- void test_equalEqual_string_false() {
- _assertEqualEqual(
- _boolValue(false), _stringValue("abc"), _stringValue("def"));
- }
-
- void test_equalEqual_string_true() {
- _assertEqualEqual(
- _boolValue(true), _stringValue("abc"), _stringValue("abc"));
- }
-
- void test_equalEqual_string_unknown() {
- _assertEqualEqual(
- _boolValue(null), _stringValue(null), _stringValue("def"));
- }
-
- void test_equals_list_false_differentSizes() {
- expect(
- _listValue([_boolValue(true)]) ==
- _listValue([_boolValue(true), _boolValue(false)]),
- isFalse);
- }
-
- void test_equals_list_false_sameSize() {
- expect(_listValue([_boolValue(true)]) == _listValue([_boolValue(false)]),
- isFalse);
- }
-
- void test_equals_list_true_empty() {
- expect(_listValue(), _listValue());
- }
-
- void test_equals_list_true_nonEmpty() {
- expect(_listValue([_boolValue(true)]), _listValue([_boolValue(true)]));
- }
-
- void test_equals_map_true_empty() {
- expect(_mapValue(), _mapValue());
- }
-
- void test_equals_symbol_false() {
- expect(_symbolValue("a") == _symbolValue("b"), isFalse);
- }
-
- void test_equals_symbol_true() {
- expect(_symbolValue("a"), _symbolValue("a"));
- }
-
- void test_getValue_bool_false() {
- expect(_boolValue(false).toBoolValue(), false);
- }
-
- void test_getValue_bool_true() {
- expect(_boolValue(true).toBoolValue(), true);
- }
-
- void test_getValue_bool_unknown() {
- expect(_boolValue(null).toBoolValue(), isNull);
- }
-
- void test_getValue_double_known() {
- double value = 2.3;
- expect(_doubleValue(value).toDoubleValue(), value);
- }
-
- void test_getValue_double_unknown() {
- expect(_doubleValue(null).toDoubleValue(), isNull);
- }
-
- void test_getValue_int_known() {
- int value = 23;
- expect(_intValue(value).toIntValue(), value);
- }
-
- void test_getValue_int_unknown() {
- expect(_intValue(null).toIntValue(), isNull);
- }
-
- void test_getValue_list_empty() {
- Object result = _listValue().toListValue();
- _assertInstanceOfObjectArray(result);
- List<Object> array = result as List<Object>;
- expect(array, hasLength(0));
- }
-
- void test_getValue_list_valid() {
- Object result = _listValue([_intValue(23)]).toListValue();
- _assertInstanceOfObjectArray(result);
- List<Object> array = result as List<Object>;
- expect(array, hasLength(1));
- }
-
- void test_getValue_map_empty() {
- Object result = _mapValue().toMapValue();
- EngineTestCase.assertInstanceOf((obj) => obj is Map, Map, result);
- Map map = result as Map;
- expect(map, hasLength(0));
- }
-
- void test_getValue_map_valid() {
- Object result =
- _mapValue([_stringValue("key"), _stringValue("value")]).toMapValue();
- EngineTestCase.assertInstanceOf((obj) => obj is Map, Map, result);
- Map map = result as Map;
- expect(map, hasLength(1));
- }
-
- void test_getValue_null() {
- expect(_nullValue().isNull, isTrue);
- }
-
- void test_getValue_string_known() {
- String value = "twenty-three";
- expect(_stringValue(value).toStringValue(), value);
- }
-
- void test_getValue_string_unknown() {
- expect(_stringValue(null).toStringValue(), isNull);
- }
-
- void test_greaterThan_knownDouble_knownDouble_false() {
- _assertGreaterThan(_boolValue(false), _doubleValue(1.0), _doubleValue(2.0));
- }
-
- void test_greaterThan_knownDouble_knownDouble_true() {
- _assertGreaterThan(_boolValue(true), _doubleValue(2.0), _doubleValue(1.0));
- }
-
- void test_greaterThan_knownDouble_knownInt_false() {
- _assertGreaterThan(_boolValue(false), _doubleValue(1.0), _intValue(2));
- }
-
- void test_greaterThan_knownDouble_knownInt_true() {
- _assertGreaterThan(_boolValue(true), _doubleValue(2.0), _intValue(1));
- }
-
- void test_greaterThan_knownDouble_unknownDouble() {
- _assertGreaterThan(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
- }
-
- void test_greaterThan_knownDouble_unknownInt() {
- _assertGreaterThan(_boolValue(null), _doubleValue(1.0), _intValue(null));
- }
-
- void test_greaterThan_knownInt_knownInt_false() {
- _assertGreaterThan(_boolValue(false), _intValue(1), _intValue(2));
- }
-
- void test_greaterThan_knownInt_knownInt_true() {
- _assertGreaterThan(_boolValue(true), _intValue(2), _intValue(1));
- }
-
- void test_greaterThan_knownInt_knownString() {
- _assertGreaterThan(null, _intValue(1), _stringValue("2"));
- }
-
- void test_greaterThan_knownInt_unknownDouble() {
- _assertGreaterThan(_boolValue(null), _intValue(1), _doubleValue(null));
- }
-
- void test_greaterThan_knownInt_unknownInt() {
- _assertGreaterThan(_boolValue(null), _intValue(1), _intValue(null));
- }
-
- void test_greaterThan_knownString_knownInt() {
- _assertGreaterThan(null, _stringValue("1"), _intValue(2));
- }
-
- void test_greaterThan_unknownDouble_knownDouble() {
- _assertGreaterThan(_boolValue(null), _doubleValue(null), _doubleValue(2.0));
- }
-
- void test_greaterThan_unknownDouble_knownInt() {
- _assertGreaterThan(_boolValue(null), _doubleValue(null), _intValue(2));
- }
-
- void test_greaterThan_unknownInt_knownDouble() {
- _assertGreaterThan(_boolValue(null), _intValue(null), _doubleValue(2.0));
- }
-
- void test_greaterThan_unknownInt_knownInt() {
- _assertGreaterThan(_boolValue(null), _intValue(null), _intValue(2));
- }
-
- void test_greaterThanOrEqual_knownDouble_knownDouble_false() {
- _assertGreaterThanOrEqual(
- _boolValue(false), _doubleValue(1.0), _doubleValue(2.0));
- }
-
- void test_greaterThanOrEqual_knownDouble_knownDouble_true() {
- _assertGreaterThanOrEqual(
- _boolValue(true), _doubleValue(2.0), _doubleValue(1.0));
- }
-
- void test_greaterThanOrEqual_knownDouble_knownInt_false() {
- _assertGreaterThanOrEqual(
- _boolValue(false), _doubleValue(1.0), _intValue(2));
- }
-
- void test_greaterThanOrEqual_knownDouble_knownInt_true() {
- _assertGreaterThanOrEqual(
- _boolValue(true), _doubleValue(2.0), _intValue(1));
- }
-
- void test_greaterThanOrEqual_knownDouble_unknownDouble() {
- _assertGreaterThanOrEqual(
- _boolValue(null), _doubleValue(1.0), _doubleValue(null));
- }
-
- void test_greaterThanOrEqual_knownDouble_unknownInt() {
- _assertGreaterThanOrEqual(
- _boolValue(null), _doubleValue(1.0), _intValue(null));
- }
-
- void test_greaterThanOrEqual_knownInt_knownInt_false() {
- _assertGreaterThanOrEqual(_boolValue(false), _intValue(1), _intValue(2));
- }
-
- void test_greaterThanOrEqual_knownInt_knownInt_true() {
- _assertGreaterThanOrEqual(_boolValue(true), _intValue(2), _intValue(2));
- }
-
- void test_greaterThanOrEqual_knownInt_knownString() {
- _assertGreaterThanOrEqual(null, _intValue(1), _stringValue("2"));
- }
-
- void test_greaterThanOrEqual_knownInt_unknownDouble() {
- _assertGreaterThanOrEqual(
- _boolValue(null), _intValue(1), _doubleValue(null));
- }
-
- void test_greaterThanOrEqual_knownInt_unknownInt() {
- _assertGreaterThanOrEqual(_boolValue(null), _intValue(1), _intValue(null));
- }
-
- void test_greaterThanOrEqual_knownString_knownInt() {
- _assertGreaterThanOrEqual(null, _stringValue("1"), _intValue(2));
- }
-
- void test_greaterThanOrEqual_unknownDouble_knownDouble() {
- _assertGreaterThanOrEqual(
- _boolValue(null), _doubleValue(null), _doubleValue(2.0));
- }
-
- void test_greaterThanOrEqual_unknownDouble_knownInt() {
- _assertGreaterThanOrEqual(
- _boolValue(null), _doubleValue(null), _intValue(2));
- }
-
- void test_greaterThanOrEqual_unknownInt_knownDouble() {
- _assertGreaterThanOrEqual(
- _boolValue(null), _intValue(null), _doubleValue(2.0));
- }
-
- void test_greaterThanOrEqual_unknownInt_knownInt() {
- _assertGreaterThanOrEqual(_boolValue(null), _intValue(null), _intValue(2));
- }
-
- void test_hasKnownValue_bool_false() {
- expect(_boolValue(false).hasKnownValue, isTrue);
- }
-
- void test_hasKnownValue_bool_true() {
- expect(_boolValue(true).hasKnownValue, isTrue);
- }
-
- void test_hasKnownValue_bool_unknown() {
- expect(_boolValue(null).hasKnownValue, isFalse);
- }
-
- void test_hasKnownValue_double_known() {
- expect(_doubleValue(2.3).hasKnownValue, isTrue);
- }
-
- void test_hasKnownValue_double_unknown() {
- expect(_doubleValue(null).hasKnownValue, isFalse);
- }
-
- void test_hasKnownValue_dynamic() {
- expect(_dynamicValue().hasKnownValue, isTrue);
- }
-
- void test_hasKnownValue_int_known() {
- expect(_intValue(23).hasKnownValue, isTrue);
- }
-
- void test_hasKnownValue_int_unknown() {
- expect(_intValue(null).hasKnownValue, isFalse);
- }
-
- void test_hasKnownValue_list_empty() {
- expect(_listValue().hasKnownValue, isTrue);
- }
-
- void test_hasKnownValue_list_invalidElement() {
- expect(_listValue([_dynamicValue]).hasKnownValue, isTrue);
- }
-
- void test_hasKnownValue_list_valid() {
- expect(_listValue([_intValue(23)]).hasKnownValue, isTrue);
- }
-
- void test_hasKnownValue_map_empty() {
- expect(_mapValue().hasKnownValue, isTrue);
- }
-
- void test_hasKnownValue_map_invalidKey() {
- expect(_mapValue([_dynamicValue(), _stringValue("value")]).hasKnownValue,
- isTrue);
- }
-
- void test_hasKnownValue_map_invalidValue() {
- expect(_mapValue([_stringValue("key"), _dynamicValue()]).hasKnownValue,
- isTrue);
- }
-
- void test_hasKnownValue_map_valid() {
- expect(
- _mapValue([_stringValue("key"), _stringValue("value")]).hasKnownValue,
- isTrue);
- }
-
- void test_hasKnownValue_null() {
- expect(_nullValue().hasKnownValue, isTrue);
- }
-
- void test_hasKnownValue_num() {
- expect(_numValue().hasKnownValue, isFalse);
- }
-
- void test_hasKnownValue_string_known() {
- expect(_stringValue("twenty-three").hasKnownValue, isTrue);
- }
-
- void test_hasKnownValue_string_unknown() {
- expect(_stringValue(null).hasKnownValue, isFalse);
- }
-
- void test_identical_bool_false() {
- _assertIdentical(_boolValue(false), _boolValue(false), _boolValue(true));
- }
-
- void test_identical_bool_true() {
- _assertIdentical(_boolValue(true), _boolValue(true), _boolValue(true));
- }
-
- void test_identical_bool_unknown() {
- _assertIdentical(_boolValue(null), _boolValue(null), _boolValue(false));
- }
-
- void test_identical_double_false() {
- _assertIdentical(_boolValue(false), _doubleValue(2.0), _doubleValue(4.0));
- }
-
- void test_identical_double_true() {
- _assertIdentical(_boolValue(true), _doubleValue(2.0), _doubleValue(2.0));
- }
-
- void test_identical_double_unknown() {
- _assertIdentical(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
- }
-
- void test_identical_int_false() {
- _assertIdentical(_boolValue(false), _intValue(-5), _intValue(5));
- }
-
- void test_identical_int_true() {
- _assertIdentical(_boolValue(true), _intValue(5), _intValue(5));
- }
-
- void test_identical_int_unknown() {
- _assertIdentical(_boolValue(null), _intValue(null), _intValue(3));
- }
-
- void test_identical_list_empty() {
- _assertIdentical(_boolValue(true), _listValue(), _listValue());
- }
-
- void test_identical_list_false() {
- _assertIdentical(
- _boolValue(false), _listValue(), _listValue([_intValue(3)]));
- }
-
- void test_identical_map_empty() {
- _assertIdentical(_boolValue(true), _mapValue(), _mapValue());
- }
-
- void test_identical_map_false() {
- _assertIdentical(_boolValue(false), _mapValue(),
- _mapValue([_intValue(1), _intValue(2)]));
- }
-
- void test_identical_null() {
- _assertIdentical(_boolValue(true), _nullValue(), _nullValue());
- }
-
- void test_identical_string_false() {
- _assertIdentical(
- _boolValue(false), _stringValue("abc"), _stringValue("def"));
- }
-
- void test_identical_string_true() {
- _assertIdentical(
- _boolValue(true), _stringValue("abc"), _stringValue("abc"));
- }
-
- void test_identical_string_unknown() {
- _assertIdentical(_boolValue(null), _stringValue(null), _stringValue("def"));
- }
-
- void test_integerDivide_knownDouble_knownDouble() {
- _assertIntegerDivide(_intValue(3), _doubleValue(6.0), _doubleValue(2.0));
- }
-
- void test_integerDivide_knownDouble_knownInt() {
- _assertIntegerDivide(_intValue(3), _doubleValue(6.0), _intValue(2));
- }
-
- void test_integerDivide_knownDouble_unknownDouble() {
- _assertIntegerDivide(
- _intValue(null), _doubleValue(6.0), _doubleValue(null));
- }
-
- void test_integerDivide_knownDouble_unknownInt() {
- _assertIntegerDivide(_intValue(null), _doubleValue(6.0), _intValue(null));
- }
-
- void test_integerDivide_knownInt_knownInt() {
- _assertIntegerDivide(_intValue(3), _intValue(6), _intValue(2));
- }
-
- void test_integerDivide_knownInt_knownString() {
- _assertIntegerDivide(null, _intValue(6), _stringValue("2"));
- }
-
- void test_integerDivide_knownInt_unknownDouble() {
- _assertIntegerDivide(_intValue(null), _intValue(6), _doubleValue(null));
- }
-
- void test_integerDivide_knownInt_unknownInt() {
- _assertIntegerDivide(_intValue(null), _intValue(6), _intValue(null));
- }
-
- void test_integerDivide_knownString_knownInt() {
- _assertIntegerDivide(null, _stringValue("6"), _intValue(2));
- }
-
- void test_integerDivide_unknownDouble_knownDouble() {
- _assertIntegerDivide(
- _intValue(null), _doubleValue(null), _doubleValue(2.0));
- }
-
- void test_integerDivide_unknownDouble_knownInt() {
- _assertIntegerDivide(_intValue(null), _doubleValue(null), _intValue(2));
- }
-
- void test_integerDivide_unknownInt_knownDouble() {
- _assertIntegerDivide(_intValue(null), _intValue(null), _doubleValue(2.0));
- }
-
- void test_integerDivide_unknownInt_knownInt() {
- _assertIntegerDivide(_intValue(null), _intValue(null), _intValue(2));
- }
-
- void test_isBoolNumStringOrNull_bool_false() {
- expect(_boolValue(false).isBoolNumStringOrNull, isTrue);
- }
-
- void test_isBoolNumStringOrNull_bool_true() {
- expect(_boolValue(true).isBoolNumStringOrNull, isTrue);
- }
-
- void test_isBoolNumStringOrNull_bool_unknown() {
- expect(_boolValue(null).isBoolNumStringOrNull, isTrue);
- }
-
- void test_isBoolNumStringOrNull_double_known() {
- expect(_doubleValue(2.3).isBoolNumStringOrNull, isTrue);
- }
-
- void test_isBoolNumStringOrNull_double_unknown() {
- expect(_doubleValue(null).isBoolNumStringOrNull, isTrue);
- }
-
- void test_isBoolNumStringOrNull_dynamic() {
- expect(_dynamicValue().isBoolNumStringOrNull, isTrue);
- }
-
- void test_isBoolNumStringOrNull_int_known() {
- expect(_intValue(23).isBoolNumStringOrNull, isTrue);
- }
-
- void test_isBoolNumStringOrNull_int_unknown() {
- expect(_intValue(null).isBoolNumStringOrNull, isTrue);
- }
-
- void test_isBoolNumStringOrNull_list() {
- expect(_listValue().isBoolNumStringOrNull, isFalse);
- }
-
- void test_isBoolNumStringOrNull_null() {
- expect(_nullValue().isBoolNumStringOrNull, isTrue);
- }
-
- void test_isBoolNumStringOrNull_num() {
- expect(_numValue().isBoolNumStringOrNull, isTrue);
- }
-
- void test_isBoolNumStringOrNull_string_known() {
- expect(_stringValue("twenty-three").isBoolNumStringOrNull, isTrue);
- }
-
- void test_isBoolNumStringOrNull_string_unknown() {
- expect(_stringValue(null).isBoolNumStringOrNull, isTrue);
- }
-
- void test_lessThan_knownDouble_knownDouble_false() {
- _assertLessThan(_boolValue(false), _doubleValue(2.0), _doubleValue(1.0));
- }
-
- void test_lessThan_knownDouble_knownDouble_true() {
- _assertLessThan(_boolValue(true), _doubleValue(1.0), _doubleValue(2.0));
- }
-
- void test_lessThan_knownDouble_knownInt_false() {
- _assertLessThan(_boolValue(false), _doubleValue(2.0), _intValue(1));
- }
-
- void test_lessThan_knownDouble_knownInt_true() {
- _assertLessThan(_boolValue(true), _doubleValue(1.0), _intValue(2));
- }
-
- void test_lessThan_knownDouble_unknownDouble() {
- _assertLessThan(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
- }
-
- void test_lessThan_knownDouble_unknownInt() {
- _assertLessThan(_boolValue(null), _doubleValue(1.0), _intValue(null));
- }
-
- void test_lessThan_knownInt_knownInt_false() {
- _assertLessThan(_boolValue(false), _intValue(2), _intValue(1));
- }
-
- void test_lessThan_knownInt_knownInt_true() {
- _assertLessThan(_boolValue(true), _intValue(1), _intValue(2));
- }
-
- void test_lessThan_knownInt_knownString() {
- _assertLessThan(null, _intValue(1), _stringValue("2"));
- }
-
- void test_lessThan_knownInt_unknownDouble() {
- _assertLessThan(_boolValue(null), _intValue(1), _doubleValue(null));
- }
-
- void test_lessThan_knownInt_unknownInt() {
- _assertLessThan(_boolValue(null), _intValue(1), _intValue(null));
- }
-
- void test_lessThan_knownString_knownInt() {
- _assertLessThan(null, _stringValue("1"), _intValue(2));
- }
-
- void test_lessThan_unknownDouble_knownDouble() {
- _assertLessThan(_boolValue(null), _doubleValue(null), _doubleValue(2.0));
- }
-
- void test_lessThan_unknownDouble_knownInt() {
- _assertLessThan(_boolValue(null), _doubleValue(null), _intValue(2));
- }
-
- void test_lessThan_unknownInt_knownDouble() {
- _assertLessThan(_boolValue(null), _intValue(null), _doubleValue(2.0));
- }
-
- void test_lessThan_unknownInt_knownInt() {
- _assertLessThan(_boolValue(null), _intValue(null), _intValue(2));
- }
-
- void test_lessThanOrEqual_knownDouble_knownDouble_false() {
- _assertLessThanOrEqual(
- _boolValue(false), _doubleValue(2.0), _doubleValue(1.0));
- }
-
- void test_lessThanOrEqual_knownDouble_knownDouble_true() {
- _assertLessThanOrEqual(
- _boolValue(true), _doubleValue(1.0), _doubleValue(2.0));
- }
-
- void test_lessThanOrEqual_knownDouble_knownInt_false() {
- _assertLessThanOrEqual(_boolValue(false), _doubleValue(2.0), _intValue(1));
- }
-
- void test_lessThanOrEqual_knownDouble_knownInt_true() {
- _assertLessThanOrEqual(_boolValue(true), _doubleValue(1.0), _intValue(2));
- }
-
- void test_lessThanOrEqual_knownDouble_unknownDouble() {
- _assertLessThanOrEqual(
- _boolValue(null), _doubleValue(1.0), _doubleValue(null));
- }
-
- void test_lessThanOrEqual_knownDouble_unknownInt() {
- _assertLessThanOrEqual(
- _boolValue(null), _doubleValue(1.0), _intValue(null));
- }
-
- void test_lessThanOrEqual_knownInt_knownInt_false() {
- _assertLessThanOrEqual(_boolValue(false), _intValue(2), _intValue(1));
- }
-
- void test_lessThanOrEqual_knownInt_knownInt_true() {
- _assertLessThanOrEqual(_boolValue(true), _intValue(1), _intValue(2));
- }
-
- void test_lessThanOrEqual_knownInt_knownString() {
- _assertLessThanOrEqual(null, _intValue(1), _stringValue("2"));
- }
-
- void test_lessThanOrEqual_knownInt_unknownDouble() {
- _assertLessThanOrEqual(_boolValue(null), _intValue(1), _doubleValue(null));
- }
-
- void test_lessThanOrEqual_knownInt_unknownInt() {
- _assertLessThanOrEqual(_boolValue(null), _intValue(1), _intValue(null));
- }
-
- void test_lessThanOrEqual_knownString_knownInt() {
- _assertLessThanOrEqual(null, _stringValue("1"), _intValue(2));
- }
-
- void test_lessThanOrEqual_unknownDouble_knownDouble() {
- _assertLessThanOrEqual(
- _boolValue(null), _doubleValue(null), _doubleValue(2.0));
- }
-
- void test_lessThanOrEqual_unknownDouble_knownInt() {
- _assertLessThanOrEqual(_boolValue(null), _doubleValue(null), _intValue(2));
- }
-
- void test_lessThanOrEqual_unknownInt_knownDouble() {
- _assertLessThanOrEqual(
- _boolValue(null), _intValue(null), _doubleValue(2.0));
- }
-
- void test_lessThanOrEqual_unknownInt_knownInt() {
- _assertLessThanOrEqual(_boolValue(null), _intValue(null), _intValue(2));
- }
-
- void test_logicalAnd_false_false() {
- _assertLogicalAnd(_boolValue(false), _boolValue(false), _boolValue(false));
- }
-
- void test_logicalAnd_false_null() {
- try {
- _assertLogicalAnd(_boolValue(false), _boolValue(false), _nullValue());
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalAnd_false_string() {
- try {
- _assertLogicalAnd(
- _boolValue(false), _boolValue(false), _stringValue("false"));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalAnd_false_true() {
- _assertLogicalAnd(_boolValue(false), _boolValue(false), _boolValue(true));
- }
-
- void test_logicalAnd_null_false() {
- try {
- _assertLogicalAnd(_boolValue(false), _nullValue(), _boolValue(false));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalAnd_null_true() {
- try {
- _assertLogicalAnd(_boolValue(false), _nullValue(), _boolValue(true));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalAnd_string_false() {
- try {
- _assertLogicalAnd(
- _boolValue(false), _stringValue("true"), _boolValue(false));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalAnd_string_true() {
- try {
- _assertLogicalAnd(
- _boolValue(false), _stringValue("false"), _boolValue(true));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalAnd_true_false() {
- _assertLogicalAnd(_boolValue(false), _boolValue(true), _boolValue(false));
- }
-
- void test_logicalAnd_true_null() {
- _assertLogicalAnd(null, _boolValue(true), _nullValue());
- }
-
- void test_logicalAnd_true_string() {
- try {
- _assertLogicalAnd(
- _boolValue(false), _boolValue(true), _stringValue("true"));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalAnd_true_true() {
- _assertLogicalAnd(_boolValue(true), _boolValue(true), _boolValue(true));
- }
-
- void test_logicalNot_false() {
- _assertLogicalNot(_boolValue(true), _boolValue(false));
- }
-
- void test_logicalNot_null() {
- _assertLogicalNot(null, _nullValue());
- }
-
- void test_logicalNot_string() {
- try {
- _assertLogicalNot(_boolValue(true), _stringValue(null));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalNot_true() {
- _assertLogicalNot(_boolValue(false), _boolValue(true));
- }
-
- void test_logicalNot_unknown() {
- _assertLogicalNot(_boolValue(null), _boolValue(null));
- }
-
- void test_logicalOr_false_false() {
- _assertLogicalOr(_boolValue(false), _boolValue(false), _boolValue(false));
- }
-
- void test_logicalOr_false_null() {
- _assertLogicalOr(null, _boolValue(false), _nullValue());
- }
-
- void test_logicalOr_false_string() {
- try {
- _assertLogicalOr(
- _boolValue(false), _boolValue(false), _stringValue("false"));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalOr_false_true() {
- _assertLogicalOr(_boolValue(true), _boolValue(false), _boolValue(true));
- }
-
- void test_logicalOr_null_false() {
- try {
- _assertLogicalOr(_boolValue(false), _nullValue(), _boolValue(false));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalOr_null_true() {
- try {
- _assertLogicalOr(_boolValue(true), _nullValue(), _boolValue(true));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalOr_string_false() {
- try {
- _assertLogicalOr(
- _boolValue(false), _stringValue("true"), _boolValue(false));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalOr_string_true() {
- try {
- _assertLogicalOr(
- _boolValue(true), _stringValue("false"), _boolValue(true));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalOr_true_false() {
- _assertLogicalOr(_boolValue(true), _boolValue(true), _boolValue(false));
- }
-
- void test_logicalOr_true_null() {
- try {
- _assertLogicalOr(_boolValue(true), _boolValue(true), _nullValue());
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalOr_true_string() {
- try {
- _assertLogicalOr(
- _boolValue(true), _boolValue(true), _stringValue("true"));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_logicalOr_true_true() {
- _assertLogicalOr(_boolValue(true), _boolValue(true), _boolValue(true));
- }
-
- void test_minus_knownDouble_knownDouble() {
- _assertMinus(_doubleValue(1.0), _doubleValue(4.0), _doubleValue(3.0));
- }
-
- void test_minus_knownDouble_knownInt() {
- _assertMinus(_doubleValue(1.0), _doubleValue(4.0), _intValue(3));
- }
-
- void test_minus_knownDouble_unknownDouble() {
- _assertMinus(_doubleValue(null), _doubleValue(4.0), _doubleValue(null));
- }
-
- void test_minus_knownDouble_unknownInt() {
- _assertMinus(_doubleValue(null), _doubleValue(4.0), _intValue(null));
- }
-
- void test_minus_knownInt_knownInt() {
- _assertMinus(_intValue(1), _intValue(4), _intValue(3));
- }
-
- void test_minus_knownInt_knownString() {
- _assertMinus(null, _intValue(4), _stringValue("3"));
- }
-
- void test_minus_knownInt_unknownDouble() {
- _assertMinus(_doubleValue(null), _intValue(4), _doubleValue(null));
- }
-
- void test_minus_knownInt_unknownInt() {
- _assertMinus(_intValue(null), _intValue(4), _intValue(null));
- }
-
- void test_minus_knownString_knownInt() {
- _assertMinus(null, _stringValue("4"), _intValue(3));
- }
-
- void test_minus_unknownDouble_knownDouble() {
- _assertMinus(_doubleValue(null), _doubleValue(null), _doubleValue(3.0));
- }
-
- void test_minus_unknownDouble_knownInt() {
- _assertMinus(_doubleValue(null), _doubleValue(null), _intValue(3));
- }
-
- void test_minus_unknownInt_knownDouble() {
- _assertMinus(_doubleValue(null), _intValue(null), _doubleValue(3.0));
- }
-
- void test_minus_unknownInt_knownInt() {
- _assertMinus(_intValue(null), _intValue(null), _intValue(3));
- }
-
- void test_negated_double_known() {
- _assertNegated(_doubleValue(2.0), _doubleValue(-2.0));
- }
-
- void test_negated_double_unknown() {
- _assertNegated(_doubleValue(null), _doubleValue(null));
- }
-
- void test_negated_int_known() {
- _assertNegated(_intValue(-3), _intValue(3));
- }
-
- void test_negated_int_unknown() {
- _assertNegated(_intValue(null), _intValue(null));
- }
-
- void test_negated_string() {
- _assertNegated(null, _stringValue(null));
- }
-
- void test_notEqual_bool_false() {
- _assertNotEqual(_boolValue(false), _boolValue(true), _boolValue(true));
- }
-
- void test_notEqual_bool_true() {
- _assertNotEqual(_boolValue(true), _boolValue(false), _boolValue(true));
- }
-
- void test_notEqual_bool_unknown() {
- _assertNotEqual(_boolValue(null), _boolValue(null), _boolValue(false));
- }
-
- void test_notEqual_double_false() {
- _assertNotEqual(_boolValue(false), _doubleValue(2.0), _doubleValue(2.0));
- }
-
- void test_notEqual_double_true() {
- _assertNotEqual(_boolValue(true), _doubleValue(2.0), _doubleValue(4.0));
- }
-
- void test_notEqual_double_unknown() {
- _assertNotEqual(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
- }
-
- void test_notEqual_int_false() {
- _assertNotEqual(_boolValue(false), _intValue(5), _intValue(5));
- }
-
- void test_notEqual_int_true() {
- _assertNotEqual(_boolValue(true), _intValue(-5), _intValue(5));
- }
-
- void test_notEqual_int_unknown() {
- _assertNotEqual(_boolValue(null), _intValue(null), _intValue(3));
- }
-
- void test_notEqual_null() {
- _assertNotEqual(_boolValue(false), _nullValue(), _nullValue());
- }
-
- void test_notEqual_string_false() {
- _assertNotEqual(
- _boolValue(false), _stringValue("abc"), _stringValue("abc"));
- }
-
- void test_notEqual_string_true() {
- _assertNotEqual(_boolValue(true), _stringValue("abc"), _stringValue("def"));
- }
-
- void test_notEqual_string_unknown() {
- _assertNotEqual(_boolValue(null), _stringValue(null), _stringValue("def"));
- }
-
- void test_performToString_bool_false() {
- _assertPerformToString(_stringValue("false"), _boolValue(false));
- }
-
- void test_performToString_bool_true() {
- _assertPerformToString(_stringValue("true"), _boolValue(true));
- }
-
- void test_performToString_bool_unknown() {
- _assertPerformToString(_stringValue(null), _boolValue(null));
- }
-
- void test_performToString_double_known() {
- _assertPerformToString(_stringValue("2.0"), _doubleValue(2.0));
- }
-
- void test_performToString_double_unknown() {
- _assertPerformToString(_stringValue(null), _doubleValue(null));
- }
-
- void test_performToString_int_known() {
- _assertPerformToString(_stringValue("5"), _intValue(5));
- }
-
- void test_performToString_int_unknown() {
- _assertPerformToString(_stringValue(null), _intValue(null));
- }
-
- void test_performToString_null() {
- _assertPerformToString(_stringValue("null"), _nullValue());
- }
-
- void test_performToString_string_known() {
- _assertPerformToString(_stringValue("abc"), _stringValue("abc"));
- }
-
- void test_performToString_string_unknown() {
- _assertPerformToString(_stringValue(null), _stringValue(null));
- }
-
- void test_remainder_knownDouble_knownDouble() {
- _assertRemainder(_doubleValue(1.0), _doubleValue(7.0), _doubleValue(2.0));
- }
-
- void test_remainder_knownDouble_knownInt() {
- _assertRemainder(_doubleValue(1.0), _doubleValue(7.0), _intValue(2));
- }
-
- void test_remainder_knownDouble_unknownDouble() {
- _assertRemainder(_doubleValue(null), _doubleValue(7.0), _doubleValue(null));
- }
-
- void test_remainder_knownDouble_unknownInt() {
- _assertRemainder(_doubleValue(null), _doubleValue(6.0), _intValue(null));
- }
-
- void test_remainder_knownInt_knownInt() {
- _assertRemainder(_intValue(1), _intValue(7), _intValue(2));
- }
-
- void test_remainder_knownInt_knownString() {
- _assertRemainder(null, _intValue(7), _stringValue("2"));
- }
-
- void test_remainder_knownInt_unknownDouble() {
- _assertRemainder(_doubleValue(null), _intValue(7), _doubleValue(null));
- }
-
- void test_remainder_knownInt_unknownInt() {
- _assertRemainder(_intValue(null), _intValue(7), _intValue(null));
- }
-
- void test_remainder_knownString_knownInt() {
- _assertRemainder(null, _stringValue("7"), _intValue(2));
- }
-
- void test_remainder_unknownDouble_knownDouble() {
- _assertRemainder(_doubleValue(null), _doubleValue(null), _doubleValue(2.0));
- }
-
- void test_remainder_unknownDouble_knownInt() {
- _assertRemainder(_doubleValue(null), _doubleValue(null), _intValue(2));
- }
-
- void test_remainder_unknownInt_knownDouble() {
- _assertRemainder(_doubleValue(null), _intValue(null), _doubleValue(2.0));
- }
-
- void test_remainder_unknownInt_knownInt() {
- _assertRemainder(_intValue(null), _intValue(null), _intValue(2));
- }
-
- void test_shiftLeft_knownInt_knownInt() {
- _assertShiftLeft(_intValue(48), _intValue(6), _intValue(3));
- }
-
- void test_shiftLeft_knownInt_knownString() {
- _assertShiftLeft(null, _intValue(6), _stringValue(null));
- }
-
- void test_shiftLeft_knownInt_tooLarge() {
- _assertShiftLeft(
- _intValue(null),
- _intValue(6),
- new DartObjectImpl(
- _typeProvider.intType, new IntState(LONG_MAX_VALUE)));
- }
-
- void test_shiftLeft_knownInt_unknownInt() {
- _assertShiftLeft(_intValue(null), _intValue(6), _intValue(null));
- }
-
- void test_shiftLeft_knownString_knownInt() {
- _assertShiftLeft(null, _stringValue(null), _intValue(3));
- }
-
- void test_shiftLeft_unknownInt_knownInt() {
- _assertShiftLeft(_intValue(null), _intValue(null), _intValue(3));
- }
-
- void test_shiftLeft_unknownInt_unknownInt() {
- _assertShiftLeft(_intValue(null), _intValue(null), _intValue(null));
- }
-
- void test_shiftRight_knownInt_knownInt() {
- _assertShiftRight(_intValue(6), _intValue(48), _intValue(3));
- }
-
- void test_shiftRight_knownInt_knownString() {
- _assertShiftRight(null, _intValue(48), _stringValue(null));
- }
-
- void test_shiftRight_knownInt_tooLarge() {
- _assertShiftRight(
- _intValue(null),
- _intValue(48),
- new DartObjectImpl(
- _typeProvider.intType, new IntState(LONG_MAX_VALUE)));
- }
-
- void test_shiftRight_knownInt_unknownInt() {
- _assertShiftRight(_intValue(null), _intValue(48), _intValue(null));
- }
-
- void test_shiftRight_knownString_knownInt() {
- _assertShiftRight(null, _stringValue(null), _intValue(3));
- }
-
- void test_shiftRight_unknownInt_knownInt() {
- _assertShiftRight(_intValue(null), _intValue(null), _intValue(3));
- }
-
- void test_shiftRight_unknownInt_unknownInt() {
- _assertShiftRight(_intValue(null), _intValue(null), _intValue(null));
- }
-
- void test_stringLength_int() {
- try {
- _assertStringLength(_intValue(null), _intValue(0));
- fail("Expected EvaluationException");
- } on EvaluationException {}
- }
-
- void test_stringLength_knownString() {
- _assertStringLength(_intValue(3), _stringValue("abc"));
- }
-
- void test_stringLength_unknownString() {
- _assertStringLength(_intValue(null), _stringValue(null));
- }
-
- void test_times_knownDouble_knownDouble() {
- _assertTimes(_doubleValue(6.0), _doubleValue(2.0), _doubleValue(3.0));
- }
-
- void test_times_knownDouble_knownInt() {
- _assertTimes(_doubleValue(6.0), _doubleValue(2.0), _intValue(3));
- }
-
- void test_times_knownDouble_unknownDouble() {
- _assertTimes(_doubleValue(null), _doubleValue(2.0), _doubleValue(null));
- }
-
- void test_times_knownDouble_unknownInt() {
- _assertTimes(_doubleValue(null), _doubleValue(2.0), _intValue(null));
- }
-
- void test_times_knownInt_knownInt() {
- _assertTimes(_intValue(6), _intValue(2), _intValue(3));
- }
-
- void test_times_knownInt_knownString() {
- _assertTimes(null, _intValue(2), _stringValue("3"));
- }
-
- void test_times_knownInt_unknownDouble() {
- _assertTimes(_doubleValue(null), _intValue(2), _doubleValue(null));
- }
-
- void test_times_knownInt_unknownInt() {
- _assertTimes(_intValue(null), _intValue(2), _intValue(null));
- }
-
- void test_times_knownString_knownInt() {
- _assertTimes(null, _stringValue("2"), _intValue(3));
- }
-
- void test_times_unknownDouble_knownDouble() {
- _assertTimes(_doubleValue(null), _doubleValue(null), _doubleValue(3.0));
- }
-
- void test_times_unknownDouble_knownInt() {
- _assertTimes(_doubleValue(null), _doubleValue(null), _intValue(3));
- }
-
- void test_times_unknownInt_knownDouble() {
- _assertTimes(_doubleValue(null), _intValue(null), _doubleValue(3.0));
- }
-
- void test_times_unknownInt_knownInt() {
- _assertTimes(_intValue(null), _intValue(null), _intValue(3));
- }
-
- /**
- * Assert that the result of adding the left and right operands is the expected value, or that the
- * operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertAdd(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.add(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = leftOperand.add(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of bit-anding the left and right operands is the expected value, or that
- * the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertBitAnd(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.bitAnd(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = leftOperand.bitAnd(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the bit-not of the operand is the expected value, or that the operation throws an
- * exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param operand the operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertBitNot(DartObjectImpl expected, DartObjectImpl operand) {
- if (expected == null) {
- try {
- operand.bitNot(_typeProvider);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = operand.bitNot(_typeProvider);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of bit-oring the left and right operands is the expected value, or that
- * the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertBitOr(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.bitOr(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = leftOperand.bitOr(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of bit-xoring the left and right operands is the expected value, or that
- * the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertBitXor(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.bitXor(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = leftOperand.bitXor(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of concatenating the left and right operands is the expected value, or
- * that the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertConcatenate(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.concatenate(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result =
- leftOperand.concatenate(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of dividing the left and right operands is the expected value, or that
- * the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertDivide(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.divide(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = leftOperand.divide(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of comparing the left and right operands for equality is the expected
- * value, or that the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertEqualEqual(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.equalEqual(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result =
- leftOperand.equalEqual(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of comparing the left and right operands is the expected value, or that
- * the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertGreaterThan(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.greaterThan(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result =
- leftOperand.greaterThan(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of comparing the left and right operands is the expected value, or that
- * the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertGreaterThanOrEqual(DartObjectImpl expected,
- DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.greaterThanOrEqual(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result =
- leftOperand.greaterThanOrEqual(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of comparing the left and right operands using
- * identical() is the expected value.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- */
- void _assertIdentical(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- DartObjectImpl result =
- leftOperand.isIdentical(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
-
- void _assertInstanceOfObjectArray(Object result) {
- // TODO(scheglov) implement
- }
-
- /**
- * Assert that the result of dividing the left and right operands as integers is the expected
- * value, or that the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertIntegerDivide(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.integerDivide(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result =
- leftOperand.integerDivide(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of comparing the left and right operands is the expected value, or that
- * the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertLessThan(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.lessThan(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = leftOperand.lessThan(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of comparing the left and right operands is the expected value, or that
- * the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertLessThanOrEqual(DartObjectImpl expected,
- DartObjectImpl leftOperand, DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.lessThanOrEqual(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result =
- leftOperand.lessThanOrEqual(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of logical-anding the left and right operands is the expected value, or
- * that the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertLogicalAnd(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.logicalAnd(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result =
- leftOperand.logicalAnd(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the logical-not of the operand is the expected value, or that the operation throws
- * an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param operand the operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertLogicalNot(DartObjectImpl expected, DartObjectImpl operand) {
- if (expected == null) {
- try {
- operand.logicalNot(_typeProvider);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = operand.logicalNot(_typeProvider);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of logical-oring the left and right operands is the expected value, or
- * that the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertLogicalOr(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.logicalOr(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result =
- leftOperand.logicalOr(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of subtracting the left and right operands is the expected value, or
- * that the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertMinus(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.minus(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = leftOperand.minus(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the negation of the operand is the expected value, or that the operation throws an
- * exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param operand the operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertNegated(DartObjectImpl expected, DartObjectImpl operand) {
- if (expected == null) {
- try {
- operand.negated(_typeProvider);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = operand.negated(_typeProvider);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of comparing the left and right operands for inequality is the expected
- * value, or that the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertNotEqual(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.notEqual(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = leftOperand.notEqual(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that converting the operand to a string is the expected value, or that the operation
- * throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param operand the operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertPerformToString(DartObjectImpl expected, DartObjectImpl operand) {
- if (expected == null) {
- try {
- operand.performToString(_typeProvider);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = operand.performToString(_typeProvider);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of taking the remainder of the left and right operands is the expected
- * value, or that the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertRemainder(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.remainder(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result =
- leftOperand.remainder(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of multiplying the left and right operands is the expected value, or
- * that the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertShiftLeft(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.shiftLeft(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result =
- leftOperand.shiftLeft(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of multiplying the left and right operands is the expected value, or
- * that the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the right operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertShiftRight(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.shiftRight(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result =
- leftOperand.shiftRight(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the length of the operand is the expected value, or that the operation throws an
- * exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param operand the operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertStringLength(DartObjectImpl expected, DartObjectImpl operand) {
- if (expected == null) {
- try {
- operand.stringLength(_typeProvider);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = operand.stringLength(_typeProvider);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- /**
- * Assert that the result of multiplying the left and right operands is the expected value, or
- * that the operation throws an exception if the expected value is `null`.
- *
- * @param expected the expected result of the operation
- * @param leftOperand the left operand to the operation
- * @param rightOperand the left operand to the operation
- * @throws EvaluationException if the result is an exception when it should not be
- */
- void _assertTimes(DartObjectImpl expected, DartObjectImpl leftOperand,
- DartObjectImpl rightOperand) {
- if (expected == null) {
- try {
- leftOperand.times(_typeProvider, rightOperand);
- fail("Expected an EvaluationException");
- } on EvaluationException {}
- } else {
- DartObjectImpl result = leftOperand.times(_typeProvider, rightOperand);
- expect(result, isNotNull);
- expect(result, expected);
- }
- }
-
- DartObjectImpl _boolValue(bool value) {
- if (value == null) {
- return new DartObjectImpl(
- _typeProvider.boolType, BoolState.UNKNOWN_VALUE);
- } else if (identical(value, false)) {
- return new DartObjectImpl(_typeProvider.boolType, BoolState.FALSE_STATE);
- } else if (identical(value, true)) {
- return new DartObjectImpl(_typeProvider.boolType, BoolState.TRUE_STATE);
- }
- fail("Invalid boolean value used in test");
- return null;
- }
-
- DartObjectImpl _doubleValue(double value) {
- if (value == null) {
- return new DartObjectImpl(
- _typeProvider.doubleType, DoubleState.UNKNOWN_VALUE);
- } else {
- return new DartObjectImpl(
- _typeProvider.doubleType, new DoubleState(value));
- }
- }
-
- DartObjectImpl _dynamicValue() {
- return new DartObjectImpl(
- _typeProvider.nullType, DynamicState.DYNAMIC_STATE);
- }
-
- DartObjectImpl _intValue(int value) {
- if (value == null) {
- return new DartObjectImpl(_typeProvider.intType, IntState.UNKNOWN_VALUE);
- } else {
- return new DartObjectImpl(_typeProvider.intType, new IntState(value));
- }
- }
-
- DartObjectImpl _listValue(
- [List<DartObjectImpl> elements = DartObjectImpl.EMPTY_LIST]) {
- return new DartObjectImpl(_typeProvider.listType, new ListState(elements));
- }
-
- DartObjectImpl _mapValue(
- [List<DartObjectImpl> keyElementPairs = DartObjectImpl.EMPTY_LIST]) {
- Map<DartObjectImpl, DartObjectImpl> map =
- new Map<DartObjectImpl, DartObjectImpl>();
- int count = keyElementPairs.length;
- for (int i = 0; i < count;) {
- map[keyElementPairs[i++]] = keyElementPairs[i++];
- }
- return new DartObjectImpl(_typeProvider.mapType, new MapState(map));
- }
-
- DartObjectImpl _nullValue() {
- return new DartObjectImpl(_typeProvider.nullType, NullState.NULL_STATE);
- }
-
- DartObjectImpl _numValue() {
- return new DartObjectImpl(_typeProvider.nullType, NumState.UNKNOWN_VALUE);
- }
-
- DartObjectImpl _stringValue(String value) {
- if (value == null) {
- return new DartObjectImpl(
- _typeProvider.stringType, StringState.UNKNOWN_VALUE);
- } else {
- return new DartObjectImpl(
- _typeProvider.stringType, new StringState(value));
- }
- }
-
- DartObjectImpl _symbolValue(String value) {
- return new DartObjectImpl(_typeProvider.symbolType, new SymbolState(value));
- }
-}
-
-@reflectiveTest
-class DeclaredVariablesTest extends EngineTestCase {
- void test_getBool_false() {
- TestTypeProvider typeProvider = new TestTypeProvider();
- String variableName = "var";
- DeclaredVariables variables = new DeclaredVariables();
- variables.define(variableName, "false");
- DartObject object = variables.getBool(typeProvider, variableName);
- expect(object, isNotNull);
- expect(object.toBoolValue(), false);
- }
-
- void test_getBool_invalid() {
- TestTypeProvider typeProvider = new TestTypeProvider();
- String variableName = "var";
- DeclaredVariables variables = new DeclaredVariables();
- variables.define(variableName, "not true");
- _assertNullDartObject(
- typeProvider, variables.getBool(typeProvider, variableName));
- }
-
- void test_getBool_true() {
- TestTypeProvider typeProvider = new TestTypeProvider();
- String variableName = "var";
- DeclaredVariables variables = new DeclaredVariables();
- variables.define(variableName, "true");
- DartObject object = variables.getBool(typeProvider, variableName);
- expect(object, isNotNull);
- expect(object.toBoolValue(), true);
- }
-
- void test_getBool_undefined() {
- TestTypeProvider typeProvider = new TestTypeProvider();
- String variableName = "var";
- DeclaredVariables variables = new DeclaredVariables();
- _assertUnknownDartObject(
- typeProvider.boolType, variables.getBool(typeProvider, variableName));
- }
-
- void test_getInt_invalid() {
- TestTypeProvider typeProvider = new TestTypeProvider();
- String variableName = "var";
- DeclaredVariables variables = new DeclaredVariables();
- variables.define(variableName, "four score and seven years");
- _assertNullDartObject(
- typeProvider, variables.getInt(typeProvider, variableName));
- }
-
- void test_getInt_undefined() {
- TestTypeProvider typeProvider = new TestTypeProvider();
- String variableName = "var";
- DeclaredVariables variables = new DeclaredVariables();
- _assertUnknownDartObject(
- typeProvider.intType, variables.getInt(typeProvider, variableName));
- }
-
- void test_getInt_valid() {
- TestTypeProvider typeProvider = new TestTypeProvider();
- String variableName = "var";
- DeclaredVariables variables = new DeclaredVariables();
- variables.define(variableName, "23");
- DartObject object = variables.getInt(typeProvider, variableName);
- expect(object, isNotNull);
- expect(object.toIntValue(), 23);
- }
-
- void test_getString_defined() {
- TestTypeProvider typeProvider = new TestTypeProvider();
- String variableName = "var";
- String value = "value";
- DeclaredVariables variables = new DeclaredVariables();
- variables.define(variableName, value);
- DartObject object = variables.getString(typeProvider, variableName);
- expect(object, isNotNull);
- expect(object.toStringValue(), value);
- }
-
- void test_getString_undefined() {
- TestTypeProvider typeProvider = new TestTypeProvider();
- String variableName = "var";
- DeclaredVariables variables = new DeclaredVariables();
- _assertUnknownDartObject(typeProvider.stringType,
- variables.getString(typeProvider, variableName));
- }
-
- void _assertNullDartObject(TestTypeProvider typeProvider, DartObject result) {
- expect(result.type, typeProvider.nullType);
- }
-
- void _assertUnknownDartObject(
- ParameterizedType expectedType, DartObject result) {
- expect((result as DartObjectImpl).isUnknown, isTrue);
- expect(result.type, expectedType);
- }
-}
-
-@reflectiveTest
-class ReferenceFinderTest {
- DirectedGraph<ConstantEvaluationTarget> _referenceGraph;
- VariableElement _head;
- Element _tail;
-
- void setUp() {
- _referenceGraph = new DirectedGraph<ConstantEvaluationTarget>();
- _head = ElementFactory.topLevelVariableElement2("v1");
- }
-
- void test_visitSimpleIdentifier_const() {
- _visitNode(_makeTailVariable("v2", true));
- _assertOneArc(_tail);
- }
-
- void test_visitSuperConstructorInvocation_const() {
- _visitNode(_makeTailSuperConstructorInvocation("A", true));
- _assertOneArc(_tail);
- }
-
- void test_visitSuperConstructorInvocation_nonConst() {
- _visitNode(_makeTailSuperConstructorInvocation("A", false));
- _assertOneArc(_tail);
- }
-
- void test_visitSuperConstructorInvocation_unresolved() {
- SuperConstructorInvocation superConstructorInvocation =
- AstFactory.superConstructorInvocation();
- _visitNode(superConstructorInvocation);
- _assertNoArcs();
- }
-
- void _assertNoArcs() {
- Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
- expect(tails, hasLength(0));
- }
-
- void _assertOneArc(Element tail) {
- Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
- expect(tails, hasLength(1));
- expect(tails.first, same(tail));
- }
-
- ReferenceFinder _createReferenceFinder(ConstantEvaluationTarget source) =>
- new ReferenceFinder((ConstantEvaluationTarget dependency) {
- _referenceGraph.addEdge(source, dependency);
- });
- SuperConstructorInvocation _makeTailSuperConstructorInvocation(
- String name, bool isConst) {
- List<ConstructorInitializer> initializers =
- new List<ConstructorInitializer>();
- ConstructorDeclaration constructorDeclaration =
- AstFactory.constructorDeclaration(AstFactory.identifier3(name), null,
- AstFactory.formalParameterList(), initializers);
- if (isConst) {
- constructorDeclaration.constKeyword = new KeywordToken(Keyword.CONST, 0);
- }
- ClassElementImpl classElement = ElementFactory.classElement2(name);
- SuperConstructorInvocation superConstructorInvocation =
- AstFactory.superConstructorInvocation();
- ConstructorElementImpl constructorElement =
- ElementFactory.constructorElement(classElement, name, isConst);
- _tail = constructorElement;
- superConstructorInvocation.staticElement = constructorElement;
- return superConstructorInvocation;
- }
-
- SimpleIdentifier _makeTailVariable(String name, bool isConst) {
- VariableDeclaration variableDeclaration =
- AstFactory.variableDeclaration(name);
- ConstLocalVariableElementImpl variableElement =
- ElementFactory.constLocalVariableElement(name);
- _tail = variableElement;
- variableElement.const3 = isConst;
- AstFactory.variableDeclarationList2(
- isConst ? Keyword.CONST : Keyword.VAR, [variableDeclaration]);
- SimpleIdentifier identifier = AstFactory.identifier3(name);
- identifier.staticElement = variableElement;
- return identifier;
- }
-
- void _visitNode(AstNode node) {
- node.accept(_createReferenceFinder(_head));
- }
-}
-
-class _TestAnalysisContext extends TestAnalysisContext {
- @override
- InternalAnalysisContext getContextFor(Source source) => this;
-}
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
index ac762c4b..02993c5 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -1917,6 +1917,26 @@
[StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE]);
}
+ void test_forIn_object() {
+ assertNoErrorsInCode(
+ '''
+f() {
+ Object o; // Could be [].
+ for (var i in o) {}
+}
+''');
+ }
+
+ void test_forIn_dynamic() {
+ assertNoErrorsInCode(
+ '''
+f() {
+ dynamic d; // Could be [].
+ for (var i in d) {}
+}
+''');
+ }
+
void test_forIn_declaredVariableWrongType() {
assertErrorsInCode(
'''
diff --git a/pkg/analyzer/test/source/error_processor_test.dart b/pkg/analyzer/test/source/error_processor_test.dart
index 864bbf8..d7aaeee 100644
--- a/pkg/analyzer/test/source/error_processor_test.dart
+++ b/pkg/analyzer/test/source/error_processor_test.dart
@@ -39,6 +39,11 @@
['x']
]);
+ AnalysisError non_bool_operand = new AnalysisError(
+ new TestSource(), 0, 1, StaticTypeWarningCode.NON_BOOL_OPERAND, [
+ ['x']
+ ]);
+
oneTimeSetup();
setUp(() {
@@ -66,7 +71,15 @@
analyzer:
strong-mode: true
''');
- expect(getProcessor(invalid_assignment).severity, ErrorSeverity.ERROR);
+ expect(getProcessor(non_bool_operand).severity, ErrorSeverity.ERROR);
+ });
+
+ test('does not upgrade other warnings to errors in strong mode', () {
+ configureOptions('''
+analyzer:
+ strong-mode: true
+''');
+ expect(getProcessor(unused_local_variable), isNull);
});
});
diff --git a/pkg/analyzer/test/src/context/cache_test.dart b/pkg/analyzer/test/src/context/cache_test.dart
index 37bd49c..3c44f09 100644
--- a/pkg/analyzer/test/src/context/cache_test.dart
+++ b/pkg/analyzer/test/src/context/cache_test.dart
@@ -1127,7 +1127,7 @@
@override
DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
- ResultDescriptor descriptor) {
+ ResultDescriptor descriptor, Object value) {
if (descriptor == keepDescriptor) {
return DeltaResult.KEEP_CONTINUE;
}
diff --git a/pkg/analyzer/test/src/context/mock_sdk.dart b/pkg/analyzer/test/src/context/mock_sdk.dart
index 715ad1c..8103e12 100644
--- a/pkg/analyzer/test/src/context/mock_sdk.dart
+++ b/pkg/analyzer/test/src/context/mock_sdk.dart
@@ -158,6 +158,15 @@
void operator []=(int index, E value) {}
Iterator<E> get iterator => null;
void clear() {}
+
+ bool get isEmpty => false;
+ E get first => null;
+
+ Iterable/*<R>*/ map/*<R>*/(/*=R*/ f(E e)) => null;
+
+ /*=R*/ fold/*<R>*/(/*=R*/ initialValue,
+ /*=R*/ combine(/*=R*/ previousValue, E element)) => null;
+
}
class Map<K, V> extends Object {
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
new file mode 100644
index 0000000..960726e
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -0,0 +1,1603 @@
+// 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 analyzer.test.constant_test;
+
+import 'package:analyzer/context/declared_variables.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/error.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/generated/testing/ast_factory.dart';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:path/path.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../../generated/resolver_test_case.dart';
+import '../../../generated/test_support.dart';
+import '../../../reflective_tests.dart';
+import '../../../utils.dart';
+
+main() {
+ initializeTestEnvironment();
+ runReflectiveTests(ConstantValueComputerTest);
+ runReflectiveTests(ConstantVisitorTest);
+}
+
+/**
+ * Implementation of [ConstantEvaluationValidator] used during unit tests;
+ * verifies that any nodes referenced during constant evaluation are present in
+ * the dependency graph.
+ */
+class ConstantEvaluationValidator_ForTest
+ implements ConstantEvaluationValidator {
+ final InternalAnalysisContext context;
+ ConstantValueComputer computer;
+ ConstantEvaluationTarget _nodeBeingEvaluated;
+
+ ConstantEvaluationValidator_ForTest(this.context);
+
+ @override
+ void beforeComputeValue(ConstantEvaluationTarget constant) {
+ _nodeBeingEvaluated = constant;
+ }
+
+ @override
+ void beforeGetConstantInitializers(ConstructorElement constructor) =>
+ _checkPathTo(constructor);
+
+ @override
+ void beforeGetEvaluationResult(ConstantEvaluationTarget constant) =>
+ _checkPathTo(constant);
+
+ @override
+ void beforeGetFieldEvaluationResult(FieldElementImpl field) =>
+ _checkPathTo(field);
+
+ @override
+ void beforeGetParameterDefault(ParameterElement parameter) =>
+ _checkPathTo(parameter);
+
+ void _checkPathTo(ConstantEvaluationTarget target) {
+ if (computer.referenceGraph.containsPath(_nodeBeingEvaluated, target)) {
+ return; // pass
+ }
+ // print a nice error message on failure
+ StringBuffer out = new StringBuffer();
+ out.writeln("missing path in constant dependency graph");
+ out.writeln("from $_nodeBeingEvaluated to $target");
+ for (var s in context.analysisCache.sources) {
+ String text = context.getContents(s).data;
+ if (text != "") {
+ out.writeln('''
+=== ${s.shortName}
+$text''');
+ }
+ }
+ fail(out.toString());
+ }
+}
+
+@reflectiveTest
+class ConstantValueComputerTest extends ResolverTestCase {
+ void test_annotation_constConstructor() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+ final int i;
+ const A(this.i);
+}
+
+class C {
+ @A(5)
+ f() {}
+}
+''');
+ EvaluationResultImpl result =
+ _evaluateAnnotation(compilationUnit, "C", "f");
+ Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A');
+ _assertIntField(annotationFields, 'i', 5);
+ }
+
+ void test_annotation_constConstructor_named() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+ final int i;
+ const A.named(this.i);
+}
+
+class C {
+ @A.named(5)
+ f() {}
+}
+''');
+ EvaluationResultImpl result =
+ _evaluateAnnotation(compilationUnit, "C", "f");
+ Map<String, DartObjectImpl> annotationFields = _assertType(result, 'A');
+ _assertIntField(annotationFields, 'i', 5);
+ }
+
+ void test_annotation_constConstructor_noArgs() {
+ // Failing to pass arguments to an annotation which is a constant
+ // constructor is illegal, but shouldn't crash analysis.
+ CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+ final int i;
+ const A(this.i);
+}
+
+class C {
+ @A
+ f() {}
+}
+''');
+ _evaluateAnnotation(compilationUnit, "C", "f");
+ }
+
+ void test_annotation_constConstructor_noArgs_named() {
+ // Failing to pass arguments to an annotation which is a constant
+ // constructor is illegal, but shouldn't crash analysis.
+ CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+ final int i;
+ const A.named(this.i);
+}
+
+class C {
+ @A.named
+ f() {}
+}
+''');
+ _evaluateAnnotation(compilationUnit, "C", "f");
+ }
+
+ void test_annotation_nonConstConstructor() {
+ // Calling a non-const constructor from an annotation that is illegal, but
+ // shouldn't crash analysis.
+ CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+ final int i;
+ A(this.i);
+}
+
+class C {
+ @A(5)
+ f() {}
+}
+''');
+ _evaluateAnnotation(compilationUnit, "C", "f");
+ }
+
+ void test_annotation_staticConst() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+class C {
+ static const int i = 5;
+
+ @i
+ f() {}
+}
+''');
+ EvaluationResultImpl result =
+ _evaluateAnnotation(compilationUnit, "C", "f");
+ expect(_assertValidInt(result), 5);
+ }
+
+ void test_annotation_staticConst_args() {
+ // Applying arguments to an annotation that is a static const is
+ // illegal, but shouldn't crash analysis.
+ CompilationUnit compilationUnit = resolveSource(r'''
+class C {
+ static const int i = 5;
+
+ @i(1)
+ f() {}
+}
+''');
+ _evaluateAnnotation(compilationUnit, "C", "f");
+ }
+
+ void test_annotation_staticConst_otherClass() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+ static const int i = 5;
+}
+
+class C {
+ @A.i
+ f() {}
+}
+''');
+ EvaluationResultImpl result =
+ _evaluateAnnotation(compilationUnit, "C", "f");
+ expect(_assertValidInt(result), 5);
+ }
+
+ void test_annotation_staticConst_otherClass_args() {
+ // Applying arguments to an annotation that is a static const is
+ // illegal, but shouldn't crash analysis.
+ CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+ static const int i = 5;
+}
+
+class C {
+ @A.i(1)
+ f() {}
+}
+''');
+ _evaluateAnnotation(compilationUnit, "C", "f");
+ }
+
+ void test_annotation_topLevelVariable() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const int i = 5;
+class C {
+ @i
+ f() {}
+}
+''');
+ EvaluationResultImpl result =
+ _evaluateAnnotation(compilationUnit, "C", "f");
+ expect(_assertValidInt(result), 5);
+ }
+
+ void test_annotation_topLevelVariable_args() {
+ // Applying arguments to an annotation that is a top-level variable is
+ // illegal, but shouldn't crash analysis.
+ CompilationUnit compilationUnit = resolveSource(r'''
+const int i = 5;
+class C {
+ @i(1)
+ f() {}
+}
+''');
+ _evaluateAnnotation(compilationUnit, "C", "f");
+ }
+
+ void test_computeValues_cycle() {
+ TestLogger logger = new TestLogger();
+ AnalysisEngine.instance.logger = logger;
+ try {
+ Source source = addSource(r'''
+ const int a = c;
+ const int b = a;
+ const int c = b;''');
+ LibraryElement libraryElement = resolve2(source);
+ CompilationUnit unit =
+ analysisContext.resolveCompilationUnit(source, libraryElement);
+ analysisContext.computeErrors(source);
+ expect(unit, isNotNull);
+ ConstantValueComputer computer = _makeConstantValueComputer();
+ computer.add(unit, source, source);
+ computer.computeValues();
+ NodeList<CompilationUnitMember> members = unit.declarations;
+ expect(members, hasLength(3));
+ _validate(false, (members[0] as TopLevelVariableDeclaration).variables);
+ _validate(false, (members[1] as TopLevelVariableDeclaration).variables);
+ _validate(false, (members[2] as TopLevelVariableDeclaration).variables);
+ } finally {
+ AnalysisEngine.instance.logger = Logger.NULL;
+ }
+ }
+
+ void test_computeValues_dependentVariables() {
+ Source source = addSource(r'''
+const int b = a;
+const int a = 0;''');
+ LibraryElement libraryElement = resolve2(source);
+ CompilationUnit unit =
+ analysisContext.resolveCompilationUnit(source, libraryElement);
+ expect(unit, isNotNull);
+ ConstantValueComputer computer = _makeConstantValueComputer();
+ computer.add(unit, source, source);
+ computer.computeValues();
+ NodeList<CompilationUnitMember> members = unit.declarations;
+ expect(members, hasLength(2));
+ _validate(true, (members[0] as TopLevelVariableDeclaration).variables);
+ _validate(true, (members[1] as TopLevelVariableDeclaration).variables);
+ }
+
+ void test_computeValues_empty() {
+ ConstantValueComputer computer = _makeConstantValueComputer();
+ computer.computeValues();
+ }
+
+ void test_computeValues_multipleSources() {
+ Source librarySource = addNamedSource(
+ "/lib.dart",
+ r'''
+library lib;
+part 'part.dart';
+const int c = b;
+const int a = 0;''');
+ Source partSource = addNamedSource(
+ "/part.dart",
+ r'''
+part of lib;
+const int b = a;
+const int d = c;''');
+ LibraryElement libraryElement = resolve2(librarySource);
+ CompilationUnit libraryUnit =
+ analysisContext.resolveCompilationUnit(librarySource, libraryElement);
+ expect(libraryUnit, isNotNull);
+ CompilationUnit partUnit =
+ analysisContext.resolveCompilationUnit(partSource, libraryElement);
+ expect(partUnit, isNotNull);
+ ConstantValueComputer computer = _makeConstantValueComputer();
+ computer.add(libraryUnit, librarySource, librarySource);
+ computer.add(partUnit, partSource, librarySource);
+ computer.computeValues();
+ NodeList<CompilationUnitMember> libraryMembers = libraryUnit.declarations;
+ expect(libraryMembers, hasLength(2));
+ _validate(
+ true, (libraryMembers[0] as TopLevelVariableDeclaration).variables);
+ _validate(
+ true, (libraryMembers[1] as TopLevelVariableDeclaration).variables);
+ NodeList<CompilationUnitMember> partMembers = libraryUnit.declarations;
+ expect(partMembers, hasLength(2));
+ _validate(true, (partMembers[0] as TopLevelVariableDeclaration).variables);
+ _validate(true, (partMembers[1] as TopLevelVariableDeclaration).variables);
+ }
+
+ void test_computeValues_singleVariable() {
+ Source source = addSource("const int a = 0;");
+ LibraryElement libraryElement = resolve2(source);
+ CompilationUnit unit =
+ analysisContext.resolveCompilationUnit(source, libraryElement);
+ expect(unit, isNotNull);
+ ConstantValueComputer computer = _makeConstantValueComputer();
+ computer.add(unit, source, source);
+ computer.computeValues();
+ NodeList<CompilationUnitMember> members = unit.declarations;
+ expect(members, hasLength(1));
+ _validate(true, (members[0] as TopLevelVariableDeclaration).variables);
+ }
+
+ void test_computeValues_value_depends_on_enum() {
+ Source source = addSource('''
+enum E { id0, id1 }
+const E e = E.id0;
+''');
+ LibraryElement libraryElement = resolve2(source);
+ CompilationUnit unit =
+ analysisContext.resolveCompilationUnit(source, libraryElement);
+ expect(unit, isNotNull);
+ ConstantValueComputer computer = _makeConstantValueComputer();
+ computer.add(unit, source, source);
+ computer.computeValues();
+ TopLevelVariableDeclaration declaration = unit.declarations
+ .firstWhere((member) => member is TopLevelVariableDeclaration);
+ _validate(true, declaration.variables);
+ }
+
+ void test_dependencyOnConstructor() {
+ // x depends on "const A()"
+ _assertProperDependencies(r'''
+class A {
+ const A();
+}
+const x = const A();''');
+ }
+
+ void test_dependencyOnConstructorArgument() {
+ // "const A(x)" depends on x
+ _assertProperDependencies(r'''
+class A {
+ const A(this.next);
+ final A next;
+}
+const A x = const A(null);
+const A y = const A(x);''');
+ }
+
+ void test_dependencyOnConstructorArgument_unresolvedConstructor() {
+ // "const A.a(x)" depends on x even if the constructor A.a can't be found.
+ _assertProperDependencies(
+ r'''
+class A {
+}
+const int x = 1;
+const A y = const A.a(x);''',
+ [CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR]);
+ }
+
+ void test_dependencyOnConstructorInitializer() {
+ // "const A()" depends on x
+ _assertProperDependencies(r'''
+const int x = 1;
+class A {
+ const A() : v = x;
+ final int v;
+}''');
+ }
+
+ void test_dependencyOnExplicitSuperConstructor() {
+ // b depends on B() depends on A()
+ _assertProperDependencies(r'''
+class A {
+ const A(this.x);
+ final int x;
+}
+class B extends A {
+ const B() : super(5);
+}
+const B b = const B();''');
+ }
+
+ void test_dependencyOnExplicitSuperConstructorParameters() {
+ // b depends on B() depends on i
+ _assertProperDependencies(r'''
+class A {
+ const A(this.x);
+ final int x;
+}
+class B extends A {
+ const B() : super(i);
+}
+const B b = const B();
+const int i = 5;''');
+ }
+
+ void test_dependencyOnFactoryRedirect() {
+ // a depends on A.foo() depends on A.bar()
+ _assertProperDependencies(r'''
+const A a = const A.foo();
+class A {
+ factory const A.foo() = A.bar;
+ const A.bar();
+}''');
+ }
+
+ void test_dependencyOnFactoryRedirectWithTypeParams() {
+ _assertProperDependencies(r'''
+class A {
+ const factory A(var a) = B<int>;
+}
+
+class B<T> implements A {
+ final T x;
+ const B(this.x);
+}
+
+const A a = const A(10);''');
+ }
+
+ void test_dependencyOnImplicitSuperConstructor() {
+ // b depends on B() depends on A()
+ _assertProperDependencies(r'''
+class A {
+ const A() : x = 5;
+ final int x;
+}
+class B extends A {
+ const B();
+}
+const B b = const B();''');
+ }
+
+ void test_dependencyOnInitializedFinal() {
+ // a depends on A() depends on A.x
+ _assertProperDependencies('''
+class A {
+ const A();
+ final int x = 1;
+}
+const A a = const A();
+''');
+ }
+
+ void test_dependencyOnInitializedNonStaticConst() {
+ // Even though non-static consts are not allowed by the language, we need
+ // to handle them for error recovery purposes.
+ // a depends on A() depends on A.x
+ _assertProperDependencies(
+ '''
+class A {
+ const A();
+ const int x = 1;
+}
+const A a = const A();
+''',
+ [CompileTimeErrorCode.CONST_INSTANCE_FIELD]);
+ }
+
+ void test_dependencyOnNonFactoryRedirect() {
+ // a depends on A.foo() depends on A.bar()
+ _assertProperDependencies(r'''
+const A a = const A.foo();
+class A {
+ const A.foo() : this.bar();
+ const A.bar();
+}''');
+ }
+
+ void test_dependencyOnNonFactoryRedirect_arg() {
+ // a depends on A.foo() depends on b
+ _assertProperDependencies(r'''
+const A a = const A.foo();
+const int b = 1;
+class A {
+ const A.foo() : this.bar(b);
+ const A.bar(x) : y = x;
+ final int y;
+}''');
+ }
+
+ void test_dependencyOnNonFactoryRedirect_defaultValue() {
+ // a depends on A.foo() depends on A.bar() depends on b
+ _assertProperDependencies(r'''
+const A a = const A.foo();
+const int b = 1;
+class A {
+ const A.foo() : this.bar();
+ const A.bar([x = b]) : y = x;
+ final int y;
+}''');
+ }
+
+ void test_dependencyOnNonFactoryRedirect_toMissing() {
+ // a depends on A.foo() which depends on nothing, since A.bar() is
+ // missing.
+ _assertProperDependencies(
+ r'''
+const A a = const A.foo();
+class A {
+ const A.foo() : this.bar();
+}''',
+ [CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR]);
+ }
+
+ void test_dependencyOnNonFactoryRedirect_toNonConst() {
+ // a depends on A.foo() which depends on nothing, since A.bar() is
+ // non-const.
+ _assertProperDependencies(r'''
+const A a = const A.foo();
+class A {
+ const A.foo() : this.bar();
+ A.bar();
+}''');
+ }
+
+ void test_dependencyOnNonFactoryRedirect_unnamed() {
+ // a depends on A.foo() depends on A()
+ _assertProperDependencies(r'''
+const A a = const A.foo();
+class A {
+ const A.foo() : this();
+ const A();
+}''');
+ }
+
+ void test_dependencyOnOptionalParameterDefault() {
+ // a depends on A() depends on B()
+ _assertProperDependencies(r'''
+class A {
+ const A([x = const B()]) : b = x;
+ final B b;
+}
+class B {
+ const B();
+}
+const A a = const A();''');
+ }
+
+ void test_dependencyOnVariable() {
+ // x depends on y
+ _assertProperDependencies(r'''
+const x = y + 1;
+const y = 2;''');
+ }
+
+ void test_final_initialized_at_declaration() {
+ CompilationUnit compilationUnit = resolveSource('''
+class A {
+ final int i = 123;
+ const A();
+}
+
+const A a = const A();
+''');
+ EvaluationResultImpl result =
+ _evaluateTopLevelVariable(compilationUnit, 'a');
+ Map<String, DartObjectImpl> fields = _assertType(result, "A");
+ expect(fields, hasLength(1));
+ _assertIntField(fields, "i", 123);
+ }
+
+ void test_fromEnvironment_bool_default_false() {
+ expect(_assertValidBool(_check_fromEnvironment_bool(null, "false")), false);
+ }
+
+ void test_fromEnvironment_bool_default_overridden() {
+ expect(
+ _assertValidBool(_check_fromEnvironment_bool("false", "true")), false);
+ }
+
+ void test_fromEnvironment_bool_default_parseError() {
+ expect(_assertValidBool(_check_fromEnvironment_bool("parseError", "true")),
+ true);
+ }
+
+ void test_fromEnvironment_bool_default_true() {
+ expect(_assertValidBool(_check_fromEnvironment_bool(null, "true")), true);
+ }
+
+ void test_fromEnvironment_bool_false() {
+ expect(_assertValidBool(_check_fromEnvironment_bool("false", null)), false);
+ }
+
+ void test_fromEnvironment_bool_parseError() {
+ expect(_assertValidBool(_check_fromEnvironment_bool("parseError", null)),
+ false);
+ }
+
+ void test_fromEnvironment_bool_true() {
+ expect(_assertValidBool(_check_fromEnvironment_bool("true", null)), true);
+ }
+
+ void test_fromEnvironment_bool_undeclared() {
+ _assertValidUnknown(_check_fromEnvironment_bool(null, null));
+ }
+
+ void test_fromEnvironment_int_default_overridden() {
+ expect(_assertValidInt(_check_fromEnvironment_int("234", "123")), 234);
+ }
+
+ void test_fromEnvironment_int_default_parseError() {
+ expect(
+ _assertValidInt(_check_fromEnvironment_int("parseError", "123")), 123);
+ }
+
+ void test_fromEnvironment_int_default_undeclared() {
+ expect(_assertValidInt(_check_fromEnvironment_int(null, "123")), 123);
+ }
+
+ void test_fromEnvironment_int_ok() {
+ expect(_assertValidInt(_check_fromEnvironment_int("234", null)), 234);
+ }
+
+ void test_fromEnvironment_int_parseError() {
+ _assertValidNull(_check_fromEnvironment_int("parseError", null));
+ }
+
+ void test_fromEnvironment_int_parseError_nullDefault() {
+ _assertValidNull(_check_fromEnvironment_int("parseError", "null"));
+ }
+
+ void test_fromEnvironment_int_undeclared() {
+ _assertValidUnknown(_check_fromEnvironment_int(null, null));
+ }
+
+ void test_fromEnvironment_int_undeclared_nullDefault() {
+ _assertValidNull(_check_fromEnvironment_int(null, "null"));
+ }
+
+ void test_fromEnvironment_string_default_overridden() {
+ expect(_assertValidString(_check_fromEnvironment_string("abc", "'def'")),
+ "abc");
+ }
+
+ void test_fromEnvironment_string_default_undeclared() {
+ expect(_assertValidString(_check_fromEnvironment_string(null, "'def'")),
+ "def");
+ }
+
+ void test_fromEnvironment_string_empty() {
+ expect(_assertValidString(_check_fromEnvironment_string("", null)), "");
+ }
+
+ void test_fromEnvironment_string_ok() {
+ expect(
+ _assertValidString(_check_fromEnvironment_string("abc", null)), "abc");
+ }
+
+ void test_fromEnvironment_string_undeclared() {
+ _assertValidUnknown(_check_fromEnvironment_string(null, null));
+ }
+
+ void test_fromEnvironment_string_undeclared_nullDefault() {
+ _assertValidNull(_check_fromEnvironment_string(null, "null"));
+ }
+
+ void test_instanceCreationExpression_computedField() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(4, 5);
+class A {
+ const A(int i, int j) : k = 2 * i + j;
+ final int k;
+}''');
+ EvaluationResultImpl result =
+ _evaluateTopLevelVariable(compilationUnit, "foo");
+ Map<String, DartObjectImpl> fields = _assertType(result, "A");
+ expect(fields, hasLength(1));
+ _assertIntField(fields, "k", 13);
+ }
+
+ void
+ test_instanceCreationExpression_computedField_namedOptionalWithDefault() {
+ _checkInstanceCreationOptionalParams(false, true, true);
+ }
+
+ void
+ test_instanceCreationExpression_computedField_namedOptionalWithoutDefault() {
+ _checkInstanceCreationOptionalParams(false, true, false);
+ }
+
+ void
+ test_instanceCreationExpression_computedField_unnamedOptionalWithDefault() {
+ _checkInstanceCreationOptionalParams(false, false, true);
+ }
+
+ void
+ test_instanceCreationExpression_computedField_unnamedOptionalWithoutDefault() {
+ _checkInstanceCreationOptionalParams(false, false, false);
+ }
+
+ void test_instanceCreationExpression_computedField_usesConstConstructor() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(3);
+class A {
+ const A(int i) : b = const B(4);
+ final int b;
+}
+class B {
+ const B(this.k);
+ final int k;
+}''');
+ EvaluationResultImpl result =
+ _evaluateTopLevelVariable(compilationUnit, "foo");
+ Map<String, DartObjectImpl> fieldsOfA = _assertType(result, "A");
+ expect(fieldsOfA, hasLength(1));
+ Map<String, DartObjectImpl> fieldsOfB =
+ _assertFieldType(fieldsOfA, "b", "B");
+ expect(fieldsOfB, hasLength(1));
+ _assertIntField(fieldsOfB, "k", 4);
+ }
+
+ void test_instanceCreationExpression_computedField_usesStaticConst() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(3);
+class A {
+ const A(int i) : k = i + B.bar;
+ final int k;
+}
+class B {
+ static const bar = 4;
+}''');
+ EvaluationResultImpl result =
+ _evaluateTopLevelVariable(compilationUnit, "foo");
+ Map<String, DartObjectImpl> fields = _assertType(result, "A");
+ expect(fields, hasLength(1));
+ _assertIntField(fields, "k", 7);
+ }
+
+ void test_instanceCreationExpression_computedField_usesTopLevelConst() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(3);
+const bar = 4;
+class A {
+ const A(int i) : k = i + bar;
+ final int k;
+}''');
+ EvaluationResultImpl result =
+ _evaluateTopLevelVariable(compilationUnit, "foo");
+ Map<String, DartObjectImpl> fields = _assertType(result, "A");
+ expect(fields, hasLength(1));
+ _assertIntField(fields, "k", 7);
+ }
+
+ void test_instanceCreationExpression_explicitSuper() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const B(4, 5);
+class A {
+ const A(this.x);
+ final int x;
+}
+class B extends A {
+ const B(int x, this.y) : super(x * 2);
+ final int y;
+}''');
+ EvaluationResultImpl result =
+ _evaluateTopLevelVariable(compilationUnit, "foo");
+ Map<String, DartObjectImpl> fields = _assertType(result, "B");
+ expect(fields, hasLength(2));
+ _assertIntField(fields, "y", 5);
+ Map<String, DartObjectImpl> superclassFields =
+ _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A");
+ expect(superclassFields, hasLength(1));
+ _assertIntField(superclassFields, "x", 8);
+ }
+
+ void test_instanceCreationExpression_fieldFormalParameter() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A(42);
+class A {
+ int x;
+ const A(this.x)
+}''');
+ EvaluationResultImpl result =
+ _evaluateTopLevelVariable(compilationUnit, "foo");
+ Map<String, DartObjectImpl> fields = _assertType(result, "A");
+ expect(fields, hasLength(1));
+ _assertIntField(fields, "x", 42);
+ }
+
+ void
+ test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithDefault() {
+ _checkInstanceCreationOptionalParams(true, true, true);
+ }
+
+ void
+ test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithoutDefault() {
+ _checkInstanceCreationOptionalParams(true, true, false);
+ }
+
+ void
+ test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithDefault() {
+ _checkInstanceCreationOptionalParams(true, false, true);
+ }
+
+ void
+ test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithoutDefault() {
+ _checkInstanceCreationOptionalParams(true, false, false);
+ }
+
+ void test_instanceCreationExpression_implicitSuper() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const B(4);
+class A {
+ const A() : x = 3;
+ final int x;
+}
+class B extends A {
+ const B(this.y);
+ final int y;
+}''');
+ EvaluationResultImpl result =
+ _evaluateTopLevelVariable(compilationUnit, "foo");
+ Map<String, DartObjectImpl> fields = _assertType(result, "B");
+ expect(fields, hasLength(2));
+ _assertIntField(fields, "y", 4);
+ Map<String, DartObjectImpl> superclassFields =
+ _assertFieldType(fields, GenericState.SUPERCLASS_FIELD, "A");
+ expect(superclassFields, hasLength(1));
+ _assertIntField(superclassFields, "x", 3);
+ }
+
+ void test_instanceCreationExpression_nonFactoryRedirect() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+ const A.a1() : this.a2();
+ const A.a2() : x = 5;
+ final int x;
+}''');
+ Map<String, DartObjectImpl> aFields =
+ _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+ _assertIntField(aFields, 'x', 5);
+ }
+
+ void test_instanceCreationExpression_nonFactoryRedirect_arg() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1(1);
+class A {
+ const A.a1(x) : this.a2(x + 100);
+ const A.a2(x) : y = x + 10;
+ final int y;
+}''');
+ Map<String, DartObjectImpl> aFields =
+ _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+ _assertIntField(aFields, 'y', 111);
+ }
+
+ void test_instanceCreationExpression_nonFactoryRedirect_cycle() {
+ // It is an error to have a cycle in non-factory redirects; however, we
+ // need to make sure that even if the error occurs, attempting to evaluate
+ // the constant will terminate.
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+ const A() : this.b();
+ const A.b() : this();
+}''');
+ _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
+ }
+
+ void test_instanceCreationExpression_nonFactoryRedirect_defaultArg() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+ const A.a1() : this.a2();
+ const A.a2([x = 100]) : y = x + 10;
+ final int y;
+}''');
+ Map<String, DartObjectImpl> aFields =
+ _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+ _assertIntField(aFields, 'y', 110);
+ }
+
+ void test_instanceCreationExpression_nonFactoryRedirect_toMissing() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+ const A.a1() : this.a2();
+}''');
+ // We don't care what value foo evaluates to (since there is a compile
+ // error), but we shouldn't crash, and we should figure
+ // out that it evaluates to an instance of class A.
+ _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+ }
+
+ void test_instanceCreationExpression_nonFactoryRedirect_toNonConst() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+ const A.a1() : this.a2();
+ A.a2();
+}''');
+ // We don't care what value foo evaluates to (since there is a compile
+ // error), but we shouldn't crash, and we should figure
+ // out that it evaluates to an instance of class A.
+ _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+ }
+
+ void test_instanceCreationExpression_nonFactoryRedirect_unnamed() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A.a1();
+class A {
+ const A.a1() : this();
+ const A() : x = 5;
+ final int x;
+}''');
+ Map<String, DartObjectImpl> aFields =
+ _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "A");
+ _assertIntField(aFields, 'x', 5);
+ }
+
+ void test_instanceCreationExpression_redirect() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+ const factory A() = B;
+}
+class B implements A {
+ const B();
+}''');
+ _assertType(_evaluateTopLevelVariable(compilationUnit, "foo"), "B");
+ }
+
+ void test_instanceCreationExpression_redirect_cycle() {
+ // It is an error to have a cycle in factory redirects; however, we need
+ // to make sure that even if the error occurs, attempting to evaluate the
+ // constant will terminate.
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+ const factory A() = A.b;
+ const factory A.b() = A;
+}''');
+ _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
+ }
+
+ void test_instanceCreationExpression_redirect_external() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+ external const factory A();
+}''');
+ _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
+ }
+
+ void test_instanceCreationExpression_redirect_nonConst() {
+ // It is an error for a const factory constructor redirect to a non-const
+ // constructor; however, we need to make sure that even if the error
+ // attempting to evaluate the constant won't cause a crash.
+ CompilationUnit compilationUnit = resolveSource(r'''
+const foo = const A();
+class A {
+ const factory A() = A.b;
+ A.b();
+}''');
+ _assertValidUnknown(_evaluateTopLevelVariable(compilationUnit, "foo"));
+ }
+
+ void test_instanceCreationExpression_redirectWithTypeParams() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+class A {
+ const factory A(var a) = B<int>;
+}
+
+class B<T> implements A {
+ final T x;
+ const B(this.x);
+}
+
+const A a = const A(10);''');
+ EvaluationResultImpl result =
+ _evaluateTopLevelVariable(compilationUnit, "a");
+ Map<String, DartObjectImpl> fields = _assertType(result, "B<int>");
+ expect(fields, hasLength(1));
+ _assertIntField(fields, "x", 10);
+ }
+
+ void test_instanceCreationExpression_redirectWithTypeSubstitution() {
+ // To evaluate the redirection of A<int>,
+ // A's template argument (T=int) must be substituted
+ // into B's template argument (B<U> where U=T) to get B<int>.
+ CompilationUnit compilationUnit = resolveSource(r'''
+class A<T> {
+ const factory A(var a) = B<T>;
+}
+
+class B<U> implements A {
+ final U x;
+ const B(this.x);
+}
+
+const A<int> a = const A<int>(10);''');
+ EvaluationResultImpl result =
+ _evaluateTopLevelVariable(compilationUnit, "a");
+ Map<String, DartObjectImpl> fields = _assertType(result, "B<int>");
+ expect(fields, hasLength(1));
+ _assertIntField(fields, "x", 10);
+ }
+
+ void test_instanceCreationExpression_symbol() {
+ CompilationUnit compilationUnit =
+ resolveSource("const foo = const Symbol('a');");
+ EvaluationResultImpl evaluationResult =
+ _evaluateTopLevelVariable(compilationUnit, "foo");
+ expect(evaluationResult.value, isNotNull);
+ DartObjectImpl value = evaluationResult.value;
+ expect(value.type, typeProvider.symbolType);
+ expect(value.toSymbolValue(), "a");
+ }
+
+ void test_instanceCreationExpression_withSupertypeParams_explicit() {
+ _checkInstanceCreation_withSupertypeParams(true);
+ }
+
+ void test_instanceCreationExpression_withSupertypeParams_implicit() {
+ _checkInstanceCreation_withSupertypeParams(false);
+ }
+
+ void test_instanceCreationExpression_withTypeParams() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+class C<E> {
+ const C();
+}
+const c_int = const C<int>();
+const c_num = const C<num>();''');
+ EvaluationResultImpl c_int =
+ _evaluateTopLevelVariable(compilationUnit, "c_int");
+ _assertType(c_int, "C<int>");
+ DartObjectImpl c_int_value = c_int.value;
+ EvaluationResultImpl c_num =
+ _evaluateTopLevelVariable(compilationUnit, "c_num");
+ _assertType(c_num, "C<num>");
+ DartObjectImpl c_num_value = c_num.value;
+ expect(c_int_value == c_num_value, isFalse);
+ }
+
+ void test_isValidSymbol() {
+ expect(ConstantEvaluationEngine.isValidPublicSymbol(""), isTrue);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("foo"), isTrue);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar"), isTrue);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$"), isTrue);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("foo\$bar"), isTrue);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("iff"), isTrue);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("gif"), isTrue);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("if\$"), isTrue);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("\$if"), isTrue);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("foo="), isTrue);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.bar="), isTrue);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.+"), isTrue);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("void"), isTrue);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo"), isFalse);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("_foo.bar"), isFalse);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("foo._bar"), isFalse);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("if"), isFalse);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("if.foo"), isFalse);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.if"), isFalse);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("foo=.bar"), isFalse);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("foo."), isFalse);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("+.foo"), isFalse);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("void.foo"), isFalse);
+ expect(ConstantEvaluationEngine.isValidPublicSymbol("foo.void"), isFalse);
+ }
+
+ void test_length_of_improperly_typed_string_expression() {
+ // Since type annotations are ignored in unchecked mode, the improper
+ // types on s1 and s2 shouldn't prevent us from evaluating i to
+ // 'alpha'.length.
+ CompilationUnit compilationUnit = resolveSource('''
+const int s1 = 'alpha';
+const int s2 = 'beta';
+const int i = (true ? s1 : s2).length;
+''');
+ ConstTopLevelVariableElementImpl element =
+ findTopLevelDeclaration(compilationUnit, 'i').element;
+ EvaluationResultImpl result = element.evaluationResult;
+ expect(_assertValidInt(result), 5);
+ }
+
+ void test_length_of_improperly_typed_string_identifier() {
+ // Since type annotations are ignored in unchecked mode, the improper type
+ // on s shouldn't prevent us from evaluating i to 'alpha'.length.
+ CompilationUnit compilationUnit = resolveSource('''
+const int s = 'alpha';
+const int i = s.length;
+''');
+ ConstTopLevelVariableElementImpl element =
+ findTopLevelDeclaration(compilationUnit, 'i').element;
+ EvaluationResultImpl result = element.evaluationResult;
+ expect(_assertValidInt(result), 5);
+ }
+
+ void test_non_static_const_initialized_at_declaration() {
+ // Even though non-static consts are not allowed by the language, we need
+ // to handle them for error recovery purposes.
+ CompilationUnit compilationUnit = resolveSource('''
+class A {
+ const int i = 123;
+ const A();
+}
+
+const A a = const A();
+''');
+ EvaluationResultImpl result =
+ _evaluateTopLevelVariable(compilationUnit, 'a');
+ Map<String, DartObjectImpl> fields = _assertType(result, "A");
+ expect(fields, hasLength(1));
+ _assertIntField(fields, "i", 123);
+ }
+
+ void test_symbolLiteral_void() {
+ CompilationUnit compilationUnit =
+ resolveSource("const voidSymbol = #void;");
+ VariableDeclaration voidSymbol =
+ findTopLevelDeclaration(compilationUnit, "voidSymbol");
+ EvaluationResultImpl voidSymbolResult =
+ (voidSymbol.element as VariableElementImpl).evaluationResult;
+ DartObjectImpl value = voidSymbolResult.value;
+ expect(value.type, typeProvider.symbolType);
+ expect(value.toSymbolValue(), "void");
+ }
+
+ Map<String, DartObjectImpl> _assertFieldType(
+ Map<String, DartObjectImpl> fields,
+ String fieldName,
+ String expectedType) {
+ DartObjectImpl field = fields[fieldName];
+ expect(field.type.displayName, expectedType);
+ return field.fields;
+ }
+
+ void _assertIntField(
+ Map<String, DartObjectImpl> fields, String fieldName, int expectedValue) {
+ DartObjectImpl field = fields[fieldName];
+ expect(field.type.name, "int");
+ expect(field.toIntValue(), expectedValue);
+ }
+
+ void _assertNullField(Map<String, DartObjectImpl> fields, String fieldName) {
+ DartObjectImpl field = fields[fieldName];
+ expect(field.isNull, isTrue);
+ }
+
+ void _assertProperDependencies(String sourceText,
+ [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) {
+ Source source = addSource(sourceText);
+ LibraryElement element = resolve2(source);
+ CompilationUnit unit =
+ analysisContext.resolveCompilationUnit(source, element);
+ expect(unit, isNotNull);
+ ConstantValueComputer computer = _makeConstantValueComputer();
+ computer.add(unit, source, source);
+ computer.computeValues();
+ assertErrors(source, expectedErrorCodes);
+ }
+
+ Map<String, DartObjectImpl> _assertType(
+ EvaluationResultImpl result, String typeName) {
+ expect(result.value, isNotNull);
+ DartObjectImpl value = result.value;
+ expect(value.type.displayName, typeName);
+ return value.fields;
+ }
+
+ bool _assertValidBool(EvaluationResultImpl result) {
+ expect(result.value, isNotNull);
+ DartObjectImpl value = result.value;
+ expect(value.type, typeProvider.boolType);
+ bool boolValue = value.toBoolValue();
+ expect(boolValue, isNotNull);
+ return boolValue;
+ }
+
+ int _assertValidInt(EvaluationResultImpl result) {
+ expect(result, isNotNull);
+ expect(result.value, isNotNull);
+ DartObjectImpl value = result.value;
+ expect(value.type, typeProvider.intType);
+ return value.toIntValue();
+ }
+
+ void _assertValidNull(EvaluationResultImpl result) {
+ expect(result.value, isNotNull);
+ DartObjectImpl value = result.value;
+ expect(value.type, typeProvider.nullType);
+ }
+
+ String _assertValidString(EvaluationResultImpl result) {
+ expect(result.value, isNotNull);
+ DartObjectImpl value = result.value;
+ expect(value.type, typeProvider.stringType);
+ return value.toStringValue();
+ }
+
+ void _assertValidUnknown(EvaluationResultImpl result) {
+ expect(result.value, isNotNull);
+ DartObjectImpl value = result.value;
+ expect(value.isUnknown, isTrue);
+ }
+
+ EvaluationResultImpl _check_fromEnvironment_bool(
+ String valueInEnvironment, String defaultExpr) {
+ String envVarName = "x";
+ String varName = "foo";
+ if (valueInEnvironment != null) {
+ analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
+ }
+ String defaultArg =
+ defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
+ CompilationUnit compilationUnit = resolveSource(
+ "const $varName = const bool.fromEnvironment('$envVarName'$defaultArg);");
+ return _evaluateTopLevelVariable(compilationUnit, varName);
+ }
+
+ EvaluationResultImpl _check_fromEnvironment_int(
+ String valueInEnvironment, String defaultExpr) {
+ String envVarName = "x";
+ String varName = "foo";
+ if (valueInEnvironment != null) {
+ analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
+ }
+ String defaultArg =
+ defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
+ CompilationUnit compilationUnit = resolveSource(
+ "const $varName = const int.fromEnvironment('$envVarName'$defaultArg);");
+ return _evaluateTopLevelVariable(compilationUnit, varName);
+ }
+
+ EvaluationResultImpl _check_fromEnvironment_string(
+ String valueInEnvironment, String defaultExpr) {
+ String envVarName = "x";
+ String varName = "foo";
+ if (valueInEnvironment != null) {
+ analysisContext2.declaredVariables.define(envVarName, valueInEnvironment);
+ }
+ String defaultArg =
+ defaultExpr == null ? "" : ", defaultValue: $defaultExpr";
+ CompilationUnit compilationUnit = resolveSource(
+ "const $varName = const String.fromEnvironment('$envVarName'$defaultArg);");
+ return _evaluateTopLevelVariable(compilationUnit, varName);
+ }
+
+ void _checkInstanceCreation_withSupertypeParams(bool isExplicit) {
+ String superCall = isExplicit ? " : super()" : "";
+ CompilationUnit compilationUnit = resolveSource("""
+class A<T> {
+ const A();
+}
+class B<T, U> extends A<T> {
+ const B()$superCall;
+}
+class C<T, U> extends A<U> {
+ const C()$superCall;
+}
+const b_int_num = const B<int, num>();
+const c_int_num = const C<int, num>();""");
+ EvaluationResultImpl b_int_num =
+ _evaluateTopLevelVariable(compilationUnit, "b_int_num");
+ Map<String, DartObjectImpl> b_int_num_fields =
+ _assertType(b_int_num, "B<int, num>");
+ _assertFieldType(b_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<int>");
+ EvaluationResultImpl c_int_num =
+ _evaluateTopLevelVariable(compilationUnit, "c_int_num");
+ Map<String, DartObjectImpl> c_int_num_fields =
+ _assertType(c_int_num, "C<int, num>");
+ _assertFieldType(c_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<num>");
+ }
+
+ void _checkInstanceCreationOptionalParams(
+ bool isFieldFormal, bool isNamed, bool hasDefault) {
+ String fieldName = "j";
+ String paramName = isFieldFormal ? fieldName : "i";
+ String formalParam =
+ "${isFieldFormal ? "this." : "int "}$paramName${hasDefault ? " = 3" : ""}";
+ CompilationUnit compilationUnit = resolveSource("""
+const x = const A();
+const y = const A(${isNamed ? '$paramName: ' : ''}10);
+class A {
+ const A(${isNamed ? "{$formalParam}" : "[$formalParam]"})${isFieldFormal ? "" : " : $fieldName = $paramName"};
+ final int $fieldName;
+}""");
+ EvaluationResultImpl x = _evaluateTopLevelVariable(compilationUnit, "x");
+ Map<String, DartObjectImpl> fieldsOfX = _assertType(x, "A");
+ expect(fieldsOfX, hasLength(1));
+ if (hasDefault) {
+ _assertIntField(fieldsOfX, fieldName, 3);
+ } else {
+ _assertNullField(fieldsOfX, fieldName);
+ }
+ EvaluationResultImpl y = _evaluateTopLevelVariable(compilationUnit, "y");
+ Map<String, DartObjectImpl> fieldsOfY = _assertType(y, "A");
+ expect(fieldsOfY, hasLength(1));
+ _assertIntField(fieldsOfY, fieldName, 10);
+ }
+
+ /**
+ * Search [compilationUnit] for a class named [className], containing a
+ * method [methodName], with exactly one annotation. Return the constant
+ * value of the annotation.
+ */
+ EvaluationResultImpl _evaluateAnnotation(
+ CompilationUnit compilationUnit, String className, String memberName) {
+ for (CompilationUnitMember member in compilationUnit.declarations) {
+ if (member is ClassDeclaration && member.name.name == className) {
+ for (ClassMember classMember in member.members) {
+ if (classMember is MethodDeclaration &&
+ classMember.name.name == memberName) {
+ expect(classMember.metadata, hasLength(1));
+ ElementAnnotationImpl elementAnnotation =
+ classMember.metadata[0].elementAnnotation;
+ return elementAnnotation.evaluationResult;
+ }
+ }
+ }
+ }
+ fail('Class member not found');
+ return null;
+ }
+
+ EvaluationResultImpl _evaluateTopLevelVariable(
+ CompilationUnit compilationUnit, String name) {
+ VariableDeclaration varDecl =
+ findTopLevelDeclaration(compilationUnit, name);
+ ConstTopLevelVariableElementImpl varElement = varDecl.element;
+ return varElement.evaluationResult;
+ }
+
+ ConstantValueComputer _makeConstantValueComputer() {
+ ConstantEvaluationValidator_ForTest validator =
+ new ConstantEvaluationValidator_ForTest(analysisContext2);
+ validator.computer = new ConstantValueComputer(
+ analysisContext2,
+ analysisContext2.typeProvider,
+ analysisContext2.declaredVariables,
+ validator,
+ analysisContext2.typeSystem);
+ return validator.computer;
+ }
+
+ void _validate(bool shouldBeValid, VariableDeclarationList declarationList) {
+ for (VariableDeclaration declaration in declarationList.variables) {
+ VariableElementImpl element = declaration.element as VariableElementImpl;
+ expect(element, isNotNull);
+ EvaluationResultImpl result = element.evaluationResult;
+ if (shouldBeValid) {
+ expect(result.value, isNotNull);
+ } else {
+ expect(result.value, isNull);
+ }
+ }
+ }
+}
+
+@reflectiveTest
+class ConstantVisitorTest extends ResolverTestCase {
+ void test_visitBinaryExpression_questionQuestion_notNull_notNull() {
+ Expression left = AstFactory.string2('a');
+ Expression right = AstFactory.string2('b');
+ Expression expression =
+ AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
+
+ GatheringErrorListener errorListener = new GatheringErrorListener();
+ ErrorReporter errorReporter =
+ new ErrorReporter(errorListener, _dummySource());
+ DartObjectImpl result = _evaluate(expression, errorReporter);
+ expect(result, isNotNull);
+ expect(result.isNull, isFalse);
+ expect(result.toStringValue(), 'a');
+ errorListener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_questionQuestion_null_notNull() {
+ Expression left = AstFactory.nullLiteral();
+ Expression right = AstFactory.string2('b');
+ Expression expression =
+ AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
+
+ GatheringErrorListener errorListener = new GatheringErrorListener();
+ ErrorReporter errorReporter =
+ new ErrorReporter(errorListener, _dummySource());
+ DartObjectImpl result = _evaluate(expression, errorReporter);
+ expect(result, isNotNull);
+ expect(result.isNull, isFalse);
+ expect(result.toStringValue(), 'b');
+ errorListener.assertNoErrors();
+ }
+
+ void test_visitBinaryExpression_questionQuestion_null_null() {
+ Expression left = AstFactory.nullLiteral();
+ Expression right = AstFactory.nullLiteral();
+ Expression expression =
+ AstFactory.binaryExpression(left, TokenType.QUESTION_QUESTION, right);
+
+ GatheringErrorListener errorListener = new GatheringErrorListener();
+ ErrorReporter errorReporter =
+ new ErrorReporter(errorListener, _dummySource());
+ DartObjectImpl result = _evaluate(expression, errorReporter);
+ expect(result, isNotNull);
+ expect(result.isNull, isTrue);
+ errorListener.assertNoErrors();
+ }
+
+ void test_visitConditionalExpression_false() {
+ Expression thenExpression = AstFactory.integer(1);
+ Expression elseExpression = AstFactory.integer(0);
+ ConditionalExpression expression = AstFactory.conditionalExpression(
+ AstFactory.booleanLiteral(false), thenExpression, elseExpression);
+ GatheringErrorListener errorListener = new GatheringErrorListener();
+ ErrorReporter errorReporter =
+ new ErrorReporter(errorListener, _dummySource());
+ _assertValue(0, _evaluate(expression, errorReporter));
+ errorListener.assertNoErrors();
+ }
+
+ void test_visitConditionalExpression_nonBooleanCondition() {
+ Expression thenExpression = AstFactory.integer(1);
+ Expression elseExpression = AstFactory.integer(0);
+ NullLiteral conditionExpression = AstFactory.nullLiteral();
+ ConditionalExpression expression = AstFactory.conditionalExpression(
+ conditionExpression, thenExpression, elseExpression);
+ GatheringErrorListener errorListener = new GatheringErrorListener();
+ ErrorReporter errorReporter =
+ new ErrorReporter(errorListener, _dummySource());
+ DartObjectImpl result = _evaluate(expression, errorReporter);
+ expect(result, isNull);
+ errorListener
+ .assertErrorsWithCodes([CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL]);
+ }
+
+ void test_visitConditionalExpression_nonConstantElse() {
+ Expression thenExpression = AstFactory.integer(1);
+ Expression elseExpression = AstFactory.identifier3("x");
+ ConditionalExpression expression = AstFactory.conditionalExpression(
+ AstFactory.booleanLiteral(true), thenExpression, elseExpression);
+ GatheringErrorListener errorListener = new GatheringErrorListener();
+ ErrorReporter errorReporter =
+ new ErrorReporter(errorListener, _dummySource());
+ DartObjectImpl result = _evaluate(expression, errorReporter);
+ expect(result, isNull);
+ errorListener
+ .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
+ }
+
+ void test_visitConditionalExpression_nonConstantThen() {
+ Expression thenExpression = AstFactory.identifier3("x");
+ Expression elseExpression = AstFactory.integer(0);
+ ConditionalExpression expression = AstFactory.conditionalExpression(
+ AstFactory.booleanLiteral(true), thenExpression, elseExpression);
+ GatheringErrorListener errorListener = new GatheringErrorListener();
+ ErrorReporter errorReporter =
+ new ErrorReporter(errorListener, _dummySource());
+ DartObjectImpl result = _evaluate(expression, errorReporter);
+ expect(result, isNull);
+ errorListener
+ .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
+ }
+
+ void test_visitConditionalExpression_true() {
+ Expression thenExpression = AstFactory.integer(1);
+ Expression elseExpression = AstFactory.integer(0);
+ ConditionalExpression expression = AstFactory.conditionalExpression(
+ AstFactory.booleanLiteral(true), thenExpression, elseExpression);
+ GatheringErrorListener errorListener = new GatheringErrorListener();
+ ErrorReporter errorReporter =
+ new ErrorReporter(errorListener, _dummySource());
+ _assertValue(1, _evaluate(expression, errorReporter));
+ errorListener.assertNoErrors();
+ }
+
+ void test_visitSimpleIdentifier_className() {
+ CompilationUnit compilationUnit = resolveSource('''
+const a = C;
+class C {}
+''');
+ DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
+ expect(result.type, typeProvider.typeType);
+ expect(result.toTypeValue().name, 'C');
+ }
+
+ void test_visitSimpleIdentifier_dynamic() {
+ CompilationUnit compilationUnit = resolveSource('''
+const a = dynamic;
+''');
+ DartObjectImpl result = _evaluateConstant(compilationUnit, 'a', null);
+ expect(result.type, typeProvider.typeType);
+ expect(result.toTypeValue(), typeProvider.dynamicType);
+ }
+
+ void test_visitSimpleIdentifier_inEnvironment() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const a = b;
+const b = 3;''');
+ Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
+ DartObjectImpl six =
+ new DartObjectImpl(typeProvider.intType, new IntState(6));
+ environment["b"] = six;
+ _assertValue(6, _evaluateConstant(compilationUnit, "a", environment));
+ }
+
+ void test_visitSimpleIdentifier_notInEnvironment() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const a = b;
+const b = 3;''');
+ Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
+ DartObjectImpl six =
+ new DartObjectImpl(typeProvider.intType, new IntState(6));
+ environment["c"] = six;
+ _assertValue(3, _evaluateConstant(compilationUnit, "a", environment));
+ }
+
+ void test_visitSimpleIdentifier_withoutEnvironment() {
+ CompilationUnit compilationUnit = resolveSource(r'''
+const a = b;
+const b = 3;''');
+ _assertValue(3, _evaluateConstant(compilationUnit, "a", null));
+ }
+
+ void _assertValue(int expectedValue, DartObjectImpl result) {
+ expect(result, isNotNull);
+ expect(result.type.name, "int");
+ expect(result.toIntValue(), expectedValue);
+ }
+
+ NonExistingSource _dummySource() {
+ String path = '/test.dart';
+ return new NonExistingSource(path, toUri(path), UriKind.FILE_URI);
+ }
+
+ DartObjectImpl _evaluate(Expression expression, ErrorReporter errorReporter) {
+ return expression.accept(new ConstantVisitor(
+ new ConstantEvaluationEngine(
+ new TestTypeProvider(), new DeclaredVariables(),
+ typeSystem: new TypeSystemImpl()),
+ errorReporter));
+ }
+
+ DartObjectImpl _evaluateConstant(CompilationUnit compilationUnit, String name,
+ Map<String, DartObjectImpl> lexicalEnvironment) {
+ Source source = compilationUnit.element.source;
+ Expression expression =
+ findTopLevelConstantExpression(compilationUnit, name);
+ GatheringErrorListener errorListener = new GatheringErrorListener();
+ ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
+ DartObjectImpl result = expression.accept(new ConstantVisitor(
+ new ConstantEvaluationEngine(typeProvider, new DeclaredVariables(),
+ typeSystem: typeSystem),
+ errorReporter,
+ lexicalEnvironment: lexicalEnvironment));
+ errorListener.assertNoErrors();
+ return result;
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/constant/test_all.dart b/pkg/analyzer/test/src/dart/constant/test_all.dart
new file mode 100644
index 0000000..a6eb5b6
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/constant/test_all.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analyzer.test.src.dart.constant.test_all;
+
+import 'package:unittest/unittest.dart';
+
+import '../../../utils.dart';
+import 'evaluation_test.dart' as evaluation;
+import 'utilities_test.dart' as utilities;
+import 'value_test.dart' as value;
+
+/// Utility for manually running all tests.
+main() {
+ initializeTestEnvironment();
+ group('constant tests', () {
+ evaluation.main();
+ utilities.main();
+ value.main();
+ });
+}
diff --git a/pkg/analyzer/test/src/dart/constant/utilities_test.dart b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
new file mode 100644
index 0000000..a922cf5
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
@@ -0,0 +1,354 @@
+// 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 analyzer.test.src.dart.constant.utilities_test;
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/generated/testing/ast_factory.dart';
+import 'package:analyzer/src/generated/testing/element_factory.dart';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:analyzer/src/generated/utilities_collection.dart';
+import 'package:analyzer/src/task/dart.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../../generated/engine_test.dart';
+import '../../../generated/test_support.dart';
+import '../../../reflective_tests.dart';
+import '../../../utils.dart';
+
+main() {
+ initializeTestEnvironment();
+ runReflectiveTests(ConstantFinderTest);
+ runReflectiveTests(ReferenceFinderTest);
+}
+
+@reflectiveTest
+class ConstantFinderTest {
+ AstNode _node;
+ TypeProvider _typeProvider;
+ AnalysisContext _context;
+ Source _source;
+
+ void setUp() {
+ _typeProvider = new TestTypeProvider();
+ _context = new _TestAnalysisContext();
+ _source = new TestSource();
+ }
+
+ /**
+ * Test an annotation that consists solely of an identifier (and hence
+ * represents a reference to a compile-time constant variable).
+ */
+ void test_visitAnnotation_constantVariable() {
+ CompilationUnitElement compilationUnitElement =
+ ElementFactory.compilationUnit('/test.dart', _source)..source = _source;
+ ElementFactory.library(_context, 'L').definingCompilationUnit =
+ compilationUnitElement;
+ ElementAnnotationImpl elementAnnotation =
+ new ElementAnnotationImpl(compilationUnitElement);
+ _node = elementAnnotation.annotationAst = AstFactory.annotation(
+ AstFactory.identifier3('x'))..elementAnnotation = elementAnnotation;
+ expect(_findAnnotations(), contains(_node));
+ }
+
+ /**
+ * Test an annotation that represents the invocation of a constant
+ * constructor.
+ */
+ void test_visitAnnotation_invocation() {
+ CompilationUnitElement compilationUnitElement =
+ ElementFactory.compilationUnit('/test.dart', _source)..source = _source;
+ ElementFactory.library(_context, 'L').definingCompilationUnit =
+ compilationUnitElement;
+ ElementAnnotationImpl elementAnnotation =
+ new ElementAnnotationImpl(compilationUnitElement);
+ _node = elementAnnotation.annotationAst = AstFactory.annotation2(
+ AstFactory.identifier3('A'), null, AstFactory.argumentList())
+ ..elementAnnotation = elementAnnotation;
+ expect(_findAnnotations(), contains(_node));
+ }
+
+ void test_visitAnnotation_partOf() {
+ // Analyzer ignores annotations on "part of" directives.
+ Annotation annotation = AstFactory.annotation2(
+ AstFactory.identifier3('A'), null, AstFactory.argumentList());
+ _node = AstFactory.partOfDirective2(
+ <Annotation>[annotation], AstFactory.libraryIdentifier2(<String>['L']));
+ expect(_findConstants(), isEmpty);
+ }
+
+ void test_visitConstructorDeclaration_const() {
+ ConstructorElement element = _setupConstructorDeclaration("A", true);
+ expect(_findConstants(), contains(element));
+ }
+
+ void test_visitConstructorDeclaration_nonConst() {
+ _setupConstructorDeclaration("A", false);
+ expect(_findConstants(), isEmpty);
+ }
+
+ void test_visitVariableDeclaration_const() {
+ VariableElement element = _setupVariableDeclaration("v", true, true);
+ expect(_findConstants(), contains(element));
+ }
+
+ void test_visitVariableDeclaration_final_inClass() {
+ _setupFieldDeclaration('C', 'f', Keyword.FINAL);
+ expect(_findConstants(), isEmpty);
+ }
+
+ void test_visitVariableDeclaration_final_inClassWithConstConstructor() {
+ VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
+ hasConstConstructor: true);
+ expect(_findConstants(), contains(field.element));
+ }
+
+ void test_visitVariableDeclaration_final_outsideClass() {
+ _setupVariableDeclaration('v', false, true, isFinal: true);
+ expect(_findConstants(), isEmpty);
+ }
+
+ void test_visitVariableDeclaration_noInitializer() {
+ _setupVariableDeclaration("v", true, false);
+ expect(_findConstants(), isEmpty);
+ }
+
+ void test_visitVariableDeclaration_nonConst() {
+ _setupVariableDeclaration("v", false, true);
+ expect(_findConstants(), isEmpty);
+ }
+
+ void test_visitVariableDeclaration_static_const_inClass() {
+ VariableDeclaration field =
+ _setupFieldDeclaration('C', 'f', Keyword.CONST, isStatic: true);
+ expect(_findConstants(), contains(field.element));
+ }
+
+ void
+ test_visitVariableDeclaration_static_const_inClassWithConstConstructor() {
+ VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.CONST,
+ isStatic: true, hasConstConstructor: true);
+ expect(_findConstants(), contains(field.element));
+ }
+
+ void
+ test_visitVariableDeclaration_static_final_inClassWithConstConstructor() {
+ VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
+ isStatic: true, hasConstConstructor: true);
+ expect(_findConstants(), isNot(contains(field.element)));
+ }
+
+ void
+ test_visitVariableDeclaration_uninitialized_final_inClassWithConstConstructor() {
+ VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
+ isInitialized: false, hasConstConstructor: true);
+ expect(_findConstants(), isNot(contains(field.element)));
+ }
+
+ void test_visitVariableDeclaration_uninitialized_static_const_inClass() {
+ _setupFieldDeclaration('C', 'f', Keyword.CONST,
+ isStatic: true, isInitialized: false);
+ expect(_findConstants(), isEmpty);
+ }
+
+ List<Annotation> _findAnnotations() {
+ Set<Annotation> annotations = new Set<Annotation>();
+ for (ConstantEvaluationTarget target in _findConstants()) {
+ if (target is ElementAnnotationImpl) {
+ expect(target.context, same(_context));
+ expect(target.source, same(_source));
+ annotations.add(target.annotationAst);
+ }
+ }
+ return new List<Annotation>.from(annotations);
+ }
+
+ List<ConstantEvaluationTarget> _findConstants() {
+ ConstantFinder finder = new ConstantFinder(_context, _source, _source);
+ _node.accept(finder);
+ List<ConstantEvaluationTarget> constants = finder.constantsToCompute;
+ expect(constants, isNotNull);
+ return constants;
+ }
+
+ ConstructorElement _setupConstructorDeclaration(String name, bool isConst) {
+ Keyword constKeyword = isConst ? Keyword.CONST : null;
+ ConstructorDeclaration constructorDeclaration =
+ AstFactory.constructorDeclaration2(
+ constKeyword,
+ null,
+ null,
+ name,
+ AstFactory.formalParameterList(),
+ null,
+ AstFactory.blockFunctionBody2());
+ ClassElement classElement = ElementFactory.classElement2(name);
+ ConstructorElement element =
+ ElementFactory.constructorElement(classElement, name, isConst);
+ constructorDeclaration.element = element;
+ _node = constructorDeclaration;
+ return element;
+ }
+
+ VariableDeclaration _setupFieldDeclaration(
+ String className, String fieldName, Keyword keyword,
+ {bool isInitialized: true,
+ bool isStatic: false,
+ bool hasConstConstructor: false}) {
+ VariableDeclaration variableDeclaration = isInitialized
+ ? AstFactory.variableDeclaration2(fieldName, AstFactory.integer(0))
+ : AstFactory.variableDeclaration(fieldName);
+ VariableElement fieldElement = ElementFactory.fieldElement(
+ fieldName,
+ isStatic,
+ keyword == Keyword.FINAL,
+ keyword == Keyword.CONST,
+ _typeProvider.intType);
+ variableDeclaration.name.staticElement = fieldElement;
+ FieldDeclaration fieldDeclaration = AstFactory.fieldDeclaration2(
+ isStatic, keyword, <VariableDeclaration>[variableDeclaration]);
+ ClassDeclaration classDeclaration =
+ AstFactory.classDeclaration(null, className, null, null, null, null);
+ classDeclaration.members.add(fieldDeclaration);
+ _node = classDeclaration;
+ ClassElementImpl classElement = ElementFactory.classElement2(className);
+ classElement.fields = <FieldElement>[fieldElement];
+ classDeclaration.name.staticElement = classElement;
+ if (hasConstConstructor) {
+ ConstructorDeclaration constructorDeclaration =
+ AstFactory.constructorDeclaration2(
+ Keyword.CONST,
+ null,
+ AstFactory.identifier3(className),
+ null,
+ AstFactory.formalParameterList(),
+ null,
+ AstFactory.blockFunctionBody2());
+ classDeclaration.members.add(constructorDeclaration);
+ ConstructorElement constructorElement =
+ ElementFactory.constructorElement(classElement, '', true);
+ constructorDeclaration.element = constructorElement;
+ classElement.constructors = <ConstructorElement>[constructorElement];
+ } else {
+ classElement.constructors = ConstructorElement.EMPTY_LIST;
+ }
+ return variableDeclaration;
+ }
+
+ VariableElement _setupVariableDeclaration(
+ String name, bool isConst, bool isInitialized,
+ {isFinal: false}) {
+ VariableDeclaration variableDeclaration = isInitialized
+ ? AstFactory.variableDeclaration2(name, AstFactory.integer(0))
+ : AstFactory.variableDeclaration(name);
+ SimpleIdentifier identifier = variableDeclaration.name;
+ VariableElement element = ElementFactory.localVariableElement(identifier);
+ identifier.staticElement = element;
+ Keyword keyword = isConst ? Keyword.CONST : isFinal ? Keyword.FINAL : null;
+ AstFactory.variableDeclarationList2(keyword, [variableDeclaration]);
+ _node = variableDeclaration;
+ return element;
+ }
+}
+
+@reflectiveTest
+class ReferenceFinderTest {
+ DirectedGraph<ConstantEvaluationTarget> _referenceGraph;
+ VariableElement _head;
+ Element _tail;
+
+ void setUp() {
+ _referenceGraph = new DirectedGraph<ConstantEvaluationTarget>();
+ _head = ElementFactory.topLevelVariableElement2("v1");
+ }
+
+ void test_visitSimpleIdentifier_const() {
+ _visitNode(_makeTailVariable("v2", true));
+ _assertOneArc(_tail);
+ }
+
+ void test_visitSuperConstructorInvocation_const() {
+ _visitNode(_makeTailSuperConstructorInvocation("A", true));
+ _assertOneArc(_tail);
+ }
+
+ void test_visitSuperConstructorInvocation_nonConst() {
+ _visitNode(_makeTailSuperConstructorInvocation("A", false));
+ _assertOneArc(_tail);
+ }
+
+ void test_visitSuperConstructorInvocation_unresolved() {
+ SuperConstructorInvocation superConstructorInvocation =
+ AstFactory.superConstructorInvocation();
+ _visitNode(superConstructorInvocation);
+ _assertNoArcs();
+ }
+
+ void _assertNoArcs() {
+ Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
+ expect(tails, hasLength(0));
+ }
+
+ void _assertOneArc(Element tail) {
+ Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
+ expect(tails, hasLength(1));
+ expect(tails.first, same(tail));
+ }
+
+ ReferenceFinder _createReferenceFinder(ConstantEvaluationTarget source) =>
+ new ReferenceFinder((ConstantEvaluationTarget dependency) {
+ _referenceGraph.addEdge(source, dependency);
+ });
+ SuperConstructorInvocation _makeTailSuperConstructorInvocation(
+ String name, bool isConst) {
+ List<ConstructorInitializer> initializers =
+ new List<ConstructorInitializer>();
+ ConstructorDeclaration constructorDeclaration =
+ AstFactory.constructorDeclaration(AstFactory.identifier3(name), null,
+ AstFactory.formalParameterList(), initializers);
+ if (isConst) {
+ constructorDeclaration.constKeyword = new KeywordToken(Keyword.CONST, 0);
+ }
+ ClassElementImpl classElement = ElementFactory.classElement2(name);
+ SuperConstructorInvocation superConstructorInvocation =
+ AstFactory.superConstructorInvocation();
+ ConstructorElementImpl constructorElement =
+ ElementFactory.constructorElement(classElement, name, isConst);
+ _tail = constructorElement;
+ superConstructorInvocation.staticElement = constructorElement;
+ return superConstructorInvocation;
+ }
+
+ SimpleIdentifier _makeTailVariable(String name, bool isConst) {
+ VariableDeclaration variableDeclaration =
+ AstFactory.variableDeclaration(name);
+ ConstLocalVariableElementImpl variableElement =
+ ElementFactory.constLocalVariableElement(name);
+ _tail = variableElement;
+ variableElement.const3 = isConst;
+ AstFactory.variableDeclarationList2(
+ isConst ? Keyword.CONST : Keyword.VAR, [variableDeclaration]);
+ SimpleIdentifier identifier = AstFactory.identifier3(name);
+ identifier.staticElement = variableElement;
+ return identifier;
+ }
+
+ void _visitNode(AstNode node) {
+ node.accept(_createReferenceFinder(_head));
+ }
+}
+
+class _TestAnalysisContext extends TestAnalysisContext {
+ @override
+ InternalAnalysisContext getContextFor(Source source) => this;
+}
diff --git a/pkg/analyzer/test/src/dart/constant/value_test.dart b/pkg/analyzer/test/src/dart/constant/value_test.dart
new file mode 100644
index 0000000..cb64c4c
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/constant/value_test.dart
@@ -0,0 +1,2029 @@
+// 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 analyzer.test.src.dart.constant.value_test;
+
+import 'package:analyzer/src/generated/constant.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/testing/test_type_provider.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../../generated/test_support.dart';
+import '../../../reflective_tests.dart';
+import '../../../utils.dart';
+
+main() {
+ initializeTestEnvironment();
+ runReflectiveTests(DartObjectImplTest);
+}
+
+const int LONG_MAX_VALUE = 0x7fffffffffffffff;
+
+@reflectiveTest
+class DartObjectImplTest extends EngineTestCase {
+ TypeProvider _typeProvider = new TestTypeProvider();
+
+ void test_add_knownDouble_knownDouble() {
+ _assertAdd(_doubleValue(3.0), _doubleValue(1.0), _doubleValue(2.0));
+ }
+
+ void test_add_knownDouble_knownInt() {
+ _assertAdd(_doubleValue(3.0), _doubleValue(1.0), _intValue(2));
+ }
+
+ void test_add_knownDouble_unknownDouble() {
+ _assertAdd(_doubleValue(null), _doubleValue(1.0), _doubleValue(null));
+ }
+
+ void test_add_knownDouble_unknownInt() {
+ _assertAdd(_doubleValue(null), _doubleValue(1.0), _intValue(null));
+ }
+
+ void test_add_knownInt_knownInt() {
+ _assertAdd(_intValue(3), _intValue(1), _intValue(2));
+ }
+
+ void test_add_knownInt_knownString() {
+ _assertAdd(null, _intValue(1), _stringValue("2"));
+ }
+
+ void test_add_knownInt_unknownDouble() {
+ _assertAdd(_doubleValue(null), _intValue(1), _doubleValue(null));
+ }
+
+ void test_add_knownInt_unknownInt() {
+ _assertAdd(_intValue(null), _intValue(1), _intValue(null));
+ }
+
+ void test_add_knownString_knownInt() {
+ _assertAdd(null, _stringValue("1"), _intValue(2));
+ }
+
+ void test_add_knownString_knownString() {
+ _assertAdd(_stringValue("ab"), _stringValue("a"), _stringValue("b"));
+ }
+
+ void test_add_knownString_unknownString() {
+ _assertAdd(_stringValue(null), _stringValue("a"), _stringValue(null));
+ }
+
+ void test_add_unknownDouble_knownDouble() {
+ _assertAdd(_doubleValue(null), _doubleValue(null), _doubleValue(2.0));
+ }
+
+ void test_add_unknownDouble_knownInt() {
+ _assertAdd(_doubleValue(null), _doubleValue(null), _intValue(2));
+ }
+
+ void test_add_unknownInt_knownDouble() {
+ _assertAdd(_doubleValue(null), _intValue(null), _doubleValue(2.0));
+ }
+
+ void test_add_unknownInt_knownInt() {
+ _assertAdd(_intValue(null), _intValue(null), _intValue(2));
+ }
+
+ void test_add_unknownString_knownString() {
+ _assertAdd(_stringValue(null), _stringValue(null), _stringValue("b"));
+ }
+
+ void test_add_unknownString_unknownString() {
+ _assertAdd(_stringValue(null), _stringValue(null), _stringValue(null));
+ }
+
+ void test_bitAnd_knownInt_knownInt() {
+ _assertBitAnd(_intValue(2), _intValue(6), _intValue(3));
+ }
+
+ void test_bitAnd_knownInt_knownString() {
+ _assertBitAnd(null, _intValue(6), _stringValue("3"));
+ }
+
+ void test_bitAnd_knownInt_unknownInt() {
+ _assertBitAnd(_intValue(null), _intValue(6), _intValue(null));
+ }
+
+ void test_bitAnd_knownString_knownInt() {
+ _assertBitAnd(null, _stringValue("6"), _intValue(3));
+ }
+
+ void test_bitAnd_unknownInt_knownInt() {
+ _assertBitAnd(_intValue(null), _intValue(null), _intValue(3));
+ }
+
+ void test_bitAnd_unknownInt_unknownInt() {
+ _assertBitAnd(_intValue(null), _intValue(null), _intValue(null));
+ }
+
+ void test_bitNot_knownInt() {
+ _assertBitNot(_intValue(-4), _intValue(3));
+ }
+
+ void test_bitNot_knownString() {
+ _assertBitNot(null, _stringValue("6"));
+ }
+
+ void test_bitNot_unknownInt() {
+ _assertBitNot(_intValue(null), _intValue(null));
+ }
+
+ void test_bitOr_knownInt_knownInt() {
+ _assertBitOr(_intValue(7), _intValue(6), _intValue(3));
+ }
+
+ void test_bitOr_knownInt_knownString() {
+ _assertBitOr(null, _intValue(6), _stringValue("3"));
+ }
+
+ void test_bitOr_knownInt_unknownInt() {
+ _assertBitOr(_intValue(null), _intValue(6), _intValue(null));
+ }
+
+ void test_bitOr_knownString_knownInt() {
+ _assertBitOr(null, _stringValue("6"), _intValue(3));
+ }
+
+ void test_bitOr_unknownInt_knownInt() {
+ _assertBitOr(_intValue(null), _intValue(null), _intValue(3));
+ }
+
+ void test_bitOr_unknownInt_unknownInt() {
+ _assertBitOr(_intValue(null), _intValue(null), _intValue(null));
+ }
+
+ void test_bitXor_knownInt_knownInt() {
+ _assertBitXor(_intValue(5), _intValue(6), _intValue(3));
+ }
+
+ void test_bitXor_knownInt_knownString() {
+ _assertBitXor(null, _intValue(6), _stringValue("3"));
+ }
+
+ void test_bitXor_knownInt_unknownInt() {
+ _assertBitXor(_intValue(null), _intValue(6), _intValue(null));
+ }
+
+ void test_bitXor_knownString_knownInt() {
+ _assertBitXor(null, _stringValue("6"), _intValue(3));
+ }
+
+ void test_bitXor_unknownInt_knownInt() {
+ _assertBitXor(_intValue(null), _intValue(null), _intValue(3));
+ }
+
+ void test_bitXor_unknownInt_unknownInt() {
+ _assertBitXor(_intValue(null), _intValue(null), _intValue(null));
+ }
+
+ void test_concatenate_knownInt_knownString() {
+ _assertConcatenate(null, _intValue(2), _stringValue("def"));
+ }
+
+ void test_concatenate_knownString_knownInt() {
+ _assertConcatenate(null, _stringValue("abc"), _intValue(3));
+ }
+
+ void test_concatenate_knownString_knownString() {
+ _assertConcatenate(
+ _stringValue("abcdef"), _stringValue("abc"), _stringValue("def"));
+ }
+
+ void test_concatenate_knownString_unknownString() {
+ _assertConcatenate(
+ _stringValue(null), _stringValue("abc"), _stringValue(null));
+ }
+
+ void test_concatenate_unknownString_knownString() {
+ _assertConcatenate(
+ _stringValue(null), _stringValue(null), _stringValue("def"));
+ }
+
+ void test_divide_knownDouble_knownDouble() {
+ _assertDivide(_doubleValue(3.0), _doubleValue(6.0), _doubleValue(2.0));
+ }
+
+ void test_divide_knownDouble_knownInt() {
+ _assertDivide(_doubleValue(3.0), _doubleValue(6.0), _intValue(2));
+ }
+
+ void test_divide_knownDouble_unknownDouble() {
+ _assertDivide(_doubleValue(null), _doubleValue(6.0), _doubleValue(null));
+ }
+
+ void test_divide_knownDouble_unknownInt() {
+ _assertDivide(_doubleValue(null), _doubleValue(6.0), _intValue(null));
+ }
+
+ void test_divide_knownInt_knownInt() {
+ _assertDivide(_doubleValue(3.0), _intValue(6), _intValue(2));
+ }
+
+ void test_divide_knownInt_knownString() {
+ _assertDivide(null, _intValue(6), _stringValue("2"));
+ }
+
+ void test_divide_knownInt_unknownDouble() {
+ _assertDivide(_doubleValue(null), _intValue(6), _doubleValue(null));
+ }
+
+ void test_divide_knownInt_unknownInt() {
+ _assertDivide(_doubleValue(null), _intValue(6), _intValue(null));
+ }
+
+ void test_divide_knownString_knownInt() {
+ _assertDivide(null, _stringValue("6"), _intValue(2));
+ }
+
+ void test_divide_unknownDouble_knownDouble() {
+ _assertDivide(_doubleValue(null), _doubleValue(null), _doubleValue(2.0));
+ }
+
+ void test_divide_unknownDouble_knownInt() {
+ _assertDivide(_doubleValue(null), _doubleValue(null), _intValue(2));
+ }
+
+ void test_divide_unknownInt_knownDouble() {
+ _assertDivide(_doubleValue(null), _intValue(null), _doubleValue(2.0));
+ }
+
+ void test_divide_unknownInt_knownInt() {
+ _assertDivide(_doubleValue(null), _intValue(null), _intValue(2));
+ }
+
+ void test_equalEqual_bool_false() {
+ _assertEqualEqual(_boolValue(false), _boolValue(false), _boolValue(true));
+ }
+
+ void test_equalEqual_bool_true() {
+ _assertEqualEqual(_boolValue(true), _boolValue(true), _boolValue(true));
+ }
+
+ void test_equalEqual_bool_unknown() {
+ _assertEqualEqual(_boolValue(null), _boolValue(null), _boolValue(false));
+ }
+
+ void test_equalEqual_double_false() {
+ _assertEqualEqual(_boolValue(false), _doubleValue(2.0), _doubleValue(4.0));
+ }
+
+ void test_equalEqual_double_true() {
+ _assertEqualEqual(_boolValue(true), _doubleValue(2.0), _doubleValue(2.0));
+ }
+
+ void test_equalEqual_double_unknown() {
+ _assertEqualEqual(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
+ }
+
+ void test_equalEqual_int_false() {
+ _assertEqualEqual(_boolValue(false), _intValue(-5), _intValue(5));
+ }
+
+ void test_equalEqual_int_true() {
+ _assertEqualEqual(_boolValue(true), _intValue(5), _intValue(5));
+ }
+
+ void test_equalEqual_int_unknown() {
+ _assertEqualEqual(_boolValue(null), _intValue(null), _intValue(3));
+ }
+
+ void test_equalEqual_list_empty() {
+ _assertEqualEqual(null, _listValue(), _listValue());
+ }
+
+ void test_equalEqual_list_false() {
+ _assertEqualEqual(null, _listValue(), _listValue());
+ }
+
+ void test_equalEqual_map_empty() {
+ _assertEqualEqual(null, _mapValue(), _mapValue());
+ }
+
+ void test_equalEqual_map_false() {
+ _assertEqualEqual(null, _mapValue(), _mapValue());
+ }
+
+ void test_equalEqual_null() {
+ _assertEqualEqual(_boolValue(true), _nullValue(), _nullValue());
+ }
+
+ void test_equalEqual_string_false() {
+ _assertEqualEqual(
+ _boolValue(false), _stringValue("abc"), _stringValue("def"));
+ }
+
+ void test_equalEqual_string_true() {
+ _assertEqualEqual(
+ _boolValue(true), _stringValue("abc"), _stringValue("abc"));
+ }
+
+ void test_equalEqual_string_unknown() {
+ _assertEqualEqual(
+ _boolValue(null), _stringValue(null), _stringValue("def"));
+ }
+
+ void test_equals_list_false_differentSizes() {
+ expect(
+ _listValue([_boolValue(true)]) ==
+ _listValue([_boolValue(true), _boolValue(false)]),
+ isFalse);
+ }
+
+ void test_equals_list_false_sameSize() {
+ expect(_listValue([_boolValue(true)]) == _listValue([_boolValue(false)]),
+ isFalse);
+ }
+
+ void test_equals_list_true_empty() {
+ expect(_listValue(), _listValue());
+ }
+
+ void test_equals_list_true_nonEmpty() {
+ expect(_listValue([_boolValue(true)]), _listValue([_boolValue(true)]));
+ }
+
+ void test_equals_map_true_empty() {
+ expect(_mapValue(), _mapValue());
+ }
+
+ void test_equals_symbol_false() {
+ expect(_symbolValue("a") == _symbolValue("b"), isFalse);
+ }
+
+ void test_equals_symbol_true() {
+ expect(_symbolValue("a"), _symbolValue("a"));
+ }
+
+ void test_getValue_bool_false() {
+ expect(_boolValue(false).toBoolValue(), false);
+ }
+
+ void test_getValue_bool_true() {
+ expect(_boolValue(true).toBoolValue(), true);
+ }
+
+ void test_getValue_bool_unknown() {
+ expect(_boolValue(null).toBoolValue(), isNull);
+ }
+
+ void test_getValue_double_known() {
+ double value = 2.3;
+ expect(_doubleValue(value).toDoubleValue(), value);
+ }
+
+ void test_getValue_double_unknown() {
+ expect(_doubleValue(null).toDoubleValue(), isNull);
+ }
+
+ void test_getValue_int_known() {
+ int value = 23;
+ expect(_intValue(value).toIntValue(), value);
+ }
+
+ void test_getValue_int_unknown() {
+ expect(_intValue(null).toIntValue(), isNull);
+ }
+
+ void test_getValue_list_empty() {
+ Object result = _listValue().toListValue();
+ _assertInstanceOfObjectArray(result);
+ List<Object> array = result as List<Object>;
+ expect(array, hasLength(0));
+ }
+
+ void test_getValue_list_valid() {
+ Object result = _listValue([_intValue(23)]).toListValue();
+ _assertInstanceOfObjectArray(result);
+ List<Object> array = result as List<Object>;
+ expect(array, hasLength(1));
+ }
+
+ void test_getValue_map_empty() {
+ Object result = _mapValue().toMapValue();
+ EngineTestCase.assertInstanceOf((obj) => obj is Map, Map, result);
+ Map map = result as Map;
+ expect(map, hasLength(0));
+ }
+
+ void test_getValue_map_valid() {
+ Object result =
+ _mapValue([_stringValue("key"), _stringValue("value")]).toMapValue();
+ EngineTestCase.assertInstanceOf((obj) => obj is Map, Map, result);
+ Map map = result as Map;
+ expect(map, hasLength(1));
+ }
+
+ void test_getValue_null() {
+ expect(_nullValue().isNull, isTrue);
+ }
+
+ void test_getValue_string_known() {
+ String value = "twenty-three";
+ expect(_stringValue(value).toStringValue(), value);
+ }
+
+ void test_getValue_string_unknown() {
+ expect(_stringValue(null).toStringValue(), isNull);
+ }
+
+ void test_greaterThan_knownDouble_knownDouble_false() {
+ _assertGreaterThan(_boolValue(false), _doubleValue(1.0), _doubleValue(2.0));
+ }
+
+ void test_greaterThan_knownDouble_knownDouble_true() {
+ _assertGreaterThan(_boolValue(true), _doubleValue(2.0), _doubleValue(1.0));
+ }
+
+ void test_greaterThan_knownDouble_knownInt_false() {
+ _assertGreaterThan(_boolValue(false), _doubleValue(1.0), _intValue(2));
+ }
+
+ void test_greaterThan_knownDouble_knownInt_true() {
+ _assertGreaterThan(_boolValue(true), _doubleValue(2.0), _intValue(1));
+ }
+
+ void test_greaterThan_knownDouble_unknownDouble() {
+ _assertGreaterThan(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
+ }
+
+ void test_greaterThan_knownDouble_unknownInt() {
+ _assertGreaterThan(_boolValue(null), _doubleValue(1.0), _intValue(null));
+ }
+
+ void test_greaterThan_knownInt_knownInt_false() {
+ _assertGreaterThan(_boolValue(false), _intValue(1), _intValue(2));
+ }
+
+ void test_greaterThan_knownInt_knownInt_true() {
+ _assertGreaterThan(_boolValue(true), _intValue(2), _intValue(1));
+ }
+
+ void test_greaterThan_knownInt_knownString() {
+ _assertGreaterThan(null, _intValue(1), _stringValue("2"));
+ }
+
+ void test_greaterThan_knownInt_unknownDouble() {
+ _assertGreaterThan(_boolValue(null), _intValue(1), _doubleValue(null));
+ }
+
+ void test_greaterThan_knownInt_unknownInt() {
+ _assertGreaterThan(_boolValue(null), _intValue(1), _intValue(null));
+ }
+
+ void test_greaterThan_knownString_knownInt() {
+ _assertGreaterThan(null, _stringValue("1"), _intValue(2));
+ }
+
+ void test_greaterThan_unknownDouble_knownDouble() {
+ _assertGreaterThan(_boolValue(null), _doubleValue(null), _doubleValue(2.0));
+ }
+
+ void test_greaterThan_unknownDouble_knownInt() {
+ _assertGreaterThan(_boolValue(null), _doubleValue(null), _intValue(2));
+ }
+
+ void test_greaterThan_unknownInt_knownDouble() {
+ _assertGreaterThan(_boolValue(null), _intValue(null), _doubleValue(2.0));
+ }
+
+ void test_greaterThan_unknownInt_knownInt() {
+ _assertGreaterThan(_boolValue(null), _intValue(null), _intValue(2));
+ }
+
+ void test_greaterThanOrEqual_knownDouble_knownDouble_false() {
+ _assertGreaterThanOrEqual(
+ _boolValue(false), _doubleValue(1.0), _doubleValue(2.0));
+ }
+
+ void test_greaterThanOrEqual_knownDouble_knownDouble_true() {
+ _assertGreaterThanOrEqual(
+ _boolValue(true), _doubleValue(2.0), _doubleValue(1.0));
+ }
+
+ void test_greaterThanOrEqual_knownDouble_knownInt_false() {
+ _assertGreaterThanOrEqual(
+ _boolValue(false), _doubleValue(1.0), _intValue(2));
+ }
+
+ void test_greaterThanOrEqual_knownDouble_knownInt_true() {
+ _assertGreaterThanOrEqual(
+ _boolValue(true), _doubleValue(2.0), _intValue(1));
+ }
+
+ void test_greaterThanOrEqual_knownDouble_unknownDouble() {
+ _assertGreaterThanOrEqual(
+ _boolValue(null), _doubleValue(1.0), _doubleValue(null));
+ }
+
+ void test_greaterThanOrEqual_knownDouble_unknownInt() {
+ _assertGreaterThanOrEqual(
+ _boolValue(null), _doubleValue(1.0), _intValue(null));
+ }
+
+ void test_greaterThanOrEqual_knownInt_knownInt_false() {
+ _assertGreaterThanOrEqual(_boolValue(false), _intValue(1), _intValue(2));
+ }
+
+ void test_greaterThanOrEqual_knownInt_knownInt_true() {
+ _assertGreaterThanOrEqual(_boolValue(true), _intValue(2), _intValue(2));
+ }
+
+ void test_greaterThanOrEqual_knownInt_knownString() {
+ _assertGreaterThanOrEqual(null, _intValue(1), _stringValue("2"));
+ }
+
+ void test_greaterThanOrEqual_knownInt_unknownDouble() {
+ _assertGreaterThanOrEqual(
+ _boolValue(null), _intValue(1), _doubleValue(null));
+ }
+
+ void test_greaterThanOrEqual_knownInt_unknownInt() {
+ _assertGreaterThanOrEqual(_boolValue(null), _intValue(1), _intValue(null));
+ }
+
+ void test_greaterThanOrEqual_knownString_knownInt() {
+ _assertGreaterThanOrEqual(null, _stringValue("1"), _intValue(2));
+ }
+
+ void test_greaterThanOrEqual_unknownDouble_knownDouble() {
+ _assertGreaterThanOrEqual(
+ _boolValue(null), _doubleValue(null), _doubleValue(2.0));
+ }
+
+ void test_greaterThanOrEqual_unknownDouble_knownInt() {
+ _assertGreaterThanOrEqual(
+ _boolValue(null), _doubleValue(null), _intValue(2));
+ }
+
+ void test_greaterThanOrEqual_unknownInt_knownDouble() {
+ _assertGreaterThanOrEqual(
+ _boolValue(null), _intValue(null), _doubleValue(2.0));
+ }
+
+ void test_greaterThanOrEqual_unknownInt_knownInt() {
+ _assertGreaterThanOrEqual(_boolValue(null), _intValue(null), _intValue(2));
+ }
+
+ void test_hasKnownValue_bool_false() {
+ expect(_boolValue(false).hasKnownValue, isTrue);
+ }
+
+ void test_hasKnownValue_bool_true() {
+ expect(_boolValue(true).hasKnownValue, isTrue);
+ }
+
+ void test_hasKnownValue_bool_unknown() {
+ expect(_boolValue(null).hasKnownValue, isFalse);
+ }
+
+ void test_hasKnownValue_double_known() {
+ expect(_doubleValue(2.3).hasKnownValue, isTrue);
+ }
+
+ void test_hasKnownValue_double_unknown() {
+ expect(_doubleValue(null).hasKnownValue, isFalse);
+ }
+
+ void test_hasKnownValue_dynamic() {
+ expect(_dynamicValue().hasKnownValue, isTrue);
+ }
+
+ void test_hasKnownValue_int_known() {
+ expect(_intValue(23).hasKnownValue, isTrue);
+ }
+
+ void test_hasKnownValue_int_unknown() {
+ expect(_intValue(null).hasKnownValue, isFalse);
+ }
+
+ void test_hasKnownValue_list_empty() {
+ expect(_listValue().hasKnownValue, isTrue);
+ }
+
+ void test_hasKnownValue_list_invalidElement() {
+ expect(_listValue([_dynamicValue]).hasKnownValue, isTrue);
+ }
+
+ void test_hasKnownValue_list_valid() {
+ expect(_listValue([_intValue(23)]).hasKnownValue, isTrue);
+ }
+
+ void test_hasKnownValue_map_empty() {
+ expect(_mapValue().hasKnownValue, isTrue);
+ }
+
+ void test_hasKnownValue_map_invalidKey() {
+ expect(_mapValue([_dynamicValue(), _stringValue("value")]).hasKnownValue,
+ isTrue);
+ }
+
+ void test_hasKnownValue_map_invalidValue() {
+ expect(_mapValue([_stringValue("key"), _dynamicValue()]).hasKnownValue,
+ isTrue);
+ }
+
+ void test_hasKnownValue_map_valid() {
+ expect(
+ _mapValue([_stringValue("key"), _stringValue("value")]).hasKnownValue,
+ isTrue);
+ }
+
+ void test_hasKnownValue_null() {
+ expect(_nullValue().hasKnownValue, isTrue);
+ }
+
+ void test_hasKnownValue_num() {
+ expect(_numValue().hasKnownValue, isFalse);
+ }
+
+ void test_hasKnownValue_string_known() {
+ expect(_stringValue("twenty-three").hasKnownValue, isTrue);
+ }
+
+ void test_hasKnownValue_string_unknown() {
+ expect(_stringValue(null).hasKnownValue, isFalse);
+ }
+
+ void test_identical_bool_false() {
+ _assertIdentical(_boolValue(false), _boolValue(false), _boolValue(true));
+ }
+
+ void test_identical_bool_true() {
+ _assertIdentical(_boolValue(true), _boolValue(true), _boolValue(true));
+ }
+
+ void test_identical_bool_unknown() {
+ _assertIdentical(_boolValue(null), _boolValue(null), _boolValue(false));
+ }
+
+ void test_identical_double_false() {
+ _assertIdentical(_boolValue(false), _doubleValue(2.0), _doubleValue(4.0));
+ }
+
+ void test_identical_double_true() {
+ _assertIdentical(_boolValue(true), _doubleValue(2.0), _doubleValue(2.0));
+ }
+
+ void test_identical_double_unknown() {
+ _assertIdentical(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
+ }
+
+ void test_identical_int_false() {
+ _assertIdentical(_boolValue(false), _intValue(-5), _intValue(5));
+ }
+
+ void test_identical_int_true() {
+ _assertIdentical(_boolValue(true), _intValue(5), _intValue(5));
+ }
+
+ void test_identical_int_unknown() {
+ _assertIdentical(_boolValue(null), _intValue(null), _intValue(3));
+ }
+
+ void test_identical_list_empty() {
+ _assertIdentical(_boolValue(true), _listValue(), _listValue());
+ }
+
+ void test_identical_list_false() {
+ _assertIdentical(
+ _boolValue(false), _listValue(), _listValue([_intValue(3)]));
+ }
+
+ void test_identical_map_empty() {
+ _assertIdentical(_boolValue(true), _mapValue(), _mapValue());
+ }
+
+ void test_identical_map_false() {
+ _assertIdentical(_boolValue(false), _mapValue(),
+ _mapValue([_intValue(1), _intValue(2)]));
+ }
+
+ void test_identical_null() {
+ _assertIdentical(_boolValue(true), _nullValue(), _nullValue());
+ }
+
+ void test_identical_string_false() {
+ _assertIdentical(
+ _boolValue(false), _stringValue("abc"), _stringValue("def"));
+ }
+
+ void test_identical_string_true() {
+ _assertIdentical(
+ _boolValue(true), _stringValue("abc"), _stringValue("abc"));
+ }
+
+ void test_identical_string_unknown() {
+ _assertIdentical(_boolValue(null), _stringValue(null), _stringValue("def"));
+ }
+
+ void test_integerDivide_knownDouble_knownDouble() {
+ _assertIntegerDivide(_intValue(3), _doubleValue(6.0), _doubleValue(2.0));
+ }
+
+ void test_integerDivide_knownDouble_knownInt() {
+ _assertIntegerDivide(_intValue(3), _doubleValue(6.0), _intValue(2));
+ }
+
+ void test_integerDivide_knownDouble_unknownDouble() {
+ _assertIntegerDivide(
+ _intValue(null), _doubleValue(6.0), _doubleValue(null));
+ }
+
+ void test_integerDivide_knownDouble_unknownInt() {
+ _assertIntegerDivide(_intValue(null), _doubleValue(6.0), _intValue(null));
+ }
+
+ void test_integerDivide_knownInt_knownInt() {
+ _assertIntegerDivide(_intValue(3), _intValue(6), _intValue(2));
+ }
+
+ void test_integerDivide_knownInt_knownString() {
+ _assertIntegerDivide(null, _intValue(6), _stringValue("2"));
+ }
+
+ void test_integerDivide_knownInt_unknownDouble() {
+ _assertIntegerDivide(_intValue(null), _intValue(6), _doubleValue(null));
+ }
+
+ void test_integerDivide_knownInt_unknownInt() {
+ _assertIntegerDivide(_intValue(null), _intValue(6), _intValue(null));
+ }
+
+ void test_integerDivide_knownString_knownInt() {
+ _assertIntegerDivide(null, _stringValue("6"), _intValue(2));
+ }
+
+ void test_integerDivide_unknownDouble_knownDouble() {
+ _assertIntegerDivide(
+ _intValue(null), _doubleValue(null), _doubleValue(2.0));
+ }
+
+ void test_integerDivide_unknownDouble_knownInt() {
+ _assertIntegerDivide(_intValue(null), _doubleValue(null), _intValue(2));
+ }
+
+ void test_integerDivide_unknownInt_knownDouble() {
+ _assertIntegerDivide(_intValue(null), _intValue(null), _doubleValue(2.0));
+ }
+
+ void test_integerDivide_unknownInt_knownInt() {
+ _assertIntegerDivide(_intValue(null), _intValue(null), _intValue(2));
+ }
+
+ void test_isBoolNumStringOrNull_bool_false() {
+ expect(_boolValue(false).isBoolNumStringOrNull, isTrue);
+ }
+
+ void test_isBoolNumStringOrNull_bool_true() {
+ expect(_boolValue(true).isBoolNumStringOrNull, isTrue);
+ }
+
+ void test_isBoolNumStringOrNull_bool_unknown() {
+ expect(_boolValue(null).isBoolNumStringOrNull, isTrue);
+ }
+
+ void test_isBoolNumStringOrNull_double_known() {
+ expect(_doubleValue(2.3).isBoolNumStringOrNull, isTrue);
+ }
+
+ void test_isBoolNumStringOrNull_double_unknown() {
+ expect(_doubleValue(null).isBoolNumStringOrNull, isTrue);
+ }
+
+ void test_isBoolNumStringOrNull_dynamic() {
+ expect(_dynamicValue().isBoolNumStringOrNull, isTrue);
+ }
+
+ void test_isBoolNumStringOrNull_int_known() {
+ expect(_intValue(23).isBoolNumStringOrNull, isTrue);
+ }
+
+ void test_isBoolNumStringOrNull_int_unknown() {
+ expect(_intValue(null).isBoolNumStringOrNull, isTrue);
+ }
+
+ void test_isBoolNumStringOrNull_list() {
+ expect(_listValue().isBoolNumStringOrNull, isFalse);
+ }
+
+ void test_isBoolNumStringOrNull_null() {
+ expect(_nullValue().isBoolNumStringOrNull, isTrue);
+ }
+
+ void test_isBoolNumStringOrNull_num() {
+ expect(_numValue().isBoolNumStringOrNull, isTrue);
+ }
+
+ void test_isBoolNumStringOrNull_string_known() {
+ expect(_stringValue("twenty-three").isBoolNumStringOrNull, isTrue);
+ }
+
+ void test_isBoolNumStringOrNull_string_unknown() {
+ expect(_stringValue(null).isBoolNumStringOrNull, isTrue);
+ }
+
+ void test_lessThan_knownDouble_knownDouble_false() {
+ _assertLessThan(_boolValue(false), _doubleValue(2.0), _doubleValue(1.0));
+ }
+
+ void test_lessThan_knownDouble_knownDouble_true() {
+ _assertLessThan(_boolValue(true), _doubleValue(1.0), _doubleValue(2.0));
+ }
+
+ void test_lessThan_knownDouble_knownInt_false() {
+ _assertLessThan(_boolValue(false), _doubleValue(2.0), _intValue(1));
+ }
+
+ void test_lessThan_knownDouble_knownInt_true() {
+ _assertLessThan(_boolValue(true), _doubleValue(1.0), _intValue(2));
+ }
+
+ void test_lessThan_knownDouble_unknownDouble() {
+ _assertLessThan(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
+ }
+
+ void test_lessThan_knownDouble_unknownInt() {
+ _assertLessThan(_boolValue(null), _doubleValue(1.0), _intValue(null));
+ }
+
+ void test_lessThan_knownInt_knownInt_false() {
+ _assertLessThan(_boolValue(false), _intValue(2), _intValue(1));
+ }
+
+ void test_lessThan_knownInt_knownInt_true() {
+ _assertLessThan(_boolValue(true), _intValue(1), _intValue(2));
+ }
+
+ void test_lessThan_knownInt_knownString() {
+ _assertLessThan(null, _intValue(1), _stringValue("2"));
+ }
+
+ void test_lessThan_knownInt_unknownDouble() {
+ _assertLessThan(_boolValue(null), _intValue(1), _doubleValue(null));
+ }
+
+ void test_lessThan_knownInt_unknownInt() {
+ _assertLessThan(_boolValue(null), _intValue(1), _intValue(null));
+ }
+
+ void test_lessThan_knownString_knownInt() {
+ _assertLessThan(null, _stringValue("1"), _intValue(2));
+ }
+
+ void test_lessThan_unknownDouble_knownDouble() {
+ _assertLessThan(_boolValue(null), _doubleValue(null), _doubleValue(2.0));
+ }
+
+ void test_lessThan_unknownDouble_knownInt() {
+ _assertLessThan(_boolValue(null), _doubleValue(null), _intValue(2));
+ }
+
+ void test_lessThan_unknownInt_knownDouble() {
+ _assertLessThan(_boolValue(null), _intValue(null), _doubleValue(2.0));
+ }
+
+ void test_lessThan_unknownInt_knownInt() {
+ _assertLessThan(_boolValue(null), _intValue(null), _intValue(2));
+ }
+
+ void test_lessThanOrEqual_knownDouble_knownDouble_false() {
+ _assertLessThanOrEqual(
+ _boolValue(false), _doubleValue(2.0), _doubleValue(1.0));
+ }
+
+ void test_lessThanOrEqual_knownDouble_knownDouble_true() {
+ _assertLessThanOrEqual(
+ _boolValue(true), _doubleValue(1.0), _doubleValue(2.0));
+ }
+
+ void test_lessThanOrEqual_knownDouble_knownInt_false() {
+ _assertLessThanOrEqual(_boolValue(false), _doubleValue(2.0), _intValue(1));
+ }
+
+ void test_lessThanOrEqual_knownDouble_knownInt_true() {
+ _assertLessThanOrEqual(_boolValue(true), _doubleValue(1.0), _intValue(2));
+ }
+
+ void test_lessThanOrEqual_knownDouble_unknownDouble() {
+ _assertLessThanOrEqual(
+ _boolValue(null), _doubleValue(1.0), _doubleValue(null));
+ }
+
+ void test_lessThanOrEqual_knownDouble_unknownInt() {
+ _assertLessThanOrEqual(
+ _boolValue(null), _doubleValue(1.0), _intValue(null));
+ }
+
+ void test_lessThanOrEqual_knownInt_knownInt_false() {
+ _assertLessThanOrEqual(_boolValue(false), _intValue(2), _intValue(1));
+ }
+
+ void test_lessThanOrEqual_knownInt_knownInt_true() {
+ _assertLessThanOrEqual(_boolValue(true), _intValue(1), _intValue(2));
+ }
+
+ void test_lessThanOrEqual_knownInt_knownString() {
+ _assertLessThanOrEqual(null, _intValue(1), _stringValue("2"));
+ }
+
+ void test_lessThanOrEqual_knownInt_unknownDouble() {
+ _assertLessThanOrEqual(_boolValue(null), _intValue(1), _doubleValue(null));
+ }
+
+ void test_lessThanOrEqual_knownInt_unknownInt() {
+ _assertLessThanOrEqual(_boolValue(null), _intValue(1), _intValue(null));
+ }
+
+ void test_lessThanOrEqual_knownString_knownInt() {
+ _assertLessThanOrEqual(null, _stringValue("1"), _intValue(2));
+ }
+
+ void test_lessThanOrEqual_unknownDouble_knownDouble() {
+ _assertLessThanOrEqual(
+ _boolValue(null), _doubleValue(null), _doubleValue(2.0));
+ }
+
+ void test_lessThanOrEqual_unknownDouble_knownInt() {
+ _assertLessThanOrEqual(_boolValue(null), _doubleValue(null), _intValue(2));
+ }
+
+ void test_lessThanOrEqual_unknownInt_knownDouble() {
+ _assertLessThanOrEqual(
+ _boolValue(null), _intValue(null), _doubleValue(2.0));
+ }
+
+ void test_lessThanOrEqual_unknownInt_knownInt() {
+ _assertLessThanOrEqual(_boolValue(null), _intValue(null), _intValue(2));
+ }
+
+ void test_logicalAnd_false_false() {
+ _assertLogicalAnd(_boolValue(false), _boolValue(false), _boolValue(false));
+ }
+
+ void test_logicalAnd_false_null() {
+ try {
+ _assertLogicalAnd(_boolValue(false), _boolValue(false), _nullValue());
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalAnd_false_string() {
+ try {
+ _assertLogicalAnd(
+ _boolValue(false), _boolValue(false), _stringValue("false"));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalAnd_false_true() {
+ _assertLogicalAnd(_boolValue(false), _boolValue(false), _boolValue(true));
+ }
+
+ void test_logicalAnd_null_false() {
+ try {
+ _assertLogicalAnd(_boolValue(false), _nullValue(), _boolValue(false));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalAnd_null_true() {
+ try {
+ _assertLogicalAnd(_boolValue(false), _nullValue(), _boolValue(true));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalAnd_string_false() {
+ try {
+ _assertLogicalAnd(
+ _boolValue(false), _stringValue("true"), _boolValue(false));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalAnd_string_true() {
+ try {
+ _assertLogicalAnd(
+ _boolValue(false), _stringValue("false"), _boolValue(true));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalAnd_true_false() {
+ _assertLogicalAnd(_boolValue(false), _boolValue(true), _boolValue(false));
+ }
+
+ void test_logicalAnd_true_null() {
+ _assertLogicalAnd(null, _boolValue(true), _nullValue());
+ }
+
+ void test_logicalAnd_true_string() {
+ try {
+ _assertLogicalAnd(
+ _boolValue(false), _boolValue(true), _stringValue("true"));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalAnd_true_true() {
+ _assertLogicalAnd(_boolValue(true), _boolValue(true), _boolValue(true));
+ }
+
+ void test_logicalNot_false() {
+ _assertLogicalNot(_boolValue(true), _boolValue(false));
+ }
+
+ void test_logicalNot_null() {
+ _assertLogicalNot(null, _nullValue());
+ }
+
+ void test_logicalNot_string() {
+ try {
+ _assertLogicalNot(_boolValue(true), _stringValue(null));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalNot_true() {
+ _assertLogicalNot(_boolValue(false), _boolValue(true));
+ }
+
+ void test_logicalNot_unknown() {
+ _assertLogicalNot(_boolValue(null), _boolValue(null));
+ }
+
+ void test_logicalOr_false_false() {
+ _assertLogicalOr(_boolValue(false), _boolValue(false), _boolValue(false));
+ }
+
+ void test_logicalOr_false_null() {
+ _assertLogicalOr(null, _boolValue(false), _nullValue());
+ }
+
+ void test_logicalOr_false_string() {
+ try {
+ _assertLogicalOr(
+ _boolValue(false), _boolValue(false), _stringValue("false"));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalOr_false_true() {
+ _assertLogicalOr(_boolValue(true), _boolValue(false), _boolValue(true));
+ }
+
+ void test_logicalOr_null_false() {
+ try {
+ _assertLogicalOr(_boolValue(false), _nullValue(), _boolValue(false));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalOr_null_true() {
+ try {
+ _assertLogicalOr(_boolValue(true), _nullValue(), _boolValue(true));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalOr_string_false() {
+ try {
+ _assertLogicalOr(
+ _boolValue(false), _stringValue("true"), _boolValue(false));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalOr_string_true() {
+ try {
+ _assertLogicalOr(
+ _boolValue(true), _stringValue("false"), _boolValue(true));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalOr_true_false() {
+ _assertLogicalOr(_boolValue(true), _boolValue(true), _boolValue(false));
+ }
+
+ void test_logicalOr_true_null() {
+ try {
+ _assertLogicalOr(_boolValue(true), _boolValue(true), _nullValue());
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalOr_true_string() {
+ try {
+ _assertLogicalOr(
+ _boolValue(true), _boolValue(true), _stringValue("true"));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_logicalOr_true_true() {
+ _assertLogicalOr(_boolValue(true), _boolValue(true), _boolValue(true));
+ }
+
+ void test_minus_knownDouble_knownDouble() {
+ _assertMinus(_doubleValue(1.0), _doubleValue(4.0), _doubleValue(3.0));
+ }
+
+ void test_minus_knownDouble_knownInt() {
+ _assertMinus(_doubleValue(1.0), _doubleValue(4.0), _intValue(3));
+ }
+
+ void test_minus_knownDouble_unknownDouble() {
+ _assertMinus(_doubleValue(null), _doubleValue(4.0), _doubleValue(null));
+ }
+
+ void test_minus_knownDouble_unknownInt() {
+ _assertMinus(_doubleValue(null), _doubleValue(4.0), _intValue(null));
+ }
+
+ void test_minus_knownInt_knownInt() {
+ _assertMinus(_intValue(1), _intValue(4), _intValue(3));
+ }
+
+ void test_minus_knownInt_knownString() {
+ _assertMinus(null, _intValue(4), _stringValue("3"));
+ }
+
+ void test_minus_knownInt_unknownDouble() {
+ _assertMinus(_doubleValue(null), _intValue(4), _doubleValue(null));
+ }
+
+ void test_minus_knownInt_unknownInt() {
+ _assertMinus(_intValue(null), _intValue(4), _intValue(null));
+ }
+
+ void test_minus_knownString_knownInt() {
+ _assertMinus(null, _stringValue("4"), _intValue(3));
+ }
+
+ void test_minus_unknownDouble_knownDouble() {
+ _assertMinus(_doubleValue(null), _doubleValue(null), _doubleValue(3.0));
+ }
+
+ void test_minus_unknownDouble_knownInt() {
+ _assertMinus(_doubleValue(null), _doubleValue(null), _intValue(3));
+ }
+
+ void test_minus_unknownInt_knownDouble() {
+ _assertMinus(_doubleValue(null), _intValue(null), _doubleValue(3.0));
+ }
+
+ void test_minus_unknownInt_knownInt() {
+ _assertMinus(_intValue(null), _intValue(null), _intValue(3));
+ }
+
+ void test_negated_double_known() {
+ _assertNegated(_doubleValue(2.0), _doubleValue(-2.0));
+ }
+
+ void test_negated_double_unknown() {
+ _assertNegated(_doubleValue(null), _doubleValue(null));
+ }
+
+ void test_negated_int_known() {
+ _assertNegated(_intValue(-3), _intValue(3));
+ }
+
+ void test_negated_int_unknown() {
+ _assertNegated(_intValue(null), _intValue(null));
+ }
+
+ void test_negated_string() {
+ _assertNegated(null, _stringValue(null));
+ }
+
+ void test_notEqual_bool_false() {
+ _assertNotEqual(_boolValue(false), _boolValue(true), _boolValue(true));
+ }
+
+ void test_notEqual_bool_true() {
+ _assertNotEqual(_boolValue(true), _boolValue(false), _boolValue(true));
+ }
+
+ void test_notEqual_bool_unknown() {
+ _assertNotEqual(_boolValue(null), _boolValue(null), _boolValue(false));
+ }
+
+ void test_notEqual_double_false() {
+ _assertNotEqual(_boolValue(false), _doubleValue(2.0), _doubleValue(2.0));
+ }
+
+ void test_notEqual_double_true() {
+ _assertNotEqual(_boolValue(true), _doubleValue(2.0), _doubleValue(4.0));
+ }
+
+ void test_notEqual_double_unknown() {
+ _assertNotEqual(_boolValue(null), _doubleValue(1.0), _doubleValue(null));
+ }
+
+ void test_notEqual_int_false() {
+ _assertNotEqual(_boolValue(false), _intValue(5), _intValue(5));
+ }
+
+ void test_notEqual_int_true() {
+ _assertNotEqual(_boolValue(true), _intValue(-5), _intValue(5));
+ }
+
+ void test_notEqual_int_unknown() {
+ _assertNotEqual(_boolValue(null), _intValue(null), _intValue(3));
+ }
+
+ void test_notEqual_null() {
+ _assertNotEqual(_boolValue(false), _nullValue(), _nullValue());
+ }
+
+ void test_notEqual_string_false() {
+ _assertNotEqual(
+ _boolValue(false), _stringValue("abc"), _stringValue("abc"));
+ }
+
+ void test_notEqual_string_true() {
+ _assertNotEqual(_boolValue(true), _stringValue("abc"), _stringValue("def"));
+ }
+
+ void test_notEqual_string_unknown() {
+ _assertNotEqual(_boolValue(null), _stringValue(null), _stringValue("def"));
+ }
+
+ void test_performToString_bool_false() {
+ _assertPerformToString(_stringValue("false"), _boolValue(false));
+ }
+
+ void test_performToString_bool_true() {
+ _assertPerformToString(_stringValue("true"), _boolValue(true));
+ }
+
+ void test_performToString_bool_unknown() {
+ _assertPerformToString(_stringValue(null), _boolValue(null));
+ }
+
+ void test_performToString_double_known() {
+ _assertPerformToString(_stringValue("2.0"), _doubleValue(2.0));
+ }
+
+ void test_performToString_double_unknown() {
+ _assertPerformToString(_stringValue(null), _doubleValue(null));
+ }
+
+ void test_performToString_int_known() {
+ _assertPerformToString(_stringValue("5"), _intValue(5));
+ }
+
+ void test_performToString_int_unknown() {
+ _assertPerformToString(_stringValue(null), _intValue(null));
+ }
+
+ void test_performToString_null() {
+ _assertPerformToString(_stringValue("null"), _nullValue());
+ }
+
+ void test_performToString_string_known() {
+ _assertPerformToString(_stringValue("abc"), _stringValue("abc"));
+ }
+
+ void test_performToString_string_unknown() {
+ _assertPerformToString(_stringValue(null), _stringValue(null));
+ }
+
+ void test_remainder_knownDouble_knownDouble() {
+ _assertRemainder(_doubleValue(1.0), _doubleValue(7.0), _doubleValue(2.0));
+ }
+
+ void test_remainder_knownDouble_knownInt() {
+ _assertRemainder(_doubleValue(1.0), _doubleValue(7.0), _intValue(2));
+ }
+
+ void test_remainder_knownDouble_unknownDouble() {
+ _assertRemainder(_doubleValue(null), _doubleValue(7.0), _doubleValue(null));
+ }
+
+ void test_remainder_knownDouble_unknownInt() {
+ _assertRemainder(_doubleValue(null), _doubleValue(6.0), _intValue(null));
+ }
+
+ void test_remainder_knownInt_knownInt() {
+ _assertRemainder(_intValue(1), _intValue(7), _intValue(2));
+ }
+
+ void test_remainder_knownInt_knownString() {
+ _assertRemainder(null, _intValue(7), _stringValue("2"));
+ }
+
+ void test_remainder_knownInt_unknownDouble() {
+ _assertRemainder(_doubleValue(null), _intValue(7), _doubleValue(null));
+ }
+
+ void test_remainder_knownInt_unknownInt() {
+ _assertRemainder(_intValue(null), _intValue(7), _intValue(null));
+ }
+
+ void test_remainder_knownString_knownInt() {
+ _assertRemainder(null, _stringValue("7"), _intValue(2));
+ }
+
+ void test_remainder_unknownDouble_knownDouble() {
+ _assertRemainder(_doubleValue(null), _doubleValue(null), _doubleValue(2.0));
+ }
+
+ void test_remainder_unknownDouble_knownInt() {
+ _assertRemainder(_doubleValue(null), _doubleValue(null), _intValue(2));
+ }
+
+ void test_remainder_unknownInt_knownDouble() {
+ _assertRemainder(_doubleValue(null), _intValue(null), _doubleValue(2.0));
+ }
+
+ void test_remainder_unknownInt_knownInt() {
+ _assertRemainder(_intValue(null), _intValue(null), _intValue(2));
+ }
+
+ void test_shiftLeft_knownInt_knownInt() {
+ _assertShiftLeft(_intValue(48), _intValue(6), _intValue(3));
+ }
+
+ void test_shiftLeft_knownInt_knownString() {
+ _assertShiftLeft(null, _intValue(6), _stringValue(null));
+ }
+
+ void test_shiftLeft_knownInt_tooLarge() {
+ _assertShiftLeft(
+ _intValue(null),
+ _intValue(6),
+ new DartObjectImpl(
+ _typeProvider.intType, new IntState(LONG_MAX_VALUE)));
+ }
+
+ void test_shiftLeft_knownInt_unknownInt() {
+ _assertShiftLeft(_intValue(null), _intValue(6), _intValue(null));
+ }
+
+ void test_shiftLeft_knownString_knownInt() {
+ _assertShiftLeft(null, _stringValue(null), _intValue(3));
+ }
+
+ void test_shiftLeft_unknownInt_knownInt() {
+ _assertShiftLeft(_intValue(null), _intValue(null), _intValue(3));
+ }
+
+ void test_shiftLeft_unknownInt_unknownInt() {
+ _assertShiftLeft(_intValue(null), _intValue(null), _intValue(null));
+ }
+
+ void test_shiftRight_knownInt_knownInt() {
+ _assertShiftRight(_intValue(6), _intValue(48), _intValue(3));
+ }
+
+ void test_shiftRight_knownInt_knownString() {
+ _assertShiftRight(null, _intValue(48), _stringValue(null));
+ }
+
+ void test_shiftRight_knownInt_tooLarge() {
+ _assertShiftRight(
+ _intValue(null),
+ _intValue(48),
+ new DartObjectImpl(
+ _typeProvider.intType, new IntState(LONG_MAX_VALUE)));
+ }
+
+ void test_shiftRight_knownInt_unknownInt() {
+ _assertShiftRight(_intValue(null), _intValue(48), _intValue(null));
+ }
+
+ void test_shiftRight_knownString_knownInt() {
+ _assertShiftRight(null, _stringValue(null), _intValue(3));
+ }
+
+ void test_shiftRight_unknownInt_knownInt() {
+ _assertShiftRight(_intValue(null), _intValue(null), _intValue(3));
+ }
+
+ void test_shiftRight_unknownInt_unknownInt() {
+ _assertShiftRight(_intValue(null), _intValue(null), _intValue(null));
+ }
+
+ void test_stringLength_int() {
+ try {
+ _assertStringLength(_intValue(null), _intValue(0));
+ fail("Expected EvaluationException");
+ } on EvaluationException {}
+ }
+
+ void test_stringLength_knownString() {
+ _assertStringLength(_intValue(3), _stringValue("abc"));
+ }
+
+ void test_stringLength_unknownString() {
+ _assertStringLength(_intValue(null), _stringValue(null));
+ }
+
+ void test_times_knownDouble_knownDouble() {
+ _assertTimes(_doubleValue(6.0), _doubleValue(2.0), _doubleValue(3.0));
+ }
+
+ void test_times_knownDouble_knownInt() {
+ _assertTimes(_doubleValue(6.0), _doubleValue(2.0), _intValue(3));
+ }
+
+ void test_times_knownDouble_unknownDouble() {
+ _assertTimes(_doubleValue(null), _doubleValue(2.0), _doubleValue(null));
+ }
+
+ void test_times_knownDouble_unknownInt() {
+ _assertTimes(_doubleValue(null), _doubleValue(2.0), _intValue(null));
+ }
+
+ void test_times_knownInt_knownInt() {
+ _assertTimes(_intValue(6), _intValue(2), _intValue(3));
+ }
+
+ void test_times_knownInt_knownString() {
+ _assertTimes(null, _intValue(2), _stringValue("3"));
+ }
+
+ void test_times_knownInt_unknownDouble() {
+ _assertTimes(_doubleValue(null), _intValue(2), _doubleValue(null));
+ }
+
+ void test_times_knownInt_unknownInt() {
+ _assertTimes(_intValue(null), _intValue(2), _intValue(null));
+ }
+
+ void test_times_knownString_knownInt() {
+ _assertTimes(null, _stringValue("2"), _intValue(3));
+ }
+
+ void test_times_unknownDouble_knownDouble() {
+ _assertTimes(_doubleValue(null), _doubleValue(null), _doubleValue(3.0));
+ }
+
+ void test_times_unknownDouble_knownInt() {
+ _assertTimes(_doubleValue(null), _doubleValue(null), _intValue(3));
+ }
+
+ void test_times_unknownInt_knownDouble() {
+ _assertTimes(_doubleValue(null), _intValue(null), _doubleValue(3.0));
+ }
+
+ void test_times_unknownInt_knownInt() {
+ _assertTimes(_intValue(null), _intValue(null), _intValue(3));
+ }
+
+ /**
+ * Assert that the result of adding the [left] and [right] operands is the
+ * [expected] value, or that the operation throws an exception if the expected
+ * value is `null`.
+ */
+ void _assertAdd(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.add(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.add(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of bit-anding the [left] and [right] operands is the
+ * [expected] value, or that the operation throws an exception if the expected
+ * value is `null`.
+ */
+ void _assertBitAnd(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.bitAnd(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.bitAnd(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the bit-not of the [operand] is the [expected] value, or that
+ * the operation throws an exception if the expected value is `null`.
+ */
+ void _assertBitNot(DartObjectImpl expected, DartObjectImpl operand) {
+ if (expected == null) {
+ try {
+ operand.bitNot(_typeProvider);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = operand.bitNot(_typeProvider);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of bit-oring the [left] and [right] operands is the
+ * [expected] value, or that the operation throws an exception if the expected
+ * value is `null`.
+ */
+ void _assertBitOr(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.bitOr(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.bitOr(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of bit-xoring the [left] and [right] operands is the
+ * [expected] value, or that the operation throws an exception if the expected
+ * value is `null`.
+ */
+ void _assertBitXor(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.bitXor(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.bitXor(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of concatenating the [left] and [right] operands is
+ * the [expected] value, or that the operation throws an exception if the
+ * expected value is `null`.
+ */
+ void _assertConcatenate(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.concatenate(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.concatenate(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of dividing the [left] and [right] operands is the
+ * [expected] value, or that the operation throws an exception if the expected
+ * value is `null`.
+ */
+ void _assertDivide(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.divide(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.divide(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of comparing the [left] and [right] operands for
+ * equality is the [expected] value, or that the operation throws an exception
+ * if the expected value is `null`.
+ */
+ void _assertEqualEqual(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.equalEqual(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.equalEqual(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of comparing the [left] and [right] operands is the
+ * [expected] value, or that the operation throws an exception if the expected
+ * value is `null`.
+ */
+ void _assertGreaterThan(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.greaterThan(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.greaterThan(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of comparing the [left] and [right] operands is the
+ * [expected] value, or that the operation throws an exception if the expected
+ * value is `null`.
+ */
+ void _assertGreaterThanOrEqual(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.greaterThanOrEqual(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.greaterThanOrEqual(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of comparing the [left] and [right] operands using
+ * identical() is the expected value.
+ */
+ void _assertIdentical(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ DartObjectImpl result = left.isIdentical(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+
+ void _assertInstanceOfObjectArray(Object result) {
+ // TODO(scheglov) implement
+ }
+
+ /**
+ * Assert that the result of dividing the [left] and [right] operands as
+ * integers is the [expected] value, or that the operation throws an exception
+ * if the expected value is `null`.
+ */
+ void _assertIntegerDivide(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.integerDivide(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.integerDivide(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of comparing the [left] and [right] operands is the
+ * [expected] value, or that the operation throws an exception if the expected
+ * value is `null`.
+ */
+ void _assertLessThan(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.lessThan(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.lessThan(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of comparing the [left] and [right] operands is the
+ * [expected] value, or that the operation throws an exception if the expected
+ * value is `null`.
+ */
+ void _assertLessThanOrEqual(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.lessThanOrEqual(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.lessThanOrEqual(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of logical-anding the [left] and [right] operands is
+ * the [expected] value, or that the operation throws an exception if the
+ * expected value is `null`.
+ */
+ void _assertLogicalAnd(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.logicalAnd(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.logicalAnd(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the logical-not of the [operand] is the [expected] value, or
+ * that the operation throws an exception if the expected value is `null`.
+ */
+ void _assertLogicalNot(DartObjectImpl expected, DartObjectImpl operand) {
+ if (expected == null) {
+ try {
+ operand.logicalNot(_typeProvider);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = operand.logicalNot(_typeProvider);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of logical-oring the [left] and [right] operands is
+ * the [expected] value, or that the operation throws an exception if the
+ * expected value is `null`.
+ */
+ void _assertLogicalOr(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.logicalOr(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.logicalOr(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of subtracting the [left] and [right] operands is
+ * the [expected] value, or that the operation throws an exception if the
+ * expected value is `null`.
+ */
+ void _assertMinus(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.minus(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.minus(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the negation of the [operand] is the [expected] value, or that
+ * the operation throws an exception if the expected value is `null`.
+ */
+ void _assertNegated(DartObjectImpl expected, DartObjectImpl operand) {
+ if (expected == null) {
+ try {
+ operand.negated(_typeProvider);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = operand.negated(_typeProvider);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of comparing the [left] and [right] operands for
+ * inequality is the [expected] value, or that the operation throws an
+ * exception if the expected value is `null`.
+ */
+ void _assertNotEqual(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.notEqual(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.notEqual(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that converting the [operand] to a string is the [expected] value,
+ * or that the operation throws an exception if the expected value is `null`.
+ */
+ void _assertPerformToString(DartObjectImpl expected, DartObjectImpl operand) {
+ if (expected == null) {
+ try {
+ operand.performToString(_typeProvider);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = operand.performToString(_typeProvider);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of taking the remainder of the [left] and [right]
+ * operands is the [expected] value, or that the operation throws an exception
+ * if the expected value is `null`.
+ */
+ void _assertRemainder(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.remainder(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.remainder(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of multiplying the [left] and [right] operands is
+ * the [expected] value, or that the operation throws an exception if the
+ * expected value is `null`.
+ */
+ void _assertShiftLeft(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.shiftLeft(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.shiftLeft(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of multiplying the [left] and [right] operands is
+ * the [expected] value, or that the operation throws an exception if the
+ * expected value is `null`.
+ */
+ void _assertShiftRight(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.shiftRight(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.shiftRight(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the length of the [operand] is the [expected] value, or that
+ * the operation throws an exception if the expected value is `null`.
+ */
+ void _assertStringLength(DartObjectImpl expected, DartObjectImpl operand) {
+ if (expected == null) {
+ try {
+ operand.stringLength(_typeProvider);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = operand.stringLength(_typeProvider);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ /**
+ * Assert that the result of multiplying the [left] and [right] operands is
+ * the [expected] value, or that the operation throws an exception if the
+ * expected value is `null`.
+ */
+ void _assertTimes(
+ DartObjectImpl expected, DartObjectImpl left, DartObjectImpl right) {
+ if (expected == null) {
+ try {
+ left.times(_typeProvider, right);
+ fail("Expected an EvaluationException");
+ } on EvaluationException {}
+ } else {
+ DartObjectImpl result = left.times(_typeProvider, right);
+ expect(result, isNotNull);
+ expect(result, expected);
+ }
+ }
+
+ DartObjectImpl _boolValue(bool value) {
+ if (value == null) {
+ return new DartObjectImpl(
+ _typeProvider.boolType, BoolState.UNKNOWN_VALUE);
+ } else if (identical(value, false)) {
+ return new DartObjectImpl(_typeProvider.boolType, BoolState.FALSE_STATE);
+ } else if (identical(value, true)) {
+ return new DartObjectImpl(_typeProvider.boolType, BoolState.TRUE_STATE);
+ }
+ fail("Invalid boolean value used in test");
+ return null;
+ }
+
+ DartObjectImpl _doubleValue(double value) {
+ if (value == null) {
+ return new DartObjectImpl(
+ _typeProvider.doubleType, DoubleState.UNKNOWN_VALUE);
+ } else {
+ return new DartObjectImpl(
+ _typeProvider.doubleType, new DoubleState(value));
+ }
+ }
+
+ DartObjectImpl _dynamicValue() {
+ return new DartObjectImpl(
+ _typeProvider.nullType, DynamicState.DYNAMIC_STATE);
+ }
+
+ DartObjectImpl _intValue(int value) {
+ if (value == null) {
+ return new DartObjectImpl(_typeProvider.intType, IntState.UNKNOWN_VALUE);
+ } else {
+ return new DartObjectImpl(_typeProvider.intType, new IntState(value));
+ }
+ }
+
+ DartObjectImpl _listValue(
+ [List<DartObjectImpl> elements = DartObjectImpl.EMPTY_LIST]) {
+ return new DartObjectImpl(_typeProvider.listType, new ListState(elements));
+ }
+
+ DartObjectImpl _mapValue(
+ [List<DartObjectImpl> keyElementPairs = DartObjectImpl.EMPTY_LIST]) {
+ Map<DartObjectImpl, DartObjectImpl> map =
+ new Map<DartObjectImpl, DartObjectImpl>();
+ int count = keyElementPairs.length;
+ for (int i = 0; i < count;) {
+ map[keyElementPairs[i++]] = keyElementPairs[i++];
+ }
+ return new DartObjectImpl(_typeProvider.mapType, new MapState(map));
+ }
+
+ DartObjectImpl _nullValue() {
+ return new DartObjectImpl(_typeProvider.nullType, NullState.NULL_STATE);
+ }
+
+ DartObjectImpl _numValue() {
+ return new DartObjectImpl(_typeProvider.nullType, NumState.UNKNOWN_VALUE);
+ }
+
+ DartObjectImpl _stringValue(String value) {
+ if (value == null) {
+ return new DartObjectImpl(
+ _typeProvider.stringType, StringState.UNKNOWN_VALUE);
+ } else {
+ return new DartObjectImpl(
+ _typeProvider.stringType, new StringState(value));
+ }
+ }
+
+ DartObjectImpl _symbolValue(String value) {
+ return new DartObjectImpl(_typeProvider.symbolType, new SymbolState(value));
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index c097cff..17f71cc 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/engine.dart'
show AnalysisContext, AnalysisOptionsImpl;
@@ -119,6 +120,24 @@
}
}
+ void test_constructors_mixinApplicationWithHandle() {
+ AnalysisContext context = createAnalysisContext();
+ context.sourceFactory = new SourceFactory([]);
+
+ ElementLocation location = new ElementLocationImpl.con2('');
+ ClassElementImpl classA = ElementFactory.classElement2("A");
+ classA.mixinApplication = true;
+ TestElementResynthesizer resynthesizer =
+ new TestElementResynthesizer(context, {location: classA});
+ ClassElementHandle classAHandle =
+ new ClassElementHandle(resynthesizer, location);
+ ClassElementImpl classB =
+ ElementFactory.classElement("B", new InterfaceTypeImpl(classAHandle));
+ classB.mixinApplication = true;
+
+ expect(classB.constructors, hasLength(1));
+ }
+
void test_getAllSupertypes_interface() {
ClassElement classA = ElementFactory.classElement2("A");
ClassElement classB = ElementFactory.classElement("B", classA.type);
@@ -3703,6 +3722,24 @@
library.visibleLibraries, unorderedEquals(<LibraryElement>[library]));
}
+ void test_invalidateLibraryCycles_withHandle() {
+ AnalysisContext context = createAnalysisContext();
+ context.sourceFactory = new SourceFactory([]);
+ LibraryElementImpl library = ElementFactory.library(context, "foo");
+ LibraryElementImpl importedLibrary = ElementFactory.library(context, "bar");
+ ElementLocation location = new ElementLocationImpl.con2('');
+ TestElementResynthesizer resynthesizer =
+ new TestElementResynthesizer(context, {location: importedLibrary});
+ LibraryElement importedLibraryHandle =
+ new LibraryElementHandle(resynthesizer, location);
+ ImportElementImpl import =
+ ElementFactory.importFor(importedLibraryHandle, null);
+ library.imports = <ImportElement>[import];
+ library.libraryCycle; // Force computation of the cycle.
+
+ library.invalidateLibraryCycles();
+ }
+
void test_isUpToDate() {
AnalysisContext context = createAnalysisContext();
context.sourceFactory = new SourceFactory([]);
@@ -3938,6 +3975,18 @@
}
}
+class TestElementResynthesizer extends ElementResynthesizer {
+ Map<ElementLocation, Element> locationMap;
+
+ TestElementResynthesizer(AnalysisContext context, this.locationMap)
+ : super(context);
+
+ @override
+ Element getElement(ElementLocation location) {
+ return locationMap[location];
+ }
+}
+
@reflectiveTest
class TypeParameterTypeImplTest extends EngineTestCase {
void test_creation() {
diff --git a/pkg/analyzer/test/src/dart/test_all.dart b/pkg/analyzer/test/src/dart/test_all.dart
index ec4f182..15a0849 100644
--- a/pkg/analyzer/test/src/dart/test_all.dart
+++ b/pkg/analyzer/test/src/dart/test_all.dart
@@ -7,12 +7,16 @@
import 'package:unittest/unittest.dart';
import '../../utils.dart';
+import 'ast/test_all.dart' as ast;
+import 'constant/test_all.dart' as constant;
import 'element/test_all.dart' as element;
/// Utility for manually running all tests.
main() {
initializeTestEnvironment();
group('dart tests', () {
+ ast.main();
+ constant.main();
element.main();
});
}
diff --git a/pkg/analyzer/test/src/summary/incremental_cache_test.dart b/pkg/analyzer/test/src/summary/incremental_cache_test.dart
new file mode 100644
index 0000000..bf7620a
--- /dev/null
+++ b/pkg/analyzer/test/src/summary/incremental_cache_test.dart
@@ -0,0 +1,187 @@
+// 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/src/generated/source.dart';
+import 'package:analyzer/src/summary/incremental_cache.dart';
+import 'package:unittest/unittest.dart';
+
+import '../../reflective_tests.dart';
+import '../abstract_single_unit.dart';
+
+main() {
+ groupSep = ' | ';
+ runReflectiveTests(IncrementalCacheTest);
+}
+
+/**
+ * TODO(scheglov) write more tests for invalidation.
+ */
+@reflectiveTest
+class IncrementalCacheTest extends AbstractSingleUnitTest {
+ _TestCacheStorage storage = new _TestCacheStorage();
+ IncrementalCache cache;
+
+ Source putLibrary(String path, String code) {
+ Source source = addSource(path, code);
+ LibraryElement libraryElement = context.computeLibraryElement(source);
+ cache.putLibrary(libraryElement);
+ return source;
+ }
+
+ void putTestLibrary(String code) {
+ resolveTestUnit(code);
+ cache.putLibrary(testLibraryElement);
+ }
+
+ @override
+ void setUp() {
+ super.setUp();
+ cache = new IncrementalCache(storage, context, <int>[]);
+ }
+
+ void test_getLibraryClosureBundles_emptyCache() {
+ resolveTestUnit('main() {}');
+ // the cache is empty, no bundles
+ List<LibraryBundleWithId> bundles =
+ cache.getLibraryClosureBundles(testSource);
+ expect(bundles, isNull);
+ }
+
+ void test_getLibraryClosureBundles_exportLib() {
+ Source aSource = putLibrary('/a.dart', '');
+ putTestLibrary(r'''
+import 'a.dart';
+main() {}
+''');
+ List<LibraryBundleWithId> bundles =
+ cache.getLibraryClosureBundles(testSource);
+ expect(bundles, isNotNull);
+ expect(_getBundleSources(bundles), [testSource, aSource].toSet());
+ // remove the 'a.dart' bundle, 'test.dart' loading fails
+ cache.clearInternalCaches();
+ storage.map.remove(_findBundleForSource(bundles, aSource).id);
+ expect(cache.getLibraryClosureBundles(testSource), isNull);
+ }
+
+ void test_getLibraryClosureBundles_importLib() {
+ Source aSource = putLibrary('/a.dart', '');
+ putTestLibrary(r'''
+import 'a.dart';
+main() {}
+''');
+ List<LibraryBundleWithId> bundles =
+ cache.getLibraryClosureBundles(testSource);
+ expect(bundles, isNotNull);
+ expect(_getBundleSources(bundles), [testSource, aSource].toSet());
+ // remove the 'a.dart' bundle, 'test.dart' loading fails
+ cache.clearInternalCaches();
+ storage.map.remove(_findBundleForSource(bundles, aSource).id);
+ expect(cache.getLibraryClosureBundles(testSource), isNull);
+ }
+
+ void test_getLibraryClosureBundles_importLib2() {
+ Source aSource = putLibrary('/a.dart', '');
+ Source bSource = putLibrary('/b.dart', "import 'a.dart';");
+ putTestLibrary(r'''
+import 'b.dart';
+main() {}
+''');
+ List<LibraryBundleWithId> bundles =
+ cache.getLibraryClosureBundles(testSource);
+ expect(bundles, isNotNull);
+ expect(_getBundleSources(bundles), [testSource, aSource, bSource].toSet());
+ // remove the 'a.dart' bundle, 'test.dart' loading fails
+ cache.clearInternalCaches();
+ storage.map.remove(_findBundleForSource(bundles, aSource).id);
+ expect(cache.getLibraryClosureBundles(testSource), isNull);
+ }
+
+ void test_getLibraryClosureBundles_importSdk() {
+ putTestLibrary(r'''
+import 'dart:async';
+main() {}
+''');
+ List<LibraryBundleWithId> bundles =
+ cache.getLibraryClosureBundles(testSource);
+ expect(bundles, isNotNull);
+ expect(_getBundleSources(bundles), [testSource].toSet());
+ }
+
+ void test_getLibraryClosureBundles_onlyLibrary() {
+ putTestLibrary(r'''
+main() {}
+''');
+ // the cache is empty, no bundles
+ List<LibraryBundleWithId> bundles =
+ cache.getLibraryClosureBundles(testSource);
+ expect(bundles, isNotNull);
+ }
+
+ void test_getSourceKind_library() {
+ putTestLibrary(r'''
+main() {}
+''');
+ expect(cache.getSourceKind(testSource), SourceKind.LIBRARY);
+ }
+
+ void test_getSourceKind_library_usedAsPart() {
+ verifyNoTestUnitErrors = false;
+ Source fooSource = addSource(
+ '/foo.dart',
+ r'''
+import 'dart:math';
+''');
+ putTestLibrary(r'''
+part 'foo.dart';
+main() {}
+''');
+ expect(cache.getSourceKind(testSource), SourceKind.LIBRARY);
+ // not a part, but also not enough information to write it as a library
+ expect(cache.getSourceKind(fooSource), isNull);
+ }
+
+ void test_getSourceKind_notCached() {
+ resolveTestUnit(r'''
+main() {}
+''');
+ expect(cache.getSourceKind(testSource), isNull);
+ }
+
+ void test_getSourceKind_part() {
+ Source partSource = addSource('/foo.dart', 'part of lib;');
+ putTestLibrary(r'''
+library lib;
+part 'foo.dart';
+''');
+ expect(cache.getSourceKind(testSource), SourceKind.LIBRARY);
+ expect(cache.getSourceKind(partSource), SourceKind.PART);
+ }
+
+ LibraryBundleWithId _findBundleForSource(
+ List<LibraryBundleWithId> bundles, Source source) {
+ return bundles.singleWhere((b) => b.source == source);
+ }
+
+ Set<Source> _getBundleSources(List<LibraryBundleWithId> bundles) {
+ return bundles.map((b) => b.source).toSet();
+ }
+}
+
+/**
+ * A [Map] based [CacheStorage].
+ */
+class _TestCacheStorage implements CacheStorage {
+ final Map<String, List<int>> map = <String, List<int>>{};
+
+ @override
+ List<int> get(String key) {
+ return map[key];
+ }
+
+ @override
+ void put(String key, List<int> bytes) {
+ map[key] = bytes;
+ }
+}
diff --git a/pkg/analyzer/test/src/summary/index_unit_test.dart b/pkg/analyzer/test/src/summary/index_unit_test.dart
index a8a3f4f..f9639e2 100644
--- a/pkg/analyzer/test/src/summary/index_unit_test.dart
+++ b/pkg/analyzer/test/src/summary/index_unit_test.dart
@@ -763,6 +763,43 @@
assertThat(enumElement.getGetter('B'))..isReferencedAt('B);', true);
}
+ void test_isReferencedBy_FieldElement_synthetic_hasGetter() {
+ verifyNoTestUnitErrors = false;
+ _indexTestUnit('''
+class A {
+ A() : f = 42;
+ int get f => 0;
+}
+''');
+ ClassElement element2 = findElement('A');
+ assertThat(element2.getField('f')).isWrittenAt('f = 42', true);
+ }
+
+ void test_isReferencedBy_FieldElement_synthetic_hasGetterSetter() {
+ verifyNoTestUnitErrors = false;
+ _indexTestUnit('''
+class A {
+ A() : f = 42;
+ int get f => 0;
+ set f(_) {}
+}
+''');
+ ClassElement element2 = findElement('A');
+ assertThat(element2.getField('f')).isWrittenAt('f = 42', true);
+ }
+
+ void test_isReferencedBy_FieldElement_synthetic_hasSetter() {
+ verifyNoTestUnitErrors = false;
+ _indexTestUnit('''
+class A {
+ A() : f = 42;
+ set f(_) {}
+}
+''');
+ ClassElement element2 = findElement('A');
+ assertThat(element2.getField('f')).isWrittenAt('f = 42', true);
+ }
+
void test_isReferencedBy_FunctionElement() {
_indexTestUnit('''
foo() {}
@@ -908,6 +945,22 @@
..isWrittenAt('field = 5', true);
}
+ void test_usedName_inLibraryIdentifier() {
+ verifyNoTestUnitErrors = false;
+ _indexTestUnit('''
+library aaa.bbb.ccc;
+class C {
+ var bbb;
+}
+main(p) {
+ p.bbb = 1;
+}
+''');
+ assertThatName('bbb')
+ ..isNotUsed('bbb.ccc', IndexRelationKind.IS_READ_BY)
+ ..isUsedQ('bbb = 1;', IndexRelationKind.IS_WRITTEN_BY);
+ }
+
void test_usedName_qualified_resolved() {
verifyNoTestUnitErrors = false;
_indexTestUnit('''
@@ -922,10 +975,10 @@
}
''');
assertThatName('x')
- ..isNotUsed('x;', IndexRelationKind.IS_READ_BY)
- ..isNotUsed('x = 1;', IndexRelationKind.IS_WRITTEN_BY)
- ..isNotUsed('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY)
- ..isNotUsed('x();', IndexRelationKind.IS_INVOKED_BY);
+ ..isNotUsedQ('x;', IndexRelationKind.IS_READ_BY)
+ ..isNotUsedQ('x = 1;', IndexRelationKind.IS_WRITTEN_BY)
+ ..isNotUsedQ('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY)
+ ..isNotUsedQ('x();', IndexRelationKind.IS_INVOKED_BY);
}
void test_usedName_qualified_unresolved() {
@@ -959,10 +1012,10 @@
}
''');
assertThatName('x')
- ..isNotUsed('x;', IndexRelationKind.IS_READ_BY)
- ..isNotUsed('x = 1;', IndexRelationKind.IS_WRITTEN_BY)
- ..isNotUsed('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY)
- ..isNotUsed('x();', IndexRelationKind.IS_INVOKED_BY);
+ ..isNotUsedQ('x;', IndexRelationKind.IS_READ_BY)
+ ..isNotUsedQ('x = 1;', IndexRelationKind.IS_WRITTEN_BY)
+ ..isNotUsedQ('x += 2;', IndexRelationKind.IS_READ_WRITTEN_BY)
+ ..isNotUsedQ('x();', IndexRelationKind.IS_INVOKED_BY);
}
void test_usedName_unqualified_unresolved() {
@@ -1201,6 +1254,11 @@
void isNotUsed(String search, IndexRelationKind kind) {
test._assertUsedName(
+ name, kind, test._expectedLocation(search, false), true);
+ }
+
+ void isNotUsedQ(String search, IndexRelationKind kind) {
+ test._assertUsedName(
name, kind, test._expectedLocation(search, true), true);
}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_test.dart b/pkg/analyzer/test/src/summary/resynthesize_test.dart
index d1f2b88..0d810b4 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_test.dart
@@ -7,6 +7,7 @@
import 'dart:convert';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
@@ -14,7 +15,6 @@
import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/constant.dart' show DartObject;
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart'
show Namespace, TypeProvider;
diff --git a/pkg/analyzer/test/src/summary/test_all.dart b/pkg/analyzer/test/src/summary/test_all.dart
index fe80a5a..08af93d 100644
--- a/pkg/analyzer/test/src/summary/test_all.dart
+++ b/pkg/analyzer/test/src/summary/test_all.dart
@@ -8,6 +8,7 @@
import '../../utils.dart';
import 'flat_buffers_test.dart' as flat_buffers_test;
+import 'incremental_cache_test.dart' as incremental_cache_test;
import 'index_unit_test.dart' as index_unit_test;
import 'name_filter_test.dart' as name_filter_test;
import 'prelinker_test.dart' as prelinker_test;
@@ -22,6 +23,7 @@
initializeTestEnvironment();
group('summary tests', () {
flat_buffers_test.main();
+ incremental_cache_test.main();
index_unit_test.main();
name_filter_test.main();
prelinker_test.main();
diff --git a/pkg/analyzer/test/src/task/driver_test.dart b/pkg/analyzer/test/src/task/driver_test.dart
index 221636a..bd21675 100644
--- a/pkg/analyzer/test/src/task/driver_test.dart
+++ b/pkg/analyzer/test/src/task/driver_test.dart
@@ -124,6 +124,32 @@
expect(analysisDriver.createNextWorkOrder(), isNull);
}
+ test_createWorkOrderForResult_aboutToComputeResult() {
+ AnalysisTarget target = new TestSource();
+ ResultDescriptor result = new ResultDescriptor('result', null);
+ TaskDescriptor descriptor = new TaskDescriptor(
+ 'task',
+ (context, target) => new TestAnalysisTask(context, target),
+ (target) => {},
+ [result]);
+ taskManager.addTaskDescriptor(descriptor);
+ context.getCacheEntry(target).setState(result, CacheState.INVALID);
+ // has result
+ {
+ when(context.aboutToComputeResult(anyObject, result)).thenReturn(true);
+ WorkOrder workOrder =
+ analysisDriver.createWorkOrderForResult(target, result);
+ expect(workOrder, isNull);
+ }
+ // no result
+ {
+ when(context.aboutToComputeResult(anyObject, result)).thenReturn(false);
+ WorkOrder workOrder =
+ analysisDriver.createWorkOrderForResult(target, result);
+ expect(workOrder, isNotNull);
+ }
+ }
+
test_createWorkOrderForResult_error() {
AnalysisTarget target = new TestSource();
ResultDescriptor result = new ResultDescriptor('result', null);
@@ -649,57 +675,6 @@
expect(item.target, target);
}
- test_gatherInputs_complete() {
- AnalysisTarget target = new TestSource();
- TaskDescriptor descriptor = new TaskDescriptor(
- 'task',
- (context, target) => new TestAnalysisTask(context, target),
- (target) => {},
- [new ResultDescriptor('output', null)]);
- WorkItem item = new WorkItem(context, target, descriptor, null, 0, null);
- WorkItem result = item.gatherInputs(taskManager, []);
- expect(result, isNull);
- expect(item.exception, isNull);
- }
-
- test_gatherInputs_incomplete() {
- AnalysisTarget target = new TestSource();
- ResultDescriptor resultA = new ResultDescriptor('resultA', null);
- ResultDescriptor resultB = new ResultDescriptor('resultB', null);
- // prepare tasks
- TaskDescriptor task1 = new TaskDescriptor(
- 'task',
- (context, target) =>
- new TestAnalysisTask(context, target, results: [resultA]),
- (target) => {},
- [resultA]);
- TaskDescriptor task2 = new TaskDescriptor(
- 'task',
- (context, target) => new TestAnalysisTask(context, target),
- (target) => {'one': resultA.of(target)},
- [resultB]);
- taskManager.addTaskDescriptor(task1);
- taskManager.addTaskDescriptor(task2);
- // gather inputs
- WorkItem item = new WorkItem(context, target, task2, null, 0, null);
- WorkItem inputItem = item.gatherInputs(taskManager, []);
- expect(inputItem, isNotNull);
- }
-
- test_gatherInputs_invalid() {
- AnalysisTarget target = new TestSource();
- ResultDescriptor inputResult = new ResultDescriptor('input', null);
- TaskDescriptor descriptor = new TaskDescriptor(
- 'task',
- (context, target) => new TestAnalysisTask(context, target),
- (target) => {'one': inputResult.of(target)},
- [new ResultDescriptor('output', null)]);
- WorkItem item = new WorkItem(context, target, descriptor, null, 0, null);
- WorkItem result = item.gatherInputs(taskManager, []);
- expect(result, isNull);
- expect(item.exception, isNotNull);
- }
-
test_gatherInputs_aboutToComputeResult_hasResult() {
AnalysisTarget target = new TestSource();
ResultDescriptor resultA = new ResultDescriptor('resultA', null);
@@ -754,6 +729,57 @@
expect(inputItem.target, target);
expect(inputItem.descriptor, task1);
}
+
+ test_gatherInputs_complete() {
+ AnalysisTarget target = new TestSource();
+ TaskDescriptor descriptor = new TaskDescriptor(
+ 'task',
+ (context, target) => new TestAnalysisTask(context, target),
+ (target) => {},
+ [new ResultDescriptor('output', null)]);
+ WorkItem item = new WorkItem(context, target, descriptor, null, 0, null);
+ WorkItem result = item.gatherInputs(taskManager, []);
+ expect(result, isNull);
+ expect(item.exception, isNull);
+ }
+
+ test_gatherInputs_incomplete() {
+ AnalysisTarget target = new TestSource();
+ ResultDescriptor resultA = new ResultDescriptor('resultA', null);
+ ResultDescriptor resultB = new ResultDescriptor('resultB', null);
+ // prepare tasks
+ TaskDescriptor task1 = new TaskDescriptor(
+ 'task',
+ (context, target) =>
+ new TestAnalysisTask(context, target, results: [resultA]),
+ (target) => {},
+ [resultA]);
+ TaskDescriptor task2 = new TaskDescriptor(
+ 'task',
+ (context, target) => new TestAnalysisTask(context, target),
+ (target) => {'one': resultA.of(target)},
+ [resultB]);
+ taskManager.addTaskDescriptor(task1);
+ taskManager.addTaskDescriptor(task2);
+ // gather inputs
+ WorkItem item = new WorkItem(context, target, task2, null, 0, null);
+ WorkItem inputItem = item.gatherInputs(taskManager, []);
+ expect(inputItem, isNotNull);
+ }
+
+ test_gatherInputs_invalid() {
+ AnalysisTarget target = new TestSource();
+ ResultDescriptor inputResult = new ResultDescriptor('input', null);
+ TaskDescriptor descriptor = new TaskDescriptor(
+ 'task',
+ (context, target) => new TestAnalysisTask(context, target),
+ (target) => {'one': inputResult.of(target)},
+ [new ResultDescriptor('output', null)]);
+ WorkItem item = new WorkItem(context, target, descriptor, null, 0, null);
+ WorkItem result = item.gatherInputs(taskManager, []);
+ expect(result, isNull);
+ expect(item.exception, isNotNull);
+ }
}
@reflectiveTest
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 09738bd..8c4eb3c 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -87,6 +87,73 @@
''');
});
+ test('for-in casts supertype sequence to iterable', () {
+ checkFile('''
+ main() {
+ dynamic d;
+ for (var i in /*info:DYNAMIC_CAST*/d) {}
+
+ Object o;
+ for (var i in /*info:DOWN_CAST_IMPLICIT*/o) {}
+ }
+ ''');
+ });
+
+ test('await for-in casts supertype sequence to stream', () {
+ checkFile('''
+ main() async {
+ dynamic d;
+ await for (var i in /*info:DYNAMIC_CAST*/d) {}
+
+ Object o;
+ await for (var i in /*info:DOWN_CAST_IMPLICIT*/o) {}
+ }
+ ''');
+ });
+
+ test('for-in casts iterable element to variable', () {
+ checkFile('''
+ main() {
+ // Don't choke if sequence is not iterable.
+ for (var i in /*warning:FOR_IN_OF_INVALID_TYPE*/1234) {}
+
+ // Dynamic cast.
+ for (String /*info:DYNAMIC_CAST*/s in <dynamic>[]) {}
+
+ // Identity cast.
+ for (String s in <String>[]) {}
+
+ // Untyped.
+ for (var s in <String>[]) {}
+
+ // Downcast.
+ for (int /*info:DOWN_CAST_IMPLICIT*/i in <num>[]) {}
+ }
+ ''');
+ });
+
+ test('await for-in casts stream element to variable', () {
+ checkFile('''
+ import 'dart:async';
+ main() async {
+ // Don't choke if sequence is not stream.
+ await for (var i in /*warning:FOR_IN_OF_INVALID_TYPE*/1234) {}
+
+ // Dynamic cast.
+ await for (String /*info:DYNAMIC_CAST*/s in new Stream<dynamic>()) {}
+
+ // Identity cast.
+ await for (String s in new Stream<String>()) {}
+
+ // Untyped.
+ await for (var s in new Stream<String>()) {}
+
+ // Downcast.
+ await for (int /*info:DOWN_CAST_IMPLICIT*/i in new Stream<num>()) {}
+ }
+ ''');
+ });
+
test('dynamic invocation', () {
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 3290d9b..58944b6 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -484,12 +484,12 @@
}
Iterable iter = list;
- for (Foo x in /*warning:DOWN_CAST_COMPOSITE*/iter) {
+ for (Foo /*info:DYNAMIC_CAST*/x in iter) {
var y = x;
}
dynamic iter2 = list;
- for (Foo x in /*warning:DOWN_CAST_COMPOSITE*/iter2) {
+ for (Foo /*info:DYNAMIC_CAST*/x in /*info:DYNAMIC_CAST*/iter2) {
var y = x;
}
diff --git a/pkg/analyzer/test/test_all.dart b/pkg/analyzer/test/test_all.dart
index 8155789..7e45412 100644
--- a/pkg/analyzer/test/test_all.dart
+++ b/pkg/analyzer/test/test_all.dart
@@ -7,6 +7,7 @@
import 'package:unittest/unittest.dart';
import 'cancelable_future_test.dart' as cancelable_future_test;
+import 'context/test_all.dart' as context;
import 'enum_test.dart' as enum_test;
import 'file_system/test_all.dart' as file_system;
import 'generated/test_all.dart' as generated;
@@ -21,6 +22,7 @@
initializeTestEnvironment();
group('analysis engine', () {
cancelable_future_test.main();
+ context.main();
enum_test.main();
file_system.main();
generated.main();
diff --git a/pkg/analyzer_cli/.analysis_options b/pkg/analyzer_cli/.analysis_options
new file mode 100644
index 0000000..78831a9
--- /dev/null
+++ b/pkg/analyzer_cli/.analysis_options
@@ -0,0 +1,3 @@
+analyzer:
+ exclude:
+ - 'test/data'
diff --git a/pkg/analyzer_cli/lib/src/analyzer_impl.dart b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
index 56eaa2f..95bed11 100644
--- a/pkg/analyzer_cli/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
@@ -40,6 +40,9 @@
final AnalysisContext context;
+ /// Accumulated analysis statistics.
+ final AnalysisStats stats;
+
final Source librarySource;
/// All [Source]s references by the analyzed library.
@@ -59,7 +62,8 @@
/// specified the "--package-warnings" option.
String _selfPackageName;
- AnalyzerImpl(this.context, this.librarySource, this.options, this.startTime);
+ AnalyzerImpl(this.context, this.librarySource, this.options, this.stats,
+ this.startTime);
/// Returns the maximal [ErrorSeverity] of the recorded errors.
ErrorSeverity get maxErrorSeverity {
@@ -76,8 +80,8 @@
return status;
}
- void addCompilationUnitSource(CompilationUnitElement unit,
- Set<LibraryElement> libraries, Set<CompilationUnitElement> units) {
+ void addCompilationUnitSource(
+ CompilationUnitElement unit, Set<CompilationUnitElement> units) {
if (unit == null || units.contains(unit)) {
return;
}
@@ -91,21 +95,13 @@
return;
}
// Maybe skip library.
- {
- UriKind uriKind = library.source.uriKind;
- // Optionally skip package: libraries.
- if (!options.showPackageWarnings && _isOtherPackage(library.source.uri)) {
- return;
- }
- // Optionally skip SDK libraries.
- if (!options.showSdkWarnings && uriKind == UriKind.DART_URI) {
- return;
- }
+ if (!_isAnalyzedLibrary(library)) {
+ return;
}
// Add compilation units.
- addCompilationUnitSource(library.definingCompilationUnit, libraries, units);
+ addCompilationUnitSource(library.definingCompilationUnit, units);
for (CompilationUnitElement child in library.parts) {
- addCompilationUnitSource(child, libraries, units);
+ addCompilationUnitSource(child, units);
}
// Add referenced libraries.
for (LibraryElement child in library.importedLibraries) {
@@ -181,18 +177,34 @@
return status;
}
- /// Determine whether the given URI refers to a package other than the package
- /// being analyzed.
- bool _isOtherPackage(Uri uri) {
- if (uri.scheme != 'package') {
+ /// Returns true if we want to report diagnostics for this library.
+ bool _isAnalyzedLibrary(LibraryElement library) {
+ switch (library.source.uriKind) {
+ case UriKind.DART_URI:
+ return options.showSdkWarnings;
+ case UriKind.PACKAGE_URI:
+ return _isAnalyzedPackage(library.source.uri);
+ default:
+ return true;
+ }
+ }
+
+ /// Determine whether the given URI refers to a package being analyzed.
+ bool _isAnalyzedPackage(Uri uri) {
+ if (uri.scheme != 'package' || uri.pathSegments.isEmpty) {
return false;
}
- if (_selfPackageName != null &&
- uri.pathSegments.length > 0 &&
- uri.pathSegments[0] == _selfPackageName) {
+
+ String packageName = uri.pathSegments.first;
+ if (packageName == _selfPackageName) {
+ return true;
+ } else if (!options.showPackageWarnings) {
return false;
+ } else if (options.showPackageWarningsPrefix == null) {
+ return true;
+ } else {
+ return packageName.startsWith(options.showPackageWarningsPrefix);
}
- return true;
}
_printColdPerf() {
@@ -220,7 +232,8 @@
StringSink sink = options.machineFormat ? errorSink : outSink;
// Print errors.
- ErrorFormatter formatter = new ErrorFormatter(sink, options, _processError);
+ ErrorFormatter formatter =
+ new ErrorFormatter(sink, options, stats, _processError);
formatter.formatErrors(errorInfos);
}
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index dc40c0d..eb1df03 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -33,6 +33,7 @@
import 'package:analyzer/src/services/lint.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:analyzer_cli/src/analyzer_impl.dart';
+import 'package:analyzer_cli/src/error_formatter.dart';
import 'package:analyzer_cli/src/options.dart';
import 'package:analyzer_cli/src/package_analyzer.dart';
import 'package:analyzer_cli/src/perf_report.dart';
@@ -79,6 +80,9 @@
/// `null` if [_analyzeAll] hasn't been called yet.
AnalysisContext _context;
+ /// The total number of source files loaded by an AnalysisContext.
+ int _analyzedFileCount = 0;
+
/// If [_context] is not `null`, the [CommandLineOptions] that guided its
/// creation.
CommandLineOptions _previousOptions;
@@ -89,6 +93,9 @@
@override
ResolverProvider packageResolverProvider;
+ /// Collected analysis statistics.
+ final AnalysisStats stats = new AnalysisStats();
+
/// This Driver's current analysis context.
///
/// *Visible for testing.*
@@ -96,11 +103,14 @@
@override
void set userDefinedPlugins(List<Plugin> plugins) {
- _userDefinedPlugins = plugins == null ? <Plugin>[] : plugins;
+ _userDefinedPlugins = plugins ?? <Plugin>[];
}
@override
void start(List<String> args) {
+ if (_context != null) {
+ throw new StateError("start() can only be called once");
+ }
int startTime = new DateTime.now().millisecondsSinceEpoch;
StringUtilities.INTERNER = new MappedInterner();
@@ -133,8 +143,13 @@
}
}
+ if (_context != null) {
+ _analyzedFileCount += _context.sources.length;
+ }
+
if (options.perfReport != null) {
- String json = makePerfReport(startTime, currentTimeMillis(), options);
+ String json = makePerfReport(
+ startTime, currentTimeMillis(), options, _analyzedFileCount, stats);
new File(options.perfReport).writeAsStringSync(json);
}
}
@@ -162,32 +177,32 @@
// Add all the files to be analyzed en masse to the context. Skip any
// files that were added earlier (whether explicitly or implicitly) to
// avoid causing those files to be unnecessarily re-read.
- Set<Source> knownSources = _context.sources.toSet();
+ Set<Source> knownSources = context.sources.toSet();
List<Source> sourcesToAnalyze = <Source>[];
ChangeSet changeSet = new ChangeSet();
for (String sourcePath in options.sourceFiles) {
sourcePath = sourcePath.trim();
- // Check that file exists.
- if (!new File(sourcePath).existsSync()) {
- errorSink.writeln('File not found: $sourcePath');
+
+ // Collect files for analysis.
+ // Note that these files will all be analyzed in the same context.
+ // This should be updated when the ContextManager re-work is complete
+ // (See: https://github.com/dart-lang/sdk/issues/24133)
+ Iterable<File> files = _collectFiles(sourcePath);
+ if (files.isEmpty) {
+ errorSink.writeln('No dart files found at: $sourcePath');
exitCode = ErrorSeverity.ERROR.ordinal;
- //Fail fast; don't analyze more files
return ErrorSeverity.ERROR;
}
- // Check that file is Dart file.
- if (!AnalysisEngine.isDartFileName(sourcePath)) {
- errorSink.writeln('$sourcePath is not a Dart file');
- exitCode = ErrorSeverity.ERROR.ordinal;
- // Fail fast; don't analyze more files.
- return ErrorSeverity.ERROR;
+
+ for (File file in files) {
+ Source source = _computeLibrarySource(file.absolute.path);
+ if (!knownSources.contains(source)) {
+ changeSet.addedSource(source);
+ }
+ sourcesToAnalyze.add(source);
}
- Source source = _computeLibrarySource(sourcePath);
- if (!knownSources.contains(source)) {
- changeSet.addedSource(source);
- }
- sourcesToAnalyze.add(source);
}
- _context.applyChanges(changeSet);
+ context.applyChanges(changeSet);
// Analyze the libraries.
ErrorSeverity allResult = ErrorSeverity.NONE;
@@ -219,13 +234,17 @@
}
}
+ if (!options.machineFormat) {
+ stats.print(outSink);
+ }
+
return allResult;
}
/// Perform package analysis according to the given [options].
ErrorSeverity _analyzePackage(CommandLineOptions options) {
return _analyzeAllTag.makeCurrentWhile(() {
- return new PackageAnalyzer(options).analyze();
+ return new PackageAnalyzer(options, stats).analyze();
});
}
@@ -259,6 +278,10 @@
if (options.showPackageWarnings != _previousOptions.showPackageWarnings) {
return false;
}
+ if (options.showPackageWarningsPrefix !=
+ _previousOptions.showPackageWarningsPrefix) {
+ return false;
+ }
if (options.showSdkWarnings != _previousOptions.showSdkWarnings) {
return false;
}
@@ -292,38 +315,14 @@
return (Source source) => true;
}
- // Determine the set of packages requiring a full parse. Use null to
- // represent the case where all packages require a full parse.
- Set<String> packagesRequiringFullParse;
- if (options.showPackageWarnings) {
- // We are showing warnings from all packages so all packages require a
- // full parse.
- packagesRequiringFullParse = null;
- } else {
- // We aren't showing warnings for dependent packages, but we may still
- // need to show warnings for "self" packages, so we need to do a full
- // parse in any package containing files mentioned on the command line.
- // TODO(paulberry): implement this. As a temporary workaround, we're
- // fully parsing all packages.
- packagesRequiringFullParse = null;
- }
return (Source source) {
if (options.sourceFiles.contains(source.fullName)) {
return true;
} else if (source.uri.scheme == 'dart') {
return options.showSdkWarnings;
- } else if (source.uri.scheme == 'package') {
- if (packagesRequiringFullParse == null) {
- return true;
- } else if (source.uri.pathSegments.length == 0) {
- // We should never see a URI like this, but fully parse it to be
- // safe.
- return true;
- } else {
- return packagesRequiringFullParse
- .contains(source.uri.pathSegments[0]);
- }
} else {
+ // TODO(paulberry): diet parse 'package:' imports when we don't want
+ // diagnostics. (Full parse is still needed for "self" packages.)
return true;
}
};
@@ -451,6 +450,29 @@
return new SourceFactory(resolvers, packages);
}
+ /// Collect all analyzable files at [filePath], recursively if it's a
+ /// directory, ignoring links.
+ Iterable<File> _collectFiles(String filePath) {
+ List<File> files = <File>[];
+ File file = new File(filePath);
+ if (file.existsSync()) {
+ files.add(file);
+ } else {
+ Directory directory = new Directory(filePath);
+ if (directory.existsSync()) {
+ for (FileSystemEntity entry
+ in directory.listSync(recursive: true, followLinks: false)) {
+ String relative = path.relative(entry.path, from: directory.path);
+ if (AnalysisEngine.isDartFileName(entry.path) &&
+ !_isInHiddenDir(relative)) {
+ files.add(entry);
+ }
+ }
+ }
+ }
+ return files;
+ }
+
/// Convert the given [sourcePath] (which may be relative to the current
/// working directory) to a [Source] object that can be fed to the analysis
/// context.
@@ -477,18 +499,22 @@
}
_previousOptions = options;
+ // Save stats from previous context before clobbering it.
+ if (_context != null) {
+ _analyzedFileCount += _context.sources.length;
+ }
+
// Create a context.
- AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
- _context = context;
+ _context = AnalysisEngine.instance.createAnalysisContext();
// Choose a package resolution policy and a diet parsing policy based on
// the command-line options.
SourceFactory sourceFactory = _chooseUriResolutionPolicy(
- options, (context as InternalAnalysisContext).embedderYamlLocator);
+ options, (_context as InternalAnalysisContext).embedderYamlLocator);
AnalyzeFunctionBodiesPredicate dietParsingPolicy =
_chooseDietParsingPolicy(options);
- context.sourceFactory = sourceFactory;
+ _context.sourceFactory = sourceFactory;
setAnalysisContextOptions(_context, options,
(AnalysisOptionsImpl contextOptions) {
@@ -525,6 +551,10 @@
return folderMap;
}
+ /// Returns `true` if this relative path is a hidden directory.
+ bool _isInHiddenDir(String relative) =>
+ path.split(relative).any((part) => part.startsWith("."));
+
void _processPlugins() {
List<Plugin> plugins = <Plugin>[];
plugins.addAll(AnalysisEngine.instance.requiredPlugins);
@@ -541,7 +571,7 @@
ErrorSeverity _runAnalyzer(Source source, CommandLineOptions options) {
int startTime = currentTimeMillis();
AnalyzerImpl analyzer =
- new AnalyzerImpl(_context, source, options, startTime);
+ new AnalyzerImpl(_context, source, options, stats, startTime);
var errorSeverity = analyzer.analyzeSync();
if (errorSeverity == ErrorSeverity.ERROR) {
exitCode = errorSeverity.ordinal;
@@ -685,7 +715,7 @@
'>>> BATCH END (${totalTests - testsFailed}/$totalTests) ${time}ms');
exitCode = batchResult.ordinal;
}
- // Prepare aruments.
+ // Prepare arguments.
var args;
{
var lineArgs = line.split(new RegExp('\\s+'));
diff --git a/pkg/analyzer_cli/lib/src/error_formatter.dart b/pkg/analyzer_cli/lib/src/error_formatter.dart
index 0154d73..c43fcd8 100644
--- a/pkg/analyzer_cli/lib/src/error_formatter.dart
+++ b/pkg/analyzer_cli/lib/src/error_formatter.dart
@@ -13,19 +13,105 @@
ProcessedSeverity _identity(AnalysisError error) =>
new ProcessedSeverity(error.errorCode.errorSeverity);
+String _pluralize(String word, int count) => count == 1 ? word : word + "s";
+
/// Returns desired severity for the given [error] (or `null` if it's to be
/// suppressed).
typedef ProcessedSeverity _SeverityProcessor(AnalysisError error);
+/// Analysis statistics counter.
+class AnalysisStats {
+ /// The total number of diagnostics sent to [formatErrors].
+ int unfilteredCount;
+
+ int errorCount;
+ int hintCount;
+ int lintCount;
+ int warnCount;
+
+ AnalysisStats() {
+ init();
+ }
+
+ /// The total number of diagnostics reported to the user.
+ int get filteredCount => errorCount + warnCount + hintCount + lintCount;
+
+ /// (Re)set initial values.
+ void init() {
+ unfilteredCount = 0;
+ errorCount = 0;
+ hintCount = 0;
+ lintCount = 0;
+ warnCount = 0;
+ }
+
+ /// Print statistics to [out].
+ void print(StringSink out) {
+ var hasErrors = errorCount != 0;
+ var hasWarns = warnCount != 0;
+ var hasHints = hintCount != 0;
+ var hasLints = lintCount != 0;
+ bool hasContent = false;
+ if (hasErrors) {
+ out.write(errorCount);
+ out.write(' ');
+ out.write(_pluralize("error", errorCount));
+ hasContent = true;
+ }
+ if (hasWarns) {
+ if (hasContent) {
+ if (!hasHints && !hasLints) {
+ out.write(' and ');
+ } else {
+ out.write(", ");
+ }
+ }
+ out.write(warnCount);
+ out.write(' ');
+ out.write(_pluralize("warning", warnCount));
+ hasContent = true;
+ }
+ if (hasHints) {
+ if (hasContent) {
+ if (!hasLints) {
+ out.write(' and ');
+ } else {
+ out.write(", ");
+ }
+ }
+ out.write(hintCount);
+ out.write(' ');
+ out.write(_pluralize("hint", hintCount));
+ hasContent = true;
+ }
+ if (hasLints) {
+ if (hasContent) {
+ out.write(" and ");
+ }
+ out.write(lintCount);
+ out.write(' ');
+ out.write(_pluralize("lint", lintCount));
+ hasContent = true;
+ }
+ if (hasContent) {
+ out.writeln(" found.");
+ } else {
+ out.writeln("No issues found");
+ }
+ }
+}
+
/// Helper for formatting [AnalysisError]s.
/// The two format options are a user consumable format and a machine consumable
/// format.
class ErrorFormatter {
final StringSink out;
final CommandLineOptions options;
+ final AnalysisStats stats;
final _SeverityProcessor processSeverity;
- ErrorFormatter(this.out, this.options, [this.processSeverity = _identity]);
+ ErrorFormatter(this.out, this.options, this.stats,
+ [this.processSeverity = _identity]);
/// Compute the severity for this [error] or `null` if this error should be
/// filtered.
@@ -83,6 +169,8 @@
}
void formatErrors(List<AnalysisErrorInfo> errorInfos) {
+ stats.unfilteredCount += errorInfos.length;
+
var errors = new List<AnalysisError>();
var errorToLine = new Map<AnalysisError, LineInfo>();
for (AnalysisErrorInfo errorInfo in errorInfos) {
@@ -112,84 +200,26 @@
return error1.offset - error2.offset;
});
// Format errors.
- int errorCount = 0;
- int warnCount = 0;
- int hintCount = 0;
- int lintCount = 0;
for (AnalysisError error in errors) {
ProcessedSeverity processedSeverity = processSeverity(error);
ErrorSeverity severity = processedSeverity.severity;
if (severity == ErrorSeverity.ERROR) {
- errorCount++;
+ stats.errorCount++;
} else if (severity == ErrorSeverity.WARNING) {
/// Only treat a warning as an error if it's not been set by a
/// proccesser.
if (!processedSeverity.overridden && options.warningsAreFatal) {
- errorCount++;
+ stats.errorCount++;
} else {
- warnCount++;
+ stats.warnCount++;
}
} else if (error.errorCode.type == ErrorType.HINT) {
- hintCount++;
+ stats.hintCount++;
} else if (error.errorCode.type == ErrorType.LINT) {
- lintCount++;
+ stats.lintCount++;
}
formatError(errorToLine, error);
}
- // Print statistics.
- if (!options.machineFormat) {
- var hasErrors = errorCount != 0;
- var hasWarns = warnCount != 0;
- var hasHints = hintCount != 0;
- var hasLints = lintCount != 0;
- bool hasContent = false;
- if (hasErrors) {
- out.write(errorCount);
- out.write(' ');
- out.write(pluralize("error", errorCount));
- hasContent = true;
- }
- if (hasWarns) {
- if (hasContent) {
- if (!hasHints && !hasLints) {
- out.write(' and ');
- } else {
- out.write(", ");
- }
- }
- out.write(warnCount);
- out.write(' ');
- out.write(pluralize("warning", warnCount));
- hasContent = true;
- }
- if (hasHints) {
- if (hasContent) {
- if (!hasLints) {
- out.write(' and ');
- } else {
- out.write(", ");
- }
- }
- out.write(hintCount);
- out.write(' ');
- out.write(pluralize("hint", hintCount));
- hasContent = true;
- }
- if (hasLints) {
- if (hasContent) {
- out.write(" and ");
- }
- out.write(lintCount);
- out.write(' ');
- out.write(pluralize("lint", lintCount));
- hasContent = true;
- }
- if (hasContent) {
- out.writeln(" found.");
- } else {
- out.writeln("No issues found");
- }
- }
}
static String escapePipe(String input) {
@@ -202,17 +232,9 @@
}
return result.toString();
}
-
- static String pluralize(String word, int count) {
- if (count == 1) {
- return word;
- } else {
- return word + "s";
- }
- }
}
-/// A severity with awareness of whether it was overriden by a processor.
+/// A severity with awareness of whether it was overridden by a processor.
class ProcessedSeverity {
ErrorSeverity severity;
bool overridden;
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index ec62ce3..3f100af 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -111,6 +111,9 @@
/// Whether to show package: warnings
final bool showPackageWarnings;
+ /// If not null, show package: warnings only for matching packages.
+ final String showPackageWarningsPrefix;
+
/// Whether to show SDK warnings
final bool showSdkWarnings;
@@ -151,8 +154,10 @@
packageRootPath = args['package-root'],
perfReport = args['x-perf-report'],
shouldBatch = args['batch'],
- showPackageWarnings =
- args['show-package-warnings'] || args['package-warnings'],
+ showPackageWarnings = args['show-package-warnings'] ||
+ args['package-warnings'] ||
+ args['x-package-warnings-prefix'] != null,
+ showPackageWarningsPrefix = args['x-package-warnings-prefix'],
showSdkWarnings = args['show-sdk-warnings'] || args['warnings'],
sourceFiles = args.rest,
warningsAreFatal = args['fatal-warnings'],
@@ -281,6 +286,10 @@
help: 'Show warnings from SDK imports (deprecated).',
defaultsTo: false,
negatable: false)
+ ..addOption('x-package-warnings-prefix',
+ help:
+ 'Show warnings from package: imports that match the given prefix',
+ hide: true)
..addOption('x-perf-report',
help: 'Writes a performance report to the given file (experimental).')
..addFlag('help',
diff --git a/pkg/analyzer_cli/lib/src/package_analyzer.dart b/pkg/analyzer_cli/lib/src/package_analyzer.dart
index 418db25..fd173a3 100644
--- a/pkg/analyzer_cli/lib/src/package_analyzer.dart
+++ b/pkg/analyzer_cli/lib/src/package_analyzer.dart
@@ -31,6 +31,7 @@
*/
class PackageAnalyzer {
final CommandLineOptions options;
+ final AnalysisStats stats;
String packagePath;
String packageLibPath;
@@ -39,7 +40,7 @@
InternalAnalysisContext context;
final List<Source> explicitSources = <Source>[];
- PackageAnalyzer(this.options);
+ PackageAnalyzer(this.options, this.stats);
/**
* Perform package analysis according to the given [options].
@@ -181,11 +182,13 @@
ErrorFormatter formatter = new ErrorFormatter(
sink,
options,
+ stats,
(AnalysisError error) =>
AnalyzerImpl.processError(error, options, context));
for (Source source in explicitSources) {
AnalysisErrorInfo errorInfo = context.getErrors(source);
formatter.formatErrors([errorInfo]);
}
+ stats.print(sink);
}
}
diff --git a/pkg/analyzer_cli/lib/src/perf_report.dart b/pkg/analyzer_cli/lib/src/perf_report.dart
index 208e560..f92ae9a 100644
--- a/pkg/analyzer_cli/lib/src/perf_report.dart
+++ b/pkg/analyzer_cli/lib/src/perf_report.dart
@@ -10,6 +10,7 @@
import 'package:analyzer/src/generated/utilities_general.dart'
show PerformanceTag;
import 'package:analyzer/task/model.dart' show AnalysisTask;
+import 'package:analyzer_cli/src/error_formatter.dart';
import 'package:analyzer_cli/src/options.dart' show CommandLineOptions;
const _JSON = const JsonEncoder.withIndent(" ");
@@ -39,7 +40,8 @@
}
}();
-String makePerfReport(int startTime, int endTime, CommandLineOptions options) {
+String makePerfReport(int startTime, int endTime, CommandLineOptions options,
+ int analyzedFileCount, AnalysisStats stats) {
int totalTime = endTime - startTime;
int otherTime = totalTime;
@@ -53,6 +55,7 @@
'dartSdkPath': options.dartSdkPath,
'strongMode': options.strongMode,
'showPackageWarnings': options.showPackageWarnings,
+ 'showPackageWarningsPrefix': options.showPackageWarningsPrefix,
'showSdkWarnings': options.showSdkWarnings,
'definedVariables': options.definedVariables,
'packageRootPath': options.packageRootPath,
@@ -89,6 +92,9 @@
'options': optionsJson,
'totalElapsedTime': totalTime,
'totalTaskTime': totalTaskTime,
+ 'analyzedFiles': analyzedFileCount,
+ 'generatedDiagnostics': stats.unfilteredCount,
+ 'reportedDiagnostics': stats.filteredCount,
'performanceTags': perfTagsJson,
'tasks': taskRows.map((r) => r.toJson()).toList(),
};
diff --git a/pkg/analyzer_cli/test/all.dart b/pkg/analyzer_cli/test/all.dart
index 9f08563..1fd1dd7 100644
--- a/pkg/analyzer_cli/test/all.dart
+++ b/pkg/analyzer_cli/test/all.dart
@@ -6,6 +6,7 @@
import 'driver_test.dart' as driver;
import 'error_test.dart' as error;
import 'options_test.dart' as options;
+import 'package_prefix_test.dart' as package_prefix;
import 'perf_report_test.dart' as perf;
import 'plugin_manager_test.dart' as plugin_manager;
import 'reporter_test.dart' as reporter;
@@ -26,4 +27,5 @@
plugin_manager.main();
reporter.main();
super_mixin.main();
+ package_prefix.main();
}
diff --git a/pkg/analyzer_cli/test/data/package_prefix/main.dart b/pkg/analyzer_cli/test/data/package_prefix/main.dart
new file mode 100644
index 0000000..4f1f313
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/package_prefix/main.dart
@@ -0,0 +1,14 @@
+// Test data for package_prefix_test.dart
+//
+// To test manually:
+//
+// This should show a hint about an unused import in foo:
+// dart ../../../bin/analyzer.dart --packages=packagelist \
+// --x-package-warnings-prefix=f main.dart
+
+import "package:foo/foo.dart";
+import "package:bar/bar.dart";
+
+main() {
+ print("$foo$bar");
+}
diff --git a/pkg/analyzer_cli/test/data/package_prefix/packagelist b/pkg/analyzer_cli/test/data/package_prefix/packagelist
new file mode 100644
index 0000000..85a25f7
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/package_prefix/packagelist
@@ -0,0 +1,2 @@
+bar:pkg/bar/
+foo:pkg/foo/
diff --git a/pkg/analyzer_cli/test/data/package_prefix/pkg/bar/bar.dart b/pkg/analyzer_cli/test/data/package_prefix/pkg/bar/bar.dart
new file mode 100644
index 0000000..0890e0a
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/package_prefix/pkg/bar/bar.dart
@@ -0,0 +1,3 @@
+import "dart:async"; // should trigger unused import
+
+var bar = "bar";
diff --git a/pkg/analyzer_cli/test/data/package_prefix/pkg/foo/foo.dart b/pkg/analyzer_cli/test/data/package_prefix/pkg/foo/foo.dart
new file mode 100644
index 0000000..ee511f5
--- /dev/null
+++ b/pkg/analyzer_cli/test/data/package_prefix/pkg/foo/foo.dart
@@ -0,0 +1,3 @@
+import "dart:async"; // should trigger unused import
+
+var foo = "foo";
diff --git a/pkg/analyzer_cli/test/package_prefix_test.dart b/pkg/analyzer_cli/test/package_prefix_test.dart
new file mode 100644
index 0000000..1ba203f
--- /dev/null
+++ b/pkg/analyzer_cli/test/package_prefix_test.dart
@@ -0,0 +1,73 @@
+import 'dart:io' show exitCode;
+
+import 'package:analyzer_cli/src/driver.dart' show Driver, outSink, errorSink;
+import 'package:analyzer_cli/src/options.dart' show ExitHandler, exitHandler;
+import 'package:unittest/unittest.dart';
+
+import 'utils.dart' show testDirectory;
+
+main() {
+ group('--x-package-warnings-prefix', () {
+ _Runner runner;
+
+ setUp(() {
+ runner = new _Runner.setUp();
+ });
+
+ tearDown(() {
+ runner.tearDown();
+ runner = null;
+ });
+
+ test('shows only the hint whose package matches the prefix', () {
+ runner.run([
+ "--packages",
+ "$testDirectory/data/package_prefix/packagelist",
+ "--x-package-warnings-prefix=f",
+ "$testDirectory/data/package_prefix/main.dart"
+ ]);
+ print("ran it");
+ expect(runner.stdout, contains('1 hint found'));
+ expect(runner.stdout, contains('Unused import'));
+ expect(runner.stdout, contains('package_prefix/pkg/foo/foo.dart'));
+ expect(runner.stdout, isNot(contains('bar.dart')));
+ });
+ });
+}
+
+class _Runner {
+ final _stdout = new StringBuffer();
+ final _stderr = new StringBuffer();
+
+ final StringSink _savedOutSink;
+ final StringSink _savedErrorSink;
+ final int _savedExitCode;
+ final ExitHandler _savedExitHandler;
+
+ _Runner.setUp()
+ : _savedOutSink = outSink,
+ _savedErrorSink = errorSink,
+ _savedExitHandler = exitHandler,
+ _savedExitCode = exitCode {
+ outSink = _stdout;
+ errorSink = _stderr;
+ exitHandler = (_) {};
+ }
+
+ void run(List<String> args) {
+ new Driver().start(args);
+ if (stderr.isNotEmpty) {
+ fail("Unexpected output to stderr:\n$stderr");
+ }
+ }
+
+ String get stdout => _stdout.toString();
+ String get stderr => _stderr.toString();
+
+ void tearDown() {
+ outSink = _savedOutSink;
+ errorSink = _savedErrorSink;
+ exitCode = _savedExitCode;
+ exitHandler = _savedExitHandler;
+ }
+}
diff --git a/pkg/analyzer_cli/test/perf_report_test.dart b/pkg/analyzer_cli/test/perf_report_test.dart
index f668485..19d91a1 100644
--- a/pkg/analyzer_cli/test/perf_report_test.dart
+++ b/pkg/analyzer_cli/test/perf_report_test.dart
@@ -6,6 +6,7 @@
import 'dart:convert' show JSON;
+import 'package:analyzer_cli/src/error_formatter.dart' show AnalysisStats;
import 'package:analyzer_cli/src/options.dart';
import 'package:analyzer_cli/src/perf_report.dart';
import 'package:unittest/unittest.dart';
@@ -13,7 +14,7 @@
main() {
test('makePerfReport', () {
var options = CommandLineOptions.parse(["somefile.dart"]);
- var encoded = makePerfReport(1000, 1234, options);
+ var encoded = makePerfReport(1000, 1234, options, 0, new AnalysisStats());
var json = JSON.decode(encoded);
expect(json['totalElapsedTime'], 234);
diff --git a/pkg/analyzer_cli/test/reporter_test.dart b/pkg/analyzer_cli/test/reporter_test.dart
index 94b0896..3a0853b 100644
--- a/pkg/analyzer_cli/test/reporter_test.dart
+++ b/pkg/analyzer_cli/test/reporter_test.dart
@@ -14,7 +14,9 @@
main() {
group('reporter', () {
var out = new StringBuffer();
+ var stats = new AnalysisStats();
+ setUp(() => stats.init());
tearDown(() => out.clear());
// Options
@@ -23,28 +25,32 @@
when(options.hintsAreFatal).thenReturn(false);
when(options.machineFormat).thenReturn(false);
- var reporter = new ErrorFormatter(out, options);
+ var reporter = new ErrorFormatter(out, options, stats);
test('error', () {
var error = mockError(ErrorType.SYNTACTIC_ERROR, ErrorSeverity.ERROR);
reporter.formatErrors([error]);
- expect(
- out.toString(),
- '''[error] MSG (/foo/bar/baz.dart, line 3, col 3)
-1 error found.
-''');
+ expect(out.toString().trim(),
+ '[error] MSG (/foo/bar/baz.dart, line 3, col 3)');
});
test('hint', () {
var error = mockError(ErrorType.HINT, ErrorSeverity.INFO);
reporter.formatErrors([error]);
+ expect(out.toString().trim(),
+ '[hint] MSG (/foo/bar/baz.dart, line 3, col 3)');
+ });
+
+ test('stats', () {
+ var error = mockError(ErrorType.HINT, ErrorSeverity.INFO);
+ reporter.formatErrors([error]);
+ stats.print(out);
expect(
- out.toString(),
+ out.toString().trim(),
'''[hint] MSG (/foo/bar/baz.dart, line 3, col 3)
-1 hint found.
-''');
+1 hint found.''');
});
});
}
diff --git a/pkg/compiler/lib/compiler.dart b/pkg/compiler/lib/compiler.dart
index 763dc4a..445e2ca 100644
--- a/pkg/compiler/lib/compiler.dart
+++ b/pkg/compiler/lib/compiler.dart
@@ -115,7 +115,7 @@
Uri packageConfig,
PackagesDiscoveryProvider packagesDiscoveryProvider]) {
- new_api.CompilerOptions compilerOptions = new new_api.CompilerOptions(
+ new_api.CompilerOptions compilerOptions = new new_api.CompilerOptions.parse(
entryPoint: script,
libraryRoot: libraryRoot,
packageRoot: packageRoot,
diff --git a/pkg/compiler/lib/compiler_new.dart b/pkg/compiler/lib/compiler_new.dart
index b6c1e4f..fa405da 100644
--- a/pkg/compiler/lib/compiler_new.dart
+++ b/pkg/compiler/lib/compiler_new.dart
@@ -9,6 +9,9 @@
import 'dart:async';
import 'src/apiimpl.dart';
+import 'src/commandline_options.dart';
+import 'src/diagnostics/diagnostic_listener.dart' show DiagnosticOptions;
+
import 'compiler.dart' show Diagnostic, PackagesDiscoveryProvider;
export 'compiler.dart' show Diagnostic, PackagesDiscoveryProvider;
@@ -71,8 +74,8 @@
/// Experimental: [code] gives access to an id for the messages. Currently it
/// is the [Message] used to create the diagnostic, if available, from which
/// the [MessageKind] is accessible.
- void report(var code,
- Uri uri, int begin, int end, String text, Diagnostic kind);
+ void report(
+ var code, Uri uri, int begin, int end, String text, Diagnostic kind);
}
/// Information resulting from the compilation.
@@ -92,52 +95,422 @@
/// Object for passing options to the compiler.
class CompilerOptions {
+ /// The entry point of the application that is being compiled.
final Uri entryPoint;
+
+ /// Root location where SDK libraries are found.
final Uri libraryRoot;
+
+ /// Package root location.
+ ///
+ /// If not null then [packageConfig] should be null.
final Uri packageRoot;
+
+ /// Location of the package configuration file.
+ ///
+ /// If not null then [packageRoot] should be null.
final Uri packageConfig;
+
+ // TODO(sigmund): Move out of here, maybe to CompilerInput. Options should not
+ // hold code, just configuration options.
final PackagesDiscoveryProvider packagesDiscoveryProvider;
- final List<String> options;
+
+ /// Resolved constant "environment" values passed to the compiler via the `-D`
+ /// flags.
final Map<String, dynamic> environment;
- /// Creates an option object for the compiler.
- // TODO(johnniwinther): Expand comment when [options] are explicit as named
- // arguments.
- factory CompilerOptions(
+ /// Whether we allow mocking compilation of libraries such as dart:io and
+ /// dart:html for unit testing purposes.
+ final bool allowMockCompilation;
+
+ /// Whether the native extension syntax is supported by the frontend.
+ final bool allowNativeExtensions;
+
+ /// Whether to resolve all functions in the program, not just those reachable
+ /// from main. This implies [analyzeOnly] is true as well.
+ final bool analyzeAll;
+
+ /// Whether to disable tree-shaking for the main script. This marks all
+ /// functions in the main script as reachable (not just a function named
+ /// `main`).
+ // TODO(sigmund): rename. The current name seems to indicate that only the
+ // main function is retained, which is the opposite of what this does.
+ final bool analyzeMain;
+
+ /// Whether to run the compiler just for the purpose of analysis. That is, to
+ /// run resolution and type-checking alone, but otherwise do not generate any
+ /// code.
+ final bool analyzeOnly;
+
+ /// Whether to skip analysis of method bodies and field initializers. Implies
+ /// [analyzeOnly].
+ final bool analyzeSignaturesOnly;
+
+ /// ID associated with this sdk build.
+ final String buildId;
+
+ /// Whether there is a build-id available so we can use it on error messages
+ /// and in the emitted output of the compiler.
+ bool get hasBuildId => buildId != _UNDETERMINED_BUILD_ID;
+
+ /// Location where to generate a map containing details of how deferred
+ /// libraries are subdivided.
+ final Uri deferredMapUri;
+
+ /// Whether to disable inlining during the backend optimizations.
+ // TODO(sigmund): negate, so all flags are positive
+ final bool disableInlining;
+
+ /// Several options to configure diagnostic messages.
+ // TODO(sigmund): should we simply embed those options here?
+ final DiagnosticOptions diagnosticOptions;
+
+ /// Whether to disable global type inference.
+ final bool disableTypeInference;
+
+ /// Whether to emit a .json file with a summary of the information used by the
+ /// compiler during optimization. This includes resolution details,
+ /// dependencies between elements, results of type inference, and the output
+ /// code for each function.
+ final bool dumpInfo;
+
+ /// Whether we allow passing an extra argument to `assert`, containing a
+ /// reason for why an assertion fails. (experimental)
+ final bool enableAssertMessage;
+
+ /// Whether to enable the experimental conditional directives feature.
+ final bool enableConditionalDirectives;
+
+ /// Whether the user specified a flag to allow the use of dart:mirrors. This
+ /// silences a warning produced by the compiler.
+ final bool enableExperimentalMirrors;
+
+ /// Whether to enable minification
+ // TODO(sigmund): rename to minify
+ final bool enableMinification;
+
+ /// Whether to model which native classes are live based on annotations on the
+ /// core libraries. If false, all native classes will be included by default.
+ final bool enableNativeLiveTypeAnalysis;
+
+ /// Whether to generate code containing checked-mode assignability checks.
+ final bool enableTypeAssertions;
+
+ /// Whether to generate code containing user's `assert` statements.
+ final bool enableUserAssertions;
+
+ /// Whether to generate output even when there are compile-time errors.
+ final bool generateCodeWithCompileTimeErrors;
+
+ /// Whether to generate a source-map file together with the output program.
+ final bool generateSourceMap;
+
+ /// Whether some values are cached for reuse in incremental compilation.
+ /// Incremental compilation allows calling `Compiler.run` more than once
+ /// (experimental).
+ final bool hasIncrementalSupport;
+
+ /// URI of the main output if the compiler is generating source maps.
+ final Uri outputUri;
+
+ /// Location of the platform configuration file.
+ final Uri platformConfigUri;
+
+ /// Whether to emit URIs in the reflection metadata.
+ final bool preserveUris;
+
+ /// URI where the compiler should generate the output source map file.
+ final Uri sourceMapUri;
+
+ /// The compiler is run from the build bot.
+ final bool testMode;
+
+ /// Whether to trust JS-interop annotations. (experimental)
+ final bool trustJSInteropTypeAnnotations;
+
+ /// Whether to trust primitive types during inference and optimizations.
+ final bool trustPrimitives;
+
+ /// Whether to trust type annotations during inference and optimizations.
+ final bool trustTypeAnnotations;
+
+ /// Whether to generate code compliant with content security policy (CSP).
+ final bool useContentSecurityPolicy;
+
+ /// Use the experimental CPS based backend.
+ final bool useCpsIr;
+
+ /// When obfuscating for minification, whether to use the frequency of a name
+ /// as an heuristic to pick shorter names.
+ final bool useFrequencyNamer;
+
+ /// Whether to use the new source-information implementation for source-maps.
+ /// (experimental)
+ final bool useNewSourceInfo;
+
+ /// Whether the user requested to use the fast startup emitter. The full
+ /// emitter might still be used if the program uses dart:mirrors.
+ final bool useStartupEmitter;
+
+ /// Enable verbose printing during compilation. Includes progress messages
+ /// during each phase and a time-breakdown between phases at the end.
+ final bool verbose;
+
+
+ // -------------------------------------------------
+ // Options for deprecated features
+ // -------------------------------------------------
+ // TODO(sigmund): delete these as we delete the underlying features
+
+ /// Whether to preserve comments while scanning (only use for dart:mirrors).
+ final bool preserveComments;
+
+ /// Whether to emit JavaScript (false enables dart2dart).
+ final bool emitJavaScript;
+
+ /// When using dart2dart, whether to use the multi file format.
+ final bool dart2dartMultiFile;
+
+ /// Strip option used by dart2dart.
+ final List<String> strips;
+
+ /// Create an options object by parsing flags from [options].
+ factory CompilerOptions.parse(
{Uri entryPoint,
- Uri libraryRoot,
- Uri packageRoot,
- Uri packageConfig,
- PackagesDiscoveryProvider packagesDiscoveryProvider,
- List<String> options: const <String>[],
- Map<String, dynamic> environment: const <String, dynamic>{}}) {
- if (entryPoint == null) {
- throw new ArgumentError("entryPoint must be non-null");
- }
- if (!libraryRoot.path.endsWith("/")) {
- throw new ArgumentError("libraryRoot must end with a /");
- }
- if (packageRoot != null && !packageRoot.path.endsWith("/")) {
- throw new ArgumentError("packageRoot must end with a /");
- }
- return new CompilerOptions._(
- entryPoint,
- libraryRoot,
- packageRoot,
- packageConfig,
- packagesDiscoveryProvider,
- options,
- environment);
+ Uri libraryRoot,
+ Uri packageRoot,
+ Uri packageConfig,
+ PackagesDiscoveryProvider packagesDiscoveryProvider,
+ Map<String, dynamic> environment: const <String, dynamic>{},
+ List<String> options}) {
+ return new CompilerOptions(
+ entryPoint: entryPoint,
+ libraryRoot: libraryRoot,
+ packageRoot: packageRoot,
+ packageConfig: packageConfig,
+ packagesDiscoveryProvider: packagesDiscoveryProvider,
+ environment: environment,
+ allowMockCompilation: _hasOption(options, Flags.allowMockCompilation),
+ allowNativeExtensions: _hasOption(options, Flags.allowNativeExtensions),
+ analyzeAll: _hasOption(options, Flags.analyzeAll),
+ analyzeMain: _hasOption(options, Flags.analyzeMain),
+ analyzeOnly: _hasOption(options, Flags.analyzeOnly),
+ analyzeSignaturesOnly: _hasOption(options, Flags.analyzeSignaturesOnly),
+ buildId: _extractStringOption(
+ options, '--build-id=', _UNDETERMINED_BUILD_ID),
+ dart2dartMultiFile: _hasOption(options, '--output-type=dart-multi'),
+ deferredMapUri: _extractUriOption(options, '--deferred-map='),
+ diagnosticOptions: new DiagnosticOptions(
+ suppressWarnings: _hasOption(options, Flags.suppressWarnings),
+ fatalWarnings: _hasOption(options, Flags.fatalWarnings),
+ suppressHints: _hasOption(options, Flags.suppressHints),
+ terseDiagnostics: _hasOption(options, Flags.terse),
+ shownPackageWarnings:
+ _extractOptionalCsvOption(options, Flags.showPackageWarnings)),
+ disableInlining: _hasOption(options, Flags.disableInlining),
+ disableTypeInference: _hasOption(options, Flags.disableTypeInference),
+ dumpInfo: _hasOption(options, Flags.dumpInfo),
+ emitJavaScript: !(_hasOption(options, '--output-type=dart') ||
+ _hasOption(options, '--output-type=dart-multi')),
+ enableAssertMessage: _hasOption(options, Flags.enableAssertMessage),
+ enableConditionalDirectives:
+ _hasOption(options, Flags.conditionalDirectives),
+ enableExperimentalMirrors:
+ _hasOption(options, Flags.enableExperimentalMirrors),
+ enableMinification: _hasOption(options, Flags.minify),
+ enableNativeLiveTypeAnalysis:
+ !_hasOption(options, Flags.disableNativeLiveTypeAnalysis),
+ enableTypeAssertions: _hasOption(options, Flags.enableCheckedMode),
+ enableUserAssertions: _hasOption(options, Flags.enableCheckedMode),
+ generateCodeWithCompileTimeErrors:
+ _hasOption(options, Flags.generateCodeWithCompileTimeErrors),
+ generateSourceMap: !_hasOption(options, Flags.noSourceMaps),
+ hasIncrementalSupport: _forceIncrementalSupport ||
+ _hasOption(options, Flags.incrementalSupport),
+ outputUri: _extractUriOption(options, '--out='),
+ platformConfigUri: _resolvePlatformConfigFromOptions(
+ libraryRoot, options),
+ preserveComments: _hasOption(options, Flags.preserveComments),
+ preserveUris: _hasOption(options, Flags.preserveUris),
+ sourceMapUri: _extractUriOption(options, '--source-map='),
+ strips: _extractCsvOption(options, '--force-strip='),
+ testMode: _hasOption(options, Flags.testMode),
+ trustJSInteropTypeAnnotations:
+ _hasOption(options, Flags.trustJSInteropTypeAnnotations),
+ trustPrimitives: _hasOption(options, Flags.trustPrimitives),
+ trustTypeAnnotations: _hasOption(options, Flags.trustTypeAnnotations),
+ useContentSecurityPolicy:
+ _hasOption(options, Flags.useContentSecurityPolicy),
+ useCpsIr: _hasOption(options, Flags.useCpsIr),
+ useFrequencyNamer:
+ !_hasOption(options, Flags.noFrequencyBasedMinification),
+ useNewSourceInfo: _hasOption(options, Flags.useNewSourceInfo),
+ useStartupEmitter: _hasOption(options, Flags.fastStartup),
+ verbose: _hasOption(options, Flags.verbose));
}
- CompilerOptions._(
- this.entryPoint,
- this.libraryRoot,
- this.packageRoot,
- this.packageConfig,
- this.packagesDiscoveryProvider,
- this.options,
- this.environment);
+ /// Creates an option object for the compiler.
+ ///
+ /// This validates and normalizes dependent options to be consistent. For
+ /// example, if [analyzeAll] is true, the resulting options object will also
+ /// have [analyzeOnly] as true.
+ factory CompilerOptions(
+ {Uri entryPoint,
+ Uri libraryRoot,
+ Uri packageRoot,
+ Uri packageConfig,
+ PackagesDiscoveryProvider packagesDiscoveryProvider,
+ Map<String, dynamic> environment: const <String, dynamic>{},
+ bool allowMockCompilation: false,
+ bool allowNativeExtensions: false,
+ bool analyzeAll: false,
+ bool analyzeMain: false,
+ bool analyzeOnly: false,
+ bool analyzeSignaturesOnly: false,
+ String buildId: _UNDETERMINED_BUILD_ID,
+ bool dart2dartMultiFile: false,
+ Uri deferredMapUri: null,
+ DiagnosticOptions diagnosticOptions: const DiagnosticOptions(),
+ bool disableInlining: false,
+ bool disableTypeInference: false,
+ bool dumpInfo: false,
+ bool emitJavaScript: true,
+ bool enableAssertMessage: false,
+ bool enableConditionalDirectives: false,
+ bool enableExperimentalMirrors: false,
+ bool enableMinification: false,
+ bool enableNativeLiveTypeAnalysis: true,
+ bool enableTypeAssertions: false,
+ bool enableUserAssertions: false,
+ bool generateCodeWithCompileTimeErrors: false,
+ bool generateSourceMap: true,
+ bool hasIncrementalSupport: false,
+ Uri outputUri: null,
+ Uri platformConfigUri: null,
+ bool preserveComments: false,
+ bool preserveUris: false,
+ Uri sourceMapUri: null,
+ List<String> strips: const [],
+ bool testMode: false,
+ bool trustJSInteropTypeAnnotations: false,
+ bool trustPrimitives: false,
+ bool trustTypeAnnotations: false,
+ bool useContentSecurityPolicy: false,
+ bool useCpsIr: false,
+ bool useFrequencyNamer: true,
+ bool useNewSourceInfo: false,
+ bool useStartupEmitter: false,
+ bool verbose: false}) {
+ // TODO(sigmund): should entrypoint be here? should we validate it is not
+ // null? In unittests we use the same compiler to analyze or build multiple
+ // entrypoints.
+ if (libraryRoot == null) {
+ throw new ArgumentError("[libraryRoot] is null.");
+ }
+ if (!libraryRoot.path.endsWith("/")) {
+ throw new ArgumentError("[libraryRoot] must end with a /");
+ }
+ if (packageRoot != null && packageConfig != null) {
+ throw new ArgumentError("Only one of [packageRoot] or [packageConfig] "
+ "may be given.");
+ }
+ if (packageRoot != null && !packageRoot.path.endsWith("/")) {
+ throw new ArgumentError("[packageRoot] must end with a /");
+ }
+ if (!analyzeOnly) {
+ if (allowNativeExtensions) {
+ throw new ArgumentError(
+ "${Flags.allowNativeExtensions} is only supported in combination "
+ "with ${Flags.analyzeOnly}");
+ }
+ }
+ return new CompilerOptions._(entryPoint, libraryRoot, packageRoot,
+ packageConfig, packagesDiscoveryProvider, environment,
+ allowMockCompilation: allowMockCompilation,
+ allowNativeExtensions: allowNativeExtensions,
+ analyzeAll: analyzeAll,
+ analyzeMain: analyzeMain,
+ analyzeOnly: analyzeOnly || analyzeSignaturesOnly || analyzeAll,
+ analyzeSignaturesOnly: analyzeSignaturesOnly,
+ buildId: buildId,
+ dart2dartMultiFile: dart2dartMultiFile,
+ deferredMapUri: deferredMapUri,
+ diagnosticOptions: diagnosticOptions,
+ disableInlining: disableInlining || hasIncrementalSupport,
+ disableTypeInference: disableTypeInference || !emitJavaScript,
+ dumpInfo: dumpInfo,
+ emitJavaScript: emitJavaScript,
+ enableAssertMessage: enableAssertMessage,
+ enableConditionalDirectives: enableConditionalDirectives,
+ enableExperimentalMirrors: enableExperimentalMirrors,
+ enableMinification: enableMinification,
+ enableNativeLiveTypeAnalysis: enableNativeLiveTypeAnalysis,
+ enableTypeAssertions: enableTypeAssertions,
+ enableUserAssertions: enableUserAssertions,
+ generateCodeWithCompileTimeErrors: generateCodeWithCompileTimeErrors,
+ generateSourceMap: generateSourceMap,
+ hasIncrementalSupport: hasIncrementalSupport,
+ outputUri: outputUri,
+ platformConfigUri: platformConfigUri ?? _resolvePlatformConfig(
+ libraryRoot, null, !emitJavaScript, const []),
+ preserveComments: preserveComments,
+ preserveUris: preserveUris,
+ sourceMapUri: sourceMapUri,
+ strips: strips,
+ testMode: testMode,
+ trustJSInteropTypeAnnotations: trustJSInteropTypeAnnotations,
+ trustPrimitives: trustPrimitives,
+ trustTypeAnnotations: trustTypeAnnotations,
+ useContentSecurityPolicy: useContentSecurityPolicy,
+ useCpsIr: useCpsIr,
+ useFrequencyNamer: useFrequencyNamer,
+ useNewSourceInfo: useNewSourceInfo,
+ useStartupEmitter: useStartupEmitter,
+ verbose: verbose);
+ }
+
+ CompilerOptions._(this.entryPoint, this.libraryRoot, this.packageRoot,
+ this.packageConfig, this.packagesDiscoveryProvider, this.environment,
+ {this.allowMockCompilation: false,
+ this.allowNativeExtensions: false,
+ this.analyzeAll: false,
+ this.analyzeMain: false,
+ this.analyzeOnly: false,
+ this.analyzeSignaturesOnly: false,
+ this.buildId: _UNDETERMINED_BUILD_ID,
+ this.dart2dartMultiFile: false,
+ this.deferredMapUri: null,
+ this.diagnosticOptions: null,
+ this.disableInlining: false,
+ this.disableTypeInference: false,
+ this.dumpInfo: false,
+ this.emitJavaScript: true,
+ this.enableAssertMessage: false,
+ this.enableConditionalDirectives: false,
+ this.enableExperimentalMirrors: false,
+ this.enableMinification: false,
+ this.enableNativeLiveTypeAnalysis: false,
+ this.enableTypeAssertions: false,
+ this.enableUserAssertions: false,
+ this.generateCodeWithCompileTimeErrors: false,
+ this.generateSourceMap: true,
+ this.hasIncrementalSupport: false,
+ this.outputUri: null,
+ this.platformConfigUri: null,
+ this.preserveComments: false,
+ this.preserveUris: false,
+ this.sourceMapUri: null,
+ this.strips: const [],
+ this.testMode: false,
+ this.trustJSInteropTypeAnnotations: false,
+ this.trustPrimitives: false,
+ this.trustTypeAnnotations: false,
+ this.useContentSecurityPolicy: false,
+ this.useCpsIr: false,
+ this.useFrequencyNamer: false,
+ this.useNewSourceInfo: false,
+ this.useStartupEmitter: false,
+ this.verbose: false});
}
/// Returns a future that completes to a [CompilationResult] when the Dart
@@ -154,7 +527,6 @@
CompilerInput compilerInput,
CompilerDiagnostics compilerDiagnostics,
CompilerOutput compilerOutput) {
-
if (compilerOptions == null) {
throw new ArgumentError("compilerOptions must be non-null");
}
@@ -169,16 +541,92 @@
}
CompilerImpl compiler = new CompilerImpl(
- compilerInput,
- compilerOutput,
- compilerDiagnostics,
- compilerOptions.libraryRoot,
- compilerOptions.packageRoot,
- compilerOptions.options,
- compilerOptions.environment,
- compilerOptions.packageConfig,
- compilerOptions.packagesDiscoveryProvider);
+ compilerInput, compilerOutput, compilerDiagnostics, compilerOptions);
return compiler.run(compilerOptions.entryPoint).then((bool success) {
return new CompilationResult(compiler, isSuccess: success);
});
}
+
+String _extractStringOption(
+ List<String> options, String prefix, String defaultValue) {
+ for (String option in options) {
+ if (option.startsWith(prefix)) {
+ return option.substring(prefix.length);
+ }
+ }
+ return defaultValue;
+}
+
+Uri _extractUriOption(List<String> options, String prefix) {
+ var option = _extractStringOption(options, prefix, null);
+ return (option == null) ? null : Uri.parse(option);
+}
+
+// CSV: Comma separated values.
+List<String> _extractCsvOption(List<String> options, String prefix) {
+ for (String option in options) {
+ if (option.startsWith(prefix)) {
+ return option.substring(prefix.length).split(',');
+ }
+ }
+ return const <String>[];
+}
+
+/// Extract list of comma separated values provided for [flag]. Returns an
+/// empty list if [option] contain [flag] without arguments. Returns `null` if
+/// [option] doesn't contain [flag] with or without arguments.
+List<String> _extractOptionalCsvOption(List<String> options, String flag) {
+ String prefix = '$flag=';
+ for (String option in options) {
+ if (option == flag) {
+ return const <String>[];
+ }
+ if (option.startsWith(flag)) {
+ return option.substring(prefix.length).split(',');
+ }
+ }
+ return null;
+}
+
+Uri _resolvePlatformConfigFromOptions(Uri libraryRoot, List<String> options) {
+ return _resolvePlatformConfig(libraryRoot,
+ _extractStringOption(options, "--platform-config=", null),
+ _hasOption(options, '--output-type=dart'),
+ _extractCsvOption(options, '--categories='));
+}
+
+Uri _resolvePlatformConfig(Uri libraryRoot,
+ String platformConfigPath, bool isDart2Dart, Iterable<String> categories) {
+ if (platformConfigPath != null) {
+ return libraryRoot.resolve(platformConfigPath);
+ } else if (isDart2Dart) {
+ return libraryRoot.resolve(_dart2dartPlatform);
+ } else {
+ if (categories.length == 0) {
+ return libraryRoot.resolve(_clientPlatform);
+ }
+ assert(categories.length <= 2);
+ if (categories.contains("Client")) {
+ if (categories.contains("Server")) {
+ return libraryRoot.resolve(_sharedPlatform);
+ }
+ return libraryRoot.resolve(_clientPlatform);
+ }
+ assert(categories.contains("Server"));
+ return libraryRoot.resolve(_serverPlatform);
+ }
+}
+
+bool _hasOption(List<String> options, String option) {
+ return options.indexOf(option) >= 0;
+}
+
+/// Locations of the platform descriptor files relative to the library root.
+const String _clientPlatform = "lib/dart_client.platform";
+const String _serverPlatform = "lib/dart_server.platform";
+const String _sharedPlatform = "lib/dart_shared.platform";
+const String _dart2dartPlatform = "lib/dart2dart.platform";
+
+const String _UNDETERMINED_BUILD_ID = "build number could not be determined";
+const bool _forceIncrementalSupport =
+ const bool.fromEnvironment('DART2JS_EXPERIMENTAL_INCREMENTAL_SUPPORT');
diff --git a/pkg/compiler/lib/src/apiimpl.dart b/pkg/compiler/lib/src/apiimpl.dart
index 31ce5a8..42eda64 100644
--- a/pkg/compiler/lib/src/apiimpl.dart
+++ b/pkg/compiler/lib/src/apiimpl.dart
@@ -30,9 +30,6 @@
import 'platform_configuration.dart' as platform_configuration;
import 'script.dart';
-const bool forceIncrementalSupport =
- const bool.fromEnvironment('DART2JS_EXPERIMENTAL_INCREMENTAL_SUPPORT');
-
/// For every 'dart:' library, a corresponding environment variable is set
/// to "true". The environment variable's name is the concatenation of
/// this prefix and the name (without the 'dart:'.
@@ -41,24 +38,13 @@
/// to "true".
const String dartLibraryEnvironmentPrefix = 'dart.library.';
-/// Locations of the platform descriptor files relative to the library root.
-const String _clientPlatform = "lib/dart_client.platform";
-const String _serverPlatform = "lib/dart_server.platform";
-const String _sharedPlatform = "lib/dart_shared.platform";
-const String _dart2dartPlatform = "lib/dart2dart.platform";
/// Implements the [Compiler] using a [api.CompilerInput] for supplying the
/// sources.
class CompilerImpl extends Compiler {
api.CompilerInput provider;
api.CompilerDiagnostics handler;
- final Uri platformConfigUri;
- final Uri packageConfig;
- final Uri packageRoot;
- final api.PackagesDiscoveryProvider packagesDiscoveryProvider;
Packages packages;
- List<String> options;
- Map<String, dynamic> environment;
bool mockableLibraryUsed = false;
/// A mapping of the dart: library-names to their location.
@@ -70,181 +56,19 @@
GenericTask userProviderTask;
GenericTask userPackagesDiscoveryTask;
- Uri get libraryRoot => platformConfigUri.resolve(".");
+ Uri get libraryRoot => options.platformConfigUri.resolve(".");
- CompilerImpl(this.provider,
- api.CompilerOutput outputProvider,
- this.handler,
- Uri libraryRoot,
- this.packageRoot,
- List<String> options,
- this.environment,
- [this.packageConfig,
- this.packagesDiscoveryProvider])
- : this.options = options,
- this.platformConfigUri = resolvePlatformConfig(libraryRoot, options),
- super(
- outputProvider: outputProvider,
- enableTypeAssertions: hasOption(options, Flags.enableCheckedMode),
- enableUserAssertions: hasOption(options, Flags.enableCheckedMode),
- trustTypeAnnotations:
- hasOption(options, Flags.trustTypeAnnotations),
- trustPrimitives:
- hasOption(options, Flags.trustPrimitives),
- trustJSInteropTypeAnnotations:
- hasOption(options, Flags.trustJSInteropTypeAnnotations),
- enableMinification: hasOption(options, Flags.minify),
- useFrequencyNamer:
- !hasOption(options, Flags.noFrequencyBasedMinification),
- preserveUris: hasOption(options, Flags.preserveUris),
- enableNativeLiveTypeAnalysis:
- !hasOption(options, Flags.disableNativeLiveTypeAnalysis),
- emitJavaScript: !(hasOption(options, '--output-type=dart') ||
- hasOption(options, '--output-type=dart-multi')),
- dart2dartMultiFile: hasOption(options, '--output-type=dart-multi'),
- generateSourceMap: !hasOption(options, Flags.noSourceMaps),
- analyzeAllFlag: hasOption(options, Flags.analyzeAll),
- analyzeOnly: hasOption(options, Flags.analyzeOnly),
- analyzeMain: hasOption(options, Flags.analyzeMain),
- analyzeSignaturesOnly:
- hasOption(options, Flags.analyzeSignaturesOnly),
- strips: extractCsvOption(options, '--force-strip='),
- disableTypeInferenceFlag:
- hasOption(options, Flags.disableTypeInference),
- preserveComments: hasOption(options, Flags.preserveComments),
- useCpsIr: hasOption(options, Flags.useCpsIr),
- verbose: hasOption(options, Flags.verbose),
- sourceMapUri: extractUriOption(options, '--source-map='),
- outputUri: extractUriOption(options, '--out='),
- deferredMapUri: extractUriOption(options, '--deferred-map='),
- dumpInfo: hasOption(options, Flags.dumpInfo),
- buildId: extractStringOption(
- options, '--build-id=',
- "build number could not be determined"),
- useContentSecurityPolicy:
- hasOption(options, Flags.useContentSecurityPolicy),
- useStartupEmitter: hasOption(options, Flags.fastStartup),
- enableConditionalDirectives:
- hasOption(options, Flags.conditionalDirectives),
- useNewSourceInfo: hasOption(options, Flags.useNewSourceInfo),
- hasIncrementalSupport:
- forceIncrementalSupport ||
- hasOption(options, Flags.incrementalSupport),
- diagnosticOptions: new DiagnosticOptions(
- suppressWarnings: hasOption(options, Flags.suppressWarnings),
- fatalWarnings: hasOption(options, Flags.fatalWarnings),
- suppressHints: hasOption(options, Flags.suppressHints),
- terseDiagnostics: hasOption(options, Flags.terse),
- shownPackageWarnings: extractOptionalCsvOption(
- options, Flags.showPackageWarnings)),
- enableExperimentalMirrors:
- hasOption(options, Flags.enableExperimentalMirrors),
- enableAssertMessage:
- hasOption(options, Flags.enableAssertMessage),
- generateCodeWithCompileTimeErrors:
- hasOption(options, Flags.generateCodeWithCompileTimeErrors),
- testMode: hasOption(options, Flags.testMode),
- allowNativeExtensions:
- hasOption(options, Flags.allowNativeExtensions)) {
+ CompilerImpl(this.provider, api.CompilerOutput outputProvider,
+ this.handler, api.CompilerOptions options)
+ : super(options: options, outputProvider: outputProvider) {
tasks.addAll([
userHandlerTask = new GenericTask('Diagnostic handler', this),
userProviderTask = new GenericTask('Input provider', this),
userPackagesDiscoveryTask =
new GenericTask('Package discovery', this),
]);
- if (libraryRoot == null) {
- throw new ArgumentError("[libraryRoot] is null.");
- }
- if (!libraryRoot.path.endsWith("/")) {
- throw new ArgumentError("[libraryRoot] must end with a /.");
- }
- if (packageRoot != null && packageConfig != null) {
- throw new ArgumentError("Only one of [packageRoot] or [packageConfig] "
- "may be given.");
- }
- if (packageRoot != null && !packageRoot.path.endsWith("/")) {
- throw new ArgumentError("[packageRoot] must end with a /.");
- }
- if (!analyzeOnly) {
- if (allowNativeExtensions) {
- throw new ArgumentError(
- "${Flags.allowNativeExtensions} is only supported in combination "
- "with ${Flags.analyzeOnly}");
- }
- }
}
- static String extractStringOption(List<String> options,
- String prefix,
- String defaultValue) {
- for (String option in options) {
- if (option.startsWith(prefix)) {
- return option.substring(prefix.length);
- }
- }
- return defaultValue;
- }
-
- static Uri extractUriOption(List<String> options, String prefix) {
- var option = extractStringOption(options, prefix, null);
- return (option == null) ? null : Uri.parse(option);
- }
-
- // CSV: Comma separated values.
- static List<String> extractCsvOption(List<String> options, String prefix) {
- for (String option in options) {
- if (option.startsWith(prefix)) {
- return option.substring(prefix.length).split(',');
- }
- }
- return const <String>[];
- }
-
- /// Extract list of comma separated values provided for [flag]. Returns an
- /// empty list if [option] contain [flag] without arguments. Returns `null` if
- /// [option] doesn't contain [flag] with or without arguments.
- static List<String> extractOptionalCsvOption(
- List<String> options, String flag) {
- String prefix = '$flag=';
- for (String option in options) {
- if (option == flag) {
- return const <String>[];
- }
- if (option.startsWith(flag)) {
- return option.substring(prefix.length).split(',');
- }
- }
- return null;
- }
-
- static Uri resolvePlatformConfig(Uri libraryRoot,
- List<String> options) {
- String platformConfigPath =
- extractStringOption(options, "--platform-config=", null);
- if (platformConfigPath != null) {
- return libraryRoot.resolve(platformConfigPath);
- } else if (hasOption(options, '--output-type=dart')) {
- return libraryRoot.resolve(_dart2dartPlatform);
- } else {
- Iterable<String> categories = extractCsvOption(options, '--categories=');
- if (categories.length == 0) {
- return libraryRoot.resolve(_clientPlatform);
- }
- assert(categories.length <= 2);
- if (categories.contains("Client")) {
- if (categories.contains("Server")) {
- return libraryRoot.resolve(_sharedPlatform);
- }
- return libraryRoot.resolve(_clientPlatform);
- }
- assert(categories.contains("Server"));
- return libraryRoot.resolve(_serverPlatform);
- }
- }
-
- static bool hasOption(List<String> options, String option) {
- return options.indexOf(option) >= 0;
- }
void log(message) {
callUserHandler(
@@ -293,7 +117,7 @@
Uri resourceUri = translateUri(node, readableUri);
if (resourceUri == null) return synthesizeScript(node, readableUri);
if (resourceUri.scheme == 'dart-ext') {
- if (!allowNativeExtensions) {
+ if (!options.allowNativeExtensions) {
reporter.withCurrentElement(element, () {
reporter.reportErrorMessage(
node, MessageKind.DART_EXT_NOT_SUPPORTED);
@@ -350,8 +174,8 @@
}
/// Translates "resolvedUri" with scheme "dart" to a [uri] resolved relative
- /// to [platformConfigUri] according to the information in the file at
- /// [platformConfigUri].
+ /// to `options.platformConfigUri` according to the information in the file at
+ /// `options.platformConfigUri`.
///
/// Returns null and emits an error if the library could not be found or
/// imported into [importingLibrary].
@@ -451,33 +275,32 @@
}
Future setupPackages(Uri uri) {
- if (packageRoot != null) {
+ if (options.packageRoot != null) {
// Use "non-file" packages because the file version requires a [Directory]
// and we can't depend on 'dart:io' classes.
- packages = new NonFilePackagesDirectoryPackages(packageRoot);
- } else if (packageConfig != null) {
- return callUserProvider(packageConfig).then((packageConfigContents) {
- if (packageConfigContents is String) {
- packageConfigContents = UTF8.encode(packageConfigContents);
+ packages = new NonFilePackagesDirectoryPackages(options.packageRoot);
+ } else if (options.packageConfig != null) {
+ return callUserProvider(options.packageConfig).then((configContents) {
+ if (configContents is String) {
+ configContents = UTF8.encode(configContents);
}
// The input provider may put a trailing 0 byte when it reads a source
// file, which confuses the package config parser.
- if (packageConfigContents.length > 0 &&
- packageConfigContents.last == 0) {
- packageConfigContents = packageConfigContents.sublist(
- 0, packageConfigContents.length - 1);
+ if (configContents.length > 0 &&
+ configContents.last == 0) {
+ configContents = configContents.sublist(0, configContents.length - 1);
}
- packages =
- new MapPackages(pkgs.parse(packageConfigContents, packageConfig));
+ packages = new MapPackages(
+ pkgs.parse(configContents, options.packageConfig));
}).catchError((error) {
reporter.reportErrorMessage(
NO_LOCATION_SPANNABLE,
MessageKind.INVALID_PACKAGE_CONFIG,
- {'uri': packageConfig, 'exception': error});
+ {'uri': options.packageConfig, 'exception': error});
packages = Packages.noPackages;
});
} else {
- if (packagesDiscoveryProvider == null) {
+ if (options.packagesDiscoveryProvider == null) {
packages = Packages.noPackages;
} else {
return callUserPackagesDiscovery(uri).then((p) {
@@ -490,7 +313,7 @@
Future<Null> setupSdk() {
if (sdkLibraries == null) {
- return platform_configuration.load(platformConfigUri, provider)
+ return platform_configuration.load(options.platformConfigUri, provider)
.then((Map<String, Uri> mapping) {
sdkLibraries = mapping;
});
@@ -502,7 +325,7 @@
}
Future<bool> run(Uri uri) {
- log('Using platform configuration at ${platformConfigUri}');
+ log('Using platform configuration at ${options.platformConfigUri}');
return Future.wait([setupSdk(), setupPackages(uri)]).then((_) {
assert(sdkLibraries != null);
@@ -552,10 +375,8 @@
}
}
- bool get isMockCompilation {
- return mockableLibraryUsed
- && (options.indexOf(Flags.allowMockCompilation) != -1);
- }
+ bool get isMockCompilation =>
+ mockableLibraryUsed && options.allowMockCompilation;
void callUserHandler(Message message, Uri uri, int begin, int end,
String text, api.Diagnostic kind) {
@@ -582,7 +403,7 @@
Future<Packages> callUserPackagesDiscovery(Uri uri) {
try {
return userPackagesDiscoveryTask.measure(
- () => packagesDiscoveryProvider(uri));
+ () => options.packagesDiscoveryProvider(uri));
} catch (ex, s) {
diagnoseCrashInUserCode('Uncaught exception in package discovery', ex, s);
rethrow;
@@ -593,8 +414,8 @@
assert(invariant(NO_LOCATION_SPANNABLE,
sdkLibraries != null, message: "setupSdk() has not been run"));
- var result = environment[name];
- if (result != null || environment.containsKey(name)) return result;
+ var result = options.environment[name];
+ if (result != null || options.environment.containsKey(name)) return result;
if (!name.startsWith(dartLibraryEnvironmentPrefix)) return null;
String libraryName = name.substring(dartLibraryEnvironmentPrefix.length);
@@ -621,6 +442,6 @@
}
Uri resolvePatchUri(String libraryName) {
- return backend.resolvePatchUri(libraryName, platformConfigUri);
+ return backend.resolvePatchUri(libraryName, options.platformConfigUri);
}
}
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index d015b7c..bb51679 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -743,7 +743,7 @@
// TODO(karlklose,johnniwinther): if the type is null, the annotation is
// from a parameter which has been analyzed before the method has been
// resolved and the result has been thrown away.
- if (compiler.enableTypeAssertions && type != null &&
+ if (compiler.options.enableTypeAssertions && type != null &&
type.containsTypeVariables) {
if (insideClosure && member.isFactoryConstructor) {
// This is a closure in a factory constructor. Since there is no
@@ -813,7 +813,7 @@
Element element = elements[node];
if (Elements.isLocal(element)) {
mutatedVariables.add(element);
- if (compiler.enableTypeAssertions) {
+ if (compiler.options.enableTypeAssertions) {
TypedElement typedElement = element;
analyzeTypeVariables(typedElement.type);
}
@@ -1065,7 +1065,7 @@
// escape the potential type variables used in that closure.
if (element is FunctionElement &&
(compiler.backend.methodNeedsRti(element) ||
- compiler.enableTypeAssertions)) {
+ compiler.options.enableTypeAssertions)) {
analyzeTypeVariables(type);
}
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 6223f3b..1997d1c 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -12,6 +12,7 @@
static const String analyzeMain = '--analyze-main';
static const String analyzeOnly = '--analyze-only';
static const String analyzeSignaturesOnly = '--analyze-signatures-only';
+ static const String disableInlining = '--disable-inlining';
static const String disableDiagnosticColors = '--disable-diagnostic-colors';
static const String disableNativeLiveTypeAnalysis =
'--disable-native-live-type-analysis';
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index 3063616..d7af0cb 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -55,6 +55,11 @@
checkNativeAnnotation, checkJsInteropAnnotation;
import '../resolution/tree_elements.dart' show
TreeElements;
+import '../serialization/serialization.dart' show
+ DeserializerPlugin,
+ ObjectDecoder,
+ ObjectEncoder,
+ SerializerPlugin;
import '../tree/tree.dart' show
Node,
Send;
@@ -102,6 +107,9 @@
return const SourceInformationStrategy();
}
+ /// Interface for serialization of backend specific data.
+ BackendSerialization get serialization => const BackendSerialization();
+
// TODO(johnniwinther): Move this to the JavaScriptBackend.
String get patchVersion => null;
@@ -430,7 +438,8 @@
/// Creates an impact strategy to use for compilation.
ImpactStrategy createImpactStrategy(
{bool supportDeferredLoad: true,
- bool supportDumpInfo: true}) {
+ bool supportDumpInfo: true,
+ bool supportSerialization: true}) {
return const ImpactStrategy();
}
}
@@ -462,3 +471,11 @@
return worldImpact;
}
}
+
+/// Interface for serialization of backend specific data.
+class BackendSerialization {
+ const BackendSerialization();
+
+ SerializerPlugin get serializer => const SerializerPlugin();
+ DeserializerPlugin get deserializer => const DeserializerPlugin();
+}
diff --git a/pkg/compiler/lib/src/common/resolution.dart b/pkg/compiler/lib/src/common/resolution.dart
index e422ef8..ce82723 100644
--- a/pkg/compiler/lib/src/common/resolution.dart
+++ b/pkg/compiler/lib/src/common/resolution.dart
@@ -187,6 +187,9 @@
bool hasBeenResolved(Element element);
+ ResolutionWorkItem createWorkItem(
+ Element element, ItemCompilationContext compilationContext);
+
/// Returns the precomputed [WorldImpact] for [element].
WorldImpact getWorldImpact(Element element);
diff --git a/pkg/compiler/lib/src/common/tasks.dart b/pkg/compiler/lib/src/common/tasks.dart
index 737c2a9..1088363 100644
--- a/pkg/compiler/lib/src/common/tasks.dart
+++ b/pkg/compiler/lib/src/common/tasks.dart
@@ -30,7 +30,7 @@
CompilerTask(Compiler compiler)
: this.compiler = compiler,
- watch = (compiler.verbose) ? new Stopwatch() : null;
+ watch = (compiler.options.verbose) ? new Stopwatch() : null;
DiagnosticReporter get reporter => compiler.reporter;
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index d633e6b..1eabdf3 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -243,7 +243,7 @@
} else {
expression = compileNodeWithDefinitions(initializer, definitions,
isConst: isConst);
- if (compiler.enableTypeAssertions &&
+ if (compiler.options.enableTypeAssertions &&
checkType &&
expression != null &&
element.isField) {
@@ -1079,7 +1079,7 @@
}
void potentiallyCheckType(TypedElement element, AstConstant constant) {
- if (compiler.enableTypeAssertions) {
+ if (compiler.options.enableTypeAssertions) {
DartType elementType = element.type.substByContext(constructedType);
DartType constantType = constant.value.getType(coreTypes);
if (!constantSystem.isSubtype(
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 9bfb7eb..3152635 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -34,6 +34,7 @@
CompilerTask,
GenericTask;
import 'common/work.dart' show
+ ItemCompilationContext,
WorkItem;
import 'compile_time_constants.dart';
import 'constants/values.dart';
@@ -184,42 +185,8 @@
final Registry mirrorDependencies =
new ResolutionRegistry(null, new TreeElementMapping(null));
- final bool enableMinification;
-
- final bool useFrequencyNamer;
-
- /// When `true` emits URIs in the reflection metadata.
- final bool preserveUris;
-
- final bool enableTypeAssertions;
- final bool enableUserAssertions;
- final bool trustTypeAnnotations;
- final bool trustPrimitives;
- final bool trustJSInteropTypeAnnotations;
- final bool disableTypeInferenceFlag;
- final Uri deferredMapUri;
- final bool dumpInfo;
- final bool useContentSecurityPolicy;
- final bool enableExperimentalMirrors;
- final bool enableAssertMessage;
-
- /**
- * The maximum size of a concrete type before it widens to dynamic during
- * concrete type inference.
- */
- final int maxConcreteTypeSize;
- final bool analyzeAllFlag;
- final bool analyzeOnly;
-
- /// If true, disable tree-shaking for the main script.
- final bool analyzeMain;
-
- /**
- * If true, skip analysis of method bodies and field initializers. Implies
- * [analyzeOnly].
- */
- final bool analyzeSignaturesOnly;
- final bool enableNativeLiveTypeAnalysis;
+ /// Options provided from command-line arguments.
+ final api.CompilerOptions options;
/**
* If true, stop compilation after type inference is complete. Used for
@@ -227,49 +194,9 @@
*/
bool stopAfterTypeInference = false;
- /**
- * If [:true:], comment tokens are collected in [commentMap] during scanning.
- */
- final bool preserveComments;
-
- /// Use the new CPS based backend end. This flag works for both the Dart and
- /// JavaScript backend.
- final bool useCpsIr;
-
- /**
- * Is the compiler in verbose mode.
- */
- final bool verbose;
-
- /**
- * URI of the main source map if the compiler is generating source
- * maps.
- */
- final Uri sourceMapUri;
-
- /**
- * URI of the main output if the compiler is generating source maps.
- */
- final Uri outputUri;
-
- /// If `true`, some values are cached for reuse in incremental compilation.
- /// Incremental compilation is basically calling [run] more than once.
- final bool hasIncrementalSupport;
-
- /// If `true` native extension syntax is supported by the frontend.
- final bool allowNativeExtensions;
-
/// Output provider from user of Compiler API.
api.CompilerOutput userOutputProvider;
- /// Generate output even when there are compile-time errors.
- final bool generateCodeWithCompileTimeErrors;
-
- /// The compiler is run from the build bot.
- final bool testMode;
-
- bool disableInlining = false;
-
List<Uri> librariesToAnalyzeWhenRun;
/// The set of platform libraries reported as unsupported.
@@ -380,7 +307,6 @@
DeferredLoadTask deferredLoadTask;
MirrorUsageAnalyzerTask mirrorUsageAnalyzerTask;
DumpInfoTask dumpInfoTask;
- String buildId;
/// A customizable filter that is applied to enqueued work items.
QueueFilter enqueuerFilter = new QueueFilter();
@@ -391,9 +317,6 @@
static const String CREATE_INVOCATION_MIRROR =
'createInvocationMirror';
- static const String UNDETERMINED_BUILD_ID =
- "build number could not be determined";
-
bool enabledRuntimeType = false;
bool enabledFunctionApply = false;
bool enabledInvokeOn = false;
@@ -404,7 +327,7 @@
Stopwatch progress;
bool get shouldPrintProgress {
- return verbose && progress.elapsedMilliseconds > 500;
+ return options.verbose && progress.elapsedMilliseconds > 500;
}
static const int PHASE_SCANNING = 0;
@@ -424,74 +347,25 @@
compilationFailedInternal = value;
}
- /// Set by the backend if real reflection is detected in use of dart:mirrors.
- bool disableTypeInferenceForMirrors = false;
-
- Compiler({this.enableTypeAssertions: false,
- this.enableUserAssertions: false,
- this.trustTypeAnnotations: false,
- this.trustPrimitives: false,
- this.trustJSInteropTypeAnnotations: false,
- bool disableTypeInferenceFlag: false,
- this.maxConcreteTypeSize: 5,
- this.enableMinification: false,
- this.preserveUris: false,
- this.enableNativeLiveTypeAnalysis: false,
- bool emitJavaScript: true,
- bool dart2dartMultiFile: false,
- bool generateSourceMap: true,
- bool analyzeAllFlag: false,
- bool analyzeOnly: false,
- this.analyzeMain: false,
- bool analyzeSignaturesOnly: false,
- this.preserveComments: false,
- this.useCpsIr: false,
- this.useFrequencyNamer: false,
- this.verbose: false,
- this.sourceMapUri: null,
- this.outputUri: null,
- this.buildId: UNDETERMINED_BUILD_ID,
- this.deferredMapUri: null,
- this.dumpInfo: false,
- bool useStartupEmitter: false,
- bool enableConditionalDirectives: false,
- bool useNewSourceInfo: false,
- this.useContentSecurityPolicy: false,
- bool hasIncrementalSupport: false,
- this.enableExperimentalMirrors: false,
- this.enableAssertMessage: false,
- this.allowNativeExtensions: false,
- this.generateCodeWithCompileTimeErrors: false,
- this.testMode: false,
- DiagnosticOptions diagnosticOptions,
- api.CompilerOutput outputProvider,
- List<String> strips: const []})
- : this.disableTypeInferenceFlag =
- disableTypeInferenceFlag || !emitJavaScript,
- this.analyzeOnly =
- analyzeOnly || analyzeSignaturesOnly || analyzeAllFlag,
- this.analyzeSignaturesOnly = analyzeSignaturesOnly,
- this.analyzeAllFlag = analyzeAllFlag,
- this.hasIncrementalSupport = hasIncrementalSupport,
- cacheStrategy = new CacheStrategy(hasIncrementalSupport),
+ Compiler({api.CompilerOptions options,
+ api.CompilerOutput outputProvider})
+ : this.options = options,
+ this.cacheStrategy = new CacheStrategy(options.hasIncrementalSupport),
this.userOutputProvider = outputProvider == null
? const NullCompilerOutput() : outputProvider {
- if (hasIncrementalSupport) {
- // TODO(ahe): This is too much. Any method from platform and package
- // libraries can be inlined.
- disableInlining = true;
- }
+
world = new World(this);
// TODO(johnniwinther): Initialize core types in [initializeCoreClasses] and
// make its field final.
- _reporter = new _CompilerDiagnosticReporter(this, diagnosticOptions);
+ _reporter = new _CompilerDiagnosticReporter(
+ this, options.diagnosticOptions);
_parsing = new _CompilerParsing(this);
_resolution = new _CompilerResolution(this);
_coreTypes = new _CompilerCoreTypes(_resolution);
types = new Types(_resolution);
tracer = new Tracer(this, this.outputProvider);
- if (verbose) {
+ if (options.verbose) {
progress = new Stopwatch()..start();
}
@@ -499,17 +373,17 @@
// for global dependencies.
globalDependencies = new GlobalDependencyRegistry(this);
- if (emitJavaScript) {
+ if (options.emitJavaScript) {
js_backend.JavaScriptBackend jsBackend =
new js_backend.JavaScriptBackend(
- this, generateSourceMap: generateSourceMap,
- useStartupEmitter: useStartupEmitter,
- useNewSourceInfo: useNewSourceInfo);
+ this, generateSourceMap: options.generateSourceMap,
+ useStartupEmitter: options.useStartupEmitter,
+ useNewSourceInfo: options.useNewSourceInfo);
backend = jsBackend;
} else {
- backend = new dart_backend.DartBackend(this, strips,
- multiFile: dart2dartMultiFile);
- if (dumpInfo) {
+ backend = new dart_backend.DartBackend(this, options.strips,
+ multiFile: options.dart2dartMultiFile);
+ if (options.dumpInfo) {
throw new ArgumentError('--dump-info is not supported for dart2dart.');
}
}
@@ -519,11 +393,11 @@
serialization = new SerializationTask(this),
scanner = new ScannerTask(this),
dietParser = new DietParserTask(
- this, enableConditionalDirectives: enableConditionalDirectives),
+ this, enableConditionalDirectives: options.enableConditionalDirectives),
parser = new ParserTask(
- this, enableConditionalDirectives: enableConditionalDirectives),
+ this, enableConditionalDirectives: options.enableConditionalDirectives),
patchParser = new PatchParserTask(
- this, enableConditionalDirectives: enableConditionalDirectives),
+ this, enableConditionalDirectives: options.enableConditionalDirectives),
resolver = new ResolverTask(this, backend.constantCompilerTask),
closureToClassMapper = new closureMapping.ClosureTask(this),
checker = new TypeCheckerTask(this),
@@ -542,15 +416,12 @@
Universe get resolverWorld => enqueuer.resolution.universe;
Universe get codegenWorld => enqueuer.codegen.universe;
- bool get hasBuildId => buildId != UNDETERMINED_BUILD_ID;
-
- bool get analyzeAll => analyzeAllFlag || compileAll;
+ bool get analyzeAll => options.analyzeAll || compileAll;
bool get compileAll => false;
- bool get disableTypeInference {
- return disableTypeInferenceFlag || compilationFailed;
- }
+ bool get disableTypeInference =>
+ options.disableTypeInference || compilationFailed;
int getNextFreeClassId() => nextFreeClassId++;
@@ -641,7 +512,7 @@
// The maximum number of full imports chains to process.
final int chainLimit = 10000;
// The maximum number of imports chains to show.
- final int compactChainLimit = verbose ? 20 : 10;
+ final int compactChainLimit = options.verbose ? 20 : 10;
int chainCount = 0;
loadedLibraries.forEachImportChain(uri,
callback: (Link<Uri> importChainReversed) {
@@ -655,7 +526,7 @@
Uri uri = link.head;
if (!currentCodeLocation.inSameLocation(uri)) {
currentCodeLocation =
- verbose ? new UriLocation(uri) : new CodeLocation(uri);
+ options.verbose ? new UriLocation(uri) : new CodeLocation(uri);
compactImportChain =
compactImportChain.prepend(currentCodeLocation);
}
@@ -728,7 +599,7 @@
MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND,
{'importChain': importChains.join(
MessageTemplate.MIRRORS_NOT_SUPPORTED_BY_BACKEND_PADDING)});
- } else if (importsMirrorsLibrary && !enableExperimentalMirrors) {
+ } else if (importsMirrorsLibrary && !options.enableExperimentalMirrors) {
Set<String> importChains =
computeImportChainsFor(loadedLibraries, Uris.dart_mirrors);
reporter.reportWarningMessage(
@@ -742,7 +613,7 @@
functionApplyMethod =
coreClasses.functionClass.lookupLocalMember('apply');
- if (preserveComments) {
+ if (options.preserveComments) {
return libraryLoader.loadLibrary(Uris.dart_mirrors)
.then((LibraryElement libraryElement) {
documentClass = libraryElement.find('Comment');
@@ -863,20 +734,20 @@
.add(selector);
}
- assert(uri != null || analyzeOnly || hasIncrementalSupport);
+ assert(uri != null || options.analyzeOnly || options.hasIncrementalSupport);
return new Future.sync(() {
if (librariesToAnalyzeWhenRun != null) {
return Future.forEach(librariesToAnalyzeWhenRun, (libraryUri) {
- reporter.log('Analyzing $libraryUri ($buildId)');
+ reporter.log('Analyzing $libraryUri (${options.buildId})');
return libraryLoader.loadLibrary(libraryUri);
});
}
}).then((_) {
if (uri != null) {
- if (analyzeOnly) {
- reporter.log('Analyzing $uri ($buildId)');
+ if (options.analyzeOnly) {
+ reporter.log('Analyzing $uri (${options.buildId})');
} else {
- reporter.log('Compiling $uri ($buildId)');
+ reporter.log('Compiling $uri (${options.buildId})');
}
return libraryLoader.loadLibrary(uri).then((LibraryElement library) {
mainApp = library;
@@ -893,7 +764,7 @@
Element main = mainApp.findExported(Identifiers.main);
ErroneousElement errorElement = null;
if (main == null) {
- if (analyzeOnly) {
+ if (options.analyzeOnly) {
if (!analyzeAll) {
errorElement = new ErroneousElementX(
MessageKind.CONSIDER_ANALYZE_ALL, {'main': Identifiers.main},
@@ -937,7 +808,7 @@
}
}
if (mainFunction == null) {
- if (errorElement == null && !analyzeOnly && !analyzeAll) {
+ if (errorElement == null && !options.analyzeOnly && !analyzeAll) {
reporter.internalError(mainApp, "Problem with '${Identifiers.main}'.");
} else {
mainFunction = errorElement;
@@ -962,8 +833,8 @@
Future<LibraryElement> analyzeUri(
Uri libraryUri,
{bool skipLibraryWithPartOfTag: true}) {
- assert(analyzeMain);
- reporter.log('Analyzing $libraryUri ($buildId)');
+ assert(options.analyzeMain);
+ reporter.log('Analyzing $libraryUri (${options.buildId})');
return libraryLoader.loadLibrary(
libraryUri, skipFileWithPartOfTag: true).then(
(LibraryElement library) {
@@ -988,7 +859,8 @@
deferredLoadTask.beforeResolution(this);
impactStrategy = backend.createImpactStrategy(
supportDeferredLoad: deferredLoadTask.isProgramSplit,
- supportDumpInfo: dumpInfo);
+ supportDumpInfo: options.dumpInfo,
+ supportSerialization: serialization.supportSerialization);
phase = PHASE_RESOLVING;
if (analyzeAll) {
@@ -996,7 +868,7 @@
reporter.log('Enqueuing ${library.canonicalUri}');
fullyEnqueueLibrary(library, enqueuer.resolution);
});
- } else if (analyzeMain) {
+ } else if (options.analyzeMain) {
if (mainApp != null) {
fullyEnqueueLibrary(mainApp, enqueuer.resolution);
}
@@ -1018,13 +890,13 @@
_reporter.reportSuppressedMessagesSummary();
if (compilationFailed){
- if (!generateCodeWithCompileTimeErrors) return;
+ if (!options.generateCodeWithCompileTimeErrors) return;
if (!backend.enableCodegenWithErrorsIfSupported(NO_LOCATION_SPANNABLE)) {
return;
}
}
- if (analyzeOnly) {
+ if (options.analyzeOnly) {
if (!analyzeAll && !compilationFailed) {
// No point in reporting unused code when [analyzeAll] is true: all
// code is artificially used.
@@ -1070,7 +942,7 @@
int programSize = backend.assembleProgram();
- if (dumpInfo) {
+ if (options.dumpInfo) {
dumpInfoTask.reportSize(programSize);
dumpInfoTask.dumpInfo();
}
@@ -1141,7 +1013,7 @@
}
world.addToWorkList(main);
}
- if (verbose) {
+ if (options.verbose) {
progress.reset();
}
emptyQueue(world);
@@ -1261,7 +1133,7 @@
];
bool markCompilationAsFailed(DiagnosticMessage message, api.Diagnostic kind) {
- if (testMode) {
+ if (options.testMode) {
// When in test mode, i.e. on the build-bot, we always stop compilation.
return true;
}
@@ -1470,7 +1342,7 @@
EventSink<String> outputProvider(String name, String extension) {
if (compilationFailed) {
- if (!generateCodeWithCompileTimeErrors || testMode) {
+ if (!options.generateCodeWithCompileTimeErrors || options.testMode) {
// Disable output in test mode: The build bot currently uses the time
// stamp of the generated file to determine whether the output is
// up-to-date.
@@ -1978,7 +1850,7 @@
void pleaseReportCrash() {
print(
MessageTemplate.TEMPLATES[MessageKind.PLEASE_REPORT_THE_CRASH]
- .message({'buildId': compiler.buildId}));
+ .message({'buildId': compiler.options.buildId}));
}
/// Finds the approximate [Element] for [node]. [currentElement] is used as
@@ -2126,7 +1998,7 @@
assert(invariant(element, !element.isSynthesized || tree == null));
ResolutionImpact resolutionImpact =
compiler.resolver.resolve(element);
- if (tree != null && !compiler.analyzeSignaturesOnly) {
+ if (tree != null && !compiler.options.analyzeSignaturesOnly) {
// TODO(het): don't do this if suppressWarnings is on, currently we have
// to do it because the typechecker also sets types
// Only analyze nodes with a corresponding [TreeElements].
@@ -2141,6 +2013,7 @@
@override
void uncacheWorldImpact(Element element) {
+ if (compiler.serialization.isDeserialized(element)) return;
assert(invariant(element, _worldImpactCache[element] != null,
message: "WorldImpact not computed for $element."));
_worldImpactCache[element] = const WorldImpact();
@@ -2157,6 +2030,17 @@
bool hasBeenResolved(Element element) {
return _worldImpactCache.containsKey(element);
}
+
+ @override
+ ResolutionWorkItem createWorkItem(
+ Element element, ItemCompilationContext compilationContext) {
+ if (compiler.serialization.isDeserialized(element)) {
+ return compiler.serialization.createResolutionWorkItem(
+ element, compilationContext);
+ } else {
+ return new ResolutionWorkItem(element, compilationContext);
+ }
+ }
}
// TODO(johnniwinther): Move [ParserTask], [PatchParserTask], [DietParserTask]
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
index 6957274..e44b840 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart
@@ -1312,7 +1312,7 @@
/// This is also where we should add type checks in checked mode, but this
/// is not supported yet.
ir.Primitive checkType(ir.Primitive value, DartType dartType) {
- if (!compiler.trustTypeAnnotations) return value;
+ if (!compiler.options.trustTypeAnnotations) return value;
TypeMask type = typeMaskSystem.subtypesOf(dartType).nullable();
return irBuilder.addPrimitive(new ir.Refinement(value, type));
}
@@ -1368,7 +1368,7 @@
irBuilder.buildNativeFunctionBody(function, javaScriptCode,
sourceInformationBuilder.buildForeignCode(node));
} else {
- String name = backend.getFixedBackendName(function);
+ String name = backend.nativeData.getFixedBackendName(function);
irBuilder.buildRedirectingNativeFunctionBody(function, name, source);
}
} else {
@@ -1869,7 +1869,7 @@
@override
ir.Primitive visitAssert(ast.Assert node) {
assert(irBuilder.isOpen);
- if (compiler.enableUserAssertions) {
+ if (compiler.options.enableUserAssertions) {
return giveup(node, 'assert in checked mode not implemented');
} else {
// The call to assert and its argument expression must be ignored
@@ -3505,7 +3505,7 @@
value = backend.mustRetainMetadata;
break;
case 'USE_CONTENT_SECURITY_POLICY':
- value = compiler.useContentSecurityPolicy;
+ value = compiler.options.useContentSecurityPolicy;
break;
default:
internalError(node, 'Unknown internal flag "$name".');
@@ -4247,7 +4247,7 @@
}
bool get trustJSInteropTypeAnnotations =>
- _compiler.trustJSInteropTypeAnnotations;
+ _compiler.options.trustJSInteropTypeAnnotations;
bool isNative(ClassElement element) => _backend.isNative(element);
@@ -4258,7 +4258,7 @@
String getJsInteropTargetPath(FunctionElement element) {
return '${_backend.namer.fixedBackendPath(element)}.'
- '${_backend.getFixedBackendName(element)}';
+ '${_backend.nativeData.getFixedBackendName(element)}';
}
DartType get jsJavascriptObjectType =>
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index 41d33f9..3f982d1 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -1163,7 +1163,7 @@
return null;
}
- bool trustPrimitives = compiler.trustPrimitives;
+ bool trustPrimitives = compiler.options.trustPrimitives;
/// Check that the receiver and argument satisfy the given type checks, and
/// throw a [NoSuchMethodError] or [ArgumentError] if the check fails.
@@ -1486,7 +1486,7 @@
Primitive list,
Primitive index,
[int checkKind = BoundsCheck.BOTH_BOUNDS | BoundsCheck.INTEGER]) {
- if (compiler.trustPrimitives) {
+ if (compiler.options.trustPrimitives) {
return cps.letPrim(new BoundsCheck.noCheck(list, cps.sourceInformation));
} else {
GetLength length = cps.letPrim(new GetLength(list));
@@ -1547,7 +1547,7 @@
if (!typeSystem.isDefinitelyUint(newLength.type)) {
// TODO(asgerf): We could let the SetLength instruction throw for
// negative right-hand sides (see length setter in js_array.dart).
- if (compiler.trustPrimitives) {
+ if (compiler.options.trustPrimitives) {
newLength = cps.refine(newLength, typeSystem.uint32Type);
newLength.type = typeSystem.uint32Type;
} else {
diff --git a/pkg/compiler/lib/src/dart_backend/backend.dart b/pkg/compiler/lib/src/dart_backend/backend.dart
index 7d99b21..bb925f9 100644
--- a/pkg/compiler/lib/src/dart_backend/backend.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend.dart
@@ -111,7 +111,7 @@
compiler.reporter, compiler.outputProvider,
forceStripTypes: strips.indexOf('types') != -1,
multiFile: multiFile,
- enableMinification: compiler.enableMinification),
+ enableMinification: compiler.options.enableMinification),
super(compiler) {
impactTransformer = new DartImpactTransformer(this);
}
@@ -194,7 +194,7 @@
sortElements: Elements.sortedByPosition,
mirrorRenamer: mirrorRenamer,
mainFunction: compiler.mainFunction,
- outputUri: compiler.outputUri);
+ outputUri: compiler.options.outputUri);
// Output verbose info about size ratio of resulting bundle to all
// referenced non-platform sources.
diff --git a/pkg/compiler/lib/src/dart_backend/outputter.dart b/pkg/compiler/lib/src/dart_backend/outputter.dart
index 3e6f564..484bda2 100644
--- a/pkg/compiler/lib/src/dart_backend/outputter.dart
+++ b/pkg/compiler/lib/src/dart_backend/outputter.dart
@@ -511,7 +511,7 @@
? mainName.substring(0, mainName.length - 5)
: mainName;
// Map each library to a path based on the uri of the original
- // library and [compiler.outputUri].
+ // library and [compiler.options.outputUri].
Set<String> usedLibraryPaths = new Set<String>();
for (LibraryElement library in libraryInfo.userLibraries) {
if (library == mainFunction.library) {
@@ -602,4 +602,4 @@
return totalSize;
}
-}
\ No newline at end of file
+}
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index c24ecbf..81ffd69 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -346,7 +346,7 @@
collectTypeDependencies(type);
break;
case TypeUseKind.CHECKED_MODE_CHECK:
- if (compiler.enableTypeAssertions) {
+ if (compiler.options.enableTypeAssertions) {
collectTypeDependencies(type);
}
break;
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index d909a47..109cd312 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -431,7 +431,7 @@
}
void registerImpact(Element element, WorldImpact impact) {
- if (compiler.dumpInfo) {
+ if (compiler.options.dumpInfo) {
impacts[element] = impact;
}
}
@@ -470,7 +470,7 @@
// Returns true if we care about tracking the size of
// this node.
bool isTracking(jsAst.Node code) {
- if (compiler.dumpInfo) {
+ if (compiler.options.dumpInfo) {
return _tracking.contains(code);
} else {
return false;
@@ -480,7 +480,7 @@
// Registers that a javascript AST node `code` was produced by the
// dart Element `element`.
void registerElementAst(Element element, jsAst.Node code) {
- if (compiler.dumpInfo) {
+ if (compiler.options.dumpInfo) {
_elementToNodes
.putIfAbsent(element, () => new List<jsAst.Node>())
.add(code);
@@ -489,7 +489,7 @@
}
void registerConstantAst(ConstantValue constant, jsAst.Node code) {
- if (compiler.dumpInfo) {
+ if (compiler.options.dumpInfo) {
assert(_constantToNode[constant] == null ||
_constantToNode[constant] == code);
_constantToNode[constant] = code;
@@ -594,13 +594,14 @@
result.program = new ProgramInfo(
entrypoint: infoCollector._elementToInfo[compiler.mainFunction],
size: _programSize,
- dart2jsVersion: compiler.hasBuildId ? compiler.buildId : null,
+ dart2jsVersion:
+ compiler.options.hasBuildId ? compiler.options.buildId : null,
compilationMoment: new DateTime.now(),
compilationDuration: compiler.totalCompileTime.elapsed,
toJsonDuration: stopwatch.elapsedMilliseconds,
dumpInfoDuration: this.timing,
noSuchMethodEnabled: compiler.backend.enabledNoSuchMethod,
- minified: compiler.enableMinification);
+ minified: compiler.options.enableMinification);
ChunkedConversionSink<Object> sink = encoder.startChunkedConversion(
new StringConversionSink.fromStringSink(buffer));
diff --git a/pkg/compiler/lib/src/elements/common.dart b/pkg/compiler/lib/src/elements/common.dart
index 1e24ff0..5d5f9e6 100644
--- a/pkg/compiler/lib/src/elements/common.dart
+++ b/pkg/compiler/lib/src/elements/common.dart
@@ -123,6 +123,19 @@
Element get origin {
throw new UnsupportedError('origin is not supported on $this');
}
+
+ @override
+ ClassElement get contextClass {
+ ClassElement cls;
+ for (Element e = this; e != null; e = e.enclosingElement) {
+ if (e.isClass) {
+ // Record [e] instead of returning it directly. We need the last class
+ // in the chain since the first classes might be closure classes.
+ cls = e.declaration;
+ }
+ }
+ return cls;
+ }
}
abstract class LibraryElementCommon implements LibraryElement {
@@ -331,7 +344,7 @@
classElement.forEachBackendMember((e) => f(classElement, e));
}
if (includeInjectedMembers) {
- if (classElement.patch != null) {
+ if (classElement.isPatched) {
classElement.patch.forEachLocalMember((e) {
if (!e.isPatch) f(classElement, e);
});
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 121a882..cfc0dcb 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -208,18 +208,6 @@
return null;
}
- ClassElement get contextClass {
- ClassElement cls;
- for (Element e = this; e != null; e = e.enclosingElement) {
- if (e.isClass) {
- // Record [e] instead of returning it directly. We need the last class
- // in the chain since the first classes might be closure classes.
- cls = e.declaration;
- }
- }
- return cls;
- }
-
/**
* Creates the scope for this element.
*/
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 2c7403f..38c02bf 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -76,7 +76,7 @@
EnqueueTask(Compiler compiler)
: resolution = new ResolutionEnqueuer(
compiler, compiler.backend.createItemCompilationContext,
- compiler.analyzeOnly && compiler.analyzeMain
+ compiler.options.analyzeOnly && compiler.options.analyzeMain
? const EnqueuerStrategy() : const TreeShakingEnqueuerStrategy()),
codegen = new CodegenEnqueuer(
compiler, compiler.backend.createItemCompilationContext,
@@ -157,7 +157,7 @@
*/
void addToWorkList(Element element) {
assert(invariant(element, element.isDeclaration));
- if (internalAddToWorkList(element) && compiler.dumpInfo) {
+ if (internalAddToWorkList(element) && compiler.options.dumpInfo) {
// TODO(sigmund): add other missing dependencies (internals, selectors
// enqueued after allocations), also enable only for the codegen enqueuer.
compiler.dumpInfoTask.registerDependency(
@@ -663,7 +663,7 @@
_registerIsCheck(type);
break;
case TypeUseKind.CHECKED_MODE_CHECK:
- if (compiler.enableTypeAssertions) {
+ if (compiler.options.enableTypeAssertions) {
_registerIsCheck(type);
}
break;
@@ -803,14 +803,8 @@
compiler.world.registerUsedElement(element);
- ResolutionWorkItem workItem;
- if (compiler.serialization.isDeserialized(element)) {
- workItem = compiler.serialization.createResolutionWorkItem(
- element, itemCompilationContextCreator());
- } else {
- workItem = new ResolutionWorkItem(
- element, itemCompilationContextCreator());
- }
+ ResolutionWorkItem workItem = compiler.resolution.createWorkItem(
+ element, itemCompilationContextCreator());
queue.add(workItem);
// Enable isolate support if we start using something from the isolate
@@ -942,13 +936,13 @@
// Codegen inlines field initializers. It only needs to generate
// code for checked setters.
if (element.isField && element.isInstanceMember) {
- if (!compiler.enableTypeAssertions
+ if (!compiler.options.enableTypeAssertions
|| element.enclosingElement.isClosure) {
return false;
}
}
- if (compiler.hasIncrementalSupport && !isProcessed(element)) {
+ if (compiler.options.hasIncrementalSupport && !isProcessed(element)) {
newlyEnqueuedElements.add(element);
}
@@ -986,7 +980,7 @@
}
void handleUnseenSelector(DynamicUse dynamicUse) {
- if (compiler.hasIncrementalSupport) {
+ if (compiler.options.hasIncrementalSupport) {
newlySeenSelectors.add(dynamicUse);
}
super.handleUnseenSelector(dynamicUse);
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
index fbb7880..85a81bc 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_visitor.dart
@@ -466,7 +466,8 @@
void update(LocalElement local, T type, Node node) {
assert(type != null);
- if (compiler.trustTypeAnnotations || compiler.enableTypeAssertions) {
+ if (compiler.options.trustTypeAnnotations ||
+ compiler.options.enableTypeAssertions) {
type = types.narrowType(type, local.type);
}
updateLocal() {
@@ -779,7 +780,7 @@
T visitAssert(Assert node) {
// Avoid pollution from assert statement unless enabled.
- if (compiler.enableUserAssertions) {
+ if (compiler.options.enableUserAssertions) {
super.visitAssert(node);
}
return null;
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index 14d904a..f12a8b4 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -709,7 +709,7 @@
void runOverAllElements() {
if (compiler.disableTypeInference) return;
- if (compiler.verbose) {
+ if (compiler.options.verbose) {
compiler.progress.reset();
}
sortResolvedElements().forEach((Element element) {
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index e549d68..0ed437c 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -515,8 +515,8 @@
TypeMask potentiallyNarrowType(TypeMask mask,
TypeGraphInferrerEngine inferrer) {
Compiler compiler = inferrer.compiler;
- if (!compiler.trustTypeAnnotations &&
- !compiler.enableTypeAssertions &&
+ if (!compiler.options.trustTypeAnnotations &&
+ !compiler.options.enableTypeAssertions &&
!inferrer.annotations.trustTypeAnnotations(element)) {
return mask;
}
@@ -664,14 +664,14 @@
TypeMask potentiallyNarrowType(TypeMask mask,
TypeGraphInferrerEngine inferrer) {
Compiler compiler = inferrer.compiler;
- if (!compiler.trustTypeAnnotations &&
+ if (!compiler.options.trustTypeAnnotations &&
!inferrer.annotations.trustTypeAnnotations(declaration)) {
return mask;
}
// When type assertions are enabled (aka checked mode), we have to always
// ignore type annotations to ensure that the checks are actually inserted
// into the function body and retained until runtime.
- assert(!compiler.enableTypeAssertions);
+ assert(!compiler.options.enableTypeAssertions);
return _narrowType(compiler, mask, element.type);
}
diff --git a/pkg/compiler/lib/src/js/js.dart b/pkg/compiler/lib/src/js/js.dart
index df510a8..837b9fe 100644
--- a/pkg/compiler/lib/src/js/js.dart
+++ b/pkg/compiler/lib/src/js/js.dart
@@ -27,7 +27,7 @@
Renamer renamerForNames: JavaScriptPrintingOptions.identityRenamer}) {
// TODO(johnniwinther): Do we need all the options here?
JavaScriptPrintingOptions options = new JavaScriptPrintingOptions(
- shouldCompressOutput: compiler.enableMinification,
+ shouldCompressOutput: compiler.options.enableMinification,
minifyLocalVariables: allowVariableMinification,
preferSemicolonToNewlineInMinifiedOutput: USE_LAZY_EMITTER,
renamerForNames: renamerForNames);
@@ -47,7 +47,7 @@
JavaScriptSourceInformationStrategy sourceInformationFactory =
compiler.backend.sourceInformationStrategy;
JavaScriptPrintingOptions options = new JavaScriptPrintingOptions(
- shouldCompressOutput: compiler.enableMinification,
+ shouldCompressOutput: compiler.options.enableMinification,
minifyLocalVariables: allowVariableMinification,
preferSemicolonToNewlineInMinifiedOutput: USE_LAZY_EMITTER,
renamerForNames: renamerForNames);
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 1d8a35a..f8afee0 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -504,6 +504,10 @@
SourceInformationStrategy sourceInformationStrategy;
+ JavaScriptBackendSerialization serialization;
+
+ final NativeData nativeData = new NativeData();
+
final BackendHelpers helpers;
final BackendImpacts impacts;
@@ -538,10 +542,11 @@
constantCompilerTask = new JavaScriptConstantTask(compiler);
impactTransformer = new JavaScriptImpactTransformer(this);
patchResolverTask = new PatchResolverTask(compiler);
- functionCompiler = compiler.useCpsIr
+ functionCompiler = compiler.options.useCpsIr
? new CpsFunctionCompiler(
compiler, this, sourceInformationStrategy)
: new SsaFunctionCompiler(this, sourceInformationStrategy);
+ serialization = new JavaScriptBackendSerialization(this);
}
ConstantSystem get constantSystem => constants.constantSystem;
@@ -585,8 +590,8 @@
}
static Namer determineNamer(Compiler compiler) {
- return compiler.enableMinification ?
- compiler.useFrequencyNamer ?
+ return compiler.options.enableMinification ?
+ compiler.options.useFrequencyNamer ?
new FrequencyBasedNamer(compiler) :
new MinifyNamer(compiler) :
new Namer(compiler);
@@ -600,44 +605,50 @@
// TODO(johnniwinther): Replace this with a more precise modelling; type
// inference of these elements is disabled.
Element registerBackendUse(Element element) {
- if (element != null) {
- bool registerUse = false;
- if (element == helpers.streamIteratorConstructor ||
- element == helpers.compiler.symbolConstructor ||
- element == helpers.compiler.symbolValidatedConstructor ||
- element == helpers.syncCompleterConstructor ||
- element == coreClasses.symbolClass ||
- element == helpers.objectNoSuchMethod) {
- // TODO(johnniwinther): These are valid but we could be more precise.
- registerUse = true;
- } else if (element.implementationLibrary.isPatch ||
- element.library == helpers.jsHelperLibrary ||
- element.library == helpers.interceptorsLibrary ||
- element.library == helpers.isolateHelperLibrary) {
- // TODO(johnniwinther): We should be more precise about these.
- registerUse = true;
- } else if (element == coreClasses.listClass ||
- element == helpers.mapLiteralClass ||
- element == coreClasses.functionClass ||
- element == coreClasses.stringClass) {
- // TODO(johnniwinther): Avoid these.
- registerUse = true;
- }
- if (!registerUse) {
- assert(invariant(element, false,
- message: "Backend use of $element is not allowed."));
- return element;
- }
- helpersUsed.add(element.declaration);
- if (element.isClass && element.isPatched) {
- // Both declaration and implementation may declare fields, so we
- // add both to the list of helpers.
- helpersUsed.add(element.implementation);
- }
+ if (element == null) return null;
+ assert(invariant(element, _isValidBackendUse(element),
+ message: "Backend use of $element is not allowed."));
+ helpersUsed.add(element.declaration);
+ if (element.isClass && element.isPatched) {
+ // Both declaration and implementation may declare fields, so we
+ // add both to the list of helpers.
+ helpersUsed.add(element.implementation);
}
return element;
}
+ bool _isValidBackendUse(Element element) {
+ assert(invariant(element, element.isDeclaration,
+ message: ""));
+ if (element == helpers.streamIteratorConstructor ||
+ element == helpers.compiler.symbolConstructor ||
+ element == helpers.compiler.symbolValidatedConstructor ||
+ element == helpers.syncCompleterConstructor ||
+ element == coreClasses.symbolClass ||
+ element == helpers.objectNoSuchMethod) {
+ // TODO(johnniwinther): These are valid but we could be more precise.
+ return true;
+ } else if (element.implementationLibrary.isPatch ||
+ // Needed to detect deserialized injected elements, that is
+ // element declared in patch files.
+ (element.library.isPlatformLibrary &&
+ element.sourcePosition.uri.path.contains(
+ '_internal/js_runtime/lib/')) ||
+ element.library == helpers.jsHelperLibrary ||
+ element.library == helpers.interceptorsLibrary ||
+ element.library == helpers.isolateHelperLibrary) {
+ // TODO(johnniwinther): We should be more precise about these.
+ return true;
+ } else if (element == coreClasses.listClass ||
+ element == helpers.mapLiteralClass ||
+ element == coreClasses.functionClass ||
+ element == coreClasses.stringClass) {
+ // TODO(johnniwinther): Avoid these.
+ return true;
+ }
+ return false;
+ }
+
bool usedByBackend(Element element) {
if (element.isParameter
|| element.isInitializingFormal
@@ -702,7 +713,7 @@
}
bool canUseAliasedSuperMember(Element member, Selector selector) {
- return !selector.isGetter && !compiler.hasIncrementalSupport;
+ return !selector.isGetter && !compiler.options.hasIncrementalSupport;
}
/**
@@ -712,161 +723,16 @@
return aliasedSuperMembers.contains(member);
}
- /// The JavaScript names for elements implemented via typed JavaScript
- /// interop.
- Map<Element, String> jsInteropNames = <Element, String>{};
-
- /// The JavaScript names for native JavaScript elements implemented.
- Map<Element, String> nativeMemberName = <Element, String>{};
-
- /// Tag info for native JavaScript classes names. See
- /// [setNativeClassTagInfo].
- Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{};
-
- /// Returns `true` if [element] is explicitly marked as part of JsInterop.
- bool _isJsInterop(Element element) {
- return jsInteropNames.containsKey(element.declaration);
- }
-
- /// Returns [element] as an explicit part of JsInterop. The js interop name is
- /// expected to be computed later.
- void markAsJsInterop(Element element) {
- jsInteropNames[element.declaration] = null;
- }
-
- /// Sets the explicit js interop [name] for [element].
- void setJsInteropName(Element element, String name) {
- assert(invariant(element,
- isJsInterop(element),
- message:
- 'Element $element is not js interop but given a js interop name.'));
- jsInteropNames[element.declaration] = name;
- }
-
- /// Returns the explicit js interop name for [element].
- String getJsInteropName(Element element) {
- return jsInteropNames[element.declaration];
- }
-
/// Returns `true` if [element] is part of JsInterop.
@override
- bool isJsInterop(Element element) {
- // An function is part of JsInterop in the following cases:
- // * It has a jsInteropName annotation
- // * It is external member of a class or library tagged as JsInterop.
- if (element.isFunction || element.isConstructor || element.isAccessor) {
- FunctionElement function = element;
- if (!function.isExternal) return false;
-
- if (_isJsInterop(function)) return true;
- if (function.isClassMember) return isJsInterop(function.contextClass);
- if (function.isTopLevel) return isJsInterop(function.library);
- return false;
- } else {
- return _isJsInterop(element);
- }
- }
-
- /// Returns `true` if the name of [element] is fixed for the generated
- /// JavaScript.
- bool hasFixedBackendName(Element element) {
- return isJsInterop(element) ||
- nativeMemberName.containsKey(element.declaration);
- }
-
- String _jsNameHelper(Element element) {
- String jsInteropName = jsInteropNames[element.declaration];
- assert(invariant(element,
- !(_isJsInterop(element) && jsInteropName == null),
- message:
- 'Element $element is js interop but js interop name has not yet '
- 'been computed.'));
- if (jsInteropName != null && jsInteropName.isNotEmpty) {
- return jsInteropName;
- }
- return element.isLibrary ? 'self' : element.name;
- }
-
- /// Computes the name for [element] to use in the generated JavaScript. This
- /// is either given through a native annotation or a js interop annotation.
- String getFixedBackendName(Element element) {
- String name = nativeMemberName[element.declaration];
- if (name == null && isJsInterop(element)) {
- // If an element isJsInterop but _isJsInterop is false that means it is
- // considered interop as the parent class is interop.
- name = _jsNameHelper(
- element.isConstructor ? element.enclosingClass : element);
- nativeMemberName[element.declaration] = name;
- }
- return name;
- }
+ bool isJsInterop(Element element) => nativeData.isJsInterop(element);
/// Whether [element] corresponds to a native JavaScript construct either
/// through the native mechanism (`@Native(...)` or the `native` pseudo
/// keyword) which is only allowed for internal libraries or via the typed
/// JavaScriptInterop mechanism which is allowed for user libraries.
@override
- bool isNative(Element element) {
- if (isJsInterop(element)) return true;
- if (element.isClass) {
- return nativeClassTagInfo.containsKey(element.declaration);
- } else {
- return nativeMemberName.containsKey(element.declaration);
- }
- }
-
- /// Sets the native [name] for the member [element]. This name is used for
- /// [element] in the generated JavaScript.
- void setNativeMemberName(MemberElement element, String name) {
- // TODO(johnniwinther): Avoid setting this more than once. The enqueuer
- // might enqueue [element] several times (before processing it) and computes
- // name on each call to `internalAddToWorkList`.
- assert(invariant(element,
- nativeMemberName[element.declaration] == null ||
- nativeMemberName[element.declaration] == name,
- message:
- "Native member name set inconsistently on $element: "
- "Existing name '${nativeMemberName[element.declaration]}', "
- "new name '$name'."));
- nativeMemberName[element.declaration] = name;
- }
-
- /// Sets the native tag info for [cls].
- ///
- /// The tag info string contains comma-separated 'words' which are either
- /// dispatch tags (having JavaScript identifier syntax) and directives that
- /// begin with `!`.
- void setNativeClassTagInfo(ClassElement cls, String tagInfo) {
- // TODO(johnniwinther): Assert that this is only called once. The memory
- // compiler copies pre-processed elements into a new compiler through
- // [Compiler.onLibraryScanned] and thereby causes multiple calls to this
- // method.
- assert(invariant(cls,
- nativeClassTagInfo[cls.declaration] == null ||
- nativeClassTagInfo[cls.declaration] == tagInfo,
- message:
- "Native tag info set inconsistently on $cls: "
- "Existing tag info '${nativeClassTagInfo[cls.declaration]}', "
- "new tag info '$tagInfo'."));
- nativeClassTagInfo[cls.declaration] = tagInfo;
- }
-
- /// Returns the list of native tag words for [cls].
- List<String> getNativeTagsOfClassRaw(ClassElement cls) {
- String quotedName = nativeClassTagInfo[cls.declaration];
- return quotedName.substring(1, quotedName.length - 1).split(',');
- }
-
- /// Returns the list of non-directive native tag words for [cls].
- List<String> getNativeTagsOfClass(ClassElement cls) {
- return getNativeTagsOfClassRaw(cls).where(
- (s) => !s.startsWith('!')).toList();
- }
-
- /// Returns `true` if [cls] has a `!nonleaf` tag word.
- bool hasNativeTagsForcedNonLeaf(ClassElement cls) {
- return getNativeTagsOfClassRaw(cls).contains('!nonleaf');
- }
+ bool isNative(Element element) => nativeData.isNative(element);
bool isNativeOrExtendsNative(ClassElement element) {
if (element == null) return false;
@@ -1009,7 +875,13 @@
Element interceptorMember = interceptorClass.lookupMember(member.name);
// Interceptors must override all Object methods due to calling convention
// differences.
- assert(interceptorMember.enclosingClass == interceptorClass);
+ assert(invariant(
+ interceptorMember,
+ interceptorMember.enclosingClass == interceptorClass,
+ message:
+ "Member ${member.name} not overridden in ${interceptorClass}. "
+ "Found $interceptorMember from "
+ "${interceptorMember.enclosingClass}."));
});
}
@@ -1209,7 +1081,7 @@
Element getFactory(String name, int arity) {
// The constructor is on the patch class, but dart2js unit tests don't
// have a patch class.
- ClassElement implementation = cls.patch != null ? cls.patch : cls;
+ ClassElement implementation = cls.implementation;
ConstructorElement ctor = implementation.lookupConstructor(name);
if (ctor == null ||
(Name.isPrivateName(name) &&
@@ -1225,7 +1097,7 @@
Element getMember(String name) {
// The constructor is on the patch class, but dart2js unit tests don't
// have a patch class.
- ClassElement implementation = cls.patch != null ? cls.patch : cls;
+ ClassElement implementation = cls.implementation;
Element element = implementation.lookupLocalMember(name);
if (element == null || !element.isFunction || !element.isStatic) {
reporter.internalError(helpers.mapLiteralClass,
@@ -1345,7 +1217,7 @@
// will instantiate those two classes.
addInterceptors(helpers.jsBoolClass, world, registry);
addInterceptors(helpers.jsNullClass, world, registry);
- if (compiler.enableTypeAssertions) {
+ if (compiler.options.enableTypeAssertions) {
// Unconditionally register the helper that checks if the
// expression in an if/while/for is a boolean.
// TODO(ngeoffray): Should we have the resolver register those instead?
@@ -1944,14 +1816,13 @@
void registerStaticUse(Element element, Enqueuer enqueuer) {
if (element == helpers.disableTreeShakingMarker) {
- compiler.disableTypeInferenceForMirrors = true;
isTreeShakingDisabled = true;
} else if (element == helpers.preserveNamesMarker) {
mustPreserveNames = true;
} else if (element == helpers.preserveMetadataMarker) {
mustRetainMetadata = true;
} else if (element == helpers.preserveUrisMarker) {
- if (compiler.preserveUris) mustPreserveUris = true;
+ if (compiler.options.preserveUris) mustPreserveUris = true;
} else if (element == helpers.preserveLibraryNamesMarker) {
mustRetainLibraryNames = true;
} else if (element == helpers.getIsolateAffinityTagMarker) {
@@ -2394,7 +2265,7 @@
enabledNoSuchMethod = true;
}
- if (compiler.hasIncrementalSupport) {
+ if (compiler.options.hasIncrementalSupport) {
// Always enable tear-off closures during incremental compilation.
Element e = helpers.closureFromTearOff;
if (e != null && !enqueuer.isProcessed(e)) {
@@ -2561,8 +2432,8 @@
/// If [addExtension] is false, the ".part.js" suffix is left out.
String deferredPartFileName(String name, {bool addExtension: true}) {
assert(name != "");
- String outPath = compiler.outputUri != null
- ? compiler.outputUri.path
+ String outPath = compiler.options.outputUri != null
+ ? compiler.options.outputUri.path
: "out";
String outName = outPath.substring(outPath.lastIndexOf('/') + 1);
String extension = addExtension ? ".part.js" : "";
@@ -2577,7 +2448,7 @@
@override
bool enableCodegenWithErrorsIfSupported(Spannable node) {
- if (compiler.useCpsIr) {
+ if (compiler.options.useCpsIr) {
// TODO(25747): Support code generation with compile-time errors.
reporter.reportHintMessage(
node,
@@ -2673,12 +2544,14 @@
@override
ImpactStrategy createImpactStrategy(
{bool supportDeferredLoad: true,
- bool supportDumpInfo: true}) {
+ bool supportDumpInfo: true,
+ bool supportSerialization: true}) {
return new JavaScriptImpactStrategy(
resolution,
compiler.dumpInfoTask,
supportDeferredLoad: supportDeferredLoad,
- supportDumpInfo: supportDumpInfo);
+ supportDumpInfo: supportDumpInfo,
+ supportSerialization: supportSerialization);
}
}
@@ -2792,7 +2665,7 @@
registerBackendImpact(transformed, impacts.catchStatement);
break;
case Feature.COMPILE_TIME_ERROR:
- if (backend.compiler.generateCodeWithCompileTimeErrors) {
+ if (backend.compiler.options.generateCodeWithCompileTimeErrors) {
// TODO(johnniwinther): This should have its own uncatchable error.
registerBackendImpact(transformed, impacts.throwRuntimeError);
}
@@ -2858,7 +2731,7 @@
hasAsCast = true;
break;
case TypeUseKind.CHECKED_MODE_CHECK:
- if (backend.compiler.enableTypeAssertions) {
+ if (backend.compiler.options.enableTypeAssertions) {
onIsCheck(type, transformed);
}
break;
@@ -3000,7 +2873,7 @@
type = type.unaliased;
registerBackendImpact(transformed, impacts.typeCheck);
- bool inCheckedMode = backend.compiler.enableTypeAssertions;
+ bool inCheckedMode = backend.compiler.options.enableTypeAssertions;
if (inCheckedMode) {
registerBackendImpact(transformed, impacts.checkedModeTypeCheck);
}
@@ -3032,7 +2905,7 @@
type = type.unaliased;
registerBackendImpact(transformed, impacts.typeCheck);
- bool inCheckedMode = backend.compiler.enableTypeAssertions;
+ bool inCheckedMode = backend.compiler.options.enableTypeAssertions;
// [registerIsCheck] is also called for checked mode checks, so we
// need to register checked mode helpers.
if (inCheckedMode) {
@@ -3154,11 +3027,13 @@
final DumpInfoTask dumpInfoTask;
final bool supportDeferredLoad;
final bool supportDumpInfo;
+ final bool supportSerialization;
JavaScriptImpactStrategy(this.resolution,
this.dumpInfoTask,
{this.supportDeferredLoad,
- this.supportDumpInfo});
+ this.supportDumpInfo,
+ this.supportSerialization});
@override
void visitImpact(Element element,
@@ -3167,7 +3042,7 @@
ImpactUseCase impactUse) {
// TODO(johnniwinther): Compute the application strategy once for each use.
if (impactUse == ResolutionEnqueuer.IMPACT_USE) {
- if (supportDeferredLoad) {
+ if (supportDeferredLoad || supportSerialization) {
impact.apply(visitor);
} else {
impact.apply(visitor);
@@ -3186,7 +3061,10 @@
@override
void onImpactUsed(ImpactUseCase impactUse) {
- if (impactUse == DeferredLoadTask.IMPACT_USE) {
+ if (impactUse == DeferredLoadTask.IMPACT_USE &&
+ !supportSerialization) {
+ // TODO(johnniwinther): Allow emptying when serialization has been
+ // performed.
resolution.emptyCache();
}
}
diff --git a/pkg/compiler/lib/src/js_backend/backend_serialization.dart b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
new file mode 100644
index 0000000..8a4923f
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/backend_serialization.dart
@@ -0,0 +1,60 @@
+// 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 js_backend.serialization;
+
+import '../common/backend_api.dart' show
+ BackendSerialization;
+import '../elements/elements.dart';
+import '../serialization/serialization.dart' show
+ DeserializerPlugin,
+ ObjectDecoder,
+ ObjectEncoder,
+ SerializerPlugin;
+import '../serialization/keys.dart';
+import 'js_backend.dart';
+
+const String _BACKEND_DATA_TAG = 'jsBackendData';
+
+class JavaScriptBackendSerialization implements BackendSerialization {
+ final JavaScriptBackendSerializer serializer;
+ final JavaScriptBackendDeserializer deserializer;
+
+ JavaScriptBackendSerialization(JavaScriptBackend backend)
+ : serializer = new JavaScriptBackendSerializer(backend),
+ deserializer = new JavaScriptBackendDeserializer(backend);
+}
+
+class JavaScriptBackendSerializer implements SerializerPlugin {
+ final JavaScriptBackend backend;
+
+ JavaScriptBackendSerializer(this.backend);
+
+ @override
+ void onElement(Element element, ObjectEncoder createEncoder(String tag)) {
+ // TODO(johnniwinther): Add more data, e.g. js-interop names, native tags,
+ // etc.
+ String nativeName = backend.nativeData.nativeMemberName[element];
+ if (nativeName != null) {
+ ObjectEncoder encoder = createEncoder(_BACKEND_DATA_TAG);
+ encoder.setString(Key.NAME, nativeName);
+ }
+ }
+}
+
+class JavaScriptBackendDeserializer implements DeserializerPlugin {
+ final JavaScriptBackend backend;
+
+ JavaScriptBackendDeserializer(this.backend);
+
+ @override
+ void onElement(Element element, ObjectDecoder getDecoder(String tag)) {
+ ObjectDecoder decoder = getDecoder(_BACKEND_DATA_TAG);
+ if (decoder != null) {
+ String nativeName = decoder.getString(Key.NAME);
+ backend.nativeData.nativeMemberName[element] = nativeName;
+ }
+ }
+}
+
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index 89b9aab..853554f 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -322,7 +322,8 @@
treeOptimizationTask.measure(() {
applyTreePass(new StatementRewriter());
- applyTreePass(new VariableMerger(minifying: compiler.enableMinification));
+ applyTreePass(new VariableMerger(minifying:
+ compiler.options.enableMinification));
applyTreePass(new LoopRewriter());
applyTreePass(new LogicalRewriter());
applyTreePass(new PullIntoInitializers());
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 0550d8d..9bb1417 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -105,7 +105,7 @@
// digits are lost anyway.
String representation = primitiveValue.toString();
String alternative = null;
- int cutoff = compiler.enableMinification ? 10000 : 1e10.toInt();
+ int cutoff = compiler.options.enableMinification ? 10000 : 1e10.toInt();
if (primitiveValue.abs() >= cutoff) {
alternative = _shortenExponentialRepresentation(
primitiveValue.toStringAsExponential());
@@ -133,7 +133,7 @@
@override
jsAst.Expression visitBool(BoolConstantValue constant, [_]) {
- if (compiler.enableMinification) {
+ if (compiler.options.enableMinification) {
if (constant.isTrue) {
// Use !0 for true.
return js("!0");
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 0a89b42..c821aea 100644
--- a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
+++ b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
@@ -14,8 +14,9 @@
// this could be because the field belongs to a mixin. In such a case this
// will return `null` and a normal field name has to be used.
jsAst.Name _minifiedInstanceFieldPropertyName(Element element) {
- if (backend.hasFixedBackendName(element)) {
- return new StringBackedName(backend.getFixedBackendName(element));
+ if (backend.nativeData.hasFixedBackendName(element)) {
+ return new StringBackedName(
+ backend.nativeData.getFixedBackendName(element));
}
_FieldNamingScope names;
diff --git a/pkg/compiler/lib/src/js_backend/js_backend.dart b/pkg/compiler/lib/src/js_backend/js_backend.dart
index 9a482f0..2704c0a 100644
--- a/pkg/compiler/lib/src/js_backend/js_backend.dart
+++ b/pkg/compiler/lib/src/js_backend/js_backend.dart
@@ -14,6 +14,7 @@
import '../common.dart';
import '../common/backend_api.dart' show
Backend,
+ BackendSerialization,
ImpactTransformer,
ForeignResolver;
import '../common/codegen.dart' show
@@ -116,11 +117,15 @@
import 'backend_helpers.dart';
import 'backend_impact.dart';
+import 'backend_serialization.dart' show
+ JavaScriptBackendSerialization;
import 'codegen/task.dart';
import 'constant_system_javascript.dart';
-import 'patch_resolver.dart';
+import 'native_data.dart' show
+ NativeData;
import 'js_interop_analysis.dart' show JsInteropAnalysis;
import 'lookup_map_analysis.dart' show LookupMapAnalysis;
+import 'patch_resolver.dart';
part 'backend.dart';
part 'checked_mode_helpers.dart';
diff --git a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
index fc96572..1ba5398 100644
--- a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
@@ -70,11 +70,11 @@
ConstantValue value = constructedConstant.fields[nameField];
if (value.isString) {
StringConstantValue stringValue = value;
- backend.setJsInteropName(
+ backend.nativeData.setJsInteropName(
e, stringValue.primitiveValue.slowToString());
} else {
// TODO(jacobr): report a warning if the value is not a String.
- backend.setJsInteropName(e, '');
+ backend.nativeData.setJsInteropName(e, '');
}
enabledJsInterop = true;
return;
@@ -179,7 +179,7 @@
if (selector.namedArgumentCount > 0) return;
int argumentCount = selector.argumentCount;
var candidateParameterNames =
- 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMOPQRSTUVWXYZ';
+ 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
var parameters = new List<String>.generate(
argumentCount, (i) => candidateParameterNames[i]);
diff --git a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
index 111eb22..ca97a3a 100644
--- a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
@@ -307,7 +307,7 @@
// When --verbose is passed, we show the total number and set of keys that
// were tree-shaken from lookup maps.
Compiler compiler = backend.compiler;
- if (compiler.verbose) {
+ if (compiler.options.verbose) {
var sb = new StringBuffer();
int count = 0;
for (var info in _lookupMaps.values) {
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index bd55710..7ffe502 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -624,7 +624,7 @@
}
String _jsNameHelper(Element e) {
- String jsInteropName = backend.getJsInteropName(e);
+ String jsInteropName = backend.nativeData.getJsInteropName(e);
if (jsInteropName != null && jsInteropName.isNotEmpty)
return jsInteropName;
return e.isLibrary ? 'self' : e.name;
@@ -779,8 +779,9 @@
jsAst.Name instanceFieldPropertyName(FieldElement element) {
ClassElement enclosingClass = element.enclosingClass;
- if (backend.hasFixedBackendName(element)) {
- return new StringBackedName(backend.getFixedBackendName(element));
+ if (backend.nativeData.hasFixedBackendName(element)) {
+ return new StringBackedName(
+ backend.nativeData.getFixedBackendName(element));
}
// Some elements, like e.g. instances of BoxFieldElement are special.
diff --git a/pkg/compiler/lib/src/js_backend/native_data.dart b/pkg/compiler/lib/src/js_backend/native_data.dart
new file mode 100644
index 0000000..1929548
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/native_data.dart
@@ -0,0 +1,170 @@
+// 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 js_backend.native_data;
+
+import '../common.dart';
+import '../elements/elements.dart' show
+ ClassElement,
+ Element,
+ FunctionElement,
+ MemberElement;
+
+/// Additional element information for native classes and methods and js-interop
+/// methods.
+class NativeData {
+ /// The JavaScript names for elements implemented via typed JavaScript
+ /// interop.
+ Map<Element, String> jsInteropNames = <Element, String>{};
+
+ /// The JavaScript names for native JavaScript elements implemented.
+ Map<Element, String> nativeMemberName = <Element, String>{};
+
+ /// Tag info for native JavaScript classes names. See
+ /// [setNativeClassTagInfo].
+ Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{};
+
+ /// Returns `true` if [element] is explicitly marked as part of JsInterop.
+ bool _isJsInterop(Element element) {
+ return jsInteropNames.containsKey(element.declaration);
+ }
+
+ /// Returns [element] as an explicit part of JsInterop. The js interop name is
+ /// expected to be computed later.
+ void markAsJsInterop(Element element) {
+ jsInteropNames[element.declaration] = null;
+ }
+
+ /// Sets the explicit js interop [name] for [element].
+ void setJsInteropName(Element element, String name) {
+ assert(invariant(element,
+ isJsInterop(element),
+ message:
+ 'Element $element is not js interop but given a js interop name.'));
+ jsInteropNames[element.declaration] = name;
+ }
+
+ /// Returns the explicit js interop name for [element].
+ String getJsInteropName(Element element) {
+ return jsInteropNames[element.declaration];
+ }
+
+ /// Returns `true` if [element] is part of JsInterop.
+ bool isJsInterop(Element element) {
+ // An function is part of JsInterop in the following cases:
+ // * It has a jsInteropName annotation
+ // * It is external member of a class or library tagged as JsInterop.
+ if (element.isFunction || element.isConstructor || element.isAccessor) {
+ FunctionElement function = element;
+ if (!function.isExternal) return false;
+
+ if (_isJsInterop(function)) return true;
+ if (function.isClassMember) return isJsInterop(function.contextClass);
+ if (function.isTopLevel) return isJsInterop(function.library);
+ return false;
+ } else {
+ return _isJsInterop(element);
+ }
+ }
+
+ /// Returns `true` if the name of [element] is fixed for the generated
+ /// JavaScript.
+ bool hasFixedBackendName(Element element) {
+ return isJsInterop(element) ||
+ nativeMemberName.containsKey(element.declaration);
+ }
+
+ String _jsNameHelper(Element element) {
+ String jsInteropName = jsInteropNames[element.declaration];
+ assert(invariant(element,
+ !(_isJsInterop(element) && jsInteropName == null),
+ message:
+ 'Element $element is js interop but js interop name has not yet '
+ 'been computed.'));
+ if (jsInteropName != null && jsInteropName.isNotEmpty) {
+ return jsInteropName;
+ }
+ return element.isLibrary ? 'self' : element.name;
+ }
+
+ /// Computes the name for [element] to use in the generated JavaScript. This
+ /// is either given through a native annotation or a js interop annotation.
+ String getFixedBackendName(Element element) {
+ String name = nativeMemberName[element.declaration];
+ if (name == null && isJsInterop(element)) {
+ // If an element isJsInterop but _isJsInterop is false that means it is
+ // considered interop as the parent class is interop.
+ name = _jsNameHelper(
+ element.isConstructor ? element.enclosingClass : element);
+ nativeMemberName[element.declaration] = name;
+ }
+ return name;
+ }
+
+ /// Whether [element] corresponds to a native JavaScript construct either
+ /// through the native mechanism (`@Native(...)` or the `native` pseudo
+ /// keyword) which is only allowed for internal libraries or via the typed
+ /// JavaScriptInterop mechanism which is allowed for user libraries.
+ bool isNative(Element element) {
+ if (isJsInterop(element)) return true;
+ if (element.isClass) {
+ return nativeClassTagInfo.containsKey(element.declaration);
+ } else {
+ return nativeMemberName.containsKey(element.declaration);
+ }
+ }
+
+ /// Sets the native [name] for the member [element]. This name is used for
+ /// [element] in the generated JavaScript.
+ void setNativeMemberName(MemberElement element, String name) {
+ // TODO(johnniwinther): Avoid setting this more than once. The enqueuer
+ // might enqueue [element] several times (before processing it) and computes
+ // name on each call to `internalAddToWorkList`.
+ assert(invariant(element,
+ nativeMemberName[element.declaration] == null ||
+ nativeMemberName[element.declaration] == name,
+ message:
+ "Native member name set inconsistently on $element: "
+ "Existing name '${nativeMemberName[element.declaration]}', "
+ "new name '$name'."));
+ nativeMemberName[element.declaration] = name;
+ }
+
+ /// Sets the native tag info for [cls].
+ ///
+ /// The tag info string contains comma-separated 'words' which are either
+ /// dispatch tags (having JavaScript identifier syntax) and directives that
+ /// begin with `!`.
+ void setNativeClassTagInfo(ClassElement cls, String tagInfo) {
+ // TODO(johnniwinther): Assert that this is only called once. The memory
+ // compiler copies pre-processed elements into a new compiler through
+ // [Compiler.onLibraryScanned] and thereby causes multiple calls to this
+ // method.
+ assert(invariant(cls,
+ nativeClassTagInfo[cls.declaration] == null ||
+ nativeClassTagInfo[cls.declaration] == tagInfo,
+ message:
+ "Native tag info set inconsistently on $cls: "
+ "Existing tag info '${nativeClassTagInfo[cls.declaration]}', "
+ "new tag info '$tagInfo'."));
+ nativeClassTagInfo[cls.declaration] = tagInfo;
+ }
+
+ /// Returns the list of native tag words for [cls].
+ List<String> getNativeTagsOfClassRaw(ClassElement cls) {
+ String quotedName = nativeClassTagInfo[cls.declaration];
+ return quotedName.substring(1, quotedName.length - 1).split(',');
+ }
+
+ /// Returns the list of non-directive native tag words for [cls].
+ List<String> getNativeTagsOfClass(ClassElement cls) {
+ return getNativeTagsOfClassRaw(cls).where(
+ (s) => !s.startsWith('!')).toList();
+ }
+
+ /// Returns `true` if [cls] has a `!nonleaf` tag word.
+ bool hasNativeTagsForcedNonLeaf(ClassElement cls) {
+ return getNativeTagsOfClassRaw(cls).contains('!nonleaf');
+ }
+}
\ No newline at end of file
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index bcede45..29aade6 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -300,7 +300,7 @@
}
}
});
- if (compiler.enableTypeAssertions) {
+ if (compiler.options.enableTypeAssertions) {
void analyzeMethod(TypedElement method) {
DartType memberType = method.type;
ClassElement contextClass = Types.getClassContext(memberType);
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index 87f9d41..c727d56 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -169,7 +169,7 @@
backend.emitter.staticFunctionAccess(
backend.helpers.createInvocationMirror),
'methodName':
- js.quoteName(compiler.enableMinification
+ js.quoteName(compiler.options.enableMinification
? internalName : methodName),
'internalName': js.quoteName(internalName),
'type': js.number(type),
@@ -227,7 +227,7 @@
}
jsAst.Statement tearOffGetter;
- if (!compiler.useContentSecurityPolicy) {
+ if (!compiler.options.useContentSecurityPolicy) {
jsAst.Expression tearOffAccessText =
new jsAst.UnparsedNode(tearOffAccessExpression, compiler, false);
tearOffGetter = js.statement('''
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
index 06aa189..77f606a 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
@@ -62,7 +62,7 @@
void emitConstructorsForCSP(Class cls) {
List<jsAst.Name> fieldNames = <jsAst.Name>[];
- if (!compiler.useContentSecurityPolicy) return;
+ if (!compiler.options.useContentSecurityPolicy) return;
if (!cls.onlyForRti && !cls.isNative) {
fieldNames = cls.fields.map((Field field) => field.name).toList();
@@ -208,7 +208,7 @@
/// Emits getters/setters for fields if compiling in CSP mode.
void emitClassGettersSettersForCSP(Class cls, ClassBuilder builder) {
- if (!compiler.useContentSecurityPolicy || cls.onlyForRti) return;
+ if (!compiler.options.useContentSecurityPolicy || cls.onlyForRti) return;
for (Field field in cls.fields) {
Element member = field.element;
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
index 30114a7..7c9b6d8 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -152,9 +152,9 @@
TypeVariableHandler get typeVariableHandler => backend.typeVariableHandler;
String get _ => space;
- String get space => compiler.enableMinification ? "" : " ";
- String get n => compiler.enableMinification ? "" : "\n";
- String get N => compiler.enableMinification ? "\n" : ";\n";
+ String get space => compiler.options.enableMinification ? "" : " ";
+ String get n => compiler.options.enableMinification ? "" : "\n";
+ String get N => compiler.options.enableMinification ? "\n" : ";\n";
/**
* List of expressions and statements that will be included in the
@@ -571,7 +571,7 @@
jsAst.Statement buildCspPrecompiledFunctionFor(
OutputUnit outputUnit) {
- if (compiler.useContentSecurityPolicy) {
+ if (compiler.options.useContentSecurityPolicy) {
// TODO(ahe): Compute a hash code.
// TODO(sigurdm): Avoid this precompiled function. Generated
// constructor-functions and getter/setter functions can be stored in the
@@ -598,7 +598,7 @@
Fragment fragment) {
ClassElement classElement = cls.element;
reporter.withCurrentElement(classElement, () {
- if (compiler.hasIncrementalSupport) {
+ if (compiler.options.hasIncrementalSupport) {
ClassBuilder cachedBuilder =
cachedClassBuilders.putIfAbsent(classElement, () {
ClassBuilder builder =
@@ -711,7 +711,7 @@
}
}
})(#laziesInfo)
- ''', {'notMinified': !compiler.enableMinification,
+ ''', {'notMinified': !compiler.options.enableMinification,
'laziesInfo': new jsAst.ArrayInitializer(laziesInfo),
'lazy': js(lazyInitializerName),
'isMainFragment': isMainFragment,
@@ -728,7 +728,7 @@
laziesInfo.add(js.quoteName(field.name));
laziesInfo.add(js.quoteName(namer.deriveLazyInitializerName(field.name)));
laziesInfo.add(field.code);
- if (!compiler.enableMinification) {
+ if (!compiler.options.enableMinification) {
laziesInfo.add(js.quoteName(field.name));
}
if (!isMainFragment) {
@@ -763,7 +763,7 @@
isolateProperties]);
}
- if (compiler.enableMinification) {
+ if (compiler.options.enableMinification) {
return js('#(#,#,#)',
[js(lazyInitializerName),
js.quoteName(namer.globalPropertyName(element)),
@@ -805,12 +805,12 @@
if (constants.isEmpty) return js.comment("No constants in program.");
List<jsAst.Statement> parts = <jsAst.Statement>[];
- if (compiler.hasIncrementalSupport && isMainFragment) {
+ if (compiler.options.hasIncrementalSupport && isMainFragment) {
parts = cachedEmittedConstantsAst;
}
for (Constant constant in constants) {
ConstantValue constantValue = constant.value;
- if (compiler.hasIncrementalSupport && isMainFragment) {
+ if (compiler.options.hasIncrementalSupport && isMainFragment) {
if (cachedEmittedConstants.contains(constantValue)) continue;
cachedEmittedConstants.add(constantValue);
}
@@ -1027,7 +1027,7 @@
'makeConstListProperty': makeConstListProperty,
'functionThatReturnsNullProperty':
backend.rtiEncoder.getFunctionThatReturnsNullName,
- 'hasIncrementalSupport': compiler.hasIncrementalSupport,
+ 'hasIncrementalSupport': compiler.options.hasIncrementalSupport,
'lazyInitializerProperty': lazyInitializerProperty,});
}
@@ -1073,7 +1073,7 @@
jsAst.Statement buildSupportsDirectProtoAccess() {
jsAst.Statement supportsDirectProtoAccess;
- if (compiler.hasIncrementalSupport) {
+ if (compiler.options.hasIncrementalSupport) {
supportsDirectProtoAccess = js.statement(r'''
var supportsDirectProtoAccess = false;
''');
@@ -1095,17 +1095,16 @@
jsAst.Expression generateLibraryDescriptor(LibraryElement library,
Fragment fragment) {
var uri = "";
- if (!compiler.enableMinification || backend.mustPreserveUris) {
+ if (!compiler.options.enableMinification || backend.mustPreserveUris) {
uri = library.canonicalUri;
- if (uri.scheme == 'file' && compiler.outputUri != null) {
- uri = relativize(compiler.outputUri, library.canonicalUri, false);
+ if (uri.scheme == 'file' && compiler.options.outputUri != null) {
+ uri = relativize(
+ compiler.options.outputUri, library.canonicalUri, false);
}
}
- String libraryName =
- (!compiler.enableMinification || backend.mustRetainLibraryNames) ?
- library.libraryName :
- "";
+ String libraryName = (!compiler.options.enableMinification ||
+ backend.mustRetainLibraryNames) ? library.libraryName : "";
jsAst.Fun metadata = task.metadataCollector.buildMetadataFunction(library);
@@ -1342,7 +1341,7 @@
void checkEverythingEmitted(Iterable<Element> elements) {
List<Element> pendingStatics;
- if (!compiler.hasIncrementalSupport) {
+ if (!compiler.options.hasIncrementalSupport) {
pendingStatics =
Elements.sortedByPosition(elements.where((e) => !e.isLibrary));
@@ -1429,7 +1428,8 @@
// The program builder does not collect libraries that only
// contain typedefs that are used for reflection.
for (LibraryElement element in remainingLibraries) {
- assert(element is LibraryElement || compiler.hasIncrementalSupport);
+ assert(element is LibraryElement ||
+ compiler.options.hasIncrementalSupport);
if (element is LibraryElement) {
parts.add(generateLibraryDescriptor(element, mainFragment));
descriptors.remove(element);
@@ -1552,7 +1552,7 @@
})();
""", {
"disableVariableRenaming": js.comment("/* ::norenaming:: */"),
- "hasIncrementalSupport": compiler.hasIncrementalSupport,
+ "hasIncrementalSupport": compiler.options.hasIncrementalSupport,
"helper": js('this.#', [namer.incrementalHelperName]),
"schemaChange": buildSchemaChangeFunction(),
"addMethod": buildIncrementalAddMethod(),
@@ -1612,27 +1612,27 @@
mainOutput.addBuffer(jsAst.createCodeBuffer(
program, compiler, monitor: compiler.dumpInfoTask));
- if (compiler.deferredMapUri != null) {
+ if (compiler.options.deferredMapUri != null) {
outputDeferredMap();
}
if (generateSourceMap) {
- mainOutput.add(
- generateSourceMapTag(compiler.sourceMapUri, compiler.outputUri));
+ mainOutput.add(generateSourceMapTag(
+ compiler.options.sourceMapUri, compiler.options.outputUri));
}
mainOutput.close();
if (generateSourceMap) {
outputSourceMap(mainOutput, lineColumnCollector, '',
- compiler.sourceMapUri, compiler.outputUri);
+ compiler.options.sourceMapUri, compiler.options.outputUri);
}
}
/// Used by incremental compilation to patch up the prototype of
/// [oldConstructor] for use as prototype of [newConstructor].
jsAst.Fun buildSchemaChangeFunction() {
- if (!compiler.hasIncrementalSupport) return null;
+ if (!compiler.options.hasIncrementalSupport) return null;
return js('''
function(newConstructor, oldConstructor, superclass) {
// Invariant: newConstructor.prototype has no interesting properties besides
@@ -1665,7 +1665,7 @@
/// top-level). [globalFunctionsAccess] is a reference to
/// [embeddedNames.GLOBAL_FUNCTIONS].
jsAst.Fun buildIncrementalAddMethod() {
- if (!compiler.hasIncrementalSupport) return null;
+ if (!compiler.options.hasIncrementalSupport) return null;
return js(r"""
function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
var arrayOrFunction = originalDescriptor[name];
@@ -1992,7 +1992,7 @@
// in stack traces and profile entries.
body.add(js.statement('var dart = #', libraryDescriptor));
- if (compiler.useContentSecurityPolicy) {
+ if (compiler.options.useContentSecurityPolicy) {
body.add(buildCspPrecompiledFunctionFor(outputUnit));
}
body.add(
@@ -2067,8 +2067,8 @@
if (generateSourceMap) {
Uri mapUri, partUri;
- Uri sourceMapUri = compiler.sourceMapUri;
- Uri outputUri = compiler.outputUri;
+ Uri sourceMapUri = compiler.options.sourceMapUri;
+ Uri outputUri = compiler.options.outputUri;
String partName = "$partPrefix.part";
@@ -2076,14 +2076,16 @@
String mapFileName = partName + ".js.map";
List<String> mapSegments = sourceMapUri.pathSegments.toList();
mapSegments[mapSegments.length - 1] = mapFileName;
- mapUri = compiler.sourceMapUri.replace(pathSegments: mapSegments);
+ mapUri = compiler.options.sourceMapUri
+ .replace(pathSegments: mapSegments);
}
if (outputUri != null) {
String partFileName = partName + ".js";
List<String> partSegments = outputUri.pathSegments.toList();
partSegments[partSegments.length - 1] = partFileName;
- partUri = compiler.outputUri.replace(pathSegments: partSegments);
+ partUri = compiler.options.outputUri.replace(
+ pathSegments: partSegments);
}
output.add(generateSourceMapTag(mapUri, partUri));
@@ -2102,7 +2104,7 @@
jsAst.Comment buildGeneratedBy() {
List<String> options = [];
if (compiler.mirrorsLibrary != null) options.add('mirrors');
- if (compiler.useContentSecurityPolicy) options.add("CSP");
+ if (compiler.options.useContentSecurityPolicy) options.add("CSP");
return new jsAst.Comment(generatedBy(compiler, flavor: options.join(", ")));
}
@@ -2130,13 +2132,14 @@
mapping["_comment"] = "This mapping shows which compiled `.js` files are "
"needed for a given deferred library import.";
mapping.addAll(compiler.deferredLoadTask.computeDeferredMap());
- compiler.outputProvider(compiler.deferredMapUri.path, 'deferred_map')
+ compiler.outputProvider(
+ compiler.options.deferredMapUri.path, 'deferred_map')
..add(const JsonEncoder.withIndent(" ").convert(mapping))
..close();
}
void invalidateCaches() {
- if (!compiler.hasIncrementalSupport) return;
+ if (!compiler.options.hasIncrementalSupport) return;
if (cachedElements.isEmpty) return;
for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) {
if (element.isInstanceMember) {
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
index f8911bd..d342642 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/nsm_emitter.dart
@@ -122,7 +122,7 @@
List<jsAst.Statement> statements = <jsAst.Statement>[];
if (trivialNsmHandlers.length == 0) return statements;
- bool minify = compiler.enableMinification;
+ bool minify = compiler.options.enableMinification;
bool useDiffEncoding = minify && trivialNsmHandlers.length > 30;
// Find out how many selectors there are with the special calling
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
index ecd8a4b..2481d12 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
@@ -81,9 +81,10 @@
String unmangledNameIndex = backend.mustRetainMetadata
? ' 3 * optionalParameterCount + 2 * requiredParameterCount + 3'
: ' 2 * optionalParameterCount + requiredParameterCount + 3';
- String receiverParamName = compiler.enableMinification ? "r" : "receiver";
- String valueParamName = compiler.enableMinification ? "v" : "value";
- String space = compiler.enableMinification ? "" : " ";
+ String receiverParamName = compiler.options.enableMinification
+ ? "r" : "receiver";
+ String valueParamName = compiler.options.enableMinification ? "v" : "value";
+ String space = compiler.options.enableMinification ? "" : " ";
String _ = space;
String specProperty = '"${namer.nativeSpecProperty}"'; // "%"
@@ -109,12 +110,12 @@
'enabledInvokeOn': compiler.enabledInvokeOn,
'interceptedNames': interceptedNamesAccess,
'interceptedNamesSet': emitter.generateInterceptedNamesSet(),
- 'notInCspMode': !compiler.useContentSecurityPolicy,
- 'inCspMode': compiler.useContentSecurityPolicy,
+ 'notInCspMode': !compiler.options.useContentSecurityPolicy,
+ 'inCspMode': compiler.options.useContentSecurityPolicy,
'deferredAction': namer.deferredAction,
'hasIsolateSupport': program.hasIsolateSupport,
'fieldNamesProperty': js.string(Emitter.FIELD_NAMES_PROPERTY_NAME),
- 'hasIncrementalSupport': compiler.hasIncrementalSupport,
+ 'hasIncrementalSupport': compiler.options.hasIncrementalSupport,
'incrementalHelper': namer.accessIncrementalHelper,
'createNewIsolateFunction': createNewIsolateFunctionAccess,
'isolateName': namer.isolateName,
diff --git a/pkg/compiler/lib/src/js_emitter/headers.dart b/pkg/compiler/lib/src/js_emitter/headers.dart
index 67fd4a2..2d15d11 100644
--- a/pkg/compiler/lib/src/js_emitter/headers.dart
+++ b/pkg/compiler/lib/src/js_emitter/headers.dart
@@ -7,7 +7,9 @@
String generatedBy(Compiler compiler, {String flavor: ""}) {
String suffix = '';
- if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}';
+ if (compiler.options.hasBuildId) {
+ suffix = ' version: ${compiler.options.buildId}';
+ }
if (flavor != "") flavor = " ($flavor)";
return '// Generated by dart2js$flavor, '
'the Dart to JavaScript compiler$suffix.';
diff --git a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
index 3d3270c..73eeeb74 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -246,7 +246,7 @@
// checked mode, so we don't optimize the interceptor if the
// compiler has type assertions enabled.
if (selector.isIndexSet
- && (compiler.enableTypeAssertions || !containsArray)) {
+ && (compiler.options.enableTypeAssertions || !containsArray)) {
return null;
}
if (!containsArray && !containsString) {
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 a0b9b48..d2dd9fd 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
@@ -193,7 +193,9 @@
String buildGeneratedBy(compiler) {
var suffix = '';
- if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}';
+ if (compiler.options.hasBuildId) {
+ suffix = ' version: ${compiler.options.buildId}';
+ }
return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n';
}
diff --git a/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart
index d3204e9..2efc6e4 100644
--- a/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/main_call_stub_generator.dart
@@ -32,7 +32,7 @@
Element isolateMain =
helpers.isolateHelperLibrary.find(BackendHelpers.START_ROOT_ISOLATE);
mainCallClosure = _buildIsolateSetupClosure(main, isolateMain);
- } else if (compiler.hasIncrementalSupport) {
+ } else if (compiler.options.hasIncrementalSupport) {
mainCallClosure = js(
'function() { return #(); }',
emitterTask.staticFunctionAccess(main));
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index fdea7ff..b51c470 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -297,7 +297,7 @@
node, _compiler, renamerForNames: nameToKey);
return _globalMetadataMap.putIfAbsent(printed, () {
_BoundMetadataEntry result = new _BoundMetadataEntry(node);
- if (_compiler.hasIncrementalSupport) {
+ if (_compiler.options.hasIncrementalSupport) {
result.finalize(_globalMetadataCounter++);
}
return result;
@@ -337,7 +337,7 @@
_BoundMetadataEntry result = new _BoundMetadataEntry(
_computeTypeRepresentation(type,
ignoreTypeVariables: ignoreTypeVariables));
- if (_compiler.hasIncrementalSupport) {
+ if (_compiler.options.hasIncrementalSupport) {
result.finalize(_globalTypesCounter++);
}
return result;
@@ -376,7 +376,7 @@
jsAst.ArrayInitializer finalizeMap(Map<dynamic, _BoundMetadataEntry> map) {
// When in incremental mode, we allocate entries eagerly.
- if (_compiler.hasIncrementalSupport) {
+ if (_compiler.options.hasIncrementalSupport) {
return new jsAst.ArrayInitializer(map.values.toList());
}
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 378b4a53..dab8fe0 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -139,7 +139,7 @@
if (backend.isJsInterop(classElement)) {
needed = true; // TODO(jacobr): we don't need all interop classes.
} else if (cls.isNative &&
- backend.hasNativeTagsForcedNonLeaf(classElement)) {
+ backend.nativeData.hasNativeTagsForcedNonLeaf(classElement)) {
needed = true;
nonLeafClasses.add(cls);
}
@@ -159,7 +159,8 @@
for (Class cls in classes) {
if (!cls.isNative) continue;
if (backend.isJsInterop(cls.element)) continue;
- List<String> nativeTags = backend.getNativeTagsOfClass(cls.element);
+ List<String> nativeTags =
+ backend.nativeData.getNativeTagsOfClass(cls.element);
if (nonLeafClasses.contains(cls) ||
extensionPoints.containsKey(cls)) {
@@ -315,7 +316,7 @@
assert(invariant(member, nativeMethods.contains(member)));
// When calling a JS method, we call it with the native name, and only the
// arguments up until the last one provided.
- target = backend.getFixedBackendName(member);
+ target = backend.nativeData.getFixedBackendName(member);
if (isInterceptedMethod) {
receiver = argumentsBuffer[0];
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
index c006e05..8325fe1 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -118,7 +118,7 @@
});
var body; // List or jsAst.Statement.
- if (backend.hasFixedBackendName(member)) {
+ if (backend.nativeData.hasFixedBackendName(member)) {
body = emitterTask.nativeEmitter.generateParameterStubStatements(
member, isInterceptedMethod, namer.invocationName(selector),
parametersBuffer, argumentsBuffer,
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
index 268d671..2f5d257 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -148,7 +148,8 @@
JavaScriptConstantCompiler handler = backend.constants;
List<ConstantValue> constants = handler.getConstantsForEmission(
- compiler.hasIncrementalSupport ? null : emitter.compareConstants);
+ compiler.options.hasIncrementalSupport ? null
+ : emitter.compareConstants);
for (ConstantValue constant in constants) {
if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue;
@@ -314,4 +315,4 @@
computeNeededStaticNonFinalFields();
computeNeededLibraries();
}
-}
\ No newline at end of file
+}
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
index 894bd92..09eabaf 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
@@ -99,7 +99,7 @@
js.Name accessorName = namer.fieldAccessorName(field);
js.Name fieldName = namer.fieldPropertyName(field);
bool needsCheckedSetter = false;
- if (compiler.enableTypeAssertions
+ if (compiler.options.enableTypeAssertions
&& needsSetter
&& !canAvoidGeneratedCheckedSetter(field)) {
needsCheckedSetter = true;
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 42f7138..7aef3a3 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -416,7 +416,7 @@
FunctionElement fn = member;
functionType = fn.type;
} else if (member.isGetter) {
- if (_compiler.trustTypeAnnotations) {
+ if (_compiler.options.trustTypeAnnotations) {
GetterElement getter = member;
DartType returnType = getter.type.returnType;
if (returnType.isFunctionType) {
@@ -522,7 +522,7 @@
///
/// Returns a class that contains the fields of a class.
Class buildFieldsHackForIncrementalCompilation(ClassElement element) {
- assert(_compiler.hasIncrementalSupport);
+ assert(_compiler.options.hasIncrementalSupport);
List<Field> instanceFields = _buildFields(element, false);
js.Name name = namer.className(element);
@@ -694,7 +694,7 @@
return backend.isAccessibleByReflection(method) ||
// During incremental compilation, we have to assume that reflection
// *might* get enabled.
- _compiler.hasIncrementalSupport;
+ _compiler.options.hasIncrementalSupport;
}
bool _methodCanBeApplied(FunctionElement method) {
@@ -704,7 +704,7 @@
// TODO(herhut): Refactor incremental compilation and remove method.
Method buildMethodHackForIncrementalCompilation(FunctionElement element) {
- assert(_compiler.hasIncrementalSupport);
+ assert(_compiler.options.hasIncrementalSupport);
if (element.isInstanceMember) {
return _buildMethod(element);
} else {
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 11826c3..056345b 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
@@ -218,7 +218,7 @@
NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE);
}
- if (compiler.deferredMapUri != null) {
+ if (compiler.options.deferredMapUri != null) {
writeDeferredMap();
}
@@ -228,7 +228,7 @@
/// Generates a simple header that provides the compiler's build id.
js.Comment buildGeneratedBy() {
- String flavor = compiler.useContentSecurityPolicy
+ String flavor = compiler.options.useContentSecurityPolicy
? 'fast startup, CSP'
: 'fast startup';
return new js.Comment(generatedBy(compiler, flavor: flavor));
@@ -284,15 +284,15 @@
monitor: compiler.dumpInfoTask));
if (shouldGenerateSourceMap) {
- mainOutput.add(
- generateSourceMapTag(compiler.sourceMapUri, compiler.outputUri));
+ mainOutput.add(generateSourceMapTag(
+ compiler.options.sourceMapUri, compiler.options.outputUri));
}
mainOutput.close();
if (shouldGenerateSourceMap) {
outputSourceMap(mainOutput, lineColumnCollector, '',
- compiler.sourceMapUri, compiler.outputUri);
+ compiler.options.sourceMapUri, compiler.options.outputUri);
}
}
@@ -348,8 +348,8 @@
if (shouldGenerateSourceMap) {
Uri mapUri, partUri;
- Uri sourceMapUri = compiler.sourceMapUri;
- Uri outputUri = compiler.outputUri;
+ Uri sourceMapUri = compiler.options.sourceMapUri;
+ Uri outputUri = compiler.options.outputUri;
String partName = "$hunkPrefix.$partExtension";
String hunkFileName = "$hunkPrefix.$deferredExtension";
@@ -357,13 +357,15 @@
String mapFileName = hunkFileName + ".map";
List<String> mapSegments = sourceMapUri.pathSegments.toList();
mapSegments[mapSegments.length - 1] = mapFileName;
- mapUri = compiler.sourceMapUri.replace(pathSegments: mapSegments);
+ mapUri = compiler.options.sourceMapUri
+ .replace(pathSegments: mapSegments);
}
if (outputUri != null) {
List<String> partSegments = outputUri.pathSegments.toList();
partSegments[partSegments.length - 1] = hunkFileName;
- partUri = compiler.outputUri.replace(pathSegments: partSegments);
+ partUri = compiler.options.outputUri
+ .replace(pathSegments: partSegments);
}
output.add(generateSourceMapTag(mapUri, partUri));
@@ -416,7 +418,8 @@
mapping["_comment"] = "This mapping shows which compiled `.js` files are "
"needed for a given deferred library import.";
mapping.addAll(compiler.deferredLoadTask.computeDeferredMap());
- compiler.outputProvider(compiler.deferredMapUri.path, 'deferred_map')
+ compiler.outputProvider(
+ compiler.options.deferredMapUri.path, 'deferred_map')
..add(const JsonEncoder.withIndent(" ").convert(mapping))
..close();
}
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/library_loader.dart
index 238d393..68f6008 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -369,8 +369,11 @@
return reporter.withCurrentElement(library, () {
return measure(() {
currentHandler.computeExports();
- LoadedLibraries loadedLibraries =
- new _LoadedLibraries(library, currentHandler.nodeMap, this);
+ LoadedLibraries loadedLibraries = new _LoadedLibraries(
+ library,
+ currentHandler.newLibraries,
+ currentHandler.nodeMap,
+ this);
currentHandler = null;
return compiler.onLibrariesLoaded(loadedLibraries)
.then((_) => library);
@@ -596,8 +599,8 @@
Future<LibraryElement> loadDeserializedLibrary(
LibraryDependencyHandler handler,
LibraryElement library) {
- compiler.onLibraryCreated(library);
libraryCanonicalUriMap[library.canonicalUri] = library;
+ handler.registerNewLibrary(library);
return compiler.onLibraryScanned(library, handler).then((_) {
return Future.forEach(library.imports, (ImportElement import) {
return createLibrary(handler, library, import.uri);
@@ -1158,6 +1161,7 @@
*/
class LibraryDependencyHandler implements LibraryLoader {
final _LibraryLoaderTask task;
+ final List<LibraryElement> _newLibraries = <LibraryElement>[];
/**
* Newly loaded libraries and their corresponding node in the library
@@ -1174,8 +1178,8 @@
DiagnosticReporter get reporter => task.reporter;
- /// The libraries loaded with this handler.
- Iterable<LibraryElement> get loadedLibraries => nodeMap.keys;
+ /// The libraries created with this handler.
+ Iterable<LibraryElement> get newLibraries => _newLibraries;
/**
* Performs a fixed-point computation on the export scopes of all registered
@@ -1264,8 +1268,11 @@
* Registers [library] for the processing of its import/export scope.
*/
void registerNewLibrary(LibraryElement library) {
- nodeMap[library] = new LibraryDependencyNode(library);
compiler.onLibraryCreated(library);
+ _newLibraries.add(library);
+ if (!library.exportsHandled) {
+ nodeMap[library] = new LibraryDependencyNode(library);
+ }
}
/**
@@ -1314,8 +1321,12 @@
final Map<Uri, LibraryElement> loadedLibraries = <Uri, LibraryElement>{};
final Map<LibraryElement, LibraryDependencyNode> nodeMap;
- _LoadedLibraries(this.rootLibrary, this.nodeMap, this.task) {
- nodeMap.keys.forEach((LibraryElement loadedLibrary) {
+ _LoadedLibraries(
+ this.rootLibrary,
+ Iterable<LibraryElement> libraries,
+ this.nodeMap,
+ this.task) {
+ libraries.forEach((LibraryElement loadedLibrary) {
loadedLibraries[loadedLibrary.canonicalUri] = loadedLibrary;
});
}
@@ -1406,4 +1417,6 @@
computeSuffixes(rootLibrary, const Link<Uri>());
}
+
+ String toString() => 'root=$rootLibrary,libraries=${loadedLibraries.keys}';
}
diff --git a/pkg/compiler/lib/src/mirrors/analyze.dart b/pkg/compiler/lib/src/mirrors/analyze.dart
index ad3c0ea..313cc92 100644
--- a/pkg/compiler/lib/src/mirrors/analyze.dart
+++ b/pkg/compiler/lib/src/mirrors/analyze.dart
@@ -9,6 +9,7 @@
import 'source_mirrors.dart';
import 'dart2js_mirrors.dart' show Dart2JsMirrorSystem;
import '../../compiler.dart' as api;
+import '../../compiler_new.dart' as new_api;
import '../apiimpl.dart' as apiimpl;
import '../compiler.dart' show Compiler;
import '../old_to_new_api.dart';
@@ -58,12 +59,13 @@
new LegacyCompilerInput(inputProvider),
new LegacyCompilerOutput(),
new LegacyCompilerDiagnostics(internalDiagnosticHandler),
- libraryRoot,
- packageRoot,
- options,
- const {},
- packageConfig,
- findPackages);
+ new new_api.CompilerOptions.parse(
+ libraryRoot: libraryRoot,
+ packageRoot: packageRoot,
+ options: options,
+ environment: const {},
+ packageConfig: packageConfig,
+ packagesDiscoveryProvider: findPackages));
compiler.librariesToAnalyzeWhenRun = libraries;
return compiler.run(null).then((bool success) {
if (success && !compilationFailed) {
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 3921b8e..d0fd80f 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -706,8 +706,8 @@
// but otherwise we would include a lot of code by default).
// TODO(sigmund,sra): consider doing something better for numeric types.
behavior.typesReturned.add(
- !isInterop || compiler.trustJSInteropTypeAnnotations ? returnType
- : const DynamicType());
+ !isInterop || compiler.options.trustJSInteropTypeAnnotations
+ ? returnType : const DynamicType());
if (!type.returnType.isVoid) {
// Declared types are nullable.
behavior.typesReturned.add(compiler.coreTypes.nullType);
@@ -734,8 +734,8 @@
bool isInterop = compiler.backend.isJsInterop(field);
// TODO(sigmund,sra): consider doing something better for numeric types.
behavior.typesReturned.add(
- !isInterop || compiler.trustJSInteropTypeAnnotations ? type
- : const DynamicType());
+ !isInterop || compiler.options.trustJSInteropTypeAnnotations
+ ? type : const DynamicType());
// Declared types are nullable.
behavior.typesReturned.add(resolution.coreTypes.nullType);
behavior._capture(type, resolution,
@@ -859,7 +859,7 @@
typesInstantiated.add(type);
}
- if (!compiler.trustJSInteropTypeAnnotations ||
+ if (!compiler.options.trustJSInteropTypeAnnotations ||
type.isDynamic || type.isObject) {
// By saying that only JS-interop types can be created, we prevent
// pulling in every other native type (e.g. all of dart:html) when a
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 738a304..0f5b985 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -141,7 +141,7 @@
CoreTypes get coreTypes => compiler.coreTypes;
void processNativeClasses(Iterable<LibraryElement> libraries) {
- if (compiler.hasIncrementalSupport) {
+ if (compiler.options.hasIncrementalSupport) {
// Since [Set.add] returns bool if an element was added, this restricts
// [libraries] to ones that haven't already been processed. This saves
// time during incremental compiles.
@@ -236,7 +236,18 @@
* Returns the source string of the class named in the extends clause, or
* `null` if there is no extends clause.
*/
- String findExtendsNameOfClass(BaseClassElementX classElement) {
+ String findExtendsNameOfClass(ClassElement classElement) {
+ if (classElement.isResolved) {
+ ClassElement superClass = classElement.superclass;
+ while (superClass != null) {
+ if (!superClass.isUnnamedMixinApplication) {
+ return superClass.name;
+ }
+ superClass = superClass.superclass;
+ }
+ return null;
+ }
+
// "class B extends A ... {}" --> "A"
// "class B extends foo.A ... {}" --> "A"
// "class B<T> extends foo.A<T,T> with M1, M2 ... {}" --> "A"
@@ -368,9 +379,9 @@
flushing = false;
}
- processClass(BaseClassElementX classElement, cause) {
+ processClass(ClassElement classElement, cause) {
// TODO(ahe): Fix this assertion to work in incremental compilation.
- assert(compiler.hasIncrementalSupport ||
+ assert(compiler.options.hasIncrementalSupport ||
!registeredClasses.contains(classElement));
bool firstTime = registeredClasses.isEmpty;
@@ -407,34 +418,40 @@
});
}
- handleFieldAnnotations(Element element) {
+ void handleFieldAnnotations(Element element) {
+ if (compiler.serialization.isDeserialized(element)) {
+ return;
+ }
if (backend.isNative(element.enclosingElement)) {
// Exclude non-instance (static) fields - they not really native and are
// compiled as isolate globals. Access of a property of a constructor
// function or a non-method property in the prototype chain, must be coded
// using a JS-call.
if (element.isInstanceMember) {
- setNativeName(element);
+ _setNativeName(element);
}
}
}
- handleMethodAnnotations(Element method) {
+ void handleMethodAnnotations(Element method) {
+ if (compiler.serialization.isDeserialized(method)) {
+ return;
+ }
if (isNativeMethod(method)) {
if (method.isStatic) {
- setNativeNameForStaticMethod(method);
+ _setNativeNameForStaticMethod(method);
} else {
- setNativeName(method);
+ _setNativeName(method);
}
}
}
/// Sets the native name of [element], either from an annotation, or
/// defaulting to the Dart name.
- void setNativeName(MemberElement element) {
+ void _setNativeName(MemberElement element) {
String name = findJsNameFromAnnotation(element);
if (name == null) name = element.name;
- backend.setNativeMemberName(element, name);
+ backend.nativeData.setNativeMemberName(element, name);
}
/// Sets the native name of the static native method [element], using the
@@ -445,20 +462,21 @@
/// use the declared @JSName as the expression
/// 3. If [element] does not have a @JSName annotation, qualify the name of
/// the method with the @Native name of the enclosing class.
- void setNativeNameForStaticMethod(MethodElement element) {
+ void _setNativeNameForStaticMethod(MethodElement element) {
String name = findJsNameFromAnnotation(element);
if (name == null) name = element.name;
if (isIdentifier(name)) {
List<String> nativeNames =
- backend.getNativeTagsOfClassRaw(element.enclosingClass);
+ backend.nativeData.getNativeTagsOfClassRaw(element.enclosingClass);
if (nativeNames.length != 1) {
reporter.internalError(element,
'Unable to determine a native name for the enclosing class, '
'options: $nativeNames');
}
- backend.setNativeMemberName(element, '${nativeNames[0]}.$name');
+ backend.nativeData.setNativeMemberName(
+ element, '${nativeNames[0]}.$name');
} else {
- backend.setNativeMemberName(element, name);
+ backend.nativeData.setNativeMemberName(element, name);
}
}
@@ -584,7 +602,7 @@
Map<String, ClassElement> tagOwner = new Map<String, ClassElement>();
NativeResolutionEnqueuer(Enqueuer world, Compiler compiler)
- : super(world, compiler, compiler.enableNativeLiveTypeAnalysis);
+ : super(world, compiler, compiler.options.enableNativeLiveTypeAnalysis);
void processNativeClass(ClassElement classElement) {
super.processNativeClass(classElement);
@@ -593,7 +611,7 @@
if (backend.isJsInterop(classElement)) return;
// Since we map from dispatch tags to classes, a dispatch tag must be used
// on only one native class.
- for (String tag in backend.getNativeTagsOfClass(classElement)) {
+ for (String tag in backend.nativeData.getNativeTagsOfClass(classElement)) {
ClassElement owner = tagOwner[tag];
if (owner != null) {
if (owner != classElement) {
@@ -670,7 +688,7 @@
final Set<ClassElement> doneAddSubtypes = new Set<ClassElement>();
NativeCodegenEnqueuer(Enqueuer world, Compiler compiler, this.emitter)
- : super(world, compiler, compiler.enableNativeLiveTypeAnalysis);
+ : super(world, compiler, compiler.options.enableNativeLiveTypeAnalysis);
void processNativeClasses(Iterable<LibraryElement> libraries) {
super.processNativeClasses(libraries);
diff --git a/pkg/compiler/lib/src/native/native.dart b/pkg/compiler/lib/src/native/native.dart
index 4a1a641..5a1af7c 100644
--- a/pkg/compiler/lib/src/native/native.dart
+++ b/pkg/compiler/lib/src/native/native.dart
@@ -30,7 +30,7 @@
|| libraryName == 'dart:web_audio'
|| libraryName == 'dart:web_gl'
|| libraryName == 'dart:web_sql'
- || compiler.allowNativeExtensions) {
+ || compiler.options.allowNativeExtensions) {
return true;
}
return false;
diff --git a/pkg/compiler/lib/src/native/ssa.dart b/pkg/compiler/lib/src/native/ssa.dart
index 7555590..a14f7ad 100644
--- a/pkg/compiler/lib/src/native/ssa.dart
+++ b/pkg/compiler/lib/src/native/ssa.dart
@@ -54,7 +54,7 @@
// hasBody = true
bool hasBody = false;
assert(backend.isNative(element));
- String nativeMethodName = backend.getFixedBackendName(element);
+ String nativeMethodName = backend.nativeData.getFixedBackendName(element);
if (nativeBody != null) {
LiteralString jsCode = nativeBody.asLiteralString();
String str = jsCode.dartString.slowToString();
diff --git a/pkg/compiler/lib/src/patch_parser.dart b/pkg/compiler/lib/src/patch_parser.dart
index 593b08f..fd747e9 100644
--- a/pkg/compiler/lib/src/patch_parser.dart
+++ b/pkg/compiler/lib/src/patch_parser.dart
@@ -463,7 +463,7 @@
String native = getNativeAnnotation(annotation);
if (native != null) {
JavaScriptBackend backend = compiler.backend;
- backend.setNativeClassTagInfo(element, native);
+ backend.nativeData.setNativeClassTagInfo(element, native);
return native;
}
}
@@ -496,7 +496,7 @@
bool hasJsInterop = hasJsNameAnnotation(annotation);
if (hasJsInterop) {
JavaScriptBackend backend = compiler.backend;
- backend.markAsJsInterop(element);
+ backend.nativeData.markAsJsInterop(element);
}
// Due to semantics of apply in the baseclass we have to return null to
// indicate that no match was found.
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 5821afa..69f9786 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -180,7 +180,7 @@
? Scope.buildEnclosingScope(element) : element.buildScope(),
// The type annotations on a typedef do not imply type checks.
// TODO(karlklose): clean this up (dartbug.com/8870).
- inCheckContext = compiler.enableTypeAssertions &&
+ inCheckContext = compiler.options.enableTypeAssertions &&
!element.isLibrary &&
!element.isTypedef &&
!element.enclosingElement.isTypedef,
@@ -496,7 +496,7 @@
}
ResolutionResult visitAssert(Assert node) {
- if (!compiler.enableAssertMessage) {
+ if (!compiler.options.enableAssertMessage) {
if (node.hasMessage) {
reporter.reportErrorMessage(
node, MessageKind.EXPERIMENTAL_ASSERT_MESSAGE);
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index b0fc586..f628e83 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -266,7 +266,8 @@
tree, MessageKind.FUNCTION_WITH_INITIALIZER);
}
- if (!compiler.analyzeSignaturesOnly || tree.isRedirectingFactory) {
+ if (!compiler.options.analyzeSignaturesOnly ||
+ tree.isRedirectingFactory) {
// We need to analyze the redirecting factory bodies to ensure that
// we can analyze compile-time constants.
visitor.visit(tree.body);
diff --git a/pkg/compiler/lib/src/resolution/signatures.dart b/pkg/compiler/lib/src/resolution/signatures.dart
index df165a6..0fc9aac 100644
--- a/pkg/compiler/lib/src/resolution/signatures.dart
+++ b/pkg/compiler/lib/src/resolution/signatures.dart
@@ -342,7 +342,7 @@
returnType = element.enclosingClass.thisType;
// Because there is no type annotation for the return type of
// this element, we explicitly add one.
- if (compiler.enableTypeAssertions) {
+ if (compiler.options.enableTypeAssertions) {
registry.registerTypeUse(new TypeUse.checkedModeCheck(returnType));
}
} else {
diff --git a/pkg/compiler/lib/src/scanner/scanner_task.dart b/pkg/compiler/lib/src/scanner/scanner_task.dart
index 17b3dbc..98be820 100644
--- a/pkg/compiler/lib/src/scanner/scanner_task.dart
+++ b/pkg/compiler/lib/src/scanner/scanner_task.dart
@@ -46,8 +46,8 @@
void scanElements(CompilationUnitElement compilationUnit) {
Script script = compilationUnit.script;
Token tokens = new Scanner(script.file,
- includeComments: compiler.preserveComments).tokenize();
- if (compiler.preserveComments) {
+ includeComments: compiler.options.preserveComments).tokenize();
+ if (compiler.options.preserveComments) {
tokens = compiler.processAndStripComments(tokens);
}
compiler.dietParser.dietParse(compilationUnit, tokens);
diff --git a/pkg/compiler/lib/src/serialization/element_serialization.dart b/pkg/compiler/lib/src/serialization/element_serialization.dart
index 173dd1e..9cea9d2 100644
--- a/pkg/compiler/lib/src/serialization/element_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/element_serialization.dart
@@ -19,6 +19,7 @@
LIBRARY,
COMPILATION_UNIT,
CLASS,
+ ENUM,
GENERATIVE_CONSTRUCTOR,
FACTORY_CONSTRUCTOR,
TOPLEVEL_FIELD,
@@ -33,6 +34,7 @@
INSTANCE_FUNCTION,
INSTANCE_GETTER,
INSTANCE_SETTER,
+ LOCAL_FUNCTION,
TYPEDEF,
TYPEVARIABLE,
PARAMETER,
@@ -79,16 +81,16 @@
class SerializerUtil {
/// Serialize the declared members of [element] into [encoder].
- static void serializeMembers(ScopeContainerElement element,
+ static void serializeMembers(Iterable<Element> members,
ObjectEncoder encoder) {
MapEncoder mapEncoder = encoder.createMap(Key.MEMBERS);
- element.forEachLocalMember((Element member) {
+ for (Element member in members) {
String name = member.name;
if (member.isSetter) {
name = '$name,=';
}
mapEncoder.setElement(name, member);
- });
+ }
}
/// Serialize the source position of [element] into [encoder].
@@ -116,24 +118,25 @@
}
/// Returns a function that adds the underlying declared elements for a
- /// particular element into [list].
+ /// particular element into [set].
///
/// For instance, for an [AbstractFieldElement] the getter and setter elements
/// are added, if available.
- static flattenElements(List<Element> list) {
+ static flattenElements(Set<Element> set) {
return (Element element) {
+ if (element.isPatch) return;
// TODO(johnniwinther): Handle ambiguous elements.
if (element.isAmbiguous) return;
if (element.isAbstractField) {
AbstractFieldElement abstractField = element;
if (abstractField.getter != null) {
- list.add(abstractField.getter);
+ set.add(abstractField.getter);
}
if (abstractField.setter != null) {
- list.add(abstractField.setter);
+ set.add(abstractField.setter);
}
} else {
- list.add(element);
+ set.add(element);
}
};
}
@@ -149,26 +152,68 @@
return null;
}
+ static List<Element> getMembers(LibraryElement element) {
+ List<Element> members = <Element>[];
+ element.implementation.forEachLocalMember((Element member) {
+ if (!member.isPatch) {
+ members.add(member);
+ }
+ });
+ return members;
+ }
+
+ static List<CompilationUnitElement> getCompilationUnits(
+ LibraryElement element) {
+ List<CompilationUnitElement> compilationUnits = <CompilationUnitElement>[];
+ compilationUnits.addAll(element.compilationUnits.toList());
+ if (element.isPatched) {
+ compilationUnits.addAll(element.implementation.compilationUnits.toList());
+ }
+ return compilationUnits;
+ }
+
+ static List<ImportElement> getImports(LibraryElement element) {
+ List<ImportElement> imports = <ImportElement>[];
+ imports.addAll(element.imports);
+ if (element.isPatched) {
+ imports.addAll(element.implementation.imports);
+ }
+ return imports;
+ }
+
+ static List<Element> getImportedElements(
+ LibraryElement element) {
+ Set<Element> importedElements = new Set<Element>();
+ element.forEachImport(SerializerUtil.flattenElements(importedElements));
+ if (element.isPatched) {
+ element.implementation.forEachImport(
+ SerializerUtil.flattenElements(importedElements));
+ }
+ return importedElements.toList();
+ }
+
+ static List<Element> getExportedElements(
+ LibraryElement element) {
+ Set<Element> exportedElements = new Set<Element>();
+ element.forEachExport(SerializerUtil.flattenElements(exportedElements));
+ return exportedElements.toList();
+ }
+
void serialize(LibraryElement element,
ObjectEncoder encoder,
SerializedElementKind kind) {
encoder.setUri(
Key.CANONICAL_URI, element.canonicalUri, element.canonicalUri);
encoder.setString(Key.LIBRARY_NAME, element.libraryName);
- SerializerUtil.serializeMembers(element, encoder);
+ SerializerUtil.serializeMembers(getMembers(element), encoder);
encoder.setElement(Key.COMPILATION_UNIT, element.entryCompilationUnit);
- encoder.setElements(
- Key.COMPILATION_UNITS, element.compilationUnits.toList());
- encoder.setElements(Key.IMPORTS, element.imports);
+ encoder.setElements(Key.COMPILATION_UNITS, getCompilationUnits(element));
+ encoder.setElements(Key.IMPORTS, getImports(element));
encoder.setElements(Key.EXPORTS, element.exports);
- List<Element> importedElements = <Element>[];
- element.forEachImport(SerializerUtil.flattenElements(importedElements));
- encoder.setElements(Key.IMPORT_SCOPE, importedElements);
+ encoder.setElements(Key.IMPORT_SCOPE, getImportedElements(element));
- List<Element> exportedElements = <Element>[];
- element.forEachExport(SerializerUtil.flattenElements(exportedElements));
- encoder.setElements(Key.EXPORT_SCOPE, exportedElements);
+ encoder.setElements(Key.EXPORT_SCOPE, getExportedElements(element));
}
}
@@ -190,7 +235,11 @@
encoder.setUri(
Key.URI, element.library.canonicalUri, element.script.resourceUri);
List<Element> elements = <Element>[];
- element.forEachLocalMember((e) => elements.add(e));
+ element.forEachLocalMember((e) {
+ if (!element.isPatch) {
+ elements.add(e);
+ }
+ });
encoder.setElements(Key.ELEMENTS, elements);
}
}
@@ -200,11 +249,28 @@
SerializedElementKind getSerializedKind(Element element) {
if (element.isClass) {
+ ClassElement cls = element;
+ if (cls.isEnumClass) {
+ return SerializedElementKind.ENUM;
+ }
return SerializedElementKind.CLASS;
}
return null;
}
+ static List<Element> getMembers(ClassElement element) {
+ List<Element> members = <Element>[];
+ element.forEachLocalMember(members.add);
+ if (element.isPatched) {
+ element.implementation.forEachLocalMember((Element member) {
+ if (!member.isPatch) {
+ members.add(member);
+ }
+ });
+ }
+ return members;
+ }
+
void serialize(ClassElement element,
ObjectEncoder encoder,
SerializedElementKind kind) {
@@ -214,6 +280,9 @@
SerializerUtil.serializePosition(element, encoder);
encoder.setTypes(Key.TYPE_VARIABLES, element.typeVariables);
encoder.setBool(Key.IS_ABSTRACT, element.isAbstract);
+ if (element.isUnnamedMixinApplication) {
+ encoder.setBool(Key.IS_UNNAMED_MIXIN_APPLICATION, true);
+ }
if (element.supertype != null) {
encoder.setType(Key.SUPERTYPE, element.supertype);
}
@@ -225,7 +294,12 @@
element.allSupertypesAndSelf.supertypes.toList());
supertypes.setInts(Key.OFFSETS, element.allSupertypesAndSelf.levelOffsets);
encoder.setTypes(Key.INTERFACES, element.interfaces.toList());
- SerializerUtil.serializeMembers(element, encoder);
+ SerializerUtil.serializeMembers(getMembers(element), encoder);
+ encoder.setBool(Key.IS_PROXY, element.isProxy);
+ if (kind == SerializedElementKind.ENUM) {
+ EnumClassElement enumClass = element;
+ encoder.setElements(Key.FIELDS, enumClass.enumValues);
+ }
}
}
@@ -306,6 +380,9 @@
if (element.isInstanceMember) {
return SerializedElementKind.INSTANCE_FUNCTION;
}
+ if (element.isLocal) {
+ return SerializedElementKind.LOCAL_FUNCTION;
+ }
}
if (element.isGetter) {
if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_GETTER;
@@ -340,6 +417,12 @@
encoder.setElement(Key.LIBRARY, element.library);
encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit);
}
+ encoder.setBool(Key.IS_EXTERNAL, element.isExternal);
+ if (element.isLocal) {
+ LocalFunctionElement localFunction = element;
+ encoder.setElement(
+ Key.EXECUTABLE_CONTEXT, localFunction.executableContext);
+ }
}
}
@@ -508,6 +591,8 @@
return new CompilationUnitElementZ(decoder);
case SerializedElementKind.CLASS:
return new ClassElementZ(decoder);
+ case SerializedElementKind.ENUM:
+ return new EnumClassElementZ(decoder);
case SerializedElementKind.TOPLEVEL_FIELD:
return new TopLevelFieldElementZ(decoder);
case SerializedElementKind.STATIC_FIELD:
@@ -524,6 +609,8 @@
return new StaticFunctionElementZ(decoder);
case SerializedElementKind.INSTANCE_FUNCTION:
return new InstanceFunctionElementZ(decoder);
+ case SerializedElementKind.LOCAL_FUNCTION:
+ return new LocalFunctionElementZ(decoder);
case SerializedElementKind.TOPLEVEL_GETTER:
return new TopLevelGetterElementZ(decoder);
case SerializedElementKind.STATIC_GETTER:
diff --git a/pkg/compiler/lib/src/serialization/impact_serialization.dart b/pkg/compiler/lib/src/serialization/impact_serialization.dart
new file mode 100644
index 0000000..92e68c5
--- /dev/null
+++ b/pkg/compiler/lib/src/serialization/impact_serialization.dart
@@ -0,0 +1,104 @@
+// 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.
+
+library dart2js.serialization.impact;
+
+import '../dart_types.dart';
+import '../elements/elements.dart';
+import '../universe/call_structure.dart';
+import '../universe/selector.dart';
+import '../universe/world_impact.dart';
+import '../universe/use.dart';
+
+import 'keys.dart';
+import 'serialization.dart';
+
+/// Visitor that serializes a [WorldImpact] object using an [ObjectEncoder].
+class ImpactSerializer implements WorldImpactVisitor {
+ final ListEncoder staticUses;
+ final ListEncoder dynamicUses;
+ final ListEncoder typeUses;
+
+ ImpactSerializer(ObjectEncoder objectEncoder)
+ : staticUses = objectEncoder.createList(Key.STATIC_USES),
+ dynamicUses = objectEncoder.createList(Key.DYNAMIC_USES),
+ typeUses = objectEncoder.createList(Key.TYPE_USES);
+
+ @override
+ void visitDynamicUse(DynamicUse dynamicUse) {
+ ObjectEncoder object = dynamicUses.createObject();
+ object.setEnum(Key.KIND, dynamicUse.selector.kind);
+
+ object.setInt(Key.ARGUMENTS,
+ dynamicUse.selector.callStructure.argumentCount);
+ object.setStrings(Key.NAMED_ARGUMENTS,
+ dynamicUse.selector.callStructure.namedArguments);
+
+ object.setString(Key.NAME,
+ dynamicUse.selector.memberName.text);
+ object.setBool(Key.IS_SETTER,
+ dynamicUse.selector.memberName.isSetter);
+ if (dynamicUse.selector.memberName.library != null) {
+ object.setElement(Key.LIBRARY,
+ dynamicUse.selector.memberName.library);
+ }
+ }
+
+ @override
+ void visitStaticUse(StaticUse staticUse) {
+ ObjectEncoder object = staticUses.createObject();
+ object.setEnum(Key.KIND, staticUse.kind);
+ object.setElement(Key.ELEMENT, staticUse.element);
+ }
+
+ @override
+ void visitTypeUse(TypeUse typeUse) {
+ ObjectEncoder object = typeUses.createObject();
+ object.setEnum(Key.KIND, typeUse.kind);
+ object.setType(Key.TYPE, typeUse.type);
+ }
+}
+
+/// A deserialized [WorldImpact] object.
+class DeserializedWorldImpact extends WorldImpact with WorldImpactBuilder {}
+
+class ImpactDeserializer {
+ /// Deserializes a [WorldImpact] from [objectDecoder].
+ static WorldImpact deserializeImpact(ObjectDecoder objectDecoder) {
+ DeserializedWorldImpact worldImpact = new DeserializedWorldImpact();
+ ListDecoder staticUses = objectDecoder.getList(Key.STATIC_USES);
+ for (int index = 0; index < staticUses.length; index++) {
+ ObjectDecoder object = staticUses.getObject(index);
+ StaticUseKind kind = object.getEnum(Key.KIND, StaticUseKind.values);
+ Element element = object.getElement(Key.ELEMENT);
+ worldImpact.registerStaticUse(new StaticUse.internal(element, kind));
+ }
+ ListDecoder dynamicUses = objectDecoder.getList(Key.DYNAMIC_USES);
+ for (int index = 0; index < dynamicUses.length; index++) {
+ ObjectDecoder object = dynamicUses.getObject(index);
+ SelectorKind kind = object.getEnum(Key.KIND, SelectorKind.values);
+ int argumentCount = object.getInt(Key.ARGUMENTS);
+ List<String> namedArguments =
+ object.getStrings(Key.NAMED_ARGUMENTS, isOptional: true);
+ String name = object.getString(Key.NAME);
+ bool isSetter = object.getBool(Key.IS_SETTER);
+ LibraryElement library = object.getElement(Key.LIBRARY, isOptional: true);
+ worldImpact.registerDynamicUse(
+ new DynamicUse(
+ new Selector(
+ kind,
+ new Name(name, library, isSetter: isSetter),
+ new CallStructure(argumentCount, namedArguments)),
+ null));
+ }
+ ListDecoder typeUses = objectDecoder.getList(Key.TYPE_USES);
+ for (int index = 0; index < typeUses.length; index++) {
+ ObjectDecoder object = typeUses.getObject(index);
+ TypeUseKind kind = object.getEnum(Key.KIND, TypeUseKind.values);
+ DartType type = object.getType(Key.TYPE);
+ worldImpact.registerTypeUse(new TypeUse.internal(type, kind));
+ }
+ return worldImpact;
+ }
+}
diff --git a/pkg/compiler/lib/src/serialization/keys.dart b/pkg/compiler/lib/src/serialization/keys.dart
index de1af42..c3b0bf8 100644
--- a/pkg/compiler/lib/src/serialization/keys.dart
+++ b/pkg/compiler/lib/src/serialization/keys.dart
@@ -18,10 +18,13 @@
static const Key CONSTANT = const Key('constant');
static const Key CONSTANTS = const Key('constants');
static const Key CONSTRUCTOR = const Key('constructor');
+ static const Key DATA = const Key('data');
static const Key DEFAULT = const Key('default');
static const Key DEFAULTS = const Key('defaults');
+ static const Key DYNAMIC_USES = const Key('dynamic-uses');
static const Key ELEMENT = const Key('element');
static const Key ELEMENTS = const Key('elements');
+ static const Key EXECUTABLE_CONTEXT = const Key('executable-context');
static const Key EXPORTS = const Key('exports');
static const Key EXPORT_SCOPE = const Key('export-scope');
static const Key EXPRESSION = const Key('expression');
@@ -30,6 +33,7 @@
static const Key FIELDS = const Key('fields');
static const Key FUNCTION = const Key('function');
static const Key ID = const Key('id');
+ static const Key IMPACTS = const Key('impacts');
static const Key IMPORT = const Key('import');
static const Key IMPORTS = const Key('imports');
static const Key IMPORT_SCOPE = const Key('import-scope');
@@ -43,6 +47,10 @@
static const Key IS_NAMED = const Key('isNamed');
static const Key IS_OPERATOR = const Key('isOperator');
static const Key IS_OPTIONAL = const Key('isOptional');
+ static const Key IS_PROXY = const Key('isProxy');
+ static const Key IS_SETTER = const Key('isSetter');
+ static const Key IS_UNNAMED_MIXIN_APPLICATION =
+ const Key('isUnnamedMixinApplication');
static const Key KEYS = const Key('keys');
static const Key KIND = const Key('kind');
static const Key LEFT = const Key('left');
@@ -53,6 +61,7 @@
static const Key MEMBERS = const Key('members');
static const Key NAME = const Key('name');
static const Key NAMES = const Key('names');
+ static const Key NAMED_ARGUMENTS = const Key('named-arguments');
static const Key NAMED_PARAMETERS = const Key('named-parameters');
static const Key NAMED_PARAMETER_TYPES = const Key('named-parameter-types');
static const Key OFFSET = const Key('offset');
@@ -65,6 +74,7 @@
static const Key PREFIX = const Key('prefix');
static const Key RETURN_TYPE = const Key('return-type');
static const Key RIGHT = const Key('right');
+ static const Key STATIC_USES = const Key('static-uses');
static const Key SUPERTYPE = const Key('supertype');
static const Key SUPERTYPES = const Key('supertypes');
static const Key TAGS = const Key('tags');
@@ -73,6 +83,7 @@
static const Key TYPES = const Key('types');
static const Key TYPE_ARGUMENTS = const Key('type-arguments');
static const Key TYPE_DECLARATION = const Key('type-declaration');
+ static const Key TYPE_USES = const Key('type-uses');
static const Key TYPE_VARIABLES = const Key('type-variables');
static const Key URI = const Key('uri');
static const Key VALUE = const Key('value');
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index 23153bf..9b825ce 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -80,9 +80,6 @@
}
@override
- ClassElement get contextClass => _unsupported('contextClass');
-
- @override
ClassElement get enclosingClass => null;
@override
@@ -91,9 +88,6 @@
}
@override
- String get fixedBackendName => _unsupported('fixedBackendName');
-
- @override
LibraryElement get implementationLibrary => library;
@override
@@ -325,6 +319,8 @@
AbstractFieldElementZ(this.name, this.getter, this.setter);
+ FunctionElement get _canonicalElement => getter != null ? getter : setter;
+
@override
ElementKind get kind => ElementKind.ABSTRACT_FIELD;
@@ -334,19 +330,16 @@
}
@override
- LibraryElement get library {
- return getter != null ? getter.library : setter.library;
- }
+ LibraryElement get library => _canonicalElement.library;
@override
- Element get enclosingElement {
- return getter != null ? getter.enclosingElement : setter.enclosingElement;
- }
+ Element get enclosingElement => _canonicalElement.enclosingElement;
@override
- SourceSpan get sourcePosition {
- return getter != null ? getter.sourcePosition : setter.sourcePosition;
- }
+ SourceSpan get sourcePosition => _canonicalElement.sourcePosition;
+
+ @override
+ ClassElement get enclosingClass => _canonicalElement.enclosingClass;
}
class LibraryElementZ extends DeserializedElementZ
@@ -533,6 +526,9 @@
CompilationUnitElement get compilationUnit => this;
@override
+ Element get enclosingElement => library;
+
+ @override
accept(ElementVisitor visitor, arg) {
return visitor.visitCompilationUnitElement(this, arg);
}
@@ -726,13 +722,16 @@
abstract class FunctionTypedElementMixin
implements FunctionElement, DeserializedElementZ {
@override
- AsyncMarker get asyncMarker => _unsupported('');
-
- @override
- bool get isExternal => _unsupported('');
+ AsyncMarker get asyncMarker => _unsupported('asyncMarker');
@override
FunctionElement asFunctionElement() => this;
+
+ @override
+ bool get isExternal {
+ return _decoder.getBool(
+ Key.IS_EXTERNAL, isOptional: true, defaultValue: false);
+ }
}
class ClassElementZ extends DeserializedElementZ
@@ -853,11 +852,12 @@
bool get isEnumClass => false;
@override
- bool get isProxy => _unsupported('isProxy');
+ bool get isProxy => _decoder.getBool(Key.IS_PROXY);
@override
bool get isUnnamedMixinApplication {
- return _unsupported('isUnnamedMixinApplication');
+ return _decoder.getBool(Key.IS_UNNAMED_MIXIN_APPLICATION,
+ isOptional: true, defaultValue: false);
}
@override
@@ -886,6 +886,25 @@
}
}
+
+class EnumClassElementZ extends ClassElementZ implements EnumClassElement {
+ List<FieldElement> _enumValues;
+
+ EnumClassElementZ(ObjectDecoder decoder)
+ : super(decoder);
+
+ @override
+ bool get isEnumClass => true;
+
+ @override
+ List<FieldElement> get enumValues {
+ if (_enumValues == null) {
+ _enumValues = _decoder.getElements(Key.FIELDS);
+ }
+ return _enumValues;
+ }
+}
+
abstract class ConstructorElementZ extends DeserializedElementZ
with AnalyzableElementMixin,
AstElementMixin,
@@ -955,6 +974,11 @@
}
@override
+ bool get isEffectiveTargetMalformed {
+ return _unsupported('isEffectiveTargetMalformed');
+ }
+
+ @override
bool get isRedirectingFactory => _unsupported('isRedirectingFactory');
@override
@@ -975,6 +999,10 @@
@override
ElementKind get kind => ElementKind.GENERATIVE_CONSTRUCTOR;
+
+ @override
+ bool get isEffectiveTargetMalformed =>
+ _unsupported('isEffectiveTargetMalformed');
}
class FactoryConstructorElementZ extends ConstructorElementZ {
@@ -984,6 +1012,10 @@
@override
ElementKind get kind => ElementKind.FACTORY_CONSTRUCTOR;
+
+ @override
+ bool get isEffectiveTargetMalformed =>
+ _unsupported('isEffectiveTargetMalformed');
}
abstract class MemberElementMixin
@@ -1096,6 +1128,61 @@
: super(decoder);
}
+abstract class LocalExecutableMixin
+ implements DeserializedElementZ, ExecutableElement, LocalElement {
+ ExecutableElement _executableContext;
+
+ @override
+ Element get enclosingElement => executableContext;
+
+ @override
+ ExecutableElement get executableContext {
+ if (_executableContext == null) {
+ _executableContext = _decoder.getElement(Key.EXECUTABLE_CONTEXT);
+ }
+ return _executableContext;
+ }
+
+ @override
+ MemberElement get memberContext => executableContext.memberContext;
+
+ @override
+ bool get isLocal => true;
+
+ @override
+ LibraryElement get library => memberContext.library;
+
+ @override
+ CompilationUnitElement get compilationUnit {
+ return memberContext.compilationUnit;
+ }
+
+ @override
+ bool get hasTreeElements => memberContext.hasTreeElements;
+
+ @override
+ TreeElements get treeElements => memberContext.treeElements;
+}
+
+class LocalFunctionElementZ extends DeserializedElementZ
+ with LocalExecutableMixin,
+ AstElementMixin,
+ ParametersMixin,
+ FunctionTypedElementMixin,
+ TypedElementMixin
+ implements LocalFunctionElement {
+ LocalFunctionElementZ(ObjectDecoder decoder)
+ : super(decoder);
+
+ @override
+ accept(ElementVisitor visitor, arg) {
+ return visitor.visitFunctionElement(this, arg);
+ }
+
+ @override
+ ElementKind get kind => ElementKind.FUNCTION;
+}
+
abstract class GetterElementZ extends DeserializedElementZ
with AnalyzableElementMixin,
AstElementMixin,
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 5a818ce..0379b6a 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -4,15 +4,18 @@
library dart2js.serialization;
+import '../common/backend_api.dart';
import '../elements/elements.dart';
import '../constants/expressions.dart';
import '../dart_types.dart';
+import '../universe/world_impact.dart';
-import 'element_serialization.dart';
import 'constant_serialization.dart';
-import 'type_serialization.dart';
-import 'keys.dart';
+import 'element_serialization.dart';
+import 'impact_serialization.dart';
import 'json_serializer.dart';
+import 'keys.dart';
+import 'type_serialization.dart';
import 'values.dart';
/// An object that supports the encoding an [ObjectValue] for serialization.
@@ -608,6 +611,7 @@
// between serialized subcomponent.
class Serializer {
final SerializationEncoder _encoder;
+ List<SerializerPlugin> plugins = <SerializerPlugin>[];
Map<Element, DataObject> _elementMap = <Element, DataObject>{};
Map<ConstantExpression, DataObject> _constantMap =
@@ -623,7 +627,6 @@
// [DataObject] for [library]. If not already created, this will
// put the serialization of [library] in the work queue.
_getElementDataObject(library);
- _emptyWorklist();
}
void _emptyWorklist() {
@@ -641,26 +644,40 @@
if (element == null) {
throw new ArgumentError('Serializer._getElementDataObject(null)');
}
- return _elementMap.putIfAbsent(element, () {
+ DataObject dataObject = _elementMap[element];
+ if (dataObject == null) {
// Run through [ELEMENT_SERIALIZERS] sequentially to find the one that
// deals with [element].
for (ElementSerializer serializer in ELEMENT_SERIALIZERS) {
SerializedElementKind kind = serializer.getSerializedKind(element);
if (kind != null) {
- DataObject dataObject = new DataObject(
+ dataObject = new DataObject(
new IntValue(_elementMap.length), new EnumValue(kind));
+ _elementMap[element] = dataObject;
// Delay the serialization of the element itself to avoid loops, and
// to keep the call stack small.
_pendingList.add(() {
- serializer.serialize(
- element, new ObjectEncoder(this, dataObject.map), kind);
+ ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map);
+ serializer.serialize(element, encoder, kind);
+
+ MapEncoder pluginData;
+ for (SerializerPlugin plugin in plugins) {
+ plugin.onElement(element, (String tag) {
+ if (pluginData == null) {
+ pluginData = encoder.createMap(Key.DATA);
+ }
+ return pluginData.createObject(tag);
+ });
+ }
});
- return dataObject;
}
}
+ }
+ if (dataObject == null) {
throw new UnsupportedError(
'Unsupported element: $element (${element.kind})');
- });
+ }
+ return dataObject;
}
/// Creates the [ElementValue] for [element].
@@ -731,6 +748,8 @@
}
ObjectValue get objectValue {
+ _emptyWorklist();
+
Map<Key, Value> map = <Key, Value>{};
map[Key.ELEMENTS] =
new ListValue(_elementMap.values.map((l) => l.objectValue).toList());
@@ -755,11 +774,34 @@
}
}
+/// Plugin for serializing additional data for an [Element].
+class SerializerPlugin {
+ const SerializerPlugin();
+
+ /// Called upon the serialization of [element].
+ ///
+ /// Use [creatorEncoder] to create a data object with id [tag] for storing
+ /// additional data for [element].
+ void onElement(Element element, ObjectEncoder createEncoder(String tag)) {}
+}
+
+/// Plugin for deserializing additional data for an [Element].
+class DeserializerPlugin {
+ const DeserializerPlugin();
+
+ /// Called upon the deserialization of [element].
+ ///
+ /// Use [getDecoder] to retrieve the data object with id [tag] stored for
+ /// [element]. If not object is stored for [tag], [getDecoder] returns `null`.
+ void onElement(Element element, ObjectDecoder getDecoder(String tag)) {}
+}
+
/// Deserializer for a closed collection of libraries.
// TODO(johnniwinther): Support per-library deserialization and dependencies
// between deserialized subcomponent.
class Deserializer {
final SerializationDecoder decoder;
+ List<DeserializerPlugin> plugins = <DeserializerPlugin>[];
ObjectDecoder _headerObject;
ListDecoder _elementList;
ListDecoder _typeList;
@@ -818,9 +860,21 @@
/// Returns the deserialized [Element] for [id].
Element deserializeElement(int id) {
if (id == null) throw new ArgumentError('Deserializer.getElement(null)');
- return _elementMap.putIfAbsent(id, () {
- return ElementDeserializer.deserialize(elements.getObject(id));
- });
+ Element element = _elementMap[id];
+ if (element == null) {
+ ObjectDecoder decoder = elements.getObject(id);
+ element = ElementDeserializer.deserialize(decoder);
+ _elementMap[id] = element;
+
+ MapDecoder pluginData = decoder.getMap(Key.DATA, isOptional: true);
+ // Call plugins even when there is no data, so they can take action in
+ // this case.
+ for (DeserializerPlugin plugin in plugins) {
+ plugin.onElement(element,
+ (String tag) => pluginData?.getObject(tag, isOptional: true));
+ }
+ }
+ return element;
}
/// Returns the deserialized [DartType] for [id].
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 551ba49..fc1dfae 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -26,6 +26,11 @@
String get name => 'Serialization';
+ /// If `true`, data must be retained to support serialization.
+ // TODO(johnniwinther): Make this more precise in terms of what needs to be
+ // retained, for instance impacts, resolution data etc.
+ bool supportSerialization = false;
+
/// Returns the [LibraryElement] for [resolvedUri] if available from
/// serialization.
LibraryElement readLibrary(Uri resolvedUri) {
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 8796e23..8c8f78c 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -1205,8 +1205,8 @@
// implementation/declaration distinction.
Element get sourceElement => sourceElementStack.last;
- bool get _checkOrTrustTypes =>
- compiler.enableTypeAssertions || compiler.trustTypeAnnotations;
+ bool get _checkOrTrustTypes => compiler.options.enableTypeAssertions ||
+ compiler.options.trustTypeAnnotations;
/// Build the graph for [target].
HGraph build() {
@@ -1225,7 +1225,7 @@
result = buildMethod(target);
} else if (target.isField) {
if (target.isInstanceMember) {
- assert(compiler.enableTypeAssertions);
+ assert(compiler.options.enableTypeAssertions);
result = buildCheckedSetter(target);
} else {
result = buildLazyInitializer(target);
@@ -1426,7 +1426,7 @@
if (cachedCanBeInlined == false) return false;
bool meetsHardConstraints() {
- if (compiler.disableInlining) return false;
+ if (compiler.options.disableInlining) return false;
assert(invariant(
currentNode != null ? currentNode : element,
@@ -1477,7 +1477,7 @@
bool doesNotContainCode() {
// A function with size 1 does not contain any code.
return InlineWeeder.canBeInlined(function, 1, true,
- enableUserAssertions: compiler.enableUserAssertions);
+ enableUserAssertions: compiler.options.enableUserAssertions);
}
bool reductiveHeuristic() {
@@ -1485,7 +1485,7 @@
// does not make the program larger.
if (isCalledOnce(element)) {
return InlineWeeder.canBeInlined(function, -1, false,
- enableUserAssertions: compiler.enableUserAssertions);
+ enableUserAssertions: compiler.options.enableUserAssertions);
}
// TODO(sra): Measure if inlining would 'reduce' the size. One desirable
// case we miss by doing nothing is inlining very simple constructors
@@ -1524,7 +1524,7 @@
// if we can inline this method regardless of size.
assert(InlineWeeder.canBeInlined(function, -1, false,
allowLoops: true,
- enableUserAssertions: compiler.enableUserAssertions));
+ enableUserAssertions: compiler.options.enableUserAssertions));
return true;
}
@@ -1548,7 +1548,7 @@
bool canInline;
canInline = InlineWeeder.canBeInlined(
function, maxInliningNodes, useMaxInliningNodes,
- enableUserAssertions: compiler.enableUserAssertions);
+ enableUserAssertions: compiler.options.enableUserAssertions);
if (canInline) {
backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop);
} else {
@@ -2642,7 +2642,7 @@
}
HInstruction _trustType(HInstruction original, DartType type) {
- assert(compiler.trustTypeAnnotations);
+ assert(compiler.options.trustTypeAnnotations);
assert(type != null);
type = localsHandler.substInContext(type);
type = type.unaliased;
@@ -2656,7 +2656,7 @@
}
HInstruction _checkType(HInstruction original, DartType type, int kind) {
- assert(compiler.enableTypeAssertions);
+ assert(compiler.options.enableTypeAssertions);
assert(type != null);
type = localsHandler.substInContext(type);
HInstruction other = buildTypeConversion(original, type, kind);
@@ -2668,9 +2668,9 @@
{ int kind: HTypeConversion.CHECKED_MODE_CHECK }) {
if (type == null) return original;
HInstruction checkedOrTrusted = original;
- if (compiler.trustTypeAnnotations) {
+ if (compiler.options.trustTypeAnnotations) {
checkedOrTrusted = _trustType(original, type);
- } else if (compiler.enableTypeAssertions) {
+ } else if (compiler.options.enableTypeAssertions) {
checkedOrTrusted = _checkType(original, type, kind);
}
if (checkedOrTrusted == original) return original;
@@ -2750,7 +2750,7 @@
}
visitAssert(ast.Assert node) {
- if (!compiler.enableUserAssertions) return;
+ if (!compiler.options.enableUserAssertions) return;
if (!node.hasMessage) {
// Generate:
@@ -4320,7 +4320,7 @@
value = backend.mustRetainMetadata;
break;
case 'USE_CONTENT_SECURITY_POLICY':
- value = compiler.useContentSecurityPolicy;
+ value = compiler.options.useContentSecurityPolicy;
break;
default:
reporter.reportErrorMessage(
@@ -5353,7 +5353,7 @@
/// In checked mode checks the [type] of [node] to be well-bounded. The method
/// returns [:true:] if an error can be statically determined.
bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) {
- if (!compiler.enableTypeAssertions) return false;
+ if (!compiler.options.enableTypeAssertions) return false;
Map<DartType, Set<DartType>> seenChecksMap =
new Map<DartType, Set<DartType>>();
@@ -5993,7 +5993,7 @@
var nativeBehavior = new native.NativeBehavior()
..codeTemplate = codeTemplate;
- if (compiler.trustJSInteropTypeAnnotations) {
+ if (compiler.options.trustJSInteropTypeAnnotations) {
nativeBehavior.typesReturned.add(constructor.enclosingClass.thisType);
}
return new HForeignCode(
@@ -6004,7 +6004,7 @@
}
var target = new HForeignCode(js.js.parseForeignJS(
"${backend.namer.fixedBackendPath(element)}."
- "${backend.getFixedBackendName(element)}"),
+ "${backend.nativeData.getFixedBackendName(element)}"),
backend.dynamicType,
<HInstruction>[]);
add(target);
@@ -6024,7 +6024,8 @@
// The return type is dynamic if we don't trust js-interop type
// declarations.
nativeBehavior.typesReturned.add(
- compiler.trustJSInteropTypeAnnotations ? type : const DynamicType());
+ compiler.options.trustJSInteropTypeAnnotations
+ ? type : const DynamicType());
// The allocation effects include the declared type if it is native (which
// includes js interop types).
@@ -6034,7 +6035,7 @@
// It also includes any other JS interop type if we don't trust the
// annotation or if is declared too broad.
- if (!compiler.trustJSInteropTypeAnnotations || type.isObject ||
+ if (!compiler.options.trustJSInteropTypeAnnotations || type.isObject ||
type.isDynamic) {
nativeBehavior.typesInstantiated.add(
backend.helpers.jsJavaScriptObjectClass.thisType);
@@ -7333,7 +7334,7 @@
visit(node.expression);
value = pop();
if (isBuildingAsyncFunction) {
- if (compiler.enableTypeAssertions &&
+ if (compiler.options.enableTypeAssertions &&
!isValidAsyncReturnType(returnType)) {
String message =
"Async function returned a Future, "
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 4032c0a..410532c 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -1598,7 +1598,7 @@
// A direct (i.e. non-interceptor) native call is the result of
// optimization. The optimization ensures any type checks or
// conversions have been satisified.
- methodName = backend.getFixedBackendName(target);
+ methodName = backend.nativeData.getFixedBackendName(target);
}
}
@@ -1960,7 +1960,7 @@
js.Expression newLiteralBool(bool value,
SourceInformation sourceInformation) {
- if (compiler.enableMinification) {
+ if (compiler.options.enableMinification) {
// Use !0 for true, !1 for false.
return new js.Prefix("!", new js.LiteralNumber(value ? "0" : "1"))
.withSourceInformation(sourceInformation);
@@ -2787,7 +2787,7 @@
ClassWorld classWorld = compiler.world;
// An int check if the input is not int or null, is not
// sufficient for doing an argument or receiver check.
- assert(compiler.trustTypeAnnotations ||
+ assert(compiler.options.trustTypeAnnotations ||
!node.checkedType.containsOnlyInt(classWorld) ||
node.checkedInput.isIntegerOrNull(compiler));
js.Expression test = generateReceiverOrArgumentTypeTest(
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index a68f70b..beb4f42 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -291,7 +291,7 @@
SsaTrustedCheckRemover(this.compiler);
void visitGraph(HGraph graph) {
- if (!compiler.trustPrimitives) return;
+ if (!compiler.options.trustPrimitives) return;
visitDominatorTree(graph);
}
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index c445190..3281111 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -324,7 +324,7 @@
}
// Try creating a one-shot interceptor or optimized is-check
- if (compiler.hasIncrementalSupport) return false;
+ if (compiler.options.hasIncrementalSupport) return false;
if (node.usedBy.length != 1) return false;
HInstruction user = node.usedBy.single;
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index 8852d1f..9e03bb9 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -98,7 +98,7 @@
Compiler compiler) {
if (instruction.inputs[1].isMutableIndexable(compiler)) {
if (!instruction.inputs[2].isInteger(compiler)
- && compiler.enableTypeAssertions) {
+ && compiler.options.enableTypeAssertions) {
// We want the right checked mode error.
return null;
}
@@ -118,7 +118,7 @@
Compiler compiler) {
if (!instruction.inputs[1].isIndexablePrimitive(compiler)) return null;
if (!instruction.inputs[2].isInteger(compiler)
- && compiler.enableTypeAssertions) {
+ && compiler.options.enableTypeAssertions) {
// We want the right checked mode error.
return null;
}
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 484a784..78d5391 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -61,7 +61,7 @@
ConstantSystem constantSystem = compiler.backend.constantSystem;
JavaScriptItemCompilationContext context = work.compilationContext;
- bool trustPrimitives = compiler.trustPrimitives;
+ bool trustPrimitives = compiler.options.trustPrimitives;
measure(() {
List<OptimizationPhase> phases = <OptimizationPhase>[
// Run trivial instruction simplification first to optimize
@@ -393,7 +393,7 @@
} else if (applies(helpers.jsArrayAdd)) {
// The codegen special cases array calls, but does not
// inline argument type checks.
- if (!compiler.enableTypeAssertions) {
+ if (!compiler.options.enableTypeAssertions) {
target = helpers.jsArrayAdd;
}
}
@@ -513,7 +513,7 @@
if (type is FunctionType) {
canInline = false;
}
- if (compiler.enableTypeAssertions) {
+ if (compiler.options.enableTypeAssertions) {
// TODO(sra): Check if [input] is guaranteed to pass the parameter
// type check. Consider using a strengthened type check to avoid
// passing `null` to primitive types since the native methods usually
@@ -918,7 +918,7 @@
// interceptor calling convention, but is not a call on an
// interceptor.
HInstruction value = node.inputs.last;
- if (compiler.enableTypeAssertions) {
+ if (compiler.options.enableTypeAssertions) {
DartType type = field.type;
if (!type.treatAsRaw || type.isTypeVariable) {
// We cannot generate the correct type representation here, so don't
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index 4758afd..0b35432 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -160,29 +160,29 @@
return "Boolify: ${temporaryId(node.inputs[0])}";
}
- String handleInvokeBinary(HInvokeBinary node, String op) {
+ String handleInvokeBinary(HInvokeBinary node, String opcode) {
String left = temporaryId(node.left);
String right= temporaryId(node.right);
- return '$left $op $right';
+ return '$opcode: $left $right';
}
- String visitAdd(HAdd node) => handleInvokeBinary(node, '+');
+ String visitAdd(HAdd node) => handleInvokeBinary(node, 'Add');
- String visitBitAnd(HBitAnd node) => handleInvokeBinary(node, '&');
+ String visitBitAnd(HBitAnd node) => handleInvokeBinary(node, 'BitAnd');
String visitBitNot(HBitNot node) {
String operand = temporaryId(node.operand);
- return "~$operand";
+ return "BitNot: $operand";
}
- String visitBitOr(HBitOr node) => handleInvokeBinary(node, '|');
+ String visitBitOr(HBitOr node) => handleInvokeBinary(node, 'BitOr');
- String visitBitXor(HBitXor node) => handleInvokeBinary(node, '^');
+ String visitBitXor(HBitXor node) => handleInvokeBinary(node, 'BitXor');
String visitBoundsCheck(HBoundsCheck node) {
String lengthId = temporaryId(node.length);
String indexId = temporaryId(node.index);
- return "Bounds check: length = $lengthId, index = $indexId";
+ return "BoundsCheck: length = $lengthId, index = $indexId";
}
String visitBreak(HBreak node) {
@@ -193,7 +193,7 @@
return "Break: (B${target.id})";
}
- String visitConstant(HConstant constant) => "Constant ${constant.constant}";
+ String visitConstant(HConstant constant) => "Constant: ${constant.constant}";
String visitContinue(HContinue node) {
HBasicBlock target = currentBlock.successors[0];
@@ -203,22 +203,22 @@
return "Continue: (B${target.id})";
}
- String visitDivide(HDivide node) => handleInvokeBinary(node, '/');
+ String visitDivide(HDivide node) => handleInvokeBinary(node, 'Divide');
- String visitExit(HExit node) => "exit";
+ String visitExit(HExit node) => "Exit";
String visitFieldGet(HFieldGet node) {
if (node.isNullCheck) {
- return 'null check on ${temporaryId(node.receiver)}';
+ return 'FieldGet: NullCheck ${temporaryId(node.receiver)}';
}
String fieldName = node.element.name;
- return 'field get ${temporaryId(node.receiver)}.$fieldName';
+ return 'FieldGet: ${temporaryId(node.receiver)}.$fieldName';
}
String visitFieldSet(HFieldSet node) {
String valueId = temporaryId(node.value);
String fieldName = node.element.name;
- return 'field set ${temporaryId(node.receiver)}.$fieldName to $valueId';
+ return 'FieldSet: ${temporaryId(node.receiver)}.$fieldName to $valueId';
}
String visitReadModifyWrite(HReadModifyWrite node) {
@@ -227,23 +227,23 @@
String op = node.jsOp;
if (node.isAssignOp) {
String valueId = temporaryId(node.value);
- return 'field-update $receiverId.$fieldName $op= $valueId';
+ return 'ReadModifyWrite: $receiverId.$fieldName $op= $valueId';
} else if (node.isPreOp) {
- return 'field-update $op$receiverId.$fieldName';
+ return 'ReadModifyWrite: $op$receiverId.$fieldName';
} else {
- return 'field-update $receiverId.$fieldName$op';
+ return 'ReadModifyWrite: $receiverId.$fieldName$op';
}
}
String visitLocalGet(HLocalGet node) {
String localName = node.variable.name;
- return 'local get ${temporaryId(node.local)}.$localName';
+ return 'LocalGet: ${temporaryId(node.local)}.$localName';
}
String visitLocalSet(HLocalSet node) {
String valueId = temporaryId(node.value);
String localName = node.variable.name;
- return 'local set ${temporaryId(node.local)}.$localName to $valueId';
+ return 'LocalSet: ${temporaryId(node.local)}.$localName to $valueId';
}
String visitGoto(HGoto node) {
@@ -251,11 +251,11 @@
return "Goto: (B${target.id})";
}
- String visitGreater(HGreater node) => handleInvokeBinary(node, '>');
+ String visitGreater(HGreater node) => handleInvokeBinary(node, 'Greater');
String visitGreaterEqual(HGreaterEqual node) {
- return handleInvokeBinary(node, '>=');
+ return handleInvokeBinary(node, 'GreaterEqual');
}
- String visitIdentity(HIdentity node) => handleInvokeBinary(node, '===');
+ String visitIdentity(HIdentity node) => handleInvokeBinary(node, 'Identity');
String visitIf(HIf node) {
HBasicBlock thenBlock = currentBlock.successors[0];
@@ -264,8 +264,8 @@
return "If ($conditionId): (B${thenBlock.id}) else (B${elseBlock.id})";
}
- String visitGenericInvoke(String invokeType, String functionName,
- List<HInstruction> arguments) {
+ String handleGenericInvoke(String invokeType, String functionName,
+ List<HInstruction> arguments) {
StringBuffer argumentsString = new StringBuffer();
for (int i = 0; i < arguments.length; i++) {
if (i != 0) argumentsString.write(", ");
@@ -293,59 +293,60 @@
JavaScriptBackend backend = compiler.backend;
String cls =
backend.namer.suffixForGetInterceptor(node.interceptedClasses);
- return "Intercept ($cls): $value";
+ return "Interceptor ($cls): $value";
}
- return "Intercept: $value";
+ return "Interceptor: $value";
}
String visitInvokeClosure(HInvokeClosure node)
- => visitInvokeDynamic(node, "closure");
+ => handleInvokeDynamic(node, "InvokeClosure");
- String visitInvokeDynamic(HInvokeDynamic invoke, String kind) {
+ String handleInvokeDynamic(HInvokeDynamic invoke, String kind) {
String receiver = temporaryId(invoke.receiver);
String name = invoke.selector.name;
- String target = "($kind) $receiver.$name";
+ String target = "$receiver.$name";
int offset = HInvoke.ARGUMENTS_OFFSET;
List arguments = invoke.inputs.sublist(offset);
- return visitGenericInvoke("Invoke", target, arguments) +
+ return handleGenericInvoke(kind, target, arguments) +
"(${invoke.mask})";
}
String visitInvokeDynamicMethod(HInvokeDynamicMethod node)
- => visitInvokeDynamic(node, "method");
+ => handleInvokeDynamic(node, "InvokeDynamicMethod");
String visitInvokeDynamicGetter(HInvokeDynamicGetter node)
- => visitInvokeDynamic(node, "get");
+ => handleInvokeDynamic(node, "InvokeDynamicGetter");
String visitInvokeDynamicSetter(HInvokeDynamicSetter node)
- => visitInvokeDynamic(node, "set");
+ => handleInvokeDynamic(node, "InvokeDynamicSetter");
String visitInvokeStatic(HInvokeStatic invoke) {
String target = invoke.element.name;
- return visitGenericInvoke("Invoke", target, invoke.inputs);
+ return handleGenericInvoke("InvokeStatic", target, invoke.inputs);
}
String visitInvokeSuper(HInvokeSuper invoke) {
String target = invoke.element.name;
- return visitGenericInvoke("Invoke super", target, invoke.inputs);
+ return handleGenericInvoke("InvokeSuper", target, invoke.inputs);
}
String visitInvokeConstructorBody(HInvokeConstructorBody invoke) {
String target = invoke.element.name;
- return visitGenericInvoke("Invoke constructor body", target, invoke.inputs);
+ return handleGenericInvoke("InvokeConstructorBody", target, invoke.inputs);
}
String visitForeignCode(HForeignCode foreign) {
- return visitGenericInvoke("Foreign", "${foreign.codeTemplate.ast}",
+ return handleGenericInvoke("ForeignCode", "${foreign.codeTemplate.ast}",
foreign.inputs);
}
String visitForeignNew(HForeignNew node) {
- return visitGenericInvoke("New",
+ return handleGenericInvoke("ForeignNew",
"${node.element.name}",
node.inputs);
}
- String visitLess(HLess node) => handleInvokeBinary(node, '<');
- String visitLessEqual(HLessEqual node) => handleInvokeBinary(node, '<=');
+ String visitLess(HLess node) => handleInvokeBinary(node, 'Less');
+ String visitLessEqual(HLessEqual node) =>
+ handleInvokeBinary(node, 'LessEqual');
String visitLiteralList(HLiteralList node) {
StringBuffer elementsString = new StringBuffer();
@@ -353,65 +354,67 @@
if (i != 0) elementsString.write(", ");
elementsString.write(temporaryId(node.inputs[i]));
}
- return "Literal list: [$elementsString]";
+ return "LiteralList: [$elementsString]";
}
String visitLoopBranch(HLoopBranch branch) {
HBasicBlock bodyBlock = currentBlock.successors[0];
HBasicBlock exitBlock = currentBlock.successors[1];
String conditionId = temporaryId(branch.inputs[0]);
- return "While ($conditionId): (B${bodyBlock.id}) then (B${exitBlock.id})";
+ return
+ "LoopBranch ($conditionId): (B${bodyBlock.id}) then (B${exitBlock.id})";
}
- String visitMultiply(HMultiply node) => handleInvokeBinary(node, '*');
+ String visitMultiply(HMultiply node) => handleInvokeBinary(node, 'Multiply');
String visitNegate(HNegate node) {
String operand = temporaryId(node.operand);
- return "-$operand";
+ return "Negate: $operand";
}
String visitNot(HNot node) => "Not: ${temporaryId(node.inputs[0])}";
String visitParameterValue(HParameterValue node) {
- return "p${node.sourceElement.name}";
+ return "ParameterValue: ${node.sourceElement.name}";
}
String visitLocalValue(HLocalValue node) {
- return "l${node.sourceElement.name}";
+ return "LocalValue: ${node.sourceElement.name}";
}
String visitPhi(HPhi phi) {
StringBuffer buffer = new StringBuffer();
- buffer.write("Phi(");
+ buffer.write("Phi: ");
for (int i = 0; i < phi.inputs.length; i++) {
if (i > 0) buffer.write(", ");
buffer.write(temporaryId(phi.inputs[i]));
}
- buffer.write(")");
return buffer.toString();
}
String visitRef(HRef node) {
- return 'Ref ${temporaryId(node.value)}';
+ return 'Ref: ${temporaryId(node.value)}';
}
- String visitReturn(HReturn node) => "Return ${temporaryId(node.inputs[0])}";
+ String visitReturn(HReturn node) => "Return: ${temporaryId(node.inputs[0])}";
- String visitShiftLeft(HShiftLeft node) => handleInvokeBinary(node, '<<');
- String visitShiftRight(HShiftRight node) => handleInvokeBinary(node, '>>');
+ String visitShiftLeft(HShiftLeft node) =>
+ handleInvokeBinary(node, 'ShiftLeft');
+ String visitShiftRight(HShiftRight node) =>
+ handleInvokeBinary(node, 'ShiftRight');
String visitStatic(HStatic node)
- => "Static ${node.element.name}";
+ => "Static: ${node.element.name}";
String visitLazyStatic(HLazyStatic node)
- => "LazyStatic ${node.element.name}";
+ => "LazyStatic: ${node.element.name}";
String visitOneShotInterceptor(HOneShotInterceptor node)
- => visitInvokeDynamic(node, "one shot interceptor");
+ => handleInvokeDynamic(node, "OneShotInterceptor");
String visitStaticStore(HStaticStore node) {
String lhs = node.element.name;
- return "Static $lhs = ${temporaryId(node.inputs[0])}";
+ return "StaticStore: $lhs = ${temporaryId(node.inputs[0])}";
}
String visitStringConcat(HStringConcat node) {
@@ -421,10 +424,10 @@
}
String visitStringify(HStringify node) {
- return "Stringify ${temporaryId(node.inputs[0])}";
+ return "Stringify: ${temporaryId(node.inputs[0])}";
}
- String visitSubtract(HSubtract node) => handleInvokeBinary(node, '-');
+ String visitSubtract(HSubtract node) => handleInvokeBinary(node, 'Subtract');
String visitSwitch(HSwitch node) {
StringBuffer buf = new StringBuffer();
@@ -442,20 +445,20 @@
return buf.toString();
}
- String visitThis(HThis node) => "this";
+ String visitThis(HThis node) => "This";
- String visitThrow(HThrow node) => "Throw ${temporaryId(node.inputs[0])}";
+ String visitThrow(HThrow node) => "Throw: ${temporaryId(node.inputs[0])}";
String visitThrowExpression(HThrowExpression node) {
- return "ThrowExpression ${temporaryId(node.inputs[0])}";
+ return "ThrowExpression: ${temporaryId(node.inputs[0])}";
}
String visitTruncatingDivide(HTruncatingDivide node) {
- return handleInvokeBinary(node, '~/');
+ return handleInvokeBinary(node, 'TruncatingDivide');
}
String visitExitTry(HExitTry node) {
- return "Exit try";
+ return "ExitTry";
}
String visitTry(HTry node) {
@@ -477,12 +480,12 @@
String visitIs(HIs node) {
String type = node.typeExpression.toString();
- return "TypeTest: ${temporaryId(node.expression)} is $type";
+ return "Is: ${temporaryId(node.expression)} is $type";
}
String visitIsViaInterceptor(HIsViaInterceptor node) {
String type = node.typeExpression.toString();
- return "TypeTest: ${temporaryId(node.inputs[0])} is $type";
+ return "IsViaInterceptor: ${temporaryId(node.inputs[0])} is $type";
}
String visitTypeConversion(HTypeConversion node) {
@@ -529,10 +532,10 @@
}
String visitAwait(HAwait node) {
- return "await ${temporaryId(node.inputs[0])}";
+ return "Await: ${temporaryId(node.inputs[0])}";
}
String visitYield(HYield node) {
- return "yield${node.hasStar ? "*" : ""} ${temporaryId(node.inputs[0])}";
+ return "Yield${node.hasStar ? "*" : ""}: ${temporaryId(node.inputs[0])}";
}
}
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 6355c6a..49373dc 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -292,7 +292,7 @@
// Return true if the argument type check was added.
bool checkArgument(HInvokeDynamic instruction) {
// We want the right error in checked mode.
- if (compiler.enableTypeAssertions) return false;
+ if (compiler.options.enableTypeAssertions) return false;
HInstruction left = instruction.inputs[1];
HInstruction right = instruction.inputs[2];
diff --git a/pkg/compiler/lib/src/tokens/token.dart b/pkg/compiler/lib/src/tokens/token.dart
index 1b05a5f..d390eb7 100644
--- a/pkg/compiler/lib/src/tokens/token.dart
+++ b/pkg/compiler/lib/src/tokens/token.dart
@@ -416,28 +416,28 @@
isUnaryOperator(value);
}
-bool isUnaryOperator(String value) => identical(value, '~');
+bool isUnaryOperator(String value) => value == '~';
bool isBinaryOperator(String value) {
return
- (identical(value, '==')) ||
- (identical(value, '[]')) ||
- (identical(value, '*')) ||
- (identical(value, '/')) ||
- (identical(value, '%')) ||
- (identical(value, '~/')) ||
- (identical(value, '+')) ||
- (identical(value, '<<')) ||
- (identical(value, '>>')) ||
- (identical(value, '>=')) ||
- (identical(value, '>')) ||
- (identical(value, '<=')) ||
- (identical(value, '<')) ||
- (identical(value, '&')) ||
- (identical(value, '^')) ||
- (identical(value, '|'));
+ value == '==' ||
+ value == '[]' ||
+ value == '*' ||
+ value == '/' ||
+ value == '%' ||
+ value == '~/' ||
+ value == '+' ||
+ value == '<<' ||
+ value == '>>' ||
+ value == '>=' ||
+ value == '>' ||
+ value == '<=' ||
+ value == '<' ||
+ value == '&' ||
+ value == '^' ||
+ value == '|';
}
-bool isTernaryOperator(String value) => identical(value, '[]=');
+bool isTernaryOperator(String value) => value == '[]=';
-bool isMinusOperator(String value) => identical(value, '-');
+bool isMinusOperator(String value) => value == '-';
diff --git a/pkg/compiler/lib/src/typechecker.dart b/pkg/compiler/lib/src/typechecker.dart
index 449618b..bd23056 100644
--- a/pkg/compiler/lib/src/typechecker.dart
+++ b/pkg/compiler/lib/src/typechecker.dart
@@ -558,7 +558,7 @@
bool checkAssignable(Spannable spannable, DartType from, DartType to,
{bool isConst: false}) {
if (!types.isAssignable(from, to)) {
- if (compiler.enableTypeAssertions && isConst) {
+ if (compiler.options.enableTypeAssertions && isConst) {
reporter.reportErrorMessage(
spannable,
MessageKind.NOT_ASSIGNABLE,
diff --git a/pkg/compiler/lib/src/universe/selector.dart b/pkg/compiler/lib/src/universe/selector.dart
index f8a44e6..014ceef 100644
--- a/pkg/compiler/lib/src/universe/selector.dart
+++ b/pkg/compiler/lib/src/universe/selector.dart
@@ -34,7 +34,12 @@
static const SelectorKind OPERATOR = const SelectorKind('operator', 3);
static const SelectorKind INDEX = const SelectorKind('index', 4);
+ int get index => hashCode;
+
String toString() => name;
+
+ static List<SelectorKind> values =
+ const <SelectorKind>[GETTER, SETTER, CALL, OPERATOR, INDEX];
}
class Selector {
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index 77c1084..73fb979 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -84,7 +84,7 @@
final StaticUseKind kind;
final int hashCode;
- StaticUse._(Element element, StaticUseKind kind)
+ StaticUse.internal(Element element, StaticUseKind kind)
: this.element = element,
this.kind = kind,
this.hashCode = Hashing.objectHash(element, Hashing.objectHash(kind)) {
@@ -101,7 +101,7 @@
assert(invariant(element, element.isStatic || element.isTopLevel,
message: "Static invoke element $element must be a top-level "
"or static method."));
- return new StaticUse._(element, StaticUseKind.GENERAL);
+ return new StaticUse.internal(element, StaticUseKind.GENERAL);
}
/// Closurization of a static or top-level function [element].
@@ -109,7 +109,7 @@
assert(invariant(element, element.isStatic || element.isTopLevel,
message: "Static tear-off element $element must be a top-level "
"or static method."));
- return new StaticUse._(element, StaticUseKind.STATIC_TEAR_OFF);
+ return new StaticUse.internal(element, StaticUseKind.STATIC_TEAR_OFF);
}
/// Read access of a static or top-level field or getter [element].
@@ -119,7 +119,7 @@
"or static method."));
assert(invariant(element, element.isField || element.isGetter,
message: "Static get element $element must be a field or a getter."));
- return new StaticUse._(element, StaticUseKind.GENERAL);
+ return new StaticUse.internal(element, StaticUseKind.GENERAL);
}
/// Write access of a static or top-level field or setter [element].
@@ -129,7 +129,7 @@
"or static method."));
assert(invariant(element, element.isField || element.isSetter,
message: "Static set element $element must be a field or a setter."));
- return new StaticUse._(element, StaticUseKind.GENERAL);
+ return new StaticUse.internal(element, StaticUseKind.GENERAL);
}
/// Invocation of the lazy initializer for a static or top-level field
@@ -140,7 +140,7 @@
"or static method."));
assert(invariant(element, element.isField,
message: "Static init element $element must be a field."));
- return new StaticUse._(element, StaticUseKind.GENERAL);
+ return new StaticUse.internal(element, StaticUseKind.GENERAL);
}
/// Invocation of a super method [element] with the given [callStructure].
@@ -149,7 +149,7 @@
// TODO(johnniwinther): Use the [callStructure].
assert(invariant(element, element.isInstanceMember,
message: "Super invoke element $element must be an instance method."));
- return new StaticUse._(element, StaticUseKind.GENERAL);
+ return new StaticUse.internal(element, StaticUseKind.GENERAL);
}
/// Read access of a super field or getter [element].
@@ -158,7 +158,7 @@
message: "Super get element $element must be an instance method."));
assert(invariant(element, element.isField || element.isGetter,
message: "Super get element $element must be a field or a getter."));
- return new StaticUse._(element, StaticUseKind.GENERAL);
+ return new StaticUse.internal(element, StaticUseKind.GENERAL);
}
/// Write access of a super field [element].
@@ -167,7 +167,7 @@
message: "Super set element $element must be an instance method."));
assert(invariant(element, element.isField,
message: "Super set element $element must be a field."));
- return new StaticUse._(element, StaticUseKind.SUPER_FIELD_SET);
+ return new StaticUse.internal(element, StaticUseKind.SUPER_FIELD_SET);
}
/// Write access of a super setter [element].
@@ -176,14 +176,14 @@
message: "Super set element $element must be an instance method."));
assert(invariant(element, element.isSetter,
message: "Super set element $element must be a setter."));
- return new StaticUse._(element, StaticUseKind.GENERAL);
+ return new StaticUse.internal(element, StaticUseKind.GENERAL);
}
/// Closurization of a super method [element].
factory StaticUse.superTearOff(MethodElement element) {
assert(invariant(element, element.isInstanceMember && element.isFunction,
message: "Super invoke element $element must be an instance method."));
- return new StaticUse._(element, StaticUseKind.SUPER_TEAR_OFF);
+ return new StaticUse.internal(element, StaticUseKind.SUPER_TEAR_OFF);
}
/// Invocation of a constructor [element] through a this or super
@@ -195,7 +195,7 @@
element.isGenerativeConstructor,
message: "Constructor invoke element $element must be a "
"generative constructor."));
- return new StaticUse._(element, StaticUseKind.GENERAL);
+ return new StaticUse.internal(element, StaticUseKind.GENERAL);
}
/// Invocation of a constructor (body) [element] through a this or super
@@ -203,26 +203,26 @@
factory StaticUse.constructorBodyInvoke(ConstructorBodyElement element,
CallStructure callStructure) {
// TODO(johnniwinther): Use the [callStructure].
- return new StaticUse._(element, StaticUseKind.GENERAL);
+ return new StaticUse.internal(element, StaticUseKind.GENERAL);
}
/// Constructor invocation of [element] with the given [callStructure].
factory StaticUse.constructorInvoke(ConstructorElement element,
CallStructure callStructure) {
// TODO(johnniwinther): Use the [callStructure].
- return new StaticUse._(element, StaticUseKind.GENERAL);
+ return new StaticUse.internal(element, StaticUseKind.GENERAL);
}
/// Constructor redirection to [element].
factory StaticUse.constructorRedirect(ConstructorElement element) {
- return new StaticUse._(element, StaticUseKind.GENERAL);
+ return new StaticUse.internal(element, StaticUseKind.GENERAL);
}
/// Initialization of an instance field [element].
factory StaticUse.fieldInit(FieldElement element) {
assert(invariant(element, element.isInstanceMember,
message: "Field init element $element must be an instance field."));
- return new StaticUse._(element, StaticUseKind.GENERAL);
+ return new StaticUse.internal(element, StaticUseKind.GENERAL);
}
/// Read access of an instance field or boxed field [element].
@@ -231,7 +231,7 @@
element.isInstanceMember || element is BoxFieldElement,
message: "Field init element $element must be an instance "
"or boxed field."));
- return new StaticUse._(element, StaticUseKind.FIELD_GET);
+ return new StaticUse.internal(element, StaticUseKind.FIELD_GET);
}
/// Write access of an instance field or boxed field [element].
@@ -240,18 +240,18 @@
element.isInstanceMember || element is BoxFieldElement,
message: "Field init element $element must be an instance "
"or boxed field."));
- return new StaticUse._(element, StaticUseKind.FIELD_SET);
+ return new StaticUse.internal(element, StaticUseKind.FIELD_SET);
}
/// Read of a local function [element].
factory StaticUse.closure(LocalFunctionElement element) {
- return new StaticUse._(element, StaticUseKind.CLOSURE);
+ return new StaticUse.internal(element, StaticUseKind.CLOSURE);
}
/// Unknown use of [element].
@deprecated
factory StaticUse.foreignUse(Element element) {
- return new StaticUse._(element, StaticUseKind.GENERAL);
+ return new StaticUse.internal(element, StaticUseKind.GENERAL);
}
bool operator ==(other) {
@@ -279,39 +279,39 @@
final TypeUseKind kind;
final int hashCode;
- TypeUse._(DartType type, TypeUseKind kind)
+ TypeUse.internal(DartType type, TypeUseKind kind)
: this.type = type,
this.kind = kind,
this.hashCode = Hashing.objectHash(type, Hashing.objectHash(kind));
/// [type] used in an is check, like `e is T` or `e is! T`.
factory TypeUse.isCheck(DartType type) {
- return new TypeUse._(type, TypeUseKind.IS_CHECK);
+ return new TypeUse.internal(type, TypeUseKind.IS_CHECK);
}
/// [type] used in an as cast, like `e as T`.
factory TypeUse.asCast(DartType type) {
- return new TypeUse._(type, TypeUseKind.AS_CAST);
+ return new TypeUse.internal(type, TypeUseKind.AS_CAST);
}
/// [type] used as a type annotation, like `T foo;`.
factory TypeUse.checkedModeCheck(DartType type) {
- return new TypeUse._(type, TypeUseKind.CHECKED_MODE_CHECK);
+ return new TypeUse.internal(type, TypeUseKind.CHECKED_MODE_CHECK);
}
/// [type] used in a on type catch clause, like `try {} on T catch (e) {}`.
factory TypeUse.catchType(DartType type) {
- return new TypeUse._(type, TypeUseKind.CATCH_TYPE);
+ return new TypeUse.internal(type, TypeUseKind.CATCH_TYPE);
}
/// [type] used as a type literal, like `foo() => T;`.
factory TypeUse.typeLiteral(DartType type) {
- return new TypeUse._(type, TypeUseKind.TYPE_LITERAL);
+ return new TypeUse.internal(type, TypeUseKind.TYPE_LITERAL);
}
/// [type] used in an instantiation, like `new T();`.
factory TypeUse.instantiation(InterfaceType type) {
- return new TypeUse._(type, TypeUseKind.INSTANTIATION);
+ return new TypeUse.internal(type, TypeUseKind.INSTANTIATION);
}
bool operator ==(other) {
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 3e382e1..a7dbad0 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -653,7 +653,8 @@
/// properties of the [ClassHierarchyNode] for [cls].
void addSubtypes(ClassElement cls) {
- if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) {
+ if (compiler.options.hasIncrementalSupport &&
+ !alreadyPopulated.add(cls)) {
return;
}
assert(cls.isDeclaration);
@@ -841,5 +842,5 @@
return functionsThatMightBePassedToApply.contains(element);
}
- bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport;
+ bool get hasClosedWorldAssumption => !compiler.options.hasIncrementalSupport;
}
diff --git a/pkg/dart2js_incremental/lib/caching_compiler.dart b/pkg/dart2js_incremental/lib/caching_compiler.dart
index 4185df1..f7f8f10 100644
--- a/pkg/dart2js_incremental/lib/caching_compiler.dart
+++ b/pkg/dart2js_incremental/lib/caching_compiler.dart
@@ -36,11 +36,11 @@
CompilerImpl compiler = cachedCompiler;
if (compiler == null ||
compiler.libraryRoot != libraryRoot ||
- !compiler.hasIncrementalSupport ||
+ !compiler.options.hasIncrementalSupport ||
compiler.hasCrashed ||
compiler.enqueuer.resolution.hasEnqueuedReflectiveElements ||
compiler.deferredLoadTask.isProgramSplit) {
- if (compiler != null && compiler.hasIncrementalSupport) {
+ if (compiler != null && compiler.options.hasIncrementalSupport) {
print('***FLUSH***');
if (compiler.hasCrashed) {
print('Unable to reuse compiler due to crash.');
@@ -57,12 +57,11 @@
inputProvider,
outputProvider,
diagnosticHandler,
- libraryRoot,
- packageRoot,
- options,
- environment,
- null,
- null);
+ new CompilerOptions.parse(
+ libraryRoot: libraryRoot,
+ packageRoot: packageRoot,
+ options: options,
+ environment: environment));
JavaScriptBackend backend = compiler.backend;
full.Emitter emitter = backend.emitter.emitter;
diff --git a/pkg/dart2js_incremental/lib/dart2js_incremental.dart b/pkg/dart2js_incremental/lib/dart2js_incremental.dart
index 1ce8039..ea42c5a 100644
--- a/pkg/dart2js_incremental/lib/dart2js_incremental.dart
+++ b/pkg/dart2js_incremental/lib/dart2js_incremental.dart
@@ -18,6 +18,7 @@
CompilerDiagnostics,
CompilerInput,
CompilerOutput,
+ CompilerOptions,
Diagnostic;
import 'package:compiler/src/null_compiler_output.dart' show
diff --git a/pkg/dart2js_incremental/lib/library_updater.dart b/pkg/dart2js_incremental/lib/library_updater.dart
index eb4bbd1..b8a5c62 100644
--- a/pkg/dart2js_incremental/lib/library_updater.dart
+++ b/pkg/dart2js_incremental/lib/library_updater.dart
@@ -796,7 +796,7 @@
compiler.phase = Compiler.PHASE_DONE_RESOLVING;
// TODO(ahe): Clean this up. Don't call this method in analyze-only mode.
- if (compiler.analyzeOnly) return "/* analyze only */";
+ if (compiler.options.analyzeOnly) return "/* analyze only */";
Set<ClassElementX> changedClasses =
new Set<ClassElementX>.from(_classesWithSchemaChanges);
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 5cfce7f..351addb 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -58,6 +58,7 @@
analyzer/test/generated/constant_test: Pass, Slow # Issue 24914
analyzer/test/generated/declaration_resolver_test: Pass, Slow # Issue 24914
analyzer/test/generated/element_test: Pass, Slow # Issue 21628
+analyzer/test/generated/element_resolver_test: Pass, Slow # Issue 21628
analyzer/test/generated/error_suppression_test: Pass, Slow # Issue 21628
analyzer/test/generated/engine_test: SkipSlow
analyzer/test/generated/hint_code_test: Pass, Slow # Issue 21628
diff --git a/pkg/typed_data/LICENSE b/pkg/typed_data/LICENSE
deleted file mode 100644
index ee99930..0000000
--- a/pkg/typed_data/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2013, the Dart project authors. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
- * Neither the name of Google Inc. nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/typed_data/README.md b/pkg/typed_data/README.md
deleted file mode 100644
index e1e7db5..0000000
--- a/pkg/typed_data/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-Helper libraries for working with typed data lists.
-
-The `typed_data` package contains utility functions and classes that makes working with typed data lists easier.
-
-## Using
-
-The `typed_data` package can be imported as
-
- import 'package:typed_data/typed_data.dart';
-
-## Typed buffers: Growable typed data lists
-
-Typed buffers are contains growable lists backed by typed arrays.
-These are similar to the growable lists returned by `new List()`,
-but stores typed data like a typed data list.
\ No newline at end of file
diff --git a/pkg/typed_data/lib/typed_buffers.dart b/pkg/typed_data/lib/typed_buffers.dart
deleted file mode 100644
index 50ed241..0000000
--- a/pkg/typed_data/lib/typed_buffers.dart
+++ /dev/null
@@ -1,235 +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.
-
-/**
- * Growable typed-data lists.
- *
- * These lists works just as a typed-data list, except that they are growable.
- * They use an underlying buffer, and when that buffer becomes too small, it
- * is replaced by a new buffer.
- *
- * That means that using the [TypedDataView.buffer] getter is not guaranteed
- * to return the same result each time it is used, and that the buffer may
- * be larger than what the list is using.
- */
-library dart.pkg.typed_data.typed_buffers;
-
-import "dart:collection" show ListBase;
-import "dart:typed_data";
-
-abstract class _TypedDataBuffer<E> extends ListBase<E> {
- static const int INITIAL_LENGTH = 8;
-
- /// This is a Uint8List for Uint8Buffer. It's both a List<E> and a TypedData,
- /// which we don't have a type for here.
- var _buffer;
- /// The length of the list being built.
- int _length;
-
- _TypedDataBuffer(List<E> buffer)
- : this._buffer = buffer, this._length = buffer.length;
-
- int get length => _length;
- E operator[](int index) {
- if (index >= length) throw new RangeError.index(index, this);
- return _buffer[index];
- }
-
- void operator[]=(int index, E value) {
- if (index >= length) throw new RangeError.index(index, this);
- _buffer[index] = value;
- }
-
- void set length(int newLength) {
- if (newLength < _length) {
- E defaultValue = _defaultValue;
- for (int i = newLength; i < _length; i++) {
- _buffer[i] = defaultValue;
- }
- } else if (newLength > _buffer.length) {
- List<E> newBuffer;
- if (_buffer.length == 0) {
- newBuffer = _createBuffer(newLength);
- } else {
- newBuffer = _createBiggerBuffer(newLength);
- }
- newBuffer.setRange(0, _length, _buffer);
- _buffer = newBuffer;
- }
- _length = newLength;
- }
-
- void _add(E value) {
- if (_length == _buffer.length) _grow();
- _buffer[_length++] = value;
- }
-
- // We override the default implementation of `add` and `addAll` because
- // they grow by setting the length in increments of one. We want to grow
- // by doubling capacity in most cases.
- void add(E value) { _add(value); }
-
- void addAll(Iterable<E> values) {
- for (E value in values) _add(value);
- }
-
- void insert(int index, E element) {
- if (index < 0 || index > _length) {
- throw new RangeError.range(index, 0, _length);
- }
- if (_length < _buffer.length) {
- _buffer.setRange(index + 1, _length + 1, _buffer, index);
- _buffer[index] = element;
- _length++;
- return;
- }
- List<E> newBuffer = _createBiggerBuffer(null);
- newBuffer.setRange(0, index, _buffer);
- newBuffer.setRange(index + 1, _length + 1, _buffer, index);
- newBuffer[index] = element;
- _length++;
- _buffer = newBuffer;
- }
-
- /**
- * Create a bigger buffer.
- *
- * This method determines how much bigger a bigger buffer should
- * be. If [requiredLength] is not null, it will be at least that
- * size. It will always have at least have double the capacity of
- * the current buffer.
- */
- List<E> _createBiggerBuffer(int requiredLength) {
- int newLength = _buffer.length * 2;
- if (requiredLength != null && newLength < requiredLength) {
- newLength = requiredLength;
- } else if (newLength < INITIAL_LENGTH) {
- newLength = INITIAL_LENGTH;
- }
- return _createBuffer(newLength);
- }
-
- void _grow() {
- _buffer = _createBiggerBuffer(null)..setRange(0, _length, _buffer);
- }
-
- void setRange(int start, int end, Iterable<E> source, [int skipCount = 0]) {
- if (end > _length) throw new RangeError.range(end, 0, _length);
- if (source is _TypedDataBuffer<E>) {
- _buffer.setRange(start, end, source._buffer, skipCount);
- } else {
- _buffer.setRange(start, end, source, skipCount);
- }
- }
-
- // TypedData.
-
- int get elementSizeInBytes => _buffer.elementSizeInBytes;
-
- int get lengthInBytes => _length * _buffer.elementSizeInBytes;
-
- int get offsetInBytes => _buffer.offsetInBytes;
-
- /**
- * Returns the underlying [ByteBuffer].
- *
- * The returned buffer may be replaced by operations that change the [length]
- * of this list.
- *
- * The buffer may be larger than [lengthInBytes] bytes, but never smaller.
- */
- ByteBuffer get buffer => _buffer.buffer;
-
- // Specialization for the specific type.
-
- // Return zero for integers, 0.0 for floats, etc.
- // Used to fill buffer when changing length.
- E get _defaultValue;
-
- // Create a new typed list to use as buffer.
- List<E> _createBuffer(int size);
-}
-
-abstract class _IntBuffer extends _TypedDataBuffer<int> {
- _IntBuffer(buffer): super(buffer);
- int get _defaultValue => 0;
-}
-
-abstract class _FloatBuffer extends _TypedDataBuffer<double> {
- _FloatBuffer(buffer): super(buffer);
- double get _defaultValue => 0.0;
-}
-
-class Uint8Buffer extends _IntBuffer {
- Uint8Buffer([int initialLength = 0]) : super(new Uint8List(initialLength));
- Uint8List _createBuffer(int size) => new Uint8List(size);
-}
-
-class Int8Buffer extends _IntBuffer {
- Int8Buffer([int initialLength = 0]) : super(new Int8List(initialLength));
- Int8List _createBuffer(int size) => new Int8List(size);
-}
-
-class Uint8ClampedBuffer extends _IntBuffer {
- Uint8ClampedBuffer([int initialLength = 0])
- : super(new Uint8ClampedList(initialLength));
- Uint8ClampedList _createBuffer(int size) => new Uint8ClampedList(size);
-}
-
-class Uint16Buffer extends _IntBuffer {
- Uint16Buffer([int initialLength = 0]) : super(new Uint16List(initialLength));
- Uint16List _createBuffer(int size) => new Uint16List(size);
-}
-
-class Int16Buffer extends _IntBuffer {
- Int16Buffer([int initialLength = 0]) : super(new Int16List(initialLength));
- Int16List _createBuffer(int size) => new Int16List(size);
-}
-
-class Uint32Buffer extends _IntBuffer {
- Uint32Buffer([int initialLength = 0]) : super(new Uint32List(initialLength));
- Uint32List _createBuffer(int size) => new Uint32List(size);
-}
-
-class Int32Buffer extends _IntBuffer {
- Int32Buffer([int initialLength = 0]) : super(new Int32List(initialLength));
- Int32List _createBuffer(int size) => new Int32List(size);
-}
-
-class Uint64Buffer extends _IntBuffer {
- Uint64Buffer([int initialLength = 0]) : super(new Uint64List(initialLength));
- Uint64List _createBuffer(int size) => new Uint64List(size);
-}
-
-class Int64Buffer extends _IntBuffer {
- Int64Buffer([int initialLength = 0]) : super(new Int64List(initialLength));
- Int64List _createBuffer(int size) => new Int64List(size);
-}
-
-class Float32Buffer extends _FloatBuffer {
- Float32Buffer([int initialLength = 0])
- : super(new Float32List(initialLength));
- Float32List _createBuffer(int size) => new Float32List(size);
-}
-
-class Float64Buffer extends _FloatBuffer {
- Float64Buffer([int initialLength = 0])
- : super(new Float64List(initialLength));
- Float64List _createBuffer(int size) => new Float64List(size);
-}
-
-class Int32x4Buffer extends _TypedDataBuffer<Int32x4> {
- static Int32x4 _zero = new Int32x4(0, 0, 0, 0);
- Int32x4Buffer([int initialLength = 0])
- : super(new Int32x4List(initialLength));
- Int32x4 get _defaultValue => _zero;
- Int32x4List _createBuffer(int size) => new Int32x4List(size);
-}
-
-class Float32x4Buffer extends _TypedDataBuffer<Float32x4> {
- Float32x4Buffer([int initialLength = 0])
- : super(new Float32x4List(initialLength));
- Float32x4 get _defaultValue => new Float32x4.zero();
- Float32x4List _createBuffer(int size) => new Float32x4List(size);
-}
diff --git a/pkg/typed_data/lib/typed_data.dart b/pkg/typed_data/lib/typed_data.dart
deleted file mode 100644
index b6619ab..0000000
--- a/pkg/typed_data/lib/typed_data.dart
+++ /dev/null
@@ -1,10 +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.
-
-/**
- * Utilities and functionality related to the "dart:typed_data" library.
- */
-library dart.pkg.typed_data;
-
-export "package:typed_data/typed_buffers.dart";
diff --git a/pkg/typed_data/pubspec.yaml b/pkg/typed_data/pubspec.yaml
deleted file mode 100644
index b4c3945..0000000
--- a/pkg/typed_data/pubspec.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-name: typed_data
-version: 1.0.1-dev
-author: Dart Team <misc@dartlang.org>
-description: Utility functions and classes related to the 'dart:typed_data' library.
-homepage: http://www.dartlang.org
-dev_dependencies:
- unittest: ">=0.9.0 <0.10.0"
-environment:
- sdk: ">=1.5.0 <2.0.0"
diff --git a/pkg/typed_data/test/typed_buffers_test.dart b/pkg/typed_data/test/typed_buffers_test.dart
deleted file mode 100644
index 1cb37b0..0000000
--- a/pkg/typed_data/test/typed_buffers_test.dart
+++ /dev/null
@@ -1,421 +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.
-
-// Tests typed-data buffer classes.
-
-import "package:typed_data/typed_buffers.dart";
-import "package:unittest/unittest.dart";
-import "dart:typed_data";
-
-main() {
- testUint(8, (l) => new Uint8Buffer(l));
- testInt(8, (l) => new Int8Buffer(l));
- test("Uint8ClampedBuffer", () {
- testIntBuffer(8, 0, 255, (l) => new Uint8ClampedBuffer(l), clampUint8);
- });
- testUint(16, (l) => new Uint16Buffer(l));
- testInt(16, (l) => new Int16Buffer(l));
- testUint(32, (l) => new Uint32Buffer(l)); /// 01: ok
- testInt(32, (l) => new Int32Buffer(l));
- testUint(64, (l) => new Uint64Buffer(l)); /// 01: continued
- testInt(64, (l) => new Int64Buffer(l)); /// 01: continued
-
- testInt32x4Buffer(intSamples);
-
- List roundedFloatSamples = floatSamples.map(roundToFloat).toList();
- testFloatBuffer(32, roundedFloatSamples,
- () => new Float32Buffer(),
- roundToFloat);
- testFloatBuffer(64, doubleSamples, () => new Float64Buffer(), (x) => x);
-
- testFloat32x4Buffer(roundedFloatSamples);
-}
-
-double roundToFloat(double value) {
- return (new Float32List(1)..[0] = value)[0];
-}
-
-typedef int Rounder(int value);
-
-Rounder roundUint(bits) {
- int halfbits = (1 << (bits ~/ 2)) - 1;
- int mask = halfbits | (halfbits << (bits ~/ 2));
- return (int x) => x & mask;
-}
-
-Rounder roundInt(bits) {
- int highBit = 1 << (bits - 1);
- int mask = highBit - 1;
- return (int x) => (x & mask) - (x & highBit);
-}
-
-int clampUint8(x) => x < 0 ? 0 : x > 255 ? 255 : x;
-
-void testUint(int bits, var buffer) {
- int min = 0;
- Function round = roundUint(bits);
- int max = round(-1);
- test("Uint${bits}Buffer", () {
- testIntBuffer(bits, min, max, buffer, round);
- });
-}
-
-void testInt(int bits, var buffer) {
- int min = -(1 << (bits - 1));
- int max = -(min + 1);
- test("Int${bits}Buffer", () {
- testIntBuffer(bits, min, max, buffer, roundInt(bits));
- });
-}
-
-const List<int> intSamples = const [
- 0x10000000000000001,
- 0x10000000000000000, // 2^64
- 0x0ffffffffffffffff,
- 0xaaaaaaaaaaaaaaaa,
- 0x8000000000000001,
- 0x8000000000000000, // 2^63
- 0x7fffffffffffffff,
- 0x5555555555555555,
- 0x100000001,
- 0x100000000, // 2^32
- 0x0ffffffff,
- 0xaaaaaaaa,
- 0x80000001,
- 0x80000000, // 2^31
- 0x7fffffff,
- 0x55555555,
- 0x10001,
- 0x10000, // 2^16
- 0x0ffff,
- 0xaaaa,
- 0x8001,
- 0x8000, // 2^15
- 0x7fff,
- 0x5555,
- 0x101,
- 0x100, // 2^8
- 0x0ff,
- 0xaa,
- 0x81,
- 0x80, // 2^7
- 0x7f,
- 0x55,
- 0x02,
- 0x01,
- 0x00
-];
-
-// Takes bit-size, min value, max value, function to create a buffer, and
-// the rounding that is applied when storing values outside the valid range
-// into the buffer.
-void testIntBuffer(int bits, int min, int max,
- create(int length),
- int round(int)) {
- assert(round(min) == min);
- assert(round(max) == max);
- // All int buffers default to the value 0.
- var buffer = create(0);
- List<int> list = buffer; // Check the type.
- expect(buffer.length, equals(0));
- var bytes = bits ~/ 8;
-
- expect(buffer.elementSizeInBytes, equals(bytes));
- expect(buffer.lengthInBytes, equals(0));
- expect(buffer.offsetInBytes, equals(0));
-
- buffer.add(min);
- expect(buffer.length, equals(1));
- expect(buffer[0], equals(min));
-
- expect(buffer.elementSizeInBytes, equals(bytes));
- expect(buffer.lengthInBytes, equals(bytes));
- expect(buffer.offsetInBytes, equals(0));
-
- buffer.length = 0;
- expect(buffer.length, equals(0));
-
- List samples = intSamples.toList()..addAll(intSamples.map((x) => -x));
- for (int value in samples) {
- int length = buffer.length;
- buffer.add(value);
- expect(buffer.length, equals(length + 1));
- expect(buffer[length], equals(round(value)));
- }
- buffer.addAll(samples); // Add all the values at once.
- for (int i = 0; i < samples.length; i++) {
- expect(buffer[samples.length + i], equals(buffer[i]));
- }
-
- // Remove range works and changes length.
- buffer.removeRange(samples.length, buffer.length);
- expect(buffer.length, equals(samples.length));
-
- // Both values are in `samples`, but equality is performed without rounding.
- expect(buffer.contains(min - 1), isFalse);
- expect(buffer.contains(max + 1), isFalse);
- expect(buffer.contains(round(min - 1)), isTrue);
- expect(buffer.contains(round(max + 1)), isTrue);
-
- // Accessing the underlying buffer works.
- buffer.length = 2;
- buffer[0] = min;
- buffer[1] = max;
- var byteBuffer = new Uint8List.view(buffer.buffer);
- int byteSize = buffer.elementSizeInBytes;
- for (int i = 0; i < byteSize; i++) {
- int tmp = byteBuffer[i];
- byteBuffer[i] = byteBuffer[byteSize + i];
- byteBuffer[byteSize + i] = tmp;
- }
- expect(buffer[0], equals(max));
- expect(buffer[1], equals(min));
-}
-
-const List doubleSamples = const [
- 0.0,
- 5e-324, // Minimal denormal value.
- 2.225073858507201e-308, // Maximal denormal value.
- 2.2250738585072014e-308, // Minimal normal value.
- 0.9999999999999999, // Maximum value < 1.
- 1.0,
- 1.0000000000000002, // Minimum value > 1.
- 4294967295.0, // 2^32 -1.
- 4294967296.0, // 2^32.
- 4503599627370495.5, // Maximal fractional value.
- 9007199254740992.0, // Maximal exact value (adding one gets lost).
- 1.7976931348623157e+308, // Maximal value.
- 1.0/0.0, // Infinity.
- 0.0/0.0, // NaN.
- 0.49999999999999994, // Round-traps 1-3 (adding 0.5 and rounding towards
- 4503599627370497.0, // minus infinity will not be the same as rounding
- 9007199254740991.0 // to nearest with 0.5 rounding up).
-];
-
-const List floatSamples = const [
- 0.0,
- 1.4e-45, // Minimal denormal value.
- 1.1754942E-38, // Maximal denormal value.
- 1.17549435E-38, // Minimal normal value.
- 0.99999994, // Maximal value < 1.
- 1.0,
- 1.0000001, // Minimal value > 1.
- 8388607.5, // Maximal fractional value.
- 16777216.0, // Maximal exact value.
- 3.4028235e+38, // Maximal value.
- 1.0/0.0, // Infinity.
- 0.0/0.0, // NaN.
- 0.99999994, // Round traps 1-3.
- 8388609.0,
- 16777215.0
-];
-
-void doubleEqual(x, y) {
- if (y.isNaN) {
- expect(x.isNaN, isTrue);
- } else {
- if (x != y) {
- }
- expect(x, equals(y));
- }
-}
-
-testFloatBuffer(int bitSize, List samples, create(), double round(double v)) {
- test("Float${bitSize}Buffer", () {
- var buffer = create();
- List<double> list = buffer; // Test type.
- int byteSize = bitSize ~/ 8;
-
- expect(buffer.length, equals(0));
- buffer.add(0.0);
- expect(buffer.length, equals(1));
- expect(buffer.removeLast(), equals(0.0));
- expect(buffer.length, equals(0));
-
- for (double value in samples) {
- buffer.add(value);
- doubleEqual(buffer[buffer.length - 1], round(value));
- }
- expect(buffer.length, equals(samples.length));
-
- buffer.addAll(samples);
- expect(buffer.length, equals(samples.length * 2));
- for (int i = 0; i < samples.length; i++) {
- doubleEqual(buffer[i], buffer[samples.length + i]);
- }
-
- buffer.removeRange(samples.length, buffer.length);
- expect(buffer.length, equals(samples.length));
-
- buffer.insertAll(0, samples);
- expect(buffer.length, equals(samples.length * 2));
- for (int i = 0; i < samples.length; i++) {
- doubleEqual(buffer[i], buffer[samples.length + i]);
- }
-
- buffer.length = samples.length;
- expect(buffer.length, equals(samples.length));
-
- // TypedData.
- expect(buffer.elementSizeInBytes, equals(byteSize));
- expect(buffer.lengthInBytes, equals(byteSize * buffer.length));
- expect(buffer.offsetInBytes, equals(0));
-
- // Accessing the buffer works.
- // Accessing the underlying buffer works.
- buffer.length = 2;
- buffer[0] = samples[0];
- buffer[1] = samples[1];
- var bytes = new Uint8List.view(buffer.buffer);
- for (int i = 0; i < byteSize; i++) {
- int tmp = bytes[i];
- bytes[i] = bytes[byteSize + i];
- bytes[byteSize + i] = tmp;
- }
- doubleEqual(buffer[0], round(samples[1]));
- doubleEqual(buffer[1], round(samples[0]));
- });
-}
-
-testFloat32x4Buffer(List floatSamples) {
- List float4Samples = [];
- for (int i = 0; i < floatSamples.length - 3; i++) {
- float4Samples.add(new Float32x4(floatSamples[i],
- floatSamples[i + 1],
- floatSamples[i + 2],
- floatSamples[i + 3]));
- }
-
- void floatEquals(x, y) {
- if (y.isNaN) {
- expect(x.isNaN, isTrue);
- } else {
- expect(x, equals(y));
- }
- }
-
- void x4Equals(Float32x4 x, Float32x4 y) {
- floatEquals(x.x, y.x);
- floatEquals(x.y, y.y);
- floatEquals(x.z, y.z);
- floatEquals(x.w, y.w);
- }
-
- test("Float32x4Buffer", () {
- var buffer = new Float32x4Buffer(5);
- List<Float32x4> list = buffer;
-
- expect(buffer.length, equals(5));
- expect(buffer.elementSizeInBytes, equals(128 ~/ 8));
- expect(buffer.lengthInBytes, equals(5 * 128 ~/ 8));
- expect(buffer.offsetInBytes, equals(0));
-
- x4Equals(buffer[0], new Float32x4.zero());
- buffer.length = 0;
- expect(buffer.length, equals(0));
-
- for (var sample in float4Samples) {
- buffer.add(sample);
- x4Equals(buffer[buffer.length - 1], sample);
- }
- expect(buffer.length, equals(float4Samples.length));
-
- buffer.addAll(float4Samples);
- expect(buffer.length, equals(float4Samples.length * 2));
- for (int i = 0; i < float4Samples.length; i++) {
- x4Equals(buffer[i], buffer[float4Samples.length + i]);
- }
-
- buffer.removeRange(4, 4 + float4Samples.length);
- for (int i = 0; i < float4Samples.length; i++) {
- x4Equals(buffer[i], float4Samples[i]);
- }
-
- // Test underlying buffer.
- buffer.length = 1;
- buffer[0] = float4Samples[0]; // Does not contain NaN.
-
- Float32List floats = new Float32List.view(buffer.buffer);
- expect(floats[0], equals(buffer[0].x));
- expect(floats[1], equals(buffer[0].y));
- expect(floats[2], equals(buffer[0].z));
- expect(floats[3], equals(buffer[0].w));
- });
-}
-
-void testInt32x4Buffer(intSamples) {
- test("Int32x4Buffer", () {
- Function round = roundInt(32);
- int bits = 128;
- int bytes = 128 ~/ 8;
- Matcher equals32x4(Int32x4 expected) => new MatchesInt32x4(expected);
-
- var buffer = new Int32x4Buffer(0);
- List<Int32x4> list = buffer; // It's a List.
- expect(buffer.length, equals(0));
-
- expect(buffer.elementSizeInBytes, equals(bytes));
- expect(buffer.lengthInBytes, equals(0));
- expect(buffer.offsetInBytes, equals(0));
-
- Int32x4 sample = new Int32x4(-0x80000000, -1, 0, 0x7fffffff);
- buffer.add(sample);
- expect(buffer.length, equals(1));
- expect(buffer[0], equals32x4(sample));
-
- expect(buffer.elementSizeInBytes, equals(bytes));
- expect(buffer.lengthInBytes, equals(bytes));
- expect(buffer.offsetInBytes, equals(0));
-
- buffer.length = 0;
- expect(buffer.length, equals(0));
-
- var samples = intSamples
- .where((value) => value == round(value)) // Issue 15130
- .map((value) => new Int32x4(value, -value, ~value, ~-value))
- .toList();
- for (Int32x4 value in samples) {
- int length = buffer.length;
- buffer.add(value);
- expect(buffer.length, equals(length + 1));
- expect(buffer[length], equals32x4(value));
- }
-
- buffer.addAll(samples); // Add all the values at once.
- for (int i = 0; i < samples.length; i++) {
- expect(buffer[samples.length + i], equals32x4(buffer[i]));
- }
-
- // Remove range works and changes length.
- buffer.removeRange(samples.length, buffer.length);
- expect(buffer.length, equals(samples.length));
-
- // Accessing the underlying buffer works.
- buffer.length = 2;
- buffer[0] = new Int32x4(-80000000, 0x7fffffff, 0, -1);
- var byteBuffer = new Uint8List.view(buffer.buffer);
- int halfBytes = bytes ~/ 2;
- for (int i = 0; i < halfBytes; i++) {
- int tmp = byteBuffer[i];
- byteBuffer[i] = byteBuffer[halfBytes + i];
- byteBuffer[halfBytes + i] = tmp;
- }
- var result = new Int32x4(0, -1, -80000000, 0x7fffffff);
- expect(buffer[0], equals32x4(result));
- });
-}
-
-class MatchesInt32x4 extends Matcher {
- Int32x4 result;
- MatchesInt32x4(this.result);
- bool matches(item, Map matchState) {
- if (item is! Int32x4) return false;
- Int32x4 value = item;
- return result.x == value.x && result.y == value.y &&
- result.z == value.z && result.w == value.w;
- }
-
- Description describe(Description description) =>
- description.add('Int32x4.==');
-}
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 02ba3c4..7a6c70f 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -239,7 +239,10 @@
"*net/nss_memio.cc",
"*net/nss_memio.h",
"*root_certificates.cc",
- "*secure_socket.cc",
+ "*secure_socket_boringssl.cc",
+ "*secure_socket_boringssl.h",
+ "*secure_socket_macos.cc",
+ "*secure_socket_macos.h",
"*secure_socket.h",
"filter.cc",
"*io_service_unsupported.cc",
@@ -294,7 +297,10 @@
"*net/nss_memio.cc",
"*net/nss_memio.h",
"*root_certificates.cc",
- "*secure_socket.cc",
+ "*secure_socket_boringssl.cc",
+ "*secure_socket_boringssl.h",
+ "*secure_socket_macos.cc",
+ "*secure_socket_macos.h",
"*secure_socket.h",
"*filter_unsupported.cc",
"*io_service_unsupported.cc",
diff --git a/runtime/bin/bin.gypi b/runtime/bin/bin.gypi
index 0840125..5bdd606 100644
--- a/runtime/bin/bin.gypi
+++ b/runtime/bin/bin.gypi
@@ -225,7 +225,7 @@
['exclude', '_test\\.(cc|h)$'],
],
'conditions': [
- ['dart_io_support==1 and dart_io_secure_socket==1', {
+ ['OS != "mac" and dart_io_support==1 and dart_io_secure_socket==1', {
'dependencies': [
'../third_party/boringssl/boringssl_dart.gyp:boringssl',
],
@@ -260,6 +260,7 @@
'libraries': [
'$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
'$(SDKROOT)/System/Library/Frameworks/CoreServices.framework',
+ '$(SDKROOT)/System/Library/Frameworks/Security.framework',
],
},
}],
@@ -300,7 +301,7 @@
'bin/zlib.gyp:zlib_dart',
],
}],
- ['dart_io_support==1 and dart_io_secure_socket==1', {
+ ['OS != "mac" and dart_io_support==1 and dart_io_secure_socket==1', {
'dependencies': [
'../third_party/boringssl/boringssl_dart.gyp:boringssl',
],
@@ -332,6 +333,7 @@
'libraries': [
'$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
'$(SDKROOT)/System/Library/Frameworks/CoreServices.framework',
+ '$(SDKROOT)/System/Library/Frameworks/Security.framework',
],
},
}],
diff --git a/runtime/bin/builtin.cc b/runtime/bin/builtin.cc
index 021140b..272976f 100644
--- a/runtime/bin/builtin.cc
+++ b/runtime/bin/builtin.cc
@@ -38,10 +38,9 @@
// Prepend the patch library URI to form a unique script URI for the patch.
intptr_t len = snprintf(NULL, 0, "%s/%s", patch_uri, patch_files[j]);
- char* patch_filename = reinterpret_cast<char*>(malloc(len + 1));
+ char* patch_filename = DartUtils::ScopedCString(len + 1);
snprintf(patch_filename, len + 1, "%s/%s", patch_uri, patch_files[j]);
Dart_Handle patch_file_uri = DartUtils::NewString(patch_filename);
- free(patch_filename);
DART_CHECK_VALID(Dart_LibraryLoadPatch(library, patch_file_uri, patch_src));
}
diff --git a/runtime/bin/builtin.dart b/runtime/bin/builtin.dart
index 9a34b51..2f64b77 100644
--- a/runtime/bin/builtin.dart
+++ b/runtime/bin/builtin.dart
@@ -295,7 +295,18 @@
if (mapping == null) {
throw "No mapping for '$packageName' package when resolving '$uri'.";
}
- var path = uri.path.substring(packageName.length + 1);
+ var path;
+ if (uri.path.length > packageName.length) {
+ path = uri.path.substring(packageName.length + 1);
+ } else {
+ // Handle naked package resolution to the default package name:
+ // package:foo is equivalent to package:foo/foo.dart
+ assert(uri.path.length == packageName.length);
+ path = "$packageName.dart";
+ }
+ if (_traceLoading) {
+ _log("Path to be resolved in package: $path");
+ }
resolvedUri = mapping.resolve(path);
}
if (_traceLoading) {
@@ -754,7 +765,17 @@
}
assert(_packagesReady);
- var result = _resolvePackageUri(packageUri);
+ var result;
+ try {
+ result = _resolvePackageUri(packageUri);
+ } catch (e, s) {
+ // Any error during resolution will resolve this package as not mapped,
+ // which is indicated by a null return.
+ if (_traceLoading) {
+ _log("Exception ($e) when resolving package URI: $packageUri");
+ }
+ result = null;
+ }
if (_traceLoading) {
_log("Resolved '$packageUri' to '$result'");
}
diff --git a/runtime/bin/builtin_gen_snapshot.cc b/runtime/bin/builtin_gen_snapshot.cc
index c1263bd..17d4a57 100644
--- a/runtime/bin/builtin_gen_snapshot.cc
+++ b/runtime/bin/builtin_gen_snapshot.cc
@@ -41,7 +41,7 @@
int num_entries = sizeof(BuiltinEntries) / sizeof(struct NativeEntries);
for (int i = 0; i < num_entries; i++) {
struct NativeEntries* entry = &(BuiltinEntries[i]);
- if (!strcmp(function_name, entry->name_) &&
+ if ((strcmp(function_name, entry->name_) == 0) &&
(entry->argument_count_ == argument_count)) {
return reinterpret_cast<Dart_NativeFunction>(entry->function_);
}
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc
index 5ba5637..ba45a73 100644
--- a/runtime/bin/builtin_natives.cc
+++ b/runtime/bin/builtin_natives.cc
@@ -60,7 +60,7 @@
int num_entries = sizeof(BuiltinEntries) / sizeof(struct NativeEntries);
for (int i = 0; i < num_entries; i++) {
struct NativeEntries* entry = &(BuiltinEntries[i]);
- if (!strcmp(function_name, entry->name_) &&
+ if ((strcmp(function_name, entry->name_) == 0) &&
(entry->argument_count_ == argument_count)) {
return reinterpret_cast<Dart_NativeFunction>(entry->function_);
}
@@ -88,7 +88,9 @@
uint8_t* chars = NULL;
Dart_Handle str = Dart_GetNativeArgument(args, 0);
Dart_Handle result = Dart_StringToUTF8(str, &chars, &length);
- if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
// Uses fwrite to support printing NUL bytes.
intptr_t res = fwrite(chars, 1, length, stdout);
diff --git a/runtime/bin/builtin_nolib.cc b/runtime/bin/builtin_nolib.cc
index fb4cf02..428927f 100644
--- a/runtime/bin/builtin_nolib.cc
+++ b/runtime/bin/builtin_nolib.cc
@@ -10,7 +10,6 @@
#include "bin/dartutils.h"
#include "bin/io_natives.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/crypto_android.cc b/runtime/bin/crypto_android.cc
index be91d4e..7a970d0 100644
--- a/runtime/bin/crypto_android.cc
+++ b/runtime/bin/crypto_android.cc
@@ -8,8 +8,8 @@
#include <errno.h> // NOLINT
#include <fcntl.h> // NOLINT
-#include "bin/fdutils.h"
#include "bin/crypto.h"
+#include "bin/fdutils.h"
#include "platform/signal_blocker.h"
namespace dart {
diff --git a/runtime/bin/crypto_linux.cc b/runtime/bin/crypto_linux.cc
index 875ec8e..c2e4ccd 100644
--- a/runtime/bin/crypto_linux.cc
+++ b/runtime/bin/crypto_linux.cc
@@ -8,8 +8,8 @@
#include <errno.h> // NOLINT
#include <fcntl.h> // NOLINT
-#include "bin/fdutils.h"
#include "bin/crypto.h"
+#include "bin/fdutils.h"
#include "platform/signal_blocker.h"
namespace dart {
diff --git a/runtime/bin/crypto_macos.cc b/runtime/bin/crypto_macos.cc
index 8a27245..7bea2ae 100644
--- a/runtime/bin/crypto_macos.cc
+++ b/runtime/bin/crypto_macos.cc
@@ -8,8 +8,8 @@
#include <errno.h> // NOLINT
#include <fcntl.h> // NOLINT
-#include "bin/fdutils.h"
#include "bin/crypto.h"
+#include "bin/fdutils.h"
#include "platform/signal_blocker.h"
namespace dart {
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc
index 3791197..c2f3dc8 100644
--- a/runtime/bin/directory.cc
+++ b/runtime/bin/directory.cc
@@ -8,7 +8,6 @@
#include "include/dart_api.h"
#include "platform/assert.h"
-
namespace dart {
namespace bin {
@@ -28,7 +27,7 @@
if (argc == 1) {
path = Dart_GetNativeArgument(args, 0);
}
- if (argc != 1 || !Dart_IsString(path)) {
+ if ((argc != 1) || !Dart_IsString(path)) {
Dart_SetReturnValue(args, DartUtils::NewDartArgumentError(NULL));
} else {
if (Directory::SetCurrent(DartUtils::GetStringValue(path))) {
@@ -66,8 +65,7 @@
}
-void FUNCTION_NAME(Directory_SystemTemp)(
- Dart_NativeArguments args) {
+void FUNCTION_NAME(Directory_SystemTemp)(Dart_NativeArguments args) {
const char* result = Directory::SystemTemp();
Dart_SetReturnValue(args, DartUtils::NewString(result));
}
@@ -127,7 +125,9 @@
Dart_Null(),
0,
NULL);
- if (Dart_IsError(results)) Dart_PropagateError(results);
+ if (Dart_IsError(results)) {
+ Dart_PropagateError(results);
+ }
SyncDirectoryListing sync_listing(results,
DartUtils::GetStringValue(path),
DartUtils::GetBooleanValue(recursive),
@@ -138,7 +138,7 @@
CObject* Directory::CreateRequest(const CObjectArray& request) {
- if (request.Length() == 1 && request[0]->IsString()) {
+ if ((request.Length() == 1) && request[0]->IsString()) {
CObjectString path(request[0]);
if (Directory::Create(path.CString())) {
return CObject::True();
@@ -151,7 +151,8 @@
CObject* Directory::DeleteRequest(const CObjectArray& request) {
- if (request.Length() == 2 && request[0]->IsString() && request[1]->IsBool()) {
+ if ((request.Length() == 2) &&
+ request[0]->IsString() && request[1]->IsBool()) {
CObjectString path(request[0]);
CObjectBool recursive(request[1]);
if (Directory::Delete(path.CString(), recursive.Value())) {
@@ -167,7 +168,7 @@
CObject* Directory::ExistsRequest(const CObjectArray& request) {
static const int kExists = 1;
static const int kDoesNotExist = 0;
- if (request.Length() == 1 && request[0]->IsString()) {
+ if ((request.Length() == 1) && request[0]->IsString()) {
CObjectString path(request[0]);
Directory::ExistsResult result = Directory::Exists(path.CString());
if (result == Directory::EXISTS) {
@@ -183,7 +184,7 @@
CObject* Directory::CreateTempRequest(const CObjectArray& request) {
- if (request.Length() == 1 && request[0]->IsString()) {
+ if ((request.Length() == 1) && request[0]->IsString()) {
CObjectString path(request[0]);
const char* result = Directory::CreateTemp(path.CString());
if (result != NULL) {
@@ -209,7 +210,7 @@
CObject* Directory::ListStartRequest(const CObjectArray& request) {
- if (request.Length() == 3 &&
+ if ((request.Length() == 3) &&
request[0]->IsString() &&
request[1]->IsBool() &&
request[2]->IsBool()) {
@@ -273,7 +274,7 @@
CObject* Directory::RenameRequest(const CObjectArray& request) {
- if (request.Length() == 2 &&
+ if ((request.Length() == 2) &&
request[0]->IsString() &&
request[1]->IsString()) {
CObjectString path(request[0]);
diff --git a/runtime/bin/directory.h b/runtime/bin/directory.h
index e37aa76..7a1c5d1 100644
--- a/runtime/bin/directory.h
+++ b/runtime/bin/directory.h
@@ -10,7 +10,6 @@
#include "bin/thread.h"
#include "platform/globals.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/directory_android.cc b/runtime/bin/directory_android.cc
index 6571f18..95f42da 100644
--- a/runtime/bin/directory_android.cc
+++ b/runtime/bin/directory_android.cc
@@ -82,8 +82,8 @@
// A linked list of symbolic links, with their unique file system identifiers.
// These are scanned to detect loops while doing a recursive directory listing.
struct LinkList {
- dev_t dev;
- ino_t ino;
+ uint64_t dev;
+ uint64_t ino;
LinkList* next;
};
@@ -366,9 +366,8 @@
char* Directory::CurrentNoScope() {
// Android's getcwd adheres closely to the POSIX standard. It won't
// allocate memory. We need to make our own copy.
-
char buffer[PATH_MAX];
- if (NULL == getcwd(buffer, PATH_MAX)) {
+ if (getcwd(buffer, PATH_MAX) == NULL) {
return NULL;
}
@@ -377,15 +376,17 @@
const char* Directory::Current() {
- char* result = DartUtils::ScopedCString(PATH_MAX);
- ASSERT(result != NULL);
- return getcwd(result, PATH_MAX);
+ char buffer[PATH_MAX];
+ if (getcwd(buffer, PATH_MAX) == NULL) {
+ return NULL;
+ }
+ return DartUtils::ScopedCopyCString(buffer);
}
bool Directory::SetCurrent(const char* path) {
int result = NO_RETRY_EXPECTED(chdir(path));
- return result == 0;
+ return (result == 0);
}
diff --git a/runtime/bin/directory_linux.cc b/runtime/bin/directory_linux.cc
index 8430134..d099b0e 100644
--- a/runtime/bin/directory_linux.cc
+++ b/runtime/bin/directory_linux.cc
@@ -366,11 +366,7 @@
char* Directory::CurrentNoScope() {
- char buffer[PATH_MAX];
- if (getcwd(buffer, PATH_MAX) == NULL) {
- return NULL;
- }
- return strdup(buffer);
+ return getcwd(NULL, 0);
}
@@ -384,7 +380,7 @@
bool Directory::SetCurrent(const char* path) {
- return NO_RETRY_EXPECTED(chdir(path)) == 0;
+ return (NO_RETRY_EXPECTED(chdir(path)) == 0);
}
@@ -469,7 +465,7 @@
if (exists != EXISTS) {
return false;
}
- return NO_RETRY_EXPECTED(rename(path, new_path)) == 0;
+ return (NO_RETRY_EXPECTED(rename(path, new_path)) == 0);
}
} // namespace bin
diff --git a/runtime/bin/directory_macos.cc b/runtime/bin/directory_macos.cc
index a10b20a..5c0f5a6 100644
--- a/runtime/bin/directory_macos.cc
+++ b/runtime/bin/directory_macos.cc
@@ -369,15 +369,17 @@
const char* Directory::Current() {
- char* result = DartUtils::ScopedCString(PATH_MAX);
- ASSERT(result != NULL);
- return getcwd(result, PATH_MAX);
+ char buffer[PATH_MAX];
+ if (getcwd(buffer, PATH_MAX) == NULL) {
+ return NULL;
+ }
+ return DartUtils::ScopedCopyCString(buffer);
}
bool Directory::SetCurrent(const char* path) {
int result = NO_RETRY_EXPECTED(chdir(path));
- return result == 0;
+ return (result == 0);
}
diff --git a/runtime/bin/embedded_dart_io.h b/runtime/bin/embedded_dart_io.h
index 4d7dbae..a5b069d 100644
--- a/runtime/bin/embedded_dart_io.h
+++ b/runtime/bin/embedded_dart_io.h
@@ -23,7 +23,6 @@
// Should Stderr events be captured?
bool ShouldCaptureStderr();
-
} // namespace bin
} // namespace dart
diff --git a/runtime/bin/eventhandler.cc b/runtime/bin/eventhandler.cc
index bb9a7fe..704cc85 100644
--- a/runtime/bin/eventhandler.cc
+++ b/runtime/bin/eventhandler.cc
@@ -10,11 +10,9 @@
#include "include/dart_api.h"
-
namespace dart {
namespace bin {
-
void TimeoutQueue::UpdateTimeout(Dart_Port port, int64_t timeout) {
// Find port if present.
Timeout* last = NULL;
@@ -47,8 +45,8 @@
next_timeout_ = NULL;
current = timeouts_;
while (current != NULL) {
- if (next_timeout_ == NULL ||
- current->timeout() < next_timeout_->timeout()) {
+ if ((next_timeout_ == NULL) ||
+ (current->timeout() < next_timeout_->timeout())) {
next_timeout_ = current;
}
current = current->next();
@@ -78,7 +76,9 @@
void EventHandler::Stop() {
- if (event_handler == NULL) return;
+ if (event_handler == NULL) {
+ return;
+ }
// Wait until it has stopped.
{
@@ -101,7 +101,9 @@
EventHandlerImplementation* EventHandler::delegate() {
- if (event_handler == NULL) return NULL;
+ if (event_handler == NULL) {
+ return NULL;
+ }
return &event_handler->delegate_;
}
diff --git a/runtime/bin/eventhandler.h b/runtime/bin/eventhandler.h
index c110d34..34f6c65 100644
--- a/runtime/bin/eventhandler.h
+++ b/runtime/bin/eventhandler.h
@@ -108,6 +108,8 @@
private:
Timeout* next_timeout_;
Timeout* timeouts_;
+
+ DISALLOW_COPY_AND_ASSIGN(TimeoutQueue);
};
@@ -221,6 +223,8 @@
};
Entry* head_;
+
+ DISALLOW_COPY_AND_ASSIGN(CircularLinkedList);
};
@@ -268,6 +272,9 @@
protected:
intptr_t fd_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DescriptorInfoBase);
};
@@ -281,7 +288,7 @@
static const int kTokenCount = 16;
public:
- explicit DescriptorInfoSingleMixin(intptr_t fd, bool disable_tokens)
+ DescriptorInfoSingleMixin(intptr_t fd, bool disable_tokens)
: DI(fd), port_(0), tokens_(kTokenCount), mask_(0),
disable_tokens_(disable_tokens) {}
@@ -356,6 +363,8 @@
int tokens_;
intptr_t mask_;
bool disable_tokens_;
+
+ DISALLOW_COPY_AND_ASSIGN(DescriptorInfoSingleMixin);
};
@@ -400,7 +409,7 @@
};
public:
- explicit DescriptorInfoMultipleMixin(intptr_t fd, bool disable_tokens)
+ DescriptorInfoMultipleMixin(intptr_t fd, bool disable_tokens)
: DI(fd), tokens_map_(&SamePortValue, kTokenCount),
disable_tokens_(disable_tokens) {}
@@ -541,7 +550,7 @@
pentry->token_count--;
}
- if (was_ready && pentry->token_count <= 0) {
+ if (was_ready && (pentry->token_count <= 0)) {
active_readers_.Remove(pentry);
}
}
@@ -586,8 +595,9 @@
HashMap tokens_map_;
bool disable_tokens_;
-};
+ DISALLOW_COPY_AND_ASSIGN(DescriptorInfoMultipleMixin);
+};
} // namespace bin
} // namespace dart
@@ -610,6 +620,7 @@
class EventHandler {
public:
+ EventHandler() {}
void SendData(intptr_t id, Dart_Port dart_port, int64_t data) {
delegate_.SendData(id, dart_port, data);
}
@@ -635,6 +646,8 @@
private:
friend class EventHandlerImplementation;
EventHandlerImplementation delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(EventHandler);
};
} // namespace bin
diff --git a/runtime/bin/eventhandler_android.cc b/runtime/bin/eventhandler_android.cc
index 6fdabfb..5daeb78 100644
--- a/runtime/bin/eventhandler_android.cc
+++ b/runtime/bin/eventhandler_android.cc
@@ -9,13 +9,13 @@
#include "bin/eventhandler_android.h"
#include <errno.h> // NOLINT
+#include <fcntl.h> // NOLINT
#include <pthread.h> // NOLINT
#include <stdio.h> // NOLINT
#include <string.h> // NOLINT
#include <sys/epoll.h> // NOLINT
#include <sys/stat.h> // NOLINT
#include <unistd.h> // NOLINT
-#include <fcntl.h> // NOLINT
#include "bin/dartutils.h"
#include "bin/fdutils.h"
@@ -27,17 +27,14 @@
#include "platform/hashmap.h"
#include "platform/utils.h"
-
// Android doesn't define EPOLLRDHUP.
#if !defined(EPOLLRDHUP)
#define EPOLLRDHUP 0x2000
#endif // !defined(EPOLLRDHUP)
-
namespace dart {
namespace bin {
-
intptr_t DescriptorInfo::GetPollEvents() {
// Do not ask for EPOLLERR and EPOLLHUP explicitly as they are
// triggered anyway.
@@ -129,11 +126,11 @@
void EventHandlerImplementation::UpdateEpollInstance(intptr_t old_mask,
DescriptorInfo *di) {
intptr_t new_mask = di->Mask();
- if (old_mask != 0 && new_mask == 0) {
+ if ((old_mask != 0) && (new_mask == 0)) {
RemoveFromEpollInstance(epoll_fd_, di);
- } else if (old_mask == 0 && new_mask != 0) {
+ } else if ((old_mask == 0) && (new_mask != 0)) {
AddToEpollInstance(epoll_fd_, di);
- } else if (old_mask != 0 && new_mask != 0 && old_mask != new_mask) {
+ } else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) {
ASSERT(!di->IsListeningSocket());
RemoveFromEpollInstance(epoll_fd_, di);
AddToEpollInstance(epoll_fd_, di);
@@ -264,15 +261,28 @@
}
}
+
#ifdef DEBUG_POLL
static void PrintEventMask(intptr_t fd, intptr_t events) {
Log::Print("%d ", fd);
- if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN ");
- if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI ");
- if ((events & EPOLLOUT) != 0) Log::Print("EPOLLOUT ");
- if ((events & EPOLLERR) != 0) Log::Print("EPOLLERR ");
- if ((events & EPOLLHUP) != 0) Log::Print("EPOLLHUP ");
- if ((events & EPOLLRDHUP) != 0) Log::Print("EPOLLRDHUP ");
+ if ((events & EPOLLIN) != 0) {
+ Log::Print("EPOLLIN ");
+ }
+ if ((events & EPOLLPRI) != 0) {
+ Log::Print("EPOLLPRI ");
+ }
+ if ((events & EPOLLOUT) != 0) {
+ Log::Print("EPOLLOUT ");
+ }
+ if ((events & EPOLLERR) != 0) {
+ Log::Print("EPOLLERR ");
+ }
+ if ((events & EPOLLHUP) != 0) {
+ Log::Print("EPOLLHUP ");
+ }
+ if ((events & EPOLLRDHUP) != 0) {
+ Log::Print("EPOLLRDHUP ");
+ }
int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT |
EPOLLERR | EPOLLHUP | EPOLLRDHUP;
if ((events & ~all_events) != 0) {
@@ -284,19 +294,26 @@
}
#endif
+
intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events,
DescriptorInfo* di) {
#ifdef DEBUG_POLL
PrintEventMask(di->fd(), events);
#endif
- if (events & EPOLLERR) {
+ if ((events & EPOLLERR) != 0) {
// Return error only if EPOLLIN is present.
- return (events & EPOLLIN) ? (1 << kErrorEvent) : 0;
+ return ((events & EPOLLIN) != 0) ? (1 << kErrorEvent) : 0;
}
intptr_t event_mask = 0;
- if (events & EPOLLIN) event_mask |= (1 << kInEvent);
- if (events & EPOLLOUT) event_mask |= (1 << kOutEvent);
- if (events & (EPOLLHUP | EPOLLRDHUP)) event_mask |= (1 << kCloseEvent);
+ if ((events & EPOLLIN) != 0) {
+ event_mask |= (1 << kInEvent);
+ }
+ if ((events & EPOLLOUT) != 0) {
+ event_mask |= (1 << kOutEvent);
+ }
+ if ((events & (EPOLLHUP | EPOLLRDHUP)) != 0) {
+ event_mask |= (1 << kCloseEvent);
+ }
return event_mask;
}
@@ -360,8 +377,10 @@
while (!handler_impl->shutdown_) {
int64_t millis = handler_impl->GetTimeout();
- ASSERT(millis == kInfinityTimeout || millis >= 0);
- if (millis > kMaxInt32) millis = kMaxInt32;
+ ASSERT((millis == kInfinityTimeout) || (millis >= 0));
+ if (millis > kMaxInt32) {
+ millis = kMaxInt32;
+ }
intptr_t result = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(
epoll_wait(handler_impl->epoll_fd_, events, kMaxEvents, millis));
ASSERT(EAGAIN == EWOULDBLOCK);
diff --git a/runtime/bin/eventhandler_android.h b/runtime/bin/eventhandler_android.h
index ee10016..8841861 100644
--- a/runtime/bin/eventhandler_android.h
+++ b/runtime/bin/eventhandler_android.h
@@ -18,7 +18,6 @@
#include "platform/hashmap.h"
#include "platform/signal_blocker.h"
-
namespace dart {
namespace bin {
@@ -34,6 +33,9 @@
VOID_TEMP_FAILURE_RETRY(close(fd_));
fd_ = -1;
}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DescriptorInfo);
};
@@ -43,6 +45,9 @@
explicit DescriptorInfoSingle(intptr_t fd)
: DescriptorInfoSingleMixin(fd, false) {}
virtual ~DescriptorInfoSingle() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DescriptorInfoSingle);
};
@@ -52,6 +57,9 @@
explicit DescriptorInfoMultiple(intptr_t fd)
: DescriptorInfoMultipleMixin(fd, false) {}
virtual ~DescriptorInfoMultiple() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DescriptorInfoMultiple);
};
@@ -86,6 +94,8 @@
bool shutdown_;
int interrupt_fds_[2];
int epoll_fd_;
+
+ DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
};
} // namespace bin
diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc
index 4c605ce..6b69ffc 100644
--- a/runtime/bin/eventhandler_linux.cc
+++ b/runtime/bin/eventhandler_linux.cc
@@ -9,6 +9,7 @@
#include "bin/eventhandler_linux.h"
#include <errno.h> // NOLINT
+#include <fcntl.h> // NOLINT
#include <pthread.h> // NOLINT
#include <stdio.h> // NOLINT
#include <string.h> // NOLINT
@@ -16,7 +17,6 @@
#include <sys/stat.h> // NOLINT
#include <sys/timerfd.h> // NOLINT
#include <unistd.h> // NOLINT
-#include <fcntl.h> // NOLINT
#include "bin/dartutils.h"
#include "bin/fdutils.h"
@@ -26,11 +26,9 @@
#include "bin/thread.h"
#include "platform/utils.h"
-
namespace dart {
namespace bin {
-
intptr_t DescriptorInfo::GetPollEvents() {
// Do not ask for EPOLLERR and EPOLLHUP explicitly as they are
// triggered anyway.
@@ -138,11 +136,11 @@
void EventHandlerImplementation::UpdateEpollInstance(intptr_t old_mask,
DescriptorInfo *di) {
intptr_t new_mask = di->Mask();
- if (old_mask != 0 && new_mask == 0) {
+ if ((old_mask != 0) && (new_mask == 0)) {
RemoveFromEpollInstance(epoll_fd_, di);
- } else if (old_mask == 0 && new_mask != 0) {
+ } else if ((old_mask == 0) && (new_mask != 0)) {
AddToEpollInstance(epoll_fd_, di);
- } else if (old_mask != 0 && new_mask != 0 && old_mask != new_mask) {
+ } else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) {
ASSERT(!di->IsListeningSocket());
RemoveFromEpollInstance(epoll_fd_, di);
AddToEpollInstance(epoll_fd_, di);
@@ -156,8 +154,7 @@
HashMap::Entry* entry = socket_map_.Lookup(
GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true);
ASSERT(entry != NULL);
- DescriptorInfo* di =
- reinterpret_cast<DescriptorInfo*>(entry->value);
+ DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(entry->value);
if (di == NULL) {
// If there is no data in the hash map for this file descriptor a
// new DescriptorInfo for the file descriptor is inserted.
@@ -282,15 +279,28 @@
}
}
+
#ifdef DEBUG_POLL
static void PrintEventMask(intptr_t fd, intptr_t events) {
Log::Print("%d ", fd);
- if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN ");
- if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI ");
- if ((events & EPOLLOUT) != 0) Log::Print("EPOLLOUT ");
- if ((events & EPOLLERR) != 0) Log::Print("EPOLLERR ");
- if ((events & EPOLLHUP) != 0) Log::Print("EPOLLHUP ");
- if ((events & EPOLLRDHUP) != 0) Log::Print("EPOLLRDHUP ");
+ if ((events & EPOLLIN) != 0) {
+ Log::Print("EPOLLIN ");
+ }
+ if ((events & EPOLLPRI) != 0) {
+ Log::Print("EPOLLPRI ");
+ }
+ if ((events & EPOLLOUT) != 0) {
+ Log::Print("EPOLLOUT ");
+ }
+ if ((events & EPOLLERR) != 0) {
+ Log::Print("EPOLLERR ");
+ }
+ if ((events & EPOLLHUP) != 0) {
+ Log::Print("EPOLLHUP ");
+ }
+ if ((events & EPOLLRDHUP) != 0) {
+ Log::Print("EPOLLRDHUP ");
+ }
int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT |
EPOLLERR | EPOLLHUP | EPOLLRDHUP;
if ((events & ~all_events) != 0) {
@@ -302,19 +312,26 @@
}
#endif
+
intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events,
DescriptorInfo* di) {
#ifdef DEBUG_POLL
PrintEventMask(di->fd(), events);
#endif
- if (events & EPOLLERR) {
+ if ((events & EPOLLERR) != 0) {
// Return error only if EPOLLIN is present.
- return (events & EPOLLIN) ? (1 << kErrorEvent) : 0;
+ return ((events & EPOLLIN) != 0) ? (1 << kErrorEvent) : 0;
}
intptr_t event_mask = 0;
- if (events & EPOLLIN) event_mask |= (1 << kInEvent);
- if (events & EPOLLOUT) event_mask |= (1 << kOutEvent);
- if (events & (EPOLLHUP | EPOLLRDHUP)) event_mask |= (1 << kCloseEvent);
+ if ((events & EPOLLIN) != 0) {
+ event_mask |= (1 << kInEvent);
+ }
+ if ((events & EPOLLOUT) != 0) {
+ event_mask |= (1 << kOutEvent);
+ }
+ if ((events & (EPOLLHUP | EPOLLRDHUP)) != 0) {
+ event_mask |= (1 << kCloseEvent);
+ }
return event_mask;
}
diff --git a/runtime/bin/eventhandler_linux.h b/runtime/bin/eventhandler_linux.h
index 099bef5..dd87c22 100644
--- a/runtime/bin/eventhandler_linux.h
+++ b/runtime/bin/eventhandler_linux.h
@@ -33,6 +33,9 @@
VOID_TEMP_FAILURE_RETRY(close(fd_));
fd_ = -1;
}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DescriptorInfo);
};
@@ -42,6 +45,9 @@
explicit DescriptorInfoSingle(intptr_t fd)
: DescriptorInfoSingleMixin(fd, false) {}
virtual ~DescriptorInfoSingle() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DescriptorInfoSingle);
};
@@ -51,6 +57,9 @@
explicit DescriptorInfoMultiple(intptr_t fd)
: DescriptorInfoMultipleMixin(fd, false) {}
virtual ~DescriptorInfoMultiple() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DescriptorInfoMultiple);
};
@@ -84,6 +93,8 @@
int interrupt_fds_[2];
int epoll_fd_;
int timer_fd_;
+
+ DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
};
} // namespace bin
diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc
index faf471b..8d4c683 100644
--- a/runtime/bin/eventhandler_macos.cc
+++ b/runtime/bin/eventhandler_macos.cc
@@ -9,12 +9,12 @@
#include "bin/eventhandler_macos.h"
#include <errno.h> // NOLINT
+#include <fcntl.h> // NOLINT
#include <pthread.h> // NOLINT
#include <stdio.h> // NOLINT
#include <string.h> // NOLINT
#include <sys/event.h> // NOLINT
#include <unistd.h> // NOLINT
-#include <fcntl.h> // NOLINT
#include "bin/dartutils.h"
#include "bin/fdutils.h"
@@ -26,11 +26,9 @@
#include "platform/hashmap.h"
#include "platform/utils.h"
-
namespace dart {
namespace bin {
-
bool DescriptorInfo::HasReadEvent() {
return (Mask() & (1 << kInEvent)) != 0;
}
@@ -43,7 +41,9 @@
// Unregister the file descriptor for a SocketData structure with kqueue.
static void RemoveFromKqueue(intptr_t kqueue_fd_, DescriptorInfo* di) {
- if (!di->tracked_by_kqueue()) return;
+ if (!di->tracked_by_kqueue()) {
+ return;
+ }
static const intptr_t kMaxChanges = 2;
struct kevent events[kMaxChanges];
EV_SET(events, di->fd(), EVFILT_READ, EV_DELETE, 0, 0, NULL);
@@ -150,9 +150,9 @@
intptr_t new_mask = di->Mask();
if (old_mask != 0 && new_mask == 0) {
RemoveFromKqueue(kqueue_fd_, di);
- } else if (old_mask == 0 && new_mask != 0) {
+ } else if ((old_mask == 0) && (new_mask != 0)) {
AddToKqueue(kqueue_fd_, di);
- } else if (old_mask != 0 && new_mask != 0 && old_mask != new_mask) {
+ } else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) {
ASSERT(!di->IsListeningSocket());
RemoveFromKqueue(kqueue_fd_, di);
AddToKqueue(kqueue_fd_, di);
@@ -281,22 +281,39 @@
}
}
+
#ifdef DEBUG_KQUEUE
static void PrintEventMask(intptr_t fd, struct kevent* event) {
Log::Print("%d ", static_cast<int>(fd));
+
Log::Print("filter=0x%x:", event->filter);
- if (event->filter == EVFILT_READ) Log::Print("EVFILT_READ ");
- if (event->filter == EVFILT_WRITE) Log::Print("EVFILT_WRITE ");
+ if (event->filter == EVFILT_READ) {
+ Log::Print("EVFILT_READ ");
+ }
+ if (event->filter == EVFILT_WRITE) {
+ Log::Print("EVFILT_WRITE ");
+ }
+
Log::Print("flags: %x: ", event->flags);
- if ((event->flags & EV_EOF) != 0) Log::Print("EV_EOF ");
- if ((event->flags & EV_ERROR) != 0) Log::Print("EV_ERROR ");
- if ((event->flags & EV_CLEAR) != 0) Log::Print("EV_CLEAR ");
- if ((event->flags & EV_ADD) != 0) Log::Print("EV_ADD ");
- if ((event->flags & EV_DELETE) != 0) Log::Print("EV_DELETE ");
+ if ((event->flags & EV_EOF) != 0) {
+ Log::Print("EV_EOF ");
+ }
+ if ((event->flags & EV_ERROR) != 0) {
+ Log::Print("EV_ERROR ");
+ }
+ if ((event->flags & EV_CLEAR) != 0) {
+ Log::Print("EV_CLEAR ");
+ }
+ if ((event->flags & EV_ADD) != 0) {
+ Log::Print("EV_ADD ");
+ }
+ if ((event->flags & EV_DELETE) != 0) {
+ Log::Print("EV_DELETE ");
+ }
+
Log::Print("- fflags: %d ", event->fflags);
Log::Print("- data: %ld ", event->data);
- Log::Print("(available %d) ",
- static_cast<int>(FDUtils::AvailableBytes(fd)));
+ Log::Print("(available %d) ", static_cast<int>(FDUtils::AvailableBytes(fd)));
Log::Print("\n");
}
#endif
@@ -319,7 +336,9 @@
event_mask |= (1 << kCloseEvent);
}
}
- if (event_mask == 0) event_mask |= (1 << kInEvent);
+ if (event_mask == 0) {
+ event_mask |= (1 << kInEvent);
+ }
} else {
UNREACHABLE();
}
@@ -421,7 +440,9 @@
while (!handler_impl->shutdown_) {
int64_t millis = handler_impl->GetTimeout();
ASSERT(millis == kInfinityTimeout || millis >= 0);
- if (millis > kMaxInt32) millis = kMaxInt32;
+ if (millis > kMaxInt32) {
+ millis = kMaxInt32;
+ }
// NULL pointer timespec for infinite timeout.
ASSERT(kInfinityTimeout < 0);
struct timespec* timeout = NULL;
diff --git a/runtime/bin/eventhandler_macos.h b/runtime/bin/eventhandler_macos.h
index 48b0b96..b846594 100644
--- a/runtime/bin/eventhandler_macos.h
+++ b/runtime/bin/eventhandler_macos.h
@@ -47,6 +47,9 @@
protected:
bool tracked_by_kqueue_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DescriptorInfo);
};
@@ -56,6 +59,9 @@
explicit DescriptorInfoSingle(intptr_t fd)
: DescriptorInfoSingleMixin(fd, false) {}
virtual ~DescriptorInfoSingle() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DescriptorInfoSingle);
};
@@ -65,6 +71,9 @@
explicit DescriptorInfoMultiple(intptr_t fd)
: DescriptorInfoMultipleMixin(fd, false) {}
virtual ~DescriptorInfoMultiple() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DescriptorInfoMultiple);
};
@@ -99,6 +108,8 @@
bool shutdown_;
int interrupt_fds_[2];
int kqueue_fd_;
+
+ DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
};
} // namespace bin
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index 8e0adc5..2698253 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -8,11 +8,11 @@
#include "bin/eventhandler.h"
#include "bin/eventhandler_win.h"
+#include <fcntl.h> // NOLINT
+#include <io.h> // NOLINT
+#include <mswsock.h> // NOLINT
#include <winsock2.h> // NOLINT
#include <ws2tcpip.h> // NOLINT
-#include <mswsock.h> // NOLINT
-#include <io.h> // NOLINT
-#include <fcntl.h> // NOLINT
#include "bin/builtin.h"
#include "bin/dartutils.h"
@@ -140,10 +140,7 @@
completion_port,
reinterpret_cast<ULONG_PTR>(this),
0);
- if (completion_port_ == NULL) {
- return false;
- }
- return true;
+ return (completion_port_ != NULL);
}
@@ -307,7 +304,7 @@
buffer->GetBufferSize(),
NULL,
buffer->GetCleanOverlapped());
- if (ok || GetLastError() == ERROR_IO_PENDING) {
+ if (ok || (GetLastError() == ERROR_IO_PENDING)) {
// Completing asynchronously.
pending_read_ = buffer;
return true;
@@ -347,7 +344,7 @@
buffer->GetBufferSize(),
NULL,
buffer->GetCleanOverlapped());
- if (ok || GetLastError() == ERROR_IO_PENDING) {
+ if (ok || (GetLastError() == ERROR_IO_PENDING)) {
// Completing asynchronously.
pending_write_ = buffer;
return true;
@@ -394,7 +391,7 @@
void FileHandle::EnsureInitialized(EventHandlerImplementation* event_handler) {
MonitorLocker ml(monitor_);
event_handler_ = event_handler;
- if (SupportsOverlappedIO() && completion_port_ == INVALID_HANDLE_VALUE) {
+ if (SupportsOverlappedIO() && (completion_port_ == INVALID_HANDLE_VALUE)) {
CreateCompletionPort(event_handler_->completion_port());
}
}
@@ -416,14 +413,16 @@
bool DirectoryWatchHandle::IsClosed() {
- return IsClosing() && pending_read_ == NULL;
+ return IsClosing() && (pending_read_ == NULL);
}
bool DirectoryWatchHandle::IssueRead() {
// It may have been started before, as we start the directory-handler when
// we create it.
- if (pending_read_ != NULL || data_ready_ != NULL) return true;
+ if ((pending_read_ != NULL) || (data_ready_ != NULL)) {
+ return true;
+ }
OverlappedBuffer* buffer = OverlappedBuffer::AllocateReadBuffer(kBufferSize);
ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
BOOL ok = ReadDirectoryChangesW(handle_,
@@ -434,7 +433,7 @@
NULL,
buffer->GetCleanOverlapped(),
NULL);
- if (ok || GetLastError() == ERROR_IO_PENDING) {
+ if (ok || (GetLastError() == ERROR_IO_PENDING)) {
// Completing asynchronously.
pending_read_ = buffer;
return true;
@@ -481,10 +480,7 @@
&bytes,
NULL,
NULL);
- if (status == SOCKET_ERROR) {
- return false;
- }
- return true;
+ return (status != SOCKET_ERROR);
}
@@ -603,7 +599,9 @@
if (accepted_head_ != NULL) {
result = accepted_head_;
accepted_head_ = accepted_head_->next();
- if (accepted_head_ == NULL) accepted_tail_ = NULL;
+ if (accepted_head_ == NULL) {
+ accepted_tail_ = NULL;
+ }
result->set_next(NULL);
accepted_count_--;
}
@@ -641,7 +639,9 @@
intptr_t Handle::Available() {
MonitorLocker ml(monitor_);
- if (data_ready_ == NULL) return 0;
+ if (data_ready_ == NULL) {
+ return 0;
+ }
ASSERT(!data_ready_->IsEmpty());
return data_ready_->GetRemainingLength();
}
@@ -649,13 +649,17 @@
intptr_t Handle::Read(void* buffer, intptr_t num_bytes) {
MonitorLocker ml(monitor_);
- if (data_ready_ == NULL) return 0;
+ if (data_ready_ == NULL) {
+ return 0;
+ }
num_bytes = data_ready_->Read(
buffer, Utils::Minimum<intptr_t>(num_bytes, INT_MAX));
if (data_ready_->IsEmpty()) {
OverlappedBuffer::DisposeBuffer(data_ready_);
data_ready_ = NULL;
- if (!IsClosing() && !IsClosedRead()) IssueRead();
+ if (!IsClosing() && !IsClosedRead()) {
+ IssueRead();
+ }
}
return num_bytes;
}
@@ -664,7 +668,9 @@
intptr_t Handle::RecvFrom(
void* buffer, intptr_t num_bytes, struct sockaddr* sa, socklen_t sa_len) {
MonitorLocker ml(monitor_);
- if (data_ready_ == NULL) return 0;
+ if (data_ready_ == NULL) {
+ return 0;
+ }
num_bytes = data_ready_->Read(
buffer, Utils::Minimum<intptr_t>(num_bytes, INT_MAX));
if (data_ready_->from()->sa_family == AF_INET) {
@@ -679,21 +685,31 @@
// entirety to match how recvfrom works in a socket.
OverlappedBuffer::DisposeBuffer(data_ready_);
data_ready_ = NULL;
- if (!IsClosing() && !IsClosedRead()) IssueRecvFrom();
+ if (!IsClosing() && !IsClosedRead()) {
+ IssueRecvFrom();
+ }
return num_bytes;
}
intptr_t Handle::Write(const void* buffer, intptr_t num_bytes) {
MonitorLocker ml(monitor_);
- if (pending_write_ != NULL) return 0;
- if (num_bytes > kBufferSize) num_bytes = kBufferSize;
+ if (pending_write_ != NULL) {
+ return 0;
+ }
+ if (num_bytes > kBufferSize) {
+ num_bytes = kBufferSize;
+ }
ASSERT(SupportsOverlappedIO());
- if (completion_port_ == INVALID_HANDLE_VALUE) return 0;
+ if (completion_port_ == INVALID_HANDLE_VALUE) {
+ return 0;
+ }
int truncated_bytes = Utils::Minimum<intptr_t>(num_bytes, INT_MAX);
pending_write_ = OverlappedBuffer::AllocateWriteBuffer(truncated_bytes);
pending_write_->Write(buffer, truncated_bytes);
- if (!IssueWrite()) return -1;
+ if (!IssueWrite()) {
+ return -1;
+ }
return truncated_bytes;
}
@@ -703,13 +719,21 @@
struct sockaddr* sa,
socklen_t sa_len) {
MonitorLocker ml(monitor_);
- if (pending_write_ != NULL) return 0;
- if (num_bytes > kBufferSize) num_bytes = kBufferSize;
+ if (pending_write_ != NULL) {
+ return 0;
+ }
+ if (num_bytes > kBufferSize) {
+ num_bytes = kBufferSize;
+ }
ASSERT(SupportsOverlappedIO());
- if (completion_port_ == INVALID_HANDLE_VALUE) return 0;
+ if (completion_port_ == INVALID_HANDLE_VALUE) {
+ return 0;
+ }
pending_write_ = OverlappedBuffer::AllocateSendToBuffer(num_bytes);
pending_write_->Write(buffer, num_bytes);
- if (!IssueSendTo(sa, sa_len)) return -1;
+ if (!IssueSendTo(sa, sa_len)) {
+ return -1;
+ }
return num_bytes;
}
@@ -765,15 +789,21 @@
intptr_t StdHandle::Write(const void* buffer, intptr_t num_bytes) {
MonitorLocker ml(monitor_);
- if (pending_write_ != NULL) return 0;
- if (num_bytes > kBufferSize) num_bytes = kBufferSize;
+ if (pending_write_ != NULL) {
+ return 0;
+ }
+ if (num_bytes > kBufferSize) {
+ num_bytes = kBufferSize;
+ }
// In the case of stdout and stderr, OverlappedIO is not supported.
// Here we'll instead use a thread, to make it async.
// This code is actually never exposed to the user, as stdout and stderr is
// not available as a RawSocket, but only wrapped in a Socket.
// Note that we return '0', unless a thread have already completed a write.
if (thread_wrote_ > 0) {
- if (num_bytes > thread_wrote_) num_bytes = thread_wrote_;
+ if (num_bytes > thread_wrote_) {
+ num_bytes = thread_wrote_;
+ }
thread_wrote_ -= num_bytes;
return num_bytes;
}
@@ -826,17 +856,18 @@
&bytes,
NULL,
NULL);
- if (status == SOCKET_ERROR) {
- return false;
- }
- return true;
+ return (status != SOCKET_ERROR);
}
void ClientSocket::Shutdown(int how) {
int rc = shutdown(socket(), how);
- if (how == SD_RECEIVE) MarkClosedRead();
- if (how == SD_SEND) MarkClosedWrite();
+ if (how == SD_RECEIVE) {
+ MarkClosedRead();
+ }
+ if (how == SD_SEND) {
+ MarkClosedWrite();
+ }
if (how == SD_BOTH) {
MarkClosedRead();
MarkClosedWrite();
@@ -870,7 +901,7 @@
&flags,
buffer->GetCleanOverlapped(),
NULL);
- if (rc == NO_ERROR || WSAGetLastError() == WSA_IO_PENDING) {
+ if ((rc == NO_ERROR) || (WSAGetLastError() == WSA_IO_PENDING)) {
pending_read_ = buffer;
return true;
}
@@ -894,7 +925,7 @@
0,
pending_write_->GetCleanOverlapped(),
NULL);
- if (rc == NO_ERROR || WSAGetLastError() == WSA_IO_PENDING) {
+ if ((rc == NO_ERROR) || (WSAGetLastError() == WSA_IO_PENDING)) {
return true;
}
OverlappedBuffer::DisposeBuffer(pending_write_);
@@ -910,7 +941,7 @@
socket(), buffer->GetCleanOverlapped(), TF_REUSE_SOCKET, 0);
// DisconnectEx works like other OverlappedIO APIs, where we can get either an
// immediate success or delayed operation by WSA_IO_PENDING being set.
- if (ok || WSAGetLastError() != WSA_IO_PENDING) {
+ if (ok || (WSAGetLastError() != WSA_IO_PENDING)) {
DisconnectComplete(buffer);
}
NotifyAllDartPorts(1 << kDestroyedEvent);
@@ -975,7 +1006,7 @@
sa_len,
pending_write_->GetCleanOverlapped(),
NULL);
- if (rc == NO_ERROR || WSAGetLastError() == WSA_IO_PENDING) {
+ if ((rc == NO_ERROR) || (WSAGetLastError() == WSA_IO_PENDING)) {
return true;
}
OverlappedBuffer::DisposeBuffer(pending_write_);
@@ -1004,7 +1035,7 @@
buffer->from_len_addr(),
buffer->GetCleanOverlapped(),
NULL);
- if (rc == NO_ERROR || WSAGetLastError() == WSA_IO_PENDING) {
+ if ((rc == NO_ERROR) || (WSAGetLastError() == WSA_IO_PENDING)) {
pending_read_ = buffer;
return true;
}
@@ -1174,8 +1205,8 @@
if (!listen_socket->IsClosing() && listen_socket->CanAccept()) {
intptr_t event_mask = 1 << kInEvent;
for (int i = 0;
- i < listen_socket->accepted_count() &&
- listen_socket->Mask() == event_mask;
+ (i < listen_socket->accepted_count()) &&
+ (listen_socket->Mask() == event_mask);
i++) {
Dart_Port port = listen_socket->NextNotifyDartPort(event_mask);
DartUtils::PostInt32(port, event_mask);
@@ -1280,7 +1311,9 @@
void EventHandlerImplementation::HandleTimeout() {
- if (!timeout_queue_.HasTimeout()) return;
+ if (!timeout_queue_.HasTimeout()) {
+ return;
+ }
DartUtils::PostNull(timeout_queue_.CurrentPort());
timeout_queue_.RemoveCurrent();
}
@@ -1389,7 +1422,9 @@
OVERLAPPED* overlapped;
int64_t millis = handler_impl->GetTimeout();
ASSERT(millis == kInfinityTimeout || millis >= 0);
- if (millis > kMaxInt32) millis = kMaxInt32;
+ if (millis > kMaxInt32) {
+ millis = kMaxInt32;
+ }
ASSERT(sizeof(int32_t) == sizeof(DWORD));
BOOL ok = GetQueuedCompletionStatus(handler_impl->completion_port(),
&bytes,
@@ -1397,7 +1432,7 @@
&overlapped,
static_cast<DWORD>(millis));
- if (!ok && overlapped == NULL) {
+ if (!ok && (overlapped == NULL)) {
if (GetLastError() == ERROR_ABANDONED_WAIT_0) {
// The completion port should never be closed.
Log::Print("Completion port closed\n");
@@ -1413,10 +1448,10 @@
// ERROR_NETNAME_DELETED occurs when the client closes
// the socket it is reading from.
DWORD last_error = GetLastError();
- if (last_error == ERROR_CONNECTION_ABORTED ||
- last_error == ERROR_OPERATION_ABORTED ||
- last_error == ERROR_NETNAME_DELETED ||
- last_error == ERROR_BROKEN_PIPE) {
+ if ((last_error == ERROR_CONNECTION_ABORTED) ||
+ (last_error == ERROR_OPERATION_ABORTED) ||
+ (last_error == ERROR_NETNAME_DELETED) ||
+ (last_error == ERROR_BROKEN_PIPE)) {
ASSERT(bytes == 0);
handler_impl->HandleIOCompletion(bytes, key, overlapped);
} else if (last_error == ERROR_MORE_DATA) {
diff --git a/runtime/bin/eventhandler_win.h b/runtime/bin/eventhandler_win.h
index 38509dd..edb5c48 100644
--- a/runtime/bin/eventhandler_win.h
+++ b/runtime/bin/eventhandler_win.h
@@ -9,14 +9,13 @@
#error Do not include eventhandler_win.h directly; use eventhandler.h instead.
#endif
+#include <mswsock.h>
#include <winsock2.h>
#include <ws2tcpip.h>
-#include <mswsock.h>
#include "bin/builtin.h"
#include "bin/thread.h"
-
namespace dart {
namespace bin {
@@ -28,7 +27,6 @@
class ClientSocket;
class ListenSocket;
-
// An OverlappedBuffer encapsulates the OVERLAPPED structure and the
// associated data buffer. For accept it also contains the pre-created
// socket for the client.
@@ -149,6 +147,8 @@
// object as the object is allocated larger than it's definition
// indicate to extend this array.
uint8_t buffer_data_[1];
+
+ DISALLOW_COPY_AND_ASSIGN(OverlappedBuffer);
};
@@ -273,6 +273,8 @@
void NotifyReadThreadFinished();
int flags_;
+
+ DISALLOW_COPY_AND_ASSIGN(Handle);
};
@@ -285,6 +287,9 @@
virtual void EnsureInitialized(EventHandlerImplementation* event_handler);
virtual bool IsClosed();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FileHandle);
};
@@ -310,6 +315,8 @@
intptr_t thread_wrote_;
bool write_thread_exists_;
bool write_thread_running_;
+
+ DISALLOW_COPY_AND_ASSIGN(StdHandle);
};
@@ -332,6 +339,8 @@
private:
int events_;
bool recursive_;
+
+ DISALLOW_COPY_AND_ASSIGN(DirectoryWatchHandle);
};
@@ -348,6 +357,8 @@
private:
const SOCKET socket_;
+
+ DISALLOW_COPY_AND_ASSIGN(SocketHandle);
};
@@ -403,6 +414,8 @@
// The number of accepted connections which are waiting to be removed from
// this queue and processed by dart isolates.
int accepted_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(ListenSocket);
};
@@ -460,6 +473,8 @@
ClientSocket* next_;
bool connected_;
bool closed_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClientSocket);
};
@@ -482,8 +497,12 @@
virtual void EnsureInitialized(EventHandlerImplementation* event_handler);
virtual void DoClose();
virtual bool IsClosed();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DatagramSocket);
};
+
// Event handler.
class EventHandlerImplementation {
public:
@@ -523,6 +542,8 @@
TimeoutQueue timeout_queue_; // Time for next timeout.
bool shutdown_;
HANDLE completion_port_;
+
+ DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
};
} // namespace bin
diff --git a/runtime/bin/extensions.cc b/runtime/bin/extensions.cc
index eaed7bb..7fa06fd 100644
--- a/runtime/bin/extensions.cc
+++ b/runtime/bin/extensions.cc
@@ -6,12 +6,11 @@
#include <stdio.h>
+#include "bin/dartutils.h"
+#include "bin/file.h"
#include "include/dart_api.h"
#include "platform/assert.h"
#include "platform/globals.h"
-#include "bin/dartutils.h"
-#include "bin/file.h"
-
namespace dart {
namespace bin {
@@ -25,17 +24,15 @@
return Dart_NewApiError("Cannot load native extensions over http:");
}
const char* library_strings[] = { extension_directory, extension_file, NULL };
- char* library_file = Concatenate(library_strings);
+ const char* library_file = Concatenate(library_strings);
void* library_handle = LoadExtensionLibrary(library_file);
- free(library_file);
if (library_handle == NULL) {
return GetError();
}
const char* strings[] = { extension_name, "_Init", NULL };
- char* init_function_name = Concatenate(strings);
+ const char* init_function_name = Concatenate(strings);
void* init_function = ResolveSymbol(library_handle, init_function_name);
- free(init_function_name);
Dart_Handle result = GetError();
if (Dart_IsError(result)) {
return result;
@@ -48,13 +45,13 @@
// Concatenates a NULL terminated array of strings.
-// The returned string must be freed.
-char* Extensions::Concatenate(const char** strings) {
+// The returned string is scope allocated.
+const char* Extensions::Concatenate(const char** strings) {
int size = 1; // null termination.
for (int i = 0; strings[i] != NULL; i++) {
size += strlen(strings[i]);
}
- char* result = reinterpret_cast<char*>(malloc(size));
+ char* result = reinterpret_cast<char*>(Dart_ScopeAllocate(size));
int index = 0;
for (int i = 0; strings[i] != NULL; i++) {
index += snprintf(result + index, size - index, "%s", strings[i]);
diff --git a/runtime/bin/extensions.h b/runtime/bin/extensions.h
index 8c172b8..da18615 100644
--- a/runtime/bin/extensions.h
+++ b/runtime/bin/extensions.h
@@ -8,7 +8,6 @@
#include "include/dart_api.h"
#include "platform/globals.h"
-
namespace dart {
namespace bin {
@@ -28,8 +27,8 @@
private:
static Dart_Handle GetError();
- // The returned string must be freed.
- static char* Concatenate(const char** strings);
+ // The returned string is scope allocated.
+ static const char* Concatenate(const char** strings);
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(Extensions);
diff --git a/runtime/bin/extensions_android.cc b/runtime/bin/extensions_android.cc
index e33c195..c34902c 100644
--- a/runtime/bin/extensions_android.cc
+++ b/runtime/bin/extensions_android.cc
@@ -8,7 +8,6 @@
#include "bin/extensions.h"
#include <dlfcn.h> // NOLINT
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/extensions_linux.cc b/runtime/bin/extensions_linux.cc
index 54a88a4..8a25cba 100644
--- a/runtime/bin/extensions_linux.cc
+++ b/runtime/bin/extensions_linux.cc
@@ -8,7 +8,6 @@
#include "bin/extensions.h"
#include <dlfcn.h> // NOLINT
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/extensions_macos.cc b/runtime/bin/extensions_macos.cc
index 0edb6b5..9910f10 100644
--- a/runtime/bin/extensions_macos.cc
+++ b/runtime/bin/extensions_macos.cc
@@ -8,7 +8,6 @@
#include "bin/extensions.h"
#include <dlfcn.h> // NOLINT
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/extensions_win.cc b/runtime/bin/extensions_win.cc
index 224bcdf..493acad 100644
--- a/runtime/bin/extensions_win.cc
+++ b/runtime/bin/extensions_win.cc
@@ -9,7 +9,6 @@
#include "bin/utils.h"
#include "bin/utils_win.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/fdutils.h b/runtime/bin/fdutils.h
index da4fcf5..93bebfb 100644
--- a/runtime/bin/fdutils.h
+++ b/runtime/bin/fdutils.h
@@ -8,7 +8,6 @@
#include "bin/builtin.h"
#include "platform/globals.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/fdutils_android.cc b/runtime/bin/fdutils_android.cc
index 83e4913..3c22a04 100644
--- a/runtime/bin/fdutils_android.cc
+++ b/runtime/bin/fdutils_android.cc
@@ -5,15 +5,15 @@
#include "platform/globals.h"
#if defined(TARGET_OS_ANDROID)
+#include "bin/fdutils.h"
+
#include <errno.h> // NOLINT
#include <fcntl.h> // NOLINT
-#include <unistd.h> // NOLINT
#include <sys/ioctl.h> // NOLINT
+#include <unistd.h> // NOLINT
-#include "bin/fdutils.h"
#include "platform/signal_blocker.h"
-
namespace dart {
namespace bin {
@@ -72,9 +72,7 @@
if (result < 0) {
return result;
}
-#ifdef DEBUG
ASSERT(available >= 0);
-#endif
return static_cast<intptr_t>(available);
}
@@ -98,7 +96,7 @@
ASSERT(errno != EWOULDBLOCK);
return -1;
} else {
- ASSERT((bytes_read > 0));
+ ASSERT(bytes_read > 0);
remaining -= bytes_read;
buffer_pos += bytes_read;
}
diff --git a/runtime/bin/fdutils_linux.cc b/runtime/bin/fdutils_linux.cc
index e8984dd..f80356e 100644
--- a/runtime/bin/fdutils_linux.cc
+++ b/runtime/bin/fdutils_linux.cc
@@ -5,15 +5,15 @@
#include "platform/globals.h"
#if defined(TARGET_OS_LINUX)
+#include "bin/fdutils.h"
+
#include <errno.h> // NOLINT
#include <fcntl.h> // NOLINT
-#include <unistd.h> // NOLINT
#include <sys/ioctl.h> // NOLINT
+#include <unistd.h> // NOLINT
-#include "bin/fdutils.h"
#include "platform/signal_blocker.h"
-
namespace dart {
namespace bin {
@@ -72,9 +72,7 @@
if (result < 0) {
return result;
}
-#ifdef DEBUG
ASSERT(available >= 0);
-#endif
return static_cast<intptr_t>(available);
}
@@ -98,7 +96,7 @@
ASSERT(errno != EWOULDBLOCK);
return -1;
} else {
- ASSERT((bytes_read > 0));
+ ASSERT(bytes_read > 0);
remaining -= bytes_read;
buffer_pos += bytes_read;
}
diff --git a/runtime/bin/fdutils_macos.cc b/runtime/bin/fdutils_macos.cc
index 2ecf600..41f1d24 100644
--- a/runtime/bin/fdutils_macos.cc
+++ b/runtime/bin/fdutils_macos.cc
@@ -5,15 +5,14 @@
#include "platform/globals.h"
#if defined(TARGET_OS_MACOS)
-#include <errno.h> // NOLINT
-#include <fcntl.h> // NOLINT
-#include <unistd.h> // NOLINT
-#include <sys/ioctl.h> // NOLINT
-
#include "bin/fdutils.h"
-#include "platform/signal_blocker.h"
+#include <errno.h> // NOLINT
+#include <fcntl.h> // NOLINT
+#include <sys/ioctl.h> // NOLINT
+#include <unistd.h> // NOLINT
+#include "platform/signal_blocker.h"
namespace dart {
namespace bin {
@@ -73,9 +72,7 @@
if (result < 0) {
return result;
}
-#ifdef DEBUG
ASSERT(available >= 0);
-#endif
return static_cast<intptr_t>(available);
}
@@ -99,7 +96,7 @@
ASSERT(errno != EWOULDBLOCK);
return -1;
} else {
- ASSERT((bytes_read > 0));
+ ASSERT(bytes_read > 0);
remaining -= bytes_read;
buffer_pos += bytes_read;
}
diff --git a/runtime/bin/file.cc b/runtime/bin/file.cc
index 7cc3e71..7d9ea28 100644
--- a/runtime/bin/file.cc
+++ b/runtime/bin/file.cc
@@ -565,7 +565,9 @@
void FUNCTION_NAME(File_OpenStdio)(Dart_NativeArguments args) {
int64_t fd = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
- ASSERT(fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO);
+ ASSERT((fd == STDIN_FILENO) ||
+ (fd == STDOUT_FILENO) ||
+ (fd == STDERR_FILENO));
File* file = File::OpenStdio(static_cast<int>(fd));
Dart_SetReturnValue(args, Dart_NewInteger(reinterpret_cast<intptr_t>(file)));
}
@@ -573,7 +575,9 @@
void FUNCTION_NAME(File_GetStdioHandleType)(Dart_NativeArguments args) {
int64_t fd = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 0));
- ASSERT(fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO);
+ ASSERT((fd == STDIN_FILENO) ||
+ (fd == STDOUT_FILENO) ||
+ (fd == STDERR_FILENO));
File::StdioHandleType type = File::GetStdioHandleType(static_cast<int>(fd));
Dart_SetReturnValue(args, Dart_NewInteger(type));
}
diff --git a/runtime/bin/file.h b/runtime/bin/file.h
index 315ebbe..3c8255f 100644
--- a/runtime/bin/file.h
+++ b/runtime/bin/file.h
@@ -5,9 +5,9 @@
#ifndef BIN_FILE_H_
#define BIN_FILE_H_
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdio.h>
#include <sys/types.h>
#include "bin/builtin.h"
diff --git a/runtime/bin/file_android.cc b/runtime/bin/file_android.cc
index c672914..a115715 100644
--- a/runtime/bin/file_android.cc
+++ b/runtime/bin/file_android.cc
@@ -9,11 +9,11 @@
#include <errno.h> // NOLINT
#include <fcntl.h> // NOLINT
+#include <libgen.h> // NOLINT
+#include <sys/sendfile.h> // NOLINT
#include <sys/stat.h> // NOLINT
#include <sys/types.h> // NOLINT
-#include <sys/sendfile.h> // NOLINT
#include <unistd.h> // NOLINT
-#include <libgen.h> // NOLINT
#include "bin/builtin.h"
#include "bin/log.h"
@@ -21,7 +21,6 @@
#include "platform/signal_blocker.h"
#include "platform/utils.h"
-
namespace dart {
namespace bin {
@@ -114,7 +113,7 @@
bool File::Lock(File::LockType lock, int64_t start, int64_t end) {
ASSERT(handle_->fd() >= 0);
- ASSERT(end == -1 || end > start);
+ ASSERT((end == -1) || (end > start));
struct flock fl;
switch (lock) {
case File::kLockUnlock:
@@ -399,7 +398,7 @@
bool File::IsAbsolutePath(const char* pathname) {
- return (pathname != NULL && pathname[0] == '/');
+ return ((pathname != NULL) && (pathname[0] == '/'));
}
diff --git a/runtime/bin/file_linux.cc b/runtime/bin/file_linux.cc
index 495dacd..3099715 100644
--- a/runtime/bin/file_linux.cc
+++ b/runtime/bin/file_linux.cc
@@ -9,11 +9,11 @@
#include <errno.h> // NOLINT
#include <fcntl.h> // NOLINT
+#include <libgen.h> // NOLINT
+#include <sys/sendfile.h> // NOLINT
#include <sys/stat.h> // NOLINT
#include <sys/types.h> // NOLINT
-#include <sys/sendfile.h> // NOLINT
#include <unistd.h> // NOLINT
-#include <libgen.h> // NOLINT
#include "bin/builtin.h"
#include "bin/log.h"
diff --git a/runtime/bin/file_macos.cc b/runtime/bin/file_macos.cc
index 1211fad..81412f6 100644
--- a/runtime/bin/file_macos.cc
+++ b/runtime/bin/file_macos.cc
@@ -7,13 +7,13 @@
#include "bin/file.h"
+#include <copyfile.h> // NOLINT
#include <errno.h> // NOLINT
#include <fcntl.h> // NOLINT
-#include <copyfile.h> // NOLINT
-#include <sys/stat.h> // NOLINT
-#include <unistd.h> // NOLINT
#include <libgen.h> // NOLINT
#include <limits.h> // NOLINT
+#include <sys/stat.h> // NOLINT
+#include <unistd.h> // NOLINT
#include "bin/builtin.h"
#include "bin/fdutils.h"
diff --git a/runtime/bin/file_system_watcher.h b/runtime/bin/file_system_watcher.h
index 6a6164a..7e142d8 100644
--- a/runtime/bin/file_system_watcher.h
+++ b/runtime/bin/file_system_watcher.h
@@ -5,15 +5,14 @@
#ifndef BIN_FILE_SYSTEM_WATCHER_H_
#define BIN_FILE_SYSTEM_WATCHER_H_
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdio.h>
#include <sys/types.h>
#include "bin/builtin.h"
#include "bin/dartutils.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/file_system_watcher_android.cc b/runtime/bin/file_system_watcher_android.cc
index ac2ad5f..ccf54da 100644
--- a/runtime/bin/file_system_watcher_android.cc
+++ b/runtime/bin/file_system_watcher_android.cc
@@ -11,10 +11,8 @@
#include <sys/inotify.h> // NOLINT
#include "bin/fdutils.h"
-
#include "platform/signal_blocker.h"
-
namespace dart {
namespace bin {
@@ -46,10 +44,18 @@
int events,
bool recursive) {
int list_events = IN_DELETE_SELF | IN_MOVE_SELF;
- if (events & kCreate) list_events |= IN_CREATE;
- if (events & kModifyContent) list_events |= IN_CLOSE_WRITE | IN_ATTRIB;
- if (events & kDelete) list_events |= IN_DELETE;
- if (events & kMove) list_events |= IN_MOVE;
+ if ((events & kCreate) != 0) {
+ list_events |= IN_CREATE;
+ }
+ if ((events & kModifyContent) != 0) {
+ list_events |= IN_CLOSE_WRITE | IN_ATTRIB;
+ }
+ if ((events & kDelete) != 0) {
+ list_events |= IN_DELETE;
+ }
+ if ((events & kMove) != 0) {
+ list_events |= IN_MOVE;
+ }
int path_id = NO_RETRY_EXPECTED(inotify_add_watch(id, path, list_events));
if (path_id < 0) {
return -1;
@@ -69,6 +75,33 @@
}
+static int InotifyEventToMask(struct inotify_event* e) {
+ int mask = 0;
+ if ((e->mask & IN_CLOSE_WRITE) != 0) {
+ mask |= FileSystemWatcher::kModifyContent;
+ }
+ if ((e->mask & IN_ATTRIB) != 0) {
+ mask |= FileSystemWatcher::kModefyAttribute;
+ }
+ if ((e->mask & IN_CREATE) != 0) {
+ mask |= FileSystemWatcher::kCreate;
+ }
+ if ((e->mask & IN_MOVE) != 0) {
+ mask |= FileSystemWatcher::kMove;
+ }
+ if ((e->mask & IN_DELETE) != 0) {
+ mask |= FileSystemWatcher::kDelete;
+ }
+ if ((e->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) != 0) {
+ mask |= FileSystemWatcher::kDeleteSelf;
+ }
+ if ((e->mask & IN_ISDIR) != 0) {
+ mask |= FileSystemWatcher::kIsDir;
+ }
+ return mask;
+}
+
+
Dart_Handle FileSystemWatcher::ReadEvents(intptr_t id, intptr_t path_id) {
USE(path_id);
const intptr_t kEventSize = sizeof(struct inotify_event);
@@ -87,14 +120,7 @@
reinterpret_cast<struct inotify_event*>(buffer + offset);
if ((e->mask & IN_IGNORED) == 0) {;
Dart_Handle event = Dart_NewList(5);
- int mask = 0;
- if (e->mask & IN_CLOSE_WRITE) mask |= kModifyContent;
- if (e->mask & IN_ATTRIB) mask |= kModefyAttribute;
- if (e->mask & IN_CREATE) mask |= kCreate;
- if (e->mask & IN_MOVE) mask |= kMove;
- if (e->mask & IN_DELETE) mask |= kDelete;
- if (e->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) mask |= kDeleteSelf;
- if (e->mask & IN_ISDIR) mask |= kIsDir;
+ int mask = InotifyEventToMask(e);
Dart_ListSetAt(event, 0, Dart_NewInteger(mask));
Dart_ListSetAt(event, 1, Dart_NewInteger(e->cookie));
if (e->len > 0) {
diff --git a/runtime/bin/file_system_watcher_linux.cc b/runtime/bin/file_system_watcher_linux.cc
index 48c7323..e692f0d 100644
--- a/runtime/bin/file_system_watcher_linux.cc
+++ b/runtime/bin/file_system_watcher_linux.cc
@@ -12,10 +12,8 @@
#include "bin/fdutils.h"
#include "bin/socket.h"
-
#include "platform/signal_blocker.h"
-
namespace dart {
namespace bin {
@@ -26,7 +24,9 @@
intptr_t FileSystemWatcher::Init() {
int id = NO_RETRY_EXPECTED(inotify_init1(IN_CLOEXEC));
- if (id < 0) return -1;
+ if (id < 0) {
+ return -1;
+ }
// Some systems dosn't support setting this as non-blocking. Since watching
// internals are kept away from the user, we know it's possible to continue,
// even if setting non-blocking fails.
@@ -45,10 +45,18 @@
int events,
bool recursive) {
int list_events = IN_DELETE_SELF | IN_MOVE_SELF;
- if (events & kCreate) list_events |= IN_CREATE;
- if (events & kModifyContent) list_events |= IN_CLOSE_WRITE | IN_ATTRIB;
- if (events & kDelete) list_events |= IN_DELETE;
- if (events & kMove) list_events |= IN_MOVE;
+ if ((events & kCreate) != 0) {
+ list_events |= IN_CREATE;
+ }
+ if ((events & kModifyContent) != 0) {
+ list_events |= IN_CLOSE_WRITE | IN_ATTRIB;
+ }
+ if ((events & kDelete) != 0) {
+ list_events |= IN_DELETE;
+ }
+ if ((events & kMove) != 0) {
+ list_events |= IN_MOVE;
+ }
int path_id = NO_RETRY_EXPECTED(inotify_add_watch(id, path, list_events));
if (path_id < 0) {
return -1;
@@ -68,6 +76,33 @@
}
+static int InotifyEventToMask(struct inotify_event* e) {
+ int mask = 0;
+ if ((e->mask & IN_CLOSE_WRITE) != 0) {
+ mask |= FileSystemWatcher::kModifyContent;
+ }
+ if ((e->mask & IN_ATTRIB) != 0) {
+ mask |= FileSystemWatcher::kModefyAttribute;
+ }
+ if ((e->mask & IN_CREATE) != 0) {
+ mask |= FileSystemWatcher::kCreate;
+ }
+ if ((e->mask & IN_MOVE) != 0) {
+ mask |= FileSystemWatcher::kMove;
+ }
+ if ((e->mask & IN_DELETE) != 0) {
+ mask |= FileSystemWatcher::kDelete;
+ }
+ if ((e->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) != 0) {
+ mask |= FileSystemWatcher::kDeleteSelf;
+ }
+ if ((e->mask & IN_ISDIR) != 0) {
+ mask |= FileSystemWatcher::kIsDir;
+ }
+ return mask;
+}
+
+
Dart_Handle FileSystemWatcher::ReadEvents(intptr_t id, intptr_t path_id) {
USE(path_id);
const intptr_t kEventSize = sizeof(struct inotify_event);
@@ -86,14 +121,7 @@
reinterpret_cast<struct inotify_event*>(buffer + offset);
if ((e->mask & IN_IGNORED) == 0) {;
Dart_Handle event = Dart_NewList(5);
- int mask = 0;
- if (e->mask & IN_CLOSE_WRITE) mask |= kModifyContent;
- if (e->mask & IN_ATTRIB) mask |= kModefyAttribute;
- if (e->mask & IN_CREATE) mask |= kCreate;
- if (e->mask & IN_MOVE) mask |= kMove;
- if (e->mask & IN_DELETE) mask |= kDelete;
- if (e->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) mask |= kDeleteSelf;
- if (e->mask & IN_ISDIR) mask |= kIsDir;
+ int mask = InotifyEventToMask(e);
Dart_ListSetAt(event, 0, Dart_NewInteger(mask));
Dart_ListSetAt(event, 1, Dart_NewInteger(e->cookie));
if (e->len > 0) {
diff --git a/runtime/bin/file_system_watcher_macos.cc b/runtime/bin/file_system_watcher_macos.cc
index 5c0d430..ff64288 100644
--- a/runtime/bin/file_system_watcher_macos.cc
+++ b/runtime/bin/file_system_watcher_macos.cc
@@ -19,10 +19,8 @@
#include "bin/file.h"
#include "bin/socket.h"
#include "bin/thread.h"
-
#include "platform/signal_blocker.h"
-
#ifndef MAC_OS_X_VERSION_10_7
enum {
kFSEventStreamCreateFlagFileEvents = 0x00000010
@@ -42,7 +40,6 @@
};
#endif
-
namespace dart {
namespace bin {
@@ -55,6 +52,7 @@
uint8_t bytes[PATH_MAX + 8];
};
+
class FSEventsWatcher {
public:
class Node {
@@ -180,6 +178,8 @@
int write_fd_;
bool recursive_;
FSEventStreamRef ref_;
+
+ DISALLOW_COPY_AND_ASSIGN(Node);
};
@@ -287,15 +287,21 @@
Thread::GetCurrentThreadId()));
// `ready` is set on same thread as this callback is invoked, so we don't
// need to lock here.
- if (!node->ready()) return;
+ if (!node->ready()) {
+ return;
+ }
for (size_t i = 0; i < num_events; i++) {
char *path = reinterpret_cast<char**>(event_paths)[i];
FSEvent event;
event.data.exists = File::GetType(path, false) != File::kDoesNotExist;
path += node->base_path_length();
// If path is longer the base, skip next character ('/').
- if (path[0] != '\0') path += 1;
- if (!node->recursive() && strstr(path, "/") != NULL) continue;
+ if (path[0] != '\0') {
+ path += 1;
+ }
+ if (!node->recursive() && (strstr(path, "/") != NULL)) {
+ continue;
+ }
event.data.flags = event_flags[i];
memmove(event.data.path, path, strlen(path) + 1);
write(node->write_fd(), event.bytes, sizeof(event));
@@ -305,6 +311,8 @@
Monitor monitor_;
CFRunLoopRef run_loop_;
ThreadId threadId_;
+
+ DISALLOW_COPY_AND_ASSIGN(FSEventsWatcher);
};
@@ -348,7 +356,9 @@
intptr_t fd = GetSocketId(id, path_id);
intptr_t avail = FDUtils::AvailableBytes(fd);
int count = avail / sizeof(FSEvent);
- if (count <= 0) return Dart_NewList(0);
+ if (count <= 0) {
+ return Dart_NewList(0);
+ }
Dart_Handle events = Dart_NewList(count);
FSEvent e;
for (int i = 0; i < count; i++) {
@@ -360,7 +370,7 @@
Dart_Handle event = Dart_NewList(5);
int flags = e.data.flags;
int mask = 0;
- if (flags & kFSEventStreamEventFlagItemRenamed) {
+ if ((flags & kFSEventStreamEventFlagItemRenamed) != 0) {
if (path_len == 0) {
// The moved path is the path being watched.
mask |= kDeleteSelf;
@@ -368,11 +378,19 @@
mask |= e.data.exists ? kCreate : kDelete;
}
}
- if (flags & kFSEventStreamEventFlagItemModified) mask |= kModifyContent;
- if (flags & kFSEventStreamEventFlagItemXattrMod) mask |= kModefyAttribute;
- if (flags & kFSEventStreamEventFlagItemCreated) mask |= kCreate;
- if (flags & kFSEventStreamEventFlagItemIsDir) mask |= kIsDir;
- if (flags & kFSEventStreamEventFlagItemRemoved) {
+ if ((flags & kFSEventStreamEventFlagItemModified) != 0) {
+ mask |= kModifyContent;
+ }
+ if ((flags & kFSEventStreamEventFlagItemXattrMod) != 0) {
+ mask |= kModefyAttribute;
+ }
+ if ((flags & kFSEventStreamEventFlagItemCreated) != 0) {
+ mask |= kCreate;
+ }
+ if ((flags & kFSEventStreamEventFlagItemIsDir) != 0) {
+ mask |= kIsDir;
+ }
+ if ((flags & kFSEventStreamEventFlagItemRemoved) != 0) {
if (path_len == 0) {
// The removed path is the path being watched.
mask |= kDeleteSelf;
@@ -404,24 +422,30 @@
return DartUtils::NewDartOSError();
}
+
intptr_t FileSystemWatcher::GetSocketId(intptr_t id, intptr_t path_id) {
return -1;
}
+
bool FileSystemWatcher::IsSupported() {
return false;
}
+
void FileSystemWatcher::UnwatchPath(intptr_t id, intptr_t path_id) {
}
+
intptr_t FileSystemWatcher::Init() {
return -1;
}
+
void FileSystemWatcher::Close(intptr_t id) {
}
+
intptr_t FileSystemWatcher::WatchPath(intptr_t id,
const char* path,
int events,
@@ -433,5 +457,4 @@
} // namespace dart
#endif // !TARGET_OS_IOS
-
#endif // defined(TARGET_OS_MACOS)
diff --git a/runtime/bin/file_system_watcher_win.cc b/runtime/bin/file_system_watcher_win.cc
index a772c6d..e6b091a 100644
--- a/runtime/bin/file_system_watcher_win.cc
+++ b/runtime/bin/file_system_watcher_win.cc
@@ -6,16 +6,15 @@
#if defined(TARGET_OS_WINDOWS)
#include "bin/file_system_watcher.h"
-#include "bin/eventhandler.h"
#include <WinIoCtl.h> // NOLINT
#include "bin/builtin.h"
+#include "bin/eventhandler.h"
#include "bin/log.h"
#include "bin/utils.h"
#include "bin/utils_win.h"
-
namespace dart {
namespace bin {
@@ -55,11 +54,13 @@
}
int list_events = 0;
- if (events & (kCreate | kMove | kDelete)) {
+ if ((events & (kCreate | kMove | kDelete)) != 0) {
list_events |= FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_DIR_NAME;
}
- if (events & kModifyContent) list_events |= FILE_NOTIFY_CHANGE_LAST_WRITE;
+ if ((events & kModifyContent) != 0) {
+ list_events |= FILE_NOTIFY_CHANGE_LAST_WRITE;
+ }
DirectoryWatchHandle* handle =
new DirectoryWatchHandle(dir, list_events, recursive);
@@ -102,11 +103,21 @@
Dart_Handle event = Dart_NewList(5);
int mask = 0;
- if (e->Action == FILE_ACTION_ADDED) mask |= kCreate;
- if (e->Action == FILE_ACTION_REMOVED) mask |= kDelete;
- if (e->Action == FILE_ACTION_MODIFIED) mask |= kModifyContent;
- if (e->Action == FILE_ACTION_RENAMED_OLD_NAME) mask |= kMove;
- if (e->Action == FILE_ACTION_RENAMED_NEW_NAME) mask |= kMove;
+ if (e->Action == FILE_ACTION_ADDED) {
+ mask |= kCreate;
+ }
+ if (e->Action == FILE_ACTION_REMOVED) {
+ mask |= kDelete;
+ }
+ if (e->Action == FILE_ACTION_MODIFIED) {
+ mask |= kModifyContent;
+ }
+ if (e->Action == FILE_ACTION_RENAMED_OLD_NAME) {
+ mask |= kMove;
+ }
+ if (e->Action == FILE_ACTION_RENAMED_NEW_NAME) {
+ mask |= kMove;
+ }
Dart_ListSetAt(event, 0, Dart_NewInteger(mask));
// Move events come in pairs. Just 'enable' by default.
Dart_ListSetAt(event, 1, Dart_NewInteger(1));
@@ -116,7 +127,9 @@
Dart_ListSetAt(event, 4, Dart_NewInteger(path_id));
Dart_ListSetAt(events, i, event);
i++;
- if (e->NextEntryOffset == 0) break;
+ if (e->NextEntryOffset == 0) {
+ break;
+ }
offset += e->NextEntryOffset;
}
return events;
diff --git a/runtime/bin/file_test.cc b/runtime/bin/file_test.cc
index 7cc9af3..518e6e5 100644
--- a/runtime/bin/file_test.cc
+++ b/runtime/bin/file_test.cc
@@ -7,7 +7,6 @@
#include "platform/globals.h"
#include "vm/unit_test.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 7c1268f..054370a 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -20,7 +20,6 @@
#include "bin/utils_win.h"
#include "platform/utils.h"
-
namespace dart {
namespace bin {
@@ -110,7 +109,7 @@
bool File::Lock(File::LockType lock, int64_t start, int64_t end) {
ASSERT(handle_->fd() >= 0);
- ASSERT(end == -1 || end > start);
+ ASSERT((end == -1) || (end > start));
HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(handle_->fd()));
OVERLAPPED overlapped;
ZeroMemory(&overlapped, sizeof(OVERLAPPED));
@@ -125,7 +124,6 @@
int32_t length_low = Utils::Low32Bits(length);
int32_t length_high = Utils::High32Bits(length);
-
BOOL rc;
switch (lock) {
case File::kLockUnlock:
@@ -549,9 +547,9 @@
if (pathname == NULL) {
return false;
}
- return (strlen(pathname) > 2) &&
+ return ((strlen(pathname) > 2) &&
(pathname[1] == ':') &&
- (pathname[2] == '\\' || pathname[2] == '/');
+ ((pathname[2] == '\\') || (pathname[2] == '/')));
}
diff --git a/runtime/bin/filter.h b/runtime/bin/filter.h
index 85592ab..889326f 100644
--- a/runtime/bin/filter.h
+++ b/runtime/bin/filter.h
@@ -10,7 +10,6 @@
#include "zlib/zlib.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/filter_unsupported.cc b/runtime/bin/filter_unsupported.cc
index f01b3db..442b9e6 100644
--- a/runtime/bin/filter_unsupported.cc
+++ b/runtime/bin/filter_unsupported.cc
@@ -7,7 +7,6 @@
#include "include/dart_api.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 20cc410..258b9a7 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -5,14 +5,12 @@
// Generate a snapshot file after loading all the scripts specified on the
// command line.
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdio.h>
#include <cstdarg>
-#include "include/dart_api.h"
-
#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/eventhandler.h"
@@ -22,8 +20,9 @@
#include "bin/utils.h"
#include "bin/vmservice_impl.h"
-#include "platform/globals.h"
+#include "include/dart_api.h"
+#include "platform/globals.h"
namespace dart {
namespace bin {
@@ -181,16 +180,16 @@
return -1;
}
- if (instructions_snapshot_filename != NULL &&
- embedder_entry_points_manifest == NULL) {
+ if ((instructions_snapshot_filename != NULL) &&
+ (embedder_entry_points_manifest == NULL)) {
Log::PrintErr(
"Specifying an instructions snapshot filename indicates precompilation"
". But no embedder entry points manifest was specified.\n\n");
return -1;
}
- if (embedder_entry_points_manifest != NULL &&
- instructions_snapshot_filename == NULL) {
+ if ((embedder_entry_points_manifest != NULL) &&
+ (instructions_snapshot_filename == NULL)) {
Log::PrintErr(
"Specifying the embedder entry points manifest indicates "
"precompilation. But no instuctions snapshot was specified.\n\n");
@@ -828,7 +827,7 @@
static Dart_QualifiedFunctionName* ParseEntryPointsManifestIfPresent() {
Dart_QualifiedFunctionName* entries =
ParseEntryPointsManifestFile(embedder_entry_points_manifest);
- if (entries == NULL && IsSnapshottingForPrecompilation()) {
+ if ((entries == NULL) && IsSnapshottingForPrecompilation()) {
Log::PrintErr(
"Could not find native embedder entry points during precompilation\n");
exit(255);
@@ -1042,6 +1041,7 @@
NULL,
NULL,
NULL,
+ NULL,
DartUtils::OpenFile,
DartUtils::ReadFile,
DartUtils::WriteFile,
diff --git a/runtime/bin/io_buffer.cc b/runtime/bin/io_buffer.cc
index c69d9c7..2317afa 100644
--- a/runtime/bin/io_buffer.cc
+++ b/runtime/bin/io_buffer.cc
@@ -4,7 +4,6 @@
#include "bin/io_buffer.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/io_buffer.h b/runtime/bin/io_buffer.h
index 386402d..fe38932 100644
--- a/runtime/bin/io_buffer.h
+++ b/runtime/bin/io_buffer.h
@@ -5,10 +5,8 @@
#ifndef BIN_IO_BUFFER_H_
#define BIN_IO_BUFFER_H_
-#include "platform/globals.h"
-
#include "include/dart_api.h"
-
+#include "platform/globals.h"
namespace dart {
namespace bin {
diff --git a/runtime/bin/io_impl_sources.gypi b/runtime/bin/io_impl_sources.gypi
index 03d20d4..9f1fe1b 100644
--- a/runtime/bin/io_impl_sources.gypi
+++ b/runtime/bin/io_impl_sources.gypi
@@ -43,8 +43,11 @@
'process_macos.cc',
'process_win.cc',
'../../third_party/root_certificates/root_certificates.cc',
- 'secure_socket.cc',
'secure_socket.h',
+ 'secure_socket_boringssl.cc',
+ 'secure_socket_boringssl.h',
+ 'secure_socket_macos.cc',
+ 'secure_socket_macos.h',
'secure_socket_unsupported.cc',
'socket.cc',
'socket.h',
@@ -72,13 +75,25 @@
'io_service_no_ssl.h',
'secure_socket_unsupported.cc',
],
+ 'conditions': [
+ ['OS=="mac"', {
+ # On Mac, we use the system keystore, so do not compile in the
+ # root certs.
+ 'sources!': [
+ '../../third_party/root_certificates/root_certificates.cc',
+ ],
+ }],
+ ],
}, { # else dart_io_secure_socket == 0
'sources!' : [
'../../third_party/root_certificates/root_certificates.cc',
'io_service.cc',
'io_service.h',
- 'secure_socket.cc',
'secure_socket.h',
+ 'secure_socket_boringssl.cc',
+ 'secure_socket_boringssl.h',
+ 'secure_socket_macos.cc',
+ 'secure_socket_macos.h',
],
}],
],
@@ -95,8 +110,11 @@
'io_service_no_ssl.cc',
'io_service_no_ssl.h',
'../../third_party/root_certificates/root_certificates.cc',
- 'secure_socket.cc',
'secure_socket.h',
+ 'secure_socket_boringssl.cc',
+ 'secure_socket_boringssl.h',
+ 'secure_socket_macos.cc',
+ 'secure_socket_macos.h',
],
}],
],
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index 91cc1e8..39946a7 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -12,7 +12,6 @@
#include "include/dart_api.h"
#include "platform/assert.h"
-
namespace dart {
namespace bin {
@@ -107,6 +106,7 @@
V(SecureSocket_Renegotiate, 4) \
V(SecurityContext_Allocate, 1) \
V(SecurityContext_UsePrivateKeyBytes, 3) \
+ V(SecurityContext_AlpnSupported, 0) \
V(SecurityContext_SetAlpnProtocols, 3) \
V(SecurityContext_SetClientAuthoritiesBytes, 3) \
V(SecurityContext_SetTrustedCertificatesBytes, 3) \
@@ -169,7 +169,7 @@
int num_entries = sizeof(IOEntries) / sizeof(struct NativeEntries);
for (int i = 0; i < num_entries; i++) {
struct NativeEntries* entry = &(IOEntries[i]);
- if (!strcmp(function_name, entry->name_) &&
+ if ((strcmp(function_name, entry->name_) == 0) &&
(entry->argument_count_ == argument_count)) {
return reinterpret_cast<Dart_NativeFunction>(entry->function_);
}
diff --git a/runtime/bin/io_natives.h b/runtime/bin/io_natives.h
index d44f839..c17dce5 100644
--- a/runtime/bin/io_natives.h
+++ b/runtime/bin/io_natives.h
@@ -7,7 +7,6 @@
#include "include/dart_api.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/io_service.cc b/runtime/bin/io_service.cc
index 77b722c..004e3d2 100644
--- a/runtime/bin/io_service.cc
+++ b/runtime/bin/io_service.cc
@@ -11,11 +11,10 @@
#include "bin/socket.h"
#include "bin/utils.h"
-#include "platform/globals.h"
-#include "platform/utils.h"
-
#include "include/dart_api.h"
+#include "platform/globals.h"
+#include "platform/utils.h"
namespace dart {
namespace bin {
@@ -30,8 +29,8 @@
Dart_Port reply_port_id = ILLEGAL_PORT;
CObject* response = CObject::IllegalArgumentError();
CObjectArray request(message);
- if (message->type == Dart_CObject_kArray &&
- request.Length() == 4 &&
+ if ((message->type == Dart_CObject_kArray) &&
+ (request.Length() == 4) &&
request[0]->IsInt32() &&
request[1]->IsSendPort() &&
request[2]->IsInt32() &&
@@ -57,10 +56,7 @@
Dart_Port IOService::GetServicePort() {
- Dart_Port result = Dart_NewNativePort("IOService",
- IOServiceCallback,
- true);
- return result;
+ return Dart_NewNativePort("IOService", IOServiceCallback, true);
}
@@ -74,6 +70,5 @@
}
}
-
} // namespace bin
} // namespace dart
diff --git a/runtime/bin/io_service.h b/runtime/bin/io_service.h
index 87810d0..c165e90 100644
--- a/runtime/bin/io_service.h
+++ b/runtime/bin/io_service.h
@@ -8,7 +8,6 @@
#include "bin/builtin.h"
#include "bin/utils.h"
-
namespace dart {
namespace bin {
@@ -65,6 +64,10 @@
};
static Dart_Port GetServicePort();
+
+ private:
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(IOService);
};
} // namespace bin
diff --git a/runtime/bin/io_service_no_ssl.cc b/runtime/bin/io_service_no_ssl.cc
index b63f8c8..5c70fe4 100644
--- a/runtime/bin/io_service_no_ssl.cc
+++ b/runtime/bin/io_service_no_ssl.cc
@@ -10,11 +10,10 @@
#include "bin/socket.h"
#include "bin/utils.h"
-#include "platform/globals.h"
-#include "platform/utils.h"
-
#include "include/dart_api.h"
+#include "platform/globals.h"
+#include "platform/utils.h"
namespace dart {
namespace bin {
@@ -29,8 +28,8 @@
Dart_Port reply_port_id = ILLEGAL_PORT;
CObject* response = CObject::IllegalArgumentError();
CObjectArray request(message);
- if (message->type == Dart_CObject_kArray &&
- request.Length() == 4 &&
+ if ((message->type == Dart_CObject_kArray) &&
+ (request.Length() == 4) &&
request[0]->IsInt32() &&
request[1]->IsSendPort() &&
request[2]->IsInt32() &&
@@ -56,10 +55,7 @@
Dart_Port IOService::GetServicePort() {
- Dart_Port result = Dart_NewNativePort("IOService",
- IOServiceCallback,
- true);
- return result;
+ return Dart_NewNativePort("IOService", IOServiceCallback, true);
}
@@ -73,6 +69,5 @@
}
}
-
} // namespace bin
} // namespace dart
diff --git a/runtime/bin/io_service_no_ssl.h b/runtime/bin/io_service_no_ssl.h
index 9cc7fc1..db2af1c 100644
--- a/runtime/bin/io_service_no_ssl.h
+++ b/runtime/bin/io_service_no_ssl.h
@@ -8,7 +8,6 @@
#include "bin/builtin.h"
#include "bin/utils.h"
-
namespace dart {
namespace bin {
@@ -66,6 +65,10 @@
};
static Dart_Port GetServicePort();
+
+ private:
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(IOService);
};
} // namespace bin
diff --git a/runtime/bin/io_service_unsupported.cc b/runtime/bin/io_service_unsupported.cc
index 9e51ca1..29a8730 100644
--- a/runtime/bin/io_service_unsupported.cc
+++ b/runtime/bin/io_service_unsupported.cc
@@ -7,7 +7,6 @@
#include "include/dart_api.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/isolate_data.h b/runtime/bin/isolate_data.h
index d3f411f..7ff2bfa 100644
--- a/runtime/bin/isolate_data.h
+++ b/runtime/bin/isolate_data.h
@@ -9,7 +9,6 @@
#include "platform/assert.h"
#include "platform/globals.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/lockers.h b/runtime/bin/lockers.h
index 87e44e8..0aefd99 100644
--- a/runtime/bin/lockers.h
+++ b/runtime/bin/lockers.h
@@ -8,7 +8,6 @@
#include "bin/thread.h"
#include "platform/assert.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/log.h b/runtime/bin/log.h
index 10629d5..51a4379 100644
--- a/runtime/bin/log.h
+++ b/runtime/bin/log.h
@@ -9,7 +9,6 @@
#include "platform/globals.h"
-
namespace dart {
namespace bin {
@@ -34,6 +33,7 @@
static void VPrintErr(const char* format, va_list args);
+ private:
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(Log);
};
diff --git a/runtime/bin/log_android.cc b/runtime/bin/log_android.cc
index e8d8e68..6e5a621 100644
--- a/runtime/bin/log_android.cc
+++ b/runtime/bin/log_android.cc
@@ -7,9 +7,8 @@
#include "bin/log.h"
-#include <stdio.h> // NOLINT
#include <android/log.h> // NOLINT
-
+#include <stdio.h> // NOLINT
namespace dart {
namespace bin {
diff --git a/runtime/bin/log_linux.cc b/runtime/bin/log_linux.cc
index f398c9e..abb1983 100644
--- a/runtime/bin/log_linux.cc
+++ b/runtime/bin/log_linux.cc
@@ -9,7 +9,6 @@
#include <stdio.h> // NOLINT
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/log_macos.cc b/runtime/bin/log_macos.cc
index 3711245..913a60d 100644
--- a/runtime/bin/log_macos.cc
+++ b/runtime/bin/log_macos.cc
@@ -9,7 +9,6 @@
#include <stdio.h> // NOLINT
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/log_win.cc b/runtime/bin/log_win.cc
index 9fb69cf..d8dfe96 100644
--- a/runtime/bin/log_win.cc
+++ b/runtime/bin/log_win.cc
@@ -9,7 +9,6 @@
#include <stdio.h> // NOLINT
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 4601588..0eafb9c 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -218,7 +218,7 @@
static bool ProcessPackagesOption(const char* arg,
CommandLineOptions* vm_options) {
ASSERT(arg != NULL);
- if (*arg == '\0' || *arg == '-') {
+ if ((*arg == '\0') || (*arg == '-')) {
return false;
}
commandline_packages_file = arg;
@@ -1076,7 +1076,7 @@
const intptr_t size) {
char* concat = NULL;
const char* qualified_filename;
- if ((snapshot_directory != NULL) && strlen(snapshot_directory) > 0) {
+ if ((snapshot_directory != NULL) && (strlen(snapshot_directory) > 0)) {
intptr_t len = snprintf(NULL, 0, "%s/%s", snapshot_directory, filename);
concat = new char[len + 1];
snprintf(concat, len + 1, "%s/%s", snapshot_directory, filename);
@@ -1110,7 +1110,7 @@
const uint8_t** buffer) {
char* concat = NULL;
const char* qualified_filename;
- if ((snapshot_directory != NULL) && strlen(snapshot_directory) > 0) {
+ if ((snapshot_directory != NULL) && (strlen(snapshot_directory) > 0)) {
intptr_t len = snprintf(NULL, 0, "%s/%s", snapshot_directory, filename);
concat = new char[len + 1];
snprintf(concat, len + 1, "%s/%s", snapshot_directory, filename);
@@ -1129,7 +1129,7 @@
}
intptr_t len = -1;
DartUtils::ReadFile(buffer, &len, file);
- if (*buffer == NULL || len == -1) {
+ if ((*buffer == NULL) || (len == -1)) {
fprintf(stderr,
"Error: Unable to read snapshot file %s\n", qualified_filename);
fflush(stderr);
@@ -1147,7 +1147,7 @@
const char* symname) {
char* concat = NULL;
const char* qualified_libname;
- if ((snapshot_directory != NULL) && strlen(snapshot_directory) > 0) {
+ if ((snapshot_directory != NULL) && (strlen(snapshot_directory) > 0)) {
intptr_t len = snprintf(NULL, 0, "%s/%s", snapshot_directory, libname);
concat = new char[len + 1];
snprintf(concat, len + 1, "%s/%s", snapshot_directory, libname);
@@ -1635,6 +1635,7 @@
char* error = Dart_Initialize(
vm_isolate_snapshot_buffer, instructions_snapshot, data_snapshot,
CreateIsolateAndSetup, NULL, NULL, ShutdownIsolate,
+ NULL,
DartUtils::OpenFile,
DartUtils::ReadFile,
DartUtils::WriteFile,
diff --git a/runtime/bin/platform.cc b/runtime/bin/platform.cc
index 75324f1..716ef29 100644
--- a/runtime/bin/platform.cc
+++ b/runtime/bin/platform.cc
@@ -13,7 +13,7 @@
namespace bin {
const char* Platform::executable_name_ = NULL;
-const char* Platform::resolved_executable_name_ = NULL;
+char* Platform::resolved_executable_name_ = NULL;
int Platform::script_index_ = 1;
char** Platform::argv_ = NULL;
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h
index d4f96bd..79cb7be 100644
--- a/runtime/bin/platform.h
+++ b/runtime/bin/platform.h
@@ -7,7 +7,6 @@
#include "bin/builtin.h"
-
namespace dart {
namespace bin {
@@ -49,7 +48,7 @@
static const char* GetResolvedExecutableName() {
if (resolved_executable_name_ == NULL) {
// Try to resolve the executable path using platform specific APIs.
- resolved_executable_name_ = Platform::ResolveExecutablePath();
+ resolved_executable_name_ = strdup(Platform::ResolveExecutablePath());
}
return resolved_executable_name_;
}
@@ -72,7 +71,7 @@
// The path to the executable.
static const char* executable_name_;
// The path to the resolved executable.
- static const char* resolved_executable_name_;
+ static char* resolved_executable_name_;
static int script_index_;
static char** argv_; // VM flags are argv_[1 ... script_index_ - 1]
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index b9a1faa..e21ff13 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -5,22 +5,19 @@
#include "platform/globals.h"
#if defined(TARGET_OS_MACOS)
-#include <mach-o/dyld.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-
-#include "bin/file.h"
-#include "bin/platform.h"
-
#if !TARGET_OS_IOS
#include <crt_externs.h> // NOLINT
#endif // !TARGET_OS_IOS
+#include <mach-o/dyld.h>
#include <signal.h> // NOLINT
#include <string.h> // NOLINT
+#include <sys/sysctl.h> // NOLINT
+#include <sys/types.h> // NOLINT
#include <unistd.h> // NOLINT
#include "bin/fdutils.h"
-
+#include "bin/file.h"
+#include "bin/platform.h"
namespace dart {
namespace bin {
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index 9bc01bc..78f6cdc 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -6,13 +6,12 @@
#if defined(TARGET_OS_WINDOWS)
#include "bin/file.h"
-#include "bin/platform.h"
#include "bin/log.h"
+#include "bin/platform.h"
#include "bin/socket.h"
#include "bin/utils.h"
#include "bin/utils_win.h"
-
namespace dart {
// Defined in vm/os_thread_win.cc
diff --git a/runtime/bin/process.cc b/runtime/bin/process.cc
index 4a87e29..3896505 100644
--- a/runtime/bin/process.cc
+++ b/runtime/bin/process.cc
@@ -34,7 +34,7 @@
}
// Protect against user-defined list implementations that can have
// arbitrary length.
- if (len < 0 || len > kMaxArgumentListLength) {
+ if ((len < 0) || (len > kMaxArgumentListLength)) {
result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
if (Dart_IsError(result)) {
Dart_PropagateError(result);
diff --git a/runtime/bin/process.h b/runtime/bin/process.h
index bd40086..359c8c1 100644
--- a/runtime/bin/process.h
+++ b/runtime/bin/process.h
@@ -12,7 +12,6 @@
#include "platform/globals.h"
#include "platform/utils.h"
-
namespace dart {
namespace bin {
@@ -183,6 +182,8 @@
Dart_Port port_;
SignalInfo* next_;
SignalInfo* prev_;
+
+ DISALLOW_COPY_AND_ASSIGN(SignalInfo);
};
@@ -285,6 +286,9 @@
// Number of free bytes in the last node in the list.
intptr_t free_size_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BufferListBase);
};
} // namespace bin
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index 6f2394d..5e53dbe 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -25,10 +25,8 @@
#include "platform/signal_blocker.h"
#include "platform/utils.h"
-
extern char **environ;
-
namespace dart {
namespace bin {
@@ -54,6 +52,8 @@
pid_t pid_;
intptr_t fd_;
ProcessInfo* next_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
};
@@ -108,6 +108,9 @@
// Mutex protecting all accesses to the linked list of active
// processes.
static Mutex* mutex_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList);
};
@@ -175,7 +178,7 @@
while (true) {
{
MonitorLocker locker(monitor_);
- while (running_ && process_count_ == 0) {
+ while (running_ && (process_count_ == 0)) {
monitor_->Wait(Monitor::kNoTimeout);
}
if (!running_) {
@@ -204,9 +207,9 @@
// pipe has been closed. It is therefore not a problem that
// write fails with a broken pipe error. Other errors should
// not happen.
- if (result != -1 && result != sizeof(message)) {
+ if ((result != -1) && (result != sizeof(message))) {
FATAL("Failed to write entire process exit message");
- } else if (result == -1 && errno != EPIPE) {
+ } else if ((result == -1) && (errno != EPIPE)) {
FATAL1("Failed to write exit code: %d", errno);
}
ProcessInfoList::RemoveProcess(pid);
@@ -223,6 +226,9 @@
static int process_count_;
static bool running_;
static Monitor* monitor_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler);
};
@@ -265,7 +271,8 @@
exec_control_[0] = -1;
exec_control_[1] = -1;
- program_arguments_ = new char*[arguments_length + 2];
+ program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+ (arguments_length + 2) * sizeof(*program_arguments_)));
program_arguments_[0] = const_cast<char*>(path_);
for (int i = 0; i < arguments_length; i++) {
program_arguments_[i + 1] = arguments[i];
@@ -274,7 +281,8 @@
program_environment_ = NULL;
if (environment != NULL) {
- program_environment_ = new char*[environment_length + 1];
+ program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+ (environment_length + 1) * sizeof(*program_environment_)));
for (int i = 0; i < environment_length; i++) {
program_environment_[i] = environment[i];
}
@@ -283,16 +291,12 @@
}
- ~ProcessStarter() {
- delete[] program_arguments_;
- delete[] program_environment_;
- }
-
-
int Start() {
// Create pipes required.
int err = CreatePipes();
- if (err != 0) return err;
+ if (err != 0) {
+ return err;
+ }
// Fork to create the new process.
pid_t pid = TEMP_FAILURE_RETRY(fork());
@@ -312,7 +316,9 @@
// Register the child process if not detached.
if (mode_ == kNormal) {
err = RegisterProcess(pid);
- if (err != 0) return err;
+ if (err != 0) {
+ return err;
+ }
}
// Notify child process to start. This is done to delay the call to exec
@@ -491,8 +497,8 @@
SetupDetachedWithStdio();
}
- if (working_directory_ != NULL &&
- TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
+ if ((working_directory_ != NULL) &&
+ (TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1)) {
ReportChildError();
}
@@ -534,9 +540,8 @@
// Read exec result from child. If no data is returned the exec was
// successful and the exec call closed the pipe. Otherwise the errno
// is written to the pipe.
- bytes_read =
- FDUtils::ReadFromBlocking(
- exec_control_[0], &child_errno, sizeof(child_errno));
+ bytes_read = FDUtils::ReadFromBlocking(
+ exec_control_[0], &child_errno, sizeof(child_errno));
if (bytes_read == sizeof(child_errno)) {
ReadChildError();
return child_errno;
@@ -555,8 +560,7 @@
// is written to the pipe as well.
int result[2];
bytes_read =
- FDUtils::ReadFromBlocking(
- exec_control_[0], result, sizeof(result));
+ FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result));
if (bytes_read == sizeof(int)) {
*pid = result[0];
} else if (bytes_read == 2 * sizeof(int)) {
@@ -576,7 +580,9 @@
// Close all open file descriptors except for exec_control_[1].
int max_fds = sysconf(_SC_OPEN_MAX);
- if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+ if (max_fds == -1) {
+ max_fds = _POSIX_OPEN_MAX;
+ }
for (int fd = 0; fd < max_fds; fd++) {
if (fd != exec_control_[1]) {
VOID_TEMP_FAILURE_RETRY(close(fd));
@@ -605,12 +611,14 @@
// exec_control_[1], write_out_[0], read_in_[1] and
// read_err_[1].
int max_fds = sysconf(_SC_OPEN_MAX);
- if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+ if (max_fds == -1) {
+ max_fds = _POSIX_OPEN_MAX;
+ }
for (int fd = 0; fd < max_fds; fd++) {
- if (fd != exec_control_[1] &&
- fd != write_out_[0] &&
- fd != read_in_[1] &&
- fd != read_err_[1]) {
+ if ((fd != exec_control_[1]) &&
+ (fd != write_out_[0]) &&
+ (fd != read_in_[1]) &&
+ (fd != read_err_[1])) {
VOID_TEMP_FAILURE_RETRY(close(fd));
}
}
@@ -731,6 +739,9 @@
intptr_t* id_;
intptr_t* exit_event_;
char** os_error_message_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter);
};
@@ -766,10 +777,14 @@
class BufferList: public BufferListBase {
public:
+ BufferList() {}
+
bool Read(int fd, intptr_t available) {
// Read all available bytes.
while (available > 0) {
- if (free_size_ == 0) Allocate();
+ if (free_size_ == 0) {
+ Allocate();
+ }
ASSERT(free_size_ > 0);
ASSERT(free_size_ <= kBufferSize);
intptr_t block_size = dart::Utils::Minimum(free_size_, available);
@@ -777,13 +792,18 @@
fd,
reinterpret_cast<void*>(FreeSpaceAddress()),
block_size));
- if (bytes < 0) return false;
+ if (bytes < 0) {
+ return false;
+ }
data_size_ += bytes;
free_size_ -= bytes;
available -= bytes;
}
return true;
}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BufferList);
};
@@ -835,7 +855,7 @@
// Process incoming data.
int current_alive = alive;
for (int i = 0; i < current_alive; i++) {
- if (fds[i].revents & POLLIN) {
+ if ((fds[i].revents & POLLIN) != 0) {
intptr_t avail = FDUtils::AvailableBytes(fds[i].fd);
if (fds[i].fd == out) {
if (!out_data.Read(out, avail)) {
@@ -857,7 +877,7 @@
UNREACHABLE();
}
}
- if (fds[i].revents & POLLHUP) {
+ if ((fds[i].revents & POLLHUP) != 0) {
VOID_TEMP_FAILURE_RETRY(close(fds[i].fd));
alive--;
if (i < alive) {
@@ -874,7 +894,9 @@
// Calculate the exit code.
intptr_t exit_code = exit_code_data.ints[0];
intptr_t negative = exit_code_data.ints[1];
- if (negative) exit_code = -exit_code;
+ if (negative != 0) {
+ exit_code = -exit_code;
+ }
result->set_exit_code(exit_code);
return true;
@@ -936,7 +958,9 @@
break;
}
}
- if (!found) return -1;
+ if (!found) {
+ return -1;
+ }
int fds[2];
if (NO_RETRY_EXPECTED(pipe2(fds, O_CLOEXEC)) != 0) {
return -1;
@@ -986,7 +1010,9 @@
bool remove = false;
if (handler->signal() == signal) {
if (handler->port() == Dart_GetMainPortId()) {
- if (signal_handlers == handler) signal_handlers = handler->next();
+ if (signal_handlers == handler) {
+ signal_handlers = handler->next();
+ }
handler->Unlink();
remove = true;
} else {
@@ -994,7 +1020,9 @@
}
}
SignalInfo* next = handler->next();
- if (remove) delete handler;
+ if (remove) {
+ delete handler;
+ }
handler = next;
}
if (unlisten) {
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index 572ced7..b657235 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -24,10 +24,8 @@
#include "platform/signal_blocker.h"
#include "platform/utils.h"
-
extern char **environ;
-
namespace dart {
namespace bin {
@@ -53,6 +51,8 @@
pid_t pid_;
intptr_t fd_;
ProcessInfo* next_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
};
@@ -107,6 +107,9 @@
// Mutex protecting all accesses to the linked list of active
// processes.
static Mutex* mutex_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList);
};
@@ -203,9 +206,9 @@
// pipe has been closed. It is therefore not a problem that
// write fails with a broken pipe error. Other errors should
// not happen.
- if (result != -1 && result != sizeof(message)) {
+ if ((result != -1) && (result != sizeof(message))) {
FATAL("Failed to write entire process exit message");
- } else if (result == -1 && errno != EPIPE) {
+ } else if ((result == -1) && (errno != EPIPE)) {
FATAL1("Failed to write exit code: %d", errno);
}
ProcessInfoList::RemoveProcess(pid);
@@ -222,6 +225,9 @@
static int process_count_;
static bool running_;
static Monitor* monitor_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler);
};
@@ -264,7 +270,8 @@
exec_control_[0] = -1;
exec_control_[1] = -1;
- program_arguments_ = new char*[arguments_length + 2];
+ program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+ (arguments_length + 2) * sizeof(*program_arguments_)));
program_arguments_[0] = const_cast<char*>(path_);
for (int i = 0; i < arguments_length; i++) {
program_arguments_[i + 1] = arguments[i];
@@ -273,7 +280,8 @@
program_environment_ = NULL;
if (environment != NULL) {
- program_environment_ = new char*[environment_length + 1];
+ program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+ (environment_length + 1) * sizeof(*program_environment_)));
for (int i = 0; i < environment_length; i++) {
program_environment_[i] = environment[i];
}
@@ -282,16 +290,12 @@
}
- ~ProcessStarter() {
- delete[] program_arguments_;
- delete[] program_environment_;
- }
-
-
int Start() {
// Create pipes required.
int err = CreatePipes();
- if (err != 0) return err;
+ if (err != 0) {
+ return err;
+ }
// Fork to create the new process.
pid_t pid = TEMP_FAILURE_RETRY(fork());
@@ -311,7 +315,9 @@
// Register the child process if not detached.
if (mode_ == kNormal) {
err = RegisterProcess(pid);
- if (err != 0) return err;
+ if (err != 0) {
+ return err;
+ }
}
// Notify child process to start. This is done to delay the call to exec
@@ -490,8 +496,8 @@
SetupDetachedWithStdio();
}
- if (working_directory_ != NULL &&
- TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
+ if ((working_directory_ != NULL) &&
+ (TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1)) {
ReportChildError();
}
@@ -533,9 +539,8 @@
// Read exec result from child. If no data is returned the exec was
// successful and the exec call closed the pipe. Otherwise the errno
// is written to the pipe.
- bytes_read =
- FDUtils::ReadFromBlocking(
- exec_control_[0], &child_errno, sizeof(child_errno));
+ bytes_read = FDUtils::ReadFromBlocking(
+ exec_control_[0], &child_errno, sizeof(child_errno));
if (bytes_read == sizeof(child_errno)) {
ReadChildError();
return child_errno;
@@ -554,8 +559,7 @@
// is written to the pipe as well.
int result[2];
bytes_read =
- FDUtils::ReadFromBlocking(
- exec_control_[0], result, sizeof(result));
+ FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result));
if (bytes_read == sizeof(int)) {
*pid = result[0];
} else if (bytes_read == 2 * sizeof(int)) {
@@ -575,7 +579,9 @@
// Close all open file descriptors except for exec_control_[1].
int max_fds = sysconf(_SC_OPEN_MAX);
- if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+ if (max_fds == -1) {
+ max_fds = _POSIX_OPEN_MAX;
+ }
for (int fd = 0; fd < max_fds; fd++) {
if (fd != exec_control_[1]) {
VOID_TEMP_FAILURE_RETRY(close(fd));
@@ -604,12 +610,14 @@
// exec_control_[1], write_out_[0], read_in_[1] and
// read_err_[1].
int max_fds = sysconf(_SC_OPEN_MAX);
- if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+ if (max_fds == -1) {
+ max_fds = _POSIX_OPEN_MAX;
+ }
for (int fd = 0; fd < max_fds; fd++) {
- if (fd != exec_control_[1] &&
- fd != write_out_[0] &&
- fd != read_in_[1] &&
- fd != read_err_[1]) {
+ if ((fd != exec_control_[1]) &&
+ (fd != write_out_[0]) &&
+ (fd != read_in_[1]) &&
+ (fd != read_err_[1])) {
VOID_TEMP_FAILURE_RETRY(close(fd));
}
}
@@ -659,9 +667,8 @@
const int kBufferSize = 1024;
char error_buf[kBufferSize];
char* os_error_message = Utils::StrError(errno, error_buf, kBufferSize);
- int bytes_written =
- FDUtils::WriteToBlocking(
- exec_control_[1], &child_errno, sizeof(child_errno));
+ int bytes_written = FDUtils::WriteToBlocking(
+ exec_control_[1], &child_errno, sizeof(child_errno));
if (bytes_written == sizeof(child_errno)) {
FDUtils::WriteToBlocking(
exec_control_[1], os_error_message, strlen(os_error_message) + 1);
@@ -730,6 +737,9 @@
intptr_t* id_;
intptr_t* exit_event_;
char** os_error_message_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter);
};
@@ -765,10 +775,14 @@
class BufferList: public BufferListBase {
public:
+ BufferList() {}
+
bool Read(int fd, intptr_t available) {
// Read all available bytes.
while (available > 0) {
- if (free_size_ == 0) Allocate();
+ if (free_size_ == 0) {
+ Allocate();
+ }
ASSERT(free_size_ > 0);
ASSERT(free_size_ <= kBufferSize);
intptr_t block_size = dart::Utils::Minimum(free_size_, available);
@@ -776,13 +790,18 @@
fd,
reinterpret_cast<void*>(FreeSpaceAddress()),
block_size));
- if (bytes < 0) return false;
+ if (bytes < 0) {
+ return false;
+ }
data_size_ += bytes;
free_size_ -= bytes;
available -= bytes;
}
return true;
}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BufferList);
};
@@ -834,7 +853,7 @@
// Process incoming data.
int current_alive = alive;
for (int i = 0; i < current_alive; i++) {
- if (fds[i].revents & POLLIN) {
+ if ((fds[i].revents & POLLIN) != 0) {
intptr_t avail = FDUtils::AvailableBytes(fds[i].fd);
if (fds[i].fd == out) {
if (!out_data.Read(out, avail)) {
@@ -856,7 +875,7 @@
UNREACHABLE();
}
}
- if (fds[i].revents & POLLHUP) {
+ if ((fds[i].revents & POLLHUP) != 0) {
VOID_TEMP_FAILURE_RETRY(close(fds[i].fd));
alive--;
if (i < alive) {
@@ -873,7 +892,9 @@
// Calculate the exit code.
intptr_t exit_code = exit_code_data.ints[0];
intptr_t negative = exit_code_data.ints[1];
- if (negative) exit_code = -exit_code;
+ if (negative != 0) {
+ exit_code = -exit_code;
+ }
result->set_exit_code(exit_code);
return true;
@@ -935,7 +956,9 @@
break;
}
}
- if (!found) return -1;
+ if (!found) {
+ return -1;
+ }
int fds[2];
if (NO_RETRY_EXPECTED(pipe2(fds, O_CLOEXEC)) != 0) {
return -1;
@@ -982,7 +1005,9 @@
bool remove = false;
if (handler->signal() == signal) {
if (handler->port() == Dart_GetMainPortId()) {
- if (signal_handlers == handler) signal_handlers = handler->next();
+ if (signal_handlers == handler) {
+ signal_handlers = handler->next();
+ }
handler->Unlink();
remove = true;
} else {
@@ -990,7 +1015,9 @@
}
}
SignalInfo* next = handler->next();
- if (remove) delete handler;
+ if (remove) {
+ delete handler;
+ }
handler = next;
}
if (unlisten) {
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index 00869a1..00b2d8e 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -28,8 +28,6 @@
#include "platform/signal_blocker.h"
#include "platform/utils.h"
-
-
namespace dart {
namespace bin {
@@ -55,6 +53,8 @@
pid_t pid_;
intptr_t fd_;
ProcessInfo* next_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
};
@@ -109,6 +109,9 @@
// Mutex protecting all accesses to the linked list of active
// processes.
static Mutex* mutex_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList);
};
@@ -205,9 +208,9 @@
// pipe has been closed. It is therefore not a problem that
// write fails with a broken pipe error. Other errors should
// not happen.
- if (result != -1 && result != sizeof(message)) {
+ if ((result != -1) && (result != sizeof(message))) {
FATAL("Failed to write entire process exit message");
- } else if (result == -1 && errno != EPIPE) {
+ } else if ((result == -1) && (errno != EPIPE)) {
FATAL1("Failed to write exit code: %d", errno);
}
ProcessInfoList::RemoveProcess(pid);
@@ -224,6 +227,9 @@
static int process_count_;
static bool running_;
static Monitor* monitor_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler);
};
@@ -266,7 +272,8 @@
exec_control_[0] = -1;
exec_control_[1] = -1;
- program_arguments_ = new char*[arguments_length + 2];
+ program_arguments_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+ (arguments_length + 2) * sizeof(*program_arguments_)));
program_arguments_[0] = const_cast<char*>(path_);
for (int i = 0; i < arguments_length; i++) {
program_arguments_[i + 1] = arguments[i];
@@ -275,7 +282,8 @@
program_environment_ = NULL;
if (environment != NULL) {
- program_environment_ = new char*[environment_length + 1];
+ program_environment_ = reinterpret_cast<char**>(Dart_ScopeAllocate(
+ (environment_length + 1) * sizeof(*program_environment_)));
for (int i = 0; i < environment_length; i++) {
program_environment_[i] = environment[i];
}
@@ -284,12 +292,6 @@
}
- ~ProcessStarter() {
- delete[] program_arguments_;
- delete[] program_environment_;
- }
-
-
int Start() {
// Create pipes required.
int err = CreatePipes();
@@ -509,8 +511,8 @@
SetupDetachedWithStdio();
}
- if (working_directory_ != NULL &&
- TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
+ if ((working_directory_ != NULL) &&
+ (TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1)) {
ReportChildError();
}
@@ -554,9 +556,8 @@
// Read exec result from child. If no data is returned the exec was
// successful and the exec call closed the pipe. Otherwise the errno
// is written to the pipe.
- bytes_read =
- FDUtils::ReadFromBlocking(
- exec_control_[0], &child_errno, sizeof(child_errno));
+ bytes_read = FDUtils::ReadFromBlocking(
+ exec_control_[0], &child_errno, sizeof(child_errno));
if (bytes_read == sizeof(child_errno)) {
ReadChildError();
return child_errno;
@@ -575,8 +576,7 @@
// is written to the pipe as well.
int result[2];
bytes_read =
- FDUtils::ReadFromBlocking(
- exec_control_[0], result, sizeof(result));
+ FDUtils::ReadFromBlocking(exec_control_[0], result, sizeof(result));
if (bytes_read == sizeof(int)) {
*pid = result[0];
} else if (bytes_read == 2 * sizeof(int)) {
@@ -596,7 +596,9 @@
// Close all open file descriptors except for exec_control_[1].
int max_fds = sysconf(_SC_OPEN_MAX);
- if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+ if (max_fds == -1) {
+ max_fds = _POSIX_OPEN_MAX;
+ }
for (int fd = 0; fd < max_fds; fd++) {
if (fd != exec_control_[1]) {
VOID_TEMP_FAILURE_RETRY(close(fd));
@@ -625,12 +627,14 @@
// exec_control_[1], write_out_[0], read_in_[1] and
// read_err_[1].
int max_fds = sysconf(_SC_OPEN_MAX);
- if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+ if (max_fds == -1) {
+ max_fds = _POSIX_OPEN_MAX;
+ }
for (int fd = 0; fd < max_fds; fd++) {
- if (fd != exec_control_[1] &&
- fd != write_out_[0] &&
- fd != read_in_[1] &&
- fd != read_err_[1]) {
+ if ((fd != exec_control_[1]) &&
+ (fd != write_out_[0]) &&
+ (fd != read_in_[1]) &&
+ (fd != read_err_[1])) {
VOID_TEMP_FAILURE_RETRY(close(fd));
}
}
@@ -680,9 +684,8 @@
const int kBufferSize = 1024;
char os_error_message[kBufferSize];
Utils::StrError(errno, os_error_message, kBufferSize);
- int bytes_written =
- FDUtils::WriteToBlocking(
- exec_control_[1], &child_errno, sizeof(child_errno));
+ int bytes_written = FDUtils::WriteToBlocking(
+ exec_control_[1], &child_errno, sizeof(child_errno));
if (bytes_written == sizeof(child_errno)) {
FDUtils::WriteToBlocking(
exec_control_[1], os_error_message, strlen(os_error_message) + 1);
@@ -751,6 +754,9 @@
intptr_t* id_;
intptr_t* exit_event_;
char** os_error_message_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter);
};
@@ -786,10 +792,14 @@
class BufferList: public BufferListBase {
public:
+ BufferList() {}
+
bool Read(int fd, intptr_t available) {
// Read all available bytes.
while (available > 0) {
- if (free_size_ == 0) Allocate();
+ if (free_size_ == 0) {
+ Allocate();
+ }
ASSERT(free_size_ > 0);
ASSERT(free_size_ <= kBufferSize);
size_t block_size = dart::Utils::Minimum(free_size_, available);
@@ -797,13 +807,18 @@
fd,
reinterpret_cast<void*>(FreeSpaceAddress()),
block_size));
- if (bytes < 0) return false;
+ if (bytes < 0) {
+ return false;
+ }
data_size_ += bytes;
free_size_ -= bytes;
available -= bytes;
}
return true;
}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BufferList);
};
@@ -856,7 +871,7 @@
int current_alive = alive;
for (int i = 0; i < current_alive; i++) {
intptr_t avail;
- if (fds[i].revents & POLLIN) {
+ if ((fds[i].revents & POLLIN) != 0) {
avail = FDUtils::AvailableBytes(fds[i].fd);
// On Mac OS POLLIN can be set with zero available
// bytes. POLLHUP is most likely also set in this case.
@@ -882,8 +897,8 @@
}
}
}
- if (fds[i].revents & POLLHUP ||
- ((fds[i].revents & POLLIN) && avail == 0)) {
+ if (((fds[i].revents & POLLHUP) != 0) ||
+ (((fds[i].revents & POLLIN) != 0) && (avail == 0))) {
VOID_TEMP_FAILURE_RETRY(close(fds[i].fd));
alive--;
if (i < alive) {
@@ -900,7 +915,9 @@
// Calculate the exit code.
intptr_t exit_code = exit_code_data.ints[0];
intptr_t negative = exit_code_data.ints[1];
- if (negative) exit_code = -exit_code;
+ if (negative != 0) {
+ exit_code = -exit_code;
+ }
result->set_exit_code(exit_code);
return true;
@@ -992,7 +1009,9 @@
intptr_t Process::SetSignalHandler(intptr_t signal) {
signal = SignalMap(signal);
- if (signal == -1) return -1;
+ if (signal == -1) {
+ return -1;
+ }
bool found = false;
for (int i = 0; i < kSignalsCount; i++) {
if (kSignals[i] == signal) {
@@ -1000,7 +1019,9 @@
break;
}
}
- if (!found) return -1;
+ if (!found) {
+ return -1;
+ }
int fds[2];
if (NO_RETRY_EXPECTED(pipe(fds)) != 0) {
return -1;
@@ -1045,7 +1066,9 @@
void Process::ClearSignalHandler(intptr_t signal) {
signal = SignalMap(signal);
- if (signal == -1) return;
+ if (signal == -1) {
+ return;
+ }
ThreadSignalBlocker blocker(kSignalsCount, kSignals);
MutexLocker lock(signal_mutex);
SignalInfo* handler = signal_handlers;
@@ -1054,7 +1077,9 @@
bool remove = false;
if (handler->signal() == signal) {
if (handler->port() == Dart_GetMainPortId()) {
- if (signal_handlers == handler) signal_handlers = handler->next();
+ if (signal_handlers == handler) {
+ signal_handlers = handler->next();
+ }
handler->Unlink();
remove = true;
} else {
@@ -1062,7 +1087,9 @@
}
}
SignalInfo* next = handler->next();
- if (remove) delete handler;
+ if (remove) {
+ delete handler;
+ }
handler = next;
}
if (unlisten) {
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index 1c0a03d..9777c55 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -5,11 +5,12 @@
#include "platform/globals.h"
#if defined(TARGET_OS_WINDOWS)
+#include "bin/process.h"
+
#include <process.h> // NOLINT
#include "bin/builtin.h"
#include "bin/dartutils.h"
-#include "bin/process.h"
#include "bin/eventhandler.h"
#include "bin/lockers.h"
#include "bin/log.h"
@@ -18,7 +19,6 @@
#include "bin/utils.h"
#include "bin/utils_win.h"
-
namespace dart {
namespace bin {
@@ -72,6 +72,8 @@
HANDLE exit_pipe_;
// Link to next ProcessInfo object in the singly-linked list.
ProcessInfo* next_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProcessInfo);
};
@@ -143,7 +145,9 @@
// Callback called when an exit code is available from one of the
// processes in the list.
static void CALLBACK ExitCodeCallback(PVOID data, BOOLEAN timed_out) {
- if (timed_out) return;
+ if (timed_out) {
+ return;
+ }
DWORD pid = reinterpret_cast<DWORD>(data);
HANDLE handle;
HANDLE wait_handle;
@@ -154,13 +158,12 @@
}
// Unregister the event in a non-blocking way.
BOOL ok = UnregisterWait(wait_handle);
- if (!ok && GetLastError() != ERROR_IO_PENDING) {
+ if (!ok && (GetLastError() != ERROR_IO_PENDING)) {
FATAL("Failed unregistering wait operation");
}
// Get and report the exit code to Dart.
int exit_code;
- ok = GetExitCodeProcess(handle,
- reinterpret_cast<DWORD*>(&exit_code));
+ ok = GetExitCodeProcess(handle, reinterpret_cast<DWORD*>(&exit_code));
if (!ok) {
FATAL1("GetExitCodeProcess failed %d\n", GetLastError());
}
@@ -176,9 +179,9 @@
// pipe has been closed. It is therefore not a problem that
// WriteFile fails with a closed pipe error
// (ERROR_NO_DATA). Other errors should not happen.
- if (ok && written != sizeof(message)) {
+ if (ok && (written != sizeof(message))) {
FATAL("Failed to write entire process exit message");
- } else if (!ok && GetLastError() != ERROR_NO_DATA) {
+ } else if (!ok && (GetLastError() != ERROR_NO_DATA)) {
FATAL1("Failed to write exit code: %d", GetLastError());
}
// Remove the process from the list of active processes.
@@ -191,6 +194,9 @@
// Mutex protecting all accesses to the linked list of active
// processes.
static Mutex* mutex_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList);
};
@@ -249,7 +255,7 @@
return false;
}
} else {
- ASSERT(type == kInheritWrite || type == kInheritNone);
+ ASSERT((type == kInheritWrite) || (type == kInheritNone));
handles[kReadHandle] =
CreateNamedPipeW(pipe_name,
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
@@ -357,19 +363,19 @@
HMODULE kernel32_module = GetModuleHandleW(L"kernel32.dll");
if (!load_attempted) {
MutexLocker locker(mutex);
- if (load_attempted) return delete_proc_thread_attr_list != NULL;
+ if (load_attempted) {
+ return (delete_proc_thread_attr_list != NULL);
+ }
init_proc_thread_attr_list = reinterpret_cast<InitProcThreadAttrListFn>(
GetProcAddress(kernel32_module, "InitializeProcThreadAttributeList"));
- update_proc_thread_attr =
- reinterpret_cast<UpdateProcThreadAttrFn>(
- GetProcAddress(kernel32_module, "UpdateProcThreadAttribute"));
+ update_proc_thread_attr = reinterpret_cast<UpdateProcThreadAttrFn>(
+ GetProcAddress(kernel32_module, "UpdateProcThreadAttribute"));
delete_proc_thread_attr_list = reinterpret_cast<DeleteProcThreadAttrListFn>(
- reinterpret_cast<DeleteProcThreadAttrListFn>(
- GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList")));
+ GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList"));
load_attempted = true;
- return delete_proc_thread_attr_list != NULL;
+ return (delete_proc_thread_attr_list != NULL);
}
- return delete_proc_thread_attr_list != NULL;
+ return (delete_proc_thread_attr_list != NULL);
}
@@ -378,7 +384,7 @@
static int GenerateNames(wchar_t pipe_names[Count][kMaxPipeNameSize]) {
UUID uuid;
RPC_STATUS status = UuidCreateSequential(&uuid);
- if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
+ if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) {
return status;
}
RPC_WSTR uuid_string;
@@ -451,7 +457,8 @@
command_line_length += arguments_length + 1;
// Put together command-line string.
- command_line_ = new wchar_t[command_line_length];
+ command_line_ = reinterpret_cast<wchar_t*>(Dart_ScopeAllocate(
+ command_line_length * sizeof(*command_line_)));
int len = 0;
int remaining = command_line_length;
int written =
@@ -460,9 +467,8 @@
remaining -= written;
ASSERT(remaining >= 0);
for (int i = 0; i < arguments_length; i++) {
- written =
- _snwprintf(
- command_line_ + len, remaining, L" %s", system_arguments[i]);
+ written = _snwprintf(
+ command_line_ + len, remaining, L" %s", system_arguments[i]);
len += written;
remaining -= written;
ASSERT(remaining >= 0);
@@ -485,7 +491,8 @@
for (intptr_t i = 0; i < environment_length; i++) {
block_size += wcslen(system_environment[i]) + 1;
}
- environment_block_ = new wchar_t[block_size];
+ environment_block_ = reinterpret_cast<wchar_t*>(Dart_ScopeAllocate(
+ block_size * sizeof(*environment_block_)));
intptr_t block_index = 0;
for (intptr_t i = 0; i < environment_length; i++) {
intptr_t len = wcslen(system_environment[i]);
@@ -513,12 +520,8 @@
~ProcessStarter() {
- // Deallocate command-line and environment block strings.
- delete[] command_line_;
- delete[] environment_block_;
if (attribute_list_ != NULL) {
delete_proc_thread_attr_list(attribute_list_);
- free(attribute_list_);
}
}
@@ -526,7 +529,9 @@
int Start() {
// Create pipes required.
int err = CreatePipes();
- if (err != 0) return err;
+ if (err != 0) {
+ return err;
+ }
// Setup info structures.
STARTUPINFOEXW startup_info;
@@ -545,11 +550,11 @@
// The call to determine the size of an attribute list always fails with
// ERROR_INSUFFICIENT_BUFFER and that error should be ignored.
if (!init_proc_thread_attr_list(NULL, 1, 0, &size) &&
- GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
return CleanupAndReturnError();
}
- attribute_list_ =
- reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size));
+ attribute_list_ = reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(
+ Dart_ScopeAllocate(size));
ZeroMemory(attribute_list_, size);
if (!init_proc_thread_attr_list(attribute_list_, 1, 0, &size)) {
return CleanupAndReturnError();
@@ -650,10 +655,19 @@
}
}
} else {
- // Open NUL for stdin, stdout and stderr.
- if ((stdin_handles_[kReadHandle] = OpenNul()) == INVALID_HANDLE_VALUE ||
- (stdout_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE ||
- (stderr_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE) {
+ // Open NUL for stdin, stdout, and stderr.
+ stdin_handles_[kReadHandle] = OpenNul();
+ if (stdin_handles_[kReadHandle] == INVALID_HANDLE_VALUE) {
+ return CleanupAndReturnError();
+ }
+
+ stdout_handles_[kWriteHandle] = OpenNul();
+ if (stdout_handles_[kWriteHandle] == INVALID_HANDLE_VALUE) {
+ return CleanupAndReturnError();
+ }
+
+ stderr_handles_[kWriteHandle] = OpenNul();
+ if (stderr_handles_[kWriteHandle] == INVALID_HANDLE_VALUE) {
return CleanupAndReturnError();
}
}
@@ -688,6 +702,10 @@
intptr_t* id_;
intptr_t* exit_handler_;
char** os_error_message_;
+
+ private:
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter);
};
@@ -738,7 +756,9 @@
// The access to the read buffer for overlapped read.
void GetReadBuffer(uint8_t** buffer, intptr_t* size) {
ASSERT(!read_pending_);
- if (free_size_ == 0) Allocate();
+ if (free_size_ == 0) {
+ Allocate();
+ }
ASSERT(free_size_ > 0);
ASSERT(free_size_ <= kBufferSize);
*buffer = FreeSpaceAddress();
@@ -763,11 +783,15 @@
private:
bool read_pending_;
+
+ DISALLOW_COPY_AND_ASSIGN(BufferList);
};
class OverlappedHandle {
public:
+ OverlappedHandle() {}
+
void Init(HANDLE handle, HANDLE event) {
handle_ = handle;
event_ = event;
@@ -775,7 +799,7 @@
}
bool HasEvent(HANDLE event) {
- return event_ == event;
+ return (event_ == event);
}
bool Read() {
@@ -793,7 +817,9 @@
intptr_t buffer_size;
buffer_.GetReadBuffer(&buffer, &buffer_size);
BOOL ok = ReadFile(handle_, buffer, buffer_size, NULL, &overlapped_);
- if (!ok) return GetLastError() == ERROR_IO_PENDING;
+ if (!ok) {
+ return (GetLastError() == ERROR_IO_PENDING);
+ }
buffer_.DataIsRead(overlapped_.InternalHigh);
}
}
@@ -833,6 +859,7 @@
BufferList buffer_;
DISALLOW_ALLOCATION();
+ DISALLOW_COPY_AND_ASSIGN(OverlappedHandle);
};
@@ -905,12 +932,14 @@
// Calculate the exit code.
ASSERT(oh[2].GetDataSize() == 8);
- uint32_t exit[2];
- memmove(&exit, oh[2].GetFirstDataBuffer(), sizeof(exit));
+ uint32_t exit_codes[2];
+ memmove(&exit_codes, oh[2].GetFirstDataBuffer(), sizeof(exit_codes));
oh[2].FreeDataBuffer();
- intptr_t exit_code = exit[0];
- intptr_t negative = exit[1];
- if (negative) exit_code = -exit_code;
+ intptr_t exit_code = exit_codes[0];
+ intptr_t negative = exit_codes[1];
+ if (negative != 0) {
+ exit_code = -exit_code;
+ }
result->set_exit_code(exit_code);
return true;
}
@@ -931,7 +960,9 @@
if (!success) {
process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id);
// The process is already dead.
- if (process_handle == INVALID_HANDLE_VALUE) return false;
+ if (process_handle == INVALID_HANDLE_VALUE) {
+ return false;
+ }
}
BOOL result = TerminateProcess(process_handle, -1);
return result ? true : false;
@@ -985,12 +1016,16 @@
intptr_t Process::SetSignalHandler(intptr_t signal) {
signal = GetWinSignal(signal);
- if (signal == -1) return -1;
+ if (signal == -1) {
+ return -1;
+ }
// Generate a unique pipe name for the named pipe.
wchar_t pipe_name[kMaxPipeNameSize];
int status = GenerateNames<1>(&pipe_name);
- if (status != 0) return status;
+ if (status != 0) {
+ return status;
+ }
HANDLE fds[2];
if (!CreateProcessPipe(fds, pipe_name, kInheritNone)) {
@@ -1019,12 +1054,14 @@
void Process::ClearSignalHandler(intptr_t signal) {
signal = GetWinSignal(signal);
- if (signal == -1) return;
+ if (signal == -1) {
+ return;
+ }
MutexLocker lock(signal_mutex);
SignalInfo* handler = signal_handlers;
while (handler != NULL) {
- if (handler->port() == Dart_GetMainPortId() &&
- handler->signal() == signal) {
+ if ((handler->port() == Dart_GetMainPortId()) &&
+ (handler->signal() == signal)) {
handler->Unlink();
break;
}
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index ec9479a..5b62b20 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -4,8 +4,8 @@
#include <stdio.h>
-#include "bin/file.h"
#include "bin/dartutils.h"
+#include "bin/file.h"
#include "bin/platform.h"
#include "vm/benchmark_test.h"
@@ -108,6 +108,7 @@
const char* err_msg = Dart::InitOnce(dart::bin::vm_isolate_snapshot_buffer,
NULL, NULL,
NULL, NULL,
+ NULL,
dart::bin::DartUtils::OpenFile,
dart::bin::DartUtils::ReadFile,
dart::bin::DartUtils::WriteFile,
diff --git a/runtime/bin/secure_socket.h b/runtime/bin/secure_socket.h
index 754d240..d9fb968 100644
--- a/runtime/bin/secure_socket.h
+++ b/runtime/bin/secure_socket.h
@@ -9,126 +9,15 @@
#error "secure_socket.h can only be included on builds with SSL enabled"
#endif
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-#include <openssl/bio.h>
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <openssl/x509.h>
-
-#include "bin/builtin.h"
-#include "bin/dartutils.h"
-#include "bin/socket.h"
-#include "bin/thread.h"
-#include "bin/utils.h"
-
-namespace dart {
-namespace bin {
-
-/* These are defined in root_certificates.cc. */
-extern const unsigned char* root_certificates_pem;
-extern unsigned int root_certificates_pem_length;
-
-/*
- * SSLFilter encapsulates the NSS SSL(TLS) code in a filter, that communicates
- * with the containing _SecureFilterImpl Dart object through four shared
- * ExternalByteArray buffers, for reading and writing plaintext, and
- * reading and writing encrypted text. The filter handles handshaking
- * and certificate verification.
- */
-class SSLFilter {
- public:
- // These enums must agree with those in sdk/lib/io/secure_socket.dart.
- enum BufferIndex {
- kReadPlaintext,
- kWritePlaintext,
- kReadEncrypted,
- kWriteEncrypted,
- kNumBuffers,
- kFirstEncrypted = kReadEncrypted
- };
-
- SSLFilter()
- : callback_error(NULL),
- ssl_(NULL),
- socket_side_(NULL),
- string_start_(NULL),
- string_length_(NULL),
- handshake_complete_(NULL),
- bad_certificate_callback_(NULL),
- in_handshake_(false),
- hostname_(NULL) { }
-
- ~SSLFilter();
-
- Dart_Handle Init(Dart_Handle dart_this);
- void Connect(const char* hostname,
- SSL_CTX* context,
- bool is_server,
- bool request_client_certificate,
- bool require_client_certificate,
- Dart_Handle protocols_handle);
- void Destroy();
- void Handshake();
- void GetSelectedProtocol(Dart_NativeArguments args);
- void Renegotiate(bool use_session_cache,
- bool request_client_certificate,
- bool require_client_certificate);
- void RegisterHandshakeCompleteCallback(Dart_Handle handshake_complete);
- void RegisterBadCertificateCallback(Dart_Handle callback);
- Dart_Handle bad_certificate_callback() {
- return Dart_HandleFromPersistent(bad_certificate_callback_);
- }
- int ProcessReadPlaintextBuffer(int start, int end);
- int ProcessWritePlaintextBuffer(int start, int end);
- int ProcessReadEncryptedBuffer(int start, int end);
- int ProcessWriteEncryptedBuffer(int start, int end);
- bool ProcessAllBuffers(int starts[kNumBuffers],
- int ends[kNumBuffers],
- bool in_handshake);
- Dart_Handle PeerCertificate();
- static void InitializeLibrary();
- Dart_Handle callback_error;
-
- static CObject* ProcessFilterRequest(const CObjectArray& request);
-
- // The index of the external data field in _ssl that points to the SSLFilter.
- static int filter_ssl_index;
-
- // TODO(whesse): make private:
- SSL* ssl_;
- BIO* socket_side_;
-
-
- private:
- static bool library_initialized_;
- static Mutex* mutex_; // To protect library initialization.
-
- uint8_t* buffers_[kNumBuffers];
- int buffer_size_;
- int encrypted_buffer_size_;
- Dart_PersistentHandle string_start_;
- Dart_PersistentHandle string_length_;
- Dart_PersistentHandle dart_buffer_objects_[kNumBuffers];
- Dart_PersistentHandle handshake_complete_;
- Dart_PersistentHandle bad_certificate_callback_;
- bool in_handshake_;
- bool is_server_;
- char* hostname_;
-
- static bool isBufferEncrypted(int i) {
- return static_cast<BufferIndex>(i) >= kFirstEncrypted;
- }
- Dart_Handle InitializeBuffers(Dart_Handle dart_this);
- void InitializePlatformData();
-
- DISALLOW_COPY_AND_ASSIGN(SSLFilter);
-};
-
-} // namespace bin
-} // namespace dart
+#include "platform/globals.h"
+#if defined(TARGET_OS_ANDROID) || \
+ defined(TARGET_OS_LINUX) || \
+ defined(TARGET_OS_WINDOWS)
+#include "bin/secure_socket_boringssl.h"
+#elif defined(TARGET_OS_MACOS)
+#include "bin/secure_socket_macos.h"
+#else
+#error Unknown target os.
+#endif
#endif // BIN_SECURE_SOCKET_H_
diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket_boringssl.cc
similarity index 98%
rename from runtime/bin/secure_socket.cc
rename to runtime/bin/secure_socket_boringssl.cc
index a269134..6c4df2b 100644
--- a/runtime/bin/secure_socket.cc
+++ b/runtime/bin/secure_socket_boringssl.cc
@@ -2,13 +2,19 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+#include "platform/globals.h"
+#if defined(TARGET_OS_ANDROID) || \
+ defined(TARGET_OS_LINUX) || \
+ defined(TARGET_OS_WINDOWS)
+
#include "bin/secure_socket.h"
+#include "bin/secure_socket_boringssl.h"
#include <errno.h>
#include <fcntl.h>
-#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
+#include <sys/stat.h>
#include <openssl/bio.h>
#include <openssl/err.h>
@@ -83,8 +89,7 @@
/* Handle an error reported from the BoringSSL library. */
static void ThrowIOException(int status,
const char* exception_type,
- const char* message,
- bool free_message = false) {
+ const char* message) {
char error_string[SSL_ERROR_MESSAGE_BUFFER_SIZE];
FetchErrorString(error_string, SSL_ERROR_MESSAGE_BUFFER_SIZE);
OSError os_error_struct(status, error_string, OSError::kBoringSSL);
@@ -92,9 +97,6 @@
Dart_Handle exception =
DartUtils::NewDartIOException(exception_type, message, os_error);
ASSERT(!Dart_IsError(exception));
- if (free_message) {
- free(const_cast<char*>(message));
- }
Dart_ThrowException(exception);
UNREACHABLE();
}
@@ -677,7 +679,7 @@
const char* password) {
ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
if (p12.get() == NULL) {
- return NULL;
+ return 0;
}
EVP_PKEY* key = NULL;
@@ -764,6 +766,11 @@
}
+void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) {
+ Dart_SetReturnValue(args, Dart_NewBoolean(true));
+}
+
+
void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
Dart_NativeArguments args) {
SSL_CTX* context = GetSecurityContext(args);
@@ -787,7 +794,7 @@
const char* password) {
ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
if (p12.get() == NULL) {
- return NULL;
+ return 0;
}
EVP_PKEY* key = NULL;
@@ -1658,3 +1665,5 @@
} // namespace bin
} // namespace dart
+
+#endif // defined(TARGET_OS_LINUX)
diff --git a/runtime/bin/secure_socket_boringssl.h b/runtime/bin/secure_socket_boringssl.h
new file mode 100644
index 0000000..9dbe250
--- /dev/null
+++ b/runtime/bin/secure_socket_boringssl.h
@@ -0,0 +1,133 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef BIN_SECURE_SOCKET_BORINGSSL_H_
+#define BIN_SECURE_SOCKET_BORINGSSL_H_
+
+#if !defined(BIN_SECURE_SOCKET_H_)
+#error Do not include secure_socket_boringssl.h directly. Use secure_socket.h.
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "bin/builtin.h"
+#include "bin/dartutils.h"
+#include "bin/socket.h"
+#include "bin/thread.h"
+#include "bin/utils.h"
+
+namespace dart {
+namespace bin {
+
+/* These are defined in root_certificates.cc. */
+extern const unsigned char* root_certificates_pem;
+extern unsigned int root_certificates_pem_length;
+
+/*
+ * SSLFilter encapsulates the NSS SSL(TLS) code in a filter, that communicates
+ * with the containing _SecureFilterImpl Dart object through four shared
+ * ExternalByteArray buffers, for reading and writing plaintext, and
+ * reading and writing encrypted text. The filter handles handshaking
+ * and certificate verification.
+ */
+class SSLFilter {
+ public:
+ // These enums must agree with those in sdk/lib/io/secure_socket.dart.
+ enum BufferIndex {
+ kReadPlaintext,
+ kWritePlaintext,
+ kReadEncrypted,
+ kWriteEncrypted,
+ kNumBuffers,
+ kFirstEncrypted = kReadEncrypted
+ };
+
+ SSLFilter()
+ : callback_error(NULL),
+ ssl_(NULL),
+ socket_side_(NULL),
+ string_start_(NULL),
+ string_length_(NULL),
+ handshake_complete_(NULL),
+ bad_certificate_callback_(NULL),
+ in_handshake_(false),
+ hostname_(NULL) { }
+
+ ~SSLFilter();
+
+ Dart_Handle Init(Dart_Handle dart_this);
+ void Connect(const char* hostname,
+ SSL_CTX* context,
+ bool is_server,
+ bool request_client_certificate,
+ bool require_client_certificate,
+ Dart_Handle protocols_handle);
+ void Destroy();
+ void Handshake();
+ void GetSelectedProtocol(Dart_NativeArguments args);
+ void Renegotiate(bool use_session_cache,
+ bool request_client_certificate,
+ bool require_client_certificate);
+ void RegisterHandshakeCompleteCallback(Dart_Handle handshake_complete);
+ void RegisterBadCertificateCallback(Dart_Handle callback);
+ Dart_Handle bad_certificate_callback() {
+ return Dart_HandleFromPersistent(bad_certificate_callback_);
+ }
+ int ProcessReadPlaintextBuffer(int start, int end);
+ int ProcessWritePlaintextBuffer(int start, int end);
+ int ProcessReadEncryptedBuffer(int start, int end);
+ int ProcessWriteEncryptedBuffer(int start, int end);
+ bool ProcessAllBuffers(int starts[kNumBuffers],
+ int ends[kNumBuffers],
+ bool in_handshake);
+ Dart_Handle PeerCertificate();
+ static void InitializeLibrary();
+ Dart_Handle callback_error;
+
+ static CObject* ProcessFilterRequest(const CObjectArray& request);
+
+ // The index of the external data field in _ssl that points to the SSLFilter.
+ static int filter_ssl_index;
+
+ // TODO(whesse): make private:
+ SSL* ssl_;
+ BIO* socket_side_;
+
+ private:
+ static bool library_initialized_;
+ static Mutex* mutex_; // To protect library initialization.
+
+ uint8_t* buffers_[kNumBuffers];
+ int buffer_size_;
+ int encrypted_buffer_size_;
+ Dart_PersistentHandle string_start_;
+ Dart_PersistentHandle string_length_;
+ Dart_PersistentHandle dart_buffer_objects_[kNumBuffers];
+ Dart_PersistentHandle handshake_complete_;
+ Dart_PersistentHandle bad_certificate_callback_;
+ bool in_handshake_;
+ bool is_server_;
+ char* hostname_;
+
+ static bool isBufferEncrypted(int i) {
+ return static_cast<BufferIndex>(i) >= kFirstEncrypted;
+ }
+ Dart_Handle InitializeBuffers(Dart_Handle dart_this);
+ void InitializePlatformData();
+
+ DISALLOW_COPY_AND_ASSIGN(SSLFilter);
+};
+
+} // namespace bin
+} // namespace dart
+
+#endif // BIN_SECURE_SOCKET_BORINGSSL_H_
diff --git a/runtime/bin/secure_socket_macos.cc b/runtime/bin/secure_socket_macos.cc
new file mode 100644
index 0000000..53c9ae7
--- /dev/null
+++ b/runtime/bin/secure_socket_macos.cc
@@ -0,0 +1,2074 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_MACOS)
+
+#include "bin/secure_socket.h"
+#include "bin/secure_socket_macos.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/syslimits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/SecureTransport.h>
+#include <Security/Security.h>
+
+#include "bin/builtin.h"
+#include "bin/dartutils.h"
+#include "bin/lockers.h"
+#include "bin/log.h"
+#include "bin/socket.h"
+#include "bin/thread.h"
+#include "bin/utils.h"
+
+#include "platform/text_buffer.h"
+#include "platform/utils.h"
+
+#include "include/dart_api.h"
+
+// Return the error from the containing function if handle is an error handle.
+#define RETURN_IF_ERROR(handle) \
+ { \
+ Dart_Handle __handle = handle; \
+ if (Dart_IsError((__handle))) { \
+ return __handle; \
+ } \
+ }
+
+// We need to access this private API function to create a SecIdentityRef
+// without writing a custom keychain to the filesystem. This is the approach
+// taken in WebKit:
+// https://webkit.googlesource.com/WebKit/+/master/Source/WebKit2/Shared/cf/ArgumentCodersCF.cpp
+extern "C" {
+SecIdentityRef SecIdentityCreate(CFAllocatorRef allocator,
+ SecCertificateRef certificate,
+ SecKeyRef private_key);
+}
+
+namespace dart {
+namespace bin {
+
+// SSLCertContext wraps the certificates needed for a SecureTransport
+// connection. Fields are protected by the mutex_ field, and may only be set
+// once. This is to allow access by both the Dart thread and the IOService
+// thread. Setters return false if the field was already set.
+class SSLCertContext {
+ public:
+ SSLCertContext() :
+ mutex_(new Mutex()),
+ private_key_(NULL),
+ keychain_(NULL),
+ cert_chain_(NULL),
+ trusted_certs_(NULL),
+ cert_authorities_(NULL),
+ trust_builtin_(false) {}
+
+ ~SSLCertContext() {
+ if (private_key_ != NULL) {
+ CFRelease(private_key_);
+ }
+ if (keychain_ != NULL) {
+ SecKeychainDelete(keychain_);
+ CFRelease(keychain_);
+ }
+ if (cert_chain_ != NULL) {
+ CFRelease(cert_chain_);
+ }
+ if (trusted_certs_ != NULL) {
+ CFRelease(trusted_certs_);
+ }
+ if (cert_authorities_ != NULL) {
+ CFRelease(cert_authorities_);
+ }
+ delete mutex_;
+ }
+
+ SecKeyRef private_key() {
+ MutexLocker m(mutex_);
+ return private_key_;
+ }
+ bool set_private_key(SecKeyRef private_key) {
+ MutexLocker m(mutex_);
+ if (private_key_ != NULL) {
+ return false;
+ }
+ private_key_ = private_key;
+ return true;
+ }
+
+ SecKeychainRef keychain() {
+ MutexLocker m(mutex_);
+ return keychain_;
+ }
+ bool set_keychain(SecKeychainRef keychain) {
+ MutexLocker m(mutex_);
+ if (keychain_ != NULL) {
+ return false;
+ }
+ keychain_ = keychain;
+ return true;
+ }
+
+ CFArrayRef cert_chain() {
+ MutexLocker m(mutex_);
+ return cert_chain_;
+ }
+ bool set_cert_chain(CFArrayRef cert_chain) {
+ MutexLocker m(mutex_);
+ if (cert_chain_ != NULL) {
+ return false;
+ }
+ cert_chain_ = cert_chain;
+ return true;
+ }
+
+ CFArrayRef trusted_certs() {
+ MutexLocker m(mutex_);
+ return trusted_certs_;
+ }
+ bool set_trusted_certs(CFArrayRef trusted_certs) {
+ MutexLocker m(mutex_);
+ if (trusted_certs_ != NULL) {
+ return false;
+ }
+ trusted_certs_ = trusted_certs;
+ return true;
+ }
+
+ CFArrayRef cert_authorities() {
+ MutexLocker m(mutex_);
+ return cert_authorities_;
+ }
+ bool set_cert_authorities(CFArrayRef cert_authorities) {
+ MutexLocker m(mutex_);
+ if (cert_authorities_ != NULL) {
+ return false;
+ }
+ cert_authorities_ = cert_authorities;
+ return true;
+ }
+
+ bool trust_builtin() {
+ MutexLocker m(mutex_);
+ return trust_builtin_;
+ }
+ void set_trust_builtin(bool trust_builtin) {
+ MutexLocker m(mutex_);
+ trust_builtin_ = trust_builtin;
+ }
+
+ private:
+ // The context is accessed both by Dart code and the IOService. This mutex
+ // protects all fields.
+ Mutex* mutex_;
+
+ SecKeyRef private_key_;
+ SecKeychainRef keychain_;
+
+ // CFArrays of SecCertificateRef.
+ CFArrayRef cert_chain_;
+ CFArrayRef trusted_certs_;
+ CFArrayRef cert_authorities_;
+
+ bool trust_builtin_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLCertContext);
+};
+
+static const int kSSLFilterNativeFieldIndex = 0;
+static const int kSecurityContextNativeFieldIndex = 0;
+static const int kX509NativeFieldIndex = 0;
+
+static const bool SSL_LOG_STATUS = false;
+static const bool SSL_LOG_DATA = false;
+static const bool SSL_LOG_CERTS = false;
+static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000;
+static const intptr_t PEM_BUFSIZE = 1024;
+
+static char* CFStringRefToCString(CFStringRef cfstring) {
+ CFIndex len = CFStringGetLength(cfstring);
+ CFIndex max_len =
+ CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8) + 1;
+ char* result = reinterpret_cast<char*>(Dart_ScopeAllocate(max_len));
+ ASSERT(result != NULL);
+ bool success =
+ CFStringGetCString(cfstring, result, max_len, kCFStringEncodingUTF8);
+ return success ? result : NULL;
+}
+
+
+// Handle an error reported from the SecureTransport library.
+static void ThrowIOException(OSStatus status,
+ const char* exception_type,
+ const char* message) {
+ TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE);
+ CFStringRef error_string = SecCopyErrorMessageString(status, NULL);
+ if (error_string == NULL) {
+ status_message.Printf("OSStatus = %ld: https://www.osstatus.com",
+ static_cast<intptr_t>(status));
+ } else {
+ char* error = CFStringRefToCString(error_string);
+ status_message.Printf("OSStatus = %ld: %s",
+ static_cast<intptr_t>(status), error);
+ CFRelease(error_string);
+ }
+ OSError os_error_struct(status, status_message.buf(), OSError::kBoringSSL);
+ Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
+ Dart_Handle exception =
+ DartUtils::NewDartIOException(exception_type, message, os_error);
+ ASSERT(!Dart_IsError(exception));
+ Dart_ThrowException(exception);
+ UNREACHABLE();
+}
+
+
+static void CheckStatus(OSStatus status,
+ const char* type,
+ const char* message) {
+ if (status == noErr) {
+ return;
+ }
+ ThrowIOException(status, type, message);
+}
+
+
+static SSLFilter* GetFilter(Dart_NativeArguments args) {
+ SSLFilter* filter;
+ Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+ ASSERT(Dart_IsInstance(dart_this));
+ ThrowIfError(Dart_GetNativeInstanceField(
+ dart_this,
+ kSSLFilterNativeFieldIndex,
+ reinterpret_cast<intptr_t*>(&filter)));
+ return filter;
+}
+
+
+static void DeleteFilter(void* isolate_data,
+ Dart_WeakPersistentHandle handle,
+ void* context_pointer) {
+ SSLFilter* filter = reinterpret_cast<SSLFilter*>(context_pointer);
+ delete filter;
+}
+
+
+static Dart_Handle SetFilter(Dart_NativeArguments args, SSLFilter* filter) {
+ ASSERT(filter != NULL);
+ const int approximate_size_of_filter = 1500;
+ Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
+ RETURN_IF_ERROR(dart_this);
+ ASSERT(Dart_IsInstance(dart_this));
+ Dart_Handle err = Dart_SetNativeInstanceField(
+ dart_this,
+ kSSLFilterNativeFieldIndex,
+ reinterpret_cast<intptr_t>(filter));
+ RETURN_IF_ERROR(err);
+ Dart_NewWeakPersistentHandle(dart_this,
+ reinterpret_cast<void*>(filter),
+ approximate_size_of_filter,
+ DeleteFilter);
+ return Dart_Null();
+}
+
+
+static SSLCertContext* GetSecurityContext(Dart_NativeArguments args) {
+ SSLCertContext* context;
+ Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+ ASSERT(Dart_IsInstance(dart_this));
+ ThrowIfError(Dart_GetNativeInstanceField(
+ dart_this,
+ kSecurityContextNativeFieldIndex,
+ reinterpret_cast<intptr_t*>(&context)));
+ return context;
+}
+
+
+static void DeleteCertContext(void* isolate_data,
+ Dart_WeakPersistentHandle handle,
+ void* context_pointer) {
+ SSLCertContext* context = static_cast<SSLCertContext*>(context_pointer);
+ delete context;
+}
+
+
+static Dart_Handle SetSecurityContext(Dart_NativeArguments args,
+ SSLCertContext* context) {
+ const int approximate_size_of_context = 1500;
+ Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
+ RETURN_IF_ERROR(dart_this);
+ ASSERT(Dart_IsInstance(dart_this));
+ Dart_Handle err = Dart_SetNativeInstanceField(
+ dart_this,
+ kSecurityContextNativeFieldIndex,
+ reinterpret_cast<intptr_t>(context));
+ RETURN_IF_ERROR(err);
+ Dart_NewWeakPersistentHandle(dart_this,
+ context,
+ approximate_size_of_context,
+ DeleteCertContext);
+ return Dart_Null();
+}
+
+
+static SecCertificateRef GetX509Certificate(Dart_NativeArguments args) {
+ SecCertificateRef certificate;
+ Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+ ASSERT(Dart_IsInstance(dart_this));
+ ThrowIfError(Dart_GetNativeInstanceField(
+ dart_this,
+ kX509NativeFieldIndex,
+ reinterpret_cast<intptr_t*>(&certificate)));
+ return certificate;
+}
+
+
+static void ReleaseCertificate(void* isolate_data,
+ Dart_WeakPersistentHandle handle,
+ void* context_pointer) {
+ SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(context_pointer);
+ CFRelease(cert);
+}
+
+
+static Dart_Handle WrappedX509Certificate(SecCertificateRef certificate) {
+ const intptr_t approximate_size_of_certificate = 1500;
+ if (certificate == NULL) {
+ return Dart_Null();
+ }
+ Dart_Handle x509_type =
+ DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
+ if (Dart_IsError(x509_type)) {
+ return x509_type;
+ }
+ Dart_Handle arguments[] = { NULL };
+
+ Dart_Handle result =
+ Dart_New(x509_type, DartUtils::NewString("_"), 0, arguments);
+ if (Dart_IsError(result)) {
+ return result;
+ }
+ ASSERT(Dart_IsInstance(result));
+
+ // CFRetain in case the returned Dart object outlives the SecurityContext.
+ // CFRelease is in the Dart object's finalizer
+ CFRetain(certificate);
+ Dart_NewWeakPersistentHandle(result,
+ reinterpret_cast<void*>(certificate),
+ approximate_size_of_certificate,
+ ReleaseCertificate);
+
+ Dart_Handle status = Dart_SetNativeInstanceField(
+ result,
+ kX509NativeFieldIndex,
+ reinterpret_cast<intptr_t>(certificate));
+ if (Dart_IsError(status)) {
+ return status;
+ }
+ return result;
+}
+
+
+// Where the argument to the constructor is the handle for an object
+// implementing List<int>, this class creates a scope in which the memory
+// backing the list can be accessed.
+//
+// Do not make Dart_ API calls while in a ScopedMemBuffer.
+// Do not call Dart_PropagateError while in a ScopedMemBuffer.
+class ScopedMemBuffer {
+ public:
+ explicit ScopedMemBuffer(Dart_Handle object) {
+ if (!Dart_IsTypedData(object) && !Dart_IsList(object)) {
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "Argument is not a List<int>"));
+ }
+
+ uint8_t* bytes = NULL;
+ intptr_t bytes_len = 0;
+ bool is_typed_data = false;
+ if (Dart_IsTypedData(object)) {
+ is_typed_data = true;
+ Dart_TypedData_Type typ;
+ ThrowIfError(Dart_TypedDataAcquireData(
+ object,
+ &typ,
+ reinterpret_cast<void**>(&bytes),
+ &bytes_len));
+ } else {
+ ASSERT(Dart_IsList(object));
+ ThrowIfError(Dart_ListLength(object, &bytes_len));
+ bytes = Dart_ScopeAllocate(bytes_len);
+ ASSERT(bytes != NULL);
+ ThrowIfError(Dart_ListGetAsBytes(object, 0, bytes, bytes_len));
+ }
+
+ object_ = object;
+ bytes_ = bytes;
+ bytes_len_ = bytes_len;
+ is_typed_data_ = is_typed_data;
+ }
+
+ ~ScopedMemBuffer() {
+ if (is_typed_data_) {
+ ThrowIfError(Dart_TypedDataReleaseData(object_));
+ }
+ }
+
+ uint8_t* get() const { return bytes_; }
+ intptr_t length() const { return bytes_len_; }
+
+ private:
+ Dart_Handle object_;
+ uint8_t* bytes_;
+ intptr_t bytes_len_;
+ bool is_typed_data_;
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_COPY_AND_ASSIGN(ScopedMemBuffer);
+};
+
+
+static const char* GetPasswordArgument(Dart_NativeArguments args,
+ intptr_t index) {
+ Dart_Handle password_object =
+ ThrowIfError(Dart_GetNativeArgument(args, index));
+ const char* password = NULL;
+ if (Dart_IsString(password_object)) {
+ ThrowIfError(Dart_StringToCString(password_object, &password));
+ if (strlen(password) > PEM_BUFSIZE - 1) {
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "Password length is greater than 1023 bytes."));
+ }
+ } else if (Dart_IsNull(password_object)) {
+ password = "";
+ } else {
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "Password is not a String or null"));
+ }
+ return password;
+}
+
+
+static OSStatus GetKeyAndCerts(CFArrayRef items,
+ CFIndex items_length,
+ CFArrayRef* out_certs,
+ SecKeyRef* out_key) {
+ OSStatus status = noErr;
+
+ // Loop through the items, take only the first private key/identity, ignore
+ // any others, populate out_certs.
+ CFMutableArrayRef certs =
+ CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ SecKeyRef key = NULL;
+
+ for (CFIndex i = 0; i < items_length; ++i) {
+ CFTypeRef item =
+ reinterpret_cast<CFTypeRef>(CFArrayGetValueAtIndex(items, i));
+ CFTypeID item_type = CFGetTypeID(item);
+ if (item_type == SecCertificateGetTypeID()) {
+ if (SSL_LOG_CERTS) {
+ Log::Print("\titem %ld: Certificate\n", i);
+ }
+ CFArrayAppendValue(certs, item);
+ } else if ((item_type == SecKeyGetTypeID()) && (key == NULL)) {
+ if (SSL_LOG_CERTS) {
+ Log::Print("\titem %ld: Key\n", i);
+ }
+ key = reinterpret_cast<SecKeyRef>(const_cast<void*>(item));
+ CFRetain(key);
+ } else if ((item_type == SecIdentityGetTypeID()) && (key == NULL)) {
+ if (SSL_LOG_CERTS) {
+ Log::Print("\titem %ld: Identity\n", i);
+ }
+ SecIdentityRef identity =
+ reinterpret_cast<SecIdentityRef>(const_cast<void*>(item));
+ SecCertificateRef cert = NULL;
+
+ status = SecIdentityCopyPrivateKey(identity, &key);
+ if (status != noErr) {
+ CFRelease(certs);
+ return status;
+ }
+
+ status = SecIdentityCopyCertificate(identity, &cert);
+ if (status != noErr) {
+ CFRelease(key);
+ CFRelease(certs);
+ return status;
+ }
+ CFArrayAppendValue(certs, cert);
+ CFRelease(cert);
+ }
+ // Other item types are ignored.
+ }
+
+ if (out_key == NULL) {
+ if (key != NULL) {
+ CFRelease(key);
+ }
+ } else {
+ *out_key = key;
+ }
+
+ if (out_certs == NULL) {
+ if (certs != NULL) {
+ CFRelease(certs);
+ }
+ } else {
+ *out_certs = certs;
+ }
+ return status;
+}
+
+
+static OSStatus TryPEMImport(CFDataRef cfdata,
+ CFStringRef password,
+ CFArrayRef* out_certs,
+ SecKeyRef* out_key) {
+ OSStatus status = noErr;
+
+ SecExternalFormat format = kSecFormatPEMSequence;
+ SecExternalItemType sitem_type = kSecItemTypeAggregate;
+
+ SecItemImportExportKeyParameters params;
+ memset(¶ms, 0, sizeof(params));
+ params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+ params.flags = kSecKeyNoAccessControl;
+ params.passphrase = password;
+
+ CFArrayRef items = NULL;
+ status = SecItemImport(
+ cfdata, NULL, &format, &sitem_type, 0, ¶ms, NULL, &items);
+
+ if (status != noErr) {
+ if (SSL_LOG_CERTS) {
+ Log::Print("TrySecItemImport failed with: %ld, type = %d, format = %d\n",
+ static_cast<intptr_t>(status), sitem_type, format);
+ }
+ return status;
+ }
+
+ CFIndex items_length = (items == NULL) ? 0 : CFArrayGetCount(items);
+ if (SSL_LOG_CERTS) {
+ Log::Print(
+ "TrySecItemImport succeeded, type = %d, format = %d, count = %ld\n",
+ sitem_type, format, items_length);
+ }
+
+ // Empty list indicates a decoding failure of some sort.
+ if ((items != NULL) && (items_length == 0)) {
+ CFRelease(items);
+ return errSSLBadCert;
+ }
+
+ status = GetKeyAndCerts(items, items_length, out_certs, out_key);
+ CFRelease(items);
+ return status;
+}
+
+
+static char* TempKeychainPath() {
+ const char* exes = "keychaindir.XXXX";
+ const char* fname = "keychain";
+ const char* temp_dir = getenv("TMPDIR");
+ if (temp_dir == NULL) {
+ temp_dir = getenv("TMP");
+ }
+ if (temp_dir == NULL) {
+ temp_dir = "/tmp/";
+ }
+ ASSERT(temp_dir != NULL);
+
+ TextBuffer path(PATH_MAX);
+ path.Printf("%s/%s", temp_dir, exes);
+ char* ret = mkdtemp(path.buf());
+ ASSERT(ret != NULL);
+ path.Printf("/%s", fname);
+
+ char* result =
+ reinterpret_cast<char*>(Dart_ScopeAllocate(path.length() + 1));
+ return strncpy(result, path.buf(), path.length() + 1);
+}
+
+
+static OSStatus CreateKeychain(SecKeychainRef* keychain) {
+ ASSERT(keychain != NULL);
+ OSStatus status = noErr;
+ const char* temp_keychain_pwd = "dartdart";
+ char* temp_file_path = TempKeychainPath();
+ ASSERT(temp_file_path != NULL);
+ if (SSL_LOG_CERTS) {
+ Log::Print("Temporary keychain at: '%s'\n", temp_file_path);
+ }
+ status = SecKeychainCreate(temp_file_path,
+ strlen(temp_keychain_pwd) + 1,
+ reinterpret_cast<const void*>(temp_keychain_pwd),
+ FALSE, // Prompt user? Definitely no.
+ NULL, // Default access rights.
+ keychain);
+ if (status != noErr) {
+ return status;
+ }
+ ASSERT(*keychain != NULL);
+ return status;
+}
+
+
+static OSStatus TryPKCS12Import(CFDataRef cfdata,
+ CFStringRef password,
+ CFArrayRef* out_certs,
+ SecKeyRef* out_key,
+ SecKeychainRef* out_keychain) {
+ OSStatus status = noErr;
+
+ SecExternalFormat format = kSecFormatPKCS12;
+ SecExternalItemType sitem_type = kSecItemTypeAggregate;
+
+ SecItemImportExportKeyParameters params;
+ memset(¶ms, 0, sizeof(params));
+ params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
+ params.flags = kSecKeyNoAccessControl;
+ params.passphrase = password;
+
+ CFArrayRef items = NULL;
+ if (SSL_LOG_CERTS) {
+ Log::Print("Trying PKCS12 import with: type = %d, format = %d\n",
+ sitem_type, format);
+ }
+
+ // The documentation for SecKeychainItemImport here:
+ //
+ // https://developer.apple.com/library/mac/documentation/Security/Reference/keychainservices/index.html
+ //
+ // states that when the SecKeychainRef argument is NULL, the CFArrayRef*
+ // argument will be populated by an array containing all keys, identities,
+ // and certificates from the data in the CFDataRef argument.
+ //
+ // Unfortunately, this is not true. The code to populate the CFArrayRef with
+ // keys and identities from PKCS12 data has been skipped and/or commented out,
+ // here:
+ //
+ // https://github.com/Apple-FOSS-Mirror/Security/blob/master/libsecurity_keychain/lib/SecImportExportAgg.cpp#L636
+ //
+ // as "floating" SecKeyRefs from the PKCS12 decoder haven't been implemented.
+ // That is, each private key instance coming from the PKCS12 decoder has to be
+ // associated with a keychain instance. Thus, as a workaround, we create a
+ // temporary keychain here if one is needed, and stash it below in a
+ // SecurityContext. This has the drawbacks:
+ // 1.) We need to make a temporary directory to hold the keychain file, and
+ // 2.) SecKeychainItemImport() probably does blocking IO to create and
+ // manipulate the keychain file.
+ // So if the API is updated, this keychain should not be used.
+ SecKeychainRef keychain = NULL;
+ if (out_key != NULL) {
+ ASSERT(out_keychain != NULL);
+ status = CreateKeychain(&keychain);
+ if (status != noErr) {
+ return status;
+ }
+ *out_keychain = keychain;
+ }
+
+ status = SecItemImport(
+ cfdata, NULL, &format, &sitem_type, 0, ¶ms, keychain, &items);
+ if (status != noErr) {
+ if (SSL_LOG_CERTS) {
+ Log::Print("TrySecItemImport failed with: %ld, it = %d, format = %d\n",
+ static_cast<intptr_t>(status), sitem_type, format);
+ }
+ return status;
+ }
+
+ CFIndex items_length = (items == NULL) ? 0 : CFArrayGetCount(items);
+ if (SSL_LOG_CERTS) {
+ Log::Print("TrySecItemImport succeeded, count = %ld\n", items_length);
+ }
+
+ // Empty list indicates a decoding failure of some sort.
+ if ((items != NULL) && (items_length == 0)) {
+ CFRelease(items);
+ return errSSLBadCert;
+ }
+
+ status = GetKeyAndCerts(items, items_length, out_certs, out_key);
+ CFRelease(items);
+ return status;
+}
+
+
+static OSStatus ExtractSecItems(uint8_t* buffer,
+ intptr_t length,
+ const char* password,
+ CFArrayRef* out_certs,
+ SecKeyRef* out_key,
+ SecKeychainRef* out_keychain) {
+ ASSERT(buffer != NULL);
+ ASSERT(password != NULL);
+ OSStatus status = noErr;
+
+ CFDataRef cfdata = CFDataCreateWithBytesNoCopy(
+ NULL, buffer, length, kCFAllocatorNull);
+ CFStringRef cfpassword = CFStringCreateWithCStringNoCopy(
+ NULL, password, kCFStringEncodingUTF8, kCFAllocatorNull);
+ ASSERT(cfdata != NULL);
+ ASSERT(cfpassword != NULL);
+
+ status = TryPEMImport(cfdata, cfpassword, out_certs, out_key);
+ if (status != noErr) {
+ status =
+ TryPKCS12Import(cfdata, cfpassword, out_certs, out_key, out_keychain);
+ }
+
+ CFRelease(cfdata);
+ CFRelease(cfpassword);
+ return status;
+}
+
+
+void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) {
+ Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+ SSLFilter* filter = new SSLFilter(); // Deleted in DeleteFilter finalizer.
+ Dart_Handle err = SetFilter(args, filter);
+ if (Dart_IsError(err)) {
+ delete filter;
+ Dart_PropagateError(err);
+ }
+ err = filter->Init(dart_this);
+ if (Dart_IsError(err)) {
+ // The finalizer was set up by SetFilter. It will delete `filter` if there
+ // is an error.
+ filter->Destroy();
+ Dart_PropagateError(err);
+ }
+}
+
+
+void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
+ Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+ Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
+ Dart_Handle context_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
+ bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
+ bool request_client_certificate =
+ DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
+ bool require_client_certificate =
+ DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5));
+
+ const char* host_name = NULL;
+ // TODO(whesse): Is truncating a Dart string containing \0 what we want?
+ ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
+
+ SSLCertContext* context = NULL;
+ if (!Dart_IsNull(context_object)) {
+ ThrowIfError(Dart_GetNativeInstanceField(
+ context_object,
+ kSecurityContextNativeFieldIndex,
+ reinterpret_cast<intptr_t*>(&context)));
+ }
+
+ GetFilter(args)->Connect(dart_this,
+ host_name,
+ context,
+ is_server,
+ request_client_certificate,
+ require_client_certificate);
+}
+
+
+void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) {
+ SSLFilter* filter = GetFilter(args);
+ // The SSLFilter is deleted in the finalizer for the Dart object created by
+ // SetFilter. There is no need to NULL-out the native field for the SSLFilter
+ // here because the SSLFilter won't be deleted until the finalizer for the
+ // Dart object runs while the Dart object is being GCd. This approach avoids a
+ // leak if Destroy isn't called, and avoids a NULL-dereference if Destroy is
+ // called more than once.
+ filter->Destroy();
+}
+
+
+void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) {
+ OSStatus status = GetFilter(args)->CheckHandshake();
+ CheckStatus(status, "HandshakeException", "Handshake error");
+}
+
+
+void FUNCTION_NAME(SecureSocket_GetSelectedProtocol)(
+ Dart_NativeArguments args) {
+ Dart_SetReturnValue(args, Dart_Null());
+}
+
+
+void FUNCTION_NAME(SecureSocket_Renegotiate)(Dart_NativeArguments args) {
+ bool use_session_cache =
+ DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 1));
+ bool request_client_certificate =
+ DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 2));
+ bool require_client_certificate =
+ DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
+ GetFilter(args)->Renegotiate(use_session_cache,
+ request_client_certificate,
+ require_client_certificate);
+}
+
+
+void FUNCTION_NAME(SecureSocket_RegisterHandshakeCompleteCallback)(
+ Dart_NativeArguments args) {
+ Dart_Handle handshake_complete =
+ ThrowIfError(Dart_GetNativeArgument(args, 1));
+ if (!Dart_IsClosure(handshake_complete)) {
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "Illegal argument to RegisterHandshakeCompleteCallback"));
+ }
+ GetFilter(args)->RegisterHandshakeCompleteCallback(handshake_complete);
+}
+
+
+void FUNCTION_NAME(SecureSocket_RegisterBadCertificateCallback)(
+ Dart_NativeArguments args) {
+ Dart_Handle callback =
+ ThrowIfError(Dart_GetNativeArgument(args, 1));
+ if (!Dart_IsClosure(callback) && !Dart_IsNull(callback)) {
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "Illegal argument to RegisterBadCertificateCallback"));
+ }
+ GetFilter(args)->RegisterBadCertificateCallback(callback);
+}
+
+
+void FUNCTION_NAME(SecureSocket_PeerCertificate)
+ (Dart_NativeArguments args) {
+ Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate());
+}
+
+
+void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
+ intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args));
+ Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
+}
+
+
+void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) {
+ SSLCertContext* cert_context = new SSLCertContext();
+ // cert_context deleted in DeleteCertContext finalizer.
+ Dart_Handle err = SetSecurityContext(args, cert_context);
+ if (Dart_IsError(err)) {
+ delete cert_context;
+ Dart_PropagateError(err);
+ }
+}
+
+
+void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)(
+ Dart_NativeArguments args) {
+ SSLCertContext* context = GetSecurityContext(args);
+ const char* password = GetPasswordArgument(args, 2);
+
+ OSStatus status;
+ SecKeyRef key = NULL;
+ SecKeychainRef keychain = NULL;
+ {
+ ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+ status = ExtractSecItems(
+ buffer.get(), buffer.length(), password, NULL, &key, &keychain);
+ }
+
+ // Set the context fields. If there's a failure, release the items.
+ bool set_failure = false;
+ if ((key != NULL) && !context->set_private_key(key)) {
+ CFRelease(key);
+ SecKeychainDelete(keychain);
+ CFRelease(keychain);
+ set_failure = true;
+ }
+ if (!set_failure && (keychain != NULL) && !context->set_keychain(keychain)) {
+ SecKeychainDelete(keychain);
+ CFRelease(keychain);
+ }
+
+ if (set_failure) {
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "usePrivateKeyBytes has already been called on the given context."));
+ }
+ CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes");
+}
+
+
+void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)(
+ Dart_NativeArguments args) {
+ SSLCertContext* context = GetSecurityContext(args);
+ const char* password = GetPasswordArgument(args, 2);
+
+ OSStatus status;
+ CFArrayRef certs = NULL;
+ {
+ ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+ status = ExtractSecItems(
+ buffer.get(), buffer.length(), password, &certs, NULL, NULL);
+ }
+
+ // Set the field in the context. If there's a failure, release the certs,
+ // and throw an exception.
+ if ((certs != NULL) && !context->set_trusted_certs(certs)) {
+ CFRelease(certs);
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "setTrustedCertificatesBytes has already been called "
+ "on the given context."));
+ }
+
+ CheckStatus(status, "TlsException", "Failure in setTrustedCertificatesBytes");
+}
+
+
+void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) {
+ Dart_SetReturnValue(args, Dart_NewBoolean(false));
+}
+
+
+void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
+ Dart_NativeArguments args) {
+ SSLCertContext* context = GetSecurityContext(args);
+ context->set_trust_builtin(true);
+}
+
+
+void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)(
+ Dart_NativeArguments args) {
+ SSLCertContext* context = GetSecurityContext(args);
+
+ const char* password = GetPasswordArgument(args, 2);
+ OSStatus status;
+ CFArrayRef certs = NULL;
+ {
+ ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+ status = ExtractSecItems(
+ buffer.get(), buffer.length(), password, &certs, NULL, NULL);
+ }
+
+ // Set the field in the context. If there's a failure, release the certs,
+ // and throw an exception.
+ if ((certs != NULL) && !context->set_cert_chain(certs)) {
+ CFRelease(certs);
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "useCertificateChainBytes has already been called "
+ "on the given context."));
+ }
+
+ CheckStatus(status, "TlsException", "Failure in useCertificateChainBytes");
+}
+
+
+void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)(
+ Dart_NativeArguments args) {
+ SSLCertContext* context = GetSecurityContext(args);
+ const char* password = GetPasswordArgument(args, 2);
+
+ OSStatus status;
+ CFArrayRef certs = NULL;
+ {
+ ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+ status = ExtractSecItems(
+ buffer.get(), buffer.length(), password, &certs, NULL, NULL);
+ }
+
+ // Set the field in the context. If there's a failure, release the certs,
+ // and throw an exception.
+ if ((certs != NULL) && !context->set_cert_authorities(certs)) {
+ CFRelease(certs);
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "setClientAuthoritiesBytes has already been called "
+ "on the given context."));
+ }
+
+ CheckStatus(status, "TlsException", "Failure in setClientAuthoritiesBytes");
+}
+
+
+void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)(
+ Dart_NativeArguments args) {
+ Dart_ThrowException(DartUtils::NewDartUnsupportedError(
+ "ALPN is not supported on this platform"));
+}
+
+
+static char* GetNameFromCert(SecCertificateRef certificate,
+ CFTypeRef field,
+ CFStringRef name) {
+ char* issuer_name = NULL;
+
+ CFTypeRef keys[] = { field };
+ CFArrayRef key_array = CFArrayCreate(NULL, keys, 1, &kCFTypeArrayCallBacks);
+ CFErrorRef error = NULL;
+ CFDictionaryRef cert_dict =
+ SecCertificateCopyValues(certificate, key_array, &error);
+ if (cert_dict == NULL) {
+ CFRelease(key_array);
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "X509.issuer failed to copy issuer field out of certificate"));
+ }
+
+ CFTypeRef item = CFDictionaryGetValue(cert_dict, keys[0]);
+ ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
+ CFDictionaryRef val_dict = reinterpret_cast<CFDictionaryRef>(item);
+
+ item = CFDictionaryGetValue(val_dict, kSecPropertyKeyValue);
+ ASSERT(CFGetTypeID(item) == CFArrayGetTypeID());
+ CFArrayRef val_array = reinterpret_cast<CFArrayRef>(item);
+
+ for (intptr_t i = 0; i < CFArrayGetCount(val_array); i++) {
+ item = CFArrayGetValueAtIndex(val_array, i);
+ ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
+ CFDictionaryRef val_dict2 = reinterpret_cast<CFDictionaryRef>(item);
+
+ item = CFDictionaryGetValue(val_dict2, kSecPropertyKeyLabel);
+ ASSERT(CFGetTypeID(item) == CFStringGetTypeID());
+ CFStringRef label = reinterpret_cast<CFStringRef>(item);
+
+ if (CFStringCompare(label, name, 0) == kCFCompareEqualTo) {
+ item = CFDictionaryGetValue(val_dict2, kSecPropertyKeyValue);
+ ASSERT(CFGetTypeID(item) == CFStringGetTypeID());
+ CFStringRef value = reinterpret_cast<CFStringRef>(item);
+ issuer_name = CFStringRefToCString(value);
+ break;
+ }
+ }
+
+ CFRelease(cert_dict);
+ CFRelease(key_array);
+ return issuer_name;
+}
+
+
+void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) {
+ SecCertificateRef certificate = GetX509Certificate(args);
+ char* subject_name = GetNameFromCert(
+ certificate,
+ kSecOIDX509V1SubjectName,
+ reinterpret_cast<CFStringRef>(kSecOIDCommonName));
+ if (subject_name == NULL) {
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "X509.subject failed to find issuer's common name."));
+ } else {
+ Dart_SetReturnValue(args, Dart_NewStringFromCString(subject_name));
+ }
+}
+
+
+void FUNCTION_NAME(X509_Issuer)(Dart_NativeArguments args) {
+ SecCertificateRef certificate = GetX509Certificate(args);
+ char* issuer_name = GetNameFromCert(
+ certificate,
+ kSecOIDX509V1IssuerName,
+ reinterpret_cast<CFStringRef>(kSecOIDCommonName));
+ if (issuer_name == NULL) {
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "X509.issuer failed to find issuer's common name."));
+ } else {
+ Dart_SetReturnValue(args, Dart_NewStringFromCString(issuer_name));
+ }
+}
+
+
+// Returns the number of seconds since the epoch from 'field'.
+static int64_t GetTimeFromCert(SecCertificateRef certificate, CFTypeRef field) {
+ CFTypeRef keys[] = { field };
+ CFArrayRef key_array = CFArrayCreate(NULL, keys, 1, &kCFTypeArrayCallBacks);
+ CFErrorRef error = NULL;
+ CFDictionaryRef cert_dict =
+ SecCertificateCopyValues(certificate, key_array, &error);
+ if (cert_dict == NULL) {
+ CFRelease(key_array);
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "X509.startValidity: failed to copy issuer field out of certificate"));
+ }
+
+ CFTypeRef item = CFDictionaryGetValue(cert_dict, keys[0]);
+ ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
+ CFDictionaryRef val_dict = reinterpret_cast<CFDictionaryRef>(item);
+
+ item = CFDictionaryGetValue(val_dict, kSecPropertyKeyValue);
+ ASSERT(CFGetTypeID(item) == CFNumberGetTypeID());
+ CFNumberRef date_number = reinterpret_cast<CFNumberRef>(item);
+
+ CFAbsoluteTime date_abs_time;
+ CFNumberGetValue(date_number, kCFNumberDoubleType, &date_abs_time);
+ CFAbsoluteTime seconds_since_epoch =
+ date_abs_time + kCFAbsoluteTimeIntervalSince1970;
+ return static_cast<int64_t>(seconds_since_epoch) * 1000LL;
+}
+
+
+void FUNCTION_NAME(X509_StartValidity)(Dart_NativeArguments args) {
+ SecCertificateRef certificate = GetX509Certificate(args);
+ int64_t seconds_since_epoch = GetTimeFromCert(certificate,
+ kSecOIDX509V1ValidityNotBefore);
+ Dart_SetReturnValue(args,
+ Dart_NewInteger(static_cast<int64_t>(seconds_since_epoch) * 1000LL));
+}
+
+
+void FUNCTION_NAME(X509_EndValidity)(Dart_NativeArguments args) {
+ SecCertificateRef certificate = GetX509Certificate(args);
+ int64_t seconds_since_epoch = GetTimeFromCert(certificate,
+ kSecOIDX509V1ValidityNotAfter);
+ Dart_SetReturnValue(args,
+ Dart_NewInteger(static_cast<int64_t>(seconds_since_epoch) * 1000LL));
+}
+
+
+// Pushes data through the SSL filter, reading and writing from circular
+// buffers shared with Dart. Called from the IOService thread.
+//
+// The Dart _SecureFilterImpl class contains 4 ExternalByteArrays used to
+// pass encrypted and plaintext data to and from the C++ SSLFilter object.
+//
+// ProcessFilter is called with a CObject array containing the pointer to
+// the SSLFilter, encoded as an int, and the start and end positions of the
+// valid data in the four circular buffers. The function only reads from
+// the valid data area of the input buffers, and only writes to the free
+// area of the output buffers. The function returns the new start and end
+// positions in the buffers, but it only updates start for input buffers, and
+// end for output buffers. Therefore, the Dart thread can simultaneously
+// write to the free space and end pointer of input buffers, and read from
+// the data space of output buffers, and modify the start pointer.
+//
+// When ProcessFilter returns, the Dart thread is responsible for combining
+// the updated pointers from Dart and C++, to make the new valid state of
+// the circular buffer.
+CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) {
+ CObjectIntptr filter_object(request[0]);
+ SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value());
+ bool in_handshake = CObjectBool(request[1]).Value();
+ intptr_t starts[SSLFilter::kNumBuffers];
+ intptr_t ends[SSLFilter::kNumBuffers];
+ for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) {
+ starts[i] = CObjectInt32(request[2 * i + 2]).Value();
+ ends[i] = CObjectInt32(request[2 * i + 3]).Value();
+ }
+
+ OSStatus status = filter->ProcessAllBuffers(starts, ends, in_handshake);
+ if (status == noErr) {
+ CObjectArray* result = new CObjectArray(
+ CObject::NewArray(SSLFilter::kNumBuffers * 2));
+ for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) {
+ result->SetAt(2 * i, new CObjectInt32(CObject::NewInt32(starts[i])));
+ result->SetAt(2 * i + 1, new CObjectInt32(CObject::NewInt32(ends[i])));
+ }
+ return result;
+ } else {
+ TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE);
+ CFStringRef error_string = SecCopyErrorMessageString(status, NULL);
+ if (error_string == NULL) {
+ status_message.Printf("OSStatus = %ld: https://www.osstatus.com",
+ static_cast<intptr_t>(status));
+ } else {
+ char* error = CFStringRefToCString(error_string);
+ status_message.Printf("OSStatus = %ld: %s",
+ static_cast<intptr_t>(status), error);
+ CFRelease(error_string);
+ }
+ CObjectArray* result = new CObjectArray(CObject::NewArray(2));
+ result->SetAt(0, new CObjectInt32(CObject::NewInt32(status)));
+ result->SetAt(1, new CObjectString(CObject::NewString(
+ status_message.buf())));
+ return result;
+ }
+}
+
+
+// Usually buffer_starts_ and buffer_ends_ are populated by ProcessAllBuffers,
+// called from ProcessFilterRequest, called from the IOService thread.
+// However, the first call to SSLHandshake comes from the Dart thread, and so
+// doesn't go through there. This results in calls to SSLReadCallback and
+// SSLWriteCallback in which buffer_starts_ and buffer_ends_ haven't been set
+// up. In that case, since we're coming from Dart anyway, we can access the
+// fieds directly from the Dart objects.
+intptr_t SSLFilter::GetBufferStart(intptr_t idx) const {
+ if (buffer_starts_[idx] != NULL) {
+ return *buffer_starts_[idx];
+ }
+ Dart_Handle buffer_handle =
+ ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
+ Dart_Handle start_handle =
+ ThrowIfError(Dart_GetField(buffer_handle, DartUtils::NewString("start")));
+ int64_t start = DartUtils::GetIntegerValue(start_handle);
+ return static_cast<intptr_t>(start);
+}
+
+
+intptr_t SSLFilter::GetBufferEnd(intptr_t idx) const {
+ if (buffer_ends_[idx] != NULL) {
+ return *buffer_ends_[idx];
+ }
+ Dart_Handle buffer_handle =
+ ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
+ Dart_Handle end_handle =
+ ThrowIfError(Dart_GetField(buffer_handle, DartUtils::NewString("end")));
+ int64_t end = DartUtils::GetIntegerValue(end_handle);
+ return static_cast<intptr_t>(end);
+}
+
+
+void SSLFilter::SetBufferStart(intptr_t idx, intptr_t value) {
+ if (buffer_starts_[idx] != NULL) {
+ *buffer_starts_[idx] = value;
+ return;
+ }
+ Dart_Handle buffer_handle =
+ ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
+ ThrowIfError(DartUtils::SetIntegerField(
+ buffer_handle, "start", static_cast<int64_t>(value)));
+}
+
+
+void SSLFilter::SetBufferEnd(intptr_t idx, intptr_t value) {
+ if (buffer_ends_[idx] != NULL) {
+ *buffer_ends_[idx] = value;
+ return;
+ }
+ Dart_Handle buffer_handle =
+ ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
+ ThrowIfError(DartUtils::SetIntegerField(
+ buffer_handle, "end", static_cast<int64_t>(value)));
+}
+
+
+OSStatus SSLFilter::ProcessAllBuffers(intptr_t starts[kNumBuffers],
+ intptr_t ends[kNumBuffers],
+ bool in_handshake) {
+ for (intptr_t i = 0; i < kNumBuffers; ++i) {
+ buffer_starts_[i] = &starts[i];
+ buffer_ends_[i] = &ends[i];
+ }
+
+ if (in_handshake) {
+ OSStatus status = Handshake();
+ if (status != noErr) {
+ return status;
+ }
+ } else {
+ for (intptr_t i = 0; i < kNumBuffers; ++i) {
+ intptr_t start = starts[i];
+ intptr_t end = ends[i];
+ intptr_t size =
+ isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
+ if (start < 0 || end < 0 || start >= size || end >= size) {
+ FATAL("Out-of-bounds internal buffer access in dart:io SecureSocket");
+ }
+ switch (i) {
+ case kReadPlaintext:
+ // Write data to the circular buffer's free space. If the buffer
+ // is full, neither if statement is executed and nothing happens.
+ if (start <= end) {
+ // If the free space may be split into two segments,
+ // then the first is [end, size), unless start == 0.
+ // Then, since the last free byte is at position start - 2,
+ // the interval is [end, size - 1).
+ intptr_t buffer_end = (start == 0) ? size - 1 : size;
+ intptr_t bytes = 0;
+ OSStatus status =
+ ProcessReadPlaintextBuffer(end, buffer_end, &bytes);
+ if ((status != noErr) && (status != errSSLWouldBlock)) {
+ return status;
+ }
+ end += bytes;
+ ASSERT(end <= size);
+ if (end == size) {
+ end = 0;
+ }
+ }
+ if (start > end + 1) {
+ intptr_t bytes = 0;
+ OSStatus status =
+ ProcessReadPlaintextBuffer(end, start - 1, &bytes);
+ if ((status != noErr) && (status != errSSLWouldBlock)) {
+ return status;
+ }
+ end += bytes;
+ ASSERT(end < start);
+ }
+ ends[i] = end;
+ break;
+ case kWritePlaintext:
+ // Read/Write data from circular buffer. If the buffer is empty,
+ // neither if statement's condition is true.
+ if (end < start) {
+ // Data may be split into two segments. In this case,
+ // the first is [start, size).
+ intptr_t bytes = 0;
+ OSStatus status = ProcessWritePlaintextBuffer(start, size, &bytes);
+ if ((status != noErr) && (status != errSSLWouldBlock)) {
+ return status;
+ }
+ start += bytes;
+ ASSERT(start <= size);
+ if (start == size) {
+ start = 0;
+ }
+ }
+ if (start < end) {
+ intptr_t bytes = 0;
+ OSStatus status = ProcessWritePlaintextBuffer(start, end, &bytes);
+ if ((status != noErr) && (status != errSSLWouldBlock)) {
+ return status;
+ }
+ start += bytes;
+ ASSERT(start <= end);
+ }
+ starts[i] = start;
+ break;
+ case kReadEncrypted:
+ case kWriteEncrypted:
+ // These buffers are advanced through SSLReadCallback and
+ // SSLWriteCallback, which are called from SSLRead, SSLWrite, and
+ // SSLHandshake.
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ }
+
+ for (intptr_t i = 0; i < kNumBuffers; ++i) {
+ buffer_starts_[i] = NULL;
+ buffer_ends_[i] = NULL;
+ }
+ return noErr;
+}
+
+
+Dart_Handle SSLFilter::Init(Dart_Handle dart_this) {
+ ASSERT(string_start_ == NULL);
+ string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start"));
+ ASSERT(string_start_ != NULL);
+ ASSERT(string_length_ == NULL);
+ string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length"));
+ ASSERT(string_length_ != NULL);
+ ASSERT(bad_certificate_callback_ == NULL);
+ bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null());
+ ASSERT(bad_certificate_callback_ != NULL);
+
+ // Caller handles cleanup on an error.
+ return InitializeBuffers(dart_this);
+}
+
+
+Dart_Handle SSLFilter::InitializeBuffers(Dart_Handle dart_this) {
+ // Create SSLFilter buffers as ExternalUint8Array objects.
+ Dart_Handle buffers_string = DartUtils::NewString("buffers");
+ RETURN_IF_ERROR(buffers_string);
+ Dart_Handle dart_buffers_object = Dart_GetField(dart_this, buffers_string);
+ RETURN_IF_ERROR(dart_buffers_object);
+ Dart_Handle secure_filter_impl_type = Dart_InstanceGetType(dart_this);
+ RETURN_IF_ERROR(secure_filter_impl_type);
+ Dart_Handle size_string = DartUtils::NewString("SIZE");
+ RETURN_IF_ERROR(size_string);
+ Dart_Handle dart_buffer_size = Dart_GetField(
+ secure_filter_impl_type, size_string);
+ RETURN_IF_ERROR(dart_buffer_size);
+
+ int64_t buffer_size = 0;
+ Dart_Handle err = Dart_IntegerToInt64(dart_buffer_size, &buffer_size);
+ RETURN_IF_ERROR(err);
+
+ Dart_Handle encrypted_size_string = DartUtils::NewString("ENCRYPTED_SIZE");
+ RETURN_IF_ERROR(encrypted_size_string);
+
+ Dart_Handle dart_encrypted_buffer_size = Dart_GetField(
+ secure_filter_impl_type, encrypted_size_string);
+ RETURN_IF_ERROR(dart_encrypted_buffer_size);
+
+ int64_t encrypted_buffer_size = 0;
+ err = Dart_IntegerToInt64(dart_encrypted_buffer_size, &encrypted_buffer_size);
+ RETURN_IF_ERROR(err);
+
+ if (buffer_size <= 0 || buffer_size > 1 * MB) {
+ FATAL("Invalid buffer size in _ExternalBuffer");
+ }
+ if (encrypted_buffer_size <= 0 || encrypted_buffer_size > 1 * MB) {
+ FATAL("Invalid encrypted buffer size in _ExternalBuffer");
+ }
+ buffer_size_ = static_cast<intptr_t>(buffer_size);
+ encrypted_buffer_size_ = static_cast<intptr_t>(encrypted_buffer_size);
+
+ Dart_Handle data_identifier = DartUtils::NewString("data");
+ RETURN_IF_ERROR(data_identifier);
+
+ for (int i = 0; i < kNumBuffers; i++) {
+ int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
+ buffers_[i] = new uint8_t[size];
+ ASSERT(buffers_[i] != NULL);
+ buffer_starts_[i] = NULL;
+ buffer_ends_[i] = NULL;
+ dart_buffer_objects_[i] = NULL;
+ }
+
+ Dart_Handle result = Dart_Null();
+ for (int i = 0; i < kNumBuffers; ++i) {
+ int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
+ result = Dart_ListGetAt(dart_buffers_object, i);
+ if (Dart_IsError(result)) {
+ break;
+ }
+
+ dart_buffer_objects_[i] = Dart_NewPersistentHandle(result);
+ ASSERT(dart_buffer_objects_[i] != NULL);
+ Dart_Handle data =
+ Dart_NewExternalTypedData(Dart_TypedData_kUint8, buffers_[i], size);
+ if (Dart_IsError(data)) {
+ result = data;
+ break;
+ }
+ result = Dart_HandleFromPersistent(dart_buffer_objects_[i]);
+ if (Dart_IsError(result)) {
+ break;
+ }
+ result = Dart_SetField(result, data_identifier, data);
+ if (Dart_IsError(result)) {
+ break;
+ }
+ }
+
+ // Caller handles cleanup on an error.
+ return result;
+}
+
+
+void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) {
+ ASSERT(NULL == handshake_complete_);
+ handshake_complete_ = Dart_NewPersistentHandle(complete);
+ ASSERT(handshake_complete_ != NULL);
+}
+
+
+void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) {
+ ASSERT(bad_certificate_callback_ != NULL);
+ Dart_DeletePersistentHandle(bad_certificate_callback_);
+ bad_certificate_callback_ = Dart_NewPersistentHandle(callback);
+ ASSERT(bad_certificate_callback_ != NULL);
+}
+
+
+Dart_Handle SSLFilter::PeerCertificate() {
+ if (peer_certs_ == NULL) {
+ return Dart_Null();
+ }
+
+ CFTypeRef item = CFArrayGetValueAtIndex(peer_certs_, 0);
+ ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID());
+ SecCertificateRef cert =
+ reinterpret_cast<SecCertificateRef>(const_cast<void*>(item));
+ if (cert == NULL) {
+ return Dart_Null();
+ }
+
+ return WrappedX509Certificate(cert);
+}
+
+
+void SSLFilter::Connect(Dart_Handle dart_this,
+ const char* hostname,
+ SSLCertContext* context,
+ bool is_server,
+ bool request_client_certificate,
+ bool require_client_certificate) {
+ if (in_handshake_) {
+ FATAL("Connect called twice on the same _SecureFilter.");
+ }
+
+ // Create the underlying context
+ SSLContextRef ssl_context = SSLCreateContext(
+ NULL, is_server ? kSSLServerSide : kSSLClientSide, kSSLStreamType);
+
+ // Configure the context.
+ OSStatus status;
+ status = SSLSetPeerDomainName(ssl_context, hostname, strlen(hostname));
+ CheckStatus(status,
+ "TlsException",
+ "Failed to set peer domain name");
+
+ status = SSLSetIOFuncs(
+ ssl_context, SSLFilter::SSLReadCallback, SSLFilter::SSLWriteCallback);
+ CheckStatus(status,
+ "TlsException",
+ "Failed to set IO Callbacks");
+
+ status = SSLSetConnection(
+ ssl_context, reinterpret_cast<SSLConnectionRef>(this));
+ CheckStatus(status,
+ "TlsException",
+ "Failed to set connection object");
+
+ // Always evaluate the certs manually so that we can cache the peer
+ // certificates in the context for calls to peerCertificate.
+ status = SSLSetSessionOption(
+ ssl_context, kSSLSessionOptionBreakOnServerAuth, true);
+ CheckStatus(status,
+ "TlsException",
+ "Failed to set BreakOnServerAuth option");
+
+ status = SSLSetProtocolVersionMin(ssl_context, kTLSProtocol1);
+ CheckStatus(status,
+ "TlsException",
+ "Failed to set minimum protocol version to kTLSProtocol1");
+
+ // If the context has a private key and certificate chain, combine the
+ // private key and first certificate into a SecIdentityRef, and place that
+ // and the remaining certs in an array to pass to SSLSetCertificate().
+ if ((context->private_key() != NULL) && (context->cert_chain() != NULL)) {
+ CFIndex chain_length = CFArrayGetCount(context->cert_chain());
+ CFMutableArrayRef certs =
+ CFArrayCreateMutable(NULL, chain_length, &kCFTypeArrayCallBacks);
+ CFTypeRef item = CFArrayGetValueAtIndex(context->cert_chain(), 0);
+ ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID());
+ SecCertificateRef first_cert =
+ reinterpret_cast<SecCertificateRef>(const_cast<void*>(item));
+ SecIdentityRef identity =
+ SecIdentityCreate(NULL, first_cert, context->private_key());
+ CFArrayAppendValue(certs, identity);
+ for (CFIndex i = 0; i < chain_length; i++) {
+ CFArrayAppendValue(certs,
+ CFArrayGetValueAtIndex(context->cert_chain(), i));
+ }
+ CFRelease(identity);
+ status = SSLSetCertificate(ssl_context, certs);
+ CFRelease(certs);
+ CheckStatus(status, "TlsException", "SSLSetCertificate failed");
+ }
+
+ if (context->cert_authorities() != NULL) {
+ status = SSLSetCertificateAuthorities(
+ ssl_context, context->cert_authorities(), true);
+ CheckStatus(status,
+ "TlsException",
+ "Failed to set certificate authorities");
+ }
+
+ if (is_server) {
+ SSLAuthenticate auth =
+ require_client_certificate
+ ? kAlwaysAuthenticate
+ : (request_client_certificate ? kTryAuthenticate : kNeverAuthenticate);
+ status = SSLSetClientSideAuthenticate(ssl_context, auth);
+ CheckStatus(status,
+ "TlsException",
+ "Failed to set client authentication mode");
+
+ // If we're at least trying client authentication, then break handshake
+ // for client authentication.
+ if (auth != kNeverAuthenticate) {
+ status = SSLSetSessionOption(
+ ssl_context, kSSLSessionOptionBreakOnClientAuth, true);
+ CheckStatus(status,
+ "TlsException",
+ "Failed to set client authentication mode");
+ }
+ }
+
+ // Add the contexts to our wrapper.
+ cert_context_ = context;
+ ssl_context_ = ssl_context;
+ is_server_ = is_server;
+
+ // Kick-off the handshake. Expect the handshake to need more data.
+ // SSLHandshake calls our SSLReadCallback and SSLWriteCallback.
+ status = SSLHandshake(ssl_context);
+ ASSERT(status != noErr);
+ if (status == errSSLWouldBlock) {
+ status = noErr;
+ in_handshake_ = true;
+ }
+ CheckStatus(status,
+ "HandshakeException",
+ is_server_ ? "Handshake error in server" : "Handshake error in client");
+}
+
+
+OSStatus SSLFilter::EvaluatePeerTrust() {
+ OSStatus status = noErr;
+
+ if (SSL_LOG_STATUS) {
+ Log::Print("Handshake evaluating trust.\n");
+ }
+ SecTrustRef peer_trust = NULL;
+ status = SSLCopyPeerTrust(ssl_context_, &peer_trust);
+ if (status != noErr) {
+ if (is_server_ && (status == errSSLBadCert)) {
+ // A client certificate was requested, but not required, and wasn't sent.
+ return noErr;
+ }
+ if (SSL_LOG_STATUS) {
+ Log::Print("Handshake error from SSLCopyPeerTrust(): %ld.\n",
+ static_cast<intptr_t>(status));
+ }
+ return status;
+ }
+
+ CFArrayRef trusted_certs = NULL;
+ if (cert_context_->trusted_certs() != NULL) {
+ trusted_certs = CFArrayCreateCopy(NULL, cert_context_->trusted_certs());
+ } else {
+ trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
+ }
+
+ status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs);
+ if (status != noErr) {
+ if (SSL_LOG_STATUS) {
+ Log::Print("Handshake error from SecTrustSetAnchorCertificates: %ld\n",
+ static_cast<intptr_t>(status));
+ }
+ CFRelease(trusted_certs);
+ CFRelease(peer_trust);
+ return status;
+ }
+
+ if (SSL_LOG_STATUS) {
+ Log::Print("Handshake %s built in root certs\n",
+ cert_context_->trust_builtin() ? "trusting" : "not trusting");
+ }
+
+ status = SecTrustSetAnchorCertificatesOnly(
+ peer_trust, !cert_context_->trust_builtin());
+ if (status != noErr) {
+ CFRelease(trusted_certs);
+ CFRelease(peer_trust);
+ return status;
+ }
+
+ SecTrustResultType trust_result;
+ status = SecTrustEvaluate(peer_trust, &trust_result);
+ if (status != noErr) {
+ CFRelease(trusted_certs);
+ CFRelease(peer_trust);
+ return status;
+ }
+
+ // Grab the peer's certificate chain.
+ CFIndex peer_chain_length = SecTrustGetCertificateCount(peer_trust);
+ CFMutableArrayRef peer_certs =
+ CFArrayCreateMutable(NULL, peer_chain_length, &kCFTypeArrayCallBacks);
+ for (CFIndex i = 0; i < peer_chain_length; ++i) {
+ CFArrayAppendValue(peer_certs,
+ SecTrustGetCertificateAtIndex(peer_trust, i));
+ }
+ peer_certs_ = peer_certs;
+
+ CFRelease(trusted_certs);
+ CFRelease(peer_trust);
+
+ if ((trust_result == kSecTrustResultProceed) ||
+ (trust_result == kSecTrustResultUnspecified)) {
+ // Trusted.
+ return noErr;
+ } else {
+ if (SSL_LOG_STATUS) {
+ Log::Print("Trust eval failed: trust_restul = %d\n", trust_result);
+ }
+ bad_cert_ = true;
+ return errSSLBadCert;
+ }
+}
+
+
+OSStatus SSLFilter::Handshake() {
+ ASSERT(cert_context_ != NULL);
+ ASSERT(ssl_context_ != NULL);
+ // Try and push handshake along.
+ if (SSL_LOG_STATUS) {
+ Log::Print("Doing SSLHandshake\n");
+ }
+ OSStatus status = SSLHandshake(ssl_context_);
+ if (SSL_LOG_STATUS) {
+ Log::Print("SSLHandshake returned %ld\n", static_cast<intptr_t>(status));
+ }
+
+ if ((status == errSSLServerAuthCompleted) ||
+ (status == errSSLClientAuthCompleted)) {
+ status = EvaluatePeerTrust();
+ if (status == errSSLBadCert) {
+ // Need to invoke the bad certificate callback.
+ return noErr;
+ } else if (status != noErr) {
+ return status;
+ }
+ // When trust evaluation succeeds, we can call SSLHandshake again
+ // immediately.
+ status = SSLHandshake(ssl_context_);
+ }
+
+ if (status == errSSLWouldBlock) {
+ in_handshake_ = true;
+ return noErr;
+ }
+
+ // Handshake succeeded.
+ if ((in_handshake_) && (status == noErr)) {
+ if (SSL_LOG_STATUS) {
+ Log::Print("Finished with the Handshake\n");
+ }
+ connected_ = true;
+ }
+ return status;
+}
+
+
+// Returns false if Handshake should fail, and true if Handshake should
+// proceed.
+Dart_Handle SSLFilter::InvokeBadCertCallback(SecCertificateRef peer_cert) {
+ Dart_Handle callback = bad_certificate_callback_;
+ if (Dart_IsNull(callback)) {
+ return callback;
+ }
+ Dart_Handle args[1];
+ args[0] = WrappedX509Certificate(peer_cert);
+ if (Dart_IsError(args[0])) {
+ return args[0];
+ }
+ Dart_Handle result = Dart_InvokeClosure(callback, 1, args);
+ if (!Dart_IsError(result) && !Dart_IsBoolean(result)) {
+ result = Dart_NewUnhandledExceptionError(DartUtils::NewDartIOException(
+ "HandshakeException",
+ "BadCertificateCallback returned a value that was not a boolean",
+ Dart_Null()));
+ }
+ return result;
+}
+
+
+OSStatus SSLFilter::CheckHandshake() {
+ if (bad_cert_ && in_handshake_) {
+ if (SSL_LOG_STATUS) {
+ Log::Print("Invoking bad certificate callback\n");
+ }
+ ASSERT(peer_certs_ != NULL);
+ CFIndex peer_certs_len = CFArrayGetCount(peer_certs_);
+ ASSERT(peer_certs_len > 0);
+ CFTypeRef item = CFArrayGetValueAtIndex(peer_certs_, peer_certs_len - 1);
+ ASSERT(item != NULL);
+ ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID());
+ SecCertificateRef peer_cert =
+ reinterpret_cast<SecCertificateRef>(const_cast<void*>(item));
+ Dart_Handle result = InvokeBadCertCallback(peer_cert);
+ ThrowIfError(result);
+ if (Dart_IsNull(result)) {
+ return errSSLBadCert;
+ } else {
+ bool good_cert = DartUtils::GetBooleanValue(result);
+ bad_cert_ = !good_cert;
+ return good_cert ? noErr : errSSLBadCert;
+ }
+ }
+
+ if (connected_ && in_handshake_) {
+ if (SSL_LOG_STATUS) {
+ Log::Print("Invoking handshake complete callback\n");
+ }
+ ThrowIfError(Dart_InvokeClosure(
+ Dart_HandleFromPersistent(handshake_complete_), 0, NULL));
+ in_handshake_ = false;
+ }
+ return noErr;
+}
+
+
+void SSLFilter::Renegotiate(bool use_session_cache,
+ bool request_client_certificate,
+ bool require_client_certificate) {
+ // The SSL_REQUIRE_CERTIFICATE option only takes effect if the
+ // SSL_REQUEST_CERTIFICATE option is also set, so set it.
+ request_client_certificate =
+ request_client_certificate || require_client_certificate;
+ // TODO(24070, 24069): Implement setting the client certificate parameters,
+ // and triggering rehandshake.
+}
+
+
+SSLFilter::~SSLFilter() {
+ // cert_context_ deleted by finalizer. Don't delete here.
+ cert_context_ = NULL;
+ if (ssl_context_ != NULL) {
+ CFRelease(ssl_context_);
+ ssl_context_ = NULL;
+ }
+ if (peer_certs_ != NULL) {
+ CFRelease(peer_certs_);
+ peer_certs_ = NULL;
+ }
+ if (hostname_ != NULL) {
+ free(hostname_);
+ hostname_ = NULL;
+ }
+ for (int i = 0; i < kNumBuffers; ++i) {
+ if (buffers_[i] != NULL) {
+ delete[] buffers_[i];
+ buffers_[i] = NULL;
+ }
+ }
+}
+
+
+void SSLFilter::Destroy() {
+ if (ssl_context_ != NULL) {
+ SSLClose(ssl_context_);
+ }
+ for (int i = 0; i < kNumBuffers; ++i) {
+ if (dart_buffer_objects_[i] != NULL) {
+ Dart_DeletePersistentHandle(dart_buffer_objects_[i]);
+ dart_buffer_objects_[i] = NULL;
+ }
+ }
+ if (string_start_ != NULL) {
+ Dart_DeletePersistentHandle(string_start_);
+ string_start_ = NULL;
+ }
+ if (string_length_ != NULL) {
+ Dart_DeletePersistentHandle(string_length_);
+ string_length_ = NULL;
+ }
+ if (handshake_complete_ != NULL) {
+ Dart_DeletePersistentHandle(handshake_complete_);
+ handshake_complete_ = NULL;
+ }
+ if (bad_certificate_callback_ != NULL) {
+ Dart_DeletePersistentHandle(bad_certificate_callback_);
+ bad_certificate_callback_ = NULL;
+ }
+}
+
+
+static intptr_t AvailableToRead(intptr_t start, intptr_t end, intptr_t size) {
+ intptr_t data_available = 0;
+ if (end < start) {
+ // Data may be split into two segments. In this case,
+ // the first is [start, size).
+ intptr_t buffer_end = (start == 0) ? size - 1 : size;
+ intptr_t available = buffer_end - start;
+ start += available;
+ data_available += available;
+ ASSERT(start <= size);
+ if (start == size) {
+ start = 0;
+ }
+ }
+ if (start < end) {
+ intptr_t available = end - start;
+ start += available;
+ data_available += available;
+ ASSERT(start <= end);
+ }
+ return data_available;
+}
+
+
+OSStatus SSLFilter::SSLReadCallback(SSLConnectionRef connection,
+ void* data, size_t* data_requested) {
+ // Copy at most `data_requested` bytes from `buffers_[kReadEncrypted]` into
+ // `data`
+ ASSERT(connection != NULL);
+ ASSERT(data != NULL);
+ ASSERT(data_requested != NULL);
+
+ SSLFilter* filter =
+ const_cast<SSLFilter*>(reinterpret_cast<const SSLFilter*>(connection));
+ uint8_t* datap = reinterpret_cast<uint8_t*>(data);
+ uint8_t* buffer = filter->buffers_[kReadEncrypted];
+ intptr_t start = filter->GetBufferStart(kReadEncrypted);
+ intptr_t end = filter->GetBufferEnd(kReadEncrypted);
+ intptr_t size = filter->encrypted_buffer_size_;
+ intptr_t requested = static_cast<intptr_t>(*data_requested);
+ intptr_t data_read = 0;
+
+ if (AvailableToRead(start, end, size) < requested) {
+ *data_requested = 0;
+ return errSSLWouldBlock;
+ }
+
+ if (end < start) {
+ // Data may be split into two segments. In this case,
+ // the first is [start, size).
+ intptr_t buffer_end = (start == 0) ? size - 1 : size;
+ intptr_t available = buffer_end - start;
+ intptr_t bytes = requested < available ? requested : available;
+ memmove(datap, &buffer[start], bytes);
+ start += bytes;
+ datap += bytes;
+ data_read += bytes;
+ requested -= bytes;
+ ASSERT(start <= size);
+ if (start == size) {
+ start = 0;
+ }
+ }
+ if ((requested > 0) && (start < end)) {
+ intptr_t available = end - start;
+ intptr_t bytes = requested < available ? requested : available;
+ memmove(datap, &buffer[start], bytes);
+ start += bytes;
+ datap += bytes;
+ data_read += bytes;
+ requested -= bytes;
+ ASSERT(start <= end);
+ }
+
+ if (SSL_LOG_DATA) {
+ Log::Print("SSLReadCallback: requested: %ld, read %ld bytes\n",
+ *data_requested, data_read);
+ }
+
+ filter->SetBufferStart(kReadEncrypted, start);
+ *data_requested = data_read;
+ return noErr;
+}
+
+
+// Read decrypted data from the filter to the circular buffer.
+OSStatus SSLFilter::ProcessReadPlaintextBuffer(intptr_t start,
+ intptr_t end,
+ intptr_t* bytes_processed) {
+ ASSERT(bytes_processed != NULL);
+ intptr_t length = end - start;
+ OSStatus status = noErr;
+ size_t bytes = 0;
+ if (length > 0) {
+ status = SSLRead(
+ ssl_context_,
+ reinterpret_cast<void*>((buffers_[kReadPlaintext] + start)),
+ length,
+ &bytes);
+ if ((status != noErr) && (status != errSSLWouldBlock)) {
+ *bytes_processed = 0;
+ return status;
+ }
+ }
+ if (SSL_LOG_DATA) {
+ Log::Print("ProcessReadPlaintextBuffer: requested: %ld, read %ld bytes\n",
+ length, bytes);
+ }
+ *bytes_processed = static_cast<intptr_t>(bytes);
+ return status;
+}
+
+
+intptr_t SpaceToWrite(intptr_t start, intptr_t end, intptr_t size) {
+ intptr_t writable_space = 0;
+
+ // is full, neither if statement is executed and nothing happens.
+ if (start <= end) {
+ // If the free space may be split into two segments,
+ // then the first is [end, size), unless start == 0.
+ // Then, since the last free byte is at position start - 2,
+ // the interval is [end, size - 1).
+ intptr_t buffer_end = (start == 0) ? size - 1 : size;
+ intptr_t available = buffer_end - end;
+ end += available;
+ writable_space += available;
+ ASSERT(end <= size);
+ if (end == size) {
+ end = 0;
+ }
+ }
+ if (start > end + 1) {
+ intptr_t available = (start - 1) - end;
+ end += available;
+ writable_space += available;
+ ASSERT(end < start);
+ }
+
+ return writable_space;
+}
+
+
+OSStatus SSLFilter::SSLWriteCallback(SSLConnectionRef connection,
+ const void* data, size_t* data_provided) {
+ // Copy at most `data_provided` bytes from data into
+ // `buffers_[kWriteEncrypted]`.
+ ASSERT(connection != NULL);
+ ASSERT(data != NULL);
+ ASSERT(data_provided != NULL);
+
+ SSLFilter* filter =
+ const_cast<SSLFilter*>(reinterpret_cast<const SSLFilter*>(connection));
+ const uint8_t* datap = reinterpret_cast<const uint8_t*>(data);
+ uint8_t* buffer = filter->buffers_[kWriteEncrypted];
+ intptr_t start = filter->GetBufferStart(kWriteEncrypted);
+ intptr_t end = filter->GetBufferEnd(kWriteEncrypted);
+ intptr_t size = filter->encrypted_buffer_size_;
+ intptr_t provided = static_cast<intptr_t>(*data_provided);
+ intptr_t data_written = 0;
+
+ if (SpaceToWrite(start, end, size) < provided) {
+ *data_provided = 0;
+ return errSSLWouldBlock;
+ }
+
+ // is full, neither if statement is executed and nothing happens.
+ if (start <= end) {
+ // If the free space may be split into two segments,
+ // then the first is [end, size), unless start == 0.
+ // Then, since the last free byte is at position start - 2,
+ // the interval is [end, size - 1).
+ intptr_t buffer_end = (start == 0) ? size - 1 : size;
+ intptr_t available = buffer_end - end;
+ intptr_t bytes = provided < available ? provided : available;
+ memmove(&buffer[end], datap, bytes);
+ end += bytes;
+ datap += bytes;
+ data_written += bytes;
+ provided -= bytes;
+ ASSERT(end <= size);
+ if (end == size) {
+ end = 0;
+ }
+ }
+ if ((provided > 0) && (start > end + 1)) {
+ intptr_t available = (start - 1) - end;
+ intptr_t bytes = provided < available ? provided : available;
+ memmove(&buffer[end], datap, bytes);
+ end += bytes;
+ datap += bytes;
+ data_written += bytes;
+ provided -= bytes;
+ ASSERT(end < start);
+ }
+
+ if (SSL_LOG_DATA) {
+ Log::Print("SSLWriteCallback: provided: %ld, written %ld bytes\n",
+ *data_provided, data_written);
+ }
+
+ filter->SetBufferEnd(kWriteEncrypted, end);
+ *data_provided = data_written;
+ return noErr;
+}
+
+
+OSStatus SSLFilter::ProcessWritePlaintextBuffer(intptr_t start,
+ intptr_t end,
+ intptr_t* bytes_processed) {
+ ASSERT(bytes_processed != NULL);
+ intptr_t length = end - start;
+ OSStatus status = noErr;
+ size_t bytes = 0;
+ if (length > 0) {
+ status = SSLWrite(
+ ssl_context_,
+ reinterpret_cast<void*>(buffers_[kWritePlaintext] + start),
+ length,
+ &bytes);
+ if ((status != noErr) && (status != errSSLWouldBlock)) {
+ *bytes_processed = 0;
+ return status;
+ }
+ }
+ *bytes_processed = static_cast<intptr_t>(bytes);
+ return status;
+}
+
+} // namespace bin
+} // namespace dart
+
+#endif // defined(TARGET_OS_MACOS)
diff --git a/runtime/bin/secure_socket_macos.h b/runtime/bin/secure_socket_macos.h
new file mode 100644
index 0000000..e78321c
--- /dev/null
+++ b/runtime/bin/secure_socket_macos.h
@@ -0,0 +1,149 @@
+// 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.
+
+#ifndef BIN_SECURE_SOCKET_MACOS_H_
+#define BIN_SECURE_SOCKET_MACOS_H_
+
+#if !defined(BIN_SECURE_SOCKET_H_)
+#error Do not include secure_socket_macos.h directly. Use secure_socket.h.
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/SecureTransport.h>
+#include <Security/Security.h>
+
+#include "bin/builtin.h"
+#include "bin/dartutils.h"
+#include "bin/socket.h"
+#include "bin/thread.h"
+#include "bin/utils.h"
+
+namespace dart {
+namespace bin {
+
+// Forward declaration of SSLContext.
+class SSLCertContext;
+
+// SSLFilter encapsulates the SecureTransport code in a filter that communicates
+// with the containing _SecureFilterImpl Dart object through four shared
+// ExternalByteArray buffers, for reading and writing plaintext, and
+// reading and writing encrypted text. The filter handles handshaking
+// and certificate verification.
+class SSLFilter {
+ public:
+ // These enums must agree with those in sdk/lib/io/secure_socket.dart.
+ enum BufferIndex {
+ kReadPlaintext,
+ kWritePlaintext,
+ kReadEncrypted,
+ kWriteEncrypted,
+ kNumBuffers,
+ kFirstEncrypted = kReadEncrypted
+ };
+
+ SSLFilter()
+ : cert_context_(NULL),
+ ssl_context_(NULL),
+ peer_certs_(NULL),
+ string_start_(NULL),
+ string_length_(NULL),
+ handshake_complete_(NULL),
+ bad_certificate_callback_(NULL),
+ in_handshake_(false),
+ connected_(false),
+ bad_cert_(false),
+ is_server_(false),
+ hostname_(NULL) {
+ }
+
+ ~SSLFilter();
+
+ // Callback called by the IOService.
+ static CObject* ProcessFilterRequest(const CObjectArray& request);
+
+ Dart_Handle Init(Dart_Handle dart_this);
+ void Connect(Dart_Handle dart_this,
+ const char* hostname,
+ SSLCertContext* context,
+ bool is_server,
+ bool request_client_certificate,
+ bool require_client_certificate);
+ void Destroy();
+ OSStatus CheckHandshake();
+ void Renegotiate(bool use_session_cache,
+ bool request_client_certificate,
+ bool require_client_certificate);
+ void RegisterHandshakeCompleteCallback(Dart_Handle handshake_complete);
+ void RegisterBadCertificateCallback(Dart_Handle callback);
+ Dart_Handle PeerCertificate();
+
+ private:
+ static OSStatus SSLReadCallback(SSLConnectionRef connection,
+ void* data,
+ size_t* data_length);
+ static OSStatus SSLWriteCallback(SSLConnectionRef connection,
+ const void* data,
+ size_t* data_length);
+
+ static bool isBufferEncrypted(intptr_t i) {
+ return static_cast<BufferIndex>(i) >= kFirstEncrypted;
+ }
+ Dart_Handle InitializeBuffers(Dart_Handle dart_this);
+
+ intptr_t GetBufferStart(intptr_t idx) const;
+ intptr_t GetBufferEnd(intptr_t idx) const;
+ void SetBufferStart(intptr_t idx, intptr_t value);
+ void SetBufferEnd(intptr_t idx, intptr_t value);
+
+ OSStatus ProcessAllBuffers(intptr_t starts[kNumBuffers],
+ intptr_t ends[kNumBuffers],
+ bool in_handshake);
+ OSStatus ProcessReadPlaintextBuffer(intptr_t start,
+ intptr_t end,
+ intptr_t* bytes_processed);
+ OSStatus ProcessWritePlaintextBuffer(intptr_t start,
+ intptr_t end,
+ intptr_t* bytes_processed);
+
+ // These calls can block on IO, and should only be invoked from
+ // from ProcessAllBuffers from ProcessFilterRequest.
+ OSStatus EvaluatePeerTrust();
+ OSStatus Handshake();
+ Dart_Handle InvokeBadCertCallback(SecCertificateRef peer_cert);
+
+ SSLCertContext* cert_context_;
+ SSLContextRef ssl_context_;
+ CFArrayRef peer_certs_;
+
+ // starts and ends filled in at the start of ProcessAllBuffers.
+ // If these are NULL, then try to get the pointers out of
+ // dart_buffer_objects_.
+ uint8_t* buffers_[kNumBuffers];
+ intptr_t* buffer_starts_[kNumBuffers];
+ intptr_t* buffer_ends_[kNumBuffers];
+ intptr_t buffer_size_;
+ intptr_t encrypted_buffer_size_;
+ Dart_PersistentHandle string_start_;
+ Dart_PersistentHandle string_length_;
+ Dart_PersistentHandle dart_buffer_objects_[kNumBuffers];
+ Dart_PersistentHandle handshake_complete_;
+ Dart_PersistentHandle bad_certificate_callback_;
+ bool in_handshake_;
+ bool connected_;
+ bool bad_cert_;
+ bool is_server_;
+ char* hostname_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLFilter);
+};
+
+} // namespace bin
+} // namespace dart
+
+#endif // BIN_SECURE_SOCKET_MACOS_H_
diff --git a/runtime/bin/secure_socket_patch.dart b/runtime/bin/secure_socket_patch.dart
index 455b132..c47c941 100644
--- a/runtime/bin/secure_socket_patch.dart
+++ b/runtime/bin/secure_socket_patch.dart
@@ -123,6 +123,10 @@
/* patch */ static SecurityContext get defaultContext {
return _SecurityContext.defaultContext;
}
+
+ /* patch */ static bool get alpnSupported {
+ return _SecurityContext.alpnSupported;
+ }
}
class _SecurityContext
@@ -165,6 +169,8 @@
void setClientAuthoritiesBytes(List<int> authCertBytes, {String password})
native "SecurityContext_SetClientAuthoritiesBytes";
+ static bool get alpnSupported => _alpnSupported();
+ static bool _alpnSupported() native "SecurityContext_AlpnSupported";
void setAlpnProtocols(List<String> protocols, bool isServer) {
Uint8List encodedProtocols =
SecurityContext._protocolsToLengthEncoding(protocols);
diff --git a/runtime/bin/secure_socket_unsupported.cc b/runtime/bin/secure_socket_unsupported.cc
index 91f4fc7..1cd09d0 100644
--- a/runtime/bin/secure_socket_unsupported.cc
+++ b/runtime/bin/secure_socket_unsupported.cc
@@ -7,7 +7,6 @@
#include "include/dart_api.h"
-
namespace dart {
namespace bin {
@@ -128,6 +127,11 @@
"Secure Sockets unsupported on this platform"));
}
+void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) {
+ Dart_ThrowException(DartUtils::NewDartArgumentError(
+ "Secure Sockets unsupported on this platform"));
+}
+
void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
Dart_NativeArguments args) {
Dart_ThrowException(DartUtils::NewDartArgumentError(
diff --git a/runtime/bin/snapshot_empty.cc b/runtime/bin/snapshot_empty.cc
index 4fd42b3..bab9212 100644
--- a/runtime/bin/snapshot_empty.cc
+++ b/runtime/bin/snapshot_empty.cc
@@ -13,7 +13,6 @@
#endif
#include <stddef.h>
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/snapshot_in.cc b/runtime/bin/snapshot_in.cc
index e2d67e9..769d96c 100644
--- a/runtime/bin/snapshot_in.cc
+++ b/runtime/bin/snapshot_in.cc
@@ -13,7 +13,6 @@
#endif
#include <stddef.h>
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index 87f39f6..cba96c0 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -2,12 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+#include "bin/dartutils.h"
#include "bin/io_buffer.h"
#include "bin/isolate_data.h"
-#include "bin/dartutils.h"
+#include "bin/lockers.h"
#include "bin/socket.h"
#include "bin/thread.h"
-#include "bin/lockers.h"
#include "bin/utils.h"
#include "platform/globals.h"
@@ -60,7 +60,6 @@
// There is already a socket listening on this port. We need to ensure
// that if there is one also listening on the same address, it was created
// with `shared = true`, ...
-
OSSocket *os_socket = it->second;
OSSocket *os_socket_same_addr = findOSSocketWithAddress(os_socket, addr);
@@ -146,7 +145,7 @@
current = current->next;
}
- if (prev == NULL && current->next == NULL) {
+ if ((prev == NULL) && (current->next == NULL)) {
// Remove last element from the list.
sockets_by_port_.erase(os_socket->port);
} else if (prev == NULL) {
@@ -271,7 +270,9 @@
}
uint8_t* buffer = NULL;
Dart_Handle result = IOBuffer::Allocate(length, &buffer);
- if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
ASSERT(buffer != NULL);
intptr_t bytes_read = Socket::Read(socket, buffer, length);
if (bytes_read == length) {
@@ -279,7 +280,9 @@
} else if (bytes_read > 0) {
uint8_t* new_buffer = NULL;
Dart_Handle new_result = IOBuffer::Allocate(bytes_read, &new_buffer);
- if (Dart_IsError(new_result)) Dart_PropagateError(new_result);
+ if (Dart_IsError(new_result)) {
+ Dart_PropagateError(new_result);
+ }
ASSERT(new_buffer != NULL);
memmove(new_buffer, buffer, bytes_read);
Dart_SetReturnValue(args, new_result);
@@ -326,7 +329,9 @@
ASSERT(bytes_read > 0);
uint8_t* data_buffer = NULL;
Dart_Handle data = IOBuffer::Allocate(bytes_read, &data_buffer);
- if (Dart_IsError(data)) Dart_PropagateError(data);
+ if (Dart_IsError(data)) {
+ Dart_PropagateError(data);
+ }
ASSERT(data_buffer != NULL);
memmove(data_buffer, isolate_data->udp_receive_buffer, bytes_read);
@@ -347,14 +352,20 @@
Dart_Handle dart_args[kNumArgs];
dart_args[0] = data;
dart_args[1] = Dart_NewStringFromCString(numeric_address);
- if (Dart_IsError(dart_args[1])) Dart_PropagateError(dart_args[1]);
+ if (Dart_IsError(dart_args[1])) {
+ Dart_PropagateError(dart_args[1]);
+ }
dart_args[2] = SocketAddress::ToTypedData(addr);
dart_args[3] = Dart_NewInteger(port);
- if (Dart_IsError(dart_args[3])) Dart_PropagateError(dart_args[3]);
+ if (Dart_IsError(dart_args[3])) {
+ Dart_PropagateError(dart_args[3]);
+ }
// TODO(sgjesse): Cache the _makeDatagram function somewhere.
Dart_Handle io_lib =
Dart_LookupLibrary(DartUtils::NewString("dart:io"));
- if (Dart_IsError(io_lib)) Dart_PropagateError(io_lib);
+ if (Dart_IsError(io_lib)) {
+ Dart_PropagateError(io_lib);
+ }
Dart_Handle result =
Dart_Invoke(io_lib,
DartUtils::NewString("_makeDatagram"),
@@ -376,7 +387,9 @@
DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 3));
bool short_write = false;
if (short_socket_writes) {
- if (length > 1) short_write = true;
+ if (length > 1) {
+ short_write = true;
+ }
length = (length + 1) / 2;
}
Dart_TypedData_Type type;
@@ -384,7 +397,9 @@
intptr_t len;
Dart_Handle result = Dart_TypedDataAcquireData(
buffer_obj, &type, reinterpret_cast<void**>(&buffer), &len);
- if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
ASSERT((offset + length) <= len);
buffer += offset;
intptr_t bytes_written = Socket::Write(socket, buffer, length);
@@ -428,7 +443,9 @@
intptr_t len;
Dart_Handle result = Dart_TypedDataAcquireData(
buffer_obj, &type, reinterpret_cast<void**>(&buffer), &len);
- if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
ASSERT((offset + length) <= len);
buffer += offset;
intptr_t bytes_written = Socket::SendTo(socket, buffer, length, addr);
@@ -518,15 +535,13 @@
void FUNCTION_NAME(Socket_GetSocketId)(Dart_NativeArguments args) {
- intptr_t id =
- Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0));
+ intptr_t id = Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0));
Dart_SetReturnValue(args, Dart_NewInteger(id));
}
void FUNCTION_NAME(Socket_SetSocketId)(Dart_NativeArguments args) {
- intptr_t id =
- DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1));
+ intptr_t id = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1));
Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 0), id);
}
@@ -569,7 +584,7 @@
CObject* Socket::LookupRequest(const CObjectArray& request) {
- if (request.Length() == 2 &&
+ if ((request.Length() == 2) &&
request[0]->IsString() &&
request[1]->IsInt32()) {
CObjectString host(request[0]);
@@ -613,7 +628,7 @@
CObject* Socket::ReverseLookupRequest(const CObjectArray& request) {
- if (request.Length() == 1 &&
+ if ((request.Length() == 1) &&
request[0]->IsTypedData()) {
CObjectUint8Array addr_object(request[0]);
RawAddr addr;
@@ -648,7 +663,7 @@
CObject* Socket::ListInterfacesRequest(const CObjectArray& request) {
- if (request.Length() == 1 &&
+ if ((request.Length() == 1) &&
request[0]->IsInt32()) {
CObjectInt32 type(request[0]);
CObject* result = NULL;
@@ -841,7 +856,9 @@
void Socket::SetSocketIdNativeField(Dart_Handle socket, intptr_t id) {
Dart_Handle err =
Dart_SetNativeInstanceField(socket, kSocketIdNativeField, id);
- if (Dart_IsError(err)) Dart_PropagateError(err);
+ if (Dart_IsError(err)) {
+ Dart_PropagateError(err);
+ }
}
@@ -849,7 +866,9 @@
intptr_t socket = 0;
Dart_Handle err =
Dart_GetNativeInstanceField(socket_obj, kSocketIdNativeField, &socket);
- if (Dart_IsError(err)) Dart_PropagateError(err);
+ if (Dart_IsError(err)) {
+ Dart_PropagateError(err);
+ }
return socket;
}
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h
index 559305c..b058a51 100644
--- a/runtime/bin/socket.h
+++ b/runtime/bin/socket.h
@@ -26,7 +26,6 @@
#include "bin/thread.h"
#include "bin/utils.h"
-
namespace dart {
namespace bin {
@@ -59,7 +58,9 @@
~SocketAddress() {}
int GetType() {
- if (addr_.ss.ss_family == AF_INET6) return TYPE_IPV6;
+ if (addr_.ss.ss_family == AF_INET6) {
+ return TYPE_IPV6;
+ }
return TYPE_IPV4;
}
@@ -67,23 +68,27 @@
const RawAddr& addr() const { return addr_; }
static intptr_t GetAddrLength(const RawAddr& addr) {
- ASSERT(addr.ss.ss_family == AF_INET || addr.ss.ss_family == AF_INET6);
- return addr.ss.ss_family == AF_INET6 ?
+ ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6));
+ return (addr.ss.ss_family == AF_INET6) ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
}
static intptr_t GetInAddrLength(const RawAddr& addr) {
- ASSERT(addr.ss.ss_family == AF_INET || addr.ss.ss_family == AF_INET6);
- return addr.ss.ss_family == AF_INET6 ?
+ ASSERT((addr.ss.ss_family == AF_INET) || (addr.ss.ss_family == AF_INET6));
+ return (addr.ss.ss_family == AF_INET6) ?
sizeof(struct in6_addr) : sizeof(struct in_addr);
}
static bool AreAddressesEqual(const RawAddr& a, const RawAddr& b) {
if (a.ss.ss_family == AF_INET) {
- if (b.ss.ss_family != AF_INET) return false;
+ if (b.ss.ss_family != AF_INET) {
+ return false;
+ }
return memcmp(&a.in.sin_addr, &b.in.sin_addr, sizeof(a.in.sin_addr)) == 0;
} else if (a.ss.ss_family == AF_INET6) {
- if (b.ss.ss_family != AF_INET6) return false;
+ if (b.ss.ss_family != AF_INET6) {
+ return false;
+ }
return memcmp(&a.in6.sin6_addr,
&b.in6.sin6_addr,
sizeof(a.in6.sin6_addr)) == 0;
@@ -99,9 +104,11 @@
intptr_t len;
Dart_Handle result = Dart_TypedDataAcquireData(
obj, &data_type, reinterpret_cast<void**>(&data), &len);
- if (Dart_IsError(result)) Dart_PropagateError(result);
- if (data_type != Dart_TypedData_kUint8 ||
- (len != sizeof(in_addr) && len != sizeof(in6_addr))) {
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ if ((data_type != Dart_TypedData_kUint8) ||
+ ((len != sizeof(in_addr)) && (len != sizeof(in6_addr)))) {
Dart_PropagateError(
Dart_NewApiError("Unexpected type for socket address"));
}
@@ -118,9 +125,13 @@
}
static int16_t FromType(int type) {
- if (type == TYPE_ANY) return AF_UNSPEC;
- if (type == TYPE_IPV4) return AF_INET;
- ASSERT(type == TYPE_IPV6 && "Invalid type");
+ if (type == TYPE_ANY) {
+ return AF_UNSPEC;
+ }
+ if (type == TYPE_IPV4) {
+ return AF_INET;
+ }
+ ASSERT((type == TYPE_IPV6) && "Invalid type");
return AF_INET6;
}
@@ -143,7 +154,9 @@
static Dart_Handle ToTypedData(const RawAddr& addr) {
int len = GetInAddrLength(addr);
Dart_Handle result = Dart_NewTypedData(Dart_TypedData_kUint8, len);
- if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
Dart_Handle err;
if (addr.addr.sa_family == AF_INET6) {
err = Dart_ListSetAsBytes(
@@ -153,7 +166,9 @@
err = Dart_ListSetAsBytes(
result, 0, reinterpret_cast<const uint8_t*>(&addr.in.sin_addr), len);
}
- if (Dart_IsError(err)) Dart_PropagateError(err);
+ if (Dart_IsError(err)) {
+ Dart_PropagateError(err);
+ }
return result;
}
@@ -178,11 +193,12 @@
DISALLOW_COPY_AND_ASSIGN(SocketAddress);
};
+
class InterfaceSocketAddress {
public:
- explicit InterfaceSocketAddress(struct sockaddr* sa,
- const char* interface_name,
- intptr_t interface_index)
+ InterfaceSocketAddress(struct sockaddr* sa,
+ const char* interface_name,
+ intptr_t interface_index)
: socket_address_(new SocketAddress(sa)),
interface_name_(interface_name),
interface_index_(interface_index) {}
@@ -203,6 +219,7 @@
DISALLOW_COPY_AND_ASSIGN(InterfaceSocketAddress);
};
+
template<typename T>
class AddressList {
public:
@@ -228,6 +245,7 @@
DISALLOW_COPY_AND_ASSIGN(AddressList);
};
+
class Socket {
public:
enum SocketRequest {
@@ -340,6 +358,7 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(ServerSocket);
};
+
class ListeningSocketRegistry {
private:
struct OSSocket {
@@ -416,7 +435,6 @@
DISALLOW_COPY_AND_ASSIGN(ListeningSocketRegistry);
};
-
} // namespace bin
} // namespace dart
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index da234f0..2d43a44 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -9,12 +9,12 @@
#include "bin/socket_android.h"
#include <errno.h> // NOLINT
+#include <netinet/tcp.h> // NOLINT
#include <stdio.h> // NOLINT
#include <stdlib.h> // NOLINT
#include <string.h> // NOLINT
#include <sys/stat.h> // NOLINT
#include <unistd.h> // NOLINT
-#include <netinet/tcp.h> // NOLINT
#include "bin/fdutils.h"
#include "bin/file.h"
@@ -36,16 +36,8 @@
bool Socket::FormatNumericAddress(const RawAddr& addr, char* address, int len) {
socklen_t salen = SocketAddress::GetAddrLength(addr);
- if (NO_RETRY_EXPECTED(getnameinfo(&addr.addr,
- salen,
- address,
- len,
- NULL,
- 0,
- NI_NUMERICHOST)) != 0) {
- return false;
- }
- return true;
+ return (NO_RETRY_EXPECTED(getnameinfo(
+ &addr.addr, salen, address, len, NULL, 0, NI_NUMERICHOST)) == 0);
}
@@ -69,7 +61,7 @@
static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
intptr_t result = TEMP_FAILURE_RETRY(
connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr)));
- if (result == 0 || errno == EINPROGRESS) {
+ if ((result == 0) || (errno == EINPROGRESS)) {
return fd;
}
VOID_TEMP_FAILURE_RETRY(close(fd));
@@ -98,7 +90,7 @@
intptr_t result = TEMP_FAILURE_RETRY(
bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
- if (result != 0 && errno != EINPROGRESS) {
+ if ((result != 0) && (errno != EINPROGRESS)) {
VOID_TEMP_FAILURE_RETRY(close(fd));
return -1;
}
@@ -116,7 +108,7 @@
ASSERT(fd >= 0);
ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
- if (read_bytes == -1 && errno == EWOULDBLOCK) {
+ if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
@@ -131,7 +123,7 @@
socklen_t addr_len = sizeof(addr->ss);
ssize_t read_bytes = TEMP_FAILURE_RETRY(
recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
- if (read_bytes == -1 && errno == EWOULDBLOCK) {
+ if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
@@ -144,7 +136,7 @@
ASSERT(fd >= 0);
ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
- if (written_bytes == -1 && errno == EWOULDBLOCK) {
+ if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;
@@ -160,7 +152,7 @@
sendto(fd, buffer, num_bytes, 0,
&addr.addr, SocketAddress::GetAddrLength(addr)));
ASSERT(EAGAIN == EWOULDBLOCK);
- if (written_bytes == -1 && errno == EWOULDBLOCK) {
+ if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;
@@ -207,10 +199,18 @@
int Socket::GetType(intptr_t fd) {
struct stat buf;
int result = fstat(fd, &buf);
- if (result == -1) return -1;
- if (S_ISCHR(buf.st_mode)) return File::kTerminal;
- if (S_ISFIFO(buf.st_mode)) return File::kPipe;
- if (S_ISREG(buf.st_mode)) return File::kFile;
+ if (result == -1) {
+ return -1;
+ }
+ if (S_ISCHR(buf.st_mode)) {
+ return File::kTerminal;
+ }
+ if (S_ISFIFO(buf.st_mode)) {
+ return File::kPipe;
+ }
+ if (S_ISREG(buf.st_mode)) {
+ return File::kFile;
+ }
return File::kOther;
}
@@ -247,12 +247,14 @@
}
intptr_t count = 0;
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
- if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
+ if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
+ count++;
+ }
}
intptr_t i = 0;
AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
- if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
+ if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
addresses->SetAt(i, new SocketAddress(c->ai_addr));
i++;
}
@@ -294,7 +296,7 @@
ASSERT(type == SocketAddress::TYPE_IPV6);
result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr);
}
- return result == 1;
+ return (result == 1);
}
@@ -302,7 +304,9 @@
intptr_t fd;
fd = NO_RETRY_EXPECTED(socket(addr.addr.sa_family, SOCK_DGRAM, IPPROTO_UDP));
- if (fd < 0) return -1;
+ if (fd < 0) {
+ return -1;
+ }
FDUtils::SetCloseOnExec(fd);
@@ -340,7 +344,9 @@
intptr_t fd;
fd = NO_RETRY_EXPECTED(socket(addr.ss.ss_family, SOCK_STREAM, 0));
- if (fd < 0) return -1;
+ if (fd < 0) {
+ return -1;
+ }
FDUtils::SetCloseOnExec(fd);
@@ -363,7 +369,8 @@
}
// Test for invalid socket port 65535 (some browsers disallow it).
- if (SocketAddress::GetAddrPort(addr) == 0 && Socket::GetPort(fd) == 65535) {
+ if ((SocketAddress::GetAddrPort(addr)) == 0 &&
+ (Socket::GetPort(fd) == 65535)) {
// Don't close the socket until we have created a new socket, ensuring
// that we do not get the bad port number again.
intptr_t new_fd = CreateBindListen(addr, backlog, v6_only);
@@ -435,9 +442,9 @@
reinterpret_cast<void *>(&on),
&len));
if (err == 0) {
- *enabled = on == 1;
+ *enabled = (on == 1);
}
- return err == 0;
+ return (err == 0);
}
@@ -521,9 +528,9 @@
reinterpret_cast<char *>(&on),
&len));
if (err == 0) {
- *enabled = on == 1;
+ *enabled = (on == 1);
}
- return err == 0;
+ return (err == 0);
}
@@ -539,7 +546,7 @@
bool Socket::JoinMulticast(
intptr_t fd, const RawAddr& addr, const RawAddr&, int interfaceIndex) {
- int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
+ int proto = (addr.addr.sa_family == AF_INET) ? IPPROTO_IP : IPPROTO_IPV6;
struct group_req mreq;
mreq.gr_interface = interfaceIndex;
memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
@@ -550,7 +557,7 @@
bool Socket::LeaveMulticast(
intptr_t fd, const RawAddr& addr, const RawAddr&, int interfaceIndex) {
- int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
+ int proto = (addr.addr.sa_family == AF_INET) ? IPPROTO_IP : IPPROTO_IPV6;
struct group_req mreq;
mreq.gr_interface = interfaceIndex;
memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr));
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index 575da3b..b9068d7 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -9,14 +9,14 @@
#include "bin/socket_linux.h"
#include <errno.h> // NOLINT
+#include <ifaddrs.h> // NOLINT
+#include <net/if.h> // NOLINT
+#include <netinet/tcp.h> // NOLINT
#include <stdio.h> // NOLINT
#include <stdlib.h> // NOLINT
#include <string.h> // NOLINT
#include <sys/stat.h> // NOLINT
#include <unistd.h> // NOLINT
-#include <net/if.h> // NOLINT
-#include <netinet/tcp.h> // NOLINT
-#include <ifaddrs.h> // NOLINT
#include "bin/fdutils.h"
#include "bin/file.h"
@@ -39,11 +39,8 @@
bool Socket::FormatNumericAddress(const RawAddr& addr, char* address, int len) {
socklen_t salen = SocketAddress::GetAddrLength(addr);
- if (NO_RETRY_EXPECTED(getnameinfo(
- &addr.addr, salen, address, len, NULL, 0, NI_NUMERICHOST) != 0)) {
- return false;
- }
- return true;
+ return (NO_RETRY_EXPECTED(getnameinfo(
+ &addr.addr, salen, address, len, NULL, 0, NI_NUMERICHOST) == 0));
}
@@ -67,7 +64,7 @@
static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
intptr_t result = TEMP_FAILURE_RETRY(
connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr)));
- if (result == 0 || errno == EINPROGRESS) {
+ if ((result == 0) || (errno == EINPROGRESS)) {
return fd;
}
VOID_TEMP_FAILURE_RETRY(close(fd));
@@ -93,7 +90,7 @@
intptr_t result = TEMP_FAILURE_RETRY(
bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
- if (result != 0 && errno != EINPROGRESS) {
+ if ((result != 0) && (errno != EINPROGRESS)) {
VOID_TEMP_FAILURE_RETRY(close(fd));
return -1;
}
@@ -111,7 +108,7 @@
ASSERT(fd >= 0);
ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
- if (read_bytes == -1 && errno == EWOULDBLOCK) {
+ if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
@@ -126,7 +123,7 @@
socklen_t addr_len = sizeof(addr->ss);
ssize_t read_bytes = TEMP_FAILURE_RETRY(
recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
- if (read_bytes == -1 && errno == EWOULDBLOCK) {
+ if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
@@ -139,7 +136,7 @@
ASSERT(fd >= 0);
ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
- if (written_bytes == -1 && errno == EWOULDBLOCK) {
+ if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;
@@ -155,7 +152,7 @@
sendto(fd, buffer, num_bytes, 0,
&addr.addr, SocketAddress::GetAddrLength(addr)));
ASSERT(EAGAIN == EWOULDBLOCK);
- if (written_bytes == -1 && errno == EWOULDBLOCK) {
+ if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;
@@ -200,10 +197,18 @@
int Socket::GetType(intptr_t fd) {
struct stat64 buf;
int result = TEMP_FAILURE_RETRY(fstat64(fd, &buf));
- if (result == -1) return -1;
- if (S_ISCHR(buf.st_mode)) return File::kTerminal;
- if (S_ISFIFO(buf.st_mode)) return File::kPipe;
- if (S_ISREG(buf.st_mode)) return File::kFile;
+ if (result == -1) {
+ return -1;
+ }
+ if (S_ISCHR(buf.st_mode)) {
+ return File::kTerminal;
+ }
+ if (S_ISFIFO(buf.st_mode)) {
+ return File::kPipe;
+ }
+ if (S_ISREG(buf.st_mode)) {
+ return File::kFile;
+ }
return File::kOther;
}
@@ -240,12 +245,14 @@
}
intptr_t count = 0;
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
- if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
+ if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
+ count++;
+ }
}
intptr_t i = 0;
AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
- if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
+ if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
addresses->SetAt(i, new SocketAddress(c->ai_addr));
i++;
}
@@ -288,7 +295,7 @@
result = NO_RETRY_EXPECTED(
inet_pton(AF_INET6, address, &addr->in6.sin6_addr));
}
- return result == 1;
+ return (result == 1);
}
@@ -298,7 +305,9 @@
fd = NO_RETRY_EXPECTED(socket(addr.addr.sa_family,
SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
IPPROTO_UDP));
- if (fd < 0) return -1;
+ if (fd < 0) {
+ return -1;
+ }
if (reuseAddress) {
int optval = 1;
@@ -321,12 +330,9 @@
return false;
}
int family = ifa->ifa_addr->sa_family;
- if (lookup_family == family) return true;
- if (lookup_family == AF_UNSPEC &&
- (family == AF_INET || family == AF_INET6)) {
- return true;
- }
- return false;
+ return ((lookup_family == family) ||
+ (((lookup_family == AF_UNSPEC) &&
+ ((family == AF_INET) || (family == AF_INET6)))));
}
@@ -348,7 +354,9 @@
intptr_t count = 0;
for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
- if (ShouldIncludeIfaAddrs(ifa, lookup_family)) count++;
+ if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
+ count++;
+ }
}
AddressList<InterfaceSocketAddress>* addresses =
@@ -374,7 +382,9 @@
fd = NO_RETRY_EXPECTED(
socket(addr.ss.ss_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
- if (fd < 0) return -1;
+ if (fd < 0) {
+ return -1;
+ }
int optval = 1;
VOID_NO_RETRY_EXPECTED(
@@ -393,7 +403,8 @@
}
// Test for invalid socket port 65535 (some browsers disallow it).
- if (SocketAddress::GetAddrPort(addr) == 0 && Socket::GetPort(fd) == 65535) {
+ if ((SocketAddress::GetAddrPort(addr) == 0) &&
+ (Socket::GetPort(fd) == 65535)) {
// Don't close the socket until we have created a new socket, ensuring
// that we do not get the bad port number again.
intptr_t new_fd = CreateBindListen(addr, backlog, v6_only);
@@ -461,9 +472,9 @@
int err = NO_RETRY_EXPECTED(getsockopt(
fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<void *>(&on), &len));
if (err == 0) {
- *enabled = on == 1;
+ *enabled = (on == 1);
}
- return err == 0;
+ return (err == 0);
}
@@ -533,9 +544,9 @@
int err = NO_RETRY_EXPECTED(getsockopt(
fd, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char *>(&on), &len));
if (err == 0) {
- *enabled = on == 1;
+ *enabled = (on == 1);
}
- return err == 0;
+ return (err == 0);
}
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index 22613d5..8306b56 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -9,14 +9,14 @@
#include "bin/socket_macos.h"
#include <errno.h> // NOLINT
+#include <ifaddrs.h> // NOLINT
+#include <net/if.h> // NOLINT
+#include <netinet/tcp.h> // NOLINT
#include <stdio.h> // NOLINT
#include <stdlib.h> // NOLINT
#include <string.h> // NOLINT
#include <sys/stat.h> // NOLINT
#include <unistd.h> // NOLINT
-#include <net/if.h> // NOLINT
-#include <netinet/tcp.h> // NOLINT
-#include <ifaddrs.h> // NOLINT
#include "bin/fdutils.h"
#include "bin/file.h"
@@ -38,16 +38,8 @@
bool Socket::FormatNumericAddress(const RawAddr& addr, char* address, int len) {
socklen_t salen = SocketAddress::GetAddrLength(addr);
- if (NO_RETRY_EXPECTED(getnameinfo(&addr.addr,
- salen,
- address,
- len,
- NULL,
- 0,
- NI_NUMERICHOST)) != 0) {
- return false;
- }
- return true;
+ return (NO_RETRY_EXPECTED(getnameinfo(
+ &addr.addr, salen, address, len, NULL, 0, NI_NUMERICHOST)) == 0);
}
@@ -71,7 +63,7 @@
static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
intptr_t result = TEMP_FAILURE_RETRY(
connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr)));
- if (result == 0 || errno == EINPROGRESS) {
+ if ((result == 0) || (errno == EINPROGRESS)) {
return fd;
}
VOID_TEMP_FAILURE_RETRY(close(fd));
@@ -100,7 +92,7 @@
intptr_t result = TEMP_FAILURE_RETRY(
bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
- if (result != 0 && errno != EINPROGRESS) {
+ if ((result != 0) && (errno != EINPROGRESS)) {
VOID_TEMP_FAILURE_RETRY(close(fd));
return -1;
}
@@ -118,7 +110,7 @@
ASSERT(fd >= 0);
ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
- if (read_bytes == -1 && errno == EWOULDBLOCK) {
+ if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
@@ -133,7 +125,7 @@
socklen_t addr_len = sizeof(addr->ss);
ssize_t read_bytes = TEMP_FAILURE_RETRY(
recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
- if (read_bytes == -1 && errno == EWOULDBLOCK) {
+ if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the read would block we need to retry and therefore return 0
// as the number of bytes written.
read_bytes = 0;
@@ -146,7 +138,7 @@
ASSERT(fd >= 0);
ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
ASSERT(EAGAIN == EWOULDBLOCK);
- if (written_bytes == -1 && errno == EWOULDBLOCK) {
+ if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;
@@ -162,7 +154,7 @@
sendto(fd, buffer, num_bytes, 0,
&addr.addr, SocketAddress::GetAddrLength(addr)));
ASSERT(EAGAIN == EWOULDBLOCK);
- if (written_bytes == -1 && errno == EWOULDBLOCK) {
+ if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
// If the would block we need to retry and therefore return 0 as
// the number of bytes written.
written_bytes = 0;
@@ -208,10 +200,18 @@
int Socket::GetType(intptr_t fd) {
struct stat buf;
int result = fstat(fd, &buf);
- if (result == -1) return -1;
- if (S_ISCHR(buf.st_mode)) return File::kTerminal;
- if (S_ISFIFO(buf.st_mode)) return File::kPipe;
- if (S_ISREG(buf.st_mode)) return File::kFile;
+ if (result == -1) {
+ return -1;
+ }
+ if (S_ISCHR(buf.st_mode)) {
+ return File::kTerminal;
+ }
+ if (S_ISFIFO(buf.st_mode)) {
+ return File::kPipe;
+ }
+ if (S_ISREG(buf.st_mode)) {
+ return File::kFile;
+ }
return File::kOther;
}
@@ -242,12 +242,14 @@
}
intptr_t count = 0;
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
- if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
+ if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
+ count++;
+ }
}
intptr_t i = 0;
AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
- if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
+ if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
addresses->SetAt(i, new SocketAddress(c->ai_addr));
i++;
}
@@ -289,7 +291,7 @@
ASSERT(type == SocketAddress::TYPE_IPV6);
result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr);
}
- return result == 1;
+ return (result == 1);
}
@@ -297,7 +299,9 @@
intptr_t fd;
fd = NO_RETRY_EXPECTED(socket(addr.addr.sa_family, SOCK_DGRAM, IPPROTO_UDP));
- if (fd < 0) return -1;
+ if (fd < 0) {
+ return -1;
+ }
FDUtils::SetCloseOnExec(fd);
@@ -324,12 +328,9 @@
return false;
}
int family = ifa->ifa_addr->sa_family;
- if (lookup_family == family) return true;
- if (lookup_family == AF_UNSPEC &&
- (family == AF_INET || family == AF_INET6)) {
- return true;
- }
- return false;
+ return ((lookup_family == family) ||
+ ((lookup_family == AF_UNSPEC) &&
+ ((family == AF_INET) || (family == AF_INET6))));
}
@@ -376,7 +377,9 @@
intptr_t fd;
fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
- if (fd < 0) return -1;
+ if (fd < 0) {
+ return -1;
+ }
FDUtils::SetCloseOnExec(fd);
@@ -397,7 +400,8 @@
}
// Test for invalid socket port 65535 (some browsers disallow it).
- if (SocketAddress::GetAddrPort(addr) == 0 && Socket::GetPort(fd) == 65535) {
+ if ((SocketAddress::GetAddrPort(addr) == 0) &&
+ (Socket::GetPort(fd) == 65535)) {
// Don't close the socket until we have created a new socket, ensuring
// that we do not get the bad port number again.
intptr_t new_fd = CreateBindListen(addr, backlog, v6_only);
@@ -459,9 +463,9 @@
reinterpret_cast<void *>(&on),
&len));
if (err == 0) {
- *enabled = on == 1;
+ *enabled = (on == 1);
}
- return err == 0;
+ return (err == 0);
}
@@ -546,9 +550,9 @@
reinterpret_cast<char *>(&on),
&len));
if (err == 0) {
- *enabled = on == 1;
+ *enabled = (on == 1);
}
- return err == 0;
+ return (err == 0);
}
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc
index 30bdc44..ea306b7 100644
--- a/runtime/bin/socket_win.cc
+++ b/runtime/bin/socket_win.cc
@@ -54,7 +54,9 @@
bool Socket::Initialize() {
MutexLocker lock(init_mutex);
- if (socket_initialized) return true;
+ if (socket_initialized) {
+ return true;
+ }
int err;
WSADATA winsock_data;
WORD version_requested = MAKEWORD(2, 2);
@@ -64,7 +66,7 @@
} else {
Log::PrintErr("Unable to initialize Winsock: %d\n", WSAGetLastError());
}
- return err == 0;
+ return (err == 0);
}
intptr_t Socket::Available(intptr_t fd) {
@@ -107,9 +109,7 @@
SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd);
RawAddr raw;
socklen_t size = sizeof(raw);
- if (getsockname(socket_handle->socket(),
- &raw.addr,
- &size) == SOCKET_ERROR) {
+ if (getsockname(socket_handle->socket(), &raw.addr, &size) == SOCKET_ERROR) {
return 0;
}
return SocketAddress::GetAddrPort(raw);
@@ -121,9 +121,7 @@
SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd);
RawAddr raw;
socklen_t size = sizeof(raw);
- if (getpeername(socket_handle->socket(),
- &raw.addr,
- &size)) {
+ if (getpeername(socket_handle->socket(), &raw.addr, &size)) {
return NULL;
}
*port = SocketAddress::GetAddrPort(raw);
@@ -268,7 +266,9 @@
intptr_t Socket::GetStdioHandle(intptr_t num) {
- if (num != 0) return -1;
+ if (num != 0) {
+ return -1;
+ }
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
if (handle == INVALID_HANDLE_VALUE) {
return -1;
@@ -320,12 +320,14 @@
}
intptr_t count = 0;
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
- if (c->ai_family == AF_INET || c->ai_family == AF_INET6) count++;
+ if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
+ count++;
+ }
}
AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
intptr_t i = 0;
for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
- if (c->ai_family == AF_INET || c->ai_family == AF_INET6) {
+ if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
addresses->SetAt(i, new SocketAddress(c->ai_addr));
i++;
}
@@ -393,9 +395,7 @@
}
}
- status = bind(s,
- &addr.addr,
- SocketAddress::GetAddrLength(addr));
+ status = bind(s, &addr.addr, SocketAddress::GetAddrLength(addr));
if (status == SOCKET_ERROR) {
DWORD rc = WSAGetLastError();
closesocket(s);
@@ -496,9 +496,7 @@
sizeof(optval));
}
- status = bind(s,
- &addr.addr,
- SocketAddress::GetAddrLength(addr));
+ status = bind(s, &addr.addr, SocketAddress::GetAddrLength(addr));
if (status == SOCKET_ERROR) {
DWORD rc = WSAGetLastError();
closesocket(s);
@@ -509,8 +507,8 @@
ListenSocket* listen_socket = new ListenSocket(s);
// Test for invalid socket port 65535 (some browsers disallow it).
- if (SocketAddress::GetAddrPort(addr) == 0 &&
- Socket::GetPort(reinterpret_cast<intptr_t>(listen_socket)) == 65535) {
+ if ((SocketAddress::GetAddrPort(addr) == 0) &&
+ (Socket::GetPort(reinterpret_cast<intptr_t>(listen_socket)) == 65535)) {
// Don't close fd until we have created new. By doing that we ensure another
// port.
intptr_t new_s = CreateBindListen(addr, backlog, v6_only);
@@ -571,9 +569,9 @@
reinterpret_cast<char *>(&on),
&len);
if (err == 0) {
- *enabled = on == 1;
+ *enabled = (on == 1);
}
- return err == 0;
+ return (err == 0);
}
@@ -618,7 +616,6 @@
optname,
reinterpret_cast<char *>(&on),
sizeof(on)) == 0;
- return false;
}
@@ -665,9 +662,9 @@
reinterpret_cast<char *>(&on),
&len);
if (err == 0) {
- *enabled = on == 1;
+ *enabled = (on == 1);
}
- return err == 0;
+ return (err == 0);
}
diff --git a/runtime/bin/socket_win.h b/runtime/bin/socket_win.h
index 76f33fd..ab32ed3 100644
--- a/runtime/bin/socket_win.h
+++ b/runtime/bin/socket_win.h
@@ -5,9 +5,9 @@
#ifndef BIN_SOCKET_WIN_H_
#define BIN_SOCKET_WIN_H_
-#include <winsock2.h>
#include <iphlpapi.h>
-#include <ws2tcpip.h>
#include <mswsock.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
#endif // BIN_SOCKET_WIN_H_
diff --git a/runtime/bin/stdio.cc b/runtime/bin/stdio.cc
index c866710..b14fe92 100644
--- a/runtime/bin/stdio.cc
+++ b/runtime/bin/stdio.cc
@@ -2,17 +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.
+#include "bin/stdio.h"
+
#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/utils.h"
-#include "bin/stdio.h"
#include "platform/globals.h"
#include "platform/utils.h"
#include "include/dart_api.h"
-
namespace dart {
namespace bin {
@@ -51,7 +51,7 @@
return;
}
intptr_t fd = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 0));
- if (fd != 1 && fd != 2) {
+ if ((fd != 1) && (fd != 2)) {
Dart_SetReturnValue(args, Dart_NewApiError("Terminal fd must be 1 or 2"));
return;
}
diff --git a/runtime/bin/stdio.h b/runtime/bin/stdio.h
index 99e2cd5..afe4637 100644
--- a/runtime/bin/stdio.h
+++ b/runtime/bin/stdio.h
@@ -10,7 +10,6 @@
#include "platform/globals.h"
-
namespace dart {
namespace bin {
diff --git a/runtime/bin/stdio_android.cc b/runtime/bin/stdio_android.cc
index a02a8e3..8d2a3c5 100644
--- a/runtime/bin/stdio_android.cc
+++ b/runtime/bin/stdio_android.cc
@@ -5,16 +5,15 @@
#include "platform/globals.h"
#if defined(TARGET_OS_ANDROID)
+#include "bin/stdio.h"
+
#include <errno.h> // NOLINT
#include <sys/ioctl.h> // NOLINT
#include <termios.h> // NOLINT
-#include "bin/stdio.h"
#include "bin/fdutils.h"
-
#include "platform/signal_blocker.h"
-
namespace dart {
namespace bin {
@@ -30,7 +29,7 @@
bool Stdin::GetEchoMode() {
struct termios term;
tcgetattr(STDIN_FILENO, &term);
- return (term.c_lflag & ECHO) != 0;
+ return ((term.c_lflag & ECHO) != 0);
}
@@ -38,9 +37,9 @@
struct termios term;
tcgetattr(STDIN_FILENO, &term);
if (enabled) {
- term.c_lflag |= ECHO|ECHONL;
+ term.c_lflag |= (ECHO | ECHONL);
} else {
- term.c_lflag &= ~(ECHO|ECHONL);
+ term.c_lflag &= ~(ECHO | ECHONL);
}
tcsetattr(STDIN_FILENO, TCSANOW, &term);
}
@@ -49,7 +48,7 @@
bool Stdin::GetLineMode() {
struct termios term;
tcgetattr(STDIN_FILENO, &term);
- return (term.c_lflag & ICANON) != 0;
+ return ((term.c_lflag & ICANON) != 0);
}
@@ -67,8 +66,8 @@
bool Stdout::GetTerminalSize(intptr_t fd, int size[2]) {
struct winsize w;
- if (NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w) == 0) &&
- (w.ws_col != 0 || w.ws_row != 0)) {
+ int status = NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w));
+ if ((status == 0) && ((w.ws_col != 0) || (w.ws_row != 0))) {
size[0] = w.ws_col;
size[1] = w.ws_row;
return true;
diff --git a/runtime/bin/stdio_linux.cc b/runtime/bin/stdio_linux.cc
index c01a771..8f51e7e 100644
--- a/runtime/bin/stdio_linux.cc
+++ b/runtime/bin/stdio_linux.cc
@@ -5,16 +5,15 @@
#include "platform/globals.h"
#if defined(TARGET_OS_LINUX)
+#include "bin/stdio.h"
+
#include <errno.h> // NOLINT
#include <sys/ioctl.h> // NOLINT
#include <termios.h> // NOLINT
-#include "bin/stdio.h"
#include "bin/fdutils.h"
-
#include "platform/signal_blocker.h"
-
namespace dart {
namespace bin {
@@ -30,7 +29,7 @@
bool Stdin::GetEchoMode() {
struct termios term;
VOID_NO_RETRY_EXPECTED(tcgetattr(STDIN_FILENO, &term));
- return (term.c_lflag & ECHO) != 0;
+ return ((term.c_lflag & ECHO) != 0);
}
@@ -38,9 +37,9 @@
struct termios term;
VOID_NO_RETRY_EXPECTED(tcgetattr(STDIN_FILENO, &term));
if (enabled) {
- term.c_lflag |= ECHO|ECHONL;
+ term.c_lflag |= (ECHO | ECHONL);
} else {
- term.c_lflag &= ~(ECHO|ECHONL);
+ term.c_lflag &= ~(ECHO | ECHONL);
}
VOID_NO_RETRY_EXPECTED(tcsetattr(STDIN_FILENO, TCSANOW, &term));
}
@@ -49,7 +48,7 @@
bool Stdin::GetLineMode() {
struct termios term;
VOID_NO_RETRY_EXPECTED(tcgetattr(STDIN_FILENO, &term));
- return (term.c_lflag & ICANON) != 0;
+ return ((term.c_lflag & ICANON) != 0);
}
@@ -67,8 +66,8 @@
bool Stdout::GetTerminalSize(intptr_t fd, int size[2]) {
struct winsize w;
- if (NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w)) == 0 &&
- (w.ws_col != 0 || w.ws_row != 0)) {
+ int status = NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w));
+ if ((status == 0) && ((w.ws_col != 0) || (w.ws_row != 0))) {
size[0] = w.ws_col;
size[1] = w.ws_row;
return true;
diff --git a/runtime/bin/stdio_macos.cc b/runtime/bin/stdio_macos.cc
index 24f0414..7dc1141 100644
--- a/runtime/bin/stdio_macos.cc
+++ b/runtime/bin/stdio_macos.cc
@@ -5,16 +5,15 @@
#include "platform/globals.h"
#if defined(TARGET_OS_MACOS)
+#include "bin/stdio.h"
+
#include <errno.h> // NOLINT
#include <sys/ioctl.h> // NOLINT
#include <termios.h> // NOLINT
-#include "bin/stdio.h"
#include "bin/fdutils.h"
-
#include "platform/signal_blocker.h"
-
namespace dart {
namespace bin {
@@ -30,7 +29,7 @@
bool Stdin::GetEchoMode() {
struct termios term;
tcgetattr(STDIN_FILENO, &term);
- return (term.c_lflag & ECHO) != 0;
+ return ((term.c_lflag & ECHO) != 0);
}
@@ -38,9 +37,9 @@
struct termios term;
tcgetattr(STDIN_FILENO, &term);
if (enabled) {
- term.c_lflag |= ECHO|ECHONL;
+ term.c_lflag |= (ECHO | ECHONL);
} else {
- term.c_lflag &= ~(ECHO|ECHONL);
+ term.c_lflag &= ~(ECHO | ECHONL);
}
tcsetattr(STDIN_FILENO, TCSANOW, &term);
}
@@ -49,7 +48,7 @@
bool Stdin::GetLineMode() {
struct termios term;
tcgetattr(STDIN_FILENO, &term);
- return (term.c_lflag & ICANON) != 0;
+ return ((term.c_lflag & ICANON) != 0);
}
@@ -67,8 +66,8 @@
bool Stdout::GetTerminalSize(intptr_t fd, int size[2]) {
struct winsize w;
- if (NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w) == 0) &&
- (w.ws_col != 0 || w.ws_row != 0)) {
+ int status = NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w));
+ if ((status == 0) && ((w.ws_col != 0) || (w.ws_row != 0))) {
size[0] = w.ws_col;
size[1] = w.ws_row;
return true;
diff --git a/runtime/bin/stdio_win.cc b/runtime/bin/stdio_win.cc
index ec479c0..1cb6a527 100644
--- a/runtime/bin/stdio_win.cc
+++ b/runtime/bin/stdio_win.cc
@@ -7,7 +7,6 @@
#include "bin/stdio.h"
-
namespace dart {
namespace bin {
@@ -16,7 +15,7 @@
uint8_t buffer[1];
DWORD read = 0;
int c = -1;
- if (ReadFile(h, buffer, 1, &read, NULL) && read == 1) {
+ if (ReadFile(h, buffer, 1, &read, NULL) && (read == 1)) {
c = buffer[0];
}
return c;
@@ -26,15 +25,19 @@
bool Stdin::GetEchoMode() {
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
- if (!GetConsoleMode(h, &mode)) return false;
- return (mode & ENABLE_ECHO_INPUT) != 0;
+ if (!GetConsoleMode(h, &mode)) {
+ return false;
+ }
+ return ((mode & ENABLE_ECHO_INPUT) != 0);
}
void Stdin::SetEchoMode(bool enabled) {
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
- if (!GetConsoleMode(h, &mode)) return;
+ if (!GetConsoleMode(h, &mode)) {
+ return;
+ }
if (enabled) {
mode |= ENABLE_ECHO_INPUT;
} else {
@@ -47,7 +50,9 @@
bool Stdin::GetLineMode() {
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
- if (!GetConsoleMode(h, &mode)) return false;
+ if (!GetConsoleMode(h, &mode)) {
+ return false;
+ }
return (mode & ENABLE_LINE_INPUT) != 0;
}
@@ -55,7 +60,9 @@
void Stdin::SetLineMode(bool enabled) {
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
- if (!GetConsoleMode(h, &mode)) return;
+ if (!GetConsoleMode(h, &mode)) {
+ return;
+ }
if (enabled) {
mode |= ENABLE_LINE_INPUT;
} else {
@@ -73,7 +80,9 @@
h = GetStdHandle(STD_ERROR_HANDLE);
}
CONSOLE_SCREEN_BUFFER_INFO info;
- if (!GetConsoleScreenBufferInfo(h, &info)) return false;
+ if (!GetConsoleScreenBufferInfo(h, &info)) {
+ return false;
+ }
size[0] = info.srWindow.Right - info.srWindow.Left + 1;
size[1] = info.srWindow.Bottom - info.srWindow.Top + 1;
return true;
diff --git a/runtime/bin/thread.h b/runtime/bin/thread.h
index d4a67bc..d95675d 100644
--- a/runtime/bin/thread.h
+++ b/runtime/bin/thread.h
@@ -57,6 +57,10 @@
static void GetThreadCpuUsage(ThreadId thread_id, int64_t* cpu_usage);
static void InitOnce();
+
+ private:
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Thread);
};
@@ -105,7 +109,6 @@
DISALLOW_COPY_AND_ASSIGN(Monitor);
};
-
} // namespace bin
} // namespace dart
diff --git a/runtime/bin/thread_android.cc b/runtime/bin/thread_android.cc
index f84a988..4f5c547 100644
--- a/runtime/bin/thread_android.cc
+++ b/runtime/bin/thread_android.cc
@@ -6,6 +6,7 @@
#if defined(TARGET_OS_ANDROID)
#include "bin/thread.h"
+#include "bin/thread_android.h"
#include <errno.h> // NOLINT
#include <sys/time.h> // NOLINT
@@ -37,7 +38,9 @@
}
#else
#define RETURN_ON_PTHREAD_FAILURE(result) \
- if (result != 0) return result;
+ if (result != 0) { \
+ return result; \
+ }
#endif
@@ -164,7 +167,7 @@
bool Thread::Compare(ThreadId a, ThreadId b) {
- return a == b;
+ return (a == b);
}
diff --git a/runtime/bin/thread_linux.cc b/runtime/bin/thread_linux.cc
index 1e01a77..7a2a92a 100644
--- a/runtime/bin/thread_linux.cc
+++ b/runtime/bin/thread_linux.cc
@@ -6,6 +6,7 @@
#if defined(TARGET_OS_LINUX)
#include "bin/thread.h"
+#include "bin/thread_linux.h"
#include <errno.h> // NOLINT
#include <sys/resource.h> // NOLINT
@@ -38,7 +39,9 @@
}
#else
#define RETURN_ON_PTHREAD_FAILURE(result) \
- if (result != 0) return result;
+ if (result != 0) { \
+ return result; \
+ }
#endif
@@ -165,7 +168,7 @@
bool Thread::Compare(ThreadId a, ThreadId b) {
- return pthread_equal(a, b) != 0;
+ return (pthread_equal(a, b) != 0);
}
diff --git a/runtime/bin/thread_macos.cc b/runtime/bin/thread_macos.cc
index 28c747d..8286835 100644
--- a/runtime/bin/thread_macos.cc
+++ b/runtime/bin/thread_macos.cc
@@ -6,17 +6,18 @@
#if defined(TARGET_OS_MACOS)
#include "bin/thread.h"
+#include "bin/thread_macos.h"
-#include <sys/errno.h> // NOLINT
-#include <sys/types.h> // NOLINT
-#include <sys/sysctl.h> // NOLINT
-#include <mach/mach_init.h> // NOLINT
#include <mach/mach_host.h> // NOLINT
+#include <mach/mach_init.h> // NOLINT
#include <mach/mach_port.h> // NOLINT
#include <mach/mach_traps.h> // NOLINT
#include <mach/task_info.h> // NOLINT
-#include <mach/thread_info.h> // NOLINT
#include <mach/thread_act.h> // NOLINT
+#include <mach/thread_info.h> // NOLINT
+#include <sys/errno.h> // NOLINT
+#include <sys/sysctl.h> // NOLINT
+#include <sys/types.h> // NOLINT
#include "platform/assert.h"
#include "platform/utils.h"
@@ -45,7 +46,9 @@
}
#else
#define RETURN_ON_PTHREAD_FAILURE(result) \
- if (result != 0) return result;
+ if (result != 0) { \
+ return result; \
+ }
#endif
@@ -157,7 +160,7 @@
bool Thread::Compare(ThreadId a, ThreadId b) {
- return pthread_equal(a, b) != 0;
+ return (pthread_equal(a, b) != 0);
}
diff --git a/runtime/bin/thread_win.cc b/runtime/bin/thread_win.cc
index 44941bb..db41196 100644
--- a/runtime/bin/thread_win.cc
+++ b/runtime/bin/thread_win.cc
@@ -6,6 +6,7 @@
#if defined(TARGET_OS_WINDOWS)
#include "bin/thread.h"
+#include "bin/thread_win.h"
#include <process.h> // NOLINT
@@ -57,7 +58,7 @@
uint32_t tid;
uintptr_t thread = _beginthreadex(NULL, Thread::GetMaxStackSize(),
ThreadEntry, start_data, 0, &tid);
- if (thread == -1L || thread == 0) {
+ if ((thread == -1L) || (thread == 0)) {
#ifdef DEBUG
fprintf(stderr, "_beginthreadex error: %d (%s)\n", errno, strerror(errno));
#endif
@@ -130,7 +131,7 @@
bool Thread::Compare(ThreadId a, ThreadId b) {
- return a == b;
+ return (a == b);
}
@@ -209,7 +210,7 @@
if (result == WAIT_OBJECT_0) {
return true;
}
- if (result == WAIT_ABANDONED || result == WAIT_FAILED) {
+ if ((result == WAIT_ABANDONED) || (result == WAIT_FAILED)) {
FATAL1("Mutex try lock failed %d", GetLastError());
}
ASSERT(result == WAIT_TIMEOUT);
@@ -273,7 +274,8 @@
EnterCriticalSection(&waiters_cs_);
if (waiters_tail_ == NULL) {
ASSERT(waiters_head_ == NULL);
- waiters_head_ = waiters_tail_ = wait_data;
+ waiters_head_ = wait_data;
+ waiters_tail_ = wait_data;
} else {
waiters_tail_->next_ = wait_data;
waiters_tail_ = wait_data;
@@ -291,7 +293,8 @@
while (current != NULL) {
if (current == wait_data) {
if (waiters_head_ == waiters_tail_) {
- waiters_head_ = waiters_tail_ = NULL;
+ waiters_head_ = NULL;
+ waiters_tail_ = NULL;
} else if (current == waiters_head_) {
waiters_head_ = waiters_head_->next_;
} else if (current == waiters_tail_) {
@@ -319,7 +322,8 @@
if (first != NULL) {
// Remove from list.
if (waiters_head_ == waiters_tail_) {
- waiters_tail_ = waiters_head_ = NULL;
+ waiters_tail_ = NULL;
+ waiters_head_ = NULL;
} else {
waiters_head_ = waiters_head_->next_;
}
@@ -340,7 +344,8 @@
// Extract list to signal.
MonitorWaitData* current = waiters_head_;
// Clear list.
- waiters_head_ = waiters_tail_ = NULL;
+ waiters_head_ = NULL;
+ waiters_tail_ = NULL;
// Iterate and signal all events.
while (current != NULL) {
// Copy next.
diff --git a/runtime/bin/utils.h b/runtime/bin/utils.h
index cbc2bab..ab02ebe 100644
--- a/runtime/bin/utils.h
+++ b/runtime/bin/utils.h
@@ -83,6 +83,10 @@
static char* Utf8ToConsoleString(char* utf8,
intptr_t len = -1,
intptr_t* result_len = NULL);
+
+ private:
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StringUtils);
};
@@ -94,14 +98,23 @@
// Returns true if the arguments are converted. In that case
// each of the arguments need to be deallocated using free.
static bool GetUtf8Argv(int argc, char** argv);
+
+ private:
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ShellUtils);
};
+
class TimerUtils {
public:
static void InitOnce();
static int64_t GetCurrentMonotonicMicros();
static int64_t GetCurrentMonotonicMillis();
static void Sleep(int64_t millis);
+
+ private:
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(TimerUtils);
};
} // namespace bin
diff --git a/runtime/bin/utils_android.cc b/runtime/bin/utils_android.cc
index e36ac11..c7a4d63 100644
--- a/runtime/bin/utils_android.cc
+++ b/runtime/bin/utils_android.cc
@@ -14,7 +14,6 @@
#include "platform/assert.h"
#include "platform/utils.h"
-
namespace dart {
namespace bin {
@@ -43,41 +42,49 @@
}
}
+
const char* StringUtils::ConsoleStringToUtf8(
const char* str, intptr_t len, intptr_t* result_len) {
UNIMPLEMENTED();
return NULL;
}
+
const char* StringUtils::Utf8ToConsoleString(
const char* utf8, intptr_t len, intptr_t* result_len) {
UNIMPLEMENTED();
return NULL;
}
+
char* StringUtils::ConsoleStringToUtf8(
char* str, intptr_t len, intptr_t* result_len) {
UNIMPLEMENTED();
return NULL;
}
+
char* StringUtils::Utf8ToConsoleString(
char* utf8, intptr_t len, intptr_t* result_len) {
UNIMPLEMENTED();
return NULL;
}
+
bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
return false;
}
+
void TimerUtils::InitOnce() {
}
+
int64_t TimerUtils::GetCurrentMonotonicMillis() {
return GetCurrentMonotonicMicros() / 1000;
}
+
int64_t TimerUtils::GetCurrentMonotonicMicros() {
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
@@ -91,6 +98,7 @@
return result;
}
+
void TimerUtils::Sleep(int64_t millis) {
struct timespec req; // requested.
struct timespec rem; // remainder.
diff --git a/runtime/bin/utils_linux.cc b/runtime/bin/utils_linux.cc
index ea6ef8c..2029071 100644
--- a/runtime/bin/utils_linux.cc
+++ b/runtime/bin/utils_linux.cc
@@ -14,7 +14,6 @@
#include "platform/assert.h"
#include "platform/utils.h"
-
namespace dart {
namespace bin {
@@ -41,41 +40,49 @@
}
}
+
const char* StringUtils::ConsoleStringToUtf8(
const char* str, intptr_t len, intptr_t* result_len) {
UNIMPLEMENTED();
return NULL;
}
+
const char* StringUtils::Utf8ToConsoleString(
const char* utf8, intptr_t len, intptr_t* result_len) {
UNIMPLEMENTED();
return NULL;
}
+
char* StringUtils::ConsoleStringToUtf8(
char* str, intptr_t len, intptr_t* result_len) {
UNIMPLEMENTED();
return NULL;
}
+
char* StringUtils::Utf8ToConsoleString(
char* utf8, intptr_t len, intptr_t* result_len) {
UNIMPLEMENTED();
return NULL;
}
+
bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
return false;
}
+
void TimerUtils::InitOnce() {
}
+
int64_t TimerUtils::GetCurrentMonotonicMillis() {
return GetCurrentMonotonicMicros() / 1000;
}
+
int64_t TimerUtils::GetCurrentMonotonicMicros() {
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
@@ -89,6 +96,7 @@
return result;
}
+
void TimerUtils::Sleep(int64_t millis) {
struct timespec req; // requested.
struct timespec rem; // remainder.
diff --git a/runtime/bin/utils_macos.cc b/runtime/bin/utils_macos.cc
index eea4cb7..136881d 100644
--- a/runtime/bin/utils_macos.cc
+++ b/runtime/bin/utils_macos.cc
@@ -6,22 +6,20 @@
#if defined(TARGET_OS_MACOS)
#include <errno.h> // NOLINT
-#include <netdb.h> // NOLINT
-#include <mach/mach.h> // NOLINT
#include <mach/clock.h> // NOLINT
+#include <mach/mach.h> // NOLINT
#include <mach/mach_time.h> // NOLINT
-#include <sys/time.h> // NOLINT
-#include <time.h> // NOLINT
-
+#include <netdb.h> // NOLINT
#if TARGET_OS_IOS
#include <sys/sysctl.h> // NOLINT
#endif
+#include <sys/time.h> // NOLINT
+#include <time.h> // NOLINT
#include "bin/utils.h"
#include "platform/assert.h"
#include "platform/utils.h"
-
namespace dart {
namespace bin {
@@ -50,47 +48,55 @@
}
}
+
const char* StringUtils::ConsoleStringToUtf8(
const char* str, intptr_t len, intptr_t* result_len) {
UNIMPLEMENTED();
return NULL;
}
+
const char* StringUtils::Utf8ToConsoleString(
const char* utf8, intptr_t len, intptr_t* result_len) {
UNIMPLEMENTED();
return NULL;
}
+
char* StringUtils::ConsoleStringToUtf8(
char* str, intptr_t len, intptr_t* result_len) {
UNIMPLEMENTED();
return NULL;
}
+
char* StringUtils::Utf8ToConsoleString(
char* utf8, intptr_t len, intptr_t* result_len) {
UNIMPLEMENTED();
return NULL;
}
+
bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
return false;
}
+
static mach_timebase_info_data_t timebase_info;
+
void TimerUtils::InitOnce() {
kern_return_t kr = mach_timebase_info(&timebase_info);
ASSERT(KERN_SUCCESS == kr);
}
+
int64_t TimerUtils::GetCurrentMonotonicMillis() {
return GetCurrentMonotonicMicros() / 1000;
}
-#if TARGET_OS_IOS
+#if TARGET_OS_IOS
static int64_t GetCurrentTimeMicros() {
// gettimeofday has microsecond resolution.
struct timeval tv;
@@ -100,9 +106,9 @@
}
return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec;
}
-
#endif // TARGET_OS_IOS
+
int64_t TimerUtils::GetCurrentMonotonicMicros() {
#if TARGET_OS_IOS
// On iOS mach_absolute_time stops while the device is sleeping. Instead use
@@ -129,6 +135,7 @@
#endif // TARGET_OS_IOS
}
+
void TimerUtils::Sleep(int64_t millis) {
struct timespec req; // requested.
struct timespec rem; // remainder.
diff --git a/runtime/bin/utils_win.cc b/runtime/bin/utils_win.cc
index 227cc24..7e3cfb6 100644
--- a/runtime/bin/utils_win.cc
+++ b/runtime/bin/utils_win.cc
@@ -8,12 +8,11 @@
#include <errno.h> // NOLINT
#include <time.h> // NOLINT
+#include "bin/log.h"
#include "bin/utils.h"
#include "bin/utils_win.h"
-#include "bin/log.h"
#include "platform/assert.h"
-
namespace dart {
namespace bin {
@@ -185,20 +184,22 @@
}
+// Although win32 uses 64-bit integers for representing timestamps,
+// these are packed into a FILETIME structure. The FILETIME
+// structure is just a struct representing a 64-bit integer. The
+// TimeStamp union allows access to both a FILETIME and an integer
+// representation of the timestamp. The Windows timestamp is in
+// 100-nanosecond intervals since January 1, 1601.
+union TimeStamp {
+ FILETIME ft_;
+ int64_t t_;
+};
+
+
static int64_t GetCurrentTimeMicros() {
static const int64_t kTimeEpoc = 116444736000000000LL;
static const int64_t kTimeScaler = 10; // 100 ns to us.
- // Although win32 uses 64-bit integers for representing timestamps,
- // these are packed into a FILETIME structure. The FILETIME
- // structure is just a struct representing a 64-bit integer. The
- // TimeStamp union allows access to both a FILETIME and an integer
- // representation of the timestamp. The Windows timestamp is in
- // 100-nanosecond intervals since January 1, 1601.
- union TimeStamp {
- FILETIME ft_;
- int64_t t_;
- };
TimeStamp time;
GetSystemTimeAsFileTime(&time.ft_);
return (time.t_ - kTimeEpoc) / kTimeScaler;
diff --git a/runtime/bin/utils_win.h b/runtime/bin/utils_win.h
index b8f9fbc..fe0fa5c 100644
--- a/runtime/bin/utils_win.h
+++ b/runtime/bin/utils_win.h
@@ -31,6 +31,10 @@
static const wchar_t* Utf8ToWide(const char* utf8,
intptr_t len = -1,
intptr_t* result_len = NULL);
+
+ private:
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StringUtilsWin);
};
} // namespace bin
diff --git a/runtime/bin/vmservice_dartium.cc b/runtime/bin/vmservice_dartium.cc
index 2a9fc8f..535fb41 100644
--- a/runtime/bin/vmservice_dartium.cc
+++ b/runtime/bin/vmservice_dartium.cc
@@ -148,6 +148,7 @@
inflateEnd(&strm);
}
+
/* DISALLOW_ALLOCATION */
void VmServiceServer::operator delete(void* pointer) {
fprintf(stderr, "unreachable code\n");
diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc
index 08fd57a..2736408 100644
--- a/runtime/bin/vmservice_impl.cc
+++ b/runtime/bin/vmservice_impl.cc
@@ -120,6 +120,7 @@
// NO-OP.
}
+
struct VmServiceIONativeEntry {
const char* name;
int num_arguments;
@@ -271,7 +272,7 @@
const char* VmService::GetErrorMessage() {
- return error_msg_ == NULL ? "No error." : error_msg_;
+ return (error_msg_ == NULL) ? "No error." : error_msg_;
}
diff --git a/runtime/bin/vmservice_impl.h b/runtime/bin/vmservice_impl.h
index 1780013..f373b4b 100644
--- a/runtime/bin/vmservice_impl.h
+++ b/runtime/bin/vmservice_impl.h
@@ -55,7 +55,6 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(VmService);
};
-
} // namespace bin
} // namespace dart
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 77d1289..6665e0a 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -721,6 +721,15 @@
typedef void (*Dart_IsolateShutdownCallback)(void* callback_data);
/**
+ * A thread death callback function.
+ * This callback, provided by the embedder, is called before a thread in the
+ * vm thread pool exits.
+ * This function could be used to dispose of native resources that
+ * are associated and attached to the thread, in order to avoid leaks.
+ */
+typedef void (*Dart_ThreadExitCallback)();
+
+/**
* Callbacks provided by the embedder for file operations. If the
* embedder does not allow file operations these callbacks can be
* NULL.
@@ -802,6 +811,7 @@
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,
diff --git a/runtime/include/dart_tools_api.h b/runtime/include/dart_tools_api.h
index 8b9b013..c880e17 100644
--- a/runtime/include/dart_tools_api.h
+++ b/runtime/include/dart_tools_api.h
@@ -902,37 +902,26 @@
#define DART_TIMELINE_STREAM_GC (1 << 5)
/** Timeline stream for isolate events */
#define DART_TIMELINE_STREAM_ISOLATE (1 << 6)
-
/** Timeline stream for VM events */
#define DART_TIMELINE_STREAM_VM (1 << 7)
-/** Enable all timeline stream recording for an isolate */
+/** All timeline streams */
#define DART_TIMELINE_STREAM_ALL (DART_TIMELINE_STREAM_API | \
DART_TIMELINE_STREAM_COMPILER | \
DART_TIMELINE_STREAM_DART | \
DART_TIMELINE_STREAM_DEBUGGER | \
DART_TIMELINE_STREAM_EMBEDDER | \
DART_TIMELINE_STREAM_GC | \
- DART_TIMELINE_STREAM_ISOLATE)
+ DART_TIMELINE_STREAM_ISOLATE | \
+ DART_TIMELINE_STREAM_VM)
/** Disable all timeline stream recording */
#define DART_TIMELINE_STREAM_DISABLE 0
-/**
- * Start recording timeline events for the current isolate.
- *
- * \param stream_mask A bitmask of streams that should be recorded.
- *
- * NOTE: Calling with 0 disables recording of all streams.
- */
-DART_EXPORT void Dart_TimelineSetRecordedStreams(int64_t stream_mask);
-
/**
* Start recording timeline events for the entire VM (including all isolates).
*
- * NOTE: When enabled, the global flag, will override the per-isolate flag.
- *
* \param stream_mask A bitmask of streams that should be recorded.
*
* NOTE: Calling with 0 disables recording of all streams.
@@ -977,20 +966,6 @@
intptr_t buffer_length,
void* stream_callback_data);
-
-/**
- * Get the timeline for the current isolate in trace-event format
- *
- * \param consumer A Dart_StreamConsumer.
- * \param user_data User data passed into consumer.
- *
- * NOTE: The trace-event format is documented here: https://goo.gl/hDZw5M
- *
- * \return True if a stream was output.
- */
-DART_EXPORT bool Dart_TimelineGetTrace(Dart_StreamConsumer consumer,
- void* user_data);
-
/**
* Get the timeline for entire VM (including all isolates).
*
@@ -1007,8 +982,34 @@
DART_EXPORT bool Dart_GlobalTimelineGetTrace(Dart_StreamConsumer consumer,
void* user_data);
+typedef enum {
+ Dart_Timeline_Event_Begin, // Phase = 'B'.
+ Dart_Timeline_Event_End, // Phase = 'E'.
+ Dart_Timeline_Event_Instant, // Phase = 'i'.
+ Dart_Timeline_Event_Duration, // Phase = 'X'.
+} Dart_Timeline_Event_Type;
+
/**
- * Add a duration timeline event to the embedder stream for the current isolate.
+ * Add a timeline event to the embedder stream.
+ *
+ * \param label The name of the evnet.
+ * \param timestamp0 The first timestamp of the event.
+ * \param timestamp1_or_async_id The second timestamp of the event or
+ * the async id.
+ * \param argument_count The number of argument names and values.
+ * \param argument_names An array of names of the arguments.
+ * \param argument_values An array of values of the arguments.
+ */
+DART_EXPORT void Dart_TimelineEvent(const char* label,
+ int64_t timestamp0,
+ int64_t timestamp1_or_async_id,
+ Dart_Timeline_Event_Type type,
+ intptr_t argument_count,
+ const char** argument_names,
+ const char** argument_values);
+
+/**
+ * Add a duration timeline event to the embedder stream.
*
* \param label The name of the event.
* \param start_micros The start of the duration (in microseconds)
@@ -1016,112 +1017,81 @@
*
* NOTE: All timestamps should be acquired from Dart_TimelineGetMicros.
*/
-DART_EXPORT Dart_Handle Dart_TimelineDuration(const char* label,
- int64_t start_micros,
- int64_t end_micros);
+DART_EXPORT void Dart_TimelineDuration(const char* label,
+ int64_t start_micros,
+ int64_t end_micros);
/**
- * Add an instant timeline event to the embedder stream for the current isolate.
+ * Add an instant timeline event to the embedder stream.
*
* \param label The name of event.
*
* NOTE: All timestamps should be acquired from Dart_TimelineGetMicros.
*/
-DART_EXPORT Dart_Handle Dart_TimelineInstant(const char* label);
+DART_EXPORT void Dart_TimelineInstant(const char* label);
/**
- * Adds an asynchronous begin timeline event to the embedder stream for the
- * current isolate.
+ * Adds an asynchronous begin timeline event to the embedder stream.
*
* \param label The name of event.
- *
- * \return Returns an asynchronous id that must be passed to
- * Dart_TimelineAsyncInstant and Dart_TimelineAsyncEnd. If the asynchronous
- * id is less than 0 the event was not added to the timeline and subsequent
- * calls to Dart_TimelineAsyncInstant and Dart_TimelineAsyncEnd will become
- * no-ops.
+ * \param async_id Pointer that receives the asynchronous id for this async
+ * operation. If it is less than 0 the event was not added to the timeline.
*
* NOTE: All timestamps should be acquired from Dart_TimelineGetMicros.
*/
-DART_EXPORT Dart_Handle Dart_TimelineAsyncBegin(const char* label,
- int64_t* async_id);
+DART_EXPORT void Dart_TimelineAsyncBegin(const char* label,
+ int64_t* async_id);
/**
- * Adds an asynchronous instant timeline event to the embedder stream for the
- * current isolate.
+ * Adds an asynchronous instant timeline event to the embedder stream.
*
* \param label The name of event.
- *
- * \return Returns an asynchronous id that must be passed to
- * Dart_TimelineAsyncInstant and Dart_TimelineAsyncEnd.
+ * \param async_id the asynchronous id received by Dart_TimelineAsyncBegin.
*
* NOTE: All timestamps should be acquired from Dart_TimelineGetMicros.
*/
-DART_EXPORT Dart_Handle Dart_TimelineAsyncInstant(const char* label,
- int64_t async_id);
+DART_EXPORT void Dart_TimelineAsyncInstant(const char* label,
+ int64_t async_id);
/**
- * Adds an asynchronous end timeline event to the embedder stream for the
- * current isolate.
+ * Adds an asynchronous end timeline event to the embedder stream.
*
* \param label The name of event.
- *
- * \return Returns an asynchronous id that must be passed to
- * Dart_TimelineAsyncInstant and Dart_TimelineAsyncEnd.
+ * \param async_id the asynchronous id received by Dart_TimelineAsyncBegin.
*
* NOTE: All timestamps should be acquired from Dart_TimelineGetMicros.
*/
-DART_EXPORT Dart_Handle Dart_TimelineAsyncEnd(const char* label,
- int64_t async_id);
+DART_EXPORT void Dart_TimelineAsyncEnd(const char* label,
+ int64_t async_id);
/**
- * Called by the VM to let the embedder know when to start recording into their
- * own timeline implementation. Can be called from any thread.
+ * Called by the VM to let the embedder know when to start recording into the
+ * timeline. Can be called from any thread.
*/
typedef void (*Dart_EmbedderTimelineStartRecording)();
/**
- * Called by the VM to let the embedder know when to stop recording into their
- * own timeline implementation. Can be called from any thread.
+ * Called by the VM to let the embedder know when to stop recording into the
+ * timeline. Can be called from any thread.
*/
typedef void (*Dart_EmbedderTimelineStopRecording)();
/**
- * Called by the VM to request data from the embedder's private timeline
- * implementation. Can be called from any thread and must complete
- * synchronously.
- *
- * \param stream_consumer The embedder must only call the stream_consumer with
- * the Dart_StreamConsumer_kData state. See Dart_StreamConsumer above.
- * \param user_data
- *
- * \return Returns true on success.
- *
- */
-typedef bool (*Dart_EmbedderTimelineGetTimeline)(
- Dart_StreamConsumer stream_consumer,
- void* user_data);
-
-
-/**
* Sets the embedder timeline callbacks. These callbacks are used by the VM
- * to notify the embedder of timeline recording state changes and to request
- * data from the embedder.
+ * to notify the embedder of timeline recording state changes.
*
* \param start_recording See Dart_EmbedderTimelineStartRecording.
* \param stop_recording See Dart_EmbedderTimelineStopRecording.
- * \param get_timeline See Dart_EmbedderTimelineGetTimeline.
*
* NOTE: To avoid races, this should be called before Dart_Initialize.
*/
DART_EXPORT void Dart_SetEmbedderTimelineCallbacks(
Dart_EmbedderTimelineStartRecording start_recording,
- Dart_EmbedderTimelineStopRecording stop_recording,
- Dart_EmbedderTimelineGetTimeline get_timeline);
+ Dart_EmbedderTimelineStopRecording stop_recording);
#endif // INCLUDE_DART_TOOLS_API_H_
diff --git a/runtime/lib/bool_patch.dart b/runtime/lib/bool_patch.dart
index 8259f2e..274b153 100644
--- a/runtime/lib/bool_patch.dart
+++ b/runtime/lib/bool_patch.dart
@@ -13,4 +13,5 @@
int get _identityHashCode {
return this ? 1231 : 1237;
}
+ int get hashCode => _identityHashCode;
}
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index 9192b28..45500d6 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -410,9 +410,8 @@
throw new UnsupportedError(
"_Smi can only be allocated by the VM");
}
- int get _identityHashCode {
- return this;
- }
+ int get _identityHashCode => this;
+ int get hashCode => this;
int operator ~() native "Smi_bitNegate";
int get bitLength native "Smi_bitLength";
@@ -608,9 +607,8 @@
throw new UnsupportedError(
"_Mint can only be allocated by the VM");
}
- int get _identityHashCode {
- return this;
- }
+ int get _identityHashCode => this;
+ int get hashCode => this;
int operator ~() native "Mint_bitNegate";
int get bitLength native "Mint_bitLength";
diff --git a/runtime/lib/math.cc b/runtime/lib/math.cc
index d383471..8e5e750 100644
--- a/runtime/lib/math.cc
+++ b/runtime/lib/math.cc
@@ -205,7 +205,7 @@
const intptr_t n = count.Value();
ASSERT((n > 0) && (n <= 8));
uint8_t buffer[8];
- Dart_EntropySource entropy_source = isolate->entropy_source_callback();
+ Dart_EntropySource entropy_source = Dart::entropy_source_callback();
if ((entropy_source == NULL) || !entropy_source(buffer, n)) {
const String& error = String::Handle(String::New(
"No source of cryptographically secure random numbers available."));
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index aaa28e1..d24f75c 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -253,8 +253,8 @@
static RawInstance* CreateFunctionTypeMirror(const AbstractType& type) {
ASSERT(type.IsFunctionType());
- const Class& cls = Class::Handle(FunctionType::Cast(type).scope_class());
- const Function& func = Function::Handle(FunctionType::Cast(type).signature());
+ const Class& cls = Class::Handle(Type::Cast(type).type_class());
+ const Function& func = Function::Handle(Type::Cast(type).signature());
const Array& args = Array::Handle(Array::New(3));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
args.SetAt(1, MirrorReference::Handle(MirrorReference::New(func)));
@@ -543,8 +543,7 @@
ASSERT(type.IsCanonical() || type.IsTypeParameter() || type.IsBoundedType());
if (type.IsFunctionType()) {
- const Class& scope_class =
- Class::Handle(FunctionType::Cast(type).scope_class());
+ const Class& scope_class = Class::Handle(Type::Cast(type).type_class());
if (scope_class.IsTypedefClass()) {
return CreateTypedefMirror(scope_class,
type, Bool::False(), Object::null_instance());
@@ -826,7 +825,7 @@
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, type, arguments->NativeArgAt(0));
PROPAGATE_IF_MALFORMED(type);
ASSERT(type.IsFinalized());
- ASSERT(type.IsFunctionType() || type.HasResolvedTypeClass());
+ ASSERT(type.HasResolvedTypeClass());
const Class& cls = Class::Handle(type.type_class());
ASSERT(!cls.IsNull());
if (cls.IsDynamicClass() || cls.IsVoidClass() || cls.IsTypedefClass()) {
@@ -1285,8 +1284,9 @@
}
DEFINE_NATIVE_ENTRY(TypedefMirror_declaration, 1) {
- GET_NON_NULL_NATIVE_ARGUMENT(FunctionType, type, arguments->NativeArgAt(0));
- const Class& cls = Class::Handle(type.scope_class());
+ GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
+ ASSERT(type.IsFunctionType());
+ const Class& cls = Class::Handle(type.type_class());
ASSERT(cls.IsTypedefClass());
return CreateTypedefMirror(cls,
AbstractType::Handle(cls.DeclarationType()),
@@ -2043,20 +2043,21 @@
DEFINE_NATIVE_ENTRY(TypedefMirror_referent, 1) {
- GET_NON_NULL_NATIVE_ARGUMENT(FunctionType, type, arguments->NativeArgAt(0));
- const Class& cls = Class::Handle(type.scope_class());
+ GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
+ ASSERT(type.IsFunctionType());
+ const Class& cls = Class::Handle(type.type_class());
ASSERT(cls.IsTypedefClass());
const Function& sig_func = Function::Handle(cls.signature_function());
- FunctionType& referent_type = FunctionType::Handle(sig_func.SignatureType());
+ Type& referent_type = Type::Handle(sig_func.SignatureType());
// If the scope class of the function type is not generic, replace it with
// Closure class (Function::SignatureType() keeps it).
- ASSERT(cls.raw() == referent_type.scope_class());
+ ASSERT(cls.raw() == referent_type.type_class());
if (!cls.IsGeneric()) {
- referent_type = FunctionType::New(
+ referent_type = Type::New(
Class::Handle(Isolate::Current()->object_store()->closure_class()),
TypeArguments::Handle(referent_type.arguments()),
- sig_func,
referent_type.token_pos());
+ referent_type.set_signature(sig_func);
referent_type ^= ClassFinalizer::FinalizeType(
cls, referent_type, ClassFinalizer::kCanonicalize);
}
diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc
index e3907d3..9e9bcea 100644
--- a/runtime/lib/regexp.cc
+++ b/runtime/lib/regexp.cc
@@ -17,7 +17,7 @@
DECLARE_FLAG(bool, trace_irregexp);
-DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_factory, 4) {
+DEFINE_NATIVE_ENTRY(RegExp_factory, 4) {
ASSERT(TypeArguments::CheckedHandle(arguments->NativeArgAt(0)).IsNull());
GET_NON_NULL_NATIVE_ARGUMENT(String, pattern, arguments->NativeArgAt(1));
GET_NON_NULL_NATIVE_ARGUMENT(
@@ -35,37 +35,37 @@
UNREACHABLE();
}
- // Create a JSRegExp object containing only the initial parameters.
- return RegExpEngine::CreateJSRegExp(zone,
- pattern,
- multi_line,
- ignore_case);
+ // Create a RegExp object containing only the initial parameters.
+ return RegExpEngine::CreateRegExp(zone,
+ pattern,
+ multi_line,
+ ignore_case);
}
-DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_getPattern, 1) {
- const JSRegExp& regexp = JSRegExp::CheckedHandle(arguments->NativeArgAt(0));
+DEFINE_NATIVE_ENTRY(RegExp_getPattern, 1) {
+ const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
ASSERT(!regexp.IsNull());
return regexp.pattern();
}
-DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_getIsMultiLine, 1) {
- const JSRegExp& regexp = JSRegExp::CheckedHandle(arguments->NativeArgAt(0));
+DEFINE_NATIVE_ENTRY(RegExp_getIsMultiLine, 1) {
+ const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
ASSERT(!regexp.IsNull());
return Bool::Get(regexp.is_multi_line()).raw();
}
-DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_getIsCaseSensitive, 1) {
- const JSRegExp& regexp = JSRegExp::CheckedHandle(arguments->NativeArgAt(0));
+DEFINE_NATIVE_ENTRY(RegExp_getIsCaseSensitive, 1) {
+ const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
ASSERT(!regexp.IsNull());
return Bool::Get(!regexp.is_ignore_case()).raw();
}
-DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_getGroupCount, 1) {
- const JSRegExp& regexp = JSRegExp::CheckedHandle(arguments->NativeArgAt(0));
+DEFINE_NATIVE_ENTRY(RegExp_getGroupCount, 1) {
+ const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
ASSERT(!regexp.IsNull());
if (regexp.is_initialized()) {
return regexp.num_bracket_expressions();
@@ -81,9 +81,9 @@
}
-DEFINE_NATIVE_ENTRY(JSSyntaxRegExp_ExecuteMatch, 3) {
- // This function is intrinsified. See Intrinsifier::JSRegExp_ExecuteMatch.
- const JSRegExp& regexp = JSRegExp::CheckedHandle(arguments->NativeArgAt(0));
+DEFINE_NATIVE_ENTRY(RegExp_ExecuteMatch, 3) {
+ // This function is intrinsified. See Intrinsifier::RegExp_ExecuteMatch.
+ const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
ASSERT(!regexp.IsNull());
GET_NON_NULL_NATIVE_ARGUMENT(String, subject, arguments->NativeArgAt(1));
GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_index, arguments->NativeArgAt(2));
diff --git a/runtime/lib/regexp_patch.dart b/runtime/lib/regexp_patch.dart
index 118b875..d8e622a 100644
--- a/runtime/lib/regexp_patch.dart
+++ b/runtime/lib/regexp_patch.dart
@@ -8,19 +8,19 @@
/* patch */ factory RegExp(String source,
{bool multiLine: false,
bool caseSensitive: true}) {
- _JSSyntaxRegExpHashKey key = new _JSSyntaxRegExpHashKey(
+ _RegExpHashKey key = new _RegExpHashKey(
source, multiLine, caseSensitive);
- _JSSyntaxRegExpHashValue value = _cache[key];
+ _RegExpHashValue value = _cache[key];
if (value == null) {
if (_cache.length > _MAX_CACHE_SIZE) {
- _JSSyntaxRegExpHashKey lastKey = _recentlyUsed.last;
+ _RegExpHashKey lastKey = _recentlyUsed.last;
lastKey.unlink();
_cache.remove(lastKey);
}
- value = new _JSSyntaxRegExpHashValue(
- new _JSSyntaxRegExp(source,
+ value = new _RegExpHashValue(
+ new _RegExp(source,
multiLine: multiLine,
caseSensitive: caseSensitive),
key);
@@ -47,24 +47,24 @@
// TODO(zerny): Use self-sizing cache similar to _AccessorCache in
// mirrors_impl.dart.
static const int _MAX_CACHE_SIZE = 256;
- static final Map<_JSSyntaxRegExpHashKey, _JSSyntaxRegExpHashValue> _cache =
- new HashMap<_JSSyntaxRegExpHashKey, _JSSyntaxRegExpHashValue>();
- static final LinkedList<_JSSyntaxRegExpHashKey> _recentlyUsed =
- new LinkedList<_JSSyntaxRegExpHashKey>();
+ static final Map<_RegExpHashKey, _RegExpHashValue> _cache =
+ new HashMap<_RegExpHashKey, _RegExpHashValue>();
+ static final LinkedList<_RegExpHashKey> _recentlyUsed =
+ new LinkedList<_RegExpHashKey>();
}
// Represents both a key in the regular expression cache as well as its
// corresponding entry in the LRU list.
-class _JSSyntaxRegExpHashKey extends LinkedListEntry<_JSSyntaxRegExpHashKey> {
+class _RegExpHashKey extends LinkedListEntry<_RegExpHashKey> {
final String pattern;
final bool multiLine;
final bool caseSensitive;
- _JSSyntaxRegExpHashKey(this.pattern, this.multiLine, this.caseSensitive);
+ _RegExpHashKey(this.pattern, this.multiLine, this.caseSensitive);
int get hashCode => pattern.hashCode;
- bool operator==(_JSSyntaxRegExpHashKey that) {
+ bool operator==(_RegExpHashKey that) {
return (this.pattern == that.pattern) &&
(this.multiLine == that.multiLine) &&
(this.caseSensitive == that.caseSensitive);
@@ -74,16 +74,16 @@
// Represents a value in the regular expression cache. Contains a pointer
// back to the key in order to access the corresponding LRU entry.
-class _JSSyntaxRegExpHashValue {
- final _JSSyntaxRegExp regexp;
- final _JSSyntaxRegExpHashKey key;
+class _RegExpHashValue {
+ final _RegExp regexp;
+ final _RegExpHashKey key;
- _JSSyntaxRegExpHashValue(this.regexp, this.key);
+ _RegExpHashValue(this.regexp, this.key);
}
-class _JSRegExpMatch implements Match {
- _JSRegExpMatch(this._regexp, this.input, this._match);
+class _RegExpMatch implements Match {
+ _RegExpMatch(this._regexp, this.input, this._match);
int get start => _start(0);
int get end => _end(0);
@@ -132,11 +132,11 @@
}
-class _JSSyntaxRegExp implements RegExp {
- factory _JSSyntaxRegExp(
+class _RegExp implements RegExp {
+ factory _RegExp(
String pattern,
{bool multiLine: false,
- bool caseSensitive: true}) native "JSSyntaxRegExp_factory";
+ bool caseSensitive: true}) native "RegExp_factory";
Match firstMatch(String str) {
if (str is! String) throw new ArgumentError(str);
@@ -144,7 +144,7 @@
if (match == null) {
return null;
}
- return new _JSRegExpMatch(this, str, match);
+ return new _RegExpMatch(this, str, match);
}
Iterable<Match> allMatches(String string, [int start = 0]) {
@@ -167,7 +167,7 @@
List<int> list = _ExecuteMatch(string, start);
if (list == null) return null;
if (list[0] != start) return null;
- return new _JSRegExpMatch(this, string, list);
+ return new _RegExpMatch(this, string, list);
}
bool hasMatch(String str) {
@@ -185,13 +185,13 @@
return str._substringUnchecked(match[0], match[1]);
}
- String get pattern native "JSSyntaxRegExp_getPattern";
+ String get pattern native "RegExp_getPattern";
- bool get isMultiLine native "JSSyntaxRegExp_getIsMultiLine";
+ bool get isMultiLine native "RegExp_getIsMultiLine";
- bool get isCaseSensitive native "JSSyntaxRegExp_getIsCaseSensitive";
+ bool get isCaseSensitive native "RegExp_getIsCaseSensitive";
- int get _groupCount native "JSSyntaxRegExp_getGroupCount";
+ int get _groupCount native "RegExp_getGroupCount";
// Byte map of one byte characters with a 0xff if the character is a word
// character (digit, letter or underscore) and 0x00 otherwise.
@@ -239,11 +239,11 @@
];
List _ExecuteMatch(String str, int start_index)
- native "JSSyntaxRegExp_ExecuteMatch";
+ native "RegExp_ExecuteMatch";
}
class _AllMatchesIterable extends IterableBase<Match> {
- final _JSSyntaxRegExp _re;
+ final _RegExp _re;
final String _str;
final int _start;
@@ -255,7 +255,7 @@
class _AllMatchesIterator implements Iterator<Match> {
final String _str;
int _nextIndex;
- _JSSyntaxRegExp _re;
+ _RegExp _re;
Match _current;
_AllMatchesIterator(this._re, this._str, this._nextIndex);
@@ -267,7 +267,7 @@
if (_nextIndex <= _str.length) {
var match = _re._ExecuteMatch(_str, _nextIndex);
if (match != null) {
- _current = new _JSRegExpMatch(_re, _str, match);
+ _current = new _RegExpMatch(_re, _str, match);
_nextIndex = _current.end;
if (_nextIndex == _current.start) {
// Zero-width match. Advance by one more.
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart
index eb1a2a2..cdb94be 100644
--- a/runtime/lib/string_patch.dart
+++ b/runtime/lib/string_patch.dart
@@ -801,6 +801,7 @@
// Convert single object to string.
static String _interpolateSingle(Object o) {
+ if (o is String) return o;
final s = o.toString();
if (s is! String) {
throw new ArgumentError(s);
diff --git a/runtime/lib/timeline.cc b/runtime/lib/timeline.cc
index ddc2f5a..df36a25 100644
--- a/runtime/lib/timeline.cc
+++ b/runtime/lib/timeline.cc
@@ -53,7 +53,7 @@
return Object::null();
}
- TimelineEvent* event = isolate->GetDartStream()->StartEvent();
+ TimelineEvent* event = Timeline::GetDartStream()->StartEvent();
if (event == NULL) {
// Stream was turned off.
return Object::null();
@@ -118,7 +118,7 @@
return Object::null();
}
- TimelineEvent* event = isolate->GetDartStream()->StartEvent();
+ TimelineEvent* event = Timeline::GetDartStream()->StartEvent();
if (event == NULL) {
// Stream was turned off.
return Object::null();
@@ -163,7 +163,7 @@
return Object::null();
}
- TimelineEvent* event = isolate->GetDartStream()->StartEvent();
+ TimelineEvent* event = Timeline::GetDartStream()->StartEvent();
if (event == NULL) {
// Stream was turned off.
return Object::null();
diff --git a/runtime/lib/type_patch.dart b/runtime/lib/type_patch.dart
index 5d0f305..67d7db5 100644
--- a/runtime/lib/type_patch.dart
+++ b/runtime/lib/type_patch.dart
@@ -13,10 +13,6 @@
class _Type extends _AbstractType {
}
-// Equivalent of RawFunctionType.
-class _FunctionType extends _AbstractType {
-}
-
// Equivalent of RawTypeRef.
class _TypeRef extends _AbstractType {
}
diff --git a/runtime/lib/typed_data.dart b/runtime/lib/typed_data.dart
index 3abb630..c4b532f 100644
--- a/runtime/lib/typed_data.dart
+++ b/runtime/lib/typed_data.dart
@@ -2,233 +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.
-// patch classes for Int8List ..... Float64List and ByteData implementations.
+library dart.typed_data;
import "dart:_internal";
+import "dart:collection" show ListBase;
import 'dart:math' show Random;
-patch class Int8List {
- /* patch */ factory Int8List(int length) {
- return new _Int8Array(length);
- }
+/**
+ * A typed view of a sequence of bytes.
+ */
+abstract class TypedData {
+ /**
+ * Returns the number of bytes in the representation of each element in this
+ * list.
+ */
+ int get elementSizeInBytes;
- /* patch */ factory Int8List.fromList(List<int> elements) {
- return new _Int8Array(elements.length)
- ..setRange(0, elements.length, elements);
- }
+ /**
+ * Returns the offset in bytes into the underlying byte buffer of this view.
+ */
+ int get offsetInBytes;
+
+ /**
+ * Returns the length of this view, in bytes.
+ */
+ int get lengthInBytes;
+
+ /**
+ * Returns the byte buffer associated with this object.
+ */
+ ByteBuffer get buffer;
}
-patch class Uint8List {
- /* patch */ factory Uint8List(int length) {
- return new _Uint8Array(length);
- }
+/**
+ * Describes endianness to be used when accessing or updating a
+ * sequence of bytes.
+ */
+class Endianness {
+ const Endianness._(this._littleEndian);
- /* patch */ factory Uint8List.fromList(List<int> elements) {
- return new _Uint8Array(elements.length)
- ..setRange(0, elements.length, elements);
- }
+ static const Endianness BIG_ENDIAN = const Endianness._(false);
+ static const Endianness LITTLE_ENDIAN = const Endianness._(true);
+ static final Endianness HOST_ENDIAN =
+ (new ByteData.view(new Uint16List.fromList([1]).buffer)).getInt8(0) == 1 ?
+ LITTLE_ENDIAN : BIG_ENDIAN;
+
+ final bool _littleEndian;
}
-patch class Uint8ClampedList {
- /* patch */ factory Uint8ClampedList(int length) {
- return new _Uint8ClampedArray(length);
- }
-
- /* patch */ factory Uint8ClampedList.fromList(List<int> elements) {
- return new _Uint8ClampedArray(elements.length)
- ..setRange(0, elements.length, elements);
- }
-}
-
-
-patch class Int16List {
- /* patch */ factory Int16List(int length) {
- return new _Int16Array(length);
- }
-
- /* patch */ factory Int16List.fromList(List<int> elements) {
- return new _Int16Array(elements.length)
- ..setRange(0, elements.length, elements);
- }
-}
-
-
-patch class Uint16List {
- /* patch */ factory Uint16List(int length) {
- return new _Uint16Array(length);
- }
-
- /* patch */ factory Uint16List.fromList(List<int> elements) {
- return new _Uint16Array(elements.length)
- ..setRange(0, elements.length, elements);
- }
-}
-
-
-patch class Int32List {
- /* patch */ factory Int32List(int length) {
- return new _Int32Array(length);
- }
-
- /* patch */ factory Int32List.fromList(List<int> elements) {
- return new _Int32Array(elements.length)
- ..setRange(0, elements.length, elements);
- }
-}
-
-
-patch class Uint32List {
- /* patch */ factory Uint32List(int length) {
- return new _Uint32Array(length);
- }
-
- /* patch */ factory Uint32List.fromList(List<int> elements) {
- return new _Uint32Array(elements.length)
- ..setRange(0, elements.length, elements);
- }
-}
-
-
-patch class Int64List {
- /* patch */ factory Int64List(int length) {
- return new _Int64Array(length);
- }
-
- /* patch */ factory Int64List.fromList(List<int> elements) {
- return new _Int64Array(elements.length)
- ..setRange(0, elements.length, elements);
- }
-}
-
-
-patch class Uint64List {
- /* patch */ factory Uint64List(int length) {
- return new _Uint64Array(length);
- }
-
- /* patch */ factory Uint64List.fromList(List<int> elements) {
- return new _Uint64Array(elements.length)
- ..setRange(0, elements.length, elements);
- }
-}
-
-
-patch class Float32List {
- /* patch */ factory Float32List(int length) {
- return new _Float32Array(length);
- }
-
- /* patch */ factory Float32List.fromList(List<double> elements) {
- return new _Float32Array(elements.length)
- ..setRange(0, elements.length, elements);
- }
-}
-
-
-patch class Float64List {
- /* patch */ factory Float64List(int length) {
- return new _Float64Array(length);
- }
-
- /* patch */ factory Float64List.fromList(List<double> elements) {
- return new _Float64Array(elements.length)
- ..setRange(0, elements.length, elements);
- }
-}
-
-
-patch class Float32x4List {
- /* patch */ factory Float32x4List(int length) {
- return new _Float32x4Array(length);
- }
-
- /* patch */ factory Float32x4List.fromList(List<Float32x4> elements) {
- return new _Float32x4Array(elements.length)
- ..setRange(0, elements.length, elements);
- }
-}
-
-
-patch class Int32x4List {
- /* patch */ factory Int32x4List(int length) {
- return new _Int32x4Array(length);
- }
-
- /* patch */ factory Int32x4List.fromList(List<Int32x4> elements) {
- return new _Int32x4Array(elements.length)
- ..setRange(0, elements.length, elements);
- }
-
-}
-
-patch class Float64x2List {
- /* patch */ factory Float64x2List(int length) {
- return new _Float64x2Array(length);
- }
-
- /* patch */ factory Float64x2List.fromList(List<Float64x2> elements) {
- return new _Float64x2Array(elements.length)
- ..setRange(0, elements.length, elements);
- }
-}
-
-
-patch class Float32x4 {
- /* patch */ factory Float32x4(double x, double y, double z, double w) {
- return new _Float32x4(x, y, z, w);
- }
- /* patch */ factory Float32x4.splat(double v) {
- return new _Float32x4.splat(v);
- }
- /* patch */ factory Float32x4.zero() {
- return new _Float32x4.zero();
- }
- /* patch */ factory Float32x4.fromInt32x4Bits(Int32x4 x) {
- return new _Float32x4.fromInt32x4Bits(x);
- }
- /* patch */ factory Float32x4.fromFloat64x2(Float64x2 v) {
- return new _Float32x4.fromFloat64x2(v);
- }
-}
-
-
-patch class Int32x4 {
- /* patch */ factory Int32x4(int x, int y, int z, int w) {
- return new _Int32x4(x, y, z, w);
- }
- /* patch */ factory Int32x4.bool(bool x, bool y, bool z, bool w) {
- return new _Int32x4.bool(x, y, z, w);
- }
- /* patch */ factory Int32x4.fromFloat32x4Bits(Float32x4 x) {
- return new _Int32x4.fromFloat32x4Bits(x);
- }
-}
-
-
-patch class Float64x2 {
- /* patch */ factory Float64x2(double x, double y) {
- return new _Float64x2(x, y);
- }
-
- /* patch */ factory Float64x2.splat(double v) {
- return new _Float64x2.splat(v);
- }
-
- /* patch */ factory Float64x2.zero() {
- return new _Float64x2.zero();
- }
-
- /* patch */ factory Float64x2.fromFloat32x4(Float32x4 v) {
- return new _Float64x2.fromFloat32x4(v);
- }
-}
-
-
-patch class ByteData {
- /* patch */ factory ByteData(int length) {
- var list = new _Uint8Array(length);
+/**
+ * A fixed-length, random-access sequence of bytes that also provides random
+ * and unaligned access to the fixed-width integers and floating point
+ * numbers represented by those bytes.
+ *
+ * `ByteData` may be used to pack and unpack data from external sources
+ * (such as networks or files systems), and to process large quantities
+ * of numerical data more efficiently than would be possible
+ * with ordinary [List] implementations.
+ * `ByteData` can save space, by eliminating the need for object headers,
+ * and time, by eliminating the need for data copies.
+ * Finally, `ByteData` may be used to intentionally reinterpret the bytes
+ * representing one arithmetic type as another.
+ * For example this code fragment determine what 32-bit signed integer
+ * is represented by the bytes of a 32-bit floating point number:
+ *
+ * var buffer = new Uint8List(8).buffer;
+ * var bdata = new ByteData.view(buffer);
+ * bdata.setFloat32(0, 3.04);
+ * int huh = bdata.getInt32(0);
+ */
+class ByteData implements TypedData {
+ /**
+ * Creates a [ByteData] of the specified length (in elements), all of
+ * whose bytes are initially zero.
+ */
+ factory ByteData(int length) {
+ var list = new Uint8List(length);
return new _ByteDataView(list, 0, length);
}
@@ -236,6 +87,292 @@
factory ByteData._view(TypedData typedData, int offsetInBytes, int length) {
return new _ByteDataView(typedData, offsetInBytes, length);
}
+
+ /**
+ * Creates an [ByteData] _view_ of the specified region in [buffer].
+ *
+ * Changes in the [ByteData] will be visible in the byte
+ * buffer and vice versa.
+ * If the [offsetInBytes] index of the region is not specified,
+ * it defaults to zero (the first byte in the byte buffer).
+ * If the length is not specified, it defaults to `null`,
+ * which indicates that the view extends to the end of the byte buffer.
+ *
+ * Throws [RangeError] if [offsetInBytes] or [length] are negative, or
+ * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than
+ * the length of [buffer].
+ */
+ factory ByteData.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asByteData(offsetInBytes, length);
+ }
+
+ /**
+ * Returns the (possibly negative) integer represented by the byte at the
+ * specified [byteOffset] in this object, in two's complement binary
+ * representation.
+ *
+ * The return value will be between -128 and 127, inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * greater than or equal to the length of this object.
+ */
+ int getInt8(int byteOffset);
+
+ /**
+ * Sets the byte at the specified [byteOffset] in this object to the
+ * two's complement binary representation of the specified [value], which
+ * must fit in a single byte.
+ *
+ * In other words, [value] must be between -128 and 127, inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * greater than or equal to the length of this object.
+ */
+ void setInt8(int byteOffset, int value);
+
+ /**
+ * Returns the positive integer represented by the byte at the specified
+ * [byteOffset] in this object, in unsigned binary form.
+ *
+ * The return value will be between 0 and 255, inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * greater than or equal to the length of this object.
+ */
+ int getUint8(int byteOffset);
+
+ /**
+ * Sets the byte at the specified [byteOffset] in this object to the
+ * unsigned binary representation of the specified [value], which must fit
+ * in a single byte.
+ *
+ * In other words, [value] must be between 0 and 255, inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative,
+ * or greater than or equal to the length of this object.
+ */
+ void setUint8(int byteOffset, int value);
+
+ /**
+ * Returns the (possibly negative) integer represented by the two bytes at
+ * the specified [byteOffset] in this object, in two's complement binary
+ * form.
+ *
+ * The return value will be between 2<sup>15</sup> and 2<sup>15</sup> - 1,
+ * inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 2` is greater than the length of this object.
+ */
+ int getInt16(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Sets the two bytes starting at the specified [byteOffset] in this
+ * object to the two's complement binary representation of the specified
+ * [value], which must fit in two bytes.
+ *
+ * In other words, [value] must lie
+ * between 2<sup>15</sup> and 2<sup>15</sup> - 1, inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 2` is greater than the length of this object.
+ */
+ void setInt16(int byteOffset,
+ int value,
+ [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Returns the positive integer represented by the two bytes starting
+ * at the specified [byteOffset] in this object, in unsigned binary
+ * form.
+ *
+ * The return value will be between 0 and 2<sup>16</sup> - 1, inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 2` is greater than the length of this object.
+ */
+ int getUint16(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Sets the two bytes starting at the specified [byteOffset] in this object
+ * to the unsigned binary representation of the specified [value],
+ * which must fit in two bytes.
+ *
+ * In other words, [value] must be between
+ * 0 and 2<sup>16</sup> - 1, inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 2` is greater than the length of this object.
+ */
+ void setUint16(int byteOffset,
+ int value,
+ [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Returns the (possibly negative) integer represented by the four bytes at
+ * the specified [byteOffset] in this object, in two's complement binary
+ * form.
+ *
+ * The return value will be between 2<sup>31</sup> and 2<sup>31</sup> - 1,
+ * inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 4` is greater than the length of this object.
+ */
+ int getInt32(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Sets the four bytes starting at the specified [byteOffset] in this
+ * object to the two's complement binary representation of the specified
+ * [value], which must fit in four bytes.
+ *
+ * In other words, [value] must lie
+ * between 2<sup>31</sup> and 2<sup>31</sup> - 1, inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 4` is greater than the length of this object.
+ */
+ void setInt32(int byteOffset,
+ int value,
+ [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Returns the positive integer represented by the four bytes starting
+ * at the specified [byteOffset] in this object, in unsigned binary
+ * form.
+ *
+ * The return value will be between 0 and 2<sup>32</sup> - 1, inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 4` is greater than the length of this object.
+ */
+ int getUint32(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Sets the four bytes starting at the specified [byteOffset] in this object
+ * to the unsigned binary representation of the specified [value],
+ * which must fit in four bytes.
+ *
+ * In other words, [value] must be between
+ * 0 and 2<sup>32</sup> - 1, inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 4` is greater than the length of this object.
+ */
+ void setUint32(int byteOffset,
+ int value,
+ [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Returns the (possibly negative) integer represented by the eight bytes at
+ * the specified [byteOffset] in this object, in two's complement binary
+ * form.
+ *
+ * The return value will be between 2<sup>63</sup> and 2<sup>63</sup> - 1,
+ * inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 8` is greater than the length of this object.
+ */
+ int getInt64(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Sets the eight bytes starting at the specified [byteOffset] in this
+ * object to the two's complement binary representation of the specified
+ * [value], which must fit in eight bytes.
+ *
+ * In other words, [value] must lie
+ * between 2<sup>63</sup> and 2<sup>63</sup> - 1, inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 8` is greater than the length of this object.
+ */
+ void setInt64(int byteOffset,
+ int value,
+ [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Returns the positive integer represented by the eight bytes starting
+ * at the specified [byteOffset] in this object, in unsigned binary
+ * form.
+ *
+ * The return value will be between 0 and 2<sup>64</sup> - 1, inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 8` is greater than the length of this object.
+ */
+ int getUint64(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Sets the eight bytes starting at the specified [byteOffset] in this object
+ * to the unsigned binary representation of the specified [value],
+ * which must fit in eight bytes.
+ *
+ * In other words, [value] must be between
+ * 0 and 2<sup>64</sup> - 1, inclusive.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 8` is greater than the length of this object.
+ */
+ void setUint64(int byteOffset,
+ int value,
+ [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Returns the floating point number represented by the four bytes at
+ * the specified [byteOffset] in this object, in IEEE 754
+ * single-precision binary floating-point format (binary32).
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 4` is greater than the length of this object.
+ */
+ double getFloat32(int byteOffset,
+ [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Sets the four bytes starting at the specified [byteOffset] in this
+ * object to the IEEE 754 single-precision binary floating-point
+ * (binary32) representation of the specified [value].
+ *
+ * **Note that this method can lose precision.** The input [value] is
+ * a 64-bit floating point value, which will be converted to 32-bit
+ * floating point value by IEEE 754 rounding rules before it is stored.
+ * If [value] cannot be represented exactly as a binary32, it will be
+ * converted to the nearest binary32 value. If two binary32 values are
+ * equally close, the one whose least significant bit is zero will be used.
+ * Note that finite (but large) values can be converted to infinity, and
+ * small non-zero values can be converted to zero.
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 4` is greater than the length of this object.
+ */
+ void setFloat32(int byteOffset,
+ double value,
+ [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Returns the floating point number represented by the eight bytes at
+ * the specified [byteOffset] in this object, in IEEE 754
+ * double-precision binary floating-point format (binary64).
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 8` is greater than the length of this object.
+ */
+ double getFloat64(int byteOffset,
+ [Endianness endian = Endianness.BIG_ENDIAN]);
+
+ /**
+ * Sets the eight bytes starting at the specified [byteOffset] in this
+ * object to the IEEE 754 double-precision binary floating-point
+ * (binary64) representation of the specified [value].
+ *
+ * Throws [RangeError] if [byteOffset] is negative, or
+ * `byteOffset + 8` is greater than the length of this object.
+ */
+ void setFloat64(int byteOffset,
+ double value,
+ [Endianness endian = Endianness.BIG_ENDIAN]);
}
@@ -711,18 +848,18 @@
}
-class _ByteBuffer implements ByteBuffer {
+class ByteBuffer {
final _TypedList _data;
- _ByteBuffer(this._data);
+ ByteBuffer(this._data);
- factory _ByteBuffer._New(data) => new _ByteBuffer(data);
+ factory ByteBuffer._New(data) => new ByteBuffer(data);
// Forward calls to _data.
int get lengthInBytes => _data.lengthInBytes;
int get hashCode => _data.hashCode;
bool operator==(Object other) =>
- (other is _ByteBuffer) && identical(_data, other._data);
+ (other is ByteBuffer) && identical(_data, other._data);
ByteData asByteData([int offsetInBytes = 0, int length]) {
if (length == null) {
@@ -852,7 +989,7 @@
return length * elementSizeInBytes;
}
- ByteBuffer get buffer => new _ByteBuffer(this);
+ ByteBuffer get buffer => new ByteBuffer(this);
// Methods implementing the collection interface.
@@ -924,10 +1061,20 @@
}
-class _Int8Array extends _TypedList with _IntListMixin implements Int8List {
+class Int8List extends _TypedList with _IntListMixin implements List<int>, TypedData {
// Factory constructors.
- factory _Int8Array(int length) native "TypedData_Int8Array_new";
+ factory Int8List(int length) native "TypedData_Int8Array_new";
+
+ factory Int8List.fromList(List<int> elements) {
+ return new Int8List(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Int8List.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asInt8List(offsetInBytes, length);
+ }
// Method(s) implementing List interface.
@@ -945,6 +1092,7 @@
_setInt8(index, _toInt8(value));
}
+ static const int BYTES_PER_ELEMENT = 1;
// Method(s) implementing TypedData interface.
@@ -955,16 +1103,26 @@
// Internal utility methods.
- _Int8Array _createList(int length) {
- return new _Int8Array(length);
+ Int8List _createList(int length) {
+ return new Int8List(length);
}
}
-class _Uint8Array extends _TypedList with _IntListMixin implements Uint8List {
+class Uint8List extends _TypedList with _IntListMixin implements List<int>, TypedData {
// Factory constructors.
- factory _Uint8Array(int length) native "TypedData_Uint8Array_new";
+ factory Uint8List(int length) native "TypedData_Uint8Array_new";
+
+ factory Uint8List.fromList(List<int> elements) {
+ return new Uint8List(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Uint8List.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asUint8List(offsetInBytes, length);
+ }
// Methods implementing List interface.
int operator[](int index) {
@@ -981,6 +1139,7 @@
_setUint8(index, _toUint8(value));
}
+ static const int BYTES_PER_ELEMENT = 1;
// Methods implementing TypedData interface.
int get elementSizeInBytes {
@@ -990,16 +1149,26 @@
// Internal utility methods.
- _Uint8Array _createList(int length) {
- return new _Uint8Array(length);
+ Uint8List _createList(int length) {
+ return new Uint8List(length);
}
}
-class _Uint8ClampedArray extends _TypedList with _IntListMixin implements Uint8ClampedList {
+class Uint8ClampedList extends _TypedList with _IntListMixin implements List<int>, TypedData {
// Factory constructors.
- factory _Uint8ClampedArray(int length) native "TypedData_Uint8ClampedArray_new";
+ factory Uint8ClampedList(int length) native "TypedData_Uint8ClampedArray_new";
+
+ factory Uint8ClampedList.fromList(List<int> elements) {
+ return new Uint8ClampedList(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Uint8ClampedList.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asUint8ClampedList(offsetInBytes, length);
+ }
// Methods implementing List interface.
@@ -1017,6 +1186,7 @@
_setUint8(index, _toClampedUint8(value));
}
+ static const int BYTES_PER_ELEMENT = 1;
// Methods implementing TypedData interface.
int get elementSizeInBytes {
@@ -1026,16 +1196,26 @@
// Internal utility methods.
- _Uint8ClampedArray _createList(int length) {
- return new _Uint8ClampedArray(length);
+ Uint8ClampedList _createList(int length) {
+ return new Uint8ClampedList(length);
}
}
-class _Int16Array extends _TypedList with _IntListMixin implements Int16List {
+class Int16List extends _TypedList with _IntListMixin implements List<int>, TypedData {
// Factory constructors.
- factory _Int16Array(int length) native "TypedData_Int16Array_new";
+ factory Int16List(int length) native "TypedData_Int16Array_new";
+
+ factory Int16List.fromList(List<int> elements) {
+ return new Int16List(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Int16List.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asInt16List(offsetInBytes, length);
+ }
// Method(s) implementing List interface.
@@ -1065,6 +1245,7 @@
}
// Method(s) implementing TypedData interface.
+ static const int BYTES_PER_ELEMENT = 2;
int get elementSizeInBytes {
return Int16List.BYTES_PER_ELEMENT;
@@ -1073,8 +1254,8 @@
// Internal utility methods.
- _Int16Array _createList(int length) {
- return new _Int16Array(length);
+ Int16List _createList(int length) {
+ return new Int16List(length);
}
int _getIndexedInt16(int index) {
@@ -1087,10 +1268,20 @@
}
-class _Uint16Array extends _TypedList with _IntListMixin implements Uint16List {
+class Uint16List extends _TypedList with _IntListMixin implements List<int>, TypedData {
// Factory constructors.
- factory _Uint16Array(int length) native "TypedData_Uint16Array_new";
+ factory Uint16List(int length) native "TypedData_Uint16Array_new";
+
+ factory Uint16List.fromList(List<int> elements) {
+ return new Uint16List(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Uint16List.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asUint16List(offsetInBytes, length);
+ }
// Method(s) implementing the List interface.
@@ -1120,6 +1311,7 @@
}
// Method(s) implementing the TypedData interface.
+ static const int BYTES_PER_ELEMENT = 2;
int get elementSizeInBytes {
return Uint16List.BYTES_PER_ELEMENT;
@@ -1128,8 +1320,8 @@
// Internal utility methods.
- _Uint16Array _createList(int length) {
- return new _Uint16Array(length);
+ Uint16List _createList(int length) {
+ return new Uint16List(length);
}
int _getIndexedUint16(int index) {
@@ -1142,10 +1334,20 @@
}
-class _Int32Array extends _TypedList with _IntListMixin implements Int32List {
+class Int32List extends _TypedList with _IntListMixin implements List<int>, TypedData {
// Factory constructors.
- factory _Int32Array(int length) native "TypedData_Int32Array_new";
+ factory Int32List(int length) native "TypedData_Int32Array_new";
+
+ factory Int32List.fromList(List<int> elements) {
+ return new Int32List(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Int32List.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asInt32List(offsetInBytes, length);
+ }
// Method(s) implementing the List interface.
@@ -1165,6 +1367,7 @@
// Method(s) implementing TypedData interface.
+ static const int BYTES_PER_ELEMENT = 4;
int get elementSizeInBytes {
return Int32List.BYTES_PER_ELEMENT;
@@ -1173,8 +1376,8 @@
// Internal utility methods.
- _Int32Array _createList(int length) {
- return new _Int32Array(length);
+ Int32List _createList(int length) {
+ return new Int32List(length);
}
int _getIndexedInt32(int index) {
@@ -1188,10 +1391,20 @@
}
-class _Uint32Array extends _TypedList with _IntListMixin implements Uint32List {
+class Uint32List extends _TypedList with _IntListMixin implements List<int>, TypedData {
// Factory constructors.
- factory _Uint32Array(int length) native "TypedData_Uint32Array_new";
+ factory Uint32List(int length) native "TypedData_Uint32Array_new";
+
+ factory Uint32List.fromList(List<int> elements) {
+ return new Uint32List(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Uint32List.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asUint32List(offsetInBytes, length);
+ }
// Method(s) implementing the List interface.
@@ -1211,6 +1424,7 @@
// Method(s) implementing the TypedData interface.
+ static const int BYTES_PER_ELEMENT = 4;
int get elementSizeInBytes {
return Uint32List.BYTES_PER_ELEMENT;
@@ -1219,8 +1433,8 @@
// Internal utility methods.
- _Uint32Array _createList(int length) {
- return new _Uint32Array(length);
+ Uint32List _createList(int length) {
+ return new Uint32List(length);
}
int _getIndexedUint32(int index) {
@@ -1233,10 +1447,20 @@
}
-class _Int64Array extends _TypedList with _IntListMixin implements Int64List {
+class Int64List extends _TypedList with _IntListMixin implements List<int>, TypedData {
// Factory constructors.
- factory _Int64Array(int length) native "TypedData_Int64Array_new";
+ factory Int64List(int length) native "TypedData_Int64Array_new";
+
+ factory Int64List.fromList(List<int> elements) {
+ return new Int64List(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Int64List.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asInt64List(offsetInBytes, length);
+ }
// Method(s) implementing the List interface.
@@ -1256,6 +1480,7 @@
// Method(s) implementing the TypedData interface.
+ static const int BYTES_PER_ELEMENT = 8;
int get elementSizeInBytes {
return Int64List.BYTES_PER_ELEMENT;
@@ -1264,8 +1489,8 @@
// Internal utility methods.
- _Int64Array _createList(int length) {
- return new _Int64Array(length);
+ Int64List _createList(int length) {
+ return new Int64List(length);
}
int _getIndexedInt64(int index) {
@@ -1278,10 +1503,20 @@
}
-class _Uint64Array extends _TypedList with _IntListMixin implements Uint64List {
+class Uint64List extends _TypedList with _IntListMixin implements List<int>, TypedData {
// Factory constructors.
- factory _Uint64Array(int length) native "TypedData_Uint64Array_new";
+ factory Uint64List(int length) native "TypedData_Uint64Array_new";
+
+ factory Uint64List.fromList(List<int> elements) {
+ return new Uint64List(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Uint64List.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asUint64List(offsetInBytes, length);
+ }
// Method(s) implementing the List interface.
@@ -1301,6 +1536,7 @@
// Method(s) implementing the TypedData interface.
+ static const int BYTES_PER_ELEMENT = 8;
int get elementSizeInBytes {
return Uint64List.BYTES_PER_ELEMENT;
@@ -1309,8 +1545,8 @@
// Internal utility methods.
- _Uint64Array _createList(int length) {
- return new _Uint64Array(length);
+ Uint64List _createList(int length) {
+ return new Uint64List(length);
}
int _getIndexedUint64(int index) {
@@ -1323,10 +1559,20 @@
}
-class _Float32Array extends _TypedList with _DoubleListMixin implements Float32List {
+class Float32List extends _TypedList with _DoubleListMixin implements List<double>, TypedData {
// Factory constructors.
- factory _Float32Array(int length) native "TypedData_Float32Array_new";
+ factory Float32List(int length) native "TypedData_Float32Array_new";
+
+ factory Float32List.fromList(List<double> elements) {
+ return new Float32List(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Float32List.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asFloat32List(offsetInBytes, length);
+ }
// Method(s) implementing the List interface.
@@ -1346,6 +1592,7 @@
// Method(s) implementing the TypedData interface.
+ static const int BYTES_PER_ELEMENT = 4;
int get elementSizeInBytes {
return Float32List.BYTES_PER_ELEMENT;
@@ -1354,8 +1601,8 @@
// Internal utility methods.
- _Float32Array _createList(int length) {
- return new _Float32Array(length);
+ Float32List _createList(int length) {
+ return new Float32List(length);
}
double _getIndexedFloat32(int index) {
@@ -1368,10 +1615,20 @@
}
-class _Float64Array extends _TypedList with _DoubleListMixin implements Float64List {
+class Float64List extends _TypedList with _DoubleListMixin implements List<double>, TypedData {
// Factory constructors.
- factory _Float64Array(int length) native "TypedData_Float64Array_new";
+ factory Float64List(int length) native "TypedData_Float64Array_new";
+
+ factory Float64List.fromList(List<double> elements) {
+ return new Float64List(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Float64List.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asFloat64List(offsetInBytes, length);
+ }
// Method(s) implementing the List interface.
@@ -1391,6 +1648,7 @@
// Method(s) implementing the TypedData interface.
+ static const int BYTES_PER_ELEMENT = 8;
int get elementSizeInBytes {
return Float64List.BYTES_PER_ELEMENT;
@@ -1399,8 +1657,8 @@
// Internal utility methods.
- _Float64Array _createList(int length) {
- return new _Float64Array(length);
+ Float64List _createList(int length) {
+ return new Float64List(length);
}
double _getIndexedFloat64(int index) {
@@ -1413,10 +1671,20 @@
}
-class _Float32x4Array extends _TypedList with _Float32x4ListMixin implements Float32x4List {
+class Float32x4List extends _TypedList with _Float32x4ListMixin implements List<Float32x4>, TypedData {
// Factory constructors.
- factory _Float32x4Array(int length) native "TypedData_Float32x4Array_new";
+ factory Float32x4List(int length) native "TypedData_Float32x4Array_new";
+
+ factory Float32x4List.fromList(List<Float32x4> elements) {
+ return new Float32x4List(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Float32x4List.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asFloat32x4List(offsetInBytes, length);
+ }
Float32x4 operator[](int index) {
if (index < 0 || index >= length) {
@@ -1434,6 +1702,7 @@
// Method(s) implementing the TypedData interface.
+ static const int BYTES_PER_ELEMENT = 16;
int get elementSizeInBytes {
return Float32x4List.BYTES_PER_ELEMENT;
@@ -1442,8 +1711,8 @@
// Internal utility methods.
- _Float32x4Array _createList(int length) {
- return new _Float32x4Array(length);
+ Float32x4List _createList(int length) {
+ return new Float32x4List(length);
}
Float32x4 _getIndexedFloat32x4(int index) {
@@ -1456,10 +1725,20 @@
}
-class _Int32x4Array extends _TypedList with _Int32x4ListMixin implements Int32x4List {
+class Int32x4List extends _TypedList with _Int32x4ListMixin implements List<Int32x4>, TypedData {
// Factory constructors.
- factory _Int32x4Array(int length) native "TypedData_Int32x4Array_new";
+ factory Int32x4List(int length) native "TypedData_Int32x4Array_new";
+
+ factory Int32x4List.fromList(List<Int32x4> elements) {
+ return new Int32x4List(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Int32x4List.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asInt32x4List(offsetInBytes, length);
+ }
Int32x4 operator[](int index) {
if (index < 0 || index >= length) {
@@ -1477,6 +1756,7 @@
// Method(s) implementing the TypedData interface.
+ static const int BYTES_PER_ELEMENT = 16;
int get elementSizeInBytes {
return Int32x4List.BYTES_PER_ELEMENT;
@@ -1485,8 +1765,8 @@
// Internal utility methods.
- _Int32x4Array _createList(int length) {
- return new _Int32x4Array(length);
+ Int32x4List _createList(int length) {
+ return new Int32x4List(length);
}
Int32x4 _getIndexedInt32x4(int index) {
@@ -1499,10 +1779,20 @@
}
-class _Float64x2Array extends _TypedList with _Float64x2ListMixin implements Float64x2List {
+class Float64x2List extends _TypedList with _Float64x2ListMixin implements List<Float64x2>, TypedData {
// Factory constructors.
- factory _Float64x2Array(int length) native "TypedData_Float64x2Array_new";
+ factory Float64x2List(int length) native "TypedData_Float64x2Array_new";
+
+ factory Float64x2List.fromList(List<Float64x2> elements) {
+ return new Float64x2List(elements.length)
+ ..setRange(0, elements.length, elements);
+ }
+
+ factory Float64x2List.view(ByteBuffer buffer,
+ [int offsetInBytes = 0, int length]) {
+ return buffer.asFloat64x2List(offsetInBytes, length);
+ }
Float64x2 operator[](int index) {
if (index < 0 || index >= length) {
@@ -1520,6 +1810,7 @@
// Method(s) implementing the TypedData interface.
+ static const int BYTES_PER_ELEMENT = 16;
int get elementSizeInBytes {
return Float64x2List.BYTES_PER_ELEMENT;
@@ -1528,8 +1819,8 @@
// Internal utility methods.
- _Float64x2Array _createList(int length) {
- return new _Float64x2Array(length);
+ Float64x2List _createList(int length) {
+ return new Float64x2List(length);
}
Float64x2 _getIndexedFloat64x2(int index) {
@@ -2147,14 +2438,14 @@
}
-class _Float32x4 implements Float32x4 {
- factory _Float32x4(double x, double y, double z, double w)
+class Float32x4 {
+ factory Float32x4(double x, double y, double z, double w)
native "Float32x4_fromDoubles";
- factory _Float32x4.splat(double v) native "Float32x4_splat";
- factory _Float32x4.zero() native "Float32x4_zero";
- factory _Float32x4.fromInt32x4Bits(Int32x4 x)
+ factory Float32x4.splat(double v) native "Float32x4_splat";
+ factory Float32x4.zero() native "Float32x4_zero";
+ factory Float32x4.fromInt32x4Bits(Int32x4 x)
native "Float32x4_fromInt32x4Bits";
- factory _Float32x4.fromFloat64x2(Float64x2 v)
+ factory Float32x4.fromFloat64x2(Float64x2 v)
native "Float32x4_fromFloat64x2";
Float32x4 operator +(Float32x4 other) {
return _add(other);
@@ -2248,15 +2539,274 @@
return _reciprocalSqrt();
}
Float32x4 _reciprocalSqrt() native "Float32x4_reciprocalSqrt";
+
+ /// Mask passed to [shuffle] or [shuffleMix].
+ static const int XXXX = 0x0;
+ static const int XXXY = 0x40;
+ static const int XXXZ = 0x80;
+ static const int XXXW = 0xC0;
+ static const int XXYX = 0x10;
+ static const int XXYY = 0x50;
+ static const int XXYZ = 0x90;
+ static const int XXYW = 0xD0;
+ static const int XXZX = 0x20;
+ static const int XXZY = 0x60;
+ static const int XXZZ = 0xA0;
+ static const int XXZW = 0xE0;
+ static const int XXWX = 0x30;
+ static const int XXWY = 0x70;
+ static const int XXWZ = 0xB0;
+ static const int XXWW = 0xF0;
+ static const int XYXX = 0x4;
+ static const int XYXY = 0x44;
+ static const int XYXZ = 0x84;
+ static const int XYXW = 0xC4;
+ static const int XYYX = 0x14;
+ static const int XYYY = 0x54;
+ static const int XYYZ = 0x94;
+ static const int XYYW = 0xD4;
+ static const int XYZX = 0x24;
+ static const int XYZY = 0x64;
+ static const int XYZZ = 0xA4;
+ static const int XYZW = 0xE4;
+ static const int XYWX = 0x34;
+ static const int XYWY = 0x74;
+ static const int XYWZ = 0xB4;
+ static const int XYWW = 0xF4;
+ static const int XZXX = 0x8;
+ static const int XZXY = 0x48;
+ static const int XZXZ = 0x88;
+ static const int XZXW = 0xC8;
+ static const int XZYX = 0x18;
+ static const int XZYY = 0x58;
+ static const int XZYZ = 0x98;
+ static const int XZYW = 0xD8;
+ static const int XZZX = 0x28;
+ static const int XZZY = 0x68;
+ static const int XZZZ = 0xA8;
+ static const int XZZW = 0xE8;
+ static const int XZWX = 0x38;
+ static const int XZWY = 0x78;
+ static const int XZWZ = 0xB8;
+ static const int XZWW = 0xF8;
+ static const int XWXX = 0xC;
+ static const int XWXY = 0x4C;
+ static const int XWXZ = 0x8C;
+ static const int XWXW = 0xCC;
+ static const int XWYX = 0x1C;
+ static const int XWYY = 0x5C;
+ static const int XWYZ = 0x9C;
+ static const int XWYW = 0xDC;
+ static const int XWZX = 0x2C;
+ static const int XWZY = 0x6C;
+ static const int XWZZ = 0xAC;
+ static const int XWZW = 0xEC;
+ static const int XWWX = 0x3C;
+ static const int XWWY = 0x7C;
+ static const int XWWZ = 0xBC;
+ static const int XWWW = 0xFC;
+ static const int YXXX = 0x1;
+ static const int YXXY = 0x41;
+ static const int YXXZ = 0x81;
+ static const int YXXW = 0xC1;
+ static const int YXYX = 0x11;
+ static const int YXYY = 0x51;
+ static const int YXYZ = 0x91;
+ static const int YXYW = 0xD1;
+ static const int YXZX = 0x21;
+ static const int YXZY = 0x61;
+ static const int YXZZ = 0xA1;
+ static const int YXZW = 0xE1;
+ static const int YXWX = 0x31;
+ static const int YXWY = 0x71;
+ static const int YXWZ = 0xB1;
+ static const int YXWW = 0xF1;
+ static const int YYXX = 0x5;
+ static const int YYXY = 0x45;
+ static const int YYXZ = 0x85;
+ static const int YYXW = 0xC5;
+ static const int YYYX = 0x15;
+ static const int YYYY = 0x55;
+ static const int YYYZ = 0x95;
+ static const int YYYW = 0xD5;
+ static const int YYZX = 0x25;
+ static const int YYZY = 0x65;
+ static const int YYZZ = 0xA5;
+ static const int YYZW = 0xE5;
+ static const int YYWX = 0x35;
+ static const int YYWY = 0x75;
+ static const int YYWZ = 0xB5;
+ static const int YYWW = 0xF5;
+ static const int YZXX = 0x9;
+ static const int YZXY = 0x49;
+ static const int YZXZ = 0x89;
+ static const int YZXW = 0xC9;
+ static const int YZYX = 0x19;
+ static const int YZYY = 0x59;
+ static const int YZYZ = 0x99;
+ static const int YZYW = 0xD9;
+ static const int YZZX = 0x29;
+ static const int YZZY = 0x69;
+ static const int YZZZ = 0xA9;
+ static const int YZZW = 0xE9;
+ static const int YZWX = 0x39;
+ static const int YZWY = 0x79;
+ static const int YZWZ = 0xB9;
+ static const int YZWW = 0xF9;
+ static const int YWXX = 0xD;
+ static const int YWXY = 0x4D;
+ static const int YWXZ = 0x8D;
+ static const int YWXW = 0xCD;
+ static const int YWYX = 0x1D;
+ static const int YWYY = 0x5D;
+ static const int YWYZ = 0x9D;
+ static const int YWYW = 0xDD;
+ static const int YWZX = 0x2D;
+ static const int YWZY = 0x6D;
+ static const int YWZZ = 0xAD;
+ static const int YWZW = 0xED;
+ static const int YWWX = 0x3D;
+ static const int YWWY = 0x7D;
+ static const int YWWZ = 0xBD;
+ static const int YWWW = 0xFD;
+ static const int ZXXX = 0x2;
+ static const int ZXXY = 0x42;
+ static const int ZXXZ = 0x82;
+ static const int ZXXW = 0xC2;
+ static const int ZXYX = 0x12;
+ static const int ZXYY = 0x52;
+ static const int ZXYZ = 0x92;
+ static const int ZXYW = 0xD2;
+ static const int ZXZX = 0x22;
+ static const int ZXZY = 0x62;
+ static const int ZXZZ = 0xA2;
+ static const int ZXZW = 0xE2;
+ static const int ZXWX = 0x32;
+ static const int ZXWY = 0x72;
+ static const int ZXWZ = 0xB2;
+ static const int ZXWW = 0xF2;
+ static const int ZYXX = 0x6;
+ static const int ZYXY = 0x46;
+ static const int ZYXZ = 0x86;
+ static const int ZYXW = 0xC6;
+ static const int ZYYX = 0x16;
+ static const int ZYYY = 0x56;
+ static const int ZYYZ = 0x96;
+ static const int ZYYW = 0xD6;
+ static const int ZYZX = 0x26;
+ static const int ZYZY = 0x66;
+ static const int ZYZZ = 0xA6;
+ static const int ZYZW = 0xE6;
+ static const int ZYWX = 0x36;
+ static const int ZYWY = 0x76;
+ static const int ZYWZ = 0xB6;
+ static const int ZYWW = 0xF6;
+ static const int ZZXX = 0xA;
+ static const int ZZXY = 0x4A;
+ static const int ZZXZ = 0x8A;
+ static const int ZZXW = 0xCA;
+ static const int ZZYX = 0x1A;
+ static const int ZZYY = 0x5A;
+ static const int ZZYZ = 0x9A;
+ static const int ZZYW = 0xDA;
+ static const int ZZZX = 0x2A;
+ static const int ZZZY = 0x6A;
+ static const int ZZZZ = 0xAA;
+ static const int ZZZW = 0xEA;
+ static const int ZZWX = 0x3A;
+ static const int ZZWY = 0x7A;
+ static const int ZZWZ = 0xBA;
+ static const int ZZWW = 0xFA;
+ static const int ZWXX = 0xE;
+ static const int ZWXY = 0x4E;
+ static const int ZWXZ = 0x8E;
+ static const int ZWXW = 0xCE;
+ static const int ZWYX = 0x1E;
+ static const int ZWYY = 0x5E;
+ static const int ZWYZ = 0x9E;
+ static const int ZWYW = 0xDE;
+ static const int ZWZX = 0x2E;
+ static const int ZWZY = 0x6E;
+ static const int ZWZZ = 0xAE;
+ static const int ZWZW = 0xEE;
+ static const int ZWWX = 0x3E;
+ static const int ZWWY = 0x7E;
+ static const int ZWWZ = 0xBE;
+ static const int ZWWW = 0xFE;
+ static const int WXXX = 0x3;
+ static const int WXXY = 0x43;
+ static const int WXXZ = 0x83;
+ static const int WXXW = 0xC3;
+ static const int WXYX = 0x13;
+ static const int WXYY = 0x53;
+ static const int WXYZ = 0x93;
+ static const int WXYW = 0xD3;
+ static const int WXZX = 0x23;
+ static const int WXZY = 0x63;
+ static const int WXZZ = 0xA3;
+ static const int WXZW = 0xE3;
+ static const int WXWX = 0x33;
+ static const int WXWY = 0x73;
+ static const int WXWZ = 0xB3;
+ static const int WXWW = 0xF3;
+ static const int WYXX = 0x7;
+ static const int WYXY = 0x47;
+ static const int WYXZ = 0x87;
+ static const int WYXW = 0xC7;
+ static const int WYYX = 0x17;
+ static const int WYYY = 0x57;
+ static const int WYYZ = 0x97;
+ static const int WYYW = 0xD7;
+ static const int WYZX = 0x27;
+ static const int WYZY = 0x67;
+ static const int WYZZ = 0xA7;
+ static const int WYZW = 0xE7;
+ static const int WYWX = 0x37;
+ static const int WYWY = 0x77;
+ static const int WYWZ = 0xB7;
+ static const int WYWW = 0xF7;
+ static const int WZXX = 0xB;
+ static const int WZXY = 0x4B;
+ static const int WZXZ = 0x8B;
+ static const int WZXW = 0xCB;
+ static const int WZYX = 0x1B;
+ static const int WZYY = 0x5B;
+ static const int WZYZ = 0x9B;
+ static const int WZYW = 0xDB;
+ static const int WZZX = 0x2B;
+ static const int WZZY = 0x6B;
+ static const int WZZZ = 0xAB;
+ static const int WZZW = 0xEB;
+ static const int WZWX = 0x3B;
+ static const int WZWY = 0x7B;
+ static const int WZWZ = 0xBB;
+ static const int WZWW = 0xFB;
+ static const int WWXX = 0xF;
+ static const int WWXY = 0x4F;
+ static const int WWXZ = 0x8F;
+ static const int WWXW = 0xCF;
+ static const int WWYX = 0x1F;
+ static const int WWYY = 0x5F;
+ static const int WWYZ = 0x9F;
+ static const int WWYW = 0xDF;
+ static const int WWZX = 0x2F;
+ static const int WWZY = 0x6F;
+ static const int WWZZ = 0xAF;
+ static const int WWZW = 0xEF;
+ static const int WWWX = 0x3F;
+ static const int WWWY = 0x7F;
+ static const int WWWZ = 0xBF;
+ static const int WWWW = 0xFF;
+
}
-class _Int32x4 implements Int32x4 {
- factory _Int32x4(int x, int y, int z, int w)
+class Int32x4 {
+ factory Int32x4(int x, int y, int z, int w)
native "Int32x4_fromInts";
- factory _Int32x4.bool(bool x, bool y, bool z, bool w)
+ factory Int32x4.bool(bool x, bool y, bool z, bool w)
native "Int32x4_fromBools";
- factory _Int32x4.fromFloat32x4Bits(Float32x4 x)
+ factory Int32x4.fromFloat32x4Bits(Float32x4 x)
native "Int32x4_fromFloat32x4Bits";
Int32x4 operator |(Int32x4 other) {
return _or(other);
@@ -2304,14 +2854,273 @@
Float32x4 _select(Float32x4 trueValue,
Float32x4 falseValue)
native "Int32x4_select";
+
+ /// Mask passed to [shuffle] or [shuffleMix].
+ static const int XXXX = 0x0;
+ static const int XXXY = 0x40;
+ static const int XXXZ = 0x80;
+ static const int XXXW = 0xC0;
+ static const int XXYX = 0x10;
+ static const int XXYY = 0x50;
+ static const int XXYZ = 0x90;
+ static const int XXYW = 0xD0;
+ static const int XXZX = 0x20;
+ static const int XXZY = 0x60;
+ static const int XXZZ = 0xA0;
+ static const int XXZW = 0xE0;
+ static const int XXWX = 0x30;
+ static const int XXWY = 0x70;
+ static const int XXWZ = 0xB0;
+ static const int XXWW = 0xF0;
+ static const int XYXX = 0x4;
+ static const int XYXY = 0x44;
+ static const int XYXZ = 0x84;
+ static const int XYXW = 0xC4;
+ static const int XYYX = 0x14;
+ static const int XYYY = 0x54;
+ static const int XYYZ = 0x94;
+ static const int XYYW = 0xD4;
+ static const int XYZX = 0x24;
+ static const int XYZY = 0x64;
+ static const int XYZZ = 0xA4;
+ static const int XYZW = 0xE4;
+ static const int XYWX = 0x34;
+ static const int XYWY = 0x74;
+ static const int XYWZ = 0xB4;
+ static const int XYWW = 0xF4;
+ static const int XZXX = 0x8;
+ static const int XZXY = 0x48;
+ static const int XZXZ = 0x88;
+ static const int XZXW = 0xC8;
+ static const int XZYX = 0x18;
+ static const int XZYY = 0x58;
+ static const int XZYZ = 0x98;
+ static const int XZYW = 0xD8;
+ static const int XZZX = 0x28;
+ static const int XZZY = 0x68;
+ static const int XZZZ = 0xA8;
+ static const int XZZW = 0xE8;
+ static const int XZWX = 0x38;
+ static const int XZWY = 0x78;
+ static const int XZWZ = 0xB8;
+ static const int XZWW = 0xF8;
+ static const int XWXX = 0xC;
+ static const int XWXY = 0x4C;
+ static const int XWXZ = 0x8C;
+ static const int XWXW = 0xCC;
+ static const int XWYX = 0x1C;
+ static const int XWYY = 0x5C;
+ static const int XWYZ = 0x9C;
+ static const int XWYW = 0xDC;
+ static const int XWZX = 0x2C;
+ static const int XWZY = 0x6C;
+ static const int XWZZ = 0xAC;
+ static const int XWZW = 0xEC;
+ static const int XWWX = 0x3C;
+ static const int XWWY = 0x7C;
+ static const int XWWZ = 0xBC;
+ static const int XWWW = 0xFC;
+ static const int YXXX = 0x1;
+ static const int YXXY = 0x41;
+ static const int YXXZ = 0x81;
+ static const int YXXW = 0xC1;
+ static const int YXYX = 0x11;
+ static const int YXYY = 0x51;
+ static const int YXYZ = 0x91;
+ static const int YXYW = 0xD1;
+ static const int YXZX = 0x21;
+ static const int YXZY = 0x61;
+ static const int YXZZ = 0xA1;
+ static const int YXZW = 0xE1;
+ static const int YXWX = 0x31;
+ static const int YXWY = 0x71;
+ static const int YXWZ = 0xB1;
+ static const int YXWW = 0xF1;
+ static const int YYXX = 0x5;
+ static const int YYXY = 0x45;
+ static const int YYXZ = 0x85;
+ static const int YYXW = 0xC5;
+ static const int YYYX = 0x15;
+ static const int YYYY = 0x55;
+ static const int YYYZ = 0x95;
+ static const int YYYW = 0xD5;
+ static const int YYZX = 0x25;
+ static const int YYZY = 0x65;
+ static const int YYZZ = 0xA5;
+ static const int YYZW = 0xE5;
+ static const int YYWX = 0x35;
+ static const int YYWY = 0x75;
+ static const int YYWZ = 0xB5;
+ static const int YYWW = 0xF5;
+ static const int YZXX = 0x9;
+ static const int YZXY = 0x49;
+ static const int YZXZ = 0x89;
+ static const int YZXW = 0xC9;
+ static const int YZYX = 0x19;
+ static const int YZYY = 0x59;
+ static const int YZYZ = 0x99;
+ static const int YZYW = 0xD9;
+ static const int YZZX = 0x29;
+ static const int YZZY = 0x69;
+ static const int YZZZ = 0xA9;
+ static const int YZZW = 0xE9;
+ static const int YZWX = 0x39;
+ static const int YZWY = 0x79;
+ static const int YZWZ = 0xB9;
+ static const int YZWW = 0xF9;
+ static const int YWXX = 0xD;
+ static const int YWXY = 0x4D;
+ static const int YWXZ = 0x8D;
+ static const int YWXW = 0xCD;
+ static const int YWYX = 0x1D;
+ static const int YWYY = 0x5D;
+ static const int YWYZ = 0x9D;
+ static const int YWYW = 0xDD;
+ static const int YWZX = 0x2D;
+ static const int YWZY = 0x6D;
+ static const int YWZZ = 0xAD;
+ static const int YWZW = 0xED;
+ static const int YWWX = 0x3D;
+ static const int YWWY = 0x7D;
+ static const int YWWZ = 0xBD;
+ static const int YWWW = 0xFD;
+ static const int ZXXX = 0x2;
+ static const int ZXXY = 0x42;
+ static const int ZXXZ = 0x82;
+ static const int ZXXW = 0xC2;
+ static const int ZXYX = 0x12;
+ static const int ZXYY = 0x52;
+ static const int ZXYZ = 0x92;
+ static const int ZXYW = 0xD2;
+ static const int ZXZX = 0x22;
+ static const int ZXZY = 0x62;
+ static const int ZXZZ = 0xA2;
+ static const int ZXZW = 0xE2;
+ static const int ZXWX = 0x32;
+ static const int ZXWY = 0x72;
+ static const int ZXWZ = 0xB2;
+ static const int ZXWW = 0xF2;
+ static const int ZYXX = 0x6;
+ static const int ZYXY = 0x46;
+ static const int ZYXZ = 0x86;
+ static const int ZYXW = 0xC6;
+ static const int ZYYX = 0x16;
+ static const int ZYYY = 0x56;
+ static const int ZYYZ = 0x96;
+ static const int ZYYW = 0xD6;
+ static const int ZYZX = 0x26;
+ static const int ZYZY = 0x66;
+ static const int ZYZZ = 0xA6;
+ static const int ZYZW = 0xE6;
+ static const int ZYWX = 0x36;
+ static const int ZYWY = 0x76;
+ static const int ZYWZ = 0xB6;
+ static const int ZYWW = 0xF6;
+ static const int ZZXX = 0xA;
+ static const int ZZXY = 0x4A;
+ static const int ZZXZ = 0x8A;
+ static const int ZZXW = 0xCA;
+ static const int ZZYX = 0x1A;
+ static const int ZZYY = 0x5A;
+ static const int ZZYZ = 0x9A;
+ static const int ZZYW = 0xDA;
+ static const int ZZZX = 0x2A;
+ static const int ZZZY = 0x6A;
+ static const int ZZZZ = 0xAA;
+ static const int ZZZW = 0xEA;
+ static const int ZZWX = 0x3A;
+ static const int ZZWY = 0x7A;
+ static const int ZZWZ = 0xBA;
+ static const int ZZWW = 0xFA;
+ static const int ZWXX = 0xE;
+ static const int ZWXY = 0x4E;
+ static const int ZWXZ = 0x8E;
+ static const int ZWXW = 0xCE;
+ static const int ZWYX = 0x1E;
+ static const int ZWYY = 0x5E;
+ static const int ZWYZ = 0x9E;
+ static const int ZWYW = 0xDE;
+ static const int ZWZX = 0x2E;
+ static const int ZWZY = 0x6E;
+ static const int ZWZZ = 0xAE;
+ static const int ZWZW = 0xEE;
+ static const int ZWWX = 0x3E;
+ static const int ZWWY = 0x7E;
+ static const int ZWWZ = 0xBE;
+ static const int ZWWW = 0xFE;
+ static const int WXXX = 0x3;
+ static const int WXXY = 0x43;
+ static const int WXXZ = 0x83;
+ static const int WXXW = 0xC3;
+ static const int WXYX = 0x13;
+ static const int WXYY = 0x53;
+ static const int WXYZ = 0x93;
+ static const int WXYW = 0xD3;
+ static const int WXZX = 0x23;
+ static const int WXZY = 0x63;
+ static const int WXZZ = 0xA3;
+ static const int WXZW = 0xE3;
+ static const int WXWX = 0x33;
+ static const int WXWY = 0x73;
+ static const int WXWZ = 0xB3;
+ static const int WXWW = 0xF3;
+ static const int WYXX = 0x7;
+ static const int WYXY = 0x47;
+ static const int WYXZ = 0x87;
+ static const int WYXW = 0xC7;
+ static const int WYYX = 0x17;
+ static const int WYYY = 0x57;
+ static const int WYYZ = 0x97;
+ static const int WYYW = 0xD7;
+ static const int WYZX = 0x27;
+ static const int WYZY = 0x67;
+ static const int WYZZ = 0xA7;
+ static const int WYZW = 0xE7;
+ static const int WYWX = 0x37;
+ static const int WYWY = 0x77;
+ static const int WYWZ = 0xB7;
+ static const int WYWW = 0xF7;
+ static const int WZXX = 0xB;
+ static const int WZXY = 0x4B;
+ static const int WZXZ = 0x8B;
+ static const int WZXW = 0xCB;
+ static const int WZYX = 0x1B;
+ static const int WZYY = 0x5B;
+ static const int WZYZ = 0x9B;
+ static const int WZYW = 0xDB;
+ static const int WZZX = 0x2B;
+ static const int WZZY = 0x6B;
+ static const int WZZZ = 0xAB;
+ static const int WZZW = 0xEB;
+ static const int WZWX = 0x3B;
+ static const int WZWY = 0x7B;
+ static const int WZWZ = 0xBB;
+ static const int WZWW = 0xFB;
+ static const int WWXX = 0xF;
+ static const int WWXY = 0x4F;
+ static const int WWXZ = 0x8F;
+ static const int WWXW = 0xCF;
+ static const int WWYX = 0x1F;
+ static const int WWYY = 0x5F;
+ static const int WWYZ = 0x9F;
+ static const int WWYW = 0xDF;
+ static const int WWZX = 0x2F;
+ static const int WWZY = 0x6F;
+ static const int WWZZ = 0xAF;
+ static const int WWZW = 0xEF;
+ static const int WWWX = 0x3F;
+ static const int WWWY = 0x7F;
+ static const int WWWZ = 0xBF;
+ static const int WWWW = 0xFF;
+
}
-class _Float64x2 implements Float64x2 {
- factory _Float64x2(double x, double y) native "Float64x2_fromDoubles";
- factory _Float64x2.splat(double v) native "Float64x2_splat";
- factory _Float64x2.zero() native "Float64x2_zero";
- factory _Float64x2.fromFloat32x4(Float32x4 v) native "Float64x2_fromFloat32x4";
+class Float64x2 {
+ factory Float64x2(double x, double y) native "Float64x2_fromDoubles";
+ factory Float64x2.splat(double v) native "Float64x2_splat";
+ factory Float64x2.zero() native "Float64x2_zero";
+ factory Float64x2.fromFloat32x4(Float32x4 v) native "Float64x2_fromFloat32x4";
Float64x2 operator +(Float64x2 other) {
return _add(other);
@@ -2397,7 +3206,7 @@
class _TypedListView extends _TypedListBase implements TypedData {
- _TypedListView(_ByteBuffer _buffer, int _offset, int _length)
+ _TypedListView(ByteBuffer _buffer, int _offset, int _length)
: _typedData = _buffer._data,
offsetInBytes = _offset,
length = _length {
diff --git a/runtime/observatory/lib/src/app/location_manager.dart b/runtime/observatory/lib/src/app/location_manager.dart
index fee2884..577cb92 100644
--- a/runtime/observatory/lib/src/app/location_manager.dart
+++ b/runtime/observatory/lib/src/app/location_manager.dart
@@ -34,6 +34,13 @@
_updateApplicationLocation(applicationPath);
}
+ bool getBoolParameter(String name, bool defaultValue) {
+ var value = uri.queryParameters[name];
+ if ("true" == value) return true;
+ if ("false" == value) return false;
+ return defaultValue;
+ }
+
/// Called whenever the browser changes the location bar (e.g. forward or
/// back button press).
void _onBrowserNavigation(PopStateEvent event) {
diff --git a/runtime/observatory/lib/src/app/view_model.dart b/runtime/observatory/lib/src/app/view_model.dart
index 072b156..94edb49 100644
--- a/runtime/observatory/lib/src/app/view_model.dart
+++ b/runtime/observatory/lib/src/app/view_model.dart
@@ -68,7 +68,8 @@
HtmlElement _makeExpander() {
var expander = new SpanElement();
- expander.style.minWidth = '2em';
+ expander.style.minWidth = '24px';
+ expander.style.minHeight = '24px';
listeners.add(expander.onClick.listen(onClick));
return expander;
}
diff --git a/runtime/observatory/lib/src/elements/class_tree.dart b/runtime/observatory/lib/src/elements/class_tree.dart
index 42de21c..16f6928 100644
--- a/runtime/observatory/lib/src/elements/class_tree.dart
+++ b/runtime/observatory/lib/src/elements/class_tree.dart
@@ -5,6 +5,7 @@
library class_tree_element;
import 'observatory_element.dart';
+import 'dart:async';
import 'dart:html';
import 'package:logging/logging.dart';
import 'package:observatory/app.dart';
@@ -20,27 +21,92 @@
assert(cls != null);
}
- void onShow() {
- super.onShow();
- if (children.length == 0) {
- for (var subclass in cls.subclasses) {
- if (subclass.isPatch) {
- continue;
- }
+ void _addChildren(List<Class> subclasses) {
+ for (var subclass in subclasses) {
+ if (subclass.isPatch) {
+ continue;
+ }
+ if (subclass.mixin != null) {
+ _addChildren(subclass.subclasses);
+ } else {
var row = new ClassTreeRow(isolate, subclass, tree, this);
children.add(row);
}
}
+ }
+
+ Future _addMixins(Class cls) async {
+ var classCell = flexColumns[0];
+ if (cls.superclass == null) {
+ return;
+ }
+ bool first = true;
+ while (cls.superclass != null && cls.superclass.mixin != null) {
+ cls = cls.superclass;
+ await cls.mixin.load();
+ var span = new SpanElement();
+ span.style.alignSelf = 'center';
+ span.style.whiteSpace = 'pre';
+ if (first) {
+ span.text = ' with ';
+ } else {
+ span.text = ', ';
+ }
+ classCell.children.add(span);
+ var mixinRef = new Element.tag('class-ref');
+ mixinRef.ref = cls.mixin.typeClass;
+ mixinRef.style.alignSelf = 'center';
+ classCell.children.add(mixinRef);
+ first = false;
+ }
+ }
+
+ Future _addClass(Class cls) async {
var classCell = flexColumns[0];
classCell.style.justifyContent = 'flex-start';
var classRef = new Element.tag('class-ref');
classRef.ref = cls;
classRef.style.alignSelf = 'center';
classCell.children.add(classRef);
+ if (cls.superclass != null && cls.superclass.mixin != null) {
+ await _addMixins(cls);
+ }
+ if (cls.subclasses.isNotEmpty) {
+ var span = new SpanElement();
+ span.style.paddingLeft = '.5em';
+ span.style.alignSelf = 'center';
+ int subclassCount = _indirectSubclassCount(cls) - 1;
+ if (subclassCount > 1) {
+ span.text = '($subclassCount subclasses)';
+ } else {
+ span.text = '($subclassCount subclass)';
+ }
+ classCell.children.add(span);
+ }
+ }
+
+ void onShow() {
+ super.onShow();
+ if (children.length == 0) {
+ _addChildren(cls.subclasses);
+ }
+ _addClass(cls);
+ }
+
+ static int _indirectSubclassCount(var cls) {
+ int count = 0;
+ if (cls.mixin == null) {
+ // Don't count synthetic mixin classes in subclass count.
+ count++;
+ }
+ for (var subclass in cls.subclasses) {
+ count += _indirectSubclassCount(subclass);
+ }
+ return count;
}
bool hasChildren() {
- return cls.subclasses.length > 0;
+ return cls.subclasses.isNotEmpty;
}
}
diff --git a/runtime/observatory/lib/src/elements/class_view.dart b/runtime/observatory/lib/src/elements/class_view.dart
index d50b092..c13cbb3 100644
--- a/runtime/observatory/lib/src/elements/class_view.dart
+++ b/runtime/observatory/lib/src/elements/class_view.dart
@@ -35,7 +35,7 @@
}
Future<ServiceObject> retainedToplist(var limit) {
- return cls.isolate.fetchHeapSnapshot().last
+ return cls.isolate.fetchHeapSnapshot(true).last
.then((HeapSnapshot snapshot) =>
Future.wait(snapshot.getMostRetained(classId: cls.vmCid,
limit: 10)))
diff --git a/runtime/observatory/lib/src/elements/class_view.html b/runtime/observatory/lib/src/elements/class_view.html
index 60e8ee0..a40ef165d 100644
--- a/runtime/observatory/lib/src/elements/class_view.html
+++ b/runtime/observatory/lib/src/elements/class_view.html
@@ -35,6 +35,9 @@
<template if="{{ cls.isPatch }}">
patch
</template>
+ <template if="{{ cls.mixin != null }}">
+ mixin
+ </template>
class {{ cls.name }}
</h1>
@@ -59,12 +62,28 @@
<template if="{{ cls.superclass != null }}">
<div class="memberItem">
- <div class="memberName">extends</div>
+ <div class="memberName">superclass</div>
<div class="memberValue">
<class-ref ref="{{ cls.superclass }}"></class-ref>
</div>
</div>
</template>
+ <template if="{{ cls.superType != null }}">
+ <div class="memberItem">
+ <div class="memberName">supertype</div>
+ <div class="memberValue">
+ <instance-ref ref="{{ cls.superType }}"></instance-ref>
+ </div>
+ </div>
+ </template>
+ <template if="{{ cls.mixin != null }}">
+ <div class="memberItem">
+ <div class="memberName">mixin</div>
+ <div class="memberValue">
+ <instance-ref ref="{{ cls.mixin }}"></instance-ref>
+ </div>
+ </div>
+ </template>
<template if="{{ cls.subclasses.length > 0 }}">
<div class="memberItem">
<div class="memberName">extended by</div>
diff --git a/runtime/observatory/lib/src/elements/heap_snapshot.dart b/runtime/observatory/lib/src/elements/heap_snapshot.dart
index a9e4a8e..4894e9f 100644
--- a/runtime/observatory/lib/src/elements/heap_snapshot.dart
+++ b/runtime/observatory/lib/src/elements/heap_snapshot.dart
@@ -407,8 +407,12 @@
var completer = new Completer();
state = "Requesting heap snapshot...";
isolate.getClassRefs();
+
+ bool collectGarbage =
+ app.locationManager.getBoolParameter('collectGarbage', true);
+
var stopwatch = new Stopwatch()..start();
- isolate.fetchHeapSnapshot().listen((event) {
+ isolate.fetchHeapSnapshot(collectGarbage).listen((event) {
if (event is String) {
print("${stopwatch.elapsedMilliseconds} $event");
state = event;
diff --git a/runtime/observatory/lib/src/elements/instance_view.dart b/runtime/observatory/lib/src/elements/instance_view.dart
index 96a3b74..dda1cc5 100644
--- a/runtime/observatory/lib/src/elements/instance_view.dart
+++ b/runtime/observatory/lib/src/elements/instance_view.dart
@@ -15,6 +15,19 @@
InstanceViewElement.created() : super.created();
+ instanceChanged(oldValue) {
+ if (instance != null) {
+ // We load typeClass and typeArguments because we want to
+ // display this info.
+ if (instance.typeClass != null) {
+ instance.typeClass.load();
+ }
+ if (instance.typeArguments != null) {
+ instance.typeArguments.load();
+ }
+ }
+ }
+
Future<ServiceObject> evaluate(String expression) {
return instance.evaluate(expression);
}
diff --git a/runtime/observatory/lib/src/elements/instance_view.html b/runtime/observatory/lib/src/elements/instance_view.html
index f54059f..77e84f9 100644
--- a/runtime/observatory/lib/src/elements/instance_view.html
+++ b/runtime/observatory/lib/src/elements/instance_view.html
@@ -69,6 +69,57 @@
</div>
</div>
</template>
+ <template if="{{ instance.typeArguments.length > 0 }}">
+ <div class="memberItem">
+ <div class="memberName">type arguments</div>
+ <div class="memberValue">
+ <
+ <template repeat="{{ index in instance.typeArguments['types'].asMap().keys }}">
+ <instance-ref ref="{{ instance.typeArguments['types'][index] }}">
+ </instance-ref>
+ <template if="{{ index < instance.typeArguments['types'].length - 1 }}">
+ ,
+ </template>
+ </template>
+ >
+ </div>
+ </div>
+ </template>
+ <template if="{{ instance.parameterizedClass != null }}">
+ <div class="memberItem">
+ <div class="memberName">parameterized class</div>
+ <div class="memberValue">
+ <class-ref ref="{{ instance.parameterizedClass }}">
+ </class-ref>
+ </div>
+ </div>
+ </template>
+ <template if="{{ instance.parameterIndex != null }}">
+ <div class="memberItem">
+ <div class="memberName">parameter index</div>
+ <div class="memberValue">
+ {{ instance.parameterIndex }}
+ </div>
+ </div>
+ </template>
+ <template if="{{ instance.targetType != null }}">
+ <div class="memberItem">
+ <div class="memberName">target type</div>
+ <div class="memberValue">
+ <instance-ref ref="{{ instance.targetType }}">
+ </instance-ref>
+ </div>
+ </div>
+ </template>
+ <template if="{{ instance.bound != null }}">
+ <div class="memberItem">
+ <div class="memberName">bound</div>
+ <div class="memberValue">
+ <instance-ref ref="{{ instance.bound }}">
+ </instance-ref>
+ </div>
+ </div>
+ </template>
<template if="{{ instance.isClosure }}">
<div class="memberItem">
@@ -109,6 +160,12 @@
<eval-link callback="{{ evaluate }}" expr="toString()"></eval-link>
</div>
</div>
+ <div class="memberItem">
+ <div class="memberName">runtimeType</div>
+ <div class="memberValue">
+ <eval-link callback="{{ evaluate }}" expr="runtimeType"></eval-link>
+ </div>
+ </div>
</div>
</div>
@@ -300,6 +357,9 @@
<template if="{{ instance.isClosure }}">
<source-inset location="{{ instance.function.location }}"></source-inset>
</template>
+ <template if="{{ instance.typeClass != null }}">
+ <source-inset location="{{ instance.typeClass.location }}"></source-inset>
+ </template>
</div>
</template>
diff --git a/runtime/observatory/lib/src/elements/isolate_view.html b/runtime/observatory/lib/src/elements/isolate_view.html
index b090fdd..a2fe66d 100644
--- a/runtime/observatory/lib/src/elements/isolate_view.html
+++ b/runtime/observatory/lib/src/elements/isolate_view.html
@@ -90,6 +90,10 @@
<div class="memberName">isolate id</div>
<div class="memberValue">{{ isolate.number }}</div>
</div>
+ <div class="memberItem">
+ <div class="memberName">service protocol extensions</div>
+ <div class="memberValue">{{ isolate.extensionRPCs }}</div>
+ </div>
</div>
</div>
</div>
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index 6528c8d..1b94f38 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -386,15 +386,19 @@
return Utils.formatPercent(totalTicks, sampleCount);
}
- double _percent() {
+ double _percent(bool self) {
if (sampleCount == 0) {
return 0.0;
}
- return totalTicks / sampleCount;
+ if (self) {
+ return selfTicks / sampleCount;
+ } else {
+ return totalTicks / sampleCount;
+ }
}
- bool get isHot => _percent() > kHotThreshold;
- bool get isMedium => _percent() > kMediumThreshold;
+ bool isHot(bool self) => _percent(self) > kHotThreshold;
+ bool isMedium(bool self) => _percent(self) > kMediumThreshold;
}
/// Box with script source code in it.
@@ -1140,9 +1144,9 @@
e.text = lineProfile.formattedTotalTicks;
}
- if (lineProfile.isHot) {
+ if (lineProfile.isHot(self)) {
e.classes.add('hotProfile');
- } else if (lineProfile.isMedium) {
+ } else if (lineProfile.isMedium(self)) {
e.classes.add('mediumProfile');
} else {
e.classes.add('coldProfile');
diff --git a/runtime/observatory/lib/src/elements/timeline_page.dart b/runtime/observatory/lib/src/elements/timeline_page.dart
index 7a70c11..cdcb1d7 100644
--- a/runtime/observatory/lib/src/elements/timeline_page.dart
+++ b/runtime/observatory/lib/src/elements/timeline_page.dart
@@ -47,6 +47,8 @@
}
Future refresh() async {
+ await app.vm.reload();
+ await app.vm.reloadIsolates();
return postMessage('refresh');
}
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 19a086c..f36683b 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1365,11 +1365,12 @@
}
}
- Stream fetchHeapSnapshot() {
+ Stream fetchHeapSnapshot(collectGarbage) {
if (_snapshotFetch == null || _snapshotFetch.isClosed) {
_snapshotFetch = new StreamController();
// isolate.vm.streamListen('_Graph');
- isolate.invokeRpcNoUpgrade('_requestHeapSnapshot', {});
+ isolate.invokeRpcNoUpgrade('_requestHeapSnapshot',
+ {'collectGarbage': collectGarbage});
}
return _snapshotFetch.stream;
}
@@ -2180,6 +2181,9 @@
@reflectable final interfaces = new ObservableList<Instance>();
@reflectable final subclasses = new ObservableList<Class>();
+ @observable Instance superType;
+ @observable Instance mixin;
+
bool get canCache => true;
bool get immutable => false;
@@ -2243,6 +2247,9 @@
if (superclass != null && superclass.name == "Object") {
superclass._addSubclass(this);
}
+ superType = map['superType'];
+ mixin = map['mixin'];
+
error = map['error'];
traceAllocations =
@@ -2292,11 +2299,17 @@
@observable bool valueAsStringIsTruncated;
@observable ServiceFunction function; // If a closure.
@observable Context context; // If a closure.
- @observable String name; // If a Type.
@observable int length; // If a List, Map or TypedData.
@observable Instance pattern; // If a RegExp.
- @observable var typeClass;
+ @observable String name;
+ @observable Class typeClass;
+ @observable Class parameterizedClass;
+ @observable ServiceObject typeArguments;
+ @observable int parameterIndex;
+ @observable Instance targetType;
+ @observable Instance bound;
+
@observable var fields;
@observable var nativeFields;
@observable var elements; // If a List.
@@ -2440,6 +2453,12 @@
}
}
typeClass = map['typeClass'];
+ parameterizedClass = map['parameterizedClass'];
+ typeArguments = map['typeArguments'];
+ parameterIndex = map['parameterIndex'];
+ targetType = map['targetType'];
+ bound = map['bound'];
+
referent = map['mirrorReferent'];
key = map['propertyKey'];
value = map['propertyValue'];
diff --git a/runtime/observatory/tests/service/crash_dump_test.dart b/runtime/observatory/tests/service/crash_dump_test.dart
index 8b60567..0d9d178 100644
--- a/runtime/observatory/tests/service/crash_dump_test.dart
+++ b/runtime/observatory/tests/service/crash_dump_test.dart
@@ -18,9 +18,11 @@
var tests = [
(VM vm) async {
HttpClient client = new HttpClient();
+ print('Requesting uri ${serviceHttpAddress}/_getCrashDump');
var request =
await client.getUrl(Uri.parse('$serviceHttpAddress/_getCrashDump'));
var response = await request.close();
+ print('Received response');
Completer completer = new Completer();
StringBuffer sb = new StringBuffer();
response.transform(UTF8.decoder).listen((chunk) {
diff --git a/runtime/observatory/tests/service/dominator_tree_test.dart b/runtime/observatory/tests/service/dominator_tree_test.dart
index a778f62..5c279c9 100644
--- a/runtime/observatory/tests/service/dominator_tree_test.dart
+++ b/runtime/observatory/tests/service/dominator_tree_test.dart
@@ -57,7 +57,7 @@
var tests = [
(Isolate isolate) async {
var rootLib = await isolate.rootLibrary.load();
- var snapshot = await isolate.fetchHeapSnapshot().last;
+ var snapshot = await isolate.fetchHeapSnapshot(false).last;
node(String className) {
var cls = rootLib.classes.singleWhere((cls) => cls.name == className);
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index a98c535..2f45f3a 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -441,7 +441,7 @@
expect(result['id'], startsWith('objects/'));
expect(result['valueAsString'], isNull);
expect(result['class']['type'], equals('@Class'));
- expect(result['class']['name'], equals('_Uint8Array'));
+ expect(result['class']['name'], equals('Uint8List'));
expect(result['size'], isPositive);
expect(result['fields'], isEmpty);
expect(result['length'], equals(3));
@@ -467,7 +467,7 @@
expect(result['id'], startsWith('objects/'));
expect(result['valueAsString'], isNull);
expect(result['class']['type'], equals('@Class'));
- expect(result['class']['name'], equals('_Uint8Array'));
+ expect(result['class']['name'], equals('Uint8List'));
expect(result['size'], isPositive);
expect(result['fields'], isEmpty);
expect(result['length'], equals(3));
@@ -494,7 +494,7 @@
expect(result['id'], startsWith('objects/'));
expect(result['valueAsString'], isNull);
expect(result['class']['type'], equals('@Class'));
- expect(result['class']['name'], equals('_Uint8Array'));
+ expect(result['class']['name'], equals('Uint8List'));
expect(result['size'], isPositive);
expect(result['fields'], isEmpty);
expect(result['length'], equals(3));
@@ -521,7 +521,7 @@
expect(result['id'], startsWith('objects/'));
expect(result['valueAsString'], isNull);
expect(result['class']['type'], equals('@Class'));
- expect(result['class']['name'], equals('_Uint8Array'));
+ expect(result['class']['name'], equals('Uint8List'));
expect(result['size'], isPositive);
expect(result['fields'], isEmpty);
expect(result['length'], equals(3));
@@ -544,7 +544,7 @@
expect(result['id'], startsWith('objects/'));
expect(result['valueAsString'], isNull);
expect(result['class']['type'], equals('@Class'));
- expect(result['class']['name'], equals('_Uint64Array'));
+ expect(result['class']['name'], equals('Uint64List'));
expect(result['size'], isPositive);
expect(result['fields'], isEmpty);
expect(result['length'], equals(3));
@@ -570,7 +570,7 @@
expect(result['id'], startsWith('objects/'));
expect(result['valueAsString'], isNull);
expect(result['class']['type'], equals('@Class'));
- expect(result['class']['name'], equals('_Uint64Array'));
+ expect(result['class']['name'], equals('Uint64List'));
expect(result['size'], isPositive);
expect(result['fields'], isEmpty);
expect(result['length'], equals(3));
@@ -597,7 +597,7 @@
expect(result['id'], startsWith('objects/'));
expect(result['valueAsString'], isNull);
expect(result['class']['type'], equals('@Class'));
- expect(result['class']['name'], equals('_Uint64Array'));
+ expect(result['class']['name'], equals('Uint64List'));
expect(result['size'], isPositive);
expect(result['fields'], isEmpty);
expect(result['length'], equals(3));
@@ -624,7 +624,7 @@
expect(result['id'], startsWith('objects/'));
expect(result['valueAsString'], isNull);
expect(result['class']['type'], equals('@Class'));
- expect(result['class']['name'], equals('_Uint64Array'));
+ expect(result['class']['name'], equals('Uint64List'));
expect(result['size'], isPositive);
expect(result['fields'], isEmpty);
expect(result['length'], equals(3));
diff --git a/runtime/observatory/tests/service/graph_test.dart b/runtime/observatory/tests/service/graph_test.dart
index fe31d16..424747b 100644
--- a/runtime/observatory/tests/service/graph_test.dart
+++ b/runtime/observatory/tests/service/graph_test.dart
@@ -42,7 +42,7 @@
Class fooClass = lib.classes.first;
fooId = fooClass.vmCid;
- HeapSnapshot snapshot = await isolate.fetchHeapSnapshot().last;
+ HeapSnapshot snapshot = await isolate.fetchHeapSnapshot(false).last;
ObjectGraph graph = snapshot.graph;
expect(fooId, isNotNull);
diff --git a/runtime/observatory/web/timeline.js b/runtime/observatory/web/timeline.js
index 9bdf46a..402723d 100644
--- a/runtime/observatory/web/timeline.js
+++ b/runtime/observatory/web/timeline.js
@@ -55,15 +55,21 @@
function fetchTimelineOnLoad(event) {
var xhr = event.target;
var response = JSON.parse(xhr.responseText);
- var result = response['result'];
- var newStackFrames = result['stackFrames']; // Map.
- var newTraceEvents = result['traceEvents']; // List.
- // Merge in timeline events.
- traceObject.traceEvents = traceObject.traceEvents.concat(newTraceEvents);
- for (var key in newStackFrames) {
- if (newStackFrames.hasOwnProperty(key)) {
- traceObject.stackFrames[key] = newStackFrames[key];
+ if (response.error) {
+ // Maybe profiling is disabled.
+ console.log("ERROR " + response.error.message);
+ } else {
+ var result = response['result'];
+ var newStackFrames = result['stackFrames']; // Map.
+ var newTraceEvents = result['traceEvents']; // List.
+
+ // Merge in timeline events.
+ traceObject.traceEvents = traceObject.traceEvents.concat(newTraceEvents);
+ for (var key in newStackFrames) {
+ if (newStackFrames.hasOwnProperty(key)) {
+ traceObject.stackFrames[key] = newStackFrames[key];
+ }
}
}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index c8a025f..62cc6da 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -91,6 +91,7 @@
[ $runtime == dart_product || $runtime == dart_precompiled ]
dart/data_uri_spawn_test: SkipByDesign # Isolate.spawnUri
+dart/optimized_stacktrace_test: SkipByDesign # Requires line numbers
[ $runtime == vm && $mode == product ]
cc/IsolateSetCheckedMode: Fail,OK # Expects exact type name.
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 07da822..f9f418b 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -82,7 +82,7 @@
INIT_LIBRARY(ObjectStore::kTypedData,
typed_data,
Bootstrap::typed_data_source_paths_,
- Bootstrap::typed_data_patch_paths_),
+ NULL),
INIT_LIBRARY(ObjectStore::kVMService,
_vmservice,
Bootstrap::_vmservice_source_paths_,
@@ -132,9 +132,9 @@
const uint8_t* utf8_array = NULL;
intptr_t file_length = -1;
- Dart_FileOpenCallback file_open = Isolate::file_open_callback();
- Dart_FileReadCallback file_read = Isolate::file_read_callback();
- Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+ Dart_FileOpenCallback file_open = Dart::file_open_callback();
+ Dart_FileReadCallback file_read = Dart::file_read_callback();
+ Dart_FileCloseCallback file_close = Dart::file_close_callback();
if ((file_open != NULL) && (file_read != NULL) && (file_close != NULL)) {
// Try to open and read the file.
void* stream = (*file_open)(source_path, false);
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 03f2869..1e79c57 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -99,12 +99,12 @@
V(Double_toStringAsExponential, 2) \
V(Double_toStringAsPrecision, 2) \
V(Double_flipSignBit, 1) \
- V(JSSyntaxRegExp_factory, 4) \
- V(JSSyntaxRegExp_getPattern, 1) \
- V(JSSyntaxRegExp_getIsMultiLine, 1) \
- V(JSSyntaxRegExp_getIsCaseSensitive, 1) \
- V(JSSyntaxRegExp_getGroupCount, 1) \
- V(JSSyntaxRegExp_ExecuteMatch, 3) \
+ V(RegExp_factory, 4) \
+ V(RegExp_getPattern, 1) \
+ V(RegExp_getIsMultiLine, 1) \
+ V(RegExp_getIsCaseSensitive, 1) \
+ V(RegExp_getGroupCount, 1) \
+ V(RegExp_ExecuteMatch, 3) \
V(List_allocate, 2) \
V(List_getIndexed, 2) \
V(List_setIndexed, 3) \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 81860b2..1a256cd 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -456,10 +456,9 @@
}
-RawAbstractType* ClassFinalizer::ResolveTypeClass(const Class& cls,
- const Type& type) {
+void ClassFinalizer::ResolveTypeClass(const Class& cls, const Type& type) {
if (type.IsFinalized()) {
- return type.raw();
+ return;
}
if (FLAG_trace_type_finalization) {
THR_Print("Resolve type class of '%s'\n",
@@ -489,66 +488,61 @@
"cannot resolve class '%s' from '%s'",
String::Handle(unresolved_class.Name()).ToCString(),
String::Handle(cls.Name()).ToCString());
- return type.raw();
+ return;
}
+ // Replace unresolved class with resolved type class.
+ type.set_type_class(type_class);
}
- // Promote the Type to a FunctionType in case its type class is a typedef.
- if (type_class.IsTypedefClass()) {
- return FunctionType::New(type_class,
- TypeArguments::Handle(type.arguments()),
- Function::Handle(type_class.signature_function()),
- type.token_pos());
+ // Promote the type to a function type in case its type class is a typedef.
+ // Note that the type may already be a function type if it was parsed as a
+ // formal parameter function type.
+ if (!type.IsFunctionType() &&
+ type_class.IsTypedefClass() &&
+ !type.IsMalformedOrMalbounded()) {
+ type.set_signature(Function::Handle(type_class.signature_function()));
}
- // Replace unresolved class with resolved type class.
- type.set_type_class(type_class);
- return type.raw();
+ ASSERT(!type_class.IsTypedefClass() ||
+ (type.signature() != Function::null()));
}
-RawAbstractType* ClassFinalizer::ResolveType(const Class& cls,
- const AbstractType& type) {
+void ClassFinalizer::ResolveType(const Class& cls, const AbstractType& type) {
if (type.IsResolved()) {
- return type.raw();
+ return;
}
if (FLAG_trace_type_finalization) {
THR_Print("Resolve type '%s'\n", String::Handle(type.Name()).ToCString());
}
- AbstractType& resolved_type = AbstractType::Handle();
if (type.IsType()) {
- resolved_type = ResolveTypeClass(cls, Type::Cast(type));
- if (resolved_type.IsMalformed()) {
- ASSERT(resolved_type.IsResolved());
- return resolved_type.raw();
+ ResolveTypeClass(cls, Type::Cast(type));
+ if (type.IsMalformed()) {
+ ASSERT(type.IsResolved());
+ return;
}
- } else {
- ASSERT(type.IsFunctionType());
- const Function& signature =
- Function::Handle(FunctionType::Cast(type).signature());
- const Class& scope_class =
- Class::Handle(FunctionType::Cast(type).scope_class());
- if (scope_class.IsTypedefClass()) {
- ResolveSignature(scope_class, signature);
- } else {
- ResolveSignature(cls, signature);
- }
- resolved_type = type.raw();
}
- // Mark type as resolved before resolving its type arguments in order to avoid
- // repeating resolution of recursive types.
- resolved_type.SetIsResolved();
+ // Mark type as resolved before resolving its type arguments and, in case of a
+ // function type, its signature, in order to avoid cycles.
+ type.SetIsResolved();
// Resolve type arguments, if any.
- const TypeArguments& arguments =
- TypeArguments::Handle(resolved_type.arguments());
+ const TypeArguments& arguments = TypeArguments::Handle(type.arguments());
if (!arguments.IsNull()) {
const intptr_t num_arguments = arguments.Length();
AbstractType& type_argument = AbstractType::Handle();
for (intptr_t i = 0; i < num_arguments; i++) {
type_argument = arguments.TypeAt(i);
- type_argument = ResolveType(cls, type_argument);
- arguments.SetTypeAt(i, type_argument);
+ ResolveType(cls, type_argument);
}
}
- return resolved_type.raw();
+ // Resolve signature if function type.
+ if (type.IsFunctionType()) {
+ const Function& signature = Function::Handle(Type::Cast(type).signature());
+ const Class& scope_class = Class::Handle(type.type_class());
+ if (scope_class.IsTypedefClass()) {
+ ResolveSignature(scope_class, signature);
+ } else {
+ ResolveSignature(cls, signature);
+ }
+ }
}
@@ -654,13 +648,13 @@
const Class& cls,
const AbstractType& type,
PendingTypes* pending_types) {
- Zone* Z = Thread::Current()->zone();
+ Zone* zone = Thread::Current()->zone();
// The type class does not need to be finalized in order to finalize the type,
// however, it must at least be resolved (this was done as part of resolving
// the type itself, a precondition to calling FinalizeType).
// Also, the interfaces of the type class must be resolved and the type
// parameters of the type class must be finalized.
- Class& type_class = Class::Handle(Z, type.type_class());
+ Class& type_class = Class::Handle(zone, type.type_class());
if (!type_class.is_type_finalized()) {
FinalizeTypeParameters(type_class, pending_types);
ResolveUpperBounds(type_class);
@@ -673,18 +667,18 @@
// If we are not reifying types, drop type arguments.
if (!FLAG_reify) {
- type.set_arguments(TypeArguments::Handle(Z, TypeArguments::null()));
+ type.set_arguments(TypeArguments::Handle(zone, TypeArguments::null()));
}
// Initialize the type argument vector.
// Check the number of parsed type arguments, if any.
// Specifying no type arguments indicates a raw type, which is not an error.
// However, type parameter bounds are checked below, even for a raw type.
- TypeArguments& arguments = TypeArguments::Handle(Z, type.arguments());
+ TypeArguments& arguments = TypeArguments::Handle(zone, type.arguments());
if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) {
// Wrong number of type arguments. The type is mapped to the raw type.
if (Isolate::Current()->error_on_bad_type()) {
- const String& type_class_name = String::Handle(Z, type_class.Name());
+ const String& type_class_name = String::Handle(zone, type_class.Name());
ReportError(cls, type.token_pos(),
"wrong number of type arguments for class '%s'",
type_class_name.ToCString());
@@ -704,7 +698,7 @@
// The full type argument vector consists of the type arguments of the
// super types of type_class, which are initialized from the parsed
// type arguments, followed by the parsed type arguments.
- TypeArguments& full_arguments = TypeArguments::Handle(Z);
+ TypeArguments& full_arguments = TypeArguments::Handle(zone);
if (FLAG_reify && (num_type_arguments > 0)) {
// If no type arguments were parsed and if the super types do not prepend
// type arguments to the vector, we can leave the vector as null.
@@ -714,7 +708,7 @@
// argument vector.
const intptr_t offset = num_type_arguments - num_type_parameters;
AbstractType& type_arg =
- AbstractType::Handle(Z, Type::DynamicType());
+ AbstractType::Handle(zone, Type::DynamicType());
// Leave the temporary type arguments at indices [0..offset[ as null.
for (intptr_t i = 0; i < num_type_parameters; i++) {
// If no type parameters were provided, a raw type is desired, so we
@@ -746,8 +740,8 @@
}
}
if (offset > 0) {
- TrailPtr instantiation_trail = new Trail(Z, 4);
- Error& bound_error = Error::Handle(Z);
+ TrailPtr instantiation_trail = new Trail(zone, 4);
+ Error& bound_error = Error::Handle(zone);
FinalizeTypeArguments(type_class, full_arguments, offset,
&bound_error, pending_types, instantiation_trail);
}
@@ -768,8 +762,8 @@
!full_arguments.IsRaw(0, num_type_arguments));
if (FLAG_trace_type_finalization) {
THR_Print("Marking type '%s' as finalized for class '%s'\n",
- String::Handle(Z, type.Name()).ToCString(),
- String::Handle(Z, cls.Name()).ToCString());
+ String::Handle(zone, type.Name()).ToCString(),
+ String::Handle(zone, cls.Name()).ToCString());
}
// Mark the type as finalized.
type.SetIsFinalized();
@@ -846,7 +840,7 @@
super_type_arg = super_type_args.TypeAt(i);
if (!super_type_arg.IsTypeRef()) {
if (super_type_arg.IsBeingFinalized()) {
- ASSERT(super_type_arg.IsType() || super_type_arg.IsFunctionType());
+ ASSERT(super_type_arg.IsType());
CheckRecursiveType(cls, super_type_arg, pending_types);
if (FLAG_trace_type_finalization) {
THR_Print("Creating TypeRef '%s': '%s'\n",
@@ -1005,8 +999,7 @@
TypeParameter::Cast(type_arg).parameterized_class());
AbstractType& bound = AbstractType::Handle(
TypeParameter::Cast(type_arg).bound());
- bound = ResolveType(type_arg_cls, bound);
- TypeParameter::Cast(type_arg).set_bound(bound);
+ ResolveType(type_arg_cls, bound);
}
// This may be called only if type needs to be finalized, therefore
// seems OK to allocate finalized types in old space.
@@ -1033,21 +1026,21 @@
void ClassFinalizer::CheckTypeBounds(const Class& cls,
const AbstractType& type) {
- Zone* Z = Thread::Current()->zone();
- ASSERT(type.IsType() || type.IsFunctionType());
+ Zone* zone = Thread::Current()->zone();
+ ASSERT(type.IsType());
ASSERT(type.IsFinalized());
ASSERT(!type.IsCanonical());
- TypeArguments& arguments = TypeArguments::Handle(Z, type.arguments());
+ TypeArguments& arguments = TypeArguments::Handle(zone, type.arguments());
if (arguments.IsNull()) {
return;
}
if (FLAG_trace_type_finalization) {
THR_Print("Checking bounds of type '%s' for class '%s'\n",
- String::Handle(Z, type.Name()).ToCString(),
- String::Handle(Z, cls.Name()).ToCString());
+ String::Handle(zone, type.Name()).ToCString(),
+ String::Handle(zone, cls.Name()).ToCString());
}
- const Class& type_class = Class::Handle(Z, type.type_class());
- Error& bound_error = Error::Handle(Z);
+ const Class& type_class = Class::Handle(zone, type.type_class());
+ Error& bound_error = Error::Handle(zone);
CheckTypeArgumentBounds(type_class, arguments, &bound_error);
// CheckTypeArgumentBounds may have indirectly canonicalized this type.
if (!type.IsCanonical()) {
@@ -1056,22 +1049,22 @@
// The bound error will be ignored in production mode.
if (!bound_error.IsNull()) {
// No compile-time error during finalization.
- const String& type_name = String::Handle(Z, type.UserVisibleName());
+ const String& type_name = String::Handle(zone, type.UserVisibleName());
FinalizeMalboundedType(bound_error,
- Script::Handle(Z, cls.script()),
+ Script::Handle(zone, cls.script()),
type,
"type '%s' has an out of bound type argument",
type_name.ToCString());
if (FLAG_trace_type_finalization) {
THR_Print("Marking type '%s' as malbounded: %s\n",
- String::Handle(Z, type.Name()).ToCString(),
+ String::Handle(zone, type.Name()).ToCString(),
bound_error.ToErrorCString());
}
}
}
if (FLAG_trace_type_finalization) {
THR_Print("Done checking bounds of type '%s': %s\n",
- String::Handle(Z, type.Name()).ToCString(),
+ String::Handle(zone, type.Name()).ToCString(),
type.ToCString());
}
}
@@ -1091,7 +1084,7 @@
if ((finalization >= kCanonicalize) &&
!type.IsMalformed() &&
!type.IsCanonical() &&
- (type.IsType() || type.IsFunctionType())) {
+ type.IsType()) {
CheckTypeBounds(cls, type);
return type.Canonicalize();
}
@@ -1109,25 +1102,24 @@
// encountered here.
ASSERT(!type.IsBeingFinalized());
- Zone* Z = Thread::Current()->zone();
- const AbstractType& resolved_type =
- AbstractType::Handle(Z, ResolveType(cls, type));
+ Zone* zone = Thread::Current()->zone();
+ ResolveType(cls, type);
// A malformed type gets mapped to a finalized type.
- if (resolved_type.IsMalformed()) {
- ASSERT(resolved_type.IsFinalized());
- return resolved_type.raw();
+ if (type.IsMalformed()) {
+ ASSERT(type.IsFinalized());
+ return type.raw();
}
if (FLAG_trace_type_finalization) {
THR_Print("Finalizing type '%s' for class '%s'\n",
- String::Handle(Z, resolved_type.Name()).ToCString(),
- String::Handle(Z, cls.Name()).ToCString());
+ String::Handle(zone, type.Name()).ToCString(),
+ String::Handle(zone, cls.Name()).ToCString());
}
- if (resolved_type.IsTypeParameter()) {
- const TypeParameter& type_parameter = TypeParameter::Cast(resolved_type);
+ if (type.IsTypeParameter()) {
+ const TypeParameter& type_parameter = TypeParameter::Cast(type);
const Class& parameterized_class =
- Class::Handle(Z, type_parameter.parameterized_class());
+ Class::Handle(zone, type_parameter.parameterized_class());
ASSERT(!parameterized_class.IsNull());
// The index must reflect the position of this type parameter in the type
// arguments vector of its parameterized class. The offset to add is the
@@ -1147,7 +1139,7 @@
if (FLAG_trace_type_finalization) {
THR_Print("Done finalizing type parameter '%s' with index %" Pd "\n",
- String::Handle(Z, type_parameter.name()).ToCString(),
+ String::Handle(zone, type_parameter.name()).ToCString(),
type_parameter.index());
}
@@ -1155,18 +1147,18 @@
return type_parameter.raw();
}
- // At this point, we can only have a Type or a FunctionType.
- ASSERT(resolved_type.IsType() || resolved_type.IsFunctionType());
+ // At this point, we can only have a Type.
+ ASSERT(type.IsType());
// This type is the root type of the type graph if no pending types queue is
// allocated yet.
const bool is_root_type = (pending_types == NULL);
if (is_root_type) {
- pending_types = new PendingTypes(Z, 4);
+ pending_types = new PendingTypes(zone, 4);
}
const intptr_t num_expanded_type_arguments =
- ExpandAndFinalizeTypeArguments(cls, resolved_type, pending_types);
+ ExpandAndFinalizeTypeArguments(cls, type, pending_types);
// If we are done finalizing a graph of mutually recursive types, check their
// bounds.
@@ -1179,18 +1171,18 @@
}
}
- // If the type is a FunctionType, we also need to finalize the types in its
+ // If the type is a function type, we also need to finalize the types in its
// signature, i.e. finalize the result type and parameter types of the
// signature function of this function type.
// We do this after marking this type as finalized in order to allow a
// function type to refer to itself via its parameter types and result type.
// Note that we do not instantiate these types according to the type
// arguments. This will happen on demand when executing a type test.
- if (resolved_type.IsFunctionType()) {
+ if (type.IsFunctionType()) {
const Function& signature =
- Function::Handle(Z, FunctionType::Cast(resolved_type).signature());
+ Function::Handle(zone, Type::Cast(type).signature());
const Class& scope_class =
- Class::Handle(Z, FunctionType::Cast(resolved_type).scope_class());
+ Class::Handle(zone, Type::Cast(type).type_class());
if (scope_class.IsTypedefClass()) {
FinalizeSignature(scope_class, signature);
} else {
@@ -1200,24 +1192,24 @@
if (FLAG_trace_type_finalization) {
THR_Print("Done finalizing type '%s' with %" Pd " type args: %s\n",
- String::Handle(Z, resolved_type.Name()).ToCString(),
+ String::Handle(zone, type.Name()).ToCString(),
num_expanded_type_arguments,
- resolved_type.ToCString());
+ type.ToCString());
}
if (finalization >= kCanonicalize) {
if (FLAG_trace_type_finalization) {
THR_Print("Canonicalizing type '%s'\n",
- String::Handle(Z, resolved_type.Name()).ToCString());
+ String::Handle(zone, type.Name()).ToCString());
AbstractType& canonical_type =
- AbstractType::Handle(Z, resolved_type.Canonicalize());
+ AbstractType::Handle(zone, type.Canonicalize());
THR_Print("Done canonicalizing type '%s'\n",
- String::Handle(Z, canonical_type.Name()).ToCString());
+ String::Handle(zone, canonical_type.Name()).ToCString());
return canonical_type.raw();
}
- return resolved_type.Canonicalize();
+ return type.Canonicalize();
} else {
- return resolved_type.raw();
+ return type.raw();
}
}
@@ -1228,18 +1220,12 @@
AbstractType& type = AbstractType::Handle(function.result_type());
// It is not a compile time error if this name does not resolve to a class or
// interface.
- AbstractType& resolved_type = AbstractType::Handle(ResolveType(cls, type));
- if (resolved_type.raw() != type.raw()) {
- function.set_result_type(resolved_type);
- }
+ ResolveType(cls, type);
// Resolve formal parameter types.
const intptr_t num_parameters = function.NumParameters();
for (intptr_t i = 0; i < num_parameters; i++) {
type = function.ParameterTypeAt(i);
- resolved_type = ResolveType(cls, type);
- if (resolved_type.raw() != type.raw()) {
- function.SetParameterTypeAt(i, resolved_type);
- }
+ ResolveType(cls, type);
}
}
@@ -1330,8 +1316,7 @@
for (intptr_t i = 0; i < num_type_params; i++) {
type_param ^= type_params.TypeAt(i);
bound = type_param.bound();
- bound = ResolveType(cls, bound);
- type_param.set_bound(bound);
+ ResolveType(cls, bound);
}
}
@@ -1382,14 +1367,14 @@
// instance method.
// Resolve type of fields and check for conflicts in super classes.
- Zone* Z = Thread::Current()->zone();
- Array& array = Array::Handle(Z, cls.fields());
- Field& field = Field::Handle(Z);
- AbstractType& type = AbstractType::Handle(Z);
- String& name = String::Handle(Z);
- String& getter_name = String::Handle(Z);
- String& setter_name = String::Handle(Z);
- Class& super_class = Class::Handle(Z);
+ Zone* zone = Thread::Current()->zone();
+ Array& array = Array::Handle(zone, cls.fields());
+ Field& field = Field::Handle(zone);
+ AbstractType& type = AbstractType::Handle(zone);
+ String& name = String::Handle(zone);
+ String& getter_name = String::Handle(zone);
+ String& setter_name = String::Handle(zone);
+ Class& super_class = Class::Handle(zone);
const intptr_t num_fields = array.Length();
for (intptr_t i = 0; i < num_fields; i++) {
field ^= array.At(i);
@@ -1401,15 +1386,15 @@
getter_name = Field::GetterSymbol(name);
super_class = FindSuperOwnerOfInstanceMember(cls, name, getter_name);
if (!super_class.IsNull()) {
- const String& class_name = String::Handle(Z, cls.Name());
- const String& super_class_name = String::Handle(Z, super_class.Name());
+ const String& class_name = String::Handle(zone, cls.Name());
+ const String& super_cls_name = String::Handle(zone, super_class.Name());
ReportError(cls, field.token_pos(),
"static field '%s' of class '%s' conflicts with "
"instance member '%s' of super class '%s'",
name.ToCString(),
class_name.ToCString(),
name.ToCString(),
- super_class_name.ToCString());
+ super_cls_name.ToCString());
}
// An implicit setter is not generated for a static field, therefore, we
// cannot rely on the code below handling the static setter case to report
@@ -1417,15 +1402,15 @@
setter_name = Field::SetterSymbol(name);
super_class = FindSuperOwnerOfFunction(cls, setter_name);
if (!super_class.IsNull()) {
- const String& class_name = String::Handle(Z, cls.Name());
- const String& super_class_name = String::Handle(Z, super_class.Name());
+ const String& class_name = String::Handle(zone, cls.Name());
+ const String& super_cls_name = String::Handle(zone, super_class.Name());
ReportError(cls, field.token_pos(),
"static field '%s' of class '%s' conflicts with "
"instance setter '%s=' of super class '%s'",
name.ToCString(),
class_name.ToCString(),
name.ToCString(),
- super_class_name.ToCString());
+ super_cls_name.ToCString());
}
} else {
@@ -1433,15 +1418,15 @@
// (but not getter).
super_class = FindSuperOwnerOfFunction(cls, name);
if (!super_class.IsNull()) {
- const String& class_name = String::Handle(Z, cls.Name());
- const String& super_class_name = String::Handle(Z, super_class.Name());
+ const String& class_name = String::Handle(zone, cls.Name());
+ const String& super_cls_name = String::Handle(zone, super_class.Name());
ReportError(cls, field.token_pos(),
"field '%s' of class '%s' conflicts with method '%s' "
"of super class '%s'",
name.ToCString(),
class_name.ToCString(),
name.ToCString(),
- super_class_name.ToCString());
+ super_cls_name.ToCString());
}
}
if (field.is_static() &&
@@ -1449,14 +1434,14 @@
(field.StaticValue() != Object::sentinel().raw())) {
// The parser does not preset the value if the type is a type parameter or
// is parameterized unless the value is null.
- Error& error = Error::Handle(Z);
+ Error& error = Error::Handle(zone);
if (type.IsMalformedOrMalbounded()) {
error = type.error();
} else {
ASSERT(type.IsInstantiated());
}
const Instance& const_value =
- Instance::Handle(Z, field.StaticValue());
+ Instance::Handle(zone, field.StaticValue());
if (!error.IsNull() ||
(!type.IsDynamicType() &&
!const_value.IsInstanceOf(type,
@@ -1464,10 +1449,11 @@
&error))) {
if (Isolate::Current()->error_on_bad_type()) {
const AbstractType& const_value_type = AbstractType::Handle(
- Z, const_value.GetType());
+ zone, const_value.GetType());
const String& const_value_type_name = String::Handle(
- Z, const_value_type.UserVisibleName());
- const String& type_name = String::Handle(Z, type.UserVisibleName());
+ zone, const_value_type.UserVisibleName());
+ const String& type_name = String::Handle(
+ zone, type.UserVisibleName());
ReportErrors(error, cls, field.token_pos(),
"error initializing static %s field '%s': "
"type '%s' is not a subtype of type '%s'",
@@ -1485,7 +1471,7 @@
// we create an implicit static final getter and reset the field value
// to the sentinel value.
const Function& getter = Function::Handle(
- Z,
+ zone,
Function::New(getter_name,
RawFunction::kImplicitStaticFinalGetter,
/* is_static = */ true,
@@ -1504,22 +1490,22 @@
}
}
// Collect interfaces, super interfaces, and super classes of this class.
- GrowableArray<const Class*> interfaces(Z, 4);
+ GrowableArray<const Class*> interfaces(zone, 4);
CollectInterfaces(cls, &interfaces);
// Include superclasses in list of interfaces and super interfaces.
super_class = cls.SuperClass();
while (!super_class.IsNull()) {
- interfaces.Add(&Class::ZoneHandle(Z, super_class.raw()));
+ interfaces.Add(&Class::ZoneHandle(zone, super_class.raw()));
CollectInterfaces(super_class, &interfaces);
super_class = super_class.SuperClass();
}
// Resolve function signatures and check for conflicts in super classes and
// interfaces.
array = cls.functions();
- Function& function = Function::Handle(Z);
- Function& overridden_function = Function::Handle(Z);
+ Function& function = Function::Handle(zone);
+ Function& overridden_function = Function::Handle(zone);
const intptr_t num_functions = array.Length();
- Error& error = Error::Handle(Z);
+ Error& error = Error::Handle(zone);
for (intptr_t i = 0; i < num_functions; i++) {
function ^= array.At(i);
FinalizeSignature(cls, function);
@@ -1537,15 +1523,15 @@
if (!overridden_function.IsNull() &&
!function.HasCompatibleParametersWith(overridden_function,
&error)) {
- const String& class_name = String::Handle(Z, cls.Name());
- const String& super_class_name =
- String::Handle(Z, super_class->Name());
+ const String& class_name = String::Handle(zone, cls.Name());
+ const String& super_cls_name =
+ String::Handle(zone, super_class->Name());
ReportErrors(error, cls, function.token_pos(),
"class '%s' overrides method '%s' of super "
"class '%s' with incompatible parameters",
class_name.ToCString(),
name.ToCString(),
- super_class_name.ToCString());
+ super_cls_name.ToCString());
}
}
}
@@ -1553,16 +1539,16 @@
if (function.is_static()) {
super_class = FindSuperOwnerOfFunction(cls, name);
if (!super_class.IsNull()) {
- const String& class_name = String::Handle(Z, cls.Name());
- const String& super_class_name =
- String::Handle(Z, super_class.Name());
+ const String& class_name = String::Handle(zone, cls.Name());
+ const String& super_cls_name =
+ String::Handle(zone, super_class.Name());
ReportError(cls, function.token_pos(),
"static setter '%s=' of class '%s' conflicts with "
"instance setter '%s=' of super class '%s'",
name.ToCString(),
class_name.ToCString(),
name.ToCString(),
- super_class_name.ToCString());
+ super_cls_name.ToCString());
}
}
continue;
@@ -1576,8 +1562,8 @@
if (function.is_static()) {
super_class = FindSuperOwnerOfInstanceMember(cls, name, getter_name);
if (!super_class.IsNull()) {
- const String& class_name = String::Handle(Z, cls.Name());
- const String& super_class_name = String::Handle(Z, super_class.Name());
+ const String& class_name = String::Handle(zone, cls.Name());
+ const String& super_cls_name = String::Handle(zone, super_class.Name());
ReportError(cls, function.token_pos(),
"static %s '%s' of class '%s' conflicts with "
"instance member '%s' of super class '%s'",
@@ -1586,7 +1572,7 @@
name.ToCString(),
class_name.ToCString(),
name.ToCString(),
- super_class_name.ToCString());
+ super_cls_name.ToCString());
}
if (function.IsRedirectingFactory()) {
// The function may be a still unresolved redirecting factory. Do not
@@ -1594,7 +1580,7 @@
// However, the redirection type should be finalized.
// If the redirection type is from a deferred library and is not
// yet loaded, do not attempt to resolve.
- Type& type = Type::Handle(Z, function.RedirectionType());
+ Type& type = Type::Handle(zone, function.RedirectionType());
if (IsLoaded(type)) {
type ^= FinalizeType(cls, type, kCanonicalize);
function.SetRedirectionType(type);
@@ -1604,15 +1590,15 @@
function.IsImplicitGetterFunction()) {
super_class = FindSuperOwnerOfFunction(cls, name);
if (!super_class.IsNull()) {
- const String& class_name = String::Handle(Z, cls.Name());
- const String& super_class_name = String::Handle(Z, super_class.Name());
+ const String& class_name = String::Handle(zone, cls.Name());
+ const String& super_cls_name = String::Handle(zone, super_class.Name());
ReportError(cls, function.token_pos(),
"getter '%s' of class '%s' conflicts with "
"method '%s' of super class '%s'",
name.ToCString(),
class_name.ToCString(),
name.ToCString(),
- super_class_name.ToCString());
+ super_cls_name.ToCString());
}
} else if (!function.IsSetterFunction() &&
!function.IsImplicitSetterFunction()) {
@@ -1620,15 +1606,15 @@
// have the same name. Thus, we do not need to check setters.
super_class = FindSuperOwnerOfFunction(cls, getter_name);
if (!super_class.IsNull()) {
- const String& class_name = String::Handle(Z, cls.Name());
- const String& super_class_name = String::Handle(Z, super_class.Name());
+ const String& class_name = String::Handle(zone, cls.Name());
+ const String& super_cls_name = String::Handle(zone, super_class.Name());
ReportError(cls, function.token_pos(),
"method '%s' of class '%s' conflicts with "
"getter '%s' of super class '%s'",
name.ToCString(),
class_name.ToCString(),
name.ToCString(),
- super_class_name.ToCString());
+ super_cls_name.ToCString());
}
}
}
@@ -2362,7 +2348,7 @@
}
if (cls.IsTypedefClass()) {
const Function& signature = Function::Handle(cls.signature_function());
- FunctionType& type = FunctionType::Handle(signature.SignatureType());
+ Type& type = Type::Handle(signature.SignatureType());
// Check for illegal self references.
GrowableArray<intptr_t> visited_aliases;
@@ -2590,15 +2576,14 @@
const AbstractType& type,
GrowableArray<intptr_t>* visited) {
ASSERT(visited != NULL);
- AbstractType& resolved_type = AbstractType::Handle(ResolveType(cls, type));
+ ResolveType(cls, type);
bool checking_typedef = false;
- if ((resolved_type.IsType() || resolved_type.IsFunctionType()) &&
- !resolved_type.IsMalformed()) {
+ if (type.IsType() && !type.IsMalformed()) {
AbstractType& other_type = AbstractType::Handle();
- if (resolved_type.IsFunctionType()) {
- const Class& scope_class = Class::Handle(resolved_type.type_class());
+ if (type.IsFunctionType()) {
+ const Class& scope_class = Class::Handle(type.type_class());
const Function& signature_function =
- Function::Handle(FunctionType::Cast(resolved_type).signature());
+ Function::Handle(Type::Cast(type).signature());
// The signature function of this function type may be a local signature
// function used in a formal parameter type of the typedef signature, but
// not the typedef signature function itself, thus not qualifying as an
@@ -2645,8 +2630,7 @@
}
}
}
- const TypeArguments& type_args =
- TypeArguments::Handle(resolved_type.arguments());
+ const TypeArguments& type_args = TypeArguments::Handle(type.arguments());
if (!type_args.IsNull()) {
for (intptr_t i = 0; i < type_args.Length(); i++) {
other_type = type_args.TypeAt(i);
@@ -2746,7 +2730,7 @@
GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
AbstractType& mixin_super_type =
AbstractType::Handle(zone, mixin_app_type.super_type());
- mixin_super_type = ResolveType(cls, mixin_super_type);
+ ResolveType(cls, mixin_super_type);
ASSERT(mixin_super_type.HasResolvedTypeClass()); // Even if malformed.
if (mixin_super_type.IsMalformedOrMalbounded()) {
ReportError(Error::Handle(zone, mixin_super_type.error()));
@@ -2770,7 +2754,7 @@
for (intptr_t i = 0; i < depth; i++) {
mixin_type = mixin_app_type.MixinTypeAt(i);
ASSERT(!mixin_type.IsNull());
- mixin_type = ResolveType(cls, mixin_type);
+ ResolveType(cls, mixin_type);
ASSERT(mixin_type.HasResolvedTypeClass()); // Even if malformed.
ASSERT(mixin_type.IsType());
const intptr_t num_super_type_args = type_args.Length();
@@ -2931,7 +2915,7 @@
Class& interface_class = Class::Handle(zone);
// Resolve super type. Failures lead to a longjmp.
- super_type = ResolveType(cls, super_type);
+ ResolveType(cls, super_type);
if (super_type.IsMalformedOrMalbounded()) {
ReportError(Error::Handle(zone, super_type.error()));
}
@@ -3011,7 +2995,7 @@
// Resolve interfaces. Failures lead to a longjmp.
for (intptr_t i = 0; i < super_interfaces.Length(); i++) {
interface ^= super_interfaces.At(i);
- interface = ResolveType(cls, interface);
+ ResolveType(cls, interface);
ASSERT(!interface.IsTypeParameter()); // Should be detected by parser.
// A malbounded interface is only reported when involved in a type test.
if (interface.IsMalformed()) {
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index e630df0..81850f6 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -89,8 +89,8 @@
#endif // defined(DART_NO_SNAPSHOT).
// Resolve the class of the type, but not the type's type arguments.
- // May promote the type from Type to FunctionType.
- static RawAbstractType* ResolveTypeClass(const Class& cls, const Type& type);
+ // May promote the type to function type by setting its signature field.
+ static void ResolveTypeClass(const Class& cls, const Type& type);
// Resolve the type and target of the redirecting factory.
static void ResolveRedirectingFactory(const Class& cls,
@@ -111,8 +111,7 @@
static void CheckForLegalConstClass(const Class& cls);
static RawClass* ResolveClass(const Class& cls,
const UnresolvedClass& unresolved_class);
- static RawAbstractType* ResolveType(const Class& cls,
- const AbstractType& type);
+ static void ResolveType(const Class& cls, const AbstractType& type);
static void ResolveRedirectingFactoryTarget(
const Class& cls,
const Function& factory,
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 85212a7..bb7d5e0 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1262,17 +1262,17 @@
#if defined(USING_SIMULATOR)
uword stack_pos = Simulator::Current()->get_register(SPREG);
#else
- uword stack_pos = Isolate::GetCurrentStackPointer();
+ uword stack_pos = Thread::GetCurrentStackPointer();
#endif
// Always clear the stack overflow flags. They are meant for this
// particular stack overflow runtime call and are not meant to
// persist.
- uword stack_overflow_flags = isolate->GetAndClearStackOverflowFlags();
+ uword stack_overflow_flags = thread->GetAndClearStackOverflowFlags();
// If an interrupt happens at the same time as a stack overflow, we
// process the stack overflow now and leave the interrupt for next
// time.
- if (stack_pos < isolate->saved_stack_limit()) {
+ if (stack_pos < thread->saved_stack_limit()) {
// Use the preallocated stack overflow exception to avoid calling
// into dart code.
const Instance& exception =
@@ -1289,7 +1289,7 @@
// TODO(turnidge): To make --deoptimize_every and
// --stacktrace-every faster we could move this increment/test to
// the generated code.
- int32_t count = isolate->IncrementAndGetStackOverflowCount();
+ int32_t count = thread->IncrementAndGetStackOverflowCount();
if (FLAG_deoptimize_every > 0 &&
(count % FLAG_deoptimize_every) == 0) {
do_deopt = true;
@@ -1344,13 +1344,13 @@
}
}
- const Error& error = Error::Handle(isolate->HandleInterrupts());
+ const Error& error = Error::Handle(thread->HandleInterrupts());
if (!error.IsNull()) {
Exceptions::PropagateError(error);
UNREACHABLE();
}
- if ((stack_overflow_flags & Isolate::kOsrRequest) != 0) {
+ if ((stack_overflow_flags & Thread::kOsrRequest) != 0) {
ASSERT(FLAG_use_osr);
DartFrameIterator iterator;
StackFrame* frame = iterator.NextFrame();
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index dd5f71c..d7a889c 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -40,6 +40,7 @@
#include "vm/symbols.h"
#include "vm/tags.h"
#include "vm/thread_registry.h"
+#include "vm/timeline.h"
#include "vm/timer.h"
namespace dart {
@@ -278,7 +279,7 @@
NOT_IN_PRODUCT(
VMTagScope tagScope(thread, VMTag::kCompileClassTagId);
TimelineDurationScope tds(thread,
- thread->isolate()->GetCompilerStream(),
+ Timeline::GetCompilerStream(),
"CompileClass");
if (tds.enabled()) {
tds.SetNumArguments(1);
@@ -487,10 +488,12 @@
}
);
if (optimized()) {
+ bool code_was_installed = false;
// Installs code while at safepoint.
if (thread()->IsMutatorThread()) {
const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
function.InstallOptimizedCode(code, is_osr);
+ code_was_installed = true;
} else {
// Background compilation.
// Before installing code check generation counts if the code may
@@ -527,28 +530,36 @@
}
if (code_is_valid) {
const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
- ASSERT(!is_osr); // OSR is compiled in background.
+ ASSERT(!is_osr); // OSR is not compiled in background.
function.InstallOptimizedCode(code, is_osr);
+ code_was_installed = true;
}
if (function.usage_counter() < 0) {
// Reset to 0 so that it can be recompiled if needed.
- function.set_usage_counter(0);
+ if (code_is_valid) {
+ function.set_usage_counter(0);
+ } else {
+ // Trigger another optimization pass soon.
+ function.set_usage_counter(FLAG_optimization_counter_threshold - 100);
+ }
}
}
- // Register code with the classes it depends on because of CHA and
- // fields it depends on because of store guards, unless we cannot
- // deopt.
- for (intptr_t i = 0;
- i < thread()->cha()->leaf_classes().length();
- ++i) {
- thread()->cha()->leaf_classes()[i]->RegisterCHACode(code);
- }
- const ZoneGrowableArray<const Field*>& guarded_fields =
- *flow_graph->parsed_function().guarded_fields();
- for (intptr_t i = 0; i < guarded_fields.length(); i++) {
- const Field* field = guarded_fields[i];
- field->RegisterDependentCode(code);
+ if (code_was_installed) {
+ // Register code with the classes it depends on because of CHA and
+ // fields it depends on because of store guards, unless we cannot
+ // deopt.
+ for (intptr_t i = 0;
+ i < thread()->cha()->leaf_classes().length();
+ ++i) {
+ thread()->cha()->leaf_classes()[i]->RegisterCHACode(code);
+ }
+ const ZoneGrowableArray<const Field*>& guarded_fields =
+ *flow_graph->parsed_function().guarded_fields();
+ for (intptr_t i = 0; i < guarded_fields.length(); i++) {
+ const Field* field = guarded_fields[i];
+ field->RegisterDependentCode(code);
+ }
}
} else { // not optimized.
if (function.ic_data_array() == Array::null()) {
@@ -582,7 +593,7 @@
bool is_compiled = false;
Zone* const zone = thread()->zone();
NOT_IN_PRODUCT(
- TimelineStream* compiler_timeline = isolate()->GetCompilerStream());
+ TimelineStream* compiler_timeline = Timeline::GetCompilerStream());
CSTAT_TIMER_SCOPE(thread(), codegen_timer);
HANDLESCOPE(thread());
@@ -1237,8 +1248,10 @@
}
#endif
Isolate* isolate = thread->isolate();
+NOT_IN_PRODUCT(
VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId);
- TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "Function", function);
+ TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "CompileFunction", function);
+) // !PRODUCT
if (!isolate->compilation_allowed()) {
FATAL3("Precompilation missed function %s (%s, %s)\n",
@@ -1293,9 +1306,13 @@
RawError* Compiler::CompileOptimizedFunction(Thread* thread,
const Function& function,
intptr_t osr_id) {
+NOT_IN_PRODUCT(
VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId);
- TIMELINE_FUNCTION_COMPILATION_DURATION(thread,
- "OptimizedFunction", function);
+ const char* event_name = IsBackgroundCompilation()
+ ? "BackgroundCompileOptimizedFunction"
+ : "CompileOptimizedFunction";
+ TIMELINE_FUNCTION_COMPILATION_DURATION(thread, event_name, function);
+) // !PRODUCT
// Optimization must happen in non-mutator/Dart thread if background
// compilation is on. OSR compilation still occurs in the main thread.
@@ -1463,7 +1480,7 @@
false, // not abstract
false, // not external
false, // not native
- Class::Handle(Type::Handle(Type::Function()).type_class()),
+ Class::Handle(Type::Handle(Type::DartFunctionType()).type_class()),
fragment->token_pos()));
func.set_result_type(Object::dynamic_type());
@@ -1635,7 +1652,7 @@
while (running_) {
// Maybe something is already in the queue, check first before waiting
// to be notified.
- bool result = Thread::EnterIsolateAsHelper(isolate_);
+ bool result = Thread::EnterIsolateAsHelper(isolate_, Thread::kCompilerTask);
ASSERT(result);
{
Thread* thread = Thread::Current();
diff --git a/runtime/vm/coverage.cc b/runtime/vm/coverage.cc
index 2e85c3d..7a678a0 100644
--- a/runtime/vm/coverage.cc
+++ b/runtime/vm/coverage.cc
@@ -253,9 +253,9 @@
return;
}
- Dart_FileOpenCallback file_open = Isolate::file_open_callback();
- Dart_FileWriteCallback file_write = Isolate::file_write_callback();
- Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+ Dart_FileOpenCallback file_open = Dart::file_open_callback();
+ Dart_FileWriteCallback file_write = Dart::file_write_callback();
+ Dart_FileCloseCallback file_close = Dart::file_close_callback();
if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
return;
}
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 36ef3f0..9c07dc0 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -29,6 +29,7 @@
#include "vm/symbols.h"
#include "vm/thread_interrupter.h"
#include "vm/thread_pool.h"
+#include "vm/timeline.h"
#include "vm/virtual_memory.h"
#include "vm/zone.h"
@@ -51,6 +52,12 @@
ReadOnlyHandles* Dart::predefined_handles_ = NULL;
const uint8_t* Dart::instructions_snapshot_buffer_ = NULL;
const uint8_t* Dart::data_snapshot_buffer_ = NULL;
+Dart_ThreadExitCallback Dart::thread_exit_callback_ = NULL;
+Dart_FileOpenCallback Dart::file_open_callback_ = NULL;
+Dart_FileReadCallback Dart::file_read_callback_ = NULL;
+Dart_FileWriteCallback Dart::file_write_callback_ = NULL;
+Dart_FileCloseCallback Dart::file_close_callback_ = NULL;
+Dart_EntropySource Dart::entropy_source_callback_ = NULL;
// Structure for managing read-only global handles allocation used for
// creating global read-only handles that are pre created and initialized
@@ -81,6 +88,7 @@
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,
@@ -91,8 +99,9 @@
if (vm_isolate_ != NULL || !Flags::Initialized()) {
return "VM already initialized or flags not initialized.";
}
- Isolate::SetFileCallbacks(file_open, file_read, file_write, file_close);
- Isolate::SetEntropySourceCallback(entropy_source);
+ set_thread_exit_callback(thread_exit);
+ SetFileCallbacks(file_open, file_read, file_write, file_close);
+ set_entropy_source_callback(entropy_source);
OS::InitOnce();
VirtualMemory::InitOnce();
OSThread::InitOnce();
@@ -391,7 +400,9 @@
Thread* T = Thread::Current();
Isolate* I = T->isolate();
NOT_IN_PRODUCT(
- TimelineDurationScope tds(T, I->GetIsolateStream(), "InitializeIsolate");
+ TimelineDurationScope tds(T,
+ Timeline::GetIsolateStream(),
+ "InitializeIsolate");
tds.SetNumArguments(1);
tds.CopyArgument(0, "isolateName", I->name());
)
@@ -400,7 +411,7 @@
HandleScope handle_scope(T);
{
NOT_IN_PRODUCT(TimelineDurationScope tds(T,
- I->GetIsolateStream(), "ObjectStore::Init"));
+ Timeline::GetIsolateStream(), "ObjectStore::Init"));
ObjectStore::Init(I);
}
@@ -411,7 +422,7 @@
if (snapshot_buffer != NULL) {
// Read the snapshot and setup the initial state.
NOT_IN_PRODUCT(TimelineDurationScope tds(T,
- I->GetIsolateStream(), "IsolateSnapshotReader"));
+ Timeline::GetIsolateStream(), "IsolateSnapshotReader"));
// TODO(turnidge): Remove once length is not part of the snapshot.
const Snapshot* snapshot = Snapshot::SetupFromBuffer(snapshot_buffer);
if (snapshot == NULL) {
@@ -449,7 +460,7 @@
{
NOT_IN_PRODUCT(TimelineDurationScope tds(T,
- I->GetIsolateStream(), "StubCode::Init"));
+ Timeline::GetIsolateStream(), "StubCode::Init"));
StubCode::Init(I);
}
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index aa43e12..afa2499 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -26,6 +26,7 @@
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,
@@ -76,6 +77,42 @@
data_snapshot_buffer_ = buffer;
}
+ static Dart_ThreadExitCallback thread_exit_callback() {
+ return thread_exit_callback_;
+ }
+ static void set_thread_exit_callback(Dart_ThreadExitCallback cback) {
+ thread_exit_callback_ = cback;
+ }
+ static void SetFileCallbacks(Dart_FileOpenCallback file_open,
+ Dart_FileReadCallback file_read,
+ Dart_FileWriteCallback file_write,
+ Dart_FileCloseCallback file_close) {
+ file_open_callback_ = file_open;
+ file_read_callback_ = file_read;
+ file_write_callback_ = file_write;
+ file_close_callback_ = file_close;
+ }
+
+ static Dart_FileOpenCallback file_open_callback() {
+ return file_open_callback_;
+ }
+ static Dart_FileReadCallback file_read_callback() {
+ return file_read_callback_;
+ }
+ static Dart_FileWriteCallback file_write_callback() {
+ return file_write_callback_;
+ }
+ static Dart_FileCloseCallback file_close_callback() {
+ return file_close_callback_;
+ }
+
+ static void set_entropy_source_callback(Dart_EntropySource entropy_source) {
+ entropy_source_callback_ = entropy_source;
+ }
+ static Dart_EntropySource entropy_source_callback() {
+ return entropy_source_callback_;
+ }
+
private:
static void WaitForIsolateShutdown();
@@ -86,6 +123,12 @@
static ReadOnlyHandles* predefined_handles_;
static const uint8_t* instructions_snapshot_buffer_;
static const uint8_t* data_snapshot_buffer_;
+ static Dart_ThreadExitCallback thread_exit_callback_;
+ static Dart_FileOpenCallback file_open_callback_;
+ static Dart_FileReadCallback file_read_callback_;
+ static Dart_FileWriteCallback file_write_callback_;
+ static Dart_FileCloseCallback file_close_callback_;
+ static Dart_EntropySource entropy_source_callback_;
};
} // namespace dart
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 12a7fdb..cb540bc 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -78,12 +78,12 @@
#ifndef PRODUCT
#define API_TIMELINE_DURATION \
TimelineDurationScope tds(Thread::Current(), \
- Timeline::GetVMApiStream(), \
+ Timeline::GetAPIStream(), \
CURRENT_FUNC)
#define API_TIMELINE_BEGIN_END \
TimelineBeginEndScope tbes(Thread::Current(), \
- Timeline::GetVMApiStream(), \
+ Timeline::GetAPIStream(), \
CURRENT_FUNC)
#else
#define API_TIMELINE_DURATION do { } while (false)
@@ -1139,6 +1139,7 @@
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,
@@ -1160,6 +1161,7 @@
instructions_snapshot,
data_snapshot,
create, shutdown,
+ thread_exit,
file_open, file_read, file_write,
file_close, entropy_source,
get_service_assets);
@@ -3491,8 +3493,8 @@
}
Object& result = Object::Handle(Z);
result = GetByteBufferConstructor(T,
- Symbols::_ByteBuffer(),
- Symbols::_ByteBufferDot_New(),
+ Symbols::ByteBuffer(),
+ Symbols::ByteBufferDot_New(),
1);
ASSERT(!result.IsNull());
ASSERT(result.IsFunction());
@@ -5775,31 +5777,7 @@
}
-DART_EXPORT void Dart_TimelineSetRecordedStreams(int64_t stream_mask) {
- if (!FLAG_support_timeline) {
- return;
- }
- Isolate* isolate = Isolate::Current();
- CHECK_ISOLATE(isolate);
- isolate->GetAPIStream()->set_enabled(
- (stream_mask & DART_TIMELINE_STREAM_API) != 0);
- isolate->GetCompilerStream()->set_enabled(
- (stream_mask & DART_TIMELINE_STREAM_COMPILER) != 0);
- isolate->GetDartStream()->set_enabled(
- (stream_mask & DART_TIMELINE_STREAM_DART) != 0);
- isolate->GetDebuggerStream()->set_enabled(
- (stream_mask & DART_TIMELINE_STREAM_DEBUGGER) != 0);
- isolate->GetEmbedderStream()->set_enabled(
- (stream_mask & DART_TIMELINE_STREAM_EMBEDDER) != 0);
- isolate->GetGCStream()->set_enabled(
- (stream_mask & DART_TIMELINE_STREAM_GC) != 0);
- isolate->GetIsolateStream()->set_enabled(
- (stream_mask & DART_TIMELINE_STREAM_ISOLATE) != 0);
-}
-
-
DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
- // Per isolate overrides.
if (!FLAG_support_timeline) {
return;
}
@@ -5815,6 +5793,8 @@
const bool gc_enabled = (stream_mask & DART_TIMELINE_STREAM_GC) != 0;
const bool isolate_enabled =
(stream_mask & DART_TIMELINE_STREAM_ISOLATE) != 0;
+ const bool vm_enabled =
+ (stream_mask & DART_TIMELINE_STREAM_VM) != 0;
Timeline::SetStreamAPIEnabled(api_enabled);
Timeline::SetStreamCompilerEnabled(compiler_enabled);
Timeline::SetStreamDartEnabled(dart_enabled);
@@ -5822,10 +5802,7 @@
Timeline::SetStreamEmbedderEnabled(embedder_enabled);
Timeline::SetStreamGCEnabled(gc_enabled);
Timeline::SetStreamIsolateEnabled(isolate_enabled);
- // VM wide.
- const bool vm_enabled =
- (stream_mask & DART_TIMELINE_STREAM_VM) != 0;
- Timeline::GetVMStream()->set_enabled(vm_enabled);
+ Timeline::SetStreamVMEnabled(vm_enabled);
}
@@ -5924,44 +5901,14 @@
}
-DART_EXPORT bool Dart_TimelineGetTrace(Dart_StreamConsumer consumer,
- void* user_data) {
- if (!FLAG_support_timeline) {
- return false;
- }
- Isolate* isolate = Isolate::Current();
- CHECK_ISOLATE(isolate);
- if (consumer == NULL) {
- return false;
- }
- TimelineEventRecorder* timeline_recorder = Timeline::recorder();
- if (timeline_recorder == NULL) {
- // Nothing has been recorded.
- return false;
- }
- Thread* T = Thread::Current();
- StackZone zone(T);
- Timeline::ReclaimCachedBlocksFromThreads();
- JSONStream js;
- IsolateTimelineEventFilter filter(isolate->main_port());
- timeline_recorder->PrintTraceEvent(&js, &filter);
- StartStreamToConsumer(consumer, user_data, "timeline");
- bool success = StreamTraceEvents(consumer, user_data, &js);
- FinishStreamToConsumer(consumer, user_data, "timeline");
- return success;
-}
-
-
DART_EXPORT void Dart_SetEmbedderTimelineCallbacks(
Dart_EmbedderTimelineStartRecording start_recording,
- Dart_EmbedderTimelineStopRecording stop_recording,
- Dart_EmbedderTimelineGetTimeline get_timeline) {
+ Dart_EmbedderTimelineStopRecording stop_recording) {
if (!FLAG_support_timeline) {
return;
}
Timeline::set_start_recording_cb(start_recording);
Timeline::set_stop_recording_cb(stop_recording);
- Timeline::set_get_timeline_cb(get_timeline);
}
@@ -5996,67 +5943,105 @@
}
-DART_EXPORT Dart_Handle Dart_TimelineDuration(const char* label,
- int64_t start_micros,
- int64_t end_micros) {
+DART_EXPORT void Dart_TimelineEvent(const char* label,
+ int64_t timestamp0,
+ int64_t timestamp1,
+ Dart_Timeline_Event_Type type,
+ intptr_t argument_count,
+ const char** argument_names,
+ const char** argument_values) {
if (!FLAG_support_timeline) {
- return Api::Success();
+ return;
}
- Isolate* isolate = Isolate::Current();
- CHECK_ISOLATE(isolate);
- if (label == NULL) {
- RETURN_NULL_ERROR(label);
+ if (type < Dart_Timeline_Event_Begin) {
+ return;
+ }
+ if (type > Dart_Timeline_Event_Duration) {
+ return;
+ }
+ TimelineStream* stream = Timeline::GetEmbedderStream();
+ ASSERT(stream != NULL);
+ TimelineEvent* event = stream->StartEvent();
+ if (event == NULL) {
+ return;
+ }
+ switch (type) {
+ case Dart_Timeline_Event_Begin:
+ event->Begin(label, timestamp0);
+ break;
+ case Dart_Timeline_Event_End:
+ event->End(label, timestamp0);
+ break;
+ case Dart_Timeline_Event_Instant:
+ event->Instant(label, timestamp0);
+ break;
+ case Dart_Timeline_Event_Duration:
+ event->Duration(label, timestamp0, timestamp1);
+ break;
+ default:
+ FATAL("Unknown Dart_Timeline_Event_Type");
+ }
+ event->SetNumArguments(argument_count);
+ for (intptr_t i = 0; i < argument_count; i++) {
+ event->CopyArgument(i, argument_names[i], argument_values[i]);
+ }
+ event->Complete();
+}
+
+
+DART_EXPORT void Dart_TimelineDuration(const char* label,
+ int64_t start_micros,
+ int64_t end_micros) {
+ if (!FLAG_support_timeline) {
+ return;
}
if (start_micros > end_micros) {
- const char* msg = "%s: start_micros must be <= end_micros";
- return Api::NewError(msg, CURRENT_FUNC);
+ FATAL1("%s: start_micros must be <= end_micros", CURRENT_FUNC);
}
- TimelineStream* stream = isolate->GetEmbedderStream();
+ if (label == NULL) {
+ return;
+ }
+ TimelineStream* stream = Timeline::GetEmbedderStream();
ASSERT(stream != NULL);
TimelineEvent* event = stream->StartEvent();
if (event != NULL) {
event->Duration(label, start_micros, end_micros);
event->Complete();
}
- return Api::Success();
}
-DART_EXPORT Dart_Handle Dart_TimelineInstant(const char* label) {
+DART_EXPORT void Dart_TimelineInstant(const char* label) {
if (!FLAG_support_timeline) {
- return Api::Success();
+ return;
}
- Isolate* isolate = Isolate::Current();
- CHECK_ISOLATE(isolate);
if (label == NULL) {
- RETURN_NULL_ERROR(label);
+ return;
}
- TimelineStream* stream = isolate->GetEmbedderStream();
+ TimelineStream* stream = Timeline::GetEmbedderStream();
ASSERT(stream != NULL);
TimelineEvent* event = stream->StartEvent();
if (event != NULL) {
event->Instant(label);
event->Complete();
}
- return Api::Success();
+ return;
}
-DART_EXPORT Dart_Handle Dart_TimelineAsyncBegin(const char* label,
- int64_t* async_id) {
+DART_EXPORT void Dart_TimelineAsyncBegin(const char* label,
+ int64_t* async_id) {
if (!FLAG_support_timeline) {
- return Api::Success();
+ return;
}
- Isolate* isolate = Isolate::Current();
- CHECK_ISOLATE(isolate);
if (label == NULL) {
- RETURN_NULL_ERROR(label);
+ return;
}
if (async_id == NULL) {
- RETURN_NULL_ERROR(async_id);
+ return;
}
*async_id = -1;
- TimelineStream* stream = isolate->GetEmbedderStream();
+ TimelineStream* stream = Timeline::GetEmbedderStream();
ASSERT(stream != NULL);
TimelineEvent* event = stream->StartEvent();
if (event != NULL) {
@@ -6066,55 +6051,51 @@
event->AsyncBegin(label, *async_id);
event->Complete();
}
- return Api::Success();
+ return;
}
-DART_EXPORT Dart_Handle Dart_TimelineAsyncInstant(const char* label,
- int64_t async_id) {
+DART_EXPORT void Dart_TimelineAsyncInstant(const char* label,
+ int64_t async_id) {
if (!FLAG_support_timeline) {
- return Api::Success();
+ return;
}
if (async_id < 0) {
- return Api::Success();
+ return;
}
- Isolate* isolate = Isolate::Current();
- CHECK_ISOLATE(isolate);
if (label == NULL) {
- RETURN_NULL_ERROR(label);
+ return;
}
- TimelineStream* stream = isolate->GetEmbedderStream();
+ TimelineStream* stream = Timeline::GetEmbedderStream();
ASSERT(stream != NULL);
TimelineEvent* event = stream->StartEvent();
if (event != NULL) {
event->AsyncInstant(label, async_id);
event->Complete();
}
- return Api::Success();
+ return;
}
-DART_EXPORT Dart_Handle Dart_TimelineAsyncEnd(const char* label,
- int64_t async_id) {
+DART_EXPORT void Dart_TimelineAsyncEnd(const char* label,
+ int64_t async_id) {
if (!FLAG_support_timeline) {
- return Api::Success();
+ return;
}
if (async_id < 0) {
- return Api::Success();
+ return;
}
- Isolate* isolate = Isolate::Current();
- CHECK_ISOLATE(isolate);
if (label == NULL) {
- RETURN_NULL_ERROR(label);
+ return;
}
- TimelineStream* stream = isolate->GetEmbedderStream();
+ TimelineStream* stream = Timeline::GetEmbedderStream();
ASSERT(stream != NULL);
TimelineEvent* event = stream->StartEvent();
if (event != NULL) {
event->AsyncEnd(label, async_id);
event->Complete();
}
- return Api::Success();
+ return;
}
// The precompiler is included in dart_bootstrap and dart_noopt, and
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 4be3fa9..d8d4fb0 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -14,6 +14,7 @@
#include "vm/dart_api_impl.h"
#include "vm/dart_api_state.h"
#include "vm/lockers.h"
+#include "vm/timeline.h"
#include "vm/unit_test.h"
#include "vm/verifier.h"
@@ -9190,7 +9191,7 @@
TEST_CASE(Timeline_Dart_TimelineDuration) {
Isolate* isolate = Isolate::Current();
// Grab embedder stream.
- TimelineStream* stream = isolate->GetEmbedderStream();
+ TimelineStream* stream = Timeline::GetEmbedderStream();
// Make sure it is enabled.
stream->set_enabled(true);
// Add a duration event.
@@ -9208,7 +9209,7 @@
TEST_CASE(Timeline_Dart_TimelineInstant) {
Isolate* isolate = Isolate::Current();
// Grab embedder stream.
- TimelineStream* stream = isolate->GetEmbedderStream();
+ TimelineStream* stream = Timeline::GetEmbedderStream();
// Make sure it is enabled.
stream->set_enabled(true);
Dart_TimelineInstant("testInstantEvent");
@@ -9223,9 +9224,8 @@
TEST_CASE(Timeline_Dart_TimelineAsyncDisabled) {
- Isolate* isolate = Isolate::Current();
// Grab embedder stream.
- TimelineStream* stream = isolate->GetEmbedderStream();
+ TimelineStream* stream = Timeline::GetEmbedderStream();
// Make sure it is disabled.
stream->set_enabled(false);
int64_t async_id = -1;
@@ -9247,7 +9247,7 @@
TEST_CASE(Timeline_Dart_TimelineAsync) {
Isolate* isolate = Isolate::Current();
// Grab embedder stream.
- TimelineStream* stream = isolate->GetEmbedderStream();
+ TimelineStream* stream = Timeline::GetEmbedderStream();
// Make sure it is enabled.
stream->set_enabled(true);
int64_t async_id = -1;
@@ -9315,7 +9315,7 @@
bool success = false;
// Enable recording of all streams.
- Dart_TimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL);
+ Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL);
// Invoke main, which will be compiled resulting in a compiler event in
// the timeline.
@@ -9327,7 +9327,7 @@
// Grab the trace.
AppendData data;
- success = Dart_TimelineGetTrace(AppendStreamConsumer, &data);
+ success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
EXPECT(success);
buffer = reinterpret_cast<char*>(data.buffer);
buffer_length = data.buffer_length;
@@ -9367,7 +9367,7 @@
bool success = false;
// Enable recording of the Dart stream.
- Dart_TimelineSetRecordedStreams(DART_TIMELINE_STREAM_DART);
+ Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_DART);
// Invoke main, which will add a new timeline event from Dart.
Dart_Handle result = Dart_Invoke(lib,
@@ -9380,7 +9380,7 @@
AppendData data;
data.buffer = NULL;
data.buffer_length = 0;
- success = Dart_TimelineGetTrace(AppendStreamConsumer, &data);
+ success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
EXPECT(success);
buffer = reinterpret_cast<char*>(data.buffer);
buffer_length = data.buffer_length;
@@ -9419,7 +9419,7 @@
bool success = false;
// Enable recording of all streams.
- Dart_TimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL);
+ Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL);
// Invoke main, which will be compiled resulting in a compiler event in
// the timeline.
@@ -9431,7 +9431,7 @@
// Grab the trace.
AppendData data;
- success = Dart_TimelineGetTrace(AppendStreamConsumer, &data);
+ success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
EXPECT(success);
buffer = reinterpret_cast<char*>(data.buffer);
buffer_length = data.buffer_length;
@@ -9480,7 +9480,7 @@
// Grab the trace.
AppendData data;
- success = Dart_TimelineGetTrace(AppendStreamConsumer, &data);
+ success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
EXPECT(success);
buffer = reinterpret_cast<char*>(data.buffer);
buffer_length = data.buffer_length;
@@ -9503,6 +9503,16 @@
}
+static const char* arg_names[] = {
+ "arg0"
+};
+
+
+static const char* arg_values[] = {
+ "value0"
+};
+
+
TEST_CASE(Timeline_Dart_GlobalTimelineGetTrace) {
const char* kScriptChars =
"bar() => 'z';\n"
@@ -9520,6 +9530,17 @@
lib = TestCase::LoadTestScript(kScriptChars, NULL);
}
+ {
+ // Add something to the embedder stream.
+ Dart_TimelineEvent("TRACE_EVENT",
+ Dart_TimelineGetMicros(),
+ 0,
+ Dart_Timeline_Event_Begin,
+ 1,
+ &arg_names[0],
+ &arg_values[0]);
+ }
+
// Invoke main, which will be compiled resulting in a compiler event in
// the timeline.
Dart_Handle result = Dart_Invoke(lib,
@@ -9559,6 +9580,9 @@
EXPECT_SUBSTRING("\"name\":\"CompileFunction\"", buffer);
EXPECT_SUBSTRING("\"function\":\"::_main\"", buffer);
EXPECT_NOTSUBSTRING("\"function\":\"::_bar\"", buffer);
+ EXPECT_SUBSTRING("TRACE_EVENT", buffer);
+ EXPECT_SUBSTRING("arg0", buffer);
+ EXPECT_SUBSTRING("value0", buffer);
// Free buffer allocated by AppendStreamConsumer
free(data.buffer);
@@ -9786,7 +9810,7 @@
TEST_CASE(Timeline_Dart_EmbedderTimelineStartStopRecording) {
- Dart_SetEmbedderTimelineCallbacks(StartRecording, StopRecording, NULL);
+ Dart_SetEmbedderTimelineCallbacks(StartRecording, StopRecording);
EXPECT(!start_called);
EXPECT(!stop_called);
@@ -9803,37 +9827,6 @@
EXPECT(stop_called);
}
-static bool GetTimeline(Dart_StreamConsumer stream_consumer,
- void* user_data) {
- ASSERT(stream_consumer != NULL);
- ASSERT(user_data != NULL);
-
- const char* test_string = "HELLO FROM EMBEDDER";
- stream_consumer(Dart_StreamConsumer_kData,
- "embedder.timeline",
- reinterpret_cast<const uint8_t*>(test_string),
- strlen(test_string),
- user_data);
- return true;
-}
-
-TEST_CASE(Timeline_Dart_EmbedderTimelineGetTimeline) {
- Dart_SetEmbedderTimelineCallbacks(NULL, NULL, GetTimeline);
-
- Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_EMBEDDER);
- Dart_TimelineDuration("testDurationEvent", 0, 1);
-
- AppendData data;
- bool success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
- EXPECT(success);
-
- EXPECT_SUBSTRING("}},HELLO FROM EMBEDDER",
- data.buffer);
-
- // Free buffer allocated by AppendStreamConsumer
- free(data.buffer);
-}
-
#endif // !PRODUCT
} // namespace dart
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 3845949..e8bc0ce 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -41,25 +41,23 @@
// grows from high to low addresses).
OSThread* os_thread = thread->os_thread();
ASSERT(os_thread != NULL);
- uword current_sp = Isolate::GetCurrentStackPointer();
+ uword current_sp = Thread::GetCurrentStackPointer();
if (current_sp > os_thread->stack_base()) {
os_thread->set_stack_base(current_sp);
}
- // Save the Isolate's current stack limit and adjust the stack
+ // Save the Thread's current stack limit and adjust the stack
// limit based on the thread's stack_base.
- Isolate* isolate = thread->isolate();
- ASSERT(isolate == Isolate::Current());
- saved_stack_limit_ = isolate->saved_stack_limit();
- isolate->SetStackLimitFromStackBase(os_thread->stack_base());
+ ASSERT(thread->isolate() == Isolate::Current());
+ saved_stack_limit_ = thread->saved_stack_limit();
+ thread->SetStackLimitFromStackBase(os_thread->stack_base());
}
~ScopedIsolateStackLimits() {
- Isolate* isolate = thread_->isolate();
- ASSERT(isolate == Isolate::Current());
+ ASSERT(thread_->isolate() == Isolate::Current());
// Since we started with a stack limit of 0 we should be getting back
// to a stack limit of 0 when all nested invocations are done and
// we have bottomed out.
- isolate->SetStackLimit(saved_stack_limit_);
+ thread_->SetStackLimit(saved_stack_limit_);
}
private:
@@ -167,12 +165,13 @@
while (!cls.IsNull()) {
function ^= cls.LookupDynamicFunction(getter_name);
if (!function.IsNull()) {
- Isolate* isolate = Isolate::Current();
- volatile uword c_stack_pos = Isolate::GetCurrentStackPointer();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
+ volatile uword c_stack_pos = Thread::GetCurrentStackPointer();
volatile uword c_stack_limit = OSThread::Current()->stack_base() -
OSThread::GetSpecifiedStackSize();
#if !defined(USING_SIMULATOR)
- ASSERT(c_stack_limit == isolate->saved_stack_limit());
+ ASSERT(c_stack_limit == thread->saved_stack_limit());
#endif
if (c_stack_pos < c_stack_limit) {
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 2739006..e9951c8 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -27,6 +27,7 @@
#include "vm/stub_code.h"
#include "vm/symbols.h"
#include "vm/thread_interrupter.h"
+#include "vm/timeline.h"
#include "vm/token_position.h"
#include "vm/visitor.h"
@@ -2558,7 +2559,7 @@
Thread* thread = Thread::Current();
DisableThreadInterruptsScope dtis(thread);
TimelineDurationScope tds(thread,
- isolate_->GetDebuggerStream(),
+ Timeline::GetDebuggerStream(),
"Debugger Pause");
InvokeEventHandler(event);
}
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 1aa11b7..8b0aa72 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -139,8 +139,7 @@
deferred_objects_ = NULL;
deferred_objects_count_ = 0;
if (FLAG_support_timeline && (deopt_start_micros_ != 0)) {
- Isolate* isolate = Isolate::Current();
- TimelineStream* compiler_stream = isolate->GetCompilerStream();
+ TimelineStream* compiler_stream = Timeline::GetCompilerStream();
ASSERT(compiler_stream != NULL);
if (compiler_stream->Enabled()) {
// Allocate all Dart objects needed before calling StartEvent,
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index e55edd0..e2fa84e 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -238,7 +238,7 @@
StubCode::JumpToExceptionHandler_entry()->EntryPoint());
// Unpoison the stack before we tear it down in the generated stub code.
- uword current_sp = Isolate::GetCurrentStackPointer() - 1024;
+ uword current_sp = Thread::GetCurrentStackPointer() - 1024;
ASAN_UNPOISON(reinterpret_cast<void*>(current_sp),
stack_pointer - current_sp);
@@ -493,12 +493,24 @@
pieces.Add(Symbols::SingleQuote());
}
// Print URIs of src and dst types.
- pieces.Add(Symbols::SpaceWhereNewLine());
+ // Do not print "where" when no URIs get printed.
+ bool printed_where = false;
if (!src_type.IsNull()) {
- pieces.Add(String::Handle(zone, src_type.EnumerateURIs()));
+ const String& uris = String::Handle(zone, src_type.EnumerateURIs());
+ if (uris.Length() > Symbols::SpaceIsFromSpace().Length()) {
+ printed_where = true;
+ pieces.Add(Symbols::SpaceWhereNewLine());
+ pieces.Add(uris);
+ }
}
if (!dst_type.IsDynamicType() && !dst_type.IsVoidType()) {
- pieces.Add(String::Handle(zone, dst_type.EnumerateURIs()));
+ const String& uris = String::Handle(zone, dst_type.EnumerateURIs());
+ if (uris.Length() > Symbols::SpaceIsFromSpace().Length()) {
+ if (!printed_where) {
+ pieces.Add(Symbols::SpaceWhereNewLine());
+ }
+ pieces.Add(uris);
+ }
}
}
}
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index c411bbd..6f7ff8d 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -2505,9 +2505,8 @@
{ LocalVariable* closure_tmp_var = EnterTempLocalScope(closure_val,
node->token_pos());
// Store type arguments if scope class is generic.
- const FunctionType& function_type =
- FunctionType::ZoneHandle(Z, function.SignatureType());
- const Class& scope_cls = Class::ZoneHandle(Z, function_type.scope_class());
+ const Type& function_type = Type::ZoneHandle(Z, function.SignatureType());
+ const Class& scope_cls = Class::ZoneHandle(Z, function_type.type_class());
if (scope_cls.IsGeneric()) {
ASSERT(function.Owner() == scope_cls.raw());
Value* closure_tmp_val = Bind(new(Z) LoadLocalInstr(*closure_tmp_var,
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index 1ca6adc..d904c86 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -255,7 +255,7 @@
void FlowGraphCompiler::InitCompiler() {
#ifndef PRODUCT
TimelineDurationScope tds(thread(),
- isolate()->GetCompilerStream(),
+ Timeline::GetCompilerStream(),
"InitCompiler");
#endif // !PRODUCT
pc_descriptors_list_ = new(zone()) DescriptorList(64);
@@ -1109,7 +1109,7 @@
*return_node.value()->AsLoadInstanceFieldNode();
// Only intrinsify getter if the field cannot contain a mutable double.
// Reading from a mutable double box requires allocating a fresh double.
- if (load_node.field().guarded_cid() == kDynamicCid) {
+ if (!IsPotentialUnboxedField(load_node.field())) {
GenerateInlinedGetter(load_node.field().Offset());
return !FLAG_use_field_guards;
}
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 247537a..9f0da1e 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -516,7 +516,7 @@
__ Bind(&fall_through);
return type_test_cache.raw();
}
- if (type.IsType() || type.IsFunctionType()) {
+ if (type.IsType()) {
const Register kInstanceReg = R0;
const Register kTypeArgumentsReg = R1;
__ tst(kInstanceReg, Operand(kSmiTagMask)); // Is instance Smi?
@@ -1367,7 +1367,7 @@
__ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize);
if (ic_data.NumArgsTested() == 1) {
__ LoadUniqueObject(R9, ic_data);
- __ BranchLinkPatchable(*StubCode::ICLookup_entry());
+ __ BranchLinkPatchable(*StubCode::ICLookupThroughFunction_entry());
} else {
const String& name = String::Handle(zone(), ic_data.target_name());
const Array& arguments_descriptor =
diff --git a/runtime/vm/flow_graph_compiler_arm64.cc b/runtime/vm/flow_graph_compiler_arm64.cc
index 4f6474c..6750d70 100644
--- a/runtime/vm/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/flow_graph_compiler_arm64.cc
@@ -508,7 +508,7 @@
__ Bind(&fall_through);
return type_test_cache.raw();
}
- if (type.IsType() || type.IsFunctionType()) {
+ if (type.IsType()) {
const Register kInstanceReg = R0;
const Register kTypeArgumentsReg = R1;
__ tsti(kInstanceReg, Immediate(kSmiTagMask)); // Is instance Smi?
@@ -1347,7 +1347,7 @@
__ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize);
if (ic_data.NumArgsTested() == 1) {
__ LoadUniqueObject(R5, ic_data);
- __ BranchLinkPatchable(*StubCode::ICLookup_entry());
+ __ BranchLinkPatchable(*StubCode::ICLookupThroughFunction_entry());
} else {
const String& name = String::Handle(zone(), ic_data.target_name());
const Array& arguments_descriptor =
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index 7407ac9..fe9696f 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -520,7 +520,7 @@
__ Bind(&fall_through);
return type_test_cache.raw();
}
- if (type.IsType() || type.IsFunctionType()) {
+ if (type.IsType()) {
const Register kInstanceReg = EAX;
const Register kTypeArgumentsReg = EDX;
__ testl(kInstanceReg, Immediate(kSmiTagMask)); // Is instance Smi?
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 18b629b..c02d511 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -504,7 +504,7 @@
__ Bind(&fall_through);
return type_test_cache.raw();
}
- if (type.IsType() || type.IsFunctionType()) {
+ if (type.IsType()) {
const Register kInstanceReg = A0;
const Register kTypeArgumentsReg = A1;
__ andi(CMPRES1, kInstanceReg, Immediate(kSmiTagMask));
@@ -1374,7 +1374,7 @@
__ lw(T0, Address(SP, (argument_count - 1) * kWordSize));
if (ic_data.NumArgsTested() == 1) {
__ LoadUniqueObject(S5, ic_data);
- __ BranchLinkPatchable(*StubCode::ICLookup_entry());
+ __ BranchLinkPatchable(*StubCode::ICLookupThroughFunction_entry());
} else {
const String& name = String::Handle(zone(), ic_data.target_name());
const Array& arguments_descriptor =
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 301de20..7c5d7de 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -515,7 +515,7 @@
__ Bind(&fall_through);
return type_test_cache.raw();
}
- if (type.IsType() || type.IsFunctionType()) {
+ if (type.IsType()) {
const Register kInstanceReg = RAX;
const Register kTypeArgumentsReg = RDX;
__ testq(kInstanceReg, Immediate(kSmiTagMask)); // Is instance Smi?
@@ -1377,7 +1377,7 @@
__ movq(RDI, Address(RSP, (argument_count - 1) * kWordSize));
if (ic_data.NumArgsTested() == 1) {
__ LoadUniqueObject(RBX, ic_data);
- __ CallPatchable(*StubCode::ICLookup_entry());
+ __ CallPatchable(*StubCode::ICLookupThroughFunction_entry());
} else {
const String& name = String::Handle(zone(), ic_data.target_name());
const Array& arguments_descriptor =
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index df32f54..bd860d9 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -8,6 +8,7 @@
#include "vm/bit_vector.h"
#include "vm/il_printer.h"
#include "vm/regexp_assembler.h"
+#include "vm/timeline.h"
namespace dart {
@@ -20,8 +21,7 @@
void FlowGraphTypePropagator::Propagate(FlowGraph* flow_graph) {
#ifndef PRODUCT
Thread* thread = flow_graph->thread();
- Isolate* const isolate = flow_graph->isolate();
- TimelineStream* compiler_timeline = isolate->GetCompilerStream();
+ TimelineStream* compiler_timeline = Timeline::GetCompilerStream();
TimelineDurationScope tds2(thread,
compiler_timeline,
"FlowGraphTypePropagator");
@@ -713,7 +713,7 @@
// from being generated.
switch (index()) {
case RegExpMacroAssembler::kParamRegExpIndex:
- return CompileType::FromCid(kJSRegExpCid);
+ return CompileType::FromCid(kRegExpCid);
case RegExpMacroAssembler::kParamStringIndex:
return CompileType::FromCid(function.string_specialization_cid());
case RegExpMacroAssembler::kParamStartOffsetIndex:
@@ -981,8 +981,7 @@
ASSERT(cls().id() == kClosureCid);
return CompileType(CompileType::kNonNullable,
kClosureCid,
- &FunctionType::ZoneHandle(
- closure_function().SignatureType()));
+ &Type::ZoneHandle(closure_function().SignatureType()));
}
// TODO(vegorov): Incorporate type arguments into the returned type.
return CompileType::FromCid(cls().id());
@@ -1009,8 +1008,9 @@
const AbstractType* abstract_type = NULL;
if (Isolate::Current()->type_checks() &&
- type().HasResolvedTypeClass() &&
- !Field::IsExternalizableCid(Class::Handle(type().type_class()).id())) {
+ (type().IsFunctionType() ||
+ (type().HasResolvedTypeClass() &&
+ !Field::IsExternalizableCid(Class::Handle(type().type_class()).id())))) {
abstract_type = &type();
}
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index c9ac9fa..cc5db20 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -19,6 +19,7 @@
#include "vm/thread_barrier.h"
#include "vm/thread_pool.h"
#include "vm/thread_registry.h"
+#include "vm/timeline.h"
#include "vm/visitor.h"
#include "vm/object_id_ring.h"
@@ -599,10 +600,13 @@
}
virtual void Run() {
- bool result = Thread::EnterIsolateAsHelper(isolate_, true);
+ bool result =
+ Thread::EnterIsolateAsHelper(isolate_, Thread::kMarkerTask, true);
ASSERT(result);
{
- StackZone stack_zone(Thread::Current());
+ Thread* thread = Thread::Current();
+ TIMELINE_FUNCTION_GC_DURATION(thread, "MarkTask");
+ StackZone stack_zone(thread);
Zone* zone = stack_zone.GetZone();
SkippedCodeFunctions* skipped_code_functions =
collect_code_ ? new(zone) SkippedCodeFunctions() : NULL;
diff --git a/runtime/vm/gc_sweeper.cc b/runtime/vm/gc_sweeper.cc
index 0dcf62f..5b7949b 100644
--- a/runtime/vm/gc_sweeper.cc
+++ b/runtime/vm/gc_sweeper.cc
@@ -11,6 +11,7 @@
#include "vm/pages.h"
#include "vm/safepoint.h"
#include "vm/thread_pool.h"
+#include "vm/timeline.h"
namespace dart {
@@ -114,32 +115,36 @@
}
virtual void Run() {
- bool result = Thread::EnterIsolateAsHelper(task_isolate_);
+ bool result = Thread::EnterIsolateAsHelper(task_isolate_,
+ Thread::kSweeperTask);
ASSERT(result);
- Thread* thread = Thread::Current();
- GCSweeper sweeper;
+ {
+ Thread* thread = Thread::Current();
+ TIMELINE_FUNCTION_GC_DURATION(thread, "SweeperTask");
+ GCSweeper sweeper;
- HeapPage* page = first_;
- HeapPage* prev_page = NULL;
+ HeapPage* page = first_;
+ HeapPage* prev_page = NULL;
- while (page != NULL) {
- thread->CheckForSafepoint();
- HeapPage* next_page = page->next();
- ASSERT(page->type() == HeapPage::kData);
- bool page_in_use = sweeper.SweepPage(page, freelist_, false);
- if (page_in_use) {
- prev_page = page;
- } else {
- old_space_->FreePage(page, prev_page);
+ while (page != NULL) {
+ thread->CheckForSafepoint();
+ HeapPage* next_page = page->next();
+ ASSERT(page->type() == HeapPage::kData);
+ bool page_in_use = sweeper.SweepPage(page, freelist_, false);
+ if (page_in_use) {
+ prev_page = page;
+ } else {
+ old_space_->FreePage(page, prev_page);
+ }
+ {
+ // Notify the mutator thread that we have added elements to the free
+ // list or that more capacity is available.
+ MonitorLocker ml(old_space_->tasks_lock());
+ ml.Notify();
+ }
+ if (page == last_) break;
+ page = next_page;
}
- {
- // Notify the mutator thread that we have added elements to the free
- // list or that more capacity is available.
- MonitorLocker ml(old_space_->tasks_lock());
- ml.Notify();
- }
- if (page == last_) break;
- page = next_page;
}
// Exit isolate cleanly *before* notifying it, to avoid shutdown race.
Thread::ExitIsolateAsHelper();
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index b34af54..138e9b1 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -224,7 +224,7 @@
ASSERT(old_space_->iterating_thread_ != thread());
#endif
while (old_space_->tasks() > 0) {
- ml.Wait();
+ ml.WaitWithSafepointCheck(thread());
}
#if defined(DEBUG)
ASSERT(old_space_->iterating_thread_ == NULL);
@@ -367,11 +367,7 @@
bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks);
RecordBeforeGC(kNew, reason);
VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId);
-#ifndef PRODUCT
- TimelineDurationScope tds(thread,
- isolate()->GetGCStream(),
- "CollectNewGeneration");
-#endif // !PRODUCT
+ TIMELINE_FUNCTION_GC_DURATION(thread, "CollectNewGeneration");
UpdateClassHeapStatsBeforeGC(kNew);
new_space_.Scavenge(invoke_api_callbacks);
isolate()->class_table()->UpdatePromoted();
@@ -394,11 +390,7 @@
bool invoke_api_callbacks = (api_callbacks == kInvokeApiCallbacks);
RecordBeforeGC(kOld, reason);
VMTagScope tagScope(thread, VMTag::kGCOldSpaceTagId);
-#ifndef PRODUCT
- TimelineDurationScope tds(thread,
- isolate()->GetGCStream(),
- "CollectOldGeneration");
-#endif // !PRODUCT
+ TIMELINE_FUNCTION_GC_DURATION(thread, "CollectOldGeneration");
UpdateClassHeapStatsBeforeGC(kOld);
old_space_.MarkSweep(invoke_api_callbacks);
RecordAfterGC(kOld);
diff --git a/runtime/vm/instructions_x64.cc b/runtime/vm/instructions_x64.cc
index 2dc98bc..3fa610a 100644
--- a/runtime/vm/instructions_x64.cc
+++ b/runtime/vm/instructions_x64.cc
@@ -48,7 +48,11 @@
int32_t offset = *reinterpret_cast<int32_t*>(pc + 3);
return Thread::ObjectAtOffset(offset, obj);
}
- if (((bytes[0] == 0x4d) && (bytes[1] == 0x8b) && (bytes[2] == 0x5e)) ||
+ if (((bytes[0] == 0x41) && (bytes[1] == 0xff) && (bytes[2] == 0x76)) ||
+ ((bytes[0] == 0x49) && (bytes[1] == 0x3b) && (bytes[2] == 0x66)) ||
+ ((bytes[0] == 0x49) && (bytes[1] == 0x8b) && (bytes[2] == 0x46)) ||
+ ((bytes[0] == 0x4d) && (bytes[1] == 0x8b) && (bytes[2] == 0x5e)) ||
+ ((bytes[0] == 0x4d) && (bytes[1] == 0x8b) && (bytes[2] == 0x66)) ||
((bytes[0] == 0x4d) && (bytes[1] == 0x8b) && (bytes[2] == 0x6e))) {
uint8_t offset = *reinterpret_cast<uint8_t*>(pc + 3);
return Thread::ObjectAtOffset(offset, obj);
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 4f4032f..4b55595 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -3714,9 +3714,9 @@
void NativeCallInstr::SetupNative() {
- Zone* Z = Thread::Current()->zone();
- const Class& cls = Class::Handle(Z, function().Owner());
- const Library& library = Library::Handle(Z, cls.library());
+ Zone* zone = Thread::Current()->zone();
+ const Class& cls = Class::Handle(zone, function().Owner());
+ const Library& library = Library::Handle(zone, cls.library());
const int num_params =
NativeArguments::ParameterCountForResolution(function());
bool auto_setup_scope = true;
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 269b1893..6b180bd 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -2874,19 +2874,11 @@
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
if (FLAG_use_osr && osr_entry_label()->IsLinked()) {
- uword flags_address = Isolate::Current()->stack_overflow_flags_address();
const Register value = instruction_->locs()->temp(0).reg();
__ Comment("CheckStackOverflowSlowPathOsr");
__ Bind(osr_entry_label());
- if (FLAG_allow_absolute_addresses) {
- __ LoadImmediate(IP, flags_address);
- __ LoadImmediate(value, Isolate::kOsrRequest);
- __ str(value, Address(IP));
- } else {
- __ LoadIsolate(IP);
- __ LoadImmediate(value, Isolate::kOsrRequest);
- __ str(value, Address(IP, Isolate::stack_overflow_flags_offset()));
- }
+ __ LoadImmediate(value, Thread::kOsrRequest);
+ __ str(value, Address(THR, Thread::stack_overflow_flags_offset()));
}
__ Comment("CheckStackOverflowSlowPath");
__ Bind(entry_label());
@@ -2928,13 +2920,7 @@
CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
compiler->AddSlowPathCode(slow_path);
- if (compiler->is_optimizing() && FLAG_allow_absolute_addresses) {
- __ LoadImmediate(IP, Isolate::Current()->stack_limit_address());
- __ ldr(IP, Address(IP));
- } else {
- __ LoadIsolate(IP);
- __ ldr(IP, Address(IP, Isolate::stack_limit_offset()));
- }
+ __ ldr(IP, Address(THR, Thread::stack_limit_offset()));
__ cmp(SP, Operand(IP));
__ b(slow_path->entry_label(), LS);
if (compiler->CanOSRFunction() && in_loop()) {
diff --git a/runtime/vm/intermediate_language_arm64.cc b/runtime/vm/intermediate_language_arm64.cc
index f43e2bb..cb225a2 100644
--- a/runtime/vm/intermediate_language_arm64.cc
+++ b/runtime/vm/intermediate_language_arm64.cc
@@ -2584,19 +2584,11 @@
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
if (FLAG_use_osr && osr_entry_label()->IsLinked()) {
- uword flags_address = Isolate::Current()->stack_overflow_flags_address();
const Register value = instruction_->locs()->temp(0).reg();
__ Comment("CheckStackOverflowSlowPathOsr");
__ Bind(osr_entry_label());
- if (FLAG_allow_absolute_addresses) {
- __ LoadImmediate(TMP, flags_address);
- __ LoadImmediate(value, Isolate::kOsrRequest);
- __ str(value, Address(TMP));
- } else {
- __ LoadIsolate(TMP);
- __ LoadImmediate(value, Isolate::kOsrRequest);
- __ str(value, Address(TMP, Isolate::stack_overflow_flags_offset()));
- }
+ __ LoadImmediate(value, Thread::kOsrRequest);
+ __ str(value, Address(THR, Thread::stack_overflow_flags_offset()));
}
__ Comment("CheckStackOverflowSlowPath");
__ Bind(entry_label());
@@ -2638,13 +2630,7 @@
CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
compiler->AddSlowPathCode(slow_path);
- if (compiler->is_optimizing() && FLAG_allow_absolute_addresses) {
- __ LoadImmediate(TMP, Isolate::Current()->stack_limit_address());
- __ ldr(TMP, Address(TMP));
- } else {
- __ LoadIsolate(TMP);
- __ ldr(TMP, Address(TMP, Isolate::stack_limit_offset()));
- }
+ __ ldr(TMP, Address(THR, Thread::stack_limit_offset()));
__ CompareRegisters(SP, TMP);
__ b(slow_path->entry_label(), LS);
if (compiler->CanOSRFunction() && in_loop()) {
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index bd83626..a6471e1 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -2583,11 +2583,10 @@
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
if (FLAG_use_osr && osr_entry_label()->IsLinked()) {
- uword flags_address = Isolate::Current()->stack_overflow_flags_address();
__ Comment("CheckStackOverflowSlowPathOsr");
__ Bind(osr_entry_label());
- __ movl(Address::Absolute(flags_address),
- Immediate(Isolate::kOsrRequest));
+ __ movl(Address(THR, Thread::stack_overflow_flags_offset()),
+ Immediate(Thread::kOsrRequest));
}
__ Comment("CheckStackOverflowSlowPath");
__ Bind(entry_label());
@@ -2629,13 +2628,7 @@
CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
compiler->AddSlowPathCode(slow_path);
- if (compiler->is_optimizing()) {
- __ cmpl(ESP, Address::Absolute(Isolate::Current()->stack_limit_address()));
- } else {
- Register tmp = locs()->temp(0).reg();
- __ LoadIsolate(tmp);
- __ cmpl(ESP, Address(tmp, Isolate::stack_limit_offset()));
- }
+ __ cmpl(ESP, Address(THR, Thread::stack_limit_offset()));
__ j(BELOW_EQUAL, slow_path->entry_label());
if (compiler->CanOSRFunction() && in_loop()) {
// In unoptimized code check the usage counter to trigger OSR at loop
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 7799bd9..7342fb6 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -2702,19 +2702,11 @@
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
if (FLAG_use_osr && osr_entry_label()->IsLinked()) {
- uword flags_address = Isolate::Current()->stack_overflow_flags_address();
Register value = instruction_->locs()->temp(0).reg();
__ Comment("CheckStackOverflowSlowPathOsr");
__ Bind(osr_entry_label());
- if (FLAG_allow_absolute_addresses) {
- __ LoadImmediate(TMP, flags_address);
- __ LoadImmediate(value, Isolate::kOsrRequest);
- __ sw(value, Address(TMP));
- } else {
- __ LoadIsolate(TMP);
- __ LoadImmediate(value, Isolate::kOsrRequest);
- __ sw(value, Address(TMP, Isolate::stack_overflow_flags_offset()));
- }
+ __ LoadImmediate(value, Thread::kOsrRequest);
+ __ sw(value, Address(THR, Thread::stack_overflow_flags_offset()));
}
__ Comment("CheckStackOverflowSlowPath");
__ Bind(entry_label());
@@ -2757,13 +2749,7 @@
CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
compiler->AddSlowPathCode(slow_path);
- if (compiler->is_optimizing() && FLAG_allow_absolute_addresses) {
- __ LoadImmediate(TMP, Isolate::Current()->stack_limit_address());
- __ lw(CMPRES1, Address(TMP));
- } else {
- __ LoadIsolate(TMP);
- __ lw(CMPRES1, Address(TMP, Isolate::stack_limit_offset()));
- }
+ __ lw(CMPRES1, Address(THR, Thread::stack_limit_offset()));
__ BranchUnsignedLessEqual(SP, CMPRES1, slow_path->entry_label());
if (compiler->CanOSRFunction() && in_loop()) {
Register temp = locs()->temp(0).reg();
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 9623ec2..1738532 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -2602,18 +2602,10 @@
virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
if (FLAG_use_osr && osr_entry_label()->IsLinked()) {
- uword flags_address = Isolate::Current()->stack_overflow_flags_address();
- Register temp = instruction_->locs()->temp(0).reg();
__ Comment("CheckStackOverflowSlowPathOsr");
__ Bind(osr_entry_label());
- if (FLAG_allow_absolute_addresses) {
- __ LoadImmediate(temp, Immediate(flags_address));
- __ movq(Address(temp, 0), Immediate(Isolate::kOsrRequest));
- } else {
- __ LoadIsolate(TMP);
- __ movq(Address(TMP, Isolate::stack_overflow_flags_offset()),
- Immediate(Isolate::kOsrRequest));
- }
+ __ movq(Address(THR, Thread::stack_overflow_flags_offset()),
+ Immediate(Thread::kOsrRequest));
}
__ Comment("CheckStackOverflowSlowPath");
__ Bind(entry_label());
@@ -2658,14 +2650,7 @@
Register temp = locs()->temp(0).reg();
// Generate stack overflow check.
- if (compiler->is_optimizing() && FLAG_allow_absolute_addresses) {
- __ LoadImmediate(
- temp, Immediate(Isolate::Current()->stack_limit_address()));
- __ cmpq(RSP, Address(temp, 0));
- } else {
- __ LoadIsolate(temp);
- __ cmpq(RSP, Address(temp, Isolate::stack_limit_offset()));
- }
+ __ cmpq(RSP, Address(THR, Thread::stack_limit_offset()));
__ j(BELOW_EQUAL, slow_path->entry_label());
if (compiler->CanOSRFunction() && in_loop()) {
// In unoptimized code check the usage counter to trigger OSR at loop
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index 979ca87..4eeee12 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -2055,7 +2055,7 @@
}
-void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
if (FLAG_interpret_irregexp) return;
static const intptr_t kRegExpParamOffset = 2 * kWordSize;
@@ -2074,7 +2074,7 @@
__ LoadClassId(R1, R1);
__ AddImmediate(R1, R1, -kOneByteStringCid);
__ add(R1, R2, Operand(R1, LSL, kWordSizeLog2));
- __ ldr(R0, FieldAddress(R1, JSRegExp::function_offset(kOneByteStringCid)));
+ __ ldr(R0, FieldAddress(R1, RegExp::function_offset(kOneByteStringCid)));
// Registers are now set up for the lazy compile stub. It expects the function
// in R0, the argument descriptor in R4, and IC-Data in R9.
diff --git a/runtime/vm/intrinsifier_arm64.cc b/runtime/vm/intrinsifier_arm64.cc
index fa7c20d0..f8611a1 100644
--- a/runtime/vm/intrinsifier_arm64.cc
+++ b/runtime/vm/intrinsifier_arm64.cc
@@ -2130,7 +2130,7 @@
}
-void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
if (FLAG_interpret_irregexp) return;
static const intptr_t kRegExpParamOffset = 2 * kWordSize;
@@ -2149,7 +2149,7 @@
__ LoadClassId(R1, R1);
__ AddImmediate(R1, R1, -kOneByteStringCid);
__ add(R1, R2, Operand(R1, LSL, kWordSizeLog2));
- __ ldr(R0, FieldAddress(R1, JSRegExp::function_offset(kOneByteStringCid)));
+ __ ldr(R0, FieldAddress(R1, RegExp::function_offset(kOneByteStringCid)));
// Registers are now set up for the lazy compile stub. It expects the function
// in R0, the argument descriptor in R4, and IC-Data in R5.
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index ab3fcb3..4e2a8e9 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -2083,7 +2083,7 @@
}
-void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
if (FLAG_interpret_irregexp) return;
static const intptr_t kRegExpParamOffset = 3 * kWordSize;
@@ -2102,7 +2102,7 @@
__ LoadClassId(EDI, EDI);
__ SubImmediate(EDI, Immediate(kOneByteStringCid));
__ movl(EAX, FieldAddress(EBX, EDI, TIMES_4,
- JSRegExp::function_offset(kOneByteStringCid)));
+ RegExp::function_offset(kOneByteStringCid)));
// Registers are now set up for the lazy compile stub. It expects the function
// in EAX, the argument descriptor in EDX, and IC-Data in ECX.
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 3625b13..1fd65bc 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -2161,7 +2161,7 @@
}
-void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
if (FLAG_interpret_irregexp) return;
static const intptr_t kRegExpParamOffset = 2 * kWordSize;
@@ -2181,7 +2181,7 @@
__ AddImmediate(T2, -kOneByteStringCid);
__ sll(T2, T2, kWordSizeLog2);
__ addu(T2, T2, T1);
- __ lw(T0, FieldAddress(T2, JSRegExp::function_offset(kOneByteStringCid)));
+ __ lw(T0, FieldAddress(T2, RegExp::function_offset(kOneByteStringCid)));
// Registers are now set up for the lazy compile stub. It expects the function
// in T0, the argument descriptor in S4, and IC-Data in S5.
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index b3f0a73..5fd3ad7 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -2039,7 +2039,7 @@
}
-void Intrinsifier::JSRegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
if (FLAG_interpret_irregexp) return;
static const intptr_t kRegExpParamOffset = 3 * kWordSize;
@@ -2058,7 +2058,7 @@
__ LoadClassId(RDI, RDI);
__ SubImmediate(RDI, Immediate(kOneByteStringCid));
__ movq(RAX, FieldAddress(RBX, RDI, TIMES_8,
- JSRegExp::function_offset(kOneByteStringCid)));
+ RegExp::function_offset(kOneByteStringCid)));
// Registers are now set up for the lazy compile stub. It expects the function
// in RAX, the argument descriptor in R10, and IC-Data in RCX.
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 0c6a662..7678eef 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -53,7 +53,6 @@
DECLARE_FLAG(bool, print_metrics);
DECLARE_FLAG(bool, timing);
DECLARE_FLAG(bool, trace_service);
-DECLARE_FLAG(bool, trace_service_verbose);
DEFINE_FLAG(bool, trace_isolates, false,
"Trace isolate creation and shut down.");
@@ -149,12 +148,12 @@
NoOOBMessageScope::NoOOBMessageScope(Thread* thread) : StackResource(thread) {
- isolate()->DeferOOBMessageInterrupts();
+ thread->DeferOOBMessageInterrupts();
}
NoOOBMessageScope::~NoOOBMessageScope() {
- isolate()->RestoreOOBMessageInterrupts();
+ thread()->RestoreOOBMessageInterrupts();
}
@@ -432,8 +431,8 @@
void IsolateMessageHandler::MessageNotify(Message::Priority priority) {
if (priority >= Message::kOOBPriority) {
- // Handle out of band messages even if the isolate is busy.
- I->ScheduleInterrupts(Isolate::kMessageInterrupt);
+ // Handle out of band messages even if the mutator thread is busy.
+ I->ScheduleMessageInterrupts();
}
Dart_MessageNotifyCallback callback = I->message_notify_callback();
if (callback) {
@@ -451,7 +450,9 @@
Zone* zone = stack_zone.GetZone();
HandleScope handle_scope(thread);
#ifndef PRODUCT
- TimelineDurationScope tds(thread, I->GetIsolateStream(), "HandleMessage");
+ TimelineDurationScope tds(thread,
+ Timeline::GetIsolateStream(),
+ "HandleMessage");
tds.SetNumArguments(1);
tds.CopyArgument(0, "isolateName", I->name());
#endif
@@ -757,8 +758,7 @@
// TODO(srdjan): Some Isolate monitors can be shared. Replace their usage with
// that shared monitor.
Isolate::Isolate(const Dart_IsolateFlags& api_flags)
- : stack_limit_(0),
- store_buffer_(new StoreBuffer()),
+ : store_buffer_(new StoreBuffer()),
heap_(NULL),
user_tag_(0),
current_tag_(UserTag::null()),
@@ -792,11 +792,6 @@
symbols_mutex_(new Mutex()),
type_canonicalization_mutex_(new Mutex()),
constant_canonicalization_mutex_(new Mutex()),
- saved_stack_limit_(0),
- deferred_interrupts_mask_(0),
- deferred_interrupts_(0),
- stack_overflow_flags_(0),
- stack_overflow_count_(0),
message_handler_(NULL),
spawn_state_(NULL),
is_runnable_(false),
@@ -903,11 +898,6 @@
ISOLATE_METRIC_LIST(ISOLATE_METRIC_INIT);
#undef ISOLATE_METRIC_INIT
-#ifndef PRODUCT
- // Initialize Timeline streams.
- Timeline::SetupIsolateStreams(result);
-#endif // !PRODUCT
-
Heap::Init(result,
is_vm_isolate
? 0 // New gen size 0; VM isolate should only allocate in old.
@@ -979,28 +969,6 @@
}
-/* static */
-uword Isolate::GetCurrentStackPointer() {
- // Since AddressSanitizer's detect_stack_use_after_return instruments the
- // C++ code to give out fake stack addresses, we call a stub in that case.
- uword (*func)() = reinterpret_cast<uword (*)()>(
- StubCode::GetStackPointer_entry()->EntryPoint());
- // But for performance (and to support simulators), we normally use a local.
-#if defined(__has_feature)
-#if __has_feature(address_sanitizer)
- uword current_sp = func();
- return current_sp;
-#else
- uword stack_allocated_local_address = reinterpret_cast<uword>(&func);
- return stack_allocated_local_address;
-#endif
-#else
- uword stack_allocated_local_address = reinterpret_cast<uword>(&func);
- return stack_allocated_local_address;
-#endif
-}
-
-
void Isolate::SetupInstructionsSnapshotPage(
const uint8_t* instructions_snapshot_buffer) {
InstructionsSnapshot snapshot(instructions_snapshot_buffer);
@@ -1034,6 +1002,16 @@
}
+void Isolate::ScheduleMessageInterrupts() {
+ // We take the threads lock here to ensure that the mutator thread does not
+ // exit the isolate while we are trying to schedule interrupts on it.
+ MonitorLocker ml(threads_lock());
+ Thread* mthread = mutator_thread();
+ if (mthread != NULL) {
+ mthread->ScheduleInterrupts(Thread::kMessageInterrupt);
+ }
+}
+
void Isolate::set_debugger_name(const char* name) {
free(debugger_name_);
@@ -1055,36 +1033,6 @@
}
-void Isolate::SetStackLimitFromStackBase(uword stack_base) {
- // Set stack limit.
-#if defined(USING_SIMULATOR)
- // Ignore passed-in native stack top and use Simulator stack top.
- Simulator* sim = Simulator::Current(); // May allocate a simulator.
- ASSERT(simulator() == sim); // This isolate's simulator is the current one.
- stack_base = sim->StackTop();
- // The overflow area is accounted for by the simulator.
-#endif
- SetStackLimit(stack_base - OSThread::GetSpecifiedStackSize());
-}
-
-
-void Isolate::SetStackLimit(uword limit) {
- // The isolate setting the stack limit is not necessarily the isolate which
- // the stack limit is being set on.
- MutexLocker ml(mutex_);
- if (stack_limit_ == saved_stack_limit_) {
- // No interrupt pending, set stack_limit_ too.
- stack_limit_ = limit;
- }
- saved_stack_limit_ = limit;
-}
-
-
-void Isolate::ClearStackLimit() {
- SetStackLimit(~static_cast<uword>(0));
-}
-
-
void Isolate::DoneLoading() {
GrowableObjectArray& libs = GrowableObjectArray::Handle(current_zone(),
object_store()->libraries());
@@ -1126,7 +1074,7 @@
}
#ifndef PRODUCT
if (FLAG_support_timeline) {
- TimelineStream* stream = GetIsolateStream();
+ TimelineStream* stream = Timeline::GetIsolateStream();
ASSERT(stream != NULL);
TimelineEvent* event = stream->StartEvent();
if (event != NULL) {
@@ -1488,118 +1436,6 @@
}
-void Isolate::ScheduleInterrupts(uword interrupt_bits) {
- MutexLocker ml(mutex_);
- ASSERT((interrupt_bits & ~kInterruptsMask) == 0); // Must fit in mask.
-
- // Check to see if any of the requested interrupts should be deferred.
- uword defer_bits = interrupt_bits & deferred_interrupts_mask_;
- if (defer_bits != 0) {
- deferred_interrupts_ |= defer_bits;
- interrupt_bits &= ~deferred_interrupts_mask_;
- if (interrupt_bits == 0) {
- return;
- }
- }
-
- if (stack_limit_ == saved_stack_limit_) {
- stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
- }
- stack_limit_ |= interrupt_bits;
-}
-
-
-uword Isolate::GetAndClearInterrupts() {
- MutexLocker ml(mutex_);
- if (stack_limit_ == saved_stack_limit_) {
- return 0; // No interrupt was requested.
- }
- uword interrupt_bits = stack_limit_ & kInterruptsMask;
- stack_limit_ = saved_stack_limit_;
- return interrupt_bits;
-}
-
-
-void Isolate::DeferOOBMessageInterrupts() {
- MutexLocker ml(mutex_);
- ASSERT(deferred_interrupts_mask_ == 0);
- deferred_interrupts_mask_ = kMessageInterrupt;
-
- if (stack_limit_ != saved_stack_limit_) {
- // Defer any interrupts which are currently pending.
- deferred_interrupts_ = stack_limit_ & deferred_interrupts_mask_;
-
- // Clear deferrable interrupts, if present.
- stack_limit_ &= ~deferred_interrupts_mask_;
-
- if ((stack_limit_ & kInterruptsMask) == 0) {
- // No other pending interrupts. Restore normal stack limit.
- stack_limit_ = saved_stack_limit_;
- }
- }
- if (FLAG_trace_service && FLAG_trace_service_verbose) {
- OS::Print("[+%" Pd64 "ms] Isolate %s deferring OOB interrupts\n",
- Dart::timestamp(), name());
- }
-}
-
-
-void Isolate::RestoreOOBMessageInterrupts() {
- MutexLocker ml(mutex_);
- ASSERT(deferred_interrupts_mask_ == kMessageInterrupt);
- deferred_interrupts_mask_ = 0;
- if (deferred_interrupts_ != 0) {
- if (stack_limit_ == saved_stack_limit_) {
- stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
- }
- stack_limit_ |= deferred_interrupts_;
- deferred_interrupts_ = 0;
- }
- if (FLAG_trace_service && FLAG_trace_service_verbose) {
- OS::Print("[+%" Pd64 "ms] Isolate %s restoring OOB interrupts\n",
- Dart::timestamp(), name());
- }
-}
-
-
-RawError* Isolate::HandleInterrupts() {
- uword interrupt_bits = GetAndClearInterrupts();
- if ((interrupt_bits & kVMInterrupt) != 0) {
- if (store_buffer()->Overflowed()) {
- if (FLAG_verbose_gc) {
- OS::PrintErr("Scavenge scheduled by store buffer overflow.\n");
- }
- heap()->CollectGarbage(Heap::kNew);
- }
- }
- if ((interrupt_bits & kMessageInterrupt) != 0) {
- MessageHandler::MessageStatus status =
- message_handler()->HandleOOBMessages();
- if (status != MessageHandler::kOK) {
- // False result from HandleOOBMessages signals that the isolate should
- // be terminating.
- if (FLAG_trace_isolates) {
- OS::Print("[!] Terminating isolate due to OOB message:\n"
- "\tisolate: %s\n", name());
- }
- Thread* thread = Thread::Current();
- const Error& error = Error::Handle(thread->sticky_error());
- ASSERT(!error.IsNull() && error.IsUnwindError());
- thread->clear_sticky_error();
- return error.raw();
- }
- }
- return Error::null();
-}
-
-
-uword Isolate::GetAndClearStackOverflowFlags() {
- uword stack_overflow_flags = stack_overflow_flags_;
- stack_overflow_flags_ = 0;
- return stack_overflow_flags;
-}
-
-
void Isolate::AddClosureFunction(const Function& function) const {
GrowableObjectArray& closures =
GrowableObjectArray::Handle(object_store()->closure_functions());
@@ -1757,7 +1593,7 @@
Thread* thread = Thread::Current();
// Don't allow anymore dart code to execution on this isolate.
- ClearStackLimit();
+ thread->ClearStackLimit();
// First, perform higher-level cleanup that may need to allocate.
{
@@ -1813,11 +1649,6 @@
Dart_IsolateCreateCallback Isolate::create_callback_ = NULL;
Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = NULL;
-Dart_FileOpenCallback Isolate::file_open_callback_ = NULL;
-Dart_FileReadCallback Isolate::file_read_callback_ = NULL;
-Dart_FileWriteCallback Isolate::file_write_callback_ = NULL;
-Dart_FileCloseCallback Isolate::file_close_callback_ = NULL;
-Dart_EntropySource Isolate::entropy_source_callback_ = NULL;
Monitor* Isolate::isolates_list_monitor_ = NULL;
Isolate* Isolate::isolates_list_head_ = NULL;
@@ -2607,6 +2438,9 @@
sticky_error_ = thread->sticky_error();
thread->clear_sticky_error();
}
+ } else {
+ ASSERT(thread->api_top_scope_ == NULL);
+ ASSERT(thread->zone_ == NULL);
}
if (!bypass_safepoint) {
// Ensure that the thread reports itself as being at a safepoint.
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index c6a5bd9..8d2508f 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -17,7 +17,6 @@
#include "vm/tags.h"
#include "vm/thread.h"
#include "vm/os_thread.h"
-#include "vm/timeline.h"
#include "vm/timer.h"
#include "vm/token_position.h"
@@ -229,78 +228,12 @@
library_tag_handler_ = value;
}
- void SetStackLimit(uword value);
- void SetStackLimitFromStackBase(uword stack_base);
- void ClearStackLimit();
-
- // Returns the current C++ stack pointer. Equivalent taking the address of a
- // stack allocated local, but plays well with AddressSanitizer.
- // TODO(koda): Move to Thread.
- static uword GetCurrentStackPointer();
-
void SetupInstructionsSnapshotPage(
const uint8_t* instructions_snapshot_buffer);
void SetupDataSnapshotPage(
const uint8_t* instructions_snapshot_buffer);
- // Returns true if any of the interrupts specified by 'interrupt_bits' are
- // currently scheduled for this isolate, but leaves them unchanged.
- //
- // NOTE: The read uses relaxed memory ordering, i.e., it is atomic and
- // an interrupt is guaranteed to be observed eventually, but any further
- // order guarantees must be ensured by other synchronization. See the
- // tests in isolate_test.cc for example usage.
- bool HasInterruptsScheduled(uword interrupt_bits) {
- ASSERT(interrupt_bits == (interrupt_bits & kInterruptsMask));
- uword limit = AtomicOperations::LoadRelaxed(&stack_limit_);
- return (limit != saved_stack_limit_) &&
- (((limit & kInterruptsMask) & interrupt_bits) != 0);
- }
-
- // Access to the current stack limit for generated code. This may be
- // overwritten with a special value to trigger interrupts.
- uword stack_limit_address() const {
- return reinterpret_cast<uword>(&stack_limit_);
- }
- static intptr_t stack_limit_offset() {
- return OFFSET_OF(Isolate, stack_limit_);
- }
-
- // The true stack limit for this isolate.
- uword saved_stack_limit() const { return saved_stack_limit_; }
-
- // Stack overflow flags
- enum {
- kOsrRequest = 0x1, // Current stack overflow caused by OSR request.
- };
-
- uword stack_overflow_flags_address() const {
- return reinterpret_cast<uword>(&stack_overflow_flags_);
- }
- static intptr_t stack_overflow_flags_offset() {
- return OFFSET_OF(Isolate, stack_overflow_flags_);
- }
-
- int32_t IncrementAndGetStackOverflowCount() {
- return ++stack_overflow_count_;
- }
-
- // Retrieves and clears the stack overflow flags. These are set by
- // the generated code before the slow path runtime routine for a
- // stack overflow is called.
- uword GetAndClearStackOverflowFlags();
-
- // Interrupt bits.
- enum {
- kVMInterrupt = 0x1, // Internal VM checks: safepoints, store buffers, etc.
- kMessageInterrupt = 0x2, // An interrupt to process an out of band message.
-
- kInterruptsMask = (kVMInterrupt | kMessageInterrupt),
- };
-
- void ScheduleInterrupts(uword interrupt_bits);
- RawError* HandleInterrupts();
- uword GetAndClearInterrupts();
+ void ScheduleMessageInterrupts();
// Marks all libraries as loaded.
void DoneLoading();
@@ -432,36 +365,6 @@
return shutdown_callback_;
}
- static void SetFileCallbacks(Dart_FileOpenCallback file_open,
- Dart_FileReadCallback file_read,
- Dart_FileWriteCallback file_write,
- Dart_FileCloseCallback file_close) {
- file_open_callback_ = file_open;
- file_read_callback_ = file_read;
- file_write_callback_ = file_write;
- file_close_callback_ = file_close;
- }
-
- static Dart_FileOpenCallback file_open_callback() {
- return file_open_callback_;
- }
- static Dart_FileReadCallback file_read_callback() {
- return file_read_callback_;
- }
- static Dart_FileWriteCallback file_write_callback() {
- return file_write_callback_;
- }
- static Dart_FileCloseCallback file_close_callback() {
- return file_close_callback_;
- }
-
- static void SetEntropySourceCallback(Dart_EntropySource entropy_source) {
- entropy_source_callback_ = entropy_source;
- }
- static Dart_EntropySource entropy_source_callback() {
- return entropy_source_callback_;
- }
-
void set_object_id_ring(ObjectIdRing* ring) {
object_id_ring_ = ring;
}
@@ -469,6 +372,7 @@
return object_id_ring_;
}
+ bool IsDeoptimizing() const { return deopt_context_ != NULL; }
DeoptContext* deopt_context() const { return deopt_context_; }
void set_deopt_context(DeoptContext* value) {
ASSERT(value == NULL || deopt_context_ == NULL);
@@ -542,18 +446,6 @@
ISOLATE_METRIC_LIST(ISOLATE_METRIC_ACCESSOR);
#undef ISOLATE_METRIC_ACCESSOR
-#ifndef PRODUCT
-#define ISOLATE_TIMELINE_STREAM_ACCESSOR(name, not_used) \
- TimelineStream* Get##name##Stream() { return &stream_##name##_; }
- ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_ACCESSOR)
-#undef ISOLATE_TIMELINE_STREAM_ACCESSOR
-#else
-#define ISOLATE_TIMELINE_STREAM_ACCESSOR(name, not_used) \
- TimelineStream* Get##name##Stream() { return NULL; }
- ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_ACCESSOR)
-#undef ISOLATE_TIMELINE_STREAM_ACCESSOR
-#endif // !PRODUCT
-
static intptr_t IsolateListLength();
RawGrowableObjectArray* tag_table() const { return tag_table_; }
@@ -676,7 +568,6 @@
private:
friend class Dart; // Init, InitOnce, Shutdown.
friend class IsolateKillerVisitor; // Kill().
- friend class NoOOBMessageScope;
explicit Isolate(const Dart_IsolateFlags& api_flags);
@@ -703,9 +594,6 @@
user_tag_ = tag;
}
- void DeferOOBMessageInterrupts();
- void RestoreOOBMessageInterrupts();
-
RawGrowableObjectArray* GetAndClearPendingServiceExtensionCalls();
RawGrowableObjectArray* pending_service_extension_calls() const {
return pending_service_extension_calls_;
@@ -730,9 +618,6 @@
}
// Accessed from generated code:
- // TODO(asiva): Need to consider moving the stack_limit_ from isolate to
- // being thread specific.
- uword stack_limit_;
StoreBuffer* store_buffer_;
Heap* heap_;
uword user_tag_;
@@ -766,15 +651,10 @@
bool has_compiled_code_; // Can check that no compilation occured.
Random random_;
Simulator* simulator_;
- Mutex* mutex_; // Protects stack_limit_, saved_stack_limit_, compiler stats.
+ Mutex* mutex_; // Protects compiler stats.
Mutex* symbols_mutex_; // Protects concurrent access to the symbol table.
Mutex* type_canonicalization_mutex_; // Protects type canonicalization.
Mutex* constant_canonicalization_mutex_; // Protects const canonicalization.
- uword saved_stack_limit_;
- uword deferred_interrupts_mask_;
- uword deferred_interrupts_;
- uword stack_overflow_flags_;
- int32_t stack_overflow_count_;
MessageHandler* message_handler_;
IsolateSpawnState* spawn_state_;
bool is_runnable_;
@@ -869,20 +749,9 @@
ISOLATE_METRIC_LIST(ISOLATE_METRIC_VARIABLE);
#undef ISOLATE_METRIC_VARIABLE
-#ifndef PRODUCT
-#define ISOLATE_TIMELINE_STREAM_VARIABLE(name, not_used) \
- TimelineStream stream_##name##_;
- ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_VARIABLE)
-#undef ISOLATE_TIMELINE_STREAM_VARIABLE
-#endif // !PRODUCT
static Dart_IsolateCreateCallback create_callback_;
static Dart_IsolateShutdownCallback shutdown_callback_;
- static Dart_FileOpenCallback file_open_callback_;
- static Dart_FileReadCallback file_read_callback_;
- static Dart_FileWriteCallback file_write_callback_;
- static Dart_FileCloseCallback file_close_callback_;
- static Dart_EntropySource entropy_source_callback_;
static Dart_IsolateInterruptCallback vmstats_callback_;
static void WakePauseEventHandler(Dart_Isolate isolate);
@@ -907,7 +776,6 @@
friend class ServiceIsolate;
friend class Thread;
friend class Timeline;
- friend class IsolateTestHelper;
DISALLOW_COPY_AND_ASSIGN(Isolate);
};
@@ -927,9 +795,9 @@
}
if (saved_isolate_ != new_isolate_) {
ASSERT(Isolate::Current() == NULL);
- // Ensure this is not a nested 'isolate enter' with prior state.
- ASSERT(new_isolate_->saved_stack_limit() == 0);
Thread::EnterIsolate(new_isolate_);
+ // Ensure this is not a nested 'isolate enter' with prior state.
+ ASSERT(Thread::Current()->saved_stack_limit() == 0);
}
}
@@ -942,7 +810,7 @@
if (saved_isolate_ != new_isolate_) {
ASSERT(saved_isolate_ == NULL);
// ASSERT that we have bottomed out of all Dart invocations.
- ASSERT(new_isolate_->saved_stack_limit() == 0);
+ ASSERT(Thread::Current()->saved_stack_limit() == 0);
Thread::ExitIsolate();
}
}
diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
index 6491c41..4e39113 100644
--- a/runtime/vm/isolate_test.cc
+++ b/runtime/vm/isolate_test.cc
@@ -89,21 +89,24 @@
static const intptr_t kTaskCount;
static const intptr_t kIterations;
- InterruptChecker(Isolate* isolate,
- ThreadBarrier* barrier)
- : isolate_(isolate),
+ InterruptChecker(Thread* thread, ThreadBarrier* barrier)
+ : thread_(thread),
barrier_(barrier) {
}
virtual void Run() {
- Thread::EnterIsolateAsHelper(isolate_);
+ Thread::EnterIsolateAsHelper(thread_->isolate(), Thread::kUnknownTask);
// Tell main thread that we are ready.
barrier_->Sync();
for (intptr_t i = 0; i < kIterations; ++i) {
// Busy wait for interrupts.
- while (!isolate_->HasInterruptsScheduled(Isolate::kVMInterrupt)) {
- // Do nothing.
- }
+ uword limit = 0;
+ do {
+ limit = AtomicOperations::LoadRelaxed(
+ reinterpret_cast<uword*>(thread_->stack_limit_address()));
+ } while ((limit == thread_->saved_stack_limit_) ||
+ (((limit & Thread::kInterruptsMask) &
+ Thread::kVMInterrupt) == 0));
// Tell main thread that we observed the interrupt.
barrier_->Sync();
}
@@ -112,7 +115,7 @@
}
private:
- Isolate* isolate_;
+ Thread* thread_;
ThreadBarrier* barrier_;
};
@@ -130,23 +133,23 @@
// compiler and/or CPU could reorder operations to make the tasks observe the
// round update *before* the interrupt is set.
TEST_CASE(StackLimitInterrupts) {
- Isolate* isolate = Thread::Current()->isolate();
+ Isolate* isolate = thread->isolate();
ThreadBarrier barrier(InterruptChecker::kTaskCount + 1,
isolate->heap()->barrier(),
isolate->heap()->barrier_done());
// Start all tasks. They will busy-wait until interrupted in the first round.
for (intptr_t task = 0; task < InterruptChecker::kTaskCount; task++) {
- Dart::thread_pool()->Run(new InterruptChecker(isolate, &barrier));
+ Dart::thread_pool()->Run(new InterruptChecker(thread, &barrier));
}
// Wait for all tasks to get ready for the first round.
barrier.Sync();
for (intptr_t i = 0; i < InterruptChecker::kIterations; ++i) {
- isolate->ScheduleInterrupts(Isolate::kVMInterrupt);
+ thread->ScheduleInterrupts(Thread::kVMInterrupt);
// Wait for all tasks to observe the interrupt.
barrier.Sync();
// Continue with next round.
- uword interrupts = isolate->GetAndClearInterrupts();
- EXPECT((interrupts & Isolate::kVMInterrupt) != 0);
+ uword interrupts = thread->GetAndClearInterrupts();
+ EXPECT((interrupts & Thread::kVMInterrupt) != 0);
}
barrier.Exit();
}
@@ -154,17 +157,17 @@
class IsolateTestHelper {
public:
- static uword GetStackLimit(Isolate* isolate) {
- return isolate->stack_limit_;
+ static uword GetStackLimit(Thread* thread) {
+ return thread->stack_limit_;
}
- static uword GetSavedStackLimit(Isolate* isolate) {
- return isolate->saved_stack_limit_;
+ static uword GetSavedStackLimit(Thread* thread) {
+ return thread->saved_stack_limit_;
}
- static uword GetDeferredInterruptsMask(Isolate* isolate) {
- return isolate->deferred_interrupts_mask_;
+ static uword GetDeferredInterruptsMask(Thread* thread) {
+ return thread->deferred_interrupts_mask_;
}
- static uword GetDeferredInterrupts(Isolate* isolate) {
- return isolate->deferred_interrupts_;
+ static uword GetDeferredInterrupts(Thread* thread) {
+ return thread->deferred_interrupts_;
}
};
@@ -172,82 +175,81 @@
TEST_CASE(NoOOBMessageScope) {
// EXPECT_EQ is picky about type agreement for its arguments.
const uword kZero = 0;
- const uword kMessageInterrupt = Isolate::kMessageInterrupt;
- const uword kVMInterrupt = Isolate::kVMInterrupt;
+ const uword kMessageInterrupt = Thread::kMessageInterrupt;
+ const uword kVMInterrupt = Thread::kVMInterrupt;
uword stack_limit;
uword interrupt_bits;
// Initially no interrupts are scheduled or deferred.
- Isolate* isolate = Thread::Current()->isolate();
- EXPECT_EQ(IsolateTestHelper::GetStackLimit(isolate),
- IsolateTestHelper::GetSavedStackLimit(isolate));
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(isolate));
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(isolate));
+ EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+ IsolateTestHelper::GetSavedStackLimit(thread));
+ EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
+ EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
{
// Defer message interrupts.
- NoOOBMessageScope no_msg_scope(Thread::Current());
- EXPECT_EQ(IsolateTestHelper::GetStackLimit(isolate),
- IsolateTestHelper::GetSavedStackLimit(isolate));
+ NoOOBMessageScope no_msg_scope(thread);
+ EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+ IsolateTestHelper::GetSavedStackLimit(thread));
EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterruptsMask(isolate));
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(isolate));
+ IsolateTestHelper::GetDeferredInterruptsMask(thread));
+ EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
// Schedule a message, it is deferred.
- isolate->ScheduleInterrupts(Isolate::kMessageInterrupt);
- EXPECT_EQ(IsolateTestHelper::GetStackLimit(isolate),
- IsolateTestHelper::GetSavedStackLimit(isolate));
+ thread->ScheduleInterrupts(Thread::kMessageInterrupt);
+ EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+ IsolateTestHelper::GetSavedStackLimit(thread));
EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterruptsMask(isolate));
+ IsolateTestHelper::GetDeferredInterruptsMask(thread));
EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterrupts(isolate));
+ IsolateTestHelper::GetDeferredInterrupts(thread));
// Schedule a vm interrupt, it is not deferred.
- isolate->ScheduleInterrupts(Isolate::kVMInterrupt);
- stack_limit = IsolateTestHelper::GetStackLimit(isolate);
- EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(isolate));
- EXPECT((stack_limit & Isolate::kVMInterrupt) != 0);
+ thread->ScheduleInterrupts(Thread::kVMInterrupt);
+ stack_limit = IsolateTestHelper::GetStackLimit(thread);
+ EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(thread));
+ EXPECT((stack_limit & Thread::kVMInterrupt) != 0);
EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterruptsMask(isolate));
+ IsolateTestHelper::GetDeferredInterruptsMask(thread));
EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterrupts(isolate));
+ IsolateTestHelper::GetDeferredInterrupts(thread));
// Clear the vm interrupt. Message is still deferred.
- interrupt_bits = isolate->GetAndClearInterrupts();
+ interrupt_bits = thread->GetAndClearInterrupts();
EXPECT_EQ(kVMInterrupt, interrupt_bits);
- EXPECT_EQ(IsolateTestHelper::GetStackLimit(isolate),
- IsolateTestHelper::GetSavedStackLimit(isolate));
+ EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+ IsolateTestHelper::GetSavedStackLimit(thread));
EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterruptsMask(isolate));
+ IsolateTestHelper::GetDeferredInterruptsMask(thread));
EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterrupts(isolate));
+ IsolateTestHelper::GetDeferredInterrupts(thread));
}
// Restore message interrupts. Message is now pending.
- stack_limit = IsolateTestHelper::GetStackLimit(isolate);
- EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(isolate));
- EXPECT((stack_limit & Isolate::kMessageInterrupt) != 0);
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(isolate));
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(isolate));
+ stack_limit = IsolateTestHelper::GetStackLimit(thread);
+ EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(thread));
+ EXPECT((stack_limit & Thread::kMessageInterrupt) != 0);
+ EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
+ EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
{
// Defer message interrupts, again. The pending interrupt is deferred.
- NoOOBMessageScope no_msg_scope(Thread::Current());
- EXPECT_EQ(IsolateTestHelper::GetStackLimit(isolate),
- IsolateTestHelper::GetSavedStackLimit(isolate));
+ NoOOBMessageScope no_msg_scope(thread);
+ EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+ IsolateTestHelper::GetSavedStackLimit(thread));
EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterruptsMask(isolate));
+ IsolateTestHelper::GetDeferredInterruptsMask(thread));
EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterrupts(isolate));
+ IsolateTestHelper::GetDeferredInterrupts(thread));
}
// Restore, then clear interrupts. The world is as it was.
- interrupt_bits = isolate->GetAndClearInterrupts();
+ interrupt_bits = thread->GetAndClearInterrupts();
EXPECT_EQ(kMessageInterrupt, interrupt_bits);
- EXPECT_EQ(IsolateTestHelper::GetStackLimit(isolate),
- IsolateTestHelper::GetSavedStackLimit(isolate));
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(isolate));
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(isolate));
+ EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
+ IsolateTestHelper::GetSavedStackLimit(thread));
+ EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
+ EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
}
} // namespace dart
diff --git a/runtime/vm/longjump.cc b/runtime/vm/longjump.cc
index 13e0133..2bc7e31 100644
--- a/runtime/vm/longjump.cc
+++ b/runtime/vm/longjump.cc
@@ -26,7 +26,7 @@
// We do not want to jump past Dart frames. Note that this code
// assumes the stack grows from high to low.
Thread* thread = Thread::Current();
- uword jumpbuf_addr = Isolate::GetCurrentStackPointer();
+ uword jumpbuf_addr = Thread::GetCurrentStackPointer();
#if defined(USING_SIMULATOR)
Simulator* sim = Simulator::Current();
// When using simulator, only mutator thread should refer to Simulator
diff --git a/runtime/vm/megamorphic_cache_table.cc b/runtime/vm/megamorphic_cache_table.cc
index 6c4ccf1..b793d35 100644
--- a/runtime/vm/megamorphic_cache_table.cc
+++ b/runtime/vm/megamorphic_cache_table.cc
@@ -61,7 +61,7 @@
// it is considered in the search for an exception handler.
code.set_exception_handlers(Object::empty_exception_handlers());
const Class& cls =
- Class::Handle(Type::Handle(Type::Function()).type_class());
+ Class::Handle(Type::Handle(Type::DartFunctionType()).type_class());
const Function& function =
Function::Handle(Function::New(Symbols::MegamorphicMiss(),
RawFunction::kRegularFunction,
diff --git a/runtime/vm/method_recognizer.h b/runtime/vm/method_recognizer.h
index 1292b84..f4d6b06 100644
--- a/runtime/vm/method_recognizer.h
+++ b/runtime/vm/method_recognizer.h
@@ -62,87 +62,87 @@
V(::, min, MathMin, 1115051548) \
V(::, max, MathMax, 1410473322) \
V(::, _doublePow, MathDoublePow, 562154128) \
- V(Float32x4, Float32x4., Float32x4Constructor, 1849420944) \
- V(Float32x4, Float32x4.zero, Float32x4Zero, 762161262) \
- V(Float32x4, Float32x4.splat, Float32x4Splat, 255855286) \
- V(Float32x4, Float32x4.fromInt32x4Bits, Float32x4FromInt32x4Bits, 1718571366)\
- V(Float32x4, Float32x4.fromFloat64x2, Float32x4FromFloat64x2, 1458098858) \
- V(_Float32x4, shuffle, Float32x4Shuffle, 2015957023) \
- V(_Float32x4, shuffleMix, Float32x4ShuffleMix, 1099087979) \
- V(_Float32x4, get:signMask, Float32x4GetSignMask, 487049875) \
- V(_Float32x4, _cmpequal, Float32x4Equal, 1069901308) \
- V(_Float32x4, _cmpgt, Float32x4GreaterThan, 2112381651) \
- V(_Float32x4, _cmpgte, Float32x4GreaterThanOrEqual, 1088241265) \
- V(_Float32x4, _cmplt, Float32x4LessThan, 2001171012) \
- V(_Float32x4, _cmplte, Float32x4LessThanOrEqual, 1568686387) \
- V(_Float32x4, _cmpnequal, Float32x4NotEqual, 1833412828) \
- V(_Float32x4, _min, Float32x4Min, 1194113943) \
- V(_Float32x4, _max, Float32x4Max, 1876936155) \
- V(_Float32x4, _scale, Float32x4Scale, 1176743640) \
- V(_Float32x4, _sqrt, Float32x4Sqrt, 526238610) \
- V(_Float32x4, _reciprocalSqrt, Float32x4ReciprocalSqrt, 860560177) \
- V(_Float32x4, _reciprocal, Float32x4Reciprocal, 1703468100) \
- V(_Float32x4, _negate, Float32x4Negate, 1409902640) \
- V(_Float32x4, _abs, Float32x4Absolute, 2116840471) \
- V(_Float32x4, _clamp, Float32x4Clamp, 1789892357) \
- V(_Float32x4, withX, Float32x4WithX, 1311992575) \
- V(_Float32x4, withY, Float32x4WithY, 175290640) \
- V(_Float32x4, withZ, Float32x4WithZ, 837367384) \
- V(_Float32x4, withW, Float32x4WithW, 1625145605) \
- V(Float64x2, Float64x2., Float64x2Constructor, 1428850802) \
- V(Float64x2, Float64x2.zero, Float64x2Zero, 29170676) \
- V(Float64x2, Float64x2.splat, Float64x2Splat, 1077183856) \
- V(Float64x2, Float64x2.fromFloat32x4, Float64x2FromFloat32x4, 1752000980) \
- V(_Float64x2, get:x, Float64x2GetX, 1488958362) \
- V(_Float64x2, get:y, Float64x2GetY, 1022688506) \
- V(_Float64x2, _negate, Float64x2Negate, 960840275) \
- V(_Float64x2, abs, Float64x2Abs, 52403783) \
- V(_Float64x2, sqrt, Float64x2Sqrt, 2012680669) \
- V(_Float64x2, get:signMask, Float64x2GetSignMask, 668856717) \
- V(_Float64x2, scale, Float64x2Scale, 646122081) \
- V(_Float64x2, withX, Float64x2WithX, 489409269) \
- V(_Float64x2, withY, Float64x2WithY, 943642284) \
- V(_Float64x2, min, Float64x2Min, 685235702) \
- V(_Float64x2, max, Float64x2Max, 198659675) \
- V(Int32x4, Int32x4., Int32x4Constructor, 80862812) \
- V(Int32x4, Int32x4.bool, Int32x4BoolConstructor, 1949580252) \
- V(Int32x4, Int32x4.fromFloat32x4Bits, Int32x4FromFloat32x4Bits, 1611205288) \
- V(_Int32x4, get:flagX, Int32x4GetFlagX, 1446544324) \
- V(_Int32x4, get:flagY, Int32x4GetFlagY, 1148149370) \
- V(_Int32x4, get:flagZ, Int32x4GetFlagZ, 550901369) \
- V(_Int32x4, get:flagW, Int32x4GetFlagW, 1346664620) \
- V(_Int32x4, get:signMask, Int32x4GetSignMask, 740215269) \
- V(_Int32x4, shuffle, Int32x4Shuffle, 549194518) \
- V(_Int32x4, shuffleMix, Int32x4ShuffleMix, 1550866145) \
- V(_Int32x4, select, Int32x4Select, 614943686) \
- V(_Int32x4, withFlagX, Int32x4WithFlagX, 250974159) \
- V(_Int32x4, withFlagY, Int32x4WithFlagY, 1686481348) \
- V(_Int32x4, withFlagZ, Int32x4WithFlagZ, 645582330) \
- V(_Int32x4, withFlagW, Int32x4WithFlagW, 878364277) \
- V(_Float32Array, [], Float32ArrayGetIndexed, 1002307136) \
- V(_Float32Array, []=, Float32ArraySetIndexed, 279546769) \
- V(_Int8Array, [], Int8ArrayGetIndexed, 1141846285) \
- V(_Int8Array, []=, Int8ArraySetIndexed, 1486839324) \
- V(_Uint8ClampedArray, [], Uint8ClampedArrayGetIndexed, 513704632) \
- V(_Uint8ClampedArray, []=, Uint8ClampedArraySetIndexed, 1015846567) \
+ V(Float32x4, Float32x4., Float32x4Constructor, 93751705) \
+ V(Float32x4, Float32x4.zero, Float32x4Zero, 1193954374) \
+ V(Float32x4, Float32x4.splat, Float32x4Splat, 12296613) \
+ V(Float32x4, Float32x4.fromInt32x4Bits, Float32x4FromInt32x4Bits, 1188039061)\
+ V(Float32x4, Float32x4.fromFloat64x2, Float32x4FromFloat64x2, 1750763218) \
+ V(Float32x4, shuffle, Float32x4Shuffle, 2015957023) \
+ V(Float32x4, shuffleMix, Float32x4ShuffleMix, 1099087979) \
+ V(Float32x4, get:signMask, Float32x4GetSignMask, 487049875) \
+ V(Float32x4, _cmpequal, Float32x4Equal, 1069901308) \
+ V(Float32x4, _cmpgt, Float32x4GreaterThan, 2112381651) \
+ V(Float32x4, _cmpgte, Float32x4GreaterThanOrEqual, 1088241265) \
+ V(Float32x4, _cmplt, Float32x4LessThan, 2001171012) \
+ V(Float32x4, _cmplte, Float32x4LessThanOrEqual, 1568686387) \
+ V(Float32x4, _cmpnequal, Float32x4NotEqual, 1833412828) \
+ V(Float32x4, _min, Float32x4Min, 1194113943) \
+ V(Float32x4, _max, Float32x4Max, 1876936155) \
+ V(Float32x4, _scale, Float32x4Scale, 1176743640) \
+ V(Float32x4, _sqrt, Float32x4Sqrt, 526238610) \
+ V(Float32x4, _reciprocalSqrt, Float32x4ReciprocalSqrt, 860560177) \
+ V(Float32x4, _reciprocal, Float32x4Reciprocal, 1703468100) \
+ V(Float32x4, _negate, Float32x4Negate, 1409902640) \
+ V(Float32x4, _abs, Float32x4Absolute, 2116840471) \
+ V(Float32x4, _clamp, Float32x4Clamp, 1789892357) \
+ V(Float32x4, withX, Float32x4WithX, 1311992575) \
+ V(Float32x4, withY, Float32x4WithY, 175290640) \
+ V(Float32x4, withZ, Float32x4WithZ, 837367384) \
+ V(Float32x4, withW, Float32x4WithW, 1625145605) \
+ V(Float64x2, Float64x2., Float64x2Constructor, 423355933) \
+ V(Float64x2, Float64x2.zero, Float64x2Zero, 2066666975) \
+ V(Float64x2, Float64x2.splat, Float64x2Splat, 716962994) \
+ V(Float64x2, Float64x2.fromFloat32x4, Float64x2FromFloat32x4, 792974246) \
+ V(Float64x2, get:x, Float64x2GetX, 1488958362) \
+ V(Float64x2, get:y, Float64x2GetY, 1022688506) \
+ V(Float64x2, _negate, Float64x2Negate, 960840275) \
+ V(Float64x2, abs, Float64x2Abs, 52403783) \
+ V(Float64x2, sqrt, Float64x2Sqrt, 2012680669) \
+ V(Float64x2, get:signMask, Float64x2GetSignMask, 668856717) \
+ V(Float64x2, scale, Float64x2Scale, 646122081) \
+ V(Float64x2, withX, Float64x2WithX, 489409269) \
+ V(Float64x2, withY, Float64x2WithY, 943642284) \
+ V(Float64x2, min, Float64x2Min, 685235702) \
+ V(Float64x2, max, Float64x2Max, 198659675) \
+ V(Int32x4, Int32x4., Int32x4Constructor, 649173415) \
+ V(Int32x4, Int32x4.bool, Int32x4BoolConstructor, 458597857) \
+ V(Int32x4, Int32x4.fromFloat32x4Bits, Int32x4FromFloat32x4Bits, 2122470988) \
+ V(Int32x4, get:flagX, Int32x4GetFlagX, 1446544324) \
+ V(Int32x4, get:flagY, Int32x4GetFlagY, 1148149370) \
+ V(Int32x4, get:flagZ, Int32x4GetFlagZ, 550901369) \
+ V(Int32x4, get:flagW, Int32x4GetFlagW, 1346664620) \
+ V(Int32x4, get:signMask, Int32x4GetSignMask, 740215269) \
+ V(Int32x4, shuffle, Int32x4Shuffle, 549194518) \
+ V(Int32x4, shuffleMix, Int32x4ShuffleMix, 1550866145) \
+ V(Int32x4, select, Int32x4Select, 614943686) \
+ V(Int32x4, withFlagX, Int32x4WithFlagX, 250974159) \
+ V(Int32x4, withFlagY, Int32x4WithFlagY, 1686481348) \
+ V(Int32x4, withFlagZ, Int32x4WithFlagZ, 645582330) \
+ V(Int32x4, withFlagW, Int32x4WithFlagW, 878364277) \
+ V(Float32List, [], Float32ArrayGetIndexed, 1002307136) \
+ V(Float32List, []=, Float32ArraySetIndexed, 279546769) \
+ V(Int8List, [], Int8ArrayGetIndexed, 1141846285) \
+ V(Int8List, []=, Int8ArraySetIndexed, 1486839324) \
+ V(Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, 513704632) \
+ V(Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, 1015846567) \
V(_ExternalUint8ClampedArray, [], ExternalUint8ClampedArrayGetIndexed, \
513704632) \
V(_ExternalUint8ClampedArray, []=, ExternalUint8ClampedArraySetIndexed, \
1015846567) \
- V(_Int16Array, [], Int16ArrayGetIndexed, 1826359619) \
- V(_Int16Array, []=, Int16ArraySetIndexed, 1108689116) \
- V(_Uint16Array, [], Uint16ArrayGetIndexed, 118958722) \
- V(_Uint16Array, []=, Uint16ArraySetIndexed, 658824450) \
- V(_Int32Array, [], Int32ArrayGetIndexed, 681203163) \
- V(_Int32Array, []=, Int32ArraySetIndexed, 1786886245) \
- V(_Int64Array, [], Int64ArrayGetIndexed, 1883155004) \
- V(_Int64Array, []=, Int64ArraySetIndexed, 905815059) \
- V(_Float32x4Array, [], Float32x4ArrayGetIndexed, 694822356) \
- V(_Float32x4Array, []=, Float32x4ArraySetIndexed, 1166109127) \
- V(_Int32x4Array, [], Int32x4ArrayGetIndexed, 668249259) \
- V(_Int32x4Array, []=, Int32x4ArraySetIndexed, 654739449) \
- V(_Float64x2Array, [], Float64x2ArrayGetIndexed, 196472005) \
- V(_Float64x2Array, []=, Float64x2ArraySetIndexed, 1421858500) \
+ V(Int16List, [], Int16ArrayGetIndexed, 1826359619) \
+ V(Int16List, []=, Int16ArraySetIndexed, 1108689116) \
+ V(Uint16List, [], Uint16ArrayGetIndexed, 118958722) \
+ V(Uint16List, []=, Uint16ArraySetIndexed, 658824450) \
+ V(Int32List, [], Int32ArrayGetIndexed, 681203163) \
+ V(Int32List, []=, Int32ArraySetIndexed, 1786886245) \
+ V(Int64List, [], Int64ArrayGetIndexed, 1883155004) \
+ V(Int64List, []=, Int64ArraySetIndexed, 905815059) \
+ V(Float32x4List, [], Float32x4ArrayGetIndexed, 694822356) \
+ V(Float32x4List, []=, Float32x4ArraySetIndexed, 1166109127) \
+ V(Int32x4List, [], Int32x4ArrayGetIndexed, 668249259) \
+ V(Int32x4List, []=, Int32x4ArraySetIndexed, 654739449) \
+ V(Float64x2List, [], Float64x2ArrayGetIndexed, 196472005) \
+ V(Float64x2List, []=, Float64x2ArraySetIndexed, 1421858500) \
V(_Bigint, get:_neg, Bigint_getNeg, 1681019799) \
V(_Bigint, get:_used, Bigint_getUsed, 1439136438) \
V(_Bigint, get:_digits, Bigint_getDigits, 769722770) \
@@ -187,7 +187,7 @@
V(_List, []=, ObjectArraySetIndexed, 886228780) \
V(_GrowableList, .withData, GrowableArray_Allocate, 131424500) \
V(_GrowableList, add, GrowableArray_add, 242296201) \
- V(_JSSyntaxRegExp, _ExecuteMatch, JSRegExp_ExecuteMatch, 1490503678) \
+ V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, 2077783530) \
V(Object, ==, ObjectEquals, 291909336) \
V(Object, get:runtimeType, ObjectRuntimeType, 15188587) \
V(_StringBase, get:hashCode, String_getHashCode, 2026040200) \
@@ -245,38 +245,38 @@
#define TYPED_DATA_LIB_INTRINSIC_LIST(V) \
- V(_Int8Array, ., TypedData_Int8Array_factory, 1058992179) \
- V(_Uint8Array, ., TypedData_Uint8Array_factory, 1807546986) \
- V(_Uint8ClampedArray, ., TypedData_Uint8ClampedArray_factory, 548459853) \
- V(_Int16Array, ., TypedData_Int16Array_factory, 1796211480) \
- V(_Uint16Array, ., TypedData_Uint16Array_factory, 1960868166) \
- V(_Int32Array, ., TypedData_Int32Array_factory, 372258367) \
- V(_Uint32Array, ., TypedData_Uint32Array_factory, 1446612721) \
- V(_Int64Array, ., TypedData_Int64Array_factory, 964028713) \
- V(_Uint64Array, ., TypedData_Uint64Array_factory, 721823156) \
- V(_Float32Array, ., TypedData_Float32Array_factory, 392399264) \
- V(_Float64Array, ., TypedData_Float64Array_factory, 42503976) \
- V(_Float32x4Array, ., TypedData_Float32x4Array_factory, 1960198693) \
- V(_Int32x4Array, ., TypedData_Int32x4Array_factory, 1433742555) \
- V(_Float64x2Array, ., TypedData_Float64x2Array_factory, 165463437) \
+ V(Int8List, ., TypedData_Int8Array_factory, 779569635) \
+ V(Uint8List, ., TypedData_Uint8Array_factory, 1790399545) \
+ V(Uint8ClampedList, ., TypedData_Uint8ClampedArray_factory, 405875159) \
+ V(Int16List, ., TypedData_Int16Array_factory, 347431914) \
+ V(Uint16List, ., TypedData_Uint16Array_factory, 121990116) \
+ V(Int32List, ., TypedData_Int32Array_factory, 1540657744) \
+ V(Uint32List, ., TypedData_Uint32Array_factory, 1012511652) \
+ V(Int64List, ., TypedData_Int64Array_factory, 1473796807) \
+ V(Uint64List, ., TypedData_Uint64Array_factory, 738799620) \
+ V(Float32List, ., TypedData_Float32Array_factory, 1938690635) \
+ V(Float64List, ., TypedData_Float64Array_factory, 1344005361) \
+ V(Float32x4List, ., TypedData_Float32x4Array_factory, 2055067416) \
+ V(Int32x4List, ., TypedData_Int32x4Array_factory, 504220232) \
+ V(Float64x2List, ., TypedData_Float64x2Array_factory, 416019673) \
#define GRAPH_TYPED_DATA_INTRINSICS_LIST(V) \
- V(_Uint8Array, [], Uint8ArrayGetIndexed, 513704632) \
- V(_Uint8Array, []=, Uint8ArraySetIndexed, 2123520783) \
+ V(Uint8List, [], Uint8ArrayGetIndexed, 513704632) \
+ V(Uint8List, []=, Uint8ArraySetIndexed, 2123520783) \
V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, 513704632) \
V(_ExternalUint8Array, []=, ExternalUint8ArraySetIndexed, 2123520783) \
- V(_Uint32Array, [], Uint32ArrayGetIndexed, 1179675338) \
- V(_Uint32Array, []=, Uint32ArraySetIndexed, 1455695417) \
- V(_Float64Array, []=, Float64ArraySetIndexed, 1929239576) \
- V(_Float64Array, [], Float64ArrayGetIndexed, 816943529) \
+ V(Uint32List, [], Uint32ArrayGetIndexed, 1179675338) \
+ V(Uint32List, []=, Uint32ArraySetIndexed, 1455695417) \
+ V(Float64List, []=, Float64ArraySetIndexed, 1929239576) \
+ V(Float64List, [], Float64ArrayGetIndexed, 816943529) \
V(_TypedList, get:length, TypedDataLength, 546364442) \
- V(_Float32x4, get:x, Float32x4ShuffleX, 1674625343) \
- V(_Float32x4, get:y, Float32x4ShuffleY, 540293915) \
- V(_Float32x4, get:z, Float32x4ShuffleZ, 320347578) \
- V(_Float32x4, get:w, Float32x4ShuffleW, 1770606624) \
- V(_Float32x4, _mul, Float32x4Mul, 861549065) \
- V(_Float32x4, _sub, Float32x4Sub, 460363214) \
- V(_Float32x4, _add, Float32x4Add, 1487592255) \
+ V(Float32x4, get:x, Float32x4ShuffleX, 1674625343) \
+ V(Float32x4, get:y, Float32x4ShuffleY, 540293915) \
+ V(Float32x4, get:z, Float32x4ShuffleZ, 320347578) \
+ V(Float32x4, get:w, Float32x4ShuffleW, 1770606624) \
+ V(Float32x4, _mul, Float32x4Mul, 861549065) \
+ V(Float32x4, _sub, Float32x4Sub, 460363214) \
+ V(Float32x4, _add, Float32x4Add, 1487592255) \
#define GRAPH_CORE_INTRINSICS_LIST(V) \
V(_List, get:length, ObjectArrayLength, 630471378) \
@@ -343,24 +343,24 @@
V(_ImmutableList, [], ImmutableArrayGetIndexed, 360400496) \
V(_GrowableList, [], GrowableArrayGetIndexed, 1957529650) \
V(_GrowableList, []=, GrowableArraySetIndexed, 225246870) \
- V(_Float32Array, [], Float32ArrayGetIndexed, 1002307136) \
- V(_Float32Array, []=, Float32ArraySetIndexed, 279546769) \
- V(_Float64Array, [], Float64ArrayGetIndexed, 816943529) \
- V(_Float64Array, []=, Float64ArraySetIndexed, 1929239576) \
- V(_Int8Array, [], Int8ArrayGetIndexed, 1141846285) \
- V(_Int8Array, []=, Int8ArraySetIndexed, 1486839324) \
- V(_Uint8Array, [], Uint8ArrayGetIndexed, 513704632) \
- V(_Uint8Array, []=, Uint8ArraySetIndexed, 2123520783) \
- V(_Uint8ClampedArray, [], Uint8ClampedArrayGetIndexed, 513704632) \
- V(_Uint8ClampedArray, []=, Uint8ClampedArraySetIndexed, 1015846567) \
- V(_Uint16Array, [], Uint16ArrayGetIndexed, 118958722) \
- V(_Uint16Array, []=, Uint16ArraySetIndexed, 658824450) \
- V(_Int16Array, [], Int16ArrayGetIndexed, 1826359619) \
- V(_Int16Array, []=, Int16ArraySetIndexed, 1108689116) \
- V(_Int32Array, [], Int32ArrayGetIndexed, 681203163) \
- V(_Int32Array, []=, Int32ArraySetIndexed, 1786886245) \
- V(_Int64Array, [], Int64ArrayGetIndexed, 1883155004) \
- V(_Int64Array, []=, Int64ArraySetIndexed, 905815059) \
+ V(Float32List, [], Float32ArrayGetIndexed, 1002307136) \
+ V(Float32List, []=, Float32ArraySetIndexed, 279546769) \
+ V(Float64List, [], Float64ArrayGetIndexed, 816943529) \
+ V(Float64List, []=, Float64ArraySetIndexed, 1929239576) \
+ V(Int8List, [], Int8ArrayGetIndexed, 1141846285) \
+ V(Int8List, []=, Int8ArraySetIndexed, 1486839324) \
+ V(Uint8List, [], Uint8ArrayGetIndexed, 513704632) \
+ V(Uint8List, []=, Uint8ArraySetIndexed, 2123520783) \
+ V(Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, 513704632) \
+ V(Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, 1015846567) \
+ V(Uint16List, [], Uint16ArrayGetIndexed, 118958722) \
+ V(Uint16List, []=, Uint16ArraySetIndexed, 658824450) \
+ V(Int16List, [], Int16ArrayGetIndexed, 1826359619) \
+ V(Int16List, []=, Int16ArraySetIndexed, 1108689116) \
+ V(Int32List, [], Int32ArrayGetIndexed, 681203163) \
+ V(Int32List, []=, Int32ArraySetIndexed, 1786886245) \
+ V(Int64List, [], Int64ArrayGetIndexed, 1883155004) \
+ V(Int64List, []=, Int64ArraySetIndexed, 905815059) \
V(_Uint8ArrayView, [], Uint8ArrayViewGetIndexed, 215420949) \
V(_Uint8ArrayView, []=, Uint8ArrayViewSetIndexed, 1138146450) \
V(_Int8ArrayView, [], Int8ArrayViewGetIndexed, 1003520035) \
@@ -412,20 +412,6 @@
V(_HashVMBase, set:_hashMask, LinkedHashMap_setHashMask, 340628211) \
V(_HashVMBase, get:_deletedKeys, LinkedHashMap_getDeletedKeys, 1340385546) \
V(_HashVMBase, set:_deletedKeys, LinkedHashMap_setDeletedKeys, 638315987) \
- V(Uint8List, ., Uint8ListFactory, 1885328419) \
- V(Int8List, ., Int8ListFactory, 551286096) \
- V(Uint16List, ., Uint16ListFactory, 2018994846) \
- V(Int16List, ., Int16ListFactory, 1934285336) \
- V(Uint32List, ., Uint32ListFactory, 990865607) \
- V(Int32List, ., Int32ListFactory, 2017670015) \
- V(Uint64List, ., Uint64ListFactory, 1593070032) \
- V(Int64List, ., Int64ListFactory, 1071205588) \
- V(Float32List, ., Float32ListFactory, 1015272745) \
- V(Float64List, ., Float64ListFactory, 626315429) \
- V(Int32x4List, ., Int32x4ListFactory, 1693091079) \
- V(Float32x4List, ., Float32x4ListFactory, 585154381) \
- V(Float64x2List, ., Float64x2ListFactory, 874435184)
-
// A list of core function that should never be inlined.
#define INLINE_BLACK_LIST(V) \
@@ -474,7 +460,7 @@
enum Kind {
kUnknown,
#define DEFINE_ENUM_LIST(class_name, function_name, enum_name, fp) k##enum_name,
-RECOGNIZED_LIST(DEFINE_ENUM_LIST)
+ RECOGNIZED_LIST(DEFINE_ENUM_LIST)
#undef DEFINE_ENUM_LIST
kNumRecognizedMethods
};
@@ -504,18 +490,18 @@
V(_ListFactory, kArrayCid, 184405219) \
V(_GrowableListWithData, kGrowableObjectArrayCid, 131424500) \
V(_GrowableListFactory, kGrowableObjectArrayCid, 664918385) \
- V(_Int8ArrayFactory, kTypedDataInt8ArrayCid, 1058992179) \
- V(_Uint8ArrayFactory, kTypedDataUint8ArrayCid, 1807546986) \
- V(_Uint8ClampedArrayFactory, kTypedDataUint8ClampedArrayCid, 548459853) \
- V(_Int16ArrayFactory, kTypedDataInt16ArrayCid, 1796211480) \
- V(_Uint16ArrayFactory, kTypedDataUint16ArrayCid, 1960868166) \
- V(_Int32ArrayFactory, kTypedDataInt32ArrayCid, 372258367) \
- V(_Uint32ArrayFactory, kTypedDataUint32ArrayCid, 1446612721) \
- V(_Int64ArrayFactory, kTypedDataInt64ArrayCid, 964028713) \
- V(_Uint64ArrayFactory, kTypedDataUint64ArrayCid, 721823156) \
- V(_Float64ArrayFactory, kTypedDataFloat64ArrayCid, 42503976) \
- V(_Float32ArrayFactory, kTypedDataFloat32ArrayCid, 392399264) \
- V(_Float32x4ArrayFactory, kTypedDataFloat32x4ArrayCid, 1960198693) \
+ V(_Int8ArrayFactory, kTypedDataInt8ArrayCid, 779569635) \
+ V(_Uint8ArrayFactory, kTypedDataUint8ArrayCid, 1790399545) \
+ V(_Uint8ClampedArrayFactory, kTypedDataUint8ClampedArrayCid, 405875159) \
+ V(_Int16ArrayFactory, kTypedDataInt16ArrayCid, 347431914) \
+ V(_Uint16ArrayFactory, kTypedDataUint16ArrayCid, 121990116) \
+ V(_Int32ArrayFactory, kTypedDataInt32ArrayCid, 1540657744) \
+ V(_Uint32ArrayFactory, kTypedDataUint32ArrayCid, 1012511652) \
+ V(_Int64ArrayFactory, kTypedDataInt64ArrayCid, 1473796807) \
+ V(_Uint64ArrayFactory, kTypedDataUint64ArrayCid, 738799620) \
+ V(_Float64ArrayFactory, kTypedDataFloat64ArrayCid, 1344005361) \
+ V(_Float32ArrayFactory, kTypedDataFloat32ArrayCid, 1938690635) \
+ V(_Float32x4ArrayFactory, kTypedDataFloat32x4ArrayCid, 2055067416) \
// Class that recognizes factories and returns corresponding result cid.
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 7b84774..8922db4 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -38,6 +38,7 @@
#include "vm/symbols.h"
#include "vm/tags.h"
#include "vm/thread_registry.h"
+#include "vm/timeline.h"
#include "vm/timer.h"
#include "vm/unicode.h"
#include "vm/verified_memory.h"
@@ -1104,7 +1105,7 @@
ASSERT(isolate == thread->isolate());
NOT_IN_PRODUCT(
TimelineDurationScope tds(thread,
- isolate->GetIsolateStream(),
+ Timeline::GetIsolateStream(),
"Object::Init");
)
@@ -1149,8 +1150,6 @@
// Setup type class early in the process.
const Class& type_cls = Class::Handle(zone, Class::New<Type>());
- const Class& function_type_cls = Class::Handle(zone,
- Class::New<FunctionType>());
const Class& type_ref_cls = Class::Handle(zone, Class::New<TypeRef>());
const Class& type_parameter_cls = Class::Handle(zone,
Class::New<TypeParameter>());
@@ -1272,8 +1271,8 @@
pending_classes.Add(stacktrace_cls);
// Super type set below, after Object is allocated.
- cls = Class::New<JSRegExp>();
- RegisterPrivateClass(cls, Symbols::JSSyntaxRegExp(), core_lib);
+ cls = Class::New<RegExp>();
+ RegisterPrivateClass(cls, Symbols::_RegExp(), core_lib);
pending_classes.Add(cls);
// Initialize the base interfaces used by the core VM classes.
@@ -1313,9 +1312,6 @@
RegisterPrivateClass(type_cls, Symbols::Type(), core_lib);
pending_classes.Add(type_cls);
- RegisterPrivateClass(function_type_cls, Symbols::FunctionType(), core_lib);
- pending_classes.Add(function_type_cls);
-
RegisterPrivateClass(type_ref_cls, Symbols::TypeRef(), core_lib);
pending_classes.Add(type_ref_cls);
@@ -1437,10 +1433,10 @@
ASSERT(!lib.IsNull());
ASSERT(lib.raw() == Library::TypedDataLibrary());
#define REGISTER_TYPED_DATA_CLASS(clazz) \
- cls = Class::NewTypedDataClass(kTypedData##clazz##Cid); \
- RegisterPrivateClass(cls, Symbols::_##clazz(), lib); \
+ cls = Class::NewTypedDataClass(kTypedData##clazz##ArrayCid); \
+ RegisterClass(cls, Symbols::clazz##List(), lib); \
- CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_CLASS);
+ DART_CLASS_LIST_TYPED_DATA(REGISTER_TYPED_DATA_CLASS);
#undef REGISTER_TYPED_DATA_CLASS
#define REGISTER_TYPED_DATA_VIEW_CLASS(clazz) \
cls = Class::NewTypedDataViewClass(kTypedData##clazz##ViewCid); \
@@ -1459,46 +1455,39 @@
cls = Class::New<Instance>(kByteBufferCid);
cls.set_instance_size(0);
cls.set_next_field_offset(-kWordSize);
- RegisterPrivateClass(cls, Symbols::_ByteBuffer(), lib);
+ RegisterClass(cls, Symbols::ByteBuffer(), lib);
pending_classes.Add(cls);
CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS);
#undef REGISTER_EXT_TYPED_DATA_CLASS
// Register Float32x4 and Int32x4 in the object store.
cls = Class::New<Float32x4>();
- object_store->set_float32x4_class(cls);
- RegisterPrivateClass(cls, Symbols::_Float32x4(), lib);
- cls = Class::New<Int32x4>();
- object_store->set_int32x4_class(cls);
- RegisterPrivateClass(cls, Symbols::_Int32x4(), lib);
- cls = Class::New<Float64x2>();
- object_store->set_float64x2_class(cls);
- RegisterPrivateClass(cls, Symbols::_Float64x2(), lib);
-
- cls = Class::New<Instance>(kIllegalCid);
RegisterClass(cls, Symbols::Float32x4(), lib);
cls.set_num_type_arguments(0);
cls.set_num_own_type_arguments(0);
cls.set_is_prefinalized();
pending_classes.Add(cls);
+ object_store->set_float32x4_class(cls);
type = Type::NewNonParameterizedType(cls);
object_store->set_float32x4_type(type);
- cls = Class::New<Instance>(kIllegalCid);
+ cls = Class::New<Int32x4>();
RegisterClass(cls, Symbols::Int32x4(), lib);
cls.set_num_type_arguments(0);
cls.set_num_own_type_arguments(0);
cls.set_is_prefinalized();
pending_classes.Add(cls);
+ object_store->set_int32x4_class(cls);
type = Type::NewNonParameterizedType(cls);
object_store->set_int32x4_type(type);
- cls = Class::New<Instance>(kIllegalCid);
+ cls = Class::New<Float64x2>();
RegisterClass(cls, Symbols::Float64x2(), lib);
cls.set_num_type_arguments(0);
cls.set_num_own_type_arguments(0);
cls.set_is_prefinalized();
pending_classes.Add(cls);
+ object_store->set_float64x2_class(cls);
type = Type::NewNonParameterizedType(cls);
object_store->set_float64x2_type(type);
@@ -1639,7 +1628,6 @@
cls = Class::New<LibraryPrefix>();
cls = Class::New<Type>();
- cls = Class::New<FunctionType>();
cls = Class::New<TypeRef>();
cls = Class::New<TypeParameter>();
cls = Class::New<BoundedType>();
@@ -1722,7 +1710,7 @@
cls = Class::New<ReceivePort>();
cls = Class::New<SendPort>();
cls = Class::New<Stacktrace>();
- cls = Class::New<JSRegExp>();
+ cls = Class::New<RegExp>();
cls = Class::New<Number>();
cls = Class::New<WeakProperty>();
@@ -2432,10 +2420,10 @@
break;
}
sup_type = cls.super_type();
- // A BoundedType, TypeRef, or FunctionType can appear as type argument of
+ // A BoundedType, TypeRef, or function type can appear as type argument of
// sup_type, but not as sup_type itself.
ASSERT(sup_type.IsType());
- sup_type = ClassFinalizer::ResolveTypeClass(cls, Type::Cast(sup_type));
+ ClassFinalizer::ResolveTypeClass(cls, Type::Cast(sup_type));
cls = sup_type.type_class();
ASSERT(!cls.IsTypedefClass());
} while (true);
@@ -3193,8 +3181,54 @@
if (FLAG_show_internal_names) {
return Name();
}
-NOT_IN_PRODUCT(
switch (id()) {
+ case kFloat32x4Cid:
+ return Symbols::Float32x4().raw();
+ case kInt32x4Cid:
+ return Symbols::Int32x4().raw();
+ case kTypedDataInt8ArrayCid:
+ case kExternalTypedDataInt8ArrayCid:
+ return Symbols::Int8List().raw();
+ case kTypedDataUint8ArrayCid:
+ case kExternalTypedDataUint8ArrayCid:
+ return Symbols::Uint8List().raw();
+ case kTypedDataUint8ClampedArrayCid:
+ case kExternalTypedDataUint8ClampedArrayCid:
+ return Symbols::Uint8ClampedList().raw();
+ case kTypedDataInt16ArrayCid:
+ case kExternalTypedDataInt16ArrayCid:
+ return Symbols::Int16List().raw();
+ case kTypedDataUint16ArrayCid:
+ case kExternalTypedDataUint16ArrayCid:
+ return Symbols::Uint16List().raw();
+ case kTypedDataInt32ArrayCid:
+ case kExternalTypedDataInt32ArrayCid:
+ return Symbols::Int32List().raw();
+ case kTypedDataUint32ArrayCid:
+ case kExternalTypedDataUint32ArrayCid:
+ return Symbols::Uint32List().raw();
+ case kTypedDataInt64ArrayCid:
+ case kExternalTypedDataInt64ArrayCid:
+ return Symbols::Int64List().raw();
+ case kTypedDataUint64ArrayCid:
+ case kExternalTypedDataUint64ArrayCid:
+ return Symbols::Uint64List().raw();
+ case kTypedDataInt32x4ArrayCid:
+ case kExternalTypedDataInt32x4ArrayCid:
+ return Symbols::Int32x4List().raw();
+ case kTypedDataFloat32x4ArrayCid:
+ case kExternalTypedDataFloat32x4ArrayCid:
+ return Symbols::Float32x4List().raw();
+ case kTypedDataFloat64x2ArrayCid:
+ case kExternalTypedDataFloat64x2ArrayCid:
+ return Symbols::Float64x2List().raw();
+ case kTypedDataFloat32ArrayCid:
+ case kExternalTypedDataFloat32ArrayCid:
+ return Symbols::Float32List().raw();
+ case kTypedDataFloat64ArrayCid:
+ case kExternalTypedDataFloat64ArrayCid:
+ return Symbols::Float64List().raw();
+NOT_IN_PRODUCT(
case kNullCid:
return Symbols::Null().raw();
case kDynamicCid:
@@ -3279,54 +3313,8 @@
case kImmutableArrayCid:
case kGrowableObjectArrayCid:
return Symbols::List().raw();
- case kFloat32x4Cid:
- return Symbols::Float32x4().raw();
- case kInt32x4Cid:
- return Symbols::Int32x4().raw();
- case kTypedDataInt8ArrayCid:
- case kExternalTypedDataInt8ArrayCid:
- return Symbols::Int8List().raw();
- case kTypedDataUint8ArrayCid:
- case kExternalTypedDataUint8ArrayCid:
- return Symbols::Uint8List().raw();
- case kTypedDataUint8ClampedArrayCid:
- case kExternalTypedDataUint8ClampedArrayCid:
- return Symbols::Uint8ClampedList().raw();
- case kTypedDataInt16ArrayCid:
- case kExternalTypedDataInt16ArrayCid:
- return Symbols::Int16List().raw();
- case kTypedDataUint16ArrayCid:
- case kExternalTypedDataUint16ArrayCid:
- return Symbols::Uint16List().raw();
- case kTypedDataInt32ArrayCid:
- case kExternalTypedDataInt32ArrayCid:
- return Symbols::Int32List().raw();
- case kTypedDataUint32ArrayCid:
- case kExternalTypedDataUint32ArrayCid:
- return Symbols::Uint32List().raw();
- case kTypedDataInt64ArrayCid:
- case kExternalTypedDataInt64ArrayCid:
- return Symbols::Int64List().raw();
- case kTypedDataUint64ArrayCid:
- case kExternalTypedDataUint64ArrayCid:
- return Symbols::Uint64List().raw();
- case kTypedDataInt32x4ArrayCid:
- case kExternalTypedDataInt32x4ArrayCid:
- return Symbols::Int32x4List().raw();
- case kTypedDataFloat32x4ArrayCid:
- case kExternalTypedDataFloat32x4ArrayCid:
- return Symbols::Float32x4List().raw();
- case kTypedDataFloat64x2ArrayCid:
- case kExternalTypedDataFloat64x2ArrayCid:
- return Symbols::Float64x2List().raw();
- case kTypedDataFloat32ArrayCid:
- case kExternalTypedDataFloat32ArrayCid:
- return Symbols::Float32List().raw();
- case kTypedDataFloat64ArrayCid:
- case kExternalTypedDataFloat64ArrayCid:
- return Symbols::Float64List().raw();
- }
)
+ }
const String& name = String::Handle(Name());
return String::ScrubName(name);
}
@@ -3637,8 +3625,8 @@
}
-bool Class::IsFunctionClass() const {
- return raw() == Type::Handle(Type::Function()).type_class();
+bool Class::IsDartFunctionClass() const {
+ return raw() == Type::Handle(Type::DartFunctionType()).type_class();
}
@@ -3716,7 +3704,7 @@
bound_trail,
space);
}
- if (other.IsFunctionClass()) {
+ if (other.IsDartFunctionClass()) {
// Check if type S has a call() method.
Function& function = Function::Handle(zone,
thsi.LookupDynamicFunctionAllowAbstract(Symbols::Call()));
@@ -5438,12 +5426,12 @@
}
-RawFunctionType* Function::SignatureType() const {
- FunctionType& type = FunctionType::Handle();
+RawType* Function::SignatureType() const {
+ Type& type = Type::Handle();
const Object& obj = Object::Handle(raw_ptr()->data_);
if (IsSignatureFunction()) {
- ASSERT(obj.IsNull() || obj.IsFunctionType());
- type = obj.IsNull() ? FunctionType::null() : FunctionType::Cast(obj).raw();
+ ASSERT(obj.IsNull() || Type::Cast(obj).IsFunctionType());
+ type = obj.IsNull() ? Type::null() : Type::Cast(obj).raw();
} else {
ASSERT(IsClosureFunction());
ASSERT(!obj.IsNull());
@@ -5479,18 +5467,15 @@
const TypeArguments& signature_type_arguments =
TypeArguments::Handle(scope_class.type_parameters());
// Return the still unfinalized signature type.
- type = FunctionType::New(scope_class,
- signature_type_arguments,
- *this,
- token_pos());
-
+ type = Type::New(scope_class, signature_type_arguments, token_pos());
+ type.set_signature(*this);
SetSignatureType(type);
}
return type.raw();
}
-void Function::SetSignatureType(const FunctionType& value) const {
+void Function::SetSignatureType(const Type& value) const {
if (IsSignatureFunction()) {
set_data(value);
} else {
@@ -5625,7 +5610,7 @@
// invoke-field dispatcher: Array arguments descriptor
// redirecting constructor: RedirectionData
// closure function: ClosureData
-// irregexp function: Array[0] = JSRegExp
+// irregexp function: Array[0] = RegExp
// Array[1] = Smi string specialization cid
// native function: Array[0] = String native name
// Array[1] = Function implicit closure function
@@ -5659,10 +5644,10 @@
}
-RawJSRegExp* Function::regexp() const {
+RawRegExp* Function::regexp() const {
ASSERT(kind() == RawFunction::kIrregexpFunction);
const Array& pair = Array::Cast(Object::Handle(raw_ptr()->data_));
- return JSRegExp::RawCast(pair.At(0));
+ return RegExp::RawCast(pair.At(0));
}
@@ -5673,7 +5658,7 @@
}
-void Function::SetRegExpData(const JSRegExp& regexp,
+void Function::SetRegExpData(const RegExp& regexp,
intptr_t string_specialization_cid) const {
ASSERT(kind() == RawFunction::kIrregexpFunction);
ASSERT(RawObject::IsStringClassId(string_specialization_cid));
@@ -6159,9 +6144,9 @@
String::Handle(UserVisibleName()).ToCString(),
String::Handle(other.UserVisibleSignature()).ToCString(),
String::Handle(other.UserVisibleName()).ToCString(),
- String::Handle(FunctionType::Handle(
+ String::Handle(Type::Handle(
SignatureType()).EnumerateURIs()).ToCString(),
- String::Handle(FunctionType::Handle(
+ String::Handle(Type::Handle(
other.SignatureType()).EnumerateURIs()).ToCString());
return false;
}
@@ -6597,8 +6582,7 @@
param_name = ParameterNameAt(has_receiver - kClosure + i);
closure_function.SetParameterNameAt(i, param_name);
}
- const FunctionType& signature_type =
- FunctionType::Handle(closure_function.SignatureType());
+ const Type& signature_type = Type::Handle(closure_function.SignatureType());
if (!signature_type.IsFinalized()) {
ClassFinalizer::FinalizeType(
Class::Handle(Owner()), signature_type, ClassFinalizer::kCanonicalize);
@@ -6673,13 +6657,6 @@
pieces->Add(Symbols::LBrace());
}
for (intptr_t i = num_fixed_params; i < num_params; i++) {
- // The parameter name of an optional positional parameter does not need
- // to be part of the signature, since it is not used.
- if (num_opt_named_params > 0) {
- name = ParameterNameAt(i);
- pieces->Add(name);
- pieces->Add(Symbols::ColonSpace());
- }
param_type = ParameterTypeAt(i);
if (instantiate &&
param_type.IsFinalized() &&
@@ -6690,6 +6667,13 @@
ASSERT(!param_type.IsNull());
name = param_type.BuildName(name_visibility);
pieces->Add(name);
+ // The parameter name of an optional positional parameter does not need
+ // to be part of the signature, since it is not used.
+ if (num_opt_named_params > 0) {
+ name = ParameterNameAt(i);
+ pieces->Add(Symbols::Blank());
+ pieces->Add(name);
+ }
if (i != (num_params - 1)) {
pieces->Add(Symbols::CommaSpace());
}
@@ -6721,7 +6705,7 @@
RawInstance* Function::ImplicitInstanceClosure(const Instance& receiver) const {
ASSERT(IsImplicitClosureFunction());
- const FunctionType& signature_type = FunctionType::Handle(SignatureType());
+ const Type& signature_type = Type::Handle(SignatureType());
const Class& cls = Class::Handle(signature_type.type_class());
const Context& context = Context::Handle(Context::New(1));
context.SetAt(0, receiver);
@@ -7051,7 +7035,6 @@
// This output can be copied into a file, then used with sed
// to replace the old values.
// sed -i .bak -f /tmp/newkeys runtime/vm/method_recognizer.h
- // sed -i .bak -f /tmp/newkeys runtime/vm/flow_graph_builder.h
THR_Print("s/V(%s, %d)/V(%s, %d)/\n",
prefix, fp, prefix, SourceFingerprint());
} else {
@@ -7133,7 +7116,7 @@
}
-void ClosureData::set_signature_type(const FunctionType& value) const {
+void ClosureData::set_signature_type(const Type& value) const {
StorePointer(&raw_ptr()->signature_type_, value.raw());
}
@@ -8807,6 +8790,10 @@
RawString* Script::GetLine(intptr_t line_number, Heap::Space space) const {
const String& src = String::Handle(Source());
+ if (src.IsNull()) {
+ ASSERT(Dart::IsRunningPrecompiledCode());
+ return Symbols::OptimizedOut().raw();
+ }
intptr_t relative_line_number = line_number - line_offset();
intptr_t current_line = 1;
intptr_t line_start_idx = -1;
@@ -12095,6 +12082,7 @@
StorePointer(&raw_ptr()->args_descriptor_, value.raw());
}
+
void ICData::set_deopt_id(intptr_t value) const {
ASSERT(value <= kMaxInt32);
StoreNonPointer(&raw_ptr()->deopt_id_, value);
@@ -12329,8 +12317,18 @@
data_pos = 0;
}
data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id)));
- data.SetAt(data_pos + 1, target);
- data.SetAt(data_pos + 2, Smi::Handle(Smi::New(count)));
+ if (Isolate::Current()->compilation_allowed()) {
+ data.SetAt(data_pos + 1, target);
+ data.SetAt(data_pos + 2, Smi::Handle(Smi::New(count)));
+ } else {
+ // Precompilation only, after all functions have been compiled.
+ ASSERT(target.HasCode());
+ const Code& code = Code::Handle(target.CurrentCode());
+ const Smi& entry_point =
+ Smi::Handle(Smi::FromAlignedAddress(code.EntryPoint()));
+ data.SetAt(data_pos + 1, code);
+ data.SetAt(data_pos + 2, entry_point);
+ }
// Multithreaded access to ICData requires setting of array to be the last
// operation.
set_ic_data_array(data);
@@ -12404,6 +12402,7 @@
RawFunction* ICData::GetTargetAt(intptr_t index) const {
+ ASSERT(Isolate::Current()->compilation_allowed());
const intptr_t data_pos = index * TestEntryLength() + NumArgsTested();
ASSERT(Object::Handle(Array::Handle(ic_data()).At(data_pos)).IsFunction());
@@ -12413,6 +12412,15 @@
}
+RawObject* ICData::GetTargetOrCodeAt(intptr_t index) const {
+ const intptr_t data_pos = index * TestEntryLength() + NumArgsTested();
+
+ NoSafepointScope no_safepoint;
+ RawArray* raw_data = ic_data();
+ return raw_data->ptr()->data()[data_pos];
+}
+
+
void ICData::IncrementCountAt(intptr_t index, intptr_t value) const {
ASSERT(0 <= value);
ASSERT(value <= Smi::kMaxValue);
@@ -12432,6 +12440,7 @@
intptr_t ICData::GetCountAt(intptr_t index) const {
+ ASSERT(Isolate::Current()->compilation_allowed());
const Array& data = Array::Handle(ic_data());
const intptr_t data_pos = index * TestEntryLength() +
CountIndexFor(NumArgsTested());
@@ -12450,6 +12459,24 @@
}
+void ICData::SetCodeAt(intptr_t index, const Code& value) const {
+ ASSERT(!Isolate::Current()->compilation_allowed());
+ const Array& data = Array::Handle(ic_data());
+ const intptr_t data_pos = index * TestEntryLength() +
+ CodeIndexFor(NumArgsTested());
+ data.SetAt(data_pos, value);
+}
+
+
+void ICData::SetEntryPointAt(intptr_t index, const Smi& value) const {
+ ASSERT(!Isolate::Current()->compilation_allowed());
+ const Array& data = Array::Handle(ic_data());
+ const intptr_t data_pos = index * TestEntryLength() +
+ EntryPointIndexFor(NumArgsTested());
+ data.SetAt(data_pos, value);
+}
+
+
RawFunction* ICData::GetTargetForReceiverClassId(intptr_t class_id) const {
const intptr_t len = NumberOfChecks();
for (intptr_t i = 0; i < len; i++) {
@@ -14575,8 +14602,8 @@
if (cls.IsClosureClass()) {
const Function& signature =
Function::Handle(Closure::Cast(*this).function());
- FunctionType& type = FunctionType::Handle(signature.SignatureType());
- if (type.scope_class() == cls.raw()) {
+ Type& type = Type::Handle(signature.SignatureType());
+ if (type.type_class() == cls.raw()) {
// Type is not parameterized.
if (!type.IsCanonical()) {
type ^= type.Canonicalize();
@@ -14584,11 +14611,11 @@
}
return type.raw();
}
- const Class& scope_cls = Class::Handle(type.scope_class());
+ const Class& scope_cls = Class::Handle(type.type_class());
ASSERT(scope_cls.NumTypeArguments() > 0);
TypeArguments& type_arguments = TypeArguments::Handle(GetTypeArguments());
- type = FunctionType::New(
- scope_cls, type_arguments, signature, TokenPosition::kNoSource);
+ type = Type::New(scope_cls, type_arguments, TokenPosition::kNoSource);
+ type.set_signature(signature);
type.SetIsFinalized();
type ^= type.Canonicalize();
return type.raw();
@@ -14668,13 +14695,13 @@
if (!instantiated_other.IsFunctionType()) {
return false;
}
- other_signature = FunctionType::Cast(instantiated_other).signature();
+ other_signature = Type::Cast(instantiated_other).signature();
other_type_arguments = instantiated_other.arguments();
} else {
if (!other.IsFunctionType()) {
return false;
}
- other_signature = FunctionType::Cast(other).signature();
+ other_signature = Type::Cast(other).signature();
other_type_arguments = other.arguments();
}
const Function& signature =
@@ -14739,7 +14766,7 @@
return true;
}
const Function& other_signature = Function::Handle(
- zone, FunctionType::Cast(instantiated_other).signature());
+ zone, Type::Cast(instantiated_other).signature());
if (call.IsSubtypeOf(type_arguments,
other_signature,
other_type_arguments,
@@ -15236,7 +15263,7 @@
if (IsFunctionType()) {
cls = type_class();
const Function& signature_function = Function::Handle(
- zone, FunctionType::Cast(*this).signature());
+ zone, Type::Cast(*this).signature());
if (!cls.IsTypedefClass() ||
(cls.signature_function() != signature_function.raw())) {
if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
@@ -15341,6 +15368,7 @@
RawString* AbstractType::ClassName() const {
+ ASSERT(!IsFunctionType());
if (HasResolvedTypeClass()) {
return Class::Handle(type_class()).Name();
} else {
@@ -15350,68 +15378,79 @@
bool AbstractType::IsNullType() const {
- return HasResolvedTypeClass() &&
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
(type_class() == Isolate::Current()->object_store()->null_class());
}
bool AbstractType::IsBoolType() const {
- return HasResolvedTypeClass() &&
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
(type_class() == Isolate::Current()->object_store()->bool_class());
}
bool AbstractType::IsIntType() const {
- return HasResolvedTypeClass() &&
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
(type_class() == Type::Handle(Type::IntType()).type_class());
}
bool AbstractType::IsDoubleType() const {
- return HasResolvedTypeClass() &&
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
(type_class() == Type::Handle(Type::Double()).type_class());
}
bool AbstractType::IsFloat32x4Type() const {
- return HasResolvedTypeClass() &&
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
(type_class() == Type::Handle(Type::Float32x4()).type_class());
}
bool AbstractType::IsFloat64x2Type() const {
- return HasResolvedTypeClass() &&
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
(type_class() == Type::Handle(Type::Float64x2()).type_class());
}
bool AbstractType::IsInt32x4Type() const {
- return HasResolvedTypeClass() &&
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
(type_class() == Type::Handle(Type::Int32x4()).type_class());
}
bool AbstractType::IsNumberType() const {
- return HasResolvedTypeClass() &&
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
(type_class() == Type::Handle(Type::Number()).type_class());
}
bool AbstractType::IsSmiType() const {
- return HasResolvedTypeClass() &&
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
(type_class() == Type::Handle(Type::SmiType()).type_class());
}
bool AbstractType::IsStringType() const {
- return HasResolvedTypeClass() &&
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
(type_class() == Type::Handle(Type::StringType()).type_class());
}
bool AbstractType::IsDartFunctionType() const {
- return HasResolvedTypeClass() &&
- (type_class() == Type::Handle(Type::Function()).type_class());
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
+ (type_class() == Type::Handle(Type::DartFunctionType()).type_class());
}
@@ -15509,7 +15548,7 @@
// We may be checking bounds at finalization time and can encounter
// a still unfinalized bound. Finalizing the bound here may lead to cycles.
if (!bound.IsFinalized()) {
- return false; // TODO(regis): Return "maybe after instantiation".
+ return false; // TODO(regis): Return "maybe after instantiation".
}
// The current bound_trail cannot be used, because operands are swapped and
// the test is different anyway (more specific vs. subtype).
@@ -15530,10 +15569,10 @@
return true;
}
const Function& other_fun =
- Function::Handle(zone, FunctionType::Cast(other).signature());
+ Function::Handle(zone, Type::Cast(other).signature());
// Check for two function types.
const Function& fun =
- Function::Handle(zone, FunctionType::Cast(*this).signature());
+ Function::Handle(zone, Type::Cast(*this).signature());
return fun.TypeTest(test_kind,
TypeArguments::Handle(zone, arguments()),
other_fun,
@@ -15557,7 +15596,7 @@
function.TypeTest(test_kind,
TypeArguments::Handle(zone, arguments()),
Function::Handle(
- zone, FunctionType::Cast(other).signature()),
+ zone, Type::Cast(other).signature()),
TypeArguments::Handle(zone, other.arguments()),
bound_error,
space)) {
@@ -15667,7 +15706,7 @@
}
-RawType* Type::Function() {
+RawType* Type::DartFunctionType() {
return Isolate::Current()->object_store()->function_type();
}
@@ -15699,6 +15738,13 @@
}
+void Type::ResetIsFinalized() const {
+ ASSERT(IsFinalized());
+ set_type_state(RawType::kBeingFinalized);
+ SetIsFinalized();
+}
+
+
void Type::SetIsBeingFinalized() const {
ASSERT(IsResolved() && !IsFinalized() && !IsBeingFinalized());
set_type_state(RawType::kBeingFinalized);
@@ -15706,31 +15752,40 @@
bool Type::IsMalformed() const {
- if (raw_ptr()->error_ == LanguageError::null()) {
- return false;
+ if (raw_ptr()->sig_or_err_.error_ == LanguageError::null()) {
+ return false; // Valid type, but not a function type.
}
const LanguageError& type_error = LanguageError::Handle(error());
+ if (type_error.IsNull()) {
+ return false; // Valid function type.
+ }
return type_error.kind() == Report::kMalformedType;
}
bool Type::IsMalbounded() const {
+ if (raw_ptr()->sig_or_err_.error_ == LanguageError::null()) {
+ return false; // Valid type, but not a function type.
+ }
if (!Isolate::Current()->type_checks()) {
return false;
}
- if (raw_ptr()->error_ == LanguageError::null()) {
- return false;
- }
const LanguageError& type_error = LanguageError::Handle(error());
+ if (type_error.IsNull()) {
+ return false; // Valid function type.
+ }
return type_error.kind() == Report::kMalboundedType;
}
bool Type::IsMalformedOrMalbounded() const {
- if (raw_ptr()->error_ == LanguageError::null()) {
- return false;
+ if (raw_ptr()->sig_or_err_.error_ == LanguageError::null()) {
+ return false; // Valid type, but not a function type.
}
const LanguageError& type_error = LanguageError::Handle(error());
+ if (type_error.IsNull()) {
+ return false; // Valid function type.
+ }
if (type_error.kind() == Report::kMalformedType) {
return true;
}
@@ -15739,15 +15794,40 @@
}
+RawLanguageError* Type::error() const {
+ const Object& type_error = Object::Handle(raw_ptr()->sig_or_err_.error_);
+ if (type_error.IsLanguageError()) {
+ return LanguageError::RawCast(type_error.raw());
+ }
+ return LanguageError::null();
+}
+
+
void Type::set_error(const LanguageError& value) const {
- StorePointer(&raw_ptr()->error_, value.raw());
+ StorePointer(&raw_ptr()->sig_or_err_.error_, value.raw());
+}
+
+
+RawFunction* Type::signature() const {
+ if (raw_ptr()->sig_or_err_.signature_ == Function::null()) {
+ return Function::null();
+ }
+ const Object& obj = Object::Handle(raw_ptr()->sig_or_err_.signature_);
+ if (obj.IsFunction()) {
+ return Function::RawCast(obj.raw());
+ }
+ ASSERT(obj.IsLanguageError()); // Type is malformed or malbounded.
+ return Function::null();
+}
+
+
+void Type::set_signature(const Function& value) const {
+ StorePointer(&raw_ptr()->sig_or_err_.signature_, value.raw());
}
void Type::SetIsResolved() const {
ASSERT(!IsResolved());
- // A Typedef is a FunctionType, not a type.
- ASSERT(!Class::Handle(type_class()).IsTypedefClass());
set_type_state(RawType::kResolved);
}
@@ -15848,6 +15928,18 @@
// with different instantiators. Allocate a new instantiated version of it.
const Type& instantiated_type =
Type::Handle(zone, Type::New(cls, type_arguments, token_pos(), space));
+ // Preserve the bound error if any.
+ if (IsMalbounded()) {
+ const LanguageError& bound_error = LanguageError::Handle(zone, error());
+ instantiated_type.set_error(bound_error);
+ }
+ // Preserve the signature if this type represents a function type.
+ // Note that the types in the signature remain unchanged. They get indirectly
+ // instantiated by instantiating the type arguments above.
+ const Function& sig_fun = Function::Handle(zone, signature());
+ if (!sig_fun.IsNull()) {
+ instantiated_type.set_signature(sig_fun);
+ }
if (IsFinalized()) {
instantiated_type.SetIsFinalized();
} else {
@@ -15874,488 +15966,82 @@
return false;
}
const Type& other_type = Type::Cast(other);
+ if (IsFunctionType() != other_type.IsFunctionType()) {
+ return false;
+ }
ASSERT(IsResolved() && other_type.IsResolved());
if (IsMalformed() || other_type.IsMalformed()) {
- return false;
+ return false; // Malformed types do not get canonicalized.
+ }
+ if (IsMalbounded() != other_type.IsMalbounded()) {
+ return false; // Do not drop bound error.
}
if (type_class() != other_type.type_class()) {
return false;
}
if (!IsFinalized() || !other_type.IsFinalized()) {
- return false;
- }
- if (arguments() == other_type.arguments()) {
- return true;
- }
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- const Class& cls = Class::Handle(zone, type_class());
- const intptr_t num_type_params = cls.NumTypeParameters(thread);
- if (num_type_params == 0) {
- // Shortcut unnecessary handle allocation below.
- return true;
- }
- const intptr_t num_type_args = cls.NumTypeArguments();
- const intptr_t from_index = num_type_args - num_type_params;
- const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
- const TypeArguments& other_type_args = TypeArguments::Handle(
- zone, other_type.arguments());
- if (type_args.IsNull()) {
- // Ignore from_index.
- return other_type_args.IsRaw(0, num_type_args);
- }
- if (other_type_args.IsNull()) {
- // Ignore from_index.
- return type_args.IsRaw(0, num_type_args);
- }
- if (!type_args.IsSubvectorEquivalent(other_type_args,
- from_index,
- num_type_params)) {
- return false;
- }
-#ifdef DEBUG
- if (from_index > 0) {
- // Verify that the type arguments of the super class match, since they
- // depend solely on the type parameters that were just verified to match.
- ASSERT(type_args.Length() >= (from_index + num_type_params));
- ASSERT(other_type_args.Length() >= (from_index + num_type_params));
- AbstractType& type_arg = AbstractType::Handle(zone);
- AbstractType& other_type_arg = AbstractType::Handle(zone);
- for (intptr_t i = 0; i < from_index; i++) {
- type_arg = type_args.TypeAt(i);
- other_type_arg = other_type_args.TypeAt(i);
- // Ignore bounds of bounded types.
- while (type_arg.IsBoundedType()) {
- type_arg = BoundedType::Cast(type_arg).type();
- }
- while (other_type_arg.IsBoundedType()) {
- other_type_arg = BoundedType::Cast(other_type_arg).type();
- }
- ASSERT(type_arg.IsEquivalent(other_type_arg, trail));
- }
- }
-#endif
- return true;
-}
-
-
-bool Type::IsRecursive() const {
- return TypeArguments::Handle(arguments()).IsRecursive();
-}
-
-
-RawAbstractType* Type::CloneUnfinalized() const {
- ASSERT(IsResolved());
- if (IsFinalized()) {
- return raw();
- }
- ASSERT(!IsMalformed()); // Malformed types are finalized.
- ASSERT(!IsBeingFinalized()); // Cloning must occur prior to finalization.
- TypeArguments& type_args = TypeArguments::Handle(arguments());
- type_args = type_args.CloneUnfinalized();
- const Type& clone = Type::Handle(
- Type::New(Class::Handle(type_class()), type_args, token_pos()));
- clone.SetIsResolved();
- return clone.raw();
-}
-
-
-RawAbstractType* Type::CloneUninstantiated(const Class& new_owner,
- TrailPtr trail) const {
- ASSERT(IsFinalized());
- ASSERT(!IsMalformed());
- if (IsInstantiated()) {
- return raw();
- }
- // We may recursively encounter a type already being cloned, because we clone
- // the upper bounds of its uninstantiated type arguments in the same pass.
- Type& clone = Type::Handle();
- clone ^= OnlyBuddyInTrail(trail);
- if (!clone.IsNull()) {
- return clone.raw();
- }
- const Class& type_cls = Class::Handle(type_class());
- clone = Type::New(type_cls, TypeArguments::Handle(), token_pos());
- TypeArguments& type_args = TypeArguments::Handle(arguments());
- // Upper bounds of uninstantiated type arguments may form a cycle.
- if (type_args.IsRecursive() || !type_args.IsInstantiated()) {
- AddOnlyBuddyToTrail(&trail, clone);
- }
- type_args = type_args.CloneUninstantiated(new_owner, trail);
- clone.set_arguments(type_args);
- clone.SetIsFinalized();
- return clone.raw();
-}
-
-
-RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
- ASSERT(IsFinalized());
- if (IsCanonical() || IsMalformed()) {
- ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld());
- return this->raw();
- }
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- Isolate* isolate = thread->isolate();
- AbstractType& type = Type::Handle(zone);
- const Class& cls = Class::Handle(zone, type_class());
- ASSERT(!cls.IsTypedefClass()); // This type should be a FunctionType.
- if (cls.raw() == Object::dynamic_class() && (isolate != Dart::vm_isolate())) {
- return Object::dynamic_type().raw();
- }
- // Fast canonical lookup/registry for simple types.
- if (!cls.IsGeneric() && !cls.IsClosureClass()) {
- type = cls.CanonicalType();
- if (type.IsNull()) {
- ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate()));
- // Canonicalize the type arguments of the supertype, if any.
- TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
- type_args = type_args.Canonicalize(trail);
- if (IsCanonical()) {
- // Canonicalizing type_args canonicalized this type.
- ASSERT(IsRecursive());
- return this->raw();
- }
- set_arguments(type_args);
- type = cls.CanonicalType(); // May be set while canonicalizing type args.
- if (type.IsNull()) {
- MutexLocker ml(isolate->type_canonicalization_mutex());
- // Recheck if type exists.
- type = cls.CanonicalType();
- if (type.IsNull()) {
- SetCanonical();
- cls.set_canonical_types(*this);
- return this->raw();
- }
- }
- }
- ASSERT(this->Equals(type));
- ASSERT(type.IsCanonical());
- return type.raw();
- }
-
- Array& canonical_types = Array::Handle(zone);
- canonical_types ^= cls.canonical_types();
- if (canonical_types.IsNull()) {
- canonical_types = empty_array().raw();
- }
- intptr_t length = canonical_types.Length();
- // Linear search to see whether this type is already present in the
- // list of canonicalized types.
- // TODO(asiva): Try to re-factor this lookup code to make sharing
- // easy between the 4 versions of this loop.
- intptr_t index = 1; // Slot 0 is reserved for CanonicalType().
- while (index < length) {
- type ^= canonical_types.At(index);
- if (type.IsNull()) {
- break;
- }
- ASSERT(type.IsFinalized());
- if (this->Equals(type)) {
- ASSERT(type.IsCanonical());
- return type.raw();
- }
- index++;
- }
- // The type was not found in the table. It is not canonical yet.
-
- // Canonicalize the type arguments.
- TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
- // In case the type is first canonicalized at runtime, its type argument
- // vector may be longer than necessary. This is not an issue.
- ASSERT(type_args.IsNull() || (type_args.Length() >= cls.NumTypeArguments()));
- type_args = type_args.Canonicalize(trail);
- if (IsCanonical()) {
- // Canonicalizing type_args canonicalized this type as a side effect.
- ASSERT(IsRecursive());
- return this->raw();
- }
- set_arguments(type_args);
- ASSERT(type_args.IsNull() || type_args.IsOld());
-
- return cls.LookupOrAddCanonicalType(*this, index);
-}
-
-
-RawString* Type::EnumerateURIs() const {
- if (IsDynamicType() || IsVoidType()) {
- return Symbols::Empty().raw();
- }
- Zone* zone = Thread::Current()->zone();
- GrowableHandlePtrArray<const String> pieces(zone, 6);
- const Class& cls = Class::Handle(zone, type_class());
- pieces.Add(Symbols::TwoSpaces());
- pieces.Add(String::Handle(zone, cls.UserVisibleName()));
- pieces.Add(Symbols::SpaceIsFromSpace());
- const Library& library = Library::Handle(zone, cls.library());
- pieces.Add(String::Handle(zone, library.url()));
- pieces.Add(Symbols::NewLine());
- const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
- pieces.Add(String::Handle(zone, type_args.EnumerateURIs()));
- return Symbols::FromConcatAll(pieces);
-}
-
-
-intptr_t Type::Hash() const {
- ASSERT(IsFinalized());
- uint32_t result = 1;
- if (IsMalformed()) return result;
- result = CombineHashes(result, Class::Handle(type_class()).id());
- result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash());
- return FinalizeHash(result);
-}
-
-
-void Type::set_type_class(const Object& value) const {
- ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass()));
- StorePointer(&raw_ptr()->type_class_, value.raw());
-}
-
-
-void Type::set_arguments(const TypeArguments& value) const {
- ASSERT(!IsCanonical());
- StorePointer(&raw_ptr()->arguments_, value.raw());
-}
-
-
-RawType* Type::New(Heap::Space space) {
- RawObject* raw = Object::Allocate(Type::kClassId,
- Type::InstanceSize(),
- space);
- return reinterpret_cast<RawType*>(raw);
-}
-
-
-RawType* Type::New(const Object& clazz,
- const TypeArguments& arguments,
- TokenPosition token_pos,
- Heap::Space space) {
- const Type& result = Type::Handle(Type::New(space));
- result.set_type_class(clazz);
- result.set_arguments(arguments);
- result.set_token_pos(token_pos);
- result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated);
- return result.raw();
-}
-
-
-void Type::set_token_pos(TokenPosition token_pos) const {
- ASSERT(!token_pos.IsClassifying());
- StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
-}
-
-
-void Type::set_type_state(int8_t state) const {
- ASSERT((state >= RawType::kAllocated) &&
- (state <= RawType::kFinalizedUninstantiated));
- StoreNonPointer(&raw_ptr()->type_state_, state);
-}
-
-
-const char* Type::ToCString() const {
- const char* unresolved = IsResolved() ? "" : "Unresolved ";
- const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
- const char* class_name;
- if (HasResolvedTypeClass()) {
- class_name = String::Handle(
- Class::Handle(type_class()).Name()).ToCString();
- } else {
- class_name = UnresolvedClass::Handle(unresolved_class()).ToCString();
- }
- if (type_arguments.IsNull()) {
- return OS::SCreate(Thread::Current()->zone(),
- "%sType: class '%s'", unresolved, class_name);
- } else if (IsResolved() && IsFinalized() && IsRecursive()) {
- const intptr_t hash = Hash();
- const char* args_cstr = TypeArguments::Handle(arguments()).ToCString();
- return OS::SCreate(Thread::Current()->zone(),
- "Type: (@%p H%" Px ") class '%s', args:[%s]",
- raw(), hash, class_name, args_cstr);
- } else {
- const char* args_cstr = TypeArguments::Handle(arguments()).ToCString();
- return OS::SCreate(Thread::Current()->zone(),
- "%sType: class '%s', args:[%s]", unresolved, class_name, args_cstr);
- }
-}
-
-
-void FunctionType::SetIsFinalized() const {
- ASSERT(!IsFinalized());
- if (IsInstantiated()) {
- set_type_state(RawFunctionType::kFinalizedInstantiated);
- } else {
- set_type_state(RawFunctionType::kFinalizedUninstantiated);
- }
-}
-
-
-void FunctionType::ResetIsFinalized() const {
- ASSERT(IsFinalized());
- set_type_state(RawFunctionType::kBeingFinalized);
- SetIsFinalized();
-}
-
-
-void FunctionType::SetIsBeingFinalized() const {
- ASSERT(IsResolved() && !IsFinalized() && !IsBeingFinalized());
- set_type_state(RawFunctionType::kBeingFinalized);
-}
-
-
-bool FunctionType::IsMalformed() const {
- if (raw_ptr()->error_ == LanguageError::null()) {
- return false;
- }
- const LanguageError& type_error = LanguageError::Handle(error());
- return type_error.kind() == Report::kMalformedType;
-}
-
-
-bool FunctionType::IsMalbounded() const {
- if (!Isolate::Current()->type_checks()) {
- return false;
- }
- if (raw_ptr()->error_ == LanguageError::null()) {
- return false;
- }
- const LanguageError& type_error = LanguageError::Handle(error());
- return type_error.kind() == Report::kMalboundedType;
-}
-
-
-bool FunctionType::IsMalformedOrMalbounded() const {
- if (raw_ptr()->error_ == LanguageError::null()) {
- return false;
- }
- const LanguageError& type_error = LanguageError::Handle(error());
- if (type_error.kind() == Report::kMalformedType) {
- return true;
- }
- ASSERT(type_error.kind() == Report::kMalboundedType);
- return Isolate::Current()->type_checks();
-}
-
-
-void FunctionType::set_error(const LanguageError& value) const {
- StorePointer(&raw_ptr()->error_, value.raw());
-}
-
-
-void FunctionType::SetIsResolved() const {
- ASSERT(!IsResolved());
- set_type_state(RawFunctionType::kResolved);
-}
-
-
-bool FunctionType::IsInstantiated(TrailPtr trail) const {
- if (raw_ptr()->type_state_ == RawFunctionType::kFinalizedInstantiated) {
- return true;
- }
- if (raw_ptr()->type_state_ == RawFunctionType::kFinalizedUninstantiated) {
- return false;
- }
- if (arguments() == TypeArguments::null()) {
- return true;
- }
- const Class& scope_cls = Class::Handle(scope_class());
- if (!scope_cls.IsGeneric()) {
- ASSERT(scope_cls.IsClosureClass() || scope_cls.IsTypedefClass());
- ASSERT(arguments() == TypeArguments::null());
- return true;
- }
- const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
- const intptr_t num_type_args = scope_cls.NumTypeArguments();
- const intptr_t num_type_params = scope_cls.NumTypeParameters();
- // The vector may be longer than necessary. An empty vector is handled above.
- ASSERT(type_arguments.Length() >= num_type_args);
- return
- (num_type_params == 0) ||
- type_arguments.IsSubvectorInstantiated(num_type_args - num_type_params,
- num_type_params);
-}
-
-
-RawAbstractType* FunctionType::InstantiateFrom(
- const TypeArguments& instantiator_type_arguments,
- Error* bound_error,
- TrailPtr instantiation_trail,
- TrailPtr bound_trail,
- Heap::Space space) const {
- Zone* zone = Thread::Current()->zone();
- ASSERT(IsFinalized() || IsBeingFinalized());
- ASSERT(!IsInstantiated());
- ASSERT(!IsMalformed()); // FunctionType cannot be malformed.
- // Instantiating this type with its own type arguments as instantiator can
- // occur during finalization and bounds checking. Return the type unchanged.
- if (arguments() == instantiator_type_arguments.raw()) {
- return raw();
- }
- // Note that the scope class has to be resolved at this time, but not
- // necessarily finalized yet. We may be checking bounds at compile time or
- // finalizing the type argument vector of a recursive type.
- const Class& cls = Class::Handle(zone, scope_class());
- TypeArguments& type_arguments = TypeArguments::Handle(zone, arguments());
- ASSERT(type_arguments.Length() == cls.NumTypeArguments());
- type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
- bound_error,
- instantiation_trail,
- bound_trail,
- space);
- // This uninstantiated type is not modified, as it can be instantiated
- // with different instantiators. Allocate a new instantiated version of it.
- const FunctionType& instantiated_type = FunctionType::Handle(zone,
- FunctionType::New(cls,
- type_arguments,
- Function::Handle(zone, signature()),
- token_pos(),
- space));
- if (IsFinalized()) {
- instantiated_type.SetIsFinalized();
- } else {
- instantiated_type.SetIsResolved();
- }
- // Canonicalization is not part of instantiation.
- return instantiated_type.raw();
-}
-
-
-bool FunctionType::IsEquivalent(const Instance& other, TrailPtr trail) const {
- ASSERT(!IsNull());
- if (raw() == other.raw()) {
- return true;
- }
- if (!other.IsFunctionType()) {
- return false;
- }
- const FunctionType& other_type = FunctionType::Cast(other);
- ASSERT(IsResolved() && other_type.IsResolved());
- if (IsMalformed() || other_type.IsMalformed()) {
- return false;
- }
- if (scope_class() != other_type.scope_class()) {
- return false;
+ return false; // Too early to decide if equal.
}
if ((arguments() == other_type.arguments()) &&
(signature() == other_type.signature())) {
return true;
}
- if (!IsFinalized() || !other_type.IsFinalized()) {
- return false;
- }
-
- // We do not instantiate the types of the signature. This happens on demand
- // at runtime during a type test.
- // Therefore, equal function types must have equal type arguments.
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
- const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
- const TypeArguments& other_type_args = TypeArguments::Handle(
- zone, other_type.arguments());
- if (!type_args.Equals(other_type_args)) {
- return false;
+ if (arguments() != other_type.arguments()) {
+ const Class& cls = Class::Handle(zone, type_class());
+ const intptr_t num_type_params = cls.NumTypeParameters(thread);
+ // Shortcut unnecessary handle allocation below if non-generic.
+ if (num_type_params > 0) {
+ const intptr_t num_type_args = cls.NumTypeArguments();
+ const intptr_t from_index = num_type_args - num_type_params;
+ const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+ const TypeArguments& other_type_args = TypeArguments::Handle(
+ zone, other_type.arguments());
+ if (type_args.IsNull()) {
+ // Ignore from_index.
+ if (!other_type_args.IsRaw(0, num_type_args)) {
+ return false;
+ }
+ } else if (other_type_args.IsNull()) {
+ // Ignore from_index.
+ if (!type_args.IsRaw(0, num_type_args)) {
+ return false;
+ }
+ } else if (!type_args.IsSubvectorEquivalent(other_type_args,
+ from_index,
+ num_type_params)) {
+ return false;
+ }
+#ifdef DEBUG
+ if (from_index > 0) {
+ // Verify that the type arguments of the super class match, since they
+ // depend solely on the type parameters that were just verified to
+ // match.
+ ASSERT(type_args.Length() >= (from_index + num_type_params));
+ ASSERT(other_type_args.Length() >= (from_index + num_type_params));
+ AbstractType& type_arg = AbstractType::Handle(zone);
+ AbstractType& other_type_arg = AbstractType::Handle(zone);
+ for (intptr_t i = 0; i < from_index; i++) {
+ type_arg = type_args.TypeAt(i);
+ other_type_arg = other_type_args.TypeAt(i);
+ // Ignore bounds of bounded types.
+ while (type_arg.IsBoundedType()) {
+ type_arg = BoundedType::Cast(type_arg).type();
+ }
+ while (other_type_arg.IsBoundedType()) {
+ other_type_arg = BoundedType::Cast(other_type_arg).type();
+ }
+ ASSERT(type_arg.IsEquivalent(other_type_arg, trail));
+ }
+ }
+#endif
+ }
}
-
- // Type arguments are equal.
+ if (!IsFunctionType()) {
+ return true;
+ }
+ ASSERT(Type::Cast(other).IsFunctionType());
// Equal function types must have equal signature types and equal optional
// named arguments.
if (signature() == other_type.signature()) {
@@ -16420,32 +16106,62 @@
}
-bool FunctionType::IsRecursive() const {
+bool Type::IsRecursive() const {
return TypeArguments::Handle(arguments()).IsRecursive();
}
-RawAbstractType* FunctionType::CloneUnfinalized() const {
+RawAbstractType* Type::CloneUnfinalized() const {
ASSERT(IsResolved());
if (IsFinalized()) {
return raw();
}
ASSERT(!IsMalformed()); // Malformed types are finalized.
ASSERT(!IsBeingFinalized()); // Cloning must occur prior to finalization.
- TypeArguments& type_args = TypeArguments::Handle(arguments());
- type_args = type_args.CloneUnfinalized();
- const FunctionType& clone = FunctionType::Handle(
- FunctionType::New(Class::Handle(scope_class()),
- type_args,
- Function::Handle(signature()),
- token_pos()));
+ Zone* zone = Thread::Current()->zone();
+ const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+ const TypeArguments& type_args_clone =
+ TypeArguments::Handle(zone, type_args.CloneUnfinalized());
+ if (type_args_clone.raw() == type_args.raw()) {
+ return raw();
+ }
+ const Type& clone = Type::Handle(zone,
+ Type::New(Class::Handle(zone, type_class()), type_args, token_pos()));
+ // Preserve the bound error if any.
+ if (IsMalbounded()) {
+ const LanguageError& bound_error = LanguageError::Handle(zone, error());
+ clone.set_error(bound_error);
+ }
+ // Clone the signature if this type represents a function type.
+ Function& fun = Function::Handle(zone, signature());
+ if (!fun.IsNull()) {
+ const Class& owner = Class::Handle(zone, fun.Owner());
+ Function& fun_clone = Function::Handle(zone,
+ Function::NewSignatureFunction(owner, TokenPosition::kNoSource));
+ AbstractType& type = AbstractType::Handle(zone, fun.result_type());
+ type = type.CloneUnfinalized();
+ fun_clone.set_result_type(type);
+ const intptr_t num_params = fun.NumParameters();
+ fun_clone.set_num_fixed_parameters(fun.num_fixed_parameters());
+ fun_clone.SetNumOptionalParameters(fun.NumOptionalParameters(),
+ fun.HasOptionalPositionalParameters());
+ fun_clone.set_parameter_types(Array::Handle(Array::New(num_params,
+ Heap::kOld)));
+ for (intptr_t i = 0; i < num_params; i++) {
+ type = fun.ParameterTypeAt(i);
+ type = type.CloneUnfinalized();
+ fun_clone.SetParameterTypeAt(i, type);
+ }
+ fun_clone.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
+ clone.set_signature(fun_clone);
+ }
clone.SetIsResolved();
return clone.raw();
}
-RawAbstractType* FunctionType::CloneUninstantiated(const Class& new_owner,
- TrailPtr trail) const {
+RawAbstractType* Type::CloneUninstantiated(const Class& new_owner,
+ TrailPtr trail) const {
ASSERT(IsFinalized());
ASSERT(!IsMalformed());
if (IsInstantiated()) {
@@ -16453,16 +16169,42 @@
}
// We may recursively encounter a type already being cloned, because we clone
// the upper bounds of its uninstantiated type arguments in the same pass.
- FunctionType& clone = FunctionType::Handle();
+ Zone* zone = Thread::Current()->zone();
+ Type& clone = Type::Handle(zone);
clone ^= OnlyBuddyInTrail(trail);
if (!clone.IsNull()) {
return clone.raw();
}
- clone = FunctionType::New(Class::Handle(scope_class()),
- TypeArguments::Handle(),
- Function::Handle(signature()),
- token_pos());
- TypeArguments& type_args = TypeArguments::Handle(arguments());
+ const Class& type_cls = Class::Handle(zone, type_class());
+ clone = Type::New(type_cls, TypeArguments::Handle(zone), token_pos());
+ // Preserve the bound error if any.
+ if (IsMalbounded()) {
+ const LanguageError& bound_error = LanguageError::Handle(zone, error());
+ clone.set_error(bound_error);
+ }
+ // Clone the signature if this type represents a function type.
+ const Function& fun = Function::Handle(zone, signature());
+ if (!fun.IsNull()) {
+ Function& fun_clone = Function::Handle(zone,
+ Function::NewSignatureFunction(new_owner, TokenPosition::kNoSource));
+ AbstractType& type = AbstractType::Handle(zone, fun.result_type());
+ type = type.CloneUninstantiated(new_owner, trail);
+ fun_clone.set_result_type(type);
+ const intptr_t num_params = fun.NumParameters();
+ fun_clone.set_num_fixed_parameters(fun.num_fixed_parameters());
+ fun_clone.SetNumOptionalParameters(fun.NumOptionalParameters(),
+ fun.HasOptionalPositionalParameters());
+ fun_clone.set_parameter_types(Array::Handle(Array::New(num_params,
+ Heap::kOld)));
+ for (intptr_t i = 0; i < num_params; i++) {
+ type = fun.ParameterTypeAt(i);
+ type = type.CloneUninstantiated(new_owner, trail);
+ fun_clone.SetParameterTypeAt(i, type);
+ }
+ fun_clone.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
+ clone.set_signature(fun_clone);
+ }
+ TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
// Upper bounds of uninstantiated type arguments may form a cycle.
if (type_args.IsRecursive() || !type_args.IsInstantiated()) {
AddOnlyBuddyToTrail(&trail, clone);
@@ -16474,7 +16216,7 @@
}
-RawAbstractType* FunctionType::Canonicalize(TrailPtr trail) const {
+RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
ASSERT(IsFinalized());
if (IsCanonical() || IsMalformed()) {
ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld());
@@ -16482,10 +16224,46 @@
}
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
+ Isolate* isolate = thread->isolate();
AbstractType& type = Type::Handle(zone);
- const Class& scope_cls = Class::Handle(zone, type_class());
+ const Class& cls = Class::Handle(zone, type_class());
+ if (cls.raw() == Object::dynamic_class() && (isolate != Dart::vm_isolate())) {
+ return Object::dynamic_type().raw();
+ }
+ // Fast canonical lookup/registry for simple types.
+ if (!cls.IsGeneric() && !cls.IsClosureClass()) {
+ ASSERT(!IsFunctionType() || cls.IsTypedefClass());
+ type = cls.CanonicalType();
+ if (type.IsNull()) {
+ ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate()));
+ // Canonicalize the type arguments of the supertype, if any.
+ TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+ type_args = type_args.Canonicalize(trail);
+ if (IsCanonical()) {
+ // Canonicalizing type_args canonicalized this type.
+ ASSERT(IsRecursive());
+ return this->raw();
+ }
+ set_arguments(type_args);
+ type = cls.CanonicalType(); // May be set while canonicalizing type args.
+ if (type.IsNull()) {
+ MutexLocker ml(isolate->type_canonicalization_mutex());
+ // Recheck if type exists.
+ type = cls.CanonicalType();
+ if (type.IsNull()) {
+ SetCanonical();
+ cls.set_canonical_types(*this);
+ return this->raw();
+ }
+ }
+ }
+ ASSERT(this->Equals(type));
+ ASSERT(type.IsCanonical());
+ return type.raw();
+ }
+
Array& canonical_types = Array::Handle(zone);
- canonical_types ^= scope_cls.canonical_types();
+ canonical_types ^= cls.canonical_types();
if (canonical_types.IsNull()) {
canonical_types = empty_array().raw();
}
@@ -16513,8 +16291,7 @@
TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
// In case the type is first canonicalized at runtime, its type argument
// vector may be longer than necessary. This is not an issue.
- ASSERT(type_args.IsNull() ||
- (type_args.Length() >= scope_cls.NumTypeArguments()));
+ ASSERT(type_args.IsNull() || (type_args.Length() >= cls.NumTypeArguments()));
type_args = type_args.Canonicalize(trail);
if (IsCanonical()) {
// Canonicalizing type_args canonicalized this type as a side effect.
@@ -16524,161 +16301,187 @@
return this->raw();
}
set_arguments(type_args);
-
- // Replace the actual function by a signature function.
- const Function& fun = Function::Handle(zone, signature());
- if (!fun.IsSignatureFunction()) {
- Function& sig_fun = Function::Handle(zone,
- Function::NewSignatureFunction(scope_cls, TokenPosition::kNoSource));
- type = fun.result_type();
- type = type.Canonicalize(trail);
- sig_fun.set_result_type(type);
- const intptr_t num_params = fun.NumParameters();
- sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters());
- sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(),
- fun.HasOptionalPositionalParameters());
- sig_fun.set_parameter_types(Array::Handle(Array::New(num_params,
- Heap::kOld)));
- for (intptr_t i = 0; i < num_params; i++) {
- type = fun.ParameterTypeAt(i);
- type = type.Canonicalize(trail);
- sig_fun.SetParameterTypeAt(i, type);
- }
- sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
- set_signature(sig_fun);
- }
ASSERT(type_args.IsNull() || type_args.IsOld());
- return scope_cls.LookupOrAddCanonicalType(*this, index);
+ // In case of a function type, replace the actual function by a signature
+ // function.
+ if (IsFunctionType()) {
+ const Function& fun = Function::Handle(zone, signature());
+ if (!fun.IsSignatureFunction()) {
+ Function& sig_fun = Function::Handle(zone,
+ Function::NewSignatureFunction(cls, TokenPosition::kNoSource));
+ type = fun.result_type();
+ type = type.Canonicalize(trail);
+ sig_fun.set_result_type(type);
+ const intptr_t num_params = fun.NumParameters();
+ sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters());
+ sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(),
+ fun.HasOptionalPositionalParameters());
+ sig_fun.set_parameter_types(Array::Handle(Array::New(num_params,
+ Heap::kOld)));
+ for (intptr_t i = 0; i < num_params; i++) {
+ type = fun.ParameterTypeAt(i);
+ type = type.Canonicalize(trail);
+ sig_fun.SetParameterTypeAt(i, type);
+ }
+ sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
+ set_signature(sig_fun);
+ }
+ }
+ return cls.LookupOrAddCanonicalType(*this, index);
}
-RawString* FunctionType::EnumerateURIs() const {
- Zone* zone = Thread::Current()->zone();
- // The scope class and type arguments do not appear explicitly in the user
- // visible name. The type arguments were used to instantiate the function type
- // prior to this call.
- const Function& sig_fun = Function::Handle(zone, signature());
- AbstractType& type = AbstractType::Handle(zone);
- const intptr_t num_params = sig_fun.NumParameters();
- GrowableHandlePtrArray<const String> pieces(zone, num_params + 1);
- for (intptr_t i = 0; i < num_params; i++) {
- type = sig_fun.ParameterTypeAt(i);
- pieces.Add(String::Handle(zone, type.EnumerateURIs()));
+RawString* Type::EnumerateURIs() const {
+ if (IsDynamicType() || IsVoidType()) {
+ return Symbols::Empty().raw();
}
- // Handle result type last, since it appears last in the user visible name.
- type = sig_fun.result_type();
- pieces.Add(String::Handle(zone, type.EnumerateURIs()));
+ Zone* zone = Thread::Current()->zone();
+ GrowableHandlePtrArray<const String> pieces(zone, 6);
+ if (IsFunctionType()) {
+ // The scope class and type arguments do not appear explicitly in the user
+ // visible name. The type arguments were used to instantiate the function
+ // type prior to this call.
+ const Function& sig_fun = Function::Handle(zone, signature());
+ AbstractType& type = AbstractType::Handle(zone);
+ const intptr_t num_params = sig_fun.NumParameters();
+ GrowableHandlePtrArray<const String> pieces(zone, num_params + 1);
+ for (intptr_t i = 0; i < num_params; i++) {
+ type = sig_fun.ParameterTypeAt(i);
+ pieces.Add(String::Handle(zone, type.EnumerateURIs()));
+ }
+ // Handle result type last, since it appears last in the user visible name.
+ type = sig_fun.result_type();
+ pieces.Add(String::Handle(zone, type.EnumerateURIs()));
+ } else {
+ const Class& cls = Class::Handle(zone, type_class());
+ pieces.Add(Symbols::TwoSpaces());
+ pieces.Add(String::Handle(zone, cls.UserVisibleName()));
+ pieces.Add(Symbols::SpaceIsFromSpace());
+ const Library& library = Library::Handle(zone, cls.library());
+ pieces.Add(String::Handle(zone, library.url()));
+ pieces.Add(Symbols::NewLine());
+ const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+ pieces.Add(String::Handle(zone, type_args.EnumerateURIs()));
+ }
return Symbols::FromConcatAll(pieces);
}
-intptr_t FunctionType::Hash() const {
+intptr_t Type::Hash() const {
ASSERT(IsFinalized());
uint32_t result = 1;
if (IsMalformed()) return result;
- result = CombineHashes(result, Class::Handle(scope_class()).id());
+ result = CombineHashes(result, Class::Handle(type_class()).id());
result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash());
- const Function& sig_fun = Function::Handle(signature());
- AbstractType& type = AbstractType::Handle(sig_fun.result_type());
- result = CombineHashes(result, type.Hash());
- result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters());
- const intptr_t num_params = sig_fun.NumParameters();
- for (intptr_t i = 0; i < num_params; i++) {
- type = sig_fun.ParameterTypeAt(i);
+ if (IsFunctionType()) {
+ const Function& sig_fun = Function::Handle(signature());
+ AbstractType& type = AbstractType::Handle(sig_fun.result_type());
result = CombineHashes(result, type.Hash());
- }
- if (sig_fun.NumOptionalNamedParameters() > 0) {
- String& param_name = String::Handle();
- for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) {
- param_name = sig_fun.ParameterNameAt(i);
- result = CombineHashes(result, param_name.Hash());
+ result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters());
+ const intptr_t num_params = sig_fun.NumParameters();
+ for (intptr_t i = 0; i < num_params; i++) {
+ type = sig_fun.ParameterTypeAt(i);
+ result = CombineHashes(result, type.Hash());
+ }
+ if (sig_fun.NumOptionalNamedParameters() > 0) {
+ String& param_name = String::Handle();
+ for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) {
+ param_name = sig_fun.ParameterNameAt(i);
+ result = CombineHashes(result, param_name.Hash());
+ }
}
}
return FinalizeHash(result);
}
-void FunctionType::set_scope_class(const Class& value) const {
- ASSERT(!value.IsNull());
- StorePointer(&raw_ptr()->scope_class_, value.raw());
+void Type::set_type_class(const Object& value) const {
+ ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass()));
+ StorePointer(&raw_ptr()->type_class_, value.raw());
}
-void FunctionType::set_arguments(const TypeArguments& value) const {
+void Type::set_arguments(const TypeArguments& value) const {
ASSERT(!IsCanonical());
StorePointer(&raw_ptr()->arguments_, value.raw());
}
-void FunctionType::set_signature(const Function& value) const {
- StorePointer(&raw_ptr()->signature_, value.raw());
-}
-
-
-RawFunctionType* FunctionType::New(Heap::Space space) {
- RawObject* raw = Object::Allocate(FunctionType::kClassId,
- FunctionType::InstanceSize(),
+RawType* Type::New(Heap::Space space) {
+ RawObject* raw = Object::Allocate(Type::kClassId,
+ Type::InstanceSize(),
space);
- return reinterpret_cast<RawFunctionType*>(raw);
+ return reinterpret_cast<RawType*>(raw);
}
-RawFunctionType* FunctionType::New(const Class& clazz,
- const TypeArguments& arguments,
- const Function& signature,
- TokenPosition token_pos,
- Heap::Space space) {
- const FunctionType& result = FunctionType::Handle(FunctionType::New(space));
- result.set_scope_class(clazz);
+RawType* Type::New(const Object& clazz,
+ const TypeArguments& arguments,
+ TokenPosition token_pos,
+ Heap::Space space) {
+ const Type& result = Type::Handle(Type::New(space));
+ result.set_type_class(clazz);
result.set_arguments(arguments);
- result.set_signature(signature);
result.set_token_pos(token_pos);
- result.StoreNonPointer(&result.raw_ptr()->type_state_,
- RawFunctionType::kAllocated);
+ result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated);
return result.raw();
}
-void FunctionType::set_token_pos(TokenPosition token_pos) const {
+void Type::set_token_pos(TokenPosition token_pos) const {
ASSERT(!token_pos.IsClassifying());
StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
}
-void FunctionType::set_type_state(int8_t state) const {
- ASSERT((state >= RawFunctionType::kAllocated) &&
- (state <= RawFunctionType::kFinalizedUninstantiated));
+void Type::set_type_state(int8_t state) const {
+ ASSERT((state >= RawType::kAllocated) &&
+ (state <= RawType::kFinalizedUninstantiated));
StoreNonPointer(&raw_ptr()->type_state_, state);
}
-const char* FunctionType::ToCString() const {
+const char* Type::ToCString() const {
+ Zone* zone = Thread::Current()->zone();
const char* unresolved = IsResolved() ? "" : "Unresolved ";
- const Class& scope_cls = Class::Handle(scope_class());
- const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
- const Function& signature_function = Function::Handle(signature());
- const String& signature_string = IsFinalized() ?
- String::Handle(
- signature_function.InstantiatedSignatureFrom(type_arguments,
- kInternalName)) :
- String::Handle(signature_function.Signature());
- if (scope_cls.IsClosureClass()) {
- ASSERT(arguments() == TypeArguments::null());
- return OS::SCreate(
- Thread::Current()->zone(),
- "%sFunctionType: %s", unresolved, signature_string.ToCString());
+ const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+ const char* args_cstr = type_args.IsNull() ? "null" : type_args.ToCString();
+ Class& cls = Class::Handle(zone);
+ const char* class_name;
+ if (HasResolvedTypeClass()) {
+ cls = type_class();
+ class_name = String::Handle(zone, cls.Name()).ToCString();
+ } else {
+ class_name = UnresolvedClass::Handle(zone, unresolved_class()).ToCString();
}
- const char* class_name = String::Handle(scope_cls.Name()).ToCString();
- const char* args_cstr =
- type_arguments.IsNull() ? "null" : type_arguments.ToCString();
- return OS::SCreate(
- Thread::Current()->zone(),
- "%s FunctionType: %s (scope_cls: %s, args: %s)",
- unresolved,
- signature_string.ToCString(),
- class_name,
- args_cstr);
+ if (IsFunctionType()) {
+ const Function& sig_fun = Function::Handle(zone, signature());
+ const String& sig = IsFinalized() ?
+ String::Handle(zone, sig_fun.InstantiatedSignatureFrom(type_args,
+ kInternalName)) :
+ String::Handle(zone, sig_fun.Signature());
+ if (cls.IsClosureClass()) {
+ ASSERT(type_args.IsNull());
+ return OS::SCreate(zone, "%sFunction Type: %s",
+ unresolved, sig.ToCString());
+ }
+ return OS::SCreate(zone, "%s Function Type: %s (class: %s, args: %s)",
+ unresolved,
+ sig.ToCString(),
+ class_name,
+ args_cstr);
+ }
+ if (type_args.IsNull()) {
+ return OS::SCreate(zone, "%sType: class '%s'", unresolved, class_name);
+ } else if (IsResolved() && IsFinalized() && IsRecursive()) {
+ const intptr_t hash = Hash();
+ return OS::SCreate(zone, "Type: (@%p H%" Px ") class '%s', args:[%s]",
+ raw(), hash, class_name, args_cstr);
+ } else {
+ return OS::SCreate(zone, "%sType: class '%s', args:[%s]",
+ unresolved, class_name, args_cstr);
+ }
}
@@ -17253,9 +17056,12 @@
if (IsFinalized()) {
return raw();
}
- AbstractType& bounded_type = AbstractType::Handle(type());
-
- bounded_type = bounded_type.CloneUnfinalized();
+ const AbstractType& bounded_type = AbstractType::Handle(type());
+ const AbstractType& bounded_type_clone =
+ AbstractType::Handle(bounded_type.CloneUnfinalized());
+ if (bounded_type_clone.raw() == bounded_type.raw()) {
+ return raw();
+ }
// No need to clone bound or type parameter, as they are not part of the
// finalization state of this bounded type.
return BoundedType::New(bounded_type,
@@ -21612,17 +21418,17 @@
}
-void JSRegExp::set_pattern(const String& pattern) const {
+void RegExp::set_pattern(const String& pattern) const {
StorePointer(&raw_ptr()->pattern_, pattern.raw());
}
-void JSRegExp::set_function(intptr_t cid, const Function& value) const {
+void RegExp::set_function(intptr_t cid, const Function& value) const {
StorePointer(FunctionAddr(cid), value.raw());
}
-void JSRegExp::set_bytecode(bool is_one_byte, const TypedData& bytecode) const {
+void RegExp::set_bytecode(bool is_one_byte, const TypedData& bytecode) const {
if (is_one_byte) {
StorePointer(&raw_ptr()->one_byte_bytecode_, bytecode.raw());
} else {
@@ -21631,16 +21437,16 @@
}
-void JSRegExp::set_num_bracket_expressions(intptr_t value) const {
+void RegExp::set_num_bracket_expressions(intptr_t value) const {
StoreSmi(&raw_ptr()->num_bracket_expressions_, Smi::New(value));
}
-RawJSRegExp* JSRegExp::New(Heap::Space space) {
- JSRegExp& result = JSRegExp::Handle();
+RawRegExp* RegExp::New(Heap::Space space) {
+ RegExp& result = RegExp::Handle();
{
- RawObject* raw = Object::Allocate(JSRegExp::kClassId,
- JSRegExp::InstanceSize(),
+ RawObject* raw = Object::Allocate(RegExp::kClassId,
+ RegExp::InstanceSize(),
space);
NoSafepointScope no_safepoint;
result ^= raw;
@@ -21652,21 +21458,21 @@
}
-void* JSRegExp::GetDataStartAddress() const {
+void* RegExp::GetDataStartAddress() const {
intptr_t addr = reinterpret_cast<intptr_t>(raw_ptr());
- return reinterpret_cast<void*>(addr + sizeof(RawJSRegExp));
+ return reinterpret_cast<void*>(addr + sizeof(RawRegExp));
}
-RawJSRegExp* JSRegExp::FromDataStartAddress(void* data) {
- JSRegExp& regexp = JSRegExp::Handle();
- intptr_t addr = reinterpret_cast<intptr_t>(data) - sizeof(RawJSRegExp);
+RawRegExp* RegExp::FromDataStartAddress(void* data) {
+ RegExp& regexp = RegExp::Handle();
+ intptr_t addr = reinterpret_cast<intptr_t>(data) - sizeof(RawRegExp);
regexp ^= RawObject::FromAddr(addr);
return regexp.raw();
}
-const char* JSRegExp::Flags() const {
+const char* RegExp::Flags() const {
switch (flags()) {
case kGlobal | kIgnoreCase | kMultiLine :
case kIgnoreCase | kMultiLine :
@@ -21684,14 +21490,14 @@
}
-bool JSRegExp::CanonicalizeEquals(const Instance& other) const {
+bool RegExp::CanonicalizeEquals(const Instance& other) const {
if (this->raw() == other.raw()) {
return true; // "===".
}
- if (other.IsNull() || !other.IsJSRegExp()) {
+ if (other.IsNull() || !other.IsRegExp()) {
return false;
}
- const JSRegExp& other_js = JSRegExp::Cast(other);
+ const RegExp& other_js = RegExp::Cast(other);
// Match the pattern.
const String& str1 = String::Handle(pattern());
const String& str2 = String::Handle(other_js.pattern());
@@ -21708,10 +21514,10 @@
}
-const char* JSRegExp::ToCString() const {
+const char* RegExp::ToCString() const {
const String& str = String::Handle(pattern());
return OS::SCreate(Thread::Current()->zone(),
- "JSRegExp: pattern=%s flags=%s", str.ToCString(), Flags());
+ "RegExp: pattern=%s flags=%s", str.ToCString(), Flags());
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 78794a9..1ed09f7 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1102,7 +1102,7 @@
bool IsObjectClass() const { return id() == kInstanceCid; }
// Check if this class represents the 'Function' class.
- bool IsFunctionClass() const;
+ bool IsDartFunctionClass() const;
// Check if this class represents the 'Closure' class.
bool IsClosureClass() const { return id() == kClosureCid; }
@@ -1514,7 +1514,6 @@
friend class Instance;
friend class Object;
friend class Type;
- friend class FunctionType;
friend class Intrinsifier;
friend class Precompiler;
};
@@ -1926,6 +1925,10 @@
RawFunction* GetTargetAt(intptr_t index) const;
RawFunction* GetTargetForReceiverClassId(intptr_t class_id) const;
+ RawObject* GetTargetOrCodeAt(intptr_t index) const;
+ void SetCodeAt(intptr_t index, const Code& value) const;
+ void SetEntryPointAt(intptr_t index, const Smi& value) const;
+
void IncrementCountAt(intptr_t index, intptr_t value) const;
void SetCountAt(intptr_t index, intptr_t value) const;
intptr_t GetCountAt(intptr_t index) const;
@@ -1962,10 +1965,16 @@
static intptr_t TargetIndexFor(intptr_t num_args) {
return num_args;
}
+ static intptr_t CodeIndexFor(intptr_t num_args) {
+ return num_args;
+ }
static intptr_t CountIndexFor(intptr_t num_args) {
return (num_args + 1);
}
+ static intptr_t EntryPointIndexFor(intptr_t num_args) {
+ return (num_args + 1);
+ }
bool IsUsedAt(intptr_t i) const;
@@ -2137,16 +2146,16 @@
// Return the type of this function's signature. It may not be canonical yet.
// For example, if this function has a signature of the form
- // '(T, [b: B, c: C]) => R', where 'T' and 'R' are type parameters of the
+ // '(T, [B, C]) => R', where 'T' and 'R' are type parameters of the
// owner class of this function, then its signature type is a parameterized
- // FunctionType with uninstantiated type arguments 'T' and 'R' as elements of
+ // function type with uninstantiated type arguments 'T' and 'R' as elements of
// its type argument vector.
- RawFunctionType* SignatureType() const;
+ RawType* SignatureType() const;
// Update the signature type (with a canonical version).
- void SetSignatureType(const FunctionType& value) const;
+ void SetSignatureType(const Type& value) const;
- // Build a string of the form 'C<T, R>(T, {b: B, c: C}) => R' representing the
+ // Build a string of the form 'C<T, R>(T, {B b, C c}) => R' representing the
// internal signature of the given function. In this example, T and R are
// type parameters of class C, the owner of the function.
RawString* Signature() const {
@@ -2154,7 +2163,7 @@
return BuildSignature(instantiate, kInternalName, TypeArguments::Handle());
}
- // Build a string of the form '(T, {b: B, c: C}) => R' representing the
+ // Build a string of the form '(T, {B b, C c}) => R' representing the
// user visible signature of the given function. In this example, T and R are
// type parameters of class C, the owner of the function, also called the
// scope class of the function type.
@@ -2166,9 +2175,9 @@
instantiate, kUserVisibleName, TypeArguments::Handle());
}
- // Build a string of the form '(A, {b: B, c: C}) => D' representing the
+ // Build a string of the form '(A, {B b, C c}) => D' representing the
// signature of the given function, where all generic types (e.g. '<T, R>' in
- // 'C<T, R>(T, {b: B, c: C}) => R') are instantiated using the given
+ // 'C<T, R>(T, {B b, C c}) => R') are instantiated using the given
// instantiator type argument vector of a C instance (e.g. '<A, D>').
RawString* InstantiatedSignatureFrom(const TypeArguments& instantiator,
NameVisibility name_visibility) const {
@@ -2180,7 +2189,7 @@
// does not involve generic parameter types or generic result type.
bool HasInstantiatedSignature() const;
- // Build a string of the form 'T, {b: B, c: C} representing the user
+ // Build a string of the form 'T, {B b, C c}' representing the user
// visible formal parameters of the function.
RawString* UserVisibleFormalParameters() const;
@@ -2189,9 +2198,9 @@
RawScript* script() const;
RawObject* RawOwner() const { return raw_ptr()->owner_; }
- RawJSRegExp* regexp() const;
+ RawRegExp* regexp() const;
intptr_t string_specialization_cid() const;
- void SetRegExpData(const JSRegExp& regexp,
+ void SetRegExpData(const RegExp& regexp,
intptr_t string_specialization_cid) const;
RawString* native_name() const;
@@ -2858,8 +2867,8 @@
void set_parent_function(const Function& value) const;
// Signature type of this closure function.
- RawFunctionType* signature_type() const { return raw_ptr()->signature_type_; }
- void set_signature_type(const FunctionType& value) const;
+ RawType* signature_type() const { return raw_ptr()->signature_type_; }
+ void set_signature_type(const Type& value) const;
RawInstance* implicit_static_closure() const {
return raw_ptr()->closure_;
@@ -5225,7 +5234,7 @@
friend class Class;
friend class Closure;
friend class DeferredObject;
- friend class JSRegExp;
+ friend class RegExp;
friend class SnapshotWriter;
friend class StubCode;
friend class TypedDataView;
@@ -5320,6 +5329,9 @@
virtual bool IsEquivalent(const Instance& other, TrailPtr trail = NULL) const;
virtual bool IsRecursive() const;
+ // Check if this type represents a function type.
+ virtual bool IsFunctionType() const { return false; }
+
// Instantiate this type using the given type argument vector.
// Return a new type, or return 'this' if it is already instantiated.
// If bound_error is not NULL, it may be set to reflect a bound error.
@@ -5395,7 +5407,9 @@
// Check if this type represents the 'dynamic' type.
bool IsDynamicType() const {
- return HasResolvedTypeClass() && (type_class() == Object::dynamic_class());
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
+ (type_class() == Object::dynamic_class());
}
// Check if this type represents the 'Null' type.
@@ -5403,12 +5417,15 @@
// Check if this type represents the 'void' type.
bool IsVoidType() const {
- return HasResolvedTypeClass() && (type_class() == Object::void_class());
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
+ (type_class() == Object::void_class());
}
bool IsObjectType() const {
- return HasResolvedTypeClass() &&
- Class::Handle(type_class()).IsObjectClass();
+ return !IsFunctionType() &&
+ HasResolvedTypeClass() &&
+ Class::Handle(type_class()).IsObjectClass();
}
// Check if this type represents the 'bool' type.
@@ -5496,6 +5513,7 @@
(raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated);
}
virtual void SetIsFinalized() const;
+ void ResetIsFinalized() const; // Ignore current state and set again.
virtual bool IsBeingFinalized() const {
return raw_ptr()->type_state_ == RawType::kBeingFinalized;
}
@@ -5503,7 +5521,7 @@
virtual bool IsMalformed() const;
virtual bool IsMalbounded() const;
virtual bool IsMalformedOrMalbounded() const;
- virtual RawLanguageError* error() const { return raw_ptr()->error_; }
+ virtual RawLanguageError* error() const;
virtual void set_error(const LanguageError& value) const;
virtual bool IsResolved() const {
return raw_ptr()->type_state_ >= RawType::kResolved;
@@ -5519,6 +5537,12 @@
virtual bool IsInstantiated(TrailPtr trail = NULL) const;
virtual bool IsEquivalent(const Instance& other, TrailPtr trail = NULL) const;
virtual bool IsRecursive() const;
+ // If signature is not null, this type represents a function type.
+ RawFunction* signature() const;
+ void set_signature(const Function& value) const;
+ virtual bool IsFunctionType() const {
+ return signature() != Function::null();
+ }
virtual RawAbstractType* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
@@ -5584,7 +5608,7 @@
static RawType* ArrayType();
// The 'Function' type.
- static RawType* Function();
+ static RawType* DartFunctionType();
// The finalized type of the given non-parameterized class.
static RawType* NewNonParameterizedType(const Class& type_class);
@@ -5606,106 +5630,6 @@
};
-// TODO(regis): FunctionType is very similar to Type. Instead of a separate
-// class FunctionType, we could consider an object of class Type as representing
-// a function type if it has a non-null function (signature) field.
-// In order to save space, we could reuse the error_ field? A malformed or
-// malbounded function type would lose its function reference, but the error
-// string would contain relevant info.
-
-// A FunctionType describes the signature of a function, i.e. the result type
-// and formal parameter types of the function, as well as the names of optional
-// named formal parameters.
-// If these types refer to type parameters of a class in scope, the function
-// type is generic. A generic function type may be instantiated by a type
-// argument vector.
-// Therefore, a FunctionType consists of a scope class, a type argument vector,
-// and a signature.
-// The scope class is either a generic class (or generic typedef) declaring the
-// type parameters referred to by the signature, or class _Closure in the
-// non-generic case (including the non-generic typedef case).
-// The type arguments specify an instantiation of the generic signature (null in
-// the non-generic case).
-// The signature is a reference to an actual closure function (kClosureFunction)
-// or to a signature function (kSignatureFunction).
-// Since typedefs cannot refer to themselves, directly or indirectly, a
-// FunctionType cannot be recursive. Only individual formal parameter types can.
-class FunctionType : public AbstractType {
- public:
- virtual bool IsFinalized() const {
- return
- (raw_ptr()->type_state_ == RawFunctionType::kFinalizedInstantiated) ||
- (raw_ptr()->type_state_ == RawFunctionType::kFinalizedUninstantiated);
- }
- virtual void SetIsFinalized() const;
- void ResetIsFinalized() const; // Ignore current state and set again.
- virtual bool IsBeingFinalized() const {
- return raw_ptr()->type_state_ == RawFunctionType::kBeingFinalized;
- }
- virtual void SetIsBeingFinalized() const;
- virtual bool IsMalformed() const;
- virtual bool IsMalbounded() const;
- virtual bool IsMalformedOrMalbounded() const;
- virtual RawLanguageError* error() const { return raw_ptr()->error_; }
- virtual void set_error(const LanguageError& value) const;
- virtual bool IsResolved() const {
- return raw_ptr()->type_state_ >= RawFunctionType::kResolved;
- }
- virtual void SetIsResolved() const;
- // The scope class of a FunctionType is always resolved. It has no actual
- // type class. Returning false is important for the type testers to work, e.g.
- // IsDynamicType(), IsBoolType(), etc...
- virtual bool HasResolvedTypeClass() const { return false; }
- // Return scope_class from virtual type_class() to factorize finalization
- // with Type, also a parameterized type.
- virtual RawClass* type_class() const { return scope_class(); }
- RawClass* scope_class() const { return raw_ptr()->scope_class_; }
- void set_scope_class(const Class& value) const;
- virtual RawTypeArguments* arguments() const { return raw_ptr()->arguments_; }
- virtual void set_arguments(const TypeArguments& value) const;
- RawFunction* signature() const { return raw_ptr()->signature_; }
- virtual TokenPosition token_pos() const { return raw_ptr()->token_pos_; }
- virtual bool IsInstantiated(TrailPtr trail = NULL) const;
- virtual bool IsEquivalent(const Instance& other, TrailPtr trail = NULL) const;
- virtual bool IsRecursive() const;
- virtual RawAbstractType* InstantiateFrom(
- const TypeArguments& instantiator_type_arguments,
- Error* malformed_error,
- TrailPtr instantiation_trail,
- TrailPtr bound_trail,
- Heap::Space space) const;
- virtual RawAbstractType* CloneUnfinalized() const;
- virtual RawAbstractType* CloneUninstantiated(
- const Class& new_owner,
- TrailPtr trail = NULL) const;
- virtual RawAbstractType* Canonicalize(TrailPtr trail = NULL) const;
- virtual RawString* EnumerateURIs() const;
-
- virtual intptr_t Hash() const;
-
- static intptr_t InstanceSize() {
- return RoundedAllocationSize(sizeof(RawFunctionType));
- }
-
- static RawFunctionType* New(const Class& scope_class,
- const TypeArguments& arguments,
- const Function& signature,
- TokenPosition token_pos,
- Heap::Space space = Heap::kOld);
-
- private:
- void set_signature(const Function& value) const;
- void set_token_pos(TokenPosition token_pos) const;
- void set_type_state(int8_t state) const;
-
- static RawFunctionType* New(Heap::Space space = Heap::kOld);
-
- FINAL_HEAP_OBJECT_IMPLEMENTATION(FunctionType, AbstractType);
- friend class Class;
- friend class TypeArguments;
-};
-
-
// A TypeRef is used to break cycles in the representation of recursive types.
// Its only field is the recursive AbstractType it refers to.
// Note that the cycle always involves type arguments.
@@ -5728,7 +5652,6 @@
}
virtual bool IsResolved() const { return true; }
virtual bool HasResolvedTypeClass() const {
- // Returns false if the ref type is a function type.
return AbstractType::Handle(type()).HasResolvedTypeClass();
}
RawAbstractType* type() const { return raw_ptr()->type_; }
@@ -6094,6 +6017,11 @@
return reinterpret_cast<RawSmi*>(raw_smi);
}
+ static RawSmi* FromAlignedAddress(uword address) {
+ ASSERT((address & kSmiTagMask) == kSmiTag);
+ return reinterpret_cast<RawSmi*>(address);
+ }
+
static RawClass* Class();
static intptr_t Value(const RawSmi* raw_smi) {
@@ -8110,7 +8038,7 @@
// Internal JavaScript regular expression object.
-class JSRegExp : public Instance {
+class RegExp : public Instance {
public:
// Meaning of RegExType:
// kUninitialized: the type of th regexp has not been initialized yet.
@@ -8164,13 +8092,13 @@
static intptr_t function_offset(intptr_t cid) {
switch (cid) {
case kOneByteStringCid:
- return OFFSET_OF(RawJSRegExp, one_byte_function_);
+ return OFFSET_OF(RawRegExp, one_byte_function_);
case kTwoByteStringCid:
- return OFFSET_OF(RawJSRegExp, two_byte_function_);
+ return OFFSET_OF(RawRegExp, two_byte_function_);
case kExternalOneByteStringCid:
- return OFFSET_OF(RawJSRegExp, external_one_byte_function_);
+ return OFFSET_OF(RawRegExp, external_one_byte_function_);
case kExternalTwoByteStringCid:
- return OFFSET_OF(RawJSRegExp, external_two_byte_function_);
+ return OFFSET_OF(RawRegExp, external_two_byte_function_);
}
UNREACHABLE();
@@ -8201,16 +8129,16 @@
}
void* GetDataStartAddress() const;
- static RawJSRegExp* FromDataStartAddress(void* data);
+ static RawRegExp* FromDataStartAddress(void* data);
const char* Flags() const;
virtual bool CanonicalizeEquals(const Instance& other) const;
static intptr_t InstanceSize() {
- return RoundedAllocationSize(sizeof(RawJSRegExp));
+ return RoundedAllocationSize(sizeof(RawRegExp));
}
- static RawJSRegExp* New(Heap::Space space = Heap::kNew);
+ static RawRegExp* New(Heap::Space space = Heap::kNew);
private:
void set_type(RegExType type) const {
@@ -8229,7 +8157,7 @@
return FlagsBits::decode(raw_ptr()->type_flags_);
}
- FINAL_HEAP_OBJECT_IMPLEMENTATION(JSRegExp, Instance);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(RegExp, Instance);
friend class Class;
};
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 6c46997..145b84e 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -511,9 +511,13 @@
};
-intptr_t ObjectGraph::Serialize(WriteStream* stream) {
+intptr_t ObjectGraph::Serialize(WriteStream* stream, bool collect_garbage) {
+ if (collect_garbage) {
+ isolate()->heap()->CollectAllGarbage();
+ }
// Current encoding assumes objects do not move, so promote everything to old.
isolate()->heap()->new_space()->Evacuate();
+
WriteGraphVisitor visitor(isolate(), stream);
stream->WriteUnsigned(kObjectAlignment);
stream->WriteUnsigned(0);
diff --git a/runtime/vm/object_graph.h b/runtime/vm/object_graph.h
index 5187d5e..70091d6 100644
--- a/runtime/vm/object_graph.h
+++ b/runtime/vm/object_graph.h
@@ -94,8 +94,10 @@
// Write the isolate's object graph to 'stream'. Smis and nulls are omitted.
// Returns the number of nodes in the stream, including the root.
+ // If collect_garabage is false, the graph will include weakly-reachable
+ // objects.
// TODO(koda): Document format; support streaming/chunking.
- intptr_t Serialize(WriteStream* stream);
+ intptr_t Serialize(WriteStream* stream, bool collect_garbage);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectGraph);
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index ba63134..d93391f 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -101,10 +101,19 @@
jsobj.AddProperty("_implemented", is_implemented());
jsobj.AddProperty("_patch", is_patch());
jsobj.AddProperty("_traceAllocations", TraceAllocation(isolate));
+
const Class& superClass = Class::Handle(SuperClass());
if (!superClass.IsNull()) {
jsobj.AddProperty("super", superClass);
}
+ const AbstractType& superType = AbstractType::Handle(super_type());
+ if (!superType.IsNull()) {
+ jsobj.AddProperty("superType", superType);
+ }
+ const Type& mix = Type::Handle(mixin());
+ if (!mix.IsNull()) {
+ jsobj.AddProperty("mixin", mix);
+ }
jsobj.AddProperty("library", Object::Handle(library()));
const Script& script = Script::Handle(this->script());
if (!script.IsNull()) {
@@ -1135,33 +1144,6 @@
}
-void FunctionType::PrintJSONImpl(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
- PrintSharedInstanceJSON(&jsobj, ref);
- jsobj.AddProperty("kind", "FunctionType");
- if (IsCanonical()) {
- const Class& scope_cls = Class::Handle(scope_class());
- intptr_t id = scope_cls.FindCanonicalTypeIndex(*this);
- ASSERT(id >= 0);
- intptr_t cid = scope_cls.id();
- jsobj.AddFixedServiceId("classes/%" Pd "/types/%" Pd "", cid, id);
- jsobj.AddProperty("scopeClass", scope_cls);
- } else {
- jsobj.AddServiceId(*this);
- }
- const String& user_name = String::Handle(UserVisibleName());
- const String& vm_name = String::Handle(Name());
- AddNameProperties(&jsobj, user_name, vm_name);
- if (ref) {
- return;
- }
- const TypeArguments& typeArgs = TypeArguments::Handle(arguments());
- if (!typeArgs.IsNull()) {
- jsobj.AddProperty("typeArguments", typeArgs);
- }
-}
-
-
void TypeRef::PrintJSONImpl(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
PrintSharedInstanceJSON(&jsobj, ref);
@@ -1536,7 +1518,7 @@
}
-void JSRegExp::PrintJSONImpl(JSONStream* stream, bool ref) const {
+void RegExp::PrintJSONImpl(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
PrintSharedInstanceJSON(&jsobj, ref);
jsobj.AddProperty("kind", "RegExp");
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 5975735..03540bb 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -37,7 +37,7 @@
class PerfCodeObserver : public CodeObserver {
public:
PerfCodeObserver() : out_file_(NULL) {
- Dart_FileOpenCallback file_open = Isolate::file_open_callback();
+ Dart_FileOpenCallback file_open = Dart::file_open_callback();
if (file_open == NULL) {
return;
}
@@ -48,7 +48,7 @@
}
~PerfCodeObserver() {
- Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+ Dart_FileCloseCallback file_close = Dart::file_close_callback();
if ((file_close == NULL) || (out_file_ == NULL)) {
return;
}
@@ -64,7 +64,7 @@
uword prologue_offset,
uword size,
bool optimized) {
- Dart_FileWriteCallback file_write = Isolate::file_write_callback();
+ Dart_FileWriteCallback file_write = Dart::file_write_callback();
if ((file_write == NULL) || (out_file_ == NULL)) {
return;
}
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index d97a3a7..edfb890 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -40,7 +40,7 @@
class PerfCodeObserver : public CodeObserver {
public:
PerfCodeObserver() : out_file_(NULL) {
- Dart_FileOpenCallback file_open = Isolate::file_open_callback();
+ Dart_FileOpenCallback file_open = Dart::file_open_callback();
if (file_open == NULL) {
return;
}
@@ -51,7 +51,7 @@
}
~PerfCodeObserver() {
- Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+ Dart_FileCloseCallback file_close = Dart::file_close_callback();
if ((file_close == NULL) || (out_file_ == NULL)) {
return;
}
@@ -67,7 +67,7 @@
uword prologue_offset,
uword size,
bool optimized) {
- Dart_FileWriteCallback file_write = Isolate::file_write_callback();
+ Dart_FileWriteCallback file_write = Dart::file_write_callback();
if ((file_write == NULL) || (out_file_ == NULL)) {
return;
}
diff --git a/runtime/vm/os_thread.cc b/runtime/vm/os_thread.cc
index 0303161..b381692 100644
--- a/runtime/vm/os_thread.cc
+++ b/runtime/vm/os_thread.cc
@@ -8,6 +8,7 @@
#include "vm/lockers.h"
#include "vm/log.h"
#include "vm/thread_interrupter.h"
+#include "vm/timeline.h"
namespace dart {
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 9c4d714..315d5a1 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -35,6 +35,7 @@
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/tags.h"
+#include "vm/timeline.h"
#include "vm/timer.h"
#include "vm/zone.h"
@@ -498,7 +499,7 @@
VMTagScope tagScope(thread, VMTag::kCompileTopLevelTagId);
#ifndef PRODUCT
TimelineDurationScope tds(thread,
- thread->isolate()->GetCompilerStream(),
+ Timeline::GetCompilerStream(),
"CompileTopLevel");
if (tds.enabled()) {
tds.SetNumArguments(1);
@@ -856,7 +857,7 @@
const int64_t num_tokes_before = STAT_VALUE(thread, num_tokens_consumed);
#ifndef PRODUCT
TimelineDurationScope tds(thread,
- thread->isolate()->GetCompilerStream(),
+ Timeline::GetCompilerStream(),
"ParseClass");
if (tds.enabled()) {
tds.SetNumArguments(1);
@@ -973,7 +974,7 @@
FLAG_profile_vm);
#ifndef PRODUCT
TimelineDurationScope tds(thread,
- thread->isolate()->GetCompilerStream(),
+ Timeline::GetCompilerStream(),
"ParseFunction");
#endif // !PRODUCT
ASSERT(thread->long_jump_base()->IsSafeToJump());
@@ -1926,8 +1927,8 @@
TokenPosition::kNoSource));
signature_function.set_result_type(result_type);
AddFormalParamsToFunction(&func_params, signature_function);
- FunctionType& signature_type =
- FunctionType::ZoneHandle(Z, signature_function.SignatureType());
+ Type& signature_type =
+ Type::ZoneHandle(Z, signature_function.SignatureType());
if (!is_top_level_) {
signature_type ^= ClassFinalizer::FinalizeType(
current_class(), signature_type, ClassFinalizer::kCanonicalize);
@@ -2317,7 +2318,7 @@
// parameterized class, make sure that the receiver is captured as
// instantiator.
if (current_block_->scope->function_level() > 0) {
- const FunctionType& signature_type = FunctionType::Handle(Z,
+ const Type& signature_type = Type::Handle(Z,
implicit_closure_function.SignatureType());
const Class& scope_class = Class::Handle(Z, signature_type.type_class());
if (scope_class.IsGeneric()) {
@@ -6118,7 +6119,7 @@
void Parser::CheckStack() {
- volatile uword c_stack_pos = Isolate::GetCurrentStackPointer();
+ volatile uword c_stack_pos = Thread::GetCurrentStackPointer();
volatile uword c_stack_base = OSThread::Current()->stack_base();
volatile uword c_stack_limit =
c_stack_base - OSThread::GetSpecifiedStackSize();
@@ -6579,8 +6580,7 @@
AddFormalParamsToFunction(&closure_params, body);
// Finalize function type.
- FunctionType& signature_type =
- FunctionType::Handle(Z, body.SignatureType());
+ Type& signature_type = Type::Handle(Z, body.SignatureType());
signature_type ^= ClassFinalizer::FinalizeType(
current_class(), signature_type, ClassFinalizer::kCanonicalize);
body.SetSignatureType(signature_type);
@@ -6712,8 +6712,7 @@
AddFormalParamsToFunction(&closure_params, closure);
// Finalize function type.
- FunctionType& signature_type =
- FunctionType::Handle(Z, closure.SignatureType());
+ Type& signature_type = Type::Handle(Z, closure.SignatureType());
signature_type ^= ClassFinalizer::FinalizeType(
current_class(), signature_type, ClassFinalizer::kCanonicalize);
closure.SetSignatureType(signature_type);
@@ -6848,8 +6847,7 @@
AddFormalParamsToFunction(&closure_params, closure);
// Finalize function type.
- FunctionType& signature_type =
- FunctionType::Handle(Z, closure.SignatureType());
+ Type& signature_type = Type::Handle(Z, closure.SignatureType());
signature_type ^= ClassFinalizer::FinalizeType(
current_class(), signature_type, ClassFinalizer::kCanonicalize);
closure.SetSignatureType(signature_type);
@@ -7597,7 +7595,7 @@
// passed as a function argument, or returned as a function result.
LocalVariable* function_variable = NULL;
- FunctionType& function_type = FunctionType::ZoneHandle(Z);
+ Type& function_type = Type::ZoneHandle(Z);
if (variable_name != NULL) {
// Since the function type depends on the signature of the closure function,
// it cannot be determined before the formal parameter list of the closure
@@ -7606,10 +7604,10 @@
// We temporarily use the Closure class as scope class.
const Class& unknown_scope_class = Class::Handle(Z,
I->object_store()->closure_class());
- function_type = FunctionType::New(unknown_scope_class,
- TypeArguments::Handle(Z),
- function,
- function_pos);
+ function_type = Type::New(unknown_scope_class,
+ TypeArguments::Handle(Z),
+ function_pos);
+ function_type.set_signature(function);
function_type.SetIsFinalized(); // No finalization needed.
// Add the function variable to the scope before parsing the function in
@@ -7637,8 +7635,7 @@
INC_STAT(thread(), num_functions_parsed, 1);
// Now that the local function has formal parameters, lookup the signature
- FunctionType& signature_type =
- FunctionType::ZoneHandle(Z, function.SignatureType());
+ Type& signature_type = Type::ZoneHandle(Z, function.SignatureType());
signature_type ^= ClassFinalizer::FinalizeType(
current_class(), signature_type, ClassFinalizer::kCanonicalize);
function.SetSignatureType(signature_type);
@@ -7655,15 +7652,15 @@
CaptureInstantiator();
}
- // A signature type itself cannot be malformed or malbounded, only its
+ // A local signature type itself cannot be malformed or malbounded, only its
// signature function's result type or parameter types may be.
ASSERT(!signature_type.IsMalformed());
ASSERT(!signature_type.IsMalbounded());
if (variable_name != NULL) {
// Patch the function type of the variable now that the signature is known.
- function_type.set_scope_class(
- Class::Handle(Z, signature_type.scope_class()));
+ function_type.set_type_class(
+ Class::Handle(Z, signature_type.type_class()));
function_type.set_arguments(
TypeArguments::Handle(Z, signature_type.arguments()));
ASSERT(function_type.signature() == function.raw());
@@ -13183,8 +13180,7 @@
AddFormalParamsToFunction(¶ms, closure);
// Finalize function type.
- FunctionType& signature_type =
- FunctionType::Handle(Z, closure.SignatureType());
+ Type& signature_type = Type::Handle(Z, closure.SignatureType());
signature_type ^= ClassFinalizer::FinalizeType(
current_class(), signature_type, ClassFinalizer::kCanonicalize);
closure.SetSignatureType(signature_type);
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index 1d111dd..d357839 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -39,6 +39,7 @@
#include "vm/resolver.h"
#include "vm/symbols.h"
#include "vm/tags.h"
+#include "vm/timeline.h"
#include "vm/timer.h"
namespace dart {
@@ -213,6 +214,7 @@
DropLibraries();
BindStaticCalls();
+ SwitchICCalls();
DedupStackmaps();
DedupStackmapLists();
@@ -311,7 +313,7 @@
{ "dart:isolate", "_SendPortImpl", "send" },
{ "dart:typed_data", "ByteData", "ByteData." },
{ "dart:typed_data", "ByteData", "ByteData._view" },
- { "dart:typed_data", "_ByteBuffer", "_ByteBuffer._New" },
+ { "dart:typed_data", "ByteBuffer", "ByteBuffer._New" },
{ "dart:_vmservice", "::", "_registerIsolate" },
{ "dart:_vmservice", "::", "boot" },
{ "dart:developer", "Metrics", "_printMetrics" },
@@ -619,14 +621,10 @@
AddTypesOf(cls);
const TypeArguments& vector = TypeArguments::Handle(Z, abstype.arguments());
AddTypeArguments(vector);
- } else if (abstype.IsFunctionType()) {
- const FunctionType& func_type = FunctionType::Cast(abstype);
- const Class& cls = Class::Handle(Z, func_type.scope_class());
- AddTypesOf(cls);
- const Function& func = Function::Handle(Z, func_type.signature());
- AddTypesOf(func);
- const TypeArguments& vector = TypeArguments::Handle(Z, abstype.arguments());
- AddTypeArguments(vector);
+ if (type.IsFunctionType()) {
+ const Function& func = Function::Handle(Z, type.signature());
+ AddTypesOf(func);
+ }
} else if (abstype.IsBoundedType()) {
AbstractType& type = AbstractType::Handle(Z);
type = BoundedType::Cast(abstype).type();
@@ -845,7 +843,7 @@
false, // not abstract
false, // not external
false, // not native
- Class::Handle(Type::Handle(Type::Function()).type_class()),
+ Class::Handle(Type::Handle(Type::DartFunctionType()).type_class()),
fragment->token_pos()));
func.set_result_type(Object::dynamic_type());
@@ -1655,6 +1653,84 @@
}
+void Precompiler::SwitchICCalls() {
+ // Now that all functions have been compiled, we can switch to an instance
+ // call sequence that loads the Code object and entry point directly from
+ // the ic data array instead indirectly through a Function in the ic data
+ // array. Iterate all the object pools and rewrite the ic data from
+ // (cid, target function, count) to (cid, target code, entry point), and
+ // replace the ICLookupThroughFunction stub with ICLookupThroughCode.
+
+ class SwitchICCallsVisitor : public FunctionVisitor {
+ public:
+ explicit SwitchICCallsVisitor(Zone* zone) :
+ code_(Code::Handle(zone)),
+ pool_(ObjectPool::Handle(zone)),
+ entry_(Object::Handle(zone)),
+ ic_(ICData::Handle(zone)),
+ target_(Function::Handle(zone)),
+ target_code_(Code::Handle(zone)),
+ entry_point_(Smi::Handle(zone)) {
+ }
+
+ void VisitFunction(const Function& function) {
+ if (!function.HasCode()) {
+ ASSERT(function.HasImplicitClosureFunction());
+ return;
+ }
+
+ code_ = function.CurrentCode();
+ pool_ = code_.object_pool();
+ for (intptr_t i = 0; i < pool_.Length(); i++) {
+ if (pool_.InfoAt(i) != ObjectPool::kTaggedObject) continue;
+ entry_ = pool_.ObjectAt(i);
+ if (entry_.IsICData()) {
+ ic_ ^= entry_.raw();
+
+ // Only single check ICs are SwitchableCalls that use the ICLookup
+ // stubs. Some operators like + have ICData that check the types of
+ // arguments in addition to the receiver and use special stubs
+ // with fast paths for Smi operations.
+ if (ic_.NumArgsTested() != 1) continue;
+
+ for (intptr_t j = 0; j < ic_.NumberOfChecks(); j++) {
+ entry_ = ic_.GetTargetOrCodeAt(j);
+ if (entry_.IsFunction()) {
+ target_ ^= entry_.raw();
+ ASSERT(target_.HasCode());
+ target_code_ = target_.CurrentCode();
+ entry_point_ = Smi::FromAlignedAddress(target_code_.EntryPoint());
+ ic_.SetCodeAt(j, target_code_);
+ ic_.SetEntryPointAt(j, entry_point_);
+ } else {
+ // We've already seen and switched this ICData.
+ ASSERT(entry_.IsCode());
+ }
+ }
+ } else if (entry_.raw() ==
+ StubCode::ICLookupThroughFunction_entry()->code()) {
+ target_code_ = StubCode::ICLookupThroughCode_entry()->code();
+ pool_.SetObjectAt(i, target_code_);
+ }
+ }
+ }
+
+ private:
+ Code& code_;
+ ObjectPool& pool_;
+ Object& entry_;
+ ICData& ic_;
+ Function& target_;
+ Code& target_code_;
+ Smi& entry_point_;
+ };
+
+ ASSERT(!I->compilation_allowed());
+ SwitchICCallsVisitor visitor(Z);
+ VisitFunctions(&visitor);
+}
+
+
void Precompiler::DedupStackmaps() {
class DedupStackmapsVisitor : public FunctionVisitor {
public:
@@ -1981,7 +2057,7 @@
bool is_compiled = false;
Zone* const zone = thread()->zone();
#ifndef PRODUCT
- TimelineStream* compiler_timeline = isolate()->GetCompilerStream();
+ TimelineStream* compiler_timeline = Timeline::GetCompilerStream();
#endif // !PRODUCT
CSTAT_TIMER_SCOPE(thread(), codegen_timer);
HANDLESCOPE(thread());
@@ -2590,7 +2666,7 @@
RawError* Precompiler::CompileFunction(Thread* thread,
const Function& function) {
VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId);
- TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "Function", function);
+ TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "CompileFunction", function);
CompilationPipeline* pipeline =
CompilationPipeline::New(thread->zone(), function);
diff --git a/runtime/vm/precompiler.h b/runtime/vm/precompiler.h
index 31465f2..319eb34 100644
--- a/runtime/vm/precompiler.h
+++ b/runtime/vm/precompiler.h
@@ -318,6 +318,7 @@
void DropLibraries();
void BindStaticCalls();
+ void SwitchICCalls();
void DedupStackmaps();
void DedupStackmapLists();
void DedupInstructions();
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 0d1ad84..f0014f4 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -307,6 +307,12 @@
}
+bool SampleFilter::TaskFilterSample(Sample* sample) {
+ const intptr_t task = static_cast<intptr_t>(sample->thread_task());
+ return (task & thread_task_mask_) != 0;
+}
+
+
ClearProfileVisitor::ClearProfileVisitor(Isolate* isolate)
: SampleVisitor(isolate) {
}
@@ -844,6 +850,7 @@
#endif
sample->set_vm_tag(vm_tag);
sample->set_user_tag(isolate->user_tag());
+ sample->set_thread_task(thread->task_kind());
return sample;
}
@@ -887,7 +894,7 @@
}
if (FLAG_profile_vm) {
- uintptr_t sp = Isolate::GetCurrentStackPointer();
+ uintptr_t sp = Thread::GetCurrentStackPointer();
uintptr_t fp = 0;
uintptr_t pc = GetProgramCounter();
@@ -945,6 +952,11 @@
ASSERT(os_thread != NULL);
Isolate* isolate = thread->isolate();
+ // Thread is not doing VM work.
+ if (thread->task_kind() == Thread::kUnknownTask) {
+ return;
+ }
+
if (StubCode::HasBeenInitialized() &&
StubCode::InJumpToExceptionHandlerStub(state.pc)) {
// The JumpToExceptionHandler stub manually adjusts the stack pointer,
@@ -985,9 +997,7 @@
return;
}
- if (!thread->IsMutatorThread()) {
- // Not a mutator thread.
- // TODO(johnmccutchan): Profile all threads with an isolate.
+ if (thread->IsMutatorThread() && isolate->IsDeoptimizing()) {
return;
}
@@ -1015,7 +1025,9 @@
// Increment counter for vm tag.
VMTagCounters* counters = isolate->vm_tag_counters();
ASSERT(counters != NULL);
- counters->Increment(sample->vm_tag());
+ if (thread->IsMutatorThread()) {
+ counters->Increment(sample->vm_tag());
+ }
ProfilerNativeStackWalker native_stack_walker(isolate,
sample,
@@ -1223,6 +1235,10 @@
// Did not pass time filter.
continue;
}
+ if (!filter->TaskFilterSample(sample)) {
+ // Did not pass task filter.
+ continue;
+ }
if (!filter->FilterSample(sample)) {
// Did not pass filter.
continue;
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index 0b1207f..1f65c91 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -91,11 +91,14 @@
class SampleFilter : public ValueObject {
public:
SampleFilter(Isolate* isolate,
+ intptr_t thread_task_mask,
int64_t time_origin_micros,
int64_t time_extent_micros)
: isolate_(isolate),
+ thread_task_mask_(thread_task_mask),
time_origin_micros_(time_origin_micros),
time_extent_micros_(time_extent_micros) {
+ ASSERT(thread_task_mask != 0);
ASSERT(time_origin_micros_ >= -1);
ASSERT(time_extent_micros_ >= -1);
}
@@ -114,9 +117,12 @@
// Returns |true| if |sample| passes the time filter.
bool TimeFilterSample(Sample* sample);
+ // Returns |true| if |sample| passes the thread task filter.
+ bool TaskFilterSample(Sample* sample);
+
private:
Isolate* isolate_;
-
+ intptr_t thread_task_mask_;
int64_t time_origin_micros_;
int64_t time_extent_micros_;
};
@@ -274,6 +280,14 @@
state_ = ClassAllocationSampleBit::update(allocation_sample, state_);
}
+ Thread::TaskKind thread_task() const {
+ return ThreadTaskBit::decode(state_);
+ }
+
+ void set_thread_task(Thread::TaskKind task) {
+ state_ = ThreadTaskBit::update(task, state_);
+ }
+
bool is_continuation_sample() const {
return ContinuationSampleBit::decode(state_);
}
@@ -338,6 +352,8 @@
kTruncatedTraceBit = 5,
kClassAllocationSampleBit = 6,
kContinuationSampleBit = 7,
+ kThreadTaskBit = 8, // 4 bits.
+ kNextFreeBit = 12,
};
class HeadSampleBit : public BitField<uword, bool, kHeadSampleBit, 1> {};
class LeafFrameIsDart :
@@ -352,6 +368,8 @@
: public BitField<uword, bool, kClassAllocationSampleBit, 1> {};
class ContinuationSampleBit
: public BitField<uword, bool, kContinuationSampleBit, 1> {};
+ class ThreadTaskBit
+ : public BitField<uword, Thread::TaskKind, kThreadTaskBit, 4> {};
int64_t timestamp_;
ThreadId tid_;
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 35fd771..09d4d43 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -2497,9 +2497,11 @@
class NoAllocationSampleFilter : public SampleFilter {
public:
NoAllocationSampleFilter(Isolate* isolate,
+ intptr_t thread_task_mask,
int64_t time_origin_micros,
int64_t time_extent_micros)
: SampleFilter(isolate,
+ thread_task_mask,
time_origin_micros,
time_extent_micros) {
}
@@ -2518,6 +2520,7 @@
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
NoAllocationSampleFilter filter(isolate,
+ Thread::kMutatorTask,
time_origin_micros,
time_extent_micros);
const bool as_timeline = false;
@@ -2529,9 +2532,11 @@
public:
ClassAllocationSampleFilter(Isolate* isolate,
const Class& cls,
+ intptr_t thread_task_mask,
int64_t time_origin_micros,
int64_t time_extent_micros)
: SampleFilter(isolate,
+ thread_task_mask,
time_origin_micros,
time_extent_micros),
cls_(Class::Handle(cls.raw())) {
@@ -2557,6 +2562,7 @@
Isolate* isolate = thread->isolate();
ClassAllocationSampleFilter filter(isolate,
cls,
+ Thread::kMutatorTask,
time_origin_micros,
time_extent_micros);
const bool as_timeline = false;
@@ -2570,7 +2576,12 @@
int64_t time_extent_micros) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
+ const intptr_t thread_task_mask = Thread::kMutatorTask |
+ Thread::kCompilerTask |
+ Thread::kSweeperTask |
+ Thread::kMarkerTask;
NoAllocationSampleFilter filter(isolate,
+ thread_task_mask,
time_origin_micros,
time_extent_micros);
const bool as_timeline = true;
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index 6f4e0ad..e1b28fe 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -201,6 +201,7 @@
int64_t time_origin_micros = -1,
int64_t time_extent_micros = -1)
: SampleFilter(isolate,
+ Thread::kMutatorTask,
time_origin_micros,
time_extent_micros),
cid_(cid),
@@ -958,7 +959,7 @@
Library::Handle(isolate->object_store()->typed_data_library());
const Class& float32_list_class =
- Class::Handle(GetClass(typed_data_library, "_Float32Array"));
+ Class::Handle(GetClass(typed_data_library, "Float32List"));
EXPECT(!float32_list_class.IsNull());
Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
@@ -990,8 +991,6 @@
walker.Reset(Profile::kExclusiveCode);
EXPECT(walker.Down());
- EXPECT_STREQ("_Float32Array._Float32Array", walker.CurrentName());
- EXPECT(walker.Down());
EXPECT_STREQ("Float32List.Float32List", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("foo", walker.CurrentName());
@@ -2310,6 +2309,7 @@
sample->Init(isolate,
OS::GetCurrentMonotonicMicros(),
OSThread::Current()->trace_id());
+ sample->set_thread_task(Thread::kMutatorTask);
intptr_t i = 0;
while (pc_offsets[i] != 0) {
@@ -2324,7 +2324,7 @@
sample->SetAt(i, pc_offsets[i] + return_address_offset);
i++;
}
- sample->SetAt(i, NULL);
+ sample->SetAt(i, 0);
}
diff --git a/runtime/vm/random.cc b/runtime/vm/random.cc
index 6f1b6eb..5153ffe 100644
--- a/runtime/vm/random.cc
+++ b/runtime/vm/random.cc
@@ -3,8 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
#include "vm/random.h"
+#include "vm/dart.h"
#include "vm/flags.h"
-#include "vm/isolate.h"
+#include "vm/os.h"
namespace dart {
@@ -13,7 +14,7 @@
Random::Random() {
uint64_t seed = FLAG_random_seed;
if (seed == 0) {
- Dart_EntropySource callback = Isolate::entropy_source_callback();
+ Dart_EntropySource callback = Dart::entropy_source_callback();
if (callback != NULL) {
if (!callback(reinterpret_cast<uint8_t*>(&seed), sizeof(seed))) {
// Callback failed. Reset the seed to 0.
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index d32b5ab..437ab7e 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -343,13 +343,6 @@
}
-intptr_t RawFunctionType::VisitFunctionTypePointers(
- RawFunctionType* raw_obj, ObjectPointerVisitor* visitor) {
- visitor->VisitPointers(raw_obj->from(), raw_obj->to());
- return FunctionType::InstanceSize();
-}
-
-
intptr_t RawTypeRef::VisitTypeRefPointers(
RawTypeRef* raw_obj, ObjectPointerVisitor* visitor) {
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
@@ -931,12 +924,12 @@
}
-intptr_t RawJSRegExp::VisitJSRegExpPointers(RawJSRegExp* raw_obj,
- ObjectPointerVisitor* visitor) {
+intptr_t RawRegExp::VisitRegExpPointers(RawRegExp* raw_obj,
+ ObjectPointerVisitor* visitor) {
// Make sure that we got here with the tagged pointer as this.
ASSERT(raw_obj->IsHeapObject());
visitor->VisitPointers(raw_obj->from(), raw_obj->to());
- return JSRegExp::InstanceSize();
+ return RegExp::InstanceSize();
}
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index f438fc9..561011c 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -52,7 +52,6 @@
V(LibraryPrefix) \
V(AbstractType) \
V(Type) \
- V(FunctionType) \
V(TypeRef) \
V(TypeParameter) \
V(BoundedType) \
@@ -75,7 +74,7 @@
V(ReceivePort) \
V(SendPort) \
V(Stacktrace) \
- V(JSRegExp) \
+ V(RegExp) \
V(WeakProperty) \
V(MirrorReference) \
V(LinkedHashMap) \
@@ -108,6 +107,22 @@
V(Int32x4Array) \
V(Float64x2Array) \
+#define DART_CLASS_LIST_TYPED_DATA(V) \
+ V(Int8) \
+ V(Uint8) \
+ V(Uint8Clamped) \
+ V(Int16) \
+ V(Uint16) \
+ V(Int32) \
+ V(Uint32) \
+ V(Int64) \
+ V(Uint64) \
+ V(Float32) \
+ V(Float64) \
+ V(Float32x4) \
+ V(Int32x4) \
+ V(Float64x2)
+
#define CLASS_LIST_FOR_HANDLES(V) \
CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V) \
V(Array) \
@@ -852,7 +867,7 @@
}
RawContextScope* context_scope_;
RawFunction* parent_function_; // Enclosing function of this local function.
- RawFunctionType* signature_type_;
+ RawType* signature_type_;
RawInstance* closure_; // Closure object for static implicit closures.
RawObject** to() {
return reinterpret_cast<RawObject**>(&ptr()->closure_);
@@ -1601,28 +1616,18 @@
}
RawObject* type_class_; // Either resolved class or unresolved class.
RawTypeArguments* arguments_;
- RawLanguageError* error_; // Error object if type is malformed or malbounded.
+ // This type object represents a function type if its signature field is a
+ // non-null function object.
+ // If this type is malformed or malbounded, the signature field gets
+ // overwritten by the error object in order to save space. If the type is a
+ // function type, its signature is lost, but the message in the error object
+ // can describe the issue without needing the signature.
+ union {
+ RawFunction* signature_; // If not null, this type is a function type.
+ RawLanguageError* error_; // If not null, type is malformed or malbounded.
+ } sig_or_err_;
RawObject** to() {
- return reinterpret_cast<RawObject**>(&ptr()->error_);
- }
- TokenPosition token_pos_;
- int8_t type_state_;
-};
-
-
-class RawFunctionType : public RawAbstractType {
- private:
- RAW_HEAP_OBJECT_IMPLEMENTATION(FunctionType);
-
- RawObject** from() {
- return reinterpret_cast<RawObject**>(&ptr()->scope_class_);
- }
- RawClass* scope_class_;
- RawTypeArguments* arguments_;
- RawFunction* signature_;
- RawLanguageError* error_; // Error object if type is malformed or malbounded.
- RawObject** to() {
- return reinterpret_cast<RawObject**>(&ptr()->error_);
+ return reinterpret_cast<RawObject**>(&ptr()->sig_or_err_.error_);
}
TokenPosition token_pos_;
int8_t type_state_;
@@ -2059,8 +2064,8 @@
// VM type for capturing JS regular expressions.
-class RawJSRegExp : public RawInstance {
- RAW_HEAP_OBJECT_IMPLEMENTATION(JSRegExp);
+class RawRegExp : public RawInstance {
+ RAW_HEAP_OBJECT_IMPLEMENTATION(RegExp);
RawObject** from() {
return reinterpret_cast<RawObject**>(&ptr()->num_bracket_expressions_);
@@ -2337,7 +2342,7 @@
(index == kCodeCid) ||
(index == kContextScopeCid) ||
(index == kInstanceCid) ||
- (index == kJSRegExpCid);
+ (index == kRegExpCid);
}
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index d02909c..194317f 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -281,83 +281,6 @@
}
-RawFunctionType* FunctionType::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Determine if the scope class of this function type is in the full snapshot.
- bool scopeclass_is_in_fullsnapshot = reader->Read<bool>();
-
- // Allocate function type object.
- FunctionType& function_type =
- FunctionType::ZoneHandle(reader->zone(), NEW_OBJECT(FunctionType));
- bool is_canonical = RawObject::IsCanonical(tags);
- bool defer_canonicalization = is_canonical &&
- (kind != Snapshot::kFull && scopeclass_is_in_fullsnapshot);
- reader->AddBackRef(object_id,
- &function_type,
- kIsDeserialized,
- defer_canonicalization);
-
- // Set all non object fields.
- function_type.set_token_pos(
- TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
- function_type.set_type_state(reader->Read<int8_t>());
-
- // Set all the object fields.
- READ_OBJECT_FIELDS(function_type,
- function_type.raw()->from(), function_type.raw()->to(),
- kAsReference);
-
- // Set the canonical bit.
- if (!defer_canonicalization && is_canonical) {
- function_type.SetCanonical();
- }
-
- return function_type.raw();
-}
-
-
-void RawFunctionType::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Only resolved and finalized function types should be written to a snapshot.
- ASSERT((ptr()->type_state_ == RawFunctionType::kFinalizedInstantiated) ||
- (ptr()->type_state_ == RawFunctionType::kFinalizedUninstantiated));
- ASSERT(ptr()->scope_class_ != Object::null());
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kFunctionTypeCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out scopeclass_is_in_fullsnapshot first as this will
- // help the reader decide on how to canonicalize the type object.
- intptr_t tags = writer->GetObjectTags(ptr()->scope_class_);
- bool scopeclass_is_in_fullsnapshot =
- (ClassIdTag::decode(tags) == kClassCid) &&
- Class::IsInFullSnapshot(reinterpret_cast<RawClass*>(ptr()->scope_class_));
- writer->Write<bool>(scopeclass_is_in_fullsnapshot);
-
- // Write out all the non object pointer fields.
- writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
- writer->Write<int8_t>(ptr()->type_state_);
-
- // Write out all the object pointer fields.
- ASSERT(ptr()->scope_class_ != Object::null());
- SnapshotWriterVisitor visitor(writer, kAsReference);
- visitor.VisitPointers(from(), to());
-}
-
-
RawTypeRef* TypeRef::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
@@ -3590,15 +3513,15 @@
}
-RawJSRegExp* JSRegExp::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
+RawRegExp* RegExp::ReadFrom(SnapshotReader* reader,
+ intptr_t object_id,
+ intptr_t tags,
+ Snapshot::Kind kind,
+ bool as_reference) {
ASSERT(reader != NULL);
- // Allocate JSRegExp object.
- JSRegExp& regex = JSRegExp::ZoneHandle(reader->zone(), NEW_OBJECT(JSRegExp));
+ // Allocate RegExp object.
+ RegExp& regex = RegExp::ZoneHandle(reader->zone(), NEW_OBJECT(RegExp));
reader->AddBackRef(object_id, ®ex, kIsDeserialized);
// Read and Set all the other fields.
@@ -3626,17 +3549,17 @@
}
-void RawJSRegExp::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
+void RawRegExp::WriteTo(SnapshotWriter* writer,
+ intptr_t object_id,
+ Snapshot::Kind kind,
+ bool as_reference) {
ASSERT(writer != NULL);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
// Write out the class and tags information.
- writer->WriteIndexedObject(kJSRegExpCid);
+ writer->WriteIndexedObject(kRegExpCid);
writer->WriteTags(writer->GetObjectTags(this));
// Write out all the other fields.
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index e49c3d8..62fab5a 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -5018,7 +5018,7 @@
const intptr_t specialization_cid = function.string_specialization_cid();
const bool is_one_byte = (specialization_cid == kOneByteStringCid ||
specialization_cid == kExternalOneByteStringCid);
- JSRegExp& regexp = JSRegExp::Handle(zone, function.regexp());
+ RegExp& regexp = RegExp::Handle(zone, function.regexp());
const String& pattern = String::Handle(zone, regexp.pattern());
ASSERT(!regexp.IsNull());
@@ -5132,7 +5132,7 @@
RegExpEngine::CompilationResult RegExpEngine::CompileBytecode(
RegExpCompileData* data,
- const JSRegExp& regexp,
+ const RegExp& regexp,
bool is_one_byte,
Zone* zone) {
ASSERT(FLAG_interpret_irregexp);
@@ -5245,7 +5245,7 @@
static void CreateSpecializedFunction(Zone* zone,
- const JSRegExp& regexp,
+ const RegExp& regexp,
intptr_t specialization_cid,
const Object& owner) {
const intptr_t kParamCount = RegExpMacroAssembler::kParamCount;
@@ -5255,7 +5255,7 @@
String::Handle(zone, Symbols::New(
String::Handle(zone, String::Concat(
String::Handle(zone, String::Concat(
- Symbols::Irregexp(),
+ Symbols::ColonMatcher(),
Symbols::ColonSpace(), Heap::kOld)),
String::Handle(regexp.pattern()), Heap::kOld)))),
RawFunction::kIrregexpFunction,
@@ -5297,11 +5297,11 @@
}
-RawJSRegExp* RegExpEngine::CreateJSRegExp(Zone* zone,
+RawRegExp* RegExpEngine::CreateRegExp(Zone* zone,
const String& pattern,
bool multi_line,
bool ignore_case) {
- const JSRegExp& regexp = JSRegExp::Handle(JSRegExp::New());
+ const RegExp& regexp = RegExp::Handle(RegExp::New());
regexp.set_pattern(pattern);
@@ -5317,14 +5317,16 @@
regexp.set_is_complex();
regexp.set_is_global(); // All dart regexps are global.
- const Library& lib = Library::Handle(zone, Library::CoreLibrary());
- const Class& owner = Class::Handle(
- zone, lib.LookupClass(Symbols::RegExp()));
+ if (!FLAG_interpret_irregexp) {
+ const Library& lib = Library::Handle(zone, Library::CoreLibrary());
+ const Class& owner = Class::Handle(
+ zone, lib.LookupClass(Symbols::RegExp()));
- CreateSpecializedFunction(zone, regexp, kOneByteStringCid, owner);
- CreateSpecializedFunction(zone, regexp, kTwoByteStringCid, owner);
- CreateSpecializedFunction(zone, regexp, kExternalOneByteStringCid, owner);
- CreateSpecializedFunction(zone, regexp, kExternalTwoByteStringCid, owner);
+ CreateSpecializedFunction(zone, regexp, kOneByteStringCid, owner);
+ CreateSpecializedFunction(zone, regexp, kTwoByteStringCid, owner);
+ CreateSpecializedFunction(zone, regexp, kExternalOneByteStringCid, owner);
+ CreateSpecializedFunction(zone, regexp, kExternalTwoByteStringCid, owner);
+ }
return regexp.raw();
}
diff --git a/runtime/vm/regexp.h b/runtime/vm/regexp.h
index 394279d..49aef37 100644
--- a/runtime/vm/regexp.h
+++ b/runtime/vm/regexp.h
@@ -1420,11 +1420,11 @@
static CompilationResult CompileBytecode(
RegExpCompileData* data,
- const JSRegExp& regexp,
+ const RegExp& regexp,
bool is_one_byte,
Zone* zone);
- static RawJSRegExp* CreateJSRegExp(
+ static RawRegExp* CreateRegExp(
Zone* zone,
const String& pattern,
bool multi_line,
diff --git a/runtime/vm/regexp_assembler_bytecode.cc b/runtime/vm/regexp_assembler_bytecode.cc
index 193616c..9586aea 100644
--- a/runtime/vm/regexp_assembler_bytecode.cc
+++ b/runtime/vm/regexp_assembler_bytecode.cc
@@ -452,7 +452,7 @@
}
-static intptr_t Prepare(const JSRegExp& regexp,
+static intptr_t Prepare(const RegExp& regexp,
const String& subject,
Zone* zone) {
bool is_one_byte = subject.IsOneByteString() ||
@@ -464,7 +464,7 @@
const bool multiline = regexp.is_multi_line();
RegExpCompileData* compile_data = new(zone) RegExpCompileData();
if (!RegExpParser::ParseRegExp(pattern, multiline, compile_data)) {
- // Parsing failures are handled in the JSRegExp factory constructor.
+ // Parsing failures are handled in the RegExp factory constructor.
UNREACHABLE();
}
@@ -491,7 +491,7 @@
}
-static IrregexpInterpreter::IrregexpResult ExecRaw(const JSRegExp& regexp,
+static IrregexpInterpreter::IrregexpResult ExecRaw(const RegExp& regexp,
const String& subject,
intptr_t index,
int32_t* output,
@@ -537,7 +537,7 @@
}
-RawInstance* BytecodeRegExpMacroAssembler::Interpret(const JSRegExp& regexp,
+RawInstance* BytecodeRegExpMacroAssembler::Interpret(const RegExp& regexp,
const String& subject,
const Smi& start_index,
Zone* zone) {
diff --git a/runtime/vm/regexp_assembler_bytecode.h b/runtime/vm/regexp_assembler_bytecode.h
index 2de00d0..da2a6d7 100644
--- a/runtime/vm/regexp_assembler_bytecode.h
+++ b/runtime/vm/regexp_assembler_bytecode.h
@@ -105,7 +105,7 @@
virtual void PrintBlocks() { UNIMPLEMENTED(); }
/////
- static RawInstance* Interpret(const JSRegExp& regexp,
+ static RawInstance* Interpret(const RegExp& regexp,
const String& str,
const Smi& start_index,
Zone* zone);
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index bd04d7f..6f656db 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -311,7 +311,7 @@
RawArray* IRRegExpMacroAssembler::Execute(
- const JSRegExp& regexp,
+ const RegExp& regexp,
const String& input,
const Smi& start_offset,
Zone* zone) {
@@ -429,7 +429,7 @@
ConstantInstr* IRRegExpMacroAssembler::WordCharacterMapConstant() const {
const Library& lib = Library::Handle(Z, Library::CoreLibrary());
const Class& regexp_class = Class::Handle(Z,
- lib.LookupClassAllowPrivate(Symbols::JSSyntaxRegExp()));
+ lib.LookupClassAllowPrivate(Symbols::_RegExp()));
const Field& word_character_field = Field::ZoneHandle(Z,
regexp_class.LookupStaticField(Symbols::_wordCharacterMap()));
ASSERT(!word_character_field.IsNull());
diff --git a/runtime/vm/regexp_assembler_ir.h b/runtime/vm/regexp_assembler_ir.h
index eeb9f26..f898346 100644
--- a/runtime/vm/regexp_assembler_ir.h
+++ b/runtime/vm/regexp_assembler_ir.h
@@ -37,7 +37,7 @@
virtual bool CanReadUnaligned();
- static RawArray* Execute(const JSRegExp& regexp,
+ static RawArray* Execute(const RegExp& regexp,
const String& input,
const Smi& start_offset,
Zone* zone);
diff --git a/runtime/vm/regexp_parser.cc b/runtime/vm/regexp_parser.cc
index 7b0e01a..c4d471a 100644
--- a/runtime/vm/regexp_parser.cc
+++ b/runtime/vm/regexp_parser.cc
@@ -220,14 +220,14 @@
VMTagScope tagScope(parsed_function->thread(),
VMTag::kCompileParseRegExpTagId);
Zone* zone = parsed_function->zone();
- JSRegExp& regexp = JSRegExp::Handle(parsed_function->function().regexp());
+ RegExp& regexp = RegExp::Handle(parsed_function->function().regexp());
const String& pattern = String::Handle(regexp.pattern());
const bool multiline = regexp.is_multi_line();
RegExpCompileData* compile_data = new(zone) RegExpCompileData();
if (!RegExpParser::ParseRegExp(pattern, multiline, compile_data)) {
- // Parsing failures are handled in the JSRegExp factory constructor.
+ // Parsing failures are handled in the RegExp factory constructor.
UNREACHABLE();
}
diff --git a/runtime/vm/regexp_test.cc b/runtime/vm/regexp_test.cc
index d75dac4..e7c5ba8 100644
--- a/runtime/vm/regexp_test.cc
+++ b/runtime/vm/regexp_test.cc
@@ -14,8 +14,8 @@
static RawArray* Match(const String& pat, const String& str) {
Zone* zone = Thread::Current()->zone();
- const JSRegExp& regexp = JSRegExp::Handle(
- RegExpEngine::CreateJSRegExp(zone, pat, false, false));
+ const RegExp& regexp = RegExp::Handle(
+ RegExpEngine::CreateRegExp(zone, pat, false, false));
const Smi& idx = Smi::Handle(Smi::New(0));
return IRRegExpMacroAssembler::Execute(regexp, str, idx, zone);
}
diff --git a/runtime/vm/safepoint.cc b/runtime/vm/safepoint.cc
index 47ef257..fcf2872 100644
--- a/runtime/vm/safepoint.cc
+++ b/runtime/vm/safepoint.cc
@@ -82,7 +82,7 @@
// get it to a safepoint and wait for it to check in.
if (current->IsMutatorThread()) {
ASSERT(T->isolate() != NULL);
- T->isolate()->ScheduleInterrupts(Isolate::kVMInterrupt);
+ current->ScheduleInterruptsLocked(Thread::kVMInterrupt);
}
MonitorLocker sl(safepoint_lock_);
++number_threads_not_at_safepoint_;
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index fb7a5db..d346361 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -35,6 +35,7 @@
#include "vm/source_report.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
+#include "vm/timeline.h"
#include "vm/unicode.h"
#include "vm/version.h"
@@ -2870,9 +2871,8 @@
"all",
#define DEFINE_NAME(name, unused) \
#name,
-ISOLATE_TIMELINE_STREAM_LIST(DEFINE_NAME)
+TIMELINE_STREAM_LIST(DEFINE_NAME)
#undef DEFINE_NAME
- "VM",
NULL
};
@@ -2915,9 +2915,8 @@
#define SET_ENABLE_STREAM(name, unused) \
Timeline::SetStream##name##Enabled(HasStream(recorded_streams, #name));
-ISOLATE_TIMELINE_STREAM_LIST(SET_ENABLE_STREAM);
+TIMELINE_STREAM_LIST(SET_ENABLE_STREAM);
#undef SET_ENABLE_STREAM
- Timeline::SetVMStreamEnabled(HasStream(recorded_streams, "VM"));
PrintSuccess(js);
@@ -3270,13 +3269,16 @@
static const MethodParameter* request_heap_snapshot_params[] = {
RUNNABLE_ISOLATE_PARAMETER,
+ new BoolParameter("collectGarbage", false /* not required */),
NULL,
};
static bool RequestHeapSnapshot(Thread* thread, JSONStream* js) {
+ const bool collect_garbage =
+ BoolParameter::Parse(js->LookupParam("collectGarbage"), true);
if (Service::graph_stream.enabled()) {
- Service::SendGraphEvent(thread);
+ Service::SendGraphEvent(thread, collect_garbage);
}
// TODO(koda): Provide some id that ties this request to async response(s).
JSONObject jsobj(js);
@@ -3285,11 +3287,11 @@
}
-void Service::SendGraphEvent(Thread* thread) {
+void Service::SendGraphEvent(Thread* thread, bool collect_garbage) {
uint8_t* buffer = NULL;
WriteStream stream(&buffer, &allocator, 1 * MB);
ObjectGraph graph(thread);
- intptr_t node_count = graph.Serialize(&stream);
+ intptr_t node_count = graph.Serialize(&stream, collect_garbage);
// Chrome crashes receiving a single tens-of-megabytes blob, so send the
// snapshot in megabyte-sized chunks instead.
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index b7917ec..f38f7f83 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -105,7 +105,7 @@
Dart_GetVMServiceAssetsArchive get_service_assets);
static void SendEchoEvent(Isolate* isolate, const char* text);
- static void SendGraphEvent(Thread* thread);
+ static void SendGraphEvent(Thread* thread, bool collect_garbage);
static void SendInspectEvent(Isolate* isolate, const Object& inspectee);
static void SendEmbedderEvent(Isolate* isolate,
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 7e6c7f0..68d134f 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -971,11 +971,21 @@
// The superclass of this class, if any.
@Class super [optional];
- // A list of interface types for this class.
+ // The supertype for this class, if any.
//
// The value will be of the kind: Type.
+ @Instance superType [optional];
+
+ // A list of interface types for this class.
+ //
+ // The values will be of the kind: Type.
@Instance[] interfaces;
+ // The mixin type for this class, if any.
+ //
+ // The value will be of the kind: Type.
+ @Instance mixin [optional];
+
// A list of fields in this class. Does not include fields from
// superclasses.
@Field[] fields;
@@ -2508,5 +2518,5 @@
3.1 | Add the getSourceReport RPC. The getObject RPC now accepts offset and count for string objects. String objects now contain length, offset, and count properties.
3.2 | Isolate objects now include the runnable bit and many debugger related RPCs will return an error if executed on an isolate before it is runnable.
3.3 | Pause event now indicates if the isolate is paused at an await, yield, or yield* suspension point via the 'atAsyncSuspension' field. Resume command now supports the step parameter 'OverAsyncSuspension'. A Breakpoint added synthetically by an 'OverAsyncSuspension' resume command identifies itself as such via the 'isSyntheticAsyncContinuation' field.
-
+3.4 | Add the superType and mixin fields to Class.
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index 502a38b..d34f439 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -51,8 +51,13 @@
bytes_(NULL),
bytes_length_(0),
timestamp_(OS::GetCurrentTimeMillis()) {
- if ((event_kind == ServiceEvent::kPauseStart) ||
- (event_kind == ServiceEvent::kPauseExit)) {
+ if ((event_kind == ServiceEvent::kPauseStart) &&
+ !isolate->message_handler()->is_paused_on_start()) {
+ // We will pause on start but the message handler lacks a valid
+ // paused timestamp because we haven't paused yet. Use the current time.
+ timestamp_ = OS::GetCurrentTimeMillis();
+ } else if ((event_kind == ServiceEvent::kPauseStart) ||
+ (event_kind == ServiceEvent::kPauseExit)) {
timestamp_ = isolate->message_handler()->paused_timestamp();
} else if (event_kind == ServiceEvent::kResume) {
timestamp_ = isolate->last_resume_timestamp();
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index 86c8aab..a75c2fd 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -19,6 +19,7 @@
#include "vm/service.h"
#include "vm/symbols.h"
#include "vm/thread_pool.h"
+#include "vm/timeline.h"
namespace dart {
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index e5d06c8..1fcb66b 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -1137,7 +1137,7 @@
void Simulator::ClearExclusive() {
MutexLocker ml(exclusive_access_lock_);
// Remove the reservation for this thread.
- SetExclusiveAccess(NULL);
+ SetExclusiveAccess(0);
}
@@ -1539,7 +1539,7 @@
(redirection->call_kind() == kBootstrapNativeCall) ||
(redirection->call_kind() == kNativeCall)) {
// Set the top_exit_frame_info of this simulator to the native stack.
- set_top_exit_frame_info(Isolate::GetCurrentStackPointer());
+ set_top_exit_frame_info(Thread::GetCurrentStackPointer());
}
if (redirection->call_kind() == kRuntimeCall) {
NativeArguments arguments;
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index a19311d..cef6aa2 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -1611,7 +1611,7 @@
(redirection->call_kind() == kBootstrapNativeCall) ||
(redirection->call_kind() == kNativeCall)) {
// Set the top_exit_frame_info of this simulator to the native stack.
- set_top_exit_frame_info(Isolate::GetCurrentStackPointer());
+ set_top_exit_frame_info(Thread::GetCurrentStackPointer());
}
if (redirection->call_kind() == kRuntimeCall) {
NativeArguments* arguments =
diff --git a/runtime/vm/simulator_mips.cc b/runtime/vm/simulator_mips.cc
index a828752..244b331 100644
--- a/runtime/vm/simulator_mips.cc
+++ b/runtime/vm/simulator_mips.cc
@@ -1250,7 +1250,7 @@
(redirection->call_kind() == kBootstrapNativeCall) ||
(redirection->call_kind() == kNativeCall)) {
// Set the top_exit_frame_info of this simulator to the native stack.
- set_top_exit_frame_info(Isolate::GetCurrentStackPointer());
+ set_top_exit_frame_info(Thread::GetCurrentStackPointer());
}
if (redirection->call_kind() == kRuntimeCall) {
NativeArguments arguments;
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 294a90b..ea0dce3 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -627,6 +627,27 @@
}
}
+ if (snapshot_code()) {
+ ICData& ic = ICData::Handle(thread->zone());
+ Object& funcOrCode = Object::Handle(thread->zone());
+ Code& code = Code::Handle(thread->zone());
+ Smi& entry_point = Smi::Handle(thread->zone());
+ for (intptr_t i = 0; i < backward_references_->length(); i++) {
+ if ((*backward_references_)[i].reference()->IsICData()) {
+ ic ^= (*backward_references_)[i].reference()->raw();
+ for (intptr_t j = 0; j < ic.NumberOfChecks(); j++) {
+ funcOrCode = ic.GetTargetOrCodeAt(j);
+ if (funcOrCode.IsCode()) {
+ code ^= funcOrCode.raw();
+ entry_point = Smi::FromAlignedAddress(code.EntryPoint());
+ ic.SetEntryPointAt(j, entry_point);
+ }
+ }
+ }
+ }
+ }
+
+
// Validate the class table.
#if defined(DEBUG)
isolate->ValidateClassTable();
@@ -939,11 +960,6 @@
}
-RawFunctionType* SnapshotReader::NewFunctionType() {
- ALLOC_NEW_OBJECT(FunctionType);
-}
-
-
RawTypeRef* SnapshotReader::NewTypeRef() {
ALLOC_NEW_OBJECT(TypeRef);
}
@@ -1049,8 +1065,8 @@
}
-RawJSRegExp* SnapshotReader::NewJSRegExp() {
- ALLOC_NEW_OBJECT(JSRegExp);
+RawRegExp* SnapshotReader::NewRegExp() {
+ ALLOC_NEW_OBJECT(RegExp);
}
@@ -1157,19 +1173,19 @@
void InstructionsWriter::WriteAssembly() {
- Zone* Z = Thread::Current()->zone();
+ Zone* zone = Thread::Current()->zone();
// Handlify collected raw pointers as building the names below
// will allocate on the Dart heap.
for (intptr_t i = 0; i < instructions_.length(); i++) {
InstructionsData& data = instructions_[i];
- data.insns_ = &Instructions::Handle(Z, data.raw_insns_);
+ data.insns_ = &Instructions::Handle(zone, data.raw_insns_);
ASSERT(data.raw_code_ != NULL);
- data.code_ = &Code::Handle(Z, data.raw_code_);
+ data.code_ = &Code::Handle(zone, data.raw_code_);
}
for (intptr_t i = 0; i < objects_.length(); i++) {
ObjectData& data = objects_[i];
- data.obj_ = &Object::Handle(Z, data.raw_obj_);
+ data.obj_ = &Object::Handle(zone, data.raw_obj_);
}
stream_.Print(".text\n");
@@ -1188,8 +1204,8 @@
WriteWordLiteral(0);
}
- Object& owner = Object::Handle(Z);
- String& str = String::Handle(Z);
+ Object& owner = Object::Handle(zone);
+ String& str = String::Handle(zone);
for (intptr_t i = 0; i < instructions_.length(); i++) {
const Instructions& insns = *instructions_[i].insns_;
@@ -1483,20 +1499,16 @@
void SnapshotReader::ProcessDeferredCanonicalizations() {
Type& typeobj = Type::Handle();
- FunctionType& funtypeobj = FunctionType::Handle();
TypeArguments& typeargs = TypeArguments::Handle();
Object& newobj = Object::Handle();
for (intptr_t i = 0; i < backward_references_->length(); i++) {
BackRefNode& backref = (*backward_references_)[i];
if (backref.defer_canonicalization()) {
Object* objref = backref.reference();
- // Object should either be a type, a function type, or a type argument.
+ // Object should either be a type or a type argument.
if (objref->IsType()) {
typeobj ^= objref->raw();
newobj = typeobj.Canonicalize();
- } else if (objref->IsFunctionType()) {
- funtypeobj ^= objref->raw();
- newobj = funtypeobj.Canonicalize();
} else {
ASSERT(objref->IsTypeArguments());
typeargs ^= objref->raw();
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 978dbd1..7f6436b 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -52,13 +52,12 @@
class RawFloat32x4;
class RawFloat64x2;
class RawFunction;
-class RawFunctionType;
class RawGrowableObjectArray;
class RawICData;
class RawImmutableArray;
class RawInstructions;
class RawInt32x4;
-class RawJSRegExp;
+class RawRegExp;
class RawLanguageError;
class RawLibrary;
class RawLibraryPrefix;
@@ -445,7 +444,6 @@
RawDouble* NewDouble(double value);
RawUnresolvedClass* NewUnresolvedClass();
RawType* NewType();
- RawFunctionType* NewFunctionType();
RawTypeRef* NewTypeRef();
RawTypeParameter* NewTypeParameter();
RawBoundedType* NewBoundedType();
@@ -483,7 +481,7 @@
RawObject* NewInteger(int64_t value);
RawStacktrace* NewStacktrace();
RawWeakProperty* NewWeakProperty();
- RawJSRegExp* NewJSRegExp();
+ RawRegExp* NewRegExp();
RawInstructions* GetInstructionsAt(int32_t offset, uword expected_tags) {
return instructions_reader_->GetInstructionsAt(offset, expected_tags);
@@ -612,7 +610,7 @@
friend class ICData;
friend class ImmutableArray;
friend class Instructions;
- friend class JSRegExp;
+ friend class RegExp;
friend class LanguageError;
friend class Library;
friend class LibraryPrefix;
@@ -631,7 +629,6 @@
friend class SubtypeTestCache;
friend class TokenStream;
friend class Type;
- friend class FunctionType;
friend class TypeArguments;
friend class TypeParameter;
friend class TypeRef;
@@ -1058,7 +1055,7 @@
friend class RawGrowableObjectArray;
friend class RawImmutableArray;
friend class RawInstructions;
- friend class RawJSRegExp;
+ friend class RawRegExp;
friend class RawLibrary;
friend class RawLinkedHashMap;
friend class RawLiteralToken;
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 494ac53..1d3e818 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -43,7 +43,9 @@
next_script_index_ = 0;
if (IsReportRequested(kProfile)) {
// Build the profile.
- SampleFilter samplesForIsolate(thread_->isolate(), -1, -1);
+ SampleFilter samplesForIsolate(thread_->isolate(),
+ Thread::kMutatorTask,
+ -1, -1);
profile_.Build(thread, &samplesForIsolate, Profile::kNoTags);
}
}
diff --git a/runtime/vm/store_buffer.cc b/runtime/vm/store_buffer.cc
index cc0a816..b257c0a 100644
--- a/runtime/vm/store_buffer.cc
+++ b/runtime/vm/store_buffer.cc
@@ -100,12 +100,13 @@
BlockStack<Block::kSize>::PushBlockImpl(block);
if ((policy == kCheckThreshold) && Overflowed()) {
MutexLocker ml(mutex_);
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
// Sanity check: it makes no sense to schedule the GC in another isolate.
// (If Isolate ever gets multiple store buffers, we should avoid this
// coupling by passing in an explicit callback+parameter at construction.)
- ASSERT(isolate->store_buffer() == this);
- isolate->ScheduleInterrupts(Isolate::kVMInterrupt);
+ ASSERT(thread->isolate()->mutator_thread() == thread);
+ ASSERT(thread->isolate()->store_buffer() == this);
+ thread->ScheduleInterrupts(Thread::kVMInterrupt);
}
}
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index f451638..d90a3ab 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -35,7 +35,8 @@
V(OptimizeFunction) \
V(InvokeDartCode) \
V(DebugStepCheck) \
- V(ICLookup) \
+ V(ICLookupThroughFunction) \
+ V(ICLookupThroughCode) \
V(MegamorphicLookup) \
V(FixAllocationStubTarget) \
V(Deoptimize) \
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 6b8812e..9a31d42 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -2110,7 +2110,7 @@
// R1: target entry point
// CODE_REG: target Code object
// R4: arguments descriptor
-void StubCode::GenerateICLookupStub(Assembler* assembler) {
+void StubCode::GenerateICLookupThroughFunctionStub(Assembler* assembler) {
Label loop, found, miss;
__ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset()));
__ ldr(R8, FieldAddress(R9, ICData::ic_data_offset()));
@@ -2144,6 +2144,41 @@
__ Ret();
}
+
+void StubCode::GenerateICLookupThroughCodeStub(Assembler* assembler) {
+ Label loop, found, miss;
+ __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset()));
+ __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset()));
+ __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag);
+ // R8: first IC entry
+ __ LoadTaggedClassIdMayBeSmi(R1, R0);
+ // R1: receiver cid as Smi
+
+ __ Bind(&loop);
+ __ ldr(R2, Address(R8, 0));
+ __ cmp(R1, Operand(R2));
+ __ b(&found, EQ);
+ __ CompareImmediate(R2, Smi::RawValue(kIllegalCid));
+ __ b(&miss, EQ);
+
+ const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize;
+ __ AddImmediate(R8, entry_length); // Next entry.
+ __ b(&loop);
+
+ __ Bind(&found);
+ const intptr_t code_offset = ICData::CodeIndexFor(1) * kWordSize;
+ const intptr_t entry_offset = ICData::EntryPointIndexFor(1) * kWordSize;
+ __ ldr(R1, Address(R8, entry_offset));
+ __ ldr(CODE_REG, Address(R8, code_offset));
+ __ Ret();
+
+ __ Bind(&miss);
+ __ LoadIsolate(R2);
+ __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset()));
+ __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset()));
+ __ Ret();
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_ARM
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 61c3a4b..22ee31f 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -2163,7 +2163,7 @@
// R1: target entry point
// CODE_REG: target Code object
// R4: arguments descriptor
-void StubCode::GenerateICLookupStub(Assembler* assembler) {
+void StubCode::GenerateICLookupThroughFunctionStub(Assembler* assembler) {
Label loop, found, miss;
__ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset()));
__ ldr(R8, FieldAddress(R5, ICData::ic_data_offset()));
@@ -2197,6 +2197,41 @@
__ ret();
}
+
+void StubCode::GenerateICLookupThroughCodeStub(Assembler* assembler) {
+ Label loop, found, miss;
+ __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset()));
+ __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset()));
+ __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag);
+ // R8: first IC entry
+ __ LoadTaggedClassIdMayBeSmi(R1, R0);
+ // R1: receiver cid as Smi
+
+ __ Bind(&loop);
+ __ ldr(R2, Address(R8, 0));
+ __ cmp(R1, Operand(R2));
+ __ b(&found, EQ);
+ __ CompareImmediate(R2, Smi::RawValue(kIllegalCid));
+ __ b(&miss, EQ);
+
+ const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize;
+ __ AddImmediate(R8, R8, entry_length); // Next entry.
+ __ b(&loop);
+
+ __ Bind(&found);
+ const intptr_t code_offset = ICData::CodeIndexFor(1) * kWordSize;
+ const intptr_t entry_offset = ICData::EntryPointIndexFor(1) * kWordSize;
+ __ ldr(R1, Address(R8, entry_offset));
+ __ ldr(CODE_REG, Address(R8, code_offset));
+ __ ret();
+
+ __ Bind(&miss);
+ __ LoadIsolate(R2);
+ __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset()));
+ __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset()));
+ __ ret();
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_ARM64
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index 640f0ec..57820c8 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -2084,7 +2084,12 @@
// Result:
// EBX: target entry point
// EDX: arguments descriptor
-void StubCode::GenerateICLookupStub(Assembler* assembler) {
+void StubCode::GenerateICLookupThroughFunctionStub(Assembler* assembler) {
+ __ int3();
+}
+
+
+void StubCode::GenerateICLookupThroughCodeStub(Assembler* assembler) {
__ int3();
}
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index b4965c33..1a13f74 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -2278,7 +2278,7 @@
// T1: target entry point
// CODE_REG: target Code object
// S4: arguments descriptor
-void StubCode::GenerateICLookupStub(Assembler* assembler) {
+void StubCode::GenerateICLookupThroughFunctionStub(Assembler* assembler) {
Label loop, found, miss;
__ lw(T6, FieldAddress(S5, ICData::ic_data_offset()));
__ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset()));
@@ -2311,6 +2311,40 @@
__ Ret();
}
+
+void StubCode::GenerateICLookupThroughCodeStub(Assembler* assembler) {
+ Label loop, found, miss;
+ __ lw(T6, FieldAddress(S5, ICData::ic_data_offset()));
+ __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset()));
+ __ AddImmediate(T6, T6, Array::data_offset() - kHeapObjectTag);
+ // T6: first IC entry.
+ __ LoadTaggedClassIdMayBeSmi(T1, T0);
+ // T1: receiver cid as Smi
+
+ __ Bind(&loop);
+ __ lw(T2, Address(T6, 0));
+ __ beq(T1, T2, &found);
+ ASSERT(Smi::RawValue(kIllegalCid) == 0);
+ __ beq(T2, ZR, &miss);
+
+ const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize;
+ __ AddImmediate(T6, entry_length); // Next entry.
+ __ b(&loop);
+
+ __ Bind(&found);
+ const intptr_t code_offset = ICData::CodeIndexFor(1) * kWordSize;
+ const intptr_t entry_offset = ICData::EntryPointIndexFor(1) * kWordSize;
+ __ lw(T1, Address(T6, entry_offset));
+ __ lw(CODE_REG, Address(T6, code_offset));
+ __ Ret();
+
+ __ Bind(&miss);
+ __ LoadIsolate(T2);
+ __ lw(CODE_REG, Address(T2, Isolate::ic_miss_code_offset()));
+ __ lw(T1, FieldAddress(CODE_REG, Code::entry_point_offset()));
+ __ Ret();
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_MIPS
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index b33ee01..a8ed6ef 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -2144,7 +2144,7 @@
// RCX: target entry point
// CODE_REG: target Code object
// R10: arguments descriptor
-void StubCode::GenerateICLookupStub(Assembler* assembler) {
+void StubCode::GenerateICLookupThroughFunctionStub(Assembler* assembler) {
Label loop, found, miss;
__ movq(R13, FieldAddress(RBX, ICData::ic_data_offset()));
@@ -2181,6 +2181,44 @@
__ ret();
}
+
+void StubCode::GenerateICLookupThroughCodeStub(Assembler* assembler) {
+ Label loop, found, miss;
+
+ __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset()));
+ __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
+ __ leaq(R13, FieldAddress(R13, Array::data_offset()));
+ // R13: first IC entry
+ __ LoadTaggedClassIdMayBeSmi(RAX, RDI);
+ // RAX: receiver cid as Smi
+
+ __ Bind(&loop);
+ __ movq(R9, Address(R13, 0));
+ __ cmpq(RAX, R9);
+ __ j(EQUAL, &found, Assembler::kNearJump);
+
+ ASSERT(Smi::RawValue(kIllegalCid) == 0);
+ __ testq(R9, R9);
+ __ j(ZERO, &miss, Assembler::kNearJump);
+
+ const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize;
+ __ addq(R13, Immediate(entry_length)); // Next entry.
+ __ jmp(&loop);
+
+ __ Bind(&found);
+ const intptr_t code_offset = ICData::CodeIndexFor(1) * kWordSize;
+ const intptr_t entry_offset = ICData::EntryPointIndexFor(1) * kWordSize;
+ __ movq(RCX, Address(R13, entry_offset));
+ __ movq(CODE_REG, Address(R13, code_offset));
+ __ ret();
+
+ __ Bind(&miss);
+ __ LoadIsolate(RAX);
+ __ movq(CODE_REG, Address(RAX, Isolate::ic_miss_code_offset()));
+ __ movq(RCX, FieldAddress(CODE_REG, Code::entry_point_offset()));
+ __ ret();
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_X64
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 5b31bef75..d5f3498 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -137,7 +137,6 @@
V(Dynamic, "dynamic") \
V(UnresolvedClass, "UnresolvedClass") \
V(Type, "_Type") \
- V(FunctionType, "_FunctionType") \
V(TypeRef, "_TypeRef") \
V(TypeParameter, "_TypeParameter") \
V(BoundedType, "_BoundedType") \
@@ -200,15 +199,12 @@
V(_RawReceivePortImpl, "_RawReceivePortImpl") \
V(_SendPortImpl, "_SendPortImpl") \
V(_StackTrace, "_StackTrace") \
- V(JSSyntaxRegExp, "_JSSyntaxRegExp") \
+ V(_RegExp, "_RegExp") \
V(RegExp, "RegExp") \
- V(Irregexp, ":irregexp") \
+ V(ColonMatcher, ":matcher") \
V(Object, "Object") \
V(Int, "int") \
V(Double, "double") \
- V(_Float32x4, "_Float32x4") \
- V(_Float64x2, "_Float64x2") \
- V(_Int32x4, "_Int32x4") \
V(Float32x4, "Float32x4") \
V(Float64x2, "Float64x2") \
V(Int32x4, "Int32x4") \
@@ -226,34 +222,20 @@
V(Float64x2List, "Float64x2List") \
V(Float32List, "Float32List") \
V(Float64List, "Float64List") \
- V(_Int8Array, "_Int8Array") \
- V(_Int8ArrayFactory, "_Int8Array.") \
- V(_Uint8Array, "_Uint8Array") \
- V(_Uint8ArrayFactory, "_Uint8Array.") \
- V(_Uint8ClampedArray, "_Uint8ClampedArray") \
- V(_Uint8ClampedArrayFactory, "_Uint8ClampedArray.") \
- V(_Int16Array, "_Int16Array") \
- V(_Int16ArrayFactory, "_Int16Array.") \
- V(_Uint16Array, "_Uint16Array") \
- V(_Uint16ArrayFactory, "_Uint16Array.") \
- V(_Int32Array, "_Int32Array") \
- V(_Int32ArrayFactory, "_Int32Array.") \
- V(_Uint32Array, "_Uint32Array") \
- V(_Uint32ArrayFactory, "_Uint32Array.") \
- V(_Int64Array, "_Int64Array") \
- V(_Int64ArrayFactory, "_Int64Array.") \
- V(_Uint64Array, "_Uint64Array") \
- V(_Uint64ArrayFactory, "_Uint64Array.") \
- V(_Float32x4Array, "_Float32x4Array") \
- V(_Float32x4ArrayFactory, "_Float32x4Array.") \
- V(_Int32x4Array, "_Int32x4Array") \
- V(_Int32x4ArrayFactory, "_Int32x4Array.") \
- V(_Float64x2Array, "_Float64x2Array") \
- V(_Float64x2ArrayFactory, "_Float64x2Array.") \
- V(_Float32Array, "_Float32Array") \
- V(_Float32ArrayFactory, "_Float32Array.") \
- V(_Float64Array, "_Float64Array") \
- V(_Float64ArrayFactory, "_Float64Array.") \
+ V(_Int8ArrayFactory, "Int8List.") \
+ V(_Uint8ArrayFactory, "Uint8List.") \
+ V(_Uint8ClampedArrayFactory, "Uint8ClampedList.") \
+ V(_Int16ArrayFactory, "Int16List.") \
+ V(_Uint16ArrayFactory, "Uint16List.") \
+ V(_Int32ArrayFactory, "Int32List.") \
+ V(_Uint32ArrayFactory, "Uint32List.") \
+ V(_Int64ArrayFactory, "Int64List.") \
+ V(_Uint64ArrayFactory, "Uint64List.") \
+ V(_Float32x4ArrayFactory, "Float32x4List.") \
+ V(_Int32x4ArrayFactory, "Int32x4List.") \
+ V(_Float64x2ArrayFactory, "Float64x2List.") \
+ V(_Float32ArrayFactory, "Float32List.") \
+ V(_Float64ArrayFactory, "Float64List.") \
V(_Int8ArrayView, "_Int8ArrayView") \
V(_Uint8ArrayView, "_Uint8ArrayView") \
V(_Uint8ClampedArrayView, "_Uint8ClampedArrayView") \
@@ -286,8 +268,8 @@
V(ByteDataDot, "ByteData.") \
V(ByteDataDot_view, "ByteData._view") \
V(_ByteDataView, "_ByteDataView") \
- V(_ByteBuffer, "_ByteBuffer") \
- V(_ByteBufferDot_New, "_ByteBuffer._New") \
+ V(ByteBuffer, "ByteBuffer") \
+ V(ByteBufferDot_New, "ByteBuffer._New") \
V(_WeakProperty, "_WeakProperty") \
V(_MirrorReference, "_MirrorReference") \
V(InvocationMirror, "_InvocationMirror") \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index c5c6e70..fd176c2 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -9,6 +9,7 @@
#include "vm/isolate.h"
#include "vm/lockers.h"
#include "vm/log.h"
+#include "vm/message_handler.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/os_thread.h"
@@ -21,6 +22,12 @@
namespace dart {
+
+DECLARE_FLAG(bool, trace_isolates);
+DECLARE_FLAG(bool, trace_service);
+DECLARE_FLAG(bool, trace_service_verbose);
+
+
Thread::~Thread() {
// We should cleanly exit any isolate before destruction.
ASSERT(isolate_ == NULL);
@@ -49,17 +56,21 @@
Thread::Thread(Isolate* isolate)
: BaseThread(false),
- os_thread_(NULL),
- thread_lock_(new Monitor()),
+ stack_limit_(0),
+ stack_overflow_flags_(0),
isolate_(NULL),
heap_(NULL),
+ top_exit_frame_info_(0),
+ store_buffer_block_(NULL),
+ vm_tag_(0),
+ task_kind_(kUnknownTask),
+ os_thread_(NULL),
+ thread_lock_(new Monitor()),
zone_(NULL),
api_reusable_scope_(NULL),
api_top_scope_(NULL),
- top_exit_frame_info_(0),
top_resource_(NULL),
long_jump_base_(NULL),
- store_buffer_block_(NULL),
no_callback_scope_depth_(0),
#if defined(DEBUG)
top_handle_scope_(NULL),
@@ -67,9 +78,12 @@
no_safepoint_scope_depth_(0),
#endif
reusable_handles_(),
+ saved_stack_limit_(0),
+ deferred_interrupts_mask_(0),
+ deferred_interrupts_(0),
+ stack_overflow_count_(0),
cha_(NULL),
deopt_id_(0),
- vm_tag_(0),
pending_functions_(GrowableObjectArray::null()),
sticky_error_(Error::null()),
REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
@@ -211,6 +225,7 @@
Thread* thread = isolate->ScheduleThread(kIsMutatorThread);
if (thread != NULL) {
ASSERT(thread->store_buffer_block_ == NULL);
+ thread->task_kind_ = kMutatorTask;
thread->StoreBufferAcquire();
return true;
}
@@ -222,7 +237,7 @@
Thread* thread = Thread::Current();
ASSERT(thread != NULL && thread->IsMutatorThread());
DEBUG_ASSERT(!thread->IsAnyReusableHandleScopeActive());
-
+ thread->task_kind_ = kUnknownTask;
Isolate* isolate = thread->isolate();
ASSERT(isolate != NULL);
ASSERT(thread->execution_state() == Thread::kThreadInVM);
@@ -239,7 +254,10 @@
}
-bool Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
+bool Thread::EnterIsolateAsHelper(Isolate* isolate,
+ TaskKind kind,
+ bool bypass_safepoint) {
+ ASSERT(kind != kMutatorTask);
const bool kIsNotMutatorThread = false;
Thread* thread = isolate->ScheduleThread(kIsNotMutatorThread,
bypass_safepoint);
@@ -250,6 +268,7 @@
thread->store_buffer_block_ =
thread->isolate()->store_buffer()->PopEmptyBlock();
// This thread should not be the main mutator.
+ thread->task_kind_ = kind;
ASSERT(!thread->IsMutatorThread());
return true;
}
@@ -262,6 +281,9 @@
ASSERT(thread != NULL);
ASSERT(!thread->IsMutatorThread());
ASSERT(thread->execution_state() == Thread::kThreadInVM);
+ thread->task_kind_ = kUnknownTask;
+ // Clear since GC will not visit the thread once it is unscheduled.
+ thread->ClearReusableHandles();
thread->StoreBufferRelease();
Isolate* isolate = thread->isolate();
ASSERT(isolate != NULL);
@@ -282,6 +304,177 @@
}
+void Thread::SetStackLimitFromStackBase(uword stack_base) {
+ // Set stack limit.
+#if defined(USING_SIMULATOR)
+ // Ignore passed-in native stack top and use Simulator stack top.
+ Simulator* sim = Simulator::Current(); // May allocate a simulator.
+ ASSERT(isolate()->simulator() == sim); // Isolate's simulator is current one.
+ stack_base = sim->StackTop();
+ // The overflow area is accounted for by the simulator.
+#endif
+ SetStackLimit(stack_base - OSThread::GetSpecifiedStackSize());
+}
+
+
+void Thread::SetStackLimit(uword limit) {
+ // The thread setting the stack limit is not necessarily the thread which
+ // the stack limit is being set on.
+ MonitorLocker ml(thread_lock_);
+ if (stack_limit_ == saved_stack_limit_) {
+ // No interrupt pending, set stack_limit_ too.
+ stack_limit_ = limit;
+ }
+ saved_stack_limit_ = limit;
+}
+
+
+void Thread::ClearStackLimit() {
+ SetStackLimit(~static_cast<uword>(0));
+}
+
+
+/* static */
+uword Thread::GetCurrentStackPointer() {
+ // Since AddressSanitizer's detect_stack_use_after_return instruments the
+ // C++ code to give out fake stack addresses, we call a stub in that case.
+ ASSERT(StubCode::GetStackPointer_entry() != NULL);
+ uword (*func)() = reinterpret_cast<uword (*)()>(
+ StubCode::GetStackPointer_entry()->EntryPoint());
+ // But for performance (and to support simulators), we normally use a local.
+#if defined(__has_feature)
+#if __has_feature(address_sanitizer)
+ uword current_sp = func();
+ return current_sp;
+#else
+ uword stack_allocated_local_address = reinterpret_cast<uword>(&func);
+ return stack_allocated_local_address;
+#endif
+#else
+ uword stack_allocated_local_address = reinterpret_cast<uword>(&func);
+ return stack_allocated_local_address;
+#endif
+}
+
+
+void Thread::ScheduleInterrupts(uword interrupt_bits) {
+ MonitorLocker ml(thread_lock_);
+ ScheduleInterruptsLocked(interrupt_bits);
+}
+
+
+void Thread::ScheduleInterruptsLocked(uword interrupt_bits) {
+ ASSERT(thread_lock_->IsOwnedByCurrentThread());
+ ASSERT((interrupt_bits & ~kInterruptsMask) == 0); // Must fit in mask.
+
+ // Check to see if any of the requested interrupts should be deferred.
+ uword defer_bits = interrupt_bits & deferred_interrupts_mask_;
+ if (defer_bits != 0) {
+ deferred_interrupts_ |= defer_bits;
+ interrupt_bits &= ~deferred_interrupts_mask_;
+ if (interrupt_bits == 0) {
+ return;
+ }
+ }
+
+ if (stack_limit_ == saved_stack_limit_) {
+ stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
+ }
+ stack_limit_ |= interrupt_bits;
+}
+
+
+uword Thread::GetAndClearInterrupts() {
+ MonitorLocker ml(thread_lock_);
+ if (stack_limit_ == saved_stack_limit_) {
+ return 0; // No interrupt was requested.
+ }
+ uword interrupt_bits = stack_limit_ & kInterruptsMask;
+ stack_limit_ = saved_stack_limit_;
+ return interrupt_bits;
+}
+
+
+void Thread::DeferOOBMessageInterrupts() {
+ MonitorLocker ml(thread_lock_);
+ ASSERT(deferred_interrupts_mask_ == 0);
+ deferred_interrupts_mask_ = kMessageInterrupt;
+
+ if (stack_limit_ != saved_stack_limit_) {
+ // Defer any interrupts which are currently pending.
+ deferred_interrupts_ = stack_limit_ & deferred_interrupts_mask_;
+
+ // Clear deferrable interrupts, if present.
+ stack_limit_ &= ~deferred_interrupts_mask_;
+
+ if ((stack_limit_ & kInterruptsMask) == 0) {
+ // No other pending interrupts. Restore normal stack limit.
+ stack_limit_ = saved_stack_limit_;
+ }
+ }
+ if (FLAG_trace_service && FLAG_trace_service_verbose) {
+ OS::Print("[+%" Pd64 "ms] Isolate %s deferring OOB interrupts\n",
+ Dart::timestamp(), isolate()->name());
+ }
+}
+
+
+void Thread::RestoreOOBMessageInterrupts() {
+ MonitorLocker ml(thread_lock_);
+ ASSERT(deferred_interrupts_mask_ == kMessageInterrupt);
+ deferred_interrupts_mask_ = 0;
+ if (deferred_interrupts_ != 0) {
+ if (stack_limit_ == saved_stack_limit_) {
+ stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
+ }
+ stack_limit_ |= deferred_interrupts_;
+ deferred_interrupts_ = 0;
+ }
+ if (FLAG_trace_service && FLAG_trace_service_verbose) {
+ OS::Print("[+%" Pd64 "ms] Isolate %s restoring OOB interrupts\n",
+ Dart::timestamp(), isolate()->name());
+ }
+}
+
+
+RawError* Thread::HandleInterrupts() {
+ uword interrupt_bits = GetAndClearInterrupts();
+ if ((interrupt_bits & kVMInterrupt) != 0) {
+ if (isolate()->store_buffer()->Overflowed()) {
+ if (FLAG_verbose_gc) {
+ OS::PrintErr("Scavenge scheduled by store buffer overflow.\n");
+ }
+ heap()->CollectGarbage(Heap::kNew);
+ }
+ }
+ if ((interrupt_bits & kMessageInterrupt) != 0) {
+ MessageHandler::MessageStatus status =
+ isolate()->message_handler()->HandleOOBMessages();
+ if (status != MessageHandler::kOK) {
+ // False result from HandleOOBMessages signals that the isolate should
+ // be terminating.
+ if (FLAG_trace_isolates) {
+ OS::Print("[!] Terminating isolate due to OOB message:\n"
+ "\tisolate: %s\n", isolate()->name());
+ }
+ Thread* thread = Thread::Current();
+ const Error& error = Error::Handle(thread->sticky_error());
+ ASSERT(!error.IsNull() && error.IsUnwindError());
+ thread->clear_sticky_error();
+ return error.raw();
+ }
+ }
+ return Error::null();
+}
+
+
+uword Thread::GetAndClearStackOverflowFlags() {
+ uword stack_overflow_flags = stack_overflow_flags_;
+ stack_overflow_flags_ = 0;
+ return stack_overflow_flags;
+}
+
+
void Thread::StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy) {
StoreBufferRelease(policy);
StoreBufferAcquire();
@@ -357,9 +550,14 @@
}
-void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor) {
+void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor,
+ bool validate_frames) {
ASSERT(visitor != NULL);
+ if (zone_ != NULL) {
+ zone_->VisitObjectPointers(visitor);
+ }
+
// Visit objects in thread specific handles area.
reusable_handles_.VisitObjectPointers(visitor);
@@ -374,6 +572,15 @@
scope->local_handles()->VisitObjectPointers(visitor);
scope = scope->previous();
}
+
+ // Iterate over all the stack frames and visit objects on the stack.
+ StackFrameIterator frames_iterator(top_exit_frame_info(),
+ validate_frames);
+ StackFrame* frame = frames_iterator.NextFrame();
+ while (frame != NULL) {
+ frame->VisitObjectPointers(visitor);
+ frame = frames_iterator.NextFrame();
+ }
}
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 3bf5aab..31313d6 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -118,6 +118,14 @@
// must currently be called manually (issue 23474).
class Thread : public BaseThread {
public:
+ // The kind of task this thread is performing. Sampled by the profiler.
+ enum TaskKind {
+ kUnknownTask = 0x0,
+ kMutatorTask = 0x1,
+ kCompilerTask = 0x2,
+ kSweeperTask = 0x4,
+ kMarkerTask = 0x8,
+ };
~Thread();
// The currently executing thread, or NULL if not yet initialized.
@@ -139,12 +147,71 @@
// SweeperTask (which uses the class table, which is copy-on-write).
// TODO(koda): Properly synchronize heap access to expand allowed operations.
static bool EnterIsolateAsHelper(Isolate* isolate,
+ TaskKind kind,
bool bypass_safepoint = false);
static void ExitIsolateAsHelper(bool bypass_safepoint = false);
// Empties the store buffer block into the isolate.
void PrepareForGC();
+ void SetStackLimit(uword value);
+ void SetStackLimitFromStackBase(uword stack_base);
+ void ClearStackLimit();
+
+ // Returns the current C++ stack pointer. Equivalent taking the address of a
+ // stack allocated local, but plays well with AddressSanitizer.
+ static uword GetCurrentStackPointer();
+
+ // Access to the current stack limit for generated code. This may be
+ // overwritten with a special value to trigger interrupts.
+ uword stack_limit_address() const {
+ return reinterpret_cast<uword>(&stack_limit_);
+ }
+ static intptr_t stack_limit_offset() {
+ return OFFSET_OF(Thread, stack_limit_);
+ }
+
+ // The true stack limit for this isolate.
+ uword saved_stack_limit() const { return saved_stack_limit_; }
+
+ // Stack overflow flags
+ enum {
+ kOsrRequest = 0x1, // Current stack overflow caused by OSR request.
+ };
+
+ uword stack_overflow_flags_address() const {
+ return reinterpret_cast<uword>(&stack_overflow_flags_);
+ }
+ static intptr_t stack_overflow_flags_offset() {
+ return OFFSET_OF(Thread, stack_overflow_flags_);
+ }
+
+ int32_t IncrementAndGetStackOverflowCount() {
+ return ++stack_overflow_count_;
+ }
+
+ TaskKind task_kind() const {
+ return task_kind_;
+ }
+
+ // Retrieves and clears the stack overflow flags. These are set by
+ // the generated code before the slow path runtime routine for a
+ // stack overflow is called.
+ uword GetAndClearStackOverflowFlags();
+
+ // Interrupt bits.
+ enum {
+ kVMInterrupt = 0x1, // Internal VM checks: safepoints, store buffers, etc.
+ kMessageInterrupt = 0x2, // An interrupt to process an out of band message.
+
+ kInterruptsMask = (kVMInterrupt | kMessageInterrupt),
+ };
+
+ void ScheduleInterrupts(uword interrupt_bits);
+ void ScheduleInterruptsLocked(uword interrupt_bits);
+ RawError* HandleInterrupts();
+ uword GetAndClearInterrupts();
+
// OSThread corresponding to this thread.
OSThread* os_thread() const { return os_thread_; }
void set_os_thread(OSThread* os_thread) {
@@ -521,7 +588,7 @@
Thread* next() const { return next_; }
// Visit all object pointers.
- void VisitObjectPointers(ObjectPointerVisitor* visitor);
+ void VisitObjectPointers(ObjectPointerVisitor* visitor, bool validate_frames);
bool IsValidLocalHandle(Dart_Handle object) const;
int CountLocalHandles() const;
@@ -533,33 +600,15 @@
private:
template<class T> T* AllocateReusableHandle();
- OSThread* os_thread_;
- Monitor* thread_lock_;
+ // Accessed from generated code:
+ uword stack_limit_;
+ uword stack_overflow_flags_;
Isolate* isolate_;
Heap* heap_;
- Zone* zone_;
- ApiLocalScope* api_reusable_scope_;
- ApiLocalScope* api_top_scope_;
uword top_exit_frame_info_;
- StackResource* top_resource_;
- LongJumpScope* long_jump_base_;
StoreBufferBlock* store_buffer_block_;
- int32_t no_callback_scope_depth_;
-#if defined(DEBUG)
- HandleScope* top_handle_scope_;
- int32_t no_handle_scope_depth_;
- int32_t no_safepoint_scope_depth_;
-#endif
- VMHandles reusable_handles_;
-
- // Compiler state:
- CHA* cha_;
- intptr_t deopt_id_; // Compilation specific counter.
uword vm_tag_;
- RawGrowableObjectArray* pending_functions_;
-
- RawError* sticky_error_;
-
+ TaskKind task_kind_;
// State that is cached in the TLS for fast access in generated code.
#define DECLARE_MEMBERS(type_name, member_name, expr, default_init_value) \
type_name member_name;
@@ -576,6 +625,32 @@
LEAF_RUNTIME_ENTRY_LIST(DECLARE_MEMBERS)
#undef DECLARE_MEMBERS
+ OSThread* os_thread_;
+ Monitor* thread_lock_;
+ Zone* zone_;
+ ApiLocalScope* api_reusable_scope_;
+ ApiLocalScope* api_top_scope_;
+ StackResource* top_resource_;
+ LongJumpScope* long_jump_base_;
+ int32_t no_callback_scope_depth_;
+#if defined(DEBUG)
+ HandleScope* top_handle_scope_;
+ int32_t no_handle_scope_depth_;
+ int32_t no_safepoint_scope_depth_;
+#endif
+ VMHandles reusable_handles_;
+ uword saved_stack_limit_;
+ uint16_t deferred_interrupts_mask_;
+ uint16_t deferred_interrupts_;
+ int32_t stack_overflow_count_;
+
+ // Compiler state:
+ CHA* cha_;
+ intptr_t deopt_id_; // Compilation specific counter.
+ RawGrowableObjectArray* pending_functions_;
+
+ RawError* sticky_error_;
+
// Reusable handles support.
#define REUSABLE_HANDLE_FIELDS(object) \
object* object##_handle_;
@@ -622,13 +697,19 @@
OSThread::SetCurrentTLS(reinterpret_cast<uword>(current));
}
+ void DeferOOBMessageInterrupts();
+ void RestoreOOBMessageInterrupts();
+
#define REUSABLE_FRIEND_DECLARATION(name) \
friend class Reusable##name##HandleScope;
REUSABLE_HANDLE_LIST(REUSABLE_FRIEND_DECLARATION)
#undef REUSABLE_FRIEND_DECLARATION
friend class ApiZone;
+ friend class InterruptChecker;
friend class Isolate;
+ friend class IsolateTestHelper;
+ friend class NoOOBMessageScope;
friend class Simulator;
friend class StackZone;
friend class ThreadRegistry;
diff --git a/runtime/vm/thread_pool.cc b/runtime/vm/thread_pool.cc
index b281d5c..fb0f7d7 100644
--- a/runtime/vm/thread_pool.cc
+++ b/runtime/vm/thread_pool.cc
@@ -4,6 +4,7 @@
#include "vm/thread_pool.h"
+#include "vm/dart.h"
#include "vm/flags.h"
#include "vm/lockers.h"
@@ -432,6 +433,9 @@
ThreadJoinId join_id = os_thread->join_id();
ThreadPool* pool;
+ // Set the thread's stack_base based on the current stack pointer.
+ os_thread->set_stack_base(Thread::GetCurrentStackPointer());
+
{
MonitorLocker ml(&worker->monitor_);
ASSERT(worker->task_);
@@ -480,6 +484,12 @@
// wait for the thread to exit by joining on it in Shutdown().
delete worker;
}
+
+ // Call the thread exit hook here to notify the embedder that the
+ // thread pool thread is exiting.
+ if (Dart::thread_exit_callback() != NULL) {
+ (*Dart::thread_exit_callback())();
+ }
}
} // namespace dart
diff --git a/runtime/vm/thread_registry.cc b/runtime/vm/thread_registry.cc
index 111ae57..c660843 100644
--- a/runtime/vm/thread_registry.cc
+++ b/runtime/vm/thread_registry.cc
@@ -56,7 +56,6 @@
// Remove thread from the active list for the isolate.
RemoveFromActiveListLocked(thread);
if (!is_mutator) {
- ASSERT(thread->api_top_scope() == NULL);
ReturnToFreelistLocked(thread);
}
}
@@ -65,22 +64,20 @@
void ThreadRegistry::VisitObjectPointers(ObjectPointerVisitor* visitor,
bool validate_frames) {
MonitorLocker ml(threads_lock());
+ bool mutator_thread_visited = false;
Thread* thread = active_list_;
while (thread != NULL) {
- if (thread->zone() != NULL) {
- thread->zone()->VisitObjectPointers(visitor);
- }
- thread->VisitObjectPointers(visitor);
- // Iterate over all the stack frames and visit objects on the stack.
- StackFrameIterator frames_iterator(thread->top_exit_frame_info(),
- validate_frames);
- StackFrame* frame = frames_iterator.NextFrame();
- while (frame != NULL) {
- frame->VisitObjectPointers(visitor);
- frame = frames_iterator.NextFrame();
+ thread->VisitObjectPointers(visitor, validate_frames);
+ if (mutator_thread_ == thread) {
+ mutator_thread_visited = true;
}
thread = thread->next_;
}
+ // Visit mutator thread even if it is not in the active list because of
+ // api handles.
+ if (!mutator_thread_visited && (mutator_thread_ != NULL)) {
+ mutator_thread_->VisitObjectPointers(visitor, validate_frames);
+ }
}
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index a20d7a4..aa006df 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -111,7 +111,7 @@
intptr_t id)
: isolate_(isolate), monitor_(monitor), done_(done), id_(id) {}
virtual void Run() {
- Thread::EnterIsolateAsHelper(isolate_);
+ Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
{
Thread* thread = Thread::Current();
// Create a zone (which is also a stack resource) and exercise it a bit.
@@ -259,7 +259,7 @@
local_done_(false) {}
virtual void Run() {
- Thread::EnterIsolateAsHelper(isolate_);
+ Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
{
MonitorLocker ml(monitor_);
++*expected_count_;
@@ -534,7 +534,7 @@
}
virtual void Run() {
- Thread::EnterIsolateAsHelper(isolate_);
+ Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
{
Thread* thread = Thread::Current();
StackZone stack_zone(thread);
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index cd0b0fd..5f3d719 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -138,20 +138,14 @@
recorder_ = new TimelineEventRingRecorder();
}
enabled_streams_ = GetEnabledByDefaultTimelineStreams();
- vm_stream_.Init("VM", HasStream(enabled_streams_, "VM"), NULL);
- vm_api_stream_.Init("API",
- HasStream(enabled_streams_, "API"),
- &stream_API_enabled_);
// Global overrides.
-#define ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT(name, not_used) \
- stream_##name##_enabled_ = HasStream(enabled_streams_, #name);
- ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT)
-#undef ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT
-}
-
-
-void Timeline::SetVMStreamEnabled(bool enabled) {
- vm_stream_.set_enabled(enabled);
+#define TIMELINE_STREAM_FLAG_DEFAULT(name, not_used) \
+ stream_##name##_enabled_ = HasStream(enabled_streams_, #name); \
+ stream_##name##_.Init(#name, \
+ stream_##name##_enabled_, \
+ &stream_##name##_enabled_);
+ TIMELINE_STREAM_LIST(TIMELINE_STREAM_FLAG_DEFAULT)
+#undef TIMELINE_STREAM_FLAG_DEFAULT
}
@@ -177,12 +171,10 @@
recorder_->WriteTo(FLAG_timeline_dir);
}
// Disable global streams.
- vm_stream_.set_enabled(false);
- vm_api_stream_.set_enabled(false);
-#define ISOLATE_TIMELINE_STREAM_DISABLE(name, not_used) \
+#define TIMELINE_STREAM_DISABLE(name, not_used) \
stream_##name##_enabled_ = false;
- ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DISABLE)
-#undef ISOLATE_TIMELINE_STREAM_DISABLE
+ TIMELINE_STREAM_LIST(TIMELINE_STREAM_DISABLE)
+#undef TIMELINE_STREAM_DISABLE
delete recorder_;
recorder_ = NULL;
if (enabled_streams_ != NULL) {
@@ -197,30 +189,6 @@
}
-void Timeline::SetupIsolateStreams(Isolate* isolate) {
- if (!FLAG_support_timeline) {
- return;
- }
-#define ISOLATE_TIMELINE_STREAM_INIT(name, enabled_by_default) \
- isolate->Get##name##Stream()->Init( \
- #name, \
- (enabled_by_default || HasStream(enabled_streams_, #name)), \
- Timeline::Stream##name##EnabledFlag());
- ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_INIT);
-#undef ISOLATE_TIMELINE_STREAM_INIT
-}
-
-
-TimelineStream* Timeline::GetVMStream() {
- return &vm_stream_;
-}
-
-
-TimelineStream* Timeline::GetVMApiStream() {
- return &vm_api_stream_;
-}
-
-
void Timeline::ReclaimCachedBlocksFromThreads() {
TimelineEventRecorder* recorder = Timeline::recorder();
if (recorder == NULL) {
@@ -256,9 +224,8 @@
JSONArray availableStreams(&obj, "availableStreams");
#define ADD_STREAM_NAME(name, not_used) \
availableStreams.AddValue(#name);
-ISOLATE_TIMELINE_STREAM_LIST(ADD_STREAM_NAME);
+TIMELINE_STREAM_LIST(ADD_STREAM_NAME);
#undef ADD_STREAM_NAME
- availableStreams.AddValue("VM");
}
{
JSONArray recordedStreams(&obj, "recordedStreams");
@@ -266,11 +233,8 @@
if (stream_##name##_enabled_) { \
recordedStreams.AddValue(#name); \
}
-ISOLATE_TIMELINE_STREAM_LIST(ADD_RECORDED_STREAM_NAME);
+TIMELINE_STREAM_LIST(ADD_RECORDED_STREAM_NAME);
#undef ADD_RECORDED_STREAM_NAME
- if (vm_stream_.enabled()) {
- recordedStreams.AddValue("VM");
- }
}
}
@@ -286,17 +250,15 @@
TimelineEventRecorder* Timeline::recorder_ = NULL;
-TimelineStream Timeline::vm_stream_;
-TimelineStream Timeline::vm_api_stream_;
MallocGrowableArray<char*>* Timeline::enabled_streams_ = NULL;
Dart_EmbedderTimelineStartRecording Timeline::start_recording_cb_ = NULL;
Dart_EmbedderTimelineStopRecording Timeline::stop_recording_cb_ = NULL;
-Dart_EmbedderTimelineGetTimeline Timeline::get_timeline_cb_ = NULL;
-#define ISOLATE_TIMELINE_STREAM_DEFINE_FLAG(name, enabled_by_default) \
- bool Timeline::stream_##name##_enabled_ = enabled_by_default;
- ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DEFINE_FLAG)
-#undef ISOLATE_TIMELINE_STREAM_DEFINE_FLAG
+#define TIMELINE_STREAM_DEFINE(name, enabled_by_default) \
+ bool Timeline::stream_##name##_enabled_ = enabled_by_default; \
+ TimelineStream Timeline::stream_##name##_;
+ TIMELINE_STREAM_LIST(TIMELINE_STREAM_DEFINE)
+#undef TIMELINE_STREAM_DEFINE
TimelineEvent::TimelineEvent()
: timestamp0_(0),
@@ -1027,21 +989,13 @@
}
-void TimelineEventRecorder::PrintEmbedderJSONEvents(JSONStream* events) {
- if (Timeline::get_get_timeline_cb() != NULL) {
- events->PrintCommaIfNeeded();
- Timeline::get_get_timeline_cb()(AppendJSONStreamConsumer, events);
- }
-}
-
-
void TimelineEventRecorder::WriteTo(const char* directory) {
if (!FLAG_support_service) {
return;
}
- Dart_FileOpenCallback file_open = Isolate::file_open_callback();
- Dart_FileWriteCallback file_write = Isolate::file_write_callback();
- Dart_FileCloseCallback file_close = Isolate::file_close_callback();
+ Dart_FileOpenCallback file_open = Dart::file_open_callback();
+ Dart_FileWriteCallback file_write = Dart::file_write_callback();
+ Dart_FileCloseCallback file_close = Dart::file_close_callback();
if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
return;
}
@@ -1174,7 +1128,6 @@
JSONArray events(&topLevel, "traceEvents");
PrintJSONMeta(&events);
PrintJSONEvents(&events, filter);
- PrintEmbedderJSONEvents(js);
}
}
@@ -1186,7 +1139,6 @@
}
JSONArray events(js);
PrintJSONEvents(&events, filter);
- PrintEmbedderJSONEvents(js);
}
@@ -1309,7 +1261,6 @@
JSONArray events(&topLevel, "traceEvents");
PrintJSONMeta(&events);
PrintJSONEvents(&events, filter);
- PrintEmbedderJSONEvents(js);
}
}
@@ -1322,7 +1273,6 @@
}
JSONArray events(js);
PrintJSONEvents(&events, filter);
- PrintEmbedderJSONEvents(js);
}
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index 9887aff..f16056e 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -28,7 +28,7 @@
class Zone;
// (name, enabled by default for isolate).
-#define ISOLATE_TIMELINE_STREAM_LIST(V) \
+#define TIMELINE_STREAM_LIST(V) \
V(API, false) \
V(Compiler, false) \
V(Dart, false) \
@@ -36,6 +36,7 @@
V(Embedder, false) \
V(GC, false) \
V(Isolate, false) \
+ V(VM, false)
class Timeline : public AllStatic {
public:
@@ -48,12 +49,6 @@
// Access the global recorder. Not thread safe.
static TimelineEventRecorder* recorder();
- static void SetupIsolateStreams(Isolate* isolate);
-
- static TimelineStream* GetVMStream();
-
- static TimelineStream* GetVMApiStream();
-
// Reclaim all |TimelineEventBlocks|s that are cached by threads.
static void ReclaimCachedBlocksFromThreads();
@@ -62,7 +57,12 @@
// Print information about streams to JSON.
static void PrintFlagsToJSON(JSONStream* json);
-#define ISOLATE_TIMELINE_STREAM_FLAGS(name, not_used) \
+#define TIMELINE_STREAM_ACCESSOR(name, not_used) \
+ static TimelineStream* Get##name##Stream() { return &stream_##name##_; }
+ TIMELINE_STREAM_LIST(TIMELINE_STREAM_ACCESSOR)
+#undef TIMELINE_STREAM_ACCESSOR
+
+#define TIMELINE_STREAM_FLAGS(name, not_used) \
static const bool* Stream##name##EnabledFlag() { \
return &stream_##name##_enabled_; \
} \
@@ -70,9 +70,8 @@
StreamStateChange(#name, stream_##name##_enabled_, enabled); \
stream_##name##_enabled_ = enabled; \
}
- ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_FLAGS)
-#undef ISOLATE_TIMELINE_STREAM_FLAGS
- static void SetVMStreamEnabled(bool enabled);
+ TIMELINE_STREAM_LIST(TIMELINE_STREAM_FLAGS)
+#undef TIMELINE_STREAM_FLAGS
static void set_start_recording_cb(
Dart_EmbedderTimelineStartRecording start_recording_cb) {
@@ -92,29 +91,18 @@
return stop_recording_cb_;
}
- static void set_get_timeline_cb(
- Dart_EmbedderTimelineGetTimeline get_timeline_cb) {
- get_timeline_cb_ = get_timeline_cb;
- }
-
- static Dart_EmbedderTimelineGetTimeline get_get_timeline_cb() {
- return get_timeline_cb_;
- }
-
private:
static void StreamStateChange(const char* stream_name, bool prev, bool curr);
static TimelineEventRecorder* recorder_;
- static TimelineStream vm_stream_;
- static TimelineStream vm_api_stream_;
static MallocGrowableArray<char*>* enabled_streams_;
static Dart_EmbedderTimelineStartRecording start_recording_cb_;
static Dart_EmbedderTimelineStopRecording stop_recording_cb_;
- static Dart_EmbedderTimelineGetTimeline get_timeline_cb_;
-#define ISOLATE_TIMELINE_STREAM_DECLARE_FLAG(name, not_used) \
- static bool stream_##name##_enabled_;
- ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DECLARE_FLAG)
-#undef ISOLATE_TIMELINE_STREAM_DECLARE_FLAG
+#define TIMELINE_STREAM_DECLARE(name, not_used) \
+ static bool stream_##name##_enabled_; \
+ static TimelineStream stream_##name##_;
+ TIMELINE_STREAM_LIST(TIMELINE_STREAM_DECLARE)
+#undef TIMELINE_STREAM_DECLARE
friend class TimelineRecorderOverride;
friend class ReclaimBlocksIsolateVisitor;
@@ -222,6 +210,10 @@
return thread_;
}
+ void set_thread(ThreadId tid) {
+ thread_ = tid;
+ }
+
Dart_Port isolate_id() const {
return isolate_id_;
}
@@ -384,10 +376,10 @@
};
#ifndef PRODUCT
-#define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, suffix, function) \
+#define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, name, function) \
TimelineDurationScope tds(thread, \
- thread->isolate()->GetCompilerStream(), \
- "Compile" suffix); \
+ Timeline::GetCompilerStream(), \
+ name); \
if (tds.enabled()) { \
tds.SetNumArguments(1); \
tds.CopyArgument( \
@@ -395,8 +387,12 @@
"function", \
function.ToLibNamePrefixedQualifiedCString()); \
}
+
+#define TIMELINE_FUNCTION_GC_DURATION(thread, name) \
+ TimelineDurationScope tds(thread, Timeline::GetGCStream(), name);
#else
-#define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, suffix, function)
+#define TIMELINE_FUNCTION_COMPILATION_DURATION(thread, name, function)
+#define TIMELINE_FUNCTION_GC_DURATION(thread, name)
#endif // !PRODUCT
// See |TimelineDurationScope| and |TimelineBeginEndScope|.
@@ -678,7 +674,6 @@
void PrintJSONMeta(JSONArray* array) const;
TimelineEvent* ThreadBlockStartEvent();
void ThreadBlockCompleteEvent(TimelineEvent* event);
- void PrintEmbedderJSONEvents(JSONStream* events);
Mutex lock_;
uintptr_t async_id_;
diff --git a/runtime/vm/vm.gypi b/runtime/vm/vm.gypi
index 0f857b3..a08a1b8 100644
--- a/runtime/vm/vm.gypi
+++ b/runtime/vm/vm.gypi
@@ -30,7 +30,6 @@
'snapshot_test_in_dat_file': 'snapshot_test_in.dat',
'snapshot_test_dart_file': 'snapshot_test.dart',
'typed_data_cc_file': '<(gen_source_dir)/typed_data_gen.cc',
- 'typed_data_patch_cc_file': '<(gen_source_dir)/typed_data_patch_gen.cc',
'vmservice_cc_file': '<(gen_source_dir)/vmservice_gen.cc',
'vmservice_patch_cc_file': '<(gen_source_dir)/vmservice_patch_gen.cc',
},
@@ -234,7 +233,6 @@
'generate_mirrors_patch_cc_file#host',
'generate_profiler_cc_file#host',
'generate_typed_data_cc_file#host',
- 'generate_typed_data_patch_cc_file#host',
'generate_vmservice_cc_file#host',
'generate_vmservice_patch_cc_file#host',
],
@@ -273,7 +271,6 @@
'<(mirrors_patch_cc_file)',
'<(profiler_cc_file)',
'<(typed_data_cc_file)',
- '<(typed_data_patch_cc_file)',
'<(vmservice_cc_file)',
'<(vmservice_patch_cc_file)',
],
@@ -974,8 +971,8 @@
'type': 'none',
'toolsets':['host'],
'includes': [
- # Load the shared library sources.
- '../../sdk/lib/typed_data/typed_data_sources.gypi',
+ # Load the runtime implementation sources.
+ '../lib/typed_data_sources.gypi',
],
'sources/': [
# Exclude all .[cc|h] files.
@@ -1010,46 +1007,6 @@
]
},
{
- 'target_name': 'generate_typed_data_patch_cc_file',
- 'type': 'none',
- 'toolsets':['host'],
- 'includes': [
- # Load the runtime implementation sources.
- '../lib/typed_data_sources.gypi',
- ],
- 'sources/': [
- # Exclude all .[cc|h] files.
- # This is only here for reference. Excludes happen after
- # variable expansion, so the script has to do its own
- # exclude processing of the sources being passed.
- ['exclude', '\\.cc|h$'],
- ],
- 'actions': [
- {
- 'action_name': 'generate_typed_data_patch_cc',
- 'inputs': [
- '../tools/gen_library_src_paths.py',
- '<(libgen_in_cc_file)',
- '<@(_sources)',
- ],
- 'outputs': [
- '<(typed_data_patch_cc_file)',
- ],
- 'action': [
- 'python',
- 'tools/gen_library_src_paths.py',
- '--output', '<(typed_data_patch_cc_file)',
- '--input_cc', '<(libgen_in_cc_file)',
- '--include', 'vm/bootstrap.h',
- '--var_name', 'dart::Bootstrap::typed_data_patch_paths_',
- '--library_name', 'dart:typed_data',
- '<@(_sources)',
- ],
- 'message': 'Generating ''<(typed_data_patch_cc_file)'' file.'
- },
- ]
- },
- {
'target_name': 'generate_profiler_cc_file',
'type': 'none',
'toolsets':['host'],
diff --git a/sdk/bin/dartdevc b/sdk/bin/dartdevc
new file mode 100755
index 0000000..331eb4e
--- /dev/null
+++ b/sdk/bin/dartdevc
@@ -0,0 +1,86 @@
+#!/usr/bin/env bash
+# Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Run dev compiler on the Dart VM. This script assumes the Dart repo's
+# directory structure.
+
+function follow_links() {
+ file="$1"
+ while [ -h "$file" ]; do
+ # On Mac OS, readlink -f doesn't work.
+ file="$(readlink "$file")"
+ done
+ echo "$file"
+}
+
+# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
+PROG_NAME="$(follow_links "$BASH_SOURCE")"
+
+# Handle the case where dart-sdk/bin has been symlinked to.
+BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
+SDK_DIR="$(cd "${BIN_DIR}/.." ; pwd -P)"
+
+SDK_ARG="--dart-sdk=$SDK_DIR"
+
+DART="$BIN_DIR/dart"
+
+unset EXTRA_VM_OPTIONS
+declare -a EXTRA_VM_OPTIONS
+
+case $0 in
+ *_developer)
+ EXTRA_VM_OPTIONS+=('--checked')
+ ;;
+esac
+
+# We allow extra vm options to be passed in through an environment variable.
+if [[ $DART_VM_OPTIONS ]]; then
+ read -a OPTIONS <<< "$DART_VM_OPTIONS"
+ EXTRA_VM_OPTIONS+=("${OPTIONS[@]}")
+fi
+
+DART_ROOT="$(cd "${SDK_DIR}/.." ; pwd -P)"
+
+DEV_COMPILER="$DART_ROOT/third_party/pkg/dev_compiler/bin/dartdevc.dart"
+
+if [[ `uname` == 'Darwin' ]];
+then
+ OUT_DIR="$DART_ROOT/xcodebuild/"
+else
+ OUT_DIR="$DART_ROOT/out/"
+fi
+
+if [ -z "$DART_CONFIGURATION" ];
+then
+ DIRS=$( ls "$OUT_DIR" )
+ # list of possible configurations in decreasing desirability
+ CONFIGS=("ReleaseX64" "ReleaseIA32" "DebugX64" "DebugIA32"
+ "ReleaseARM" "ReleaseARM64" "ReleaseARMV5TE" "ReleaseMIPS"
+ "DebugARM" "DebugARM64" "DebugARMV5TE" "DebugMIPS")
+ DART_CONFIGURATION="None"
+ for CONFIG in ${CONFIGS[*]}
+ do
+ for DIR in $DIRS;
+ do
+ if [ "$CONFIG" = "$DIR" ];
+ then
+ # choose most desirable configuration that is available and break
+ DART_CONFIGURATION="$DIR"
+ break 2
+ fi
+ done
+ done
+ if [ "$DART_CONFIGURATION" = "None" ]
+ then
+ echo "No valid dart configuration found in $OUT_DIR"
+ exit 1
+ fi
+fi
+
+BUILD_DIR="$OUT_DIR$DART_CONFIGURATION"
+
+PACKAGE_ROOT="$BUILD_DIR/packages/"
+
+exec "$DART" "${EXTRA_VM_OPTIONS[@]}" "--package-root=$PACKAGE_ROOT" "$DEV_COMPILER" "$SDK_ARG" "$@"
diff --git a/sdk/bin/dartdevc.bat b/sdk/bin/dartdevc.bat
new file mode 100644
index 0000000..4e02005
--- /dev/null
+++ b/sdk/bin/dartdevc.bat
@@ -0,0 +1,73 @@
+@echo off
+REM Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+REM for details. All rights reserved. Use of this source code is governed by a
+REM BSD-style license that can be found in the LICENSE file.
+
+setlocal
+rem Handle the case where dart-sdk/bin has been symlinked to.
+set DIR_NAME_WITH_SLASH=%~dp0
+set DIR_NAME=%DIR_NAME_WITH_SLASH:~0,-1%%
+call :follow_links "%DIR_NAME%", RETURNED_BIN_DIR
+rem Get rid of surrounding quotes.
+for %%i in ("%RETURNED_BIN_DIR%") do set BIN_DIR=%%~fi
+
+set DART=%BIN_DIR%\dart
+
+rem Get absolute full name for SDK_DIR.
+for %%i in ("%BIN_DIR%\..\") do set SDK_DIR=%%~fi
+
+rem Remove trailing backslash if there is one
+if %SDK_DIR:~-1%==\ set SDK_DIR=%SDK_DIR:~0,-1%
+
+set SDK_ARG=--dart-sdk=%SDK_DIR%
+
+set EXTRA_VM_OPTIONS=
+
+rem We allow extra vm options to be passed in through an environment variable.
+if not "_%DART_VM_OPTIONS%_" == "__" (
+ set EXTRA_VM_OPTIONS=%EXTRA_VM_OPTIONS% %DART_VM_OPTIONS%
+)
+
+rem Get absolute full name for DART_ROOT.
+for %%i in ("%SDK_DIR%\..\") do set DART_ROOT=%%~fi
+
+rem Remove trailing backslash if there is one
+if %DART_ROOT:~-1%==\ set DART_ROOT=%DART_ROOT:~0,-1%
+
+set DEV_COMPILER=%DART_ROOT%\third_party\pkg\dev_compiler\bin\dartdevc.dart
+
+rem DART_CONFIGURATION defaults to ReleaseX64
+if "%DART_CONFIGURATION%"=="" set DART_CONFIGURATION=ReleaseX64
+
+set BUILD_DIR=%DART_ROOT%\build\%DART_CONFIGURATION%
+
+set PACKAGE_ROOT=%BUILD_DIR%\packages
+
+"%DART%" %EXTRA_VM_OPTIONS% "--package-root=%PACKAGE_ROOT%" "DEV_COMPILER%" "%SDK_ARG%" %*
+
+endlocal
+
+exit /b %errorlevel%
+
+rem Follow the symbolic links (junctions points) using `dir to determine the
+rem canonical path. Output with a link looks something like this
+rem
+rem 01/03/2013 10:11 PM <JUNCTION> abc def
+rem [c:\dart_bleeding\dart-repo.9\dart\build\ReleaseIA32\dart-sdk]
+rem
+rem So in the output of 'dir /a:l "targetdir"' we are looking for a filename
+rem surrounded by right angle bracket and left square bracket. Once we get
+rem the filename, which is name of the link, we recursively follow that.
+:follow_links
+setlocal
+for %%i in (%1) do set result=%%~fi
+set current=
+for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
+ ^| find "> %~n1 ["`) do (
+ set current=%%i
+)
+if not "%current%"=="" call :follow_links "%current%", result
+endlocal & set %~2=%result%
+goto :eof
+
+:end
diff --git a/sdk/bin/dartdevc_sdk b/sdk/bin/dartdevc_sdk
new file mode 100755
index 0000000..7bc98de
--- /dev/null
+++ b/sdk/bin/dartdevc_sdk
@@ -0,0 +1,31 @@
+#!/usr/bin/env bash
+# Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Run dev compiler on the Dart VM. This script assumes the Dart SDK's
+# directory structure.
+
+function follow_links() {
+ file="$1"
+ while [ -h "$file" ]; do
+ # On Mac OS, readlink -f doesn't work.
+ file="$(readlink "$file")"
+ done
+ echo "$file"
+}
+
+# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
+PROG_NAME="$(follow_links "$BASH_SOURCE")"
+
+# Handle the case where dart-sdk/bin has been symlinked to.
+BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
+SDK_DIR="$(cd "${BIN_DIR}/.." ; pwd -P)"
+
+SDK_ARG="--dart-sdk=$SDK_DIR"
+
+SNAPSHOT="$BIN_DIR/snapshots/dartdevc.dart.snapshot"
+
+# We are running the snapshot in the built SDK.
+DART="$BIN_DIR/dart"
+exec "$DART" "$SNAPSHOT" "$SDK_ARG" "$@"
diff --git a/sdk/bin/dartdevc_sdk.bat b/sdk/bin/dartdevc_sdk.bat
new file mode 100644
index 0000000..72c2069
--- /dev/null
+++ b/sdk/bin/dartdevc_sdk.bat
@@ -0,0 +1,52 @@
+@echo off
+REM Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+REM for details. All rights reserved. Use of this source code is governed by a
+REM BSD-style license that can be found in the LICENSE file.
+
+setlocal
+rem Handle the case where dart-sdk/bin has been symlinked to.
+set DIR_NAME_WITH_SLASH=%~dp0
+set DIR_NAME=%DIR_NAME_WITH_SLASH:~0,-1%%
+call :follow_links "%DIR_NAME%", RETURNED_BIN_DIR
+rem Get rid of surrounding quotes.
+for %%i in ("%RETURNED_BIN_DIR%") do set BIN_DIR=%%~fi
+
+set DART=%BIN_DIR%\dart
+set SNAPSHOT=%BIN_DIR%\snapshots\dartdevc.dart.snapshot
+
+rem Get absolute full name for SDK_DIR.
+for %%i in ("%BIN_DIR%\..\") do set SDK_DIR=%%~fi
+
+rem Remove trailing backslash if there is one
+if %SDK_DIR:~-1%==\ set SDK_DIR=%SDK_DIR:~0,-1%
+
+set SDK_ARG=--dart-sdk=%SDK_DIR%
+
+"%DART%" "%SNAPSHOT%" "%SDK_ARG%" %*
+
+endlocal
+
+exit /b %errorlevel%
+
+rem Follow the symbolic links (junctions points) using `dir to determine the
+rem canonical path. Output with a link looks something like this
+rem
+rem 01/03/2013 10:11 PM <JUNCTION> abc def
+rem [c:\dart_bleeding\dart-repo.9\dart\build\ReleaseIA32\dart-sdk]
+rem
+rem So in the output of 'dir /a:l "targetdir"' we are looking for a filename
+rem surrounded by right angle bracket and left square bracket. Once we get
+rem the filename, which is name of the link, we recursively follow that.
+:follow_links
+setlocal
+for %%i in (%1) do set result=%%~fi
+set current=
+for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^
+ ^| find "> %~n1 ["`) do (
+ set current=%%i
+)
+if not "%current%"=="" call :follow_links "%current%", result
+endlocal & set %~2=%result%
+goto :eof
+
+:end
diff --git a/sdk/lib/_internal/js_runtime/lib/io_patch.dart b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
index 350ab96..e403844 100644
--- a/sdk/lib/_internal/js_runtime/lib/io_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
@@ -420,6 +420,11 @@
static SecurityContext get defaultContext {
throw new UnsupportedError("default SecurityContext getter");
}
+
+ @patch
+ static bool get alpnSupported {
+ throw new UnsupportedError("SecurityContext alpnSupported getter");
+ }
}
@patch
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index ad72431..8ca10c9 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -64,9 +64,11 @@
static const int MASK_WHENCOMPLETE = 8;
static const int STATE_CHAIN = 0;
static const int STATE_THEN = MASK_VALUE;
- static const int STATE_THEN_ONERROR = MASK_VALUE | MASK_ERROR;
+ // TODO(johnmccutchan): Remove the hard coded value. See #26030.
+ static const int STATE_THEN_ONERROR = 3; // MASK_VALUE | MASK_ERROR.
static const int STATE_CATCHERROR = MASK_ERROR;
- static const int STATE_CATCHERROR_TEST = MASK_ERROR | MASK_TEST_ERROR;
+ // TODO(johnmccutchan): Remove the hard coded value. See #26030.
+ static const int STATE_CATCHERROR_TEST = 6; // MASK_ERROR | MASK_TEST_ERROR.
static const int STATE_WHENCOMPLETE = MASK_WHENCOMPLETE;
// Listeners on the same future are linked through this link.
_FutureListener _nextListener = null;
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index dc2593b..7b17154 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -34132,12 +34132,14 @@
@DomName('VTTCue.line')
@DocsEditable()
@Experimental() // untriaged
+ @Creates('Null')
@Returns('num|String')
Object line;
@DomName('VTTCue.position')
@DocsEditable()
@Experimental() // untriaged
+ @Creates('Null')
@Returns('num|String')
Object position;
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index cf8dec0..c271d77 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -970,8 +970,16 @@
return _IOService._dispatch(_SSL_PROCESS_FILTER, args).then((response) {
if (response.length == 2) {
- _reportError(new TlsException('${response[1]} error ${response[0]}'),
- null);
+ if (wasInHandshake) {
+ // If we're in handshake, throw a handshake error.
+ _reportError(
+ new HandshakeException('${response[1]} error ${response[0]}'),
+ null);
+ } else {
+ // If we're connected, throw a TLS error.
+ _reportError(new TlsException('${response[1]} error ${response[0]}'),
+ null);
+ }
}
int start(int index) => response[2 * index];
int end(int index) => response[2 * index + 1];
diff --git a/sdk/lib/io/security_context.dart b/sdk/lib/io/security_context.dart
index 86dfc96..1e169af 100644
--- a/sdk/lib/io/security_context.dart
+++ b/sdk/lib/io/security_context.dart
@@ -126,6 +126,11 @@
void setClientAuthoritiesBytes(List<int> authCertBytes, {String password});
/**
+ * Whether the platform supports ALPN.
+ */
+ external static bool get alpnSupported;
+
+ /**
* Sets the list of application-level protocols supported by a client
* connection or server connection. The ALPN (application level protocol
* negotiation) extension to TLS allows a client to send a list of
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 021b554..2d3d20f 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -3179,13 +3179,12 @@
Language/Classes/Constructors/Factories/return_type_t05: Pass, Slow # Issue 25940
[ $compiler == dart2js && $runtime == ff && $system != windows ]
-LayoutTests/fast/canvas/canvas-resetTransform_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/canvas/canvas-setTransform_t01: RuntimeError # Please triage this failure
LayoutTests/fast/xpath/4XPath/Core/test_parser_t01: RuntimeError # Dartium JSInterop failure
LayoutTests/fast/xpath/py-dom-xpath/abbreviations_t01: RuntimeError # Dartium JSInterop failure
[ $compiler == dart2js && $runtime == ff && $system == linux]
LayoutTests/fast/canvas/canvas-composite-text-alpha_t01: RuntimeError # co19 issue 16
+LayoutTests/fast/text/whitespace/nowrap-line-break-after-white-space_t01: Pass, RuntimeError # Please triage this failure
[ $compiler == dart2js && $runtime == safari ]
LayoutTests/fast/alignment/parse-align-items_t01: RuntimeError # Please triage this failure
diff --git a/tests/compiler/dart2js/analyze_helper.dart b/tests/compiler/dart2js/analyze_helper.dart
index 41dc321..8db5912 100644
--- a/tests/compiler/dart2js/analyze_helper.dart
+++ b/tests/compiler/dart2js/analyze_helper.dart
@@ -7,6 +7,7 @@
import 'dart:async';
import 'dart:io';
import 'package:compiler/compiler.dart' as api;
+import 'package:compiler/compiler_new.dart' as new_api;
import 'package:compiler/src/apiimpl.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/diagnostics/messages.dart' show
@@ -194,10 +195,11 @@
provider,
null,
handler,
- libraryRoot,
- packageRoot,
- options,
- {});
+ new new_api.CompilerOptions.parse(
+ libraryRoot: libraryRoot,
+ packageRoot: packageRoot,
+ options: options,
+ environment: {}));
String MESSAGE = """
diff --git a/tests/compiler/dart2js/bad_loop_test.dart b/tests/compiler/dart2js/bad_loop_test.dart
index c1b2a6d..525aa8c 100644
--- a/tests/compiler/dart2js/bad_loop_test.dart
+++ b/tests/compiler/dart2js/bad_loop_test.dart
@@ -8,7 +8,7 @@
import 'package:compiler/compiler.dart'
show Diagnostic;
-import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/compiler_new.dart' show CompilerOptions;
import 'package:compiler/src/old_to_new_api.dart';
main() {
@@ -37,10 +37,9 @@
new LegacyCompilerInput(provider.readStringFromUri),
new LegacyCompilerOutput(),
new LegacyCompilerDiagnostics(diagnosticHandler),
- libraryRoot,
- packageRoot,
- [Flags.analyzeOnly],
- {});
+ new CompilerOptions(
+ libraryRoot: libraryRoot,
+ packageRoot: packageRoot));
asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
Expect.isTrue(compiler.compilationFailed);
Expect.equals(5, errorCount);
diff --git a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
index 517a347..123ae7e 100644
--- a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
+++ b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
@@ -14,8 +14,7 @@
bool disableInlining,
check(compiler, element)) {
Uri uri = new Uri(scheme: 'source');
- var compiler = compilerFor(code, uri);
- compiler.disableInlining = disableInlining;
+ var compiler = compilerFor(code, uri, disableInlining: disableInlining);
asyncTest(() => compiler.run(uri).then((_) {
var cls = findElement(compiler, className);
var member = cls.lookupLocalMember(memberName);
diff --git a/tests/compiler/dart2js/codegen_helper.dart b/tests/compiler/dart2js/codegen_helper.dart
index c99fc49..1e1dec8 100644
--- a/tests/compiler/dart2js/codegen_helper.dart
+++ b/tests/compiler/dart2js/codegen_helper.dart
@@ -4,6 +4,7 @@
import 'dart:async';
import 'package:expect/expect.dart';
+import 'package:compiler/compiler_new.dart' show CompilerOptions;
import 'package:compiler/src/null_compiler_output.dart';
import 'memory_source_file_helper.dart';
@@ -16,14 +17,15 @@
var provider = new MemorySourceFileProvider({ 'main.dart': code });
var handler = new FormattingDiagnosticHandler(provider);
+ Uri uri = Uri.parse('memory:main.dart');
CompilerImpl compiler = new CompilerImpl(provider,
const NullCompilerOutput(),
handler,
- libraryRoot,
- packageRoot,
- options,
- {});
- Uri uri = Uri.parse('memory:main.dart');
+ new CompilerOptions.parse(
+ entryPoint: uri,
+ libraryRoot: libraryRoot,
+ packageRoot: packageRoot,
+ options: options));
return compiler.run(uri).then((success) {
Expect.isTrue(success);
Map<String, String> result = new Map<String, String>();
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart
index bef0984..e365f3b 100644
--- a/tests/compiler/dart2js/compiler_helper.dart
+++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -112,6 +112,10 @@
options.add(Flags.trustJSInteropTypeAnnotations);
}
+ if (disableInlining) {
+ options.add(Flags.disableInlining);
+ }
+
Map<String, String> source;
if (entry != 'main') {
source = {'main.dart': "$code\n\nmain() => $entry;" };
@@ -122,12 +126,7 @@
CompilationResult result = await runCompiler(
memorySourceFiles: source,
options: options,
- outputProvider: outputCollector,
- beforeRun: (compiler) {
- if (disableInlining) {
- compiler.disableInlining = true;
- }
- });
+ outputProvider: outputCollector);
Expect.isTrue(result.isSuccess);
Compiler compiler = result.compiler;
lego.Element element = compiler.mainApp.find(entry);
diff --git a/tests/compiler/dart2js/exit_code_test.dart b/tests/compiler/dart2js/exit_code_test.dart
index e5263e4..ec9c160 100644
--- a/tests/compiler/dart2js/exit_code_test.dart
+++ b/tests/compiler/dart2js/exit_code_test.dart
@@ -50,8 +50,14 @@
String this.testMarker,
String this.testType,
Function this.onTest)
- : super(inputProvider, outputProvider, handler, libraryRoot,
- packageRoot, options, environment, packageConfig, findPackages) {
+ : super(inputProvider, outputProvider, handler,
+ new api.CompilerOptions.parse(
+ libraryRoot: libraryRoot,
+ packageRoot: packageRoot,
+ options: options,
+ environment: environment,
+ packageConfig: packageConfig,
+ packagesDiscoveryProvider: findPackages)) {
scanner = new TestScanner(this);
resolver = new TestResolver(this, backend.constantCompilerTask);
reporter = new TestDiagnosticReporter(this, super.reporter);
diff --git a/tests/compiler/dart2js/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
index 7eeb5f9..534a7ed 100644
--- a/tests/compiler/dart2js/field_type_simple_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
@@ -16,9 +16,9 @@
bool disableInlining,
check(compiler, element)) {
Uri uri = new Uri(scheme: 'source');
- var compiler = compilerFor(code, uri);
+ var compiler = compilerFor(code, uri,
+ disableInlining: disableInlining);
asyncTest(() => compiler.run(uri).then((_) {
- compiler.disableInlining = disableInlining;
var cls = findElement(compiler, className);
var member = cls.lookupMember(memberName);
check(compiler, member);
diff --git a/tests/compiler/dart2js/incremental/compile_all.dart b/tests/compiler/dart2js/incremental/compile_all.dart
index 9d62061..fb22d15 100644
--- a/tests/compiler/dart2js/incremental/compile_all.dart
+++ b/tests/compiler/dart2js/incremental/compile_all.dart
@@ -53,7 +53,7 @@
inputProvider: memoryCompiler.provider,
outputProvider: memoryCompiler.userOutputProvider,
diagnosticHandler: memoryCompiler.handler,
- packageRoot: memoryCompiler.packageRoot,
+ packageRoot: memoryCompiler.options.packageRoot,
options: options);
Future.forEach(sources.keys, (String path) {
UserTag.defaultTag.makeCurrent();
diff --git a/tests/compiler/dart2js/library_env_test.dart b/tests/compiler/dart2js/library_env_test.dart
index 0f0ff6d..7f377cf 100644
--- a/tests/compiler/dart2js/library_env_test.dart
+++ b/tests/compiler/dart2js/library_env_test.dart
@@ -24,7 +24,8 @@
import 'package:compiler/compiler_new.dart' show
CompilerInput,
- CompilerDiagnostics;
+ CompilerDiagnostics,
+ CompilerOptions;
import 'package:sdk_library_metadata/libraries.dart' show
LibraryInfo;
@@ -80,23 +81,19 @@
}
class CustomCompiler extends CompilerImpl {
- CustomCompiler(
- options,
- environment)
+ CustomCompiler(options, environment)
: super(
const DummyCompilerInput(),
const NullCompilerOutput(),
const DummyCompilerDiagnostics(),
- Uri.base.resolve("sdk/"),
- null,
- options,
- environment);
+ new CompilerOptions.parse(
+ libraryRoot: Uri.base.resolve("sdk/"),
+ options: options,
+ environment: environment));
}
runTest() async {
- var compiler = new CustomCompiler(
- [],
- {});
+ var compiler = new CustomCompiler([], {});
await compiler.setupSdk();
@@ -113,9 +110,7 @@
Expect.equals(null, compiler.fromEnvironment("dart.library.mock.server"));
Expect.equals(null, compiler.fromEnvironment("dart.library.io"));
- compiler = new CustomCompiler(
- ['--categories=Server'],
- {});
+ compiler = new CustomCompiler(['--categories=Server'], {});
await compiler.setupSdk();
@@ -133,8 +128,7 @@
Expect.equals("true", compiler.fromEnvironment("dart.library.io"));
// Check that user-defined env-variables win.
- compiler = new CustomCompiler(
- [],
+ compiler = new CustomCompiler([],
{'dart.library.collection': "false",
'dart.library.mock.client': "foo"});
@@ -149,4 +143,4 @@
runTest().then((_) {
asyncEnd();
});
-}
\ No newline at end of file
+}
diff --git a/tests/compiler/dart2js/library_resolution_test.dart b/tests/compiler/dart2js/library_resolution_test.dart
index 28ad567..23e4a0a 100644
--- a/tests/compiler/dart2js/library_resolution_test.dart
+++ b/tests/compiler/dart2js/library_resolution_test.dart
@@ -25,16 +25,18 @@
import 'package:compiler/src/old_to_new_api.dart'
show LegacyCompilerDiagnostics, LegacyCompilerInput;
+import 'package:compiler/compiler_new.dart' show CompilerOptions;
Uri sdkRoot = Uri.base.resolve("sdk/");
Uri mock1LibraryUri = sdkRoot.resolve("lib/mock1.dart");
Uri mock2LibraryUri = sdkRoot.resolve("lib/mock2.dart");
class CustomCompiler extends CompilerImpl {
- CustomCompiler(provider, handler, libraryRoot,
- packageRoot, options, environment)
- : super(provider, const NullCompilerOutput(), handler, libraryRoot,
- packageRoot, options, environment);
+ CustomCompiler(provider, handler, libraryRoot, packageRoot)
+ : super(provider, const NullCompilerOutput(), handler,
+ new CompilerOptions(
+ libraryRoot: libraryRoot,
+ packageRoot: packageRoot));
Uri lookupLibraryUri(String libraryName) {
if (libraryName == "m_o_c_k_1") return mock1LibraryUri;
@@ -81,9 +83,7 @@
new LegacyCompilerInput(wrappedProvider),
new LegacyCompilerDiagnostics(wrappedHandler),
sdkRoot,
- packageRoot,
- [],
- {});
+ packageRoot);
asyncStart();
await compiler.setupSdk();
diff --git a/tests/compiler/dart2js/memory_compiler.dart b/tests/compiler/dart2js/memory_compiler.dart
index fa69df7..df9807e 100644
--- a/tests/compiler/dart2js/memory_compiler.dart
+++ b/tests/compiler/dart2js/memory_compiler.dart
@@ -11,6 +11,7 @@
import 'package:compiler/compiler_new.dart' show
CompilationResult,
CompilerDiagnostics,
+ CompilerOptions,
CompilerOutput,
Diagnostic,
PackagesDiscoveryProvider;
@@ -84,6 +85,7 @@
entryPoint = Uri.parse('memory:main.dart');
}
CompilerImpl compiler = compilerFor(
+ entryPoint: entryPoint,
memorySourceFiles: memorySourceFiles,
diagnosticHandler: diagnosticHandler,
outputProvider: outputProvider,
@@ -102,7 +104,8 @@
}
CompilerImpl compilerFor(
- {Map<String, String> memorySourceFiles: const <String, String>{},
+ {Uri entryPoint,
+ Map<String, String> memorySourceFiles: const <String, String>{},
CompilerDiagnostics diagnosticHandler,
CompilerOutput outputProvider,
List<String> options: const <String>[],
@@ -143,12 +146,14 @@
provider,
outputProvider,
diagnosticHandler,
- libraryRoot,
- packageRoot,
- options,
- {},
- packageConfig,
- packagesDiscoveryProvider);
+ new CompilerOptions.parse(
+ entryPoint: entryPoint,
+ libraryRoot: libraryRoot,
+ packageRoot: packageRoot,
+ options: options,
+ environment: {},
+ packageConfig: packageConfig,
+ packagesDiscoveryProvider: packagesDiscoveryProvider));
if (cachedCompiler != null) {
compiler.coreLibrary =
@@ -213,7 +218,6 @@
cachedCompiler.deferredLoadTask = null;
cachedCompiler.mirrorUsageAnalyzerTask = null;
cachedCompiler.dumpInfoTask = null;
- cachedCompiler.buildId = null;
}
return compiler;
}
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 11b450d..2d4862c 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -9,6 +9,7 @@
import 'dart:collection';
import 'package:compiler/compiler.dart' as api;
+import 'package:compiler/compiler_new.dart' as new_api;
import 'package:compiler/src/common/names.dart' show
Uris;
import 'package:compiler/src/constants/expressions.dart';
@@ -69,7 +70,6 @@
bool enableTypeAssertions: false,
bool enableUserAssertions: false,
bool enableMinification: false,
- int maxConcreteTypeSize: 5,
bool disableTypeInference: false,
bool analyzeAll: false,
bool analyzeOnly: false,
@@ -88,22 +88,24 @@
LibrarySourceProvider this.librariesOverride})
: sourceFiles = new Map<String, SourceFile>(),
testedPatchVersion = patchVersion,
- super(enableTypeAssertions: enableTypeAssertions,
+ super(options: new new_api.CompilerOptions(
+ entryPoint: new Uri(scheme: 'mock'),
+ libraryRoot: Uri.parse('placeholder_library_root_for_mock/'),
+ enableTypeAssertions: enableTypeAssertions,
enableUserAssertions: enableUserAssertions,
+ disableInlining: disableInlining,
enableAssertMessage: true,
enableMinification: enableMinification,
- maxConcreteTypeSize: maxConcreteTypeSize,
- disableTypeInferenceFlag: disableTypeInference,
- analyzeAllFlag: analyzeAll,
+ disableTypeInference: disableTypeInference,
+ analyzeAll: analyzeAll,
analyzeOnly: analyzeOnly,
emitJavaScript: emitJavaScript,
preserveComments: preserveComments,
trustTypeAnnotations: trustTypeAnnotations,
trustJSInteropTypeAnnotations: trustJSInteropTypeAnnotations,
diagnosticOptions:
- new DiagnosticOptions(shownPackageWarnings: const []),
+ new DiagnosticOptions(shownPackageWarnings: const [])),
outputProvider: new LegacyCompilerOutput(outputProvider)) {
- this.disableInlining = disableInlining;
deferredLoadTask = new MockDeferredLoadTask(this);
diff --git a/tests/compiler/dart2js/serialization_analysis_test.dart b/tests/compiler/dart2js/serialization_analysis_test.dart
index ffef134..e8c651d 100644
--- a/tests/compiler/dart2js/serialization_analysis_test.dart
+++ b/tests/compiler/dart2js/serialization_analysis_test.dart
@@ -8,11 +8,15 @@
import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
import 'package:compiler/src/commandline_options.dart';
-import 'package:compiler/src/elements/elements.dart';
+import 'package:compiler/src/common/names.dart';
+import 'package:compiler/src/common/resolution.dart';
import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/filenames.dart';
-import 'package:compiler/src/serialization/serialization.dart';
+import 'package:compiler/src/serialization/element_serialization.dart';
+import 'package:compiler/src/serialization/impact_serialization.dart';
import 'package:compiler/src/serialization/json_serializer.dart';
+import 'package:compiler/src/serialization/serialization.dart';
import 'package:compiler/src/serialization/task.dart';
import 'package:compiler/src/universe/world_impact.dart';
import 'memory_compiler.dart';
@@ -142,6 +146,61 @@
},
expectedWarningCount: 1,
expectedInfoCount: 1),
+
+ const Test(const {
+ 'main.dart': r'''
+import 'dart:math';
+
+class MyRandom implements Random {
+ int nextInt(int max) {
+ return max.length;
+ }
+ bool nextBool() => true;
+ double nextDouble() => 0.0;
+}
+main() {
+ new MyRandom().nextInt(0);
+}'''
+ },
+ expectedWarningCount: 1,
+ expectedInfoCount: 0),
+
+ const Test(const {
+ 'main.dart': r'''
+import 'dart:math';
+
+class MyRandom implements Random {
+ int nextInt(int max) {
+ return max.length;
+ }
+ bool nextBool() => true;
+ double nextDouble() => 0.0;
+}
+main() {
+ new MyRandom();
+}'''
+ }),
+
+ const Test(const {
+ 'main.dart': r'''
+import 'dart:math';
+
+class MyRandom implements Random {
+ int nextInt(int max) {
+ return max.length;
+ }
+ bool nextBool() => true;
+ double nextDouble() => 0.0;
+}
+main() {
+ // Invocation of `MyRandom.nextInt` is only detected knowing the actual
+ // implementation class for `List` and the world impact of its `shuffle`
+ // method.
+ [].shuffle(new MyRandom());
+}'''
+ },
+ expectedWarningCount: 1,
+ expectedInfoCount: 0),
];
main(List<String> arguments) {
@@ -175,15 +234,17 @@
}
Future analyze(String serializedData, Uri entryPoint, Test test) async {
- Deserializer deserializer = new Deserializer.fromText(
- serializedData, const JsonSerializationDecoder());
DiagnosticCollector diagnosticCollector = new DiagnosticCollector();
await runCompiler(
entryPoint: entryPoint,
memorySourceFiles: test != null ? test.sourceFiles : const {},
- options: [Flags.analyzeOnly, '--output-type=dart'],
+ options: [Flags.analyzeOnly],
diagnosticHandler: diagnosticCollector,
beforeRun: (Compiler compiler) {
+ Deserializer deserializer = new Deserializer.fromText(
+ serializedData,
+ const JsonSerializationDecoder());
+ deserializer.plugins.add(compiler.backend.serialization.deserializer);
compiler.serialization.deserializer =
new _DeserializerSystem(deserializer);
});
@@ -203,24 +264,61 @@
Future<String> serializeDartCore() async {
Compiler compiler = compilerFor(
- options: ['--analyze-all', '--output-type=dart']);
- await compiler.run(Uri.parse('dart:core'));
- return serialize(compiler.libraryLoader.libraries);
+ options: [Flags.analyzeAll]);
+ compiler.serialization.supportSerialization = true;
+ await compiler.run(Uris.dart_core);
+ return serialize(compiler);
}
-String serialize(Iterable<LibraryElement> libraries) {
+String serialize(Compiler compiler) {
Serializer serializer = new Serializer(const JsonSerializationEncoder());
- for (LibraryElement library in libraries) {
+ serializer.plugins.add(compiler.backend.serialization.serializer);
+ serializer.plugins.add(new WorldImpactSerializer(compiler.resolution));
+
+ for (LibraryElement library in compiler.libraryLoader.libraries) {
serializer.serialize(library);
}
return serializer.toText();
}
+const String WORLD_IMPACT_TAG = 'worldImpact';
+
+class WorldImpactSerializer extends SerializerPlugin {
+ final Resolution resolution;
+
+ WorldImpactSerializer(this.resolution);
+
+ @override
+ void onElement(Element element, ObjectEncoder createEncoder(String tag)) {
+ if (resolution.hasBeenResolved(element)) {
+ WorldImpact impact = resolution.getWorldImpact(element);
+ ObjectEncoder encoder = createEncoder(WORLD_IMPACT_TAG);
+ impact.apply(new ImpactSerializer(encoder));
+ }
+ }
+}
+
+class WorldImpactDeserializer extends DeserializerPlugin {
+ Map<Element, WorldImpact> impactMap = <Element, WorldImpact>{};
+
+ @override
+ void onElement(Element element, ObjectDecoder getDecoder(String tag)) {
+ ObjectDecoder decoder = getDecoder(WORLD_IMPACT_TAG);
+ if (decoder != null) {
+ impactMap[element] = ImpactDeserializer.deserializeImpact(decoder);
+ }
+ }
+}
+
class _DeserializerSystem extends DeserializerSystem {
final Deserializer _deserializer;
final List<LibraryElement> deserializedLibraries = <LibraryElement>[];
+ final WorldImpactDeserializer _worldImpactDeserializer =
+ new WorldImpactDeserializer();
- _DeserializerSystem(this._deserializer);
+ _DeserializerSystem(this._deserializer) {
+ _deserializer.plugins.add(_worldImpactDeserializer);
+ }
LibraryElement readLibrary(Uri resolvedUri) {
LibraryElement library = _deserializer.lookupLibrary(resolvedUri);
@@ -232,11 +330,16 @@
@override
WorldImpact computeWorldImpact(Element element) {
- return const WorldImpact();
+ WorldImpact impact = _worldImpactDeserializer.impactMap[element];
+ if (impact == null) {
+ print('No impact found for $element (${element.library})');
+ impact = const WorldImpact();
+ }
+ return impact;
}
@override
bool isDeserialized(Element element) {
return deserializedLibraries.contains(element.library);
}
-}
\ No newline at end of file
+}
diff --git a/tests/compiler/dart2js/serialization_test.dart b/tests/compiler/dart2js/serialization_test.dart
index c913a3c..3522c41 100644
--- a/tests/compiler/dart2js/serialization_test.dart
+++ b/tests/compiler/dart2js/serialization_test.dart
@@ -15,9 +15,9 @@
import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/elements/visitor.dart';
import 'package:compiler/src/ordered_typeset.dart';
-import 'package:compiler/src/serialization/serialization.dart';
+import 'package:compiler/src/serialization/element_serialization.dart';
import 'package:compiler/src/serialization/json_serializer.dart';
-import 'package:compiler/src/tree/tree.dart';
+import 'package:compiler/src/serialization/serialization.dart';
main(List<String> arguments) {
// Ensure that we can print out constant expressions.
@@ -342,6 +342,10 @@
const ElementIdentityEquivalence();
void visit(Element element1, Element element2) {
+ if (element1 == null && element2 == null) return;
+ element1 = element1.declaration;
+ element2 = element2.declaration;
+ if (element1 == element2) return;
check(element1, element2, 'kind', element1.kind, element2.kind);
element1.accept(this, element2);
}
@@ -454,6 +458,9 @@
const ElementPropertyEquivalence();
void visit(Element element1, Element element2) {
+ if (element1 == null && element2 == null) return;
+ element1 = element1.declaration;
+ element2 = element2.declaration;
if (element1 == element2) return;
check(element1, element2, 'kind', element1.kind, element2.kind);
element1.accept(this, element2);
@@ -472,41 +479,28 @@
element1.libraryName, element2.libraryName);
visitMembers(element1, element2);
visit(element1.entryCompilationUnit, element2.entryCompilationUnit);
+
checkElementLists(
element1, element2, 'compilationUnits',
- element1.compilationUnits.toList(),
- element2.compilationUnits.toList());
+ LibrarySerializer.getCompilationUnits(element1),
+ LibrarySerializer.getCompilationUnits(element2));
checkElementListIdentities(
- element1, element2, 'imports', element1.imports, element2.imports);
+ element1, element2, 'imports',
+ LibrarySerializer.getImports(element1),
+ LibrarySerializer.getImports(element2));
checkElementListIdentities(
element1, element2, 'exports', element1.exports, element2.exports);
- List<Element> imports1 = <Element>[];
- List<Element> imports2 = <Element>[];
- element1.forEachImport((Element import) {
- if (import.isAmbiguous) return;
- imports1.add(import);
- });
- element2.forEachImport((Element import) {
- if (import.isAmbiguous) return;
- imports2.add(import);
- });
checkElementListIdentities(
- element1, element2, 'importScope', imports1, imports2);
+ element1, element2, 'importScope',
+ LibrarySerializer.getImportedElements(element1),
+ LibrarySerializer.getImportedElements(element2));
- List<Element> exports1 = <Element>[];
- List<Element> exports2 = <Element>[];
- element1.forEachExport((Element export) {
- if (export.isAmbiguous) return;
- exports1.add(export);
- });
- element2.forEachExport((Element export) {
- if (export.isAmbiguous) return;
- exports2.add(export);
- });
checkElementListIdentities(
- element1, element2, 'exportScope', exports1, exports2);
+ element1, element2, 'exportScope',
+ LibrarySerializer.getExportedElements(element1),
+ LibrarySerializer.getExportedElements(element2));
}
@override
@@ -536,21 +530,29 @@
void visitMembers(ScopeContainerElement element1,
ScopeContainerElement element2) {
Set<String> names = new Set<String>();
- element1.forEachLocalMember((Element member) {
+ Iterable<Element> members1 = element1.isLibrary
+ ? LibrarySerializer.getMembers(element1)
+ : ClassSerializer.getMembers(element1);
+ Iterable<Element> members2 = element2.isLibrary
+ ? LibrarySerializer.getMembers(element2)
+ : ClassSerializer.getMembers(element2);
+ for (Element member in members1) {
names.add(member.name);
- });
- element2.forEachLocalMember((Element member) {
+ }
+ for (Element member in members2) {
names.add(member.name);
- });
+ }
+ element1 = element1.implementation;
+ element2 = element2.implementation;
for (String name in names) {
Element member1 = element1.localLookup(name);
Element member2 = element2.localLookup(name);
if (member1 == null) {
- print('Missing member for $member2');
+ print('Missing member for $member2 in\n ${members1.join('\n ')}');
continue;
}
if (member2 == null) {
- print('Missing member for $member1');
+ print('Missing member for $member1 in\n ${members2.join('\n ')}');
continue;
}
visit(member1, member2);
@@ -576,6 +578,16 @@
element1.typeVariables, element2.typeVariables);
check(element1, element2, 'isAbstract',
element1.isAbstract, element2.isAbstract);
+ check(element1, element2, 'isUnnamedMixinApplication',
+ element1.isUnnamedMixinApplication, element2.isUnnamedMixinApplication);
+ check(element1, element2, 'isEnumClass',
+ element1.isEnumClass, element2.isEnumClass);
+ if (element1.isEnumClass) {
+ EnumClassElement enum1 = element1;
+ EnumClassElement enum2 = element2;
+ checkElementLists(enum1, enum2, 'enumValues',
+ enum1.enumValues, enum2.enumValues);
+ }
if (!element1.isObject) {
checkTypes(element1, element2, 'supertype',
element1.supertype, element2.supertype);
diff --git a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
index cb78cd4..9bc1ac8 100644
--- a/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/sourcemap_helper.dart
@@ -272,8 +272,6 @@
}
}
-const String DISABLE_INLINING = '--disable-inlining';
-
/// Processor that computes [SourceMapInfo] for the JavaScript compiled for a
/// given Dart file.
class SourceMapProcessor {
@@ -315,15 +313,14 @@
if (options.contains(Flags.useNewSourceInfo)) {
if (verbose) print('Using the new source information system.');
}
+ if (options.contains(Flags.disableInlining)) {
+ if (verbose) print('Inlining disabled');
+ }
api.CompilerImpl compiler = await compilerFor(
outputProvider: outputProvider,
// TODO(johnniwinther): Use [verbose] to avoid showing diagnostics.
options: ['--out=$targetUri', '--source-map=$sourceMapFileUri']
..addAll(options));
- if (options.contains(DISABLE_INLINING)) {
- if (verbose) print('Inlining disabled');
- compiler.disableInlining = true;
- }
JavaScriptBackend backend = compiler.backend;
var handler = compiler.handler;
diff --git a/tests/compiler/dart2js/type_test_helper.dart b/tests/compiler/dart2js/type_test_helper.dart
index fc04a58..1e20ba7 100644
--- a/tests/compiler/dart2js/type_test_helper.dart
+++ b/tests/compiler/dart2js/type_test_helper.dart
@@ -62,6 +62,7 @@
collector = new memory.DiagnosticCollector();
uri = Uri.parse('memory:main.dart');
compiler = memory.compilerFor(
+ entryPoint: uri,
memorySourceFiles: {'main.dart': source},
diagnosticHandler: collector,
options: stopAfterTypeInference
diff --git a/tests/html/html.status b/tests/html/html.status
index 5b30a0a..c7df0fe 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -45,7 +45,6 @@
[ $compiler == dart2js && $browser ]
custom/created_callback_test: Fail # Support for created constructor. Issue 14835
fontface_loaded_test: Fail # Support for promises.
-js_typed_interop_side_cast_exp_test: RuntimeError # Issue 25937
[ $compiler == dart2js && ($runtime == safari || $runtime == safarimobilesim || $runtime == ff || $ie) ]
custom/entered_left_view_test/viewless_document: Fail # Polyfill does not handle this
diff --git a/tests/isolate/scenarios/bad_resolve_package/.packages b/tests/isolate/scenarios/bad_resolve_package/.packages
new file mode 100644
index 0000000..5acc702
--- /dev/null
+++ b/tests/isolate/scenarios/bad_resolve_package/.packages
@@ -0,0 +1 @@
+# Intentionally left blank to ensure no packages are resolved.
diff --git a/tests/isolate/scenarios/bad_resolve_package/bad_resolve_package_test.dart b/tests/isolate/scenarios/bad_resolve_package/bad_resolve_package_test.dart
new file mode 100644
index 0000000..c8017e1
--- /dev/null
+++ b/tests/isolate/scenarios/bad_resolve_package/bad_resolve_package_test.dart
@@ -0,0 +1,47 @@
+// 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.
+
+// PackageRoot=none
+
+import 'dart:io';
+import 'dart:isolate';
+
+main([args, port]) async {
+ if (port != null) {
+ testBadResolvePackage(port);
+ return;
+ }
+ var p = new RawReceivePort();
+ Isolate.spawnUri(Platform.script, [], p.sendPort);
+ p.handler = (msg) {
+ p.close();
+ if (msg is! List) {
+ print(msg.runtimeType);
+ throw "Failure return from spawned isolate:\n\n$msg";
+ }
+ // Expecting a null resolution for inexistent package mapping.
+ if (msg[0] != null) {
+ throw "Bad package config in child isolate: ${msg[0]}\n"
+ "Expected: 'Foo'";
+ }
+ print("SUCCESS");
+ };
+}
+
+testBadResolvePackage(port) async {
+ try {
+ var packageRootStr = Platform.packageRoot;
+ var packageConfigStr = Platform.packageConfig;
+ var packageConfig = await Isolate.packageConfig;
+ var badPackageUri = Uri.parse("package:asdf/qwerty.dart");
+ var resolvedPkg = await Isolate.resolvePackageUri(badPackageUri);
+ print("Spawned isolate's package root flag: $packageRootStr");
+ print("Spawned isolate's package config flag: $packageConfigStr");
+ print("Spawned isolate's loaded package config: $packageConfig");
+ print("Spawned isolate's resolved package path: $resolvedPkg");
+ port.send([resolvedPkg]);
+ } catch (e, s) {
+ port.send("$e\n$s\n");
+ }
+}
diff --git a/tests/isolate/scenarios/short_package/.packages b/tests/isolate/scenarios/short_package/.packages
new file mode 100644
index 0000000..324934c
--- /dev/null
+++ b/tests/isolate/scenarios/short_package/.packages
@@ -0,0 +1 @@
+flu:flu_package/
diff --git a/tests/isolate/scenarios/short_package/flu_package/flu.dart b/tests/isolate/scenarios/short_package/flu_package/flu.dart
new file mode 100644
index 0000000..5e33f7c
--- /dev/null
+++ b/tests/isolate/scenarios/short_package/flu_package/flu.dart
@@ -0,0 +1,3 @@
+class Flu {
+ static var value = "Flu";
+}
diff --git a/tests/isolate/scenarios/short_package/flu_package/flu.text b/tests/isolate/scenarios/short_package/flu_package/flu.text
new file mode 100644
index 0000000..d9d3a9a
--- /dev/null
+++ b/tests/isolate/scenarios/short_package/flu_package/flu.text
@@ -0,0 +1 @@
+Bar
\ No newline at end of file
diff --git a/tests/isolate/scenarios/short_package/short_package_test.dart b/tests/isolate/scenarios/short_package/short_package_test.dart
new file mode 100644
index 0000000..bfbe61c
--- /dev/null
+++ b/tests/isolate/scenarios/short_package/short_package_test.dart
@@ -0,0 +1,37 @@
+// 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.
+
+// PackageRoot=none
+
+import 'dart:io';
+import 'dart:isolate';
+
+import "package:flu";
+
+var PACKAGE_FLU = "package:flu";
+var FLU_TEXT = "flu.text";
+
+testShortResolution(package_uri) async {
+ var fluPackage = await Isolate.resolvePackageUri(Uri.parse(package_uri));
+ print("Resolved $package_uri to $fluPackage");
+ var fluText = fluPackage.resolve(FLU_TEXT);
+ print("Resolved $FLU_TEXT from $package_uri to $fluText");
+ var fluFile = new File.fromUri(fluText);
+ var fluString = await fluFile.readAsString();
+ if (fluString != "Bar") {
+ throw "Contents of $FLU_TEXT not matching.\n"
+ "Got: $fluString\n"
+ "Expected: Bar";
+ }
+}
+
+main([args, port]) async {
+ if (Flu.value != "Flu") {
+ throw "Import of wrong Flu package.";
+ }
+ await testShortResolution(PACKAGE_FLU);
+ await testShortResolution(PACKAGE_FLU + "/");
+ await testShortResolution(PACKAGE_FLU + "/abc.def");
+ print("SUCCESS");
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index ff38b09..261ea59 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -157,11 +157,23 @@
deferred_inheritance_constraints_test: Skip
deferred_load_constants_test: Skip # multitest gets confused
tearoff_basic_test: RuntimeError, Crash # Conflicting flag.
-deferred_global_test: RuntimeError # Issue 25845
vm/type_vm_test: RuntimeError # Expects line and column numbers
vm/type_cast_vm_test: RuntimeError # Line number mismatch.
+issue13474_test: SkipByDesign # Requires checked mode.
+assertion_test: SkipByDesign # Requires checked mode.
+named_parameters_type_test/01: SkipByDesign # Requires checked mode.
+named_parameters_type_test/02: SkipByDesign # Requires checked mode.
+named_parameters_type_test/03: SkipByDesign # Requires checked mode.
+type_checks_in_factory_method_test: SkipByDesign # Requires checked mode.
+positional_parameters_type_test/01: SkipByDesign # Requires checked mode.
+positional_parameters_type_test/02: SkipByDesign # Requires checked mode.
+list_literal4_test: SkipByDesign # Requires checked mode.
+generic_test: SkipByDesign # Requires checked mode.
+map_literal4_test: SkipByDesign # Requires checked mode.
+
+
[ $runtime == dart_precompiled ]
deferred_global_test: RuntimeError # Tries to produce a stack trace.
ct_const2_test: Pass, Crash # Incompatible flag --compile_all
diff --git a/tests/lib/convert/json_test.dart b/tests/lib/convert/json_test.dart
index cfed8d9..ef7b077 100644
--- a/tests/lib/convert/json_test.dart
+++ b/tests/lib/convert/json_test.dart
@@ -1,6 +1,8 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+// Disable background compilation so that the Issue 24908 can be reproduced.
+// VMOptions=--no-background-compilation
library json_test;
diff --git a/tests/standalone/io/certificates/client1_key.p12 b/tests/standalone/io/certificates/client1_key.p12
index d9cf05b..5d11e73 100644
--- a/tests/standalone/io/certificates/client1_key.p12
+++ b/tests/standalone/io/certificates/client1_key.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/client1_key_malformed.pem b/tests/standalone/io/certificates/client1_key_malformed.pem
index 33a79bf..8c1f7d8 100644
--- a/tests/standalone/io/certificates/client1_key_malformed.pem
+++ b/tests/standalone/io/certificates/client1_key_malformed.pem
@@ -1,4 +1,3 @@
------BEGIN ENCRYPTED PRIVATE KEY-----
MIIE4jAcBgoqhkiG9w0BDAEBMA4ECF4ZB27y60SWAgIIAASCBMCEL3ZCzfC0q+m+
B8gM9jQe1JFRD5reAuwK6+3speBS4KE+wjbcyQq09/5UoQu3Dci1WG1nKLB1u0Bk
w9NuRahWCpvVLzz/GQ6Psesixq3V69zD3N6iMl/XQKymQBwGK51xIkeJO+6Skh2d
diff --git a/tests/standalone/io/certificates/client_authority_malformed.pem b/tests/standalone/io/certificates/client_authority_malformed.pem
index d206dce3..d0aeff4 100644
--- a/tests/standalone/io/certificates/client_authority_malformed.pem
+++ b/tests/standalone/io/certificates/client_authority_malformed.pem
@@ -1,4 +1,3 @@
------BEGIN CERTIFICATE-----
MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAaMRgw
FgYDVQQDEw9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
diff --git a/tests/standalone/io/certificates/server_chain.p12 b/tests/standalone/io/certificates/server_chain.p12
index 1e8c66d..79e412d 100644
--- a/tests/standalone/io/certificates/server_chain.p12
+++ b/tests/standalone/io/certificates/server_chain.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/server_chain_malformed1.pem b/tests/standalone/io/certificates/server_chain_malformed1.pem
index cbbeb55..cb623fd 100644
--- a/tests/standalone/io/certificates/server_chain_malformed1.pem
+++ b/tests/standalone/io/certificates/server_chain_malformed1.pem
@@ -1,4 +1,3 @@
------BEGIN CERTIFICATE-----
MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
diff --git a/tests/standalone/io/certificates/server_chain_malformed2.pem b/tests/standalone/io/certificates/server_chain_malformed2.pem
index 2c99e78..978c523 100644
--- a/tests/standalone/io/certificates/server_chain_malformed2.pem
+++ b/tests/standalone/io/certificates/server_chain_malformed2.pem
@@ -1,4 +1,3 @@
------BEGIN CERTIFICATE-----
MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
diff --git a/tests/standalone/io/certificates/server_key.p12 b/tests/standalone/io/certificates/server_key.p12
index 2434fb7..204d42d 100644
--- a/tests/standalone/io/certificates/server_key.p12
+++ b/tests/standalone/io/certificates/server_key.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/trusted_certs.p12 b/tests/standalone/io/certificates/trusted_certs.p12
index 167f2e8..76c76ec 100644
--- a/tests/standalone/io/certificates/trusted_certs.p12
+++ b/tests/standalone/io/certificates/trusted_certs.p12
Binary files differ
diff --git a/tests/standalone/io/certificates/trusted_certs_malformed.pem b/tests/standalone/io/certificates/trusted_certs_malformed.pem
index ea26cc7..f96698e 100644
--- a/tests/standalone/io/certificates/trusted_certs_malformed.pem
+++ b/tests/standalone/io/certificates/trusted_certs_malformed.pem
@@ -1,4 +1,3 @@
------BEGIN CERTIFICATE-----
MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNFoXDTI1MTAyNDEwMjYzNFowGDEWMBQG
A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
@@ -6,3 +5,4 @@
FfaHczXQTwnTCaYA4u4uSDvSOsFFEfxEwYORsdKmQEM8nGpVX2NVvKsMcGIhh8kh
ZwJfkMIOcAxmGIHGdMhF8VghonJ8uGiuqktxdfpARq0g3fqIjDHsF9/LpfshUfk9
wsRyTF0yr90U/dsfnE+u8l7GvVl8j2Zegp0sagAGtLaNv7tP17AibqEGg2yDBrBN
+a
diff --git a/tests/standalone/io/https_bad_certificate_test.dart b/tests/standalone/io/https_bad_certificate_test.dart
index 90c630f..7dc5aa2 100644
--- a/tests/standalone/io/https_bad_certificate_test.dart
+++ b/tests/standalone/io/https_bad_certificate_test.dart
@@ -57,8 +57,8 @@
result) async {
HttpClient client = new HttpClient(context: context);
client.badCertificateCallback = (X509Certificate certificate, host, port) {
- Expect.equals('/CN=rootauthority', certificate.subject);
- Expect.equals('/CN=rootauthority', certificate.issuer);
+ Expect.isTrue(certificate.subject.contains('rootauthority'));
+ Expect.isTrue(certificate.issuer.contains('rootauthority'));
// Throw exception if one is requested.
if (callbackReturns == 'exception') throw new CustomException();
return callbackReturns;
diff --git a/tests/standalone/io/secure_bad_certificate_test.dart b/tests/standalone/io/secure_bad_certificate_test.dart
index 610bcdb..7b28284 100644
--- a/tests/standalone/io/secure_bad_certificate_test.dart
+++ b/tests/standalone/io/secure_bad_certificate_test.dart
@@ -55,8 +55,8 @@
callbackReturns,
result) async {
badCertificateCallback(X509Certificate certificate) {
- Expect.equals('/CN=rootauthority', certificate.subject);
- Expect.equals('/CN=rootauthority', certificate.issuer);
+ Expect.isTrue(certificate.subject.contains('rootauthority'));
+ Expect.isTrue(certificate.issuer.contains('rootauthority'));
// Throw exception if one is requested.
if (callbackReturns == 'exception') throw new CustomException();
return callbackReturns;
diff --git a/tests/standalone/io/secure_builtin_roots_test.dart b/tests/standalone/io/secure_builtin_roots_test.dart
index 6cb85d6..ce89d11 100644
--- a/tests/standalone/io/secure_builtin_roots_test.dart
+++ b/tests/standalone/io/secure_builtin_roots_test.dart
@@ -13,7 +13,7 @@
// We need to use an external server that is backed by a
// built-in root certificate authority.
try {
- // First, check if the lookup works.
+ // First, check if the lookup works.
await InternetAddress.lookup('www.google.com');
var request = await client.getUrl(Uri.parse('https://www.google.com'));
request.followRedirects = false;
diff --git a/tests/standalone/io/secure_server_client_certificate_test.dart b/tests/standalone/io/secure_server_client_certificate_test.dart
index 6891037..4c16ab0 100644
--- a/tests/standalone/io/secure_server_client_certificate_test.dart
+++ b/tests/standalone/io/secure_server_client_certificate_test.dart
@@ -66,15 +66,15 @@
X509Certificate clientCertificate = serverEnd.peerCertificate;
if (sendCert) {
Expect.isNotNull(clientCertificate);
- Expect.equals("/CN=user1", clientCertificate.subject);
- Expect.equals("/CN=clientauthority", clientCertificate.issuer);
+ Expect.isTrue(clientCertificate.subject.contains("user1"));
+ Expect.isTrue(clientCertificate.issuer.contains("clientauthority"));
} else {
Expect.isNull(clientCertificate);
}
X509Certificate serverCertificate = clientEnd.peerCertificate;
Expect.isNotNull(serverCertificate);
- Expect.equals("/CN=localhost", serverCertificate.subject);
- Expect.equals("/CN=intermediateauthority", serverCertificate.issuer);
+ Expect.isTrue(serverCertificate.subject.contains("localhost"));
+ Expect.isTrue(serverCertificate.issuer.contains("intermediateauthority"));
clientEnd.close();
serverEnd.close();
}
diff --git a/tests/standalone/io/secure_socket_alpn_test.dart b/tests/standalone/io/secure_socket_alpn_test.dart
index 8599991..8bd4e27 100644
--- a/tests/standalone/io/secure_socket_alpn_test.dart
+++ b/tests/standalone/io/secure_socket_alpn_test.dart
@@ -113,6 +113,9 @@
}
main() {
+ if (!SecurityContext.alpnSupported) {
+ return 0;
+ }
final longname256 = 'p' * 256;
final String longname255 = 'p' * 255;
final String strangelongname255 = 'ø' + 'p' * 253;
diff --git a/tests/standalone/io/secure_socket_test.dart b/tests/standalone/io/secure_socket_test.dart
index 1566b5a..bf128df 100644
--- a/tests/standalone/io/secure_socket_test.dart
+++ b/tests/standalone/io/secure_socket_test.dart
@@ -50,6 +50,7 @@
Future test(String certType, String password) {
List<int> body = <int>[];
+ Completer completer = new Completer();
startServer(certType, password).then((server) {
SecureSocket.connect(
"localhost", server.port, context: clientContext(certType, password))
@@ -65,14 +66,17 @@
Expect.equals(72, body[0]);
Expect.equals(9, body[body.length - 1]);
server.close();
+ completer.complete(null);
},
onError: (e, trace) {
String msg = "Unexpected error $e";
if (trace != null) msg += "\nStackTrace: $trace";
Expect.fail(msg);
+ completer.complete(null);
});
});
});
+ return completer.future;
}
main() async {
diff --git a/tests/standalone/io/security_context_argument_test.dart b/tests/standalone/io/security_context_argument_test.dart
index 6e9ddcf..fc6ff1c 100644
--- a/tests/standalone/io/security_context_argument_test.dart
+++ b/tests/standalone/io/security_context_argument_test.dart
@@ -116,9 +116,6 @@
Expect.throws(() => c.setClientAuthorities(
localFile('certificates/client_authority_malformed.pem')),
tlsException);
-
- c.usePrivateKey(
- localFile('certificates/server_key.pem'), password: "dartdart");
}
void main() {
diff --git a/tests/standalone/regress_26031_test.dart b/tests/standalone/regress_26031_test.dart
new file mode 100644
index 0000000..44765c2b
--- /dev/null
+++ b/tests/standalone/regress_26031_test.dart
@@ -0,0 +1,20 @@
+// 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:io';
+import 'dart:isolate';
+
+import "package:expect/expect.dart";
+
+void checkResolvedExecutable(String re) {
+ Expect.equals(Platform.resolvedExecutable, re);
+}
+
+main() {
+ var exitPort = new ReceivePort();
+ Isolate.spawn(checkResolvedExecutable,
+ Platform.resolvedExecutable,
+ onExit: exitPort.sendPort);
+ exitPort.listen((_) => exitPort.close());
+}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index fecad33..7cd6257 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -44,6 +44,8 @@
# This is expected as MacOS by default runs with a very low number
# of allowed open files ('ulimit -n' says something like 256).
io/socket_many_connections_test: Skip
+# Re-enable once the bots have been updated. Issue #26057
+io/secure_server_client_certificate_test: Skip
[ $runtime == vm && $system == linux ]
# These tests have started timing out and issue 25649 has been filed to
@@ -69,6 +71,7 @@
verbose_gc_to_bmu_test: Skip
precompilation_test: Skip # Standalone only test.
precompilation_dart2js_test: Skip # Standalone only test.
+regress_26031_test: SkipByDesign # Standalone only test
[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
issue14236_test: Skip # Analyzer can't handle Script snapshots.
@@ -270,6 +273,8 @@
io/test_extension_test: Skip # Platform.executable
io/regress_7679_test: Skip # Platform.executable
io/process_*: Skip # Most use Platform.executable
+assert_test: SkipByDesign # Requires checked mode.
+no_assert_test: SkipByDesign # Requires checked mode.
# Code coverage is not supported in product mode.
[ $mode == product ]
diff --git a/tools/VERSION b/tools/VERSION
index 4c33897..4d89b8c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 1
MINOR 16
PATCH 0
-PRERELEASE 1
+PRERELEASE 2
PRERELEASE_PATCH 0
diff --git a/tools/create_sdk.py b/tools/create_sdk.py
index 0d72c9d..65f585e 100755
--- a/tools/create_sdk.py
+++ b/tools/create_sdk.py
@@ -19,6 +19,7 @@
# ......dartfmt
# ......dart2js
# ......dartanalyzer
+# ......dartdevc
# ......pub
# ......snapshots/
# ........analysis_server.dart.snapshot
@@ -26,6 +27,7 @@
# ........dartanalyzer.dart.snapshot
# ........dartdoc.dart.snapshot
# ........dartfmt.dart.snapshot
+# ........dartdevc.dart.snapshot
# ........pub.dart.snapshot
# ........utils_wrapper.dart.snapshot
#.........resources/
@@ -129,14 +131,14 @@
def CopyDartScripts(home, sdk_root):
for executable in ['dart2js_sdk', 'dartanalyzer_sdk', 'dartfmt_sdk',
- 'pub_sdk', 'dartdoc']:
+ 'pub_sdk', 'dartdoc', 'dartdevc_sdk']:
CopyShellScript(os.path.join(home, 'sdk', 'bin', executable),
os.path.join(sdk_root, 'bin'))
def CopySnapshots(snapshots, sdk_root):
for snapshot in ['analysis_server', 'dart2js', 'dartanalyzer', 'dartfmt',
- 'utils_wrapper', 'pub', 'dartdoc']:
+ 'utils_wrapper', 'pub', 'dartdoc', 'dartdevc']:
snapshot += '.dart.snapshot'
copyfile(join(snapshots, snapshot),
join(sdk_root, 'bin', 'snapshots', snapshot))
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 0af7797..7187fd1 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -8,8 +8,8 @@
# Now we need to override some settings and add some new ones.
vars.update({
- "dartium_chromium_commit": "18e2b11bf18e8db4dd3e0f77991a1dc6b87ce07b",
- "dartium_webkit_commit": "28b9a6c03797eaecf6c92677cba747eb9df0787c",
+ "dartium_chromium_commit": "b16942297fc65fd478c6f46afd1c3aaecde77009",
+ "dartium_webkit_commit": "bf6d7afefd0ed68cae4a595a8fb8eea089303326",
"chromium_base_revision": "338390",
# We use mirrors of all github repos to guarantee reproducibility and
diff --git a/tools/dom/scripts/dartmetadata.py b/tools/dom/scripts/dartmetadata.py
index 9beaef9..37877f1 100644
--- a/tools/dom/scripts/dartmetadata.py
+++ b/tools/dom/scripts/dartmetadata.py
@@ -340,10 +340,12 @@
],
'VTTCue.line': [
+ "@Creates('Null')",
"@Returns('num|String')",
],
'VTTCue.position': [
+ "@Creates('Null')",
"@Returns('num|String')",
],
diff --git a/tools/gyp/xcode.gypi b/tools/gyp/xcode.gypi
index 1c0faff..1799baf 100644
--- a/tools/gyp/xcode.gypi
+++ b/tools/gyp/xcode.gypi
@@ -18,8 +18,8 @@
# Chrome normally builds with the Mac OS X 10.5 SDK and sets the
# deployment target to 10.5. Other projects, such as O3D, may override
# these defaults.
- 'mac_sdk%': '<!(python <(DEPTH)/tools/gyp/find_mac_sdk.py 10.6)',
- 'mac_deployment_target%': '10.6',
+ 'mac_sdk%': '<!(python <(DEPTH)/tools/gyp/find_mac_sdk.py 10.8)',
+ 'mac_deployment_target%': '10.8',
},
'xcode_settings': {
# DON'T ADD ANYTHING NEW TO THIS BLOCK UNLESS YOU REALLY REALLY NEED IT!
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index ed9f2c0..5c8d41d 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -517,7 +517,7 @@
CommandBuilder commandBuilder,
List arguments,
Map<String, String> environmentOverrides) {
- var exec = "$buildDir/dart_no_snapshot";
+ var exec = "$buildDir/dart_bootstrap";
var args = new List();
args.add("--full-snapshot-after-run=$outputName");
args.addAll(arguments);
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index 2151a6d..a4abf47 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -793,14 +793,11 @@
}
int get timeout {
- return configuration['timeout'] * SLOW_TIMEOUT_MULTIPLIER;
-/*
if (expectedOutcomes.contains(Expectation.SLOW)) {
return configuration['timeout'] * SLOW_TIMEOUT_MULTIPLIER;
} else {
return configuration['timeout'];
}
-*/
}
String get configurationString {
diff --git a/utils/dartdevc/dartdevc.gyp b/utils/dartdevc/dartdevc.gyp
new file mode 100644
index 0000000..60e3f65
--- /dev/null
+++ b/utils/dartdevc/dartdevc.gyp
@@ -0,0 +1,37 @@
+# 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.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'dartdevc',
+ 'type': 'none',
+ 'dependencies': [
+ '../../runtime/dart-runtime.gyp:dart',
+ '../../pkg/pkg.gyp:pkg_packages',
+ ],
+ 'actions': [
+ {
+ 'action_name': 'generate_dartdevc_snapshot',
+ 'inputs': [
+ '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+ '../../sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart',
+ '<!@(["python", "../../tools/list_files.py", "\\.dart$", "../../third_party/pkg/dev_compiler/bin"])',
+ '<(SHARED_INTERMEDIATE_DIR)/packages.stamp',
+ '<(SHARED_INTERMEDIATE_DIR)/pkg_files.stamp',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/dartdevc.dart.snapshot',
+ ],
+ 'action': [
+ '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)dart<(EXECUTABLE_SUFFIX)',
+ '--snapshot=<(SHARED_INTERMEDIATE_DIR)/dartdevc.dart.snapshot',
+ '--package-root=<(PRODUCT_DIR)/packages/',
+ '../../third_party/pkg/dev_compiler/bin/dartdevc.dart'
+ ],
+ },
+ ],
+ },
+ ],
+}