Version 1.0.2.0
svn merge -r 30576:30767 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@30779 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/dart.gyp b/dart.gyp
index 9bfc1d3..0b4e11e 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -15,7 +15,6 @@
'packages',
'runtime',
'samples',
- 'upload_sdk',
],
},
{
@@ -41,8 +40,6 @@
],
},
{
- # Build the SDK. This target is separate from upload_sdk as the
- # editor needs to build the SDK without uploading it.
'target_name': 'create_sdk',
'type': 'none',
'dependencies': [
@@ -79,35 +76,6 @@
],
},
{
- # Upload the SDK. This target is separate from create_sdk as the
- # editor needs to build the SDK without uploading it.
- 'target_name': 'upload_sdk',
- 'type': 'none',
- 'dependencies': [
- 'create_sdk',
- ],
- 'inputs': [
- '<(PRODUCT_DIR)/dart-sdk/README',
- ],
- 'actions': [
- {
- 'action_name': 'upload_sdk_py',
- 'inputs': [
- '<(PRODUCT_DIR)/dart-sdk/README',
- 'tools/upload_sdk.py',
- ],
- 'outputs': [
- '<(PRODUCT_DIR)/dart-sdk/upload.stamp',
- ],
- 'action': [
- 'python',
- 'tools/upload_sdk.py',
- '<(PRODUCT_DIR)/dart-sdk'
- ],
- },
- ],
- },
- {
'target_name': 'dart2js',
'type': 'none',
'dependencies': [
diff --git a/pkg/analyzer/bin/formatter.dart b/pkg/analyzer/bin/formatter.dart
index 5693e9c..b49aff3 100755
--- a/pkg/analyzer/bin/formatter.dart
+++ b/pkg/analyzer/bin/formatter.dart
@@ -20,6 +20,7 @@
var formatterSettings;
+CodeKind kind;
bool machineFormat;
bool overwriteFileContents;
Selection selection;
@@ -36,13 +37,14 @@
_readOptions(options);
if (options.rest.isEmpty) {
- _formatStdin(options);
+ _formatStdin(kind);
} else {
_formatPaths(options.rest);
}
}
_readOptions(options) {
+ kind = _parseKind(options['kind']);
machineFormat = options['machine'];
overwriteFileContents = options['write'];
selection = _parseSelection(options['selection']);
@@ -50,6 +52,15 @@
new FormatterOptions(codeTransforms: options['transform']);
}
+CodeKind _parseKind(kindOption) {
+ switch(kindOption) {
+ case 'stmt' :
+ return CodeKind.STATEMENT;
+ default:
+ return CodeKind.COMPILATION_UNIT;
+ }
+}
+
Selection _parseSelection(selectionOption) {
if (selectionOption != null) {
var units = selectionOption.split(',');
@@ -93,7 +104,7 @@
try {
var buffer = new StringBuffer();
var rawSource = file.readAsStringSync();
- var formatted = _formatCU(rawSource);
+ var formatted = _format(rawSource, CodeKind.COMPILATION_UNIT);
if (overwriteFileContents) {
file.writeAsStringSync(formatted);
} else {
@@ -107,12 +118,12 @@
_isDartFile(file) => dartFileRegExp.hasMatch(path.basename(file.path));
-_formatStdin(options) {
+_formatStdin(kind) {
var input = new StringBuffer();
stdin.transform(new Utf8Decoder())
.listen((data) => input.write(data),
onError: (error) => _log('Error reading from stdin'),
- onDone: () => print(_formatCU(input.toString())));
+ onDone: () => print(_format(input.toString(), kind)));
}
/// Initialize the arg parser instance.
@@ -122,6 +133,9 @@
parser.addFlag('write', abbr: 'w', negatable: false,
help: 'Write reformatted sources to files (overwriting contents). '
'Do not print reformatted sources to standard output.');
+ parser.addOption('kind', abbr: 'k', defaultsTo: 'cu',
+ help: 'Specify source snippet kind ("stmt" or "cu")'
+ ' --- [PROVISIONAL API].');
parser.addFlag('machine', abbr: 'm', negatable: false,
help: 'Produce output in a format suitable for parsing.');
parser.addOption('selection', abbr: 's',
@@ -153,10 +167,10 @@
_log(buffer.toString());
}
-/// Format the given [src] as a compilation unit.
-String _formatCU(src) {
+/// Format this [src], treating it as the given snippet [kind].
+String _format(src, kind) {
var formatResult = new CodeFormatter(formatterSettings).format(
- CodeKind.COMPILATION_UNIT, src, selection: selection);
+ kind, src, selection: selection);
if (machineFormat) {
if (formatResult.selection == null) {
formatResult.selection = defaultSelection;
diff --git a/pkg/args/lib/args.dart b/pkg/args/lib/args.dart
index 7f524df..a76e726 100644
--- a/pkg/args/lib/args.dart
+++ b/pkg/args/lib/args.dart
@@ -321,9 +321,9 @@
* * There is already an option using abbreviation [abbr].
*/
void addFlag(String name, {String abbr, String help, bool defaultsTo: false,
- bool negatable: true, void callback(bool value)}) {
+ bool negatable: true, void callback(bool value), bool hide: false}) {
_addOption(name, abbr, help, null, null, defaultsTo, callback,
- isFlag: true, negatable: negatable);
+ isFlag: true, negatable: negatable, hide: hide);
}
/**
diff --git a/pkg/args/pubspec.yaml b/pkg/args/pubspec.yaml
index 0ff36a8..06e201f 100644
--- a/pkg/args/pubspec.yaml
+++ b/pkg/args/pubspec.yaml
@@ -1,5 +1,5 @@
name: args
-version: 0.9.0
+version: 0.10.0
author: "Dart Team <misc@dartlang.org>"
homepage: http://www.dartlang.org
documentation: http://api.dartlang.org/docs/pkg/args
@@ -12,4 +12,4 @@
dev_dependencies:
unittest: ">=0.9.0 <0.10.0"
environment:
- sdk: ">=0.8.10+6 <2.0.0"
+ sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/args/test/args_test.dart b/pkg/args/test/args_test.dart
index cf31cc2..075a3e8 100644
--- a/pkg/args/test/args_test.dart
+++ b/pkg/args/test/args_test.dart
@@ -6,8 +6,9 @@
import 'package:unittest/unittest.dart';
import 'package:args/args.dart';
+import 'utils.dart';
-main() {
+void main() {
group('ArgParser.addFlag()', () {
test('throws ArgumentError if the flag already exists', () {
var parser = new ArgParser();
@@ -182,45 +183,42 @@
});
});
- group('ArgResults.options', () {
- test('returns the provided options', () {
- var parser = new ArgParser();
- parser.addFlag('woof');
- parser.addOption('meow');
- var args = parser.parse(['--woof', '--meow', 'kitty']);
- expect(args.options, hasLength(2));
- expect(args.options.any((o) => o == 'woof'), isTrue);
- expect(args.options.any((o) => o == 'meow'), isTrue);
+ group('ArgResults', () {
+ group('options', () {
+ test('returns the provided options', () {
+ var parser = new ArgParser();
+ parser.addFlag('woof');
+ parser.addOption('meow');
+ var args = parser.parse(['--woof', '--meow', 'kitty']);
+ expect(args.options, hasLength(2));
+ expect(args.options, contains('woof'));
+ expect(args.options, contains('meow'));
+ });
+
+ test('includes defaulted options', () {
+ var parser = new ArgParser();
+ parser.addFlag('woof', defaultsTo: false);
+ parser.addOption('meow', defaultsTo: 'kitty');
+ var args = parser.parse([]);
+ expect(args.options, hasLength(2));
+ expect(args.options, contains('woof'));
+ expect(args.options, contains('meow'));
+ });
});
- test('includes defaulted options', () {
- var parser = new ArgParser();
- parser.addFlag('woof', defaultsTo: false);
- parser.addOption('meow', defaultsTo: 'kitty');
- var args = parser.parse([]);
- expect(args.options, hasLength(2));
- expect(args.options.any((o) => o == 'woof'), isTrue);
- expect(args.options.any((o) => o == 'meow'), isTrue);
- });
- });
-
- group('ArgResults[]', () {
- test('throws if the name is not an option', () {
+ test('[] throws if the name is not an option', () {
var parser = new ArgParser();
var results = parser.parse([]);
throwsIllegalArg(() => results['unknown']);
});
+
+ test('rest cannot be modified', () {
+ var results = new ArgResults({}, '', null, []);
+ expect(() => results.rest.add('oops'), throwsUnsupportedError);
+ });
});
}
-throwsIllegalArg(function, {String reason: null}) {
- expect(function, throwsArgumentError, reason: reason);
-}
-
-throwsFormat(ArgParser parser, List<String> args) {
- expect(() => parser.parse(args), throwsFormatException);
-}
-
const _INVALID_OPTIONS = const [
' ', '', '-', '--', '--foo',
' with space',
diff --git a/pkg/args/test/command_test.dart b/pkg/args/test/command_test.dart
index 6115ab1..1380e16 100644
--- a/pkg/args/test/command_test.dart
+++ b/pkg/args/test/command_test.dart
@@ -6,8 +6,9 @@
import 'package:unittest/unittest.dart';
import 'package:args/args.dart';
+import 'utils.dart';
-main() {
+void main() {
group('ArgParser.addCommand()', () {
test('creates a new ArgParser if none is given', () {
var parser = new ArgParser();
@@ -204,11 +205,3 @@
});
});
}
-
-throwsIllegalArg(function) {
- expect(function, throwsArgumentError);
-}
-
-throwsFormat(ArgParser parser, List<String> args) {
- expect(() => parser.parse(args), throwsFormatException);
-}
diff --git a/pkg/args/test/parse_all_test.dart b/pkg/args/test/parse_all_test.dart
index 8498ae6..d404c2f 100644
--- a/pkg/args/test/parse_all_test.dart
+++ b/pkg/args/test/parse_all_test.dart
@@ -7,7 +7,7 @@
import 'package:unittest/unittest.dart';
import 'package:args/args.dart';
-main() {
+void main() {
group('ArgParser.parse(allowTrailingOptions: true) '
'starting with a non-option', () {
test('followed by flag', () {
@@ -57,7 +57,8 @@
});
});
}
-expectThrows(ArgParser parser, List<String> args) =>
+
+void expectThrows(ArgParser parser, List<String> args) =>
expect(() => parser.parse(args, allowTrailingOptions: true),
throwsFormatException,
reason: "with allowTrailingOptions: true");
diff --git a/pkg/args/test/parse_test.dart b/pkg/args/test/parse_test.dart
index 715c226..659c08e 100644
--- a/pkg/args/test/parse_test.dart
+++ b/pkg/args/test/parse_test.dart
@@ -6,8 +6,9 @@
import 'package:unittest/unittest.dart';
import 'package:args/args.dart';
+import 'utils.dart';
-main() {
+void main() {
group('ArgParser.parse()', () {
test('does not destructively modify the argument list', () {
var parser = new ArgParser();
@@ -421,11 +422,3 @@
});
});
}
-
-throwsIllegalArg(function) {
- expect(function, throwsArgumentError);
-}
-
-throwsFormat(ArgParser parser, List<String> args) {
- expect(() => parser.parse(args), throwsFormatException);
-}
diff --git a/pkg/args/test/usage_test.dart b/pkg/args/test/usage_test.dart
index 27b0389..ddd223c 100644
--- a/pkg/args/test/usage_test.dart
+++ b/pkg/args/test/usage_test.dart
@@ -7,7 +7,7 @@
import 'package:unittest/unittest.dart';
import 'package:args/args.dart';
-main() {
+void main() {
group('ArgParser.getUsage()', () {
test('negatable flags show "no-" in title', () {
var parser = new ArgParser();
@@ -168,7 +168,7 @@
''');
});
- test("hidden flags don't appear in the help", () {
+ test("hidden options don't appear in the help", () {
var parser = new ArgParser();
parser.addOption('first', help: 'The first option');
parser.addOption('second', hide: true);
@@ -181,14 +181,24 @@
--third The third option
''');
});
+
+ test("hidden flags don't appear in the help", () {
+ var parser = new ArgParser();
+ parser.addFlag('first', help: 'The first flag');
+ parser.addFlag('second', hide: true);
+ parser.addFlag('third', help: 'The third flag');
+
+
+ validateUsage(parser,
+ '''
+ --[no-]first The first flag
+ --[no-]third The third flag
+ ''');
+ });
});
}
-throwsIllegalArg(function) {
- expect(function, throwsArgumentError);
-}
-
-validateUsage(ArgParser parser, String expected) {
+void validateUsage(ArgParser parser, String expected) {
expected = unindentString(expected);
expect(parser.getUsage(), equals(expected));
}
diff --git a/pkg/args/test/utils.dart b/pkg/args/test/utils.dart
new file mode 100644
index 0000000..4586f57
--- /dev/null
+++ b/pkg/args/test/utils.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library utils;
+
+import 'package:unittest/unittest.dart';
+import 'package:args/args.dart';
+
+void throwsIllegalArg(function, {String reason: null}) {
+ expect(function, throwsArgumentError, reason: reason);
+}
+
+void throwsFormat(ArgParser parser, List<String> args) {
+ expect(() => parser.parse(args), throwsFormatException);
+}
diff --git a/pkg/barback/lib/src/cancelable_future.dart b/pkg/barback/lib/src/cancelable_future.dart
index 284df41..4454f5c 100644
--- a/pkg/barback/lib/src/cancelable_future.dart
+++ b/pkg/barback/lib/src/cancelable_future.dart
@@ -32,7 +32,8 @@
Future then(onValue(T value), {Function onError}) =>
_completer.future.then(onValue, onError: onError);
Future<T> whenComplete(action()) => _completer.future.whenComplete(action);
-
+ Future timeout(Duration timeLimit, [void onTimeout()]) =>
+ _completer.future.timeout(timeLimit, onTimeout);
/// Cancels this future.
void cancel() {
_canceled = true;
diff --git a/pkg/barback/lib/src/pool.dart b/pkg/barback/lib/src/pool.dart
index 23b878f..7f89c12 100644
--- a/pkg/barback/lib/src/pool.dart
+++ b/pkg/barback/lib/src/pool.dart
@@ -106,7 +106,7 @@
/// emit exceptions.
void _onTimeout() {
for (var completer in _requestedResources) {
- completer.completeException("Pool deadlock: all resources have been "
+ completer.completeError("Pool deadlock: all resources have been "
"allocated for too long.", new Trace.current().vmTrace);
}
_requestedResources.clear();
diff --git a/pkg/barback/pubspec.yaml b/pkg/barback/pubspec.yaml
index 93604ed..54e3a1a 100644
--- a/pkg/barback/pubspec.yaml
+++ b/pkg/barback/pubspec.yaml
@@ -1,5 +1,5 @@
name: barback
-version: 0.9.0
+version: 0.9.0 # Replaced by publish_barback.py. Do not edit.
author: "Dart Team <misc@dartlang.org>"
homepage: http://www.dartlang.org
description: >
diff --git a/pkg/docgen/bin/dartdoc.py b/pkg/docgen/bin/dartdoc.py
index c822cba..4971e36 100644
--- a/pkg/docgen/bin/dartdoc.py
+++ b/pkg/docgen/bin/dartdoc.py
@@ -15,7 +15,6 @@
import sys
sys.path.append(abspath(join(dirname(__file__), '../../../tools')))
import utils
-from upload_sdk import ExecuteCommand
DIRECTORY = abspath(dirname(__file__))
DART_DIR = dirname(dirname(dirname(DIRECTORY)))
@@ -134,15 +133,15 @@
docgen = [DART_EXECUTABLE, '--checked',
'--package-root=' + PACKAGE_ROOT, join(DIRECTORY, 'docgen.dart')]
docgen.extend(options.options.split())
- ExecuteCommand(docgen)
+ utils.ExecuteCommand(docgen)
if generate_all_docs:
GenerateAllDocs(docgen_options)
if not options.just_docs:
cwd = os.getcwd()
try:
- ExecuteCommand(['git', 'clone', '-b', 'master',
+ utils.ExecuteCommand(['git', 'clone', '-b', 'master',
'git://github.com/dart-lang/dartdoc-viewer.git'])
- ExecuteCommand(['mv', 'docs', 'dartdoc-viewer/client/local'])
+ utils.ExecuteCommand(['mv', 'docs', 'dartdoc-viewer/client/local'])
os.chdir('dartdoc-viewer/client/')
subprocess.call([PUB, 'install'])
subprocess.call([DART_EXECUTABLE, 'deploy.dart'])
diff --git a/pkg/docgen/bin/upload_docgen.py b/pkg/docgen/bin/upload_docgen.py
index b598394..c376dad 100644
--- a/pkg/docgen/bin/upload_docgen.py
+++ b/pkg/docgen/bin/upload_docgen.py
@@ -16,7 +16,6 @@
import sys
sys.path.append(abspath(join(dirname(__file__), '../../../tools')))
import utils
-from upload_sdk import ExecuteCommand
DART = abspath(join(dirname(__file__), '../../../%s/%s/dart-sdk/bin/dart'
@@ -63,7 +62,7 @@
def Upload(source, target):
""" Upload files to Google Storage. """
cmd = [GSUTIL, '-m', 'cp', '-q', '-a', 'public-read', '-r', source, target]
- (status, output) = ExecuteCommand(cmd)
+ (status, output) = utils.ExecuteCommand(cmd)
return status
@@ -73,7 +72,7 @@
SetGsutil()
# Execute Docgen.dart on the SDK.
- ExecuteCommand(['python', 'dartdoc.py', '-d'])
+ utils.ExecuteCommand(['python', 'dartdoc.py', '-d'])
# Use SVN Revision to get the revision number.
revision = None
@@ -109,8 +108,8 @@
Upload('./VERSION', GS_SITE + '/' + revision + '/' + 'VERSION')
# Clean up the files it creates.
- ExecuteCommand(['rm', '-rf', './docs'])
- ExecuteCommand(['rm', '-f', './VERSION'])
+ utils.ExecuteCommand(['rm', '-rf', './docs'])
+ utils.ExecuteCommand(['rm', '-f', './VERSION'])
if __name__ == '__main__':
diff --git a/pkg/docgen/lib/docgen.dart b/pkg/docgen/lib/docgen.dart
index 0482da1..d21d235 100644
--- a/pkg/docgen/lib/docgen.dart
+++ b/pkg/docgen/lib/docgen.dart
@@ -128,7 +128,7 @@
_coreLibrary = _sdkLibraries.singleWhere((lib) =>
lib.uri.toString().startsWith('dart:core'));
var availableLibrariesByPath = new Map.fromIterables(
- availableLibraries.map((each) => each.uri.toFilePath()),
+ availableLibraries.map((each) => each.uri),
availableLibraries);
var librariesToDocument = requestedLibraries.map(
(each) => availableLibrariesByPath.putIfAbsent(each,
@@ -189,14 +189,14 @@
return contents;
}
-List<String> _listLibraries(List<String> args) {
- var libraries = new List<String>();
+List<Uri> _listLibraries(List<String> args) {
+ var libraries = new List<Uri>();
for (var arg in args) {
var type = FileSystemEntity.typeSync(arg);
if (type == FileSystemEntityType.FILE) {
if (arg.endsWith('.dart')) {
- libraries.add(path.absolute(arg));
+ libraries.add(new Uri.file(path.absolute(arg)));
logger.info('Added to libraries: ${libraries.last}');
}
} else {
@@ -206,7 +206,7 @@
return libraries;
}
-List<String> _listDartFromDir(String args) {
+List<Uri> _listDartFromDir(String args) {
var libraries = [];
// To avoid anaylzing package files twice, only files with paths not
// containing '/packages' will be added. The only exception is if the file to
@@ -223,12 +223,12 @@
var contents = new File(f).readAsStringSync();
if (!(contents.contains(new RegExp('\npart of ')) ||
contents.startsWith(new RegExp('part of ')))) {
- libraries.add(f);
+ libraries.add(new Uri.file(path.normalize(path.absolute(f))));
logger.info('Added to libraries: $f');
}
}
});
- return libraries.map(path.absolute).map(path.normalize).toList();
+ return libraries;
}
String _findPackageRoot(String directory) {
@@ -251,11 +251,11 @@
return spec["name"];
}
-List<String> _listSdk() {
- var sdk = new List<String>();
+List<Uri> _listSdk() {
+ var sdk = new List<Uri>();
LIBRARIES.forEach((String name, LibraryInfo info) {
if (info.documented) {
- sdk.add('dart:$name');
+ sdk.add(Uri.parse('dart:$name'));
logger.info('Add to SDK: ${sdk.last}');
}
});
@@ -264,7 +264,7 @@
/// Analyzes set of libraries by getting a mirror system and triggers the
/// documentation of the libraries.
-Future<MirrorSystem> getMirrorSystem(List<String> libraries,
+Future<MirrorSystem> getMirrorSystem(List<Uri> libraries,
{String packageRoot, bool parseSdk: false}) {
if (libraries.isEmpty) throw new StateError('No Libraries.');
// Finds the root of SDK library based off the location of docgen.
@@ -286,7 +286,7 @@
/// Analyzes set of libraries and provides a mirror system which can be used
/// for static inspection of the source code.
-Future<MirrorSystem> _analyzeLibraries(List<String> libraries,
+Future<MirrorSystem> _analyzeLibraries(List<Uri> libraries,
String libraryRoot, {String packageRoot}) {
SourceFileProvider provider = new CompilerSourceFileProvider();
api.DiagnosticHandler diagnosticHandler =
@@ -294,16 +294,12 @@
..showHints = false
..showWarnings = false)
.diagnosticHandler;
- Uri libraryUri = new Uri(scheme: 'file', path: appendSlash(libraryRoot));
+ Uri libraryUri = new Uri.file(appendSlash(libraryRoot));
Uri packageUri = null;
if (packageRoot != null) {
- packageUri = new Uri(scheme: 'file', path: appendSlash(packageRoot));
+ packageUri = new Uri.file(appendSlash(packageRoot));
}
- List<Uri> librariesUri = <Uri>[];
- libraries.forEach((library) {
- librariesUri.add(currentDirectory.resolve(library));
- });
- return dart2js.analyze(librariesUri, libraryUri, packageUri,
+ return dart2js.analyze(libraries, libraryUri, packageUri,
provider.readStringFromUri, diagnosticHandler,
['--preserve-comments', '--categories=Client,Server'])
..catchError((error) {
diff --git a/pkg/docgen/test/single_library_test.dart b/pkg/docgen/test/single_library_test.dart
index d2c94a7..12cd6b6 100644
--- a/pkg/docgen/test/single_library_test.dart
+++ b/pkg/docgen/test/single_library_test.dart
@@ -46,7 +46,7 @@
var fileName = path.join(temporaryDir.path, 'temp.dart');
var file = new File(fileName);
file.writeAsStringSync(DART_LIBRARY);
- getMirrorSystem([fileName])
+ getMirrorSystem([new Uri.file(fileName)])
.then(expectAsync1((mirrorSystem) {
var testLibraryUri = new Uri(scheme: 'file',
path: path.absolute(fileName));
diff --git a/pkg/http/test/safe_http_server.dart b/pkg/http/test/safe_http_server.dart
index 5d709f9..9c3622d 100644
--- a/pkg/http/test/safe_http_server.dart
+++ b/pkg/http/test/safe_http_server.dart
@@ -30,8 +30,9 @@
: super(server),
_inner = server;
- Future close() => _inner.close();
+ Future close({bool force: false}) => _inner.close(force: force);
+ InternetAddress get address => _inner.address;
int get port => _inner.port;
set sessionTimeout(int timeout) {
@@ -138,6 +139,7 @@
Future<HttpResponse> addStream(Stream<List<int>> stream) =>
_inner.addStream(stream);
Future close() => _inner.close();
+ Future flush() => _inner.flush();
void write(Object obj) => _inner.write(obj);
void writeAll(Iterable objects, [String separator = ""]) =>
_inner.writeAll(objects, separator);
diff --git a/pkg/intl/test/date_time_format_test_core.dart b/pkg/intl/test/date_time_format_test_core.dart
index 757bb6b..5d39090 100644
--- a/pkg/intl/test/date_time_format_test_core.dart
+++ b/pkg/intl/test/date_time_format_test_core.dart
@@ -144,7 +144,7 @@
// At least in most cases. In some cases, we can't even do that. e.g.
// the skeleton WEEKDAY can't be reconstructed at all, and YEAR_MONTH
// formats don't give us enough information to construct a valid date.
- var badSkeletons = [
+ var badSkeletons = const [
DateFormat.ABBR_WEEKDAY,
DateFormat.WEEKDAY,
DateFormat.QUARTER,
@@ -156,6 +156,9 @@
DateFormat.MONTH_WEEKDAY_DAY,
DateFormat.NUM_MONTH_WEEKDAY_DAY,
DateFormat.ABBR_MONTH_WEEKDAY_DAY];
+ var originalTime = new DateTime.now();
+ var originalTimeZoneOffset = date.timeZoneOffset;
+ var originalTimeZoneName = date.timeZoneName;
for(int i = 0; i < formatsToTest.length; i++) {
var skeleton = formatsToTest[i];
if (!badSkeletons.any((x) => x == skeleton)) {
@@ -163,6 +166,25 @@
var actualResult = format.format(date);
var parsed = format.parse(actualResult);
var thenPrintAgain = format.format(parsed);
+ // We've seen a case where this failed in a way that seemed like a time
+ // zone shifting or some other strange behaviour that caused an off by
+ // one error in the date. Check for this and print out as much information
+ // as possible if it occurs again.
+ if (thenPrintAgain != actualResult) {
+ print("Date mismatch!");
+ print(" Expected $actualResult");
+ print(" Got $thenPrintAgain");
+ print(" Original date = $date");
+ print(" Original ms = ${date.millisecondsSinceEpoch}");
+ print(" Parsed back to $parsed");
+ print(" Parsed ms = ${parsed.millisecondsSinceEpoch}");
+ print(" Original tz = $originalTimeZoneOffset");
+ print(" Current tz name = $originalTimeZoneName");
+ print(" Current tz = ${parsed.timeZoneOffset}");
+ print(" Current tz name = ${parsed.timeZoneName}");
+ print(" Start time = $originalTime");
+ print(" Current time ${new DateTime.now()}");
+ }
expect(thenPrintAgain, equals(actualResult));
}
}
diff --git a/pkg/logging/lib/logging.dart b/pkg/logging/lib/logging.dart
index 37ac67d..8bff36b 100644
--- a/pkg/logging/lib/logging.dart
+++ b/pkg/logging/lib/logging.dart
@@ -311,6 +311,9 @@
/** Key for extra debugging loudness ([value] = 1200). */
static const Level SHOUT = const Level('SHOUT', 1200);
+ static const List<Level> LEVELS = const
+ [ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, SHOUT, OFF];
+
bool operator ==(Object other) => other is Level && value == other.value;
bool operator <(Level other) => value < other.value;
bool operator <=(Level other) => value <= other.value;
diff --git a/pkg/logging/pubspec.yaml b/pkg/logging/pubspec.yaml
index d298608..334113f 100644
--- a/pkg/logging/pubspec.yaml
+++ b/pkg/logging/pubspec.yaml
@@ -1,12 +1,12 @@
name: logging
-version: 0.9.0
+version: 0.9.1-dev
author: Dart Team <misc@dartlang.org>
description: Provides APIs for debugging and error logging. This library introduces abstractions similar to those used in other languages, such as the Closure JS Logger and java.util.logging.Logger.
homepage: http://www.dartlang.org
documentation: http://api.dartlang.org/docs/pkg/logging
-dependencies:
- collection_helpers: ">=0.9.0 <0.10.0"
-dev_dependencies:
- unittest: ">=0.9.0 <0.10.0"
environment:
- sdk: ">=0.8.10+6 <2.0.0"
+ sdk: '>=0.8.10+6 <2.0.0'
+dependencies:
+ collection_helpers: '>=0.9.1 <0.10.0'
+dev_dependencies:
+ unittest: '>=0.9.0 <0.10.0'
diff --git a/pkg/logging/test/logging_test.dart b/pkg/logging/test/logging_test.dart
index a188bb5..82ef3e1 100644
--- a/pkg/logging/test/logging_test.dart
+++ b/pkg/logging/test/logging_test.dart
@@ -29,10 +29,7 @@
});
test('default levels are in order', () {
- final levels = const [
- Level.ALL, Level.FINEST, Level.FINER, Level.FINE, Level.CONFIG,
- Level.INFO, Level.WARNING, Level.SEVERE, Level.SHOUT, Level.OFF
- ];
+ final levels = Level.LEVELS;
for (int i = 0; i < levels.length; i++) {
for (int j = i + 1; j < levels.length; j++) {
@@ -46,13 +43,12 @@
Level.INFO, Level.CONFIG, Level.FINE, Level.SHOUT, Level.OFF,
Level.FINER, Level.ALL, Level.WARNING, Level.FINEST, Level.SEVERE,
];
- final sorted = const [
- Level.ALL, Level.FINEST, Level.FINER, Level.FINE, Level.CONFIG,
- Level.INFO, Level.WARNING, Level.SEVERE, Level.SHOUT, Level.OFF
- ];
+
+ final sorted = Level.LEVELS;
+
expect(unsorted, isNot(orderedEquals(sorted)));
- unsorted.sort((a, b) => a.compareTo(b));
+ unsorted.sort();
expect(unsorted, orderedEquals(sorted));
});
@@ -65,7 +61,7 @@
});
test('logger name cannot start with a "." ', () {
- expect(() => new Logger('.c'), throws);
+ expect(() => new Logger('.c'), throwsArgumentError);
});
test('logger naming is hierarchical', () {
diff --git a/pkg/observe/AUTHORS b/pkg/observe/AUTHORS
new file mode 100644
index 0000000..0617765
--- /dev/null
+++ b/pkg/observe/AUTHORS
@@ -0,0 +1,9 @@
+# Names should be added to this file with this pattern:
+#
+# For individuals:
+# Name <email address>
+#
+# For organizations:
+# Organization <fnmatch pattern>
+#
+Google Inc. <*@google.com>
diff --git a/pkg/observe/LICENSE b/pkg/observe/LICENSE
new file mode 100644
index 0000000..ee99930
--- /dev/null
+++ b/pkg/observe/LICENSE
@@ -0,0 +1,26 @@
+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/observe/PATENTS b/pkg/observe/PATENTS
new file mode 100644
index 0000000..6954196
--- /dev/null
+++ b/pkg/observe/PATENTS
@@ -0,0 +1,23 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Dart Project.
+
+Google hereby grants to you a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this
+section) patent license to make, have made, use, offer to sell, sell,
+import, transfer, and otherwise run, modify and propagate the contents
+of this implementation of Dart, where such license applies only to
+those patent claims, both currently owned by Google and acquired in
+the future, licensable by Google that are necessarily infringed by
+this implementation of Dart. This grant does not include claims that
+would be infringed only as a consequence of further modification of
+this implementation. If you or your agent or exclusive licensee
+institute or order or agree to the institution of patent litigation
+against any entity (including a cross-claim or counterclaim in a
+lawsuit) alleging that this implementation of Dart or any code
+incorporated within this implementation of Dart constitutes direct or
+contributory patent infringement, or inducement of patent
+infringement, then any patent rights granted to you under this License
+for this implementation of Dart shall terminate as of the date such
+litigation is filed.
diff --git a/pkg/observe/lib/src/observable.dart b/pkg/observe/lib/src/observable.dart
index f798f44..35e91c8 100644
--- a/pkg/observe/lib/src/observable.dart
+++ b/pkg/observe/lib/src/observable.dart
@@ -82,8 +82,11 @@
// actually includes this mixin. While perhaps too inclusive, it lets us
// avoid complex logic that walks "with" and "implements" clauses.
for (var type = mirror.type; type != objectType; type = type.superclass) {
- for (var field in type.variables.values) {
- if (field.isFinal || field.isStatic || field.isPrivate) continue;
+ for (var field in type.declarations.values) {
+ if (field is! VariableMirror ||
+ field.isFinal ||
+ field.isStatic ||
+ field.isPrivate) continue;
for (var meta in field.metadata) {
if (meta.reflectee is ObservableProperty) {
diff --git a/pkg/observe/lib/src/observable_list.dart b/pkg/observe/lib/src/observable_list.dart
index 76cf06b..be25afa 100644
--- a/pkg/observe/lib/src/observable_list.dart
+++ b/pkg/observe/lib/src/observable_list.dart
@@ -82,7 +82,7 @@
if (len == value) return;
// Produce notifications if needed
- notifyPropertyChange(#length, len, value);
+ _notifyChangeLength(len, value);
if (_hasListObservers) {
if (value < len) {
_recordChange(new ListChangeRecord(this, value,
@@ -106,6 +106,15 @@
_list[index] = value;
}
+ // Forwarders so we can reflect on the properties.
+ @reflectable bool get isEmpty => super.isEmpty;
+ @reflectable bool get isNotEmpty => super.isNotEmpty;
+
+ // TODO(jmesserly): should we support first/last/single? They're kind of
+ // dangerous to use in a path because they throw exceptions. Also we'd need
+ // to produce property change notifications which seems to conflict with our
+ // existing list notifications.
+
// The following methods are here so that we can provide nice change events.
void setAll(int index, Iterable<E> iterable) {
@@ -122,7 +131,7 @@
void add(E value) {
int len = _list.length;
- notifyPropertyChange(#length, len, len + 1);
+ _notifyChangeLength(len, len + 1);
if (_hasListObservers) {
_recordChange(new ListChangeRecord(this, len, addedCount: 1));
}
@@ -134,7 +143,7 @@
int len = _list.length;
_list.addAll(iterable);
- notifyPropertyChange(#length, len, _list.length);
+ _notifyChangeLength(len, _list.length);
int added = _list.length - len;
if (_hasListObservers && added > 0) {
@@ -157,7 +166,7 @@
int rangeLength = end - start;
int len = _list.length;
- notifyPropertyChange(#length, len, len - rangeLength);
+ _notifyChangeLength(len, len - rangeLength);
if (_hasListObservers && rangeLength > 0) {
_recordChange(new ListChangeRecord(this, start,
removed: _list.getRange(start, end).toList()));
@@ -184,7 +193,7 @@
_list.setRange(index + insertionLength, this.length, this, index);
_list.setAll(index, iterable);
- notifyPropertyChange(#length, len, _list.length);
+ _notifyChangeLength(len, _list.length);
if (_hasListObservers && insertionLength > 0) {
_recordChange(new ListChangeRecord(this, index,
@@ -207,7 +216,7 @@
_list.length++;
_list.setRange(index + 1, length, this, index);
- notifyPropertyChange(#length, _list.length - 1, _list.length);
+ _notifyChangeLength(_list.length - 1, _list.length);
if (_hasListObservers) {
_recordChange(new ListChangeRecord(this, index, addedCount: 1));
}
@@ -240,6 +249,12 @@
_listRecords.add(record);
}
+ void _notifyChangeLength(int oldValue, int newValue) {
+ notifyPropertyChange(#length, oldValue, newValue);
+ notifyPropertyChange(#isEmpty, oldValue == 0, newValue == 0);
+ notifyPropertyChange(#isNotEmpty, oldValue != 0, newValue != 0);
+ }
+
bool deliverListChanges() {
if (_listRecords == null) return false;
var records = projectListSplices(this, _listRecords);
diff --git a/pkg/observe/pubspec.yaml b/pkg/observe/pubspec.yaml
index 7938f6e..75dd77a 100644
--- a/pkg/observe/pubspec.yaml
+++ b/pkg/observe/pubspec.yaml
@@ -1,5 +1,5 @@
name: observe
-version: 0.9.1-dev
+version: 0.9.1+1
author: Polymer.dart Authors <web-ui-dev@dartlang.org>
description: >
Observable properties and objects for use in Model-Driven-Views (MDV).
@@ -10,11 +10,11 @@
homepage: https://www.dartlang.org/polymer-dart/
dependencies:
analyzer: ">=0.10.1 <0.11.0"
- barback: ">=0.9.0 <0.10.0"
+ barback: ">=0.9.0 <0.11.0"
logging: ">=0.9.0 <0.10.0"
path: ">=0.9.0 <0.10.0"
source_maps: ">=0.9.0 <0.10.0"
dev_dependencies:
unittest: ">=0.9.0 <0.10.0"
environment:
- sdk: ">=0.8.10+6 <2.0.0"
+ sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/observe/test/observable_list_test.dart b/pkg/observe/test/observable_list_test.dart
index 0b4575d..66a03d3 100644
--- a/pkg/observe/test/observable_list_test.dart
+++ b/pkg/observe/test/observable_list_test.dart
@@ -253,7 +253,11 @@
expect(list, []);
performMicrotaskCheckpoint();
- expectChanges(propRecords, [_lengthChange(6, 0)]);
+ expectChanges(propRecords, [
+ _lengthChange(6, 0),
+ new PropertyChangeRecord(list, #isEmpty, false, true),
+ new PropertyChangeRecord(list, #isNotEmpty, true, false),
+ ]);
expectChanges(listRecords, [_change(0, removed: [1, 2, 3, 1, 3, 4])]);
});
});
diff --git a/pkg/observe/test/path_observer_test.dart b/pkg/observe/test/path_observer_test.dart
index 91d68a1..10378fa 100644
--- a/pkg/observe/test/path_observer_test.dart
+++ b/pkg/observe/test/path_observer_test.dart
@@ -152,6 +152,34 @@
model.add(123);
});
+ group('ObservableList', () {
+ observeTest('isNotEmpty', () {
+ var model = new ObservableList();
+ var path = observePath(model, 'isNotEmpty');
+ expect(path.value, false);
+
+ var future = path.changes.first.then((_) {
+ expect(path.value, true);
+ });
+ model.add(123);
+
+ return future;
+ });
+
+ observeTest('isEmpty', () {
+ var model = new ObservableList();
+ var path = observePath(model, 'isEmpty');
+ expect(path.value, true);
+
+ var future = path.changes.first.then((_) {
+ expect(path.value, false);
+ });
+ model.add(123);
+
+ return future;
+ });
+ });
+
for (var createModel in [() => new TestModel(), () => new WatcherModel()]) {
observeTest('Path Observation - ${createModel().runtimeType}', () {
var model = createModel()..a =
diff --git a/pkg/path/pubspec.yaml b/pkg/path/pubspec.yaml
index a391d96..491c3bc 100644
--- a/pkg/path/pubspec.yaml
+++ b/pkg/path/pubspec.yaml
@@ -10,4 +10,4 @@
dev_dependencies:
unittest: ">=0.9.0 <0.10.0"
environment:
- sdk: ">=1.0.0+3.r30188 <2.0.0"
+ sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 41fd2a5..d9c7d08 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -40,6 +40,7 @@
[ $runtime == d8 || $runtime == jsshell ]
unittest/test/unittest_nested_groups_setup_teardown_test: Pass, RuntimeError # http://dartbug.com/10109
stack_trace/test/vm_test: RuntimeError, OK # VM-specific traces
+stack_trace/test/chain_test: Fail # Issues 15171 and 15105
sequence_zip/test/stream_test: RuntimeError, OK # Timers are not supported.
unittest/test/missing_tick_test: Fail # Timer interface not supported: dartbug.com/7728.
@@ -169,6 +170,7 @@
[ $compiler == dart2js && $browser ]
stack_trace/test/vm_test: Fail, OK # VM-specific traces
+stack_trace/test/chain_test: Fail # Issues 15171 and 15105
crypto/test/sha256_test: Slow, Pass
crypto/test/sha1_test: Slow, Pass
polymer/example/component: Fail # Issue 13198
diff --git a/pkg/polymer/AUTHORS b/pkg/polymer/AUTHORS
new file mode 100644
index 0000000..0617765
--- /dev/null
+++ b/pkg/polymer/AUTHORS
@@ -0,0 +1,9 @@
+# Names should be added to this file with this pattern:
+#
+# For individuals:
+# Name <email address>
+#
+# For organizations:
+# Organization <fnmatch pattern>
+#
+Google Inc. <*@google.com>
diff --git a/pkg/polymer/LICENSE b/pkg/polymer/LICENSE
new file mode 100644
index 0000000..92d60b0
--- /dev/null
+++ b/pkg/polymer/LICENSE
@@ -0,0 +1,27 @@
+// Copyright (c) 2012 The Polymer 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/polymer/PATENTS b/pkg/polymer/PATENTS
new file mode 100644
index 0000000..e120963
--- /dev/null
+++ b/pkg/polymer/PATENTS
@@ -0,0 +1,23 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Polymer project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Polymer, where such license applies only to those
+patent claims, both currently owned or controlled by Google and acquired
+in the future, licensable by Google that are necessarily infringed by
+this implementation of Polymer. This grant does not include claims
+that would be infringed only as a consequence of further modification of
+this implementation. If you or your agent or exclusive licensee
+institute or order or agree to the institution of patent litigation
+against any entity (including a cross-claim or counterclaim in a
+lawsuit) alleging that this implementation of Polymer or any code
+incorporated within this implementation of Polymer constitutes
+direct or contributory patent infringement, or inducement of patent
+infringement, then any patent rights granted to you under this License
+for this implementation of Polymer shall terminate as of the date
+such litigation is filed.
diff --git a/pkg/polymer/pubspec.yaml b/pkg/polymer/pubspec.yaml
index ab6bad8..ba87001 100644
--- a/pkg/polymer/pubspec.yaml
+++ b/pkg/polymer/pubspec.yaml
@@ -1,5 +1,5 @@
name: polymer
-version: 0.9.1-dev
+version: 0.9.1+1
author: Polymer.dart Authors <web-ui-dev@dartlang.org>
description: >
Polymer.dart is a new type of library for the web, built on top of Web
@@ -9,17 +9,17 @@
dependencies:
analyzer: ">=0.10.1 <0.11.0"
args: ">=0.9.0 <0.10.0"
- barback: ">=0.9.0 <0.10.0"
+ barback: ">=0.9.0 <0.11.0"
browser: ">=0.9.0 <0.10.0"
csslib: ">=0.9.0 <0.10.0"
custom_element: ">=0.9.0 <0.10.0"
- html5lib: ">=0.9.1-dev <0.10.0"
+ html5lib: ">=0.9.1 <0.10.0"
html_import: ">=0.9.0 <0.10.0"
logging: ">=0.9.0 <0.10.0"
- observe: ">=0.9.1-dev <0.10.0"
+ observe: ">=0.9.1 <0.10.0"
path: ">=0.9.0 <0.10.0"
- polymer_expressions: ">=0.9.0 <0.10.0"
- shadow_dom: ">=0.9.0 <0.10.0"
+ polymer_expressions: ">=0.9.1 <0.10.0"
+ shadow_dom: ">=0.9.1 <0.10.0"
source_maps: ">=0.9.0 <0.10.0"
template_binding: ">=0.9.0 <0.10.0"
yaml: ">=0.9.0 <0.10.0"
@@ -29,4 +29,4 @@
dev_dependencies:
unittest: ">=0.9.0 <0.10.0"
environment:
- sdk: ">=0.8.10+6 <2.0.0"
+ sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/polymer_expressions/AUTHORS b/pkg/polymer_expressions/AUTHORS
new file mode 100644
index 0000000..0617765
--- /dev/null
+++ b/pkg/polymer_expressions/AUTHORS
@@ -0,0 +1,9 @@
+# Names should be added to this file with this pattern:
+#
+# For individuals:
+# Name <email address>
+#
+# For organizations:
+# Organization <fnmatch pattern>
+#
+Google Inc. <*@google.com>
diff --git a/pkg/polymer_expressions/LICENSE b/pkg/polymer_expressions/LICENSE
new file mode 100644
index 0000000..ee99930
--- /dev/null
+++ b/pkg/polymer_expressions/LICENSE
@@ -0,0 +1,26 @@
+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/polymer_expressions/PATENTS b/pkg/polymer_expressions/PATENTS
new file mode 100644
index 0000000..6954196
--- /dev/null
+++ b/pkg/polymer_expressions/PATENTS
@@ -0,0 +1,23 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Dart Project.
+
+Google hereby grants to you a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this
+section) patent license to make, have made, use, offer to sell, sell,
+import, transfer, and otherwise run, modify and propagate the contents
+of this implementation of Dart, where such license applies only to
+those patent claims, both currently owned by Google and acquired in
+the future, licensable by Google that are necessarily infringed by
+this implementation of Dart. This grant does not include claims that
+would be infringed only as a consequence of further modification of
+this implementation. If you or your agent or exclusive licensee
+institute or order or agree to the institution of patent litigation
+against any entity (including a cross-claim or counterclaim in a
+lawsuit) alleging that this implementation of Dart or any code
+incorporated within this implementation of Dart constitutes direct or
+contributory patent infringement, or inducement of patent
+infringement, then any patent rights granted to you under this License
+for this implementation of Dart shall terminate as of the date such
+litigation is filed.
diff --git a/pkg/polymer_expressions/pubspec.yaml b/pkg/polymer_expressions/pubspec.yaml
index 92db8e4..5b80ae9 100644
--- a/pkg/polymer_expressions/pubspec.yaml
+++ b/pkg/polymer_expressions/pubspec.yaml
@@ -1,5 +1,5 @@
name: polymer_expressions
-version: 0.9.0
+version: 0.9.1
author: Web UI Authors <html-dev@dartlang.org>
description: An expressive custom binding syntax for MDV templates
homepage: http://www.dartlang.org/polymer-dart/
@@ -11,4 +11,4 @@
unittest: ">=0.9.0 <0.10.0"
benchmark_harness: ">=1.0.0 <2.0.0"
environment:
- sdk: ">=0.8.10+6 <2.0.0"
+ sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart b/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart
index 9e1eeb2..4c9abe7 100644
--- a/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart
+++ b/pkg/scheduled_test/lib/src/scheduled_server/safe_http_server.dart
@@ -32,6 +32,7 @@
Future close({bool force: false}) => _inner.close(force: force);
+ InternetAddress get address => _inner.address;
int get port => _inner.port;
set sessionTimeout(int timeout) {
@@ -138,6 +139,7 @@
Future<HttpResponse> addStream(Stream<List<int>> stream) =>
_inner.addStream(stream);
Future close() => _inner.close();
+ Future flush() => _inner.flush();
void write(Object obj) => _inner.write(obj);
void writeAll(Iterable objects, [String separator = ""]) =>
_inner.writeAll(objects, separator);
diff --git a/pkg/scheduled_test/lib/src/substitute_future.dart b/pkg/scheduled_test/lib/src/substitute_future.dart
index c4b9ffb..d30c936 100644
--- a/pkg/scheduled_test/lib/src/substitute_future.dart
+++ b/pkg/scheduled_test/lib/src/substitute_future.dart
@@ -29,6 +29,8 @@
Future then(onValue(T value), {Function onError}) =>
_completer.future.then(onValue, onError: onError);
Future<T> whenComplete(action()) => _completer.future.whenComplete(action);
+ Future timeout(Duration timeLimit, [void onTimeout()]) =>
+ _completer.future.timeout(timeLimit, onTimeout);
/// Substitutes [newFuture] for the currently wrapped [Future], which is
/// returned.
diff --git a/pkg/scheduled_test/lib/src/value_future.dart b/pkg/scheduled_test/lib/src/value_future.dart
index a7d6517..3821feb 100644
--- a/pkg/scheduled_test/lib/src/value_future.dart
+++ b/pkg/scheduled_test/lib/src/value_future.dart
@@ -35,4 +35,6 @@
Future then(onValue(T value), {Function onError}) =>
_future.then(onValue, onError: onError);
Future<T> whenComplete(action()) => _future.whenComplete(action);
+ Future timeout(Duration timeLimit, [void onTimeout()]) =>
+ _future.timeout(timeLimit, onTimeout);
}
diff --git a/pkg/serialization/lib/src/serialization_rule.dart b/pkg/serialization/lib/src/serialization_rule.dart
index 49e42ae..38fafca 100644
--- a/pkg/serialization/lib/src/serialization_rule.dart
+++ b/pkg/serialization/lib/src/serialization_rule.dart
@@ -410,13 +410,17 @@
if (name.contains(":")) {
var uri = Uri.parse(name);
var libMirror = currentMirrorSystem().libraries[uri];
- return libMirror.classes[new Symbol(type)];
+ var candidate = libMirror.declarations[new Symbol(type)];
+ return candidate is ClassMirror ? candidate : null;
} else {
var symbol = new Symbol(name);
var typeSymbol = new Symbol(type);
- var libMirror = currentMirrorSystem().libraries.values.firstWhere(
- (lib) => lib.simpleName == symbol && lib.classes[typeSymbol] != null);
- return libMirror.classes[typeSymbol];
+ for (var libMirror in currentMirrorSystem().libraries.values) {
+ if (libMirror.simpleName != symbol) continue;
+ var candidate = libMirror.declarations[typeSymbol];
+ if (candidate != null && candidate is ClassMirror) return candidate;
+ }
+ return null;
}
}
}
diff --git a/pkg/shadow_dom/AUTHORS b/pkg/shadow_dom/AUTHORS
new file mode 100644
index 0000000..0617765
--- /dev/null
+++ b/pkg/shadow_dom/AUTHORS
@@ -0,0 +1,9 @@
+# Names should be added to this file with this pattern:
+#
+# For individuals:
+# Name <email address>
+#
+# For organizations:
+# Organization <fnmatch pattern>
+#
+Google Inc. <*@google.com>
diff --git a/pkg/shadow_dom/LICENSE b/pkg/shadow_dom/LICENSE
new file mode 100644
index 0000000..92d60b0
--- /dev/null
+++ b/pkg/shadow_dom/LICENSE
@@ -0,0 +1,27 @@
+// Copyright (c) 2012 The Polymer 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/shadow_dom/PATENTS b/pkg/shadow_dom/PATENTS
new file mode 100644
index 0000000..e120963
--- /dev/null
+++ b/pkg/shadow_dom/PATENTS
@@ -0,0 +1,23 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Polymer project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Polymer, where such license applies only to those
+patent claims, both currently owned or controlled by Google and acquired
+in the future, licensable by Google that are necessarily infringed by
+this implementation of Polymer. This grant does not include claims
+that would be infringed only as a consequence of further modification of
+this implementation. If you or your agent or exclusive licensee
+institute or order or agree to the institution of patent litigation
+against any entity (including a cross-claim or counterclaim in a
+lawsuit) alleging that this implementation of Polymer or any code
+incorporated within this implementation of Polymer constitutes
+direct or contributory patent infringement, or inducement of patent
+infringement, then any patent rights granted to you under this License
+for this implementation of Polymer shall terminate as of the date
+such litigation is filed.
diff --git a/pkg/shadow_dom/lib/shadow_dom.debug.js b/pkg/shadow_dom/lib/shadow_dom.debug.js
index 477e03b..f86df70 100644
--- a/pkg/shadow_dom/lib/shadow_dom.debug.js
+++ b/pkg/shadow_dom/lib/shadow_dom.debug.js
@@ -904,36 +904,35 @@
// every PathObserver used by defineProperty share a single Object.observe
// callback, and thus get() can simply call observer.deliver() and any changes
// to any dependent value will be observed.
- PathObserver.defineProperty = function(object, name, descriptor) {
+ PathObserver.defineProperty = function(target, name, object, path) {
// TODO(rafaelw): Validate errors
- var obj = descriptor.object;
- var path = getPath(descriptor.path);
- var notify = notifyFunction(object, name);
+ path = getPath(path);
+ var notify = notifyFunction(target, name);
- var observer = new PathObserver(obj, descriptor.path,
+ var observer = new PathObserver(object, path,
function(newValue, oldValue) {
if (notify)
notify(PROP_UPDATE_TYPE, oldValue);
}
);
- Object.defineProperty(object, name, {
+ Object.defineProperty(target, name, {
get: function() {
- return path.getValueFrom(obj);
+ return path.getValueFrom(object);
},
set: function(newValue) {
- path.setValueFrom(obj, newValue);
+ path.setValueFrom(object, newValue);
},
configurable: true
});
return {
close: function() {
- var oldValue = path.getValueFrom(obj);
+ var oldValue = path.getValueFrom(object);
if (notify)
observer.deliver();
observer.close();
- Object.defineProperty(object, name, {
+ Object.defineProperty(target, name, {
value: oldValue,
writable: true,
configurable: true
@@ -1419,7 +1418,7 @@
'delete': PROP_DELETE_TYPE,
splice: ARRAY_SPLICE_TYPE
};
-})(typeof global !== 'undefined' && global ? global : this);
+})(typeof global !== 'undefined' && global ? global : this || window);
/*
* Copyright 2012 The Polymer Authors. All rights reserved.
@@ -1490,16 +1489,19 @@
throw new Error('Assertion failed');
};
+ var defineProperty = Object.defineProperty;
+ var getOwnPropertyNames = Object.getOwnPropertyNames;
+ var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+
function mixin(to, from) {
- Object.getOwnPropertyNames(from).forEach(function(name) {
- Object.defineProperty(to, name,
- Object.getOwnPropertyDescriptor(from, name));
+ getOwnPropertyNames(from).forEach(function(name) {
+ defineProperty(to, name, getOwnPropertyDescriptor(from, name));
});
return to;
};
function mixinStatics(to, from) {
- Object.getOwnPropertyNames(from).forEach(function(name) {
+ getOwnPropertyNames(from).forEach(function(name) {
switch (name) {
case 'arguments':
case 'caller':
@@ -1509,8 +1511,7 @@
case 'toString':
return;
}
- Object.defineProperty(to, name,
- Object.getOwnPropertyDescriptor(from, name));
+ defineProperty(to, name, getOwnPropertyDescriptor(from, name));
});
return to;
};
@@ -1525,7 +1526,7 @@
// Mozilla's old DOM bindings are bretty busted:
// https://bugzilla.mozilla.org/show_bug.cgi?id=855844
// Make sure they are create before we start modifying things.
- Object.getOwnPropertyNames(window);
+ getOwnPropertyNames(window);
function getWrapperConstructor(node) {
var nativePrototype = node.__proto__ || Object.getPrototypeOf(node);
@@ -1587,28 +1588,39 @@
function() { return this.impl[name].apply(this.impl, arguments); };
}
- function installProperty(source, target, allowMethod) {
- Object.getOwnPropertyNames(source).forEach(function(name) {
+ function getDescriptor(source, name) {
+ try {
+ return Object.getOwnPropertyDescriptor(source, name);
+ } catch (ex) {
+ // JSC and V8 both use data properties instead of accessors which can
+ // cause getting the property desciptor to throw an exception.
+ // https://bugs.webkit.org/show_bug.cgi?id=49739
+ return dummyDescriptor;
+ }
+ }
+
+ function installProperty(source, target, allowMethod, opt_blacklist) {
+ var names = getOwnPropertyNames(source);
+ for (var i = 0; i < names.length; i++) {
+ var name = names[i];
+ if (name === 'polymerBlackList_')
+ continue;
+
if (name in target)
- return;
+ continue;
+
+ if (source.polymerBlackList_ && source.polymerBlackList_[name])
+ continue;
if (isFirefox) {
// Tickle Firefox's old bindings.
source.__lookupGetter__(name);
}
- var descriptor;
- try {
- descriptor = Object.getOwnPropertyDescriptor(source, name);
- } catch (ex) {
- // JSC and V8 both use data properties instead of accessors which can
- // cause getting the property desciptor to throw an exception.
- // https://bugs.webkit.org/show_bug.cgi?id=49739
- descriptor = dummyDescriptor;
- }
+ var descriptor = getDescriptor(source, name);
var getter, setter;
if (allowMethod && typeof descriptor.value === 'function') {
target[name] = getMethod(name);
- return;
+ continue;
}
var isEvent = isEventHandlerName(name);
@@ -1624,13 +1636,13 @@
setter = getSetter(name);
}
- Object.defineProperty(target, name, {
+ defineProperty(target, name, {
get: getter,
set: setter,
configurable: descriptor.configurable,
enumerable: descriptor.enumerable
});
- });
+ }
}
/**
@@ -1655,6 +1667,12 @@
addForwardingProperties(nativePrototype, wrapperPrototype);
if (opt_instance)
registerInstanceProperties(wrapperPrototype, opt_instance);
+ defineProperty(wrapperPrototype, 'constructor', {
+ value: wrapperConstructor,
+ configurable: true,
+ enumerable: false,
+ writable: true
+ });
}
function isWrapperFor(wrapperConstructor, nativeConstructor) {
@@ -1665,11 +1683,7 @@
/**
* Creates a generic wrapper constructor based on |object| and its
* constructor.
- * Sometimes the constructor does not have an associated instance
- * (CharacterData for example). In that case you can pass the constructor that
- * you want to map the object to using |opt_nativeConstructor|.
* @param {Node} object
- * @param {Function=} opt_nativeConstructor
* @return {Function} The generated constructor.
*/
function registerObject(object) {
@@ -1782,7 +1796,7 @@
}
function defineGetter(constructor, name, getter) {
- Object.defineProperty(constructor.prototype, name, {
+ defineProperty(constructor.prototype, name, {
get: getter,
configurable: true,
enumerable: true
@@ -2437,17 +2451,6 @@
return false;
}
- var mutationEventsAreSilenced = 0;
-
- function muteMutationEvents() {
- mutationEventsAreSilenced++;
- }
-
- function unmuteMutationEvents() {
- mutationEventsAreSilenced--;
- }
-
- var OriginalMutationEvent = window.MutationEvent;
function dispatchOriginalEvent(originalEvent) {
// Make sure this event is only dispatched once.
@@ -2455,15 +2458,9 @@
return;
handledEventsTable.set(originalEvent, true);
- // Don't do rendering if this is a mutation event since rendering might
- // mutate the DOM which would fire more events and we would most likely
- // just iloop.
- if (originalEvent instanceof OriginalMutationEvent) {
- if (mutationEventsAreSilenced)
- return;
- } else {
- scope.renderAllPending();
- }
+ // Render before dispatching the event to ensure that the event path is
+ // correct.
+ scope.renderAllPending();
var target = wrap(originalEvent.target);
var event = wrap(originalEvent);
@@ -2633,6 +2630,7 @@
};
var OriginalEvent = window.Event;
+ OriginalEvent.prototype.polymerBlackList_ = {returnValue: true};
/**
* Creates a new Event wrapper or wraps an existin native Event object.
@@ -2748,13 +2746,6 @@
var MouseEvent = registerGenericEvent('MouseEvent', UIEvent, mouseEventProto);
var FocusEvent = registerGenericEvent('FocusEvent', UIEvent, focusEventProto);
- var MutationEvent = registerGenericEvent('MutationEvent', Event, {
- initMutationEvent: getInitFunction('initMutationEvent', 3),
- get relatedNode() {
- return wrap(this.impl.relatedNode);
- },
- });
-
// In case the browser does not support event constructors we polyfill that
// by calling `createEvent('Foo')` and `initFooEvent` where the arguments to
// `initFooEvent` are derived from the registered default event init dict.
@@ -2821,12 +2812,41 @@
configureEventConstructor('FocusEvent', {relatedTarget: null}, 'UIEvent');
}
+ function BeforeUnloadEvent(impl) {
+ Event.call(this);
+ }
+ BeforeUnloadEvent.prototype = Object.create(Event.prototype);
+ mixin(BeforeUnloadEvent.prototype, {
+ get returnValue() {
+ return this.impl.returnValue;
+ },
+ set returnValue(v) {
+ this.impl.returnValue = v;
+ }
+ });
+
function isValidListener(fun) {
if (typeof fun === 'function')
return true;
return fun && fun.handleEvent;
}
+ function isMutationEvent(type) {
+ switch (type) {
+ case 'DOMAttrModified':
+ case 'DOMAttributeNameChanged':
+ case 'DOMCharacterDataModified':
+ case 'DOMElementNameChanged':
+ case 'DOMNodeInserted':
+ case 'DOMNodeInsertedIntoDocument':
+ case 'DOMNodeRemoved':
+ case 'DOMNodeRemovedFromDocument':
+ case 'DOMSubtreeModified':
+ return true;
+ }
+ return false;
+ }
+
var OriginalEventTarget = window.EventTarget;
/**
@@ -2861,7 +2881,7 @@
EventTarget.prototype = {
addEventListener: function(type, fun, capture) {
- if (!isValidListener(fun))
+ if (!isValidListener(fun) || isMutationEvent(type))
return;
var listener = new Listener(type, fun, capture);
@@ -2991,15 +3011,13 @@
scope.elementFromPoint = elementFromPoint;
scope.getEventHandlerGetter = getEventHandlerGetter;
scope.getEventHandlerSetter = getEventHandlerSetter;
- scope.muteMutationEvents = muteMutationEvents;
- scope.unmuteMutationEvents = unmuteMutationEvents;
scope.wrapEventTargetMethods = wrapEventTargetMethods;
+ scope.wrappers.BeforeUnloadEvent = BeforeUnloadEvent;
scope.wrappers.CustomEvent = CustomEvent;
scope.wrappers.Event = Event;
scope.wrappers.EventTarget = EventTarget;
scope.wrappers.FocusEvent = FocusEvent;
scope.wrappers.MouseEvent = MouseEvent;
- scope.wrappers.MutationEvent = MutationEvent;
scope.wrappers.UIEvent = UIEvent;
})(window.ShadowDOMPolyfill);
@@ -4365,10 +4383,8 @@
var HTMLElement = scope.wrappers.HTMLElement;
var getInnerHTML = scope.getInnerHTML;
var mixin = scope.mixin;
- var muteMutationEvents = scope.muteMutationEvents;
var registerWrapper = scope.registerWrapper;
var setInnerHTML = scope.setInnerHTML;
- var unmuteMutationEvents = scope.unmuteMutationEvents;
var unwrap = scope.unwrap;
var wrap = scope.wrap;
@@ -4397,11 +4413,9 @@
var doc = getTemplateContentsOwner(templateElement.ownerDocument);
var df = unwrap(doc.createDocumentFragment());
var child;
- muteMutationEvents();
while (child = templateElement.firstChild) {
df.appendChild(child);
}
- unmuteMutationEvents();
return df;
}
@@ -4894,9 +4908,7 @@
var ShadowRoot = scope.wrappers.ShadowRoot;
var assert = scope.assert;
var mixin = scope.mixin;
- var muteMutationEvents = scope.muteMutationEvents;
var oneOf = scope.oneOf;
- var unmuteMutationEvents = scope.unmuteMutationEvents;
var unwrap = scope.unwrap;
var wrap = scope.wrap;
@@ -5240,11 +5252,8 @@
this.renderNode(shadowRoot, renderNode, node, false);
}
- if (topMostRenderer) {
- //muteMutationEvents();
+ if (topMostRenderer)
renderNode.sync();
- //unmuteMutationEvents();
- }
this.dirty = false;
},
@@ -5679,6 +5688,8 @@
doc.adoptNode(oldShadowRoot);
}
+ var originalImportNode = document.importNode;
+
mixin(Document.prototype, {
adoptNode: function(node) {
if (node.parentNode)
@@ -5688,6 +5699,17 @@
},
elementFromPoint: function(x, y) {
return elementFromPoint(this, this, x, y);
+ },
+ importNode: function(node, deep) {
+ // We need to manually walk the tree to ensure we do not include rendered
+ // shadow trees.
+ var clone = wrap(originalImportNode.call(this.impl, unwrap(node), false));
+ if (deep) {
+ for (var child = node.firstChild; child; child = child.nextSibling) {
+ clone.appendChild(this.importNode(child, true));
+ }
+ }
+ return clone;
}
});
@@ -5806,6 +5828,7 @@
window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument
], [
'adoptNode',
+ 'importNode',
'contains',
'createComment',
'createDocumentFragment',
@@ -6529,11 +6552,16 @@
return cssText.replace(cssColonHostRe, function(m, p1, p2, p3) {
p1 = polyfillHostNoCombinator;
if (p2) {
- if (p2.match(polyfillHost)) {
- return p1 + p2.replace(polyfillHost, '') + p3;
- } else {
- return p1 + p2 + p3 + ', ' + p2 + ' ' + p1 + p3;
+ var parts = p2.split(','), r = [];
+ for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) {
+ p = p.trim();
+ if (p.match(polyfillHost)) {
+ r.push(p1 + p.replace(polyfillHost, '') + p3);
+ } else {
+ r.push(p1 + p + p3 + ', ' + p + ' ' + p1 + p3);
+ }
}
+ return r.join(',');
} else {
return p1 + p3;
}
@@ -6555,7 +6583,7 @@
cssText += this.propertiesFromRule(rule) + '\n}\n\n';
} else if (rule.media) {
cssText += '@media ' + rule.media.mediaText + ' {\n';
- cssText += this.scopeRules(rule.cssRules, name);
+ cssText += this.scopeRules(rule.cssRules, name, typeExtension);
cssText += '\n}\n\n';
} else if (rule.cssText) {
cssText += rule.cssText + '\n\n';
@@ -6568,8 +6596,9 @@
parts.forEach(function(p) {
p = p.trim();
if (this.selectorNeedsScoping(p, name, typeExtension)) {
- p = strict ? this.applyStrictSelectorScope(p, name) :
- this.applySimpleSelectorScope(p, name, typeExtension);
+ p = (strict && !p.match(polyfillHostNoCombinator)) ?
+ this.applyStrictSelectorScope(p, name) :
+ this.applySimpleSelectorScope(p, name, typeExtension);
}
r.push(p);
}, this);
@@ -6617,14 +6646,7 @@
polyfillHost);
},
propertiesFromRule: function(rule) {
- var properties = rule.style.cssText;
- // TODO(sorvell): Chrome cssom incorrectly removes quotes from the content
- // property. (https://code.google.com/p/chromium/issues/detail?id=247231)
- if (rule.style.content && !rule.style.content.match(/['"]+/)) {
- properties = 'content: \'' + rule.style.content + '\';\n' +
- rule.style.cssText.replace(/content:[^;]*;/g, '');
- }
- return properties;
+ return rule.style.cssText;
}
};
@@ -6638,15 +6660,18 @@
cssPolyfillUnscopedRuleCommentRe = /\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,
cssPseudoRe = /::(x-[^\s{,(]*)/gim,
cssPartRe = /::part\(([^)]*)\)/gim,
- // note: :host pre-processed to -host.
- cssColonHostRe = /(-host)(?:\(([^)]*)\))?([^,{]*)/gim,
+ // note: :host pre-processed to -shadowcsshost.
+ polyfillHost = '-shadowcsshost',
+ cssColonHostRe = new RegExp('(' + polyfillHost +
+ ')(?:\\((' +
+ '(?:\\([^)(]*\\)|[^)(]*)+?' +
+ ')\\))?([^,{]*)', 'gim'),
selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$',
hostRe = /@host/gim,
colonHostRe = /\:host/gim,
- polyfillHost = '-host',
/* host name without combinator */
- polyfillHostNoCombinator = '-host-no-combinator',
- polyfillHostRe = /-host/gim;
+ polyfillHostNoCombinator = polyfillHost + '-no-combinator',
+ polyfillHostRe = new RegExp(polyfillHost, 'gim');
function stylesToCssText(styles, preserveComments) {
var cssText = '';
diff --git a/pkg/shadow_dom/lib/shadow_dom.min.js b/pkg/shadow_dom/lib/shadow_dom.min.js
index 1080a13..a0ff506 100644
--- a/pkg/shadow_dom/lib/shadow_dom.min.js
+++ b/pkg/shadow_dom/lib/shadow_dom.min.js
@@ -1,3 +1,3 @@
-if(!HTMLElement.prototype.createShadowRoot||window.__forceShadowDomPolyfill){!function(){Element.prototype.webkitCreateShadowRoot&&(Element.prototype.webkitCreateShadowRoot=function(){return window.ShadowDOMPolyfill.wrapIfNeeded(this).createShadowRoot()})}(),function(a){"use strict";function b(){function a(a){b=a}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=[],c={};if(Object.observe(c,a),c.id=1,c.id=2,delete c.id,Object.deliverChangeRecords(a),3!==b.length)return!1;if("new"==b[0].type&&"updated"==b[1].type&&"deleted"==b[2].type)F="new",G="updated",H="reconfigured",I="deleted";else if("add"!=b[0].type||"update"!=b[1].type||"delete"!=b[2].type)return console.error("Unexpected change record names for Object.observe. Using dirty-checking instead"),!1;return Object.unobserve(c,a),c=[0],Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),2!=b.length?!1:b[0].type!=J||b[1].type!=J?!1:(Array.unobserve(c,a),!0)}function c(){if(a.document&&"securityPolicy"in a.document&&!a.document.securityPolicy.allowsEval)return!1;try{var b=new Function("","return true;");return b()}catch(c){return!1}}function d(a){return+a===a>>>0}function e(a){return+a}function f(a){return a===Object(a)}function g(a,b){return a===b?0!==a||1/a===1/b:M(a)&&M(b)?!0:a!==a&&b!==b}function h(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:U.test(a))}function i(a,b){if(b!==V)throw Error("Use Path.get to retrieve path objects");return""==a.trim()?this:d(a)?(this.push(a),this):(a.split(/\s*\.\s*/).filter(function(a){return a}).forEach(function(a){this.push(a)},this),L&&!K&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn()),void 0)}function j(a){if(a instanceof i)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=W[a];if(b)return b;if(!h(a))return X;var b=new i(a,V);return W[a]=b,b}function k(b){for(var c=0;Y>c&&b.check();)b.report(),c++;a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=c)}function l(a){for(var b in a)return!1;return!0}function m(a){return l(a.added)&&l(a.removed)&&l(a.changed)}function n(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function o(a,b){var c=b||(Array.isArray(a)?[]:{});for(var d in a)c[d]=a[d];return Array.isArray(a)&&(c.length=a.length),c}function p(a,b,c,d){if(this.closed=!1,this.object=a,this.callback=b,this.target=c,this.token=d,this.reporting=!0,K){var e=this;this.boundInternalCallback=function(a){e.internalCallback(a)}}q(this)}function q(a){$&&(Z.push(a),p._allObserversCount++)}function r(a,b,c,d){p.call(this,a,b,c,d),this.connect(),this.sync(!0)}function s(a,b,c,d){if(!Array.isArray(a))throw Error("Provided object is not an Array");r.call(this,a,b,c,d)}function t(a){this.arr=[],this.callback=a,this.isObserved=!0}function u(a,b,c,d,e,g,h){var b=b instanceof i?b:j(b);return b&&b.length&&f(a)?(p.call(this,a,c,d,e),this.valueFn=g,this.setValueFn=h,this.path=b,this.connect(),this.sync(!0),void 0):(this.value_=b?b.getValueFrom(a):void 0,this.value=g?g(this.value_):this.value_,this.closed=!0,void 0)}function v(a,b,c,d){p.call(this,void 0,a,b,c),this.valueFn=d,this.observed=[],this.values=[],this.value=void 0,this.oldValue=void 0,this.oldValues=void 0,this.changeFlags=void 0,this.started=!1}function w(a,b){if("function"==typeof Object.observe){var c=Object.getNotifier(a);return function(d,e){var f={object:a,type:d,name:b};2===arguments.length&&(f.oldValue=e),c.notify(f)}}}function x(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];db[g.type]?(g.name in c||(c[g.name]=g.oldValue),g.type!=G&&(g.type!=F?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}function y(a,b,c){return{index:a,removed:b,addedCount:c}}function z(){}function A(a,b,c,d,e,f){return ib.calcSplices(a,b,c,d,e,f)}function B(a,b,c,d){return c>b||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function C(a,b,c,d){for(var e=y(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=B(e.index,e.index+e.removed.length,i.index,i.index+i.addedCount);if(j>=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.index<i.index){var l=e.removed.slice(0,i.index-e.index);Array.prototype.push.apply(l,c),c=l}if(e.index+e.removed.length>i.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.index<e.index&&(e.index=i.index)}else f=!0}else if(e.index<i.index){f=!0,a.splice(h,0,e),h++;var n=e.addedCount-e.removed.length;i.index+=n,g+=n}}}f||a.push(e)}function D(a,b){for(var c=[],f=0;f<b.length;f++){var g=b[f];switch(g.type){case J:C(c,g.index,g.removed.slice(),g.addedCount);break;case F:case G:case I:if(!d(g.name))continue;var h=e(g.name);if(0>h)continue;C(c,h,[g.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(g))}}return c}function E(a,b){var c=[];return D(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?(b.removed[0]!==a[b.index]&&c.push(b),void 0):(c=c.concat(A(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)),void 0)}),c}var F="add",G="update",H="reconfigure",I="delete",J="splice",K=b(),L=c(),M=a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},N="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c},O="[$_a-zA-Z]",P="[$_a-zA-Z0-9]",Q=O+"+"+P+"*",R="(?:[0-9]|[1-9]+[0-9]+)",S="(?:"+Q+"|"+R+")",T="(?:"+S+")(?:\\s*\\.\\s*"+S+")*",U=new RegExp("^"+T+"$"),V={},W={};i.get=j,i.prototype=N({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a,b){for(var c=0;c<this.length;c++){if(null==a)return;b&&b.observe(a),a=a[this[c]]}return a},compiledGetValueFromFn:function(){var a=this.map(function(a){return d(a)?'["'+a+'"]':"."+a}),b="",c="obj";b+="if (obj != null";for(var e=0;e<this.length-1;e++)this[e],c+=a[e],b+=" &&\n "+c+" != null";return b+=")\n",c+=a[e],b+=" return "+c+";\nelse\n return undefined;",new Function("obj",b)},setValueFrom:function(a,b){if(!this.length)return!1;for(var c=0;c<this.length-1;c++){if(!f(a))return!1;a=a[this[c]]}return f(a)?(a[this[c]]=b,!0):!1}});var X=new i("",V);X.valid=!1,X.getValueFrom=X.setValueFrom=function(){};var Y=1e3;p.prototype={internalCallback:function(a){this.closed||this.reporting&&this.check(a)&&(this.report(),this.testingResults&&(this.testingResults.anyChanged=!0))},close:function(){this.closed||(this.object&&"function"==typeof this.object.close&&this.object.close(),this.disconnect(),this.object=void 0,this.closed=!0)},deliver:function(a){this.closed||(K?(this.testingResults=a,Object.deliverChangeRecords(this.boundInternalCallback),this.testingResults=void 0):k(this))},report:function(){this.reporting&&(this.sync(!1),this.callback&&(this.reportArgs.push(this.token),this.invokeCallback(this.reportArgs)),this.reportArgs=void 0)},invokeCallback:function(a){try{this.callback.apply(this.target,a)}catch(b){p._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},reset:function(){this.closed||(K&&(this.reporting=!1,Object.deliverChangeRecords(this.boundInternalCallback),this.reporting=!0),this.sync(!0))}};var Z,$=!K||a.forceCollectObservers;p._allObserversCount=0,$&&(Z=[]);var _=!1,ab="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!_){if(ab)return Object.deliverAllChangeRecords(),void 0;if($){_=!0;var b=0,c={};do{b++;var d=Z;Z=[],c.anyChanged=!1;for(var e=0;e<d.length;e++){var f=d[e];f.closed||(K?f.deliver(c):f.check()&&(c.anyChanged=!0,f.report()),Z.push(f))}}while(Y>b&&c.anyChanged);a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=b),p._allObserversCount=Z.length,_=!1}}},$&&(a.Platform.clearObservers=function(){Z=[]}),r.prototype=N({__proto__:p.prototype,connect:function(){K&&Object.observe(this.object,this.boundInternalCallback)},sync:function(){K||(this.oldObject=o(this.object))},check:function(a){var b,c;if(K){if(!a)return!1;c={},b=x(this.object,a,c)}else c=this.oldObject,b=n(this.object,this.oldObject);return m(b)?!1:(this.reportArgs=[b.added||{},b.removed||{},b.changed||{}],this.reportArgs.push(function(a){return c[a]}),!0)},disconnect:function(){K?this.object&&Object.unobserve(this.object,this.boundInternalCallback):this.oldObject=void 0}}),s.prototype=N({__proto__:r.prototype,connect:function(){K&&Array.observe(this.object,this.boundInternalCallback)},sync:function(){K||(this.oldObject=this.object.slice())},check:function(a){var b;if(K){if(!a)return!1;b=E(this.object,a)}else b=A(this.object,0,this.object.length,this.oldObject,0,this.oldObject.length);return b&&b.length?(this.reportArgs=[b],!0):!1}}),s.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;e<c.index+c.addedCount;)d.push(b[e]),e++;Array.prototype.splice.apply(a,d)})};var bb=Object.getPrototypeOf({}),cb=Object.getPrototypeOf([]);t.prototype={reset:function(){this.isObserved=!this.isObserved},observe:function(a){if(f(a)&&a!==bb&&a!==cb){var b=this.arr.indexOf(a);b>=0&&this.arr[b+1]===this.isObserved||(0>b&&(b=this.arr.length,this.arr[b]=a,Object.observe(a,this.callback)),this.arr[b+1]=this.isObserved,this.observe(Object.getPrototypeOf(a)))}},cleanup:function(){for(var a=0,b=0,c=this.isObserved;b<this.arr.length;){var d=this.arr[b];this.arr[b+1]==c?(b>a&&(this.arr[a]=d,this.arr[a+1]=c),a+=2):Object.unobserve(d,this.callback),b+=2}this.arr.length=a}},u.prototype=N({__proto__:p.prototype,connect:function(){K&&(this.observedSet=new t(this.boundInternalCallback))},disconnect:function(){this.value=void 0,this.value_=void 0,this.observedSet&&(this.observedSet.reset(),this.observedSet.cleanup(),this.observedSet=void 0)},check:function(){return this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.observedSet&&this.observedSet.cleanup(),g(this.value_,this.oldValue_)?!1:(this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.reportArgs=[this.value,this.oldValue],!0)},sync:function(a){a&&(this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.observedSet&&this.observedSet.cleanup()),this.oldValue_=this.value_,this.oldValue=this.value},setValue:function(a){this.path&&("function"==typeof this.setValueFn&&(a=this.setValueFn(a)),this.path.setValueFrom(this.object,a))}}),v.prototype=N({__proto__:u.prototype,addPath:function(a,b){if(this.started)throw Error("Cannot add more paths once started.");var b=b instanceof i?b:j(b),c=b?b.getValueFrom(a):void 0;this.observed.push(a,b),this.values.push(c)},start:function(){this.started=!0,this.connect(),this.sync(!0)},getValues:function(){this.observedSet&&this.observedSet.reset();for(var a=!1,b=0;b<this.observed.length;b+=2){var c=this.observed[b+1];if(c){var d=this.observed[b],e=c.getValueFrom(d,this.observedSet),f=this.values[b/2];if(!g(e,f)){if(!a&&!this.valueFn){this.oldValues=this.oldValues||[],this.changeFlags=this.changeFlags||[];for(var h=0;h<this.values.length;h++)this.oldValues[h]=this.values[h],this.changeFlags[h]=!1}this.valueFn||(this.changeFlags[b/2]=!0),this.values[b/2]=e,a=!0}}}return this.observedSet&&this.observedSet.cleanup(),a},check:function(){if(this.getValues()){if(this.valueFn){if(this.value=this.valueFn(this.values),g(this.value,this.oldValue))return!1;this.reportArgs=[this.value,this.oldValue]}else this.reportArgs=[this.values,this.oldValues,this.changeFlags,this.observed];return!0}},sync:function(a){a&&(this.getValues(),this.valueFn&&(this.value=this.valueFn(this.values))),this.valueFn&&(this.oldValue=this.value)},close:function(){if(this.observed){for(var a=0;a<this.observed.length;a+=2){var b=this.observed[a];b&&"function"==typeof b.close&&b.close()}this.observed=void 0,this.values=void 0}p.prototype.close.call(this)}});var db={};db[F]=!0,db[G]=!0,db[I]=!0,u.defineProperty=function(a,b,c){var d=c.object,e=j(c.path),f=w(a,b),g=new u(d,c.path,function(a,b){f&&f(G,b)});return Object.defineProperty(a,b,{get:function(){return e.getValueFrom(d)},set:function(a){e.setValueFrom(d,a)},configurable:!0}),{close:function(){var c=e.getValueFrom(d);f&&g.deliver(),g.close(),Object.defineProperty(a,b,{value:c,writable:!0,configurable:!0})}}};var eb=0,fb=1,gb=2,hb=3;z.prototype={calcEditDistances:function(a,b,c,d,e,f){for(var g=f-e+1,h=c-b+1,i=new Array(g),j=0;g>j;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(this.equals(a[b+k-1],d[e+j-1]))i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i},spliceOperationsFromEditDistances:function(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(eb):(e.push(fb),d=g),b--,c--):f==h?(e.push(hb),b--,d=h):(e.push(gb),c--,d=i)}else e.push(hb),b--;else e.push(gb),c--;return e.reverse(),e},calcSplices:function(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=this.sharedPrefix(a,d,i)),c==a.length&&f==d.length&&(h=this.sharedSuffix(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,0==c-b&&0==f-e)return[];if(b==c){for(var j=y(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[y(b,[],c-b)];for(var k=this.spliceOperationsFromEditDistances(this.calcEditDistances(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;o<k.length;o++)switch(k[o]){case eb:j&&(l.push(j),j=void 0),m++,n++;break;case fb:j||(j=y(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case gb:j||(j=y(m,[],0)),j.addedCount++,m++;break;case hb:j||(j=y(m,[],0)),j.removed.push(d[n]),n++}return j&&l.push(j),l},sharedPrefix:function(a,b,c){for(var d=0;c>d;d++)if(!this.equals(a[d],b[d]))return d;return c},sharedSuffix:function(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&this.equals(a[--d],b[--e]);)f++;return f},calculateSplices:function(a,b){return this.calcSplices(a,0,a.length,b,0,b.length)},equals:function(a,b){return a===b}};var ib=new z;a.Observer=p,a.Observer.hasObjectObserve=K,a.ArrayObserver=s,a.ArrayObserver.calculateSplices=function(a,b){return ib.calculateSplices(a,b)},a.ArraySplice=z,a.ObjectObserver=r,a.PathObserver=u,a.CompoundPathObserver=v,a.Path=i,a.Observer.changeRecordTypes={add:F,update:G,reconfigure:H,"delete":I,splice:J}}("undefined"!=typeof global&&global?global:this),"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}(),window.ShadowDOMPolyfill={},function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function d(a,b){return Object.getOwnPropertyNames(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))}),a}function e(a,b){for(var c=0;c<b.length;c++)if(b[c]in a)return b[c]}function f(a){var b=a.__proto__||Object.getPrototypeOf(a),c=D.get(b);if(c)return c;var d=f(b),e=s(d);return p(b,e,a),e}function g(a,b){n(a,b,!0)}function h(a,b){n(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return/^\w[a-zA-Z_0-9]*$/.test(a)}function k(a){return G&&j(a)?new Function("return this.impl."+a):function(){return this.impl[a]}}function l(a){return G&&j(a)?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function m(a){return G&&j(a)?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function n(b,c,d){Object.getOwnPropertyNames(b).forEach(function(e){if(!(e in c)){J&&b.__lookupGetter__(e);var f;try{f=Object.getOwnPropertyDescriptor(b,e)}catch(g){f=K}var h,j;if(d&&"function"==typeof f.value)return c[e]=m(e),void 0;var n=i(e);h=n?a.getEventHandlerGetter(e):k(e),(f.writable||f.set)&&(j=n?a.getEventHandlerSetter(e):l(e)),Object.defineProperty(c,e,{get:h,set:j,configurable:f.configurable,enumerable:f.enumerable})}})}function o(a,b,c){var e=a.prototype;p(e,b,c),d(b,a)}function p(a,c,d){var e=c.prototype;b(void 0===D.get(a)),D.set(a,c),E.set(e,a),g(a,e),d&&h(e,d)}function q(a,b){return D.get(b.prototype)===a}function r(a){var b=Object.getPrototypeOf(a),c=f(b),d=s(c);return p(b,d,a),d}function s(a){function b(b){a.call(this,b)}return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b}function t(a){return a instanceof F.EventTarget||a instanceof F.Event||a instanceof F.Range||a instanceof F.DOMImplementation||a instanceof F.CanvasRenderingContext2D||F.WebGLRenderingContext&&a instanceof F.WebGLRenderingContext}function u(a){return a instanceof N||a instanceof M||a instanceof O||a instanceof P||a instanceof L||a instanceof Q||R&&a instanceof R}function v(a){return null===a?null:(b(u(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function w(a){return null===a?null:(b(t(a)),a.impl)}function x(a){return a&&t(a)?w(a):a}function y(a){return a&&!t(a)?v(a):a}function z(a,c){null!==c&&(b(u(a)),b(void 0===c||t(c)),a.polymerWrapper_=c)}function A(a,b,c){Object.defineProperty(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function B(a,b){A(a,b,function(){return v(this.impl[b])})}function C(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=y(this);return a[b].apply(a,arguments)}})})}var D=new WeakMap,E=new WeakMap,F=Object.create(null),G=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(G)try{var H=new Function("","return true;");G=H()}catch(I){G=!1}Object.getOwnPropertyNames(window);var J=/Firefox/.test(navigator.userAgent),K={get:function(){},set:function(){},configurable:!0,enumerable:!0},L=window.DOMImplementation,M=window.Event,N=window.Node,O=window.Window,P=window.Range,Q=window.CanvasRenderingContext2D,R=window.WebGLRenderingContext;a.assert=b,a.constructorTable=D,a.defineGetter=A,a.defineWrapGetter=B,a.forwardMethodsToWrapper=C,a.isWrapperFor=q,a.mixin=c,a.nativePrototypeTable=E,a.oneOf=e,a.registerObject=r,a.registerWrapper=o,a.rewrap=z,a.unwrap=w,a.unwrapIfNeeded=x,a.wrap=v,a.wrapIfNeeded=y,a.wrappers=F}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){g=!1;var a=f.slice(0);f=[];for(var b=0;b<a.length;b++)a[b]()}function c(a){f.push(a),g||(g=!0,d(b,0))}var d,e=window.MutationObserver,f=[],g=!1;if(e){var h=1,i=new e(b),j=document.createTextNode(h);i.observe(j,{characterData:!0}),d=function(){h=(h+1)%2,j.data=h}}else d=window.setImmediate||window.setTimeout;a.setEndOfMicrotask=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){p||(k(c),p=!0)}function c(){p=!1;do for(var a=o.slice(),b=!1,c=0;c<a.length;c++){var d=a[c],e=d.takeRecords();f(d),e.length&&(d.callback_(e,d),b=!0)}while(b)}function d(a,b){this.type=a,this.target=b,this.addedNodes=new m.NodeList,this.removedNodes=new m.NodeList,this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function e(a,b){for(;a;a=a.parentNode){var c=n.get(a);if(c)for(var d=0;d<c.length;d++){var e=c[d];e.options.subtree&&e.addTransientObserver(b)}}}function f(a){for(var b=0;b<a.nodes_.length;b++){var c=a.nodes_[b],d=n.get(c);if(!d)return;for(var e=0;e<d.length;e++){var f=d[e];f.observer===a&&f.removeTransientObservers()}}}function g(a,c,e){for(var f=Object.create(null),g=Object.create(null),h=a;h;h=h.parentNode){var i=n.get(h);if(i)for(var j=0;j<i.length;j++){var k=i[j],l=k.options;if(!(h!==a&&!l.subtree||"attributes"===c&&!l.attributes||"attributes"===c&&l.attributeFilter&&(null!==e.namespace||-1===l.attributeFilter.indexOf(e.name))||"characterData"===c&&!l.characterData||"childList"===c&&!l.childList)){var m=k.observer;f[m.uid_]=m,("attributes"===c&&l.attributeOldValue||"characterData"===c&&l.characterDataOldValue)&&(g[m.uid_]=e.oldValue)}}}var o=!1;for(var p in f){var m=f[p],q=new d(c,a);"name"in e&&"namespace"in e&&(q.attributeName=e.name,q.attributeNamespace=e.namespace),e.addedNodes&&(q.addedNodes=e.addedNodes),e.removedNodes&&(q.removedNodes=e.removedNodes),e.previousSibling&&(q.previousSibling=e.previousSibling),e.nextSibling&&(q.nextSibling=e.nextSibling),void 0!==g[p]&&(q.oldValue=g[p]),m.records_.push(q),o=!0}o&&b()}function h(a){if(this.childList=!!a.childList,this.subtree=!!a.subtree,this.attributes="attributes"in a||!("attributeOldValue"in a||"attributeFilter"in a)?!!a.attributes:!0,this.characterData="characterDataOldValue"in a&&!("characterData"in a)?!0:!!a.characterData,!this.attributes&&(a.attributeOldValue||"attributeFilter"in a)||!this.characterData&&a.characterDataOldValue)throw new TypeError;if(this.characterData=!!a.characterData,this.attributeOldValue=!!a.attributeOldValue,this.characterDataOldValue=!!a.characterDataOldValue,"attributeFilter"in a){if(null==a.attributeFilter||"object"!=typeof a.attributeFilter)throw new TypeError;this.attributeFilter=q.call(a.attributeFilter)}else this.attributeFilter=null}function i(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++r,o.push(this)}function j(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var k=a.setEndOfMicrotask,l=a.wrapIfNeeded,m=a.wrappers,n=new WeakMap,o=[],p=!1,q=Array.prototype.slice,r=0;i.prototype={observe:function(a,b){a=l(a);var c,d=new h(b),e=n.get(a);e||n.set(a,e=[]);for(var f=0;f<e.length;f++)e[f].observer===this&&(c=e[f],c.removeTransientObservers(),c.options=d);c||(c=new j(this,a,d),e.push(c),this.nodes_.push(a))},disconnect:function(){this.nodes_.forEach(function(a){for(var b=n.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}},j.prototype={addTransientObserver:function(a){if(a!==this.target){this.transientObservedNodes.push(a);var b=n.get(a);b||n.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[];for(var b=0;b<a.length;b++)for(var c=a[b],d=n.get(c),e=0;e<d.length;e++)if(d[e]===this){d.splice(e,1);break}}},a.enqueueMutation=g,a.registerTransientObservers=e,a.wrappers.MutationObserver=i,a.wrappers.MutationRecord=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof O.ShadowRoot}function c(a){var b=a.localName;return"content"===b||"shadow"===b}function d(a){return!!a.shadowRoot}function e(a){var b;return a.parentNode||(b=a.defaultView)&&N(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||f.host;var i=a.eventParentsTable.get(f);if(i){for(var k=1;k<i.length;k++)h[k-1]=i[k];return i[0]}if(g&&c(f)){var l=f.parentNode;if(l&&d(l))for(var m=a.getShadowTrees(l),n=j(g),k=0;k<m.length;k++)if(m[k].contains(n))return n}return e(f)}function g(a){for(var d=[],e=a,g=[],i=[];e;){var j=null;if(c(e)){j=h(d);var k=d[d.length-1]||e;d.push(k)}else d.length||d.push(e);var l=d[d.length-1];g.push({target:l,currentTarget:e}),b(e)&&d.pop(),e=f(e,j,i)}return g}function h(a){for(var b=a.length-1;b>=0;b--)if(!c(a[b]))return a[b];return null}function i(a,d){for(var e=[];a;){for(var g=[],i=d,j=void 0;i;){var l=null;if(g.length){if(c(i)&&(l=h(g),k(j))){var n=g[g.length-1];g.push(n)}}else g.push(i);if(m(i,a))return g[g.length-1];b(i)&&g.pop(),j=i,i=f(i,l,e)}a=b(a)?a.host:a.parentNode}}function j(b){return a.insertionParentTable.get(b)}function k(a){return j(a)}function l(a){for(var b;b=a.parentNode;)a=b;return a}function m(a,b){return l(a)===l(b)}function n(a,b){return a===b?!0:a instanceof O.ShadowRoot?n(l(a.host),b):!1}function o(){Z++}function p(){Z--}function q(b){if(!Q.get(b)){if(Q.set(b,!0),b instanceof $){if(Z)return}else a.renderAllPending();var c=N(b.target),d=N(b);return r(d,c)}}function r(a,b){var c=g(b);return"load"===a.type&&2===c.length&&c[0].target instanceof O.Document&&c.shift(),Y.set(a,c),s(a,c)&&t(a,c)&&u(a,c),U.set(a,x.NONE),S.set(a,null),a.defaultPrevented}function s(a,b){for(var c,d=b.length-1;d>0;d--){var e=b[d].target,f=b[d].currentTarget;if(e!==f&&(c=x.CAPTURING_PHASE,!v(b[d],a,c)))return!1}return!0}function t(a,b){var c=x.AT_TARGET;return v(b[0],a,c)}function u(a,b){for(var c,d=a.bubbles,e=1;e<b.length;e++){var f=b[e].target,g=b[e].currentTarget;if(f===g)c=x.AT_TARGET;else{if(!d||W.get(a))continue;c=x.BUBBLING_PHASE}if(!v(b[e],a,c))return}}function v(a,b,c){var d=a.target,e=a.currentTarget,f=P.get(e);if(!f)return!0;if("relatedTarget"in b){var g=M(b);if(g.relatedTarget){var h=N(g.relatedTarget),j=i(e,h);if(j===d)return!0;T.set(b,j)}}U.set(b,c);var k=b.type,l=!1;R.set(b,d),S.set(b,e);for(var m=0;m<f.length;m++){var n=f[m];if(n.removed)l=!0;else if(!(n.type!==k||!n.capture&&c===x.CAPTURING_PHASE||n.capture&&c===x.BUBBLING_PHASE))try{if("function"==typeof n.handler?n.handler.call(e,b):n.handler.handleEvent(b),W.get(b))return!1}catch(o){window.onerror?window.onerror(o.message):console.error(o,o.stack)}}if(l){var p=f.slice();f.length=0;for(var m=0;m<p.length;m++)p[m].removed||f.push(p[m])}return!V.get(b)}function w(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function x(a,b){return a instanceof _?(this.impl=a,void 0):N(B(_,"Event",a,b))}function y(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:M(a.relatedTarget)}}):a}function z(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?(this.impl=b,void 0):N(B(d,a,b,c))};return e.prototype=Object.create(b.prototype),c&&K(e.prototype,c),d&&(d.prototype["init"+a]?L(d,e,document.createEvent(a)):L(d,e,new d("temp"))),e}function A(a,b){return function(){arguments[b]=M(arguments[b]);var c=M(this);c[a].apply(c,arguments)}}function B(a,b,c,d){if(jb)return new a(c,y(d));var e=M(document.createEvent(b)),f=ib[b],g=[c];return Object.keys(f).forEach(function(a){var b=null!=d&&a in d?d[a]:f[a];"relatedTarget"===a&&(b=M(b)),g.push(b)}),e["init"+b].apply(e,g),e}function C(a){return"function"==typeof a?!0:a&&a.handleEvent}function D(a){this.impl=a}function E(a){return a instanceof O.ShadowRoot&&(a=a.host),M(a)}function F(a){J(a,mb)}function G(b,c,d,e){a.renderAllPending();for(var f=N(nb.call(c.impl,d,e)),h=g(f,this),i=0;i<h.length;i++){var j=h[i];if(j.currentTarget===b)return j.target}return null}function H(a){return function(){var b=X.get(this);return b&&b[a]&&b[a].value||null}}function I(a){var b=a.slice(2);return function(c){var d=X.get(this);d||(d=Object.create(null),X.set(this,d));var e=d[a];if(e&&this.removeEventListener(b,e.wrapped,!1),"function"==typeof c){var f=function(b){var d=c.call(this,b);d===!1?b.preventDefault():"onbeforeunload"===a&&"string"==typeof d&&(b.returnValue=d)};this.addEventListener(b,f,!1),d[a]={value:c,wrapped:f}}}}var J=a.forwardMethodsToWrapper,K=a.mixin,L=a.registerWrapper,M=a.unwrap,N=a.wrap,O=a.wrappers;new WeakMap;var P=new WeakMap,Q=new WeakMap,R=new WeakMap,S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=0,$=window.MutationEvent;w.prototype={equals:function(a){return this.handler===a.handler&&this.type===a.type&&this.capture===a.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var _=window.Event;x.prototype={get target(){return R.get(this)},get currentTarget(){return S.get(this)},get eventPhase(){return U.get(this)},get path(){var a=new O.NodeList,b=Y.get(this);if(b){for(var c=0,d=b.length-1,e=l(S.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=l(g);n(e,h)&&(f!==d||g instanceof O.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){V.set(this,!0)},stopImmediatePropagation:function(){V.set(this,!0),W.set(this,!0)}},L(_,x,document.createEvent("Event"));var ab=z("UIEvent",x),bb=z("CustomEvent",x),cb={get relatedTarget(){return T.get(this)||N(M(this).relatedTarget)}},db=K({initMouseEvent:A("initMouseEvent",14)},cb),eb=K({initFocusEvent:A("initFocusEvent",5)},cb),fb=z("MouseEvent",ab,db),gb=z("FocusEvent",ab,eb),hb=z("MutationEvent",x,{initMutationEvent:A("initMutationEvent",3),get relatedNode(){return N(this.impl.relatedNode)}}),ib=Object.create(null),jb=function(){try{new window.MouseEvent("click")}catch(a){return!1}return!0}();if(!jb){var kb=function(a,b,c){if(c){var d=ib[c];b=K(K({},d),b)}ib[a]=b};kb("Event",{bubbles:!1,cancelable:!1}),kb("CustomEvent",{detail:null},"Event"),kb("UIEvent",{view:null,detail:0},"Event"),kb("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),kb("FocusEvent",{relatedTarget:null},"UIEvent")}var lb=window.EventTarget,mb=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(a){var b=a.prototype;mb.forEach(function(a){Object.defineProperty(b,a+"_",{value:b[a]})})}),D.prototype={addEventListener:function(a,b,c){if(C(b)){var d=new w(a,b,c),e=P.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],P.set(this,e);e.push(d);var g=E(this);g.addEventListener_(a,q,!0)}},removeEventListener:function(a,b,c){c=Boolean(c);var d=P.get(this);if(d){for(var e=0,f=!1,g=0;g<d.length;g++)d[g].type===a&&d[g].capture===c&&(e++,d[g].handler===b&&(f=!0,d[g].remove()));if(f&&1===e){var h=E(this);h.removeEventListener_(a,q,!0)}}},dispatchEvent:function(a){var b=E(this),c=M(a);return Q.set(c,!1),b.dispatchEvent_(c)}},lb&&L(lb,D);var nb=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=G,a.getEventHandlerGetter=H,a.getEventHandlerSetter=I,a.muteMutationEvents=o,a.unmuteMutationEvents=p,a.wrapEventTargetMethods=F,a.wrappers.CustomEvent=bb,a.wrappers.Event=x,a.wrappers.EventTarget=D,a.wrappers.FocusEvent=gb,a.wrappers.MouseEvent=fb,a.wrappers.MutationEvent=hb,a.wrappers.UIEvent=ab}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){Object.defineProperty(a,b,{enumerable:!1})}function c(){this.length=0,b(this,"length")}function d(a){if(null==a)return a;for(var b=new c,d=0,e=a.length;e>d;d++)b[d]=f(a[d]);return b.length=e,b}function e(a,b){a.prototype[b]=function(){return d(this.impl[b].apply(this.impl,arguments))}}var f=a.wrap;c.prototype={item:function(a){return this[a]}},b(c.prototype,"item"),a.wrappers.NodeList=c,a.addWrapNodeListMethod=e,a.wrapNodeList=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){v(a instanceof s)}function c(a){var b=new u;return b[0]=a,b.length=1,b}function d(a,b,c){x(b,"childList",{removedNodes:c,previousSibling:a.previousSibling,nextSibling:a.nextSibling})}function e(a,b){x(a,"childList",{removedNodes:b})}function f(a,b,d,e){if(a instanceof DocumentFragment){var f=h(a);E=!0;for(var g=f.length-1;g>=0;g--)a.removeChild(f[g]),f[g].parentNode_=b;E=!1;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||d,f[g].nextSibling_=f[g+1]||e;return d&&(d.nextSibling_=f[0]),e&&(e.previousSibling_=f[f.length-1]),f}var f=c(a),i=a.parentNode;return i&&i.removeChild(a),a.parentNode_=b,a.previousSibling_=d,a.nextSibling_=e,d&&(d.nextSibling_=a),e&&(e.previousSibling_=a),f}function g(a){if(a instanceof DocumentFragment)return h(a);var b=c(a),e=a.parentNode;return e&&d(a,e,b),b}function h(a){for(var b=new u,c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;
-return b.length=c,e(a,b),b}function i(a){return a}function j(a){a.nodeIsInserted_()}function k(a){for(var b=0;b<a.length;b++)j(a[b])}function l(){}function m(){}function n(a,b){var c=a.nodeType===s.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function o(b,c){if(c.length){var d=b.ownerDocument;if(d!==c[0].ownerDocument)for(var e=0;e<c.length;e++)a.adoptNodeNoRemove(c[e],d)}}function p(a,b){o(a,b);var c=b.length;if(1===c)return B(b[0]);for(var d=B(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(B(b[e]));return d}function q(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){v(b.parentNode===a);var c=b.nextSibling,d=B(b),e=d.parentNode;e&&J.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=B(a),g=f.firstChild;g;)c=g.nextSibling,J.call(f,g),g=c}function r(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function s(a){v(a instanceof F),t.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0}var t=a.wrappers.EventTarget,u=a.wrappers.NodeList,v=a.assert,w=a.defineWrapGetter,x=a.enqueueMutation,y=a.mixin,z=a.registerTransientObservers,A=a.registerWrapper,B=a.unwrap,C=a.wrap,D=a.wrapIfNeeded,E=!1,F=window.Node,G=window.DocumentFragment;F.prototype.appendChild;var H=F.prototype.compareDocumentPosition,I=F.prototype.insertBefore,J=F.prototype.removeChild,K=F.prototype.replaceChild,L=/Trident/.test(navigator.userAgent),M=L?function(a,b){try{J.call(a,b)}catch(c){if(!(a instanceof G))throw c}}:function(a,b){J.call(a,b)};s.prototype=Object.create(t.prototype),y(s.prototype,{appendChild:function(a){return this.insertBefore(a,null)},insertBefore:function(a,c){b(a),c=c||null,c&&b(c),c&&v(c.parentNode===this);var d,e=c?c.previousSibling:this.lastChild,h=!this.invalidateShadowRenderer()&&!r(a);if(d=h?g(a):f(a,this,e,c),h)n(this,a),I.call(this.impl,B(a),B(c));else{e||(this.firstChild_=d[0]),c||(this.lastChild_=d[d.length-1]);var i=B(c),j=i?i.parentNode:this.impl;j?I.call(j,p(this,d),i):o(this,d)}return x(this,"childList",{addedNodes:d,nextSibling:c,previousSibling:e}),k(d),a},removeChild:function(a){if(b(a),a.parentNode!==this){var d=!1;this.childNodes;for(var e=this.firstChild;e;e=e.nextSibling)if(e===a){d=!0;break}if(!d)throw new Error("NotFoundError")}var f=B(a),g=a.nextSibling,h=a.previousSibling;if(this.invalidateShadowRenderer()){var i=this.firstChild,j=this.lastChild,k=f.parentNode;k&&M(k,f),i===a&&(this.firstChild_=g),j===a&&(this.lastChild_=h),h&&(h.nextSibling_=g),g&&(g.previousSibling_=h),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else M(this.impl,f);return E||x(this,"childList",{removedNodes:c(a),nextSibling:g,previousSibling:h}),z(this,a),a},replaceChild:function(a,d){if(b(a),b(d),d.parentNode!==this)throw new Error("NotFoundError");var e,h=B(d),i=d.nextSibling,j=d.previousSibling,m=!this.invalidateShadowRenderer()&&!r(a);return m?e=g(a):(i===a&&(i=a.nextSibling),e=f(a,this,j,i)),m?(n(this,a),K.call(this.impl,B(a),h)):(this.firstChild===d&&(this.firstChild_=e[0]),this.lastChild===d&&(this.lastChild_=e[e.length-1]),d.previousSibling_=d.nextSibling_=d.parentNode_=void 0,h.parentNode&&K.call(h.parentNode,p(this,e),h)),x(this,"childList",{addedNodes:e,removedNodes:c(d),nextSibling:i,previousSibling:j}),l(d),k(e),d},nodeIsInserted_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeIsInserted_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:C(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:C(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:C(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:C(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:C(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==s.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)a+=b.textContent;return a},set textContent(a){var b=i(this.childNodes);if(this.invalidateShadowRenderer()){if(q(this),""!==a){var c=this.impl.ownerDocument.createTextNode(a);this.appendChild(c)}}else this.impl.textContent=a;var d=i(this.childNodes);x(this,"childList",{addedNodes:d,removedNodes:b}),m(b),k(d)},get childNodes(){for(var a=new u,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){var b=C(this.impl.cloneNode(!1));if(a)for(var c=this.firstChild;c;c=c.nextSibling)b.appendChild(c.cloneNode(!0));return b},contains:function(a){if(!a)return!1;if(a=D(a),a===this)return!0;var b=a.parentNode;return b?this.contains(b):!1},compareDocumentPosition:function(a){return H.call(this.impl,B(a))}}),w(s,"ownerDocument"),A(F,s,document.createDocumentFragment()),delete s.prototype.querySelector,delete s.prototype.querySelectorAll,s.prototype=y(Object.create(t.prototype),s.prototype),a.nodeWasAdded=j,a.nodeWasRemoved=l,a.nodesWereAdded=k,a.nodesWereRemoved=m,a.snapshotNodeList=i,a.wrappers.Node=s}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,c){for(var d,e=a.firstElementChild;e;){if(e.matches(c))return e;if(d=b(e,c))return d;e=e.nextElementSibling}return null}function c(a,b,d){for(var e=a.firstElementChild;e;)e.matches(b)&&(d[d.length++]=e),c(e,b,d),e=e.nextElementSibling;return d}var d={querySelector:function(a){return b(this,a)},querySelectorAll:function(a){return c(this,a,new NodeList)}},e={getElementsByTagName:function(a){return this.querySelectorAll(a)},getElementsByClassName:function(a){return this.querySelectorAll("."+a)},getElementsByTagNameNS:function(a,b){if("*"===a)return this.getElementsByTagName(b);for(var c=new NodeList,d=this.getElementsByTagName(b),e=0,f=0;e<d.length;e++)d[e].namespaceURI===a&&(c[f++]=d[e]);return c.length=f,c}};a.GetElementsByInterface=e,a.SelectorsInterface=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.nextSibling;return a}function c(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.previousSibling;return a}var d=a.wrappers.NodeList,e={get firstElementChild(){return b(this.firstChild)},get lastElementChild(){return c(this.lastChild)},get childElementCount(){for(var a=0,b=this.firstElementChild;b;b=b.nextElementSibling)a++;return a},get children(){for(var a=new d,b=0,c=this.firstElementChild;c;c=c.nextElementSibling)a[b++]=c;return a.length=b,a}},f={get nextElementSibling(){return b(this.nextSibling)},get previousElementSibling(){return c(this.previousSibling)}};a.ChildNodeInterface=f,a.ParentNodeInterface=e}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.enqueueMutation,f=a.mixin,g=a.registerWrapper,h=window.CharacterData;b.prototype=Object.create(d.prototype),f(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a},get data(){return this.impl.data},set data(a){var b=this.impl.data;e(this,"characterData",{oldValue:b}),this.impl.data=a}}),f(b.prototype,c),g(h,b,document.createTextNode("")),a.wrappers.CharacterData=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(b,c){var d=b.parentNode;if(d&&d.shadowRoot){var e=a.getRendererForHost(d);e.dependsOnAttribute(c)&&e.invalidate()}}function c(a,b,c){k(a,"attributes",{name:b,namespace:null,oldValue:c})}function d(a){h.call(this,a)}function e(a,c,d){var e=d||c;Object.defineProperty(a,c,{get:function(){return this.impl[c]},set:function(a){this.impl[c]=a,b(this,e)},configurable:!0,enumerable:!0})}var f=a.ChildNodeInterface,g=a.GetElementsByInterface,h=a.wrappers.Node,i=a.ParentNodeInterface,j=a.SelectorsInterface;a.addWrapNodeListMethod;var k=a.enqueueMutation,l=a.mixin,m=a.oneOf,n=a.registerWrapper,o=a.wrappers,p=window.Element,q=m(p.prototype,["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"]),r=p.prototype[q];d.prototype=Object.create(h.prototype),l(d.prototype,{createShadowRoot:function(){var b=new o.ShadowRoot(this);this.impl.polymerShadowRoot_=b;var c=a.getRendererForHost(this);return c.invalidate(),b},get shadowRoot(){return this.impl.polymerShadowRoot_||null},setAttribute:function(a,d){var e=this.impl.getAttribute(a);this.impl.setAttribute(a,d),c(this,a,e),b(this,a)},removeAttribute:function(a){var d=this.impl.getAttribute(a);this.impl.removeAttribute(a),c(this,a,d),b(this,a)},matches:function(a){return r.call(this.impl,a)}}),d.prototype[q]=function(a){return this.matches(a)},p.prototype.webkitCreateShadowRoot&&(d.prototype.webkitCreateShadowRoot=d.prototype.createShadowRoot),e(d.prototype,"id"),e(d.prototype,"className","class"),l(d.prototype,f),l(d.prototype,g),l(d.prototype,i),l(d.prototype,j),n(p,d),a.matchesName=q,a.wrappers.Element=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&";case"<":return"<";case'"':return"""}}function c(a){return a.replace(v,b)}function d(a){switch(a.nodeType){case Node.ELEMENT_NODE:for(var b,d=a.tagName.toLowerCase(),f="<"+d,g=a.attributes,h=0;b=g[h];h++)f+=" "+b.name+'="'+c(b.value)+'"';return f+=">",w[d]?f:f+e(a)+"</"+d+">";case Node.TEXT_NODE:return c(a.nodeValue);case Node.COMMENT_NODE:return"<!--"+c(a.nodeValue)+"-->";default:throw console.error(a),new Error("not implemented")}}function e(a){for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=d(c);return b}function f(a,b,c){var d=c||"div";a.textContent="";var e=t(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(u(f))}function g(a){l.call(this,a)}function h(b){return function(){return a.renderAllPending(),this.impl[b]}}function i(a){m(g,a,h(a))}function j(b){Object.defineProperty(g.prototype,b,{get:h(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function k(b){Object.defineProperty(g.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var l=a.wrappers.Element,m=a.defineGetter,n=a.enqueueMutation,o=a.mixin,p=a.nodesWereAdded,q=a.nodesWereRemoved,r=a.registerWrapper,s=a.snapshotNodeList,t=a.unwrap,u=a.wrap,v=/&|<|"/g,w={area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},x=window.HTMLElement;g.prototype=Object.create(l.prototype),o(g.prototype,{get innerHTML(){return e(this)},set innerHTML(a){var b=s(this.childNodes);this.invalidateShadowRenderer()?f(this,a,this.tagName):this.impl.innerHTML=a;var c=s(this.childNodes);n(this,"childList",{addedNodes:c,removedNodes:b}),q(b),p(c)},get outerHTML(){return d(this)},set outerHTML(a){var b=this.parentNode;b&&(b.invalidateShadowRenderer(),this.impl.outerHTML=a)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(i),["scrollLeft","scrollTop"].forEach(j),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(k),r(x,g,document.createElement("b")),a.wrappers.HTMLElement=g,a.getInnerHTML=e,a.setInnerHTML=f}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.HTMLCanvasElement;b.prototype=Object.create(c.prototype),d(b.prototype,{getContext:function(){var a=this.impl.getContext.apply(this.impl,arguments);return a&&f(a)}}),e(g,b,document.createElement("canvas")),a.wrappers.HTMLCanvasElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLContentElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get select(){return this.getAttribute("select")},set select(a){this.setAttribute("select",a)},setAttribute:function(a,b){c.prototype.setAttribute.call(this,a,b),"select"===String(a).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),f&&e(f,b),a.wrappers.HTMLContentElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a,b){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var e=f(document.createElement("img"));d.call(this,e),g(e,this),void 0!==a&&(e.width=a),void 0!==b&&(e.height=b)}var d=a.wrappers.HTMLElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLImageElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("img")),c.prototype=b.prototype,a.wrappers.HTMLImageElement=b,a.wrappers.Image=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLShadowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{}),f&&e(f,b),a.wrappers.HTMLShadowElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=o.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);o.set(a,b)}return b}function c(a){var c,d=b(a.ownerDocument),e=l(d.createDocumentFragment());for(h();c=a.firstChild;)e.appendChild(c);return k(),e}function d(a){if(e.call(this,a),!p){var b=c(a);n.set(this,m(b))}}var e=a.wrappers.HTMLElement,f=a.getInnerHTML,g=a.mixin,h=a.muteMutationEvents,i=a.registerWrapper,j=a.setInnerHTML,k=a.unmuteMutationEvents,l=a.unwrap,m=a.wrap,n=new WeakMap,o=new WeakMap,p=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),g(d.prototype,{get content(){return p?m(this.impl.content):n.get(this)},get innerHTML(){return f(this.content)},set innerHTML(a){j(this.content,a)}}),p&&i(p,d),a.wrappers.HTMLTemplateElement=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.registerWrapper,e=window.HTMLMediaElement;b.prototype=Object.create(c.prototype),d(e,b,document.createElement("audio")),a.wrappers.HTMLMediaElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var b=f(document.createElement("audio"));d.call(this,b),g(b,this),b.setAttribute("preload","auto"),void 0!==a&&b.setAttribute("src",a)}var d=a.wrappers.HTMLMediaElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLAudioElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("audio")),c.prototype=b.prototype,a.wrappers.HTMLAudioElement=b,a.wrappers.Audio=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a.replace(/\s+/g," ").trim()}function c(a){e.call(this,a)}function d(a,b,c,f){if(!(this instanceof d))throw new TypeError("DOM object constructor cannot be called as a function.");var g=i(document.createElement("option"));e.call(this,g),h(g,this),void 0!==a&&(g.text=a),void 0!==b&&g.setAttribute("value",b),c===!0&&g.setAttribute("selected",""),g.selected=f===!0}var e=a.wrappers.HTMLElement,f=a.mixin,g=a.registerWrapper,h=a.rewrap,i=a.unwrap,j=a.wrap,k=window.HTMLOptionElement;c.prototype=Object.create(e.prototype),f(c.prototype,{get text(){return b(this.textContent)},set text(a){this.textContent=b(String(a))},get form(){return j(i(this).form)}}),g(k,c,document.createElement("option")),d.prototype=c.prototype,a.wrappers.HTMLOptionElement=c,a.wrappers.Option=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a.localName){case"content":return new c(a);case"shadow":return new e(a);case"template":return new f(a)}d.call(this,a)}var c=a.wrappers.HTMLContentElement,d=a.wrappers.HTMLElement,e=a.wrappers.HTMLShadowElement,f=a.wrappers.HTMLTemplateElement;a.mixin;var g=a.registerWrapper,h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.unwrapIfNeeded,g=a.wrap,h=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return g(this.impl.canvas)},drawImage:function(){arguments[0]=f(arguments[0]),this.impl.drawImage.apply(this.impl,arguments)},createPattern:function(){return arguments[0]=e(arguments[0]),this.impl.createPattern.apply(this.impl,arguments)}}),d(h,b,document.createElement("canvas").getContext("2d")),a.wrappers.CanvasRenderingContext2D=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrapIfNeeded,f=a.wrap,g=window.WebGLRenderingContext;if(g){c(b.prototype,{get canvas(){return f(this.impl.canvas)},texImage2D:function(){arguments[5]=e(arguments[5]),this.impl.texImage2D.apply(this.impl,arguments)},texSubImage2D:function(){arguments[6]=e(arguments[6]),this.impl.texSubImage2D.apply(this.impl,arguments)}});var h=/WebKit/.test(navigator.userAgent)?{drawingBufferHeight:null,drawingBufferWidth:null}:{};d(g,b,h),a.wrappers.WebGLRenderingContext=b}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap,g=window.Range;b.prototype={get startContainer(){return f(this.impl.startContainer)},get endContainer(){return f(this.impl.endContainer)},get commonAncestorContainer(){return f(this.impl.commonAncestorContainer)},setStart:function(a,b){this.impl.setStart(e(a),b)},setEnd:function(a,b){this.impl.setEnd(e(a),b)},setStartBefore:function(a){this.impl.setStartBefore(e(a))},setStartAfter:function(a){this.impl.setStartAfter(e(a))},setEndBefore:function(a){this.impl.setEndBefore(e(a))},setEndAfter:function(a){this.impl.setEndAfter(e(a))},selectNode:function(a){this.impl.selectNode(e(a))},selectNodeContents:function(a){this.impl.selectNodeContents(e(a))},compareBoundaryPoints:function(a,b){return this.impl.compareBoundaryPoints(a,d(b))},extractContents:function(){return f(this.impl.extractContents())},cloneContents:function(){return f(this.impl.cloneContents())},insertNode:function(a){this.impl.insertNode(e(a))},surroundContents:function(a){this.impl.surroundContents(e(a))},cloneRange:function(){return f(this.impl.cloneRange())},isPointInRange:function(a,b){return this.impl.isPointInRange(e(a),b)},comparePoint:function(a,b){return this.impl.comparePoint(e(a),b)},intersectsNode:function(a){return this.impl.intersectsNode(e(a))}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b,document.createRange()),a.wrappers.Range=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.GetElementsByInterface,c=a.ParentNodeInterface,d=a.SelectorsInterface,e=a.mixin,f=a.registerObject,g=f(document.createDocumentFragment());e(g.prototype,c),e(g.prototype,d),e(g.prototype,b);var h=f(document.createTextNode("")),i=f(document.createComment(""));a.wrappers.Comment=i,a.wrappers.DocumentFragment=g,a.wrappers.Text=h}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=i(a.impl.ownerDocument.createDocumentFragment());c.call(this,b),g(b,this);var d=a.shadowRoot;k.set(this,d),j.set(this,a)}var c=a.wrappers.DocumentFragment,d=a.elementFromPoint,e=a.getInnerHTML,f=a.mixin,g=a.rewrap,h=a.setInnerHTML,i=a.unwrap,j=new WeakMap,k=new WeakMap;b.prototype=Object.create(c.prototype),f(b.prototype,{get innerHTML(){return e(this)},set innerHTML(a){h(this,a),this.invalidateShadowRenderer()},get olderShadowRoot(){return k.get(this)||null},get host(){return j.get(this)||null},invalidateShadowRenderer:function(){return j.get(this).invalidateShadowRenderer()},elementFromPoint:function(a,b){return d(this,this.ownerDocument,a,b)},getElementById:function(a){return this.querySelector("#"+a)}}),a.wrappers.ShadowRoot=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){a.previousSibling_=a.previousSibling,a.nextSibling_=a.nextSibling,a.parentNode_=a.parentNode}function c(a,c,e){var f=F(a),g=F(c),h=e?F(e):null;if(d(c),b(c),e)a.firstChild===e&&(a.firstChild_=e),e.previousSibling_=e.previousSibling;else{a.lastChild_=a.lastChild,a.lastChild===a.firstChild&&(a.firstChild_=a.firstChild);var i=G(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=F(a),d=c.parentNode;if(d){var e=G(d);b(a),a.previousSibling&&(a.previousSibling.nextSibling_=a),a.nextSibling&&(a.nextSibling.previousSibling_=a),e.lastChild===a&&(e.lastChild_=a),e.firstChild===a&&(e.firstChild_=a),d.removeChild(c)}}function e(a,b){g(b).push(a),x(a,b);var c=I.get(a);c||I.set(a,c=[]),c.push(b)}function f(a){H.set(a,[])}function g(a){return H.get(a)}function h(a){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}function i(a,b,c){for(var d=a.firstChild;d;d=d.nextSibling)if(b(d)){if(c(d)===!1)return}else i(d,b,c)}function j(a,b){var c=b.getAttribute("select");if(!c)return!0;if(c=c.trim(),!c)return!0;if(!(a instanceof y))return!1;if(!L.test(c))return!1;if(":"===c[0]&&!M.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<O.length;a++)O[a].render();O=[]}function l(){E=null,k()}function m(a){var b=K.get(a);return b||(b=new q(a),K.set(a,b)),b}function n(a){for(;a;a=a.parentNode)if(a instanceof C)return a;return null}function o(a){return m(a.host)}function p(a){this.skip=!1,this.node=a,this.childNodes=[]}function q(a){this.host=a,this.dirty=!1,this.invalidateAttributes(),this.associateNode(a)}function r(a){return a instanceof z}function s(a){return a instanceof z}function t(a){return a instanceof A}function u(a){return a instanceof A}function v(a){return a.shadowRoot}function w(a){for(var b=[],c=a.shadowRoot;c;c=c.olderShadowRoot)b.push(c);return b}function x(a,b){J.set(a,b)}var y=a.wrappers.Element,z=a.wrappers.HTMLContentElement,A=a.wrappers.HTMLShadowElement,B=a.wrappers.Node,C=a.wrappers.ShadowRoot;a.assert,a.mixin,a.muteMutationEvents;var D=a.oneOf;a.unmuteMutationEvents;var E,F=a.unwrap,G=a.wrap,H=new WeakMap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=/^[*.:#[a-zA-Z_|]/,M=new RegExp("^:("+["link","visited","target","enabled","disabled","checked","indeterminate","nth-child","nth-last-child","nth-of-type","nth-last-of-type","first-child","last-child","first-of-type","last-of-type","only-of-type"].join("|")+")"),N=D(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),O=[],P=new ArraySplice;P.equals=function(a,b){return F(a.node)===b},p.prototype={append:function(a){var b=new p(a);return this.childNodes.push(b),b},sync:function(a){if(!this.skip){for(var b=this.node,e=this.childNodes,f=h(F(b)),g=a||new WeakMap,i=P.calculateSplices(e,f),j=0,k=0,l=0,m=0;m<i.length;m++){for(var n=i[m];l<n.index;l++)k++,e[j++].sync(g);for(var o=n.removed.length,p=0;o>p;p++){var q=G(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&G(f[k]),p=0;r>p;p++){var t=e[j++],u=t.node;c(b,u,s),g.set(u,!0),t.sync(g)}l+=r}for(var m=l;m<e.length;m++)e[m].sync(g)}}},q.prototype={render:function(a){if(this.dirty){this.invalidateAttributes(),this.treeComposition();var b=this.host,c=b.shadowRoot;this.associateNode(b);for(var d=!e,e=a||new p(b),f=c.firstChild;f;f=f.nextSibling)this.renderNode(c,e,f,!1);d&&e.sync(),this.dirty=!1}},invalidate:function(){if(!this.dirty){if(this.dirty=!0,O.push(this),E)return;E=window[N](l,0)}},renderNode:function(a,b,c,d){if(v(c)){b=b.append(c);var e=m(c);e.dirty=!0,e.render(b)}else r(c)?this.renderInsertionPoint(a,b,c,d):t(c)?this.renderShadowInsertionPoint(a,b,c):this.renderAsAnyDomTree(a,b,c,d)},renderAsAnyDomTree:function(a,b,c,d){if(b=b.append(c),v(c)){var e=m(c);b.skip=!e.dirty,e.render(b)}else for(var f=c.firstChild;f;f=f.nextSibling)this.renderNode(a,b,f,d)},renderInsertionPoint:function(a,b,c,d){var e=g(c);if(e.length){this.associateNode(c);for(var f=0;f<e.length;f++){var h=e[f];r(h)&&d?this.renderInsertionPoint(a,b,h,d):this.renderAsAnyDomTree(a,b,h,d)}}else this.renderFallbackContent(a,b,c);this.associateNode(c.parentNode)},renderShadowInsertionPoint:function(a,b,c){var d=a.olderShadowRoot;if(d){x(d,c),this.associateNode(c.parentNode);for(var e=d.firstChild;e;e=e.nextSibling)this.renderNode(d,b,e,!0)}else this.renderFallbackContent(a,b,c)},renderFallbackContent:function(a,b,c){this.associateNode(c),this.associateNode(c.parentNode);for(var d=c.firstChild;d;d=d.nextSibling)this.renderAsAnyDomTree(a,b,d,!1)},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(a){if(a){var b=this.attributes;/\.\w+/.test(a)&&(b["class"]=!0),/#\w+/.test(a)&&(b.id=!0),a.replace(/\[\s*([^\s=\|~\]]+)/g,function(a,c){b[c]=!0})}},dependsOnAttribute:function(a){return this.attributes[a]},distribute:function(a,b){var c=this;i(a,s,function(a){f(a),c.updateDependentAttributes(a.getAttribute("select"));for(var d=0;d<b.length;d++){var g=b[d];void 0!==g&&j(g,a)&&(e(g,a),b[d]=void 0)}})},treeComposition:function(){for(var a=this.host,b=a.shadowRoot,c=[],d=a.firstChild;d;d=d.nextSibling)if(r(d)){var e=g(d);e&&e.length||(e=h(d)),c.push.apply(c,e)}else c.push(d);for(var f,j;b;){if(f=void 0,i(b,u,function(a){return f=a,!1}),j=f,this.distribute(b,c),j){var k=b.olderShadowRoot;if(k){b=k,x(b,j);continue}break}break}},associateNode:function(a){a.impl.polymerShadowRenderer_=this}},B.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},z.prototype.getDistributedNodes=function(){return k(),g(this)},A.prototype.nodeIsInserted_=z.prototype.nodeIsInserted_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=I,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=J,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(b){if(window[b]){d(!a.wrappers[b]);var i=function(a){c.call(this,a)};i.prototype=Object.create(c.prototype),e(i.prototype,{get form(){return h(g(this).form)}}),f(window[b],i,document.createElement(b.slice(4,-7))),a.wrappers[b]=i}}var c=a.wrappers.HTMLElement,d=a.assert,e=a.mixin,f=a.registerWrapper,g=a.unwrap,h=a.wrap,i=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOutputElement","HTMLSelectElement","HTMLTextAreaElement"];i.forEach(b)}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a)}function c(a){var c=document[a];b.prototype[a]=function(){return v(c.apply(this.impl,arguments))}}function d(a,b){y.call(b.impl,u(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof n&&f(a,b);for(var c=a.firstChild;c;c=c.nextSibling)e(c,b)}function f(a,b){var c=a.olderShadowRoot;c&&b.adoptNode(c)}function g(a){this.impl=a}function h(a,b){var c=document.implementation[b];a.prototype[b]=function(){return v(c.apply(this.impl,arguments))}}function i(a,b){var c=document.implementation[b];a.prototype[b]=function(){return c.apply(this.impl,arguments)}}var j=a.GetElementsByInterface,k=a.wrappers.Node,l=a.ParentNodeInterface,m=a.SelectorsInterface,n=a.wrappers.ShadowRoot,o=a.defineWrapGetter,p=a.elementFromPoint,q=a.forwardMethodsToWrapper,r=a.matchesName,s=a.mixin,t=a.registerWrapper,u=a.unwrap,v=a.wrap,w=a.wrapEventTargetMethods;a.wrapNodeList;var x=new WeakMap;b.prototype=Object.create(k.prototype),o(b,"documentElement"),o(b,"body"),o(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var y=document.adoptNode;if(s(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return p(this,this,a,b)}}),document.register){var z=document.register;b.prototype.register=function(b,c){function d(a){return a?(this.impl=a,void 0):c.extends?document.createElement(c.extends,b):document.createElement(b)}var e=c.prototype;if(a.nativePrototypeTable.get(e))throw new Error("NotSupportedError");for(var f,g=Object.getPrototypeOf(e),h=[];g&&!(f=a.nativePrototypeTable.get(g));)h.push(g),g=Object.getPrototypeOf(g);if(!f)throw new Error("NotSupportedError");for(var i=Object.create(f),j=h.length-1;j>=0;j--)i=Object.create(i);["createdCallback","enteredViewCallback","leftViewCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){b.apply(v(this),arguments)})});var k={prototype:i};return c.extends&&(k.extends=c.extends),z.call(u(this),b,k),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i),d},q([window.HTMLDocument||window.Document],["register"])}q([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild",r]),q([window.HTMLDocument||window.Document],["adoptNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById"]),s(b.prototype,j),s(b.prototype,l),s(b.prototype,m),s(b.prototype,{get implementation(){var a=x.get(this);return a?a:(a=new g(u(this).implementation),x.set(this,a),a)}}),t(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&t(window.HTMLDocument,b),w([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),t(window.DOMImplementation,g),q([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.unwrapIfNeeded,h=a.wrap,i=a.renderAllPending,j=window.Window;b.prototype=Object.create(c.prototype);var k=window.getComputedStyle;j.prototype.getComputedStyle=function(a,b){return i(),k.call(this||window,g(a),b)},["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){j.prototype[a]=function(){var b=h(this||window);return b[a].apply(b,arguments)}}),d(b.prototype,{getComputedStyle:function(a,b){return k.call(f(this),g(a),b)}}),e(j,b),a.wrappers.Window=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=c[a],d=window[b];if(d){var e=document.createElement(a),f=e.constructor;window[b]=f}}a.isWrapperFor;var c={a:"HTMLAnchorElement",applet:"HTMLAppletElement",area:"HTMLAreaElement",br:"HTMLBRElement",base:"HTMLBaseElement",body:"HTMLBodyElement",button:"HTMLButtonElement",dl:"HTMLDListElement",datalist:"HTMLDataListElement",data:"HTMLDataElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",hr:"HTMLHRElement",head:"HTMLHeadElement",h1:"HTMLHeadingElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",input:"HTMLInputElement",li:"HTMLLIElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",link:"HTMLLinkElement",map:"HTMLMapElement",marquee:"HTMLMarqueeElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",del:"HTMLModElement",ol:"HTMLOListElement",object:"HTMLObjectElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",time:"HTMLTimeElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",table:"HTMLTableElement",tr:"HTMLTableRowElement",thead:"HTMLTableSectionElement",tbody:"HTMLTableSectionElement",textarea:"HTMLTextAreaElement",track:"HTMLTrackElement",title:"HTMLTitleElement",ul:"HTMLUListElement",video:"HTMLVideoElement"};
-Object.keys(c).forEach(b),Object.getOwnPropertyNames(a.wrappers).forEach(function(b){window[b]=a.wrappers[b]}),a.knownElements=c}(window.ShadowDOMPolyfill),function(){var a=window.ShadowDOMPolyfill;a.wrap,Object.defineProperties(HTMLElement.prototype,{webkitShadowRoot:{get:function(){return this.shadowRoot}}}),HTMLElement.prototype.webkitCreateShadowRoot=HTMLElement.prototype.createShadowRoot,window.dartExperimentalFixupGetTag=function(b){function c(a){if(a instanceof d)return"NodeList";if(a instanceof e)return"ShadowRoot";if(window.MutationRecord&&a instanceof MutationRecord)return"MutationRecord";if(window.MutationObserver&&a instanceof MutationObserver)return"MutationObserver";if(a instanceof HTMLTemplateElement)return"HTMLTemplateElement";var c=f(a);if(a!==c){var g=a.constructor;if(g===c.constructor){var h=g._ShadowDOMPolyfill$cacheTag_;return h||(h=Object.prototype.toString.call(c),h=h.substring(8,h.length-1),g._ShadowDOMPolyfill$cacheTag_=h),h}a=c}return b(a)}var d=a.wrappers.NodeList,e=a.wrappers.ShadowRoot,f=a.unwrapIfNeeded;return c}}();var Platform={};!function(a){function b(a,b){var c="";return Array.prototype.forEach.call(a,function(a){c+=a.textContent+"\n\n"}),b||(c=c.replace(n,"")),c}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){var b=c(a);document.head.appendChild(b);var d=b.sheet.cssRules;return b.parentNode.removeChild(b),d}function e(a){for(var b=0,c=[];b<a.length;b++)c.push(a[b].cssText);return c.join("\n\n")}function f(a){a&&g().appendChild(document.createTextNode(a))}function g(){return h||(h=document.createElement("style"),h.setAttribute("ShadowCSSShim","")),h}var h,i={strictStyling:!1,registry:{},shimStyling:function(a,b,d){var e=this.isTypeExtension(d),g=this.registerDefinition(a,b,d);this.strictStyling&&this.applyScopeToContent(a,b),this.insertPolyfillDirectives(g.rootStyles),this.insertPolyfillRules(g.rootStyles);var h=this.stylesToShimmedCssText(g.scopeStyles,b,e);h+=this.extractPolyfillUnscopedRules(g.rootStyles),g.shimmedStyle=c(h),a&&(a.shimmedStyle=g.shimmedStyle);for(var i,j=0,k=g.rootStyles.length;k>j&&(i=g.rootStyles[j]);j++)i.parentNode.removeChild(i);f(h)},registerDefinition:function(a,b,c){var d=this.registry[b]={root:a,name:b,extendsName:c},e=a?a.querySelectorAll("style"):[];e=e?Array.prototype.slice.call(e,0):[],d.rootStyles=e,d.scopeStyles=d.rootStyles;var f=this.registry[d.extendsName];return!f||a&&!a.querySelector("shadow")||(d.scopeStyles=f.scopeStyles.concat(d.scopeStyles)),d},isTypeExtension:function(a){return a&&a.indexOf("-")<0},applyScopeToContent:function(a,b){a&&(Array.prototype.forEach.call(a.querySelectorAll("*"),function(a){a.setAttribute(b,"")}),Array.prototype.forEach.call(a.querySelectorAll("template"),function(a){this.applyScopeToContent(a.content,b)},this))},insertPolyfillDirectives:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillDirectivesInCssText(a.textContent)},this)},insertPolyfillDirectivesInCssText:function(a){return a.replace(o,function(a,b){return b.slice(0,-2)+"{"})},insertPolyfillRules:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillRulesInCssText(a.textContent)},this)},insertPolyfillRulesInCssText:function(a){return a.replace(p,function(a,b){return b.slice(0,-1)})},extractPolyfillUnscopedRules:function(a){var b="";return a&&Array.prototype.forEach.call(a,function(a){b+=this.extractPolyfillUnscopedRulesFromCssText(a.textContent)+"\n\n"},this),b},extractPolyfillUnscopedRulesFromCssText:function(a){for(var b,c="";b=q.exec(a);)c+=b[1].slice(0,-1)+"\n\n";return c},stylesToShimmedCssText:function(a,b,c){return this.shimAtHost(a,b,c)+this.shimScoping(a,b,c)},shimAtHost:function(a,b,c){return a?this.convertAtHostStyles(a,b,c):void 0},convertAtHostStyles:function(a,c,f){var g=b(a),h=this;return g=g.replace(j,function(a,b){return h.scopeHostCss(b,c,f)}),g=e(this.findAtHostRules(d(g),this.makeScopeMatcher(c,f)))},scopeHostCss:function(a,b,c){var d=this;return a.replace(k,function(a,e,f){return d.scopeHostSelector(e,b,c)+" "+f+"\n "})},scopeHostSelector:function(a,b,c){var d=[],e=a.split(","),f="[is="+b+"]";return e.forEach(function(a){a=a.trim(),a.match(l)?a=a.replace(l,c?f+"$1$3":b+"$1$3"):a.match(m)&&(a=c?f+a:b+a),d.push(a)},this),d.join(", ")},findAtHostRules:function(a,b){return Array.prototype.filter.call(a,this.isHostRule.bind(this,b))},isHostRule:function(a,b){return b.selectorText&&b.selectorText.match(a)||b.cssRules&&this.findAtHostRules(b.cssRules,a).length||b.type==CSSRule.WEBKIT_KEYFRAMES_RULE},shimScoping:function(a,b,c){return a?this.convertScopedStyles(a,b,c):void 0},convertScopedStyles:function(a,c,e){var f=b(a).replace(j,"");f=this.insertPolyfillHostInCssText(f),f=this.convertColonHost(f),f=this.convertPseudos(f),f=this.convertParts(f),f=this.convertCombinators(f);var g=d(f);return f=this.scopeRules(g,c,e)},convertPseudos:function(a){return a.replace(r," [pseudo=$1]")},convertParts:function(a){return a.replace(s," [part=$1]")},convertColonHost:function(a){return a.replace(t,function(a,b,c,d){return b=y,c?c.match(x)?b+c.replace(x,"")+d:b+c+d+", "+c+" "+b+d:b+d})},convertCombinators:function(a){return a.replace(/\^\^/g," ").replace(/\^/g," ")},scopeRules:function(a,b,c){var d="";return Array.prototype.forEach.call(a,function(a){a.selectorText&&a.style&&a.style.cssText?(d+=this.scopeSelector(a.selectorText,b,c,this.strictStyling)+" {\n ",d+=this.propertiesFromRule(a)+"\n}\n\n"):a.media?(d+="@media "+a.media.mediaText+" {\n",d+=this.scopeRules(a.cssRules,b),d+="\n}\n\n"):a.cssText&&(d+=a.cssText+"\n\n")},this),d},scopeSelector:function(a,b,c,d){var e=[],f=a.split(",");return f.forEach(function(a){a=a.trim(),this.selectorNeedsScoping(a,b,c)&&(a=d?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b,c)),e.push(a)},this),e.join(", ")},selectorNeedsScoping:function(a,b,c){var d=this.makeScopeMatcher(b,c);return!a.match(d)},makeScopeMatcher:function(a,b){var c=b?"\\[is=['\"]?"+a+"['\"]?\\]":a;return new RegExp("^("+c+")"+u,"m")},applySimpleSelectorScope:function(a,b,c){var d=c?"[is="+b+"]":b;return a.match(z)?(a=a.replace(y,d),a.replace(z,d+" ")):d+" "+a},applyStrictSelectorScope:function(a,b){var c=[" ",">","+","~"],d=a,e="["+b+"]";return c.forEach(function(a){var b=d.split(a);d=b.map(function(a){var b=a.trim().replace(z,"");return b&&c.indexOf(b)<0&&b.indexOf(e)<0&&(a=b.replace(/([^:]*)(:*)(.*)/,"$1"+e+"$2$3")),a}).join(a)}),d},insertPolyfillHostInCssText:function(a){return a.replace(v,x).replace(w,x)},propertiesFromRule:function(a){var b=a.style.cssText;return a.style.content&&!a.style.content.match(/['"]+/)&&(b="content: '"+a.style.content+"';\n"+a.style.cssText.replace(/content:[^;]*;/g,"")),b}},j=/@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,k=/([^{]*)({[\s\S]*?})/gim,l=/(.*)((?:\*)|(?:\:scope))(.*)/,m=/^[.\[:]/,n=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,o=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,p=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,q=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,r=/::(x-[^\s{,(]*)/gim,s=/::part\(([^)]*)\)/gim,t=/(-host)(?:\(([^)]*)\))?([^,{]*)/gim,u="([>\\s~+[.,{:][\\s\\S]*)?$",v=/@host/gim,w=/\:host/gim,x="-host",y="-host-no-combinator",z=/-host/gim;if(window.ShadowDOMPolyfill){f("style { display: none !important; }\n");var A=document.querySelector("head");A.insertBefore(g(),A.childNodes[0])}a.ShadowCSS=i}(window.Platform)}
\ No newline at end of file
+if(!HTMLElement.prototype.createShadowRoot||window.__forceShadowDomPolyfill){!function(){Element.prototype.webkitCreateShadowRoot&&(Element.prototype.webkitCreateShadowRoot=function(){return window.ShadowDOMPolyfill.wrapIfNeeded(this).createShadowRoot()})}(),function(a){"use strict";function b(){function a(a){b=a}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=[],c={};if(Object.observe(c,a),c.id=1,c.id=2,delete c.id,Object.deliverChangeRecords(a),3!==b.length)return!1;if("new"==b[0].type&&"updated"==b[1].type&&"deleted"==b[2].type)F="new",G="updated",H="reconfigured",I="deleted";else if("add"!=b[0].type||"update"!=b[1].type||"delete"!=b[2].type)return console.error("Unexpected change record names for Object.observe. Using dirty-checking instead"),!1;return Object.unobserve(c,a),c=[0],Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),2!=b.length?!1:b[0].type!=J||b[1].type!=J?!1:(Array.unobserve(c,a),!0)}function c(){if(a.document&&"securityPolicy"in a.document&&!a.document.securityPolicy.allowsEval)return!1;try{var b=new Function("","return true;");return b()}catch(c){return!1}}function d(a){return+a===a>>>0}function e(a){return+a}function f(a){return a===Object(a)}function g(a,b){return a===b?0!==a||1/a===1/b:M(a)&&M(b)?!0:a!==a&&b!==b}function h(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:U.test(a))}function i(a,b){if(b!==V)throw Error("Use Path.get to retrieve path objects");return""==a.trim()?this:d(a)?(this.push(a),this):(a.split(/\s*\.\s*/).filter(function(a){return a}).forEach(function(a){this.push(a)},this),L&&!K&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn()),void 0)}function j(a){if(a instanceof i)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=W[a];if(b)return b;if(!h(a))return X;var b=new i(a,V);return W[a]=b,b}function k(b){for(var c=0;Y>c&&b.check();)b.report(),c++;a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=c)}function l(a){for(var b in a)return!1;return!0}function m(a){return l(a.added)&&l(a.removed)&&l(a.changed)}function n(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function o(a,b){var c=b||(Array.isArray(a)?[]:{});for(var d in a)c[d]=a[d];return Array.isArray(a)&&(c.length=a.length),c}function p(a,b,c,d){if(this.closed=!1,this.object=a,this.callback=b,this.target=c,this.token=d,this.reporting=!0,K){var e=this;this.boundInternalCallback=function(a){e.internalCallback(a)}}q(this)}function q(a){$&&(Z.push(a),p._allObserversCount++)}function r(a,b,c,d){p.call(this,a,b,c,d),this.connect(),this.sync(!0)}function s(a,b,c,d){if(!Array.isArray(a))throw Error("Provided object is not an Array");r.call(this,a,b,c,d)}function t(a){this.arr=[],this.callback=a,this.isObserved=!0}function u(a,b,c,d,e,g,h){var b=b instanceof i?b:j(b);return b&&b.length&&f(a)?(p.call(this,a,c,d,e),this.valueFn=g,this.setValueFn=h,this.path=b,this.connect(),this.sync(!0),void 0):(this.value_=b?b.getValueFrom(a):void 0,this.value=g?g(this.value_):this.value_,this.closed=!0,void 0)}function v(a,b,c,d){p.call(this,void 0,a,b,c),this.valueFn=d,this.observed=[],this.values=[],this.value=void 0,this.oldValue=void 0,this.oldValues=void 0,this.changeFlags=void 0,this.started=!1}function w(a,b){if("function"==typeof Object.observe){var c=Object.getNotifier(a);return function(d,e){var f={object:a,type:d,name:b};2===arguments.length&&(f.oldValue=e),c.notify(f)}}}function x(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];db[g.type]?(g.name in c||(c[g.name]=g.oldValue),g.type!=G&&(g.type!=F?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}function y(a,b,c){return{index:a,removed:b,addedCount:c}}function z(){}function A(a,b,c,d,e,f){return ib.calcSplices(a,b,c,d,e,f)}function B(a,b,c,d){return c>b||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function C(a,b,c,d){for(var e=y(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=B(e.index,e.index+e.removed.length,i.index,i.index+i.addedCount);if(j>=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.index<i.index){var l=e.removed.slice(0,i.index-e.index);Array.prototype.push.apply(l,c),c=l}if(e.index+e.removed.length>i.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.index<e.index&&(e.index=i.index)}else f=!0}else if(e.index<i.index){f=!0,a.splice(h,0,e),h++;var n=e.addedCount-e.removed.length;i.index+=n,g+=n}}}f||a.push(e)}function D(a,b){for(var c=[],f=0;f<b.length;f++){var g=b[f];switch(g.type){case J:C(c,g.index,g.removed.slice(),g.addedCount);break;case F:case G:case I:if(!d(g.name))continue;var h=e(g.name);if(0>h)continue;C(c,h,[g.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(g))}}return c}function E(a,b){var c=[];return D(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?(b.removed[0]!==a[b.index]&&c.push(b),void 0):(c=c.concat(A(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)),void 0)}),c}var F="add",G="update",H="reconfigure",I="delete",J="splice",K=b(),L=c(),M=a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},N="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c},O="[$_a-zA-Z]",P="[$_a-zA-Z0-9]",Q=O+"+"+P+"*",R="(?:[0-9]|[1-9]+[0-9]+)",S="(?:"+Q+"|"+R+")",T="(?:"+S+")(?:\\s*\\.\\s*"+S+")*",U=new RegExp("^"+T+"$"),V={},W={};i.get=j,i.prototype=N({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a,b){for(var c=0;c<this.length;c++){if(null==a)return;b&&b.observe(a),a=a[this[c]]}return a},compiledGetValueFromFn:function(){var a=this.map(function(a){return d(a)?'["'+a+'"]':"."+a}),b="",c="obj";b+="if (obj != null";for(var e=0;e<this.length-1;e++){{this[e]}c+=a[e],b+=" &&\n "+c+" != null"}return b+=")\n",c+=a[e],b+=" return "+c+";\nelse\n return undefined;",new Function("obj",b)},setValueFrom:function(a,b){if(!this.length)return!1;for(var c=0;c<this.length-1;c++){if(!f(a))return!1;a=a[this[c]]}return f(a)?(a[this[c]]=b,!0):!1}});var X=new i("",V);X.valid=!1,X.getValueFrom=X.setValueFrom=function(){};var Y=1e3;p.prototype={internalCallback:function(a){this.closed||this.reporting&&this.check(a)&&(this.report(),this.testingResults&&(this.testingResults.anyChanged=!0))},close:function(){this.closed||(this.object&&"function"==typeof this.object.close&&this.object.close(),this.disconnect(),this.object=void 0,this.closed=!0)},deliver:function(a){this.closed||(K?(this.testingResults=a,Object.deliverChangeRecords(this.boundInternalCallback),this.testingResults=void 0):k(this))},report:function(){this.reporting&&(this.sync(!1),this.callback&&(this.reportArgs.push(this.token),this.invokeCallback(this.reportArgs)),this.reportArgs=void 0)},invokeCallback:function(a){try{this.callback.apply(this.target,a)}catch(b){p._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},reset:function(){this.closed||(K&&(this.reporting=!1,Object.deliverChangeRecords(this.boundInternalCallback),this.reporting=!0),this.sync(!0))}};var Z,$=!K||a.forceCollectObservers;p._allObserversCount=0,$&&(Z=[]);var _=!1,ab="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!_){if(ab)return Object.deliverAllChangeRecords(),void 0;if($){_=!0;var b=0,c={};do{b++;var d=Z;Z=[],c.anyChanged=!1;for(var e=0;e<d.length;e++){var f=d[e];f.closed||(K?f.deliver(c):f.check()&&(c.anyChanged=!0,f.report()),Z.push(f))}}while(Y>b&&c.anyChanged);a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=b),p._allObserversCount=Z.length,_=!1}}},$&&(a.Platform.clearObservers=function(){Z=[]}),r.prototype=N({__proto__:p.prototype,connect:function(){K&&Object.observe(this.object,this.boundInternalCallback)},sync:function(){K||(this.oldObject=o(this.object))},check:function(a){var b,c;if(K){if(!a)return!1;c={},b=x(this.object,a,c)}else c=this.oldObject,b=n(this.object,this.oldObject);return m(b)?!1:(this.reportArgs=[b.added||{},b.removed||{},b.changed||{}],this.reportArgs.push(function(a){return c[a]}),!0)},disconnect:function(){K?this.object&&Object.unobserve(this.object,this.boundInternalCallback):this.oldObject=void 0}}),s.prototype=N({__proto__:r.prototype,connect:function(){K&&Array.observe(this.object,this.boundInternalCallback)},sync:function(){K||(this.oldObject=this.object.slice())},check:function(a){var b;if(K){if(!a)return!1;b=E(this.object,a)}else b=A(this.object,0,this.object.length,this.oldObject,0,this.oldObject.length);return b&&b.length?(this.reportArgs=[b],!0):!1}}),s.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;e<c.index+c.addedCount;)d.push(b[e]),e++;Array.prototype.splice.apply(a,d)})};var bb=Object.getPrototypeOf({}),cb=Object.getPrototypeOf([]);t.prototype={reset:function(){this.isObserved=!this.isObserved},observe:function(a){if(f(a)&&a!==bb&&a!==cb){var b=this.arr.indexOf(a);b>=0&&this.arr[b+1]===this.isObserved||(0>b&&(b=this.arr.length,this.arr[b]=a,Object.observe(a,this.callback)),this.arr[b+1]=this.isObserved,this.observe(Object.getPrototypeOf(a)))}},cleanup:function(){for(var a=0,b=0,c=this.isObserved;b<this.arr.length;){var d=this.arr[b];this.arr[b+1]==c?(b>a&&(this.arr[a]=d,this.arr[a+1]=c),a+=2):Object.unobserve(d,this.callback),b+=2}this.arr.length=a}},u.prototype=N({__proto__:p.prototype,connect:function(){K&&(this.observedSet=new t(this.boundInternalCallback))},disconnect:function(){this.value=void 0,this.value_=void 0,this.observedSet&&(this.observedSet.reset(),this.observedSet.cleanup(),this.observedSet=void 0)},check:function(){return this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.observedSet&&this.observedSet.cleanup(),g(this.value_,this.oldValue_)?!1:(this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.reportArgs=[this.value,this.oldValue],!0)},sync:function(a){a&&(this.observedSet&&this.observedSet.reset(),this.value_=this.path.getValueFrom(this.object,this.observedSet),this.value=this.valueFn?this.valueFn(this.value_):this.value_,this.observedSet&&this.observedSet.cleanup()),this.oldValue_=this.value_,this.oldValue=this.value},setValue:function(a){this.path&&("function"==typeof this.setValueFn&&(a=this.setValueFn(a)),this.path.setValueFrom(this.object,a))}}),v.prototype=N({__proto__:u.prototype,addPath:function(a,b){if(this.started)throw Error("Cannot add more paths once started.");var b=b instanceof i?b:j(b),c=b?b.getValueFrom(a):void 0;this.observed.push(a,b),this.values.push(c)},start:function(){this.started=!0,this.connect(),this.sync(!0)},getValues:function(){this.observedSet&&this.observedSet.reset();for(var a=!1,b=0;b<this.observed.length;b+=2){var c=this.observed[b+1];if(c){var d=this.observed[b],e=c.getValueFrom(d,this.observedSet),f=this.values[b/2];if(!g(e,f)){if(!a&&!this.valueFn){this.oldValues=this.oldValues||[],this.changeFlags=this.changeFlags||[];for(var h=0;h<this.values.length;h++)this.oldValues[h]=this.values[h],this.changeFlags[h]=!1}this.valueFn||(this.changeFlags[b/2]=!0),this.values[b/2]=e,a=!0}}}return this.observedSet&&this.observedSet.cleanup(),a},check:function(){if(this.getValues()){if(this.valueFn){if(this.value=this.valueFn(this.values),g(this.value,this.oldValue))return!1;this.reportArgs=[this.value,this.oldValue]}else this.reportArgs=[this.values,this.oldValues,this.changeFlags,this.observed];return!0}},sync:function(a){a&&(this.getValues(),this.valueFn&&(this.value=this.valueFn(this.values))),this.valueFn&&(this.oldValue=this.value)},close:function(){if(this.observed){for(var a=0;a<this.observed.length;a+=2){var b=this.observed[a];b&&"function"==typeof b.close&&b.close()}this.observed=void 0,this.values=void 0}p.prototype.close.call(this)}});var db={};db[F]=!0,db[G]=!0,db[I]=!0,u.defineProperty=function(a,b,c,d){d=j(d);var e=w(a,b),f=new u(c,d,function(a,b){e&&e(G,b)});return Object.defineProperty(a,b,{get:function(){return d.getValueFrom(c)},set:function(a){d.setValueFrom(c,a)},configurable:!0}),{close:function(){var g=d.getValueFrom(c);e&&f.deliver(),f.close(),Object.defineProperty(a,b,{value:g,writable:!0,configurable:!0})}}};var eb=0,fb=1,gb=2,hb=3;z.prototype={calcEditDistances:function(a,b,c,d,e,f){for(var g=f-e+1,h=c-b+1,i=new Array(g),j=0;g>j;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(this.equals(a[b+k-1],d[e+j-1]))i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i},spliceOperationsFromEditDistances:function(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(eb):(e.push(fb),d=g),b--,c--):f==h?(e.push(hb),b--,d=h):(e.push(gb),c--,d=i)}else e.push(hb),b--;else e.push(gb),c--;return e.reverse(),e},calcSplices:function(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=this.sharedPrefix(a,d,i)),c==a.length&&f==d.length&&(h=this.sharedSuffix(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,c-b==0&&f-e==0)return[];if(b==c){for(var j=y(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[y(b,[],c-b)];for(var k=this.spliceOperationsFromEditDistances(this.calcEditDistances(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;o<k.length;o++)switch(k[o]){case eb:j&&(l.push(j),j=void 0),m++,n++;break;case fb:j||(j=y(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case gb:j||(j=y(m,[],0)),j.addedCount++,m++;break;case hb:j||(j=y(m,[],0)),j.removed.push(d[n]),n++}return j&&l.push(j),l},sharedPrefix:function(a,b,c){for(var d=0;c>d;d++)if(!this.equals(a[d],b[d]))return d;return c},sharedSuffix:function(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&this.equals(a[--d],b[--e]);)f++;return f},calculateSplices:function(a,b){return this.calcSplices(a,0,a.length,b,0,b.length)},equals:function(a,b){return a===b}};var ib=new z;a.Observer=p,a.Observer.hasObjectObserve=K,a.ArrayObserver=s,a.ArrayObserver.calculateSplices=function(a,b){return ib.calculateSplices(a,b)},a.ArraySplice=z,a.ObjectObserver=r,a.PathObserver=u,a.CompoundPathObserver=v,a.Path=i,a.Observer.changeRecordTypes={add:F,update:G,reconfigure:H,"delete":I,splice:J}}("undefined"!=typeof global&&global?global:this||window),"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}(),window.ShadowDOMPolyfill={},function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return L(b).forEach(function(c){K(a,c,M(b,c))}),a}function d(a,b){return L(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}K(a,c,M(b,c))}),a}function e(a,b){for(var c=0;c<b.length;c++)if(b[c]in a)return b[c]}function f(a){var b=a.__proto__||Object.getPrototypeOf(a),c=E.get(b);if(c)return c;var d=f(b),e=t(d);return q(b,e,a),e}function g(a,b){o(a,b,!0)}function h(a,b){o(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return/^\w[a-zA-Z_0-9]*$/.test(a)}function k(a){return H&&j(a)?new Function("return this.impl."+a):function(){return this.impl[a]}}function l(a){return H&&j(a)?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function m(a){return H&&j(a)?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function n(a,b){try{return Object.getOwnPropertyDescriptor(a,b)}catch(c){return O}}function o(b,c,d){for(var e=L(b),f=0;f<e.length;f++){var g=e[f];if("polymerBlackList_"!==g&&!(g in c||b.polymerBlackList_&&b.polymerBlackList_[g])){N&&b.__lookupGetter__(g);var h,j,o=n(b,g);if(d&&"function"==typeof o.value)c[g]=m(g);else{var p=i(g);h=p?a.getEventHandlerGetter(g):k(g),(o.writable||o.set)&&(j=p?a.getEventHandlerSetter(g):l(g)),K(c,g,{get:h,set:j,configurable:o.configurable,enumerable:o.enumerable})}}}}function p(a,b,c){var e=a.prototype;q(e,b,c),d(b,a)}function q(a,c,d){var e=c.prototype;b(void 0===E.get(a)),E.set(a,c),F.set(e,a),g(a,e),d&&h(e,d),K(e,"constructor",{value:c,configurable:!0,enumerable:!1,writable:!0})}function r(a,b){return E.get(b.prototype)===a}function s(a){var b=Object.getPrototypeOf(a),c=f(b),d=t(c);return q(b,d,a),d}function t(a){function b(b){a.call(this,b)}return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b}function u(a){return a instanceof G.EventTarget||a instanceof G.Event||a instanceof G.Range||a instanceof G.DOMImplementation||a instanceof G.CanvasRenderingContext2D||G.WebGLRenderingContext&&a instanceof G.WebGLRenderingContext}function v(a){return a instanceof R||a instanceof Q||a instanceof S||a instanceof T||a instanceof P||a instanceof U||V&&a instanceof V}function w(a){return null===a?null:(b(v(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function x(a){return null===a?null:(b(u(a)),a.impl)}function y(a){return a&&u(a)?x(a):a}function z(a){return a&&!u(a)?w(a):a}function A(a,c){null!==c&&(b(v(a)),b(void 0===c||u(c)),a.polymerWrapper_=c)}function B(a,b,c){K(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function C(a,b){B(a,b,function(){return w(this.impl[b])})}function D(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=z(this);return a[b].apply(a,arguments)}})})}var E=new WeakMap,F=new WeakMap,G=Object.create(null),H=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(H)try{var I=new Function("","return true;");H=I()}catch(J){H=!1}var K=Object.defineProperty,L=Object.getOwnPropertyNames,M=Object.getOwnPropertyDescriptor;L(window);var N=/Firefox/.test(navigator.userAgent),O={get:function(){},set:function(){},configurable:!0,enumerable:!0},P=window.DOMImplementation,Q=window.Event,R=window.Node,S=window.Window,T=window.Range,U=window.CanvasRenderingContext2D,V=window.WebGLRenderingContext;a.assert=b,a.constructorTable=E,a.defineGetter=B,a.defineWrapGetter=C,a.forwardMethodsToWrapper=D,a.isWrapperFor=r,a.mixin=c,a.nativePrototypeTable=F,a.oneOf=e,a.registerObject=s,a.registerWrapper=p,a.rewrap=A,a.unwrap=x,a.unwrapIfNeeded=y,a.wrap=w,a.wrapIfNeeded=z,a.wrappers=G}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){g=!1;var a=f.slice(0);f=[];for(var b=0;b<a.length;b++)a[b]()}function c(a){f.push(a),g||(g=!0,d(b,0))}var d,e=window.MutationObserver,f=[],g=!1;if(e){var h=1,i=new e(b),j=document.createTextNode(h);i.observe(j,{characterData:!0}),d=function(){h=(h+1)%2,j.data=h}}else d=window.setImmediate||window.setTimeout;a.setEndOfMicrotask=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){p||(k(c),p=!0)}function c(){p=!1;do for(var a=o.slice(),b=!1,c=0;c<a.length;c++){var d=a[c],e=d.takeRecords();f(d),e.length&&(d.callback_(e,d),b=!0)}while(b)}function d(a,b){this.type=a,this.target=b,this.addedNodes=new m.NodeList,this.removedNodes=new m.NodeList,this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function e(a,b){for(;a;a=a.parentNode){var c=n.get(a);if(c)for(var d=0;d<c.length;d++){var e=c[d];e.options.subtree&&e.addTransientObserver(b)}}}function f(a){for(var b=0;b<a.nodes_.length;b++){var c=a.nodes_[b],d=n.get(c);if(!d)return;for(var e=0;e<d.length;e++){var f=d[e];f.observer===a&&f.removeTransientObservers()}}}function g(a,c,e){for(var f=Object.create(null),g=Object.create(null),h=a;h;h=h.parentNode){var i=n.get(h);if(i)for(var j=0;j<i.length;j++){var k=i[j],l=k.options;if((h===a||l.subtree)&&!("attributes"===c&&!l.attributes||"attributes"===c&&l.attributeFilter&&(null!==e.namespace||-1===l.attributeFilter.indexOf(e.name))||"characterData"===c&&!l.characterData||"childList"===c&&!l.childList)){var m=k.observer;f[m.uid_]=m,("attributes"===c&&l.attributeOldValue||"characterData"===c&&l.characterDataOldValue)&&(g[m.uid_]=e.oldValue)}}}var o=!1;for(var p in f){var m=f[p],q=new d(c,a);"name"in e&&"namespace"in e&&(q.attributeName=e.name,q.attributeNamespace=e.namespace),e.addedNodes&&(q.addedNodes=e.addedNodes),e.removedNodes&&(q.removedNodes=e.removedNodes),e.previousSibling&&(q.previousSibling=e.previousSibling),e.nextSibling&&(q.nextSibling=e.nextSibling),void 0!==g[p]&&(q.oldValue=g[p]),m.records_.push(q),o=!0}o&&b()}function h(a){if(this.childList=!!a.childList,this.subtree=!!a.subtree,this.attributes="attributes"in a||!("attributeOldValue"in a||"attributeFilter"in a)?!!a.attributes:!0,this.characterData="characterDataOldValue"in a&&!("characterData"in a)?!0:!!a.characterData,!this.attributes&&(a.attributeOldValue||"attributeFilter"in a)||!this.characterData&&a.characterDataOldValue)throw new TypeError;if(this.characterData=!!a.characterData,this.attributeOldValue=!!a.attributeOldValue,this.characterDataOldValue=!!a.characterDataOldValue,"attributeFilter"in a){if(null==a.attributeFilter||"object"!=typeof a.attributeFilter)throw new TypeError;this.attributeFilter=q.call(a.attributeFilter)}else this.attributeFilter=null}function i(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++r,o.push(this)}function j(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var k=a.setEndOfMicrotask,l=a.wrapIfNeeded,m=a.wrappers,n=new WeakMap,o=[],p=!1,q=Array.prototype.slice,r=0;i.prototype={observe:function(a,b){a=l(a);var c,d=new h(b),e=n.get(a);e||n.set(a,e=[]);for(var f=0;f<e.length;f++)e[f].observer===this&&(c=e[f],c.removeTransientObservers(),c.options=d);c||(c=new j(this,a,d),e.push(c),this.nodes_.push(a))},disconnect:function(){this.nodes_.forEach(function(a){for(var b=n.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}},j.prototype={addTransientObserver:function(a){if(a!==this.target){this.transientObservedNodes.push(a);var b=n.get(a);b||n.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[];for(var b=0;b<a.length;b++)for(var c=a[b],d=n.get(c),e=0;e<d.length;e++)if(d[e]===this){d.splice(e,1);break}}},a.enqueueMutation=g,a.registerTransientObservers=e,a.wrappers.MutationObserver=i,a.wrappers.MutationRecord=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof O.ShadowRoot}function c(a){var b=a.localName;return"content"===b||"shadow"===b}function d(a){return!!a.shadowRoot}function e(a){var b;return a.parentNode||(b=a.defaultView)&&N(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||f.host;var i=a.eventParentsTable.get(f);if(i){for(var k=1;k<i.length;k++)h[k-1]=i[k];return i[0]}if(g&&c(f)){var l=f.parentNode;if(l&&d(l))for(var m=a.getShadowTrees(l),n=j(g),k=0;k<m.length;k++)if(m[k].contains(n))return n}return e(f)}function g(a){for(var d=[],e=a,g=[],i=[];e;){var j=null;if(c(e)){j=h(d);var k=d[d.length-1]||e;d.push(k)}else d.length||d.push(e);var l=d[d.length-1];g.push({target:l,currentTarget:e}),b(e)&&d.pop(),e=f(e,j,i)}return g}function h(a){for(var b=a.length-1;b>=0;b--)if(!c(a[b]))return a[b];return null}function i(a,d){for(var e=[];a;){for(var g=[],i=d,j=void 0;i;){var l=null;if(g.length){if(c(i)&&(l=h(g),k(j))){var n=g[g.length-1];g.push(n)}}else g.push(i);if(m(i,a))return g[g.length-1];b(i)&&g.pop(),j=i,i=f(i,l,e)}a=b(a)?a.host:a.parentNode}}function j(b){return a.insertionParentTable.get(b)}function k(a){return j(a)}function l(a){for(var b;b=a.parentNode;)a=b;return a}function m(a,b){return l(a)===l(b)}function n(a,b){return a===b?!0:a instanceof O.ShadowRoot?n(l(a.host),b):!1}function o(b){if(!Q.get(b)){Q.set(b,!0),a.renderAllPending();var c=N(b.target),d=N(b);return p(d,c)}}function p(a,b){var c=g(b);return"load"===a.type&&2===c.length&&c[0].target instanceof O.Document&&c.shift(),Y.set(a,c),q(a,c)&&r(a,c)&&s(a,c),U.set(a,v.NONE),S.set(a,null),a.defaultPrevented}function q(a,b){for(var c,d=b.length-1;d>0;d--){var e=b[d].target,f=b[d].currentTarget;if(e!==f&&(c=v.CAPTURING_PHASE,!t(b[d],a,c)))return!1}return!0}function r(a,b){var c=v.AT_TARGET;return t(b[0],a,c)}function s(a,b){for(var c,d=a.bubbles,e=1;e<b.length;e++){var f=b[e].target,g=b[e].currentTarget;if(f===g)c=v.AT_TARGET;else{if(!d||W.get(a))continue;c=v.BUBBLING_PHASE}if(!t(b[e],a,c))return}}function t(a,b,c){var d=a.target,e=a.currentTarget,f=P.get(e);if(!f)return!0;if("relatedTarget"in b){var g=M(b);if(g.relatedTarget){var h=N(g.relatedTarget),j=i(e,h);if(j===d)return!0;T.set(b,j)}}U.set(b,c);var k=b.type,l=!1;R.set(b,d),S.set(b,e);for(var m=0;m<f.length;m++){var n=f[m];if(n.removed)l=!0;else if(!(n.type!==k||!n.capture&&c===v.CAPTURING_PHASE||n.capture&&c===v.BUBBLING_PHASE))try{if("function"==typeof n.handler?n.handler.call(e,b):n.handler.handleEvent(b),W.get(b))return!1}catch(o){window.onerror?window.onerror(o.message):console.error(o,o.stack)}}if(l){var p=f.slice();f.length=0;for(var m=0;m<p.length;m++)p[m].removed||f.push(p[m])}return!V.get(b)}function u(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function v(a,b){return a instanceof Z?(this.impl=a,void 0):N(z(Z,"Event",a,b))}function w(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:M(a.relatedTarget)}}):a}function x(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?(this.impl=b,void 0):N(z(d,a,b,c))};return e.prototype=Object.create(b.prototype),c&&K(e.prototype,c),d&&(d.prototype["init"+a]?L(d,e,document.createEvent(a)):L(d,e,new d("temp"))),e}function y(a,b){return function(){arguments[b]=M(arguments[b]);var c=M(this);c[a].apply(c,arguments)}}function z(a,b,c,d){if(gb)return new a(c,w(d));var e=M(document.createEvent(b)),f=fb[b],g=[c];return Object.keys(f).forEach(function(a){var b=null!=d&&a in d?d[a]:f[a];"relatedTarget"===a&&(b=M(b)),g.push(b)}),e["init"+b].apply(e,g),e}function A(){v.call(this)}function B(a){return"function"==typeof a?!0:a&&a.handleEvent}function C(a){switch(a){case"DOMAttrModified":case"DOMAttributeNameChanged":case"DOMCharacterDataModified":case"DOMElementNameChanged":case"DOMNodeInserted":case"DOMNodeInsertedIntoDocument":case"DOMNodeRemoved":case"DOMNodeRemovedFromDocument":case"DOMSubtreeModified":return!0}return!1}function D(a){this.impl=a}function E(a){return a instanceof O.ShadowRoot&&(a=a.host),M(a)}function F(a){J(a,jb)}function G(b,c,d,e){a.renderAllPending();for(var f=N(kb.call(c.impl,d,e)),h=g(f,this),i=0;i<h.length;i++){var j=h[i];if(j.currentTarget===b)return j.target}return null}function H(a){return function(){var b=X.get(this);return b&&b[a]&&b[a].value||null}}function I(a){var b=a.slice(2);return function(c){var d=X.get(this);d||(d=Object.create(null),X.set(this,d));var e=d[a];if(e&&this.removeEventListener(b,e.wrapped,!1),"function"==typeof c){var f=function(b){var d=c.call(this,b);d===!1?b.preventDefault():"onbeforeunload"===a&&"string"==typeof d&&(b.returnValue=d)};this.addEventListener(b,f,!1),d[a]={value:c,wrapped:f}}}}var J=a.forwardMethodsToWrapper,K=a.mixin,L=a.registerWrapper,M=a.unwrap,N=a.wrap,O=a.wrappers,P=(new WeakMap,new WeakMap),Q=new WeakMap,R=new WeakMap,S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap;u.prototype={equals:function(a){return this.handler===a.handler&&this.type===a.type&&this.capture===a.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var Z=window.Event;Z.prototype.polymerBlackList_={returnValue:!0},v.prototype={get target(){return R.get(this)},get currentTarget(){return S.get(this)},get eventPhase(){return U.get(this)},get path(){var a=new O.NodeList,b=Y.get(this);if(b){for(var c=0,d=b.length-1,e=l(S.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=l(g);n(e,h)&&(f!==d||g instanceof O.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){V.set(this,!0)},stopImmediatePropagation:function(){V.set(this,!0),W.set(this,!0)}},L(Z,v,document.createEvent("Event"));var $=x("UIEvent",v),_=x("CustomEvent",v),ab={get relatedTarget(){return T.get(this)||N(M(this).relatedTarget)}},bb=K({initMouseEvent:y("initMouseEvent",14)},ab),cb=K({initFocusEvent:y("initFocusEvent",5)},ab),db=x("MouseEvent",$,bb),eb=x("FocusEvent",$,cb),fb=Object.create(null),gb=function(){try{new window.MouseEvent("click")}catch(a){return!1}return!0}();if(!gb){var hb=function(a,b,c){if(c){var d=fb[c];b=K(K({},d),b)}fb[a]=b};hb("Event",{bubbles:!1,cancelable:!1}),hb("CustomEvent",{detail:null},"Event"),hb("UIEvent",{view:null,detail:0},"Event"),hb("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),hb("FocusEvent",{relatedTarget:null},"UIEvent")}A.prototype=Object.create(v.prototype),K(A.prototype,{get returnValue(){return this.impl.returnValue},set returnValue(a){this.impl.returnValue=a}});var ib=window.EventTarget,jb=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(a){var b=a.prototype;jb.forEach(function(a){Object.defineProperty(b,a+"_",{value:b[a]})})}),D.prototype={addEventListener:function(a,b,c){if(B(b)&&!C(a)){var d=new u(a,b,c),e=P.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],P.set(this,e);e.push(d);var g=E(this);g.addEventListener_(a,o,!0)}},removeEventListener:function(a,b,c){c=Boolean(c);var d=P.get(this);if(d){for(var e=0,f=!1,g=0;g<d.length;g++)d[g].type===a&&d[g].capture===c&&(e++,d[g].handler===b&&(f=!0,d[g].remove()));if(f&&1===e){var h=E(this);h.removeEventListener_(a,o,!0)}}},dispatchEvent:function(a){var b=E(this),c=M(a);return Q.set(c,!1),b.dispatchEvent_(c)}},ib&&L(ib,D);var kb=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=G,a.getEventHandlerGetter=H,a.getEventHandlerSetter=I,a.wrapEventTargetMethods=F,a.wrappers.BeforeUnloadEvent=A,a.wrappers.CustomEvent=_,a.wrappers.Event=v,a.wrappers.EventTarget=D,a.wrappers.FocusEvent=eb,a.wrappers.MouseEvent=db,a.wrappers.UIEvent=$}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){Object.defineProperty(a,b,{enumerable:!1})}function c(){this.length=0,b(this,"length")}function d(a){if(null==a)return a;for(var b=new c,d=0,e=a.length;e>d;d++)b[d]=f(a[d]);return b.length=e,b}function e(a,b){a.prototype[b]=function(){return d(this.impl[b].apply(this.impl,arguments))}}var f=a.wrap;c.prototype={item:function(a){return this[a]}},b(c.prototype,"item"),a.wrappers.NodeList=c,a.addWrapNodeListMethod=e,a.wrapNodeList=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){v(a instanceof s)}function c(a){var b=new u;return b[0]=a,b.length=1,b}function d(a,b,c){x(b,"childList",{removedNodes:c,previousSibling:a.previousSibling,nextSibling:a.nextSibling})}function e(a,b){x(a,"childList",{removedNodes:b})}function f(a,b,d,e){if(a instanceof DocumentFragment){var f=h(a);E=!0;for(var g=f.length-1;g>=0;g--)a.removeChild(f[g]),f[g].parentNode_=b;E=!1;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||d,f[g].nextSibling_=f[g+1]||e;return d&&(d.nextSibling_=f[0]),e&&(e.previousSibling_=f[f.length-1]),f
+}var f=c(a),i=a.parentNode;return i&&i.removeChild(a),a.parentNode_=b,a.previousSibling_=d,a.nextSibling_=e,d&&(d.nextSibling_=a),e&&(e.previousSibling_=a),f}function g(a){if(a instanceof DocumentFragment)return h(a);var b=c(a),e=a.parentNode;return e&&d(a,e,b),b}function h(a){for(var b=new u,c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b.length=c,e(a,b),b}function i(a){return a}function j(a){a.nodeIsInserted_()}function k(a){for(var b=0;b<a.length;b++)j(a[b])}function l(){}function m(){}function n(a,b){var c=a.nodeType===s.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function o(b,c){if(c.length){var d=b.ownerDocument;if(d!==c[0].ownerDocument)for(var e=0;e<c.length;e++)a.adoptNodeNoRemove(c[e],d)}}function p(a,b){o(a,b);var c=b.length;if(1===c)return B(b[0]);for(var d=B(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(B(b[e]));return d}function q(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){v(b.parentNode===a);var c=b.nextSibling,d=B(b),e=d.parentNode;e&&J.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=B(a),g=f.firstChild;g;)c=g.nextSibling,J.call(f,g),g=c}function r(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function s(a){v(a instanceof F),t.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0}var t=a.wrappers.EventTarget,u=a.wrappers.NodeList,v=a.assert,w=a.defineWrapGetter,x=a.enqueueMutation,y=a.mixin,z=a.registerTransientObservers,A=a.registerWrapper,B=a.unwrap,C=a.wrap,D=a.wrapIfNeeded,E=!1,F=window.Node,G=window.DocumentFragment,H=(F.prototype.appendChild,F.prototype.compareDocumentPosition),I=F.prototype.insertBefore,J=F.prototype.removeChild,K=F.prototype.replaceChild,L=/Trident/.test(navigator.userAgent),M=L?function(a,b){try{J.call(a,b)}catch(c){if(!(a instanceof G))throw c}}:function(a,b){J.call(a,b)};s.prototype=Object.create(t.prototype),y(s.prototype,{appendChild:function(a){return this.insertBefore(a,null)},insertBefore:function(a,c){b(a),c=c||null,c&&b(c),c&&v(c.parentNode===this);var d,e=c?c.previousSibling:this.lastChild,h=!this.invalidateShadowRenderer()&&!r(a);if(d=h?g(a):f(a,this,e,c),h)n(this,a),I.call(this.impl,B(a),B(c));else{e||(this.firstChild_=d[0]),c||(this.lastChild_=d[d.length-1]);var i=B(c),j=i?i.parentNode:this.impl;j?I.call(j,p(this,d),i):o(this,d)}return x(this,"childList",{addedNodes:d,nextSibling:c,previousSibling:e}),k(d),a},removeChild:function(a){if(b(a),a.parentNode!==this){for(var d=!1,e=(this.childNodes,this.firstChild);e;e=e.nextSibling)if(e===a){d=!0;break}if(!d)throw new Error("NotFoundError")}var f=B(a),g=a.nextSibling,h=a.previousSibling;if(this.invalidateShadowRenderer()){var i=this.firstChild,j=this.lastChild,k=f.parentNode;k&&M(k,f),i===a&&(this.firstChild_=g),j===a&&(this.lastChild_=h),h&&(h.nextSibling_=g),g&&(g.previousSibling_=h),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else M(this.impl,f);return E||x(this,"childList",{removedNodes:c(a),nextSibling:g,previousSibling:h}),z(this,a),a},replaceChild:function(a,d){if(b(a),b(d),d.parentNode!==this)throw new Error("NotFoundError");var e,h=B(d),i=d.nextSibling,j=d.previousSibling,m=!this.invalidateShadowRenderer()&&!r(a);return m?e=g(a):(i===a&&(i=a.nextSibling),e=f(a,this,j,i)),m?(n(this,a),K.call(this.impl,B(a),h)):(this.firstChild===d&&(this.firstChild_=e[0]),this.lastChild===d&&(this.lastChild_=e[e.length-1]),d.previousSibling_=d.nextSibling_=d.parentNode_=void 0,h.parentNode&&K.call(h.parentNode,p(this,e),h)),x(this,"childList",{addedNodes:e,removedNodes:c(d),nextSibling:i,previousSibling:j}),l(d),k(e),d},nodeIsInserted_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeIsInserted_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:C(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:C(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:C(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:C(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:C(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==s.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)a+=b.textContent;return a},set textContent(a){var b=i(this.childNodes);if(this.invalidateShadowRenderer()){if(q(this),""!==a){var c=this.impl.ownerDocument.createTextNode(a);this.appendChild(c)}}else this.impl.textContent=a;var d=i(this.childNodes);x(this,"childList",{addedNodes:d,removedNodes:b}),m(b),k(d)},get childNodes(){for(var a=new u,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){var b=C(this.impl.cloneNode(!1));if(a)for(var c=this.firstChild;c;c=c.nextSibling)b.appendChild(c.cloneNode(!0));return b},contains:function(a){if(!a)return!1;if(a=D(a),a===this)return!0;var b=a.parentNode;return b?this.contains(b):!1},compareDocumentPosition:function(a){return H.call(this.impl,B(a))}}),w(s,"ownerDocument"),A(F,s,document.createDocumentFragment()),delete s.prototype.querySelector,delete s.prototype.querySelectorAll,s.prototype=y(Object.create(t.prototype),s.prototype),a.nodeWasAdded=j,a.nodeWasRemoved=l,a.nodesWereAdded=k,a.nodesWereRemoved=m,a.snapshotNodeList=i,a.wrappers.Node=s}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,c){for(var d,e=a.firstElementChild;e;){if(e.matches(c))return e;if(d=b(e,c))return d;e=e.nextElementSibling}return null}function c(a,b,d){for(var e=a.firstElementChild;e;)e.matches(b)&&(d[d.length++]=e),c(e,b,d),e=e.nextElementSibling;return d}var d={querySelector:function(a){return b(this,a)},querySelectorAll:function(a){return c(this,a,new NodeList)}},e={getElementsByTagName:function(a){return this.querySelectorAll(a)},getElementsByClassName:function(a){return this.querySelectorAll("."+a)},getElementsByTagNameNS:function(a,b){if("*"===a)return this.getElementsByTagName(b);for(var c=new NodeList,d=this.getElementsByTagName(b),e=0,f=0;e<d.length;e++)d[e].namespaceURI===a&&(c[f++]=d[e]);return c.length=f,c}};a.GetElementsByInterface=e,a.SelectorsInterface=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.nextSibling;return a}function c(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.previousSibling;return a}var d=a.wrappers.NodeList,e={get firstElementChild(){return b(this.firstChild)},get lastElementChild(){return c(this.lastChild)},get childElementCount(){for(var a=0,b=this.firstElementChild;b;b=b.nextElementSibling)a++;return a},get children(){for(var a=new d,b=0,c=this.firstElementChild;c;c=c.nextElementSibling)a[b++]=c;return a.length=b,a}},f={get nextElementSibling(){return b(this.nextSibling)},get previousElementSibling(){return c(this.previousSibling)}};a.ChildNodeInterface=f,a.ParentNodeInterface=e}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.enqueueMutation,f=a.mixin,g=a.registerWrapper,h=window.CharacterData;b.prototype=Object.create(d.prototype),f(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a},get data(){return this.impl.data},set data(a){var b=this.impl.data;e(this,"characterData",{oldValue:b}),this.impl.data=a}}),f(b.prototype,c),g(h,b,document.createTextNode("")),a.wrappers.CharacterData=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(b,c){var d=b.parentNode;if(d&&d.shadowRoot){var e=a.getRendererForHost(d);e.dependsOnAttribute(c)&&e.invalidate()}}function c(a,b,c){k(a,"attributes",{name:b,namespace:null,oldValue:c})}function d(a){h.call(this,a)}function e(a,c,d){var e=d||c;Object.defineProperty(a,c,{get:function(){return this.impl[c]},set:function(a){this.impl[c]=a,b(this,e)},configurable:!0,enumerable:!0})}var f=a.ChildNodeInterface,g=a.GetElementsByInterface,h=a.wrappers.Node,i=a.ParentNodeInterface,j=a.SelectorsInterface,k=(a.addWrapNodeListMethod,a.enqueueMutation),l=a.mixin,m=a.oneOf,n=a.registerWrapper,o=a.wrappers,p=window.Element,q=m(p.prototype,["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"]),r=p.prototype[q];d.prototype=Object.create(h.prototype),l(d.prototype,{createShadowRoot:function(){var b=new o.ShadowRoot(this);this.impl.polymerShadowRoot_=b;var c=a.getRendererForHost(this);return c.invalidate(),b},get shadowRoot(){return this.impl.polymerShadowRoot_||null},setAttribute:function(a,d){var e=this.impl.getAttribute(a);this.impl.setAttribute(a,d),c(this,a,e),b(this,a)},removeAttribute:function(a){var d=this.impl.getAttribute(a);this.impl.removeAttribute(a),c(this,a,d),b(this,a)},matches:function(a){return r.call(this.impl,a)}}),d.prototype[q]=function(a){return this.matches(a)},p.prototype.webkitCreateShadowRoot&&(d.prototype.webkitCreateShadowRoot=d.prototype.createShadowRoot),e(d.prototype,"id"),e(d.prototype,"className","class"),l(d.prototype,f),l(d.prototype,g),l(d.prototype,i),l(d.prototype,j),n(p,d),a.matchesName=q,a.wrappers.Element=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&";case"<":return"<";case'"':return"""}}function c(a){return a.replace(v,b)}function d(a){switch(a.nodeType){case Node.ELEMENT_NODE:for(var b,d=a.tagName.toLowerCase(),f="<"+d,g=a.attributes,h=0;b=g[h];h++)f+=" "+b.name+'="'+c(b.value)+'"';return f+=">",w[d]?f:f+e(a)+"</"+d+">";case Node.TEXT_NODE:return c(a.nodeValue);case Node.COMMENT_NODE:return"<!--"+c(a.nodeValue)+"-->";default:throw console.error(a),new Error("not implemented")}}function e(a){for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=d(c);return b}function f(a,b,c){var d=c||"div";a.textContent="";var e=t(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(u(f))}function g(a){l.call(this,a)}function h(b){return function(){return a.renderAllPending(),this.impl[b]}}function i(a){m(g,a,h(a))}function j(b){Object.defineProperty(g.prototype,b,{get:h(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function k(b){Object.defineProperty(g.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var l=a.wrappers.Element,m=a.defineGetter,n=a.enqueueMutation,o=a.mixin,p=a.nodesWereAdded,q=a.nodesWereRemoved,r=a.registerWrapper,s=a.snapshotNodeList,t=a.unwrap,u=a.wrap,v=/&|<|"/g,w={area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},x=window.HTMLElement;g.prototype=Object.create(l.prototype),o(g.prototype,{get innerHTML(){return e(this)},set innerHTML(a){var b=s(this.childNodes);this.invalidateShadowRenderer()?f(this,a,this.tagName):this.impl.innerHTML=a;var c=s(this.childNodes);n(this,"childList",{addedNodes:c,removedNodes:b}),q(b),p(c)},get outerHTML(){return d(this)},set outerHTML(a){var b=this.parentNode;b&&(b.invalidateShadowRenderer(),this.impl.outerHTML=a)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(i),["scrollLeft","scrollTop"].forEach(j),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(k),r(x,g,document.createElement("b")),a.wrappers.HTMLElement=g,a.getInnerHTML=e,a.setInnerHTML=f}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.HTMLCanvasElement;b.prototype=Object.create(c.prototype),d(b.prototype,{getContext:function(){var a=this.impl.getContext.apply(this.impl,arguments);return a&&f(a)}}),e(g,b,document.createElement("canvas")),a.wrappers.HTMLCanvasElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLContentElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get select(){return this.getAttribute("select")},set select(a){this.setAttribute("select",a)},setAttribute:function(a,b){c.prototype.setAttribute.call(this,a,b),"select"===String(a).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),f&&e(f,b),a.wrappers.HTMLContentElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a,b){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var e=f(document.createElement("img"));d.call(this,e),g(e,this),void 0!==a&&(e.width=a),void 0!==b&&(e.height=b)}var d=a.wrappers.HTMLElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLImageElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("img")),c.prototype=b.prototype,a.wrappers.HTMLImageElement=b,a.wrappers.Image=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLShadowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{}),f&&e(f,b),a.wrappers.HTMLShadowElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=m.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);m.set(a,b)}return b}function c(a){for(var c,d=b(a.ownerDocument),e=j(d.createDocumentFragment());c=a.firstChild;)e.appendChild(c);return e}function d(a){if(e.call(this,a),!n){var b=c(a);l.set(this,k(b))}}var e=a.wrappers.HTMLElement,f=a.getInnerHTML,g=a.mixin,h=a.registerWrapper,i=a.setInnerHTML,j=a.unwrap,k=a.wrap,l=new WeakMap,m=new WeakMap,n=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),g(d.prototype,{get content(){return n?k(this.impl.content):l.get(this)},get innerHTML(){return f(this.content)},set innerHTML(a){i(this.content,a)}}),n&&h(n,d),a.wrappers.HTMLTemplateElement=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.registerWrapper,e=window.HTMLMediaElement;b.prototype=Object.create(c.prototype),d(e,b,document.createElement("audio")),a.wrappers.HTMLMediaElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var b=f(document.createElement("audio"));d.call(this,b),g(b,this),b.setAttribute("preload","auto"),void 0!==a&&b.setAttribute("src",a)}var d=a.wrappers.HTMLMediaElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLAudioElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("audio")),c.prototype=b.prototype,a.wrappers.HTMLAudioElement=b,a.wrappers.Audio=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a.replace(/\s+/g," ").trim()}function c(a){e.call(this,a)}function d(a,b,c,f){if(!(this instanceof d))throw new TypeError("DOM object constructor cannot be called as a function.");var g=i(document.createElement("option"));e.call(this,g),h(g,this),void 0!==a&&(g.text=a),void 0!==b&&g.setAttribute("value",b),c===!0&&g.setAttribute("selected",""),g.selected=f===!0}var e=a.wrappers.HTMLElement,f=a.mixin,g=a.registerWrapper,h=a.rewrap,i=a.unwrap,j=a.wrap,k=window.HTMLOptionElement;c.prototype=Object.create(e.prototype),f(c.prototype,{get text(){return b(this.textContent)},set text(a){this.textContent=b(String(a))},get form(){return j(i(this).form)}}),g(k,c,document.createElement("option")),d.prototype=c.prototype,a.wrappers.HTMLOptionElement=c,a.wrappers.Option=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a.localName){case"content":return new c(a);case"shadow":return new e(a);case"template":return new f(a)}d.call(this,a)}var c=a.wrappers.HTMLContentElement,d=a.wrappers.HTMLElement,e=a.wrappers.HTMLShadowElement,f=a.wrappers.HTMLTemplateElement,g=(a.mixin,a.registerWrapper),h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.unwrapIfNeeded,g=a.wrap,h=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return g(this.impl.canvas)},drawImage:function(){arguments[0]=f(arguments[0]),this.impl.drawImage.apply(this.impl,arguments)},createPattern:function(){return arguments[0]=e(arguments[0]),this.impl.createPattern.apply(this.impl,arguments)}}),d(h,b,document.createElement("canvas").getContext("2d")),a.wrappers.CanvasRenderingContext2D=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrapIfNeeded,f=a.wrap,g=window.WebGLRenderingContext;if(g){c(b.prototype,{get canvas(){return f(this.impl.canvas)},texImage2D:function(){arguments[5]=e(arguments[5]),this.impl.texImage2D.apply(this.impl,arguments)},texSubImage2D:function(){arguments[6]=e(arguments[6]),this.impl.texSubImage2D.apply(this.impl,arguments)}});var h=/WebKit/.test(navigator.userAgent)?{drawingBufferHeight:null,drawingBufferWidth:null}:{};d(g,b,h),a.wrappers.WebGLRenderingContext=b}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap,g=window.Range;b.prototype={get startContainer(){return f(this.impl.startContainer)},get endContainer(){return f(this.impl.endContainer)},get commonAncestorContainer(){return f(this.impl.commonAncestorContainer)},setStart:function(a,b){this.impl.setStart(e(a),b)},setEnd:function(a,b){this.impl.setEnd(e(a),b)},setStartBefore:function(a){this.impl.setStartBefore(e(a))},setStartAfter:function(a){this.impl.setStartAfter(e(a))},setEndBefore:function(a){this.impl.setEndBefore(e(a))},setEndAfter:function(a){this.impl.setEndAfter(e(a))},selectNode:function(a){this.impl.selectNode(e(a))},selectNodeContents:function(a){this.impl.selectNodeContents(e(a))},compareBoundaryPoints:function(a,b){return this.impl.compareBoundaryPoints(a,d(b))},extractContents:function(){return f(this.impl.extractContents())},cloneContents:function(){return f(this.impl.cloneContents())},insertNode:function(a){this.impl.insertNode(e(a))},surroundContents:function(a){this.impl.surroundContents(e(a))},cloneRange:function(){return f(this.impl.cloneRange())},isPointInRange:function(a,b){return this.impl.isPointInRange(e(a),b)},comparePoint:function(a,b){return this.impl.comparePoint(e(a),b)},intersectsNode:function(a){return this.impl.intersectsNode(e(a))}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b,document.createRange()),a.wrappers.Range=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.GetElementsByInterface,c=a.ParentNodeInterface,d=a.SelectorsInterface,e=a.mixin,f=a.registerObject,g=f(document.createDocumentFragment());e(g.prototype,c),e(g.prototype,d),e(g.prototype,b);var h=f(document.createTextNode("")),i=f(document.createComment(""));a.wrappers.Comment=i,a.wrappers.DocumentFragment=g,a.wrappers.Text=h}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=i(a.impl.ownerDocument.createDocumentFragment());c.call(this,b),g(b,this);var d=a.shadowRoot;k.set(this,d),j.set(this,a)}var c=a.wrappers.DocumentFragment,d=a.elementFromPoint,e=a.getInnerHTML,f=a.mixin,g=a.rewrap,h=a.setInnerHTML,i=a.unwrap,j=new WeakMap,k=new WeakMap;b.prototype=Object.create(c.prototype),f(b.prototype,{get innerHTML(){return e(this)},set innerHTML(a){h(this,a),this.invalidateShadowRenderer()},get olderShadowRoot(){return k.get(this)||null},get host(){return j.get(this)||null},invalidateShadowRenderer:function(){return j.get(this).invalidateShadowRenderer()},elementFromPoint:function(a,b){return d(this,this.ownerDocument,a,b)},getElementById:function(a){return this.querySelector("#"+a)}}),a.wrappers.ShadowRoot=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){a.previousSibling_=a.previousSibling,a.nextSibling_=a.nextSibling,a.parentNode_=a.parentNode}function c(a,c,e){var f=F(a),g=F(c),h=e?F(e):null;if(d(c),b(c),e)a.firstChild===e&&(a.firstChild_=e),e.previousSibling_=e.previousSibling;else{a.lastChild_=a.lastChild,a.lastChild===a.firstChild&&(a.firstChild_=a.firstChild);var i=G(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=F(a),d=c.parentNode;if(d){var e=G(d);b(a),a.previousSibling&&(a.previousSibling.nextSibling_=a),a.nextSibling&&(a.nextSibling.previousSibling_=a),e.lastChild===a&&(e.lastChild_=a),e.firstChild===a&&(e.firstChild_=a),d.removeChild(c)}}function e(a,b){g(b).push(a),x(a,b);var c=I.get(a);c||I.set(a,c=[]),c.push(b)}function f(a){H.set(a,[])}function g(a){return H.get(a)}function h(a){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}function i(a,b,c){for(var d=a.firstChild;d;d=d.nextSibling)if(b(d)){if(c(d)===!1)return}else i(d,b,c)}function j(a,b){var c=b.getAttribute("select");if(!c)return!0;if(c=c.trim(),!c)return!0;if(!(a instanceof z))return!1;if(!L.test(c))return!1;if(":"===c[0]&&!M.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<O.length;a++)O[a].render();O=[]}function l(){y=null,k()}function m(a){var b=K.get(a);return b||(b=new q(a),K.set(a,b)),b}function n(a){for(;a;a=a.parentNode)if(a instanceof D)return a;return null}function o(a){return m(a.host)}function p(a){this.skip=!1,this.node=a,this.childNodes=[]}function q(a){this.host=a,this.dirty=!1,this.invalidateAttributes(),this.associateNode(a)}function r(a){return a instanceof A}function s(a){return a instanceof A}function t(a){return a instanceof B}function u(a){return a instanceof B}function v(a){return a.shadowRoot}function w(a){for(var b=[],c=a.shadowRoot;c;c=c.olderShadowRoot)b.push(c);return b}function x(a,b){J.set(a,b)}var y,z=a.wrappers.Element,A=a.wrappers.HTMLContentElement,B=a.wrappers.HTMLShadowElement,C=a.wrappers.Node,D=a.wrappers.ShadowRoot,E=(a.assert,a.mixin,a.oneOf),F=a.unwrap,G=a.wrap,H=new WeakMap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=/^[*.:#[a-zA-Z_|]/,M=new RegExp("^:("+["link","visited","target","enabled","disabled","checked","indeterminate","nth-child","nth-last-child","nth-of-type","nth-last-of-type","first-child","last-child","first-of-type","last-of-type","only-of-type"].join("|")+")"),N=E(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),O=[],P=new ArraySplice;P.equals=function(a,b){return F(a.node)===b},p.prototype={append:function(a){var b=new p(a);return this.childNodes.push(b),b},sync:function(a){if(!this.skip){for(var b=this.node,e=this.childNodes,f=h(F(b)),g=a||new WeakMap,i=P.calculateSplices(e,f),j=0,k=0,l=0,m=0;m<i.length;m++){for(var n=i[m];l<n.index;l++)k++,e[j++].sync(g);for(var o=n.removed.length,p=0;o>p;p++){var q=G(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&G(f[k]),p=0;r>p;p++){var t=e[j++],u=t.node;c(b,u,s),g.set(u,!0),t.sync(g)}l+=r}for(var m=l;m<e.length;m++)e[m].sync(g)}}},q.prototype={render:function(a){if(this.dirty){this.invalidateAttributes(),this.treeComposition();var b=this.host,c=b.shadowRoot;this.associateNode(b);for(var d=!e,e=a||new p(b),f=c.firstChild;f;f=f.nextSibling)this.renderNode(c,e,f,!1);d&&e.sync(),this.dirty=!1}},invalidate:function(){if(!this.dirty){if(this.dirty=!0,O.push(this),y)return;y=window[N](l,0)}},renderNode:function(a,b,c,d){if(v(c)){b=b.append(c);var e=m(c);e.dirty=!0,e.render(b)}else r(c)?this.renderInsertionPoint(a,b,c,d):t(c)?this.renderShadowInsertionPoint(a,b,c):this.renderAsAnyDomTree(a,b,c,d)},renderAsAnyDomTree:function(a,b,c,d){if(b=b.append(c),v(c)){var e=m(c);b.skip=!e.dirty,e.render(b)}else for(var f=c.firstChild;f;f=f.nextSibling)this.renderNode(a,b,f,d)},renderInsertionPoint:function(a,b,c,d){var e=g(c);if(e.length){this.associateNode(c);for(var f=0;f<e.length;f++){var h=e[f];r(h)&&d?this.renderInsertionPoint(a,b,h,d):this.renderAsAnyDomTree(a,b,h,d)}}else this.renderFallbackContent(a,b,c);this.associateNode(c.parentNode)},renderShadowInsertionPoint:function(a,b,c){var d=a.olderShadowRoot;if(d){x(d,c),this.associateNode(c.parentNode);for(var e=d.firstChild;e;e=e.nextSibling)this.renderNode(d,b,e,!0)}else this.renderFallbackContent(a,b,c)},renderFallbackContent:function(a,b,c){this.associateNode(c),this.associateNode(c.parentNode);for(var d=c.firstChild;d;d=d.nextSibling)this.renderAsAnyDomTree(a,b,d,!1)},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(a){if(a){var b=this.attributes;/\.\w+/.test(a)&&(b["class"]=!0),/#\w+/.test(a)&&(b.id=!0),a.replace(/\[\s*([^\s=\|~\]]+)/g,function(a,c){b[c]=!0})}},dependsOnAttribute:function(a){return this.attributes[a]},distribute:function(a,b){var c=this;i(a,s,function(a){f(a),c.updateDependentAttributes(a.getAttribute("select"));for(var d=0;d<b.length;d++){var g=b[d];void 0!==g&&j(g,a)&&(e(g,a),b[d]=void 0)}})},treeComposition:function(){for(var a=this.host,b=a.shadowRoot,c=[],d=a.firstChild;d;d=d.nextSibling)if(r(d)){var e=g(d);e&&e.length||(e=h(d)),c.push.apply(c,e)}else c.push(d);for(var f,j;b;){if(f=void 0,i(b,u,function(a){return f=a,!1}),j=f,this.distribute(b,c),j){var k=b.olderShadowRoot;if(k){b=k,x(b,j);continue}break}break}},associateNode:function(a){a.impl.polymerShadowRenderer_=this}},C.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},A.prototype.getDistributedNodes=function(){return k(),g(this)},B.prototype.nodeIsInserted_=A.prototype.nodeIsInserted_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=I,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=J,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(b){if(window[b]){d(!a.wrappers[b]);var i=function(a){c.call(this,a)};i.prototype=Object.create(c.prototype),e(i.prototype,{get form(){return h(g(this).form)}}),f(window[b],i,document.createElement(b.slice(4,-7))),a.wrappers[b]=i}}var c=a.wrappers.HTMLElement,d=a.assert,e=a.mixin,f=a.registerWrapper,g=a.unwrap,h=a.wrap,i=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOutputElement","HTMLSelectElement","HTMLTextAreaElement"];i.forEach(b)}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a)}function c(a){var c=document[a];b.prototype[a]=function(){return v(c.apply(this.impl,arguments))}}function d(a,b){y.call(b.impl,u(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof n&&f(a,b);for(var c=a.firstChild;c;c=c.nextSibling)e(c,b)}function f(a,b){var c=a.olderShadowRoot;c&&b.adoptNode(c)}function g(a){this.impl=a}function h(a,b){var c=document.implementation[b];a.prototype[b]=function(){return v(c.apply(this.impl,arguments))}}function i(a,b){var c=document.implementation[b];a.prototype[b]=function(){return c.apply(this.impl,arguments)}}var j=a.GetElementsByInterface,k=a.wrappers.Node,l=a.ParentNodeInterface,m=a.SelectorsInterface,n=a.wrappers.ShadowRoot,o=a.defineWrapGetter,p=a.elementFromPoint,q=a.forwardMethodsToWrapper,r=a.matchesName,s=a.mixin,t=a.registerWrapper,u=a.unwrap,v=a.wrap,w=a.wrapEventTargetMethods,x=(a.wrapNodeList,new WeakMap);b.prototype=Object.create(k.prototype),o(b,"documentElement"),o(b,"body"),o(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var y=document.adoptNode,z=document.importNode;if(s(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return p(this,this,a,b)},importNode:function(a,b){var c=v(z.call(this.impl,u(a),!1));if(b)for(var d=a.firstChild;d;d=d.nextSibling)c.appendChild(this.importNode(d,!0));return c}}),document.register){var A=document.register;b.prototype.register=function(b,c){function d(a){return a?(this.impl=a,void 0):c.extends?document.createElement(c.extends,b):document.createElement(b)}var e=c.prototype;if(a.nativePrototypeTable.get(e))throw new Error("NotSupportedError");for(var f,g=Object.getPrototypeOf(e),h=[];g&&!(f=a.nativePrototypeTable.get(g));)h.push(g),g=Object.getPrototypeOf(g);if(!f)throw new Error("NotSupportedError");for(var i=Object.create(f),j=h.length-1;j>=0;j--)i=Object.create(i);["createdCallback","enteredViewCallback","leftViewCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){b.apply(v(this),arguments)})});var k={prototype:i};c.extends&&(k.extends=c.extends);A.call(u(this),b,k);return d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i),d},q([window.HTMLDocument||window.Document],["register"])}q([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild",r]),q([window.HTMLDocument||window.Document],["adoptNode","importNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById"]),s(b.prototype,j),s(b.prototype,l),s(b.prototype,m),s(b.prototype,{get implementation(){var a=x.get(this);return a?a:(a=new g(u(this).implementation),x.set(this,a),a)}}),t(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&t(window.HTMLDocument,b),w([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),t(window.DOMImplementation,g),q([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.unwrapIfNeeded,h=a.wrap,i=a.renderAllPending,j=window.Window;b.prototype=Object.create(c.prototype);var k=window.getComputedStyle;j.prototype.getComputedStyle=function(a,b){return i(),k.call(this||window,g(a),b)},["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){j.prototype[a]=function(){var b=h(this||window);return b[a].apply(b,arguments)}}),d(b.prototype,{getComputedStyle:function(a,b){return k.call(f(this),g(a),b)}}),e(j,b),a.wrappers.Window=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=c[a],d=window[b];if(d){var e=document.createElement(a),f=e.constructor;window[b]=f}}var c=(a.isWrapperFor,{a:"HTMLAnchorElement",applet:"HTMLAppletElement",area:"HTMLAreaElement",br:"HTMLBRElement",base:"HTMLBaseElement",body:"HTMLBodyElement",button:"HTMLButtonElement",dl:"HTMLDListElement",datalist:"HTMLDataListElement",data:"HTMLDataElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",hr:"HTMLHRElement",head:"HTMLHeadElement",h1:"HTMLHeadingElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",input:"HTMLInputElement",li:"HTMLLIElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",link:"HTMLLinkElement",map:"HTMLMapElement",marquee:"HTMLMarqueeElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",del:"HTMLModElement",ol:"HTMLOListElement",object:"HTMLObjectElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",time:"HTMLTimeElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",table:"HTMLTableElement",tr:"HTMLTableRowElement",thead:"HTMLTableSectionElement",tbody:"HTMLTableSectionElement",textarea:"HTMLTextAreaElement",track:"HTMLTrackElement",title:"HTMLTitleElement",ul:"HTMLUListElement",video:"HTMLVideoElement"});
+Object.keys(c).forEach(b),Object.getOwnPropertyNames(a.wrappers).forEach(function(b){window[b]=a.wrappers[b]}),a.knownElements=c}(window.ShadowDOMPolyfill),function(){{var a=window.ShadowDOMPolyfill;a.wrap}Object.defineProperties(HTMLElement.prototype,{webkitShadowRoot:{get:function(){return this.shadowRoot}}}),HTMLElement.prototype.webkitCreateShadowRoot=HTMLElement.prototype.createShadowRoot,window.dartExperimentalFixupGetTag=function(b){function c(a){if(a instanceof d)return"NodeList";if(a instanceof e)return"ShadowRoot";if(window.MutationRecord&&a instanceof MutationRecord)return"MutationRecord";if(window.MutationObserver&&a instanceof MutationObserver)return"MutationObserver";if(a instanceof HTMLTemplateElement)return"HTMLTemplateElement";var c=f(a);if(a!==c){var g=a.constructor;if(g===c.constructor){var h=g._ShadowDOMPolyfill$cacheTag_;return h||(h=Object.prototype.toString.call(c),h=h.substring(8,h.length-1),g._ShadowDOMPolyfill$cacheTag_=h),h}a=c}return b(a)}var d=a.wrappers.NodeList,e=a.wrappers.ShadowRoot,f=a.unwrapIfNeeded;return c}}();var Platform={};!function(a){function b(a,b){var c="";return Array.prototype.forEach.call(a,function(a){c+=a.textContent+"\n\n"}),b||(c=c.replace(n,"")),c}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){var b=c(a);document.head.appendChild(b);var d=b.sheet.cssRules;return b.parentNode.removeChild(b),d}function e(a){for(var b=0,c=[];b<a.length;b++)c.push(a[b].cssText);return c.join("\n\n")}function f(a){a&&g().appendChild(document.createTextNode(a))}function g(){return h||(h=document.createElement("style"),h.setAttribute("ShadowCSSShim","")),h}var h,i={strictStyling:!1,registry:{},shimStyling:function(a,b,d){var e=this.isTypeExtension(d),g=this.registerDefinition(a,b,d);this.strictStyling&&this.applyScopeToContent(a,b),this.insertPolyfillDirectives(g.rootStyles),this.insertPolyfillRules(g.rootStyles);var h=this.stylesToShimmedCssText(g.scopeStyles,b,e);h+=this.extractPolyfillUnscopedRules(g.rootStyles),g.shimmedStyle=c(h),a&&(a.shimmedStyle=g.shimmedStyle);for(var i,j=0,k=g.rootStyles.length;k>j&&(i=g.rootStyles[j]);j++)i.parentNode.removeChild(i);f(h)},registerDefinition:function(a,b,c){var d=this.registry[b]={root:a,name:b,extendsName:c},e=a?a.querySelectorAll("style"):[];e=e?Array.prototype.slice.call(e,0):[],d.rootStyles=e,d.scopeStyles=d.rootStyles;var f=this.registry[d.extendsName];return!f||a&&!a.querySelector("shadow")||(d.scopeStyles=f.scopeStyles.concat(d.scopeStyles)),d},isTypeExtension:function(a){return a&&a.indexOf("-")<0},applyScopeToContent:function(a,b){a&&(Array.prototype.forEach.call(a.querySelectorAll("*"),function(a){a.setAttribute(b,"")}),Array.prototype.forEach.call(a.querySelectorAll("template"),function(a){this.applyScopeToContent(a.content,b)},this))},insertPolyfillDirectives:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillDirectivesInCssText(a.textContent)},this)},insertPolyfillDirectivesInCssText:function(a){return a.replace(o,function(a,b){return b.slice(0,-2)+"{"})},insertPolyfillRules:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillRulesInCssText(a.textContent)},this)},insertPolyfillRulesInCssText:function(a){return a.replace(p,function(a,b){return b.slice(0,-1)})},extractPolyfillUnscopedRules:function(a){var b="";return a&&Array.prototype.forEach.call(a,function(a){b+=this.extractPolyfillUnscopedRulesFromCssText(a.textContent)+"\n\n"},this),b},extractPolyfillUnscopedRulesFromCssText:function(a){for(var b,c="";b=q.exec(a);)c+=b[1].slice(0,-1)+"\n\n";return c},stylesToShimmedCssText:function(a,b,c){return this.shimAtHost(a,b,c)+this.shimScoping(a,b,c)},shimAtHost:function(a,b,c){return a?this.convertAtHostStyles(a,b,c):void 0},convertAtHostStyles:function(a,c,f){var g=b(a),h=this;return g=g.replace(j,function(a,b){return h.scopeHostCss(b,c,f)}),g=e(this.findAtHostRules(d(g),this.makeScopeMatcher(c,f)))},scopeHostCss:function(a,b,c){var d=this;return a.replace(k,function(a,e,f){return d.scopeHostSelector(e,b,c)+" "+f+"\n "})},scopeHostSelector:function(a,b,c){var d=[],e=a.split(","),f="[is="+b+"]";return e.forEach(function(a){a=a.trim(),a.match(l)?a=a.replace(l,c?f+"$1$3":b+"$1$3"):a.match(m)&&(a=c?f+a:b+a),d.push(a)},this),d.join(", ")},findAtHostRules:function(a,b){return Array.prototype.filter.call(a,this.isHostRule.bind(this,b))},isHostRule:function(a,b){return b.selectorText&&b.selectorText.match(a)||b.cssRules&&this.findAtHostRules(b.cssRules,a).length||b.type==CSSRule.WEBKIT_KEYFRAMES_RULE},shimScoping:function(a,b,c){return a?this.convertScopedStyles(a,b,c):void 0},convertScopedStyles:function(a,c,e){var f=b(a).replace(j,"");f=this.insertPolyfillHostInCssText(f),f=this.convertColonHost(f),f=this.convertPseudos(f),f=this.convertParts(f),f=this.convertCombinators(f);var g=d(f);return f=this.scopeRules(g,c,e)},convertPseudos:function(a){return a.replace(r," [pseudo=$1]")},convertParts:function(a){return a.replace(s," [part=$1]")},convertColonHost:function(a){return a.replace(u,function(a,b,c,d){if(b=y,c){for(var e,f=c.split(","),g=[],h=0,i=f.length;i>h&&(e=f[h]);h++)e=e.trim(),e.match(t)?g.push(b+e.replace(t,"")+d):g.push(b+e+d+", "+e+" "+b+d);return g.join(",")}return b+d})},convertCombinators:function(a){return a.replace(/\^\^/g," ").replace(/\^/g," ")},scopeRules:function(a,b,c){var d="";return Array.prototype.forEach.call(a,function(a){a.selectorText&&a.style&&a.style.cssText?(d+=this.scopeSelector(a.selectorText,b,c,this.strictStyling)+" {\n ",d+=this.propertiesFromRule(a)+"\n}\n\n"):a.media?(d+="@media "+a.media.mediaText+" {\n",d+=this.scopeRules(a.cssRules,b,c),d+="\n}\n\n"):a.cssText&&(d+=a.cssText+"\n\n")},this),d},scopeSelector:function(a,b,c,d){var e=[],f=a.split(",");return f.forEach(function(a){a=a.trim(),this.selectorNeedsScoping(a,b,c)&&(a=d&&!a.match(y)?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b,c)),e.push(a)},this),e.join(", ")},selectorNeedsScoping:function(a,b,c){var d=this.makeScopeMatcher(b,c);return!a.match(d)},makeScopeMatcher:function(a,b){var c=b?"\\[is=['\"]?"+a+"['\"]?\\]":a;return new RegExp("^("+c+")"+v,"m")},applySimpleSelectorScope:function(a,b,c){var d=c?"[is="+b+"]":b;return a.match(z)?(a=a.replace(y,d),a.replace(z,d+" ")):d+" "+a},applyStrictSelectorScope:function(a,b){var c=[" ",">","+","~"],d=a,e="["+b+"]";return c.forEach(function(a){var b=d.split(a);d=b.map(function(a){var b=a.trim().replace(z,"");return b&&c.indexOf(b)<0&&b.indexOf(e)<0&&(a=b.replace(/([^:]*)(:*)(.*)/,"$1"+e+"$2$3")),a}).join(a)}),d},insertPolyfillHostInCssText:function(a){return a.replace(w,t).replace(x,t)},propertiesFromRule:function(a){return a.style.cssText}},j=/@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,k=/([^{]*)({[\s\S]*?})/gim,l=/(.*)((?:\*)|(?:\:scope))(.*)/,m=/^[.\[:]/,n=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,o=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,p=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,q=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,r=/::(x-[^\s{,(]*)/gim,s=/::part\(([^)]*)\)/gim,t="-shadowcsshost",u=new RegExp("("+t+")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)","gim"),v="([>\\s~+[.,{:][\\s\\S]*)?$",w=/@host/gim,x=/\:host/gim,y=t+"-no-combinator",z=new RegExp(t,"gim");if(window.ShadowDOMPolyfill){f("style { display: none !important; }\n");var A=document.querySelector("head");A.insertBefore(g(),A.childNodes[0])}a.ShadowCSS=i}(window.Platform)}
\ No newline at end of file
diff --git a/pkg/shadow_dom/pubspec.yaml b/pkg/shadow_dom/pubspec.yaml
index 358945b..0c3bb3e 100644
--- a/pkg/shadow_dom/pubspec.yaml
+++ b/pkg/shadow_dom/pubspec.yaml
@@ -1,5 +1,5 @@
name: shadow_dom
-version: 0.9.1-dev
+version: 0.9.1
author: Polymer.dart Authors <web-ui-dev@dartlang.org>
homepage: https://www.dartlang.org/polymer-dart/
description: >
@@ -9,4 +9,4 @@
within a document, thus enabling better functional encapsulation within the
DOM.
environment:
- sdk: ">=0.8.10+6 <2.0.0"
+ sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/shadow_dom/tool/build.json b/pkg/shadow_dom/tool/build.json
index 8c2b7be..76e4ec4 100644
--- a/pkg/shadow_dom/tool/build.json
+++ b/pkg/shadow_dom/tool/build.json
@@ -4,6 +4,6 @@
"../../../third_party/polymer/ShadowDOM/build.json",
"../lib/src/platform/patches-shadowdom-polyfill.js",
"../lib/src/platform/platform-init.js",
- "../../../third_party/polymer/platform/src/ShadowCSS.js",
+ "../../../third_party/polymer/platform-dev/src/ShadowCSS.js",
"build/end-if.js"
]
diff --git a/pkg/shadow_dom/tool/build.sh b/pkg/shadow_dom/tool/build.sh
index 10cd859..f10e8c2 100755
--- a/pkg/shadow_dom/tool/build.sh
+++ b/pkg/shadow_dom/tool/build.sh
@@ -18,7 +18,7 @@
NEWLINE=$'\n'
REVISIONS=""
-for NAME in ShadowDOM observe-js WeakMap platform; do
+for NAME in ShadowDOM observe-js WeakMap platform-dev; do
GIT_REMOTE="$POLYMER_REMOTE/$NAME.git"
GIT_DIR="$POLYMER_DIR/$NAME"
echo "*** Syncing $GIT_DIR from $GIT_REMOTE"
diff --git a/pkg/stack_trace/lib/src/chain.dart b/pkg/stack_trace/lib/src/chain.dart
new file mode 100644
index 0000000..f6e2f3f
--- /dev/null
+++ b/pkg/stack_trace/lib/src/chain.dart
@@ -0,0 +1,173 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library stack_trace.chain;
+
+import 'dart:async';
+import 'dart:collection';
+
+import 'stack_zone_specification.dart';
+import 'trace.dart';
+import 'utils.dart';
+
+/// A function that handles errors in the zone wrapped by [Chain.capture].
+typedef void ChainHandler(error, Chain chain);
+
+/// A chain of stack traces.
+///
+/// A stack chain is a collection of one or more stack traces that collectively
+/// represent the path from [main] through nested function calls to a particular
+/// code location, usually where an error was thrown. Multiple stack traces are
+/// necessary when using asynchronous functions, since the program's stack is
+/// reset before each asynchronous callback is run.
+///
+/// Stack chains can be automatically tracked using [Chain.capture]. This sets
+/// up a new [Zone] in which the current stack chain is tracked and can be
+/// accessed using [new Chain.current]. Any errors that would be top-leveled in
+/// the zone can be handled, along with their associated chains, with the
+/// `onError` callback.
+///
+/// For the most part [Chain.capture] will notice when an error is thrown and
+/// associate the correct stack chain with it; the chain can be accessed using
+/// [new Chain.forTrace]. However, there are some cases where exceptions won't
+/// be automatically detected: any [Future] constructor,
+/// [Completer.completeError], [Stream.addError], and libraries that use these.
+/// For these, all you need to do is wrap the Future or Stream in a call to
+/// [Chain.track] and the errors will be tracked correctly.
+class Chain implements StackTrace {
+ /// The line used in the string representation of stack chains to represent
+ /// the gap between traces.
+ static const _GAP = '===== asynchronous gap ===========================\n';
+
+ /// The stack traces that make up this chain.
+ ///
+ /// Like the frames in a stack trace, the traces are ordered from most local
+ /// to least local. The first one is the trace where the actual exception was
+ /// raised, the second one is where that callback was scheduled, and so on.
+ final List<Trace> traces;
+
+ /// The [StackZoneSpecification] for the current zone.
+ static StackZoneSpecification get _currentSpec =>
+ Zone.current[#stack_trace.stack_zone.spec];
+
+ /// Runs [callback] in a [Zone] in which the current stack chain is tracked
+ /// and automatically associated with (most) errors.
+ ///
+ /// If [onError] is passed, any error in the zone that would otherwise go
+ /// unhandled is passed to it, along with the [Chain] associated with that
+ /// error. Note that if [callback] produces multiple unhandled errors,
+ /// [onError] may be called more than once. If [onError] isn't passed, the
+ /// parent Zone's `unhandledErrorHandler` will be called with the error and
+ /// its chain.
+ ///
+ /// For the most part an error thrown in the zone will have the correct stack
+ /// chain associated with it. However, there are some cases where exceptions
+ /// won't be automatically detected: any [Future] constructor,
+ /// [Completer.completeError], [Stream.addError], and libraries that use
+ /// these. For these, all you need to do is wrap the Future or Stream in a
+ /// call to [Chain.track] and the errors will be tracked correctly.
+ ///
+ /// Note that even if [onError] isn't passed, this zone will still be an error
+ /// zone. This means that any errors that would cross the zone boundary are
+ /// considered unhandled.
+ ///
+ /// If [callback] returns a value, it will be returned by [capture] as well.
+ ///
+ /// Currently, capturing stack chains doesn't work when using dart2js due to
+ /// issues [15171] and [15105]. Stack chains reported on dart2js will contain
+ /// only one trace.
+ ///
+ /// [15171]: https://code.google.com/p/dart/issues/detail?id=15171
+ /// [15105]: https://code.google.com/p/dart/issues/detail?id=15105
+ static capture(callback(), {ChainHandler onError}) {
+ var spec = new StackZoneSpecification(onError);
+ return runZoned(callback, zoneSpecification: spec.toSpec(), zoneValues: {
+ #stack_trace.stack_zone.spec: spec
+ });
+ }
+
+ /// Ensures that any errors emitted by [futureOrStream] have the correct stack
+ /// chain information associated with them.
+ ///
+ /// For the most part an error thrown within a [capture] zone will have the
+ /// correct stack chain automatically associated with it. However, there are
+ /// some cases where exceptions won't be automatically detected: any [Future]
+ /// constructor, [Completer.completeError], [Stream.addError], and libraries
+ /// that use these.
+ ///
+ /// This returns a [Future] or [Stream] that will emit the same values and
+ /// errors as [futureOrStream]. The only exception is that if [futureOrStream]
+ /// emits an error without a stack trace, one will be added in the return
+ /// value.
+ ///
+ /// If this is called outside of a [capture] zone, it just returns
+ /// [futureOrStream] as-is.
+ ///
+ /// As the name suggests, [futureOrStream] may be either a [Future] or a
+ /// [Stream].
+ static track(futureOrStream) {
+ if (_currentSpec == null) return futureOrStream;
+ if (futureOrStream is Future) {
+ return _currentSpec.trackFuture(futureOrStream, 1);
+ } else {
+ return _currentSpec.trackStream(futureOrStream, 1);
+ }
+ }
+
+ /// Returns the current stack chain.
+ ///
+ /// By default, the first frame of the first trace will be the line where
+ /// [Chain.current] is called. If [level] is passed, the first trace will
+ /// start that many frames up instead.
+ ///
+ /// If this is called outside of a [capture] zone, it just returns a
+ /// single-trace chain.
+ factory Chain.current([int level=0]) {
+ if (_currentSpec != null) return _currentSpec.currentChain(level + 1);
+ return new Chain([new Trace.current(level + 1)]);
+ }
+
+ /// Returns the stack chain associated with [trace].
+ ///
+ /// The first stack trace in the returned chain will always be [trace]
+ /// (converted to a [Trace] if necessary). If there is no chain associated
+ /// with [trace] or if this is called outside of a [capture] zone, this just
+ /// returns a single-trace chain containing [trace].
+ ///
+ /// If [trace] is already a [Chain], it will be returned as-is.
+ factory Chain.forTrace(StackTrace trace) {
+ if (trace is Chain) return trace;
+ if (_currentSpec == null) return new Chain([new Trace.from(trace)]);
+ return _currentSpec.chainFor(trace);
+ }
+
+ /// Parses a string representation of a stack chain.
+ ///
+ /// Specifically, this parses the output of [Chain.toString].
+ factory Chain.parse(String chain) =>
+ new Chain(chain.split(_GAP).map((trace) => new Trace.parseFriendly(trace)));
+
+ /// Returns a new [Chain] comprised of [traces].
+ Chain(Iterable<Trace> traces)
+ : traces = new UnmodifiableListView<Trace>(traces.toList());
+
+ /// Returns a terser version of [this].
+ ///
+ /// This calls [Trace.terse] on every trace in [traces], and discards any
+ /// trace that contain only internal frames.
+ Chain get terse {
+ return new Chain(traces.map((trace) => trace.terse).where((trace) {
+ // Ignore traces that contain only internal processing.
+ return trace.frames.length > 1;
+ }));
+ }
+
+ /// Converts [this] to a [Trace].
+ ///
+ /// The trace version of a chain is just the concatenation of all the traces
+ /// in the chain.
+ Trace toTrace() => new Trace(flatten(traces.map((trace) => trace.frames)));
+
+ String toString() => traces.join(_GAP);
+}
diff --git a/pkg/stack_trace/lib/src/stack_zone_specification.dart b/pkg/stack_trace/lib/src/stack_zone_specification.dart
new file mode 100644
index 0000000..36e0717
--- /dev/null
+++ b/pkg/stack_trace/lib/src/stack_zone_specification.dart
@@ -0,0 +1,205 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library stack_trace.stack_zone_specification;
+
+import 'dart:async';
+
+import 'trace.dart';
+import 'chain.dart';
+
+/// A class encapsulating the zone specification for a [Chain.capture] zone.
+///
+/// Until they're materialized and exposed to the user, stack chains are tracked
+/// as linked lists of [Trace]s using the [_Node] class. These nodes are stored
+/// in three distinct ways:
+///
+/// * When a callback is registered, a node is created and stored as a captured
+/// local variable until the callback is run.
+///
+/// * When a callback is run, its captured node is set as the [_currentNode] so
+/// it can be available to [Chain.current] and to be linked into additional
+/// chains when more callbacks are scheduled.
+///
+/// * When a callback throws an error or a [Chain.track]ed Future or Stream
+/// emits an error, the current node is associated with that error's stack
+/// trace using the [_chains] expando.
+///
+/// Since [ZoneSpecification] can't be extended or even implemented, in order to
+/// get a real [ZoneSpecification] instance it's necessary to call [toSpec].
+class StackZoneSpecification {
+ /// The expando that associates stack chains with [StackTrace]s.
+ ///
+ /// The chains are associated with stack traces rather than errors themselves
+ /// because it's a common practice to throw strings as errors, which can't be
+ /// used with expandos.
+ ///
+ /// The chain associated with a given stack trace doesn't contain a node for
+ /// that stack trace.
+ final _chains = new Expando<_Node>("stack chains");
+
+ /// The error handler for the zone.
+ ///
+ /// If this is null, that indicates that any unhandled errors should be passed
+ /// to the parent zone.
+ final ChainHandler _onError;
+
+ /// The most recent node of the current stack chain.
+ _Node _currentNode;
+
+ StackZoneSpecification([this._onError]);
+
+ /// Converts [this] to a real [ZoneSpecification].
+ ZoneSpecification toSpec() {
+ return new ZoneSpecification(
+ handleUncaughtError: handleUncaughtError,
+ registerCallback: registerCallback,
+ registerUnaryCallback: registerUnaryCallback,
+ registerBinaryCallback: registerBinaryCallback);
+ }
+
+ /// Returns the current stack chain.
+ ///
+ /// By default, the first frame of the first trace will be the line where
+ /// [currentChain] is called. If [level] is passed, the first trace will start
+ /// that many frames up instead.
+ Chain currentChain([int level=0]) => _createNode(level + 1).toChain();
+
+ /// Returns the stack chain associated with [trace], if one exists.
+ ///
+ /// The first stack trace in the returned chain will always be [trace]
+ /// (converted to a [Trace] if necessary). If there is no chain associated
+ /// with [trace], this just returns a single-trace chain containing [trace].
+ Chain chainFor(StackTrace trace) {
+ if (trace is Chain) return trace;
+ var previous = trace == null ? null : _chains[trace];
+ return new _Node(trace, previous).toChain();
+ }
+
+ /// Ensures that an error emitted by [future] has the correct stack
+ /// information associated with it.
+ ///
+ /// By default, the first frame of the first trace will be the line where
+ /// [trackFuture] is called. If [level] is passed, the first trace will start
+ /// that many frames up instead.
+ Future trackFuture(Future future, [int level=0]) {
+ var completer = new Completer.sync();
+ var node = _createNode(level + 1);
+ future.then(completer.complete).catchError((e, stackTrace) {
+ if (stackTrace == null) stackTrace = new Trace.current();
+ if (_chains[stackTrace] == null) _chains[stackTrace] = node;
+ completer.completeError(e, stackTrace);
+ });
+ return completer.future;
+ }
+
+ /// Ensures that any errors emitted by [stream] have the correct stack
+ /// information associated with them.
+ ///
+ /// By default, the first frame of the first trace will be the line where
+ /// [trackStream] is called. If [level] is passed, the first trace will start
+ /// that many frames up instead.
+ Stream trackStream(Stream stream, [int level=0]) {
+ var node = _createNode(level + 1);
+ return stream.transform(new StreamTransformer.fromHandlers(
+ handleError: (error, stackTrace, sink) {
+ if (stackTrace == null) stackTrace = new Trace.current();
+ if (_chains[stackTrace] == null) _chains[stackTrace] = node;
+ sink.addError(error, stackTrace);
+ }));
+ }
+
+ /// Tracks the current stack chain so it can be set to [_currentChain] when
+ /// [f] is run.
+ ZoneCallback registerCallback(Zone self, ZoneDelegate parent, Zone zone,
+ Function f) {
+ if (f == null) return parent.registerCallback(zone, null);
+ var node = _createNode(1);
+ return parent.registerCallback(zone, () => _run(f, node));
+ }
+
+ /// Tracks the current stack chain so it can be set to [_currentChain] when
+ /// [f] is run.
+ ZoneUnaryCallback registerUnaryCallback(Zone self, ZoneDelegate parent,
+ Zone zone, Function f) {
+ if (f == null) return parent.registerUnaryCallback(zone, null);
+ var node = _createNode(1);
+ return parent.registerUnaryCallback(zone, (arg) {
+ return _run(() => f(arg), node);
+ });
+ }
+
+ /// Tracks the current stack chain so it can be set to [_currentChain] when
+ /// [f] is run.
+ ZoneBinaryCallback registerBinaryCallback(Zone self, ZoneDelegate parent,
+ Zone zone, Function f) {
+ if (f == null) return parent.registerBinaryCallback(zone, null);
+ var node = _createNode(1);
+ return parent.registerBinaryCallback(zone, (arg1, arg2) {
+ return _run(() => f(arg1, arg2), node);
+ });
+ }
+
+ /// Looks up the chain associated with [stackTrace] and passes it either to
+ /// [_onError] or [parent]'s error handler.
+ handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone, error,
+ StackTrace stackTrace) {
+ if (_onError == null) {
+ return parent.handleUncaughtError(zone, error, chainFor(stackTrace));
+ } else {
+ _onError(error, chainFor(stackTrace));
+ }
+ }
+
+ /// Creates a [_Node] with the current stack trace and linked to
+ /// [_currentNode].
+ ///
+ /// By default, the first frame of the first trace will be the line where
+ /// [_createNode] is called. If [level] is passed, the first trace will start
+ /// that many frames up instead.
+ _Node _createNode([int level=0]) =>
+ new _Node(new Trace.current(level + 1), _currentNode);
+
+ // TODO(nweiz): use a more robust way of detecting and tracking errors when
+ // issue 15105 is fixed.
+ /// Runs [f] with [_currentNode] set to [node].
+ ///
+ /// If [f] throws an error, this associates [node] with that error's stack
+ /// trace.
+ _run(Function f, _Node node) {
+ var previousNode = _currentNode;
+ _currentNode = node;
+ try {
+ return f();
+ } catch (e, stackTrace) {
+ _chains[stackTrace] = node;
+ rethrow;
+ } finally {
+ _currentNode = previousNode;
+ }
+ }
+}
+
+/// A linked list node representing a single entry in a stack chain.
+class _Node {
+ /// The stack trace for this link of the chain.
+ final Trace trace;
+
+ /// The previous node in the chain.
+ final _Node previous;
+
+ _Node(StackTrace trace, [this.previous])
+ : trace = trace == null ? new Trace.current() : new Trace.from(trace);
+
+ /// Converts this to a [Chain].
+ Chain toChain() {
+ var nodes = <Trace>[];
+ var node = this;
+ while (node != null) {
+ nodes.add(node.trace);
+ node = node.previous;
+ }
+ return new Chain(nodes);
+ }
+}
diff --git a/pkg/stack_trace/lib/src/trace.dart b/pkg/stack_trace/lib/src/trace.dart
index c3db43e..88b9275 100644
--- a/pkg/stack_trace/lib/src/trace.dart
+++ b/pkg/stack_trace/lib/src/trace.dart
@@ -7,6 +7,7 @@
import 'dart:collection';
import 'dart:math' as math;
+import 'chain.dart';
import 'frame.dart';
import 'lazy_trace.dart';
import 'utils.dart';
@@ -92,6 +93,7 @@
/// a [Trace], it will be returned as-is.
factory Trace.from(StackTrace trace) {
if (trace is Trace) return trace;
+ if (trace is Chain) return trace.toTrace();
return new LazyTrace(() => new Trace.parse(trace.toString()));
}
@@ -172,9 +174,14 @@
.where((line) => line != '[native code]')
.map((line) => new Frame.parseFirefox(line)));
- /// Parses this package's a string representation of a stack trace.
+ /// Parses this package's string representation of a stack trace.
+ ///
+ /// This also parses string representations of [Chain]s. They parse to the
+ /// same trace that [Chain.toTrace] would return.
Trace.parseFriendly(String trace)
: this(trace.trim().split("\n")
+ // Filter out asynchronous gaps from [Chain]s.
+ .where((line) => !line.startsWith('====='))
.map((line) => new Frame.parseFriendly(line)));
/// Returns a new [Trace] comprised of [frames].
@@ -191,10 +198,13 @@
/// Returns a terser version of [this].
///
/// This is accomplished by folding together multiple stack frames from the
- /// core library, as in [foldFrames]. Remaining core library frames have their
- /// libraries, "-patch" suffixes, and line numbers removed.
+ /// core library or from this package, as in [foldFrames]. Remaining core
+ /// library frames have their libraries, "-patch" suffixes, and line numbers
+ /// removed.
Trace get terse {
- return new Trace(foldFrames((frame) => frame.isCore).frames.map((frame) {
+ return new Trace(foldFrames((frame) {
+ return frame.isCore || frame.package == 'stack_trace';
+ }).frames.map((frame) {
if (!frame.isCore) return frame;
var library = frame.library.replaceAll(_terseRegExp, '');
return new Frame(Uri.parse(library), null, null, frame.member);
diff --git a/pkg/stack_trace/lib/src/utils.dart b/pkg/stack_trace/lib/src/utils.dart
index 08b3b96..62a2820 100644
--- a/pkg/stack_trace/lib/src/utils.dart
+++ b/pkg/stack_trace/lib/src/utils.dart
@@ -18,3 +18,19 @@
return result.toString();
}
+/// Flattens nested lists inside an iterable into a single list containing only
+/// non-list elements.
+List flatten(Iterable nested) {
+ var result = [];
+ helper(list) {
+ for (var element in list) {
+ if (element is List) {
+ helper(element);
+ } else {
+ result.add(element);
+ }
+ }
+ }
+ helper(nested);
+ return result;
+}
diff --git a/pkg/stack_trace/lib/stack_trace.dart b/pkg/stack_trace/lib/stack_trace.dart
index dba95e9..ac875a9 100644
--- a/pkg/stack_trace/lib/stack_trace.dart
+++ b/pkg/stack_trace/lib/stack_trace.dart
@@ -25,3 +25,4 @@
export 'src/trace.dart';
export 'src/frame.dart';
+export 'src/chain.dart';
diff --git a/pkg/stack_trace/test/chain_test.dart b/pkg/stack_trace/test/chain_test.dart
new file mode 100644
index 0000000..4d31acb
--- /dev/null
+++ b/pkg/stack_trace/test/chain_test.dart
@@ -0,0 +1,620 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library chain_test;
+
+import 'dart:async';
+
+import 'package:path/path.dart' as p;
+import 'package:stack_trace/stack_trace.dart';
+import 'package:unittest/unittest.dart';
+
+import 'utils.dart';
+
+void main() {
+ group('capture() with onError catches exceptions', () {
+ test('thrown in a microtask', () {
+ return captureFuture(() => inMicrotask(() => throw 'error'))
+ .then((chain) {
+ // Since there was only one asynchronous operation, there should be only
+ // two traces in the chain.
+ expect(chain.traces, hasLength(2));
+
+ // The first frame of the first trace should be the line on which the
+ // actual error was thrown.
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+
+ // The second trace should describe the stack when the error callback
+ // was scheduled.
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('inMicrotask'))));
+ });
+ });
+
+ test('thrown in a one-shot timer', () {
+ return captureFuture(() => inOneShotTimer(() => throw 'error'))
+ .then((chain) {
+ expect(chain.traces, hasLength(2));
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('inOneShotTimer'))));
+ });
+ });
+
+ test('thrown in a periodic timer', () {
+ return captureFuture(() => inPeriodicTimer(() => throw 'error'))
+ .then((chain) {
+ expect(chain.traces, hasLength(2));
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('inPeriodicTimer'))));
+ });
+ });
+
+ test('thrown in a nested series of asynchronous operations', () {
+ return captureFuture(() {
+ inPeriodicTimer(() {
+ inOneShotTimer(() => inMicrotask(() => throw 'error'));
+ });
+ }).then((chain) {
+ expect(chain.traces, hasLength(4));
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('inMicrotask'))));
+ expect(chain.traces[2].frames,
+ contains(frameMember(startsWith('inOneShotTimer'))));
+ expect(chain.traces[3].frames,
+ contains(frameMember(startsWith('inPeriodicTimer'))));
+ });
+ });
+
+ test('thrown in a long future chain', () {
+ return captureFuture(() => inFutureChain(() => throw 'error'))
+ .then((chain) {
+ // Despite many asynchronous operations, there's only one level of
+ // nested calls, so there should be only two traces in the chain. This
+ // is important; programmers expect stack trace memory consumption to be
+ // O(depth of program), not O(length of program).
+ expect(chain.traces, hasLength(2));
+
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('inFutureChain'))));
+ });
+ });
+
+ test('multiple times', () {
+ var completer = new Completer();
+ var first = true;
+
+ Chain.capture(() {
+ inMicrotask(() => throw 'first error');
+ inPeriodicTimer(() => throw 'second error');
+ }, onError: (error, chain) {
+ if (first) {
+ expect(error, equals('first error'));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('inMicrotask'))));
+ first = false;
+ } else {
+ expect(error, equals('second error'));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('inPeriodicTimer'))));
+ completer.complete();
+ }
+ });
+
+ return completer.future;
+ });
+ });
+
+ test('capture() without onError passes exceptions to parent zone', () {
+ var completer = new Completer();
+
+ runZoned(() {
+ Chain.capture(() => inMicrotask(() => throw 'error'));
+ }, onError: (error, chain) {
+ expect(error, equals('error'));
+ expect(chain, new isInstanceOf<Chain>());
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('inMicrotask'))));
+ completer.complete();
+ });
+
+ return completer.future;
+ });
+
+ group('current() within capture()', () {
+ test('called in a microtask', () {
+ var completer = new Completer();
+ Chain.capture(() {
+ inMicrotask(() => completer.complete(new Chain.current()));
+ });
+
+ return completer.future.then((chain) {
+ expect(chain.traces, hasLength(2));
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('inMicrotask'))));
+ });
+ });
+
+ test('called in a one-shot timer', () {
+ var completer = new Completer();
+ Chain.capture(() {
+ inOneShotTimer(() => completer.complete(new Chain.current()));
+ });
+
+ return completer.future.then((chain) {
+ expect(chain.traces, hasLength(2));
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('inOneShotTimer'))));
+ });
+ });
+
+ test('called in a periodic timer', () {
+ var completer = new Completer();
+ Chain.capture(() {
+ inPeriodicTimer(() => completer.complete(new Chain.current()));
+ });
+
+ return completer.future.then((chain) {
+ expect(chain.traces, hasLength(2));
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('inPeriodicTimer'))));
+ });
+ });
+
+ test('called in a nested series of asynchronous operations', () {
+ var completer = new Completer();
+ Chain.capture(() {
+ inPeriodicTimer(() {
+ inOneShotTimer(() {
+ inMicrotask(() => completer.complete(new Chain.current()));
+ });
+ });
+ });
+
+ return completer.future.then((chain) {
+ expect(chain.traces, hasLength(4));
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('inMicrotask'))));
+ expect(chain.traces[2].frames,
+ contains(frameMember(startsWith('inOneShotTimer'))));
+ expect(chain.traces[3].frames,
+ contains(frameMember(startsWith('inPeriodicTimer'))));
+ });
+ });
+
+ test('called in a long future chain', () {
+ var completer = new Completer();
+ Chain.capture(() {
+ inFutureChain(() => completer.complete(new Chain.current()));
+ });
+
+ return completer.future.then((chain) {
+ expect(chain.traces, hasLength(2));
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('inFutureChain'))));
+ });
+ });
+ });
+
+ test('current() outside of capture() returns a chain wrapping the current '
+ 'trace', () {
+ var completer = new Completer();
+ inMicrotask(() => completer.complete(new Chain.current()));
+
+ return completer.future.then((chain) {
+ // Since the chain wasn't loaded within [Chain.capture], the full stack
+ // chain isn't available and it just returns the current stack when
+ // called.
+ expect(chain.traces, hasLength(1));
+ expect(chain.traces.first.frames.first, frameMember(startsWith('main')));
+ });
+ });
+
+ group('forTrace() within capture()', () {
+ test('called for a stack trace from a microtask', () {
+ return Chain.capture(() {
+ return chainForTrace(inMicrotask, () => throw 'error');
+ }).then((chain) {
+ // Because [chainForTrace] has to set up a future chain to capture the
+ // stack trace while still showing it to the zone specification, it adds
+ // an additional level of async nesting and so an additional trace.
+ expect(chain.traces, hasLength(3));
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('chainForTrace'))));
+ expect(chain.traces[2].frames,
+ contains(frameMember(startsWith('inMicrotask'))));
+ });
+ });
+
+ test('called for a stack trace from a one-shot timer', () {
+ return Chain.capture(() {
+ return chainForTrace(inOneShotTimer, () => throw 'error');
+ }).then((chain) {
+ expect(chain.traces, hasLength(3));
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('chainForTrace'))));
+ expect(chain.traces[2].frames,
+ contains(frameMember(startsWith('inOneShotTimer'))));
+ });
+ });
+
+ test('called for a stack trace from a periodic timer', () {
+ return Chain.capture(() {
+ return chainForTrace(inPeriodicTimer, () => throw 'error');
+ }).then((chain) {
+ expect(chain.traces, hasLength(3));
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('chainForTrace'))));
+ expect(chain.traces[2].frames,
+ contains(frameMember(startsWith('inPeriodicTimer'))));
+ });
+ });
+
+ test('called for a stack trace from a nested series of asynchronous '
+ 'operations', () {
+ return Chain.capture(() {
+ return chainForTrace((callback) {
+ inPeriodicTimer(() => inOneShotTimer(() => inMicrotask(callback)));
+ }, () => throw 'error');
+ }).then((chain) {
+ expect(chain.traces, hasLength(5));
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('chainForTrace'))));
+ expect(chain.traces[2].frames,
+ contains(frameMember(startsWith('inMicrotask'))));
+ expect(chain.traces[3].frames,
+ contains(frameMember(startsWith('inOneShotTimer'))));
+ expect(chain.traces[4].frames,
+ contains(frameMember(startsWith('inPeriodicTimer'))));
+ });
+ });
+
+ test('called for a stack trace from a long future chain', () {
+ return Chain.capture(() {
+ return chainForTrace(inFutureChain, () => throw 'error');
+ }).then((chain) {
+ expect(chain.traces, hasLength(3));
+ expect(chain.traces[0].frames.first, frameMember(startsWith('main')));
+ expect(chain.traces[1].frames,
+ contains(frameMember(startsWith('chainForTrace'))));
+ expect(chain.traces[2].frames,
+ contains(frameMember(startsWith('inFutureChain'))));
+ });
+ });
+
+ test('called for an unregistered stack trace returns a chain wrapping that '
+ 'trace', () {
+ var trace;
+ var chain = Chain.capture(() {
+ try {
+ throw 'error';
+ } catch (_, stackTrace) {
+ trace = stackTrace;
+ return new Chain.forTrace(stackTrace);
+ }
+ });
+
+ expect(chain.traces, hasLength(1));
+ expect(chain.traces.first.toString(),
+ equals(new Trace.from(trace).toString()));
+ });
+ });
+
+ test('forTrace() outside of capture() returns a chain wrapping the given '
+ 'trace', () {
+ var trace;
+ var chain = Chain.capture(() {
+ try {
+ throw 'error';
+ } catch (_, stackTrace) {
+ trace = stackTrace;
+ return new Chain.forTrace(stackTrace);
+ }
+ });
+
+ expect(chain.traces, hasLength(1));
+ expect(chain.traces.first.toString(),
+ equals(new Trace.from(trace).toString()));
+ });
+
+ test('Chain.parse() parses a real Chain', () {
+ return captureFuture(() => inMicrotask(() => throw 'error')).then((chain) {
+ expect(new Chain.parse(chain.toString()).toString(),
+ equals(chain.toString()));
+ });
+ });
+
+ var userSlashCode = p.join('user', 'code.dart');
+ group('Chain.terse', () {
+ test('makes each trace terse', () {
+ var chain = new Chain([
+ new Trace.parse(
+ 'dart:core 10:11 Foo.bar\n'
+ 'dart:core 10:11 Bar.baz\n'
+ 'user/code.dart 10:11 Bang.qux\n'
+ 'dart:core 10:11 Zip.zap\n'
+ 'dart:core 10:11 Zop.zoop'),
+ new Trace.parse(
+ 'user/code.dart 10:11 Bang.qux\n'
+ 'dart:core 10:11 Foo.bar\n'
+ 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n'
+ 'dart:core 10:11 Zip.zap\n'
+ 'user/code.dart 10:11 Zop.zoop')
+ ]);
+
+ expect(chain.terse.toString(), equals(
+ 'dart:core Bar.baz\n'
+ '$userSlashCode 10:11 Bang.qux\n'
+ 'dart:core Zop.zoop\n'
+ '===== asynchronous gap ===========================\n'
+ '$userSlashCode 10:11 Bang.qux\n'
+ 'dart:core Zip.zap\n'
+ '$userSlashCode 10:11 Zop.zoop\n'));
+ });
+
+ test('eliminates internal-only traces', () {
+ var chain = new Chain([
+ new Trace.parse(
+ 'user/code.dart 10:11 Foo.bar\n'
+ 'dart:core 10:11 Bar.baz'),
+ new Trace.parse(
+ 'dart:core 10:11 Foo.bar\n'
+ 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n'
+ 'dart:core 10:11 Zip.zap'),
+ new Trace.parse(
+ 'user/code.dart 10:11 Foo.bar\n'
+ 'dart:core 10:11 Bar.baz')
+ ]);
+
+ expect(chain.terse.toString(), equals(
+ '$userSlashCode 10:11 Foo.bar\n'
+ 'dart:core Bar.baz\n'
+ '===== asynchronous gap ===========================\n'
+ '$userSlashCode 10:11 Foo.bar\n'
+ 'dart:core Bar.baz\n'));
+ });
+ });
+
+ test('Chain.toTrace eliminates asynchronous gaps', () {
+ var trace = new Chain([
+ new Trace.parse(
+ 'user/code.dart 10:11 Foo.bar\n'
+ 'dart:core 10:11 Bar.baz'),
+ new Trace.parse(
+ 'user/code.dart 10:11 Foo.bar\n'
+ 'dart:core 10:11 Bar.baz')
+ ]).toTrace();
+
+ expect(trace.toString(), equals(
+ '$userSlashCode 10:11 Foo.bar\n'
+ 'dart:core 10:11 Bar.baz\n'
+ '$userSlashCode 10:11 Foo.bar\n'
+ 'dart:core 10:11 Bar.baz\n'));
+ });
+
+ group('Chain.track(Future)', () {
+ test('associates the current chain with a manually-reported exception with '
+ 'a stack trace', () {
+ var trace = new Trace.current();
+ return captureFuture(() {
+ inMicrotask(() => trackedErrorFuture(trace));
+ }).then((chain) {
+ expect(chain.traces, hasLength(3));
+
+ // The first trace is the trace that was manually reported for the
+ // error.
+ expect(chain.traces.first.toString(), equals(trace.toString()));
+
+ // The second trace is the trace that was captured when [Chain.track]
+ // was called.
+ expect(chain.traces[1].frames.first,
+ frameMember(startsWith('trackedErrorFuture')));
+
+ // The third trace is the automatically-captured trace from when the
+ // microtask was scheduled.
+ expect(chain.traces[2].frames,
+ contains(frameMember(startsWith('inMicrotask'))));
+ });
+ });
+
+ test('associates the current chain with a manually-reported exception with '
+ 'no stack trace', () {
+ return captureFuture(() {
+ inMicrotask(() => trackedErrorFuture());
+ }).then((chain) {
+ expect(chain.traces, hasLength(3));
+
+ // The first trace is the one captured by
+ // [StackZoneSpecification.trackFuture], which should contain only
+ // stack_trace and dart: frames.
+ expect(chain.traces.first.frames,
+ everyElement(frameLibrary(isNot(contains('chain_test')))));
+
+ expect(chain.traces[1].frames.first,
+ frameMember(startsWith('trackedErrorFuture')));
+ expect(chain.traces[2].frames,
+ contains(frameMember(startsWith('inMicrotask'))));
+ });
+ });
+
+ test('forwards the future value within Chain.capture()', () {
+ Chain.capture(() {
+ expect(Chain.track(new Future.value('value')),
+ completion(equals('value')));
+
+ var trace = new Trace.current();
+ expect(Chain.track(new Future.error('error', trace))
+ .catchError((e, stackTrace) {
+ expect(e, equals('error'));
+ expect(stackTrace.toString(), equals(trace.toString()));
+ }), completes);
+ });
+ });
+
+ test('forwards the future value outside of Chain.capture()', () {
+ expect(Chain.track(new Future.value('value')),
+ completion(equals('value')));
+
+ var trace = new Trace.current();
+ expect(Chain.track(new Future.error('error', trace))
+ .catchError((e, stackTrace) {
+ expect(e, equals('error'));
+ expect(stackTrace.toString(), equals(trace.toString()));
+ }), completes);
+ });
+ });
+
+ group('Chain.track(Stream)', () {
+ test('associates the current chain with a manually-reported exception with '
+ 'a stack trace', () {
+ var trace = new Trace.current();
+ return captureFuture(() {
+ inMicrotask(() => trackedErrorStream(trace).listen(null));
+ }).then((chain) {
+ expect(chain.traces, hasLength(3));
+ expect(chain.traces.first.toString(), equals(trace.toString()));
+ expect(chain.traces[1].frames.first,
+ frameMember(startsWith('trackedErrorStream')));
+ expect(chain.traces[2].frames,
+ contains(frameMember(startsWith('inMicrotask'))));
+ });
+ });
+
+ test('associates the current chain with a manually-reported exception with '
+ 'no stack trace', () {
+ return captureFuture(() {
+ inMicrotask(() => trackedErrorStream().listen(null));
+ }).then((chain) {
+ expect(chain.traces, hasLength(3));
+ expect(chain.traces.first.frames,
+ everyElement(frameLibrary(isNot(contains('chain_test')))));
+ expect(chain.traces[1].frames.first,
+ frameMember(startsWith('trackedErrorStream')));
+ expect(chain.traces[2].frames,
+ contains(frameMember(startsWith('inMicrotask'))));
+ });
+ });
+
+ test('forwards stream values within Chain.capture()', () {
+ Chain.capture(() {
+ var controller = new StreamController()
+ ..add(1)..add(2)..add(3)..close();
+ expect(Chain.track(controller.stream).toList(),
+ completion(equals([1, 2, 3])));
+
+ var trace = new Trace.current();
+ controller = new StreamController()..addError('error', trace);
+ expect(Chain.track(controller.stream).toList()
+ .catchError((e, stackTrace) {
+ expect(e, equals('error'));
+ expect(stackTrace.toString(), equals(trace.toString()));
+ }), completes);
+ });
+ });
+
+ test('forwards stream values outside of Chain.capture()', () {
+ Chain.capture(() {
+ var controller = new StreamController()
+ ..add(1)..add(2)..add(3)..close();
+ expect(Chain.track(controller.stream).toList(),
+ completion(equals([1, 2, 3])));
+
+ var trace = new Trace.current();
+ controller = new StreamController()..addError('error', trace);
+ expect(Chain.track(controller.stream).toList()
+ .catchError((e, stackTrace) {
+ expect(e, equals('error'));
+ expect(stackTrace.toString(), equals(trace.toString()));
+ }), completes);
+ });
+ });
+ });
+}
+
+/// Runs [callback] in a microtask callback.
+void inMicrotask(callback()) => scheduleMicrotask(callback);
+
+/// Runs [callback] in a one-shot timer callback.
+void inOneShotTimer(callback()) => Timer.run(callback);
+
+/// Runs [callback] once in a periodic timer callback.
+void inPeriodicTimer(callback()) {
+ var count = 0;
+ new Timer.periodic(new Duration(milliseconds: 1), (timer) {
+ count++;
+ if (count != 5) return;
+ timer.cancel();
+ callback();
+ });
+}
+
+/// Runs [callback] within a long asynchronous Future chain.
+void inFutureChain(callback()) {
+ new Future(() {})
+ .then((_) => new Future(() {}))
+ .then((_) => new Future(() {}))
+ .then((_) => new Future(() {}))
+ .then((_) => new Future(() {}))
+ .then((_) => callback())
+ .then((_) => new Future(() {}));
+}
+
+/// Returns a Future that completes to an error and is wrapped in [Chain.track].
+///
+/// If [trace] is passed, it's used as the stack trace for the error.
+Future trackedErrorFuture([StackTrace trace]) {
+ var completer = new Completer();
+ completer.completeError('error', trace);
+ return Chain.track(completer.future);
+}
+
+/// Returns a Stream that emits an error and is wrapped in [Chain.track].
+///
+/// If [trace] is passed, it's used as the stack trace for the error.
+Stream trackedErrorStream([StackTrace trace]) {
+ var controller = new StreamController();
+ controller.addError('error', trace);
+ return Chain.track(controller.stream);
+}
+
+/// Runs [callback] within [asyncFn], then converts any errors raised into a
+/// [Chain] with [Chain.forTrace].
+Future<Chain> chainForTrace(asyncFn(callback()), callback()) {
+ var completer = new Completer();
+ asyncFn(() {
+ // We use `new Future.value().then(...)` here as opposed to [new Future] or
+ // [new Future.sync] because those methods don't pass the exception through
+ // the zone specification before propagating it, so there's no chance to
+ // attach a chain to its stack trace. See issue 15105.
+ new Future.value().then((_) => callback())
+ .catchError(completer.completeError);
+ });
+ return completer.future
+ .catchError((_, stackTrace) => new Chain.forTrace(stackTrace));
+}
+
+/// Runs [callback] in a [Chain.capture] zone and returns a Future that
+/// completes to the stack chain for an error thrown by [callback].
+///
+/// [callback] is expected to throw the string `"error"`.
+Future<Chain> captureFuture(callback()) {
+ var completer = new Completer<Chain>();
+ Chain.capture(callback, onError: (error, chain) {
+ expect(error, equals('error'));
+ completer.complete(chain);
+ });
+ return completer.future;
+}
diff --git a/pkg/stack_trace/test/trace_test.dart b/pkg/stack_trace/test/trace_test.dart
index ad916f1..4c3278f 100644
--- a/pkg/stack_trace/test/trace_test.dart
+++ b/pkg/stack_trace/test/trace_test.dart
@@ -171,6 +171,24 @@
equals(Uri.parse("http://dartlang.org/foo/baz.dart")));
});
+ test('parses a package:stack_trace stack chain correctly', () {
+ var trace = new Trace.parse(
+ 'http://dartlang.org/foo/bar.dart 10:11 Foo.<fn>.bar\n'
+ 'http://dartlang.org/foo/baz.dart Foo.<fn>.bar\n'
+ '===== asynchronous gap ===========================\n'
+ 'http://dartlang.org/foo/bang.dart 10:11 Foo.<fn>.bar\n'
+ 'http://dartlang.org/foo/quux.dart Foo.<fn>.bar');
+
+ expect(trace.frames[0].uri,
+ equals(Uri.parse("http://dartlang.org/foo/bar.dart")));
+ expect(trace.frames[1].uri,
+ equals(Uri.parse("http://dartlang.org/foo/baz.dart")));
+ expect(trace.frames[2].uri,
+ equals(Uri.parse("http://dartlang.org/foo/bang.dart")));
+ expect(trace.frames[3].uri,
+ equals(Uri.parse("http://dartlang.org/foo/quux.dart")));
+ });
+
test('parses a real package:stack_trace stack trace correctly', () {
var traceString = new Trace.current().toString();
expect(new Trace.parse(traceString).toString(), equals(traceString));
diff --git a/pkg/stack_trace/test/utils.dart b/pkg/stack_trace/test/utils.dart
new file mode 100644
index 0000000..ed75631
--- /dev/null
+++ b/pkg/stack_trace/test/utils.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library stack_trace.test.utils;
+
+import 'package:unittest/unittest.dart';
+
+/// Returns a matcher that runs [matcher] against a [Frame]'s `member` field.
+Matcher frameMember(matcher) =>
+ transform((frame) => frame.member, matcher, 'member');
+
+/// Returns a matcher that runs [matcher] against a [Frame]'s `library` field.
+Matcher frameLibrary(matcher) =>
+ transform((frame) => frame.library, matcher, 'library');
+
+/// Returns a matcher that runs [transformation] on its input, then matches
+/// the output against [matcher].
+///
+/// [description] should be a noun phrase that describes the relation of the
+/// output of [transformation] to its input.
+Matcher transform(transformation(value), matcher, String description) =>
+ new _TransformMatcher(transformation, wrapMatcher(matcher), description);
+
+class _TransformMatcher extends Matcher {
+ final Function _transformation;
+ final Matcher _matcher;
+ final String _description;
+
+ _TransformMatcher(this._transformation, this._matcher, this._description);
+
+ bool matches(item, Map matchState) =>
+ _matcher.matches(_transformation(item), matchState);
+
+ Description describe(Description description) =>
+ description.add(_description).add(' ').addDescriptionOf(_matcher);
+}
diff --git a/pkg/template_binding/test/template_binding_test.dart b/pkg/template_binding/test/template_binding_test.dart
index cc52811..7639d76 100644
--- a/pkg/template_binding/test/template_binding_test.dart
+++ b/pkg/template_binding/test/template_binding_test.dart
@@ -1177,27 +1177,38 @@
});
recursivelySetTemplateModel(div, m);
+
+ var completer = new Completer();
+
+ new MutationObserver((records, observer) {
+ var select = div.nodes[0].nextNode;
+ if (select == null || select.querySelector('option') == null) return;
+
+ observer.disconnect();
+ new Future(() {
+ expect(select.nodes.length, 2);
+
+ expect(select.selectedIndex, 1, reason: 'selected index should update '
+ 'after template expands.');
+
+ expect(select.nodes[0].tagName, 'TEMPLATE');
+ expect((templateBind(templateBind(select.nodes[0]).ref)
+ .content.nodes[0] as Element).tagName, 'OPTGROUP');
+
+ var optgroup = select.nodes[1];
+ expect(optgroup.nodes[0].tagName, 'TEMPLATE');
+ expect(optgroup.nodes[1].tagName, 'OPTION');
+ expect(optgroup.nodes[1].text, '0');
+ expect(optgroup.nodes[2].tagName, 'OPTION');
+ expect(optgroup.nodes[2].text, '1');
+
+ completer.complete();
+ });
+ })..observe(div, childList: true, subtree: true);
+
Observable.dirtyCheck();
- // Use a timer so it's slower than mutation observers.
- return new Future(() {
- var select = div.nodes[0].nextNode;
- expect(select.nodes.length, 2);
-
- expect(select.selectedIndex, 1, reason: 'selected index should update by '
- 'animationFrame time');
-
- expect(select.nodes[0].tagName, 'TEMPLATE');
- expect((templateBind(templateBind(select.nodes[0]).ref)
- .content.nodes[0] as Element).tagName, 'OPTGROUP');
-
- var optgroup = select.nodes[1];
- expect(optgroup.nodes[0].tagName, 'TEMPLATE');
- expect(optgroup.nodes[1].tagName, 'OPTION');
- expect(optgroup.nodes[1].text, '0');
- expect(optgroup.nodes[2].tagName, 'OPTION');
- expect(optgroup.nodes[2].text, '1');
- });
+ return completer.future;
});
observeTest('NestedIterateTableMixedSemanticNative', () {
diff --git a/pkg/third_party/html5lib/pubspec.yaml b/pkg/third_party/html5lib/pubspec.yaml
index 0e54366..955132d 100644
--- a/pkg/third_party/html5lib/pubspec.yaml
+++ b/pkg/third_party/html5lib/pubspec.yaml
@@ -1,5 +1,5 @@
name: html5lib
-version: 0.9.1-dev
+version: 0.9.1
author: Dart Team <misc@dartlang.org>
description: A library for working with HTML documents.
homepage: http://pub.dartlang.org/packages/html5lib
@@ -11,4 +11,4 @@
path: ">=0.9.0 <0.10.0"
unittest: ">=0.9.0 <0.10.0"
environment:
- sdk: ">=0.8.10+6 <2.0.0"
+ sdk: ">=1.0.0 <2.0.0"
diff --git a/pkg/watcher/lib/src/directory_watcher/linux.dart b/pkg/watcher/lib/src/directory_watcher/linux.dart
index 5196078..d62c6ef 100644
--- a/pkg/watcher/lib/src/directory_watcher/linux.dart
+++ b/pkg/watcher/lib/src/directory_watcher/linux.dart
@@ -166,7 +166,7 @@
if (error is FileSystemException) return;
_eventsController.addError(error, stackTrace);
- _eventsController.close();
+ close();
}, cancelOnError: true);
});
}
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 1c1277b..ed010db 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -65,19 +65,30 @@
int64_t DartUtils::GetIntegerValue(Dart_Handle value_obj) {
- ASSERT(Dart_IsInteger(value_obj));
int64_t value = 0;
Dart_Handle result = Dart_IntegerToInt64(value_obj, &value);
- ASSERT(!Dart_IsError(result));
+ if (Dart_IsError(result)) Dart_PropagateError(result);
+ return value;
+}
+
+
+int64_t DartUtils::GetInt64ValueCheckRange(
+ Dart_Handle value_obj, int64_t lower, int64_t upper) {
+ int64_t value = DartUtils::GetIntegerValue(value_obj);
+ if (value < lower || upper < value) {
+ Dart_PropagateError(Dart_NewApiError("Value outside expected range"));
+ }
return value;
}
intptr_t DartUtils::GetIntptrValue(Dart_Handle value_obj) {
- ASSERT(Dart_IsInteger(value_obj));
int64_t value = 0;
Dart_Handle result = Dart_IntegerToInt64(value_obj, &value);
- ASSERT(!Dart_IsError(result));
+ if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (value < kIntptrMin || kIntptrMax < value) {
+ Dart_PropagateError(Dart_NewApiError("Value outside intptr_t range"));
+ }
return static_cast<intptr_t>(value);
}
@@ -86,11 +97,11 @@
bool valid = Dart_IsInteger(value_obj);
if (valid) {
Dart_Handle result = Dart_IntegerFitsIntoInt64(value_obj, &valid);
- ASSERT(!Dart_IsError(result));
+ if (Dart_IsError(result)) Dart_PropagateError(result);
}
if (!valid) return false;
Dart_Handle result = Dart_IntegerToInt64(value_obj, value);
- ASSERT(!Dart_IsError(result));
+ if (Dart_IsError(result)) Dart_PropagateError(result);
return true;
}
@@ -98,7 +109,7 @@
const char* DartUtils::GetStringValue(Dart_Handle str_obj) {
const char* cstring = NULL;
Dart_Handle result = Dart_StringToCString(str_obj, &cstring);
- ASSERT(!Dart_IsError(result));
+ if (Dart_IsError(result)) Dart_PropagateError(result);
return cstring;
}
@@ -106,7 +117,7 @@
bool DartUtils::GetBooleanValue(Dart_Handle bool_obj) {
bool value = false;
Dart_Handle result = Dart_BooleanValue(bool_obj, &value);
- ASSERT(!Dart_IsError(result));
+ if (Dart_IsError(result)) Dart_PropagateError(result);
return value;
}
@@ -117,14 +128,14 @@
Dart_Handle result = Dart_SetField(handle,
NewString(name),
Dart_NewInteger(val));
- ASSERT(!Dart_IsError(result));
+ if (Dart_IsError(result)) Dart_PropagateError(result);
}
intptr_t DartUtils::GetIntegerField(Dart_Handle handle,
const char* name) {
Dart_Handle result = Dart_GetField(handle, NewString(name));
- ASSERT(!Dart_IsError(result));
+ if (Dart_IsError(result)) Dart_PropagateError(result);
intptr_t value = DartUtils::GetIntegerValue(result);
return value;
}
@@ -134,7 +145,7 @@
const char* name,
const char* val) {
Dart_Handle result = Dart_SetField(handle, NewString(name), NewString(val));
- ASSERT(!Dart_IsError(result));
+ if (Dart_IsError(result)) Dart_PropagateError(result);
}
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 476d813..f6ae3ab 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -78,23 +78,30 @@
class DartUtils {
public:
- // TODO(turnidge): Clean up the implementations of these so that
- // they allow for proper error propagation.
-
- // Assumes that the value object is known to be an integer object
- // that fits in a signed 64-bit integer.
+ // Returns the integer value of a Dart object. If the object is not
+ // an integer value an API error is propagated.
static int64_t GetIntegerValue(Dart_Handle value_obj);
- // Assumes that the value object is known to be an intptr_t. This should
- // only be known when the value has been put into Dart as a pointer encoded
- // in a 64-bit integer. This is the case for file and directory operations.
+ // Returns the integer value of a Dart object. If the object is not
+ // an integer value or outside the requested range an API error is
+ // propagated.
+ static int64_t GetInt64ValueCheckRange(
+ Dart_Handle value_obj, int64_t lower, int64_t upper);
+ // Returns the intptr_t value of a Dart object. If the object is not
+ // an integer value or the value is outside the intptr_t range an
+ // API error is propagated.
static intptr_t GetIntptrValue(Dart_Handle value_obj);
// Checks that the value object is an integer object that fits in a
// signed 64-bit integer. If it is, the value is returned in the
// value out parameter and true is returned. Otherwise, false is
// returned.
static bool GetInt64Value(Dart_Handle value_obj, int64_t* value);
+ // Returns the string value of a Dart object. If the object is not
+ // a string value an API error is propagated.
static const char* GetStringValue(Dart_Handle str_obj);
+ // Returns the boolean value of a Dart object. If the object is not
+ // a boolean value an API error is propagated.
static bool GetBooleanValue(Dart_Handle bool_obj);
+
static void SetIntegerField(Dart_Handle handle,
const char* name,
intptr_t val);
diff --git a/runtime/bin/directory_linux.cc b/runtime/bin/directory_linux.cc
index d4960ec..3b9d016 100644
--- a/runtime/bin/directory_linux.cc
+++ b/runtime/bin/directory_linux.cc
@@ -69,7 +69,7 @@
// These are scanned to detect loops while doing a recursive directory listing.
struct LinkList {
dev_t dev;
- ino_t ino;
+ ino64_t ino;
LinkList* next;
};
diff --git a/runtime/bin/eventhandler_android.cc b/runtime/bin/eventhandler_android.cc
index 6a339b3..fb8cc25 100644
--- a/runtime/bin/eventhandler_android.cc
+++ b/runtime/bin/eventhandler_android.cc
@@ -74,9 +74,6 @@
event.events = sd->GetPollEvents();
event.data.ptr = sd;
if (sd->port() != 0 && event.events != 0) {
- // Only report events once and wait for them to be re-enabled after the
- // event has been handled by the Dart code.
- event.events |= EPOLLONESHOT;
int status = 0;
if (sd->tracked_by_epoll()) {
status = TEMP_FAILURE_RETRY(epoll_ctl(epoll_fd_,
@@ -341,10 +338,11 @@
} else {
SocketData* sd = reinterpret_cast<SocketData*>(events[i].data.ptr);
intptr_t event_mask = GetPollEvents(events[i].events, sd);
- if (event_mask == 0) {
- // Event not handled, re-add to epoll.
- UpdateEpollInstance(epoll_fd_, sd);
- } else {
+ if (event_mask != 0) {
+ // Unregister events for the file descriptor. Events will be
+ // registered again when the current event has been handled in
+ // Dart code.
+ RemoveFromEpollInstance(epoll_fd_, sd);
Dart_Port port = sd->port();
ASSERT(port != 0);
DartUtils::PostInt32(port, event_mask);
@@ -400,9 +398,8 @@
if (errno != EWOULDBLOCK) {
perror("Poll failed");
}
- } else if (result == 0) {
- handler->HandleTimeout();
} else {
+ handler->HandleTimeout();
handler->HandleEvents(events, result);
}
}
diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc
index 67f5c46..6c7744f 100644
--- a/runtime/bin/eventhandler_macos.cc
+++ b/runtime/bin/eventhandler_macos.cc
@@ -78,11 +78,19 @@
static const intptr_t kMaxChanges = 2;
intptr_t changes = 0;
struct kevent events[kMaxChanges];
+ // Only report events once and wait for them to be re-enabled after the
+ // event has been handled by the Dart code. This is done by using EV_ONESHOT.
if (sd->port() != 0) {
// Register or unregister READ filter if needed.
if (sd->HasReadEvent()) {
if (!sd->read_tracked_by_kqueue()) {
- EV_SET(events + changes, sd->fd(), EVFILT_READ, EV_ADD, 0, 0, sd);
+ EV_SET(events + changes,
+ sd->fd(),
+ EVFILT_READ,
+ EV_ADD | EV_ONESHOT,
+ 0,
+ 0,
+ sd);
++changes;
sd->set_read_tracked_by_kqueue(true);
}
@@ -94,7 +102,13 @@
// Register or unregister WRITE filter if needed.
if (sd->HasWriteEvent()) {
if (!sd->write_tracked_by_kqueue()) {
- EV_SET(events + changes, sd->fd(), EVFILT_WRITE, EV_ADD, 0, 0, sd);
+ EV_SET(events + changes,
+ sd->fd(),
+ EVFILT_WRITE,
+ EV_ADD | EV_ONESHOT,
+ 0,
+ 0,
+ sd);
++changes;
sd->set_write_tracked_by_kqueue(true);
}
@@ -339,12 +353,13 @@
interrupt_seen = true;
} else {
SocketData* sd = reinterpret_cast<SocketData*>(events[i].udata);
+ sd->set_write_tracked_by_kqueue(false);
+ sd->set_read_tracked_by_kqueue(false);
intptr_t event_mask = GetEvents(events + i, sd);
- if (event_mask != 0) {
- // Unregister events for the file descriptor. Events will be
- // registered again when the current event has been handled in
- // Dart code.
- RemoveFromKqueue(kqueue_fd_, sd);
+ if (event_mask == 0) {
+ // Event not handled, re-add to kqueue.
+ UpdateKqueue(kqueue_fd_, sd);
+ } else {
Dart_Port port = sd->port();
ASSERT(port != 0);
DartUtils::PostInt32(port, event_mask);
diff --git a/runtime/bin/file_system_watcher_macos.cc b/runtime/bin/file_system_watcher_macos.cc
index 77fb6a9..2200b78 100644
--- a/runtime/bin/file_system_watcher_macos.cc
+++ b/runtime/bin/file_system_watcher_macos.cc
@@ -14,6 +14,7 @@
#include "bin/eventhandler.h"
#include "bin/fdutils.h"
+#include "bin/file.h"
#include "bin/socket.h"
#include "bin/thread.h"
@@ -49,10 +50,11 @@
union FSEvent {
struct {
+ uint32_t exists;
uint32_t flags;
char path[PATH_MAX];
} data;
- uint8_t bytes[PATH_MAX + 4];
+ uint8_t bytes[PATH_MAX + 8];
};
class FSEventsWatcher {
@@ -179,7 +181,7 @@
CFArrayCreate(NULL, reinterpret_cast<const void**>(&path_ref), 1, NULL),
kFSEventStreamEventIdSinceNow,
0.10,
- kFSEventStreamCreateFlagFileEvents);
+ kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents);
node->set_ref(ref);
@@ -201,11 +203,12 @@
Node* node = reinterpret_cast<Node*>(client);
for (size_t i = 0; i < num_events; i++) {
char *path = reinterpret_cast<char**>(event_paths)[i];
+ FSEvent event;
+ event.data.exists = File::Exists(path);
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;
- FSEvent event;
event.data.flags = event_flags[i];
memmove(event.data.path, path, strlen(path) + 1);
write(node->write_fd(), event.bytes, sizeof(event));
@@ -272,7 +275,7 @@
// The moved path is the path being watched.
mask |= kDeleteSelf;
} else {
- mask |= kMove;
+ mask |= e.data.exists ? kCreate : kDelete;
}
}
if (flags & kFSEventStreamEventFlagItemModified) mask |= kModifyContent;
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index ef204de..59cf35a 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -689,8 +689,7 @@
// Exit code indicating an unhandled error that is not a compilation error.
static const int kErrorExitCode = 255;
-
-static int ErrorExit(int exit_code, const char* format, ...) {
+static void ErrorExit(int exit_code, const char* format, ...) {
va_list arguments;
va_start(arguments, format);
Log::VPrintErr(format, arguments);
@@ -702,14 +701,17 @@
Dart_Cleanup();
- return exit_code;
+ exit(exit_code);
}
-static int DartErrorExit(Dart_Handle error) {
+static void DartExitOnError(Dart_Handle error) {
+ if (!Dart_IsError(error)) {
+ return;
+ }
const int exit_code = Dart_IsCompilationError(error) ?
kCompilationErrorExitCode : kErrorExitCode;
- return ErrorExit(exit_code, "%s\n", Dart_GetError(error));
+ ErrorExit(exit_code, "%s\n", Dart_GetError(error));
}
@@ -754,7 +756,7 @@
}
-int main(int argc, char** argv) {
+void main(int argc, char** argv) {
char* script_name;
CommandLineOptions vm_options(argc);
CommandLineOptions dart_options(argc);
@@ -780,18 +782,18 @@
&verbose_debug_seen) < 0) {
if (has_help_option) {
PrintUsage();
- return 0;
+ exit(0);
} else if (has_version_option) {
PrintVersion();
- return 0;
+ exit(0);
} else if (print_flags_seen) {
// Will set the VM flags, print them out and then we exit as no
// script was specified on the command line.
Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
- return 0;
+ exit(0);
} else {
PrintUsage();
- return kErrorExitCode;
+ exit(kErrorExitCode);
}
}
@@ -799,7 +801,7 @@
OSError err;
fprintf(stderr, "Error determinig current directory: %s\n", err.message());
fflush(stderr);
- return kErrorExitCode;
+ exit(kErrorExitCode);
}
Dart_SetVMFlags(vm_options.count(), vm_options.arguments());
@@ -813,7 +815,7 @@
DartUtils::EntropySource)) {
fprintf(stderr, "%s", "VM initialization failed\n");
fflush(stderr);
- return kErrorExitCode;
+ exit(kErrorExitCode);
}
// Start the debugger wire protocol handler if necessary.
@@ -854,7 +856,7 @@
Log::PrintErr("%s\n", error);
free(error);
delete [] isolate_name;
- return is_compile_error ? kCompilationErrorExitCode : kErrorExitCode;
+ exit(is_compile_error ? kCompilationErrorExitCode : kErrorExitCode);
}
delete [] isolate_name;
@@ -871,10 +873,7 @@
uint8_t* buffer = NULL;
intptr_t size = 0;
result = Dart_CreateScriptSnapshot(&buffer, &size);
- if (Dart_IsError(result)) {
- Log::PrintErr("%s\n", Dart_GetError(result));
- return DartErrorExit(result);
- }
+ DartExitOnError(result);
// Write the magic number to indicate file is a script snapshot.
DartUtils::WriteMagicNumber(snapshot_file);
@@ -894,40 +893,34 @@
if (has_compile_all) {
result = Dart_CompileAll();
- if (Dart_IsError(result)) {
- return DartErrorExit(result);
- }
+ DartExitOnError(result);
}
if (Dart_IsNull(root_lib)) {
- return ErrorExit(kErrorExitCode,
- "Unable to find root library for '%s'\n",
- script_name);
+ ErrorExit(kErrorExitCode,
+ "Unable to find root library for '%s'\n",
+ script_name);
}
if (has_print_script) {
result = GenerateScriptSource();
- if (Dart_IsError(result)) {
- return DartErrorExit(result);
- }
+ DartExitOnError(result);
} else {
// The helper function _getMainClosure creates a closure for the main
// entry point which is either explicitly or implictly exported from the
// root library.
Dart_Handle main_closure = Dart_Invoke(
builtin_lib, Dart_NewStringFromCString("_getMainClosure"), 0, NULL);
- if (Dart_IsError(main_closure)) {
- return DartErrorExit(result);
- }
+ DartExitOnError(main_closure);
// Set debug breakpoint if specified on the command line before calling
// the main function.
if (breakpoint_at != NULL) {
result = SetBreakpoint(breakpoint_at, root_lib);
if (Dart_IsError(result)) {
- return ErrorExit(kErrorExitCode,
- "Error setting breakpoint at '%s': %s\n",
- breakpoint_at,
- Dart_GetError(result));
+ ErrorExit(kErrorExitCode,
+ "Error setting breakpoint at '%s': %s\n",
+ breakpoint_at,
+ Dart_GetError(result));
}
}
@@ -948,22 +941,18 @@
Dart_Handle initial_startup_msg = Dart_NewList(3);
result = Dart_ListSetAt(initial_startup_msg, 1,
CreateRuntimeOptions(&dart_options));
- if (Dart_IsError(result)) {
- return DartErrorExit(result);
- }
+ DartExitOnError(result);
Dart_Port main_port = Dart_GetMainPortId();
bool posted = Dart_Post(main_port, initial_startup_msg);
if (!posted) {
- return ErrorExit(kErrorExitCode,
- "Failed posting startup message to main "
- "isolate control port.");
+ ErrorExit(kErrorExitCode,
+ "Failed posting startup message to main "
+ "isolate control port.");
}
// Keep handling messages until the last active receive port is closed.
result = Dart_RunLoop();
- if (Dart_IsError(result)) {
- return DartErrorExit(result);
- }
+ DartExitOnError(result);
}
}
@@ -993,12 +982,13 @@
Platform::Cleanup();
- return Process::GlobalExitCode();
+ exit(Process::GlobalExitCode());
}
} // namespace bin
} // namespace dart
int main(int argc, char** argv) {
- return dart::bin::main(argc, argv);
+ dart::bin::main(argc, argv);
+ UNREACHABLE();
}
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index e4ee1ab..175d07e 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -103,21 +103,17 @@
void FUNCTION_NAME(Socket_CreateConnect)(Dart_NativeArguments args) {
RawAddr addr;
GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
- int64_t port = 0;
- if (DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 2), &port)) {
- intptr_t socket = Socket::CreateConnect(addr, port);
- OSError error;
- if (socket >= 0) {
- Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 0), socket);
- Dart_SetReturnValue(args, Dart_True());
- } else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError(&error));
- }
+ int64_t port = DartUtils::GetInt64ValueCheckRange(
+ Dart_GetNativeArgument(args, 2),
+ 0,
+ 65535);
+ intptr_t socket = Socket::CreateConnect(addr, port);
+ OSError error;
+ if (socket >= 0) {
+ Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 0), socket);
+ Dart_SetReturnValue(args, Dart_True());
} else {
- OSError os_error(-1, "Invalid argument", OSError::kUnknown);
- Dart_Handle err = DartUtils::NewDartOSError(&os_error);
- if (Dart_IsError(err)) Dart_PropagateError(err);
- Dart_SetReturnValue(args, err);
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&error));
}
}
@@ -285,9 +281,8 @@
void FUNCTION_NAME(Socket_GetStdioHandle)(Dart_NativeArguments args) {
- intptr_t num =
- DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 1));
- ASSERT(num == 0 || num == 1 || num == 2);
+ int64_t num = DartUtils::GetInt64ValueCheckRange(
+ Dart_GetNativeArgument(args, 1), 0, 2);
intptr_t socket = Socket::GetStdioHandle(num);
Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 0), socket);
Dart_SetReturnValue(args, Dart_NewBoolean(socket >= 0));
@@ -303,31 +298,29 @@
void FUNCTION_NAME(ServerSocket_CreateBindListen)(Dart_NativeArguments args) {
RawAddr addr;
- int64_t port = 0;
- int64_t backlog = 0;
GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
- if (DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 2), &port) &&
- DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 3), &backlog)) {
- bool v6_only = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
- intptr_t socket = ServerSocket::CreateBindListen(
- addr, port, backlog, v6_only);
- OSError error;
- if (socket >= 0) {
- Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 0), socket);
- Dart_SetReturnValue(args, Dart_True());
- } else {
- if (socket == -5) {
- OSError os_error(-1, "Invalid host", OSError::kUnknown);
- Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
- } else {
- Dart_SetReturnValue(args, DartUtils::NewDartOSError(&error));
- }
- }
+ int64_t port = DartUtils::GetInt64ValueCheckRange(
+ Dart_GetNativeArgument(args, 2),
+ 0,
+ 65535);
+ int64_t backlog = DartUtils::GetInt64ValueCheckRange(
+ Dart_GetNativeArgument(args, 3),
+ 0,
+ 65535);
+ bool v6_only = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
+ intptr_t socket = ServerSocket::CreateBindListen(
+ addr, port, backlog, v6_only);
+ OSError error;
+ if (socket >= 0) {
+ Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 0), socket);
+ Dart_SetReturnValue(args, Dart_True());
} else {
- OSError os_error(-1, "Invalid argument", OSError::kUnknown);
- Dart_Handle err = DartUtils::NewDartOSError(&os_error);
- if (Dart_IsError(err)) Dart_PropagateError(err);
- Dart_SetReturnValue(args, err);
+ if (socket == -5) {
+ OSError os_error(-1, "Invalid host", OSError::kUnknown);
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
+ } else {
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&error));
+ }
}
}
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 789dd00..1480f1f 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -615,7 +615,9 @@
if (isClosedRead) {
close();
} else {
+ bool connected = eventPort != null;
sendToEventHandler(1 << SHUTDOWN_WRITE_COMMAND);
+ if (!connected) disconnectFromEventHandler();
}
isClosedWrite = true;
}
@@ -626,7 +628,9 @@
if (isClosedWrite) {
close();
} else {
+ bool connected = eventPort != null;
sendToEventHandler(1 << SHUTDOWN_READ_COMMAND);
+ if (!connected) disconnectFromEventHandler();
}
isClosedRead = true;
}
diff --git a/runtime/bin/vmservice/client/.gitignore b/runtime/bin/vmservice/client/.gitignore
index 4653995..54dafe2 100644
--- a/runtime/bin/vmservice/client/.gitignore
+++ b/runtime/bin/vmservice/client/.gitignore
@@ -1 +1,2 @@
bootstrap_css
+out
diff --git a/runtime/bin/vmservice/client/build.dart b/runtime/bin/vmservice/client/build.dart
index 71faf8b..627da4e2 100644
--- a/runtime/bin/vmservice/client/build.dart
+++ b/runtime/bin/vmservice/client/build.dart
@@ -13,9 +13,12 @@
compileToJs(_) {
print("Running dart2js");
- var dart_path = Platform.executable;
- var bin_path = dart_path.substring(0, dart_path.lastIndexOf(Platform.pathSeparator));
- var dart2js_path = "$bin_path${Platform.pathSeparator}dart2js";
+ var dart_path = Platform.executable;
+ var dart2js_path = 'dart2js';
+ if (dart_path.lastIndexOf(Platform.pathSeparator) != -1) {
+ var bin_path = dart_path.substring(0, dart_path.lastIndexOf(Platform.pathSeparator));
+ dart2js_path = "$bin_path${Platform.pathSeparator}dart2js";
+ }
var result =
Process.runSync(dart2js_path,
[ '--minify', '-o', 'out/web/index.html_bootstrap.dart.js',
diff --git a/runtime/bin/vmservice/client/deployed/web/index.html b/runtime/bin/vmservice/client/deployed/web/index.html
index fedfc5f..94b6cc8 100644
--- a/runtime/bin/vmservice/client/deployed/web/index.html
+++ b/runtime/bin/vmservice/client/deployed/web/index.html
@@ -18,12 +18,12 @@
<div class="panel panel-danger">
<div class="panel-heading">Error</div>
<div class="panel-body">
- <template if="{{ (error_obj == null) || (error_obj['type'] != '@LanguageError') }}">
- <p>{{ error }}</p>
- </template>
- <template if="{{ (error_obj != null) && (error_obj['type'] == '@LanguageError') }}">
- <pre>{{ error_obj['error_msg'] }}</pre>
- </template>
+ <template if="{{ (error_obj == null) || (error_obj['type'] != 'LanguageError') }}">
+ <p>{{ error }}</p>
+ </template>
+ <template if="{{ (error_obj != null) && (error_obj['type'] == 'LanguageError') }}">
+ <pre>{{ error_obj['error_msg'] }}</pre>
+ </template>
</div>
</div>
</div>
@@ -108,7 +108,8 @@
</div>
</template>
-</polymer-element><polymer-element name="disassembly-entry" extends="observatory-element">
+</polymer-element>
+<polymer-element name="disassembly-entry" extends="observatory-element">
<template>
<div class="row">
<template if="{{ instruction['type'] == 'DisassembledInstructionComment' }}">
@@ -260,7 +261,7 @@
<template>
<div class="row">
<div class="col-md-1">
- <img src="packages/observatory/src/observatory_elements/img/isolate_icon.png" class="img-polaroid">
+ <img src="img/isolate_icon.png" class="img-polaroid">
</div>
<div class="col-md-1">{{ isolate }}</div>
<div class="col-md-10">{{ name }}</div>
@@ -317,16 +318,78 @@
</template>
</template>
-</polymer-element><polymer-element name="library-view" extends="observatory-element">
+</polymer-element>
+<polymer-element name="library-view" extends="observatory-element">
<template>
<div class="alert alert-success">Library {{ library['name'] }}</div>
+ <div class="alert alert-info">Scripts</div>
+ <table class="table table-hover">
+ <tbody>
+ <tr template="" repeat="{{ script in library['scripts']}}">
+ <td>
+ {{ script['kind'] }}
+ </td>
+ <td>
+ <a href="{{ app.locationManager.currentIsolateScriptLink(script['id'], script['name']) }}">{{ script['name'] }}</a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
<div class="alert alert-info">Imported Libraries</div>
<table class="table table-hover">
<tbody>
<tr template="" repeat="{{ lib in library['libraries'] }}">
<td>
<a href="{{ app.locationManager.currentIsolateObjectLink(lib['id'])}}">
- {{ lib['name'] }}
+ {{ lib['url'] }}
+ </a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="alert alert-info">Variables</div>
+ <table class="table table-hover">
+ <tbody>
+ <tr template="" repeat="{{ variable in library['variables'] }}">
+ <td>
+ <template if="{{ variable['final'] }}">
+ final
+ </template>
+ <template if="{{ variable['const'] }}">
+ const
+ </template>
+ <template if="{{ (variable['declared_type']['name'] == 'dynamic' && !variable['final'] && !variable['const']) }}">
+ var
+ </template>
+ <template if="{{ (variable['declared_type']['name'] != 'dynamic') }}">
+ <a href="{{ app.locationManager.currentIsolateClassLink(variable['declared_type']['id']) }}">
+ {{ variable['declared_type']['user_name'] }}
+ </a>
+ </template>
+ <a href="{{ app.locationManager.currentIsolateObjectLink(variable['id'])}}">
+ {{ variable['user_name'] }}
+ </a>
+ </td>
+ <td>
+ <template if="{{ (variable['value']['type'] == 'null') }}">
+ {{ "null" }}
+ </template>
+ <template if="{{ (variable['value']['type'] != 'null') }}">
+ <a href="{{ app.locationManager.currentIsolateObjectLink(variable['value']['id'])}}">
+ {{ variable['value']['preview'] }}
+ </a>
+ </template>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="alert alert-info">Functions</div>
+ <table class="table table-hover">
+ <tbody>
+ <tr template="" repeat="{{ func in library['functions'] }}">
+ <td>
+ <a href="{{ app.locationManager.currentIsolateObjectLink(func['id'])}}">
+ {{ func['user_name'] }}
</a>
</td>
</tr>
@@ -355,6 +418,29 @@
</tr>
</tbody>
</table>
+
+ </template>
+
+</polymer-element><polymer-element name="source-view" extends="observatory-element">
+ <template>
+ <div class="row">
+ <div class="col-md-8 col-md-offset-2">
+ <div class="panel-heading">{{ source.url }}</div>
+ <div class="panel-body">
+ <div class="row">
+ <div><strong>Source</strong></div>
+ </div>
+ <pre> <template repeat="{{ line in source.lines }}">{{line.paddedLine}} {{line.src}}
+ </template>
+ </pre>
+ </div>
+ </div>
+ </div>
+ </template>
+
+</polymer-element><polymer-element name="script-view" extends="observatory-element">
+ <template>
+ <source-view app="{{ app }}" source="{{ script['source'] }}"></source-view>
</template>
</polymer-element><polymer-element name="stack-trace" extends="observatory-element">
@@ -413,6 +499,9 @@
<template if="{{ messageType == 'Code' }}">
<code-view app="{{ app }}" code="{{ message }}"></code-view>
</template>
+ <template if="{{ messageType == 'Script' }}">
+ <script-view app="{{ app }}" script="{{ message }}"></script-view>
+ </template>
<!-- Add new views and message types in the future here. -->
</template>
@@ -447,4 +536,4 @@
</polymer-element>
<observatory-application></observatory-application>
-</body></html>
\ No newline at end of file
+</body></html>
diff --git a/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart b/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart
index b00f899..4d2d042 100644
--- a/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart
+++ b/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart
@@ -14,12 +14,14 @@
import 'package:observatory/src/observatory_elements/isolate_list.dart' as i9;
import 'package:observatory/src/observatory_elements/json_view.dart' as i10;
import 'package:observatory/src/observatory_elements/library_view.dart' as i11;
-import 'package:observatory/src/observatory_elements/stack_trace.dart' as i12;
-import 'package:observatory/src/observatory_elements/message_viewer.dart' as i13;
-import 'package:observatory/src/observatory_elements/navigation_bar.dart' as i14;
-import 'package:observatory/src/observatory_elements/response_viewer.dart' as i15;
-import 'package:observatory/src/observatory_elements/observatory_application.dart' as i16;
-import 'index.html.0.dart' as i17;
+import 'package:observatory/src/observatory_elements/source_view.dart' as i12;
+import 'package:observatory/src/observatory_elements/script_view.dart' as i13;
+import 'package:observatory/src/observatory_elements/stack_trace.dart' as i14;
+import 'package:observatory/src/observatory_elements/message_viewer.dart' as i15;
+import 'package:observatory/src/observatory_elements/navigation_bar.dart' as i16;
+import 'package:observatory/src/observatory_elements/response_viewer.dart' as i17;
+import 'package:observatory/src/observatory_elements/observatory_application.dart' as i18;
+import 'index.html.0.dart_modified.dart' as i19;
void main() {
configureForDeployment([
@@ -35,12 +37,14 @@
'package:observatory/src/observatory_elements/isolate_list.dart',
'package:observatory/src/observatory_elements/json_view.dart',
'package:observatory/src/observatory_elements/library_view.dart',
+ 'package:observatory/src/observatory_elements/source_view.dart',
+ 'package:observatory/src/observatory_elements/script_view.dart',
'package:observatory/src/observatory_elements/stack_trace.dart',
'package:observatory/src/observatory_elements/message_viewer.dart',
'package:observatory/src/observatory_elements/navigation_bar.dart',
'package:observatory/src/observatory_elements/response_viewer.dart',
'package:observatory/src/observatory_elements/observatory_application.dart',
- 'index.html.0.dart',
+ 'index.html.0.dart_modified.dart',
]);
- i17.main();
+ i19.polymerMainWrapper();
}
diff --git a/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart.js b/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart.js
index f838e39..f571390 100644
--- a/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart.js
+++ b/runtime/bin/vmservice/client/deployed/web/index.html_bootstrap.dart.js
@@ -904,36 +904,35 @@
// every PathObserver used by defineProperty share a single Object.observe
// callback, and thus get() can simply call observer.deliver() and any changes
// to any dependent value will be observed.
- PathObserver.defineProperty = function(object, name, descriptor) {
+ PathObserver.defineProperty = function(target, name, object, path) {
// TODO(rafaelw): Validate errors
- var obj = descriptor.object;
- var path = getPath(descriptor.path);
- var notify = notifyFunction(object, name);
+ path = getPath(path);
+ var notify = notifyFunction(target, name);
- var observer = new PathObserver(obj, descriptor.path,
+ var observer = new PathObserver(object, path,
function(newValue, oldValue) {
if (notify)
notify(PROP_UPDATE_TYPE, oldValue);
}
);
- Object.defineProperty(object, name, {
+ Object.defineProperty(target, name, {
get: function() {
- return path.getValueFrom(obj);
+ return path.getValueFrom(object);
},
set: function(newValue) {
- path.setValueFrom(obj, newValue);
+ path.setValueFrom(object, newValue);
},
configurable: true
});
return {
close: function() {
- var oldValue = path.getValueFrom(obj);
+ var oldValue = path.getValueFrom(object);
if (notify)
observer.deliver();
observer.close();
- Object.defineProperty(object, name, {
+ Object.defineProperty(target, name, {
value: oldValue,
writable: true,
configurable: true
@@ -1419,7 +1418,7 @@
'delete': PROP_DELETE_TYPE,
splice: ARRAY_SPLICE_TYPE
};
-})(typeof global !== 'undefined' && global ? global : this);
+})(typeof global !== 'undefined' && global ? global : this || window);
/*
* Copyright 2012 The Polymer Authors. All rights reserved.
@@ -1462,7 +1461,7 @@
// Use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE file.
-var ShadowDOMPolyfill = {};
+window.ShadowDOMPolyfill = {};
(function(scope) {
'use strict';
@@ -1490,16 +1489,19 @@
throw new Error('Assertion failed');
};
+ var defineProperty = Object.defineProperty;
+ var getOwnPropertyNames = Object.getOwnPropertyNames;
+ var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
+
function mixin(to, from) {
- Object.getOwnPropertyNames(from).forEach(function(name) {
- Object.defineProperty(to, name,
- Object.getOwnPropertyDescriptor(from, name));
+ getOwnPropertyNames(from).forEach(function(name) {
+ defineProperty(to, name, getOwnPropertyDescriptor(from, name));
});
return to;
};
function mixinStatics(to, from) {
- Object.getOwnPropertyNames(from).forEach(function(name) {
+ getOwnPropertyNames(from).forEach(function(name) {
switch (name) {
case 'arguments':
case 'caller':
@@ -1509,8 +1511,7 @@
case 'toString':
return;
}
- Object.defineProperty(to, name,
- Object.getOwnPropertyDescriptor(from, name));
+ defineProperty(to, name, getOwnPropertyDescriptor(from, name));
});
return to;
};
@@ -1525,7 +1526,7 @@
// Mozilla's old DOM bindings are bretty busted:
// https://bugzilla.mozilla.org/show_bug.cgi?id=855844
// Make sure they are create before we start modifying things.
- Object.getOwnPropertyNames(window);
+ getOwnPropertyNames(window);
function getWrapperConstructor(node) {
var nativePrototype = node.__proto__ || Object.getPrototypeOf(node);
@@ -1587,28 +1588,39 @@
function() { return this.impl[name].apply(this.impl, arguments); };
}
- function installProperty(source, target, allowMethod) {
- Object.getOwnPropertyNames(source).forEach(function(name) {
+ function getDescriptor(source, name) {
+ try {
+ return Object.getOwnPropertyDescriptor(source, name);
+ } catch (ex) {
+ // JSC and V8 both use data properties instead of accessors which can
+ // cause getting the property desciptor to throw an exception.
+ // https://bugs.webkit.org/show_bug.cgi?id=49739
+ return dummyDescriptor;
+ }
+ }
+
+ function installProperty(source, target, allowMethod, opt_blacklist) {
+ var names = getOwnPropertyNames(source);
+ for (var i = 0; i < names.length; i++) {
+ var name = names[i];
+ if (name === 'polymerBlackList_')
+ continue;
+
if (name in target)
- return;
+ continue;
+
+ if (source.polymerBlackList_ && source.polymerBlackList_[name])
+ continue;
if (isFirefox) {
// Tickle Firefox's old bindings.
source.__lookupGetter__(name);
}
- var descriptor;
- try {
- descriptor = Object.getOwnPropertyDescriptor(source, name);
- } catch (ex) {
- // JSC and V8 both use data properties instead of accessors which can
- // cause getting the property desciptor to throw an exception.
- // https://bugs.webkit.org/show_bug.cgi?id=49739
- descriptor = dummyDescriptor;
- }
+ var descriptor = getDescriptor(source, name);
var getter, setter;
if (allowMethod && typeof descriptor.value === 'function') {
target[name] = getMethod(name);
- return;
+ continue;
}
var isEvent = isEventHandlerName(name);
@@ -1624,13 +1636,13 @@
setter = getSetter(name);
}
- Object.defineProperty(target, name, {
+ defineProperty(target, name, {
get: getter,
set: setter,
configurable: descriptor.configurable,
enumerable: descriptor.enumerable
});
- });
+ }
}
/**
@@ -1655,6 +1667,12 @@
addForwardingProperties(nativePrototype, wrapperPrototype);
if (opt_instance)
registerInstanceProperties(wrapperPrototype, opt_instance);
+ defineProperty(wrapperPrototype, 'constructor', {
+ value: wrapperConstructor,
+ configurable: true,
+ enumerable: false,
+ writable: true
+ });
}
function isWrapperFor(wrapperConstructor, nativeConstructor) {
@@ -1665,11 +1683,7 @@
/**
* Creates a generic wrapper constructor based on |object| and its
* constructor.
- * Sometimes the constructor does not have an associated instance
- * (CharacterData for example). In that case you can pass the constructor that
- * you want to map the object to using |opt_nativeConstructor|.
* @param {Node} object
- * @param {Function=} opt_nativeConstructor
* @return {Function} The generated constructor.
*/
function registerObject(object) {
@@ -1782,7 +1796,7 @@
}
function defineGetter(constructor, name, getter) {
- Object.defineProperty(constructor.prototype, name, {
+ defineProperty(constructor.prototype, name, {
get: getter,
configurable: true,
enumerable: true
@@ -1831,7 +1845,430 @@
scope.wrapIfNeeded = wrapIfNeeded;
scope.wrappers = wrappers;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is goverened by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+(function(context) {
+ 'use strict';
+
+ var OriginalMutationObserver = window.MutationObserver;
+ var callbacks = [];
+ var pending = false;
+ var timerFunc;
+
+ function handle() {
+ pending = false;
+ var copies = callbacks.slice(0);
+ callbacks = [];
+ for (var i = 0; i < copies.length; i++) {
+ (0, copies[i])();
+ }
+ }
+
+ if (OriginalMutationObserver) {
+ var counter = 1;
+ var observer = new OriginalMutationObserver(handle);
+ var textNode = document.createTextNode(counter);
+ observer.observe(textNode, {characterData: true});
+
+ timerFunc = function() {
+ counter = (counter + 1) % 2;
+ textNode.data = counter;
+ };
+
+ } else {
+ timerFunc = window.setImmediate || window.setTimeout;
+ }
+
+ function setEndOfMicrotask(func) {
+ callbacks.push(func);
+ if (pending)
+ return;
+ pending = true;
+ timerFunc(handle, 0);
+ }
+
+ context.setEndOfMicrotask = setEndOfMicrotask;
+
+})(window.ShadowDOMPolyfill);
+
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is goverened by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+(function(scope) {
+ 'use strict';
+
+ var setEndOfMicrotask = scope.setEndOfMicrotask
+ var wrapIfNeeded = scope.wrapIfNeeded
+ var wrappers = scope.wrappers;
+
+ var registrationsTable = new WeakMap();
+ var globalMutationObservers = [];
+ var isScheduled = false;
+
+ function scheduleCallback(observer) {
+ if (isScheduled)
+ return;
+ setEndOfMicrotask(notifyObservers);
+ isScheduled = true;
+ }
+
+ // http://dom.spec.whatwg.org/#mutation-observers
+ function notifyObservers() {
+ isScheduled = false;
+
+ do {
+ var notifyList = globalMutationObservers.slice();
+ var anyNonEmpty = false;
+ for (var i = 0; i < notifyList.length; i++) {
+ var mo = notifyList[i];
+ var queue = mo.takeRecords();
+ removeTransientObserversFor(mo);
+ if (queue.length) {
+ mo.callback_(queue, mo);
+ anyNonEmpty = true;
+ }
+ }
+ } while (anyNonEmpty);
+ }
+
+ /**
+ * @param {string} type
+ * @param {Node} target
+ * @constructor
+ */
+ function MutationRecord(type, target) {
+ this.type = type;
+ this.target = target;
+ this.addedNodes = new wrappers.NodeList();
+ this.removedNodes = new wrappers.NodeList();
+ this.previousSibling = null;
+ this.nextSibling = null;
+ this.attributeName = null;
+ this.attributeNamespace = null;
+ this.oldValue = null;
+ }
+
+ /**
+ * Registers transient observers to ancestor and its ancesors for the node
+ * which was removed.
+ * @param {!Node} ancestor
+ * @param {!Node} node
+ */
+ function registerTransientObservers(ancestor, node) {
+ for (; ancestor; ancestor = ancestor.parentNode) {
+ var registrations = registrationsTable.get(ancestor);
+ if (!registrations)
+ continue;
+ for (var i = 0; i < registrations.length; i++) {
+ var registration = registrations[i];
+ if (registration.options.subtree)
+ registration.addTransientObserver(node);
+ }
+ }
+ }
+
+ function removeTransientObserversFor(observer) {
+ for (var i = 0; i < observer.nodes_.length; i++) {
+ var node = observer.nodes_[i];
+ var registrations = registrationsTable.get(node);
+ if (!registrations)
+ return;
+ for (var j = 0; j < registrations.length; j++) {
+ var registration = registrations[j];
+ if (registration.observer === observer)
+ registration.removeTransientObservers();
+ }
+ }
+ }
+
+ // http://dom.spec.whatwg.org/#queue-a-mutation-record
+ function enqueueMutation(target, type, data) {
+ // 1.
+ var interestedObservers = Object.create(null);
+ var associatedStrings = Object.create(null);
+
+ // 2.
+ for (var node = target; node; node = node.parentNode) {
+ // 3.
+ var registrations = registrationsTable.get(node);
+ if (!registrations)
+ continue;
+ for (var j = 0; j < registrations.length; j++) {
+ var registration = registrations[j];
+ var options = registration.options;
+ // 1.
+ if (node !== target && !options.subtree)
+ continue;
+
+ // 2.
+ if (type === 'attributes' && !options.attributes)
+ continue;
+
+ // 3. If type is "attributes", options's attributeFilter is present, and
+ // either options's attributeFilter does not contain name or namespace
+ // is non-null, continue.
+ if (type === 'attributes' && options.attributeFilter &&
+ (data.namespace !== null ||
+ options.attributeFilter.indexOf(data.name) === -1)) {
+ continue;
+ }
+
+ // 4.
+ if (type === 'characterData' && !options.characterData)
+ continue;
+
+ // 5.
+ if (type === 'childList' && !options.childList)
+ continue;
+
+ // 6.
+ var observer = registration.observer;
+ interestedObservers[observer.uid_] = observer;
+
+ // 7. If either type is "attributes" and options's attributeOldValue is
+ // true, or type is "characterData" and options's characterDataOldValue
+ // is true, set the paired string of registered observer's observer in
+ // interested observers to oldValue.
+ if (type === 'attributes' && options.attributeOldValue ||
+ type === 'characterData' && options.characterDataOldValue) {
+ associatedStrings[observer.uid_] = data.oldValue;
+ }
+ }
+ }
+
+ var anyRecordsEnqueued = false;
+
+ // 4.
+ for (var uid in interestedObservers) {
+ var observer = interestedObservers[uid];
+ var record = new MutationRecord(type, target);
+
+ // 2.
+ if ('name' in data && 'namespace' in data) {
+ record.attributeName = data.name;
+ record.attributeNamespace = data.namespace;
+ }
+
+ // 3.
+ if (data.addedNodes)
+ record.addedNodes = data.addedNodes;
+
+ // 4.
+ if (data.removedNodes)
+ record.removedNodes = data.removedNodes;
+
+ // 5.
+ if (data.previousSibling)
+ record.previousSibling = data.previousSibling;
+
+ // 6.
+ if (data.nextSibling)
+ record.nextSibling = data.nextSibling;
+
+ // 7.
+ if (associatedStrings[uid] !== undefined)
+ record.oldValue = associatedStrings[uid];
+
+ // 8.
+ observer.records_.push(record);
+
+ anyRecordsEnqueued = true;
+ }
+
+ if (anyRecordsEnqueued)
+ scheduleCallback();
+ }
+
+ var slice = Array.prototype.slice;
+
+ /**
+ * @param {!Object} options
+ * @constructor
+ */
+ function MutationObserverOptions(options) {
+ this.childList = !!options.childList;
+ this.subtree = !!options.subtree;
+
+ // 1. If either options' attributeOldValue or attributeFilter is present
+ // and options' attributes is omitted, set options' attributes to true.
+ if (!('attributes' in options) &&
+ ('attributeOldValue' in options || 'attributeFilter' in options)) {
+ this.attributes = true;
+ } else {
+ this.attributes = !!options.attributes;
+ }
+
+ // 2. If options' characterDataOldValue is present and options'
+ // characterData is omitted, set options' characterData to true.
+ if ('characterDataOldValue' in options && !('characterData' in options))
+ this.characterData = true;
+ else
+ this.characterData = !!options.characterData;
+
+ // 3. & 4.
+ if (!this.attributes &&
+ (options.attributeOldValue || 'attributeFilter' in options) ||
+ // 5.
+ !this.characterData && options.characterDataOldValue) {
+ throw new TypeError();
+ }
+
+ this.characterData = !!options.characterData;
+ this.attributeOldValue = !!options.attributeOldValue;
+ this.characterDataOldValue = !!options.characterDataOldValue;
+ if ('attributeFilter' in options) {
+ if (options.attributeFilter == null ||
+ typeof options.attributeFilter !== 'object') {
+ throw new TypeError();
+ }
+ this.attributeFilter = slice.call(options.attributeFilter);
+ } else {
+ this.attributeFilter = null;
+ }
+ }
+
+ var uidCounter = 0;
+
+ /**
+ * The class that maps to the DOM MutationObserver interface.
+ * @param {Function} callback.
+ * @constructor
+ */
+ function MutationObserver(callback) {
+ this.callback_ = callback;
+ this.nodes_ = [];
+ this.records_ = [];
+ this.uid_ = ++uidCounter;
+
+ // This will leak. There is no way to implement this without WeakRefs :'(
+ globalMutationObservers.push(this);
+ }
+
+ MutationObserver.prototype = {
+ // http://dom.spec.whatwg.org/#dom-mutationobserver-observe
+ observe: function(target, options) {
+ target = wrapIfNeeded(target);
+
+ var newOptions = new MutationObserverOptions(options);
+
+ // 6.
+ var registration;
+ var registrations = registrationsTable.get(target);
+ if (!registrations)
+ registrationsTable.set(target, registrations = []);
+
+ for (var i = 0; i < registrations.length; i++) {
+ if (registrations[i].observer === this) {
+ registration = registrations[i];
+ // 6.1.
+ registration.removeTransientObservers();
+ // 6.2.
+ registration.options = newOptions;
+ }
+ }
+
+ // 7.
+ if (!registration) {
+ registration = new Registration(this, target, newOptions);
+ registrations.push(registration);
+ this.nodes_.push(target);
+ }
+ },
+
+ // http://dom.spec.whatwg.org/#dom-mutationobserver-disconnect
+ disconnect: function() {
+ this.nodes_.forEach(function(node) {
+ var registrations = registrationsTable.get(node);
+ for (var i = 0; i < registrations.length; i++) {
+ var registration = registrations[i];
+ if (registration.observer === this) {
+ registrations.splice(i, 1);
+ // Each node can only have one registered observer associated with
+ // this observer.
+ break;
+ }
+ }
+ }, this);
+ this.records_ = [];
+ },
+
+ takeRecords: function() {
+ var copyOfRecords = this.records_;
+ this.records_ = [];
+ return copyOfRecords;
+ }
+ };
+
+ /**
+ * Class used to represent a registered observer.
+ * @param {MutationObserver} observer
+ * @param {Node} target
+ * @param {MutationObserverOptions} options
+ * @constructor
+ */
+ function Registration(observer, target, options) {
+ this.observer = observer;
+ this.target = target;
+ this.options = options;
+ this.transientObservedNodes = [];
+ }
+
+ Registration.prototype = {
+ /**
+ * Adds a transient observer on node. The transient observer gets removed
+ * next time we deliver the change records.
+ * @param {Node} node
+ */
+ addTransientObserver: function(node) {
+ // Don't add transient observers on the target itself. We already have all
+ // the required listeners set up on the target.
+ if (node === this.target)
+ return;
+
+ this.transientObservedNodes.push(node);
+ var registrations = registrationsTable.get(node);
+ if (!registrations)
+ registrationsTable.set(node, registrations = []);
+
+ // We know that registrations does not contain this because we already
+ // checked if node === this.target.
+ registrations.push(this);
+ },
+
+ removeTransientObservers: function() {
+ var transientObservedNodes = this.transientObservedNodes;
+ this.transientObservedNodes = [];
+
+ for (var i = 0; i < transientObservedNodes.length; i++) {
+ var node = transientObservedNodes[i];
+ var registrations = registrationsTable.get(node);
+ for (var j = 0; j < registrations.length; j++) {
+ if (registrations[j] === this) {
+ registrations.splice(j, 1);
+ // Each node can only have one registered observer associated with
+ // this observer.
+ break;
+ }
+ }
+ }
+ }
+ };
+
+ scope.enqueueMutation = enqueueMutation;
+ scope.registerTransientObservers = registerTransientObservers;
+ scope.wrappers.MutationObserver = MutationObserver;
+ scope.wrappers.MutationRecord = MutationRecord;
+
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -2014,17 +2451,6 @@
return false;
}
- var mutationEventsAreSilenced = 0;
-
- function muteMutationEvents() {
- mutationEventsAreSilenced++;
- }
-
- function unmuteMutationEvents() {
- mutationEventsAreSilenced--;
- }
-
- var OriginalMutationEvent = window.MutationEvent;
function dispatchOriginalEvent(originalEvent) {
// Make sure this event is only dispatched once.
@@ -2032,15 +2458,9 @@
return;
handledEventsTable.set(originalEvent, true);
- // Don't do rendering if this is a mutation event since rendering might
- // mutate the DOM which would fire more events and we would most likely
- // just iloop.
- if (originalEvent instanceof OriginalMutationEvent) {
- if (mutationEventsAreSilenced)
- return;
- } else {
- scope.renderAllPending();
- }
+ // Render before dispatching the event to ensure that the event path is
+ // correct.
+ scope.renderAllPending();
var target = wrap(originalEvent.target);
var event = wrap(originalEvent);
@@ -2210,6 +2630,7 @@
};
var OriginalEvent = window.Event;
+ OriginalEvent.prototype.polymerBlackList_ = {returnValue: true};
/**
* Creates a new Event wrapper or wraps an existin native Event object.
@@ -2325,13 +2746,6 @@
var MouseEvent = registerGenericEvent('MouseEvent', UIEvent, mouseEventProto);
var FocusEvent = registerGenericEvent('FocusEvent', UIEvent, focusEventProto);
- var MutationEvent = registerGenericEvent('MutationEvent', Event, {
- initMutationEvent: getInitFunction('initMutationEvent', 3),
- get relatedNode() {
- return wrap(this.impl.relatedNode);
- },
- });
-
// In case the browser does not support event constructors we polyfill that
// by calling `createEvent('Foo')` and `initFooEvent` where the arguments to
// `initFooEvent` are derived from the registered default event init dict.
@@ -2398,12 +2812,41 @@
configureEventConstructor('FocusEvent', {relatedTarget: null}, 'UIEvent');
}
+ function BeforeUnloadEvent(impl) {
+ Event.call(this);
+ }
+ BeforeUnloadEvent.prototype = Object.create(Event.prototype);
+ mixin(BeforeUnloadEvent.prototype, {
+ get returnValue() {
+ return this.impl.returnValue;
+ },
+ set returnValue(v) {
+ this.impl.returnValue = v;
+ }
+ });
+
function isValidListener(fun) {
if (typeof fun === 'function')
return true;
return fun && fun.handleEvent;
}
+ function isMutationEvent(type) {
+ switch (type) {
+ case 'DOMAttrModified':
+ case 'DOMAttributeNameChanged':
+ case 'DOMCharacterDataModified':
+ case 'DOMElementNameChanged':
+ case 'DOMNodeInserted':
+ case 'DOMNodeInsertedIntoDocument':
+ case 'DOMNodeRemoved':
+ case 'DOMNodeRemovedFromDocument':
+ case 'DOMSubtreeModified':
+ return true;
+ }
+ return false;
+ }
+
var OriginalEventTarget = window.EventTarget;
/**
@@ -2438,7 +2881,7 @@
EventTarget.prototype = {
addEventListener: function(type, fun, capture) {
- if (!isValidListener(fun))
+ if (!isValidListener(fun) || isMutationEvent(type))
return;
var listener = new Listener(type, fun, capture);
@@ -2568,18 +3011,16 @@
scope.elementFromPoint = elementFromPoint;
scope.getEventHandlerGetter = getEventHandlerGetter;
scope.getEventHandlerSetter = getEventHandlerSetter;
- scope.muteMutationEvents = muteMutationEvents;
- scope.unmuteMutationEvents = unmuteMutationEvents;
scope.wrapEventTargetMethods = wrapEventTargetMethods;
+ scope.wrappers.BeforeUnloadEvent = BeforeUnloadEvent;
scope.wrappers.CustomEvent = CustomEvent;
scope.wrappers.Event = Event;
scope.wrappers.EventTarget = EventTarget;
scope.wrappers.FocusEvent = FocusEvent;
scope.wrappers.MouseEvent = MouseEvent;
- scope.wrappers.MutationEvent = MutationEvent;
scope.wrappers.UIEvent = UIEvent;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2012 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -2626,7 +3067,8 @@
scope.addWrapNodeListMethod = addWrapNodeListMethod;
scope.wrapNodeList = wrapNodeList;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
+
// Copyright 2012 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE file.
@@ -2636,9 +3078,11 @@
var EventTarget = scope.wrappers.EventTarget;
var NodeList = scope.wrappers.NodeList;
- var defineWrapGetter = scope.defineWrapGetter;
var assert = scope.assert;
+ var defineWrapGetter = scope.defineWrapGetter;
+ var enqueueMutation = scope.enqueueMutation;
var mixin = scope.mixin;
+ var registerTransientObservers = scope.registerTransientObservers;
var registerWrapper = scope.registerWrapper;
var unwrap = scope.unwrap;
var wrap = scope.wrap;
@@ -2648,6 +3092,36 @@
assert(node instanceof Node);
}
+ function createOneElementNodeList(node) {
+ var nodes = new NodeList();
+ nodes[0] = node;
+ nodes.length = 1;
+ return nodes;
+ }
+
+ var surpressMutations = false;
+
+ /**
+ * Called before node is inserted into a node to enqueue its removal from its
+ * old parent.
+ * @param {!Node} node The node that is about to be removed.
+ * @param {!Node} parent The parent node that the node is being removed from.
+ * @param {!NodeList} nodes The collected nodes.
+ */
+ function enqueueRemovalForInsertedNodes(node, parent, nodes) {
+ enqueueMutation(parent, 'childList', {
+ removedNodes: nodes,
+ previousSibling: node.previousSibling,
+ nextSibling: node.nextSibling
+ });
+ }
+
+ function enqueueRemovalForInsertedDocumentFragment(df, nodes) {
+ enqueueMutation(df, 'childList', {
+ removedNodes: nodes
+ });
+ }
+
/**
* Collects nodes from a DocumentFragment or a Node for removal followed
* by an insertion.
@@ -2655,60 +3129,95 @@
* This updates the internal pointers for node, previousNode and nextNode.
*/
function collectNodes(node, parentNode, previousNode, nextNode) {
- if (!(node instanceof DocumentFragment)) {
- if (node.parentNode)
- node.parentNode.removeChild(node);
- node.parentNode_ = parentNode;
- node.previousSibling_ = previousNode;
- node.nextSibling_ = nextNode;
+ if (node instanceof DocumentFragment) {
+ var nodes = collectNodesForDocumentFragment(node);
+
+ // The extra loop is to work around bugs with DocumentFragments in IE.
+ surpressMutations = true;
+ for (var i = nodes.length - 1; i >= 0; i--) {
+ node.removeChild(nodes[i]);
+ nodes[i].parentNode_ = parentNode;
+ }
+ surpressMutations = false;
+
+ for (var i = 0; i < nodes.length; i++) {
+ nodes[i].previousSibling_ = nodes[i - 1] || previousNode;
+ nodes[i].nextSibling_ = nodes[i + 1] || nextNode;
+ }
+
if (previousNode)
- previousNode.nextSibling_ = node;
+ previousNode.nextSibling_ = nodes[0];
if (nextNode)
- nextNode.previousSibling_ = node;
- return [node];
+ nextNode.previousSibling_ = nodes[nodes.length - 1];
+
+ return nodes;
}
- var nodes = [];
- for (var child = node.firstChild; child; child = child.nextSibling) {
- nodes.push(child);
+ var nodes = createOneElementNodeList(node);
+ var oldParent = node.parentNode;
+ if (oldParent) {
+ // This will enqueue the mutation record for the removal as needed.
+ oldParent.removeChild(node);
}
- for (var i = nodes.length - 1; i >= 0; i--) {
- node.removeChild(nodes[i]);
- nodes[i].parentNode_ = parentNode;
- }
-
- for (var i = 0; i < nodes.length; i++) {
- nodes[i].previousSibling_ = nodes[i - 1] || previousNode;
- nodes[i].nextSibling_ = nodes[i + 1] || nextNode;
- }
-
+ node.parentNode_ = parentNode;
+ node.previousSibling_ = previousNode;
+ node.nextSibling_ = nextNode;
if (previousNode)
- previousNode.nextSibling_ = nodes[0];
+ previousNode.nextSibling_ = node;
if (nextNode)
- nextNode.previousSibling_ = nodes[nodes.length - 1];
+ nextNode.previousSibling_ = node;
return nodes;
}
- function collectNodesNoNeedToUpdatePointers(node) {
- if (node instanceof DocumentFragment) {
- var nodes = [];
- var i = 0;
- for (var child = node.firstChild; child; child = child.nextSibling) {
- nodes[i++] = child;
- }
- return nodes;
+ function collectNodesNative(node) {
+ if (node instanceof DocumentFragment)
+ return collectNodesForDocumentFragment(node);
+
+ var nodes = createOneElementNodeList(node);
+ var oldParent = node.parentNode;
+ if (oldParent)
+ enqueueRemovalForInsertedNodes(node, oldParent, nodes);
+ return nodes;
+ }
+
+ function collectNodesForDocumentFragment(node) {
+ var nodes = new NodeList();
+ var i = 0;
+ for (var child = node.firstChild; child; child = child.nextSibling) {
+ nodes[i++] = child;
}
- return [node];
+ nodes.length = i;
+ enqueueRemovalForInsertedDocumentFragment(node, nodes);
+ return nodes;
+ }
+
+ function snapshotNodeList(nodeList) {
+ // NodeLists are not live at the moment so just return the same object.
+ return nodeList;
+ }
+
+ // http://dom.spec.whatwg.org/#node-is-inserted
+ function nodeWasAdded(node) {
+ node.nodeIsInserted_();
}
function nodesWereAdded(nodes) {
for (var i = 0; i < nodes.length; i++) {
- nodes[i].nodeWasAdded_();
+ nodeWasAdded(nodes[i]);
}
}
+ // http://dom.spec.whatwg.org/#node-is-removed
+ function nodeWasRemoved(node) {
+ // Nothing at this point in time.
+ }
+
+ function nodesWereRemoved(nodes) {
+ // Nothing at this point in time.
+ }
+
function ensureSameOwnerDocument(parent, child) {
var ownerDoc = parent.nodeType === Node.DOCUMENT_NODE ?
parent : parent.ownerDocument;
@@ -2851,69 +3360,56 @@
Node.prototype = Object.create(EventTarget.prototype);
mixin(Node.prototype, {
appendChild: function(childWrapper) {
- assertIsNodeWrapper(childWrapper);
-
- var nodes;
-
- if (this.invalidateShadowRenderer() || invalidateParent(childWrapper)) {
- var previousNode = this.lastChild;
- var nextNode = null;
- nodes = collectNodes(childWrapper, this, previousNode, nextNode);
-
- this.lastChild_ = nodes[nodes.length - 1];
- if (!previousNode)
- this.firstChild_ = nodes[0];
-
- originalAppendChild.call(this.impl, unwrapNodesForInsertion(this, nodes));
- } else {
- nodes = collectNodesNoNeedToUpdatePointers(childWrapper)
- ensureSameOwnerDocument(this, childWrapper);
- originalAppendChild.call(this.impl, unwrap(childWrapper));
- }
-
- nodesWereAdded(nodes);
-
- return childWrapper;
+ return this.insertBefore(childWrapper, null);
},
insertBefore: function(childWrapper, refWrapper) {
- // TODO(arv): Unify with appendChild
- if (!refWrapper)
- return this.appendChild(childWrapper);
-
assertIsNodeWrapper(childWrapper);
- assertIsNodeWrapper(refWrapper);
- assert(refWrapper.parentNode === this);
+
+ refWrapper = refWrapper || null;
+ refWrapper && assertIsNodeWrapper(refWrapper);
+ refWrapper && assert(refWrapper.parentNode === this);
var nodes;
+ var previousNode =
+ refWrapper ? refWrapper.previousSibling : this.lastChild;
- if (this.invalidateShadowRenderer() || invalidateParent(childWrapper)) {
- var previousNode = refWrapper.previousSibling;
- var nextNode = refWrapper;
- nodes = collectNodes(childWrapper, this, previousNode, nextNode);
+ var useNative = !this.invalidateShadowRenderer() &&
+ !invalidateParent(childWrapper);
- if (this.firstChild === refWrapper)
- this.firstChild_ = nodes[0];
+ if (useNative)
+ nodes = collectNodesNative(childWrapper);
+ else
+ nodes = collectNodes(childWrapper, this, previousNode, refWrapper);
- // insertBefore refWrapper no matter what the parent is?
- var refNode = unwrap(refWrapper);
- var parentNode = refNode.parentNode;
-
- if (parentNode) {
- originalInsertBefore.call(
- parentNode,
- unwrapNodesForInsertion(this, nodes),
- refNode);
- } else {
- adoptNodesIfNeeded(this, nodes);
- }
- } else {
- nodes = collectNodesNoNeedToUpdatePointers(childWrapper);
+ if (useNative) {
ensureSameOwnerDocument(this, childWrapper);
originalInsertBefore.call(this.impl, unwrap(childWrapper),
unwrap(refWrapper));
+ } else {
+ if (!previousNode)
+ this.firstChild_ = nodes[0];
+ if (!refWrapper)
+ this.lastChild_ = nodes[nodes.length - 1];
+
+ var refNode = unwrap(refWrapper);
+ var parentNode = refNode ? refNode.parentNode : this.impl;
+
+ // insertBefore refWrapper no matter what the parent is?
+ if (parentNode) {
+ originalInsertBefore.call(parentNode,
+ unwrapNodesForInsertion(this, nodes), refNode);
+ } else {
+ adoptNodesIfNeeded(this, nodes);
+ }
}
+ enqueueMutation(this, 'childList', {
+ addedNodes: nodes,
+ nextSibling: refWrapper,
+ previousSibling: previousNode
+ });
+
nodesWereAdded(nodes);
return childWrapper;
@@ -2939,15 +3435,15 @@
}
var childNode = unwrap(childWrapper);
- if (this.invalidateShadowRenderer()) {
+ var childWrapperNextSibling = childWrapper.nextSibling;
+ var childWrapperPreviousSibling = childWrapper.previousSibling;
+ if (this.invalidateShadowRenderer()) {
// We need to remove the real node from the DOM before updating the
// pointers. This is so that that mutation event is dispatched before
// the pointers have changed.
var thisFirstChild = this.firstChild;
var thisLastChild = this.lastChild;
- var childWrapperNextSibling = childWrapper.nextSibling;
- var childWrapperPreviousSibling = childWrapper.previousSibling;
var parentNode = childNode.parentNode;
if (parentNode)
@@ -2970,6 +3466,16 @@
removeChildOriginalHelper(this.impl, childNode);
}
+ if (!surpressMutations) {
+ enqueueMutation(this, 'childList', {
+ removedNodes: createOneElementNodeList(childWrapper),
+ nextSibling: childWrapperNextSibling,
+ previousSibling: childWrapperPreviousSibling
+ });
+ }
+
+ registerTransientObservers(this, childWrapper);
+
return childWrapper;
},
@@ -2983,16 +3489,22 @@
}
var oldChildNode = unwrap(oldChildWrapper);
+ var nextNode = oldChildWrapper.nextSibling;
+ var previousNode = oldChildWrapper.previousSibling;
var nodes;
- if (this.invalidateShadowRenderer() ||
- invalidateParent(newChildWrapper)) {
- var previousNode = oldChildWrapper.previousSibling;
- var nextNode = oldChildWrapper.nextSibling;
+ var useNative = !this.invalidateShadowRenderer() &&
+ !invalidateParent(newChildWrapper);
+
+ if (useNative) {
+ nodes = collectNodesNative(newChildWrapper);
+ } else {
if (nextNode === newChildWrapper)
nextNode = newChildWrapper.nextSibling;
nodes = collectNodes(newChildWrapper, this, previousNode, nextNode);
+ }
+ if (!useNative) {
if (this.firstChild === oldChildWrapper)
this.firstChild_ = nodes[0];
if (this.lastChild === oldChildWrapper)
@@ -3009,25 +3521,32 @@
oldChildNode);
}
} else {
- nodes = collectNodesNoNeedToUpdatePointers(newChildWrapper);
ensureSameOwnerDocument(this, newChildWrapper);
originalReplaceChild.call(this.impl, unwrap(newChildWrapper),
oldChildNode);
}
+ enqueueMutation(this, 'childList', {
+ addedNodes: nodes,
+ removedNodes: createOneElementNodeList(oldChildWrapper),
+ nextSibling: nextNode,
+ previousSibling: previousNode
+ });
+
+ nodeWasRemoved(oldChildWrapper);
nodesWereAdded(nodes);
return oldChildWrapper;
},
/**
- * Called after a node was added. Subclasses override this to invalidate
+ * Called after a node was inserted. Subclasses override this to invalidate
* the renderer as needed.
* @private
*/
- nodeWasAdded_: function() {
+ nodeIsInserted_: function() {
for (var child = this.firstChild; child; child = child.nextSibling) {
- child.nodeWasAdded_();
+ child.nodeIsInserted_();
}
},
@@ -3084,6 +3603,8 @@
return s;
},
set textContent(textContent) {
+ var removedNodes = snapshotNodeList(this.childNodes);
+
if (this.invalidateShadowRenderer()) {
removeAllChildNodes(this);
if (textContent !== '') {
@@ -3093,6 +3614,16 @@
} else {
this.impl.textContent = textContent;
}
+
+ var addedNodes = snapshotNodeList(this.childNodes);
+
+ enqueueMutation(this, 'childList', {
+ addedNodes: addedNodes,
+ removedNodes: removedNodes
+ });
+
+ nodesWereRemoved(removedNodes);
+ nodesWereAdded(addedNodes);
},
get childNodes() {
@@ -3106,9 +3637,6 @@
},
cloneNode: function(deep) {
- if (!this.invalidateShadowRenderer())
- return wrap(this.impl.cloneNode(deep));
-
var clone = wrap(this.impl.cloneNode(false));
if (deep) {
for (var child = this.firstChild; child; child = child.nextSibling) {
@@ -3151,9 +3679,14 @@
delete Node.prototype.querySelectorAll;
Node.prototype = mixin(Object.create(EventTarget.prototype), Node.prototype);
+ scope.nodeWasAdded = nodeWasAdded;
+ scope.nodeWasRemoved = nodeWasRemoved;
+ scope.nodesWereAdded = nodesWereAdded;
+ scope.nodesWereRemoved = nodesWereRemoved;
+ scope.snapshotNodeList = snapshotNodeList;
scope.wrappers.Node = Node;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -3227,7 +3760,7 @@
scope.GetElementsByInterface = GetElementsByInterface;
scope.SelectorsInterface = SelectorsInterface;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -3297,7 +3830,7 @@
scope.ChildNodeInterface = ChildNodeInterface;
scope.ParentNodeInterface = ParentNodeInterface;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -3308,6 +3841,7 @@
var ChildNodeInterface = scope.ChildNodeInterface;
var Node = scope.wrappers.Node;
+ var enqueueMutation = scope.enqueueMutation;
var mixin = scope.mixin;
var registerWrapper = scope.registerWrapper;
@@ -3323,6 +3857,16 @@
},
set textContent(value) {
this.data = value;
+ },
+ get data() {
+ return this.impl.data;
+ },
+ set data(value) {
+ var oldValue = this.impl.data;
+ enqueueMutation(this, 'characterData', {
+ oldValue: oldValue
+ });
+ this.impl.data = value;
}
});
@@ -3332,7 +3876,7 @@
document.createTextNode(''));
scope.wrappers.CharacterData = CharacterData;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -3347,6 +3891,7 @@
var ParentNodeInterface = scope.ParentNodeInterface;
var SelectorsInterface = scope.SelectorsInterface;
var addWrapNodeListMethod = scope.addWrapNodeListMethod;
+ var enqueueMutation = scope.enqueueMutation;
var mixin = scope.mixin;
var oneOf = scope.oneOf;
var registerWrapper = scope.registerWrapper;
@@ -3374,6 +3919,17 @@
renderer.invalidate();
}
+ function enqueAttributeChange(element, name, oldValue) {
+ // This is not fully spec compliant. We should use localName (which might
+ // have a different case than name) and the namespace (which requires us
+ // to get the Attr object).
+ enqueueMutation(element, 'attributes', {
+ name: name,
+ namespace: null,
+ oldValue: oldValue
+ });
+ }
+
function Element(node) {
Node.call(this, node);
}
@@ -3394,12 +3950,16 @@
},
setAttribute: function(name, value) {
+ var oldValue = this.impl.getAttribute(name);
this.impl.setAttribute(name, value);
+ enqueAttributeChange(this, name, oldValue);
invalidateRendererBasedOnAttribute(this, name);
},
removeAttribute: function(name) {
+ var oldValue = this.impl.getAttribute(name);
this.impl.removeAttribute(name);
+ enqueAttributeChange(this, name, oldValue);
invalidateRendererBasedOnAttribute(this, name);
},
@@ -3450,7 +4010,7 @@
// that reflect attributes.
scope.matchesName = matchesName;
scope.wrappers.Element = Element;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -3461,8 +4021,12 @@
var Element = scope.wrappers.Element;
var defineGetter = scope.defineGetter;
+ var enqueueMutation = scope.enqueueMutation;
var mixin = scope.mixin;
+ var nodesWereAdded = scope.nodesWereAdded;
+ var nodesWereRemoved = scope.nodesWereRemoved;
var registerWrapper = scope.registerWrapper;
+ var snapshotNodeList = scope.snapshotNodeList;
var unwrap = scope.unwrap;
var wrap = scope.wrap;
@@ -3564,10 +4128,21 @@
return getInnerHTML(this);
},
set innerHTML(value) {
+ var removedNodes = snapshotNodeList(this.childNodes);
+
if (this.invalidateShadowRenderer())
setInnerHTML(this, value, this.tagName);
else
this.impl.innerHTML = value;
+ var addedNodes = snapshotNodeList(this.childNodes);
+
+ enqueueMutation(this, 'childList', {
+ addedNodes: addedNodes,
+ removedNodes: removedNodes
+ });
+
+ nodesWereRemoved(removedNodes);
+ nodesWereAdded(addedNodes);
},
get outerHTML() {
@@ -3651,7 +4226,8 @@
// TODO: Find a better way to share these two with WrapperShadowRoot.
scope.getInnerHTML = getInnerHTML;
scope.setInnerHTML = setInnerHTML
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
+
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE file.
@@ -3682,7 +4258,7 @@
document.createElement('canvas'));
scope.wrappers.HTMLCanvasElement = HTMLCanvasElement;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -3724,7 +4300,8 @@
registerWrapper(OriginalHTMLContentElement, HTMLContentElement);
scope.wrappers.HTMLContentElement = HTMLContentElement;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
+
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE file.
@@ -3767,7 +4344,7 @@
scope.wrappers.HTMLImageElement = HTMLImageElement;
scope.wrappers.Image = Image;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -3794,7 +4371,7 @@
registerWrapper(OriginalHTMLShadowElement, HTMLShadowElement);
scope.wrappers.HTMLShadowElement = HTMLShadowElement;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -3806,10 +4383,8 @@
var HTMLElement = scope.wrappers.HTMLElement;
var getInnerHTML = scope.getInnerHTML;
var mixin = scope.mixin;
- var muteMutationEvents = scope.muteMutationEvents;
var registerWrapper = scope.registerWrapper;
var setInnerHTML = scope.setInnerHTML;
- var unmuteMutationEvents = scope.unmuteMutationEvents;
var unwrap = scope.unwrap;
var wrap = scope.wrap;
@@ -3838,11 +4413,9 @@
var doc = getTemplateContentsOwner(templateElement.ownerDocument);
var df = unwrap(doc.createDocumentFragment());
var child;
- muteMutationEvents();
while (child = templateElement.firstChild) {
df.appendChild(child);
}
- unmuteMutationEvents();
return df;
}
@@ -3879,7 +4452,8 @@
registerWrapper(OriginalHTMLTemplateElement, HTMLTemplateElement);
scope.wrappers.HTMLTemplateElement = HTMLTemplateElement;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
+
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE file.
@@ -3901,7 +4475,7 @@
document.createElement('audio'));
scope.wrappers.HTMLMediaElement = HTMLMediaElement;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -3944,7 +4518,7 @@
scope.wrappers.HTMLAudioElement = HTMLAudioElement;
scope.wrappers.Audio = Audio;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -4008,7 +4582,7 @@
scope.wrappers.HTMLOptionElement = HTMLOptionElement;
scope.wrappers.Option = Option;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -4040,7 +4614,8 @@
HTMLUnknownElement.prototype = Object.create(HTMLElement.prototype);
registerWrapper(OriginalHTMLUnknownElement, HTMLUnknownElement);
scope.wrappers.HTMLUnknownElement = HTMLUnknownElement;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
+
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE file.
@@ -4076,10 +4651,11 @@
}
});
- registerWrapper(OriginalCanvasRenderingContext2D, CanvasRenderingContext2D);
+ registerWrapper(OriginalCanvasRenderingContext2D, CanvasRenderingContext2D,
+ document.createElement('canvas').getContext('2d'));
scope.wrappers.CanvasRenderingContext2D = CanvasRenderingContext2D;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -4119,10 +4695,111 @@
}
});
- registerWrapper(OriginalWebGLRenderingContext, WebGLRenderingContext);
+ // Blink/WebKit has broken DOM bindings. Usually we would create an instance
+ // of the object and pass it into registerWrapper as a "blueprint" but
+ // creating WebGL contexts is expensive and might fail so we use a dummy
+ // object with dummy instance properties for these broken browsers.
+ var instanceProperties = /WebKit/.test(navigator.userAgent) ?
+ {drawingBufferHeight: null, drawingBufferWidth: null} : {};
+
+ registerWrapper(OriginalWebGLRenderingContext, WebGLRenderingContext,
+ instanceProperties);
scope.wrappers.WebGLRenderingContext = WebGLRenderingContext;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+ 'use strict';
+
+ var registerWrapper = scope.registerWrapper;
+ var unwrap = scope.unwrap;
+ var unwrapIfNeeded = scope.unwrapIfNeeded;
+ var wrap = scope.wrap;
+
+ var OriginalRange = window.Range;
+
+ function Range(impl) {
+ this.impl = impl;
+ }
+ Range.prototype = {
+ get startContainer() {
+ return wrap(this.impl.startContainer);
+ },
+ get endContainer() {
+ return wrap(this.impl.endContainer);
+ },
+ get commonAncestorContainer() {
+ return wrap(this.impl.commonAncestorContainer);
+ },
+ setStart: function(refNode,offset) {
+ this.impl.setStart(unwrapIfNeeded(refNode), offset);
+ },
+ setEnd: function(refNode,offset) {
+ this.impl.setEnd(unwrapIfNeeded(refNode), offset);
+ },
+ setStartBefore: function(refNode) {
+ this.impl.setStartBefore(unwrapIfNeeded(refNode));
+ },
+ setStartAfter: function(refNode) {
+ this.impl.setStartAfter(unwrapIfNeeded(refNode));
+ },
+ setEndBefore: function(refNode) {
+ this.impl.setEndBefore(unwrapIfNeeded(refNode));
+ },
+ setEndAfter: function(refNode) {
+ this.impl.setEndAfter(unwrapIfNeeded(refNode));
+ },
+ selectNode: function(refNode) {
+ this.impl.selectNode(unwrapIfNeeded(refNode));
+ },
+ selectNodeContents: function(refNode) {
+ this.impl.selectNodeContents(unwrapIfNeeded(refNode));
+ },
+ compareBoundaryPoints: function(how, sourceRange) {
+ return this.impl.compareBoundaryPoints(how, unwrap(sourceRange));
+ },
+ extractContents: function() {
+ return wrap(this.impl.extractContents());
+ },
+ cloneContents: function() {
+ return wrap(this.impl.cloneContents());
+ },
+ insertNode: function(node) {
+ this.impl.insertNode(unwrapIfNeeded(node));
+ },
+ surroundContents: function(newParent) {
+ this.impl.surroundContents(unwrapIfNeeded(newParent));
+ },
+ cloneRange: function() {
+ return wrap(this.impl.cloneRange());
+ },
+ isPointInRange: function(node, offset) {
+ return this.impl.isPointInRange(unwrapIfNeeded(node), offset);
+ },
+ comparePoint: function(node, offset) {
+ return this.impl.comparePoint(unwrapIfNeeded(node), offset);
+ },
+ intersectsNode: function(node) {
+ return this.impl.intersectsNode(unwrapIfNeeded(node));
+ }
+ };
+
+ // IE9 does not have createContextualFragment.
+ if (OriginalRange.prototype.createContextualFragment) {
+ Range.prototype.createContextualFragment = function(html) {
+ return wrap(this.impl.createContextualFragment(html));
+ };
+ }
+
+ registerWrapper(window.Range, Range, document.createRange());
+
+ scope.wrappers.Range = Range;
+
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -4149,7 +4826,7 @@
scope.wrappers.DocumentFragment = DocumentFragment;
scope.wrappers.Text = Text;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -4214,7 +4891,9 @@
});
scope.wrappers.ShadowRoot = ShadowRoot;
-})(this.ShadowDOMPolyfill);
+
+})(window.ShadowDOMPolyfill);
+
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -4229,9 +4908,7 @@
var ShadowRoot = scope.wrappers.ShadowRoot;
var assert = scope.assert;
var mixin = scope.mixin;
- var muteMutationEvents = scope.muteMutationEvents;
var oneOf = scope.oneOf;
- var unmuteMutationEvents = scope.unmuteMutationEvents;
var unwrap = scope.unwrap;
var wrap = scope.wrap;
@@ -4575,11 +5252,8 @@
this.renderNode(shadowRoot, renderNode, node, false);
}
- if (topMostRenderer) {
- //muteMutationEvents();
+ if (topMostRenderer)
renderNode.sync();
- //unmuteMutationEvents();
- }
this.dirty = false;
},
@@ -4849,8 +5523,8 @@
return getDistributedChildNodes(this);
};
- HTMLShadowElement.prototype.nodeWasAdded_ =
- HTMLContentElement.prototype.nodeWasAdded_ = function() {
+ HTMLShadowElement.prototype.nodeIsInserted_ =
+ HTMLContentElement.prototype.nodeIsInserted_ = function() {
// Invalidate old renderer if any.
this.invalidateShadowRenderer();
@@ -4875,7 +5549,8 @@
remove: remove,
};
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
+
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE file.
@@ -4929,7 +5604,7 @@
elementsWithFormProperty.forEach(createWrapperConstructor);
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -5013,6 +5688,8 @@
doc.adoptNode(oldShadowRoot);
}
+ var originalImportNode = document.importNode;
+
mixin(Document.prototype, {
adoptNode: function(node) {
if (node.parentNode)
@@ -5022,6 +5699,17 @@
},
elementFromPoint: function(x, y) {
return elementFromPoint(this, this, x, y);
+ },
+ importNode: function(node, deep) {
+ // We need to manually walk the tree to ensure we do not include rendered
+ // shadow trees.
+ var clone = wrap(originalImportNode.call(this.impl, unwrap(node), false));
+ if (deep) {
+ for (var child = node.firstChild; child; child = child.nextSibling) {
+ clone.appendChild(this.importNode(child, true));
+ }
+ }
+ return clone;
}
});
@@ -5140,6 +5828,7 @@
window.HTMLDocument || window.Document, // Gecko adds these to HTMLDocument
], [
'adoptNode',
+ 'importNode',
'contains',
'createComment',
'createDocumentFragment',
@@ -5221,7 +5910,7 @@
scope.wrappers.DOMImplementation = DOMImplementation;
scope.wrappers.Document = Document;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -5271,188 +5960,7 @@
scope.wrappers.Window = Window;
-})(this.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
- 'use strict';
-
- var defineGetter = scope.defineGetter;
- var defineWrapGetter = scope.defineWrapGetter;
- var registerWrapper = scope.registerWrapper;
- var unwrapIfNeeded = scope.unwrapIfNeeded;
- var wrapNodeList = scope.wrapNodeList;
- var wrappers = scope.wrappers;
-
- var OriginalMutationObserver = window.MutationObserver ||
- window.WebKitMutationObserver;
-
- if (!OriginalMutationObserver)
- return;
-
- var OriginalMutationRecord = window.MutationRecord;
-
- function MutationRecord(impl) {
- this.impl = impl;
- }
-
- MutationRecord.prototype = {
- get addedNodes() {
- return wrapNodeList(this.impl.addedNodes);
- },
- get removedNodes() {
- return wrapNodeList(this.impl.removedNodes);
- }
- };
-
- ['target', 'previousSibling', 'nextSibling'].forEach(function(name) {
- defineWrapGetter(MutationRecord, name);
- });
-
- // WebKit/Blink treats these as instance properties so we override
- [
- 'type',
- 'attributeName',
- 'attributeNamespace',
- 'oldValue'
- ].forEach(function(name) {
- defineGetter(MutationRecord, name, function() {
- return this.impl[name];
- });
- });
-
- if (OriginalMutationRecord)
- registerWrapper(OriginalMutationRecord, MutationRecord);
-
- function wrapRecord(record) {
- return new MutationRecord(record);
- }
-
- function wrapRecords(records) {
- return records.map(wrapRecord);
- }
-
- function MutationObserver(callback) {
- var self = this;
- this.impl = new OriginalMutationObserver(function(mutations, observer) {
- callback.call(self, wrapRecords(mutations), self);
- });
- }
-
- var OriginalNode = window.Node;
-
- MutationObserver.prototype = {
- observe: function(target, options) {
- this.impl.observe(unwrapIfNeeded(target), options);
- },
- disconnect: function() {
- this.impl.disconnect();
- },
- takeRecords: function() {
- return wrapRecords(this.impl.takeRecords());
- }
- };
-
- scope.wrappers.MutationObserver = MutationObserver;
- scope.wrappers.MutationRecord = MutationRecord;
-
-})(this.ShadowDOMPolyfill);
-
-// Copyright 2013 The Polymer Authors. All rights reserved.
-// Use of this source code is goverened by a BSD-style
-// license that can be found in the LICENSE file.
-
-(function(scope) {
- 'use strict';
-
- var registerWrapper = scope.registerWrapper;
- var unwrap = scope.unwrap;
- var unwrapIfNeeded = scope.unwrapIfNeeded;
- var wrap = scope.wrap;
-
- var OriginalRange = window.Range;
-
- function Range(impl) {
- this.impl = impl;
- }
- Range.prototype = {
- get startContainer() {
- return wrap(this.impl.startContainer);
- },
- get endContainer() {
- return wrap(this.impl.endContainer);
- },
- get commonAncestorContainer() {
- return wrap(this.impl.commonAncestorContainer);
- },
- setStart: function(refNode,offset) {
- this.impl.setStart(unwrapIfNeeded(refNode), offset);
- },
- setEnd: function(refNode,offset) {
- this.impl.setEnd(unwrapIfNeeded(refNode), offset);
- },
- setStartBefore: function(refNode) {
- this.impl.setStartBefore(unwrapIfNeeded(refNode));
- },
- setStartAfter: function(refNode) {
- this.impl.setStartAfter(unwrapIfNeeded(refNode));
- },
- setEndBefore: function(refNode) {
- this.impl.setEndBefore(unwrapIfNeeded(refNode));
- },
- setEndAfter: function(refNode) {
- this.impl.setEndAfter(unwrapIfNeeded(refNode));
- },
- selectNode: function(refNode) {
- this.impl.selectNode(unwrapIfNeeded(refNode));
- },
- selectNodeContents: function(refNode) {
- this.impl.selectNodeContents(unwrapIfNeeded(refNode));
- },
- compareBoundaryPoints: function(how, sourceRange) {
- return this.impl.compareBoundaryPoints(how, unwrap(sourceRange));
- },
- extractContents: function() {
- return wrap(this.impl.extractContents());
- },
- cloneContents: function() {
- return wrap(this.impl.cloneContents());
- },
- insertNode: function(node) {
- this.impl.insertNode(unwrapIfNeeded(node));
- },
- surroundContents: function(newParent) {
- this.impl.surroundContents(unwrapIfNeeded(newParent));
- },
- cloneRange: function() {
- return wrap(this.impl.cloneRange());
- },
- isPointInRange: function(node, offset) {
- return this.impl.isPointInRange(unwrapIfNeeded(node), offset);
- },
- comparePoint: function(node, offset) {
- return this.impl.comparePoint(unwrapIfNeeded(node), offset);
- },
- intersectsNode: function(node) {
- return this.impl.intersectsNode(unwrapIfNeeded(node));
- }
- };
-
- // IE9 does not have createContextualFragment.
- if (OriginalRange.prototype.createContextualFragment) {
- Range.prototype.createContextualFragment = function(html) {
- return wrap(this.impl.createContextualFragment(html));
- };
- }
-
- registerWrapper(window.Range, Range);
-
- scope.wrappers.Range = Range;
-
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
@@ -5554,7 +6062,8 @@
// Export for testing.
scope.knownElements = elements;
-})(this.ShadowDOMPolyfill);
+})(window.ShadowDOMPolyfill);
+
/*
* Copyright 2013 The Polymer Authors. All rights reserved.
* Use of this source code is governed by a BSD-style
@@ -6043,11 +6552,16 @@
return cssText.replace(cssColonHostRe, function(m, p1, p2, p3) {
p1 = polyfillHostNoCombinator;
if (p2) {
- if (p2.match(polyfillHost)) {
- return p1 + p2.replace(polyfillHost, '') + p3;
- } else {
- return p1 + p2 + p3 + ', ' + p2 + ' ' + p1 + p3;
+ var parts = p2.split(','), r = [];
+ for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) {
+ p = p.trim();
+ if (p.match(polyfillHost)) {
+ r.push(p1 + p.replace(polyfillHost, '') + p3);
+ } else {
+ r.push(p1 + p + p3 + ', ' + p + ' ' + p1 + p3);
+ }
}
+ return r.join(',');
} else {
return p1 + p3;
}
@@ -6057,7 +6571,7 @@
* Convert ^ and ^^ combinators by replacing with space.
*/
convertCombinators: function(cssText) {
- return cssText.replace('^^', ' ').replace('^', ' ');
+ return cssText.replace(/\^\^/g, ' ').replace(/\^/g, ' ');
},
// change a selector like 'div' to 'name div'
scopeRules: function(cssRules, name, typeExtension) {
@@ -6069,7 +6583,7 @@
cssText += this.propertiesFromRule(rule) + '\n}\n\n';
} else if (rule.media) {
cssText += '@media ' + rule.media.mediaText + ' {\n';
- cssText += this.scopeRules(rule.cssRules, name);
+ cssText += this.scopeRules(rule.cssRules, name, typeExtension);
cssText += '\n}\n\n';
} else if (rule.cssText) {
cssText += rule.cssText + '\n\n';
@@ -6082,8 +6596,9 @@
parts.forEach(function(p) {
p = p.trim();
if (this.selectorNeedsScoping(p, name, typeExtension)) {
- p = strict ? this.applyStrictSelectorScope(p, name) :
- this.applySimpleSelectorScope(p, name, typeExtension);
+ p = (strict && !p.match(polyfillHostNoCombinator)) ?
+ this.applyStrictSelectorScope(p, name) :
+ this.applySimpleSelectorScope(p, name, typeExtension);
}
r.push(p);
}, this);
@@ -6131,14 +6646,7 @@
polyfillHost);
},
propertiesFromRule: function(rule) {
- var properties = rule.style.cssText;
- // TODO(sorvell): Chrome cssom incorrectly removes quotes from the content
- // property. (https://code.google.com/p/chromium/issues/detail?id=247231)
- if (rule.style.content && !rule.style.content.match(/['"]+/)) {
- properties = 'content: \'' + rule.style.content + '\';\n' +
- rule.style.cssText.replace(/content:[^;]*;/g, '');
- }
- return properties;
+ return rule.style.cssText;
}
};
@@ -6152,15 +6660,18 @@
cssPolyfillUnscopedRuleCommentRe = /\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,
cssPseudoRe = /::(x-[^\s{,(]*)/gim,
cssPartRe = /::part\(([^)]*)\)/gim,
- // note: :host pre-processed to -host.
- cssColonHostRe = /(-host)(?:\(([^)]*)\))?([^,{]*)/gim,
+ // note: :host pre-processed to -shadowcsshost.
+ polyfillHost = '-shadowcsshost',
+ cssColonHostRe = new RegExp('(' + polyfillHost +
+ ')(?:\\((' +
+ '(?:\\([^)(]*\\)|[^)(]*)+?' +
+ ')\\))?([^,{]*)', 'gim'),
selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$',
hostRe = /@host/gim,
colonHostRe = /\:host/gim,
- polyfillHost = '-host',
/* host name without combinator */
- polyfillHostNoCombinator = '-host-no-combinator',
- polyfillHostRe = /-host/gim;
+ polyfillHostNoCombinator = polyfillHost + '-no-combinator',
+ polyfillHostRe = new RegExp(polyfillHost, 'gim');
function stylesToCssText(styles, preserveComments) {
var cssText = '';
@@ -7786,7 +8297,7 @@
call$3:function(a,b,c){return this.nn.call(this.wc,a,b,c)}}]
$$.zy=[H,{"":"Tp;call$2,$name",$is_bh:true}]
$$.Nb=[H,{"":"Tp;call$1,$name",$is_HB:true,$is_Dv:true}]
-$$.HB=[H,{"":"Tp;call$0,$name",$is_X0:true}]
+$$.Fy=[H,{"":"Tp;call$0,$name",$is_X0:true}]
$$.eU=[H,{"":"Tp;call$7,$name"}]
$$.ADW=[P,{"":"Tp;call$2,$name",
call$1:function(a){return this.call$2(a,null)},
@@ -7805,7 +8316,7 @@
call$catchAll:function(){return{onError:null,radix:null}},
$is_HB:true,
$is_Dv:true}]
-;init.mangledNames={gAQ:"iconClass",gB:"length",gDb:"_cachedDeclarations",gEI:"prefix",gF1:"isolate",gFJ:"__$cls",gFT:"__$instruction",gFU:"_cachedMethodsMap",gG1:"message",gH8:"_fieldsDescriptor",gHt:"_fieldsMetadata",gKM:"$",gLy:"_cachedSetters",gM2:"_cachedVariables",gMj:"function",gNI:"instruction",gOk:"_cachedMetadata",gP:"value",gP2:"_collapsed",gPw:"__$isolate",gPy:"__$error",gQG:"app",gQq:"__$trace",gRu:"cls",gT1:"_cachedGetters",gTn:"json",gTx:"_jsConstructorOrInterceptor",gUF:"_cachedTypeVariables",gVA:"__$displayValue",gVB:"error_obj",gWL:"_mangledName",gXB:"_message",gXf:"__$iconClass",gZ6:"locationManager",gZw:"__$code",ga:"a",gai:"displayValue",gb:"b",gb0:"_cachedConstructors",gcC:"hash",geb:"__$json",ghO:"__$error_obj",gi0:"__$name",gi2:"isolates",giI:"__$library",gjO:"id",gjd:"_cachedMethods",gkc:"error",gkf:"_count",gle:"_metadata",glw:"requestManager",gn2:"responses",gnI:"isolateManager",gnz:"_owner",goc:"name",gpz:"_jsConstructorCache",gqN:"_superclass",gql:"__$function",gqm:"_cachedSuperinterfaces",gt0:"field",gtB:"_cachedFields",gtD:"library",gtH:"__$app",gtN:"trace",gtT:"code",guA:"_cachedMembers",gvH:"index",gvt:"__$field",gxj:"collapsed",gzd:"currentHash"};init.mangledGlobalNames={DI:"_closeIconClass",Vl:"_openIconClass"};(function (reflectionData) {
+;init.mangledNames={gB:"length",gCr:"_mangledName",gCt:"paddedLine",gDb:"_cachedDeclarations",gEI:"prefix",gF1:"isolate",gFF:"source",gFJ:"__$cls",gFT:"__$instruction",gFU:"_cachedMethodsMap",gG1:"message",gH8:"_fieldsDescriptor",gHX:"__$displayValue",gHt:"_fieldsMetadata",gKM:"$",gLA:"src",gLy:"_cachedSetters",gM2:"_cachedVariables",gMj:"function",gNI:"instruction",gNl:"script",gO3:"url",gOk:"_cachedMetadata",gP:"value",gPw:"__$isolate",gPy:"__$error",gQG:"app",gQq:"__$trace",gRu:"cls",gT1:"_cachedGetters",gTn:"json",gTx:"_jsConstructorOrInterceptor",gUF:"_cachedTypeVariables",gUy:"_collapsed",gUz:"__$script",gVB:"error_obj",gXB:"_message",gXJ:"lines",gXR:"scripts",gZ6:"locationManager",gZw:"__$code",ga:"a",gai:"displayValue",gb:"b",gb0:"_cachedConstructors",gcC:"hash",geb:"__$json",gfY:"kind",ghO:"__$error_obj",ghm:"__$app",gi0:"__$name",gi2:"isolates",giI:"__$library",gjO:"id",gjd:"_cachedMethods",gkc:"error",gkf:"_count",gl7:"iconClass",glD:"currentHashUri",gle:"_metadata",glw:"requestManager",gn2:"responses",gnI:"isolateManager",gnz:"_owner",goc:"name",gpz:"_jsConstructorCache",gqN:"_superclass",gql:"__$function",gqm:"_cachedSuperinterfaces",gt0:"field",gtB:"_cachedFields",gtD:"library",gtN:"trace",gtT:"code",guA:"_cachedMembers",gvH:"index",gvX:"__$source",gvt:"__$field",gxj:"collapsed",gzd:"currentHash",gzh:"__$iconClass"};init.mangledGlobalNames={DI:"_closeIconClass",Vl:"_openIconClass"};(function (reflectionData) {
function map(x){x={x:x};delete x.x;return x}
if (!init.libraries) init.libraries = [];
if (!init.mangledNames) init.mangledNames = map();
@@ -7915,22 +8426,31 @@
if(typeof z!=="number")throw z.g()
return J.UQ(y,z+2)[b]},Gv:{"":"a;",
n:function(a,b){return a===b},
+"+==:1:0":0,
giO:function(a){return H.eQ(a)},
+"+hashCode":0,
bu:function(a){return H.a5(a)},
+"+toString:0:0":0,
T:function(a,b){throw H.b(P.lr(a,b.gWa(),b.gnd(),b.gVm(),null))},
"+noSuchMethod:1:0":0,
gbx:function(a){return new H.cu(H.dJ(a),null)},
$isGv:true,
"%":"DOMImplementation|SVGAnimatedEnumeration|SVGAnimatedNumberList|SVGAnimatedString"},kn:{"":"bool/Gv;",
bu:function(a){return String(a)},
+"+toString:0:0":0,
giO:function(a){return a?519018:218159},
+"+hashCode":0,
gbx:function(a){return C.HL},
$isbool:true},PE:{"":"Gv;",
n:function(a,b){return null==b},
+"+==:1:0":0,
bu:function(a){return"null"},
+"+toString:0:0":0,
giO:function(a){return 0},
+"+hashCode":0,
gbx:function(a){return C.GX}},QI:{"":"Gv;",
giO:function(a){return 0},
+"+hashCode":0,
gbx:function(a){return C.CS}},Tm:{"":"QI;"},is:{"":"QI;"},Q:{"":"List/Gv;",
h:function(a,b){if(!!a.fixed$length)H.vh(P.f("add"))
a.push(b)},
@@ -8003,12 +8523,14 @@
gor:function(a){return a.length!==0},
"+isNotEmpty":0,
bu:function(a){return H.mx(a,"[","]")},
+"+toString:0:0":0,
tt:function(a,b){return P.F(a,b,H.W8(a,"Q",0))},
br:function(a){return this.tt(a,!0)},
gA:function(a){var z=new H.a7(a,a.length,0,null)
H.VM(z,[H.W8(a,"Q",0)])
return z},
giO:function(a){return H.eQ(a)},
+"+hashCode":0,
gB:function(a){return a.length},
"+length":0,
sB:function(a,b){if(typeof b!=="number"||Math.floor(b)!==b)throw H.b(new P.AT(b))
@@ -8054,9 +8576,13 @@
HG:function(a){return this.yu(this.UD(a))},
UD:function(a){if(a<0)return-Math.round(-a)
else return Math.round(a)},
+WZ:function(a,b){if(b<2||b>36)throw H.b(P.C3(b))
+return a.toString(b)},
bu:function(a){if(a===0&&1/a<0)return"-0.0"
else return""+a},
+"+toString:0:0":0,
giO:function(a){return a&0x1FFFFFFF},
+"+hashCode":0,
J:function(a){return-a},
g:function(a,b){if(typeof b!=="number")throw H.b(new P.AT(b))
return a+b},
@@ -8087,7 +8613,7 @@
F:function(a,b){if(typeof b!=="number")throw H.b(P.u(b))
return a>=b},
$isnum:true,
-static:{"":"Cv,nr",}},im:{"":"int/P;",
+static:{"":"l8,nr",}},im:{"":"int/P;",
gbx:function(a){return C.yw},
$isdouble:true,
$isnum:true,
@@ -8179,12 +8705,14 @@
else z=a<b?-1:1
return z},
bu:function(a){return a},
+"+toString:0:0":0,
giO:function(a){var z,y,x
for(z=a.length,y=0,x=0;x<z;++x){y=536870911&y+a.charCodeAt(x)
y=536870911&y+((524287&y)<<10>>>0)
y^=y>>6}y=536870911&y+((67108863&y)<<3>>>0)
y^=y>>11
return 536870911&y+((16383&y)<<15>>>0)},
+"+hashCode":0,
gbx:function(a){return C.Db},
gB:function(a){return a.length},
"+length":0,
@@ -8286,7 +8814,7 @@
return z.YQ(a)}else{z=new H.NO(new H.X1())
z.mR=new H.aJ(null)
return z.YQ(a)}},Hh:function(a){if($globalState.ji===!0)return new H.II(null).QS(a)
-else return a},vM:function(a){return a==null||typeof a==="string"||typeof a==="number"||typeof a==="boolean"},kV:function(a){return a==null||typeof a==="string"||typeof a==="number"||typeof a==="boolean"},PK:{"":"Tp;a",
+else return a},VO:function(a){return a==null||typeof a==="string"||typeof a==="number"||typeof a==="boolean"},kV:function(a){return a==null||typeof a==="string"||typeof a==="number"||typeof a==="boolean"},PK:{"":"Tp;a",
call$0:function(){this.a.call$1([])},
"+call:0:0":0,
$isEH:true,
@@ -8373,8 +8901,8 @@
P.rT(C.RT,this)},
"+call:0:0":0,
$isEH:true,
-$is_X0:true},IY:{"":"a;F1*,i3,G1*",
-VU:function(){this.F1.vV(this.i3)},
+$is_X0:true},IY:{"":"a;F1*,xh,G1*",
+VU:function(){this.F1.vV(this.xh)},
$isIY:true},JH:{"":"a;"},jl:{"":"Tp;a,b,c,d,e",
call$0:function(){H.Kc(this.a,this.b,this.c,this.d,this.e)},
"+call:0:0":0,
@@ -8385,7 +8913,9 @@
if(b==null)return!1
z=J.x(b)
return typeof b==="object"&&b!==null&&!!z.$isJM&&J.xC(this.JE,b.JE)},
+"+==:1:0":0,
giO:function(a){return this.JE.gng()},
+"+hashCode":0,
$isJM:true,
$isbC:true},Ua:{"":"Tp;b,c",
call$0:function(){var z,y,x,w,v,u,t
@@ -8421,12 +8951,14 @@
if(b==null)return!1
z=J.x(b)
return typeof b==="object"&&b!==null&&!!z.$isns&&J.xC(this.Ws,b.Ws)&&J.xC(this.tv,b.tv)&&J.xC(this.bv,b.bv)},
+"+==:1:0":0,
giO:function(a){var z,y,x
-z=J.Eh(this.Ws,16)
-y=J.Eh(this.tv,8)
+z=J.c1(this.Ws,16)
+y=J.c1(this.tv,8)
x=this.bv
if(typeof x!=="number")throw H.s(x)
return(z^y^x)>>>0},
+"+hashCode":0,
$isns:true,
$isbC:true},wd:{"":"Tp;a,b",
call$0:function(){var z,y,x,w
@@ -8517,7 +9049,7 @@
Hn:function(a){},
F4:function(){}},HU:{"":"a;",
YQ:function(a){var z,y
-if(H.vM(a))return this.Pq(a)
+if(H.VO(a))return this.Pq(a)
y=this.mR
y.Hn(y)
z=null
@@ -8777,11 +9309,11 @@
if(q==null){if(c==null)z=[]
else{z=c.gvc(c)
z=P.F(z,!0,H.W8(z,"mW",0))}return J.jf(a,new H.LI(C.Ka,r,0,x,z,null))}return q.apply(a,x)},pL:function(a){if(a=="String")return C.Kn
-if(a=="int")return C.c1
+if(a=="int")return C.wq
if(a=="double")return C.yX
if(a=="num")return C.oD
if(a=="bool")return C.Fm
-if(a=="List")return C.E3
+if(a=="List")return C.l0
return init.allClasses[a]},Pq:function(){var z={x:0}
delete z.x
return z},s:function(a){throw H.b(P.u(a))},e:function(a,b){if(a==null)J.q8(a)
@@ -9062,6 +9594,7 @@
gor:function(a){return!J.xC(this.gB(this),0)},
"+isNotEmpty":0,
bu:function(a){return P.vW(this)},
+"+toString:0:0":0,
q3:function(){throw H.b(P.f("Cannot modify unmodifiable Map"))},
u:function(a,b,c){return this.q3()},
"+[]=:2:0":0,
@@ -9250,6 +9783,7 @@
bu:function(a){var z=this.Sp
if(z==null)return"NullError: "+H.d(this.Zf)
return"NullError: Cannot call \""+H.d(z)+"\" on null"},
+"+toString:0:0":0,
$ismp:true,
$isGe:true},az:{"":"Ge;Zf,Sp,lv",
bu:function(a){var z,y
@@ -9258,6 +9792,7 @@
y=this.lv
if(y==null)return"NoSuchMethodError: Cannot call \""+z+"\" ("+H.d(this.Zf)+")"
return"NoSuchMethodError: Cannot call \""+z+"\" on \""+y+"\" ("+H.d(this.Zf)+")"},
+"+toString:0:0":0,
$ismp:true,
$isGe:true,
static:{T3:function(a,b){var z,y
@@ -9266,7 +9801,8 @@
z=z?null:b.receiver
return new H.az(a,y,z)}}},vV:{"":"Ge;Zf",
bu:function(a){var z=this.Zf
-return C.xB.gl0(z)?"Error":"Error: "+z}},Hk:{"":"Tp;a",
+return C.xB.gl0(z)?"Error":"Error: "+z},
+"+toString:0:0":0},Hk:{"":"Tp;a",
call$1:function(a){var z=J.x(a)
if(typeof a==="object"&&a!==null&&!!z.$isGe)if(a.$thrownJsError==null)a.$thrownJsError=this.a
return a},
@@ -9281,7 +9817,8 @@
y=typeof z==="object"?z.stack:null
z=y==null?"":y
this.bQ=z
-return z}},dr:{"":"Tp;a",
+return z},
+"+toString:0:0":0},dr:{"":"Tp;a",
call$0:function(){return this.a.call$0()},
"+call:0:0":0,
$isEH:true,
@@ -9303,6 +9840,7 @@
$isEH:true,
$is_X0:true},Tp:{"":"a;",
bu:function(a){return"Closure"},
+"+toString:0:0":0,
$isTp:true,
$isEH:true},v:{"":"Tp;wc<,nn<,lv,Pp>",
n:function(a,b){var z
@@ -9311,17 +9849,21 @@
z=J.x(b)
if(typeof b!=="object"||b===null||!z.$isv)return!1
return this.wc===b.wc&&this.nn===b.nn&&this.lv===b.lv},
+"+==:1:0":0,
giO:function(a){var z,y
z=this.lv
if(z==null)y=H.eQ(this.wc)
else y=typeof z!=="object"?J.v1(z):H.eQ(z)
return(y^H.eQ(this.nn))>>>0},
+"+hashCode":0,
$isv:true},Z3:{"":"a;Jy"},D2:{"":"a;Jy"},GT:{"":"a;oc>"},Pe:{"":"Ge;G1>",
bu:function(a){return this.G1},
+"+toString:0:0":0,
$isGe:true,
static:{aq:function(a,b){return new H.Pe("CastError: Casting value of type "+a+" to incompatible type "+H.d(b))}}},Eq:{"":"Ge;G1>",
bu:function(a){return"RuntimeError: "+this.G1},
-static:{Pa:function(a){return new H.Eq(a)}}},cu:{"":"a;IE<,rE",
+"+toString:0:0":0,
+static:{Ef:function(a){return new H.Eq(a)}}},cu:{"":"a;IE<,rE",
bu:function(a){var z,y,x
z=this.rE
if(z!=null)return z
@@ -9330,11 +9872,14 @@
y=x==null?y:x
this.rE=y
return y},
+"+toString:0:0":0,
giO:function(a){return J.v1(this.IE)},
+"+hashCode":0,
n:function(a,b){var z
if(b==null)return!1
z=J.x(b)
return typeof b==="object"&&b!==null&&!!z.$iscu&&J.xC(this.IE,b.IE)},
+"+==:1:0":0,
$iscu:true,
$isuq:true},Lm:{"":"a;h7<,oc>,kU>"},dC:{"":"Tp;a",
call$1:function(a){return this.a(a)},
@@ -9435,14 +9980,14 @@
t:function(a,b){if(!J.xC(b,0))H.vh(P.N(b))
return this.zO},
"+[]:1:0":0,
-$isOd:true}}],["app_bootstrap","index.html_bootstrap.dart",,E,{E2:function(){$.x2=["package:observatory/src/observatory_elements/observatory_element.dart","package:observatory/src/observatory_elements/error_view.dart","package:observatory/src/observatory_elements/class_view.dart","package:observatory/src/observatory_elements/disassembly_entry.dart","package:observatory/src/observatory_elements/code_view.dart","package:observatory/src/observatory_elements/collapsible_content.dart","package:observatory/src/observatory_elements/field_view.dart","package:observatory/src/observatory_elements/function_view.dart","package:observatory/src/observatory_elements/isolate_summary.dart","package:observatory/src/observatory_elements/isolate_list.dart","package:observatory/src/observatory_elements/json_view.dart","package:observatory/src/observatory_elements/library_view.dart","package:observatory/src/observatory_elements/stack_trace.dart","package:observatory/src/observatory_elements/message_viewer.dart","package:observatory/src/observatory_elements/navigation_bar.dart","package:observatory/src/observatory_elements/response_viewer.dart","package:observatory/src/observatory_elements/observatory_application.dart","index.html.0.dart"]
+$isOd:true}}],["app_bootstrap","index.html_bootstrap.dart",,E,{E2:function(){$.x2=["package:observatory/src/observatory_elements/observatory_element.dart","package:observatory/src/observatory_elements/error_view.dart","package:observatory/src/observatory_elements/class_view.dart","package:observatory/src/observatory_elements/disassembly_entry.dart","package:observatory/src/observatory_elements/code_view.dart","package:observatory/src/observatory_elements/collapsible_content.dart","package:observatory/src/observatory_elements/field_view.dart","package:observatory/src/observatory_elements/function_view.dart","package:observatory/src/observatory_elements/isolate_summary.dart","package:observatory/src/observatory_elements/isolate_list.dart","package:observatory/src/observatory_elements/json_view.dart","package:observatory/src/observatory_elements/library_view.dart","package:observatory/src/observatory_elements/source_view.dart","package:observatory/src/observatory_elements/script_view.dart","package:observatory/src/observatory_elements/stack_trace.dart","package:observatory/src/observatory_elements/message_viewer.dart","package:observatory/src/observatory_elements/navigation_bar.dart","package:observatory/src/observatory_elements/response_viewer.dart","package:observatory/src/observatory_elements/observatory_application.dart","index.html.0.dart"]
$.uP=!1
-A.Ok()}},1],["class_view_element","package:observatory/src/observatory_elements/class_view.dart",,Z,{aC:{"":["Vf;FJ%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+A.Ok()}},1],["class_view_element","package:observatory/src/observatory_elements/class_view.dart",,Z,{aC:{"":["Vf;FJ%-,VJ,Ai,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
gRu:function(a){return a.FJ
-"32,33,34"},
+"34,35,36"},
"+cls":1,
-sRu:function(a,b){a.FJ=this.pD(a,C.XA,a.FJ,b)
-"35,28,32,33"},
+sRu:function(a,b){a.FJ=this.ct(a,C.XA,a.FJ,b)
+"37,28,34,35"},
"+cls=":1,
"@":function(){return[C.aQ]},
static:{zg:function(a){var z,y,x,w,v
@@ -9458,12 +10003,12 @@
C.kk.ZL(a)
C.kk.FH(a)
return a
-"9"},"+new ClassViewElement$created:0:0":1}},"+ClassViewElement": [36],Vf:{"":"uL+Pi;",$isd3:true}}],["code_view_element","package:observatory/src/observatory_elements/code_view.dart",,F,{Be:{"":["tu;Zw%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"9"},"+new ClassViewElement$created:0:0":1}},"+ClassViewElement": [38],Vf:{"":"uL+Pi;",$isd3:true}}],["code_view_element","package:observatory/src/observatory_elements/code_view.dart",,F,{Be:{"":["tu;Zw%-,VJ,Ai,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
gtT:function(a){return a.Zw
-"32,33,34"},
+"34,35,36"},
"+code":1,
-stT:function(a,b){a.Zw=this.pD(a,C.b1,a.Zw,b)
-"35,28,32,33"},
+stT:function(a,b){a.Zw=this.ct(a,C.b1,a.Zw,b)
+"37,28,34,35"},
"+code=":1,
grK:function(a){var z=a.Zw
if(z!=null&&J.UQ(z,"is_optimized")!=null)return"panel panel-success"
@@ -9487,41 +10032,41 @@
C.YD.ZL(a)
C.YD.FH(a)
return a
-"10"},"+new CodeViewElement$created:0:0":1}},"+CodeViewElement": [37],tu:{"":"uL+Pi;",$isd3:true}}],["collapsible_content_element","package:observatory/src/observatory_elements/collapsible_content.dart",,R,{i6:{"":["Vc;Xf%-,VA%-,P2%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
-gAQ:function(a){return a.Xf
-"8,33,38"},
+"10"},"+new CodeViewElement$created:0:0":1}},"+CodeViewElement": [39],tu:{"":"uL+Pi;",$isd3:true}}],["collapsible_content_element","package:observatory/src/observatory_elements/collapsible_content.dart",,R,{i6:{"":["Vc;zh%-,HX%-,Uy%-,VJ,Ai,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+gl7:function(a){return a.zh
+"8,35,40"},
"+iconClass":1,
-sAQ:function(a,b){a.Xf=this.pD(a,C.Di,a.Xf,b)
-"35,28,8,33"},
+sl7:function(a,b){a.zh=this.ct(a,C.Di,a.zh,b)
+"37,28,8,35"},
"+iconClass=":1,
-gai:function(a){return a.VA
-"8,33,38"},
+gai:function(a){return a.HX
+"8,35,40"},
"+displayValue":1,
-sai:function(a,b){a.VA=this.pD(a,C.Jw,a.VA,b)
-"35,28,8,33"},
+sai:function(a,b){a.HX=this.ct(a,C.Jw,a.HX,b)
+"37,28,8,35"},
"+displayValue=":1,
-gxj:function(a){return a.P2
-"39"},
+gxj:function(a){return a.Uy
+"41"},
"+collapsed":1,
-sxj:function(a,b){a.P2=b
-this.dR(a)
-"35,40,39"},
+sxj:function(a,b){a.Uy=b
+this.SS(a)
+"37,42,41"},
"+collapsed=":1,
i4:function(a){Z.uL.prototype.i4.call(this,a)
-this.dR(a)
-"35"},
+this.SS(a)
+"37"},
"+enteredView:0:0":1,
-rS:function(a,b,c,d){a.P2=a.P2!==!0
-this.dR(a)
-this.dR(a)
-"35,41,42,43,35,44,45"},
+rS:function(a,b,c,d){a.Uy=a.Uy!==!0
+this.SS(a)
+this.SS(a)
+"37,43,44,45,37,46,47"},
"+toggleDisplay:3:0":1,
-dR:function(a){var z,y
-z=a.P2
-y=a.Xf
-if(z===!0){a.Xf=this.pD(a,C.Di,y,"glyphicon glyphicon-chevron-down")
-a.VA=this.pD(a,C.Jw,a.VA,"none")}else{a.Xf=this.pD(a,C.Di,y,"glyphicon glyphicon-chevron-up")
-a.VA=this.pD(a,C.Jw,a.VA,"block")}"35"},
+SS:function(a){var z,y
+z=a.Uy
+y=a.zh
+if(z===!0){a.zh=this.ct(a,C.Di,y,"glyphicon glyphicon-chevron-down")
+a.HX=this.ct(a,C.Jw,a.HX,"none")}else{a.zh=this.ct(a,C.Di,y,"glyphicon glyphicon-chevron-up")
+a.HX=this.ct(a,C.Jw,a.HX,"block")}"37"},
"+_refresh:0:0":1,
"@":function(){return[C.Gu]},
static:{"":"Vl<-,DI<-",IT:function(a){var z,y,x,w,v
@@ -9531,16 +10076,16 @@
w=W.cv
v=new V.br(P.Py(null,null,null,x,w),null,null)
H.VM(v,[x,w])
-a.Xf="glyphicon glyphicon-chevron-down"
-a.VA="none"
-a.P2=!0
+a.zh="glyphicon glyphicon-chevron-down"
+a.HX="none"
+a.Uy=!0
a.Ye=z
a.mT=y
a.KM=v
C.j8.ZL(a)
C.j8.FH(a)
return a
-"11"},"+new CollapsibleContentElement$created:0:0":1}},"+CollapsibleContentElement": [46],Vc:{"":"uL+Pi;",$isd3:true}}],["custom_element.polyfill","package:custom_element/polyfill.dart",,B,{G9:function(){if($.LX()==null)return!0
+"11"},"+new CollapsibleContentElement$created:0:0":1}},"+CollapsibleContentElement": [48],Vc:{"":"uL+Pi;",$isd3:true}}],["custom_element.polyfill","package:custom_element/polyfill.dart",,B,{G9:function(){if($.LX()==null)return!0
var z=J.UQ($.LX(),"CustomElements")
if(z==null)return"register" in document
return J.xC(J.UQ(z,"ready"),!0)},zO:{"":"Tp;",
@@ -9761,7 +10306,7 @@
H.VM(z,[c,d])
return z}}},xy:{"":"i1;Kw,ew",$asi1:null,
$ascX:function(a,b){return[b]},
-$isqC:true},MH:{"":"Fl;mD,RX,ew",
+$isqC:true},MH:{"":"eL;mD,RX,ew",
ei:function(a){return this.ew.call$1(a)},
G:function(){var z=this.RX
if(z.G()){this.mD=this.ei(z.gl())
@@ -9769,7 +10314,7 @@
return!1},
gl:function(){return this.mD},
"+current":0,
-$asFl:function(a,b){return[b]}},A8:{"":"aL;qb,ew",
+$aseL:function(a,b){return[b]}},A8:{"":"aL;qb,ew",
ei:function(a){return this.ew.call$1(a)},
gB:function(a){return J.q8(this.qb)},
"+length":0,
@@ -9782,13 +10327,13 @@
H.VM(z,[H.W8(this,"U5",0)])
return z},
$asmW:null,
-$ascX:null},SO:{"":"Fl;RX,ew",
+$ascX:null},SO:{"":"eL;RX,ew",
ei:function(a){return this.ew.call$1(a)},
G:function(){for(var z=this.RX;z.G();)if(this.ei(z.gl())===!0)return!0
return!1},
gl:function(){return this.RX.gl()},
"+current":0,
-$asFl:null},zs:{"":"mW;Kw,ew",
+$aseL:null},zs:{"":"mW;Kw,ew",
gA:function(a){var z=J.GP(this.Kw)
z=new H.rR(z,this.ew,C.Gw,null)
H.VM(z,[H.W8(this,"zs",0),H.W8(this,"zs",1)])
@@ -9802,13 +10347,13 @@
for(var z=this.RX;!this.IO.G();){this.mD=null
if(z.G()){this.IO=null
this.IO=J.GP(this.ei(z.gl()))}else return!1}this.mD=this.IO.gl()
-return!0}},AM:{"":"mW;Kw,xZ",
+return!0}},vZ:{"":"mW;Kw,xZ",
eR:function(a,b){if(b<0)throw H.b(new P.bJ("value "+b))
-return H.ke(this.Kw,this.xZ+b,H.W8(this,"AM",0))},
+return H.ke(this.Kw,this.xZ+b,H.W8(this,"vZ",0))},
gA:function(a){var z=this.Kw
z=z.gA(z)
z=new H.U1(z,this.xZ)
-H.VM(z,[H.W8(this,"AM",0)])
+H.VM(z,[H.W8(this,"vZ",0)])
return z},
q1:function(a,b,c){if(this.xZ<0)throw H.b(P.C3(this.xZ))},
$asmW:null,
@@ -9818,26 +10363,26 @@
y=new H.d5(a,b)
H.VM(y,[z])
y.q1(a,b,z)
-return y}return H.bk(a,b,c)},bk:function(a,b,c){var z=new H.AM(a,b)
+return y}return H.bk(a,b,c)},bk:function(a,b,c){var z=new H.vZ(a,b)
H.VM(z,[c])
z.q1(a,b,c)
-return z}}},d5:{"":"AM;Kw,xZ",
+return z}}},d5:{"":"vZ;Kw,xZ",
gB:function(a){var z,y
z=this.Kw
y=J.xH(z.gB(z),this.xZ)
if(J.J5(y,0))return y
return 0},
"+length":0,
-$asAM:null,
+$asvZ:null,
$ascX:null,
-$isqC:true},U1:{"":"Fl;RX,xZ",
+$isqC:true},U1:{"":"eL;RX,xZ",
G:function(){var z,y
for(z=this.RX,y=0;y<this.xZ;++y)z.G()
this.xZ=0
return z.G()},
gl:function(){return this.RX.gl()},
"+current":0,
-$asFl:null},SJ:{"":"a;",
+$aseL:null},SJ:{"":"a;",
G:function(){return!1},
gl:function(){return},
"+current":0},SU:{"":"a;",
@@ -9869,8 +10414,11 @@
if(b==null)return!1
z=J.x(b)
return typeof b==="object"&&b!==null&&!!z.$isGD&&J.xC(this.hr,b.hr)},
+"+==:1:0":0,
giO:function(a){return 536870911&664597*J.v1(this.hr)},
+"+hashCode":0,
bu:function(a){return"Symbol(\""+H.d(this.hr)+"\")"},
+"+toString:0:0":0,
$isGD:true,
$iswv:true,
static:{"":"zP",le:function(a){var z=J.U6(a)
@@ -10023,14 +10571,15 @@
$isEH:true,
$is_X0:true},jU:{"":"a;",
bu:function(a){return this.gOO()},
+"+toString:0:0":0,
IB:function(a){throw H.b(P.SY(null))},
Hy:function(a,b){throw H.b(P.SY(null))},
-$isQF:true},Lj:{"":"jU;MA",
+$isej:true},Lj:{"":"jU;MA",
gOO:function(){return"Isolate"},
gcZ:function(){var z=$.At().gvU().nb
z=z.gUQ(z)
return z.XG(z,new H.mb())},
-$isQF:true},mb:{"":"Tp;",
+$isej:true},mb:{"":"Tp;",
call$1:function(a){return a.grv()},
"+call:1:0":0,
$isEH:true,
@@ -10039,22 +10588,25 @@
gvd:function(){return H.fb(this.gh7(),this.gIf())},
gkw:function(){return J.co(J.Z0(this.gIf()),"_")},
bu:function(a){return this.gOO()+" on '"+H.d(J.Z0(this.gIf()))+"'"},
-gEO:function(){throw H.b(H.Pa("Should not call _methods"))},
-qj:function(a,b){throw H.b(H.Pa("Should not call _invoke"))},
+"+toString:0:0":0,
+gEO:function(){throw H.b(H.Ef("Should not call _methods"))},
+qj:function(a,b){throw H.b(H.Ef("Should not call _invoke"))},
gmW:function(a){return H.vh(P.SY(null))},
$isNL:true,
-$isQF:true},cw:{"":"EE;h7<,xW,LQ,If",
+$isej:true},cw:{"":"EE;h7<,xW,LQ,If",
n:function(a,b){var z
if(b==null)return!1
z=J.x(b)
return typeof b==="object"&&b!==null&&!!z.$iscw&&J.xC(this.If,b.If)&&J.xC(this.h7,b.h7)},
+"+==:1:0":0,
giO:function(a){return(1073741823&J.v1(C.Gp.IE)^17*J.v1(this.If)^19*J.v1(this.h7))>>>0},
+"+hashCode":0,
gOO:function(){return"TypeVariableMirror"},
$iscw:true,
$isFw:true,
-$isX9:true,
+$isL9u:true,
$isNL:true,
-$isQF:true},EE:{"":"am;If",
+$isej:true},EE:{"":"am;If",
gOO:function(){return"TypeMirror"},
gh7:function(){return},
gc9:function(){return H.vh(P.SY(null))},
@@ -10062,9 +10614,9 @@
gw8:function(){return C.hU},
gHA:function(){return!0},
gJi:function(){return this},
-$isX9:true,
+$isL9u:true,
$isNL:true,
-$isQF:true},Uz:{"":"uh;FP<,aP,wP,le,LB,rv<,ae<,SD,tB,P8,mX,T1,Ly,M2,uA,Db,Ok,If",
+$isej:true},Uz:{"":"uh;FP<,aP,wP,le,LB,rv<,ae<,SD,tB,P8,mX,T1,Ly,M2,uA,Db,Ok,If",
gOO:function(){return"LibraryMirror"},
gvd:function(){return this.If},
gEO:function(){return this.gm8()},
@@ -10108,7 +10660,7 @@
if(typeof y==="object"&&y!==null&&!!z.$isZk)if(!("$reflectable" in y.dl))H.Hz(J.Z0(a))
return H.vn(y.qj(b,c))},
"+invoke:3:0":0,
-"*invoke":[35],
+"*invoke":[37],
CI:function(a,b){return this.F2(a,b,null)},
"+invoke:2:0":0,
Z0:function(a){return $[a]},
@@ -10137,7 +10689,7 @@
y.push(p)
p.nz=this}++v}this.SD=y
return y},
-gKn:function(){var z,y
+gTH:function(){var z,y
z=this.tB
if(z!=null)return z
y=[]
@@ -10154,7 +10706,7 @@
H.VM(z,[P.wv,P.RS])
this.mX=z
return z},
-gII:function(){var z=this.T1
+gE4:function(){var z=this.T1
if(z!=null)return z
z=new H.Gj(P.L5(null,null,null,null,null))
H.VM(z,[P.wv,P.RS])
@@ -10170,7 +10722,7 @@
z=this.M2
if(z!=null)return z
y=P.L5(null,null,null,null,null)
-for(z=this.gKn(),z.toString,x=new H.a7(z,z.length,0,null),H.VM(x,[H.W8(z,"Q",0)]);x.G();){w=x.mD
+for(z=this.gTH(),z.toString,x=new H.a7(z,z.length,0,null),H.VM(x,[H.W8(z,"Q",0)]);x.G();){w=x.mD
y.u(y,w.gIf(),w)}z=new H.Gj(y)
H.VM(z,[P.wv,P.RY])
this.M2=z
@@ -10184,14 +10736,14 @@
z=new H.Kv(y)
x=this.gmu().nb
x.aN(x,z)
-x=this.gII().nb
+x=this.gE4().nb
x.aN(x,z)
x=this.gF8().nb
x.aN(x,z)
x=this.gZ3().nb
x.aN(x,z)
z=new H.Gj(y)
-H.VM(z,[P.wv,P.QF])
+H.VM(z,[P.wv,P.ej])
this.uA=z
return z},
"+members":0,
@@ -10214,8 +10766,8 @@
return z},
gh7:function(){return},
$isD4:true,
-$isQF:true,
-$isNL:true},uh:{"":"am+M2;",$isQF:true},Kv:{"":"Tp;a",
+$isej:true,
+$isNL:true},uh:{"":"am+M2;",$isej:true},Kv:{"":"Tp;a",
call$2:function(a,b){var z=this.a
z.u(z,a,b)},
"+call:2:0":0,
@@ -10242,13 +10794,12 @@
gvd:function(){return this.gIf()},
glc:function(a){return J.GK(this.XW)},
"+members":0,
-gtx:function(){return this.XW.gtx()},
gZ3:function(){return this.XW.gZ3()},
gYK:function(){return this.XW.gYK()},
"+declarations":0,
F2:function(a,b,c){throw H.b(P.lr(this,a,b,c,null))},
"+invoke:3:0":0,
-"*invoke":[35],
+"*invoke":[37],
CI:function(a,b){return this.F2(a,b,null)},
"+invoke:2:0":0,
rN:function(a){throw H.b(P.lr(this,a,null,null,null))},
@@ -10261,16 +10812,16 @@
gNy:function(){throw H.b(P.SY(null))},
gw8:function(){return C.hU},
$isMs:true,
-$isQF:true,
-$isX9:true,
-$isNL:true},y1:{"":"EE+M2;",$isQF:true},M2:{"":"a;",$isQF:true},iu:{"":"M2;Ax<",
+$isej:true,
+$isL9u:true,
+$isNL:true},y1:{"":"EE+M2;",$isej:true},M2:{"":"a;",$isej:true},iu:{"":"M2;Ax<",
gr9:function(a){return H.jO(J.bB(this.Ax).IE)},
F2:function(a,b,c){var z,y
z=J.Z0(a)
y=z+":"+b.length+":0"
return this.tu(a,0,y,b)},
"+invoke:3:0":0,
-"*invoke":[35],
+"*invoke":[37],
CI:function(a,b){return this.F2(a,b,null)},
"+invoke:2:0":0,
tu:function(a,b,c,d){var z,y,x,w,v,u,t,s
@@ -10302,11 +10853,14 @@
y=z==null?y==null:z===y
z=y}else z=!1
return z},
+"+==:1:0":0,
giO:function(a){return(H.CU(this.Ax)^909522486)>>>0},
+"+hashCode":0,
bu:function(a){return"InstanceMirror on "+H.d(P.hl(this.Ax))},
+"+toString:0:0":0,
$isiu:true,
$isvr:true,
-$isQF:true},mg:{"":"Tp;",
+$isej:true},mg:{"":"Tp;",
call$1:function(a){return init.metadata[a]},
"+call:1:0":0,
$isEH:true,
@@ -10321,14 +10875,14 @@
$isEH:true,
$is_bh:true},bl:{"":"am;NK,EZ,ut,Db,uA,b0,M2,T1,Ly,FU,jd,qN,qm,If",
gOO:function(){return"ClassMirror"},
-gWL:function(){return H.d(this.NK.gWL())+"<"+this.EZ+">"},
+gCr:function(){return H.d(this.NK.gCr())+"<"+this.EZ+">"},
"+_mangledName":0,
gNy:function(){return this.NK.gNy()},
gw8:function(){var z,y,x,w,v,u,t,s
z=this.ut
if(z!=null)return z
y=P.A(null,null)
-z=new H.Ef(y)
+z=new H.tB(y)
x=this.EZ
if(C.xB.u8(x,"<")===-1)H.bQ(x.split(","),new H.Tc(z))
else{for(w=x.length,v=0,u="",t=0;t<w;++t){s=x[t]
@@ -10344,12 +10898,6 @@
z=this.NK.ly(this)
this.jd=z
return z},
-gtx:function(){var z=this.FU
-if(z!=null)return z
-z=new H.Gj(H.Vv(this.gEO()))
-H.VM(z,[P.wv,P.RS])
-this.FU=z
-return z},
gDI:function(){var z=this.b0
if(z!=null)return z
z=new H.Gj(H.Fk(this.gEO()))
@@ -10392,12 +10940,12 @@
gc9:function(){return this.NK.gc9()},
gAY:function(){var z=this.qN
if(z!=null)return z
-z=H.Jf(this,init.metadata[J.UQ(init.typeInformation[this.NK.gWL()],0)])
+z=H.Jf(this,init.metadata[J.UQ(init.typeInformation[this.NK.gCr()],0)])
this.qN=z
return z},
F2:function(a,b,c){return this.NK.F2(a,b,c)},
"+invoke:3:0":0,
-"*invoke":[35],
+"*invoke":[37],
CI:function(a,b){return this.F2(a,b,null)},
"+invoke:2:0":0,
gHA:function(){return!1},
@@ -10407,13 +10955,14 @@
z=this.NK.MR(this)
this.qm=z
return z},
+gkw:function(){return this.NK.gkw()},
gmW:function(a){return J.UX(this.NK)},
gvd:function(){return this.NK.gvd()},
gIf:function(){return this.NK.gIf()},
$isMs:true,
-$isQF:true,
-$isX9:true,
-$isNL:true},Ef:{"":"Tp;a",
+$isej:true,
+$isL9u:true,
+$isNL:true},tB:{"":"Tp;a",
call$1:function(a){var z,y,x
z=H.BU(a,null,new H.Oo())
y=this.a
@@ -10440,7 +10989,7 @@
"+call:1:0":0,
$isEH:true,
$is_HB:true,
-$is_Dv:true},Wf:{"":"Un;WL<-,Tx<-,H8<-,Ht<-,pz<-,le@-,qN@-,jd@-,tB@-,b0@-,FU@-,T1@-,Ly@-,M2@-,uA@-,Db@-,Ok@-,qm@-,UF@-,nz@-,If",
+$is_Dv:true},Wf:{"":"Un;Cr<-,Tx<-,H8<-,Ht<-,pz<-,le@-,qN@-,jd@-,tB@-,b0@-,FU@-,T1@-,Ly@-,M2@-,uA@-,Db@-,Ok@-,qm@-,UF@-,nz@-,If",
gOO:function(){return"ClassMirror"
"8"},
"+_prettyName":1,
@@ -10449,7 +10998,7 @@
y=J.x(z)
if(typeof z==="object"&&z!==null&&!!y.$isGv)return z.constructor
else return z
-"35"},
+"37"},
"+_jsConstructor":1,
gDI:function(){var z=this.b0
if(z!=null)return z
@@ -10457,7 +11006,7 @@
H.VM(z,[P.wv,P.RS])
this.b0=z
return z
-"47"},
+"49"},
"+constructors":1,
ly:function(a){var z,y,x,w,v,u,t,s,r,q,p,o,n,m,l,k
z=this.gaB().prototype
@@ -10483,7 +11032,7 @@
if (hasOwnProperty.call(victim, key)) result.push(key);
}
return result;
-})(init.statics[this.WL], Object.prototype.hasOwnProperty)
+})(init.statics[this.Cr], Object.prototype.hasOwnProperty)
w=J.U6(y)
r=w.gB(y)
if(typeof r!=="number")throw H.s(r)
@@ -10502,14 +11051,14 @@
l=!1}s=H.Sd(k,o,!l,l)
x.push(s)
s.nz=a}return x
-"48,49,50"},
+"50,51,52"},
"+_getMethodsWithOwner:1:0":1,
gEO:function(){var z=this.jd
if(z!=null)return z
z=this.ly(this)
this.jd=z
return z
-"48"},
+"50"},
"+_methods":1,
ws:function(a){var z,y,x,w
z=[]
@@ -10520,17 +11069,17 @@
y=this.Ht
if(y!=null){x=[x]
C.Nm.Ay(x,y)}H.jw(a,x,!1,z)
-w=init.statics[this.WL]
+w=init.statics[this.Cr]
if(w!=null)H.jw(a,w[""],!0,z)
return z
-"51,52,50"},
+"53,54,52"},
"+_getFieldsWithOwner:1:0":1,
-gKn:function(){var z=this.tB
+gTH:function(){var z=this.tB
if(z!=null)return z
z=this.ws(this)
this.tB=z
return z
-"51"},
+"53"},
"+_fields":1,
gtx:function(){var z=this.FU
if(z!=null)return z
@@ -10538,26 +11087,26 @@
H.VM(z,[P.wv,P.RS])
this.FU=z
return z
-"47"},
+"49"},
"+methods":1,
gZ3:function(){var z,y,x
z=this.M2
if(z!=null)return z
y=P.L5(null,null,null,null,null)
-for(z=J.GP(this.gKn());z.G();){x=z.gl()
+for(z=J.GP(this.gTH());z.G();){x=z.gl()
y.u(y,x.gIf(),x)}z=new H.Gj(y)
H.VM(z,[P.wv,P.RY])
this.M2=z
return z
-"53"},
+"55"},
"+variables":1,
glc:function(a){var z=this.uA
if(z!=null)return z
z=new H.Gj(H.vE(this.gEO(),this.gZ3()))
-H.VM(z,[P.wv,P.QF])
+H.VM(z,[P.wv,P.ej])
this.uA=z
return z
-"54"},
+"56"},
"+members":1,
gYK:function(){var z,y
z=this.Db
@@ -10571,23 +11120,23 @@
H.VM(z,[P.wv,P.NL])
this.Db=z
return z
-"55"},
+"57"},
"+declarations":1,
PU:function(a,b){var z,y
z=J.UQ(this.gZ3(),a)
if(z!=null&&z.gFo()&&!z.gV5()){y=z.gao()
-if(!(y in $))throw H.b(H.Pa("Cannot find \""+y+"\" in current isolate."))
+if(!(y in $))throw H.b(H.Ef("Cannot find \""+y+"\" in current isolate."))
$[y]=b
return H.vn(b)}throw H.b(P.lr(this,H.X7(a),[b],null,null))
-"56,57,58,59,0"},
+"58,59,60,61,0"},
"+setField:2:0":1,
rN:function(a){var z,y
z=J.UQ(this.gZ3(),a)
if(z!=null&&z.gFo()){y=z.gao()
-if(!(y in $))throw H.b(H.Pa("Cannot find \""+y+"\" in current isolate."))
+if(!(y in $))throw H.b(H.Ef("Cannot find \""+y+"\" in current isolate."))
if(y in init.lazies)return H.vn($[init.lazies[y]]())
else return H.vn($[y])}throw H.b(P.lr(this,a,null,null,null))
-"56,57,58"},
+"58,59,60"},
"+getField:1:0":1,
gh7:function(){var z,y,x,w,v,u,t
if(this.nz==null){z=this.Tx
@@ -10606,7 +11155,7 @@
z=new H.MH(null,y,z.ew)
z.$builtinTypeInfo=[u,t]
for(;z.G();)for(y=J.GP(z.mD);y.G();)J.pP(y.gl())}if(this.nz==null)throw H.b(new P.lj("Class \""+H.d(J.Z0(this.If))+"\" has no owner"))}return this.nz
-"60"},
+"62"},
"+owner":1,
gc9:function(){var z=this.Ok
if(z!=null)return z
@@ -10615,10 +11164,10 @@
H.VM(z,[P.vr])
this.Ok=z
return z
-"61"},
+"63"},
"+metadata":1,
gAY:function(){var z,y,x,w,v,u
-if(this.qN==null){z=init.typeInformation[this.WL]
+if(this.qN==null){z=init.typeInformation[this.Cr]
if(z!=null)this.qN=H.Jf(this,init.metadata[J.UQ(z,0)])
else{y=this.H8
x=J.uH(y,";")
@@ -10627,9 +11176,9 @@
x=J.rY(w)
v=x.Fr(w,"+")
u=v.length
-if(u>1){if(u!==2)throw H.b(H.Pa("Strange mixin: "+H.d(y)))
+if(u>1){if(u!==2)throw H.b(H.Ef("Strange mixin: "+H.d(y)))
this.qN=H.jO(v[0])}else this.qN=x.n(w,"")?this:H.jO(w)}}return J.xC(this.qN,this)?null:this.qN
-"62"},
+"64"},
"+superclass":1,
F2:function(a,b,c){var z
if(c!=null&&J.FN(c)!==!0)throw H.b(P.f("Named arguments are not implemented."))
@@ -10637,33 +11186,33 @@
if(z==null||!z.gFo())throw H.b(P.lr(this,a,b,c,null))
if(!z.yR())H.Hz(J.Z0(a))
return H.vn(z.qj(b,c))
-"56,63,58,64,65,66,67"},
+"58,65,60,66,67,68,69"},
"+invoke:3:0":1,
-"*invoke":[35],
+"*invoke":[37],
CI:function(a,b){return this.F2(a,b,null)},
"+invoke:2:0":1,
gHA:function(){return!0
-"39"},
+"41"},
"+isOriginalDeclaration":1,
gJi:function(){return this
-"62"},
+"64"},
"+originalDeclaration":1,
MR:function(a){var z,y,x
-z=init.typeInformation[this.WL]
+z=init.typeInformation[this.Cr]
if(z!=null){y=new H.A8(J.Pr(z,1),new H.t0(a))
H.VM(y,[null,null])
x=y.br(y)}else x=C.Me
y=new P.Yp(x)
H.VM(y,[P.Ms])
return y
-"68,69,50"},
+"70,71,52"},
"+_getSuperinterfacesWithOwner:1:0":1,
gkZ:function(){var z=this.qm
if(z!=null)return z
z=this.MR(this)
this.qm=z
return z
-"68"},
+"70"},
"+superinterfaces":1,
gNy:function(){var z,y,x,w,v
z=this.UF
@@ -10676,34 +11225,34 @@
H.VM(z,[null])
this.UF=z
return z
-"70"},
+"72"},
"+typeVariables":1,
gw8:function(){return C.hU
-"71"},
+"73"},
"+typeArguments":1,
$isWf:true,
$isMs:true,
-$isQF:true,
-$isX9:true,
-$isNL:true},"+JsClassMirror": [72, 62],Un:{"":"EE+M2;",$isQF:true},Ei:{"":"Tp;a-",
+$isej:true,
+$isL9u:true,
+$isNL:true},"+JsClassMirror": [74, 64],Un:{"":"EE+M2;",$isej:true},Ei:{"":"Tp;a-",
call$2:function(a,b){J.kW(this.a,a,b)
-"35,73,58,28,74"},
+"37,75,60,28,76"},
"+call:2:0":1,
$isEH:true,
-$is_bh:true},"+JsClassMirror_declarations_addToResult": [75],U7:{"":"Tp;b-",
+$is_bh:true},"+JsClassMirror_declarations_addToResult": [77],U7:{"":"Tp;b-",
call$1:function(a){J.kW(this.b,a.gIf(),a)
return a
-"35,76,35"},
+"37,78,37"},
"+call:1:0":1,
$isEH:true,
$is_HB:true,
-$is_Dv:true},"+JsClassMirror_declarations_closure": [75],t0:{"":"Tp;a-",
+$is_Dv:true},"+JsClassMirror_declarations_closure": [77],t0:{"":"Tp;a-",
call$1:function(a){return H.Jf(this.a,init.metadata[a])
-"62,77,27"},
+"64,79,27"},
"+call:1:0":1,
$isEH:true,
$is_HB:true,
-$is_Dv:true},"+JsClassMirror__getSuperinterfacesWithOwner_lookupType": [75],Ld:{"":"am;ao<,V5<,Fo<,n6,nz,le,If",
+$is_Dv:true},"+JsClassMirror__getSuperinterfacesWithOwner_lookupType": [77],Ld:{"":"am;ao<,V5<,Fo<,n6,nz,le,If",
gOO:function(){return"VariableMirror"},
"+_prettyName":0,
gr9:function(a){return $.Cr()},
@@ -10718,7 +11267,7 @@
a.H7(this.ao,b)},
$isRY:true,
$isNL:true,
-$isQF:true,
+$isej:true,
static:{"":"Z8",pS:function(a,b,c,d){var z,y,x,w,v,u,t,s,r,q
z=J.U6(a)
y=z.gB(a)
@@ -10754,7 +11303,7 @@
return null;
}
(y)
-if(w==null)throw H.b(H.Pa("Cannot find callName on \""+H.d(y)+"\""))
+if(w==null)throw H.b(H.Ef("Cannot find callName on \""+H.d(y)+"\""))
v=w.split("$")
if(1>=v.length)throw H.e(v,1)
u=H.BU(v[1],null,null)
@@ -10769,14 +11318,17 @@
return x},
"+function":0,
bu:function(a){return"ClosureMirror on '"+H.d(P.hl(this.Ax))+"'"},
+"+toString:0:0":0,
+gFF:function(a){return H.vh(P.SY(null))},
+"+source":0,
$isvr:true,
-$isQF:true},Zk:{"":"am;dl,Yq,lT<,hB<,Fo<,xV<,qx,nz,le,G6,Cr,If",
+$isej:true},Zk:{"":"am;dl,Yq,lT<,hB<,Fo<,xV<,qx,nz,le,G6,H3,If",
gOO:function(){return"MethodMirror"},
"+_prettyName":0,
-gJx:function(){var z=this.Cr
+gJx:function(){var z=this.H3
if(z!=null)return z
this.gc9()
-return this.Cr},
+return this.H3},
yR:function(){return"$reflectable" in this.dl},
gh7:function(){return this.nz},
"+owner":0,
@@ -10803,13 +11355,13 @@
if(t>=w)throw H.e(x,t)
x[t]=new H.fu(this,null,p)}}y=new P.Yp(x)
H.VM(y,[P.Ys])
-this.Cr=y
+this.H3=y
y=new P.Yp(J.C0(z,H.Yf))
H.VM(y,[null])
this.le=y}return this.le},
"+metadata":0,
qj:function(a,b){if(b!=null&&J.FN(b)!==!0)throw H.b(P.f("Named arguments are not implemented."))
-if(!this.Fo&&!this.xV)throw H.b(H.Pa("Cannot invoke instance method without receiver."))
+if(!this.Fo&&!this.xV)throw H.b(H.Ef("Cannot invoke instance method without receiver."))
if(!J.xC(this.Yq,J.q8(a))||this.dl==null)throw H.b(P.lr(this.nz,this.If,a,b,null))
return this.dl.apply($,P.F(a,!0,null))},
IB:function(a){if(this.lT)return this.qj([],null)
@@ -10820,7 +11372,7 @@
$isZk:true,
$isRS:true,
$isNL:true,
-$isQF:true,
+$isej:true,
static:{Sd:function(a,b,c,d){var z,y,x,w,v,u,t
z=J.uH(a,":")
if(0>=z.length)throw H.e(z,0)
@@ -10847,15 +11399,15 @@
$isYs:true,
$isRY:true,
$isNL:true,
-$isQF:true},ng:{"":"am;WL<,CM,If",
+$isej:true},ng:{"":"am;Cr<,CM,If",
gP:function(a){return this.CM},
"+value":0,
r6:function(a,b){return this.gP(a).call$1(b)},
gOO:function(){return"TypedefMirror"},
"+_prettyName":0,
-$isX9:true,
+$isL9u:true,
$isNL:true,
-$isQF:true},Ar:{"":"a;d9,o3,yA,zM,h7<",
+$isej:true},Ar:{"":"a;d9,o3,yA,zM,h7<",
gHA:function(){return!0},
"+isOriginalDeclaration":0,
gJx:function(){var z,y,x,w,v,u,t
@@ -10899,15 +11451,16 @@
z=w+"'"
this.o3=z
return z},
+"+toString:0:0":0,
$isMs:true,
-$isQF:true,
-$isX9:true,
+$isej:true,
+$isL9u:true,
$isNL:true},jB:{"":"Tp;a",
call$1:function(a){var z,y,x
z=init.metadata[a]
y=this.a
x=H.w2(y.a.gNy(),J.DA(z))
-return J.UQ(y.a.gw8(),x).gWL()},
+return J.UQ(y.a.gw8(),x).gCr()},
"+call:1:0":0,
$isEH:true,
$is_HB:true,
@@ -10947,6 +11500,7 @@
$isL8:true,
static:{kT:function(){throw H.b(P.f("Cannot modify an unmodifiable Map"))}}},Zz:{"":"Ge;hu",
bu:function(a){return"Unsupported operation: "+this.hu},
+"+toString:0:0":0,
$ismp:true,
$isGe:true,
static:{WE:function(a){return new H.Zz(a)}}},"":"uN<"}],["dart._js_names","dart:_js_names",,H,{hY:function(a,b){var z,y,x,w,v,u,t
@@ -11084,7 +11638,7 @@
gZ9:function(){return new P.Ip(this,P.JI.prototype.LP,null,"LP")},
$asyU:null,
$asMO:null,
-static:{"":"HO,HC,fw",}},WV:{"":"a;nL<,QC<,iE@,SJ@",
+static:{"":"kb,HC,fw",}},WV:{"":"a;nL<,QC<,iE@,SJ@",
gP4:function(){return(this.Gv&2)!==0},
SL:function(){var z=this.Ip
if(z!=null)return z
@@ -11249,10 +11803,10 @@
this.au(z)
return z},
ml:function(a){return this.Rx(a,null)},
-co:function(a,b){var z=P.RP(a,b,null)
+pU:function(a,b){var z=P.RP(a,b,null)
this.au(z)
return z},
-OA:function(a){return this.co(a,null)},
+OA:function(a){return this.pU(a,null)},
wM:function(a){var z=P.X4(a,H.W8(this,"vs",0))
this.au(z)
return z},
@@ -11281,7 +11835,13 @@
P.HZ(this,z)},
Lp:function(a){return this.K5(a,null)},
gbY:function(){return new P.CQ(this,P.vs.prototype.K5,null,"K5")},
-OH:function(a){if(this.Gv!==0)H.vh(new P.lj("Future already completed"))
+OH:function(a){var z,y
+z=J.x(a)
+y=typeof a==="object"&&a!==null&&!!z.$isb8
+if(y);if(y)z=typeof a!=="object"||a===null||!z.$isvs||a.Gv<4
+else z=!1
+if(z){this.rX(a)
+return}if(this.Gv!==0)H.vh(new P.lj("Future already completed"))
this.Gv=1
this.Lj.wr(new P.rH(this,a))},
CG:function(a,b){if(this.Gv!==0)H.vh(new P.lj("Future already completed"))
@@ -11290,7 +11850,7 @@
L7:function(a,b){this.OH(a)},
$isvs:true,
$isb8:true,
-static:{"":"Gn,Ry,cp,oN,NK",Dt:function(a){var z=new P.vs(0,$.X3,null,null,null,null,null,null)
+static:{"":"Gn,JE,cp,oN,NK",Dt:function(a){var z=new P.vs(0,$.X3,null,null,null,null,null,null)
H.VM(z,[a])
return z},Ab:function(a,b){var z=new P.vs(0,$.X3,null,null,null,null,null,null)
H.VM(z,[b])
@@ -11362,7 +11922,7 @@
$is_Dv:true},dm:{"":"Tp;b",
call$2:function(a,b){this.b.K5(a,b)},
"+call:2:0":0,
-"*call":[35],
+"*call":[37],
call$1:function(a){return this.call$2(a,null)},
"+call:1:0":0,
$isEH:true,
@@ -11431,7 +11991,7 @@
if(typeof y!=="object"||y===null||!x.$isvs){z.a=P.Dt(null)
z.a.E6(a,b)}P.HZ(z.a,this.h)},
"+call:2:0":0,
-"*call":[35],
+"*call":[37],
call$1:function(a){return this.call$2(a,null)},
"+call:1:0":0,
$isEH:true,
@@ -11743,12 +12303,14 @@
SY:function(){this.ghG().w6(C.Wj)}},Gh:{"":"XB;nL<,p4<,Z9<,QC<,iP,Gv,Ip"},XB:{"":"ms+lk;",$asms:null},ly:{"":"cK;nL<,p4<,Z9<,QC<,iP,Gv,Ip"},cK:{"":"ms+vp;",$asms:null},O9:{"":"ez;Y8",
w4:function(a){return this.Y8.ET(a)},
giO:function(a){return(H.eQ(this.Y8)^892482866)>>>0},
+"+hashCode":0,
n:function(a,b){var z
if(b==null)return!1
if(this===b)return!0
z=J.x(b)
if(typeof b!=="object"||b===null||!z.$isO9)return!1
return b.Y8===this.Y8},
+"+==:1:0":0,
$isO9:true,
$asez:null,
$asqh:null},yU:{"":"KA;Y8<,dB,o7,Bd,Lj,Gv,lz,Ri",
@@ -11907,9 +12469,9 @@
return x},
fN:function(a){},
gnL:function(){return new H.Pm(this,P.ez.prototype.fN,null,"fN")},
-$asqh:null},fI:{"":"a;LD@"},LV:{"":"fI;P>,LD",
+$asqh:null},lx:{"":"a;LD@"},LV:{"":"lx;P>,LD",
r6:function(a,b){return this.P.call$1(b)},
-pP:function(a){a.Iv(this.P)}},DS:{"":"fI;kc>,I4<,LD",
+pP:function(a){a.Iv(this.P)}},DS:{"":"lx;kc>,I4<,LD",
pP:function(a){a.pb(this.kc,this.I4)}},dp:{"":"a;",
pP:function(a){a.SY()},
gLD:function(){return},
@@ -12434,6 +12996,7 @@
for(y=0;y<z;y+=2)if(this.C2(a[y],b)===!0)return y
return-1},
bu:function(a){return P.vW(this)},
+"+toString:0:0":0,
$ask6:null,
$asL8:null,
static:{MP:function(a,b,c,d,e){var z=new P.jG(d)
@@ -12606,6 +13169,7 @@
for(y=0;y<z;++y)if(J.xC(a[y].gkh(),b))return y
return-1},
bu:function(a){return P.vW(this)},
+"+toString:0:0":0,
$isFo:true,
$isL8:true},iX:{"":"Tp;a",
call$1:function(a){var z=this.a
@@ -12946,6 +13510,7 @@
z[x]=w}return z},
br:function(a){return this.tt(a,!0)},
bu:function(a){return H.mx(this,"{","}")},
+"+toString:0:0":0,
$asmW:null,
$ascX:null,
$isqC:true,
@@ -13004,6 +13569,7 @@
if(w.n(y,0))return x
y=w.W(y,1)}throw H.b(P.N(b))},
bu:function(a){return P.FO(this)},
+"+toString:0:0":0,
$iscX:true,
$ascX:null},ar:{"":"a+lD;",$isList:true,$asWO:null,$isqC:true,$iscX:true,$ascX:null},lD:{"":"a;",
gA:function(a){var z=new H.a7(a,this.gB(a),0,null)
@@ -13146,6 +13712,7 @@
z.We(a,", ")
z.KF("]")}finally{y=$.xb()
y.Rz(y,a)}return z.gvM()},
+"+toString:0:0":0,
$isList:true,
$asWO:null,
$isqC:true,
@@ -13206,6 +13773,7 @@
this.qT=this.qT+1
return!0}}return!1},
bu:function(a){return H.mx(this,"{","}")},
+"+toString:0:0":0,
Ux:function(){var z,y,x,w
if(this.av===this.HV)throw H.b(P.w("No elements"))
this.qT=this.qT+1
@@ -13408,6 +13976,7 @@
return z},
"+values":0,
bu:function(a){return P.vW(this)},
+"+toString:0:0":0,
$isBa:true,
$asXt:function(a,b){return[a]},
$asL8:null,
@@ -13531,7 +14100,7 @@
$aswI:function(){return[J.O,P.a]}},z0:{"":"ob;lH",
goc:function(a){return"utf-8"},
"+name":0,
-gZE:function(){return new P.Vx()}},Vx:{"":"wI;",
+gZE:function(){return new P.E3()}},E3:{"":"wI;",
WJ:function(a){var z,y,x
z=a.length
y=P.A(z*3,J.im)
@@ -13539,7 +14108,7 @@
x=new P.Rw(0,0,y)
if(x.fJ(a,0,z)!==z)x.Lb(C.xB.j(a,z-1),0)
return C.Nm.D6(x.EN,0,x.An)},
-$aswI:function(){return[J.O,[J.Q,J.im]]}},Rw:{"":"a;WF,An,EN",
+$aswI:function(){return[J.O,[J.Q,J.im]]}},Rw:{"":"a;vn,An,EN",
Lb:function(a,b){var z,y,x,w,v
z=this.EN
y=this.An
@@ -13616,7 +14185,80 @@
this.An=u+1
if(u<0||u>=y)throw H.e(z,u)
z[u]=(128|v&63)>>>0}}return w},
-static:{"":"Ij",}}}],["dart.core","dart:core",,P,{Te:function(a){return},Wc:function(a,b){return J.oE(a,b)},hl:function(a){var z,y,x,w,v,u
+static:{"":"Ij",}},GY:{"":"wI;lH",
+WJ:function(a){var z,y
+z=P.p9("")
+y=new P.jZ(this.lH,z,!0,0,0,0)
+y.ME(a,0,a.length)
+y.fZ()
+return z.vM},
+$aswI:function(){return[[J.Q,J.im],J.O]}},jZ:{"":"a;lH,aS,rU,Hu,iU,VN",
+cO:function(a){this.fZ()},
+fZ:function(){if(this.iU>0){if(this.lH!==!0)throw H.b(P.cD("Unfinished UTF-8 octet sequence"))
+this.aS.KF(P.fc(65533))
+this.Hu=0
+this.iU=0
+this.VN=0}},
+ME:function(a,b,c){var z,y,x,w,v,u,t,s,r,q
+z=this.Hu
+y=this.iU
+x=this.VN
+this.Hu=0
+this.iU=0
+this.VN=0
+$loop$0:for(w=this.aS,v=this.lH!==!0,u=b;!0;u=q){$multibyte$2:{if(y>0){t=a.length
+do{if(u===c)break $loop$0
+if(u<0||u>=t)throw H.e(a,u)
+s=a[u]
+if((s&192)!==128){if(v)throw H.b(P.cD("Bad UTF-8 encoding 0x"+C.jn.WZ(s,16)))
+this.rU=!1
+r=P.O8(1,65533,J.im)
+r.$builtinTypeInfo=[J.im]
+t=H.eT(r)
+w.vM=w.vM+t
+y=0
+break $multibyte$2}else{z=(z<<6|s&63)>>>0;--y;++u}}while(y>0)
+t=x-1
+if(t<0||t>=4)throw H.e(C.Gb,t)
+if(z<=C.Gb[t]){if(v)throw H.b(P.cD("Overlong encoding of 0x"+C.jn.WZ(z,16)))
+z=65533
+y=0
+x=0}if(z>1114111){if(v)throw H.b(P.cD("Character outside valid Unicode range: 0x"+C.jn.WZ(z,16)))
+z=65533}if(!this.rU||z!==65279){r=P.O8(1,z,J.im)
+r.$builtinTypeInfo=[J.im]
+t=H.eT(r)
+w.vM=w.vM+t}this.rU=!1}}for(;u<c;u=q){q=u+1
+if(u<0||u>=a.length)throw H.e(a,u)
+s=a[u]
+if(s<0){if(v)throw H.b(P.cD("Negative UTF-8 code unit: -0x"+C.jn.WZ(-s,16)))
+r=P.O8(1,65533,J.im)
+r.$builtinTypeInfo=[J.im]
+t=H.eT(r)
+w.vM=w.vM+t}else if(s<=127){this.rU=!1
+r=P.O8(1,s,J.im)
+r.$builtinTypeInfo=[J.im]
+t=H.eT(r)
+w.vM=w.vM+t}else{if((s&224)===192){z=s&31
+y=1
+x=1
+continue $loop$0}if((s&240)===224){z=s&15
+y=2
+x=2
+continue $loop$0}if((s&248)===240&&s<245){z=s&7
+y=3
+x=3
+continue $loop$0}if(v)throw H.b(P.cD("Bad UTF-8 encoding 0x"+C.jn.WZ(s,16)))
+this.rU=!1
+r=P.O8(1,65533,J.im)
+r.$builtinTypeInfo=[J.im]
+t=H.eT(r)
+w.vM=w.vM+t
+z=65533
+y=0
+x=0}}break $loop$0}if(y>0){this.Hu=z
+this.iU=y
+this.VN=x}},
+static:{"":"a3",}}}],["dart.core","dart:core",,P,{Te:function(a){return},Wc:function(a,b){return J.oE(a,b)},hl:function(a){var z,y,x,w,v,u
if(typeof a==="number"||typeof a==="boolean"||null==a)return J.AG(a)
if(typeof a==="string"){z=new P.Rn("")
z.vM="\""
@@ -13676,16 +14318,20 @@
"+call:2:0":0,
$isEH:true,
$is_bh:true},K8:{"":"a;OF",
-bu:function(a){return"Deprecated feature. Will be removed "+this.OF}},a2:{"":"a;",
+bu:function(a){return"Deprecated feature. Will be removed "+this.OF},
+"+toString:0:0":0},a2:{"":"a;",
bu:function(a){return this?"true":"false"},
+"+toString:0:0":0,
$isbool:true},fR:{"":"a;"},iP:{"":"a;rq<,aL",
n:function(a,b){var z
if(b==null)return!1
z=J.x(b)
if(typeof b!=="object"||b===null||!z.$isiP)return!1
return this.rq===b.rq&&this.aL===b.aL},
+"+==:1:0":0,
iM:function(a,b){return C.CD.iM(this.rq,b.grq())},
giO:function(a){return this.rq},
+"+hashCode":0,
bu:function(a){var z,y,x,w,v,u,t,s
z=new P.pl()
y=new P.Hn().call$1(H.tJ(this))
@@ -13697,11 +14343,12 @@
s=new P.Zl().call$1(H.o1(this))
if(this.aL)return H.d(y)+"-"+H.d(x)+"-"+H.d(w)+" "+H.d(v)+":"+H.d(u)+":"+H.d(t)+"."+H.d(s)+"Z"
else return H.d(y)+"-"+H.d(x)+"-"+H.d(w)+" "+H.d(v)+":"+H.d(u)+":"+H.d(t)+"."+H.d(s)},
+"+toString:0:0":0,
h:function(a,b){return P.Wu(this.rq+b.gVs(),this.aL)},
EK:function(){H.U8(this)},
RM:function(a,b){if(Math.abs(a)>8640000000000000)throw H.b(new P.AT(a))},
$isiP:true,
-static:{"":"Oj,bI,df,yM,h2,JE,nm,DU,H9,EN,k3,cR,E0,Ke,lT,Nr,bm,o4,Kz,J7,TO,I2",Gl:function(a){var z,y,x,w,v,u,t,s,r,q,p,o,n
+static:{"":"Oj,bI,df,yM,h2,OK,nm,DU,H9,Gio,k3,cR,E0,Ke,lT,Nr,bm,o4,Kz,J7,TO,I2",Gl:function(a){var z,y,x,w,v,u,t,s,r,q,p,o,n
z=new H.VR(H.v4("^([+-]?\\d?\\d\\d\\d\\d)-?(\\d\\d)-?(\\d\\d)(?:[ T](\\d\\d)(?::?(\\d\\d)(?::?(\\d\\d)(.\\d{1,6})?)?)?( ?[zZ]| ?\\+00(?::?00)?)?)?$",!1,!0,!1),null,null).ej(a)
if(z!=null){y=new P.MF()
x=z.oH
@@ -13781,7 +14428,9 @@
z=J.x(b)
if(typeof b!=="object"||b===null||!z.$isa6)return!1
return this.Fq===b.Fq},
+"+==:1:0":0,
giO:function(a){return this.Fq&0x1FFFFFFF},
+"+hashCode":0,
iM:function(a,b){return C.CD.iM(this.Fq,b.gFq())},
bu:function(a){var z,y,x,w,v
z=new P.DW()
@@ -13791,6 +14440,7 @@
w=z.call$1(C.CD.JV(C.CD.Z(y,1000000),60))
v=new P.P7().call$1(C.CD.JV(y,1000000))
return H.d(C.CD.Z(y,3600000000))+":"+H.d(x)+":"+H.d(w)+"."+H.d(v)},
+"+toString:0:0":0,
$isa6:true,
static:{"":"Bp,S4,dk,Lo,RD,b2,q9,Ie,Do,f4,vd,IJ,V6,Vk,fm,rG",k5:function(a,b,c,d,e,f){return new P.a6(a*86400000000+b*3600000000+e*60000000+f*1000000+d*1000+c)}}},P7:{"":"Tp;",
call$1:function(a){var z=J.Wx(a)
@@ -13812,12 +14462,15 @@
$is_Dv:true},Ge:{"":"a;",
gI4:function(){return new H.XO(this.$thrownJsError,null)},
$isGe:true},LK:{"":"Ge;",
-bu:function(a){return"Throw of null."}},AT:{"":"Ge;G1>",
+bu:function(a){return"Throw of null."},
+"+toString:0:0":0},AT:{"":"Ge;G1>",
bu:function(a){var z=this.G1
if(z!=null)return"Illegal argument(s): "+H.d(z)
return"Illegal argument(s)"},
+"+toString:0:0":0,
static:{u:function(a){return new P.AT(a)}}},bJ:{"":"AT;G1",
bu:function(a){return"RangeError: "+H.d(this.G1)},
+"+toString:0:0":0,
static:{C3:function(a){return new P.bJ(a)},N:function(a){return new P.bJ("value "+H.d(a))},"+new RangeError$value:1:0":0,TE:function(a,b,c){return new P.bJ("value "+H.d(a)+" not in range "+H.d(b)+".."+H.d(c))}}},mp:{"":"Ge;uF,UP,mP,SA,vG",
bu:function(a){var z,y,x,w,v,u
z={}
@@ -13837,33 +14490,43 @@
z.b=z.b+1}}y=this.SA
if(y!=null)J.kH(y,new P.CL(z))
return"NoSuchMethodError : method not found: '"+H.d(this.UP)+"'\nReceiver: "+H.d(P.hl(this.uF))+"\nArguments: ["+H.d(z.a)+"]"},
+"+toString:0:0":0,
$ismp:true,
static:{lr:function(a,b,c,d,e){return new P.mp(a,b,c,d,e)}}},ub:{"":"Ge;G1>",
bu:function(a){return"Unsupported operation: "+this.G1},
+"+toString:0:0":0,
$isub:true,
static:{f:function(a){return new P.ub(a)}}},ds:{"":"Ge;G1>",
bu:function(a){var z=this.G1
return z!=null?"UnimplementedError: "+H.d(z):"UnimplementedError"},
+"+toString:0:0":0,
$isub:true,
$isGe:true,
static:{SY:function(a){return new P.ds(a)}}},lj:{"":"Ge;G1>",
bu:function(a){return"Bad state: "+this.G1},
+"+toString:0:0":0,
static:{w:function(a){return new P.lj(a)}}},UV:{"":"Ge;YA",
bu:function(a){var z=this.YA
if(z==null)return"Concurrent modification during iteration."
return"Concurrent modification during iteration: "+H.d(P.hl(z))+"."},
+"+toString:0:0":0,
static:{a4:function(a){return new P.UV(a)}}},VS:{"":"a;",
bu:function(a){return"Stack Overflow"},
+"+toString:0:0":0,
gI4:function(){return},
$isGe:true},t7:{"":"Ge;Wo",
bu:function(a){return"Reading static variable '"+this.Wo+"' during its initialization"},
+"+toString:0:0":0,
static:{Gz:function(a){return new P.t7(a)}}},HG:{"":"a;G1>",
bu:function(a){var z=this.G1
if(z==null)return"Exception"
-return"Exception: "+H.d(z)}},aE:{"":"a;G1>",
+return"Exception: "+H.d(z)},
+"+toString:0:0":0},aE:{"":"a;G1>",
bu:function(a){return"FormatException: "+H.d(this.G1)},
+"+toString:0:0":0,
static:{cD:function(a){return new P.aE(a)}}},kM:{"":"a;oc>",
bu:function(a){return"Expando:"+this.oc},
+"+toString:0:0":0,
t:function(a,b){var z=H.of(b,"expando$values")
return z==null?null:H.of(z,this.Qz())},
"+[]:1:0":0,
@@ -13877,11 +14540,15 @@
$.Ss=y+1
z="expando$key$"+y
H.aw(this,"expando$key",z)}return z},
-static:{"":"bZ,rt,Ss",}},EH:{"":"a;",$isEH:true},cX:{"":"a;",$iscX:true,$ascX:null},Fl:{"":"a;"},L8:{"":"a;",$isL8:true},c8:{"":"a;",
-bu:function(a){return"null"}},a:{"":";",
+static:{"":"bZ,rt,Ss",}},EH:{"":"a;",$isEH:true},cX:{"":"a;",$iscX:true,$ascX:null},eL:{"":"a;"},L8:{"":"a;",$isL8:true},c8:{"":"a;",
+bu:function(a){return"null"},
+"+toString:0:0":0},a:{"":";",
n:function(a,b){return this===b},
+"+==:1:0":0,
giO:function(a){return H.eQ(this)},
+"+hashCode":0,
bu:function(a){return H.a5(this)},
+"+toString:0:0":0,
T:function(a,b){throw H.b(P.lr(this,b.gWa(),b.gnd(),b.gVm(),null))},
"+noSuchMethod:1:0":0,
gbx:function(a){return new H.cu(H.dJ(this),null)},
@@ -13924,6 +14591,7 @@
y=typeof y==="string"?y:H.d(y)
this.vM=this.vM+y}}},
bu:function(a){return this.vM},
+"+toString:0:0":0,
PD:function(a){if(typeof a==="string")this.vM=a
else this.KF(a)},
static:{p9:function(a){var z=new P.Rn("")
@@ -13940,6 +14608,9 @@
if(y.n(z,"https"))return 443}return this.HC},
gIi:function(a){return this.r0},
Ja:function(a,b){return this.tP.call$1(b)},
+ghY:function(){if(this.yW==null){var z=new P.dD(P.Ak(this.tP,C.dy))
+H.VM(z,[null,null])
+this.yW=z}return this.yW},
x6:function(a,b){var z,y
z=a==null
if(z&&!0)return""
@@ -14004,20 +14675,23 @@
z.KF(y)}y=this.BJ
if(""!==y){z.KF("#")
z.KF(y)}return z.vM},
+"+toString:0:0":0,
n:function(a,b){var z
if(b==null)return!1
z=J.RE(b)
if(typeof b!=="object"||b===null||!z.$isiD)return!1
return J.xC(this.Fi,b.Fi)&&J.xC(this.iV,b.iV)&&J.xC(this.gJf(this),z.gJf(b))&&J.xC(this.gGL(this),z.gGL(b))&&J.xC(this.r0,b.r0)&&J.xC(this.tP,b.tP)&&J.xC(this.BJ,b.BJ)},
+"+==:1:0":0,
giO:function(a){var z=new P.XZ()
return z.call$2(this.Fi,z.call$2(this.iV,z.call$2(this.gJf(this),z.call$2(this.gGL(this),z.call$2(this.r0,z.call$2(this.tP,z.call$2(this.BJ,1)))))))},
+"+hashCode":0,
n3:function(a,b,c,d,e,f,g,h,i){var z=J.x(h)
if(z.n(h,"http")&&J.xC(e,80))this.HC=0
else if(z.n(h,"https")&&J.xC(e,443))this.HC=0
else this.HC=e
this.r0=this.x6(c,d)},
$isiD:true,
-static:{"":"Um,B4,Bx,iR,LM,iI,nR,jJ,d2,q7,ux,vI,il,tC,IL,Q5,vl,yt,fC,O5,eq,qf,Tx,y3,Cn,R1,oe,vT,K7,nL,H5,zst,eK,bf,Sp,nU,uj,SQ,SD",r6:function(a){var z,y,x,w,v,u,t,s
+static:{"":"Um,B4,Bx,iR,LM,iI,nR,jJ,d2,q7,ux,vI,bL,tC,IL,Q5,zk,om,fC,O5,eq,qf,Tx,y3,Cn,R1,oe,vT,K7,nL,H5,zst,eK,bf,nc,nU,uj,SQ,SD",r6:function(a){var z,y,x,w,v,u,t,s
z=a.oH
if(1>=z.length)throw H.e(z,1)
y=z[1]
@@ -14132,7 +14806,7 @@
return J.AG(z)},n7:function(a){if(a!=null&&!J.xC(a,""))return H.BU(a,null,null)
else return 0},K6:function(a,b){if(a!=null)return a
if(b!=null)return b
-return""},q5:function(a){var z,y
+return""},Ak:function(a,b){return H.n3(J.uH(a,"&"),H.B7([],P.L5(null,null,null,null,null)),new P.qz(b))},q5:function(a){var z,y
z=new P.hQ()
y=a.split(".")
if(y.length!==4)z.call$1("IPv4 address should contain exactly 4 parts")
@@ -14160,11 +14834,11 @@
if(r&&!q)z.call$1("expected a part after last `:`")
if(!r)try{J.bi(x,y.call$2(w,J.q8(a)))}catch(p){H.Ru(p)
try{v=P.q5(J.ZZ(a,w))
-s=J.Eh(J.UQ(v,0),8)
+s=J.c1(J.UQ(v,0),8)
o=J.UQ(v,1)
if(typeof o!=="number")throw H.s(o)
J.bi(x,(s|o)>>>0)
-o=J.Eh(J.UQ(v,2),8)
+o=J.c1(J.UQ(v,2),8)
s=J.UQ(v,3)
if(typeof s!=="number")throw H.s(s)
J.bi(x,(o|s)>>>0)}catch(p){H.Ru(p)
@@ -14197,7 +14871,36 @@
v=C.Nm.gA(C.dy.gZE().WJ(v))
for(;v.G();){t=z.call$1(v.mD)
t=typeof t==="string"?t:H.d(t)
-y.vM=y.vM+t}}++w}return y.vM}}},hb:{"":"Tp;",
+y.vM=y.vM+t}}++w}return y.vM},oh:function(a,b){var z,y,x,w
+for(z=J.rY(a),y=0,x=0;x<2;++x){w=z.j(a,b+x)
+if(48<=w&&w<=57)y=y*16+w-48
+else{w=(w|32)>>>0
+if(97<=w&&w<=102)y=y*16+w-87
+else throw H.b(new P.AT("Invalid URL encoding"))}}return y},pE:function(a,b,c){var z,y,x,w,v,u,t,s
+z=P.p9("")
+y=P.A(null,J.im)
+H.VM(y,[J.im])
+x=J.U6(a)
+w=b.lH
+v=0
+while(!0){u=x.gB(a)
+if(typeof u!=="number")throw H.s(u)
+if(!(v<u))break
+t=x.j(a,v)
+if(t!==37){if(c&&t===43)z.vM=z.vM+" "
+else{s=P.O8(1,t,J.im)
+s.$builtinTypeInfo=[J.im]
+u=H.eT(s)
+z.vM=z.vM+u}++v}else{C.Nm.sB(y,0)
+for(;t===37;){++v
+u=J.xH(x.gB(a),2)
+if(typeof u!=="number")throw H.s(u)
+if(v>u)throw H.b(new P.AT("Truncated URI"))
+y.push(P.oh(a,v))
+v+=2
+if(v===x.gB(a))break
+t=x.j(a,v)}u=new P.GY(w).WJ(y)
+z.vM=z.vM+u}}return z.vM}}},hb:{"":"Tp;",
call$1:function(a){var z,y
z=J.Wx(a)
if(z.C(a,128)){y=z.m(a,4)
@@ -14292,6 +14995,16 @@
call$2:function(a,b){return J.mQ(J.WB(J.p0(b,31),J.v1(a)),1073741823)},
"+call:2:0":0,
$isEH:true,
+$is_bh:true},qz:{"":"Tp;a",
+call$2:function(a,b){var z,y,x,w
+z=J.U6(b)
+y=z.u8(b,"=")
+if(y===-1){if(!z.n(b,""))J.kW(a,P.pE(b,this.a,!0),"")}else if(y!==0){x=z.JT(b,0,y)
+w=z.yn(b,y+1)
+z=this.a
+J.kW(a,P.pE(x,z,!0),P.pE(w,z,!0))}return a},
+"+call:2:0":0,
+$isEH:true,
$is_bh:true},hQ:{"":"Tp;",
call$1:function(a){throw H.b(P.cD("Illegal IPv4 address, "+H.d(a)))},
"+call:1:0":0,
@@ -14339,7 +15052,28 @@
"+call:1:0":0,
$isEH:true,
$is_HB:true,
-$is_Dv:true}}],["dart.dom.html","dart:html",,W,{lq:function(){return window
+$is_Dv:true},dD:{"":"a;iY",
+PF:function(a){return this.iY.PF(a)},
+"+containsValue:1:0":0,
+x4:function(a){return this.iY.x4(a)},
+"+containsKey:1:0":0,
+t:function(a,b){return J.UQ(this.iY,b)},
+"+[]:1:0":0,
+u:function(a,b,c){throw H.b(P.f("Cannot modify an unmodifiable map"))},
+"+[]=:2:0":0,
+Rz:function(a,b){throw H.b(P.f("Cannot modify an unmodifiable map"))},
+aN:function(a,b){return J.kH(this.iY,b)},
+gvc:function(a){return J.iY(this.iY)},
+"+keys":0,
+gUQ:function(a){return J.hI(this.iY)},
+"+values":0,
+gB:function(a){return J.q8(this.iY)},
+"+length":0,
+gl0:function(a){return J.FN(this.iY)},
+"+isEmpty":0,
+gor:function(a){return J.pO(this.iY)},
+"+isNotEmpty":0,
+$isL8:true}}],["dart.dom.html","dart:html",,W,{lq:function(){return window
"12"},"+window":1,UE:function(a){if(P.F7()===!0)return"webkitTransitionEnd"
else if(P.dg()===!0)return"oTransitionEnd"
return"transitionend"},r3:function(a,b){return document.createElement(a)},It:function(a,b,c){return W.lt(a,null,null,b,null,null,null,c).ml(new W.Kx())},lt:function(a,b,c,d,e,f,g,h){var z,y,x,w
@@ -14347,7 +15081,7 @@
y=new P.Zf(P.Dt(z))
H.VM(y,[z])
x=new XMLHttpRequest()
-C.W3.xI(x,"GET",a,!0)
+C.W3.i3(x,"GET",a,!0)
z=C.fK.aM(x)
w=new W.Ov(0,z.uv,z.Ph,W.aF(new W.bU(y,x)),z.Sg)
H.VM(w,[H.W8(z,"RO",0)])
@@ -14372,7 +15106,7 @@
if("setInterval" in a){z=W.P1(a)
y=J.x(z)
if(typeof z==="object"&&z!==null&&!!y.$isD0)return z
-return}else return a},m7:function(a){return a},YT:function(a,b){return new W.vZ(a,b)},GO:function(a){return J.TD(a)},Yb:function(a){return J.W7(a)},Qp:function(a,b,c,d){return J.qd(a,b,c,d)},wi:function(a,b,c,d,e){var z,y,x,w,v,u,t,s,r,q
+return}else return a},m7:function(a){return a},YT:function(a,b){return new W.uY(a,b)},GO:function(a){return J.TD(a)},Yb:function(a){return J.W7(a)},Qp:function(a,b,c,d){return J.qd(a,b,c,d)},wi:function(a,b,c,d,e){var z,y,x,w,v,u,t,s,r,q
z=J.Fb(d)
if(z==null)throw H.b(new P.AT(d))
y=z.prototype
@@ -14411,24 +15145,29 @@
q={prototype: s}
if(!J.xC(w,"HTMLElement"))if(!v)q.extends=e
b.register(c,q)},aF:function(a){if(J.xC($.X3,C.NU))return a
-return $.X3.oj(a,!0)},qE:{"":"cv;","%":"HTMLAppletElement|HTMLBRElement|HTMLBaseFontElement|HTMLBodyElement|HTMLCanvasElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDetailsElement|HTMLDialogElement|HTMLDirectoryElement|HTMLDivElement|HTMLFontElement|HTMLFrameElement|HTMLFrameSetElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLMarqueeElement|HTMLMenuElement|HTMLModElement|HTMLOptGroupElement|HTMLParagraphElement|HTMLPreElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement|HTMLTableRowElement|HTMLTableSectionElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement;Tt|GN|ir|Xf|uL|Vf|aC|tu|Be|Vc|i6|WZ|Fv|pv|I3|Vfx|Gk|Dsd|Ds|u7|tuj|St|Vct|vj|D13|CX|Nh|ih|F1|XP|NQ|WZq|uw"},Yy:{"":"Gv;",$isList:true,
+return $.X3.oj(a,!0)},qE:{"":"cv;","%":"HTMLAppletElement|HTMLBRElement|HTMLBaseFontElement|HTMLBodyElement|HTMLCanvasElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDetailsElement|HTMLDialogElement|HTMLDirectoryElement|HTMLDivElement|HTMLFontElement|HTMLFrameElement|HTMLFrameSetElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLMarqueeElement|HTMLMenuElement|HTMLModElement|HTMLOptGroupElement|HTMLParagraphElement|HTMLPreElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement|HTMLTableRowElement|HTMLTableSectionElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement;Tt|GN|ir|Xf|uL|Vf|aC|tu|Be|Vc|i6|WZ|Fv|pv|I3|Vfx|Gk|Dsd|Ds|u7|tuj|St|Vct|vj|D13|CX|BK|ih|F1|XP|NQ|WZq|fI|pva|kK|cda|uw"},Yy:{"":"Gv;",$isList:true,
$asWO:function(){return[W.M5]},
$isqC:true,
$iscX:true,
$ascX:function(){return[W.M5]},
"%":"EntryArray"},Ps:{"":"qE;cC:hash%,LU:href=,N:target=,r9:type%",
bu:function(a){return a.toString()},
-"%":"HTMLAnchorElement"},fY:{"":"qE;cC:hash=,LU:href=,N:target=","%":"HTMLAreaElement"},nB:{"":"qE;LU:href=,N:target=","%":"HTMLBaseElement"},Az:{"":"Gv;r9:type=",$isAz:true,"%":";Blob"},QW:{"":"qE;MB:form=,oc:name%,r9:type%,P:value%",
+"+toString:0:0":0,
+"%":"HTMLAnchorElement"},fY:{"":"qE;cC:hash=,LU:href=,N:target=","%":"HTMLAreaElement"},nB:{"":"qE;LU:href=,N:target=","%":"HTMLBaseElement"},i3:{"":"ea;O3:url=","%":"BeforeLoadEvent"},Az:{"":"Gv;r9:type=",$isAz:true,"%":";Blob"},QW:{"":"qE;MB:form=,oc:name%,r9:type%,P:value%",
r6:function(a,b){return this.value.call$1(b)},
"%":"HTMLButtonElement"},OM:{"":"KV;B:length=",$isGv:true,"%":"Comment;CharacterData"},QQ:{"":"ea;tT:code=","%":"CloseEvent"},oJ:{"":"BV;B:length=",
T2:function(a,b){var z=a.getPropertyValue(b)
return z!=null?z:""},
+hV:function(a,b,c,d){var z
+try{if(d==null)d=""
+a.setProperty(b,c,d)
+if(!!a.setAttribute)a.setAttribute(b,c)}catch(z){H.Ru(z)}},
"%":"CSS2Properties|CSSStyleDeclaration|MSStyleCSSProperties"},DG:{"":"ea;",
gey:function(a){var z=a._dartDetail
if(z!=null)return z
return P.o7(a.detail,!0)},
$isDG:true,
-"%":"CustomEvent"},YN:{"":"KV;",
+"%":"CustomEvent"},QF:{"":"KV;",
JP:function(a){return a.createDocumentFragment()},
Kb:function(a,b){return a.getElementById(b)},
gEr:function(a){return C.mt.aM(a)},
@@ -14437,19 +15176,21 @@
Md:function(a,b){return W.vD(a.querySelectorAll(b),null)},
Ja:function(a,b){return a.querySelector(b)},
pr:function(a,b){return W.vD(a.querySelectorAll(b),null)},
-$isYN:true,
+$isQF:true,
"%":"Document|HTMLDocument|SVGDocument"},bA:{"":"KV;",
Md:function(a,b){return W.vD(a.querySelectorAll(b),null)},
Ja:function(a,b){return a.querySelector(b)},
pr:function(a,b){return W.vD(a.querySelectorAll(b),null)},
$isGv:true,
-"%":";DocumentFragment"},Wq:{"":"KV;",$isGv:true,"%":"DocumentType"},rz:{"":"Gv;G1:message=,oc:name=","%":";DOMError"},BK:{"":"Gv;G1:message=",
+"%":";DocumentFragment"},Wq:{"":"KV;",$isGv:true,"%":"DocumentType"},rz:{"":"Gv;G1:message=,oc:name=","%":";DOMError"},Nh:{"":"Gv;G1:message=",
goc:function(a){var z=a.name
if(P.F7()===!0&&z==="SECURITY_ERR")return"SecurityError"
if(P.F7()===!0&&z==="SYNTAX_ERR")return"SyntaxError"
return z},
"+name":0,
bu:function(a){return a.toString()},
+"+toString:0:0":0,
+$isNh:true,
"%":"DOMException"},cv:{"":"KV;xr:className%,jO:id%",
gQg:function(a){return new W.E9(a)},
Md:function(a,b){return W.vD(a.querySelectorAll(b),null)},
@@ -14463,6 +15204,7 @@
aC:function(a,b,c,d){},
gjU:function(a){return a.localName},
bu:function(a){return a.localName},
+"+toString:0:0":0,
WO:function(a,b){if(!!a.matches)return a.matches(b)
else if(!!a.webkitMatchesSelector)return a.webkitMatchesSelector(b)
else if(!!a.mozMatchesSelector)return a.mozMatchesSelector(b)
@@ -14482,10 +15224,10 @@
ZL:function(a){},
$iscv:true,
$isGv:true,
-"%":";Element"},Fs:{"":"qE;oc:name%,LA:src=,r9:type%","%":"HTMLEmbedElement"},SX:{"":"ea;kc:error=,G1:message=","%":"ErrorEvent"},ea:{"":"Gv;It:_selector},Xt:bubbles=,Ii:path=,r9:type=",
+"%":";Element"},Fs:{"":"qE;oc:name%,LA:src%,r9:type%","%":"HTMLEmbedElement"},SX:{"":"ea;kc:error=,G1:message=","%":"ErrorEvent"},ea:{"":"Gv;It:_selector},Xt:bubbles=,Ii:path=,r9:type=",
gN:function(a){return W.bt(a.target)},
$isea:true,
-"%":"AudioProcessingEvent|AutocompleteErrorEvent|BeforeLoadEvent|BeforeUnloadEvent|CSSFontFaceLoadEvent|DeviceMotionEvent|DeviceOrientationEvent|HashChangeEvent|IDBVersionChangeEvent|MIDIConnectionEvent|MIDIMessageEvent|MediaKeyNeededEvent|MediaStreamEvent|MediaStreamTrackEvent|MessageEvent|MutationEvent|OfflineAudioCompletionEvent|OverflowEvent|PageTransitionEvent|PopStateEvent|RTCDTMFToneChangeEvent|RTCDataChannelEvent|RTCIceCandidateEvent|SecurityPolicyViolationEvent|SpeechInputEvent|SpeechRecognitionEvent|TrackEvent|WebGLContextEvent|WebKitAnimationEvent;Event"},D0:{"":"Gv;",
+"%":"AudioProcessingEvent|AutocompleteErrorEvent|BeforeUnloadEvent|CSSFontFaceLoadEvent|DeviceMotionEvent|DeviceOrientationEvent|HashChangeEvent|IDBVersionChangeEvent|MIDIConnectionEvent|MIDIMessageEvent|MediaKeyNeededEvent|MediaStreamEvent|MediaStreamTrackEvent|MutationEvent|OfflineAudioCompletionEvent|OverflowEvent|PageTransitionEvent|PopStateEvent|RTCDTMFToneChangeEvent|RTCDataChannelEvent|RTCIceCandidateEvent|SecurityPolicyViolationEvent|SpeechInputEvent|SpeechRecognitionEvent|TrackEvent|WebGLContextEvent|WebKitAnimationEvent;Event"},D0:{"":"Gv;",
gI:function(a){return new W.Jn(a)},
On:function(a,b,c,d){return a.addEventListener(b,H.tR(c,1),d)},
Y9:function(a,b,c,d){return a.removeEventListener(b,H.tR(c,1),d)},
@@ -14514,12 +15256,12 @@
$isXj:true,
"%":"HTMLCollection|HTMLFormControlsCollection|HTMLOptionsCollection"},fJ:{"":"Vi;iC:responseText=,ys:status=,po:statusText=",
R3:function(a,b,c,d,e,f){return a.open(b,c,d,f,e)},
-xI:function(a,b,c,d){return a.open(b,c,d)},
+i3:function(a,b,c,d){return a.open(b,c,d)},
wR:function(a,b){return a.send(b)},
$isfJ:true,
-"%":"XMLHttpRequest"},Vi:{"":"D0;","%":";XMLHttpRequestEventTarget"},tX:{"":"qE;oc:name%,LA:src=","%":"HTMLIFrameElement"},Sg:{"":"Gv;",$isSg:true,"%":"ImageData"},pA:{"":"qE;LA:src=",
+"%":"XMLHttpRequest"},Vi:{"":"D0;","%":";XMLHttpRequestEventTarget"},tX:{"":"qE;oc:name%,LA:src%","%":"HTMLIFrameElement"},Sg:{"":"Gv;",$isSg:true,"%":"ImageData"},pA:{"":"qE;LA:src%",
tZ:function(a){return this.complete.call$0()},
-"%":"HTMLImageElement"},Mi:{"":"qE;Tq:checked%,MB:form=,qC:list=,oc:name%,LA:src=,r9:type%,P:value%",
+"%":"HTMLImageElement"},Mi:{"":"qE;Tq:checked%,MB:form=,qC:list=,oc:name%,LA:src%,r9:type%,P:value%",
RR:function(a,b){return this.accept.call$1(b)},
r6:function(a,b){return this.value.call$1(b)},
$isMi:true,
@@ -14531,10 +15273,14 @@
r6:function(a,b){return this.value.call$1(b)},
"%":"HTMLLIElement"},eP:{"":"qE;MB:form=","%":"HTMLLabelElement"},AL:{"":"qE;MB:form=","%":"HTMLLegendElement"},Og:{"":"qE;LU:href=,r9:type%",$isOg:true,"%":"HTMLLinkElement"},cS:{"":"Gv;cC:hash%,LU:href=",
bu:function(a){return a.toString()},
+"+toString:0:0":0,
$iscS:true,
-"%":"Location"},M6:{"":"qE;oc:name%","%":"HTMLMapElement"},El:{"":"qE;kc:error=,LA:src=",
+"%":"Location"},M6:{"":"qE;oc:name%","%":"HTMLMapElement"},El:{"":"qE;kc:error=,LA:src%",
yy:function(a){return a.pause()},
-"%":"HTMLAudioElement|HTMLMediaElement|HTMLVideoElement"},zm:{"":"Gv;tT:code=","%":"MediaError"},SV:{"":"Gv;tT:code=","%":"MediaKeyError"},aB:{"":"ea;G1:message=","%":"MediaKeyEvent"},ku:{"":"ea;G1:message=","%":"MediaKeyMessageEvent"},cW:{"":"D0;jO:id=","%":"MediaStream"},la:{"":"qE;jb:content=,oc:name%","%":"HTMLMetaElement"},Vn:{"":"qE;P:value%",
+"%":"HTMLAudioElement|HTMLMediaElement|HTMLVideoElement"},zm:{"":"Gv;tT:code=","%":"MediaError"},SV:{"":"Gv;tT:code=","%":"MediaKeyError"},aB:{"":"ea;G1:message=","%":"MediaKeyEvent"},ku:{"":"ea;G1:message=","%":"MediaKeyMessageEvent"},cW:{"":"D0;jO:id=","%":"MediaStream"},cx:{"":"ea;",
+gFF:function(a){return W.bt(a.source)},
+"+source":0,
+"%":"MessageEvent"},la:{"":"qE;jb:content=,oc:name%","%":"HTMLMetaElement"},Vn:{"":"qE;P:value%",
r6:function(a,b){return this.value.call$1(b)},
"%":"HTMLMeterElement"},bn:{"":"Im;",
LV:function(a,b,c){return a.send(b,c)},
@@ -14549,6 +15295,7 @@
if(z!=null)z.removeChild(a)},
bu:function(a){var z=a.nodeValue
return z==null?J.Gv.prototype.bu.call(this,a):z},
+"+toString:0:0":0,
jx:function(a,b){return a.appendChild(b)},
Yv:function(a,b){return a.cloneNode(b)},
tg:function(a,b){return a.contains(b)},
@@ -14585,17 +15332,17 @@
r6:function(a,b){return this.value.call$1(b)},
"%":"HTMLParamElement"},p3:{"":"Gv;tT:code=,G1:message=","%":"PositionError"},qW:{"":"OM;N:target=","%":"ProcessingInstruction"},KR:{"":"qE;P:value%",
r6:function(a,b){return this.value.call$1(b)},
-"%":"HTMLProgressElement"},ew:{"":"ea;",$isew:true,"%":"ProgressEvent|ResourceProgressEvent|XMLHttpRequestProgressEvent"},j2:{"":"qE;LA:src=,r9:type%",$isj2:true,"%":"HTMLScriptElement"},lp:{"":"qE;MB:form=,B:length%,oc:name%,ig:selectedIndex%,r9:type=,P:value%",
+"%":"HTMLProgressElement"},ew:{"":"ea;",$isew:true,"%":"XMLHttpRequestProgressEvent;ProgressEvent"},bX:{"":"ew;O3:url=","%":"ResourceProgressEvent"},j2:{"":"qE;LA:src%,r9:type%",$isj2:true,"%":"HTMLScriptElement"},lp:{"":"qE;MB:form=,B:length%,oc:name%,ig:selectedIndex%,r9:type=,P:value%",
r6:function(a,b){return this.value.call$1(b)},
$islp:true,
"%":"HTMLSelectElement"},I0:{"":"bA;pQ:applyAuthorStyles=",
Yv:function(a,b){return a.cloneNode(b)},
Kb:function(a,b){return a.getElementById(b)},
$isI0:true,
-"%":"ShadowRoot"},QR:{"":"qE;LA:src=,r9:type%","%":"HTMLSourceElement"},zD:{"":"ea;kc:error=,G1:message=","%":"SpeechRecognitionError"},G0:{"":"ea;oc:name=","%":"SpeechSynthesisEvent"},wb:{"":"ea;G3:key=,zZ:newValue=,jL:oldValue=","%":"StorageEvent"},fq:{"":"qE;r9:type%","%":"HTMLStyleElement"},yY:{"":"qE;jb:content=",$isyY:true,"%":"HTMLTemplateElement"},kJ:{"":"OM;",$iskJ:true,"%":"CDATASection|Text"},AE:{"":"qE;MB:form=,oc:name%,r9:type=,P:value%",
+"%":"ShadowRoot"},QR:{"":"qE;LA:src%,r9:type%","%":"HTMLSourceElement"},zD:{"":"ea;kc:error=,G1:message=","%":"SpeechRecognitionError"},G0:{"":"ea;oc:name=","%":"SpeechSynthesisEvent"},wb:{"":"ea;G3:key=,zZ:newValue=,jL:oldValue=,O3:url=","%":"StorageEvent"},fq:{"":"qE;r9:type%","%":"HTMLStyleElement"},yY:{"":"qE;jb:content=",$isyY:true,"%":"HTMLTemplateElement"},kJ:{"":"OM;",$iskJ:true,"%":"CDATASection|Text"},AE:{"":"qE;MB:form=,oc:name%,r9:type=,P:value%",
r6:function(a,b){return this.value.call$1(b)},
$isAE:true,
-"%":"HTMLTextAreaElement"},RH:{"":"qE;fY:kind=,LA:src=","%":"HTMLTrackElement"},Lq:{"":"ea;",$isLq:true,"%":"TransitionEvent|WebKitTransitionEvent"},Mf:{"":"ea;","%":"CompositionEvent|FocusEvent|SVGZoomEvent|TextEvent|TouchEvent;UIEvent"},K5:{"":"D0;oc:name%,ys:status=",
+"%":"HTMLTextAreaElement"},RH:{"":"qE;fY:kind%,LA:src%","%":"HTMLTrackElement"},Lq:{"":"ea;",$isLq:true,"%":"TransitionEvent|WebKitTransitionEvent"},Mf:{"":"ea;","%":"CompositionEvent|FocusEvent|SVGZoomEvent|TextEvent|TouchEvent;UIEvent"},K5:{"":"D0;oc:name%,ys:status=",
gmW:function(a){var z=a.location
if(W.uC(z)===!0)return z
if(null==a._location_wrapper)a._location_wrapper=new W.H2(z)
@@ -14621,6 +15368,7 @@
geT:function(a){return W.uV(a.parent)},
cO:function(a){return a.close()},
bu:function(a){return a.toString()},
+"+toString:0:0":0,
gEr:function(a){return C.mt.aM(a)},
gVl:function(a){return C.T1.aM(a)},
gLm:function(a){return C.io.aM(a)},
@@ -14629,7 +15377,7 @@
$isD0:true,
"%":"DOMWindow|Window"},UM:{"":"KV;oc:name=,P:value%",
r6:function(a,b){return this.value.call$1(b)},
-"%":"Attr"},rh:{"":"Gb;",
+"%":"Attr"},rh:{"":"ma;",
gB:function(a){return a.length},
"+length":0,
t:function(a,b){var z=a.length
@@ -14656,14 +15404,17 @@
"+error:1:0":0,
gkc:function(a){return new P.C7(this,W.QZ.prototype.Wt,a,"Wt")},
To:function(a){return typeof console!="undefined"?console.info(a):null},
-ZF:function(a,b){return typeof console!="undefined"?console.trace(b):null},
+WL:function(a,b){return typeof console!="undefined"?console.trace(b):null},
"+trace:1:0":0,
-gtN:function(a){return new P.C7(this,W.QZ.prototype.ZF,a,"ZF")},
-static:{"":"wk",}},BV:{"":"Gv+E1;"},E1:{"":"a;",
+gtN:function(a){return new P.C7(this,W.QZ.prototype.WL,a,"WL")},
+static:{"":"wk",}},BV:{"":"Gv+id;"},id:{"":"a;",
gjb:function(a){return this.T2(a,"content")},
gBb:function(a){return this.T2(a,"left")},
gT8:function(a){return this.T2(a,"right")},
-gLA:function(a){return this.T2(a,"src")}},wz:{"":"ar;Sn,Sc",
+gLA:function(a){return this.T2(a,"src")},
+"+src":0,
+sLA:function(a,b){this.hV(a,"src",b,"")},
+"+src=":0},wz:{"":"ar;Sn,Sc",
gB:function(a){return this.Sn.length},
"+length":0,
t:function(a,b){var z=this.Sn
@@ -14769,7 +15520,7 @@
"+[]:1:0":0,
$asar:function(){return[W.KV]},
$asWO:function(){return[W.KV]},
-$ascX:function(){return[W.KV]}},nj:{"":"Gv+lD;",$isList:true,$asWO:null,$isqC:true,$iscX:true,$ascX:null},rl:{"":"nj+Gm;",$asWO:null,$ascX:null,$isList:true,$isqC:true,$iscX:true},RAp:{"":"Gv+lD;",$isList:true,$asWO:null,$isqC:true,$iscX:true,$ascX:null},Gb:{"":"RAp+Gm;",$asWO:null,$ascX:null,$isList:true,$isqC:true,$iscX:true},cf:{"":"a;",
+$ascX:function(){return[W.KV]}},nj:{"":"Gv+lD;",$isList:true,$asWO:null,$isqC:true,$iscX:true,$ascX:null},rl:{"":"nj+Gm;",$asWO:null,$ascX:null,$isList:true,$isqC:true,$iscX:true},RAp:{"":"Gv+lD;",$isList:true,$asWO:null,$isqC:true,$iscX:true,$ascX:null},ma:{"":"RAp+Gm;",$asWO:null,$ascX:null,$isList:true,$isqC:true,$iscX:true},cf:{"":"a;",
PF:function(a){var z,y
for(z=this.gUQ(this),y=new H.a7(z,z.length,0,null),H.VM(y,[H.W8(z,"Q",0)]);y.G(););return!1},
"+containsValue:1:0":0,
@@ -15008,7 +15759,7 @@
"+current":0,
static:{yB:function(a,b){var z=new W.W9(a,J.q8(a),-1,null)
H.VM(z,[b])
-return z}}},vZ:{"":"Tp;a,b",
+return z}}},uY:{"":"Tp;a,b",
call$1:function(a){var z=H.Va(this.b)
Object.defineProperty(a, init.dispatchPropertyName, {value: z, enumerable: false, writable: true, configurable: true})
return this.a(a)},
@@ -15016,13 +15767,13 @@
$isEH:true,
$is_HB:true,
$is_Dv:true},dW:{"":"a;Ui",
-gmW:function(a){return W.zX(this.Ui.location)},
+gmW:function(a){return W.tF(this.Ui.location)},
geT:function(a){return W.P1(this.Ui.parent)},
cO:function(a){return this.Ui.close()},
$isD0:true,
$isGv:true,
static:{P1:function(a){if(a===window)return a
-else return new W.dW(a)}}},PA:{"":"a;mf",static:{zX:function(a){if(a===C.ol.gmW(window))return a
+else return new W.dW(a)}}},PA:{"":"a;mf",static:{tF:function(a){if(a===C.ol.gmW(window))return a
else return new W.PA(a)}}},H2:{"":"a;WK",
gcC:function(a){return this.WK.hash},
"+hash":0,
@@ -15030,15 +15781,16 @@
"+hash=":0,
gLU:function(a){return this.WK.href},
bu:function(a){return this.WK.toString()},
+"+toString:0:0":0,
$iscS:true,
-$isGv:true}}],["dart.dom.indexed_db","dart:indexed_db",,P,{hF:{"":"Gv;",$ishF:true,"%":"IDBKeyRange"}}],["dart.dom.svg","dart:svg",,P,{Y0:{"":"tp;N:target=,LU:href=",$isGv:true,"%":"SVGAElement"},ZJ:{"":"Eo;LU:href=",$isGv:true,"%":"SVGAltGlyphElement"},ui:{"":"MB;",$isGv:true,"%":"SVGAnimateColorElement|SVGAnimateElement|SVGAnimateMotionElement|SVGAnimateTransformElement|SVGAnimationElement|SVGSetElement"},D6:{"":"tp;",$isGv:true,"%":"SVGCircleElement"},DQ:{"":"tp;",$isGv:true,"%":"SVGClipPathElement"},Sm:{"":"tp;",$isGv:true,"%":"SVGDefsElement"},es:{"":"tp;",$isGv:true,"%":"SVGEllipseElement"},eG:{"":"MB;",$isGv:true,"%":"SVGFEBlendElement"},lv:{"":"MB;r9:type=,UQ:values=",$isGv:true,"%":"SVGFEColorMatrixElement"},pf:{"":"MB;",$isGv:true,"%":"SVGFEComponentTransferElement"},NV:{"":"MB;kp:operator=",$isGv:true,"%":"SVGFECompositeElement"},W1:{"":"MB;",$isGv:true,"%":"SVGFEConvolveMatrixElement"},zo:{"":"MB;",$isGv:true,"%":"SVGFEDiffuseLightingElement"},wf:{"":"MB;",$isGv:true,"%":"SVGFEDisplacementMapElement"},bb:{"":"MB;",$isGv:true,"%":"SVGFEFloodElement"},tk:{"":"MB;",$isGv:true,"%":"SVGFEGaussianBlurElement"},me:{"":"MB;LU:href=",$isGv:true,"%":"SVGFEImageElement"},qN:{"":"MB;",$isGv:true,"%":"SVGFEMergeElement"},d4:{"":"MB;kp:operator=",$isGv:true,"%":"SVGFEMorphologyElement"},MI:{"":"MB;",$isGv:true,"%":"SVGFEOffsetElement"},kK:{"":"MB;",$isGv:true,"%":"SVGFESpecularLightingElement"},um:{"":"MB;",$isGv:true,"%":"SVGFETileElement"},Fu:{"":"MB;r9:type=",$isGv:true,"%":"SVGFETurbulenceElement"},OE:{"":"MB;LU:href=",$isGv:true,"%":"SVGFilterElement"},l6:{"":"tp;",$isGv:true,"%":"SVGForeignObjectElement"},BA:{"":"tp;",$isGv:true,"%":"SVGGElement"},tp:{"":"MB;",$isGv:true,"%":";SVGGraphicsElement"},rE:{"":"tp;LU:href=",$isGv:true,"%":"SVGImageElement"},CC:{"":"tp;",$isGv:true,"%":"SVGLineElement"},uz:{"":"MB;",$isGv:true,"%":"SVGMarkerElement"},Yd:{"":"MB;",$isGv:true,"%":"SVGMaskElement"},AD:{"":"tp;",$isGv:true,"%":"SVGPathElement"},Gr:{"":"MB;LU:href=",$isGv:true,"%":"SVGPatternElement"},tc:{"":"tp;",$isGv:true,"%":"SVGPolygonElement"},GH:{"":"tp;",$isGv:true,"%":"SVGPolylineElement"},NJ:{"":"tp;",$isGv:true,"%":"SVGRectElement"},nd:{"":"MB;r9:type%,LU:href=",$isGv:true,"%":"SVGScriptElement"},EU:{"":"MB;r9:type%","%":"SVGStyleElement"},MB:{"":"cv;",
+$isGv:true}}],["dart.dom.indexed_db","dart:indexed_db",,P,{hF:{"":"Gv;",$ishF:true,"%":"IDBKeyRange"}}],["dart.dom.svg","dart:svg",,P,{HB:{"":"tp;N:target=,LU:href=",$isGv:true,"%":"SVGAElement"},ZJ:{"":"Eo;LU:href=",$isGv:true,"%":"SVGAltGlyphElement"},ui:{"":"MB;",$isGv:true,"%":"SVGAnimateColorElement|SVGAnimateElement|SVGAnimateMotionElement|SVGAnimateTransformElement|SVGAnimationElement|SVGSetElement"},D6:{"":"tp;",$isGv:true,"%":"SVGCircleElement"},DQ:{"":"tp;",$isGv:true,"%":"SVGClipPathElement"},Sm:{"":"tp;",$isGv:true,"%":"SVGDefsElement"},es:{"":"tp;",$isGv:true,"%":"SVGEllipseElement"},eG:{"":"MB;",$isGv:true,"%":"SVGFEBlendElement"},lv:{"":"MB;r9:type=,UQ:values=",$isGv:true,"%":"SVGFEColorMatrixElement"},pf:{"":"MB;",$isGv:true,"%":"SVGFEComponentTransferElement"},NV:{"":"MB;kp:operator=",$isGv:true,"%":"SVGFECompositeElement"},W1:{"":"MB;",$isGv:true,"%":"SVGFEConvolveMatrixElement"},zo:{"":"MB;",$isGv:true,"%":"SVGFEDiffuseLightingElement"},wf:{"":"MB;",$isGv:true,"%":"SVGFEDisplacementMapElement"},bb:{"":"MB;",$isGv:true,"%":"SVGFEFloodElement"},tk:{"":"MB;",$isGv:true,"%":"SVGFEGaussianBlurElement"},me:{"":"MB;LU:href=",$isGv:true,"%":"SVGFEImageElement"},qN:{"":"MB;",$isGv:true,"%":"SVGFEMergeElement"},d4:{"":"MB;kp:operator=",$isGv:true,"%":"SVGFEMorphologyElement"},MI:{"":"MB;",$isGv:true,"%":"SVGFEOffsetElement"},xX:{"":"MB;",$isGv:true,"%":"SVGFESpecularLightingElement"},um:{"":"MB;",$isGv:true,"%":"SVGFETileElement"},Fu:{"":"MB;r9:type=",$isGv:true,"%":"SVGFETurbulenceElement"},OE:{"":"MB;LU:href=",$isGv:true,"%":"SVGFilterElement"},l6:{"":"tp;",$isGv:true,"%":"SVGForeignObjectElement"},BA:{"":"tp;",$isGv:true,"%":"SVGGElement"},tp:{"":"MB;",$isGv:true,"%":";SVGGraphicsElement"},rE:{"":"tp;LU:href=",$isGv:true,"%":"SVGImageElement"},CC:{"":"tp;",$isGv:true,"%":"SVGLineElement"},uz:{"":"MB;",$isGv:true,"%":"SVGMarkerElement"},Yd:{"":"MB;",$isGv:true,"%":"SVGMaskElement"},AD:{"":"tp;",$isGv:true,"%":"SVGPathElement"},Gr:{"":"MB;LU:href=",$isGv:true,"%":"SVGPatternElement"},tc:{"":"tp;",$isGv:true,"%":"SVGPolygonElement"},GH:{"":"tp;",$isGv:true,"%":"SVGPolylineElement"},NJ:{"":"tp;",$isGv:true,"%":"SVGRectElement"},nd:{"":"MB;r9:type%,LU:href=",$isGv:true,"%":"SVGScriptElement"},EU:{"":"MB;r9:type%","%":"SVGStyleElement"},MB:{"":"cv;",
gDD:function(a){if(a._cssClassSet==null)a._cssClassSet=new P.O7(a)
return a._cssClassSet},
"%":"SVGAltGlyphDefElement|SVGAltGlyphItemElement|SVGComponentTransferFunctionElement|SVGDescElement|SVGFEDistantLightElement|SVGFEFuncAElement|SVGFEFuncBElement|SVGFEFuncGElement|SVGFEFuncRElement|SVGFEMergeNodeElement|SVGFEPointLightElement|SVGFESpotLightElement|SVGFontElement|SVGFontFaceElement|SVGFontFaceFormatElement|SVGFontFaceNameElement|SVGFontFaceSrcElement|SVGFontFaceUriElement|SVGGlyphElement|SVGHKernElement|SVGMetadataElement|SVGMissingGlyphElement|SVGStopElement|SVGTitleElement|SVGVKernElement;SVGElement"},hy:{"":"tp;",
Kb:function(a,b){return a.getElementById(b)},
$ishy:true,
$isGv:true,
-"%":"SVGSVGElement"},r8:{"":"tp;",$isGv:true,"%":"SVGSwitchElement"},aS:{"":"MB;",$isGv:true,"%":"SVGSymbolElement"},qF:{"":"tp;",$isGv:true,"%":";SVGTextContentElement"},Rk:{"":"qF;bP:method=,LU:href=",$isGv:true,"%":"SVGTextPathElement"},Eo:{"":"qF;","%":"SVGTSpanElement|SVGTextElement;SVGTextPositioningElement"},ox:{"":"tp;LU:href=",$isGv:true,"%":"SVGUseElement"},ZD:{"":"MB;",$isGv:true,"%":"SVGViewElement"},wD:{"":"MB;LU:href=",$isGv:true,"%":"SVGGradientElement|SVGLinearGradientElement|SVGRadialGradientElement"},mj:{"":"MB;",$isGv:true,"%":"SVGCursorElement"},cB:{"":"MB;",$isGv:true,"%":"SVGFEDropShadowElement"},nb:{"":"MB;",$isGv:true,"%":"SVGGlyphRefElement"},xt:{"":"MB;",$isGv:true,"%":"SVGMPathElement"},O7:{"":"As;CE",
+"%":"SVGSVGElement"},r8:{"":"tp;",$isGv:true,"%":"SVGSwitchElement"},aS:{"":"MB;",$isGv:true,"%":"SVGSymbolElement"},qF:{"":"tp;",$isGv:true,"%":";SVGTextContentElement"},xN:{"":"qF;bP:method=,LU:href=",$isGv:true,"%":"SVGTextPathElement"},Eo:{"":"qF;","%":"SVGTSpanElement|SVGTextElement;SVGTextPositioningElement"},ox:{"":"tp;LU:href=",$isGv:true,"%":"SVGUseElement"},ZD:{"":"MB;",$isGv:true,"%":"SVGViewElement"},wD:{"":"MB;LU:href=",$isGv:true,"%":"SVGGradientElement|SVGLinearGradientElement|SVGRadialGradientElement"},mj:{"":"MB;",$isGv:true,"%":"SVGCursorElement"},cB:{"":"MB;",$isGv:true,"%":"SVGFEDropShadowElement"},nb:{"":"MB;",$isGv:true,"%":"SVGGlyphRefElement"},xt:{"":"MB;",$isGv:true,"%":"SVGMPathElement"},O7:{"":"As;CE",
lF:function(){var z,y,x,w,v
z=new W.E9(this.CE).MW.getAttribute("class")
y=P.Ls(null,null,null,J.O)
@@ -15083,15 +15835,18 @@
this.eh[b]=P.wY(c)},
"+[]=:2:0":0,
giO:function(a){return 0},
+"+hashCode":0,
n:function(a,b){var z
if(b==null)return!1
z=J.x(b)
return typeof b==="object"&&b!==null&&!!z.$isE4&&this.eh===b.eh},
+"+==:1:0":0,
Bm:function(a){return a in this.eh},
bu:function(a){var z,y
try{z=String(this.eh)
return z}catch(y){H.Ru(y)
return P.a.prototype.bu.call(this,this)}},
+"+toString:0:0":0,
V7:function(a,b){var z,y
z=this.eh
if(b==null)y=null
@@ -15191,7 +15946,7 @@
z=J.x(y)
if(typeof y!=="object"||y===null||!z.$isMs)throw H.b(new P.AT(H.d(a)+" does not denote a class"))
return y.gJi()},yq:function(a){if(J.xC(a,C.HH)){$.At().toString
-return $.Cr()}return H.jO(a.gIE())},QF:{"":"a;",$isQF:true},NL:{"":"a;",$isNL:true,$isQF:true},vr:{"":"a;",$isvr:true,$isQF:true},D4:{"":"a;",$isD4:true,$isQF:true,$isNL:true},X9:{"":"a;",$isX9:true,$isNL:true,$isQF:true},Ms:{"":"a;",$isMs:true,$isQF:true,$isX9:true,$isNL:true},Fw:{"":"X9;",$isFw:true},RS:{"":"a;",$isRS:true,$isNL:true,$isQF:true},RY:{"":"a;",$isRY:true,$isNL:true,$isQF:true},Ys:{"":"a;",$isYs:true,$isRY:true,$isNL:true,$isQF:true},vg:{"":"a;c1,m2,nV,V3"}}],["dart.typed_data","dart:typed_data",,P,{AS:{"":"Gv;",
+return $.Cr()}return H.jO(a.gIE())},ej:{"":"a;",$isej:true},NL:{"":"a;",$isNL:true,$isej:true},vr:{"":"a;",$isvr:true,$isej:true},D4:{"":"a;",$isD4:true,$isej:true,$isNL:true},L9u:{"":"a;",$isL9u:true,$isNL:true,$isej:true},Ms:{"":"a;",$isMs:true,$isej:true,$isL9u:true,$isNL:true},Fw:{"":"L9u;",$isFw:true},RS:{"":"a;",$isRS:true,$isNL:true,$isej:true},RY:{"":"a;",$isRY:true,$isNL:true,$isej:true},Ys:{"":"a;",$isYs:true,$isRY:true,$isNL:true,$isej:true},vg:{"":"a;c1,m2,nV,V3"}}],["dart.typed_data","dart:typed_data",,P,{AS:{"":"Gv;",
aq:function(a,b,c){var z=J.Wx(b)
if(z.C(b,0)||z.F(b,c))throw H.b(P.TE(b,0,c))
else throw H.b(P.u("Invalid list index "+H.d(b)))},
@@ -15319,7 +16074,7 @@
$isqC:true,
$iscX:true,
$isXj:true,
-"%":"Int8Array"},hn:{"":"TkQ;",
+"%":"Int8Array"},ycx:{"":"TkQ;",
gB:function(a){return C.i7(a)},
"+length":0,
t:function(a,b){var z=C.i7(a)
@@ -15427,12 +16182,12 @@
$iscX:true,
$ascX:function(){return[J.im]},
$isXj:true,
-static:{"":"U9",}}}],["disassembly_entry_element","package:observatory/src/observatory_elements/disassembly_entry.dart",,E,{Fv:{"":["WZ;FT%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+static:{"":"U9",}}}],["disassembly_entry_element","package:observatory/src/observatory_elements/disassembly_entry.dart",,E,{Fv:{"":["WZ;FT%-,VJ,Ai,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
gNI:function(a){return a.FT
-"32,33,34"},
+"34,35,36"},
"+instruction":1,
-sNI:function(a,b){a.FT=this.pD(a,C.eJ,a.FT,b)
-"35,28,32,33"},
+sNI:function(a,b){a.FT=this.ct(a,C.eJ,a.FT,b)
+"37,28,34,35"},
"+instruction=":1,
"@":function(){return[C.Vy]},
static:{AH:function(a){var z,y,x,w,v,u
@@ -15451,18 +16206,18 @@
C.Tl.ZL(a)
C.Tl.FH(a)
return a
-"13"},"+new DisassemblyEntryElement$created:0:0":1}},"+DisassemblyEntryElement": [78],WZ:{"":"uL+Pi;",$isd3:true}}],["error_view_element","package:observatory/src/observatory_elements/error_view.dart",,F,{I3:{"":["pv;Py%-,hO%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"13"},"+new DisassemblyEntryElement$created:0:0":1}},"+DisassemblyEntryElement": [80],WZ:{"":"uL+Pi;",$isd3:true}}],["error_view_element","package:observatory/src/observatory_elements/error_view.dart",,F,{I3:{"":["pv;Py%-,hO%-,VJ,Ai,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
gkc:function(a){return a.Py
-"8,33,34"},
+"8,35,36"},
"+error":1,
-skc:function(a,b){a.Py=this.pD(a,C.yh,a.Py,b)
-"35,28,8,33"},
+skc:function(a,b){a.Py=this.ct(a,C.yh,a.Py,b)
+"37,28,8,35"},
"+error=":1,
gVB:function(a){return a.hO
-"35,33,34"},
+"37,35,36"},
"+error_obj":1,
-sVB:function(a,b){a.hO=this.pD(a,C.Yn,a.hO,b)
-"35,28,35,33"},
+sVB:function(a,b){a.hO=this.ct(a,C.Yn,a.hO,b)
+"37,28,37,35"},
"+error_obj=":1,
"@":function(){return[C.uW]},
static:{TW:function(a){var z,y,x,w,v
@@ -15479,12 +16234,12 @@
C.OD.ZL(a)
C.OD.FH(a)
return a
-"14"},"+new ErrorViewElement$created:0:0":1}},"+ErrorViewElement": [79],pv:{"":"uL+Pi;",$isd3:true}}],["field_view_element","package:observatory/src/observatory_elements/field_view.dart",,A,{Gk:{"":["Vfx;vt%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"14"},"+new ErrorViewElement$created:0:0":1}},"+ErrorViewElement": [81],pv:{"":"uL+Pi;",$isd3:true}}],["field_view_element","package:observatory/src/observatory_elements/field_view.dart",,A,{Gk:{"":["Vfx;vt%-,VJ,Ai,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
gt0:function(a){return a.vt
-"32,33,34"},
+"34,35,36"},
"+field":1,
-st0:function(a,b){a.vt=this.pD(a,C.WQ,a.vt,b)
-"35,28,32,33"},
+st0:function(a,b){a.vt=this.ct(a,C.WQ,a.vt,b)
+"37,28,34,35"},
"+field=":1,
"@":function(){return[C.mv]},
static:{cY:function(a){var z,y,x,w,v
@@ -15500,14 +16255,14 @@
C.lS.ZL(a)
C.lS.FH(a)
return a
-"15"},"+new FieldViewElement$created:0:0":1}},"+FieldViewElement": [80],Vfx:{"":"uL+Pi;",$isd3:true}}],["function_view_element","package:observatory/src/observatory_elements/function_view.dart",,N,{Ds:{"":["Dsd;ql%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"15"},"+new FieldViewElement$created:0:0":1}},"+FieldViewElement": [82],Vfx:{"":"uL+Pi;",$isd3:true}}],["function_view_element","package:observatory/src/observatory_elements/function_view.dart",,N,{Ds:{"":["Dsd;ql%-,VJ,Ai,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
gMj:function(a){return a.ql
-"32,33,34"},
+"34,35,36"},
"+function":1,
-sMj:function(a,b){a.ql=this.pD(a,C.nf,a.ql,b)
-"35,28,32,33"},
+sMj:function(a,b){a.ql=this.ct(a,C.nf,a.ql,b)
+"37,28,34,35"},
"+function=":1,
-"@":function(){return[C.nu]},
+"@":function(){return[C.Uc]},
static:{p7:function(a){var z,y,x,w,v
z=$.Nd()
y=P.Py(null,null,null,J.O,W.I0)
@@ -15521,7 +16276,7 @@
C.PJ.ZL(a)
C.PJ.FH(a)
return a
-"16"},"+new FunctionViewElement$created:0:0":1}},"+FunctionViewElement": [81],Dsd:{"":"uL+Pi;",$isd3:true}}],["html_common","dart:html_common",,P,{jD:function(a){return P.Wu(a.getTime(),!0)},o7:function(a,b){var z=[]
+"16"},"+new FunctionViewElement$created:0:0":1}},"+FunctionViewElement": [83],Dsd:{"":"uL+Pi;",$isd3:true}}],["html_common","dart:html_common",,P,{jD:function(a){return P.Wu(a.getTime(),!0)},o7:function(a,b){var z=[]
return new P.xL(b,new P.CA([],z),new P.YL(z),new P.KC(z)).call$1(a)},dg:function(){if($.L4==null)$.L4=J.Vw(window.navigator.userAgent,"Opera",0)
return $.L4},F7:function(){if($.PN==null)$.PN=P.dg()!==!0&&J.Vw(window.navigator.userAgent,"WebKit",0)
return $.PN},CA:{"":"Tp;a,b",
@@ -15580,6 +16335,7 @@
$is_Dv:true},As:{"":"a;",
bu:function(a){var z=this.lF()
return z.zV(z," ")},
+"+toString:0:0":0,
gA:function(a){var z=this.lF()
z=new P.zQ(z,z.zN,null,null)
H.VM(z,[null])
@@ -15637,7 +16393,7 @@
"+call:1:0":0,
$isEH:true,
$is_HB:true,
-$is_Dv:true}}],["isolate_list_element","package:observatory/src/observatory_elements/isolate_list.dart",,L,{u7:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+$is_Dv:true}}],["isolate_list_element","package:observatory/src/observatory_elements/isolate_list.dart",,L,{u7:{"":["uL;hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
"@":function(){return[C.jF]},
static:{ip:function(a){var z,y,x,w,v
z=$.Nd()
@@ -15652,18 +16408,18 @@
C.Dh.ZL(a)
C.Dh.FH(a)
return a
-"17"},"+new IsolateListElement$created:0:0":1}},"+IsolateListElement": [24]}],["isolate_summary_element","package:observatory/src/observatory_elements/isolate_summary.dart",,D,{St:{"":["tuj;Pw%-,i0%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"17"},"+new IsolateListElement$created:0:0":1}},"+IsolateListElement": [24]}],["isolate_summary_element","package:observatory/src/observatory_elements/isolate_summary.dart",,D,{St:{"":["tuj;Pw%-,i0%-,VJ,Ai,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
gF1:function(a){return a.Pw
-"27,33,34"},
+"27,35,36"},
"+isolate":1,
-sF1:function(a,b){a.Pw=this.pD(a,C.Y2,a.Pw,b)
-"35,28,27,33"},
+sF1:function(a,b){a.Pw=this.ct(a,C.Y2,a.Pw,b)
+"37,28,27,35"},
"+isolate=":1,
goc:function(a){return a.i0
-"8,33,34"},
+"8,35,36"},
"+name":1,
-soc:function(a,b){a.i0=this.pD(a,C.YS,a.i0,b)
-"35,28,8,33"},
+soc:function(a,b){a.i0=this.ct(a,C.YS,a.i0,b)
+"37,28,8,35"},
"+name=":1,
"@":function(){return[C.aM]},
static:{N5:function(a){var z,y,x,w,v
@@ -15680,19 +16436,19 @@
C.nM.ZL(a)
C.nM.FH(a)
return a
-"18"},"+new IsolateSummaryElement$created:0:0":1}},"+IsolateSummaryElement": [82],tuj:{"":"uL+Pi;",$isd3:true}}],["json_view_element","package:observatory/src/observatory_elements/json_view.dart",,Z,{vj:{"":["Vct;eb%-,kf%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"18"},"+new IsolateSummaryElement$created:0:0":1}},"+IsolateSummaryElement": [84],tuj:{"":"uL+Pi;",$isd3:true}}],["json_view_element","package:observatory/src/observatory_elements/json_view.dart",,Z,{vj:{"":["Vct;eb%-,kf%-,VJ,Ai,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
gTn:function(a){return a.eb
-"35,33,34"},
+"37,35,36"},
"+json":1,
-sTn:function(a,b){a.eb=this.pD(a,C.Gd,a.eb,b)
-"35,28,35,33"},
+sTn:function(a,b){a.eb=this.ct(a,C.Gd,a.eb,b)
+"37,28,37,35"},
"+json=":1,
i4:function(a){Z.uL.prototype.i4.call(this,a)
a.kf=0
-"35"},
+"37"},
"+enteredView:0:0":1,
-yC:function(a,b){this.pD(a,C.eR,"a","b")
-"35,83,35"},
+yC:function(a,b){this.ct(a,C.eR,"a","b")
+"37,85,37"},
"+jsonChanged:1:0":1,
gE8:function(a){return J.AG(a.eb)
"8"},
@@ -15715,17 +16471,17 @@
y=J.x(z)
if(typeof z==="object"&&z!==null&&(z.constructor===Array||!!y.$isList))return z
return[]
-"65"},
+"67"},
"+list":1,
gvc:function(a){var z,y
z=a.eb
y=J.RE(z)
if(typeof z==="object"&&z!==null&&!!y.$isL8)return J.qA(y.gvc(z))
return[]
-"65"},
+"67"},
"+keys":1,
r6:function(a,b){return J.UQ(a.eb,b)
-"35,73,8"},
+"37,75,8"},
"+value:1:0":1,
gP:function(a){return new P.C7(this,Z.vj.prototype.r6,a,"r6")},
"@":function(){return[C.HN]},
@@ -15741,17 +16497,17 @@
a.Ye=z
a.mT=y
a.KM=v
-C.jZ.ZL(a)
-C.jZ.FH(a)
+C.GB.ZL(a)
+C.GB.FH(a)
return a
-"19"},"+new JsonViewElement$created:0:0":1}},"+JsonViewElement": [84],Vct:{"":"uL+Pi;",$isd3:true}}],["library_view_element","package:observatory/src/observatory_elements/library_view.dart",,M,{CX:{"":["D13;iI%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"19"},"+new JsonViewElement$created:0:0":1}},"+JsonViewElement": [86],Vct:{"":"uL+Pi;",$isd3:true}}],["library_view_element","package:observatory/src/observatory_elements/library_view.dart",,M,{CX:{"":["D13;iI%-,VJ,Ai,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
gtD:function(a){return a.iI
-"32,33,34"},
+"34,35,36"},
"+library":1,
-stD:function(a,b){a.iI=this.pD(a,C.EV,a.iI,b)
-"35,28,32,33"},
+stD:function(a,b){a.iI=this.ct(a,C.EV,a.iI,b)
+"37,28,34,35"},
"+library=":1,
-"@":function(){return[C.Oy]},
+"@":function(){return[C.Ob]},
static:{SP:function(a){var z,y,x,w,v,u
z=H.B7([],P.L5(null,null,null,null,null))
z=R.Jk(z)
@@ -15768,7 +16524,7 @@
C.MG.ZL(a)
C.MG.FH(a)
return a
-"20"},"+new LibraryViewElement$created:0:0":1}},"+LibraryViewElement": [85],D13:{"":"uL+Pi;",$isd3:true}}],["logging","package:logging/logging.dart",,N,{TJ:{"":"a;oc>,eT>,yz,Cj>,wd,Gs",
+"20"},"+new LibraryViewElement$created:0:0":1}},"+LibraryViewElement": [87],D13:{"":"uL+Pi;",$isd3:true}}],["logging","package:logging/logging.dart",,N,{TJ:{"":"a;oc>,eT>,yz,Cj>,wd,Gs",
gB8:function(){var z,y,x
z=this.eT
y=z==null||J.xC(J.DA(z),"")
@@ -15818,6 +16574,7 @@
if(b==null)return!1
z=J.x(b)
return typeof b==="object"&&b!==null&&!!z.$isNg&&this.P===b.P},
+"+==:1:0":0,
C:function(a,b){var z=J.Vm(b)
if(typeof z!=="number")throw H.s(z)
return this.P<z},
@@ -15834,18 +16591,21 @@
if(typeof z!=="number")throw H.s(z)
return this.P-z},
giO:function(a){return this.P},
+"+hashCode":0,
bu:function(a){return this.oc},
+"+toString:0:0":0,
$isNg:true,
-static:{"":"bR,tm,pR,X8,IQ,Fn,Eb,BC,JY,bo",}},HV:{"":"a;OR<,G1>,iJ,Fl,O0,kc>,I4<",
+static:{"":"bR,tm,pR,X8,IQ,Pk,Eb,BC,JY,bo",}},HV:{"":"a;OR<,G1>,iJ,Fl,O0,kc>,I4<",
bu:function(a){return"["+this.OR.oc+"] "+this.iJ+": "+this.G1},
-static:{"":"xO",}}}],["message_viewer_element","package:observatory/src/observatory_elements/message_viewer.dart",,L,{Nh:{"":["uL;XB%-,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"+toString:0:0":0,
+static:{"":"xO",}}}],["message_viewer_element","package:observatory/src/observatory_elements/message_viewer.dart",,L,{BK:{"":["uL;XB%-,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
gG1:function(a){return a.XB
-"32,34"},
+"34,36"},
"+message":1,
sG1:function(a,b){a.XB=b
-this.pD(a,C.KY,"",this.gQW(a))
-this.pD(a,C.wt,[],this.glc(a))
-"35,86,32,34"},
+this.ct(a,C.KY,"",this.gQW(a))
+this.ct(a,C.wt,[],this.glc(a))
+"37,88,34,36"},
"+message=":1,
gQW:function(a){var z=a.XB
if(z==null||J.UQ(z,"type")==null)return"Error"
@@ -15855,7 +16615,7 @@
glc:function(a){var z=a.XB
if(z==null||J.UQ(z,"members")==null)return[]
return J.UQ(a.XB,"members")
-"87"},
+"89"},
"+members":1,
"@":function(){return[C.c0]},
static:{rJ:function(a){var z,y,x,w,v
@@ -15871,7 +16631,7 @@
C.Wp.ZL(a)
C.Wp.FH(a)
return a
-"21"},"+new MessageViewerElement$created:0:0":1}},"+MessageViewerElement": [24]}],["metadata","/Users/iposva/Downloads/dart/dart-sdk/lib/html/html_common/metadata.dart",,B,{fA:{"":"a;T9,Jt",static:{"":"Xd,en,yS,PZ,xa",}},tz:{"":"a;"},jR:{"":"a;oc>"},PO:{"":"a;"},c5:{"":"a;"}}],["navigation_bar_element","package:observatory/src/observatory_elements/navigation_bar.dart",,Q,{ih:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"21"},"+new MessageViewerElement$created:0:0":1}},"+MessageViewerElement": [24]}],["metadata","../../../../../../../../../dart/dart-sdk/lib/html/html_common/metadata.dart",,B,{fA:{"":"a;T9,Jt",static:{"":"Xd,en,yS,PZ,xa",}},tz:{"":"a;"},jR:{"":"a;oc>"},PO:{"":"a;"},c5:{"":"a;"}}],["navigation_bar_element","package:observatory/src/observatory_elements/navigation_bar.dart",,Q,{ih:{"":["uL;hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
"@":function(){return[C.KG]},
static:{BW:function(a){var z,y,x,w,v
z=$.Nd()
@@ -15887,6 +16647,7 @@
C.Xg.FH(a)
return a
"22"},"+new NavigationBarElement$created:0:0":1}},"+NavigationBarElement": [24]}],["observatory","package:observatory/observatory.dart",,L,{mL:{"":["Pi;Z6<-,lw<-,nI<-,VJ,Ai",function(){return[C.mI]},function(){return[C.mI]},function(){return[C.mI]},null,null],
+AQ:function(a){return J.UQ(this.nI.gi2(),a)},
US:function(){var z,y,x
z=this.Z6
z.sJR(this)
@@ -15900,13 +16661,34 @@
z=R.Jk([])
y=P.L5(null,null,null,J.im,L.bv)
y=R.Jk(y)
-y=new L.mL(new L.dZ(null,"",null,null),new L.jI(null,null,"http://127.0.0.1:8181",z,null,null),new L.pt(null,y,null,null),null,null)
+y=new L.mL(new L.dZ(null,"",null,null,null),new L.jI(null,null,"http://127.0.0.1:8181",z,null,null),new L.pt(null,y,null,null),null,null)
y.US()
-return y}}},bv:{"":["Pi;jO>-,oc>-,VJ,Ai",function(){return[C.mI]},function(){return[C.mI]},null,null],
-bu:function(a){return H.d(this.jO)+" "+H.d(this.oc)},
+return y}}},bv:{"":["Pi;nk,YG,XR<-,VJ,Ai",null,null,function(){return[C.mI]},null,null],
+gjO:function(a){return this.nk
+"27,35,40"},
+"+id":1,
+sjO:function(a,b){this.nk=F.Wi(this,C.EN,this.nk,b)
+"37,28,27,35"},
+"+id=":1,
+goc:function(a){return this.YG
+"8,35,40"},
+"+name":1,
+soc:function(a,b){this.YG=F.Wi(this,C.YS,this.YG,b)
+"37,28,8,35"},
+"+name=":1,
+bu:function(a){return H.d(this.nk)+" "+H.d(this.YG)},
+"+toString:0:0":0,
$isbv:true},pt:{"":["Pi;JR?,i2<-,VJ,Ai",null,function(){return[C.mI]},null,null],
yi:function(){J.kH(this.JR.lw.gn2(),new L.dY(this))},
gVY:function(){return new P.Ip(this,L.pt.prototype.yi,null,"yi")},
+AQ:function(a){var z,y,x,w
+z=this.i2
+y=J.U6(z)
+x=y.t(z,a)
+if(x==null){w=P.L5(null,null,null,J.O,L.Pf)
+w=R.Jk(w)
+x=new L.bv(a,"",w,null,null)
+y.u(z,a,x)}return x},
LZ:function(a){var z=[]
J.kH(this.i2,new L.vY(a,z))
H.bQ(z,new L.dS(this))
@@ -15932,23 +16714,31 @@
$isEH:true,
$is_HB:true,
$is_Dv:true},ZW:{"":"Tp;d",
-call$1:function(a){var z,y,x,w
+call$1:function(a){var z,y,x,w,v
z=J.U6(a)
y=z.t(a,"id")
x=z.t(a,"name")
z=this.d.i2
w=J.U6(z)
-if(w.t(z,y)==null)w.u(z,y,new L.bv(y,x,null,null))},
+if(w.t(z,y)==null){v=P.L5(null,null,null,J.O,L.Pf)
+v=R.Jk(v)
+w.u(z,y,new L.bv(y,x,v,null,null))}else J.DF(w.t(z,y),x)},
"+call:1:0":0,
$isEH:true,
$is_HB:true,
-$is_Dv:true},dZ:{"":"Pi;JR?,IT,VJ,Ai",
+$is_Dv:true},dZ:{"":"Pi;JR?,IT,Jj,VJ,Ai",
gzd:function(){return this.IT
-"8,33,38"},
+"8,35,40"},
"+currentHash":1,
szd:function(a){this.IT=F.Wi(this,C.h1,this.IT,a)
-"35,28,8,33"},
+"37,28,8,35"},
"+currentHash=":1,
+glD:function(){return this.Jj
+"90,35,40"},
+"+currentHashUri":1,
+slD:function(a){this.Jj=F.Wi(this,C.tv,this.Jj,a)
+"37,28,90,35"},
+"+currentHashUri=":1,
kI:function(){var z,y
z=C.PP.aM(window)
y=new W.Ov(0,z.uv,z.Ph,W.aF(new L.Qe(this)),z.Sg)
@@ -15967,6 +16757,8 @@
z=J.q8(z[0])
if(typeof z!=="number")throw H.s(z)
return C.xB.JT(x,w,v+z)},
+gAT:function(){return J.xC(J.UQ(this.Jj.ghY().iY,"type"),"Script")},
+gDe:function(){return P.pE(J.UQ(this.Jj.ghY().iY,"name"),C.dy,!0)},
R6:function(){var z,y
z=this.vI()
if(z==null)return 0
@@ -15981,31 +16773,42 @@
z=J.Co(C.ol.gmW(window))
this.IT=F.Wi(this,C.h1,this.IT,z)
y=J.ZZ(this.IT,1)
+z=P.r6($.cO().ej(y))
+this.Jj=F.Wi(this,C.tv,this.Jj,z)
this.JR.lw.ox(y)},
PI:function(a){var z=this.R6()
if(J.xC(z,0))return"#/isolates/"
return"#/isolates/"+H.d(z)+"/"+H.d(a)
-"8,88,8,38"},
+"8,91,8,40"},
"+currentIsolateRelativeLink:1:0":1,
Ao:function(a){var z=this.R6()
if(J.xC(z,0))return"#/isolates/"
return"#/isolates/"+H.d(z)+"/objects/"+H.d(a)
-"8,89,27,38"},
+"8,92,27,40"},
"+currentIsolateObjectLink:1:0":1,
dL:function(a){var z=this.R6()
if(J.xC(z,0))return"#/isolates/"
return"#/isolates/"+H.d(z)+"/classes/"+H.d(a)
-"8,90,27,38"},
+"8,93,27,40"},
"+currentIsolateClassLink:1:0":1,
+WW:function(a,b){var z=this.R6()
+if(J.xC(z,0))return"#/isolates/"
+return this.yX(z,a,b)
+"8,92,27,7,8,40"},
+"+currentIsolateScriptLink:2:0":1,
r4:function(a,b){return"#/isolates/"+H.d(a)+"/"+H.d(b)
-"8,91,27,88,8,38"},
+"8,94,27,91,8,40"},
"+relativeLink:2:0":1,
Dd:function(a,b){return"#/isolates/"+H.d(a)+"/objects/"+H.d(b)
-"8,91,27,89,27,38"},
+"8,94,27,92,27,40"},
"+objectLink:2:0":1,
bD:function(a,b){return"#/isolates/"+H.d(a)+"/classes/"+H.d(b)
-"8,91,27,90,27,38"},
+"8,94,27,93,27,40"},
"+classLink:2:0":1,
+yX:function(a,b,c){var z=P.jW(C.kg,c,!0)
+return"#/isolates/"+H.d(a)+"/objects/"+H.d(b)+"?type=Script&name="+z
+"8,94,27,92,27,7,8,40"},
+"+scriptLink:3:0":1,
static:{"":"kx,K3D,qY",}},Qe:{"":"Tp;a",
call$1:function(a){var z=this.a
if(z.S7())return
@@ -16016,16 +16819,16 @@
$is_Dv:true},Nu:{"":"Pi;JR?,e0?",
pG:function(){return this.e0.call$0()},
gEI:function(){return this.oJ
-"8,33,38"},
+"8,35,40"},
"+prefix":1,
sEI:function(a){this.oJ=F.Wi(this,C.qb,this.oJ,a)
-"35,28,8,33"},
+"37,28,8,35"},
"+prefix=":1,
gn2:function(){return this.vm
-"87,33,38"},
+"89,35,40"},
"+responses":1,
sn2:function(a){this.vm=F.Wi(this,C.wH,this.vm,a)
-"35,28,87,33"},
+"37,28,89,35"},
"+responses=":1,
Qn:function(a){var z,y
z=C.lM.kV(a)
@@ -16040,21 +16843,107 @@
y=H.d(z.gys(a))+" "+z.gpo(a)
if(z.gys(a)===0)y="No service found. Did you run with --enable-vm-service ?"
this.dq([H.B7(["type","RequestError","error",y],P.L5(null,null,null,null,null))])},
-ox:function(a){this.ym(this,a).ml(new L.pF(this)).OA(new L.Ha(this))}},pF:{"":"Tp;a",
-call$1:function(a){this.a.Qn(a)},
+ox:function(a){var z
+if(this.JR.Z6.gAT()){z=this.JR.Z6.gDe()
+this.iG(z,a).ml(new L.pF(this,z))}else this.ym(this,a).ml(new L.Ha(this)).OA(new L.nu(this))},
+iG:function(a,b){var z,y,x
+z=this.JR.Z6.R6()
+y=this.JR.nI.AQ(z)
+x=J.UQ(y.gXR(),a)
+if(x!=null)return P.Ab(x,null)
+return this.ym(this,b).ml(new L.be(a,y)).OA(new L.Pg(this))}},pF:{"":"Tp;a,b",
+call$1:function(a){var z=this.a
+if(a!=null)z.dq([H.B7(["type","Script","source",a],P.L5(null,null,null,null,null))])
+else z.dq([H.B7(["type","RequestError","error","Source for "+this.b+" could not be loaded."],P.L5(null,null,null,null,null))])},
"+call:1:0":0,
$isEH:true,
$is_HB:true,
-$is_Dv:true},Ha:{"":"Tp;b",
-call$1:function(a){this.b.AI(J.l2(a))},
+$is_Dv:true},Ha:{"":"Tp;c",
+call$1:function(a){this.c.Qn(a)},
+"+call:1:0":0,
+$isEH:true,
+$is_HB:true,
+$is_Dv:true},nu:{"":"Tp;d",
+call$1:function(a){this.d.AI(J.l2(a))},
+"+call:1:0":0,
+$isEH:true,
+$is_HB:true,
+$is_Dv:true},be:{"":"Tp;a,b",
+call$1:function(a){var z=L.Sp(C.lM.kV(a))
+J.kW(this.b.gXR(),this.a,z)
+return z},
+"+call:1:0":0,
+$isEH:true,
+$is_HB:true,
+$is_Dv:true},Pg:{"":"Tp;c",
+call$1:function(a){this.c.AI(J.l2(a))
+return},
"+call:1:0":0,
$isEH:true,
$is_HB:true,
$is_Dv:true},jI:{"":"Nu;JR,e0,oJ,vm,VJ,Ai",
-ym:function(a,b){return W.It(J.WB(this.oJ,b),null,null)}}}],["observatory_application_element","package:observatory/src/observatory_elements/observatory_application.dart",,V,{F1:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+ym:function(a,b){return W.It(J.WB(this.oJ,b),null,null)}},Zw:{"":["Pi;Rd,n7,LA>-,Vg,VJ,Ai",null,null,function(){return[C.mI]},null,null,null],
+gCt:function(){return this.Vg
+"8,35,40"},
+"+paddedLine":1,
+sCt:function(a){var z=this.Vg
+if(this.gUV(this)&&!J.xC(z,a)){z=new T.qI(this,C.X9,z,a)
+z.$builtinTypeInfo=[null]
+this.SZ(this,z)}this.Vg=a
+"37,28,8,35"},
+"+paddedLine=":1,
+QQ:function(a,b,c){var z,y,x,w,v
+z=""+this.Rd
+this.Vg=F.Wi(this,C.X9,this.Vg,z)
+for(y=J.q8(this.Vg),z=this.n7;x=J.Wx(y),x.C(y,z);y=x.g(y,1)){w=" "+H.d(this.Vg)
+v=this.Vg
+if(this.gUV(this)&&!J.xC(v,w)){v=new T.qI(this,C.X9,v,w)
+v.$builtinTypeInfo=[null]
+this.SZ(this,v)}this.Vg=w}},
+static:{il:function(a,b,c){var z=new L.Zw(a,b,c,null,null,null)
+z.QQ(a,b,c)
+return z}}},Pf:{"":"Pi;WF,uM,ZQ,VJ,Ai",
+gfY:function(a){return this.WF
+"8,35,40"},
+"+kind":1,
+sfY:function(a,b){this.WF=F.Wi(this,C.fy,this.WF,b)
+"37,28,8,35"},
+"+kind=":1,
+gO3:function(a){return this.uM
+"8,35,40"},
+"+url":1,
+sO3:function(a,b){this.uM=F.Wi(this,C.Fh,this.uM,b)
+"37,28,8,35"},
+"+url=":1,
+gXJ:function(){return this.ZQ
+"95,35,40"},
+"+lines":1,
+sXJ:function(a){this.ZQ=F.Wi(this,C.Cv,this.ZQ,a)
+"37,28,95,35"},
+"+lines=":1,
+Cn:function(a){var z,y,x,w,v
+z=J.uH(a,"\n")
+y=(""+(z.length+1)).length
+for(x=0;x<z.length;x=w){w=x+1
+v=L.il(w,y,z[x])
+J.bi(this.ZQ,v)}},
+bu:function(a){return"ScriptSource"},
+"+toString:0:0":0,
+EQ:function(a){var z,y
+z=J.U6(a)
+y=z.t(a,"kind")
+this.WF=F.Wi(this,C.fy,this.WF,y)
+y=z.t(a,"name")
+this.uM=F.Wi(this,C.Fh,this.uM,y)
+this.Cn(z.t(a,"source"))},
+$isPf:true,
+static:{Sp:function(a){var z=R.Jk([])
+z=new L.Pf("","",z,null,null)
+z.EQ(a)
+return z}}}}],["observatory_application_element","package:observatory/src/observatory_elements/observatory_application.dart",,V,{F1:{"":["uL;hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
ZB:function(a){var z=L.AK()
-a.tH=this.pD(a,C.wh,a.tH,z)
-"35"},
+a.hm=this.ct(a,C.wh,a.hm,z)
+"37"},
"@":function(){return[C.bd]},
static:{fv:function(a){var z,y,x,w,v
z=$.Nd()
@@ -16070,21 +16959,21 @@
C.k0.FH(a)
C.k0.ZB(a)
return a
-"23"},"+new ObservatoryApplicationElement$created:0:0":1}},"+ObservatoryApplicationElement": [24]}],["observatory_element","package:observatory/src/observatory_elements/observatory_element.dart",,Z,{uL:{"":["Xf;tH%-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"23"},"+new ObservatoryApplicationElement$created:0:0":1}},"+ObservatoryApplicationElement": [24]}],["observatory_element","package:observatory/src/observatory_elements/observatory_element.dart",,Z,{uL:{"":["Xf;hm%-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
i4:function(a){A.dM.prototype.i4.call(this,a)
-"35"},
+"37"},
"+enteredView:0:0":1,
Nz:function(a){A.dM.prototype.Nz.call(this,a)
-"35"},
+"37"},
"+leftView:0:0":1,
-gQG:function(a){return a.tH
-"92,33,34"},
+gQG:function(a){return a.hm
+"96,35,36"},
"+app":1,
-sQG:function(a,b){a.tH=this.pD(a,C.wh,a.tH,b)
-"35,28,92,33"},
+sQG:function(a,b){a.hm=this.ct(a,C.wh,a.hm,b)
+"37,28,96,35"},
"+app=":1,
gpQ:function(a){return!0
-"39"},
+"41"},
"+applyAuthorStyles":1,
"@":function(){return[C.J0]},
static:{Hx:function(a){var z,y,x,w,v
@@ -16097,10 +16986,10 @@
a.Ye=z
a.mT=y
a.KM=v
-C.Pf.ZL(a)
-C.Pf.FH(a)
+C.mk.ZL(a)
+C.mk.FH(a)
return a
-"24"},"+new ObservatoryElement$created:0:0":1}},"+ObservatoryElement": [93],Xf:{"":"ir+Pi;",$isd3:true}}],["observe.src.change_notifier","package:observe/src/change_notifier.dart",,O,{Pi:{"":"a;",
+"24"},"+new ObservatoryElement$created:0:0":1}},"+ObservatoryElement": [97],Xf:{"":"ir+Pi;",$isd3:true}}],["observe.src.change_notifier","package:observe/src/change_notifier.dart",,O,{Pi:{"":"a;",
gqh:function(a){var z,y
if(a.VJ==null){z=this.gqw(a)
a.VJ=P.bK(this.gl1(a),z,!0,null)}z=a.VJ
@@ -16129,7 +17018,7 @@
if(z!=null){y=z.iE
z=y==null?z!=null:y!==z}else z=!1
return z},
-pD:function(a,b,c,d){return F.Wi(a,b,c,d)},
+ct:function(a,b,c,d){return F.Wi(a,b,c,d)},
SZ:function(a,b){var z,y
z=a.VJ
if(z!=null){y=z.iE
@@ -16139,12 +17028,13 @@
P.rb(this.gDx(a))}a.Ai.push(b)},
$isd3:true}}],["observe.src.change_record","package:observe/src/change_record.dart",,T,{yj:{"":"a;",$isyj:true},qI:{"":"yj;WA<,oc>,jL>,zZ>",
bu:function(a){return"#<PropertyChangeRecord "+H.d(this.oc)+" from: "+H.d(this.jL)+" to: "+H.d(this.zZ)+">"},
+"+toString:0:0":0,
$isqI:true}}],["observe.src.compound_path_observer","package:observe/src/compound_path_observer.dart",,Y,{J3:{"":"Pi;b9,kK,Sv,rk,YX,B6,VJ,Ai",
kb:function(a){return this.rk.call$1(a)},
gB:function(a){return this.b9.length},
"+length":0,
gP:function(a){return this.Sv
-"35,33"},
+"37,35"},
"+value":1,
r6:function(a,b){return this.gP(a).call$1(b)},
wE:function(a){var z,y,x,w
@@ -16210,7 +17100,7 @@
$.Td=!1},Ht:function(){var z={}
z.a=!1
z=new O.o5(z)
-return new P.wJ(null,null,null,null,new O.zI(z),new O.id(z),null,null,null,null,null,null)},o5:{"":"Tp;a",
+return new P.wJ(null,null,null,null,new O.zI(z),new O.bF(z),null,null,null,null,null,null)},o5:{"":"Tp;a",
call$2:function(a,b){var z=this.a
if(z.a)return
z.a=!0
@@ -16231,7 +17121,7 @@
return this.f.call$0()},
"+call:0:0":0,
$isEH:true,
-$is_X0:true},id:{"":"Tp;g",
+$is_X0:true},bF:{"":"Tp;g",
call$4:function(a,b,c,d){if(d==null)return d
return new O.iV(this.g,b,c,d)},
"+call:4:0":0,
@@ -16443,13 +17333,14 @@
if(typeof z!=="number")throw H.s(z)
return a<z},
bu:function(a){return"#<ListChangeRecord index: "+H.d(this.jr)+", removed: "+H.d(this.Uj)+", addedCount: "+H.d(this.dM)+">"},
+"+toString:0:0":0,
$isW4:true,
static:{XM:function(a,b,c,d){var z
if(d==null)d=[]
if(c==null)c=0
z=new P.Yp(d)
z.$builtinTypeInfo=[null]
-return new G.W4(a,z,d,b,c)}}}}],["observe.src.metadata","package:observe/src/metadata.dart",,K,{Fa:{"":"a;"},ma:{"":"a;"}}],["observe.src.observable","package:observe/src/observable.dart",,F,{Wi:function(a,b,c,d){var z,y
+return new G.W4(a,z,d,b,c)}}}}],["observe.src.metadata","package:observe/src/metadata.dart",,K,{ndx:{"":"a;"},Hm:{"":"a;"}}],["observe.src.observable","package:observe/src/observable.dart",,F,{Wi:function(a,b,c,d){var z,y
z=J.RE(a)
if(z.gUV(a)&&!J.xC(c,d)){y=new T.qI(a,b,c,d)
H.VM(y,[null])
@@ -16469,13 +17360,14 @@
$isEH:true,
$is_bh:true}}],["observe.src.observable_box","package:observe/src/observable_box.dart",,A,{xh:{"":"Pi;",
gP:function(a){return this.L1
-"94,33"},
+"98,35"},
"+value":1,
r6:function(a,b){return this.gP(a).call$1(b)},
sP:function(a,b){this.L1=F.Wi(this,C.ls,this.L1,b)
-"35,95,94,33"},
+"37,99,98,35"},
"+value=":1,
-bu:function(a){return"#<"+H.d(new H.cu(H.dJ(this),null))+" value: "+H.d(this.L1)+">"}}}],["observe.src.observable_list","package:observe/src/observable_list.dart",,Q,{wn:{"":"uF;b3,xg,h3,VJ,Ai",
+bu:function(a){return"#<"+H.d(new H.cu(H.dJ(this),null))+" value: "+H.d(this.L1)+">"},
+"+toString:0:0":0}}],["observe.src.observable_list","package:observe/src/observable_list.dart",,Q,{wn:{"":"uF;b3,xg,h3,VJ,Ai",
gRT:function(){var z,y
if(this.xg==null)this.xg=P.bK(new Q.cj(this),null,!0,null)
z=this.xg
@@ -16484,18 +17376,21 @@
H.VM(y,[H.W8(z,"WV",0)])
return y},
gB:function(a){return this.h3.length
-"27,33"},
+"27,35"},
"+length":1,
sB:function(a,b){var z,y,x,w,v,u,t
z=this.h3
y=z.length
if(y===b)return
-this.pD(this,C.Wn,y,b)
+this.ct(this,C.Wn,y,b)
+x=y===0
+w=J.x(b)
+this.ct(this,C.ai,x,w.n(b,0))
+this.ct(this,C.nZ,!x,!w.n(b,0))
x=this.xg
-if(x!=null){w=x.iE
-x=w==null?x!=null:w!==x}else x=!1
-if(x){x=J.Wx(b)
-if(x.C(b,y)){if(x.C(b,0)||x.D(b,z.length))H.vh(P.TE(b,0,z.length))
+if(x!=null){v=x.iE
+x=v==null?x!=null:v!==x}else x=!1
+if(x)if(w.C(b,y)){if(w.C(b,0)||w.D(b,z.length))H.vh(P.TE(b,0,z.length))
if(typeof b!=="number")throw H.s(b)
if(y<b||y>z.length)H.vh(P.TE(y,b,z.length))
x=new H.nH(z,b,y)
@@ -16508,17 +17403,17 @@
if(v.D(w,u))H.vh(P.TE(w,0,u))}x=x.br(x)
w=new P.Yp(x)
w.$builtinTypeInfo=[null]
-this.iH(new G.W4(this,w,x,b,0))}else{x=x.W(b,y)
+this.iH(new G.W4(this,w,x,b,0))}else{x=w.W(b,y)
t=[]
w=new P.Yp(t)
w.$builtinTypeInfo=[null]
-this.iH(new G.W4(this,w,t,y,x))}}C.Nm.sB(z,b)
-"35,28,27,33"},
+this.iH(new G.W4(this,w,t,y,x))}C.Nm.sB(z,b)
+"37,28,27,35"},
"+length=":1,
t:function(a,b){var z=this.h3
if(b>>>0!==b||b>=z.length)throw H.e(z,b)
return z[b]
-"96,26,27,33"},
+"100,26,27,35"},
"+[]:1:0":1,
u:function(a,b,c){var z,y,x,w
z=this.h3
@@ -16532,12 +17427,18 @@
w.$builtinTypeInfo=[null]
this.iH(new G.W4(this,w,x,b,1))}if(b>=z.length)throw H.e(z,b)
z[b]=c
-"35,26,27,28,96,33"},
+"37,26,27,28,100,35"},
"+[]=:2:0":1,
+gl0:function(a){return P.lD.prototype.gl0.call(this,this)
+"41,35"},
+"+isEmpty":1,
+gor:function(a){return P.lD.prototype.gor.call(this,this)
+"41,35"},
+"+isNotEmpty":1,
h:function(a,b){var z,y,x,w
z=this.h3
y=z.length
-this.pD(this,C.Wn,y,y+1)
+this.Fg(y,y+1)
x=this.xg
if(x!=null){w=x.iE
x=w==null?x!=null:w!==x}else x=!1
@@ -16547,7 +17448,7 @@
z=this.h3
y=z.length
C.Nm.Ay(z,b)
-this.pD(this,C.Wn,y,z.length)
+this.Fg(y,z.length)
x=z.length-y
z=this.xg
if(z!=null){w=z.iE
@@ -16564,7 +17465,12 @@
x=c-b
w=this.h3
v=w.length
-this.pD(this,C.Wn,v,v-x)
+u=v-x
+this.ct(this,C.Wn,v,u)
+t=v===0
+u=u===0
+this.ct(this,C.ai,t,u)
+this.ct(this,C.nZ,!t,!u)
u=this.xg
if(u!=null){t=u.iE
u=t==null?u!=null:t!==u}else u=!1
@@ -16588,6 +17494,12 @@
if(!z)return
if(this.b3==null){this.b3=[]
P.rb(this.gL6())}this.b3.push(a)},
+Fg:function(a,b){var z,y
+this.ct(this,C.Wn,a,b)
+z=a===0
+y=J.x(b)
+this.ct(this,C.ai,z,y.n(b,0))
+this.ct(this,C.nZ,!z,!y.n(b,0))},
oC:function(){var z,y,x
z=this.b3
if(z==null)return!1
@@ -16618,36 +17530,37 @@
if(this.JD)z="insert"
else z=this.dr?"remove":"set"
return"#<MapChangeRecord "+z+" "+H.d(this.G3)+" from: "+H.d(this.jL)+" to: "+H.d(this.zZ)+">"},
+"+toString:0:0":0,
$isHA:true},br:{"":"Pi;Zp,VJ,Ai",
gvc:function(a){var z=this.Zp
return z.gvc(z)
-"97,33"},
+"101,35"},
"+keys":1,
gUQ:function(a){var z=this.Zp
return z.gUQ(z)
-"98,33"},
+"102,35"},
"+values":1,
gB:function(a){var z=this.Zp
return z.gB(z)
-"27,33"},
+"27,35"},
"+length":1,
gl0:function(a){var z=this.Zp
return z.gB(z)===0
-"39,33"},
+"41,35"},
"+isEmpty":1,
gor:function(a){var z=this.Zp
return z.gB(z)!==0
-"39,33"},
+"41,35"},
"+isNotEmpty":1,
PF:function(a){return this.Zp.PF(a)
-"39,28,0,33"},
+"41,28,0,35"},
"+containsValue:1:0":1,
x4:function(a){return this.Zp.x4(a)
-"39,73,0,33"},
+"41,75,0,35"},
"+containsKey:1:0":1,
t:function(a,b){var z=this.Zp
return z.t(z,b)
-"99,73,0,33"},
+"103,75,0,35"},
"+[]:1:0":1,
u:function(a,b,c){var z,y,x,w,v
z=this.Zp
@@ -16664,7 +17577,7 @@
z.$builtinTypeInfo=[null,null]
this.SZ(this,z)}else if(!J.xC(x,c)){z=new V.HA(b,x,c,!1,!1)
z.$builtinTypeInfo=[null,null]
-this.SZ(this,z)}"35,73,100,28,99,33"},
+this.SZ(this,z)}"37,75,104,28,103,35"},
"+[]=:2:0":1,
Ay:function(a,b){b.aN(b,new V.zT(this))},
Rz:function(a,b){var z,y,x,w,v
@@ -16681,6 +17594,7 @@
aN:function(a,b){var z=this.Zp
return z.aN(z,b)},
bu:function(a){return P.vW(this)},
+"+toString:0:0":0,
$asL8:null,
$isL8:true,
static:{WF:function(a,b,c){var z=V.Bq(a,b,c)
@@ -16764,7 +17678,7 @@
if(0>=a.length)throw H.e(a,0)
if(a[0]===".")return!1
return $.tN().zD(a)},D7:{"":"Pi;Ii>,YB,BK,kN,cs,cT,VJ,Ai",
-E4:function(a){return this.cT.call$1(a)},
+AR:function(a){return this.cT.call$1(a)},
gWA:function(){var z=this.kN
if(0>=z.length)throw H.e(z,0)
return z[0]},
@@ -16775,7 +17689,7 @@
z=y==null?z!=null:y!==z}else z=!1
if(!z)this.ov()
return C.Nm.grZ(this.kN)
-"35,33"},
+"37,35"},
"+value":1,
r6:function(a,b){return this.gP(a).call$1(b)},
sP:function(a,b){var z,y,x,w
@@ -16793,7 +17707,7 @@
if(w>=z.length)throw H.e(z,w)
if(L.h6(x,z[w],b)){z=this.kN
if(y>=z.length)throw H.e(z,y)
-z[y]=b}"35,95,0,33"},
+z[y]=b}"37,99,0,35"},
"+value=":1,
w3:function(a){O.Pi.prototype.w3.call(this,this)
this.ov()
@@ -16818,7 +17732,7 @@
v=v[w]
if(w>=z.length)throw H.e(z,w)
u=L.yf(v,z[w])
-if(w===y&&x)u=this.E4(u)
+if(w===y&&x)u=this.AR(u)
v=this.kN;++w
if(w>=v.length)throw H.e(v,w)
v[w]=u}},
@@ -16833,7 +17747,7 @@
t=t[w]
if(w>=z.length)throw H.e(z,w)
u=L.yf(t,z[w])
-if(w===y&&x)u=this.E4(u)
+if(w===y&&x)u=this.AR(u)
if(v==null?u==null:v===u){this.Rl(a,w)
return}t=this.kN
if(s>=t.length)throw H.e(t,s)
@@ -17092,7 +18006,9 @@
y=new H.KW(z,a)
if(!y.gA(y).G())return
return J.UQ(y.gFV(y),0)},
-bu:function(a){return this.goc(this)}},BE:{"":"OO;oc>,mI<,DF<,nK<,Ew<,TL"},Qb:{"":"OO;oc>,mI<,DF<,nK<,Ew<,TL"},xI:{"":"OO;oc>,mI<,DF<,nK<,Ew<,TL<,qW"},q1:{"":"a;S,SF,aA,dY,Yj",
+bu:function(a){return this.goc(this)},
+"+toString:0:0":0,
+static:{"":"ak<",}},BE:{"":"OO;oc>,mI<,DF<,nK<,Ew<,TL"},Qb:{"":"OO;oc>,mI<,DF<,nK<,Ew<,TL"},xI:{"":"OO;oc>,mI<,DF<,nK<,Ew<,TL<,qW"},q1:{"":"a;S,SF,aA,dY,Yj",
IV:function(){var z,y
z=this.Yj
while(!0){y=this.dY
@@ -17114,7 +18030,8 @@
w=v[x]
w=typeof w==="string"?w:H.d(w)
z.vM=z.vM+w}z.KF(C.Nm.grZ(y))
-return z.vM}}}],["polymer","package:polymer/polymer.dart",,A,{JX:function(){var z,y
+return z.vM},
+"+toString:0:0":0},"":"O3<"}],["polymer","package:polymer/polymer.dart",,A,{JX:function(){var z,y
z=document.createElement("style",null)
z.textContent=".polymer-veiled { opacity: 0; } \n.polymer-unveil{ -webkit-transition: opacity 0.3s; transition: opacity 0.3s; }\n"
y=document.querySelector("head")
@@ -17130,43 +18047,57 @@
if(J.xC(a,$.Tf()))return b
b=A.oF(a.gAY(),b)
for(z=J.GP(J.hI(a.gYK()));z.G();){y=z.gl()
+if(y.gFo()||y.gkw())continue
x=J.x(y)
-if(typeof y!=="object"||y===null||!x.$isRY||y.gV5()||y.gFo()||y.gkw())continue
-for(x=J.GP(y.gc9());x.G();){w=x.gl().gAx()
-v=J.x(w)
-if(typeof w==="object"&&w!==null&&!!v.$isyL){if(b==null)b=H.B7([],P.L5(null,null,null,null,null))
-b.u(b,y.gIf(),y)
-break}}}for(z=J.GP(J.hI(a.gYK()));z.G();){u=z.gl()
-x=J.x(u)
-if(typeof u!=="object"||u===null||!x.$isRS||!u.glT()||u.Fo||u.gkw())continue
-for(x=J.GP(u.gc9());x.G();){w=x.gl().gAx()
-v=J.x(w)
-if(typeof w==="object"&&w!==null&&!!v.$isyL){if(A.bc(a,u)){if(b==null)b=H.B7([],P.L5(null,null,null,null,null))
-b.u(b,u.gIf(),u)}break}}}return b},bc:function(a,b){var z,y
+if(!(typeof y==="object"&&y!==null&&!!x.$isRY&&!y.gV5()))w=typeof y==="object"&&y!==null&&!!x.$isRS&&y.glT()
+else w=!0
+if(w)for(w=J.GP(y.gc9());w.G();){v=w.mD.gAx()
+u=J.x(v)
+if(typeof v==="object"&&v!==null&&!!u.$isyL){if(typeof y!=="object"||y===null||!x.$isRS||A.bc(a,y)){if(b==null)b=H.B7([],P.L5(null,null,null,null,null))
+b.u(b,y.gIf(),y)}break}}}return b},Oy:function(a,b){var z,y
+do{z=J.UQ(a.gYK(),b)
+y=J.x(z)
+if(typeof z==="object"&&z!==null&&!!y.$isRS&&z.glT()&&A.bc(a,z)||typeof z==="object"&&z!==null&&!!y.$isRY)return z
+a=a.gAY()}while(a!=null)
+return},bc:function(a,b){var z,y
z=H.le(H.d(J.Z0(b.gIf()))+"=")
y=J.UQ(a.gYK(),new H.GD(z))
z=J.x(y)
return typeof y==="object"&&y!==null&&!!z.$isRS&&y.ghB()},hO:function(a,b,c){var z,y
if($.LX()==null||a==null)return
-if($.LX().Bm("ShadowDOMPolyfill"))return
+if(!$.LX().Bm("ShadowDOMPolyfill"))return
z=J.UQ($.LX(),"Platform")
if(z==null)return
y=J.UQ(z,"ShadowCSS")
if(y==null)return
-y.V7("shimStyling",[a,b,c])},Hl:function(a){var z
-if(a==null||$.LX()==null)return""
-z=J.UQ(P.Oe(a),"__resource")
-return z!=null?z:""},oY:function(a){var z=J.UQ($.pT(),a)
+y.V7("shimStyling",[a,b,c])},Hl:function(a){var z,y,x,w,v,u,t
+if(a==null)return""
+w=J.RE(a)
+z=w.gLU(a)
+if(J.xC(z,""))z=w.gQg(a).MW.getAttribute("href")
+if($.LX()!=null&&$.LX().Bm("HTMLImports")){v=J.UQ(P.Oe(a),"__resource")
+if(v!=null)return v
+$.vM().J4("failed to get stylesheet text href=\""+H.d(z)+"\"")
+return""}try{w=new XMLHttpRequest()
+C.W3.i3(w,"GET",z,!1)
+w.send()
+w=w.responseText
+return w}catch(u){w=H.Ru(u)
+t=J.x(w)
+if(typeof w==="object"&&w!==null&&!!t.$isNh){y=w
+x=new H.XO(u,null)
+$.vM().J4("failed to get stylesheet text href=\""+H.d(z)+"\" error: "+H.d(y)+", trace: "+H.d(x))
+return""}else throw u}},oY:function(a){var z=J.UQ($.pT(),a)
return z!=null?z:a},Ad:function(a,b){var z,y
if(b==null)b=C.hG
z=$.Ej()
z.u(z,a,b)
z=$.p2()
y=z.Rz(z,a)
-if(y!=null)J.Or(y)},zM:function(a){A.om(a,new A.Mq())},om:function(a,b){var z
+if(y!=null)J.Or(y)},zM:function(a){A.Vx(a,new A.Mq())},Vx:function(a,b){var z
if(a==null)return
b.call$1(a)
-for(z=a.firstChild;z!=null;z=z.nextSibling)A.om(z,b)},p1:function(a,b,c,d){var z
+for(z=a.firstChild;z!=null;z=z.nextSibling)A.Vx(z,b)},p1:function(a,b,c,d){var z
if($.ZH().mL(C.R5))$.ZH().J4("["+H.d(c)+"]: bindProperties: ["+H.d(d)+"] to ["+J.Ro(a)+"].["+H.d(b)+"]")
z=L.ao(c,d,null)
if(z.gP(z)==null)z.sP(z,H.vn(a).rN(b).Ax)
@@ -17175,10 +18106,14 @@
for(;z=J.TZ(a),z!=null;a=z);y=$.od()
return y.t(y,a)},HR:function(a,b,c){var z,y,x
z=H.vn(a)
-y=J.UQ(H.jO(J.bB(z.Ax).IE).gtx(),b)
+y=A.Rk(H.jO(J.bB(z.Ax).IE),b)
if(y!=null){x=y.gJx()
x=x.ev(x,new A.uJ())
-C.Nm.sB(c,x.gB(x))}return z.CI(b,c).Ax},ZI:function(a,b){var z,y
+C.Nm.sB(c,x.gB(x))}return z.CI(b,c).Ax},Rk:function(a,b){var z,y
+do{z=J.UQ(a.gYK(),b)
+y=J.x(z)
+if(typeof z==="object"&&z!==null&&!!y.$isRS)return z
+a=a.gAY()}while(a!=null)},ZI:function(a,b){var z,y
if(a==null)return
z=document.createElement("style",null)
z.textContent=a.textContent
@@ -17225,7 +18160,7 @@
t=t.MM
if(t.Gv!==0)H.vh(new P.lj("Future already completed"))
t.CG(w,x)}}},GA:function(a,b,c,d){var z,y,x,w,v,u
-if(c==null)c=P.Ls(null,null,null,W.YN)
+if(c==null)c=P.Ls(null,null,null,W.QF)
if(d==null){d=[]
d.$builtinTypeInfo=[J.O]}if(a==null){z="warning: "+H.d(b)+" not found."
y=$.oK
@@ -17252,37 +18187,17 @@
z=$.UG().nb
v=z.t(z,w)
if(v!=null)x=v}if(x==null){$.M7().To(H.d(y)+" library not found")
-return}z=x.gmu().nb
-z=z.gUQ(z)
-u=z.Kw
-u=u.gA(u)
-t=H.Y9(z.$asi1,H.oX(z))
-s=t==null?null:t[0]
-t=H.Y9(z.$asi1,H.oX(z))
-r=t==null?null:t[1]
-z=new H.MH(null,u,z.ew)
-z.$builtinTypeInfo=[s,r]
-for(;z.G();)A.h5(x,z.mD)
-z=J.pP(x)
-z=z.gUQ(z)
-u=z.Kw
-u=u.gA(u)
-t=H.Y9(z.$asi1,H.oX(z))
-s=t==null?null:t[0]
-t=H.Y9(z.$asi1,H.oX(z))
-r=t==null?null:t[1]
-z=new H.MH(null,u,z.ew)
-z.$builtinTypeInfo=[s,r]
-for(;z.G();){q=z.mD
-for(u=J.GP(q.gc9());u.G();){p=u.gl().gAx()
-s=J.x(p)
-if(typeof p==="object"&&p!==null&&!!s.$isV3){s=p.ns
-o=M.Lh(q)
-if(o==null)o=C.hG
-r=$.Ej()
-r.u(r,s,o)
-r=$.p2()
-n=r.Rz(r,s)
+return}for(z=J.vo(J.hI(x.gYK()),new A.Fn()),z=z.gA(z),u=z.RX;z.G();)A.h5(x,u.gl())
+for(z=J.vo(J.hI(x.gYK()),new A.e3()),z=z.gA(z),u=z.RX;z.G();){t=u.gl()
+for(s=J.GP(t.gc9());s.G();){r=s.gl().gAx()
+q=J.x(r)
+if(typeof r==="object"&&r!==null&&!!q.$isV3){q=r.ns
+p=M.Lh(t)
+if(p==null)p=C.hG
+o=$.Ej()
+o.u(o,q,p)
+o=$.p2()
+n=o.Rz(o,q)
if(n!=null)J.Or(n)}}}},h5:function(a,b){var z,y,x
for(z=J.GP(b.gc9());y=!1,z.G();)if(z.gl().gAx()===C.za){y=!0
break}if(!y)return
@@ -17343,7 +18258,7 @@
z=a.Dg
if(z!=null)a.Q0=this.Pv(a,z)
this.oq(a,y)},
-fj:function(a,b,c){var z,y
+fj:function(a,b,c){var z,y,x
this.uG(a)
this.W3(a,a.EX)
this.Mi(a)
@@ -17352,8 +18267,10 @@
this.u5(a)
A.hO(this.gr3(a),b,c)
z=P.re(a.di)
-y=J.UQ(z.gtx(),C.Qi)
-if(y!=null&&y.gFo()&&y.guU())z.CI(C.Qi,[a])},
+y=J.UQ(z.gYK(),C.Qi)
+if(y!=null){x=J.x(y)
+x=typeof y==="object"&&y!==null&&!!x.$isRS&&y.gFo()&&y.guU()}else x=!1
+if(x)z.CI(C.Qi,[a])},
Ba:function(a,b){var z,y,x,w
for(z=a,y=null;z!=null;){x=J.RE(z)
y=x.gQg(z).MW.getAttribute("extends")
@@ -17374,9 +18291,7 @@
z=z!=null&&z.x4(w)}else z=!1
if(z)continue
v=new H.GD(H.le(w))
-u=J.UQ(b.gYK(),v)
-z=J.x(u)
-if(typeof u==="object"&&u!==null&&!!z.$isRS){if(!u.glT()||!A.bc(b,u))u=null}else if(typeof u!=="object"||u===null||!z.$isRY)u=null
+u=A.Oy(b,v)
if(u==null){window
z=$.UT()
t="property for attribute "+w+" of polymer-element name="+a.S6+" not found."
@@ -17438,6 +18353,8 @@
new W.E9(z).MW.setAttribute("element",a.S6+"-"+c)
return z},
oq:function(a,b){var z,y,x,w
+if(J.xC(b,$.Tf()))return
+this.oq(a,b.gAY())
for(z=J.GP(J.hI(b.gYK()));z.G();){y=z.gl()
x=J.x(y)
if(typeof y!=="object"||y===null||!x.$isRS||y.gFo()||!y.guU())continue
@@ -17493,16 +18410,16 @@
$isEH:true,
$is_bh:true},w12:{"":"Tp;",
call$0:function(){var z=P.L5(null,null,null,J.O,J.O)
-C.FS.aN(C.FS,new A.fTP(z))
+C.FS.aN(C.FS,new A.ppY(z))
return z},
"+call:0:0":0,
$isEH:true,
-$is_X0:true},fTP:{"":"Tp;a",
+$is_X0:true},ppY:{"":"Tp;a",
call$2:function(a,b){var z=this.a
z.u(z,b,a)},
"+call:2:0":0,
$isEH:true,
-$is_bh:true},yL:{"":"Fa;",$isyL:true},dM:{"":["a;KM=-",function(){return[C.nJ]}],
+$is_bh:true},yL:{"":"ndx;",$isyL:true},dM:{"":["a;KM=-",function(){return[C.nJ]}],
gpQ:function(a){return!1},
"+applyAuthorStyles":0,
Pa:function(a){if(W.uV(this.gM0(a).defaultView)!=null||$.M0>0)this.Ec(a)},
@@ -17530,7 +18447,7 @@
z=J.RE(b)
y=z.Ja(b,"template")
if(y!=null)if(J.Vs(a.ZI).MW.hasAttribute("lightdom")===!0){this.vs(a,y)
-x=null}else x=this.TH(a,y)
+x=null}else x=this.Tp(a,y)
else x=null
w=J.x(x)
if(typeof x!=="object"||x===null||!w.$isI0)return
@@ -17546,7 +18463,7 @@
this.jx(a,y)
this.lj(a,a)
return y},
-TH:function(a,b){var z,y
+Tp:function(a,b){var z,y
if(b==null)return
this.gKE(a)
z=this.er(a)
@@ -17620,7 +18537,7 @@
z=a.TQ
if(z!=null){z.TP(z)
a.TQ=null}if(b===!0)return
-A.om(this.gKE(a),new A.TV())},
+A.Vx(this.gKE(a),new A.TV())},
oW:function(a){return this.BT(a,null)},
Xl:function(a){var z,y,x,w,v,u,t
z=a.ZI
@@ -17747,7 +18664,7 @@
y=z.t(z,a)
if(y!=null){z=this.b
x=J.RE(b)
-J.GS(z,a,x.gzZ(b),x.gjL(b))
+J.Ut(z,a,x.gzZ(b),x.gjL(b))
A.HR(z,y,[x.gjL(b),x.gzZ(b),this.c])}},
"+call:2:0":0,
$isEH:true,
@@ -17842,8 +18759,8 @@
a.Ye=z
a.mT=y
a.KM=v
-C.GB.ZL(a)
-C.GB.FH(a)
+C.Iv.ZL(a)
+C.Iv.FH(a)
return a},"+new PolymerElement$created:0:0":0}},Tt:{"":["qE+dM;KM=-",function(){return[C.nJ]}],$isdM:true,$ishs:true,$isd3:true,$iscv:true,$isGv:true,$isKV:true,$isD0:true},GN:{"":"Tt+Pi;",$isd3:true},k8:{"":"a;jL>,zZ*",$isk8:true},HJ:{"":"e9;nF"},S0:{"":"a;Ow,VC",
E5:function(){return this.Ow.call$0()},
TP:function(a){var z=this.VC
@@ -17859,12 +18776,24 @@
"+call:1:0":0,
$isEH:true,
$is_HB:true,
+$is_Dv:true},Fn:{"":"Tp;",
+call$1:function(a){var z=J.x(a)
+return typeof a==="object"&&a!==null&&!!z.$isRS},
+"+call:1:0":0,
+$isEH:true,
+$is_HB:true,
+$is_Dv:true},e3:{"":"Tp;",
+call$1:function(a){var z=J.x(a)
+return typeof a==="object"&&a!==null&&!!z.$isMs},
+"+call:1:0":0,
+$isEH:true,
+$is_HB:true,
$is_Dv:true},pM:{"":"Tp;",
call$1:function(a){return!a.gQ2()},
"+call:1:0":0,
$isEH:true,
$is_HB:true,
-$is_Dv:true},Mh:{"":"a;"}}],["polymer.deserialize","package:polymer/deserialize.dart",,Z,{Zh:function(a,b,c){var z,y,x
+$is_Dv:true},jh:{"":"a;"}}],["polymer.deserialize","package:polymer/deserialize.dart",,Z,{Zh:function(a,b,c){var z,y,x
z=J.UQ($.WJ(),c.gvd())
if(z!=null)return z.call$2(a,b)
try{y=C.lM.kV(J.JA(a,"'","\""))
@@ -17876,7 +18805,7 @@
z.u(z,C.nz,new Z.pp())
z.u(z,C.Ts,new Z.Nq())
z.u(z,C.PC,new Z.nl())
-z.u(z,C.md,new Z.ej())
+z.u(z,C.md,new Z.ik())
return z},
"+call:0:0":0,
$isEH:true,
@@ -17908,7 +18837,7 @@
"+call:1:0":0,
$isEH:true,
$is_HB:true,
-$is_Dv:true},ej:{"":"Tp;",
+$is_Dv:true},ik:{"":"Tp;",
call$2:function(a,b){return H.IH(a,new Z.HK(b))},
"+call:2:0":0,
$isEH:true,
@@ -17957,8 +18886,8 @@
gca:function(){return new T.Dw(this,T.e9.prototype.yt,null,"yt")},
A5:function(a){return new T.uK(this)}},Xy:{"":"Tp;a,b,c",
call$2:function(a,b){var z=J.x(a)
-if(typeof a!=="object"||a===null||!z.$isz6)a=new K.z6(null,a,V.WF(this.a.nF,null,null),null)
-z=J.x(b)
+if(typeof a!=="object"||a===null||!z.$isz6){z=this.a.nF
+a=new K.z6(null,a,V.WF(z==null?H.B7([],P.L5(null,null,null,null,null)):z,null,null),null)}z=J.x(b)
z=typeof b==="object"&&b!==null&&!!z.$iscv
if(z&&J.xC(this.b,"class"))return T.FL(this.c,a,T.qP)
if(z&&J.xC(this.b,"style"))return T.FL(this.c,a,T.Fx)
@@ -17967,7 +18896,9 @@
$isEH:true,
$is_bh:true},uK:{"":"Tp;a",
call$1:function(a){var z=J.x(a)
-return typeof a==="object"&&a!==null&&!!z.$isz6?a:new K.z6(null,a,V.WF(this.a.nF,null,null),null)},
+if(typeof a==="object"&&a!==null&&!!z.$isz6)z=a
+else{z=this.a.nF
+z=new K.z6(null,a,V.WF(z==null?H.B7([],P.L5(null,null,null,null,null)):z,null,null),null)}return z},
"+call:1:0":0,
$isEH:true,
$is_HB:true,
@@ -17981,14 +18912,14 @@
F.Wi(this,C.ls,z,this.uK)},
gnc:function(){return new H.Pm(this,T.mY.prototype.vr,null,"vr")},
gP:function(a){return this.uK
-"35,33"},
+"37,35"},
"+value":1,
r6:function(a,b){return this.gP(a).call$1(b)},
sP:function(a,b){var z,y,x,w
try{K.jX(this.jf,b,this.qc)}catch(y){x=H.Ru(y)
w=J.x(x)
if(typeof x==="object"&&x!==null&&!!w.$isB0){z=x
-$.IS().A3("Error evaluating expression '"+H.d(this.jf)+"': "+J.z2(z))}else throw y}"35,101,35,33"},
+$.IS().A3("Error evaluating expression '"+H.d(this.jf)+"': "+J.z2(z))}else throw y}"37,105,37,35"},
"+value=":1,
Va:function(a,b,c){var z,y,x,w,v
y=this.jf
@@ -18036,25 +18967,23 @@
H.VM(x,[U.hw])
for(;w=z.a,v=J.RE(w),typeof w==="object"&&w!==null&&!!v.$isuk;){if(!J.xC(v.gkp(w),"|"))break
x.push(v.gT8(w))
-z.a=v.gBb(w)}z=z.a
-w=J.x(z)
-if(typeof z==="object"&&z!==null&&!!w.$isw6){u=w.gP(z)
+z.a=v.gBb(w)}w=z.a
+v=J.x(w)
+if(typeof w==="object"&&w!==null&&!!v.$isw6){u=v.gP(w)
t=C.OL
-s=!1}else if(typeof z==="object"&&z!==null&&!!w.$isRW){t=z.ghP()
-if(J.xC(w.gbP(z),"[]")){w=z.gre()
-if(0>=w.length)throw H.e(w,0)
-w=w[0]
+s=!1}else if(typeof w==="object"&&w!==null&&!!v.$iszX){w=w.gJn()
v=J.x(w)
if(typeof w!=="object"||w===null||!v.$isno)y.call$0()
-z=z.gre()
-if(0>=z.length)throw H.e(z,0)
-u=J.Vm(z[0])
-s=!0}else{if(w.gbP(z)!=null){if(z.gre()!=null)y.call$0()
-u=w.gbP(z)}else{y.call$0()
-u=null}s=!1}}else{y.call$0()
+z=z.a
+t=z.ghP()
+u=J.Vm(z.gJn())
+s=!0}else{if(typeof w==="object"&&w!==null&&!!v.$isx9){t=w.ghP()
+u=v.goc(w)}else if(typeof w==="object"&&w!==null&&!!v.$isRW){t=w.ghP()
+if(v.gbP(w)!=null){if(z.a.gre()!=null)y.call$0()
+u=J.vF(z.a)}else{y.call$0()
+u=null}}else{y.call$0()
t=null
-u=null
-s=!1}for(z=new H.a7(x,x.length,0,null),H.VM(z,[H.W8(x,"Q",0)]);z.G();){r=z.mD
+u=null}s=!1}for(z=new H.a7(x,x.length,0,null),H.VM(z,[H.W8(x,"Q",0)]);z.G();){r=z.mD
q=J.UK(r,new K.G1(c,P.NZ(null,null)))
J.UK(q,new K.Ed(c))
q.gLv()
@@ -18195,6 +19124,7 @@
x.Iv(z)}},
bu:function(a){var z=this.KL
return z.bu(z)},
+"+toString:0:0":0,
$ishw:true},Ed:{"":"a0;Jd",
xn:function(a){a.yc(a,this.Jd)},
ky:function(a){J.UK(a.gT8(a),this)
@@ -18202,6 +19132,18 @@
W9:function(a){return new K.Wh(a,null,null,null,P.bK(null,null,!1,null))},
LT:function(a){var z=a.wz
return z.RR(z,this)},
+co:function(a){var z,y
+z=J.UK(a.ghP(),this)
+y=new K.vl(z,a,null,null,null,P.bK(null,null,!1,null))
+z.sbO(y)
+return y},
+CU:function(a){var z,y,x
+z=J.UK(a.ghP(),this)
+y=J.UK(a.gJn(),this)
+x=new K.iT(z,y,a,null,null,null,P.bK(null,null,!1,null))
+z.sbO(x)
+y.sbO(x)
+return x},
Y7:function(a){var z,y,x,w,v
z=J.UK(a.ghP(),this)
y=a.gre()
@@ -18333,44 +19275,95 @@
$ishw:true},ky:{"":"Ay;Bb>,T8>,KL,bO,tj,Lv,k6",
gkp:function(a){var z=this.KL
return z.gkp(z)},
-Qh:function(a){var z,y,x
-z=$.bF()
+Qh:function(a){var z,y,x,w
+z=$.e6()
y=this.KL
x=z.t(z,y.gkp(y))
if(J.xC(y.gkp(y),"&&")||J.xC(y.gkp(y),"||")){z=this.Bb.gLv()
if(z==null)z=!1
y=this.T8.gLv()
this.Lv=x.call$2(z,y==null?!1:y)}else if(J.xC(y.gkp(y),"==")||J.xC(y.gkp(y),"!="))this.Lv=x.call$2(this.Bb.gLv(),this.T8.gLv())
-else{z=this.Bb.gLv()
-if(z==null||this.T8.gLv()==null)this.Lv=null
-else this.Lv=x.call$2(z,this.T8.gLv())}},
+else{z=this.Bb
+if(z.gLv()==null||this.T8.gLv()==null)this.Lv=null
+else{if(J.xC(y.gkp(y),"|")){y=z.gLv()
+w=J.x(y)
+w=typeof y==="object"&&y!==null&&!!w.$iswn
+y=w}else y=!1
+if(y)this.tj=H.Go(z.gLv(),"$iswn").gRT().yI(new K.uA(this,a))
+this.Lv=x.call$2(z.gLv(),this.T8.gLv())}}},
RR:function(a,b){return b.im(this)},
$asAy:function(){return[U.uk]},
$isuk:true,
-$ishw:true},fa:{"":"Ay;hP<,re<,KL,bO,tj,Lv,k6",
-glT:function(){return this.KL.glT()},
+$ishw:true},uA:{"":"Tp;a,b",
+call$1:function(a){return this.a.DX(this.b)},
+"+call:1:0":0,
+$isEH:true,
+$is_HB:true,
+$is_Dv:true},vl:{"":"Ay;hP<,KL,bO,tj,Lv,k6",
+goc:function(a){var z=this.KL
+return z.goc(z)},
+"+name":0,
+Qh:function(a){var z,y,x
+z=this.hP.gLv()
+if(z==null){this.Lv=null
+return}y=this.KL
+x=new H.GD(H.le(y.goc(y)))
+this.Lv=H.vn(z).rN(x).Ax
+y=J.RE(z)
+if(typeof z==="object"&&z!==null&&!!y.$isd3)this.tj=y.gqh(z).yI(new K.Li(this,a,x))},
+RR:function(a,b){return b.co(this)},
+$asAy:function(){return[U.x9]},
+$isx9:true,
+$ishw:true},Li:{"":"Tp;a,b,c",
+call$1:function(a){if(J.ja(a,new K.WK(this.c))===!0)this.a.DX(this.b)},
+"+call:1:0":0,
+$isEH:true,
+$is_HB:true,
+$is_Dv:true},WK:{"":"Tp;d",
+call$1:function(a){var z=J.x(a)
+return typeof a==="object"&&a!==null&&!!z.$isqI&&J.xC(a.oc,this.d)},
+"+call:1:0":0,
+$isEH:true,
+$is_HB:true,
+$is_Dv:true},iT:{"":"Ay;hP<,Jn<,KL,bO,tj,Lv,k6",
+Qh:function(a){var z,y,x
+z=this.hP.gLv()
+if(z==null){this.Lv=null
+return}y=this.Jn.gLv()
+x=J.U6(z)
+this.Lv=x.t(z,y)
+if(typeof z==="object"&&z!==null&&!!x.$isd3)this.tj=x.gqh(z).yI(new K.tE(this,a,y))},
+RR:function(a,b){return b.CU(this)},
+$asAy:function(){return[U.zX]},
+$iszX:true,
+$ishw:true},tE:{"":"Tp;a,b,c",
+call$1:function(a){if(J.ja(a,new K.GS(this.c))===!0)this.a.DX(this.b)},
+"+call:1:0":0,
+$isEH:true,
+$is_HB:true,
+$is_Dv:true},GS:{"":"Tp;d",
+call$1:function(a){var z=J.x(a)
+return typeof a==="object"&&a!==null&&!!z.$isHA&&J.xC(a.G3,this.d)},
+"+call:1:0":0,
+$isEH:true,
+$is_HB:true,
+$is_Dv:true},fa:{"":"Ay;hP<,re<,KL,bO,tj,Lv,k6",
gbP:function(a){var z=this.KL
return z.gbP(z)},
-Qh:function(a){var z,y,x,w,v,u
+Qh:function(a){var z,y,x,w
z=this.re
-if(z==null)y=[]
-else{z.toString
+z.toString
z=new H.A8(z,new K.WW())
H.VM(z,[null,null])
-y=z.tt(z,!1)}x=this.hP.gLv()
-if(x==null)this.Lv=null
-else{z=this.KL
-if(z.gbP(z)==null)if(z.glT())this.Lv=x
-else this.Lv=K.Ku(x,y)
-else if(J.xC(z.gbP(z),"[]")){if(0>=y.length)throw H.e(y,0)
-w=y[0]
-z=J.U6(x)
-this.Lv=z.t(x,w)
-if(typeof x==="object"&&x!==null&&!!z.$isd3)this.tj=z.gqh(x).yI(new K.vQ(this,a,w))}else{v=H.vn(x)
-u=new H.GD(H.le(z.gbP(z)))
-this.Lv=z.glT()?v.rN(u).Ax:v.F2(u,y,null).Ax
+y=z.br(z)
+x=this.hP.gLv()
+if(x==null){this.Lv=null
+return}z=this.KL
+if(z.gbP(z)==null)this.Lv=K.Ku(x,y)
+else{w=new H.GD(H.le(z.gbP(z)))
+this.Lv=H.vn(x).F2(w,y,null).Ax
z=J.RE(x)
-if(typeof x==="object"&&x!==null&&!!z.$isd3)this.tj=z.gqh(x).yI(new K.jh(this,a,u))}}},
+if(typeof x==="object"&&x!==null&&!!z.$isd3)this.tj=z.gqh(x).yI(new K.vQ(this,a,w))}},
RR:function(a,b){return b.Y7(this)},
$asAy:function(){return[U.RW]},
$isRW:true,
@@ -18386,18 +19379,7 @@
$is_HB:true,
$is_Dv:true},a9:{"":"Tp;d",
call$1:function(a){var z=J.x(a)
-return typeof a==="object"&&a!==null&&!!z.$isHA&&J.xC(a.G3,this.d)},
-"+call:1:0":0,
-$isEH:true,
-$is_HB:true,
-$is_Dv:true},jh:{"":"Tp;e,f,g",
-call$1:function(a){if(J.ja(a,new K.e3(this.g))===!0)this.e.DX(this.f)},
-"+call:1:0":0,
-$isEH:true,
-$is_HB:true,
-$is_Dv:true},e3:{"":"Tp;h",
-call$1:function(a){var z=J.x(a)
-return typeof a==="object"&&a!==null&&!!z.$isqI&&J.xC(a.oc,this.h)},
+return typeof a==="object"&&a!==null&&!!z.$isqI&&J.xC(a.oc,this.d)},
"+call:1:0":0,
$isEH:true,
$is_HB:true,
@@ -18427,6 +19409,7 @@
$is_HB:true,
$is_Dv:true},B0:{"":"a;G1>",
bu:function(a){return"EvalException: "+this.G1},
+"+toString:0:0":0,
$isB0:true,
static:{yN:function(a){return new K.B0(a)}}}}],["polymer_expressions.expression","package:polymer_expressions/expression.dart",,U,{ZP:function(a,b){var z,y,x
z=J.x(a)
@@ -18448,111 +19431,165 @@
a=536870911&a+((67108863&a)<<3>>>0)
a=(a^C.jn.m(a,11))>>>0
return 536870911&a+((16383&a)<<15>>>0)},Fq:{"":"a;",
+Bf:function(a,b,c){return new U.zX(b,c)},
+"+index:2:0":0,
+gvH:function(a){return new A.Y7(this,U.Fq.prototype.Bf,a,"Bf")},
F2:function(a,b,c){return new U.RW(a,b,c)},
-"+invoke:3:0":0,
-"*invoke":[35],
-CI:function(a,b){return this.F2(a,b,null)},
-"+invoke:2:0":0},hw:{"":"a;",$ishw:true},EZ:{"":"hw;",
+"+invoke:3:0":0},hw:{"":"a;",$ishw:true},EZ:{"":"hw;",
RR:function(a,b){return b.W9(this)},
$isEZ:true},no:{"":"hw;P>",
r6:function(a,b){return this.P.call$1(b)},
RR:function(a,b){return b.I6(this)},
bu:function(a){var z=this.P
return typeof z==="string"?"\""+H.d(z)+"\"":H.d(z)},
+"+toString:0:0":0,
n:function(a,b){var z
if(b==null)return!1
z=H.RB(b,"$isno",[H.W8(this,"no",0)],"$asno")
return z&&J.xC(J.Vm(b),this.P)},
+"+==:1:0":0,
giO:function(a){return J.v1(this.P)},
+"+hashCode":0,
$isno:true},kB:{"":"hw;Pu>",
RR:function(a,b){return b.o0(this)},
bu:function(a){return"{"+H.d(this.Pu)+"}"},
+"+toString:0:0":0,
n:function(a,b){var z
if(b==null)return!1
z=J.RE(b)
return typeof b==="object"&&b!==null&&!!z.$iskB&&U.ZP(z.gPu(b),this.Pu)},
+"+==:1:0":0,
giO:function(a){return U.au(this.Pu)},
+"+hashCode":0,
$iskB:true},ae:{"":"hw;G3>,v4<",
RR:function(a,b){return b.YV(this)},
bu:function(a){return H.d(this.G3)+": "+H.d(this.v4)},
+"+toString:0:0":0,
n:function(a,b){var z
if(b==null)return!1
z=J.RE(b)
return typeof b==="object"&&b!==null&&!!z.$isae&&J.xC(z.gG3(b),this.G3)&&J.xC(b.gv4(),this.v4)},
+"+==:1:0":0,
giO:function(a){var z,y
z=J.v1(this.G3.P)
y=J.v1(this.v4)
return U.Up(U.Zm(U.Zm(0,z),y))},
+"+hashCode":0,
$isae:true},Iq:{"":"hw;wz",
RR:function(a,b){return b.LT(this)},
bu:function(a){return"("+H.d(this.wz)+")"},
+"+toString:0:0":0,
n:function(a,b){var z
if(b==null)return!1
z=J.x(b)
return typeof b==="object"&&b!==null&&!!z.$isIq&&J.xC(b.wz,this.wz)},
+"+==:1:0":0,
giO:function(a){return J.v1(this.wz)},
+"+hashCode":0,
$isIq:true},w6:{"":"hw;P>",
r6:function(a,b){return this.P.call$1(b)},
RR:function(a,b){return b.qv(this)},
bu:function(a){return this.P},
+"+toString:0:0":0,
n:function(a,b){var z
if(b==null)return!1
z=J.RE(b)
return typeof b==="object"&&b!==null&&!!z.$isw6&&J.xC(z.gP(b),this.P)},
+"+==:1:0":0,
giO:function(a){return J.v1(this.P)},
+"+hashCode":0,
$isw6:true},jK:{"":"hw;kp>,wz<",
RR:function(a,b){return b.Hx(this)},
bu:function(a){return H.d(this.kp)+" "+H.d(this.wz)},
+"+toString:0:0":0,
n:function(a,b){var z
if(b==null)return!1
z=J.RE(b)
return typeof b==="object"&&b!==null&&!!z.$isjK&&J.xC(z.gkp(b),this.kp)&&J.xC(b.gwz(),this.wz)},
+"+==:1:0":0,
giO:function(a){var z,y
z=J.v1(this.kp)
y=J.v1(this.wz)
return U.Up(U.Zm(U.Zm(0,z),y))},
+"+hashCode":0,
$isjK:true},uk:{"":"hw;kp>,Bb>,T8>",
RR:function(a,b){return b.im(this)},
bu:function(a){return"("+H.d(this.Bb)+" "+H.d(this.kp)+" "+H.d(this.T8)+")"},
+"+toString:0:0":0,
n:function(a,b){var z
if(b==null)return!1
z=J.RE(b)
return typeof b==="object"&&b!==null&&!!z.$isuk&&J.xC(z.gkp(b),this.kp)&&J.xC(z.gBb(b),this.Bb)&&J.xC(z.gT8(b),this.T8)},
+"+==:1:0":0,
giO:function(a){var z,y,x
z=J.v1(this.kp)
y=J.v1(this.Bb)
x=J.v1(this.T8)
return U.Up(U.Zm(U.Zm(U.Zm(0,z),y),x))},
+"+hashCode":0,
$isuk:true},K9:{"":"hw;Bb>,T8>",
RR:function(a,b){return b.ky(this)},
bu:function(a){return"("+H.d(this.Bb)+" in "+H.d(this.T8)+")"},
+"+toString:0:0":0,
n:function(a,b){var z
if(b==null)return!1
z=J.RE(b)
return typeof b==="object"&&b!==null&&!!z.$isK9&&J.xC(z.gBb(b),this.Bb)&&J.xC(z.gT8(b),this.T8)},
+"+==:1:0":0,
giO:function(a){var z,y
z=this.Bb
z=z.giO(z)
y=J.v1(this.T8)
return U.Up(U.Zm(U.Zm(0,z),y))},
-$isK9:true},RW:{"":"hw;hP<,bP>,re<",
+"+hashCode":0,
+$isK9:true},zX:{"":"hw;hP<,Jn<",
+RR:function(a,b){return b.CU(this)},
+bu:function(a){return H.d(this.hP)+"["+H.d(this.Jn)+"]"},
+"+toString:0:0":0,
+n:function(a,b){var z
+if(b==null)return!1
+z=J.x(b)
+return typeof b==="object"&&b!==null&&!!z.$iszX&&J.xC(b.ghP(),this.hP)&&J.xC(b.gJn(),this.Jn)},
+"+==:1:0":0,
+giO:function(a){var z,y
+z=J.v1(this.hP)
+y=J.v1(this.Jn)
+return U.Up(U.Zm(U.Zm(0,z),y))},
+"+hashCode":0,
+$iszX:true},x9:{"":"hw;hP<,oc>",
+RR:function(a,b){return b.co(this)},
+bu:function(a){return H.d(this.hP)+"."+H.d(this.oc)},
+"+toString:0:0":0,
+n:function(a,b){var z
+if(b==null)return!1
+z=J.RE(b)
+return typeof b==="object"&&b!==null&&!!z.$isx9&&J.xC(b.ghP(),this.hP)&&J.xC(z.goc(b),this.oc)},
+"+==:1:0":0,
+giO:function(a){var z,y
+z=J.v1(this.hP)
+y=J.v1(this.oc)
+return U.Up(U.Zm(U.Zm(0,z),y))},
+"+hashCode":0,
+$isx9:true},RW:{"":"hw;hP<,bP>,re<",
RR:function(a,b){return b.Y7(this)},
-glT:function(){return this.re==null},
bu:function(a){return H.d(this.hP)+"."+H.d(this.bP)+"("+H.d(this.re)+")"},
+"+toString:0:0":0,
n:function(a,b){var z
if(b==null)return!1
z=J.RE(b)
return typeof b==="object"&&b!==null&&!!z.$isRW&&J.xC(b.ghP(),this.hP)&&J.xC(z.gbP(b),this.bP)&&U.ZP(b.gre(),this.re)},
+"+==:1:0":0,
giO:function(a){var z,y,x
z=J.v1(this.hP)
y=J.v1(this.bP)
x=U.au(this.re)
return U.Up(U.Zm(U.Zm(U.Zm(0,z),y),x))},
+"+hashCode":0,
$isRW:true},xs:{"":"Tp;",
call$2:function(a,b){return U.Zm(a,J.v1(b))},
"+call:2:0":0,
$isEH:true,
-$is_bh:true}}],["polymer_expressions.parser","package:polymer_expressions/parser.dart",,T,{FX:{"":"a;Sk,Ix,ku,fL,lQ",
+$is_bh:true}}],["polymer_expressions.parser","package:polymer_expressions/parser.dart",,T,{FX:{"":"a;Sk,Ix,ku,fL",
oK:function(){var z,y
this.ku=this.Ix.zl()
z=this.ku
@@ -18563,34 +19600,29 @@
this.w5()
return this.o9()},
Gd:function(a,b){var z
-if(a!=null){z=J.Iz(this.lQ)
-z=z==null?a!=null:z!==a}else z=!1
-if(!z)z=b!=null&&!J.xC(J.Vm(this.lQ),b)
+if(!(a!=null&&!J.xC(J.Iz(this.fL.mD),a)))z=b!=null&&!J.xC(J.Vm(this.fL.mD),b)
else z=!0
-if(z)throw H.b(Y.RV("Expected "+b+": "+H.d(this.lQ)))
-this.lQ=this.fL.G()?this.fL.mD:null},
+if(z)throw H.b(Y.RV("Expected "+b+": "+H.d(this.fL.mD)))
+this.fL.G()},
w5:function(){return this.Gd(null,null)},
-o9:function(){if(this.lQ==null){this.Sk.toString
+o9:function(){if(this.fL.mD==null){this.Sk.toString
return C.OL}var z=this.Dl()
return z==null?null:this.BH(z,0)},
-BH:function(a,b){var z,y,x,w,v,u
-for(z=this.Sk;y=this.lQ,y!=null;){x=J.RE(y)
-w=x.gfY(y)
-if(w===9)if(J.xC(x.gP(y),"(")){v=this.qk()
+BH:function(a,b){var z,y,x,w
+for(z=this.Sk;y=this.fL.mD,y!=null;)if(J.xC(J.Iz(y),9))if(J.xC(J.Vm(this.fL.mD),"(")){x=this.qk()
z.toString
-a=new U.RW(a,null,v)}else if(J.xC(J.Vm(this.lQ),"[")){u=this.bK()
-v=u==null?[]:[u]
+a=new U.RW(a,null,x)}else if(J.xC(J.Vm(this.fL.mD),"[")){w=this.bK()
z.toString
-a=new U.RW(a,"[]",v)}else break
-else if(w===3){this.w5()
-a=this.ct(a,this.Dl())}else if(w===10&&J.xC(x.gP(y),"in"))a=this.xo(a)
-else{y=this.lQ
-if(J.Iz(y)===8&&J.J5(y.gG8(),b))a=this.Tw(a)
-else break}}return a},
-ct:function(a,b){var z,y
+a=new U.zX(a,w)}else break
+else if(J.xC(J.Iz(this.fL.mD),3)){this.w5()
+a=this.qL(a,this.Dl())}else if(J.xC(J.Iz(this.fL.mD),10)&&J.xC(J.Vm(this.fL.mD),"in"))a=this.xo(a)
+else if(J.xC(J.Iz(this.fL.mD),8)&&J.J5(this.fL.mD.gG8(),b))a=this.Tw(a)
+else break
+return a},
+qL:function(a,b){var z,y
if(typeof b==="object"&&b!==null&&!!b.$isw6){z=b.gP(b)
this.Sk.toString
-return new U.RW(a,z,null)}else{if(typeof b==="object"&&b!==null&&!!b.$isRW){z=b.ghP()
+return new U.x9(a,z)}else{if(typeof b==="object"&&b!==null&&!!b.$isRW){z=b.ghP()
y=J.x(z)
y=typeof z==="object"&&z!==null&&!!y.$isw6
z=y}else z=!1
@@ -18598,73 +19630,66 @@
y=b.gre()
this.Sk.toString
return new U.RW(a,z,y)}else throw H.b(Y.RV("expected identifier: "+H.d(b)))}},
-Tw:function(a){var z,y,x,w
-z=this.lQ
+Tw:function(a){var z,y,x
+z=this.fL.mD
this.w5()
y=this.Dl()
-while(!0){x=this.lQ
-if(x!=null){w=J.Iz(x)
-x=(w===8||w===3||w===9)&&J.xZ(x.gG8(),z.gG8())}else x=!1
+while(!0){x=this.fL.mD
+if(x!=null)x=(J.xC(J.Iz(x),8)||J.xC(J.Iz(this.fL.mD),3)||J.xC(J.Iz(this.fL.mD),9))&&J.xZ(this.fL.mD.gG8(),z.gG8())
+else x=!1
if(!x)break
-y=this.BH(y,this.lQ.gG8())}x=J.Vm(z)
+y=this.BH(y,this.fL.mD.gG8())}x=J.Vm(z)
this.Sk.toString
return new U.uk(x,a,y)},
Dl:function(){var z,y,x,w
-z=this.lQ
-y=J.RE(z)
-if(y.gfY(z)===8){x=y.gP(z)
-z=J.x(x)
-if(z.n(x,"+")||z.n(x,"-")){this.w5()
-z=J.Iz(this.lQ)
-if(z===6){z=H.BU(H.d(x)+H.d(J.Vm(this.lQ)),null,null)
+if(J.xC(J.Iz(this.fL.mD),8)){z=J.Vm(this.fL.mD)
+y=J.x(z)
+if(y.n(z,"+")||y.n(z,"-")){this.w5()
+if(J.xC(J.Iz(this.fL.mD),6)){y=H.BU(H.d(z)+H.d(J.Vm(this.fL.mD)),null,null)
this.Sk.toString
-x=new U.no(z)
-x.$builtinTypeInfo=[null]
+z=new U.no(y)
+z.$builtinTypeInfo=[null]
this.w5()
-return x}else{y=this.Sk
-if(z===7){z=H.IH(H.d(x)+H.d(J.Vm(this.lQ)),null)
+return z}else{y=this.Sk
+if(J.xC(J.Iz(this.fL.mD),7)){x=H.IH(H.d(z)+H.d(J.Vm(this.fL.mD)),null)
y.toString
-x=new U.no(z)
-x.$builtinTypeInfo=[null]
+z=new U.no(x)
+z.$builtinTypeInfo=[null]
this.w5()
-return x}else{w=this.BH(this.lb(),11)
+return z}else{w=this.BH(this.lb(),11)
y.toString
-return new U.jK(x,w)}}}else if(z.n(x,"!")){this.w5()
+return new U.jK(z,w)}}}else if(y.n(z,"!")){this.w5()
w=this.BH(this.lb(),11)
this.Sk.toString
-return new U.jK(x,w)}}return this.lb()},
-lb:function(){var z,y,x
-z=this.lQ
-y=J.RE(z)
-switch(y.gfY(z)){case 10:x=y.gP(z)
-z=J.x(x)
-if(z.n(x,"this")){this.w5()
+return new U.jK(z,w)}}return this.lb()},
+lb:function(){var z,y
+switch(J.Iz(this.fL.mD)){case 10:z=J.Vm(this.fL.mD)
+y=J.x(z)
+if(y.n(z,"this")){this.w5()
this.Sk.toString
-return new U.w6("this")}else if(z.n(x,"in"))return
-throw H.b(new P.AT("unrecognized keyword: "+H.d(x)))
+return new U.w6("this")}else if(y.n(z,"in"))return
+throw H.b(new P.AT("unrecognized keyword: "+H.d(z)))
case 2:return this.Cy()
case 1:return this.qF()
case 6:return this.Ud()
case 7:return this.tw()
-case 9:if(J.xC(y.gP(z),"("))return this.Pj()
-else if(J.xC(J.Vm(this.lQ),"{"))return this.Wc()
+case 9:if(J.xC(J.Vm(this.fL.mD),"("))return this.Pj()
+else if(J.xC(J.Vm(this.fL.mD),"{"))return this.Wc()
return
default:return}},
-Wc:function(){var z,y,x,w,v
+Wc:function(){var z,y,x,w
z=[]
y=this.Sk
do{this.w5()
-x=this.lQ
-w=J.RE(x)
-if(w.gfY(x)===9&&J.xC(w.gP(x),"}"))break
-x=J.Vm(this.lQ)
+if(J.xC(J.Iz(this.fL.mD),9)&&J.xC(J.Vm(this.fL.mD),"}"))break
+x=J.Vm(this.fL.mD)
y.toString
-v=new U.no(x)
-v.$builtinTypeInfo=[null]
+w=new U.no(x)
+w.$builtinTypeInfo=[null]
this.w5()
this.Gd(5,":")
-z.push(new U.ae(v,this.o9()))
-x=this.lQ}while(x!=null&&J.xC(J.Vm(x),","))
+z.push(new U.ae(w,this.o9()))
+x=this.fL.mD}while(x!=null&&J.xC(J.Vm(x),","))
this.Gd(9,"}")
return new U.kB(z)},
xo:function(a){var z,y
@@ -18675,15 +19700,15 @@
this.Sk.toString
return new U.K9(a,y)},
Cy:function(){var z,y,x
-if(J.xC(J.Vm(this.lQ),"true")){this.w5()
+if(J.xC(J.Vm(this.fL.mD),"true")){this.w5()
this.Sk.toString
z=new U.no(!0)
H.VM(z,[null])
-return z}if(J.xC(J.Vm(this.lQ),"false")){this.w5()
+return z}if(J.xC(J.Vm(this.fL.mD),"false")){this.w5()
this.Sk.toString
z=new U.no(!1)
H.VM(z,[null])
-return z}if(J.xC(J.Vm(this.lQ),"null")){this.w5()
+return z}if(J.xC(J.Vm(this.fL.mD),"null")){this.w5()
this.Sk.toString
z=new U.no(null)
H.VM(z,[null])
@@ -18692,49 +19717,40 @@
if(x==null)return y
else{this.Sk.toString
return new U.RW(y,null,x)}},
-nt:function(){var z,y,x
-z=this.lQ
-y=J.RE(z)
-if(y.gfY(z)!==2)throw H.b(Y.RV("expected identifier: "+H.d(z)+".value"))
-x=y.gP(z)
+nt:function(){if(!J.xC(J.Iz(this.fL.mD),2))throw H.b(Y.RV("expected identifier: "+H.d(this.fL.mD)+".value"))
+var z=J.Vm(this.fL.mD)
this.w5()
this.Sk.toString
-return new U.w6(x)},
-qk:function(){var z,y,x
-z=this.lQ
-if(z!=null){y=J.RE(z)
-z=y.gfY(z)===9&&J.xC(y.gP(z),"(")}else z=!1
-if(z){x=[]
+return new U.w6(z)},
+qk:function(){var z,y
+z=this.fL.mD
+if(z!=null&&J.xC(J.Iz(z),9)&&J.xC(J.Vm(this.fL.mD),"(")){y=[]
do{this.w5()
-z=this.lQ
-y=J.RE(z)
-if(y.gfY(z)===9&&J.xC(y.gP(z),")"))break
-x.push(this.o9())
-z=this.lQ}while(z!=null&&J.xC(J.Vm(z),","))
+if(J.xC(J.Iz(this.fL.mD),9)&&J.xC(J.Vm(this.fL.mD),")"))break
+y.push(this.o9())
+z=this.fL.mD}while(z!=null&&J.xC(J.Vm(z),","))
this.Gd(9,")")
-return x}return},
-bK:function(){var z,y,x
-z=this.lQ
-if(z!=null){y=J.RE(z)
-z=y.gfY(z)===9&&J.xC(y.gP(z),"[")}else z=!1
-if(z){this.w5()
-x=this.o9()
+return y}return},
+bK:function(){var z,y
+z=this.fL.mD
+if(z!=null&&J.xC(J.Iz(z),9)&&J.xC(J.Vm(this.fL.mD),"[")){this.w5()
+y=this.o9()
this.Gd(9,"]")
-return x}return},
+return y}return},
Pj:function(){this.w5()
var z=this.o9()
this.Gd(9,")")
this.Sk.toString
return new U.Iq(z)},
qF:function(){var z,y
-z=J.Vm(this.lQ)
+z=J.Vm(this.fL.mD)
this.Sk.toString
y=new U.no(z)
H.VM(y,[null])
this.w5()
return y},
pT:function(a){var z,y
-z=H.BU(H.d(a)+H.d(J.Vm(this.lQ)),null,null)
+z=H.BU(H.d(a)+H.d(J.Vm(this.fL.mD)),null,null)
this.Sk.toString
y=new U.no(z)
H.VM(y,[null])
@@ -18742,7 +19758,7 @@
return y},
Ud:function(){return this.pT("")},
yj:function(a){var z,y
-z=H.IH(H.d(a)+H.d(J.Vm(this.lQ)),null)
+z=H.IH(H.d(a)+H.d(J.Vm(this.fL.mD)),null)
this.Sk.toString
y=new U.no(z)
H.VM(y,[null])
@@ -18754,10 +19770,22 @@
H.VM(z,[Y.Pn])
y=P.p9("")
x=new U.Fq()
-return new T.FX(x,new Y.hc(z,y,new P.WU(a,0,0,null),null),null,null,null)}}}}],["polymer_expressions.src.globals","package:polymer_expressions/src/globals.dart",,K,{Dc:function(a){var z=new K.Bt(a)
+return new T.FX(x,new Y.hc(z,y,new P.WU(a,0,0,null),null),null,null)}}}}],["polymer_expressions.src.globals","package:polymer_expressions/src/globals.dart",,K,{Dc:function(a){var z=new K.Bt(a)
H.VM(z,[null])
return z},Ae:{"":"a;vH>-,P>-",
r6:function(a,b){return this.P.call$1(b)},
+n:function(a,b){var z
+if(b==null)return!1
+z=J.x(b)
+return typeof b==="object"&&b!==null&&!!z.$isAe&&J.xC(b.vH,this.vH)&&J.xC(b.P,this.P)
+"37,106,37"},
+"+==:1:0":1,
+giO:function(a){return J.v1(this.P)
+"27"},
+"+hashCode":1,
+bu:function(a){return"("+H.d(this.vH)+", "+H.d(this.P)+")"
+"8"},
+"+toString:0:0":1,
$isAe:true,
"@":function(){return[C.nJ]},
"<>":[3],
@@ -18786,7 +19814,7 @@
H.VM(z,[H.W8(this,"Bt",0)])
return z},
$asmW:function(a){return[[K.Ae,a]]},
-$ascX:function(a){return[[K.Ae,a]]}},vR:{"":"Fl;Ee,wX,CD",
+$ascX:function(a){return[[K.Ae,a]]}},vR:{"":"eL;Ee,wX,CD",
gl:function(){return this.CD},
"+current":0,
G:function(){var z,y
@@ -18798,7 +19826,7 @@
this.CD=z
return!0}this.CD=null
return!1},
-$asFl:function(a){return[[K.Ae,a]]}}}],["polymer_expressions.src.mirrors","package:polymer_expressions/src/mirrors.dart",,Z,{xq:function(a,b){var z,y,x
+$aseL:function(a){return[[K.Ae,a]]}}}],["polymer_expressions.src.mirrors","package:polymer_expressions/src/mirrors.dart",,Z,{xq:function(a,b){var z,y,x
if(a.gYK().x4(b)===!0)return J.UQ(a.gYK(),b)
z=a.gAY()
if(z!=null&&!J.xC(z.gvd(),C.PU)){y=Z.xq(a.gAY(),b)
@@ -18820,6 +19848,7 @@
default:return a}},Pn:{"":"a;fY>,P>,G8<",
r6:function(a,b){return this.P.call$1(b)},
bu:function(a){return"("+this.fY+", '"+this.P+"')"},
+"+toString:0:0":0,
$isPn:true},hc:{"":"a;MV,wV,jI,x0",
zl:function(){var z,y,x,w,v
z=this.jI
@@ -18917,11 +19946,18 @@
u.$builtinTypeInfo=[J.im]
v=H.eT(u)}this.MV.push(new Y.Pn(8,v,C.dj.t(C.dj,v)))}},hA:{"":"a;G1>",
bu:function(a){return"ParseException: "+this.G1},
+"+toString:0:0":0,
static:{RV:function(a){return new Y.hA(a)}}}}],["polymer_expressions.visitor","package:polymer_expressions/visitor.dart",,S,{fr:{"":"a;",
DV:function(a){return J.UK(a,this)},
gnG:function(){return new H.Pm(this,S.fr.prototype.DV,null,"DV")}},a0:{"":"fr;",
W9:function(a){return this.xn(a)},
-LT:function(a){a.RR(a,this)
+LT:function(a){var z=a.wz
+z.RR(z,this)
+this.xn(a)},
+co:function(a){J.UK(a.ghP(),this)
+this.xn(a)},
+CU:function(a){J.UK(a.ghP(),this)
+J.UK(a.gJn(),this)
this.xn(a)},
Y7:function(a){var z,y
J.UK(a.ghP(),this)
@@ -18943,7 +19979,7 @@
this.xn(a)},
ky:function(a){J.UK(a.gBb(a),this)
J.UK(a.gT8(a),this)
-this.xn(a)}}}],["response_viewer_element","package:observatory/src/observatory_elements/response_viewer.dart",,Q,{NQ:{"":["uL;tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+this.xn(a)}}}],["response_viewer_element","package:observatory/src/observatory_elements/response_viewer.dart",,Q,{NQ:{"":["uL;hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
"@":function(){return[C.Ig]},
static:{Zo:function(a){var z,y,x,w,v
z=$.Nd()
@@ -18958,12 +19994,54 @@
C.Cc.ZL(a)
C.Cc.FH(a)
return a
-"30"},"+new ResponseViewerElement$created:0:0":1}},"+ResponseViewerElement": [24]}],["stack_trace_element","package:observatory/src/observatory_elements/stack_trace.dart",,X,{uw:{"":["WZq;Qq%-,VJ,Ai,tH-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+"30"},"+new ResponseViewerElement$created:0:0":1}},"+ResponseViewerElement": [24]}],["script_view_element","package:observatory/src/observatory_elements/script_view.dart",,U,{fI:{"":["WZq;Uz%-,VJ,Ai,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+gNl:function(a){return a.Uz
+"34,35,36"},
+"+script":1,
+sNl:function(a,b){a.Uz=this.ct(a,C.fX,a.Uz,b)
+"37,28,34,35"},
+"+script=":1,
+"@":function(){return[C.Er]},
+static:{Ry:function(a){var z,y,x,w,v
+z=$.Nd()
+y=P.Py(null,null,null,J.O,W.I0)
+x=J.O
+w=W.cv
+v=new V.br(P.Py(null,null,null,x,w),null,null)
+H.VM(v,[x,w])
+a.Ye=z
+a.mT=y
+a.KM=v
+C.cJ.ZL(a)
+C.cJ.FH(a)
+return a
+"31"},"+new ScriptViewElement$created:0:0":1}},"+ScriptViewElement": [107],WZq:{"":"uL+Pi;",$isd3:true}}],["source_view_element","package:observatory/src/observatory_elements/source_view.dart",,X,{kK:{"":["pva;vX%-,VJ,Ai,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
+gFF:function(a){return a.vX
+"108,35,36"},
+"+source":1,
+sFF:function(a,b){a.vX=this.ct(a,C.hn,a.vX,b)
+"37,28,108,35"},
+"+source=":1,
+"@":function(){return[C.H8]},
+static:{HO:function(a){var z,y,x,w,v
+z=$.Nd()
+y=P.Py(null,null,null,J.O,W.I0)
+x=J.O
+w=W.cv
+v=new V.br(P.Py(null,null,null,x,w),null,null)
+H.VM(v,[x,w])
+a.Ye=z
+a.mT=y
+a.KM=v
+C.Ks.ZL(a)
+C.Ks.FH(a)
+return a
+"32"},"+new SourceViewElement$created:0:0":1}},"+SourceViewElement": [109],pva:{"":"uL+Pi;",$isd3:true}}],["stack_trace_element","package:observatory/src/observatory_elements/stack_trace.dart",,X,{uw:{"":["cda;Qq%-,VJ,Ai,hm-,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM-",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,function(){return[C.nJ]}],
gtN:function(a){return a.Qq
-"32,33,34"},
+"34,35,36"},
"+trace":1,
-stN:function(a,b){a.Qq=this.pD(a,C.kw,a.Qq,b)
-"35,28,32,33"},
+stN:function(a,b){a.Qq=this.ct(a,C.kw,a.Qq,b)
+"37,28,34,35"},
"+trace=":1,
"@":function(){return[C.js]},
static:{bV:function(a){var z,y,x,w,v,u
@@ -18982,7 +20060,7 @@
C.bg.ZL(a)
C.bg.FH(a)
return a
-"31"},"+new StackTraceElement$created:0:0":1}},"+StackTraceElement": [102],WZq:{"":"uL+Pi;",$isd3:true}}],["template_binding","package:template_binding/template_binding.dart",,M,{IP:function(a){var z=J.RE(a)
+"33"},"+new StackTraceElement$created:0:0":1}},"+StackTraceElement": [110],cda:{"":"uL+Pi;",$isd3:true}}],["template_binding","package:template_binding/template_binding.dart",,M,{IP:function(a){var z=J.RE(a)
if(typeof a==="object"&&a!==null&&!!z.$isQl)return C.io.f0(a)
switch(z.gr9(a)){case"checkbox":return $.FF().aM(a)
case"radio":case"select-multiple":case"select-one":return z.gEr(a)
@@ -18997,7 +20075,7 @@
for(y=a.firstChild,x=0;y!=null;y=y.nextSibling,x=w){w=x+1
if(x>=z.length)throw H.e(z,x)
M.HP(y,z[x],c,d,e)}},bM:function(a){var z,y
-for(;z=J.RE(a),y=z.gKV(a),y!=null;a=y);if(typeof a==="object"&&a!==null&&!!z.$isYN||typeof a==="object"&&a!==null&&!!z.$isI0||typeof a==="object"&&a!==null&&!!z.$ishy)return a
+for(;z=J.RE(a),y=z.gKV(a),y!=null;a=y);if(typeof a==="object"&&a!==null&&!!z.$isQF||typeof a==="object"&&a!==null&&!!z.$isI0||typeof a==="object"&&a!==null&&!!z.$ishy)return a
return},pN:function(a,b){var z,y
z=J.x(a)
if(typeof a==="object"&&a!==null&&!!z.$iscv)return M.F5(a,b)
@@ -19138,23 +20216,23 @@
y.sr9(z,"checkbox")
x=[]
w=y.gVl(z)
-v=new W.Ov(0,w.uv,w.Ph,W.aF(new M.ik(x)),w.Sg)
+v=new W.Ov(0,w.uv,w.Ph,W.aF(new M.LfS(x)),w.Sg)
H.VM(v,[H.W8(w,"RO",0)])
v.Zz()
y=y.gEr(z)
-v=new W.Ov(0,y.uv,y.Ph,W.aF(new M.LfS(x)),y.Sg)
+v=new W.Ov(0,y.uv,y.Ph,W.aF(new M.fTP(x)),y.Sg)
H.VM(v,[H.W8(y,"RO",0)])
v.Zz()
z.dispatchEvent(W.H6("click",!1,0,!0,!0,0,0,!1,0,!1,null,0,0,!1,window))
return x.length===1?C.mt:C.Nm.gFV(x)},
"+call:0:0":0,
$isEH:true,
-$is_X0:true},ik:{"":"Tp;a",
+$is_X0:true},LfS:{"":"Tp;a",
call$1:function(a){this.a.push(C.T1)},
"+call:1:0":0,
$isEH:true,
$is_HB:true,
-$is_Dv:true},LfS:{"":"Tp;b",
+$is_Dv:true},fTP:{"":"Tp;b",
call$1:function(a){this.b.push(C.mt)},
"+call:1:0":0,
$isEH:true,
@@ -19788,15 +20866,15 @@
$$=null
init.globalFunctions.NB=H.NB=new H.zy(H.Mg,"NB")
init.globalFunctions.Rm=H.Rm=new H.Nb(H.vx,"Rm")
-init.globalFunctions.Eu=H.Eu=new H.HB(H.Ju,"Eu")
+init.globalFunctions.Eu=H.Eu=new H.Fy(H.Ju,"Eu")
init.globalFunctions.eH=H.eH=new H.eU(H.ft,"eH")
init.globalFunctions.Qv=H.Qv=new H.zy(H.pe,"Qv")
-init.globalFunctions.qg=E.qg=new H.HB(E.E2,"qg")
+init.globalFunctions.qg=E.qg=new H.Fy(E.E2,"qg")
init.globalFunctions.Yf=H.Yf=new H.Nb(H.vn,"Yf")
-init.globalFunctions.qZ=P.qZ=new H.HB(P.BG,"qZ")
+init.globalFunctions.qZ=P.qZ=new H.Fy(P.BG,"qZ")
init.globalFunctions.Xw=P.Xw=new H.Nb(P.YE,"Xw")
init.globalFunctions.AY=P.AY=new P.ADW(P.SZ,"AY")
-init.globalFunctions.No=P.No=new H.HB(P.ax,"No")
+init.globalFunctions.No=P.No=new H.Fy(P.ax,"No")
init.globalFunctions.xP=P.xP=new P.Ri(P.L2,"xP")
init.globalFunctions.AI=P.AI=new P.kq(P.T8,"AI")
init.globalFunctions.MM=P.MM=new P.Ri(P.V7,"MM")
@@ -19823,7 +20901,7 @@
init.globalFunctions.En=P.En=new H.Nb(P.wY,"En")
init.globalFunctions.Xl=P.Xl=new H.Nb(P.dU,"Xl")
init.globalFunctions.np=R.np=new H.Nb(R.Jk,"np")
-init.globalFunctions.PB=A.PB=new H.HB(A.ei,"PB")
+init.globalFunctions.PB=A.PB=new H.Fy(A.ei,"PB")
init.globalFunctions.qP=T.qP=new H.Nb(T.ul,"qP")
init.globalFunctions.Fx=T.Fx=new H.Nb(T.PX,"Fx")
init.globalFunctions.ZO=K.ZO=new H.Nb(K.Dc,"ZO")
@@ -19869,10 +20947,15 @@
U.EZ.$isa=true
U.RW.$ishw=true
U.RW.$isa=true
+U.zX.$iszX=true
+U.zX.$ishw=true
+U.zX.$isa=true
U.uk.$ishw=true
U.uk.$isa=true
U.K9.$ishw=true
U.K9.$isa=true
+U.x9.$ishw=true
+U.x9.$isa=true
U.no.$ishw=true
U.no.$isa=true
U.jK.$ishw=true
@@ -19898,38 +20981,38 @@
A.XP.$isD0=true
A.XP.$isa=true
P.vr.$isvr=true
-P.vr.$isQF=true
+P.vr.$isej=true
P.vr.$isa=true
-P.D4.$isD4=true
-P.D4.$isQF=true
-P.D4.$isQF=true
-P.D4.$isa=true
-P.RS.$isQF=true
+P.NL.$isej=true
+P.NL.$isa=true
+P.RS.$isej=true
P.RS.$isa=true
-H.Zk.$isQF=true
-H.Zk.$isQF=true
-H.Zk.$isQF=true
+H.Zk.$isej=true
+H.Zk.$isej=true
+H.Zk.$isej=true
H.Zk.$isa=true
-P.Ys.$isQF=true
-P.Ys.$isa=true
+P.D4.$isD4=true
+P.D4.$isej=true
+P.D4.$isej=true
+P.D4.$isa=true
+P.ej.$isej=true
+P.ej.$isa=true
+P.RY.$isej=true
+P.RY.$isa=true
P.Ms.$isMs=true
-P.Ms.$isQF=true
-P.Ms.$isQF=true
+P.Ms.$isej=true
+P.Ms.$isej=true
P.Ms.$isa=true
-P.Fw.$isQF=true
+P.Ys.$isej=true
+P.Ys.$isa=true
+P.Fw.$isej=true
P.Fw.$isa=true
-P.X9.$isQF=true
-P.X9.$isa=true
+P.L9u.$isej=true
+P.L9u.$isa=true
X.TR.$isa=true
N.TJ.$isa=true
T.yj.$isyj=true
T.yj.$isa=true
-P.NL.$isQF=true
-P.NL.$isa=true
-P.RY.$isQF=true
-P.RY.$isa=true
-P.QF.$isQF=true
-P.QF.$isa=true
P.MO.$isMO=true
P.MO.$isa=true
F.d3.$isa=true
@@ -19953,9 +21036,9 @@
P.uq.$isa=true
P.iD.$isiD=true
P.iD.$isa=true
-W.YN.$isKV=true
-W.YN.$isD0=true
-W.YN.$isa=true
+W.QF.$isKV=true
+W.QF.$isD0=true
+W.QF.$isa=true
P.HI.$isqh=true
P.HI.$asqh=[null]
P.HI.$isa=true
@@ -19973,6 +21056,7 @@
W.fJ.$isa=true
W.ew.$isea=true
W.ew.$isa=true
+L.Pf.$isa=true
P.mE.$ismE=true
P.mE.$isa=true
P.KA.$isKA=true
@@ -19986,11 +21070,11 @@
P.JI.$isa=true
H.Uz.$isUz=true
H.Uz.$isD4=true
-H.Uz.$isQF=true
-H.Uz.$isQF=true
-H.Uz.$isQF=true
-H.Uz.$isQF=true
-H.Uz.$isQF=true
+H.Uz.$isej=true
+H.Uz.$isej=true
+H.Uz.$isej=true
+H.Uz.$isej=true
+H.Uz.$isej=true
H.Uz.$isa=true
P.e4.$ise4=true
P.e4.$isa=true
@@ -20020,8 +21104,8 @@
P.iP.$isfR=true
P.iP.$asfR=[null]
P.iP.$isa=true
-P.fI.$isfI=true
-P.fI.$isa=true
+P.lx.$islx=true
+P.lx.$isa=true
J.Qc=function(a){if(typeof a=="number")return J.P.prototype
if(typeof a=="string")return J.O.prototype
if(a==null)return a
@@ -20060,18 +21144,18 @@
return J.ks(a)}
C.OL=new U.EZ()
C.Gw=new H.SJ()
-C.E3=new J.Q()
+C.l0=new J.Q()
C.Fm=new J.kn()
C.yX=new J.Pp()
-C.c1=new J.im()
+C.wq=new J.im()
C.oD=new J.P()
C.Kn=new J.O()
C.lM=new P.by()
-C.mI=new K.Fa()
+C.mI=new K.ndx()
C.Us=new A.yL()
-C.nJ=new K.ma()
+C.nJ=new K.Hm()
C.Wj=new P.dp()
-C.za=new A.Mh()
+C.za=new A.jh()
C.NU=new P.R8()
C.v8=new P.W5()
C.kk=Z.aC.prototype
@@ -20079,12 +21163,13 @@
C.j8=R.i6.prototype
C.Vy=new A.V3("disassembly-entry")
C.J0=new A.V3("observatory-element")
+C.Er=new A.V3("script-view")
C.aM=new A.V3("isolate-summary")
C.Ig=new A.V3("response-viewer")
-C.nu=new A.V3("function-view")
+C.Uc=new A.V3("function-view")
C.xW=new A.V3("code-view")
C.aQ=new A.V3("class-view")
-C.Oy=new A.V3("library-view")
+C.Ob=new A.V3("library-view")
C.c0=new A.V3("message-viewer")
C.js=new A.V3("stack-trace")
C.jF=new A.V3("isolate-list")
@@ -20093,6 +21178,7 @@
C.bd=new A.V3("observatory-application")
C.uW=new A.V3("error-view")
C.HN=new A.V3("json-view")
+C.H8=new A.V3("source-view")
C.mv=new A.V3("field-view")
C.Tl=E.Fv.prototype
C.RT=new P.a6(0)
@@ -20233,7 +21319,7 @@
hooks.prototypeForTag = prototypeForTagIE;
}
C.A3=new P.QM(null)
-C.jZ=Z.vj.prototype
+C.GB=Z.vj.prototype
C.VZ=new N.Ng("FINER",400)
C.R5=new N.Ng("FINE",500)
C.IF=new N.Ng("INFO",800)
@@ -20244,13 +21330,14 @@
list.fixed$length = true;
return list;
};
+C.Gb=H.VM(I.makeConstantList([127,2047,65535,1114111]),[J.im])
C.HE=I.makeConstantList([0,0,26624,1023,0,0,65534,2047])
C.mK=I.makeConstantList([0,0,26624,1023,65534,2047,65534,2047])
C.xu=I.makeConstantList([43,45,42,47,33,38,60,61,62,63,94,124])
C.u0=I.makeConstantList(["==","!=","<=",">=","||","&&"])
C.Me=H.VM(I.makeConstantList([]),[P.Ms])
C.dn=H.VM(I.makeConstantList([]),[P.Fw])
-C.hU=H.VM(I.makeConstantList([]),[P.X9])
+C.hU=H.VM(I.makeConstantList([]),[P.L9u])
C.xD=I.makeConstantList([])
C.Qy=I.makeConstantList(["in","this"])
C.kg=I.makeConstantList([0,0,24576,1023,65534,34815,65534,18431])
@@ -20266,14 +21353,16 @@
C.kr=new H.LP(5,{name:1,extends:1,constructor:1,noscript:1,attributes:1},C.pa)
C.ME=I.makeConstantList(["enumerate"])
C.va=new H.LP(1,{enumerate:K.ZO},C.ME)
-C.Wp=L.Nh.prototype
+C.Wp=L.BK.prototype
C.Xg=Q.ih.prototype
C.t5=W.BH.prototype
C.k0=V.F1.prototype
-C.Pf=Z.uL.prototype
+C.mk=Z.uL.prototype
C.xk=A.XP.prototype
-C.GB=A.ir.prototype
+C.Iv=A.ir.prototype
C.Cc=Q.NQ.prototype
+C.cJ=U.fI.prototype
+C.Ks=X.kK.prototype
C.bg=X.uw.prototype
C.PU=new H.GD("dart.core.Object")
C.nz=new H.GD("dart.core.DateTime")
@@ -20288,6 +21377,7 @@
C.to=new H.GD("createRuntimeType")
C.Je=new H.GD("current")
C.h1=new H.GD("currentHash")
+C.tv=new H.GD("currentHashUri")
C.Jw=new H.GD("displayValue")
C.nN=new H.GD("dynamic")
C.yh=new H.GD("error")
@@ -20296,24 +21386,33 @@
C.nf=new H.GD("function")
C.AZ=new H.GD("dart.core.String")
C.Di=new H.GD("iconClass")
+C.EN=new H.GD("id")
C.eJ=new H.GD("instruction")
+C.ai=new H.GD("isEmpty")
+C.nZ=new H.GD("isNotEmpty")
C.Y2=new H.GD("isolate")
C.Gd=new H.GD("json")
+C.fy=new H.GD("kind")
C.Wn=new H.GD("length")
C.EV=new H.GD("library")
+C.Cv=new H.GD("lines")
C.PC=new H.GD("dart.core.int")
C.wt=new H.GD("members")
C.KY=new H.GD("messageType")
C.YS=new H.GD("name")
C.OV=new H.GD("noSuchMethod")
C.Ws=new H.GD("operatingSystem")
+C.X9=new H.GD("paddedLine")
C.qb=new H.GD("prefix")
C.Qi=new H.GD("registerCallback")
C.wH=new H.GD("responses")
C.ok=new H.GD("dart.core.Null")
C.md=new H.GD("dart.core.double")
+C.fX=new H.GD("script")
C.eC=new H.GD("[]=")
+C.hn=new H.GD("source")
C.kw=new H.GD("trace")
+C.Fh=new H.GD("url")
C.ls=new H.GD("value")
C.eR=new H.GD("valueType")
C.QK=new H.GD("window")
@@ -20327,7 +21426,6 @@
C.Ti=H.mm('wn')
C.Mt=new H.Lm(C.Ti,"E",0)
C.qM=H.mm('F1')
-C.NM=H.mm('Nh')
C.nY=H.mm('a')
C.Yc=H.mm('iP')
C.LN=H.mm('Be')
@@ -20337,7 +21435,9 @@
C.Op=H.mm('G8')
C.xF=H.mm('NQ')
C.b4=H.mm('ih')
+C.ced=H.mm('kK')
C.hG=H.mm('ir')
+C.aj=H.mm('fI')
C.dA=H.mm('Ms')
C.mo=H.mm('Fv')
C.O4=H.mm('double')
@@ -20359,6 +21459,7 @@
C.CS=H.mm('vm')
C.XK=H.mm('Gk')
C.GX=H.mm('c8')
+C.WIe=H.mm('BK')
C.vB=J.is.prototype
C.dy=new P.z0(!1)
C.ol=W.K5.prototype
@@ -20400,11 +21501,11 @@
J.Co=function(a){return J.RE(a).gcC(a)}
J.DA=function(a){return J.RE(a).goc(a)}
J.DB=function(a,b){return J.w1(a).Ay(a,b)}
+J.DF=function(a,b){return J.RE(a).soc(a,b)}
J.Dz=function(a,b){return J.rY(a).j(a,b)}
J.EC=function(a){return J.RE(a).giC(a)}
J.EY=function(a,b){return J.RE(a).od(a,b)}
J.Eg=function(a,b){return J.rY(a).Tc(a,b)}
-J.Eh=function(a,b){return J.Wx(a).O(a,b)}
J.F8=function(a){return J.RE(a).gjO(a)}
J.FN=function(a){return J.U6(a).gl0(a)}
J.FW=function(a,b){if(typeof a=="number"&&typeof b=="number")return a/b
@@ -20412,7 +21513,6 @@
J.GJ=function(a,b,c,d){return J.RE(a).Y9(a,b,c,d)}
J.GK=function(a){return J.RE(a).glc(a)}
J.GP=function(a){return J.w1(a).gA(a)}
-J.GS=function(a,b,c,d){return J.RE(a).rJ(a,b,c,d)}
J.GW=function(a){return J.RE(a).gn4(a)}
J.H4=function(a,b){return J.RE(a).wR(a,b)}
J.Hb=function(a,b){if(typeof a=="number"&&typeof b=="number")return a<=b
@@ -20453,6 +21553,7 @@
J.UU=function(a,b){return J.U6(a).u8(a,b)}
J.UW=function(a){return J.RE(a).gLU(a)}
J.UX=function(a){return J.RE(a).gmW(a)}
+J.Ut=function(a,b,c,d){return J.RE(a).rJ(a,b,c,d)}
J.V1=function(a,b){return J.w1(a).Rz(a,b)}
J.VN=function(a){return J.RE(a).gM0(a)}
J.Vm=function(a){return J.RE(a).gP(a)}
@@ -20472,6 +21573,7 @@
J.bh=function(a,b,c){return J.rY(a).JT(a,b,c)}
J.bi=function(a,b){return J.w1(a).h(a,b)}
J.bs=function(a){return J.RE(a).JP(a)}
+J.c1=function(a,b){return J.Wx(a).O(a,b)}
J.c9=function(a,b){return J.RE(a).sa4(a,b)}
J.co=function(a,b){return J.rY(a).nC(a,b)}
J.e2=function(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p){return J.RE(a).nH(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)}
@@ -20515,6 +21617,7 @@
J.uH=function(a,b){return J.rY(a).Fr(a,b)}
J.uf=function(a){return J.RE(a).gxr(a)}
J.v1=function(a){return J.x(a).giO(a)}
+J.vF=function(a){return J.RE(a).gbP(a)}
J.vX=function(a){return J.w1(a).wg(a)}
J.vo=function(a,b){return J.w1(a).ev(a,b)}
J.w8=function(a){return J.RE(a).gkc(a)}
@@ -20531,8 +21634,8 @@
J.z2=function(a){return J.RE(a).gG1(a)}
J.zZ=function(a,b){return J.RE(a).Yv(a,b)}
J.zj=function(a){return J.RE(a).gvH(a)}
-$.Dq=["Ay","BN","BT","Ba","C","C0","C8","Ch","D","D3","D6","Dh","E","Ec","F","FH","Fr","GB","HG","Hn","Id","Ih","Im","Is","J","J3","JP","JT","JV","Ja","Jk","Kb","LV","Md","Mi","Mu","Nj","Nz","O","On","PM","Pa","Pk","Pv","R3","R4","RB","RR","Rz","SZ","T","T2","TH","TP","TW","Tc","Td","U","UD","UH","UZ","Uc","V","V1","Vr","Vy","W","W3","W4","WO","Wt","Wz","XG","XU","Xl","Y9","YU","YW","Ys","Yv","Z","Z1","Z2","ZB","ZF","ZL","ZP","Zv","aC","aN","aq","bA","bS","br","bu","cO","cn","d0","dR","dd","du","eR","ea","er","es","ev","ez","f6","fd","fj","fk","fm","g","gA","gAQ","gB","gBb","gCd","gCj","gDD","gDg","gE8","gEX","gEr","gF1","gFJ","gFT","gFV","gFe","gG0","gG1","gG3","gGL","gHs","gI","gIi","gJS","gJf","gKE","gKM","gKV","gLA","gLU","gLm","gM0","gMB","gMj","gN","gNI","gP","gP1","gP2","gPp","gPu","gPw","gPy","gQ0","gQG","gQW","gQg","gQq","gRu","gT8","gTM","gTn","gTq","gUQ","gUV","gVA","gVB","gVl","gXB","gXf","gXt","gZw","gai","gbP","gbx","gcC","geT","geb","gey","gfY","ghO","ghr","gi0","giC","giI","giO","gig","gjL","gjO","gjU","gjb","gkU","gkc","gkf","gkp","gl0","glc","gmW","gmm","gn4","goc","gor","gpQ","gpo","gq6","gqC","gqh","gql","gr3","gr9","grK","grZ","gt0","gtD","gtH","gtN","gtT","guD","gvH","gvc","gvt","gxj","gxr","gyT","gys","gzP","gzZ","h","h8","hc","i","i4","iA","iM","iw","j","jT","jx","kO","l5","l8","lj","m","mK","mv","n","nB","nC","nH","nP","ni","oB","oW","od","oo","oq","pD","pZ","pl","pr","qZ","r6","rJ","rS","sAQ","sB","sF1","sFJ","sFT","sG1","sIt","sMj","sNI","sP","sP2","sPw","sPy","sQG","sQq","sRu","sTn","sTq","sVA","sVB","sXB","sXf","sZw","sa4","sai","scC","seb","shO","si0","siI","sig","sjO","skc","skf","soc","sql","sr9","st0","stD","stH","stN","stT","svt","sxj","sxr","szZ","t","tZ","tg","tt","u","u5","u8","uG","vs","w3","wE","wL","wR","wg","x3","xI","xe","y0","yC","yc","ym","yn","yq","yu","yx","yy","z2","zV"]
-$.Au=[C.qM,V.F1,{created:V.fv},C.NM,L.Nh,{created:L.rJ},C.LN,F.Be,{created:F.Fe},C.Qa,L.u7,{created:L.ip},C.xS,P.UZ,{},C.PT,M.CX,{created:M.SP},C.Op,P.G8,{},C.xF,Q.NQ,{created:Q.Zo},C.b4,Q.ih,{created:Q.BW},C.hG,A.ir,{created:A.oa},C.mo,E.Fv,{created:E.AH},C.xE,Z.aC,{created:Z.zg},C.vuj,X.uw,{created:X.bV},C.Tq,Z.vj,{created:Z.un},C.CT,D.St,{created:D.N5},C.Q4,Z.uL,{created:Z.Hx},C.yg,F.I3,{created:F.TW},C.XU,R.i6,{created:R.IT},C.Bm,A.XP,{created:A.XL},C.Sa,N.Ds,{created:N.p7},C.XK,A.Gk,{created:A.cY}]
+$.Dq=["Ay","BN","BT","Ba","Bf","C","C0","C8","Ch","D","D3","D6","Dh","E","Ec","F","FH","Fr","GB","HG","Hn","Id","Ih","Im","Is","J","J3","JP","JT","JV","Ja","Jk","Kb","LV","Md","Mi","Mu","Nj","Nz","O","On","PM","Pa","Pk","Pv","R3","R4","RB","RR","Rz","SS","SZ","T","T2","TP","TW","Tc","Td","Tp","U","UD","UH","UZ","Uc","V","V1","Vr","Vy","W","W3","W4","WL","WO","WZ","Wt","Wz","XG","XU","Xl","Y9","YU","YW","Ys","Yv","Z","Z1","Z2","ZB","ZL","ZP","Zv","aC","aN","aq","bA","bS","br","bu","cO","cn","ct","d0","dd","du","eR","ea","er","es","ev","ez","f6","fd","fj","fk","fm","g","gA","gB","gBb","gCd","gCj","gDD","gDg","gE8","gEX","gEr","gF1","gFF","gFJ","gFT","gFV","gFe","gG0","gG1","gG3","gGL","gHX","gHs","gI","gIi","gJS","gJf","gKE","gKM","gKV","gLA","gLU","gLm","gM0","gMB","gMj","gN","gNI","gNl","gO3","gP","gP1","gPp","gPu","gPw","gPy","gQ0","gQG","gQW","gQg","gQq","gRu","gT8","gTM","gTn","gTq","gUQ","gUV","gUy","gUz","gVB","gVl","gXB","gXt","gZw","gai","gbP","gbx","gcC","geT","geb","gey","gfY","ghO","ghm","ghr","gi0","giC","giI","giO","gig","gjL","gjO","gjU","gjb","gkU","gkc","gkf","gkp","gl0","gl7","glc","gmW","gmm","gn4","goc","gor","gpQ","gpo","gq6","gqC","gqh","gql","gr3","gr9","grK","grZ","gt0","gtD","gtN","gtT","guD","gvH","gvX","gvc","gvt","gxj","gxr","gyT","gys","gzP","gzZ","gzh","h","h8","hV","hc","i","i3","i4","iA","iM","iw","j","jT","jx","kO","l5","l8","lj","m","mK","mv","n","nB","nC","nH","nP","ni","oB","oW","od","oo","oq","pZ","pl","pr","qZ","r6","rJ","rS","sB","sF1","sFF","sFJ","sFT","sG1","sHX","sIt","sLA","sMj","sNI","sNl","sO3","sP","sPw","sPy","sQG","sQq","sRu","sTn","sTq","sUy","sUz","sVB","sXB","sZw","sa4","sai","scC","seb","sfY","shO","shm","si0","siI","sig","sjO","skc","skf","sl7","soc","sql","sr9","st0","stD","stN","stT","svX","svt","sxj","sxr","szZ","szh","t","tZ","tg","tt","u","u5","u8","uG","vs","w3","wE","wL","wR","wg","x3","xe","y0","yC","yc","ym","yn","yq","yu","yx","yy","z2","zV"]
+$.Au=[C.qM,V.F1,{created:V.fv},C.LN,F.Be,{created:F.Fe},C.Qa,L.u7,{created:L.ip},C.xS,P.UZ,{},C.PT,M.CX,{created:M.SP},C.Op,P.G8,{},C.xF,Q.NQ,{created:Q.Zo},C.b4,Q.ih,{created:Q.BW},C.ced,X.kK,{created:X.HO},C.hG,A.ir,{created:A.oa},C.aj,U.fI,{created:U.Ry},C.mo,E.Fv,{created:E.AH},C.xE,Z.aC,{created:Z.zg},C.vuj,X.uw,{created:X.bV},C.Tq,Z.vj,{created:Z.un},C.CT,D.St,{created:D.N5},C.Q4,Z.uL,{created:Z.Hx},C.yg,F.I3,{created:F.TW},C.XU,R.i6,{created:R.IT},C.Bm,A.XP,{created:A.XL},C.Sa,N.Ds,{created:N.p7},C.XK,A.Gk,{created:A.cY},C.WIe,L.BK,{created:L.rJ}]
I.$lazy($,"globalThis","DX","jk",function(){return function() { return this; }()})
I.$lazy($,"globalWindow","pG","Qm",function(){return $.jk().window})
I.$lazy($,"globalWorker","zA","Nl",function(){return $.jk().Worker})
@@ -20586,6 +21689,7 @@
I.$lazy($,"_waitSuper","uv","xY",function(){return P.L5(null,null,null,J.O,[J.Q,A.XP])})
I.$lazy($,"_declarations","EJ","cd",function(){return P.L5(null,null,null,J.O,A.XP)})
I.$lazy($,"_objectType","Cy","Tf",function(){return P.re(C.nY)})
+I.$lazy($,"_sheetLog","Fa","vM",function(){return N.Jx("polymer.stylesheet")})
I.$lazy($,"_reverseEventTranslations","fp","pT",function(){return new A.w12().call$0()})
I.$lazy($,"bindPattern","ZA","VC",function(){return new H.VR(H.v4("\\{\\{([^{}]*)}}",!1,!0,!1),null,null)})
I.$lazy($,"_polymerSyntax","Df","Nd",function(){var z=P.L5(null,null,null,J.O,P.a)
@@ -20619,7 +21723,7 @@
return z.t(z,y)})
I.$lazy($,"_mangledNameField","AU","av",function(){return new M.w13().call$0()})
I.$lazy($,"_logger","Kp","IS",function(){return N.Jx("polymer_expressions")})
-I.$lazy($,"_BINARY_OPERATORS","tB","bF",function(){return H.B7(["+",new K.wJY(),"-",new K.zOQ(),"*",new K.W6o(),"/",new K.MdQ(),"==",new K.YJG(),"!=",new K.DOe(),">",new K.lPa(),">=",new K.Ufa(),"<",new K.Raa(),"<=",new K.w0(),"||",new K.w4(),"&&",new K.w5(),"|",new K.w7()],P.L5(null,null,null,null,null))})
+I.$lazy($,"_BINARY_OPERATORS","AM","e6",function(){return H.B7(["+",new K.wJY(),"-",new K.zOQ(),"*",new K.W6o(),"/",new K.MdQ(),"==",new K.YJG(),"!=",new K.DOe(),">",new K.lPa(),">=",new K.Ufa(),"<",new K.Raa(),"<=",new K.w0(),"||",new K.w4(),"&&",new K.w5(),"|",new K.w7()],P.L5(null,null,null,null,null))})
I.$lazy($,"_UNARY_OPERATORS","ju","YG",function(){return H.B7(["+",new K.w9(),"-",new K.w10(),"!",new K.w11()],P.L5(null,null,null,null,null))})
I.$lazy($,"_checkboxEventType","S8","FF",function(){return new M.Uf().call$0()})
I.$lazy($,"_contentsOwner","mn","LQ",function(){var z=new P.kM(null)
@@ -20632,7 +21736,7 @@
return z})
init.functionAliases={}
-init.metadata=[P.a,C.wK,C.wa,C.WX,C.Mt,C.wW,P.uq,"name",J.O,Z.aC,F.Be,R.i6,W.K5,E.Fv,F.I3,A.Gk,N.Ds,L.u7,D.St,Z.vj,M.CX,L.Nh,Q.ih,V.F1,Z.uL,[K.Ae,3],"index",J.im,"value",3,Q.NQ,X.uw,P.L8,C.nJ,C.Us,,Z.Vf,F.tu,C.mI,J.kn,"r","e",W.ea,"detail","target",W.KV,R.Vc,[P.L8,P.wv,P.RS],[J.Q,H.Zk],"methodOwner",P.NL,[J.Q,P.RY],"fieldOwner",[P.L8,P.wv,P.RY],[P.L8,P.wv,P.QF],[P.L8,P.wv,P.NL],P.vr,"fieldName",P.wv,"arg",H.Uz,[J.Q,P.vr],P.Ms,"memberName","positionalArguments",J.Q,"namedArguments",[P.L8,P.wv,null],[J.Q,P.Ms],"owner",[J.Q,P.Fw],[J.Q,P.X9],H.Un,"key",P.QF,H.Tp,"tv","i",E.WZ,F.pv,A.Vfx,N.Dsd,D.tuj,"oldValue",Z.Vct,M.D13,"m",[J.Q,P.L8],"l","objectId","cid","isolateId",L.mL,Z.Xf,5,"newValue",4,[P.cX,1],[P.cX,2],2,1,"v",X.WZq,];$=null
+init.metadata=[P.a,C.wK,C.wa,C.WX,C.Mt,C.wW,P.uq,"name",J.O,Z.aC,F.Be,R.i6,W.K5,E.Fv,F.I3,A.Gk,N.Ds,L.u7,D.St,Z.vj,M.CX,L.BK,Q.ih,V.F1,Z.uL,[K.Ae,3],"index",J.im,"value",3,Q.NQ,U.fI,X.kK,X.uw,P.L8,C.nJ,C.Us,,Z.Vf,F.tu,C.mI,J.kn,"r","e",W.ea,"detail","target",W.KV,R.Vc,[P.L8,P.wv,P.RS],[J.Q,H.Zk],"methodOwner",P.NL,[J.Q,P.RY],"fieldOwner",[P.L8,P.wv,P.RY],[P.L8,P.wv,P.ej],[P.L8,P.wv,P.NL],P.vr,"fieldName",P.wv,"arg",H.Uz,[J.Q,P.vr],P.Ms,"memberName","positionalArguments",J.Q,"namedArguments",[P.L8,P.wv,null],[J.Q,P.Ms],"owner",[J.Q,P.Fw],[J.Q,P.L9u],H.Un,"key",P.ej,H.Tp,"tv","i",E.WZ,F.pv,A.Vfx,N.Dsd,D.tuj,"oldValue",Z.Vct,M.D13,"m",[J.Q,P.L8],P.iD,"l","objectId","cid","isolateId",[J.Q,L.Zw],L.mL,Z.Xf,5,"newValue",4,[P.cX,1],[P.cX,2],2,1,"v","o",U.WZq,L.Pf,X.pva,X.cda,];$=null
I = I.$finishIsolateConstructor(I)
$=new I()
function convertToFastObject(properties) {
@@ -20876,6 +21980,7 @@
$desc=$collectedClasses.i3
if($desc instanceof Array)$desc=$desc[1]
i3.prototype=$desc
+i3.prototype.gO3=function(receiver){return receiver.url}
function it(){}it.builtin$cls="it"
if(!"name" in it)it.name="it"
$desc=$collectedClasses.it
@@ -20992,11 +22097,11 @@
$desc=$collectedClasses.Wy
if($desc instanceof Array)$desc=$desc[1]
Wy.prototype=$desc
-function YN(){}YN.builtin$cls="YN"
-if(!"name" in YN)YN.name="YN"
-$desc=$collectedClasses.YN
+function QF(){}QF.builtin$cls="QF"
+if(!"name" in QF)QF.name="QF"
+$desc=$collectedClasses.QF
if($desc instanceof Array)$desc=$desc[1]
-YN.prototype=$desc
+QF.prototype=$desc
function bA(){}bA.builtin$cls="bA"
if(!"name" in bA)bA.name="bA"
$desc=$collectedClasses.bA
@@ -21014,12 +22119,12 @@
rz.prototype=$desc
rz.prototype.gG1=function(receiver){return receiver.message}
rz.prototype.goc=function(receiver){return receiver.name}
-function BK(){}BK.builtin$cls="BK"
-if(!"name" in BK)BK.name="BK"
-$desc=$collectedClasses.BK
+function Nh(){}Nh.builtin$cls="Nh"
+if(!"name" in Nh)Nh.name="Nh"
+$desc=$collectedClasses.Nh
if($desc instanceof Array)$desc=$desc[1]
-BK.prototype=$desc
-BK.prototype.gG1=function(receiver){return receiver.message}
+Nh.prototype=$desc
+Nh.prototype.gG1=function(receiver){return receiver.message}
function wj(){}wj.builtin$cls="wj"
if(!"name" in wj)wj.name="wj"
$desc=$collectedClasses.wj
@@ -21042,6 +22147,7 @@
Fs.prototype.goc=function(receiver){return receiver.name}
Fs.prototype.soc=function(receiver,v){return receiver.name=v}
Fs.prototype.gLA=function(receiver){return receiver.src}
+Fs.prototype.sLA=function(receiver,v){return receiver.src=v}
Fs.prototype.gr9=function(receiver){return receiver.type}
Fs.prototype.sr9=function(receiver,v){return receiver.type=v}
function SX(){}SX.builtin$cls="SX"
@@ -21167,6 +22273,7 @@
tX.prototype.goc=function(receiver){return receiver.name}
tX.prototype.soc=function(receiver,v){return receiver.name=v}
tX.prototype.gLA=function(receiver){return receiver.src}
+tX.prototype.sLA=function(receiver,v){return receiver.src=v}
function Sg(){}Sg.builtin$cls="Sg"
if(!"name" in Sg)Sg.name="Sg"
$desc=$collectedClasses.Sg
@@ -21178,6 +22285,7 @@
if($desc instanceof Array)$desc=$desc[1]
pA.prototype=$desc
pA.prototype.gLA=function(receiver){return receiver.src}
+pA.prototype.sLA=function(receiver,v){return receiver.src=v}
function Mi(){}Mi.builtin$cls="Mi"
if(!"name" in Mi)Mi.name="Mi"
$desc=$collectedClasses.Mi
@@ -21190,6 +22298,7 @@
Mi.prototype.goc=function(receiver){return receiver.name}
Mi.prototype.soc=function(receiver,v){return receiver.name=v}
Mi.prototype.gLA=function(receiver){return receiver.src}
+Mi.prototype.sLA=function(receiver,v){return receiver.src=v}
Mi.prototype.gr9=function(receiver){return receiver.type}
Mi.prototype.sr9=function(receiver,v){return receiver.type=v}
Mi.prototype.gP=function(receiver){return receiver.value}
@@ -21258,6 +22367,7 @@
El.prototype=$desc
El.prototype.gkc=function(receiver){return receiver.error}
El.prototype.gLA=function(receiver){return receiver.src}
+El.prototype.sLA=function(receiver,v){return receiver.src=v}
function zm(){}zm.builtin$cls="zm"
if(!"name" in zm)zm.name="zm"
$desc=$collectedClasses.zm
@@ -21411,11 +22521,11 @@
G7.prototype.soc=function(receiver,v){return receiver.name=v}
G7.prototype.gr9=function(receiver){return receiver.type}
G7.prototype.sr9=function(receiver,v){return receiver.type=v}
-function wq(){}wq.builtin$cls="wq"
-if(!"name" in wq)wq.name="wq"
-$desc=$collectedClasses.wq
+function kl(){}kl.builtin$cls="kl"
+if(!"name" in kl)kl.name="kl"
+$desc=$collectedClasses.kl
if($desc instanceof Array)$desc=$desc[1]
-wq.prototype=$desc
+kl.prototype=$desc
function Ql(){}Ql.builtin$cls="Ql"
if(!"name" in Ql)Ql.name="Ql"
$desc=$collectedClasses.Ql
@@ -21505,6 +22615,7 @@
$desc=$collectedClasses.bX
if($desc instanceof Array)$desc=$desc[1]
bX.prototype=$desc
+bX.prototype.gO3=function(receiver){return receiver.url}
function BL(){}BL.builtin$cls="BL"
if(!"name" in BL)BL.name="BL"
$desc=$collectedClasses.BL
@@ -21526,6 +22637,7 @@
if($desc instanceof Array)$desc=$desc[1]
j2.prototype=$desc
j2.prototype.gLA=function(receiver){return receiver.src}
+j2.prototype.sLA=function(receiver,v){return receiver.src=v}
j2.prototype.gr9=function(receiver){return receiver.type}
j2.prototype.sr9=function(receiver,v){return receiver.type=v}
function yz(){}yz.builtin$cls="yz"
@@ -21565,6 +22677,7 @@
if($desc instanceof Array)$desc=$desc[1]
QR.prototype=$desc
QR.prototype.gLA=function(receiver){return receiver.src}
+QR.prototype.sLA=function(receiver,v){return receiver.src=v}
QR.prototype.gr9=function(receiver){return receiver.type}
QR.prototype.sr9=function(receiver,v){return receiver.type=v}
function Cp(){}Cp.builtin$cls="Cp"
@@ -21603,6 +22716,7 @@
wb.prototype.gG3=function(receiver){return receiver.key}
wb.prototype.gzZ=function(receiver){return receiver.newValue}
wb.prototype.gjL=function(receiver){return receiver.oldValue}
+wb.prototype.gO3=function(receiver){return receiver.url}
function fq(){}fq.builtin$cls="fq"
if(!"name" in fq)fq.name="fq"
$desc=$collectedClasses.fq
@@ -21630,11 +22744,11 @@
$desc=$collectedClasses.Tb
if($desc instanceof Array)$desc=$desc[1]
Tb.prototype=$desc
-function Iv(){}Iv.builtin$cls="Iv"
-if(!"name" in Iv)Iv.name="Iv"
-$desc=$collectedClasses.Iv
+function tV(){}tV.builtin$cls="tV"
+if(!"name" in tV)tV.name="tV"
+$desc=$collectedClasses.tV
if($desc instanceof Array)$desc=$desc[1]
-Iv.prototype=$desc
+tV.prototype=$desc
function BT(){}BT.builtin$cls="BT"
if(!"name" in BT)BT.name="BT"
$desc=$collectedClasses.BT
@@ -21683,7 +22797,9 @@
if($desc instanceof Array)$desc=$desc[1]
RH.prototype=$desc
RH.prototype.gfY=function(receiver){return receiver.kind}
+RH.prototype.sfY=function(receiver,v){return receiver.kind=v}
RH.prototype.gLA=function(receiver){return receiver.src}
+RH.prototype.sLA=function(receiver,v){return receiver.src=v}
function pU(){}pU.builtin$cls="pU"
if(!"name" in pU)pU.name="pU"
$desc=$collectedClasses.pU
@@ -21755,11 +22871,11 @@
$desc=$collectedClasses.kc
if($desc instanceof Array)$desc=$desc[1]
kc.prototype=$desc
-function ij(){}ij.builtin$cls="ij"
-if(!"name" in ij)ij.name="ij"
-$desc=$collectedClasses.ij
+function Eh(){}Eh.builtin$cls="Eh"
+if(!"name" in Eh)Eh.name="Eh"
+$desc=$collectedClasses.Eh
if($desc instanceof Array)$desc=$desc[1]
-ij.prototype=$desc
+Eh.prototype=$desc
function ty(){}ty.builtin$cls="ty"
if(!"name" in ty)ty.name="ty"
$desc=$collectedClasses.ty
@@ -21805,13 +22921,13 @@
$desc=$collectedClasses.yK
if($desc instanceof Array)$desc=$desc[1]
yK.prototype=$desc
-function Y0(){}Y0.builtin$cls="Y0"
-if(!"name" in Y0)Y0.name="Y0"
-$desc=$collectedClasses.Y0
+function HB(){}HB.builtin$cls="HB"
+if(!"name" in HB)HB.name="HB"
+$desc=$collectedClasses.HB
if($desc instanceof Array)$desc=$desc[1]
-Y0.prototype=$desc
-Y0.prototype.gN=function(receiver){return receiver.target}
-Y0.prototype.gLU=function(receiver){return receiver.href}
+HB.prototype=$desc
+HB.prototype.gN=function(receiver){return receiver.target}
+HB.prototype.gLU=function(receiver){return receiver.href}
function ZJ(){}ZJ.builtin$cls="ZJ"
if(!"name" in ZJ)ZJ.name="ZJ"
$desc=$collectedClasses.ZJ
@@ -21828,11 +22944,11 @@
$desc=$collectedClasses.eZ
if($desc instanceof Array)$desc=$desc[1]
eZ.prototype=$desc
-function Ak(){}Ak.builtin$cls="Ak"
-if(!"name" in Ak)Ak.name="Ak"
-$desc=$collectedClasses.Ak
+function Fl(){}Fl.builtin$cls="Fl"
+if(!"name" in Fl)Fl.name="Fl"
+$desc=$collectedClasses.Fl
if($desc instanceof Array)$desc=$desc[1]
-Ak.prototype=$desc
+Fl.prototype=$desc
function y5(){}y5.builtin$cls="y5"
if(!"name" in y5)y5.name="y5"
$desc=$collectedClasses.y5
@@ -21983,11 +23099,11 @@
$desc=$collectedClasses.ca
if($desc instanceof Array)$desc=$desc[1]
ca.prototype=$desc
-function kK(){}kK.builtin$cls="kK"
-if(!"name" in kK)kK.name="kK"
-$desc=$collectedClasses.kK
+function xX(){}xX.builtin$cls="xX"
+if(!"name" in xX)xX.name="xX"
+$desc=$collectedClasses.xX
if($desc instanceof Array)$desc=$desc[1]
-kK.prototype=$desc
+xX.prototype=$desc
function eW(){}eW.builtin$cls="eW"
if(!"name" in eW)eW.name="eW"
$desc=$collectedClasses.eW
@@ -22152,13 +23268,13 @@
$desc=$collectedClasses.MT
if($desc instanceof Array)$desc=$desc[1]
MT.prototype=$desc
-function Rk(){}Rk.builtin$cls="Rk"
-if(!"name" in Rk)Rk.name="Rk"
-$desc=$collectedClasses.Rk
+function xN(){}xN.builtin$cls="xN"
+if(!"name" in xN)xN.name="xN"
+$desc=$collectedClasses.xN
if($desc instanceof Array)$desc=$desc[1]
-Rk.prototype=$desc
-Rk.prototype.gbP=function(receiver){return receiver.method}
-Rk.prototype.gLU=function(receiver){return receiver.href}
+xN.prototype=$desc
+xN.prototype.gbP=function(receiver){return receiver.method}
+xN.prototype.gLU=function(receiver){return receiver.href}
function Eo(){}Eo.builtin$cls="Eo"
if(!"name" in Eo)Eo.name="Eo"
$desc=$collectedClasses.Eo
@@ -22221,11 +23337,11 @@
$desc=$collectedClasses.cB
if($desc instanceof Array)$desc=$desc[1]
cB.prototype=$desc
-function uY(){}uY.builtin$cls="uY"
-if(!"name" in uY)uY.name="uY"
-$desc=$collectedClasses.uY
+function k2(){}k2.builtin$cls="k2"
+if(!"name" in k2)k2.name="k2"
+$desc=$collectedClasses.k2
if($desc instanceof Array)$desc=$desc[1]
-uY.prototype=$desc
+k2.prototype=$desc
function yR(){}yR.builtin$cls="yR"
if(!"name" in yR)yR.name="yR"
$desc=$collectedClasses.yR
@@ -22338,11 +23454,11 @@
$desc=$collectedClasses.ZX
if($desc instanceof Array)$desc=$desc[1]
ZX.prototype=$desc
-function hn(){}hn.builtin$cls="hn"
-if(!"name" in hn)hn.name="hn"
-$desc=$collectedClasses.hn
+function ycx(){}ycx.builtin$cls="ycx"
+if(!"name" in ycx)ycx.name="ycx"
+$desc=$collectedClasses.ycx
if($desc instanceof Array)$desc=$desc[1]
-hn.prototype=$desc
+ycx.prototype=$desc
function nE(){}nE.builtin$cls="nE"
if(!"name" in nE)nE.name="nE"
$desc=$collectedClasses.nE
@@ -22484,8 +23600,8 @@
$desc=$collectedClasses.RA
if($desc instanceof Array)$desc=$desc[1]
RA.prototype=$desc
-function IY(F1,i3,G1){this.F1=F1
-this.i3=i3
+function IY(F1,xh,G1){this.F1=F1
+this.xh=xh
this.G1=G1}IY.builtin$cls="IY"
if(!"name" in IY)IY.name="IY"
$desc=$collectedClasses.IY
@@ -22910,10 +24026,10 @@
$desc=$collectedClasses.tQ
if($desc instanceof Array)$desc=$desc[1]
tQ.prototype=$desc
-function aC(FJ,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.FJ=FJ
+function aC(FJ,VJ,Ai,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.FJ=FJ
this.VJ=VJ
this.Ai=Ai
-this.tH=tH
+this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -22939,10 +24055,10 @@
$desc=$collectedClasses.Vf
if($desc instanceof Array)$desc=$desc[1]
Vf.prototype=$desc
-function Be(Zw,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Zw=Zw
+function Be(Zw,VJ,Ai,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Zw=Zw
this.VJ=VJ
this.Ai=Ai
-this.tH=tH
+this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -22968,12 +24084,12 @@
$desc=$collectedClasses.tu
if($desc instanceof Array)$desc=$desc[1]
tu.prototype=$desc
-function i6(Xf,VA,P2,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Xf=Xf
-this.VA=VA
-this.P2=P2
+function i6(zh,HX,Uy,VJ,Ai,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.zh=zh
+this.HX=HX
+this.Uy=Uy
this.VJ=VJ
this.Ai=Ai
-this.tH=tH
+this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -22990,18 +24106,18 @@
$desc=$collectedClasses.i6
if($desc instanceof Array)$desc=$desc[1]
i6.prototype=$desc
-i6.prototype.gXf=function(receiver){return receiver.Xf}
-i6.prototype.gXf.$reflectable=1
-i6.prototype.sXf=function(receiver,v){return receiver.Xf=v}
-i6.prototype.sXf.$reflectable=1
-i6.prototype.gVA=function(receiver){return receiver.VA}
-i6.prototype.gVA.$reflectable=1
-i6.prototype.sVA=function(receiver,v){return receiver.VA=v}
-i6.prototype.sVA.$reflectable=1
-i6.prototype.gP2=function(receiver){return receiver.P2}
-i6.prototype.gP2.$reflectable=1
-i6.prototype.sP2=function(receiver,v){return receiver.P2=v}
-i6.prototype.sP2.$reflectable=1
+i6.prototype.gzh=function(receiver){return receiver.zh}
+i6.prototype.gzh.$reflectable=1
+i6.prototype.szh=function(receiver,v){return receiver.zh=v}
+i6.prototype.szh.$reflectable=1
+i6.prototype.gHX=function(receiver){return receiver.HX}
+i6.prototype.gHX.$reflectable=1
+i6.prototype.sHX=function(receiver,v){return receiver.HX=v}
+i6.prototype.sHX.$reflectable=1
+i6.prototype.gUy=function(receiver){return receiver.Uy}
+i6.prototype.gUy.$reflectable=1
+i6.prototype.sUy=function(receiver,v){return receiver.Uy=v}
+i6.prototype.sUy.$reflectable=1
function Vc(){}Vc.builtin$cls="Vc"
if(!"name" in Vc)Vc.name="Vc"
$desc=$collectedClasses.Vc
@@ -23083,12 +24199,12 @@
$desc=$collectedClasses.rR
if($desc instanceof Array)$desc=$desc[1]
rR.prototype=$desc
-function AM(Kw,xZ){this.Kw=Kw
-this.xZ=xZ}AM.builtin$cls="AM"
-if(!"name" in AM)AM.name="AM"
-$desc=$collectedClasses.AM
+function vZ(Kw,xZ){this.Kw=Kw
+this.xZ=xZ}vZ.builtin$cls="vZ"
+if(!"name" in vZ)vZ.name="vZ"
+$desc=$collectedClasses.vZ
if($desc instanceof Array)$desc=$desc[1]
-AM.prototype=$desc
+vZ.prototype=$desc
function d5(Kw,xZ){this.Kw=Kw
this.xZ=xZ}d5.builtin$cls="d5"
if(!"name" in d5)d5.name="d5"
@@ -23277,11 +24393,11 @@
$desc=$collectedClasses.bl
if($desc instanceof Array)$desc=$desc[1]
bl.prototype=$desc
-function Ef(a){this.a=a}Ef.builtin$cls="Ef"
-if(!"name" in Ef)Ef.name="Ef"
-$desc=$collectedClasses.Ef
+function tB(a){this.a=a}tB.builtin$cls="tB"
+if(!"name" in tB)tB.name="tB"
+$desc=$collectedClasses.tB
if($desc instanceof Array)$desc=$desc[1]
-Ef.prototype=$desc
+tB.prototype=$desc
function Oo(){}Oo.builtin$cls="Oo"
if(!"name" in Oo)Oo.name="Oo"
$desc=$collectedClasses.Oo
@@ -23297,7 +24413,7 @@
$desc=$collectedClasses.Ax
if($desc instanceof Array)$desc=$desc[1]
Ax.prototype=$desc
-function Wf(WL,Tx,H8,Ht,pz,le,qN,jd,tB,b0,FU,T1,Ly,M2,uA,Db,Ok,qm,UF,nz,If){this.WL=WL
+function Wf(Cr,Tx,H8,Ht,pz,le,qN,jd,tB,b0,FU,T1,Ly,M2,uA,Db,Ok,qm,UF,nz,If){this.Cr=Cr
this.Tx=Tx
this.H8=H8
this.Ht=Ht
@@ -23322,8 +24438,8 @@
$desc=$collectedClasses.Wf
if($desc instanceof Array)$desc=$desc[1]
Wf.prototype=$desc
-Wf.prototype.gWL=function(){return this.WL}
-Wf.prototype.gWL.$reflectable=1
+Wf.prototype.gCr=function(){return this.Cr}
+Wf.prototype.gCr.$reflectable=1
Wf.prototype.gTx=function(){return this.Tx}
Wf.prototype.gTx.$reflectable=1
Wf.prototype.gH8=function(){return this.H8}
@@ -23431,7 +24547,7 @@
$desc=$collectedClasses.Sz
if($desc instanceof Array)$desc=$desc[1]
Sz.prototype=$desc
-function Zk(dl,Yq,lT,hB,Fo,xV,qx,nz,le,G6,Cr,If){this.dl=dl
+function Zk(dl,Yq,lT,hB,Fo,xV,qx,nz,le,G6,H3,If){this.dl=dl
this.Yq=Yq
this.lT=lT
this.hB=hB
@@ -23441,7 +24557,7 @@
this.nz=nz
this.le=le
this.G6=G6
-this.Cr=Cr
+this.H3=H3
this.If=If}Zk.builtin$cls="Zk"
if(!"name" in Zk)Zk.name="Zk"
$desc=$collectedClasses.Zk
@@ -23459,14 +24575,14 @@
if($desc instanceof Array)$desc=$desc[1]
fu.prototype=$desc
fu.prototype.gh7=function(){return this.h7}
-function ng(WL,CM,If){this.WL=WL
+function ng(Cr,CM,If){this.Cr=Cr
this.CM=CM
this.If=If}ng.builtin$cls="ng"
if(!"name" in ng)ng.name="ng"
$desc=$collectedClasses.ng
if($desc instanceof Array)$desc=$desc[1]
ng.prototype=$desc
-ng.prototype.gWL=function(){return this.WL}
+ng.prototype.gCr=function(){return this.Cr}
function Ar(d9,o3,yA,zM,h7){this.d9=d9
this.o3=o3
this.yA=yA
@@ -24000,13 +25116,13 @@
$desc=$collectedClasses.ez
if($desc instanceof Array)$desc=$desc[1]
ez.prototype=$desc
-function fI(LD){this.LD=LD}fI.builtin$cls="fI"
-if(!"name" in fI)fI.name="fI"
-$desc=$collectedClasses.fI
+function lx(LD){this.LD=LD}lx.builtin$cls="lx"
+if(!"name" in lx)lx.name="lx"
+$desc=$collectedClasses.lx
if($desc instanceof Array)$desc=$desc[1]
-fI.prototype=$desc
-fI.prototype.gLD=function(){return this.LD}
-fI.prototype.sLD=function(v){return this.LD=v}
+lx.prototype=$desc
+lx.prototype.gLD=function(){return this.LD}
+lx.prototype.sLD=function(v){return this.LD=v}
function LV(P,LD){this.P=P
this.LD=LD}LV.builtin$cls="LV"
if(!"name" in LV)LV.name="LV"
@@ -24591,18 +25707,33 @@
$desc=$collectedClasses.z0
if($desc instanceof Array)$desc=$desc[1]
z0.prototype=$desc
-function Vx(){}Vx.builtin$cls="Vx"
-if(!"name" in Vx)Vx.name="Vx"
-$desc=$collectedClasses.Vx
+function E3(){}E3.builtin$cls="E3"
+if(!"name" in E3)E3.name="E3"
+$desc=$collectedClasses.E3
if($desc instanceof Array)$desc=$desc[1]
-Vx.prototype=$desc
-function Rw(WF,An,EN){this.WF=WF
+E3.prototype=$desc
+function Rw(vn,An,EN){this.vn=vn
this.An=An
this.EN=EN}Rw.builtin$cls="Rw"
if(!"name" in Rw)Rw.name="Rw"
$desc=$collectedClasses.Rw
if($desc instanceof Array)$desc=$desc[1]
Rw.prototype=$desc
+function GY(lH){this.lH=lH}GY.builtin$cls="GY"
+if(!"name" in GY)GY.name="GY"
+$desc=$collectedClasses.GY
+if($desc instanceof Array)$desc=$desc[1]
+GY.prototype=$desc
+function jZ(lH,aS,rU,Hu,iU,VN){this.lH=lH
+this.aS=aS
+this.rU=rU
+this.Hu=Hu
+this.iU=iU
+this.VN=VN}jZ.builtin$cls="jZ"
+if(!"name" in jZ)jZ.name="jZ"
+$desc=$collectedClasses.jZ
+if($desc instanceof Array)$desc=$desc[1]
+jZ.prototype=$desc
function h0(a){this.a=a}h0.builtin$cls="h0"
if(!"name" in h0)h0.name="h0"
$desc=$collectedClasses.h0
@@ -24767,11 +25898,11 @@
$desc=$collectedClasses.cX
if($desc instanceof Array)$desc=$desc[1]
cX.prototype=$desc
-function Fl(){}Fl.builtin$cls="Fl"
-if(!"name" in Fl)Fl.name="Fl"
-$desc=$collectedClasses.Fl
+function eL(){}eL.builtin$cls="eL"
+if(!"name" in eL)eL.name="eL"
+$desc=$collectedClasses.eL
if($desc instanceof Array)$desc=$desc[1]
-Fl.prototype=$desc
+eL.prototype=$desc
function L8(){}L8.builtin$cls="L8"
if(!"name" in L8)L8.name="L8"
$desc=$collectedClasses.L8
@@ -24893,6 +26024,11 @@
$desc=$collectedClasses.XZ
if($desc instanceof Array)$desc=$desc[1]
XZ.prototype=$desc
+function qz(a){this.a=a}qz.builtin$cls="qz"
+if(!"name" in qz)qz.name="qz"
+$desc=$collectedClasses.qz
+if($desc instanceof Array)$desc=$desc[1]
+qz.prototype=$desc
function hQ(){}hQ.builtin$cls="hQ"
if(!"name" in hQ)hQ.name="hQ"
$desc=$collectedClasses.hQ
@@ -24924,6 +26060,11 @@
$desc=$collectedClasses.rI
if($desc instanceof Array)$desc=$desc[1]
rI.prototype=$desc
+function dD(iY){this.iY=iY}dD.builtin$cls="dD"
+if(!"name" in dD)dD.name="dD"
+$desc=$collectedClasses.dD
+if($desc instanceof Array)$desc=$desc[1]
+dD.prototype=$desc
function QZ(){}QZ.builtin$cls="QZ"
if(!"name" in QZ)QZ.name="QZ"
$desc=$collectedClasses.QZ
@@ -24934,11 +26075,11 @@
$desc=$collectedClasses.BV
if($desc instanceof Array)$desc=$desc[1]
BV.prototype=$desc
-function E1(){}E1.builtin$cls="E1"
-if(!"name" in E1)E1.name="E1"
-$desc=$collectedClasses.E1
+function id(){}id.builtin$cls="id"
+if(!"name" in id)id.name="id"
+$desc=$collectedClasses.id
if($desc instanceof Array)$desc=$desc[1]
-E1.prototype=$desc
+id.prototype=$desc
function wz(Sn,Sc){this.Sn=Sn
this.Sc=Sc}wz.builtin$cls="wz"
if(!"name" in wz)wz.name="wz"
@@ -25014,11 +26155,11 @@
$desc=$collectedClasses.RAp
if($desc instanceof Array)$desc=$desc[1]
RAp.prototype=$desc
-function Gb(){}Gb.builtin$cls="Gb"
-if(!"name" in Gb)Gb.name="Gb"
-$desc=$collectedClasses.Gb
+function ma(){}ma.builtin$cls="ma"
+if(!"name" in ma)ma.name="ma"
+$desc=$collectedClasses.ma
if($desc instanceof Array)$desc=$desc[1]
-Gb.prototype=$desc
+ma.prototype=$desc
function cf(){}cf.builtin$cls="cf"
if(!"name" in cf)cf.name="cf"
$desc=$collectedClasses.cf
@@ -25150,12 +26291,12 @@
$desc=$collectedClasses.W9
if($desc instanceof Array)$desc=$desc[1]
W9.prototype=$desc
-function vZ(a,b){this.a=a
-this.b=b}vZ.builtin$cls="vZ"
-if(!"name" in vZ)vZ.name="vZ"
-$desc=$collectedClasses.vZ
+function uY(a,b){this.a=a
+this.b=b}uY.builtin$cls="uY"
+if(!"name" in uY)uY.name="uY"
+$desc=$collectedClasses.uY
if($desc instanceof Array)$desc=$desc[1]
-vZ.prototype=$desc
+uY.prototype=$desc
function dW(Ui){this.Ui=Ui}dW.builtin$cls="dW"
if(!"name" in dW)dW.name="dW"
$desc=$collectedClasses.dW
@@ -25226,11 +26367,11 @@
$desc=$collectedClasses.QS
if($desc instanceof Array)$desc=$desc[1]
QS.prototype=$desc
-function QF(){}QF.builtin$cls="QF"
-if(!"name" in QF)QF.name="QF"
-$desc=$collectedClasses.QF
+function ej(){}ej.builtin$cls="ej"
+if(!"name" in ej)ej.name="ej"
+$desc=$collectedClasses.ej
if($desc instanceof Array)$desc=$desc[1]
-QF.prototype=$desc
+ej.prototype=$desc
function NL(){}NL.builtin$cls="NL"
if(!"name" in NL)NL.name="NL"
$desc=$collectedClasses.NL
@@ -25246,11 +26387,11 @@
$desc=$collectedClasses.D4
if($desc instanceof Array)$desc=$desc[1]
D4.prototype=$desc
-function X9(){}X9.builtin$cls="X9"
-if(!"name" in X9)X9.name="X9"
-$desc=$collectedClasses.X9
+function L9u(){}L9u.builtin$cls="L9u"
+if(!"name" in L9u)L9u.name="L9u"
+$desc=$collectedClasses.L9u
if($desc instanceof Array)$desc=$desc[1]
-X9.prototype=$desc
+L9u.prototype=$desc
function Ms(){}Ms.builtin$cls="Ms"
if(!"name" in Ms)Ms.name="Ms"
$desc=$collectedClasses.Ms
@@ -25384,10 +26525,10 @@
$desc=$collectedClasses.UZ
if($desc instanceof Array)$desc=$desc[1]
UZ.prototype=$desc
-function Fv(FT,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.FT=FT
+function Fv(FT,VJ,Ai,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.FT=FT
this.VJ=VJ
this.Ai=Ai
-this.tH=tH
+this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -25413,11 +26554,11 @@
$desc=$collectedClasses.WZ
if($desc instanceof Array)$desc=$desc[1]
WZ.prototype=$desc
-function I3(Py,hO,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Py=Py
+function I3(Py,hO,VJ,Ai,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Py=Py
this.hO=hO
this.VJ=VJ
this.Ai=Ai
-this.tH=tH
+this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -25447,10 +26588,10 @@
$desc=$collectedClasses.pv
if($desc instanceof Array)$desc=$desc[1]
pv.prototype=$desc
-function Gk(vt,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.vt=vt
+function Gk(vt,VJ,Ai,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.vt=vt
this.VJ=VJ
this.Ai=Ai
-this.tH=tH
+this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -25476,10 +26617,10 @@
$desc=$collectedClasses.Vfx
if($desc instanceof Array)$desc=$desc[1]
Vfx.prototype=$desc
-function Ds(ql,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.ql=ql
+function Ds(ql,VJ,Ai,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.ql=ql
this.VJ=VJ
this.Ai=Ai
-this.tH=tH
+this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -25539,7 +26680,7 @@
$desc=$collectedClasses.GE
if($desc instanceof Array)$desc=$desc[1]
GE.prototype=$desc
-function u7(tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.tH=tH
+function u7(hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -25556,11 +26697,11 @@
$desc=$collectedClasses.u7
if($desc instanceof Array)$desc=$desc[1]
u7.prototype=$desc
-function St(Pw,i0,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Pw=Pw
+function St(Pw,i0,VJ,Ai,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Pw=Pw
this.i0=i0
this.VJ=VJ
this.Ai=Ai
-this.tH=tH
+this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -25590,11 +26731,11 @@
$desc=$collectedClasses.tuj
if($desc instanceof Array)$desc=$desc[1]
tuj.prototype=$desc
-function vj(eb,kf,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.eb=eb
+function vj(eb,kf,VJ,Ai,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.eb=eb
this.kf=kf
this.VJ=VJ
this.Ai=Ai
-this.tH=tH
+this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -25624,10 +26765,10 @@
$desc=$collectedClasses.Vct
if($desc instanceof Array)$desc=$desc[1]
Vct.prototype=$desc
-function CX(iI,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.iI=iI
+function CX(iI,VJ,Ai,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.iI=iI
this.VJ=VJ
this.Ai=Ai
-this.tH=tH
+this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -25694,8 +26835,8 @@
HV.prototype.gG1=function(receiver){return this.G1}
HV.prototype.gkc=function(receiver){return this.kc}
HV.prototype.gI4=function(){return this.I4}
-function Nh(XB,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.XB=XB
-this.tH=tH
+function BK(XB,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.XB=XB
+this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -25707,15 +26848,15 @@
this.Vk=Vk
this.Ye=Ye
this.mT=mT
-this.KM=KM}Nh.builtin$cls="Nh"
-if(!"name" in Nh)Nh.name="Nh"
-$desc=$collectedClasses.Nh
+this.KM=KM}BK.builtin$cls="BK"
+if(!"name" in BK)BK.name="BK"
+$desc=$collectedClasses.BK
if($desc instanceof Array)$desc=$desc[1]
-Nh.prototype=$desc
-Nh.prototype.gXB=function(receiver){return receiver.XB}
-Nh.prototype.gXB.$reflectable=1
-Nh.prototype.sXB=function(receiver,v){return receiver.XB=v}
-Nh.prototype.sXB.$reflectable=1
+BK.prototype=$desc
+BK.prototype.gXB=function(receiver){return receiver.XB}
+BK.prototype.gXB.$reflectable=1
+BK.prototype.sXB=function(receiver,v){return receiver.XB=v}
+BK.prototype.sXB.$reflectable=1
function fA(T9,Jt){this.T9=T9
this.Jt=Jt}fA.builtin$cls="fA"
if(!"name" in fA)fA.name="fA"
@@ -25743,7 +26884,7 @@
$desc=$collectedClasses.c5
if($desc instanceof Array)$desc=$desc[1]
c5.prototype=$desc
-function ih(tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.tH=tH
+function ih(hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -25775,18 +26916,17 @@
mL.prototype.glw.$reflectable=1
mL.prototype.gnI=function(){return this.nI}
mL.prototype.gnI.$reflectable=1
-function bv(jO,oc,VJ,Ai){this.jO=jO
-this.oc=oc
+function bv(nk,YG,XR,VJ,Ai){this.nk=nk
+this.YG=YG
+this.XR=XR
this.VJ=VJ
this.Ai=Ai}bv.builtin$cls="bv"
if(!"name" in bv)bv.name="bv"
$desc=$collectedClasses.bv
if($desc instanceof Array)$desc=$desc[1]
bv.prototype=$desc
-bv.prototype.gjO=function(receiver){return this.jO}
-bv.prototype.gjO.$reflectable=1
-bv.prototype.goc=function(receiver){return this.oc}
-bv.prototype.goc.$reflectable=1
+bv.prototype.gXR=function(){return this.XR}
+bv.prototype.gXR.$reflectable=1
function pt(JR,i2,VJ,Ai){this.JR=JR
this.i2=i2
this.VJ=VJ
@@ -25824,8 +26964,9 @@
$desc=$collectedClasses.ZW
if($desc instanceof Array)$desc=$desc[1]
ZW.prototype=$desc
-function dZ(JR,IT,VJ,Ai){this.JR=JR
+function dZ(JR,IT,Jj,VJ,Ai){this.JR=JR
this.IT=IT
+this.Jj=Jj
this.VJ=VJ
this.Ai=Ai}dZ.builtin$cls="dZ"
if(!"name" in dZ)dZ.name="dZ"
@@ -25846,16 +26987,33 @@
Nu.prototype=$desc
Nu.prototype.sJR=function(v){return this.JR=v}
Nu.prototype.se0=function(v){return this.e0=v}
-function pF(a){this.a=a}pF.builtin$cls="pF"
+function pF(a,b){this.a=a
+this.b=b}pF.builtin$cls="pF"
if(!"name" in pF)pF.name="pF"
$desc=$collectedClasses.pF
if($desc instanceof Array)$desc=$desc[1]
pF.prototype=$desc
-function Ha(b){this.b=b}Ha.builtin$cls="Ha"
+function Ha(c){this.c=c}Ha.builtin$cls="Ha"
if(!"name" in Ha)Ha.name="Ha"
$desc=$collectedClasses.Ha
if($desc instanceof Array)$desc=$desc[1]
Ha.prototype=$desc
+function nu(d){this.d=d}nu.builtin$cls="nu"
+if(!"name" in nu)nu.name="nu"
+$desc=$collectedClasses.nu
+if($desc instanceof Array)$desc=$desc[1]
+nu.prototype=$desc
+function be(a,b){this.a=a
+this.b=b}be.builtin$cls="be"
+if(!"name" in be)be.name="be"
+$desc=$collectedClasses.be
+if($desc instanceof Array)$desc=$desc[1]
+be.prototype=$desc
+function Pg(c){this.c=c}Pg.builtin$cls="Pg"
+if(!"name" in Pg)Pg.name="Pg"
+$desc=$collectedClasses.Pg
+if($desc instanceof Array)$desc=$desc[1]
+Pg.prototype=$desc
function jI(JR,e0,oJ,vm,VJ,Ai){this.JR=JR
this.e0=e0
this.oJ=oJ
@@ -25866,7 +27024,28 @@
$desc=$collectedClasses.jI
if($desc instanceof Array)$desc=$desc[1]
jI.prototype=$desc
-function F1(tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.tH=tH
+function Zw(Rd,n7,LA,Vg,VJ,Ai){this.Rd=Rd
+this.n7=n7
+this.LA=LA
+this.Vg=Vg
+this.VJ=VJ
+this.Ai=Ai}Zw.builtin$cls="Zw"
+if(!"name" in Zw)Zw.name="Zw"
+$desc=$collectedClasses.Zw
+if($desc instanceof Array)$desc=$desc[1]
+Zw.prototype=$desc
+Zw.prototype.gLA=function(receiver){return this.LA}
+Zw.prototype.gLA.$reflectable=1
+function Pf(WF,uM,ZQ,VJ,Ai){this.WF=WF
+this.uM=uM
+this.ZQ=ZQ
+this.VJ=VJ
+this.Ai=Ai}Pf.builtin$cls="Pf"
+if(!"name" in Pf)Pf.name="Pf"
+$desc=$collectedClasses.Pf
+if($desc instanceof Array)$desc=$desc[1]
+Pf.prototype=$desc
+function F1(hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -25883,7 +27062,7 @@
$desc=$collectedClasses.F1
if($desc instanceof Array)$desc=$desc[1]
F1.prototype=$desc
-function uL(tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.tH=tH
+function uL(hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -25900,10 +27079,10 @@
$desc=$collectedClasses.uL
if($desc instanceof Array)$desc=$desc[1]
uL.prototype=$desc
-uL.prototype.gtH=function(receiver){return receiver.tH}
-uL.prototype.gtH.$reflectable=1
-uL.prototype.stH=function(receiver,v){return receiver.tH=v}
-uL.prototype.stH.$reflectable=1
+uL.prototype.ghm=function(receiver){return receiver.hm}
+uL.prototype.ghm.$reflectable=1
+uL.prototype.shm=function(receiver,v){return receiver.hm=v}
+uL.prototype.shm.$reflectable=1
function Xf(){}Xf.builtin$cls="Xf"
if(!"name" in Xf)Xf.name="Xf"
$desc=$collectedClasses.Xf
@@ -25971,11 +27150,11 @@
$desc=$collectedClasses.Zb
if($desc instanceof Array)$desc=$desc[1]
Zb.prototype=$desc
-function id(g){this.g=g}id.builtin$cls="id"
-if(!"name" in id)id.name="id"
-$desc=$collectedClasses.id
+function bF(g){this.g=g}bF.builtin$cls="bF"
+if(!"name" in bF)bF.name="bF"
+$desc=$collectedClasses.bF
if($desc instanceof Array)$desc=$desc[1]
-id.prototype=$desc
+bF.prototype=$desc
function iV(h,i,j,k){this.h=h
this.i=i
this.j=j
@@ -25995,16 +27174,16 @@
W4.prototype=$desc
W4.prototype.gWA=function(){return this.WA}
W4.prototype.gIl=function(){return this.Il}
-function Fa(){}Fa.builtin$cls="Fa"
-if(!"name" in Fa)Fa.name="Fa"
-$desc=$collectedClasses.Fa
+function ndx(){}ndx.builtin$cls="ndx"
+if(!"name" in ndx)ndx.name="ndx"
+$desc=$collectedClasses.ndx
if($desc instanceof Array)$desc=$desc[1]
-Fa.prototype=$desc
-function ma(){}ma.builtin$cls="ma"
-if(!"name" in ma)ma.name="ma"
-$desc=$collectedClasses.ma
+ndx.prototype=$desc
+function Hm(){}Hm.builtin$cls="Hm"
+if(!"name" in Hm)Hm.name="Hm"
+$desc=$collectedClasses.Hm
if($desc instanceof Array)$desc=$desc[1]
-ma.prototype=$desc
+Hm.prototype=$desc
function d3(){}d3.builtin$cls="d3"
if(!"name" in d3)d3.name="d3"
$desc=$collectedClasses.d3
@@ -26255,11 +27434,11 @@
$desc=$collectedClasses.w12
if($desc instanceof Array)$desc=$desc[1]
w12.prototype=$desc
-function fTP(a){this.a=a}fTP.builtin$cls="fTP"
-if(!"name" in fTP)fTP.name="fTP"
-$desc=$collectedClasses.fTP
+function ppY(a){this.a=a}ppY.builtin$cls="ppY"
+if(!"name" in ppY)ppY.name="ppY"
+$desc=$collectedClasses.ppY
if($desc instanceof Array)$desc=$desc[1]
-fTP.prototype=$desc
+ppY.prototype=$desc
function yL(){}yL.builtin$cls="yL"
if(!"name" in yL)yL.name="yL"
$desc=$collectedClasses.yL
@@ -26417,16 +27596,26 @@
$desc=$collectedClasses.Bl
if($desc instanceof Array)$desc=$desc[1]
Bl.prototype=$desc
+function Fn(){}Fn.builtin$cls="Fn"
+if(!"name" in Fn)Fn.name="Fn"
+$desc=$collectedClasses.Fn
+if($desc instanceof Array)$desc=$desc[1]
+Fn.prototype=$desc
+function e3(){}e3.builtin$cls="e3"
+if(!"name" in e3)e3.name="e3"
+$desc=$collectedClasses.e3
+if($desc instanceof Array)$desc=$desc[1]
+e3.prototype=$desc
function pM(){}pM.builtin$cls="pM"
if(!"name" in pM)pM.name="pM"
$desc=$collectedClasses.pM
if($desc instanceof Array)$desc=$desc[1]
pM.prototype=$desc
-function Mh(){}Mh.builtin$cls="Mh"
-if(!"name" in Mh)Mh.name="Mh"
-$desc=$collectedClasses.Mh
+function jh(){}jh.builtin$cls="jh"
+if(!"name" in jh)jh.name="jh"
+$desc=$collectedClasses.jh
if($desc instanceof Array)$desc=$desc[1]
-Mh.prototype=$desc
+jh.prototype=$desc
function Md(){}Md.builtin$cls="Md"
if(!"name" in Md)Md.name="Md"
$desc=$collectedClasses.Md
@@ -26462,11 +27651,11 @@
$desc=$collectedClasses.mf
if($desc instanceof Array)$desc=$desc[1]
mf.prototype=$desc
-function ej(){}ej.builtin$cls="ej"
-if(!"name" in ej)ej.name="ej"
-$desc=$collectedClasses.ej
+function ik(){}ik.builtin$cls="ik"
+if(!"name" in ik)ik.name="ik"
+$desc=$collectedClasses.ik
if($desc instanceof Array)$desc=$desc[1]
-ej.prototype=$desc
+ik.prototype=$desc
function HK(b){this.b=b}HK.builtin$cls="HK"
if(!"name" in HK)HK.name="HK"
$desc=$collectedClasses.HK
@@ -26761,6 +27950,60 @@
ky.prototype=$desc
ky.prototype.gBb=function(receiver){return this.Bb}
ky.prototype.gT8=function(receiver){return this.T8}
+function uA(a,b){this.a=a
+this.b=b}uA.builtin$cls="uA"
+if(!"name" in uA)uA.name="uA"
+$desc=$collectedClasses.uA
+if($desc instanceof Array)$desc=$desc[1]
+uA.prototype=$desc
+function vl(hP,KL,bO,tj,Lv,k6){this.hP=hP
+this.KL=KL
+this.bO=bO
+this.tj=tj
+this.Lv=Lv
+this.k6=k6}vl.builtin$cls="vl"
+if(!"name" in vl)vl.name="vl"
+$desc=$collectedClasses.vl
+if($desc instanceof Array)$desc=$desc[1]
+vl.prototype=$desc
+vl.prototype.ghP=function(){return this.hP}
+function Li(a,b,c){this.a=a
+this.b=b
+this.c=c}Li.builtin$cls="Li"
+if(!"name" in Li)Li.name="Li"
+$desc=$collectedClasses.Li
+if($desc instanceof Array)$desc=$desc[1]
+Li.prototype=$desc
+function WK(d){this.d=d}WK.builtin$cls="WK"
+if(!"name" in WK)WK.name="WK"
+$desc=$collectedClasses.WK
+if($desc instanceof Array)$desc=$desc[1]
+WK.prototype=$desc
+function iT(hP,Jn,KL,bO,tj,Lv,k6){this.hP=hP
+this.Jn=Jn
+this.KL=KL
+this.bO=bO
+this.tj=tj
+this.Lv=Lv
+this.k6=k6}iT.builtin$cls="iT"
+if(!"name" in iT)iT.name="iT"
+$desc=$collectedClasses.iT
+if($desc instanceof Array)$desc=$desc[1]
+iT.prototype=$desc
+iT.prototype.ghP=function(){return this.hP}
+iT.prototype.gJn=function(){return this.Jn}
+function tE(a,b,c){this.a=a
+this.b=b
+this.c=c}tE.builtin$cls="tE"
+if(!"name" in tE)tE.name="tE"
+$desc=$collectedClasses.tE
+if($desc instanceof Array)$desc=$desc[1]
+tE.prototype=$desc
+function GS(d){this.d=d}GS.builtin$cls="GS"
+if(!"name" in GS)GS.name="GS"
+$desc=$collectedClasses.GS
+if($desc instanceof Array)$desc=$desc[1]
+GS.prototype=$desc
function fa(hP,re,KL,bO,tj,Lv,k6){this.hP=hP
this.re=re
this.KL=KL
@@ -26791,18 +28034,6 @@
$desc=$collectedClasses.a9
if($desc instanceof Array)$desc=$desc[1]
a9.prototype=$desc
-function jh(e,f,g){this.e=e
-this.f=f
-this.g=g}jh.builtin$cls="jh"
-if(!"name" in jh)jh.name="jh"
-$desc=$collectedClasses.jh
-if($desc instanceof Array)$desc=$desc[1]
-jh.prototype=$desc
-function e3(h){this.h=h}e3.builtin$cls="e3"
-if(!"name" in e3)e3.name="e3"
-$desc=$collectedClasses.e3
-if($desc instanceof Array)$desc=$desc[1]
-e3.prototype=$desc
function VA(Bb,T8,KL,bO,tj,Lv,k6){this.Bb=Bb
this.T8=T8
this.KL=KL
@@ -26912,6 +28143,22 @@
K9.prototype=$desc
K9.prototype.gBb=function(receiver){return this.Bb}
K9.prototype.gT8=function(receiver){return this.T8}
+function zX(hP,Jn){this.hP=hP
+this.Jn=Jn}zX.builtin$cls="zX"
+if(!"name" in zX)zX.name="zX"
+$desc=$collectedClasses.zX
+if($desc instanceof Array)$desc=$desc[1]
+zX.prototype=$desc
+zX.prototype.ghP=function(){return this.hP}
+zX.prototype.gJn=function(){return this.Jn}
+function x9(hP,oc){this.hP=hP
+this.oc=oc}x9.builtin$cls="x9"
+if(!"name" in x9)x9.name="x9"
+$desc=$collectedClasses.x9
+if($desc instanceof Array)$desc=$desc[1]
+x9.prototype=$desc
+x9.prototype.ghP=function(){return this.hP}
+x9.prototype.goc=function(receiver){return this.oc}
function RW(hP,bP,re){this.hP=hP
this.bP=bP
this.re=re}RW.builtin$cls="RW"
@@ -26927,11 +28174,10 @@
$desc=$collectedClasses.xs
if($desc instanceof Array)$desc=$desc[1]
xs.prototype=$desc
-function FX(Sk,Ix,ku,fL,lQ){this.Sk=Sk
+function FX(Sk,Ix,ku,fL){this.Sk=Sk
this.Ix=Ix
this.ku=ku
-this.fL=fL
-this.lQ=lQ}FX.builtin$cls="FX"
+this.fL=fL}FX.builtin$cls="FX"
if(!"name" in FX)FX.name="FX"
$desc=$collectedClasses.FX
if($desc instanceof Array)$desc=$desc[1]
@@ -26992,7 +28238,7 @@
$desc=$collectedClasses.a0
if($desc instanceof Array)$desc=$desc[1]
a0.prototype=$desc
-function NQ(tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.tH=tH
+function NQ(hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -27009,10 +28255,68 @@
$desc=$collectedClasses.NQ
if($desc instanceof Array)$desc=$desc[1]
NQ.prototype=$desc
-function uw(Qq,VJ,Ai,tH,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Qq=Qq
+function fI(Uz,VJ,Ai,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Uz=Uz
this.VJ=VJ
this.Ai=Ai
-this.tH=tH
+this.hm=hm
+this.VJ=VJ
+this.Ai=Ai
+this.VJ=VJ
+this.Ai=Ai
+this.ZI=ZI
+this.uN=uN
+this.z3=z3
+this.TQ=TQ
+this.Vk=Vk
+this.Ye=Ye
+this.mT=mT
+this.KM=KM}fI.builtin$cls="fI"
+if(!"name" in fI)fI.name="fI"
+$desc=$collectedClasses.fI
+if($desc instanceof Array)$desc=$desc[1]
+fI.prototype=$desc
+fI.prototype.gUz=function(receiver){return receiver.Uz}
+fI.prototype.gUz.$reflectable=1
+fI.prototype.sUz=function(receiver,v){return receiver.Uz=v}
+fI.prototype.sUz.$reflectable=1
+function WZq(){}WZq.builtin$cls="WZq"
+if(!"name" in WZq)WZq.name="WZq"
+$desc=$collectedClasses.WZq
+if($desc instanceof Array)$desc=$desc[1]
+WZq.prototype=$desc
+function kK(vX,VJ,Ai,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.vX=vX
+this.VJ=VJ
+this.Ai=Ai
+this.hm=hm
+this.VJ=VJ
+this.Ai=Ai
+this.VJ=VJ
+this.Ai=Ai
+this.ZI=ZI
+this.uN=uN
+this.z3=z3
+this.TQ=TQ
+this.Vk=Vk
+this.Ye=Ye
+this.mT=mT
+this.KM=KM}kK.builtin$cls="kK"
+if(!"name" in kK)kK.name="kK"
+$desc=$collectedClasses.kK
+if($desc instanceof Array)$desc=$desc[1]
+kK.prototype=$desc
+kK.prototype.gvX=function(receiver){return receiver.vX}
+kK.prototype.gvX.$reflectable=1
+kK.prototype.svX=function(receiver,v){return receiver.vX=v}
+kK.prototype.svX.$reflectable=1
+function pva(){}pva.builtin$cls="pva"
+if(!"name" in pva)pva.name="pva"
+$desc=$collectedClasses.pva
+if($desc instanceof Array)$desc=$desc[1]
+pva.prototype=$desc
+function uw(Qq,VJ,Ai,hm,VJ,Ai,VJ,Ai,ZI,uN,z3,TQ,Vk,Ye,mT,KM){this.Qq=Qq
+this.VJ=VJ
+this.Ai=Ai
+this.hm=hm
this.VJ=VJ
this.Ai=Ai
this.VJ=VJ
@@ -27033,11 +28337,11 @@
uw.prototype.gQq.$reflectable=1
uw.prototype.sQq=function(receiver,v){return receiver.Qq=v}
uw.prototype.sQq.$reflectable=1
-function WZq(){}WZq.builtin$cls="WZq"
-if(!"name" in WZq)WZq.name="WZq"
-$desc=$collectedClasses.WZq
+function cda(){}cda.builtin$cls="cda"
+if(!"name" in cda)cda.name="cda"
+$desc=$collectedClasses.cda
if($desc instanceof Array)$desc=$desc[1]
-WZq.prototype=$desc
+cda.prototype=$desc
function V2(N1,bn,Ck){this.N1=N1
this.bn=bn
this.Ck=Ck}V2.builtin$cls="V2"
@@ -27077,16 +28381,16 @@
$desc=$collectedClasses.Uf
if($desc instanceof Array)$desc=$desc[1]
Uf.prototype=$desc
-function ik(a){this.a=a}ik.builtin$cls="ik"
-if(!"name" in ik)ik.name="ik"
-$desc=$collectedClasses.ik
-if($desc instanceof Array)$desc=$desc[1]
-ik.prototype=$desc
-function LfS(b){this.b=b}LfS.builtin$cls="LfS"
+function LfS(a){this.a=a}LfS.builtin$cls="LfS"
if(!"name" in LfS)LfS.name="LfS"
$desc=$collectedClasses.LfS
if($desc instanceof Array)$desc=$desc[1]
LfS.prototype=$desc
+function fTP(b){this.b=b}fTP.builtin$cls="fTP"
+if(!"name" in fTP)fTP.name="fTP"
+$desc=$collectedClasses.fTP
+if($desc instanceof Array)$desc=$desc[1]
+fTP.prototype=$desc
function NP(Ca,LO,ZY,xS,PB,eS,Ii){this.Ca=Ca
this.LO=LO
this.ZY=ZY
@@ -27340,11 +28644,11 @@
$desc=$collectedClasses.Nb
if($desc instanceof Array)$desc=$desc[1]
Nb.prototype=$desc
-function HB(call$0,$name){this.call$0=call$0
-this.$name=$name}HB.builtin$cls="HB"
-$desc=$collectedClasses.HB
+function Fy(call$0,$name){this.call$0=call$0
+this.$name=$name}Fy.builtin$cls="Fy"
+$desc=$collectedClasses.Fy
if($desc instanceof Array)$desc=$desc[1]
-HB.prototype=$desc
+Fy.prototype=$desc
function eU(call$7,$name){this.call$7=call$7
this.$name=$name}eU.builtin$cls="eU"
$desc=$collectedClasses.eU
@@ -27375,4 +28679,4 @@
$desc=$collectedClasses.PW
if($desc instanceof Array)$desc=$desc[1]
PW.prototype=$desc
-return[qE,Yy,Ps,rK,fY,Mr,zx,ct,nB,i3,it,Az,QP,QW,n6,Ny,OM,QQ,MA,y4,d7,Rb,oJ,DG,mN,vH,hh,Em,Sb,rV,Wy,YN,bA,Wq,rz,BK,wj,cv,Fs,SX,ea,D0,as,T5,Aa,u5,Yu,iG,jP,U2,tA,xn,Vb,QH,ST,X2,fJ,Vi,tX,Sg,pA,Mi,Gt,In,Gx,eP,AL,Og,cS,M6,El,zm,SV,aB,ku,Ih,cW,DK,qm,ZY,cx,la,Vn,PG,xe,Hw,bn,Im,oB,Aj,oU,qT,KV,BH,mh,G7,wq,Ql,Xp,bP,mX,SN,HD,ni,p3,qj,qW,KR,ew,fs,bX,BL,MC,Mx,j2,yz,lp,kd,I0,QR,Cp,ua,zD,Ul,G0,wb,fq,h4,qk,GI,Tb,Iv,BT,yY,kJ,AE,xV,FH,y6,RH,pU,Lq,Mf,BR,r4,aG,J6,K5,UM,WS,rq,nK,kc,ij,ty,Nf,Nc,rj,rh,Zv,Q7,hF,yK,Y0,ZJ,mU,eZ,Ak,y5,nV,Zc,ui,D6,DQ,Sm,dx,es,eG,lv,pf,NV,W1,zo,wf,TU,bb,VE,zp,Xu,lu,tk,me,qN,NY,d4,MI,ca,kK,eW,um,Fu,OE,l6,BA,tp,rE,CC,PQ,uz,Yd,U0,AD,Gr,tc,GH,lo,NJ,nd,vt,rQ,EU,LR,MB,hy,r8,aS,CG,qF,MT,Rk,Eo,Dn,ox,ZD,NE,wD,BD,vRT,Fi,Qr,mj,cB,uY,yR,AX,xJ,l4,Et,NC,nb,By,xt,tG,P0,Jq,Xr,qD,Cf,AS,Kq,oI,mJ,rF,vi,ZX,hn,nE,zt,F0,Lt,Gv,kn,PE,QI,Tm,is,Q,jx,ZC,Jt,P,im,Pp,O,PK,JO,O2,aX,cC,RA,IY,JH,jl,Iy,JM,Ua,JG,ns,wd,TA,YP,yc,I9,Bj,NO,II,aJ,X1,HU,Pm,oo,OW,Dd,AP,yH,FA,Av,oH,LP,c2,WT,p8,XR,LI,A2,F3,u8,Gi,t2,Zr,ZQ,az,vV,Hk,XO,dr,TL,KX,uZ,OQ,Tp,v,Z3,D2,GT,Pe,Eq,cu,Lm,dC,wN,VX,VR,EK,KW,Pb,tQ,aC,Vf,Be,tu,i6,Vc,zO,aL,nH,a7,i1,xy,MH,A8,U5,SO,zs,rR,AM,d5,U1,SJ,SU,Tv,XC,iK,GD,Sn,nI,jU,Lj,mb,am,cw,EE,Uz,uh,Kv,oP,YX,BI,y1,M2,iu,mg,zE,bl,Ef,Oo,Tc,Ax,Wf,Un,Ei,U7,t0,Ld,Sz,Zk,fu,ng,Ar,jB,ye,Gj,Zz,Xh,Ca,Ik,JI,Ip,WV,C7,CQ,dz,tK,OR,Bg,DL,b8,j7,oV,TP,Zf,vs,da,xw,dm,rH,ZL,mi,jb,wB,Pu,qh,QC,Yl,Rv,YJ,jv,LB,DO,lz,Rl,Jb,M4,Jp,h7,pr,eN,B5,PI,j4,i9,VV,Dy,lU,xp,UH,Z5,ii,ib,MO,ms,UO,Bc,vp,lk,Gh,XB,ly,cK,O9,yU,nP,KA,Vo,qB,ez,fI,LV,DS,dp,B3,CR,ny,dR,uR,QX,YR,fB,eO,nO,t3,dq,dX,aY,wJ,e4,JB,Id,fZ,TF,Xz,Cg,Hs,uo,pK,eM,Ue,W5,R8,k6,oi,ce,o2,jG,fG,EQ,YB,iX,ou,S9,ey,xd,v6,db,Cm,N6,jg,YO,oz,b6,ef,zQ,Yp,u3,mW,ar,lD,W0,Sw,o0,a1,jp,Xt,Ba,An,LD,YI,OG,ro,DN,ZM,HW,JC,f1,Uk,wI,ob,by,QM,z0,Vx,Rw,h0,CL,K8,a2,fR,iP,MF,Rq,Hn,Zl,pl,a6,P7,DW,Ge,LK,AT,bJ,mp,ub,ds,lj,UV,VS,t7,HG,aE,kM,EH,cX,Fl,L8,c8,a,Od,mE,WU,Rn,wv,uq,iD,hb,XX,Kd,yZ,Gs,pm,Tw,wm,FB,Lk,XZ,hQ,Nw,kZ,JT,d9,rI,QZ,BV,E1,wz,B1,M5,Jn,DM,zL,ec,Kx,iO,bU,e7,nj,rl,RAp,Gb,cf,E9,nF,FK,Si,vf,Fc,hD,I4,e0,RO,eu,ie,Ea,pu,i2,b0,Ov,qO,RX,kG,Gm,W9,vZ,dW,PA,H2,O7,HI,E4,r7,Tz,Wk,DV,Hp,Nz,Jd,QS,QF,NL,vr,D4,X9,Ms,Fw,RS,RY,Ys,vg,xG,Vj,VW,RK,DH,ZK,Th,Vju,KB,RKu,na,TkQ,xGn,ZKG,VWk,w6W,DHb,z9g,G8,UZ,Fv,WZ,I3,pv,Gk,Vfx,Ds,Dsd,CA,YL,KC,xL,As,GE,u7,St,tuj,vj,Vct,CX,D13,TJ,dG,Ng,HV,Nh,fA,tz,jR,PO,c5,ih,mL,bv,pt,Zd,dY,vY,dS,ZW,dZ,Qe,Nu,pF,Ha,jI,F1,uL,Xf,Pi,yj,qI,J3,E5,o5,b5,zI,Zb,id,iV,W4,Fa,ma,d3,X6,xh,wn,uF,cj,HA,br,zT,D7,qL,C4,l9,lP,km,Qt,Dk,A0,rm,eY,OO,BE,Qb,xI,q1,Zj,XP,q6,CK,BO,ZG,Oc,MX,w12,fTP,yL,dM,Y7,WC,Xi,TV,Mq,Oa,n1,xf,L6,Rs,uJ,hm,Ji,Bf,ir,Tt,GN,k8,HJ,S0,V3,Bl,pM,Mh,Md,Lf,fT,pp,Nq,nl,mf,ej,HK,w13,o8,GL,e9,Dw,Xy,uK,mY,fE,mB,XF,iH,wJY,zOQ,W6o,MdQ,YJG,DOe,lPa,Ufa,Raa,w0,w4,w5,w7,w9,w10,w11,c4,z6,Ay,Ed,G1,Os,Dl,Wh,x5,ev,ID,jV,ek,OC,Xm,Jy,ky,fa,WW,vQ,a9,jh,e3,VA,J1,fk,wL,B0,Fq,hw,EZ,no,kB,ae,Iq,w6,jK,uk,K9,RW,xs,FX,Ae,Bt,vR,Pn,hc,hA,fr,a0,NQ,uw,WZq,V2,D8,jY,ll,Uf,ik,LfS,NP,Vh,r0,jz,SA,zV,nv,ee,XI,hs,yp,ug,DT,OB,Ra,N9,NW,HS,TG,ts,Kj,VU,Ya,XT,ic,VT,T4,TR,VD,Oh,zy,Nb,HB,eU,ADW,Ri,kq,Ag,PW]}
\ No newline at end of file
+return[qE,Yy,Ps,rK,fY,Mr,zx,ct,nB,i3,it,Az,QP,QW,n6,Ny,OM,QQ,MA,y4,d7,Rb,oJ,DG,mN,vH,hh,Em,Sb,rV,Wy,QF,bA,Wq,rz,Nh,wj,cv,Fs,SX,ea,D0,as,T5,Aa,u5,Yu,iG,jP,U2,tA,xn,Vb,QH,ST,X2,fJ,Vi,tX,Sg,pA,Mi,Gt,In,Gx,eP,AL,Og,cS,M6,El,zm,SV,aB,ku,Ih,cW,DK,qm,ZY,cx,la,Vn,PG,xe,Hw,bn,Im,oB,Aj,oU,qT,KV,BH,mh,G7,kl,Ql,Xp,bP,mX,SN,HD,ni,p3,qj,qW,KR,ew,fs,bX,BL,MC,Mx,j2,yz,lp,kd,I0,QR,Cp,ua,zD,Ul,G0,wb,fq,h4,qk,GI,Tb,tV,BT,yY,kJ,AE,xV,FH,y6,RH,pU,Lq,Mf,BR,r4,aG,J6,K5,UM,WS,rq,nK,kc,Eh,ty,Nf,Nc,rj,rh,Zv,Q7,hF,yK,HB,ZJ,mU,eZ,Fl,y5,nV,Zc,ui,D6,DQ,Sm,dx,es,eG,lv,pf,NV,W1,zo,wf,TU,bb,VE,zp,Xu,lu,tk,me,qN,NY,d4,MI,ca,xX,eW,um,Fu,OE,l6,BA,tp,rE,CC,PQ,uz,Yd,U0,AD,Gr,tc,GH,lo,NJ,nd,vt,rQ,EU,LR,MB,hy,r8,aS,CG,qF,MT,xN,Eo,Dn,ox,ZD,NE,wD,BD,vRT,Fi,Qr,mj,cB,k2,yR,AX,xJ,l4,Et,NC,nb,By,xt,tG,P0,Jq,Xr,qD,Cf,AS,Kq,oI,mJ,rF,vi,ZX,ycx,nE,zt,F0,Lt,Gv,kn,PE,QI,Tm,is,Q,jx,ZC,Jt,P,im,Pp,O,PK,JO,O2,aX,cC,RA,IY,JH,jl,Iy,JM,Ua,JG,ns,wd,TA,YP,yc,I9,Bj,NO,II,aJ,X1,HU,Pm,oo,OW,Dd,AP,yH,FA,Av,oH,LP,c2,WT,p8,XR,LI,A2,F3,u8,Gi,t2,Zr,ZQ,az,vV,Hk,XO,dr,TL,KX,uZ,OQ,Tp,v,Z3,D2,GT,Pe,Eq,cu,Lm,dC,wN,VX,VR,EK,KW,Pb,tQ,aC,Vf,Be,tu,i6,Vc,zO,aL,nH,a7,i1,xy,MH,A8,U5,SO,zs,rR,vZ,d5,U1,SJ,SU,Tv,XC,iK,GD,Sn,nI,jU,Lj,mb,am,cw,EE,Uz,uh,Kv,oP,YX,BI,y1,M2,iu,mg,zE,bl,tB,Oo,Tc,Ax,Wf,Un,Ei,U7,t0,Ld,Sz,Zk,fu,ng,Ar,jB,ye,Gj,Zz,Xh,Ca,Ik,JI,Ip,WV,C7,CQ,dz,tK,OR,Bg,DL,b8,j7,oV,TP,Zf,vs,da,xw,dm,rH,ZL,mi,jb,wB,Pu,qh,QC,Yl,Rv,YJ,jv,LB,DO,lz,Rl,Jb,M4,Jp,h7,pr,eN,B5,PI,j4,i9,VV,Dy,lU,xp,UH,Z5,ii,ib,MO,ms,UO,Bc,vp,lk,Gh,XB,ly,cK,O9,yU,nP,KA,Vo,qB,ez,lx,LV,DS,dp,B3,CR,ny,dR,uR,QX,YR,fB,eO,nO,t3,dq,dX,aY,wJ,e4,JB,Id,fZ,TF,Xz,Cg,Hs,uo,pK,eM,Ue,W5,R8,k6,oi,ce,o2,jG,fG,EQ,YB,iX,ou,S9,ey,xd,v6,db,Cm,N6,jg,YO,oz,b6,ef,zQ,Yp,u3,mW,ar,lD,W0,Sw,o0,a1,jp,Xt,Ba,An,LD,YI,OG,ro,DN,ZM,HW,JC,f1,Uk,wI,ob,by,QM,z0,E3,Rw,GY,jZ,h0,CL,K8,a2,fR,iP,MF,Rq,Hn,Zl,pl,a6,P7,DW,Ge,LK,AT,bJ,mp,ub,ds,lj,UV,VS,t7,HG,aE,kM,EH,cX,eL,L8,c8,a,Od,mE,WU,Rn,wv,uq,iD,hb,XX,Kd,yZ,Gs,pm,Tw,wm,FB,Lk,XZ,qz,hQ,Nw,kZ,JT,d9,rI,dD,QZ,BV,id,wz,B1,M5,Jn,DM,zL,ec,Kx,iO,bU,e7,nj,rl,RAp,ma,cf,E9,nF,FK,Si,vf,Fc,hD,I4,e0,RO,eu,ie,Ea,pu,i2,b0,Ov,qO,RX,kG,Gm,W9,uY,dW,PA,H2,O7,HI,E4,r7,Tz,Wk,DV,Hp,Nz,Jd,QS,ej,NL,vr,D4,L9u,Ms,Fw,RS,RY,Ys,vg,xG,Vj,VW,RK,DH,ZK,Th,Vju,KB,RKu,na,TkQ,xGn,ZKG,VWk,w6W,DHb,z9g,G8,UZ,Fv,WZ,I3,pv,Gk,Vfx,Ds,Dsd,CA,YL,KC,xL,As,GE,u7,St,tuj,vj,Vct,CX,D13,TJ,dG,Ng,HV,BK,fA,tz,jR,PO,c5,ih,mL,bv,pt,Zd,dY,vY,dS,ZW,dZ,Qe,Nu,pF,Ha,nu,be,Pg,jI,Zw,Pf,F1,uL,Xf,Pi,yj,qI,J3,E5,o5,b5,zI,Zb,bF,iV,W4,ndx,Hm,d3,X6,xh,wn,uF,cj,HA,br,zT,D7,qL,C4,l9,lP,km,Qt,Dk,A0,rm,eY,OO,BE,Qb,xI,q1,Zj,XP,q6,CK,BO,ZG,Oc,MX,w12,ppY,yL,dM,Y7,WC,Xi,TV,Mq,Oa,n1,xf,L6,Rs,uJ,hm,Ji,Bf,ir,Tt,GN,k8,HJ,S0,V3,Bl,Fn,e3,pM,jh,Md,Lf,fT,pp,Nq,nl,mf,ik,HK,w13,o8,GL,e9,Dw,Xy,uK,mY,fE,mB,XF,iH,wJY,zOQ,W6o,MdQ,YJG,DOe,lPa,Ufa,Raa,w0,w4,w5,w7,w9,w10,w11,c4,z6,Ay,Ed,G1,Os,Dl,Wh,x5,ev,ID,jV,ek,OC,Xm,Jy,ky,uA,vl,Li,WK,iT,tE,GS,fa,WW,vQ,a9,VA,J1,fk,wL,B0,Fq,hw,EZ,no,kB,ae,Iq,w6,jK,uk,K9,zX,x9,RW,xs,FX,Ae,Bt,vR,Pn,hc,hA,fr,a0,NQ,fI,WZq,kK,pva,uw,cda,V2,D8,jY,ll,Uf,LfS,fTP,NP,Vh,r0,jz,SA,zV,nv,ee,XI,hs,yp,ug,DT,OB,Ra,N9,NW,HS,TG,ts,Kj,VU,Ya,XT,ic,VT,T4,TR,VD,Oh,zy,Nb,Fy,eU,ADW,Ri,kq,Ag,PW]}
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/lib/observatory.dart b/runtime/bin/vmservice/client/lib/observatory.dart
index 990b5f2c..11a25ac 100644
--- a/runtime/bin/vmservice/client/lib/observatory.dart
+++ b/runtime/bin/vmservice/client/lib/observatory.dart
@@ -11,3 +11,4 @@
part 'src/observatory/isolate.dart';
part 'src/observatory/isolate_manager.dart';
part 'src/observatory/request_manager.dart';
+part 'src/observatory/script_source.dart';
diff --git a/runtime/bin/vmservice/client/lib/observatory_elements.dart b/runtime/bin/vmservice/client/lib/observatory_elements.dart
index ab3025a..6847736 100644
--- a/runtime/bin/vmservice/client/lib/observatory_elements.dart
+++ b/runtime/bin/vmservice/client/lib/observatory_elements.dart
@@ -12,4 +12,6 @@
export
'package:observatory/src/observatory_elements/observatory_application.dart';
export 'package:observatory/src/observatory_elements/response_viewer.dart';
-export 'package:observatory/src/observatory_elements/stack_trace.dart';
\ No newline at end of file
+export 'package:observatory/src/observatory_elements/script_view.dart';
+export 'package:observatory/src/observatory_elements/source_view.dart';
+export 'package:observatory/src/observatory_elements/stack_trace.dart';
diff --git a/runtime/bin/vmservice/client/lib/observatory_elements.html b/runtime/bin/vmservice/client/lib/observatory_elements.html
index b8955fd..199998a 100644
--- a/runtime/bin/vmservice/client/lib/observatory_elements.html
+++ b/runtime/bin/vmservice/client/lib/observatory_elements.html
@@ -15,9 +15,11 @@
<link rel="import" href="src/observatory_elements/navigation_bar.html">
<link rel="import"
href="src/observatory_elements/observatory_application.html">
-<link rel="import"
- href="src/observatory_elements/observatory_element.html">
+ <link rel="import"
+ href="src/observatory_elements/observatory_element.html">
<link rel="import" href="src/observatory_elements/response_viewer.html">
+ <link rel="import" href="src/observatory_elements/script_view.html">
+ <link rel="import" href="src/observatory_elements/source_view.html">
<link rel="import" href="src/observatory_elements/stack_trace.html">
</head>
</html>
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/lib/src/observatory/isolate.dart b/runtime/bin/vmservice/client/lib/src/observatory/isolate.dart
index b761b2f..c5423b9 100644
--- a/runtime/bin/vmservice/client/lib/src/observatory/isolate.dart
+++ b/runtime/bin/vmservice/client/lib/src/observatory/isolate.dart
@@ -6,8 +6,10 @@
/// State for a running isolate.
class Isolate extends Observable {
- @observable final int id;
- @observable final String name;
+ @observable int id;
+ @observable String name;
+ @observable final Map<String, ScriptSource> scripts =
+ toObservable(new Map<String, ScriptSource>());
Isolate(this.id, this.name);
diff --git a/runtime/bin/vmservice/client/lib/src/observatory/isolate_manager.dart b/runtime/bin/vmservice/client/lib/src/observatory/isolate_manager.dart
index 93cba65..1471450 100644
--- a/runtime/bin/vmservice/client/lib/src/observatory/isolate_manager.dart
+++ b/runtime/bin/vmservice/client/lib/src/observatory/isolate_manager.dart
@@ -24,6 +24,15 @@
});
}
+ Isolate getIsolate(int id) {
+ Isolate isolate = isolates[id];
+ if (isolate == null) {
+ isolate = new Isolate(id, '');
+ isolates[id] = isolate;
+ }
+ return isolate;
+ }
+
void _updateIsolates(List<Map> members) {
// Find dead isolates.
var deadIsolates = [];
@@ -43,6 +52,8 @@
if (isolates[id] == null) {
var isolate = new Isolate(id, name);
isolates[id] = isolate;
+ } else {
+ isolates[id].name = name;
}
});
}
diff --git a/runtime/bin/vmservice/client/lib/src/observatory/location_manager.dart b/runtime/bin/vmservice/client/lib/src/observatory/location_manager.dart
index 97df456..b4f487c 100644
--- a/runtime/bin/vmservice/client/lib/src/observatory/location_manager.dart
+++ b/runtime/bin/vmservice/client/lib/src/observatory/location_manager.dart
@@ -16,7 +16,7 @@
ObservatoryApplication get application => _application;
@observable String currentHash = '';
-
+ @observable Uri currentHashUri;
void init() {
window.onHashChange.listen((event) {
if (setDefaultHash()) {
@@ -48,6 +48,15 @@
return currentIsolateAnchorPrefix() != null;
}
+ bool get isScriptLink {
+ String type = currentHashUri.queryParameters['type'];
+ return type == 'Script';
+ }
+
+ String get scriptName {
+ return Uri.decodeQueryComponent(currentHashUri.queryParameters['name']);
+ }
+
/// Extract the current isolate id as an integer. Returns [InvalidIsolateId]
/// if none is present in window.location.
int currentIsolateId() {
@@ -76,6 +85,7 @@
currentHash = window.location.hash;
// Chomp off the #
String requestUrl = currentHash.substring(1);
+ currentHashUri = Uri.parse(requestUrl);
application.requestManager.get(requestUrl);
}
@@ -109,6 +119,16 @@
return classLink(isolateId, cid);
}
+ /// Create a request for the script [objectId] with script [name].
+ @observable
+ String currentIsolateScriptLink(int objectId, String name) {
+ var isolateId = currentIsolateId();
+ if (isolateId == LocationManager.InvalidIsolateId) {
+ return defaultHash;
+ }
+ return scriptLink(isolateId, objectId, name);
+ }
+
/// Create a request for [l] on [isolateId].
@observable
String relativeLink(int isolateId, String l) {
@@ -126,4 +146,12 @@
String classLink(int isolateId, int cid) {
return '#/isolates/$isolateId/classes/$cid';
}
+
+ @observable
+ /// Create a request for the script [objectId] with script [url].
+ String scriptLink(int isolateId, int objectId, String name) {
+ String encodedName = Uri.encodeQueryComponent(name);
+ return '#/isolates/$isolateId/objects/$objectId'
+ '?type=Script&name=$encodedName';
+ }
}
diff --git a/runtime/bin/vmservice/client/lib/src/observatory/request_manager.dart b/runtime/bin/vmservice/client/lib/src/observatory/request_manager.dart
index 328601d..9a26b54 100644
--- a/runtime/bin/vmservice/client/lib/src/observatory/request_manager.dart
+++ b/runtime/bin/vmservice/client/lib/src/observatory/request_manager.dart
@@ -47,11 +47,47 @@
/// Request [requestString] from the VM service. Updates [responses].
/// Will trigger [interceptor] if one is set.
- Future<Map> get(String requestString) {
- request(requestString).then((responseString) {
- parseResponses(responseString);
+ void get(String requestString) {
+ if (_application.locationManager.isScriptLink) {
+ // We cache script sources.
+ String scriptName = _application.locationManager.scriptName;
+ getScriptSource(scriptName, requestString).then((source) {
+ if (source != null) {
+ setResponses([{
+ 'type': 'Script',
+ 'source': source
+ }]);
+ } else {
+ setResponses([{
+ 'type': 'RequestError',
+ 'error': 'Source for $scriptName could not be loaded.'
+ }]);
+ }
+ });
+ } else {
+ request(requestString).then((responseString) {
+ parseResponses(responseString);
+ }).catchError((e) {
+ setResponseError(e.target);
+ });
+ }
+ }
+
+ Future<ScriptSource> getScriptSource(String name, String requestString) {
+ int isolateId = _application.locationManager.currentIsolateId();
+ Isolate isolate = _application.isolateManager.getIsolate(isolateId);
+ ScriptSource source = isolate.scripts[name];
+ if (source != null) {
+ return new Future.value(source);
+ }
+ return request(requestString).then((responseString) {
+ var r = JSON.decode(responseString);
+ ScriptSource scriptSource = new ScriptSource(r);
+ isolate.scripts[name] = scriptSource;
+ return scriptSource;
}).catchError((e) {
setResponseError(e.target);
+ return null;
});
}
diff --git a/runtime/bin/vmservice/client/lib/src/observatory/script_source.dart b/runtime/bin/vmservice/client/lib/src/observatory/script_source.dart
new file mode 100644
index 0000000..1c2acec
--- /dev/null
+++ b/runtime/bin/vmservice/client/lib/src/observatory/script_source.dart
@@ -0,0 +1,42 @@
+// 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.
+
+part of observatory;
+
+class ScriptSourceLine extends Observable {
+ final int line;
+ final int numDigits;
+ @observable final String src;
+ @observable String paddedLine;
+ ScriptSourceLine(this.line, this.numDigits, this.src) {
+ paddedLine = '$line';
+ for (int i = paddedLine.length; i < numDigits; i++) {
+ paddedLine = ' $paddedLine';
+ }
+ }
+}
+
+class ScriptSource extends Observable {
+ @observable String kind = '';
+ @observable String url = '';
+ @observable List<ScriptSourceLine> lines = toObservable([]);
+
+ ScriptSource(Map response) {
+ kind = response['kind'];
+ url = response['name'];
+ buildSourceLines(response['source']);
+ }
+
+ void buildSourceLines(String src) {
+ List<String> splitSrc = src.split('\n');
+ int numDigits = '${splitSrc.length+1}'.length;
+ for (int i = 0; i < splitSrc.length; i++) {
+ ScriptSourceLine sourceLine = new ScriptSourceLine(i+1, numDigits,
+ splitSrc[i]);
+ lines.add(sourceLine);
+ }
+ }
+
+ String toString() => 'ScriptSource';
+}
diff --git a/runtime/bin/vmservice/client/lib/src/observatory_elements/error_view.dart b/runtime/bin/vmservice/client/lib/src/observatory_elements/error_view.dart
index 787dba1..33c4089 100644
--- a/runtime/bin/vmservice/client/lib/src/observatory_elements/error_view.dart
+++ b/runtime/bin/vmservice/client/lib/src/observatory_elements/error_view.dart
@@ -11,7 +11,7 @@
@CustomTag('error-view')
class ErrorViewElement extends ObservatoryElement {
@published String error = '';
- @published error_obj;
+ @published var error_obj;
ErrorViewElement.created() : super.created();
}
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/lib/src/observatory_elements/library_view.html b/runtime/bin/vmservice/client/lib/src/observatory_elements/library_view.html
index aaa0667..93009fb 100644
--- a/runtime/bin/vmservice/client/lib/src/observatory_elements/library_view.html
+++ b/runtime/bin/vmservice/client/lib/src/observatory_elements/library_view.html
@@ -4,13 +4,74 @@
<polymer-element name="library-view" extends="observatory-element">
<template>
<div class="alert alert-success">Library {{ library['name'] }}</div>
+ <div class="alert alert-info">Scripts</div>
+ <table class="table table-hover">
+ <tbody>
+ <tr template repeat="{{ script in library['scripts']}}">
+ <td>
+ {{ script['kind'] }}
+ </td>
+ <td>
+ <a href="{{ app.locationManager.currentIsolateScriptLink(script['id'], script['name']) }}">{{ script['name'] }}</a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
<div class="alert alert-info">Imported Libraries</div>
<table class="table table-hover">
<tbody>
<tr template repeat="{{ lib in library['libraries'] }}">
<td>
<a href="{{ app.locationManager.currentIsolateObjectLink(lib['id'])}}">
- {{ lib['name'] }}
+ {{ lib['url'] }}
+ </a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="alert alert-info">Variables</div>
+ <table class="table table-hover">
+ <tbody>
+ <tr template repeat="{{ variable in library['variables'] }}">
+ <td>
+ <template if="{{ variable['final'] }}">
+ final
+ </template>
+ <template if="{{ variable['const'] }}">
+ const
+ </template>
+ <template if="{{ (variable['declared_type']['name'] == 'dynamic' && !variable['final'] && !variable['const']) }}">
+ var
+ </template>
+ <template if="{{ (variable['declared_type']['name'] != 'dynamic') }}">
+ <a href="{{ app.locationManager.currentIsolateClassLink(variable['declared_type']['id']) }}">
+ {{ variable['declared_type']['user_name'] }}
+ </a>
+ </template>
+ <a href="{{ app.locationManager.currentIsolateObjectLink(variable['id'])}}">
+ {{ variable['user_name'] }}
+ </a>
+ </td>
+ <td>
+ <template if="{{ (variable['value']['type'] == 'null') }}">
+ {{ "null" }}
+ </template>
+ <template if="{{ (variable['value']['type'] != 'null') }}">
+ <a href="{{ app.locationManager.currentIsolateObjectLink(variable['value']['id'])}}">
+ {{ variable['value']['preview'] }}
+ </a>
+ </template>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <div class="alert alert-info">Functions</div>
+ <table class="table table-hover">
+ <tbody>
+ <tr template repeat="{{ func in library['functions'] }}">
+ <td>
+ <a href="{{ app.locationManager.currentIsolateObjectLink(func['id'])}}">
+ {{ func['user_name'] }}
</a>
</td>
</tr>
@@ -39,6 +100,7 @@
</tr>
</tbody>
</table>
+
</template>
<script type="application/dart" src="library_view.dart"></script>
</polymer-element>
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/lib/src/observatory_elements/message_viewer.html b/runtime/bin/vmservice/client/lib/src/observatory_elements/message_viewer.html
index 3ea91e3..6ed611e 100644
--- a/runtime/bin/vmservice/client/lib/src/observatory_elements/message_viewer.html
+++ b/runtime/bin/vmservice/client/lib/src/observatory_elements/message_viewer.html
@@ -7,6 +7,8 @@
<link rel="import" href="isolate_list.html">
<link rel="import" href="library_view.html">
<link rel="import" href="observatory_element.html">
+ <link rel="import" href="script_view.html">
+ <link rel="import" href="source_view.html">
<link rel="import" href="stack_trace.html">
</head>
<polymer-element name="message-viewer" extends="observatory-element">
@@ -42,6 +44,9 @@
<template if="{{ messageType == 'Code' }}">
<code-view app="{{ app }}" code="{{ message }}"></code-view>
</template>
+ <template if="{{ messageType == 'Script' }}">
+ <script-view app="{{ app }}" script="{{ message }}"></script-view>
+ </template>
<!-- Add new views and message types in the future here. -->
</template>
<script type="application/dart" src="message_viewer.dart"></script>
diff --git a/runtime/bin/vmservice/client/lib/src/observatory_elements/script_view.dart b/runtime/bin/vmservice/client/lib/src/observatory_elements/script_view.dart
new file mode 100644
index 0000000..2b8550e
--- /dev/null
+++ b/runtime/bin/vmservice/client/lib/src/observatory_elements/script_view.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library script_view_element;
+
+import 'package:polymer/polymer.dart';
+import 'observatory_element.dart';
+
+/// Displays an Error response.
+@CustomTag('script-view')
+class ScriptViewElement extends ObservatoryElement {
+ @published Map script;
+
+ ScriptViewElement.created() : super.created();
+}
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/lib/src/observatory_elements/script_view.html b/runtime/bin/vmservice/client/lib/src/observatory_elements/script_view.html
new file mode 100644
index 0000000..0666dff
--- /dev/null
+++ b/runtime/bin/vmservice/client/lib/src/observatory_elements/script_view.html
@@ -0,0 +1,10 @@
+<head>
+ <link rel="import" href="observatory_element.html">
+ <link rel="import" href="source_view.html">
+</head>
+<polymer-element name="script-view" extends="observatory-element">
+ <template>
+ <source-view app="{{ app }}" source="{{ script['source'] }}"></source-view>
+ </template>
+ <script type="application/dart" src="script_view.dart"></script>
+</polymer-element>
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/lib/src/observatory_elements/source_view.dart b/runtime/bin/vmservice/client/lib/src/observatory_elements/source_view.dart
new file mode 100644
index 0000000..4065aed
--- /dev/null
+++ b/runtime/bin/vmservice/client/lib/src/observatory_elements/source_view.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library source_view_element;
+
+import 'package:polymer/polymer.dart';
+import 'package:observatory/observatory.dart';
+import 'observatory_element.dart';
+
+/// Displays an Error response.
+@CustomTag('source-view')
+class SourceViewElement extends ObservatoryElement {
+ @published ScriptSource source;
+
+ SourceViewElement.created() : super.created();
+}
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/lib/src/observatory_elements/source_view.html b/runtime/bin/vmservice/client/lib/src/observatory_elements/source_view.html
new file mode 100644
index 0000000..38f3160
--- /dev/null
+++ b/runtime/bin/vmservice/client/lib/src/observatory_elements/source_view.html
@@ -0,0 +1,22 @@
+<head>
+ <link rel="import" href="observatory_element.html">
+</head>
+<polymer-element name="source-view" extends="observatory-element">
+ <template>
+ <div class="row">
+ <div class="col-md-8 col-md-offset-2">
+ <div class="panel-heading">{{ source.url }}</div>
+ <div class="panel-body">
+ <div class="row">
+ <div><strong>Source</strong></div>
+ </div>
+ <pre>
+ <template repeat="{{ line in source.lines }}">{{line.paddedLine}} {{line.src}}
+ </template>
+ </pre>
+ </div>
+ </div>
+ </div>
+ </template>
+ <script type="application/dart" src="source_view.dart"></script>
+</polymer-element>
\ No newline at end of file
diff --git a/runtime/bin/vmservice/client/web/index.html b/runtime/bin/vmservice/client/web/index.html
index 48a9cbd..b96cbdc 100644
--- a/runtime/bin/vmservice/client/web/index.html
+++ b/runtime/bin/vmservice/client/web/index.html
@@ -5,7 +5,7 @@
<link type="text/css" rel="stylesheet"
href="bootstrap_css/css/bootstrap.min.css" />
<link rel="import" href="packages/observatory/observatory_elements.html">
- <script type='application/dart'>export 'package:polymer/init.dart';</script>
+ <script type="application/dart">export 'package:polymer/init.dart';</script>
<script src="packages/browser/dart.js"></script>
</head>
<body>
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 805737c..feb3819 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -409,6 +409,12 @@
* This handle has the lifetime of the current isolate unless it is
* explicitly deallocated by calling Dart_DeletePersistentHandle.
*
+ * If the object becomes unreachable the callback is invoked with the weak
+ * persistent handle and the peer as arguments. This gives the native code the
+ * ability to cleanup data associated with the object and to delete the weak
+ * persistent handle. It is illegal to call into the VM from the callback,
+ * except to delete the weak persistent handle.
+ *
* Requires there to be a current isolate.
*
* \param object An object.
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 405c129..d67d438 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -250,7 +250,7 @@
const Array& args = Array::Handle(Array::New(6));
args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
args.SetAt(1, type);
- args.SetAt(2, String::Handle(cls.UserVisibleName()));
+ args.SetAt(2, String::Handle(cls.Name()));
args.SetAt(3, Bool::Get(cls.NumTypeParameters() != 0));
args.SetAt(4, cls.NumTypeParameters() == 0 ? Bool::False() : is_declaration);
args.SetAt(5, owner_mirror);
diff --git a/runtime/lib/simd128.cc b/runtime/lib/simd128.cc
index 2bda632..d52530b 100644
--- a/runtime/lib/simd128.cc
+++ b/runtime/lib/simd128.cc
@@ -406,10 +406,10 @@
GET_NON_NULL_NATIVE_ARGUMENT(Integer, y, arguments->NativeArgAt(2));
GET_NON_NULL_NATIVE_ARGUMENT(Integer, z, arguments->NativeArgAt(3));
GET_NON_NULL_NATIVE_ARGUMENT(Integer, w, arguments->NativeArgAt(4));
- int32_t _x = static_cast<int32_t>(x.AsInt64Value() & 0xFFFFFFFF);
- int32_t _y = static_cast<int32_t>(y.AsInt64Value() & 0xFFFFFFFF);
- int32_t _z = static_cast<int32_t>(z.AsInt64Value() & 0xFFFFFFFF);
- int32_t _w = static_cast<int32_t>(w.AsInt64Value() & 0xFFFFFFFF);
+ int32_t _x = static_cast<int32_t>(x.AsTruncatedUint32Value());
+ int32_t _y = static_cast<int32_t>(y.AsTruncatedUint32Value());
+ int32_t _z = static_cast<int32_t>(z.AsTruncatedUint32Value());
+ int32_t _w = static_cast<int32_t>(w.AsTruncatedUint32Value());
return Int32x4::New(_x, _y, _z, _w);
}
diff --git a/runtime/lib/typed_data.dart b/runtime/lib/typed_data.dart
index fb3d65f..2a71553 100644
--- a/runtime/lib/typed_data.dart
+++ b/runtime/lib/typed_data.dart
@@ -317,14 +317,14 @@
// Method(s) implementing the Collection interface.
bool contains(element) => IterableMixinWorkaround.contains(this, element);
- void forEach(void f(num element)) {
+ void forEach(void f(element)) {
var len = this.length;
for (var i = 0; i < len; i++) {
f(this[i]);
}
}
- Iterable map(f(num element)) {
+ Iterable map(f(element)) {
return IterableMixinWorkaround.mapList(this, f);
}
@@ -332,20 +332,20 @@
return IterableMixinWorkaround.join(this, separator);
}
- num reduce(dynamic combine(num value, num element)) {
+ dynamic reduce(dynamic combine(value, element)) {
return IterableMixinWorkaround.reduce(this, combine);
}
dynamic fold(dynamic initialValue,
- dynamic combine(dynamic initialValue, num element)) {
+ dynamic combine(dynamic initialValue, element)) {
return IterableMixinWorkaround.fold(this, initialValue, combine);
}
- Iterable where(bool f(num element)) {
+ Iterable where(bool f(element)) {
return IterableMixinWorkaround.where(this, f);
}
- Iterable expand(Iterable f(num element)) {
+ Iterable expand(Iterable f(element)) {
return IterableMixinWorkaround.expand(this, f);
}
@@ -353,7 +353,7 @@
return IterableMixinWorkaround.takeList(this, n);
}
- Iterable takeWhile(bool test(num element)) {
+ Iterable takeWhile(bool test(element)) {
return IterableMixinWorkaround.takeWhile(this, test);
}
@@ -361,35 +361,35 @@
return IterableMixinWorkaround.skipList(this, n);
}
- Iterable skipWhile(bool test(num element)) {
+ Iterable skipWhile(bool test(element)) {
return IterableMixinWorkaround.skipWhile(this, test);
}
- bool every(bool f(num element)) {
+ bool every(bool f(element)) {
return IterableMixinWorkaround.every(this, f);
}
- bool any(bool f(num element)) {
+ bool any(bool f(element)) {
return IterableMixinWorkaround.any(this, f);
}
- num firstWhere(bool test(num element), {orElse()}) {
+ dynamic firstWhere(bool test(element), {orElse()}) {
return IterableMixinWorkaround.firstWhere(this, test, orElse);
}
- num lastWhere(bool test(num element), {orElse()}) {
+ dynamic lastWhere(bool test(element), {orElse()}) {
return IterableMixinWorkaround.lastWhereList(this, test, orElse);
}
- num singleWhere(bool test(num element)) {
+ dynamic singleWhere(bool test(element)) {
return IterableMixinWorkaround.singleWhere(this, test);
}
- Iterable<num> get reversed {
+ Iterable<dynamic> get reversed {
return IterableMixinWorkaround.reversedList(this);
}
- num elementAt(int index) {
+ dynamic elementAt(int index) {
return this[index];
}
@@ -426,7 +426,7 @@
"Cannot insert into a non-extendable array");
}
- void sort([int compare(num a, num b)]) {
+ void sort([int compare(a, b)]) {
IterableMixinWorkaround.sortList(this, compare);
}
@@ -472,17 +472,17 @@
"Cannot remove from a non-extendable array");
}
- num get first {
+ dynamic get first {
if (length > 0) return this[0];
throw new StateError("No elements");
}
- num get last {
+ dynamic get last {
if (length > 0) return this[length - 1];
throw new StateError("No elements");
}
- num get single {
+ dynamic get single {
if (length == 1) return this[0];
if (length == 0) throw new StateError("No elements");
throw new StateError("More than one element");
@@ -506,7 +506,7 @@
return new Set.from(this);
}
- Map<int, num> asMap() {
+ Map<int, dynamic> asMap() {
return IterableMixinWorkaround.asMapList(this);
}
@@ -534,7 +534,7 @@
IterableMixinWorkaround.setAllList(this, index, iterable);
}
- void fillRange(int start, int end, [num fillValue]) {
+ void fillRange(int start, int end, [fillValue]) {
IterableMixinWorkaround.fillRangeList(this, start, end, fillValue);
}
diff --git a/runtime/platform/c99_support_win.h b/runtime/platform/c99_support_win.h
index 71ec127..b952ecd 100644
--- a/runtime/platform/c99_support_win.h
+++ b/runtime/platform/c99_support_win.h
@@ -5,8 +5,10 @@
#ifndef PLATFORM_C99_SUPPORT_WIN_H_
#define PLATFORM_C99_SUPPORT_WIN_H_
-// Visual C++ is missing a bunch of C99 math macros and
-// functions. Define them here.
+#if defined(_MSC_VER) && (_MSC_VER < 1800)
+
+// Before Visual Studio 2013 Visual C++ was missing a bunch of C99 math macros
+// and functions. Define them here.
#include <float.h>
#include <string.h>
@@ -70,5 +72,6 @@
#define strtoll _strtoi64
#endif
+#endif
#endif // PLATFORM_C99_SUPPORT_WIN_H_
diff --git a/runtime/platform/thread_win.cc b/runtime/platform/thread_win.cc
index d3712d2..f4494ae 100644
--- a/runtime/platform/thread_win.cc
+++ b/runtime/platform/thread_win.cc
@@ -293,6 +293,8 @@
ASSERT(previous != NULL);
previous->next_ = current->next_;
}
+ // Clear next.
+ wait_data->next_ = NULL;
break;
}
previous = current;
diff --git a/runtime/vm/bigint_operations.cc b/runtime/vm/bigint_operations.cc
index c77eb42..d036fde 100644
--- a/runtime/vm/bigint_operations.cc
+++ b/runtime/vm/bigint_operations.cc
@@ -693,6 +693,16 @@
}
+uint32_t BigintOperations::TruncateToUint32(const Bigint& bigint) {
+ uint32_t value = 0;
+ for (intptr_t i = bigint.Length() - 1; i >= 0; i--) {
+ value <<= kDigitBitSize;
+ value += static_cast<uint32_t>(bigint.GetChunkAt(i));
+ }
+ return value;
+}
+
+
bool BigintOperations::AbsFitsIntoUint64(const Bigint& bigint) {
intptr_t b_length = bigint.Length();
intptr_t num_bits = CountBits(bigint.GetChunkAt(b_length - 1));
diff --git a/runtime/vm/bigint_operations.h b/runtime/vm/bigint_operations.h
index b56eb83..70fe3a2 100644
--- a/runtime/vm/bigint_operations.h
+++ b/runtime/vm/bigint_operations.h
@@ -68,6 +68,7 @@
static bool FitsIntoUint64(const Bigint& bigint);
static bool AbsFitsIntoUint64(const Bigint& bigint);
static uint64_t ToUint64(const Bigint& bigint);
+ static uint32_t TruncateToUint32(const Bigint& bigint);
static uint64_t AbsToUint64(const Bigint& bigint);
static RawDouble* ToDouble(const Bigint& bigint);
diff --git a/runtime/vm/block_scheduler.cc b/runtime/vm/block_scheduler.cc
index 37a9710..1591929 100644
--- a/runtime/vm/block_scheduler.cc
+++ b/runtime/vm/block_scheduler.cc
@@ -53,7 +53,8 @@
void BlockScheduler::AssignEdgeWeights() const {
const Code& unoptimized_code = Code::Handle(
- flow_graph()->parsed_function().function().unoptimized_code());
+ flow_graph()->parsed_function().code());
+ ASSERT(!unoptimized_code.IsNull());
intptr_t entry_count =
ComputeEdgeCount(unoptimized_code,
diff --git a/runtime/vm/cha_test.cc b/runtime/vm/cha_test.cc
index 1b2786f..f78aeef 100644
--- a/runtime/vm/cha_test.cc
+++ b/runtime/vm/cha_test.cc
@@ -28,7 +28,7 @@
"}\n";
TestCase::LoadTestScript(kScriptChars, NULL);
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
const String& name = String::Handle(String::New(TestCase::url()));
const Library& lib = Library::Handle(Library::LookupLibrary(name));
EXPECT(!lib.IsNull());
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index b5216dc..64a2c87 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -104,10 +104,10 @@
}
-// Type hierarchy finalization occurs:
+// Processing ObjectStore::pending_classes_ occurs:
// a) when bootstrap process completes (VerifyBootstrapClasses).
// b) after the user classes are loaded (dart_api).
-bool ClassFinalizer::FinalizeTypeHierarchy() {
+bool ClassFinalizer::ProcessPendingClasses() {
bool retval = true;
Isolate* isolate = Isolate::Current();
ASSERT(isolate != NULL);
@@ -227,7 +227,7 @@
// Finalize type hierarchy for types that aren't pre-finalized
// by Object::Init().
- if (!FinalizeTypeHierarchy()) {
+ if (!ProcessPendingClasses()) {
// TODO(srdjan): Exit like a real VM instead.
const Error& err = Error::Handle(object_store->sticky_error());
OS::PrintErr("Could not verify bootstrap classes : %s\n",
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index 25d4861..91ec1ff 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -78,11 +78,11 @@
// Return false if we still have classes pending to be finalized.
static bool AllClassesFinalized();
- // Return whether type hierarchy finalization failed.
- // The function returns true if the finalization was successful.
- // If finalization fails, an error message is set in the sticky error field
+ // Return whether processing pending classes (ObjectStore::pending_classes_)
+ // failed. The function returns true if the processing was successful.
+ // If processin fails, an error message is set in the sticky error field
// in the object store.
- static bool FinalizeTypeHierarchy();
+ static bool ProcessPendingClasses();
// Finalize the types appearing in the declaration of class 'cls', i.e. its
// type parameters and their upper bounds, its super type and interfaces.
diff --git a/runtime/vm/class_finalizer_test.cc b/runtime/vm/class_finalizer_test.cc
index 1f55b0f..972eb6d 100644
--- a/runtime/vm/class_finalizer_test.cc
+++ b/runtime/vm/class_finalizer_test.cc
@@ -40,7 +40,7 @@
pending_classes.Add(*classes_2[1]);
classes_2.Add(&Class::ZoneHandle(CreateTestClass("Alfa")));
pending_classes.Add(*classes_2[2]);
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
for (int i = 0; i < classes_1.length(); i++) {
EXPECT(classes_1[i]->is_type_finalized());
}
@@ -48,7 +48,7 @@
EXPECT(classes_2[i]->is_type_finalized());
}
EXPECT(ClassFinalizer::AllClassesFinalized());
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
}
@@ -67,7 +67,7 @@
Type::Handle(Type::NewNonParameterizedType(*classes[1])));
classes[1]->set_super_type(
Type::Handle(Type::NewNonParameterizedType(*classes[0])));
- EXPECT(!ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(!ClassFinalizer::ProcessPendingClasses());
}
@@ -99,7 +99,7 @@
Type::New(Object::Handle(unresolved.raw()),
type_arguments,
Scanner::kDummyTokenIndex)));
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
}
} // namespace dart
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index 3d87602..0d007b2 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -219,7 +219,7 @@
"}\n";
// First setup the script and compile the script.
TestCase::LoadTestScript(kScriptChars, native_resolver);
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
const String& name = String::Handle(String::New(TestCase::url()));
const Library& lib = Library::Handle(Library::LookupLibrary(name));
EXPECT(!lib.IsNull());
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 686ddd1..882f593 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -1341,9 +1341,16 @@
DartFrameIterator iterator;
StackFrame* frame = iterator.NextFrame();
ASSERT(frame != NULL);
- const Function& function = Function::Handle(frame->LookupDartFunction());
+ const Code& code = Code::ZoneHandle(frame->LookupDartCode());
+ ASSERT(!code.IsNull());
+ const Function& function = Function::Handle(code.function());
ASSERT(!function.IsNull());
- if (!CanOptimizeFunction(function, isolate)) return;
+ // Since the code is referenced from the frame and the ZoneHandle,
+ // it cannot have been removed from the function.
+ ASSERT(function.HasCode());
+ if (!CanOptimizeFunction(function, isolate)) {
+ return;
+ }
intptr_t osr_id =
Code::Handle(function.unoptimized_code()).GetDeoptIdForOsr(frame->pc());
if (FLAG_trace_osr) {
@@ -1354,9 +1361,14 @@
}
const Code& original_code = Code::Handle(function.CurrentCode());
+ // Since the code is referenced from the frame and the ZoneHandle,
+ // it cannot have been removed from the function.
+ ASSERT(!original_code.IsNull());
const Error& error =
Error::Handle(Compiler::CompileOptimizedFunction(function, osr_id));
- if (!error.IsNull()) Exceptions::PropagateError(error);
+ if (!error.IsNull()) {
+ Exceptions::PropagateError(error);
+ }
const Code& optimized_code = Code::Handle(function.CurrentCode());
// The current code will not be changed in the case that the compiler
@@ -1433,30 +1445,25 @@
ASSERT(caller_code.is_optimized());
const Function& target_function = Function::Handle(
caller_code.GetStaticCallTargetFunctionAt(frame->pc()));
+ const Code& target_code = Code::Handle(
+ caller_code.GetStaticCallTargetCodeAt(frame->pc()));
+ ASSERT(!target_code.IsNull());
+ // Since there was a reference to the target_code in the caller_code, it is
+ // not possible for the target_function's code to be disconnected.
+ ASSERT(target_function.HasCode());
+ ASSERT(target_function.raw() == target_code.function());
- // Check whether the code object has been detached from the target function.
- // If it has been detached, reattach it.
- Code& target_code = Code::Handle();
- if (target_function.HasCode()) {
- target_code ^= target_function.CurrentCode();
- CodePatcher::PatchStaticCallAt(frame->pc(), caller_code,
- target_code.EntryPoint());
- caller_code.SetStaticCallTargetCodeAt(frame->pc(), target_code);
- } else {
- ASSERT(target_function.unoptimized_code() == Code::null());
- target_code ^= caller_code.GetStaticCallTargetCodeAt(frame->pc());
- ASSERT(!target_code.IsNull());
- ASSERT(!target_code.is_optimized());
- target_function.ReattachCode(target_code);
- }
+ const Code& current_target_code = Code::Handle(target_function.CurrentCode());
+ CodePatcher::PatchStaticCallAt(frame->pc(), caller_code,
+ current_target_code.EntryPoint());
+ caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code);
if (FLAG_trace_patching) {
OS::PrintErr("FixCallersTarget: patching from %#" Px " to '%s' %#" Px "\n",
frame->pc(),
- Function::Handle(target_code.function()).ToFullyQualifiedCString(),
- target_code.EntryPoint());
+ target_function.ToFullyQualifiedCString(),
+ current_target_code.EntryPoint());
}
- arguments.SetReturn(target_code);
- ASSERT(target_function.HasCode());
+ arguments.SetReturn(current_target_code);
}
@@ -1481,7 +1488,7 @@
const Function& function = Function::Handle(optimized_code.function());
const Code& unoptimized_code = Code::Handle(function.unoptimized_code());
ASSERT(!unoptimized_code.IsNull());
- // The switch to unoptimized code may have already occured.
+ // The switch to unoptimized code may have already occurred.
if (function.HasOptimizedCode()) {
function.SwitchToUnoptimizedCode();
}
diff --git a/runtime/vm/code_generator_test.cc b/runtime/vm/code_generator_test.cc
index c7e7cdb..42d1121 100644
--- a/runtime/vm/code_generator_test.cc
+++ b/runtime/vm/code_generator_test.cc
@@ -293,7 +293,7 @@
RawScript::kScriptTag));
Library& lib = MakeTestLibrary("TestLib");
EXPECT(CompilerTest::TestCompileScript(lib, script));
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
Class& cls = Class::Handle(LookupClass(lib, "A"));
EXPECT(!cls.IsNull());
@@ -340,7 +340,7 @@
RawScript::kScriptTag));
Library& lib = MakeTestLibrary("TestLib");
EXPECT(CompilerTest::TestCompileScript(lib, script));
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
Class& cls = Class::ZoneHandle(LookupClass(lib, "A"));
EXPECT(!cls.IsNull());
@@ -532,7 +532,7 @@
RawScript::kScriptTag));
Library& lib = MakeTestLibrary("TestLib");
EXPECT(CompilerTest::TestCompileScript(lib, script));
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
Class& cls = Class::ZoneHandle(LookupClass(lib, "A"));
EXPECT(!cls.IsNull());
diff --git a/runtime/vm/code_patcher.h b/runtime/vm/code_patcher.h
index 9294e0e..c0f4799 100644
--- a/runtime/vm/code_patcher.h
+++ b/runtime/vm/code_patcher.h
@@ -42,7 +42,7 @@
// Restore entry point with original code (i.e., before patching).
static void RestoreEntry(const Code& code);
- // Returns true if the code can be patched with a jump at beginnning (checks
+ // Returns true if the code can be patched with a jump at beginning (checks
// that there are no conflicts with object pointers). Used in ASSERTs.
static bool CodeIsPatchable(const Code& code);
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 87e85db..d8771dc 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -388,7 +388,11 @@
DEBUG_ASSERT(flow_graph->VerifyUseLists());
// Do optimizations that depend on the propagated type information.
- optimizer.Canonicalize();
+ if (optimizer.Canonicalize()) {
+ // Invoke Canonicalize twice in order to fully canonicalize patterns
+ // like "if (a & const == 0) { }".
+ optimizer.Canonicalize();
+ }
DEBUG_ASSERT(flow_graph->VerifyUseLists());
BranchSimplifier::Simplify(flow_graph);
@@ -734,8 +738,10 @@
LongJump* base = isolate->long_jump_base();
LongJump jump;
isolate->set_long_jump_base(&jump);
+ // Make sure unoptimized code is not collected while we are compiling.
+ const Code& unoptimized_code = Code::ZoneHandle(function.unoptimized_code());
// Skips parsing if we need to only install unoptimized code.
- if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) {
+ if (!optimized && !unoptimized_code.IsNull()) {
InstallUnoptimizedCode(function);
isolate->set_long_jump_base(base);
return Error::null();
diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc
index e7c4820..3e6ef9d 100644
--- a/runtime/vm/compiler_test.cc
+++ b/runtime/vm/compiler_test.cc
@@ -42,7 +42,7 @@
RawScript::kScriptTag));
Library& lib = Library::Handle(Library::CoreLibrary());
EXPECT(CompilerTest::TestCompileScript(lib, script));
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
Class& cls = Class::Handle(
lib.LookupClass(String::Handle(Symbols::New("A"))));
EXPECT(!cls.IsNull());
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 7503dd0..2633f25 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -17,7 +17,6 @@
#include "vm/object_id_ring.h"
#include "vm/port.h"
#include "vm/profiler.h"
-#include "vm/signal_handler.h"
#include "vm/simulator.h"
#include "vm/snapshot.h"
#include "vm/stub_code.h"
@@ -173,7 +172,6 @@
vm_isolate_ = NULL;
#endif
- ScopedSignalBlocker ssb;
ProfilerManager::Shutdown();
CodeObservers::DeleteAll();
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 19d01a2..8280f94 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -160,7 +160,7 @@
// Class finalization is blocked for the isolate. Do nothing.
return Api::Success();
}
- if (ClassFinalizer::FinalizeTypeHierarchy()) {
+ if (ClassFinalizer::ProcessPendingClasses()) {
return Api::Success();
}
ASSERT(isolate->object_store()->sticky_error() != Object::null());
diff --git a/runtime/vm/dart_entry_test.cc b/runtime/vm/dart_entry_test.cc
index 576d6f3..301dd56 100644
--- a/runtime/vm/dart_entry_test.cc
+++ b/runtime/vm/dart_entry_test.cc
@@ -26,7 +26,7 @@
RawScript::kScriptTag));
Library& lib = Library::Handle(Library::CoreLibrary());
EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
Class& cls = Class::Handle(
lib.LookupClass(String::Handle(Symbols::New("A"))));
EXPECT(!cls.IsNull()); // No ambiguity error expected.
@@ -54,7 +54,7 @@
RawScript::kScriptTag));
Library& lib = Library::Handle(Library::CoreLibrary());
EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
Class& cls = Class::Handle(
lib.LookupClass(String::Handle(Symbols::New("A"))));
EXPECT(!cls.IsNull()); // No ambiguity error expected.
@@ -81,7 +81,7 @@
RawScript::kScriptTag));
Library& lib = Library::Handle(Library::CoreLibrary());
EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
Class& cls = Class::Handle(
lib.LookupClass(String::Handle(Symbols::New("A"))));
EXPECT(!cls.IsNull()); // No ambiguity error expected.
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index ea2e147..6a1bad4 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -566,10 +566,8 @@
}
void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
- Function& function = Function::Handle(deopt_context->isolate());
- function ^= deopt_context->ObjectAt(object_table_index_);
- const Code& code =
- Code::Handle(deopt_context->isolate(), function.unoptimized_code());
+ Code& code = Code::Handle(deopt_context->isolate());
+ code ^= deopt_context->ObjectAt(object_table_index_);
ASSERT(!code.IsNull());
uword continue_at_pc = code.GetPcForDeoptId(deopt_id_,
PcDescriptors::kDeopt);
@@ -789,16 +787,16 @@
}
void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
- Function& function = Function::Handle(deopt_context->isolate());
- function ^= deopt_context->ObjectAt(object_table_index_);
- if (function.IsNull()) {
+ Code& code = Code::Handle(deopt_context->isolate());
+ code ^= deopt_context->ObjectAt(object_table_index_);
+ if (code.IsNull()) {
// Callee's PC marker is not used (pc of Deoptimize stub). Set to 0.
*dest_addr = 0;
return;
}
- const Code& code =
- Code::Handle(deopt_context->isolate(), function.unoptimized_code());
- ASSERT(!code.IsNull());
+ const Function& function =
+ Function::Handle(deopt_context->isolate(), code.function());
+ ASSERT(function.HasCode());
const intptr_t pc_marker =
code.EntryPoint() + Assembler::kEntryPointToPcMarkerOffset;
*dest_addr = pc_marker;
@@ -813,7 +811,9 @@
// Clear invocation counter so that hopefully the function gets reoptimized
// only after more feedback has been collected.
function.set_usage_counter(0);
- if (function.HasOptimizedCode()) function.SwitchToUnoptimizedCode();
+ if (function.HasOptimizedCode()) {
+ function.SwitchToUnoptimizedCode();
+ }
}
private:
@@ -841,10 +841,8 @@
}
void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) {
- Function& function = Function::Handle(deopt_context->isolate());
- function ^= deopt_context->ObjectAt(object_table_index_);
- const Code& code =
- Code::Handle(deopt_context->isolate(), function.unoptimized_code());
+ Code& code = Code::Handle(deopt_context->isolate());
+ code ^= deopt_context->ObjectAt(object_table_index_);
ASSERT(!code.IsNull());
const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool());
*dest_addr = pp;
@@ -1051,9 +1049,10 @@
ASSERT(Isolate::IsDeoptAfter(ret_address_instr->deopt_id()));
ASSERT(!object_table.IsNull());
ASSERT(func != NULL);
- *func ^= object_table.At(ret_address_instr->object_table_index());
- const Code& code = Code::Handle(func->unoptimized_code());
+ Code& code = Code::Handle();
+ code ^= object_table.At(ret_address_instr->object_table_index());
ASSERT(!code.IsNull());
+ *func ^= code.function();
uword res = code.GetPcForDeoptId(ret_address_instr->deopt_id(),
PcDescriptors::kDeopt);
ASSERT(res != 0);
@@ -1161,36 +1160,32 @@
}
-void DeoptInfoBuilder::AddReturnAddress(const Function& function,
+void DeoptInfoBuilder::AddReturnAddress(const Code& code,
intptr_t deopt_id,
intptr_t dest_index) {
// Check that deopt_id exists.
// TODO(vegorov): verify after deoptimization targets as well.
#ifdef DEBUG
- const Code& code = Code::Handle(function.unoptimized_code());
- // The inlined function's code pointer may be null if there is a GC during
- // compilation.
- // TODO(zra): See if we can avoid this check by ensuring that code is not
- // removed during inlining.
- ASSERT(code.IsNull() || Isolate::IsDeoptAfter(deopt_id) ||
- (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0));
+ ASSERT(Isolate::IsDeoptAfter(deopt_id) ||
+ (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0));
#endif
- const intptr_t object_table_index = FindOrAddObjectInTable(function);
+ const intptr_t object_table_index = FindOrAddObjectInTable(code);
ASSERT(dest_index == FrameSize());
instructions_.Add(new DeoptRetAddressInstr(object_table_index, deopt_id));
}
-void DeoptInfoBuilder::AddPcMarker(const Function& function,
+void DeoptInfoBuilder::AddPcMarker(const Code& code,
intptr_t dest_index) {
- intptr_t object_table_index = FindOrAddObjectInTable(function);
+ intptr_t object_table_index = FindOrAddObjectInTable(code);
ASSERT(dest_index == FrameSize());
instructions_.Add(new DeoptPcMarkerInstr(object_table_index));
}
-void DeoptInfoBuilder::AddPp(const Function& function, intptr_t dest_index) {
- intptr_t object_table_index = FindOrAddObjectInTable(function);
+void DeoptInfoBuilder::AddPp(const Code& code,
+ intptr_t dest_index) {
+ intptr_t object_table_index = FindOrAddObjectInTable(code);
ASSERT(dest_index == FrameSize());
instructions_.Add(new DeoptPpInstr(object_table_index));
}
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index f55c120..43a2bdc 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -282,14 +282,14 @@
const GrowableObjectArray& object_table() { return object_table_; }
// Return address before instruction.
- void AddReturnAddress(const Function& function,
+ void AddReturnAddress(const Code& code,
intptr_t deopt_id,
intptr_t dest_index);
// Copy from optimized frame to unoptimized.
void AddCopy(Value* value, const Location& source_loc, intptr_t dest_index);
- void AddPcMarker(const Function& function, intptr_t dest_index);
- void AddPp(const Function& function, intptr_t dest_index);
+ void AddPcMarker(const Code& code, intptr_t dest_index);
+ void AddPp(const Code& code, intptr_t dest_index);
void AddCallerFp(intptr_t dest_index);
void AddCallerPp(intptr_t dest_index);
void AddCallerPc(intptr_t dest_index);
diff --git a/runtime/vm/find_code_object_test.cc b/runtime/vm/find_code_object_test.cc
index 599b8c9..f67b684 100644
--- a/runtime/vm/find_code_object_test.cc
+++ b/runtime/vm/find_code_object_test.cc
@@ -22,6 +22,12 @@
const int kScriptSize = 512 * KB;
const int kNumFunctions = 1024;
char scriptChars[kScriptSize];
+
+ // Get access to the code index table.
+ Isolate* isolate = Isolate::Current();
+ ASSERT(isolate != NULL);
+
+ StackZone zone(isolate);
String& url = String::Handle(String::New("dart-test:FindCodeObject"));
String& source = String::Handle();
Script& script = Script::Handle();
@@ -32,10 +38,6 @@
Function& function = Function::Handle();
char buffer[256];
- // Get access to the code index table.
- Isolate* isolate = Isolate::Current();
- ASSERT(isolate != NULL);
-
lib = Library::CoreLibrary();
// Load up class A with 1024 functions.
@@ -55,13 +57,15 @@
EXPECT(CompilerTest::TestCompileScript(lib, script));
clsA = lib.LookupClass(String::Handle(Symbols::New("A")));
EXPECT(!clsA.IsNull());
- ClassFinalizer::FinalizeTypeHierarchy();
+ ClassFinalizer::ProcessPendingClasses();
for (int i = 0; i < kNumFunctions; i++) {
OS::SNPrint(buffer, 256, "foo%d", i);
function_name = String::New(buffer);
function = clsA.LookupStaticFunction(function_name);
EXPECT(!function.IsNull());
EXPECT(CompilerTest::TestCompileFunction(function));
+ const Code& code = Code::ZoneHandle(function.CurrentCode());
+ EXPECT(!code.IsNull())
EXPECT(function.HasCode());
}
@@ -103,13 +107,15 @@
EXPECT(CompilerTest::TestCompileScript(lib, script));
clsB = lib.LookupClass(String::Handle(Symbols::New("B")));
EXPECT(!clsB.IsNull());
- ClassFinalizer::FinalizeTypeHierarchy();
+ ClassFinalizer::ProcessPendingClasses();
for (int i = 0; i < kNumFunctions; i++) {
OS::SNPrint(buffer, 256, "moo%d", i);
function_name = String::New(buffer);
function = clsB.LookupStaticFunction(function_name);
EXPECT(!function.IsNull());
EXPECT(CompilerTest::TestCompileFunction(function));
+ const Code& code = Code::ZoneHandle(function.CurrentCode());
+ EXPECT(!code.IsNull());
EXPECT(function.HasCode());
}
@@ -142,19 +148,11 @@
code = function.CurrentCode();
EXPECT(code.Size() > 16);
pc = code.EntryPoint() + 16;
-#if defined(TARGET_ARCH_MIPS)
- // MIPS can only Branch +/- 128KB
- EXPECT(code.Size() > ((PageSpace::kPageSizeInWords << kWordSizeLog2) / 2));
- EXPECT(Code::LookupCode(pc) == code.raw());
- pc = code.EntryPoint() + ((PageSpace::kPageSizeInWords << kWordSizeLog2) / 4);
- EXPECT(Code::LookupCode(pc) == code.raw());
-#else
EXPECT(code.Size() > (PageSpace::kPageSizeInWords << kWordSizeLog2));
EXPECT(Code::LookupCode(pc) == code.raw());
EXPECT(code.Size() > (1 * MB));
pc = code.EntryPoint() + (1 * MB);
EXPECT(Code::LookupCode(pc) == code.raw());
-#endif // defined(TARGET_ARCH_MIPS)
}
} // namespace dart
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index ff6be53..5f03f47 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -755,7 +755,7 @@
Environment* deopt_env =
Environment::From(*env,
num_non_copied_params_,
- parsed_function_.function());
+ Code::Handle(parsed_function_.code()));
instr->SetEnvironment(deopt_env);
for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
Value* use = it.CurrentValue();
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index a70becc..848a632 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -433,7 +433,8 @@
new BranchInstr(new StrictCompareInstr(call_block->start_pos(),
Token::kEQ_STRICT,
new Value(true_const),
- new Value(true_const)));
+ new Value(true_const),
+ false)); // No number check.
branch->InheritDeoptTarget(call_);
*branch->true_successor_address() = callee_entry;
*branch->false_successor_address() = false_block;
@@ -833,8 +834,8 @@
new StrictCompareInstr(condition_token_pos(),
Token::kEQ_STRICT,
value,
- constant_true);
- comp->set_needs_number_check(false);
+ constant_true,
+ false); // No number check.
BranchInstr* branch = new BranchInstr(comp);
AddInstruction(branch);
CloseFragment();
@@ -856,7 +857,8 @@
comp->token_pos(),
(comp->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT,
comp->left(),
- comp->right()));
+ comp->right(),
+ false)); // No number check.
} else {
branch = new BranchInstr(comp, FLAG_enable_type_checks);
}
@@ -874,8 +876,8 @@
new StrictCompareInstr(condition_token_pos(),
Token::kNE_STRICT,
neg->value(),
- constant_true);
- comp->set_needs_number_check(false);
+ constant_true,
+ false); // No number check.
BranchInstr* branch = new BranchInstr(comp);
AddInstruction(branch);
CloseFragment();
@@ -1201,7 +1203,8 @@
for_right.Bind(new StrictCompareInstr(node->token_pos(),
Token::kEQ_STRICT,
right_value,
- constant_true));
+ constant_true,
+ false)); // No number check.
for_right.Do(BuildStoreExprTemp(compare));
if (node->kind() == Token::kAND) {
@@ -1536,7 +1539,8 @@
StrictCompareInstr* comp = new StrictCompareInstr(token_pos,
kind,
for_left_value.value(),
- for_right_value.value());
+ for_right_value.value(),
+ true); // Number check.
return comp;
}
@@ -3090,13 +3094,14 @@
node->scope()->LookupVariable(Symbols::Other(),
true); // Test only.
Value* other = Bind(new LoadLocalInstr(*other_var));
+ // Receiver is not a number because numbers override equality.
+ const bool kNoNumberCheck = false;
StrictCompareInstr* compare =
new StrictCompareInstr(node->token_pos(),
Token::kEQ_STRICT,
receiver,
- other);
- // Receiver is not a number because numbers override equality.
- compare->set_needs_number_check(false);
+ other,
+ kNoNumberCheck);
return ReturnDefinition(compare);
}
case MethodRecognizer::kStringBaseLength:
@@ -3124,7 +3129,8 @@
new StrictCompareInstr(node->token_pos(),
Token::kEQ_STRICT,
load_val,
- zero_val);
+ zero_val,
+ false); // No number check.
return ReturnDefinition(compare);
}
case MethodRecognizer::kGrowableArrayLength:
@@ -3994,7 +4000,9 @@
new CheckStackOverflowInstr(function.token_pos(), 0);
// If we are inlining don't actually attach the stack check. We must still
// create the stack check in order to allocate a deopt id.
- if (!IsInlining()) for_effect.AddInstruction(check);
+ if (!IsInlining()) {
+ for_effect.AddInstruction(check);
+ }
}
parsed_function()->node_sequence()->Visit(&for_effect);
AppendFragment(normal_entry, for_effect);
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index 3683838..bf9df1a 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -23,13 +23,6 @@
class ParsedFunction;
-struct BranchLabels {
- Label* true_label;
- Label* false_label;
- Label* fall_through;
-};
-
-
class ParallelMoveResolver : public ValueObject {
public:
explicit ParallelMoveResolver(FlowGraphCompiler* compiler);
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 737514f..19a75bb 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -61,12 +61,12 @@
builder->MarkFrameStart();
// Current PP, FP, and PC.
- builder->AddPp(current->function(), slot_ix++);
+ builder->AddPp(current->code(), slot_ix++);
builder->AddCallerFp(slot_ix++);
- builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++);
+ builder->AddReturnAddress(current->code(), deopt_id(), slot_ix++);
// Callee's PC marker is not used anymore. Pass Function::null() to set to 0.
- builder->AddPcMarker(Function::Handle(), slot_ix++);
+ builder->AddPcMarker(Code::Handle(), slot_ix++);
// Emit all values that are needed for materialization as a part of the
// expression stack for the bottom-most frame. This guarantees that GC
@@ -84,17 +84,17 @@
current = current->outer();
while (current != NULL) {
// PP, FP, and PC.
- builder->AddPp(current->function(), slot_ix++);
+ builder->AddPp(current->code(), slot_ix++);
builder->AddCallerFp(slot_ix++);
// For any outer environment the deopt id is that of the call instruction
// which is recorded in the outer environment.
- builder->AddReturnAddress(current->function(),
+ builder->AddReturnAddress(current->code(),
Isolate::ToDeoptAfter(current->deopt_id()),
slot_ix++);
// PC marker.
- builder->AddPcMarker(previous->function(), slot_ix++);
+ builder->AddPcMarker(previous->code(), slot_ix++);
// The values of outgoing arguments can be changed from the inlined call so
// we must read them from the previous environment.
@@ -126,7 +126,7 @@
builder->AddCallerPc(slot_ix++);
// PC marker.
- builder->AddPcMarker(previous->function(), slot_ix++);
+ builder->AddPcMarker(previous->code(), slot_ix++);
// For the outermost environment, set the incoming arguments.
for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
@@ -1359,7 +1359,11 @@
Label is_compiled;
__ CompareImmediate(R1, reinterpret_cast<intptr_t>(Object::null()));
__ b(&is_compiled, NE);
- __ BranchLink(&StubCode::CompileFunctionRuntimeCallLabel());
+ __ BranchLinkPatchable(&StubCode::CompileFunctionRuntimeCallLabel());
+ AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
+ Isolate::kNoDeoptId,
+ token_pos);
+ RecordSafepoint(locs);
// R0: target function.
__ ldr(R1, FieldAddress(R0, Function::code_offset()));
__ Bind(&is_compiled);
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index ed47c72..81ae0aa 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -64,12 +64,12 @@
// The real frame starts here.
builder->MarkFrameStart();
- // Callee's PC marker is not used anymore. Pass Function::null() to set to 0.
- builder->AddPcMarker(Function::Handle(), slot_ix++);
+ // Callee's PC marker is not used anymore. Pass Code::null() to set to 0.
+ builder->AddPcMarker(Code::Handle(), slot_ix++);
// Current FP and PC.
builder->AddCallerFp(slot_ix++);
- builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++);
+ builder->AddReturnAddress(current->code(), deopt_id(), slot_ix++);
// Emit all values that are needed for materialization as a part of the
// expression stack for the bottom-most frame. This guarantees that GC
@@ -84,7 +84,7 @@
}
// Current PC marker and caller FP.
- builder->AddPcMarker(current->function(), slot_ix++);
+ builder->AddPcMarker(current->code(), slot_ix++);
builder->AddCallerFp(slot_ix++);
Environment* previous = current;
@@ -92,7 +92,7 @@
while (current != NULL) {
// For any outer environment the deopt id is that of the call instruction
// which is recorded in the outer environment.
- builder->AddReturnAddress(current->function(),
+ builder->AddReturnAddress(current->code(),
Isolate::ToDeoptAfter(current->deopt_id()),
slot_ix++);
@@ -114,7 +114,7 @@
}
// PC marker and caller FP.
- builder->AddPcMarker(current->function(), slot_ix++);
+ builder->AddPcMarker(current->code(), slot_ix++);
builder->AddCallerFp(slot_ix++);
// Iterate on the outer environment.
@@ -146,7 +146,9 @@
#define __ assem->
__ Comment("Deopt stub for id %" Pd "", deopt_id());
__ Bind(entry_label());
- if (FLAG_trap_on_deoptimization) __ int3();
+ if (FLAG_trap_on_deoptimization) {
+ __ int3();
+ }
ASSERT(deopt_env() != NULL);
@@ -1406,6 +1408,10 @@
__ cmpl(EBX, raw_null);
__ j(NOT_EQUAL, &is_compiled, Assembler::kNearJump);
__ call(&StubCode::CompileFunctionRuntimeCallLabel());
+ AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
+ Isolate::kNoDeoptId,
+ token_pos);
+ RecordSafepoint(locs);
__ movl(EBX, FieldAddress(EAX, Function::code_offset()));
__ Bind(&is_compiled);
}
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 721597f..9c09757 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -61,12 +61,12 @@
builder->MarkFrameStart();
// Current PP, FP, and PC.
- builder->AddPp(current->function(), slot_ix++);
+ builder->AddPp(current->code(), slot_ix++);
builder->AddCallerFp(slot_ix++);
- builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++);
+ builder->AddReturnAddress(current->code(), deopt_id(), slot_ix++);
- // Callee's PC marker is not used anymore. Pass Function::null() to set to 0.
- builder->AddPcMarker(Function::Handle(), slot_ix++);
+ // Callee's PC marker is not used anymore. Pass Code::null() to set to 0.
+ builder->AddPcMarker(Code::Handle(), slot_ix++);
// Emit all values that are needed for materialization as a part of the
// expression stack for the bottom-most frame. This guarantees that GC
@@ -84,17 +84,17 @@
current = current->outer();
while (current != NULL) {
// PP, FP, and PC.
- builder->AddPp(current->function(), slot_ix++);
+ builder->AddPp(current->code(), slot_ix++);
builder->AddCallerFp(slot_ix++);
// For any outer environment the deopt id is that of the call instruction
// which is recorded in the outer environment.
- builder->AddReturnAddress(current->function(),
+ builder->AddReturnAddress(current->code(),
Isolate::ToDeoptAfter(current->deopt_id()),
slot_ix++);
// PC marker.
- builder->AddPcMarker(previous->function(), slot_ix++);
+ builder->AddPcMarker(previous->code(), slot_ix++);
// The values of outgoing arguments can be changed from the inlined call so
// we must read them from the previous environment.
@@ -126,7 +126,7 @@
builder->AddCallerPc(slot_ix++);
// PC marker.
- builder->AddPcMarker(previous->function(), slot_ix++);
+ builder->AddPcMarker(previous->code(), slot_ix++);
// For the outermost environment, set the incoming arguments.
for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
@@ -1406,6 +1406,10 @@
__ BranchNotEqual(T1, reinterpret_cast<int32_t>(Object::null()),
&is_compiled);
__ BranchLink(&StubCode::CompileFunctionRuntimeCallLabel());
+ AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
+ Isolate::kNoDeoptId,
+ token_pos);
+ RecordSafepoint(locs);
__ lw(T1, FieldAddress(T0, Function::code_offset()));
__ Bind(&is_compiled);
}
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index 9257c35..c2b1561 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -62,10 +62,10 @@
builder->MarkFrameStart();
// Current PP, FP, and PC.
- builder->AddPp(current->function(), slot_ix++);
- builder->AddPcMarker(Function::Handle(), slot_ix++);
+ builder->AddPp(current->code(), slot_ix++);
+ builder->AddPcMarker(Code::Handle(), slot_ix++);
builder->AddCallerFp(slot_ix++);
- builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++);
+ builder->AddReturnAddress(current->code(), deopt_id(), slot_ix++);
// Emit all values that are needed for materialization as a part of the
// expression stack for the bottom-most frame. This guarantees that GC
@@ -83,13 +83,13 @@
current = current->outer();
while (current != NULL) {
// PP, FP, and PC.
- builder->AddPp(current->function(), slot_ix++);
- builder->AddPcMarker(previous->function(), slot_ix++);
+ builder->AddPp(current->code(), slot_ix++);
+ builder->AddPcMarker(previous->code(), slot_ix++);
builder->AddCallerFp(slot_ix++);
// For any outer environment the deopt id is that of the call instruction
// which is recorded in the outer environment.
- builder->AddReturnAddress(current->function(),
+ builder->AddReturnAddress(current->code(),
Isolate::ToDeoptAfter(current->deopt_id()),
slot_ix++);
@@ -120,7 +120,7 @@
// For the outermost environment, set caller PC, caller PP, and caller FP.
builder->AddCallerPp(slot_ix++);
// PC marker.
- builder->AddPcMarker(previous->function(), slot_ix++);
+ builder->AddPcMarker(previous->code(), slot_ix++);
builder->AddCallerFp(slot_ix++);
builder->AddCallerPc(slot_ix++);
@@ -1441,6 +1441,10 @@
__ cmpq(RBX, raw_null);
__ j(NOT_EQUAL, &is_compiled, Assembler::kNearJump);
__ call(&StubCode::CompileFunctionRuntimeCallLabel());
+ AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
+ Isolate::kNoDeoptId,
+ token_pos);
+ RecordSafepoint(locs);
__ movq(RBX, FieldAddress(RAX, Function::code_offset()));
__ Bind(&is_compiled);
}
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index b6512b1..dd798b8 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -59,10 +59,12 @@
// Test if a call is recursive by looking in the deoptimization environment.
-static bool IsCallRecursive(const Function& function, Definition* call) {
+static bool IsCallRecursive(const Code& code, Definition* call) {
Environment* env = call->env();
while (env != NULL) {
- if (function.raw() == env->function().raw()) return true;
+ if (code.raw() == env->code().raw()) {
+ return true;
+ }
env = env->outer();
}
return false;
@@ -434,6 +436,9 @@
return false;
}
+ // Make a handle for the unoptimized code so that it is not disconnected
+ // from the function while we are trying to inline it.
+ const Code& unoptimized_code = Code::Handle(function.unoptimized_code());
// Abort if the inlinable bit on the function is low.
if (!function.IsInlineable()) {
TRACE_INLINING(OS::Print(" Bailout: not inlinable\n"));
@@ -466,7 +471,7 @@
// Abort if this is a recursive occurrence.
Definition* call = call_data->call;
- if (!FLAG_inline_recursive && IsCallRecursive(function, call)) {
+ if (!FLAG_inline_recursive && IsCallRecursive(unoptimized_code, call)) {
function.set_is_inlinable(false);
TRACE_INLINING(OS::Print(" Bailout: recursive function\n"));
return false;
@@ -493,11 +498,11 @@
// Load IC data for the callee.
Array& ic_data_array = Array::Handle();
- if (function.HasCode()) {
- const Code& unoptimized_code =
- Code::Handle(function.unoptimized_code());
- ic_data_array = unoptimized_code.ExtractTypeFeedbackArray();
- }
+
+ // IsInlineable above checked HasCode. Creating a Handle for the code
+ // should have kept GC from detaching, but let's assert just to make sure.
+ ASSERT(function.HasCode());
+ ic_data_array = unoptimized_code.ExtractTypeFeedbackArray();
// Build the callee graph.
InlineExitCollector* exit_collector =
@@ -620,7 +625,9 @@
collected_call_sites_->FindCallSites(callee_graph, inlining_depth_);
// Add the function to the cache.
- if (!in_cache) function_cache_.Add(parsed_function);
+ if (!in_cache) {
+ function_cache_.Add(parsed_function);
+ }
// Build succeeded so we restore the bailout jump.
inlined_ = true;
@@ -639,6 +646,9 @@
(*callee_graph->guarded_fields())[i]);
}
+ // We allocate a ZoneHandle for the unoptimized code so that it cannot be
+ // disconnected from its function during the rest of compilation.
+ Code::ZoneHandle(unoptimized_code.raw());
TRACE_INLINING(OS::Print(" Success\n"));
return true;
} else {
@@ -1280,7 +1290,8 @@
new StrictCompareInstr(call_->instance_call()->token_pos(),
Token::kEQ_STRICT,
new Value(load_cid),
- new Value(cid_constant));
+ new Value(cid_constant),
+ false); // No number check.
BranchInstr* branch = new BranchInstr(compare);
branch->InheritDeoptTarget(call_);
AppendInstruction(AppendInstruction(cursor, cid_constant), branch);
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index a036153..3efaad4 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -1456,10 +1456,12 @@
ConstantInstr* left_const = left->AsConstant();
if ((right_const != NULL && right_const->value().IsNull()) ||
(left_const != NULL && left_const->value().IsNull())) {
- StrictCompareInstr* comp = new StrictCompareInstr(call->token_pos(),
- Token::kEQ_STRICT,
- new Value(left),
- new Value(right));
+ StrictCompareInstr* comp =
+ new StrictCompareInstr(call->token_pos(),
+ Token::kEQ_STRICT,
+ new Value(left),
+ new Value(right),
+ false); // No number check.
ReplaceCall(call, comp);
return true;
}
@@ -6368,34 +6370,17 @@
void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) {
- ASSERT(Token::IsEqualityOperator(instr->kind()));
-
- const Object& left = instr->left()->definition()->constant_value();
- const Object& right = instr->right()->definition()->constant_value();
-
- if (IsNonConstant(left) || IsNonConstant(right)) {
- // TODO(vegorov): incorporate nullability information into the lattice.
- if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) ||
- (right.IsNull() && instr->left()->Type()->HasDecidableNullability())) {
- bool result = left.IsNull() ? instr->right()->Type()->IsNull()
- : instr->left()->Type()->IsNull();
- if (instr->kind() == Token::kNE_STRICT ||
- instr->kind() == Token::kNE) {
- result = !result;
- }
- SetValue(instr, Smi::Handle(
- Smi::New(result ? instr->if_true() : instr->if_false())));
- } else {
- SetValue(instr, non_constant_);
- }
- } else if (IsConstant(left) && IsConstant(right)) {
- bool result = (left.raw() == right.raw());
- if (instr->kind() == Token::kNE_STRICT ||
- instr->kind() == Token::kNE) {
- result = !result;
- }
- SetValue(instr, Smi::Handle(
- Smi::New(result ? instr->if_true() : instr->if_false())));
+ instr->comparison()->Accept(this);
+ const Object& value = instr->comparison()->constant_value();
+ if (IsNonConstant(value)) {
+ SetValue(instr, non_constant_);
+ } else if (IsConstant(value)) {
+ ASSERT(!value.IsNull());
+ ASSERT(value.IsBool());
+ bool result = Bool::Cast(value).value();
+ SetValue(instr,
+ Smi::Handle(Smi::New(
+ result ? instr->if_true() : instr->if_false())));
}
}
@@ -7466,37 +7451,11 @@
BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch,
- Value* left,
- Value* right) {
+ Value* new_left,
+ Value* new_right) {
ComparisonInstr* comparison = branch->comparison();
- ComparisonInstr* new_comparison = NULL;
- if (comparison->IsStrictCompare()) {
- new_comparison = new StrictCompareInstr(comparison->token_pos(),
- comparison->kind(),
- left,
- right);
- } else if (comparison->IsEqualityCompare()) {
- EqualityCompareInstr* equality_compare = comparison->AsEqualityCompare();
- EqualityCompareInstr* new_equality_compare =
- new EqualityCompareInstr(equality_compare->token_pos(),
- comparison->kind(),
- left,
- right,
- equality_compare->operation_cid(),
- equality_compare->deopt_id());
- new_comparison = new_equality_compare;
- } else {
- ASSERT(comparison->IsRelationalOp());
- RelationalOpInstr* relational_op = comparison->AsRelationalOp();
- RelationalOpInstr* new_relational_op =
- new RelationalOpInstr(relational_op->token_pos(),
- comparison->kind(),
- left,
- right,
- relational_op->operation_cid(),
- relational_op->deopt_id());
- new_comparison = new_relational_op;
- }
+ ComparisonInstr* new_comparison =
+ comparison->CopyWithNewOperands(new_left, new_right);
return new BranchInstr(new_comparison, branch->is_checked());
}
@@ -7708,10 +7667,11 @@
Value* if_true = (pred1 == branch->true_successor()) ? v1 : v2;
Value* if_false = (pred2 == branch->true_successor()) ? v1 : v2;
+ ComparisonInstr* new_comparison =
+ comparison->CopyWithNewOperands(comparison->left()->Copy(),
+ comparison->right()->Copy());
IfThenElseInstr* if_then_else = new IfThenElseInstr(
- comparison->kind(),
- comparison->InputAt(0)->Copy(),
- comparison->InputAt(1)->Copy(),
+ new_comparison,
if_true->Copy(),
if_false->Copy());
flow_graph->InsertBefore(branch,
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index 6137831..b1fd751 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -341,8 +341,8 @@
// Duplicate a branch while replacing its comparison's left and right
// inputs.
static BranchInstr* CloneBranch(BranchInstr* branch,
- Value* left,
- Value* right);
+ Value* new_left,
+ Value* new_right);
};
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index e19c5c2..47015a9 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -680,7 +680,6 @@
CompileType IfThenElseInstr::ComputeType() const {
- ASSERT(InputCount() == 2);
return CompileType::FromCid(kSmiCid);
}
diff --git a/runtime/vm/gc_marker.cc b/runtime/vm/gc_marker.cc
index c5b5dc8..4a9eabd 100644
--- a/runtime/vm/gc_marker.cc
+++ b/runtime/vm/gc_marker.cc
@@ -123,13 +123,15 @@
MarkingVisitor(Isolate* isolate,
Heap* heap,
PageSpace* page_space,
- MarkingStack* marking_stack)
+ MarkingStack* marking_stack,
+ bool visit_function_code)
: ObjectPointerVisitor(isolate),
heap_(heap),
vm_heap_(Dart::vm_isolate()->heap()),
page_space_(page_space),
marking_stack_(marking_stack),
- visiting_old_object_(NULL) {
+ visiting_old_object_(NULL),
+ visit_function_code_(visit_function_code) {
ASSERT(heap_ != vm_heap_);
}
@@ -141,6 +143,12 @@
}
}
+ bool visit_function_code() const { return visit_function_code_; }
+
+ GrowableArray<RawFunction*>* skipped_code_functions() {
+ return &skipped_code_functions_;
+ }
+
void DelayWeakProperty(RawWeakProperty* raw_weak) {
RawObject* raw_key = raw_weak->ptr()->key_;
DelaySet::iterator it = delay_set_.find(raw_key);
@@ -158,6 +166,9 @@
for (; it != delay_set_.end(); ++it) {
WeakProperty::Clear(it->second);
}
+ if (!visit_function_code_) {
+ DetachCode();
+ }
}
void VisitingOldObject(RawObject* obj) {
@@ -195,10 +206,14 @@
void MarkObject(RawObject* raw_obj, RawObject** p) {
// Fast exit if the raw object is a Smi.
- if (!raw_obj->IsHeapObject()) return;
+ if (!raw_obj->IsHeapObject()) {
+ return;
+ }
// Fast exit if the raw object is marked.
- if (raw_obj->IsMarked()) return;
+ if (raw_obj->IsMarked()) {
+ return;
+ }
// Skip over new objects, but verify consistency of heap while at it.
if (raw_obj->IsNewObject()) {
@@ -215,6 +230,31 @@
MarkAndPush(raw_obj);
}
+ void DetachCode() {
+ for (int i = 0; i < skipped_code_functions_.length(); i++) {
+ RawFunction* func = skipped_code_functions_[i];
+ RawCode* code = func->ptr()->code_;
+ if (!code->IsMarked()) {
+ // If the code wasn't strongly visited through other references
+ // after skipping the function's code pointer, then we disconnect the
+ // code from the function.
+ func->ptr()->code_ = Code::null();
+ func->ptr()->unoptimized_code_ = Code::null();
+ if (FLAG_log_code_drop) {
+ // NOTE: This code runs while GC is in progress and runs within
+ // a NoHandleScope block. Hence it is not okay to use a regular Zone
+ // or Scope handle. We use a direct stack handle so the raw pointer in
+ // this handle is not traversed. The use of a handle is mainly to
+ // be able to reuse the handle based code and avoid having to add
+ // helper functions to the raw object interface.
+ String name;
+ name = func->ptr()->name_;
+ OS::Print("Detaching code: %s\n", name.ToCString());
+ }
+ }
+ }
+ }
+
Heap* heap_;
Heap* vm_heap_;
PageSpace* page_space_;
@@ -222,6 +262,8 @@
RawObject* visiting_old_object_;
typedef std::multimap<RawObject*, RawWeakProperty*> DelaySet;
DelaySet delay_set_;
+ const bool visit_function_code_;
+ GrowableArray<RawFunction*> skipped_code_functions_;
DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitor);
};
@@ -429,10 +471,13 @@
void GCMarker::MarkObjects(Isolate* isolate,
PageSpace* page_space,
- bool invoke_api_callbacks) {
+ bool invoke_api_callbacks,
+ bool collect_code) {
+ const bool visit_function_code = !collect_code;
MarkingStack marking_stack;
Prologue(isolate, invoke_api_callbacks);
- MarkingVisitor mark(isolate, heap_, page_space, &marking_stack);
+ MarkingVisitor mark(
+ isolate, heap_, page_space, &marking_stack, visit_function_code);
IterateRoots(isolate, &mark, !invoke_api_callbacks);
DrainMarkingStack(isolate, &mark);
IterateWeakReferences(isolate, &mark);
@@ -442,7 +487,6 @@
ProcessWeakTables(page_space);
ProcessObjectIdTable(isolate);
-
Epilogue(isolate, invoke_api_callbacks);
}
diff --git a/runtime/vm/gc_marker.h b/runtime/vm/gc_marker.h
index 422d062..4dae874 100644
--- a/runtime/vm/gc_marker.h
+++ b/runtime/vm/gc_marker.h
@@ -27,7 +27,8 @@
void MarkObjects(Isolate* isolate,
PageSpace* page_space,
- bool invoke_api_callbacks);
+ bool invoke_api_callbacks,
+ bool collect_code);
private:
void Prologue(Isolate* isolate, bool invoke_api_callbacks);
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index ef2dde6..7af39e3 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -365,6 +365,9 @@
left()->PrintTo(f);
f->Print(", ");
right()->PrintTo(f);
+ if (needs_number_check()) {
+ f->Print(", with number check");
+ }
}
@@ -427,9 +430,7 @@
void IfThenElseInstr::PrintOperandsTo(BufferFormatter* f) const {
- left()->PrintTo(f);
- f->Print(" %s ", Token::Str(kind_));
- right()->PrintTo(f);
+ comparison()->PrintOperandsTo(f);
f->Print(" ? %" Pd " : %" Pd,
if_true_,
if_false_);
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 8a8f06a..07604df 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -24,8 +24,6 @@
namespace dart {
-DEFINE_FLAG(bool, new_identity_spec, true,
- "Use new identity check rules for numbers.");
DEFINE_FLAG(bool, propagate_ic_data, true,
"Propagate IC data from unoptimized to optimized IC calls.");
DECLARE_FLAG(bool, enable_type_checks);
@@ -755,23 +753,6 @@
}
-BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked)
- : comparison_(comparison),
- is_checked_(is_checked),
- constrained_type_(NULL),
- constant_target_(NULL) {
- ASSERT(comparison->env() == NULL);
- for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) {
- comparison->InputAt(i)->set_instruction(this);
- }
-}
-
-
-void BranchInstr::RawSetInputAt(intptr_t i, Value* value) {
- comparison()->RawSetInputAt(i, value);
-}
-
-
void BranchInstr::SetComparison(ComparisonInstr* new_comparison) {
for (intptr_t i = new_comparison->InputCount() - 1; i >= 0; --i) {
Value* input = new_comparison->InputAt(i);
@@ -1133,6 +1114,10 @@
}
return true;
}
+ case Token::kMOD: {
+ Range* right_range = this->right()->definition()->range();
+ return (right_range == NULL) || right_range->Overlaps(0, 0);
+ }
default:
return overflow_;
}
@@ -1922,9 +1907,10 @@
StrictCompareInstr::StrictCompareInstr(intptr_t token_pos,
Token::Kind kind,
Value* left,
- Value* right)
+ Value* right,
+ bool needs_number_check)
: ComparisonInstr(token_pos, kind, left, right),
- needs_number_check_(FLAG_new_identity_spec) {
+ needs_number_check_(needs_number_check) {
ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT));
}
@@ -2024,12 +2010,12 @@
Environment* Environment::From(const GrowableArray<Definition*>& definitions,
intptr_t fixed_parameter_count,
- const Function& function) {
+ const Code& code) {
Environment* env =
new Environment(definitions.length(),
fixed_parameter_count,
Isolate::kNoDeoptId,
- function,
+ code,
NULL);
for (intptr_t i = 0; i < definitions.length(); ++i) {
env->values_.Add(new Value(definitions[i]));
@@ -2044,7 +2030,7 @@
new Environment(length,
fixed_parameter_count_,
deopt_id_,
- function_,
+ code_,
(outer_ == NULL) ? NULL : outer_->DeepCopy());
if (locations_ != NULL) {
Location* new_locations =
@@ -2475,21 +2461,60 @@
}
+ComparisonInstr* EqualityCompareInstr::CopyWithNewOperands(Value* new_left,
+ Value* new_right) {
+ return new EqualityCompareInstr(token_pos(),
+ kind(),
+ new_left,
+ new_right,
+ operation_cid(),
+ deopt_id());
+}
+
+
+ComparisonInstr* RelationalOpInstr::CopyWithNewOperands(Value* new_left,
+ Value* new_right) {
+ return new RelationalOpInstr(token_pos(),
+ kind(),
+ new_left,
+ new_right,
+ operation_cid(),
+ deopt_id());
+}
+
+
+ComparisonInstr* StrictCompareInstr::CopyWithNewOperands(Value* new_left,
+ Value* new_right) {
+ return new StrictCompareInstr(token_pos(),
+ kind(),
+ new_left,
+ new_right,
+ needs_number_check());
+}
+
+
+
+ComparisonInstr* TestSmiInstr::CopyWithNewOperands(Value* new_left,
+ Value* new_right) {
+ return new TestSmiInstr(token_pos(), kind(), new_left, new_right);
+}
+
+
bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
Value* v1,
Value* v2) {
- if (!(comparison->IsStrictCompare() &&
- !comparison->AsStrictCompare()->needs_number_check()) &&
- !(comparison->IsEqualityCompare() &&
- (comparison->AsEqualityCompare()->operation_cid() == kSmiCid))) {
+ bool is_smi_result = BindsToSmiConstant(v1) && BindsToSmiConstant(v2);
+ if (comparison->IsStrictCompare()) {
+ // Strict comparison with number checks calls a stub and is not supported
+ // by if-conversion.
+ return is_smi_result
+ && !comparison->AsStrictCompare()->needs_number_check();
+ }
+ if (comparison->operation_cid() != kSmiCid) {
+ // Non-smi comparisons are not supported by if-conversion.
return false;
}
-
- if (!BindsToSmiConstant(v1) || !BindsToSmiConstant(v2)) {
- return false;
- }
-
- return true;
+ return is_smi_result;
}
@@ -2665,6 +2690,16 @@
}
+bool Range::Overlaps(intptr_t min_int, intptr_t max_int) const {
+ const intptr_t this_min = min().LowerBound().value();
+ const intptr_t this_max = max().UpperBound().value();
+ if ((this_min <= min_int) && (min_int <= this_max)) return true;
+ if ((this_min <= max_int) && (max_int <= this_max)) return true;
+ if ((min_int < this_min) && (max_int > this_max)) return true;
+ return false;
+}
+
+
bool Range::IsUnsatisfiable() const {
// Constant case: For example [0, -1].
if (Range::ConstantMin(this).value() > Range::ConstantMax(this).value()) {
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 3d85345..f5f4ac7 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -2152,6 +2152,7 @@
private:
friend class BranchInstr;
+ friend class IfThenElseInstr;
virtual void RawSetInputAt(intptr_t i, Value* value) {
inputs_[i] = value;
@@ -2161,6 +2162,13 @@
};
+struct BranchLabels {
+ Label* true_label;
+ Label* false_label;
+ Label* fall_through;
+};
+
+
class ComparisonInstr : public TemplateDefinition<2> {
public:
Value* left() const { return inputs_[0]; }
@@ -2171,9 +2179,14 @@
intptr_t token_pos() const { return token_pos_; }
Token::Kind kind() const { return kind_; }
+ virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right) = 0;
+
virtual void EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) = 0;
+ virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) = 0;
+
void SetDeoptId(intptr_t deopt_id) {
deopt_id_ = deopt_id;
}
@@ -2207,7 +2220,16 @@
class BranchInstr : public Instruction {
public:
- explicit BranchInstr(ComparisonInstr* comparison, bool is_checked = false);
+ explicit BranchInstr(ComparisonInstr* comparison, bool is_checked = false)
+ : comparison_(comparison),
+ is_checked_(is_checked),
+ constrained_type_(NULL),
+ constant_target_(NULL) {
+ ASSERT(comparison->env() == NULL);
+ for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) {
+ comparison->InputAt(i)->set_instruction(this);
+ }
+ }
DECLARE_INSTRUCTION(Branch)
@@ -2243,6 +2265,8 @@
LocationSummary* summary = comparison()->MakeLocationSummary();
// Branches don't produce a result.
summary->set_out(Location::NoLocation());
+ // The back-end expects the location summary to be stored in the
+ // comparison.
comparison()->locs_ = summary;
}
return comparison()->locs_;
@@ -2296,7 +2320,9 @@
virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
private:
- virtual void RawSetInputAt(intptr_t i, Value* value);
+ virtual void RawSetInputAt(intptr_t i, Value* value) {
+ comparison()->RawSetInputAt(i, value);
+ }
TargetEntryInstr* true_successor_;
TargetEntryInstr* false_successor_;
@@ -2513,6 +2539,9 @@
// Inclusive.
bool IsWithin(intptr_t min_int, intptr_t max_int) const;
+ // Inclusive.
+ bool Overlaps(intptr_t min_int, intptr_t max_int) const;
+
bool IsUnsatisfiable() const;
private:
@@ -2888,9 +2917,13 @@
StrictCompareInstr(intptr_t token_pos,
Token::Kind kind,
Value* left,
- Value* right);
+ Value* right,
+ bool needs_number_check);
DECLARE_INSTRUCTION(StrictCompare)
+
+ virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
+
virtual CompileType ComputeType() const;
virtual void PrintOperandsTo(BufferFormatter* f) const;
@@ -2907,6 +2940,9 @@
virtual void EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch);
+ virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels);
+
bool needs_number_check() const { return needs_number_check_; }
void set_needs_number_check(bool value) { needs_number_check_ = value; }
@@ -2936,6 +2972,9 @@
}
DECLARE_INSTRUCTION(TestSmi);
+
+ virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
+
virtual CompileType ComputeType() const;
virtual bool CanDeoptimize() const { return false; }
@@ -2960,6 +2999,9 @@
virtual void EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch);
+ virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels);
+
private:
DISALLOW_COPY_AND_ASSIGN(TestSmiInstr);
};
@@ -2980,6 +3022,9 @@
}
DECLARE_INSTRUCTION(EqualityCompare)
+
+ virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
+
virtual CompileType ComputeType() const;
virtual void PrintOperandsTo(BufferFormatter* f) const;
@@ -2994,6 +3039,9 @@
virtual void EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch);
+ virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels);
+
virtual intptr_t DeoptimizationTarget() const {
return GetDeoptId();
}
@@ -3029,6 +3077,9 @@
}
DECLARE_INSTRUCTION(RelationalOp)
+
+ virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
+
virtual CompileType ComputeType() const;
virtual void PrintOperandsTo(BufferFormatter* f) const;
@@ -3043,6 +3094,8 @@
virtual void EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch);
+ virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels);
virtual intptr_t DeoptimizationTarget() const {
return GetDeoptId();
@@ -3068,19 +3121,19 @@
// TODO(vegorov): ComparisonInstr should be switched to use IfTheElseInstr for
// materialization of true and false constants.
-class IfThenElseInstr : public TemplateDefinition<2> {
+class IfThenElseInstr : public Definition {
public:
- IfThenElseInstr(Token::Kind kind,
- Value* left,
- Value* right,
+ IfThenElseInstr(ComparisonInstr* comparison,
Value* if_true,
Value* if_false)
- : kind_(kind),
+ : comparison_(comparison),
if_true_(Smi::Cast(if_true->BoundConstant()).Value()),
if_false_(Smi::Cast(if_false->BoundConstant()).Value()) {
- ASSERT(Token::IsEqualityOperator(kind));
- SetInputAt(0, left);
- SetInputAt(1, right);
+ // Adjust uses at the comparison.
+ ASSERT(comparison->env() == NULL);
+ for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) {
+ comparison->InputAt(i)->set_instruction(this);
+ }
}
// Returns true if this combination of comparison and values flowing on
@@ -3089,35 +3142,66 @@
DECLARE_INSTRUCTION(IfThenElse)
+ intptr_t InputCount() const { return comparison()->InputCount(); }
+
+ Value* InputAt(intptr_t i) const { return comparison()->InputAt(i); }
+
+ virtual bool CanDeoptimize() const {
+ return comparison()->CanDeoptimize();
+ }
+
+ virtual bool CanBecomeDeoptimizationTarget() const {
+ return comparison()->CanBecomeDeoptimizationTarget();
+ }
+
+ virtual LocationSummary* locs() {
+ if (comparison()->locs_ == NULL) {
+ LocationSummary* summary = MakeLocationSummary();
+ // The back-end expects the location summary to be stored in the
+ // comparison.
+ comparison()->locs_ = summary;
+ }
+ return comparison()->locs_;
+ }
+
+ virtual intptr_t DeoptimizationTarget() const {
+ return comparison()->DeoptimizationTarget();
+ }
+
+ virtual Representation RequiredInputRepresentation(intptr_t i) const {
+ return comparison()->RequiredInputRepresentation(i);
+ }
+
virtual void PrintOperandsTo(BufferFormatter* f) const;
virtual CompileType ComputeType() const;
virtual void InferRange();
- virtual bool CanDeoptimize() const { return false; }
-
- Value* left() const { return inputs_[0]; }
- Value* right() const { return inputs_[1]; }
+ ComparisonInstr* comparison() const { return comparison_; }
intptr_t if_true() const { return if_true_; }
intptr_t if_false() const { return if_false_; }
- Token::Kind kind() const { return kind_; }
-
- virtual bool AllowsCSE() const { return true; }
- virtual EffectSet Effects() const { return EffectSet::None(); }
- virtual EffectSet Dependencies() const { return EffectSet::None(); }
+ virtual bool AllowsCSE() const { return comparison()->AllowsCSE(); }
+ virtual EffectSet Effects() const { return comparison()->Effects(); }
+ virtual EffectSet Dependencies() const {
+ return comparison()->Dependencies();
+ }
virtual bool AttributesEqual(Instruction* other) const {
IfThenElseInstr* other_if_then_else = other->AsIfThenElse();
- return (kind_ == other_if_then_else->kind_) &&
+ return comparison()->AttributesEqual(other_if_then_else->comparison()) &&
(if_true_ == other_if_then_else->if_true_) &&
(if_false_ == other_if_then_else->if_false_);
}
- virtual bool MayThrow() const { return false; }
+ virtual bool MayThrow() const { return comparison()->MayThrow(); }
private:
- const Token::Kind kind_;
+ virtual void RawSetInputAt(intptr_t i, Value* value) {
+ comparison()->RawSetInputAt(i, value);
+ }
+
+ ComparisonInstr* comparison_;
const intptr_t if_true_;
const intptr_t if_false_;
@@ -6889,7 +6973,7 @@
// Construct an environment by constructing uses from an array of definitions.
static Environment* From(const GrowableArray<Definition*>& definitions,
intptr_t fixed_parameter_count,
- const Function& function);
+ const Code& code);
void set_locations(Location* locations) {
ASSERT(locations_ == NULL);
@@ -6929,7 +7013,7 @@
return fixed_parameter_count_;
}
- const Function& function() const { return function_; }
+ const Code& code() const { return code_; }
Environment* DeepCopy() const { return DeepCopy(Length()); }
@@ -6944,13 +7028,13 @@
Environment(intptr_t length,
intptr_t fixed_parameter_count,
intptr_t deopt_id,
- const Function& function,
+ const Code& code,
Environment* outer)
: values_(length),
locations_(NULL),
fixed_parameter_count_(fixed_parameter_count),
deopt_id_(deopt_id),
- function_(function),
+ code_(code),
outer_(outer) { }
// Deep copy an environment. The 'length' parameter may be less than the
@@ -6962,7 +7046,7 @@
Location* locations_;
const intptr_t fixed_parameter_count_;
intptr_t deopt_id_;
- const Function& function_;
+ const Code& code_;
Environment* outer_;
DISALLOW_COPY_AND_ASSIGN(Environment);
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index 0377a24..c7854cd 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -136,24 +136,12 @@
LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
- const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps = 0;
- LocationSummary* locs =
- new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
- locs->set_in(0, Location::RegisterOrConstant(left()));
- // Only one of the inputs can be a constant. Choose register if the first one
- // is a constant.
- locs->set_in(1, locs->in(0).IsConstant()
- ? Location::RequiresRegister()
- : Location::RegisterOrConstant(right()));
- locs->set_out(Location::RequiresRegister());
- return locs;
+ return comparison()->MakeLocationSummary();
}
void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register result = locs()->out().reg();
- ASSERT(Token::IsEqualityOperator(kind()));
Location left = locs()->in(0);
Location right = locs()->in(1);
@@ -162,19 +150,9 @@
// Clear out register.
__ eor(result, result, ShifterOperand(result));
- // Compare left and right. For now only equality comparison is supported.
- // TODO(vegorov): reuse code from the other comparison instructions instead of
- // generating it inline here.
- if (left.IsConstant()) {
- __ CompareObject(right.reg(), left.constant());
- } else if (right.IsConstant()) {
- __ CompareObject(left.reg(), right.constant());
- } else {
- __ cmp(left.reg(), ShifterOperand(right.reg()));
- }
-
- Condition true_condition =
- ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQ : NE;
+ // Emit comparison code. This must not overwrite the result register.
+ BranchLabels labels = { NULL, NULL, NULL };
+ Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
@@ -495,31 +473,44 @@
}
-static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
- LocationSummary* locs) {
+static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
+ LocationSummary* locs,
+ Token::Kind kind) {
QRegister left = locs->in(0).fpu_reg();
QRegister right = locs->in(1).fpu_reg();
DRegister dleft = EvenDRegisterOf(left);
DRegister dright = EvenDRegisterOf(right);
__ vcmpd(dleft, dright);
__ vmstat();
+ Condition true_condition = TokenKindToDoubleCondition(kind);
+ return true_condition;
+}
+
+
+Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
+ if (operation_cid() == kSmiCid) {
+ return EmitSmiComparisonOp(compiler, locs(), kind());
+ } else {
+ ASSERT(operation_cid() == kDoubleCid);
+ return EmitDoubleComparisonOp(compiler, locs(), kind());
+ }
}
void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
+ // The ARM code does not use true- and false-labels here.
+ BranchLabels labels = { NULL, NULL, NULL };
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+
+ Register result = locs()->out().reg();
if (operation_cid() == kSmiCid) {
- Condition true_condition = EmitSmiComparisonOp(compiler, locs(), kind());
- Register result = locs()->out().reg();
__ LoadObject(result, Bool::True(), true_condition);
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
} else {
ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, locs());
-
- Register result = locs()->out().reg();
- Condition true_condition = TokenKindToDoubleCondition(kind());
Label done;
__ LoadObject(result, Bool::False());
if (true_condition != NE) {
@@ -536,15 +527,9 @@
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
BranchLabels labels = compiler->CreateBranchLabels(branch);
+ Condition true_condition = EmitComparisonCode(compiler, labels);
- Condition true_condition = kNoCondition;
- if (operation_cid() == kSmiCid) {
- true_condition = EmitSmiComparisonOp(compiler, locs(), kind());
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- true_condition = TokenKindToDoubleCondition(kind());
- EmitDoubleComparisonOp(compiler, locs());
-
+ if (operation_cid() == kDoubleCid) {
Label* nan_result = (true_condition == NE) ?
labels.true_label : labels.false_label;
__ b(nan_result, VS);
@@ -566,17 +551,8 @@
}
-void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- // Never emitted outside of the BranchInstr.
- UNREACHABLE();
-}
-
-
-void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
- BranchInstr* branch) {
- BranchLabels labels = compiler->CreateBranchLabels(branch);
-
- Condition true_condition = (kind() == Token::kNE) ? NE : EQ;
+Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
Register left = locs()->in(0).reg();
Location right = locs()->in(1);
if (right.IsConstant()) {
@@ -587,6 +563,20 @@
} else {
__ tst(left, ShifterOperand(right.reg()));
}
+ Condition true_condition = (kind() == Token::kNE) ? NE : EQ;
+ return true_condition;
+}
+
+void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ // Never emitted outside of the BranchInstr.
+ UNREACHABLE();
+}
+
+
+void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
+ BranchInstr* branch) {
+ BranchLabels labels = compiler->CreateBranchLabels(branch);
+ Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
@@ -627,18 +617,28 @@
}
-void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
if (operation_cid() == kSmiCid) {
- Condition true_condition = EmitSmiComparisonOp(compiler, locs(), kind());
- Register result = locs()->out().reg();
+ return EmitSmiComparisonOp(compiler, locs(), kind());
+ } else {
+ ASSERT(operation_cid() == kDoubleCid);
+ return EmitDoubleComparisonOp(compiler, locs(), kind());
+ }
+}
+
+
+void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ // The ARM code does not use true- and false-labels here.
+ BranchLabels labels = { NULL, NULL, NULL };
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+
+ Register result = locs()->out().reg();
+ if (operation_cid() == kSmiCid) {
__ LoadObject(result, Bool::True(), true_condition);
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
} else {
ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, locs());
-
- Register result = locs()->out().reg();
- Condition true_condition = TokenKindToDoubleCondition(kind());
Label done;
__ LoadObject(result, Bool::False());
if (true_condition != NE) {
@@ -653,15 +653,9 @@
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
+ Condition true_condition = EmitComparisonCode(compiler, labels);
- Condition true_condition = kNoCondition;
- if (operation_cid() == kSmiCid) {
- true_condition = EmitSmiComparisonOp(compiler, locs(), kind());
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- true_condition = TokenKindToDoubleCondition(kind());
- EmitDoubleComparisonOp(compiler, locs());
-
+ if (operation_cid() == kDoubleCid) {
Label* nan_result = (true_condition == NE) ?
labels.true_label : labels.false_label;
__ b(nan_result, VS);
@@ -2380,6 +2374,7 @@
}
Register right = locs()->in(1).reg();
+ Range* right_range = this->right()->definition()->range();
switch (op_kind()) {
case Token::kADD: {
if (deopt == NULL) {
@@ -2427,9 +2422,11 @@
break;
}
case Token::kTRUNCDIV: {
- // Handle divide by zero in runtime.
- __ cmp(right, ShifterOperand(0));
- __ b(deopt, EQ);
+ if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
+ // Handle divide by zero in runtime.
+ __ cmp(right, ShifterOperand(0));
+ __ b(deopt, EQ);
+ }
Register temp = locs()->temp(0).reg();
DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
__ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp.
@@ -2445,9 +2442,11 @@
break;
}
case Token::kMOD: {
- // Handle divide by zero in runtime.
- __ cmp(right, ShifterOperand(0));
- __ b(deopt, EQ);
+ if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
+ // Handle divide by zero in runtime.
+ __ cmp(right, ShifterOperand(0));
+ __ b(deopt, EQ);
+ }
Register temp = locs()->temp(0).reg();
DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
__ Asr(temp, left, kSmiTagSize); // SmiUntag left into temp.
@@ -2484,7 +2483,6 @@
__ Asr(IP, right, kSmiTagSize); // SmiUntag right into IP.
// sarl operation masks the count to 5 bits.
const intptr_t kCountLimit = 0x1F;
- Range* right_range = this->right()->definition()->range();
if ((right_range == NULL) ||
!right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
__ CompareImmediate(IP, kCountLimit);
@@ -4094,9 +4092,12 @@
Register left = locs()->in(0).reg();
Register right = locs()->in(1).reg();
Register result = locs()->out().reg();
- // Handle divide by zero in runtime.
- __ cmp(right, ShifterOperand(0));
- __ b(deopt, EQ);
+ Range* right_range = InputAt(1)->definition()->range();
+ if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
+ // Handle divide by zero in runtime.
+ __ cmp(right, ShifterOperand(0));
+ __ b(deopt, EQ);
+ }
Register temp = locs()->temp(0).reg();
DRegister dtemp = EvenDRegisterOf(locs()->temp(1).fpu_reg());
Register result_div = locs()->temp(2).reg();
@@ -4504,41 +4505,40 @@
}
-static void EmitStrictComparison(FlowGraphCompiler* compiler,
- StrictCompareInstr* compare) {
- LocationSummary* locs = compare->locs();
- bool needs_number_check = compare->needs_number_check();
- intptr_t token_pos = compare->token_pos();
- Location left = locs->in(0);
- Location right = locs->in(1);
+Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
+ Location left = locs()->in(0);
+ Location right = locs()->in(1);
ASSERT(!left.IsConstant() || !right.IsConstant());
if (left.IsConstant()) {
compiler->EmitEqualityRegConstCompare(right.reg(),
left.constant(),
- needs_number_check,
- token_pos);
+ needs_number_check(),
+ token_pos());
} else if (right.IsConstant()) {
compiler->EmitEqualityRegConstCompare(left.reg(),
right.constant(),
- needs_number_check,
- token_pos);
+ needs_number_check(),
+ token_pos());
} else {
compiler->EmitEqualityRegRegCompare(left.reg(),
right.reg(),
- needs_number_check,
- token_pos);
+ needs_number_check(),
+ token_pos());
}
+ Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE;
+ return true_condition;
}
-// Special code for numbers (compare values instead of references.)
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
- EmitStrictComparison(compiler, this);
+ // The ARM code does not use true- and false-labels here.
+ BranchLabels labels = { NULL, NULL, NULL };
+ Condition true_condition = EmitComparisonCode(compiler, labels);
Register result = locs()->out().reg();
- Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE;
__ LoadObject(result, Bool::True(), true_condition);
__ LoadObject(result, Bool::False(), NegateCondition(true_condition));
}
@@ -4548,10 +4548,8 @@
BranchInstr* branch) {
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
- EmitStrictComparison(compiler, this);
-
BranchLabels labels = compiler->CreateBranchLabels(branch);
- Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE;
+ Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index b0e0f54..dc8a237 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -345,10 +345,10 @@
}
-static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
- const LocationSummary& locs,
- Token::Kind kind,
- BranchLabels labels) {
+static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
+ const LocationSummary& locs,
+ Token::Kind kind,
+ BranchLabels labels) {
Location left = locs.in(0);
Location right = locs.in(1);
ASSERT(!left.IsConstant() || !right.IsConstant());
@@ -365,7 +365,7 @@
} else {
__ cmpl(left.reg(), right.reg());
}
- EmitBranchOnCondition(compiler, true_condition, labels);
+ return true_condition;
}
@@ -410,10 +410,10 @@
}
-static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
- const LocationSummary& locs,
- Token::Kind kind,
- BranchLabels labels) {
+static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
+ const LocationSummary& locs,
+ Token::Kind kind,
+ BranchLabels labels) {
ASSERT(Token::IsEqualityOperator(kind));
XmmRegister left = locs.in(0).fpu_reg();
XmmRegister right = locs.in(1).fpu_reg();
@@ -424,14 +424,14 @@
Condition true_condition = TokenKindToMintCondition(kind);
__ cmpl(temp, Immediate(-1));
- EmitBranchOnCondition(compiler, true_condition, labels);
+ return true_condition;
}
-static void EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
- const LocationSummary& locs,
- Token::Kind kind,
- BranchLabels labels) {
+static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
+ const LocationSummary& locs,
+ Token::Kind kind,
+ BranchLabels labels) {
XmmRegister left = locs.in(0).fpu_reg();
XmmRegister right = locs.in(1).fpu_reg();
Register left_tmp = locs.temp(0).reg();
@@ -471,7 +471,7 @@
__ pextrd(left_tmp, left, Immediate(0));
__ pextrd(right_tmp, right, Immediate(0));
__ cmpl(left_tmp, right_tmp);
- EmitBranchOnCondition(compiler, lo_cond, labels);
+ return lo_cond;
}
@@ -490,10 +490,10 @@
}
-static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
- const LocationSummary& locs,
- Token::Kind kind,
- BranchLabels labels) {
+static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
+ const LocationSummary& locs,
+ Token::Kind kind,
+ BranchLabels labels) {
XmmRegister left = locs.in(0).fpu_reg();
XmmRegister right = locs.in(1).fpu_reg();
@@ -503,7 +503,20 @@
Label* nan_result = (true_condition == NOT_EQUAL)
? labels.true_label : labels.false_label;
__ j(PARITY_EVEN, nan_result);
- EmitBranchOnCondition(compiler, true_condition, labels);
+ return true_condition;
+}
+
+
+Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
+ if (operation_cid() == kSmiCid) {
+ return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
+ } else if (operation_cid() == kMintCid) {
+ return EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
+ } else {
+ ASSERT(operation_cid() == kDoubleCid);
+ return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
+ }
}
@@ -512,15 +525,9 @@
Label is_true, is_false;
BranchLabels labels = { &is_true, &is_false, &is_false };
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
- if (operation_cid() == kSmiCid) {
- EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
- } else if (operation_cid() == kMintCid) {
- EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
- }
Register result = locs()->out().reg();
Label done;
__ Bind(&is_false);
@@ -537,15 +544,8 @@
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
BranchLabels labels = compiler->CreateBranchLabels(branch);
-
- if (operation_cid() == kSmiCid) {
- EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
- } else if (operation_cid() == kMintCid) {
- EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), labels);
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
- }
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
}
@@ -562,17 +562,8 @@
}
-void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- // Never emitted outside of the BranchInstr.
- UNREACHABLE();
-}
-
-
-void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
- BranchInstr* branch) {
- BranchLabels labels = compiler->CreateBranchLabels(branch);
-
- Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO;
+Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
Register left = locs()->in(0).reg();
Location right = locs()->in(1);
if (right.IsConstant()) {
@@ -583,6 +574,21 @@
} else {
__ testl(left, right.reg());
}
+ Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO;
+ return true_condition;
+}
+
+
+void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ // Never emitted outside of the BranchInstr.
+ UNREACHABLE();
+}
+
+
+void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
+ BranchInstr* branch) {
+ BranchLabels labels = compiler->CreateBranchLabels(branch);
+ Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
@@ -623,18 +629,25 @@
}
+Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
+ if (operation_cid() == kSmiCid) {
+ return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
+ } else if (operation_cid() == kMintCid) {
+ return EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
+ } else {
+ ASSERT(operation_cid() == kDoubleCid);
+ return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
+ }
+}
+
+
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = { &is_true, &is_false, &is_false };
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
- if (operation_cid() == kSmiCid) {
- EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
- } else if (operation_cid() == kMintCid) {
- EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
- }
Register result = locs()->out().reg();
Label done;
__ Bind(&is_false);
@@ -649,15 +662,8 @@
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
-
- if (operation_cid() == kSmiCid) {
- EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
- } else if (operation_cid() == kMintCid) {
- EmitUnboxedMintComparisonOp(compiler, *locs(), kind(), labels);
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
- }
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
}
@@ -2420,6 +2426,7 @@
// if locs()->in(1).IsRegister.
Register right = locs()->in(1).reg();
+ Range* right_range = this->right()->definition()->range();
switch (op_kind()) {
case Token::kADD: {
__ addl(left, right);
@@ -2453,9 +2460,11 @@
break;
}
case Token::kTRUNCDIV: {
- // Handle divide by zero in runtime.
- __ testl(right, right);
- __ j(ZERO, deopt);
+ if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
+ // Handle divide by zero in runtime.
+ __ testl(right, right);
+ __ j(ZERO, deopt);
+ }
ASSERT(left == EAX);
ASSERT((right != EDX) && (right != EAX));
ASSERT(locs()->temp(0).reg() == EDX);
@@ -2472,9 +2481,11 @@
break;
}
case Token::kMOD: {
- // Handle divide by zero in runtime.
- __ testl(right, right);
- __ j(ZERO, deopt);
+ if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
+ // Handle divide by zero in runtime.
+ __ testl(right, right);
+ __ j(ZERO, deopt);
+ }
ASSERT(left == EDX);
ASSERT((right != EDX) && (right != EAX));
ASSERT(locs()->temp(0).reg() == EAX);
@@ -2492,16 +2503,26 @@
// res = res + right;
// }
// }
- Label subtract, done;
+ Label done;
__ cmpl(result, Immediate(0));
__ j(GREATER_EQUAL, &done, Assembler::kNearJump);
// Result is negative, adjust it.
- __ cmpl(right, Immediate(0));
- __ j(LESS, &subtract, Assembler::kNearJump);
- __ addl(result, right);
- __ jmp(&done, Assembler::kNearJump);
- __ Bind(&subtract);
- __ subl(result, right);
+ if ((right_range == NULL) || right_range->Overlaps(-1, 1)) {
+ // Right can be positive and negative.
+ Label subtract;
+ __ cmpl(right, Immediate(0));
+ __ j(LESS, &subtract, Assembler::kNearJump);
+ __ addl(result, right);
+ __ jmp(&done, Assembler::kNearJump);
+ __ Bind(&subtract);
+ __ subl(result, right);
+ } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) {
+ // Right is positive.
+ __ addl(result, right);
+ } else {
+ // Right is negative.
+ __ subl(result, right);
+ }
__ Bind(&done);
__ SmiTag(result);
break;
@@ -2514,7 +2535,6 @@
__ SmiUntag(right);
// sarl operation masks the count to 5 bits.
const intptr_t kCountLimit = 0x1F;
- Range* right_range = this->right()->definition()->range();
if ((right_range == NULL) ||
!right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
__ cmpl(right, Immediate(kCountLimit));
@@ -4007,9 +4027,12 @@
Register left = locs()->in(0).reg();
Register right = locs()->in(1).reg();
Register result = locs()->out().reg();
- // Handle divide by zero in runtime.
- __ testl(right, right);
- __ j(ZERO, deopt);
+ Range* right_range = InputAt(1)->definition()->range();
+ if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
+ // Handle divide by zero in runtime.
+ __ testl(right, right);
+ __ j(ZERO, deopt);
+ }
ASSERT(left == EAX);
ASSERT((right != EDX) && (right != EAX));
ASSERT(locs()->temp(0).reg() == EDX);
@@ -4034,16 +4057,25 @@
// res = res + right;
// }
// }
- Label subtract, done;
+ Label done;
__ cmpl(EDX, Immediate(0));
__ j(GREATER_EQUAL, &done, Assembler::kNearJump);
// Result is negative, adjust it.
- __ cmpl(right, Immediate(0));
- __ j(LESS, &subtract, Assembler::kNearJump);
- __ addl(EDX, right);
- __ jmp(&done, Assembler::kNearJump);
- __ Bind(&subtract);
- __ subl(EDX, right);
+ if ((right_range == NULL) || right_range->Overlaps(-1, 1)) {
+ Label subtract;
+ __ cmpl(right, Immediate(0));
+ __ j(LESS, &subtract, Assembler::kNearJump);
+ __ addl(EDX, right);
+ __ jmp(&done, Assembler::kNearJump);
+ __ Bind(&subtract);
+ __ subl(EDX, right);
+ } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) {
+ // Right is positive.
+ __ addl(EDX, right);
+ } else {
+ // Right is negative.
+ __ subl(EDX, right);
+ }
__ Bind(&done);
__ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld)));
@@ -4709,45 +4741,39 @@
}
-static void EmitStrictComparison(FlowGraphCompiler* compiler,
- StrictCompareInstr* compare,
- BranchLabels labels) {
- LocationSummary* locs = compare->locs();
- bool needs_number_check = compare->needs_number_check();
- intptr_t token_pos = compare->token_pos();
- Token::Kind kind = compare->kind();
- Location left = locs->in(0);
- Location right = locs->in(1);
+Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
+ Location left = locs()->in(0);
+ Location right = locs()->in(1);
ASSERT(!left.IsConstant() || !right.IsConstant());
if (left.IsConstant()) {
compiler->EmitEqualityRegConstCompare(right.reg(),
left.constant(),
- needs_number_check,
- token_pos);
+ needs_number_check(),
+ token_pos());
} else if (right.IsConstant()) {
compiler->EmitEqualityRegConstCompare(left.reg(),
right.constant(),
- needs_number_check,
- token_pos);
+ needs_number_check(),
+ token_pos());
} else {
compiler->EmitEqualityRegRegCompare(left.reg(),
right.reg(),
- needs_number_check,
- token_pos);
+ needs_number_check(),
+ token_pos());
}
- Condition true_condition = (kind == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
- EmitBranchOnCondition(compiler, true_condition, labels);
+ Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
+ return true_condition;
}
-// Special code for numbers (compare values instead of references.)
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
Label is_true, is_false;
BranchLabels labels = { &is_true, &is_false, &is_false };
-
- EmitStrictComparison(compiler, this, labels);
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out().reg();
Label done;
@@ -4765,8 +4791,8 @@
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
BranchLabels labels = compiler->CreateBranchLabels(branch);
-
- EmitStrictComparison(compiler, this, labels);
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
}
@@ -4778,16 +4804,7 @@
LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
- const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps = 0;
- LocationSummary* locs =
- new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
- locs->set_in(0, Location::RegisterOrConstant(left()));
- // Only one of the inputs can be a constant. Choose register if the first one
- // is a constant.
- locs->set_in(1, locs->in(0).IsConstant()
- ? Location::RequiresRegister()
- : Location::RegisterOrConstant(right()));
+ LocationSummary* locs = comparison()->MakeLocationSummary();
// TODO(vegorov): support byte register constraints in the register allocator.
locs->set_out(Location::RegisterLocation(EDX));
return locs;
@@ -4796,30 +4813,14 @@
void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(locs()->out().reg() == EDX);
- ASSERT(Token::IsEqualityOperator(kind()));
-
- Location left = locs()->in(0);
- Location right = locs()->in(1);
- ASSERT(!left.IsConstant() || !right.IsConstant());
// Clear upper part of the out register. We are going to use setcc on it
// which is a byte move.
__ xorl(EDX, EDX);
- // Compare left and right. For now only equality comparison is supported.
- // TODO(vegorov): reuse code from the other comparison instructions instead of
- // generating it inline here.
- if (left.IsConstant()) {
- __ CompareObject(right.reg(), left.constant());
- } else if (right.IsConstant()) {
- __ CompareObject(left.reg(), right.constant());
- } else {
- __ cmpl(left.reg(), right.reg());
- }
-
- Condition true_condition =
- ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQUAL
- : NOT_EQUAL;
+ // Emit comparison code. This must not overwrite the result register.
+ BranchLabels labels = { NULL, NULL, NULL };
+ Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 1d31672..83d0b0c 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -135,24 +135,12 @@
LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
- const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps = 0;
- LocationSummary* locs =
- new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
- locs->set_in(0, Location::RegisterOrConstant(left()));
- // Only one of the inputs can be a constant. Choose register if the first one
- // is a constant.
- locs->set_in(1, locs->in(0).IsConstant()
- ? Location::RequiresRegister()
- : Location::RegisterOrConstant(right()));
- locs->set_out(Location::RequiresRegister());
- return locs;
+ return comparison()->MakeLocationSummary();
}
void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register result = locs()->out().reg();
- ASSERT(Token::IsEqualityOperator(kind()));
Location left = locs()->in(0);
Location right = locs()->in(1);
@@ -161,20 +149,9 @@
// Clear out register.
__ mov(result, ZR);
- // Compare left and right. For now only equality comparison is supported.
- // TODO(vegorov): reuse code from the other comparison instructions instead of
- // generating it inline here.
- if (left.IsConstant()) {
- __ CompareObject(CMPRES1, CMPRES2, right.reg(), left.constant());
- } else if (right.IsConstant()) {
- __ CompareObject(CMPRES1, CMPRES2, left.reg(), right.constant());
- } else {
- __ slt(CMPRES1, left.reg(), right.reg());
- __ slt(CMPRES2, right.reg(), left.reg());
- }
-
- Condition true_condition =
- ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQ : NE;
+ // Emit comparison code. This must not overwrite the result register.
+ BranchLabels labels = { NULL, NULL, NULL };
+ Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
@@ -197,12 +174,29 @@
}
}
- if (true_condition == EQ) {
- __ xor_(result, CMPRES1, CMPRES2);
- __ xori(result, result, Immediate(1));
- } else {
- ASSERT(true_condition == NE);
- __ xor_(result, CMPRES1, CMPRES2);
+ switch (true_condition) {
+ case EQ:
+ __ xor_(result, CMPRES1, CMPRES2);
+ __ xori(result, result, Immediate(1));
+ break;
+ case NE:
+ __ xor_(result, CMPRES1, CMPRES2);
+ break;
+ case GT:
+ __ mov(result, CMPRES2);
+ break;
+ case GE:
+ __ xori(result, CMPRES1, Immediate(1));
+ break;
+ case LT:
+ __ mov(result, CMPRES1);
+ break;
+ case LE:
+ __ xori(result, CMPRES2, Immediate(1));
+ break;
+ default:
+ UNREACHABLE();
+ break;
}
if (is_power_of_two_kind) {
@@ -482,10 +476,10 @@
}
-static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
- const LocationSummary& locs,
- Token::Kind kind,
- BranchLabels labels) {
+static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
+ const LocationSummary& locs,
+ Token::Kind kind,
+ BranchLabels labels) {
__ TraceSimMsg("EmitSmiComparisonOp");
__ Comment("EmitSmiComparisonOp");
Location left = locs.in(0);
@@ -503,7 +497,7 @@
__ slt(CMPRES1, left.reg(), right.reg());
__ slt(CMPRES2, right.reg(), left.reg());
}
- EmitBranchOnCondition(compiler, true_condition, labels);
+ return true_condition;
}
@@ -522,10 +516,10 @@
}
-static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
- const LocationSummary& locs,
- Token::Kind kind,
- BranchLabels labels) {
+static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
+ const LocationSummary& locs,
+ Token::Kind kind,
+ BranchLabels labels) {
DRegister left = locs.in(0).fpu_reg();
DRegister right = locs.in(1).fpu_reg();
@@ -551,6 +545,7 @@
}
}
+ // Ordering is expected to be described by CMPRES1, CMPRES2.
__ LoadImmediate(TMP, 1);
if (true_condition == NE) {
__ movf(CMPRES1, ZR);
@@ -560,9 +555,18 @@
__ movt(CMPRES1, ZR);
}
__ mov(CMPRES2, ZR);
+ return EQ;
+}
- // EmitBranchOnCondition expects ordering to be described by CMPRES1, CMPRES2.
- EmitBranchOnCondition(compiler, EQ, labels);
+
+Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
+ if (operation_cid() == kSmiCid) {
+ return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
+ } else {
+ ASSERT(operation_cid() == kDoubleCid);
+ return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
+ }
}
@@ -572,13 +576,9 @@
Label is_true, is_false;
BranchLabels labels = { &is_true, &is_false, &is_false };
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
- if (operation_cid() == kSmiCid) {
- EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
- }
Register result = locs()->out().reg();
Label done;
__ Bind(&is_false);
@@ -597,13 +597,8 @@
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
BranchLabels labels = compiler->CreateBranchLabels(branch);
-
- if (operation_cid() == kSmiCid) {
- EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
- }
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
}
@@ -620,17 +615,8 @@
}
-void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- // Never emitted outside of the BranchInstr.
- UNREACHABLE();
-}
-
-
-void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
- BranchInstr* branch) {
- BranchLabels labels = compiler->CreateBranchLabels(branch);
-
- Condition true_condition = (kind() == Token::kNE) ? NE : EQ;
+Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
Register left = locs()->in(0).reg();
Location right = locs()->in(1);
if (right.IsConstant()) {
@@ -642,6 +628,21 @@
__ and_(CMPRES1, left, right.reg());
}
__ mov(CMPRES2, ZR);
+ Condition true_condition = (kind() == Token::kNE) ? NE : EQ;
+ return true_condition;
+}
+
+
+void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ // Never emitted outside of the BranchInstr.
+ UNREACHABLE();
+}
+
+
+void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
+ BranchInstr* branch) {
+ BranchLabels labels = compiler->CreateBranchLabels(branch);
+ Condition true_condition = EmitComparisonCode(compiler, labels);
EmitBranchOnCondition(compiler, true_condition, labels);
}
@@ -682,18 +683,25 @@
}
+Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
+ if (operation_cid() == kSmiCid) {
+ return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
+ } else {
+ ASSERT(operation_cid() == kDoubleCid);
+ return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
+ }
+}
+
+
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ TraceSimMsg("RelationalOpInstr");
Label is_true, is_false;
BranchLabels labels = { &is_true, &is_false, &is_false };
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
- if (operation_cid() == kSmiCid) {
- EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
- }
Register result = locs()->out().reg();
Label done;
__ Bind(&is_false);
@@ -710,13 +718,8 @@
__ TraceSimMsg("RelationalOpInstr");
BranchLabels labels = compiler->CreateBranchLabels(branch);
-
- if (operation_cid() == kSmiCid) {
- EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
- }
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
}
@@ -2479,6 +2482,7 @@
}
Register right = locs()->in(1).reg();
+ Range* right_range = this->right()->definition()->range();
switch (op_kind()) {
case Token::kADD: {
if (deopt == NULL) {
@@ -2528,8 +2532,10 @@
break;
}
case Token::kTRUNCDIV: {
- // Handle divide by zero in runtime.
- __ beq(right, ZR, deopt);
+ if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
+ // Handle divide by zero in runtime.
+ __ beq(right, ZR, deopt);
+ }
Register temp = locs()->temp(0).reg();
__ sra(temp, left, kSmiTagSize); // SmiUntag left into temp.
__ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP.
@@ -2542,8 +2548,10 @@
break;
}
case Token::kMOD: {
- // Handle divide by zero in runtime.
- __ beq(right, ZR, deopt);
+ if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
+ // Handle divide by zero in runtime.
+ __ beq(right, ZR, deopt);
+ }
Register temp = locs()->temp(0).reg();
__ sra(temp, left, kSmiTagSize); // SmiUntag left into temp.
__ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP.
@@ -2557,13 +2565,22 @@
// res = res + right;
// }
// }
- Label done, subtract;
+ Label done;
__ bgez(result, &done);
- __ bltz(right, &subtract);
- __ addu(result, result, TMP);
- __ b(&done);
- __ Bind(&subtract);
- __ subu(result, result, TMP);
+ if ((right_range == NULL) || right_range->Overlaps(-1, 1)) {
+ Label subtract;
+ __ bltz(right, &subtract);
+ __ addu(result, result, TMP);
+ __ b(&done);
+ __ Bind(&subtract);
+ __ subu(result, result, TMP);
+ } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) {
+ // Right is positive.
+ __ addu(result, result, TMP);
+ } else {
+ // Right is negative.
+ __ subu(result, result, TMP);
+ }
__ Bind(&done);
__ SmiTag(result);
break;
@@ -2576,7 +2593,6 @@
__ sra(temp, right, kSmiTagSize); // SmiUntag right into temp.
// sra operation masks the count to 5 bits.
const intptr_t kCountLimit = 0x1F;
- Range* right_range = this->right()->definition()->range();
if ((right_range == NULL) ||
!right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
Label ok;
@@ -3428,8 +3444,11 @@
Register temp = locs()->temp(0).reg();
Register result_div = locs()->temp(1).reg();
Register result_mod = locs()->temp(2).reg();
- // Handle divide by zero in runtime.
- __ beq(right, ZR, deopt);
+ Range* right_range = InputAt(1)->definition()->range();
+ if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
+ // Handle divide by zero in runtime.
+ __ beq(right, ZR, deopt);
+ }
__ sra(temp, left, kSmiTagSize); // SmiUntag left into temp.
__ sra(TMP, right, kSmiTagSize); // SmiUntag right into TMP.
__ div(temp, TMP);
@@ -3446,13 +3465,22 @@
// res = res + right;
// }
// }
- Label done, subtract;
+ Label done;
__ bgez(result_mod, &done);
- __ bltz(right, &subtract);
- __ addu(result_mod, result_mod, TMP);
- __ b(&done);
- __ Bind(&subtract);
- __ subu(result_mod, result_mod, TMP);
+ if ((right_range == NULL) || right_range->Overlaps(-1, 1)) {
+ Label subtract;
+ __ bltz(right, &subtract);
+ __ addu(result_mod, result_mod, TMP);
+ __ b(&done);
+ __ Bind(&subtract);
+ __ subu(result_mod, result_mod, TMP);
+ } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) {
+ // Right is positive.
+ __ addu(result_mod, result_mod, TMP);
+ } else {
+ // Right is negative.
+ __ subu(result_mod, result_mod, TMP);
+ }
__ Bind(&done);
__ SmiTag(result_div);
@@ -3831,37 +3859,32 @@
}
-static void EmitStrictComparison(FlowGraphCompiler* compiler,
- StrictCompareInstr* compare,
- BranchLabels labels) {
- LocationSummary* locs = compare->locs();
- bool needs_number_check = compare->needs_number_check();
- intptr_t token_pos = compare->token_pos();
- Token::Kind kind = compare->kind();
- Location left = locs->in(0);
- Location right = locs->in(1);
+Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
+ Location left = locs()->in(0);
+ Location right = locs()->in(1);
ASSERT(!left.IsConstant() || !right.IsConstant());
if (left.IsConstant()) {
compiler->EmitEqualityRegConstCompare(right.reg(),
left.constant(),
- needs_number_check,
- token_pos);
+ needs_number_check(),
+ token_pos());
} else if (right.IsConstant()) {
compiler->EmitEqualityRegConstCompare(left.reg(),
right.constant(),
- needs_number_check,
- token_pos);
+ needs_number_check(),
+ token_pos());
} else {
compiler->EmitEqualityRegRegCompare(left.reg(),
right.reg(),
- needs_number_check,
- token_pos);
+ needs_number_check(),
+ token_pos());
}
- Condition true_condition = (kind == Token::kEQ_STRICT) ? EQ : NE;
- EmitBranchOnCondition(compiler, true_condition, labels);
+ Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQ : NE;
+ return true_condition;
}
-// Special code for numbers (compare values instead of references.)
+
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ TraceSimMsg("StrictCompareInstr");
__ Comment("StrictCompareInstr");
@@ -3869,8 +3892,8 @@
Label is_true, is_false;
BranchLabels labels = { &is_true, &is_false, &is_false };
-
- EmitStrictComparison(compiler, this, labels);
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out().reg();
Label done;
@@ -3889,8 +3912,8 @@
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
BranchLabels labels = compiler->CreateBranchLabels(branch);
-
- EmitStrictComparison(compiler, this, labels);
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
}
diff --git a/runtime/vm/intermediate_language_test.cc b/runtime/vm/intermediate_language_test.cc
index 4caaa86..ac57c55 100644
--- a/runtime/vm/intermediate_language_test.cc
+++ b/runtime/vm/intermediate_language_test.cc
@@ -39,4 +39,24 @@
EXPECT(!c3->Equals(c1));
}
+
+TEST_CASE(RangeTests) {
+ Range* zero = new Range(
+ RangeBoundary::FromConstant(0),
+ RangeBoundary::FromConstant(0));
+ Range* positive = new Range(
+ RangeBoundary::FromConstant(0),
+ RangeBoundary::FromConstant(100));
+ Range* negative = new Range(
+ RangeBoundary::FromConstant(-1),
+ RangeBoundary::FromConstant(-100));
+ Range* range_x = new Range(
+ RangeBoundary::FromConstant(-15),
+ RangeBoundary::FromConstant(100));
+ EXPECT(zero->Overlaps(0, 0));
+ EXPECT(positive->Overlaps(0, 0));
+ EXPECT(!negative->Overlaps(0, 0));
+ EXPECT(range_x->Overlaps(0, 0));
+}
+
} // namespace dart
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 055ba3c..9f61a2f 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -131,16 +131,7 @@
LocationSummary* IfThenElseInstr::MakeLocationSummary() const {
- const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps = 0;
- LocationSummary* locs =
- new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
- locs->set_in(0, Location::RegisterOrConstant(left()));
- // Only one of the inputs can be a constant. Choose register if the first one
- // is a constant.
- locs->set_in(1, locs->in(0).IsConstant()
- ? Location::RequiresRegister()
- : Location::RegisterOrConstant(right()));
+ LocationSummary* locs = comparison()->MakeLocationSummary();
// TODO(vegorov): support byte register constraints in the register allocator.
locs->set_out(Location::RegisterLocation(RDX));
return locs;
@@ -149,30 +140,14 @@
void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(locs()->out().reg() == RDX);
- ASSERT(Token::IsEqualityOperator(kind()));
-
- Location left = locs()->in(0);
- Location right = locs()->in(1);
- ASSERT(!left.IsConstant() || !right.IsConstant());
// Clear upper part of the out register. We are going to use setcc on it
// which is a byte move.
__ xorq(RDX, RDX);
- // Compare left and right. For now only equality comparison is supported.
- // TODO(vegorov): reuse code from the other comparison instructions instead of
- // generating it inline here.
- if (left.IsConstant()) {
- __ CompareObject(right.reg(), left.constant(), PP);
- } else if (right.IsConstant()) {
- __ CompareObject(left.reg(), right.constant(), PP);
- } else {
- __ cmpq(left.reg(), right.reg());
- }
-
- Condition true_condition =
- ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQUAL
- : NOT_EQUAL;
+ // Emit comparison code. This must not overwrite the result register.
+ BranchLabels labels = { NULL, NULL, NULL };
+ Condition true_condition = comparison()->EmitComparisonCode(compiler, labels);
const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
@@ -420,10 +395,10 @@
}
-static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
- const LocationSummary& locs,
- Token::Kind kind,
- BranchLabels labels) {
+static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
+ const LocationSummary& locs,
+ Token::Kind kind,
+ BranchLabels labels) {
Location left = locs.in(0);
Location right = locs.in(1);
ASSERT(!left.IsConstant() || !right.IsConstant());
@@ -440,7 +415,7 @@
} else {
__ cmpq(left.reg(), right.reg());
}
- EmitBranchOnCondition(compiler, true_condition, labels);
+ return true_condition;
}
@@ -459,10 +434,10 @@
}
-static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
- const LocationSummary& locs,
- Token::Kind kind,
- BranchLabels labels) {
+static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
+ const LocationSummary& locs,
+ Token::Kind kind,
+ BranchLabels labels) {
XmmRegister left = locs.in(0).fpu_reg();
XmmRegister right = locs.in(1).fpu_reg();
@@ -472,7 +447,18 @@
Label* nan_result = (true_condition == NOT_EQUAL)
? labels.true_label : labels.false_label;
__ j(PARITY_EVEN, nan_result);
- EmitBranchOnCondition(compiler, true_condition, labels);
+ return true_condition;
+}
+
+
+Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
+ if (operation_cid() == kSmiCid) {
+ return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
+ } else {
+ ASSERT(operation_cid() == kDoubleCid);
+ return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
+ }
}
@@ -481,13 +467,9 @@
Label is_true, is_false;
BranchLabels labels = { &is_true, &is_false, &is_false };
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
- if (operation_cid() == kSmiCid) {
- EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
- }
Register result = locs()->out().reg();
Label done;
__ Bind(&is_false);
@@ -504,13 +486,8 @@
ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
BranchLabels labels = compiler->CreateBranchLabels(branch);
-
- if (operation_cid() == kSmiCid) {
- EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
- }
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
}
@@ -527,17 +504,8 @@
}
-void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- // Never emitted outside of the BranchInstr.
- UNREACHABLE();
-}
-
-
-void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
- BranchInstr* branch) {
- BranchLabels labels = compiler->CreateBranchLabels(branch);
-
- Condition branch_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO;
+Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
Register left_reg = locs()->in(0).reg();
Location right = locs()->in(1);
if (right.IsConstant()) {
@@ -548,7 +516,22 @@
} else {
__ testq(left_reg, right.reg());
}
- EmitBranchOnCondition(compiler, branch_condition, labels);
+ Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO;
+ return true_condition;
+}
+
+
+void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ // Never emitted outside of the BranchInstr.
+ UNREACHABLE();
+}
+
+
+void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler,
+ BranchInstr* branch) {
+ BranchLabels labels = compiler->CreateBranchLabels(branch);
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
}
@@ -577,16 +560,23 @@
}
+Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
+ if (operation_cid() == kSmiCid) {
+ return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
+ } else {
+ ASSERT(operation_cid() == kDoubleCid);
+ return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
+ }
+}
+
+
void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Label is_true, is_false;
BranchLabels labels = { &is_true, &is_false, &is_false };
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
- if (operation_cid() == kSmiCid) {
- EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
- }
Register result = locs()->out().reg();
Label done;
__ Bind(&is_false);
@@ -601,13 +591,8 @@
void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler,
BranchInstr* branch) {
BranchLabels labels = compiler->CreateBranchLabels(branch);
-
- if (operation_cid() == kSmiCid) {
- EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
- } else {
- ASSERT(operation_cid() == kDoubleCid);
- EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
- }
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
}
@@ -2391,6 +2376,7 @@
// if locs()->in(1).IsRegister.
Register right = locs()->in(1).reg();
+ Range* right_range = this->right()->definition()->range();
switch (op_kind()) {
case Token::kADD: {
__ addq(left, right);
@@ -2431,11 +2417,11 @@
ASSERT((right != RDX) && (right != RAX));
ASSERT(temp == RDX);
ASSERT(result == RAX);
-
- // Handle divide by zero in runtime.
- __ testq(right, right);
- __ j(ZERO, deopt);
-
+ if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
+ // Handle divide by zero in runtime.
+ __ testq(right, right);
+ __ j(ZERO, deopt);
+ }
// Check if both operands fit into 32bits as idiv with 64bit operands
// requires twice as many cycles and has much higher latency.
// We are checking this before untagging them to avoid corner case
@@ -2478,9 +2464,11 @@
ASSERT((right != RDX) && (right != RAX));
ASSERT(temp == RAX);
ASSERT(result == RDX);
- // Handle divide by zero in runtime.
- __ testq(right, right);
- __ j(ZERO, deopt);
+ if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
+ // Handle divide by zero in runtime.
+ __ testq(right, right);
+ __ j(ZERO, deopt);
+ }
// Check if both operands fit into 32bits as idiv with 64bit operands
// requires twice as many cycles and has much higher latency.
// We are checking this before untagging them to avoid corner case
@@ -2517,16 +2505,25 @@
// res = res + right;
// }
// }
- Label subtract, all_done;
+ Label all_done;
__ cmpq(result, Immediate(0));
__ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
// Result is negative, adjust it.
- __ cmpq(right, Immediate(0));
- __ j(LESS, &subtract, Assembler::kNearJump);
- __ addq(result, right);
- __ jmp(&all_done, Assembler::kNearJump);
- __ Bind(&subtract);
- __ subq(result, right);
+ if ((right_range == NULL) || right_range->Overlaps(-1, 1)) {
+ Label subtract;
+ __ cmpq(right, Immediate(0));
+ __ j(LESS, &subtract, Assembler::kNearJump);
+ __ addq(result, right);
+ __ jmp(&all_done, Assembler::kNearJump);
+ __ Bind(&subtract);
+ __ subq(result, right);
+ } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) {
+ // Right is positive.
+ __ addq(result, right);
+ } else {
+ // Right is negative.
+ __ subq(result, right);
+ }
__ Bind(&all_done);
__ SmiTag(result);
break;
@@ -2539,7 +2536,6 @@
__ SmiUntag(right);
// sarq operation masks the count to 6 bits.
const intptr_t kCountLimit = 0x3F;
- Range* right_range = this->right()->definition()->range();
if ((right_range == NULL) ||
!right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
__ CompareImmediate(right, Immediate(kCountLimit), PP);
@@ -4076,9 +4072,13 @@
ASSERT((right != RDX) && (right != RAX));
ASSERT(temp == RDX);
ASSERT((result != RDX) && (result != RAX));
- // Handle divide by zero in runtime.
- __ testq(right, right);
- __ j(ZERO, deopt);
+
+ Range* right_range = InputAt(1)->definition()->range();
+ if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
+ // Handle divide by zero in runtime.
+ __ testq(right, right);
+ __ j(ZERO, deopt);
+ }
// Check if both operands fit into 32bits as idiv with 64bit operands
// requires twice as many cycles and has much higher latency.
// We are checking this before untagging them to avoid corner case
@@ -4121,16 +4121,25 @@
// res = res + right;
// }
// }
- Label subtract, all_done;
+ Label all_done;
__ cmpq(RDX, Immediate(0));
__ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
// Result is negative, adjust it.
- __ cmpq(right, Immediate(0));
- __ j(LESS, &subtract, Assembler::kNearJump);
- __ addq(RDX, right);
- __ jmp(&all_done, Assembler::kNearJump);
- __ Bind(&subtract);
- __ subq(RDX, right);
+ if ((right_range == NULL) || right_range->Overlaps(-1, 1)) {
+ Label subtract;
+ __ cmpq(right, Immediate(0));
+ __ j(LESS, &subtract, Assembler::kNearJump);
+ __ addq(RDX, right);
+ __ jmp(&all_done, Assembler::kNearJump);
+ __ Bind(&subtract);
+ __ subq(RDX, right);
+ } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) {
+ // Right is positive.
+ __ addq(RDX, right);
+ } else {
+ // Right is negative.
+ __ subq(RDX, right);
+ }
__ Bind(&all_done);
__ SmiTag(result);
@@ -4519,46 +4528,41 @@
}
-static void EmitStrictComparison(FlowGraphCompiler* compiler,
- StrictCompareInstr* compare,
- BranchLabels labels) {
- LocationSummary* locs = compare->locs();
- bool needs_number_check = compare->needs_number_check();
- intptr_t token_pos = compare->token_pos();
- Token::Kind kind = compare->kind();
- Location left = locs->in(0);
- Location right = locs->in(1);
+Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
+ BranchLabels labels) {
+ Location left = locs()->in(0);
+ Location right = locs()->in(1);
ASSERT(!left.IsConstant() || !right.IsConstant());
if (left.IsConstant()) {
compiler->EmitEqualityRegConstCompare(right.reg(),
left.constant(),
- needs_number_check,
- token_pos);
+ needs_number_check(),
+ token_pos());
} else if (right.IsConstant()) {
compiler->EmitEqualityRegConstCompare(left.reg(),
right.constant(),
- needs_number_check,
- token_pos);
+ needs_number_check(),
+ token_pos());
} else {
compiler->EmitEqualityRegRegCompare(left.reg(),
right.reg(),
- needs_number_check,
- token_pos);
+ needs_number_check(),
+ token_pos());
}
- Condition true_condition = (kind == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
- EmitBranchOnCondition(compiler, true_condition, labels);
+ Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
+ return true_condition;
}
-// Special code for numbers (compare values instead of references.)
void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
Label is_true, is_false;
BranchLabels labels = { &is_true, &is_false, &is_false };
- EmitStrictComparison(compiler, this, labels);
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
Register result = locs()->out().reg();
Label done;
@@ -4576,8 +4580,8 @@
ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT);
BranchLabels labels = compiler->CreateBranchLabels(branch);
-
- EmitStrictComparison(compiler, this, labels);
+ Condition true_condition = EmitComparisonCode(compiler, labels);
+ EmitBranchOnCondition(compiler, true_condition, labels);
}
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index c3e92fa..1874127 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -25,7 +25,6 @@
#include "vm/profiler.h"
#include "vm/reusable_handles.h"
#include "vm/service.h"
-#include "vm/signal_handler.h"
#include "vm/simulator.h"
#include "vm/stack_frame.h"
#include "vm/stub_code.h"
@@ -340,7 +339,6 @@
}
void Isolate::SetCurrent(Isolate* current) {
- ScopedSignalBlocker ssb;
Isolate* old_isolate = Current();
if (old_isolate != NULL) {
ProfilerManager::DescheduleIsolate(old_isolate);
@@ -371,6 +369,9 @@
Isolate* result = new Isolate();
ASSERT(result != NULL);
+ // Setup for profiling.
+ ProfilerManager::SetupIsolateForProfiling(result);
+
// TODO(5411455): For now just set the recently created isolate as
// the current isolate.
SetCurrent(result);
@@ -409,8 +410,6 @@
}
}
- // Setup for profiling.
- ProfilerManager::SetupIsolateForProfiling(result);
return result;
}
@@ -529,7 +528,7 @@
StartIsolateScope start_scope(isolate);
StackZone zone(isolate);
HandleScope handle_scope(isolate);
- if (!ClassFinalizer::FinalizeTypeHierarchy()) {
+ if (!ClassFinalizer::ProcessPendingClasses()) {
// Error is in sticky error already.
return false;
}
@@ -704,11 +703,6 @@
StackZone stack_zone(this);
HandleScope handle_scope(this);
- ScopedSignalBlocker ssb;
-
- ProfilerManager::DescheduleIsolate(this);
-
-
if (FLAG_print_object_histogram) {
heap()->CollectAllGarbage();
object_histogram()->Print();
@@ -750,6 +744,7 @@
// TODO(5411455): For now just make sure there are no current isolates
// as we are shutting down the isolate.
SetCurrent(NULL);
+ ProfilerManager::DescheduleIsolate(this);
ProfilerManager::ShutdownIsolateForProfiling(this);
}
diff --git a/runtime/vm/megamorphic_cache_table.cc b/runtime/vm/megamorphic_cache_table.cc
index 91272a1..a392731 100644
--- a/runtime/vm/megamorphic_cache_table.cc
+++ b/runtime/vm/megamorphic_cache_table.cc
@@ -12,7 +12,8 @@
namespace dart {
MegamorphicCacheTable::MegamorphicCacheTable()
- : miss_handler_(NULL),
+ : miss_handler_function_(NULL),
+ miss_handler_code_(NULL),
capacity_(0),
length_(0),
table_(NULL) {
@@ -65,14 +66,16 @@
false, // Not external.
cls,
0)); // No token position.
+ miss_handler_code_ = code.raw();
+ miss_handler_function_ = function.raw();
function.SetCode(code);
- miss_handler_ = function.raw();
}
void MegamorphicCacheTable::VisitObjectPointers(ObjectPointerVisitor* v) {
ASSERT(v != NULL);
- v->VisitPointer(reinterpret_cast<RawObject**>(&miss_handler_));
+ v->VisitPointer(reinterpret_cast<RawObject**>(&miss_handler_code_));
+ v->VisitPointer(reinterpret_cast<RawObject**>(&miss_handler_function_));
for (intptr_t i = 0; i < length_; ++i) {
v->VisitPointer(reinterpret_cast<RawObject**>(&table_[i].name));
v->VisitPointer(reinterpret_cast<RawObject**>(&table_[i].descriptor));
diff --git a/runtime/vm/megamorphic_cache_table.h b/runtime/vm/megamorphic_cache_table.h
index 1cfd8c2..eafb35b 100644
--- a/runtime/vm/megamorphic_cache_table.h
+++ b/runtime/vm/megamorphic_cache_table.h
@@ -14,6 +14,7 @@
class ObjectPointerVisitor;
class RawArray;
class RawFunction;
+class RawCode;
class RawMegamorphicCache;
class RawString;
class String;
@@ -23,7 +24,7 @@
MegamorphicCacheTable();
~MegamorphicCacheTable();
- RawFunction* miss_handler() const { return miss_handler_; }
+ RawFunction* miss_handler() const { return miss_handler_function_; }
void InitMissHandler();
RawMegamorphicCache* Lookup(const String& name, const Array& descriptor);
@@ -41,7 +42,8 @@
static const int kCapacityIncrement = 128;
- RawFunction* miss_handler_;
+ RawFunction* miss_handler_function_;
+ RawCode* miss_handler_code_;
intptr_t capacity_;
intptr_t length_;
Entry* table_;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index c420682..a954661 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1578,7 +1578,7 @@
case kExternalTypedDataFloat64ArrayCid:
return Symbols::Float64List().raw();
default:
- if (!IsSignatureClass()) {
+ if (!IsCanonicalSignatureClass()) {
const String& name = String::Handle(Name());
return String::IdentifierPrettyName(name);
} else {
@@ -4103,22 +4103,6 @@
}
-void Function::DetachCode() const {
- // Set unoptimized code as non-entrant, and set code and unoptimized code
- // to null.
- CodePatcher::PatchEntry(Code::Handle(unoptimized_code()));
- StorePointer(&raw_ptr()->code_, Code::null());
- StorePointer(&raw_ptr()->unoptimized_code_, Code::null());
-}
-
-
-void Function::ReattachCode(const Code& code) const {
- StorePointer(&raw_ptr()->code_, code.raw());
- StorePointer(&raw_ptr()->unoptimized_code_, code.raw());
- CodePatcher::RestoreEntry(code);
-}
-
-
void Function::SwitchToUnoptimizedCode() const {
ASSERT(HasOptimizedCode());
@@ -5918,18 +5902,21 @@
jsobj.AddProperty("id", id);
jsobj.AddProperty("name", internal_field_name);
jsobj.AddProperty("user_name", field_name);
- if (ref) {
- return;
+ if (is_static()) {
+ const Object& valueObj = Object::Handle(value());
+ jsobj.AddProperty("value", valueObj);
}
Class& cls = Class::Handle(owner());
- jsobj.AddProperty("type", "Field");
- jsobj.AddProperty("id", id);
- jsobj.AddProperty("name", internal_field_name);
- jsobj.AddProperty("user_name", field_name);
- jsobj.AddProperty("class", cls);
+ jsobj.AddProperty("owner", cls);
+ AbstractType& declared_type = AbstractType::Handle(type());
+ cls = declared_type.type_class();
+ jsobj.AddProperty("declared_type", cls);
jsobj.AddProperty("static", is_static());
jsobj.AddProperty("final", is_final());
jsobj.AddProperty("const", is_const());
+ if (ref) {
+ return;
+ }
jsobj.AddProperty("guard_nullable", is_nullable());
if (guarded_cid() == kIllegalCid) {
jsobj.AddProperty("guard_class", "unknown");
@@ -6804,6 +6791,24 @@
}
+const char* Script::GetKindAsCString() const {
+ switch (kind()) {
+ case RawScript::kScriptTag:
+ return "script";
+ case RawScript::kLibraryTag:
+ return "library";
+ case RawScript::kSourceTag:
+ return "source";
+ case RawScript::kPatchTag:
+ return "patch";
+ default:
+ UNIMPLEMENTED();
+ }
+ UNREACHABLE();
+ return NULL;
+}
+
+
void Script::set_url(const String& value) const {
StorePointer(&raw_ptr()->url_, value.raw());
}
@@ -7055,6 +7060,18 @@
void Script::PrintToJSONStream(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
+ ObjectIdRing* ring = Isolate::Current()->object_id_ring();
+ intptr_t id = ring->GetIdForObject(raw());
+ jsobj.AddProperty("type", JSONType(ref));
+ jsobj.AddProperty("id", id);
+ const String& name = String::Handle(url());
+ jsobj.AddProperty("name", name.ToCString());
+ jsobj.AddProperty("kind", GetKindAsCString());
+ if (ref) {
+ return;
+ }
+ const String& source = String::Handle(Source());
+ jsobj.AddProperty("source", source.ToCString());
}
@@ -8123,15 +8140,18 @@
jsobj.AddProperty("type", JSONType(ref));
jsobj.AddProperty("id", id);
jsobj.AddProperty("name", library_name);
- if (ref) return;
jsobj.AddProperty("url", library_url);
+ if (ref) return;
{
JSONArray jsarr(&jsobj, "classes");
ClassDictionaryIterator class_iter(*this);
Class& klass = Class::Handle();
while (class_iter.HasNext()) {
klass = class_iter.GetNextClass();
- jsarr.AddValue(klass);
+ if (!klass.IsCanonicalSignatureClass() &&
+ !klass.IsAnonymousMixinApplication()) {
+ jsarr.AddValue(klass);
+ }
}
}
{
@@ -8142,6 +8162,42 @@
jsarr.AddValue(lib);
}
}
+ {
+ JSONArray jsarr(&jsobj, "variables");
+ DictionaryIterator entries(*this);
+ Object& entry = Object::Handle();
+ while (entries.HasNext()) {
+ entry = entries.GetNext();
+ if (entry.IsField()) {
+ jsarr.AddValue(entry);
+ }
+ }
+ }
+ {
+ JSONArray jsarr(&jsobj, "functions");
+ DictionaryIterator entries(*this);
+ Object& entry = Object::Handle();
+ while (entries.HasNext()) {
+ entry = entries.GetNext();
+ if (entry.IsFunction()) {
+ const Function& func = Function::Cast(entry);
+ if (func.kind() == RawFunction::kRegularFunction ||
+ func.kind() == RawFunction::kGetterFunction ||
+ func.kind() == RawFunction::kSetterFunction) {
+ jsarr.AddValue(func);
+ }
+ }
+ }
+ }
+ {
+ JSONArray jsarr(&jsobj, "scripts");
+ Array& scripts = Array::Handle(LoadedScripts());
+ Script& script = Script::Handle();
+ for (intptr_t i = 0; i < scripts.Length(); i++) {
+ script ^= scripts.At(i);
+ jsarr.AddValue(script);
+ }
+ }
}
@@ -11342,7 +11398,23 @@
void Instance::PrintToJSONStream(JSONStream* stream, bool ref) const {
+ ObjectIdRing* ring = Isolate::Current()->object_id_ring();
+ intptr_t id = ring->GetIdForObject(raw());
+
JSONObject jsobj(stream);
+ jsobj.AddProperty("type", JSONType(ref));
+ jsobj.AddProperty("id", id);
+
+ // Set the "preview" property for this instance.
+ if (IsNull()) {
+ jsobj.AddProperty("preview", "null");
+ } else if (raw() == Object::sentinel().raw() ||
+ raw() == Object::transition_sentinel().raw()) {
+ jsobj.AddProperty("preview", "<uninitialized>");
+ } else {
+ // TODO(turnidge): Handle special characters? Truncate?
+ jsobj.AddProperty("preview", ToCString());
+ }
}
@@ -12677,7 +12749,7 @@
void Number::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Instance::PrintToJSONStream(stream, ref);
}
@@ -12689,7 +12761,7 @@
void Integer::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Number::PrintToJSONStream(stream, ref);
}
@@ -12788,6 +12860,12 @@
}
+uint32_t Integer::AsTruncatedUint32Value() const {
+ UNIMPLEMENTED();
+ return 0;
+}
+
+
int Integer::CompareWith(const Integer& other) const {
UNIMPLEMENTED();
return 0;
@@ -13057,6 +13135,11 @@
}
+uint32_t Smi::AsTruncatedUint32Value() const {
+ return this->Value() & 0xFFFFFFFF;
+}
+
+
static bool FitsIntoSmi(const Integer& integer) {
if (integer.IsSmi()) {
return true;
@@ -13107,7 +13190,7 @@
void Smi::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Number::PrintToJSONStream(stream, ref);
}
@@ -13190,6 +13273,11 @@
}
+uint32_t Mint::AsTruncatedUint32Value() const {
+ return this->value() & 0xFFFFFFFF;
+}
+
+
int Mint::CompareWith(const Integer& other) const {
ASSERT(!FitsIntoSmi(*this));
if (other.IsMint() || other.IsSmi()) {
@@ -13226,7 +13314,7 @@
void Mint::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Number::PrintToJSONStream(stream, ref);
}
@@ -13332,7 +13420,7 @@
void Double::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Number::PrintToJSONStream(stream, ref);
}
@@ -13457,6 +13545,11 @@
}
+uint32_t Bigint::AsTruncatedUint32Value() const {
+ return BigintOperations::TruncateToUint32(*this);
+}
+
+
// For positive values: Smi < Mint < Bigint.
int Bigint::CompareWith(const Integer& other) const {
ASSERT(!FitsIntoSmi(*this));
@@ -13503,7 +13596,7 @@
void Bigint::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Number::PrintToJSONStream(stream, ref);
}
@@ -14126,7 +14219,7 @@
void String::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Instance::PrintToJSONStream(stream, ref);
}
@@ -14884,7 +14977,7 @@
void Bool::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Instance::PrintToJSONStream(stream, ref);
}
@@ -14970,7 +15063,7 @@
void Array::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Instance::PrintToJSONStream(stream, ref);
}
@@ -15183,7 +15276,7 @@
void GrowableObjectArray::PrintToJSONStream(JSONStream* stream,
bool ref) const {
- JSONObject jsobj(stream);
+ Instance::PrintToJSONStream(stream, ref);
}
@@ -15288,7 +15381,7 @@
void Float32x4::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Instance::PrintToJSONStream(stream, ref);
}
@@ -15393,7 +15486,7 @@
void Int32x4::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Instance::PrintToJSONStream(stream, ref);
}
@@ -15443,7 +15536,7 @@
void TypedData::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Instance::PrintToJSONStream(stream, ref);
}
@@ -15479,7 +15572,7 @@
void ExternalTypedData::PrintToJSONStream(JSONStream* stream,
bool ref) const {
- JSONObject jsobj(stream);
+ Instance::PrintToJSONStream(stream, ref);
}
@@ -15666,7 +15759,7 @@
void Stacktrace::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Instance::PrintToJSONStream(stream, ref);
}
@@ -15876,7 +15969,7 @@
void JSRegExp::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Instance::PrintToJSONStream(stream, ref);
}
@@ -15896,7 +15989,7 @@
void WeakProperty::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Instance::PrintToJSONStream(stream, ref);
}
RawAbstractType* MirrorReference::GetAbstractTypeReferent() const {
@@ -15958,7 +16051,7 @@
void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ Instance::PrintToJSONStream(stream, ref);
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 2334c28..99a9fb5 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1508,13 +1508,6 @@
// Sets function's code and code's function.
void SetCode(const Code& value) const;
- // Detaches code from the function by setting the code to null, and patches
- // the code to be non-entrant.
- void DetachCode() const;
-
- // Reattaches code to the function, and patches the code to be entrant.
- void ReattachCode(const Code& code) const;
-
// Disables optimized code and switches to unoptimized code.
void SwitchToUnoptimizedCode() const;
@@ -2002,6 +1995,9 @@
FINAL_HEAP_OBJECT_IMPLEMENTATION(Function, Object);
friend class Class;
+ // RawFunction::VisitFunctionPointers accesses the private constructor of
+ // Function.
+ friend class RawFunction;
};
@@ -2365,6 +2361,7 @@
RawScript::Kind kind() const {
return static_cast<RawScript::Kind>(raw_ptr()->kind_);
}
+ const char* GetKindAsCString() const;
intptr_t line_offset() const { return raw_ptr()->line_offset_; }
intptr_t col_offset() const { return raw_ptr()->col_offset_; }
@@ -3360,6 +3357,10 @@
FINAL_HEAP_OBJECT_IMPLEMENTATION(Code, Object);
friend class Class;
+
+ // So that the RawFunction pointer visitor can determine whether code the
+ // function points to is optimized.
+ friend class RawFunction;
};
@@ -4476,6 +4477,7 @@
virtual double AsDoubleValue() const;
virtual int64_t AsInt64Value() const;
+ virtual uint32_t AsTruncatedUint32Value() const;
// Returns 0, -1 or 1.
virtual int CompareWith(const Integer& other) const;
@@ -4518,6 +4520,7 @@
virtual double AsDoubleValue() const;
virtual int64_t AsInt64Value() const;
+ virtual uint32_t AsTruncatedUint32Value() const;
virtual int CompareWith(const Integer& other) const;
@@ -4607,6 +4610,7 @@
virtual double AsDoubleValue() const;
virtual int64_t AsInt64Value() const;
+ virtual uint32_t AsTruncatedUint32Value() const;
virtual int CompareWith(const Integer& other) const;
@@ -4644,6 +4648,7 @@
virtual double AsDoubleValue() const;
virtual int64_t AsInt64Value() const;
+ virtual uint32_t AsTruncatedUint32Value() const;
virtual int CompareWith(const Integer& other) const;
@@ -5020,6 +5025,8 @@
friend class TwoByteString;
friend class ExternalOneByteString;
friend class ExternalTwoByteString;
+ // So that the MarkingVisitor can print a debug string from a NoHandleScope.
+ friend class MarkingVisitor;
};
diff --git a/runtime/vm/object_id_ring.cc b/runtime/vm/object_id_ring.cc
index 434463b..5bc056b 100644
--- a/runtime/vm/object_id_ring.cc
+++ b/runtime/vm/object_id_ring.cc
@@ -86,7 +86,7 @@
int32_t ObjectIdRing::AllocateNewId(RawObject* raw_obj) {
- ASSERT(raw_obj->IsHeapObject());
+ // TODO(turnidge): Do not enter Smis into the ObjectIdRing.
int32_t id = NextSerial();
ASSERT(id != kInvalidId);
int32_t cursor = IndexOfId(id);
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 921976a..a4a22a6 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -3518,7 +3518,7 @@
" }\n"
"}";
TestCase::LoadTestScript(kScriptChars, NULL);
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
const String& name = String::Handle(String::New(TestCase::url()));
const Library& lib = Library::Handle(Library::LookupLibrary(name));
EXPECT(!lib.IsNull());
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index e5a96c5..be05e97 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -23,12 +23,14 @@
"Print free list statistics before a GC");
DEFINE_FLAG(bool, print_free_list_after_gc, false,
"Print free list statistics after a GC");
-DEFINE_FLAG(bool, collect_code, false,
+DEFINE_FLAG(bool, collect_code, true,
"Attempt to GC infrequently used code.");
DEFINE_FLAG(int, code_collection_interval_in_us, 30000000,
"Time between attempts to collect unused code.");
DEFINE_FLAG(bool, log_code_drop, false,
"Emit a log message when pointers to unused code are dropped.");
+DEFINE_FLAG(bool, always_drop_code, false,
+ "Always try to drop code if the function's usage counter is >= 0");
HeapPage* HeapPage::Initialize(VirtualMemory* memory, PageType type) {
ASSERT(memory->size() > VirtualMemory::PageSize());
@@ -385,61 +387,21 @@
}
-class CodeDetacherVisitor : public ObjectVisitor {
- public:
- explicit CodeDetacherVisitor(Isolate* isolate) : ObjectVisitor(isolate) { }
-
- virtual void VisitObject(RawObject* obj);
-
- private:
- static bool MayDetachCode(const Function& fn);
- DISALLOW_COPY_AND_ASSIGN(CodeDetacherVisitor);
-};
-
-
-bool CodeDetacherVisitor::MayDetachCode(const Function& fn) {
- return fn.HasCode() && // Not already detached.
- !fn.HasOptimizedCode() &&
- !fn.HasBreakpoint() &&
- (fn.usage_counter() > 0);
-}
-
-
-void CodeDetacherVisitor::VisitObject(RawObject* raw_obj) {
- Isolate* isolate = Isolate::Current();
- HANDLESCOPE(isolate);
- const Object& obj = Object::Handle(raw_obj);
- if (obj.GetClassId() == kFunctionCid) {
- const Function& fn = Function::Cast(obj);
- if (CodeDetacherVisitor::MayDetachCode(fn)) {
- fn.set_usage_counter(fn.usage_counter() / 2);
- if (fn.usage_counter() == 0) {
- if (FLAG_log_code_drop) {
- const String& name = String::Handle(fn.name());
- OS::Print("Detaching code for function %s\n", name.ToCString());
- }
- fn.DetachCode();
- }
- }
- }
-}
-
-
-void PageSpace::TryDetachingCode() {
+bool PageSpace::ShouldCollectCode() {
// Try to collect code if enough time has passed since the last attempt.
const int64_t start = OS::GetCurrentTimeMicros();
const int64_t last_code_collection_in_us =
page_space_controller_.last_code_collection_in_us();
+
if ((start - last_code_collection_in_us) >
- FLAG_code_collection_interval_in_us) {
+ FLAG_code_collection_interval_in_us) {
if (FLAG_log_code_drop) {
OS::Print("Trying to detach code.\n");
}
- Isolate* isolate = Isolate::Current();
- CodeDetacherVisitor code_detacher(isolate);
- heap_->IterateObjects(&code_detacher);
page_space_controller_.set_last_code_collection_in_us(start);
+ return true;
}
+ return false;
}
@@ -448,9 +410,6 @@
ASSERT(!sweeping_);
sweeping_ = true;
Isolate* isolate = Isolate::Current();
- if (FLAG_collect_code) {
- TryDetachingCode();
- }
NoHandleScope no_handles(isolate);
@@ -470,8 +429,9 @@
const int64_t start = OS::GetCurrentTimeMicros();
// Mark all reachable old-gen objects.
+ bool collect_code = FLAG_collect_code && ShouldCollectCode();
GCMarker marker(heap_);
- marker.MarkObjects(isolate, this, invoke_api_callbacks);
+ marker.MarkObjects(isolate, this, invoke_api_callbacks, collect_code);
int64_t mid1 = OS::GetCurrentTimeMicros();
diff --git a/runtime/vm/pages.h b/runtime/vm/pages.h
index 71707a8..ad2e3b0 100644
--- a/runtime/vm/pages.h
+++ b/runtime/vm/pages.h
@@ -13,6 +13,7 @@
DECLARE_FLAG(bool, collect_code);
DECLARE_FLAG(bool, log_code_drop);
+DECLARE_FLAG(bool, always_drop_code);
// Forward declarations.
class Heap;
@@ -199,9 +200,9 @@
RawObject* FindObject(FindObjectVisitor* visitor,
HeapPage::PageType type) const;
- // Runs a visitor that attempts to drop references to code that has not
- // been run in awhile.
- void TryDetachingCode();
+ // Checks if enough time has elapsed since the last attempt to collect
+ // code.
+ bool ShouldCollectCode();
// Collect the garbage in the page space using mark-sweep.
void MarkSweep(bool invoke_api_callbacks);
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index d1f891e..fc9ddbe 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -40,6 +40,7 @@
public:
explicit ParsedFunction(const Function& function)
: function_(function),
+ code_(Code::Handle(function.unoptimized_code())),
node_sequence_(NULL),
instantiator_(NULL),
default_parameter_values_(Array::ZoneHandle()),
@@ -54,6 +55,7 @@
}
const Function& function() const { return function_; }
+ RawCode* code() const { return code_.raw(); }
SequenceNode* node_sequence() const { return node_sequence_; }
void SetNodeSequence(SequenceNode* node_sequence);
@@ -115,6 +117,7 @@
private:
const Function& function_;
+ Code& code_;
SequenceNode* node_sequence_;
AstNode* instantiator_;
Array& default_parameter_values_;
diff --git a/runtime/vm/parser_test.cc b/runtime/vm/parser_test.cc
index 567ea81..3706489 100644
--- a/runtime/vm/parser_test.cc
+++ b/runtime/vm/parser_test.cc
@@ -123,7 +123,7 @@
script.Tokenize(String::Handle(String::New("")));
Parser::ParseCompilationUnit(lib, script);
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
CheckField(lib, "A", "f1", false, false);
CheckField(lib, "A", "f2", false, true);
CheckField(lib, "A", "f3", false, true);
@@ -158,7 +158,7 @@
script.Tokenize(String::Handle(String::New("")));
Parser::ParseCompilationUnit(lib, script);
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
DumpFunction(lib, "A", "foo");
DumpFunction(lib, "A", "bar");
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 95601ba..8de6d12 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -12,6 +12,7 @@
#include "vm/object.h"
#include "vm/os.h"
#include "vm/profiler.h"
+#include "vm/signal_handler.h"
namespace dart {
@@ -54,9 +55,8 @@
// mutex and the profile manager monitor. When an isolate running thread
// (potential signal target) calls into an entry point which acquires
// ProfileManager::monitor_ signal delivery must be blocked. An example is
-// Isolate::SetCurrent which blocks signal delivery while removing the old
-// current isolate from the scheduled list and adding the new current isolate
-// to the scheduled list.
+// ProfileManager::ScheduleIsolate which blocks signal delivery while removing
+// the scheduling the isolate.
//
// Notes on stack frame walking:
@@ -68,27 +68,51 @@
// fail (sometimes leading to a crash).
//
-
DEFINE_FLAG(bool, profile, false, "Enable Sampling Profiler");
+DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates.");
bool ProfilerManager::initialized_ = false;
bool ProfilerManager::shutdown_ = false;
+bool ProfilerManager::thread_running_ = false;
Monitor* ProfilerManager::monitor_ = NULL;
+Monitor* ProfilerManager::start_stop_monitor_ = NULL;
Isolate** ProfilerManager::isolates_ = NULL;
intptr_t ProfilerManager::isolates_capacity_ = 0;
intptr_t ProfilerManager::isolates_size_ = 0;
void ProfilerManager::InitOnce() {
+#if defined(USING_SIMULATOR)
+ // Force disable of profiling on simulator.
+ FLAG_profile = false;
+#endif
+#if defined(TARGET_OS_WINDOWS)
+ // Force disable of profiling on Windows.
+ FLAG_profile = false;
+#endif
if (!FLAG_profile) {
return;
}
NativeSymbolResolver::InitOnce();
ASSERT(!initialized_);
monitor_ = new Monitor();
+ start_stop_monitor_ = new Monitor();
initialized_ = true;
ResizeIsolates(16);
- Thread::Start(ThreadMain, 0);
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager starting up.\n");
+ }
+ {
+ ScopedMonitor startup_lock(start_stop_monitor_);
+ Thread::Start(ThreadMain, 0);
+ while (!thread_running_) {
+ // Wait until profiler thread has started up.
+ startup_lock.Wait();
+ }
+ }
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager running.\n");
+ }
}
@@ -97,18 +121,33 @@
return;
}
ASSERT(initialized_);
- ScopedMonitor lock(monitor_);
- shutdown_ = true;
- for (intptr_t i = 0; i < isolates_size_; i++) {
- Isolate* isolate = isolates_[i];
- ASSERT(isolate != NULL);
- FreeIsolateProfilingData(isolate);
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager shutting down.\n");
}
- isolates_size_ = 0;
- free(isolates_);
- isolates_ = NULL;
- lock.Notify();
+ intptr_t size_at_shutdown = 0;
+ {
+ ScopedSignalBlocker ssb;
+ {
+ ScopedMonitor lock(monitor_);
+ shutdown_ = true;
+ size_at_shutdown = isolates_size_;
+ isolates_size_ = 0;
+ free(isolates_);
+ isolates_ = NULL;
+ lock.Notify();
+ }
+ }
NativeSymbolResolver::ShutdownOnce();
+ {
+ ScopedMonitor shutdown_lock(start_stop_monitor_);
+ while (thread_running_) {
+ // Wait until profiler thread has exited.
+ shutdown_lock.Wait();
+ }
+ }
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager shut down (%" Pd ").\n", size_at_shutdown);
+ }
}
@@ -117,12 +156,25 @@
return;
}
ASSERT(isolate != NULL);
- ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
- SampleBuffer* sample_buffer = new SampleBuffer();
- IsolateProfilerData* profiler_data =
- new IsolateProfilerData(isolate, sample_buffer);
- profiler_data->set_sample_interval_micros(1000);
- isolate->set_profiler_data(profiler_data);
+ {
+ ScopedSignalBlocker ssb;
+ {
+ ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
+ SampleBuffer* sample_buffer = new SampleBuffer();
+ ASSERT(sample_buffer != NULL);
+ IsolateProfilerData* profiler_data =
+ new IsolateProfilerData(isolate, sample_buffer);
+ ASSERT(profiler_data != NULL);
+ profiler_data->set_sample_interval_micros(1000);
+ isolate->set_profiler_data(profiler_data);
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager Setup Isolate %p %s %p\n",
+ isolate,
+ isolate->name(),
+ reinterpret_cast<void*>(Thread::GetCurrentThreadId()));
+ }
+ }
+ }
}
@@ -136,8 +188,15 @@
isolate->set_profiler_data(NULL);
SampleBuffer* sample_buffer = profiler_data->sample_buffer();
ASSERT(sample_buffer != NULL);
+ profiler_data->set_sample_buffer(NULL);
delete sample_buffer;
delete profiler_data;
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager Shutdown Isolate %p %s %p\n",
+ isolate,
+ isolate->name(),
+ reinterpret_cast<void*>(Thread::GetCurrentThreadId()));
+ }
}
@@ -146,26 +205,55 @@
if (!FLAG_profile) {
return;
}
- FreeIsolateProfilingData(isolate);
+ {
+ ScopedSignalBlocker ssb;
+ FreeIsolateProfilingData(isolate);
+ }
}
-void ProfilerManager::ScheduleIsolate(Isolate* isolate) {
+void ProfilerManager::ScheduleIsolateHelper(Isolate* isolate) {
+ ScopedMonitor lock(monitor_);
+ {
+ if (shutdown_) {
+ // Shutdown.
+ return;
+ }
+ ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
+ IsolateProfilerData* profiler_data = isolate->profiler_data();
+ if (profiler_data == NULL) {
+ return;
+ }
+ profiler_data->Scheduled(OS::GetCurrentTimeMicros(),
+ Thread::GetCurrentThreadId());
+ }
+ intptr_t i = FindIsolate(isolate);
+ if (i >= 0) {
+ // Already scheduled.
+ return;
+ }
+ AddIsolate(isolate);
+ lock.Notify();
+}
+
+
+void ProfilerManager::ScheduleIsolate(Isolate* isolate, bool inside_signal) {
if (!FLAG_profile) {
return;
}
ASSERT(initialized_);
ASSERT(isolate != NULL);
- ScopedMonitor lock(monitor_);
- ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
- IsolateProfilerData* profiler_data = isolate->profiler_data();
- if (profiler_data == NULL) {
- return;
+ if (!inside_signal) {
+ ScopedSignalBlocker ssb;
+ {
+ ScheduleIsolateHelper(isolate);
+ }
+ } else {
+ // Do not need a signal blocker inside a signal handler.
+ {
+ ScheduleIsolateHelper(isolate);
+ }
}
- profiler_data->Scheduled(OS::GetCurrentTimeMicros(),
- Thread::GetCurrentThreadId());
- AddIsolate(isolate);
- lock.Notify();
}
@@ -175,20 +263,30 @@
}
ASSERT(initialized_);
ASSERT(isolate != NULL);
- ScopedMonitor lock(monitor_);
- intptr_t i = FindIsolate(isolate);
- if (i < 0) {
- // Not scheduled.
- return;
- }
{
- ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
- IsolateProfilerData* profiler_data = isolate->profiler_data();
- ASSERT(profiler_data != NULL);
- profiler_data->Descheduled();
+ ScopedSignalBlocker ssb;
+ {
+ ScopedMonitor lock(monitor_);
+ if (shutdown_) {
+ // Shutdown.
+ return;
+ }
+ intptr_t i = FindIsolate(isolate);
+ if (i < 0) {
+ // Not scheduled.
+ return;
+ }
+ {
+ ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
+ IsolateProfilerData* profiler_data = isolate->profiler_data();
+ if (profiler_data != NULL) {
+ profiler_data->Descheduled();
+ }
+ }
+ RemoveIsolate(i);
+ lock.Notify();
+ }
}
- RemoveIsolate(i);
- lock.Notify();
}
@@ -212,11 +310,11 @@
void ProfilerManager::AddIsolate(Isolate* isolate) {
+ // Must be called with monitor_ locked.
if (isolates_ == NULL) {
// We are shutting down.
return;
}
- // Must be called with monitor_ locked.
if (isolates_size_ == isolates_capacity_) {
ResizeIsolates(isolates_capacity_ == 0 ? 16 : isolates_capacity_ * 2);
}
@@ -227,6 +325,10 @@
intptr_t ProfilerManager::FindIsolate(Isolate* isolate) {
// Must be called with monitor_ locked.
+ if (isolates_ == NULL) {
+ // We are shutting down.
+ return -1;
+ }
for (intptr_t i = 0; i < isolates_size_; i++) {
if (isolates_[i] == isolate) {
return i;
@@ -238,6 +340,10 @@
void ProfilerManager::RemoveIsolate(intptr_t i) {
// Must be called with monitor_ locked.
+ if (isolates_ == NULL) {
+ // We are shutting down.
+ return;
+ }
ASSERT(i < isolates_size_);
intptr_t last = isolates_size_ - 1;
if (i != last) {
@@ -280,139 +386,141 @@
void ProfilerManager::WriteTracing(Isolate* isolate, const char* name,
Dart_Port port) {
ASSERT(isolate == Isolate::Current());
- ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
- IsolateProfilerData* profiler_data = isolate->profiler_data();
- if (profiler_data == NULL) {
- return;
- }
- SampleBuffer* sample_buffer = profiler_data->sample_buffer();
- ASSERT(sample_buffer != NULL);
- JSONStream stream(10 * MB);
- intptr_t tid = reinterpret_cast<intptr_t>(sample_buffer);
- intptr_t pid = 1;
{
- JSONArray events(&stream);
+ ScopedSignalBlocker ssb;
{
- JSONObject thread_name(&events);
- thread_name.AddProperty("name", "thread_name");
- thread_name.AddProperty("ph", "M");
- thread_name.AddProperty("tid", tid);
- thread_name.AddProperty("pid", pid);
- {
- JSONObject args(&thread_name, "args");
- args.AddProperty("name", name);
+ ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
+ IsolateProfilerData* profiler_data = isolate->profiler_data();
+ if (profiler_data == NULL) {
+ return;
}
- }
- {
- JSONObject process_name(&events);
- process_name.AddProperty("name", "process_name");
- process_name.AddProperty("ph", "M");
- process_name.AddProperty("tid", tid);
- process_name.AddProperty("pid", pid);
+ SampleBuffer* sample_buffer = profiler_data->sample_buffer();
+ ASSERT(sample_buffer != NULL);
+ JSONStream stream(10 * MB);
+ intptr_t tid = reinterpret_cast<intptr_t>(sample_buffer);
+ intptr_t pid = 1;
{
- JSONObject args(&process_name, "args");
- args.AddProperty("name", "Dart VM");
- }
- }
- uint64_t last_time = 0;
- for (Sample* i = sample_buffer->FirstSample();
- i != sample_buffer->LastSample();
- i = sample_buffer->NextSample(i)) {
- if (last_time == 0) {
- last_time = i->timestamp;
- }
- intptr_t delta = i->timestamp - last_time;
- {
- double percentage = static_cast<double>(i->cpu_usage) /
- static_cast<double>(delta) * 100.0;
- if (percentage != percentage) {
- percentage = 0.0;
- }
- percentage = percentage < 0.0 ? 0.0 : percentage;
- percentage = percentage > 100.0 ? 100.0 : percentage;
+ JSONArray events(&stream);
{
- JSONObject cpu_usage(&events);
- cpu_usage.AddProperty("name", "CPU Usage");
- cpu_usage.AddProperty("ph", "C");
- cpu_usage.AddProperty("tid", tid);
- cpu_usage.AddProperty("pid", pid);
- cpu_usage.AddProperty("ts", static_cast<double>(last_time));
+ JSONObject thread_name(&events);
+ thread_name.AddProperty("name", "thread_name");
+ thread_name.AddProperty("ph", "M");
+ thread_name.AddProperty("tid", tid);
+ thread_name.AddProperty("pid", pid);
{
- JSONObject args(&cpu_usage, "args");
- args.AddProperty("CPU", percentage);
+ JSONObject args(&thread_name, "args");
+ args.AddProperty("name", name);
}
}
{
- JSONObject cpu_usage(&events);
- cpu_usage.AddProperty("name", "CPU Usage");
- cpu_usage.AddProperty("ph", "C");
- cpu_usage.AddProperty("tid", tid);
- cpu_usage.AddProperty("pid", pid);
- cpu_usage.AddProperty("ts", static_cast<double>(i->timestamp));
+ JSONObject process_name(&events);
+ process_name.AddProperty("name", "process_name");
+ process_name.AddProperty("ph", "M");
+ process_name.AddProperty("tid", tid);
+ process_name.AddProperty("pid", pid);
{
- JSONObject args(&cpu_usage, "args");
- args.AddProperty("CPU", percentage);
+ JSONObject args(&process_name, "args");
+ args.AddProperty("name", "Dart VM");
}
}
- }
- for (int j = 0; j < Sample::kNumStackFrames; j++) {
- if (i->pcs[j] == 0) {
- continue;
- }
- bool native_symbol = false;
- char* symbol_name = FindSymbolName(i->pcs[j], &native_symbol);
- {
- JSONObject begin(&events);
- begin.AddProperty("ph", "B");
- begin.AddProperty("tid", tid);
- begin.AddProperty("pid", pid);
- begin.AddProperty("name", symbol_name);
- begin.AddProperty("ts", static_cast<double>(last_time));
- }
- if (native_symbol) {
- NativeSymbolResolver::FreeSymbolName(symbol_name);
+ uint64_t last_time = 0;
+ for (Sample* i = sample_buffer->FirstSample();
+ i != sample_buffer->LastSample();
+ i = sample_buffer->NextSample(i)) {
+ if (last_time == 0) {
+ last_time = i->timestamp;
+ }
+ intptr_t delta = i->timestamp - last_time;
+ {
+ double percentage = static_cast<double>(i->cpu_usage) /
+ static_cast<double>(delta) * 100.0;
+ if (percentage != percentage) {
+ percentage = 0.0;
+ }
+ percentage = percentage < 0.0 ? 0.0 : percentage;
+ percentage = percentage > 100.0 ? 100.0 : percentage;
+ {
+ JSONObject cpu_usage(&events);
+ cpu_usage.AddProperty("name", "CPU Usage");
+ cpu_usage.AddProperty("ph", "C");
+ cpu_usage.AddProperty("tid", tid);
+ cpu_usage.AddProperty("pid", pid);
+ cpu_usage.AddProperty("ts", static_cast<double>(last_time));
+ {
+ JSONObject args(&cpu_usage, "args");
+ args.AddProperty("CPU", percentage);
+ }
+ }
+ {
+ JSONObject cpu_usage(&events);
+ cpu_usage.AddProperty("name", "CPU Usage");
+ cpu_usage.AddProperty("ph", "C");
+ cpu_usage.AddProperty("tid", tid);
+ cpu_usage.AddProperty("pid", pid);
+ cpu_usage.AddProperty("ts", static_cast<double>(i->timestamp));
+ {
+ JSONObject args(&cpu_usage, "args");
+ args.AddProperty("CPU", percentage);
+ }
+ }
+ }
+ for (int j = 0; j < Sample::kNumStackFrames; j++) {
+ if (i->pcs[j] == 0) {
+ continue;
+ }
+ bool native_symbol = false;
+ char* symbol_name = FindSymbolName(i->pcs[j], &native_symbol);
+ {
+ JSONObject begin(&events);
+ begin.AddProperty("ph", "B");
+ begin.AddProperty("tid", tid);
+ begin.AddProperty("pid", pid);
+ begin.AddProperty("name", symbol_name);
+ begin.AddProperty("ts", static_cast<double>(last_time));
+ }
+ if (native_symbol) {
+ NativeSymbolResolver::FreeSymbolName(symbol_name);
+ }
+ }
+ for (int j = Sample::kNumStackFrames-1; j >= 0; j--) {
+ if (i->pcs[j] == 0) {
+ continue;
+ }
+ bool native_symbol = false;
+ char* symbol_name = FindSymbolName(i->pcs[j], &native_symbol);
+ {
+ JSONObject end(&events);
+ end.AddProperty("ph", "E");
+ end.AddProperty("tid", tid);
+ end.AddProperty("pid", pid);
+ end.AddProperty("name", symbol_name);
+ end.AddProperty("ts", static_cast<double>(i->timestamp));
+ }
+ if (native_symbol) {
+ NativeSymbolResolver::FreeSymbolName(symbol_name);
+ }
+ }
+ last_time = i->timestamp;
}
}
- for (int j = Sample::kNumStackFrames-1; j >= 0; j--) {
- if (i->pcs[j] == 0) {
- continue;
- }
- bool native_symbol = false;
- char* symbol_name = FindSymbolName(i->pcs[j], &native_symbol);
- {
- JSONObject end(&events);
- end.AddProperty("ph", "E");
- end.AddProperty("tid", tid);
- end.AddProperty("pid", pid);
- end.AddProperty("name", symbol_name);
- end.AddProperty("ts", static_cast<double>(i->timestamp));
- }
- if (native_symbol) {
- NativeSymbolResolver::FreeSymbolName(symbol_name);
- }
- }
- last_time = i->timestamp;
+ char fname[1024];
+ #if defined(TARGET_OS_WINDOWS)
+ snprintf(fname, sizeof(fname)-1, "c:\\tmp\\isolate-%d.prof",
+ static_cast<int>(port));
+ #else
+ snprintf(fname, sizeof(fname)-1, "/tmp/isolate-%d.prof",
+ static_cast<int>(port));
+ #endif
+ printf("%s\n", fname);
+ FILE* f = fopen(fname, "wb");
+ ASSERT(f != NULL);
+ fputs(stream.ToCString(), f);
+ fclose(f);
}
}
- char fname[1024];
-#if defined(TARGET_OS_WINDOWS)
- snprintf(fname, sizeof(fname)-1, "c:\\tmp\\isolate-%d.prof",
- static_cast<int>(port));
-#else
- snprintf(fname, sizeof(fname)-1, "/tmp/isolate-%d.prof",
- static_cast<int>(port));
-#endif
- printf("%s\n", fname);
- FILE* f = fopen(fname, "wb");
- ASSERT(f != NULL);
- fputs(stream.ToCString(), f);
- fclose(f);
}
-
-
-
IsolateProfilerData::IsolateProfilerData(Isolate* isolate,
SampleBuffer* sample_buffer) {
isolate_ = isolate;
@@ -434,8 +542,8 @@
void IsolateProfilerData::Scheduled(int64_t current_time, ThreadId thread_id) {
timer_expiration_micros_ = current_time + sample_interval_micros_;
- Thread::GetThreadCpuUsage(thread_id, &cpu_usage_);
thread_id_ = thread_id;
+ Thread::GetThreadCpuUsage(thread_id_, &cpu_usage_);
}
@@ -445,7 +553,6 @@
// isolate again.
cpu_usage_ = kDescheduledCpuUsage;
timer_expiration_micros_ = kNoExpirationTime;
- thread_id_ = 0;
Sample* sample = sample_buffer_->ReserveSample();
ASSERT(sample != NULL);
sample->timestamp = OS::GetCurrentTimeMicros();
@@ -480,16 +587,22 @@
if (samples_ != NULL) {
free(samples_);
samples_ = NULL;
+ start_ = 0;
+ end_ = 0;
+ capacity_ = 0;
}
}
Sample* SampleBuffer::ReserveSample() {
+ ASSERT(samples_ != NULL);
intptr_t index = end_;
end_ = WrapIncrement(end_);
if (end_ == start_) {
start_ = WrapIncrement(start_);
}
+ ASSERT(index >= 0);
+ ASSERT(index < capacity_);
// Reset.
samples_[index] = Sample();
return &samples_[index];
@@ -539,6 +652,7 @@
int ProfilerSampleStackWalker::walk() {
uword* pc = reinterpret_cast<uword*>(original_pc_);
+#if defined(WALK_STACK)
uword* fp = reinterpret_cast<uword*>(original_fp_);
uword* previous_fp = fp;
if (original_sp_ < lower_bound_) {
@@ -563,6 +677,10 @@
lower_bound_ = reinterpret_cast<uintptr_t>(fp);
}
return i;
+#else
+ sample_->pcs[0] = reinterpret_cast<uintptr_t>(pc);
+ return 0;
+#endif
}
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index ba25c43..bec51e6 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -24,7 +24,7 @@
static void SetupIsolateForProfiling(Isolate* isolate);
static void ShutdownIsolateForProfiling(Isolate* isolate);
- static void ScheduleIsolate(Isolate* isolate);
+ static void ScheduleIsolate(Isolate* isolate, bool inside_signal = false);
static void DescheduleIsolate(Isolate* isolate);
static void PrintToJSONStream(Isolate* isolate, JSONStream* stream);
@@ -35,12 +35,15 @@
static const intptr_t kMaxProfiledIsolates = 4096;
static bool initialized_;
static bool shutdown_;
+ static bool thread_running_;
static Monitor* monitor_;
+ static Monitor* start_stop_monitor_;
static Isolate** isolates_;
static intptr_t isolates_capacity_;
static intptr_t isolates_size_;
+ static void ScheduleIsolateHelper(Isolate* isolate);
static void ResizeIsolates(intptr_t new_capacity);
static void AddIsolate(Isolate* isolate);
static intptr_t FindIsolate(Isolate* isolate);
@@ -108,6 +111,10 @@
SampleBuffer* sample_buffer() const { return sample_buffer_; }
+ void set_sample_buffer(SampleBuffer* sample_buffer) {
+ sample_buffer_ = sample_buffer;
+ }
+
private:
int64_t last_sampled_micros_;
int64_t timer_expiration_micros_;
@@ -142,7 +149,7 @@
// Ring buffer of samples. One per isolate.
class SampleBuffer {
public:
- static const intptr_t kDefaultBufferCapacity = 1000000;
+ static const intptr_t kDefaultBufferCapacity = 120000; // 2 minutes @ 1000hz.
explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity);
~SampleBuffer();
diff --git a/runtime/vm/profiler_android.cc b/runtime/vm/profiler_android.cc
index d8d6747..f1d5704 100644
--- a/runtime/vm/profiler_android.cc
+++ b/runtime/vm/profiler_android.cc
@@ -13,7 +13,7 @@
namespace dart {
DECLARE_FLAG(bool, profile);
-
+DECLARE_FLAG(bool, trace_profiled_isolates);
static void ProfileSignalAction(int signal, siginfo_t* info, void* context_) {
if (signal != SIGPROF) {
@@ -28,14 +28,20 @@
// Thread owns isolate profiler data mutex.
ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
IsolateProfilerData* profiler_data = isolate->profiler_data();
- if (profiler_data == NULL) {
+ if ((profiler_data == NULL) || !profiler_data->CanExpire() ||
+ (profiler_data->sample_buffer() == NULL)) {
+ // Descheduled.
return;
}
+ if (profiler_data->thread_id() == Thread::GetCurrentThreadId()) {
+ // Still scheduled on this thread.
+ // TODO(johnmccutchan): Perform sample on Android.
+ }
}
// Thread owns no profiler locks at this point.
// This call will acquire both ProfilerManager::monitor and the
// isolate's profiler data mutex.
- ProfilerManager::ScheduleIsolate(isolate);
+ ProfilerManager::ScheduleIsolate(isolate, true);
}
@@ -50,6 +56,12 @@
Isolate* isolate = isolates_[i];
ScopedMutex isolate_lock(isolate->profiler_data_mutex());
IsolateProfilerData* profiler_data = isolate->profiler_data();
+ if (profiler_data == NULL) {
+ // Isolate has been shutdown for profiling.
+ RemoveIsolate(i);
+ // Remove moves the last element into i, do not increment i.
+ continue;
+ }
ASSERT(profiler_data != NULL);
if (profiler_data->ShouldSample(current_time)) {
pthread_kill(profiler_data->thread_id(), SIGPROF);
@@ -85,12 +97,30 @@
ASSERT(initialized_);
ASSERT(FLAG_profile);
SignalHandler::Install(ProfileSignalAction);
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager Android ready.\n");
+ }
+ {
+ // Signal to main thread we are ready.
+ ScopedMonitor startup_lock(start_stop_monitor_);
+ thread_running_ = true;
+ startup_lock.Notify();
+ }
ScopedMonitor lock(monitor_);
while (!shutdown_) {
int64_t current_time = OS::GetCurrentTimeMicros();
int64_t next_sample = SampleAndRescheduleIsolates(current_time);
lock.WaitMicros(next_sample);
}
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager Android exiting.\n");
+ }
+ {
+ // Signal to main thread we are exiting.
+ ScopedMonitor shutdown_lock(start_stop_monitor_);
+ thread_running_ = false;
+ shutdown_lock.Notify();
+ }
}
diff --git a/runtime/vm/profiler_linux.cc b/runtime/vm/profiler_linux.cc
index a58821d..6489a43 100644
--- a/runtime/vm/profiler_linux.cc
+++ b/runtime/vm/profiler_linux.cc
@@ -13,6 +13,7 @@
namespace dart {
DECLARE_FLAG(bool, profile);
+DECLARE_FLAG(bool, trace_profiled_isolates);
static void CollectSample(IsolateProfilerData* profiler_data,
uintptr_t pc,
@@ -52,24 +53,28 @@
// Thread owns isolate profiler data mutex.
ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
IsolateProfilerData* profiler_data = isolate->profiler_data();
- if (profiler_data == NULL) {
+ if ((profiler_data == NULL) || !profiler_data->CanExpire() ||
+ (profiler_data->sample_buffer() == NULL)) {
+ // Descheduled.
return;
}
-
- uintptr_t stack_lower = 0;
- uintptr_t stack_upper = 0;
- isolate->GetStackBounds(&stack_lower, &stack_upper);
- uintptr_t PC = SignalHandler::GetProgramCounter(mcontext);
- uintptr_t FP = SignalHandler::GetFramePointer(mcontext);
- uintptr_t SP = SignalHandler::GetStackPointer(mcontext);
- int64_t sample_time = OS::GetCurrentTimeMicros();
- profiler_data->SampledAt(sample_time);
- CollectSample(profiler_data, PC, FP, SP, stack_lower, stack_upper);
+ if (profiler_data->thread_id() == Thread::GetCurrentThreadId()) {
+ // Still scheduled on this thread.
+ uintptr_t stack_lower = 0;
+ uintptr_t stack_upper = 0;
+ isolate->GetStackBounds(&stack_lower, &stack_upper);
+ uintptr_t PC = SignalHandler::GetProgramCounter(mcontext);
+ uintptr_t FP = SignalHandler::GetFramePointer(mcontext);
+ uintptr_t SP = SignalHandler::GetStackPointer(mcontext);
+ int64_t sample_time = OS::GetCurrentTimeMicros();
+ profiler_data->SampledAt(sample_time);
+ CollectSample(profiler_data, PC, FP, SP, stack_lower, stack_upper);
+ }
}
// Thread owns no profiler locks at this point.
// This call will acquire both ProfilerManager::monitor and the
// isolate's profiler data mutex.
- ProfilerManager::ScheduleIsolate(isolate);
+ ProfilerManager::ScheduleIsolate(isolate, true);
}
@@ -84,6 +89,12 @@
Isolate* isolate = isolates_[i];
ScopedMutex isolate_lock(isolate->profiler_data_mutex());
IsolateProfilerData* profiler_data = isolate->profiler_data();
+ if (profiler_data == NULL) {
+ // Isolate has been shutdown for profiling.
+ RemoveIsolate(i);
+ // Remove moves the last element into i, do not increment i.
+ continue;
+ }
ASSERT(profiler_data != NULL);
if (profiler_data->ShouldSample(current_time)) {
pthread_kill(profiler_data->thread_id(), SIGPROF);
@@ -119,12 +130,30 @@
ASSERT(initialized_);
ASSERT(FLAG_profile);
SignalHandler::Install(ProfileSignalAction);
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager Linux ready.\n");
+ }
+ {
+ // Signal to main thread we are ready.
+ ScopedMonitor startup_lock(start_stop_monitor_);
+ thread_running_ = true;
+ startup_lock.Notify();
+ }
ScopedMonitor lock(monitor_);
while (!shutdown_) {
int64_t current_time = OS::GetCurrentTimeMicros();
int64_t next_sample = SampleAndRescheduleIsolates(current_time);
lock.WaitMicros(next_sample);
}
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager Linux exiting.\n");
+ }
+ {
+ // Signal to main thread we are exiting.
+ ScopedMonitor shutdown_lock(start_stop_monitor_);
+ thread_running_ = false;
+ shutdown_lock.Notify();
+ }
}
diff --git a/runtime/vm/profiler_macos.cc b/runtime/vm/profiler_macos.cc
index 2cb31c6..e1ae399 100644
--- a/runtime/vm/profiler_macos.cc
+++ b/runtime/vm/profiler_macos.cc
@@ -13,6 +13,7 @@
namespace dart {
DECLARE_FLAG(bool, profile);
+DECLARE_FLAG(bool, trace_profiled_isolates);
static void CollectSample(IsolateProfilerData* profiler_data,
uintptr_t pc,
@@ -52,24 +53,28 @@
// Thread owns isolate profiler data mutex.
ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
IsolateProfilerData* profiler_data = isolate->profiler_data();
- if (profiler_data == NULL) {
+ if ((profiler_data == NULL) || !profiler_data->CanExpire() ||
+ (profiler_data->sample_buffer() == NULL)) {
+ // Descheduled.
return;
}
-
- uintptr_t stack_lower = 0;
- uintptr_t stack_upper = 0;
- isolate->GetStackBounds(&stack_lower, &stack_upper);
- uintptr_t PC = SignalHandler::GetProgramCounter(mcontext);
- uintptr_t FP = SignalHandler::GetFramePointer(mcontext);
- uintptr_t SP = SignalHandler::GetStackPointer(mcontext);
- int64_t sample_time = OS::GetCurrentTimeMicros();
- profiler_data->SampledAt(sample_time);
- CollectSample(profiler_data, PC, FP, SP, stack_lower, stack_upper);
+ if (profiler_data->thread_id() == Thread::GetCurrentThreadId()) {
+ // Still scheduled on this thread.
+ uintptr_t stack_lower = 0;
+ uintptr_t stack_upper = 0;
+ isolate->GetStackBounds(&stack_lower, &stack_upper);
+ uintptr_t PC = SignalHandler::GetProgramCounter(mcontext);
+ uintptr_t FP = SignalHandler::GetFramePointer(mcontext);
+ uintptr_t SP = SignalHandler::GetStackPointer(mcontext);
+ int64_t sample_time = OS::GetCurrentTimeMicros();
+ profiler_data->SampledAt(sample_time);
+ CollectSample(profiler_data, PC, FP, SP, stack_lower, stack_upper);
+ }
}
// Thread owns no profiler locks at this point.
// This call will acquire both ProfilerManager::monitor and the
// isolate's profiler data mutex.
- ProfilerManager::ScheduleIsolate(isolate);
+ ProfilerManager::ScheduleIsolate(isolate, true);
}
@@ -84,6 +89,12 @@
Isolate* isolate = isolates_[i];
ScopedMutex isolate_lock(isolate->profiler_data_mutex());
IsolateProfilerData* profiler_data = isolate->profiler_data();
+ if (profiler_data == NULL) {
+ // Isolate has been shutdown for profiling.
+ RemoveIsolate(i);
+ // Remove moves the last element into i, do not increment i.
+ continue;
+ }
ASSERT(profiler_data != NULL);
if (profiler_data->ShouldSample(current_time)) {
pthread_kill(profiler_data->thread_id(), SIGPROF);
@@ -119,12 +130,30 @@
ASSERT(initialized_);
ASSERT(FLAG_profile);
SignalHandler::Install(ProfileSignalAction);
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager MacOS ready.\n");
+ }
+ {
+ // Signal to main thread we are ready.
+ ScopedMonitor startup_lock(start_stop_monitor_);
+ thread_running_ = true;
+ startup_lock.Notify();
+ }
ScopedMonitor lock(monitor_);
while (!shutdown_) {
int64_t current_time = OS::GetCurrentTimeMicros();
int64_t next_sample = SampleAndRescheduleIsolates(current_time);
lock.WaitMicros(next_sample);
}
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager MacOS exiting.\n");
+ }
+ {
+ // Signal to main thread we are exiting.
+ ScopedMonitor shutdown_lock(start_stop_monitor_);
+ thread_running_ = false;
+ shutdown_lock.Notify();
+ }
}
diff --git a/runtime/vm/profiler_win.cc b/runtime/vm/profiler_win.cc
index 61aa28b..3bc9e41 100644
--- a/runtime/vm/profiler_win.cc
+++ b/runtime/vm/profiler_win.cc
@@ -13,6 +13,7 @@
#define kThreadError -1
DECLARE_FLAG(bool, profile);
+DECLARE_FLAG(bool, trace_profiled_isolates);
static void CollectSample(IsolateProfilerData* profiler_data,
uintptr_t pc,
@@ -20,7 +21,9 @@
uintptr_t stack_lower,
uintptr_t stack_upper) {
uintptr_t sp = stack_lower;
+ ASSERT(profiler_data != NULL);
SampleBuffer* sample_buffer = profiler_data->sample_buffer();
+ ASSERT(sample_buffer != NULL);
Sample* sample = sample_buffer->ReserveSample();
ASSERT(sample != NULL);
sample->timestamp = OS::GetCurrentTimeMicros();
@@ -101,7 +104,11 @@
Isolate* isolate = isolates_[i];
ScopedMutex isolate_lock(isolate->profiler_data_mutex());
IsolateProfilerData* profiler_data = isolate->profiler_data();
- ASSERT(profiler_data != NULL);
+ if ((profiler_data == NULL) || !profiler_data->CanExpire() ||
+ (profiler_data->sample_buffer() == NULL)) {
+ // Descheduled.
+ continue;
+ }
if (profiler_data->ShouldSample(current_time)) {
SuspendAndSample(isolate, profiler_data);
Reschedule(profiler_data);
@@ -132,12 +139,30 @@
void ProfilerManager::ThreadMain(uword parameters) {
ASSERT(initialized_);
ASSERT(FLAG_profile);
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager Windows ready.\n");
+ }
+ {
+ // Signal to main thread we are ready.
+ ScopedMonitor startup_lock(start_stop_monitor_);
+ thread_running_ = true;
+ startup_lock.Notify();
+ }
ScopedMonitor lock(monitor_);
while (!shutdown_) {
int64_t current_time = OS::GetCurrentTimeMicros();
int64_t next_sample = SampleAndRescheduleIsolates(current_time);
lock.WaitMicros(next_sample);
}
+ if (FLAG_trace_profiled_isolates) {
+ OS::Print("ProfilerManager Windows exiting.\n");
+ }
+ {
+ // Signal to main thread we are exiting.
+ ScopedMonitor shutdown_lock(start_stop_monitor_);
+ thread_running_ = false;
+ shutdown_lock.Notify();
+ }
}
} // namespace dart
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 361006f..c425df7 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -366,9 +366,44 @@
}
+bool RawFunction::SkipCode(RawFunction* raw_fun) {
+ // NOTE: This code runs while GC is in progress and runs within
+ // a NoHandleScope block. Hence it is not okay to use regular Zone or
+ // Scope handles. We use direct stack handles, and so the raw pointers in
+ // these handles are not traversed. The use of handles is mainly to
+ // be able to reuse the handle based code and avoid having to add
+ // helper functions to the raw object interface.
+ Function fn;
+ fn = raw_fun;
+
+ Code code;
+ code = fn.CurrentCode();
+
+ if (!code.IsNull() && // The function may not have code.
+ !code.is_optimized() &&
+ (fn.CurrentCode() == fn.unoptimized_code()) &&
+ !fn.HasBreakpoint() &&
+ (fn.usage_counter() >= 0)) {
+ fn.set_usage_counter(fn.usage_counter() / 2);
+ if (FLAG_always_drop_code || (fn.usage_counter() == 0)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
intptr_t RawFunction::VisitFunctionPointers(RawFunction* raw_obj,
ObjectPointerVisitor* visitor) {
- visitor->VisitPointers(raw_obj->from(), raw_obj->to());
+ if (visitor->visit_function_code() ||
+ !RawFunction::SkipCode(raw_obj)) {
+ visitor->VisitPointers(raw_obj->from(), raw_obj->to());
+ } else {
+ GrowableArray<RawFunction*>* sfga = visitor->skipped_code_functions();
+ ASSERT(sfga != NULL);
+ sfga->Add(raw_obj);
+ visitor->VisitPointers(raw_obj->from(), raw_obj->to_no_code());
+ }
return Function::InstanceSize();
}
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 89f4690..dce7cbf 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -610,8 +610,11 @@
};
private:
+ // So that the MarkingVisitor::DetachCode can null out the code fields.
+ friend class MarkingVisitor;
friend class Class;
RAW_HEAP_OBJECT_IMPLEMENTATION(Function);
+ static bool SkipCode(RawFunction* raw_fun);
RawObject** from() { return reinterpret_cast<RawObject**>(&ptr()->name_); }
RawString* name_;
@@ -620,10 +623,13 @@
RawAbstractType* result_type_;
RawArray* parameter_types_;
RawArray* parameter_names_;
+ RawObject* data_; // Additional data specific to the function kind.
RawCode* code_; // Compiled code for the function.
RawCode* unoptimized_code_; // Unoptimized code, keep it after optimization.
- RawObject* data_; // Additional data specific to the function kind.
RawObject** to() {
+ return reinterpret_cast<RawObject**>(&ptr()->unoptimized_code_);
+ }
+ RawObject** to_no_code() {
return reinterpret_cast<RawObject**>(&ptr()->data_);
}
diff --git a/runtime/vm/resolver_test.cc b/runtime/vm/resolver_test.cc
index c2997a6..f06e42f 100644
--- a/runtime/vm/resolver_test.cc
+++ b/runtime/vm/resolver_test.cc
@@ -46,7 +46,7 @@
Library& lib = Library::Handle(Library::New(lib_name));
lib.Register();
EXPECT(CompilerTest::TestCompileScript(lib, script));
- EXPECT(ClassFinalizer::FinalizeTypeHierarchy());
+ EXPECT(ClassFinalizer::ProcessPendingClasses());
}
diff --git a/runtime/vm/signal_handler_linux.cc b/runtime/vm/signal_handler_linux.cc
index d4021cf..4345dd4 100644
--- a/runtime/vm/signal_handler_linux.cc
+++ b/runtime/vm/signal_handler_linux.cc
@@ -20,6 +20,8 @@
pc = static_cast<uintptr_t>(mcontext.gregs[REG_EIP]);
#elif defined(TARGET_ARCH_ARM) && defined(USING_SIMULATOR)
pc = static_cast<uintptr_t>(mcontext.gregs[REG_EIP]);
+#elif defined(TARGET_ARCH_ARM)
+ pc = static_cast<uintptr_t>(mcontext.arm_pc);
#else
UNIMPLEMENTED();
#endif // TARGET_ARCH_...
@@ -38,6 +40,8 @@
fp = static_cast<uintptr_t>(mcontext.gregs[REG_EBP]);
#elif defined(TARGET_ARCH_ARM) && defined(USING_SIMULATOR)
fp = static_cast<uintptr_t>(mcontext.gregs[REG_EBP]);
+#elif defined(TARGET_ARCH_ARM)
+ fp = static_cast<uintptr_t>(mcontext.arm_fp);
#else
UNIMPLEMENTED();
#endif // TARGET_ARCH_...
@@ -57,6 +61,8 @@
sp = static_cast<uintptr_t>(mcontext.gregs[REG_ESP]);
#elif defined(TARGET_ARCH_ARM) && defined(USING_SIMULATOR)
sp = static_cast<uintptr_t>(mcontext.gregs[REG_ESP]);
+#elif defined(TARGET_ARCH_ARM)
+ sp = static_cast<uintptr_t>(mcontext.arm_sp);
#else
UNIMPLEMENTED();
#endif // TARGET_ARCH_...
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 33c8238..76b4370 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -86,7 +86,7 @@
// | spill slots | outgoing arguments | saved registers |
// |XXXXXXXXXXXXX|--------------------|XXXXXXXXXXXXXXXXX|
//
- // The splill slots and any saved registers are described in the stack
+ // The spill slots and any saved registers are described in the stack
// map. The outgoing arguments are assumed to be tagged; the number
// of outgoing arguments is not explicitly tracked.
//
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index ff8b563..1305a1c 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -5,6 +5,7 @@
#include "platform/assert.h"
#include "vm/isolate.h"
#include "vm/unit_test.h"
+#include "vm/signal_handler.h"
#include "vm/thread.h"
namespace dart {
@@ -42,6 +43,10 @@
const int kNumAttempts = 5;
int attempts = 0;
while (attempts < kNumAttempts) {
+ // This test verifies that a monitor returns after the specified timeout. If
+ // a signal is delivered to this thread, the monitor may return early.
+ // Block signal delivery in this scope.
+ ScopedSignalBlocker ssb;
MonitorLocker ml(monitor);
int64_t start = OS::GetCurrentTimeMillis();
int64_t wait_time = 2017;
diff --git a/runtime/vm/visitor.h b/runtime/vm/visitor.h
index 20b48b3..78de10f 100644
--- a/runtime/vm/visitor.h
+++ b/runtime/vm/visitor.h
@@ -6,6 +6,7 @@
#define VM_VISITOR_H_
#include "vm/globals.h"
+#include "vm/growable_array.h"
namespace dart {
@@ -24,6 +25,11 @@
// Range of pointers to visit 'first' <= pointer <= 'last'.
virtual void VisitPointers(RawObject** first, RawObject** last) = 0;
+ virtual bool visit_function_code() const { return true; }
+ virtual GrowableArray<RawFunction*>* skipped_code_functions() {
+ return NULL;
+ }
+
// len argument is the number of pointers to visit starting from 'p'.
void VisitPointers(RawObject** p, intptr_t len) {
VisitPointers(p, (p + len - 1));
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index 3173ded..10f4950 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -254,6 +254,7 @@
'object_id_ring.h',
'object_id_ring_test.cc',
'object_mips_test.cc',
+ 'object_set.h',
'object_store.cc',
'object_store.h',
'object_store_test.cc',
diff --git a/sdk/lib/_internal/compiler/implementation/apiimpl.dart b/sdk/lib/_internal/compiler/implementation/apiimpl.dart
index cc8be6e..f16cabe 100644
--- a/sdk/lib/_internal/compiler/implementation/apiimpl.dart
+++ b/sdk/lib/_internal/compiler/implementation/apiimpl.dart
@@ -57,8 +57,6 @@
preserveComments: hasOption(options, '--preserve-comments'),
verbose: hasOption(options, '--verbose'),
sourceMapUri: extractSourceMapUri(options),
- globalJsName: extractStringOption(
- options, '--global-js-name=', r'$'),
terseDiagnostics: hasOption(options, '--terse'),
buildId: extractStringOption(
options, '--build-id=',
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index 0cadcae..38c18ee 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -127,8 +127,9 @@
superclass.ensureResolved(compiler);
supertype = superclass.computeType(compiler);
interfaces = const Link<DartType>();
- allSupertypes = const Link<DartType>().prepend(supertype);
thisType = rawType = new InterfaceType(this);
+ allSupertypesAndSelf =
+ superclass.allSupertypesAndSelf.extendClass(thisType);
}
bool isClosure() => true;
diff --git a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
index 4117c78..fd1163e 100644
--- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -365,7 +365,7 @@
}
Constant visitLiteralString(LiteralString node) {
- return constantSystem.createString(node.dartString, node);
+ return constantSystem.createString(node.dartString);
}
Constant visitStringJuxtaposition(StringJuxtaposition node) {
@@ -373,7 +373,7 @@
StringConstant right = evaluate(node.second);
if (left == null || right == null) return null;
return constantSystem.createString(
- new DartString.concat(left.value, right.value), node);
+ new DartString.concat(left.value, right.value));
}
Constant visitStringInterpolation(StringInterpolation node) {
@@ -399,14 +399,14 @@
if (partString == null) return null;
accumulator = new DartString.concat(accumulator, partString.value);
};
- return constantSystem.createString(accumulator, node);
+ return constantSystem.createString(accumulator);
}
Constant visitLiteralSymbol(LiteralSymbol node) {
InterfaceType type = compiler.symbolClass.computeType(compiler);
List<Constant> createArguments(_) {
return [constantSystem.createString(
- new DartString.literal(node.slowNameString), node)];
+ new DartString.literal(node.slowNameString))];
}
return makeConstructedConstant(
node, type, compiler.symbolConstructor, createArguments);
@@ -711,7 +711,7 @@
}
} else {
assert(constructor == compiler.stringEnvironment);
- return constantSystem.createString(new DartString.literal(value), node);
+ return constantSystem.createString(new DartString.literal(value));
}
} else {
return makeConstructedConstant(
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index ecfe995..1ded67e 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -254,6 +254,9 @@
ClassElement get typeImplementation => compiler.typeClass;
ClassElement get boolImplementation => compiler.boolClass;
ClassElement get nullImplementation => compiler.nullClass;
+ ClassElement get uint32Implementation => compiler.intClass;
+ ClassElement get uint31Implementation => compiler.intClass;
+ ClassElement get positiveIntImplementation => compiler.intClass;
ClassElement defaultSuperclass(ClassElement element) => compiler.objectClass;
@@ -263,6 +266,8 @@
return classElement == compiler.objectClass;
}
+ bool isInterceptorClass(ClassElement element) => false;
+
void registerStaticUse(Element element, Enqueuer enqueuer) {}
Future onLibraryLoaded(LibraryElement library, Uri uri) {
@@ -394,12 +399,6 @@
*/
final Uri sourceMapUri;
- /**
- * The name to use for the global JS object in JS output. Default
- * value is "$".
- */
- final String globalJsName;
-
/// Emit terse diagnostics without howToFix.
final bool terseDiagnostics;
@@ -504,31 +503,30 @@
_currentElement = element;
try {
return f();
- } on SpannableAssertionFailure catch (ex, s) {
+ } on SpannableAssertionFailure catch (ex) {
if (!hasCrashed) {
String message = (ex.message != null) ? tryToString(ex.message)
: tryToString(ex);
SourceSpan span = spanFromSpannable(ex.node);
reportError(ex.node, MessageKind.GENERIC, {'text': message});
- pleaseReportCrash(s, 'The compiler crashed: $message.');
+ pleaseReportCrash();
}
hasCrashed = true;
- throw new CompilerCancelledException('The compiler crashed.');
+ rethrow;
} on CompilerCancelledException catch (ex) {
rethrow;
} on StackOverflowError catch (ex) {
// We cannot report anything useful in this case, because we
// do not have enough stack space.
rethrow;
- } catch (ex, s) {
+ } catch (ex) {
if (hasCrashed) rethrow;
- String message = 'The compiler crashed: ${tryToString(ex)}.';
try {
- unhandledExceptionOnElement(element, s, message);
+ unhandledExceptionOnElement(element);
} catch (doubleFault) {
// Ignoring exceptions in exception handling.
}
- throw new CompilerCancelledException(message);
+ rethrow;
} finally {
_currentElement = old;
}
@@ -544,6 +542,7 @@
ResolverTask resolver;
closureMapping.ClosureTask closureToClassMapper;
TypeCheckerTask checker;
+ IrBuilderTask irBuilder;
ti.TypesTask typesTask;
Backend backend;
ConstantHandler constantHandler;
@@ -622,7 +621,6 @@
this.verbose: false,
this.sourceMapUri: null,
this.buildId: UNDETERMINED_BUILD_ID,
- this.globalJsName: r'$',
this.terseDiagnostics: false,
outputProvider,
List<String> strips: const []})
@@ -656,6 +654,7 @@
resolver = new ResolverTask(this),
closureToClassMapper = new closureMapping.ClosureTask(this, closureNamer),
checker = new TypeCheckerTask(this),
+ irBuilder = new IrBuilderTask(this),
typesTask = new ti.TypesTask(this),
constantHandler = new ConstantHandler(this, backend.constantSystem),
deferredLoadTask = new DeferredLoadTask(this),
@@ -702,25 +701,17 @@
internalError(message, element: element);
}
- void unhandledExceptionOnElement(Element element,
- StackTrace stackTrace,
- String message) {
+ void unhandledExceptionOnElement(Element element) {
if (hasCrashed) return;
hasCrashed = true;
reportDiagnostic(spanFromElement(element),
MessageKind.COMPILER_CRASHED.error().toString(),
api.Diagnostic.CRASH);
- pleaseReportCrash(stackTrace, message);
+ pleaseReportCrash();
}
- void pleaseReportCrash(StackTrace stackTrace, String message) {
+ void pleaseReportCrash() {
print(MessageKind.PLEASE_REPORT_THE_CRASH.message({'buildId': buildId}));
- if (message != null) {
- print(message);
- }
- if (stackTrace != null) {
- print(stackTrace);
- }
}
void cancel(String reason, {Node node, Token token,
@@ -774,7 +765,7 @@
Future<bool> run(Uri uri) {
totalCompileTime.start();
- return new Future.sync(() => runCompiler(uri)).catchError((error, trace) {
+ return new Future.sync(() => runCompiler(uri)).catchError((error) {
if (error is CompilerCancelledException) {
log('Error: $error');
return false;
@@ -786,8 +777,7 @@
reportDiagnostic(new SourceSpan(uri, 0, 0),
MessageKind.COMPILER_CRASHED.error().toString(),
api.Diagnostic.CRASH);
- String message = 'The compiler crashed.';
- pleaseReportCrash(trace, message);
+ pleaseReportCrash();
}
} catch (doubleFault) {
// Ignoring exceptions in exception handling.
@@ -1111,6 +1101,9 @@
deferredLoadTask.onResolutionComplete(main);
+ log('Building IR...');
+ irBuilder.buildNodes();
+
log('Inferring types...');
typesTask.onResolutionComplete(main);
diff --git a/sdk/lib/_internal/compiler/implementation/constant_system.dart b/sdk/lib/_internal/compiler/implementation/constant_system.dart
index b2688b5..b2e2b54 100644
--- a/sdk/lib/_internal/compiler/implementation/constant_system.dart
+++ b/sdk/lib/_internal/compiler/implementation/constant_system.dart
@@ -52,8 +52,7 @@
Constant createInt(int i);
Constant createDouble(double d);
- // We need a diagnostic node to report errors in case the string is malformed.
- Constant createString(DartString string, Node diagnosticNode);
+ Constant createString(DartString string);
Constant createBool(bool value);
Constant createNull();
diff --git a/sdk/lib/_internal/compiler/implementation/constant_system_dart.dart b/sdk/lib/_internal/compiler/implementation/constant_system_dart.dart
index 7be2ed3..a1067c3 100644
--- a/sdk/lib/_internal/compiler/implementation/constant_system_dart.dart
+++ b/sdk/lib/_internal/compiler/implementation/constant_system_dart.dart
@@ -363,8 +363,7 @@
IntConstant createInt(int i) => new IntConstant(i);
DoubleConstant createDouble(double d) => new DoubleConstant(d);
- StringConstant createString(DartString string, Node diagnosticNode)
- => new StringConstant(string, diagnosticNode);
+ StringConstant createString(DartString string) => new StringConstant(string);
BoolConstant createBool(bool value) => new BoolConstant(value);
NullConstant createNull() => new NullConstant();
diff --git a/sdk/lib/_internal/compiler/implementation/constants.dart b/sdk/lib/_internal/compiler/implementation/constants.dart
index c32a52e..3e15ab8 100644
--- a/sdk/lib/_internal/compiler/implementation/constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/constants.dart
@@ -48,6 +48,8 @@
// TODO(johnniwinther): Replace with a 'type' getter.
DartType computeType(Compiler compiler);
+ ti.TypeMask computeMask(Compiler compiler);
+
List<Constant> getDependencies();
accept(ConstantVisitor visitor);
@@ -75,6 +77,10 @@
return compiler.functionClass.computeType(compiler);
}
+ ti.TypeMask computeMask(Compiler compiler) {
+ return compiler.typesTask.functionType;
+ }
+
int get hashCode => (17 * element.hashCode) & 0x7fffffff;
accept(ConstantVisitor visitor) => visitor.visitFunction(this);
@@ -113,6 +119,10 @@
return compiler.nullClass.computeType(compiler);
}
+ ti.TypeMask computeMask(Compiler compiler) {
+ return compiler.typesTask.nullType;
+ }
+
void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
buffer.write(JsNull);
}
@@ -152,11 +162,21 @@
}
const IntConstant._internal(this.value);
bool isInt() => true;
+ bool isUInt31() => value >= 0 && value < (1 << 31);
+ bool isUInt32() => value >= 0 && value < (1 << 32);
+ bool isPositive() => value >= 0;
DartType computeType(Compiler compiler) {
return compiler.intClass.computeType(compiler);
}
+ ti.TypeMask computeMask(Compiler compiler) {
+ if (isUInt31()) return compiler.typesTask.uint31Type;
+ if (isUInt32()) return compiler.typesTask.uint32Type;
+ if (isPositive()) return compiler.typesTask.positiveIntType;
+ return compiler.typesTask.intType;
+ }
+
// We have to override the equality operator so that ints and doubles are
// treated as separate constants.
// The is [:!IntConstant:] check at the beginning of the function makes sure
@@ -200,6 +220,10 @@
return compiler.doubleClass.computeType(compiler);
}
+ ti.TypeMask computeMask(Compiler compiler) {
+ return compiler.typesTask.doubleType;
+ }
+
bool operator ==(var other) {
if (other is !DoubleConstant) return false;
DoubleConstant otherDouble = other;
@@ -230,6 +254,10 @@
return compiler.boolClass.computeType(compiler);
}
+ ti.TypeMask computeMask(Compiler compiler) {
+ return compiler.typesTask.boolType;
+ }
+
BoolConstant negate();
}
@@ -272,12 +300,11 @@
class StringConstant extends PrimitiveConstant {
final DartString value;
final int hashCode;
- final Node node;
// TODO(floitsch): cache StringConstants.
// TODO(floitsch): compute hashcode without calling toString() on the
// DartString.
- StringConstant(DartString value, this.node)
+ StringConstant(DartString value)
: this.value = value,
this.hashCode = value.slowToString().hashCode;
bool isString() => true;
@@ -286,6 +313,10 @@
return compiler.stringClass.computeType(compiler);
}
+ ti.TypeMask computeMask(Compiler compiler) {
+ return compiler.typesTask.stringType;
+ }
+
bool operator ==(var other) {
if (other is !StringConstant) return false;
StringConstant otherString = other;
@@ -323,6 +354,10 @@
return other is TypeConstant && representedType == other.representedType;
}
+ ti.TypeMask computeMask(Compiler compiler) {
+ return compiler.typesTask.typeType;
+ }
+
int get hashCode => representedType.hashCode * 13;
List<Constant> getDependencies() => const <Constant>[];
@@ -368,6 +403,10 @@
int get length => entries.length;
+ ti.TypeMask computeMask(Compiler compiler) {
+ return compiler.typesTask.constListType;
+ }
+
accept(ConstantVisitor visitor) => visitor.visitList(this);
String toString() {
@@ -424,6 +463,10 @@
return hash;
}
+ ti.TypeMask computeMask(Compiler compiler) {
+ return compiler.typesTask.constMapType;
+ }
+
bool operator ==(var other) {
if (other is !MapConstant) return false;
MapConstant otherMap = other;
@@ -489,6 +532,10 @@
DartType computeType(Compiler compiler) => compiler.types.dynamicType;
+ ti.TypeMask computeMask(Compiler compiler) {
+ return compiler.typesTask.nonNullType;
+ }
+
String toString() {
return 'InterceptorConstant(${Error.safeToString(dispatchedType)})';
}
@@ -530,6 +577,13 @@
List<Constant> getDependencies() => fields;
+ ti.TypeMask computeMask(Compiler compiler) {
+ if (compiler.backend.isInterceptorClass(type.element)) {
+ return compiler.typesTask.nonNullType;
+ }
+ return new ti.TypeMask.nonNullExact(type.element);
+ }
+
accept(ConstantVisitor visitor) => visitor.visitConstructed(this);
Map<Element, Constant> get fieldElements {
diff --git a/sdk/lib/_internal/compiler/implementation/dart2js.dart b/sdk/lib/_internal/compiler/implementation/dart2js.dart
index 7869913..3138995 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2js.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2js.dart
@@ -4,7 +4,8 @@
library dart2js.cmdline;
-import 'dart:async';
+import 'dart:async'
+ show Future, EventSink;
import 'dart:io'
show exit, File, FileMode, Platform, RandomAccessFile;
import 'dart:math' as math;
@@ -205,14 +206,6 @@
passThrough('--categories=${categories.join(",")}');
}
- checkGlobalName(String argument) {
- String globalName = extractParameter(argument);
- if (!new RegExp(r'^\$[a-z]*$').hasMatch(globalName)) {
- fail('Error: "$globalName" must match "\\\$[a-z]*"');
- }
- passThrough(argument);
- }
-
handleShortOptions(String argument) {
var shortOptions = argument.substring(1).split("");
for (var shortOption in shortOptions) {
@@ -278,7 +271,6 @@
new OptionHandler('--analyze-signatures-only', passThrough),
new OptionHandler('--disable-native-live-type-analysis', passThrough),
new OptionHandler('--categories=.*', setCategories),
- new OptionHandler('--global-js-name=.*', checkGlobalName),
new OptionHandler('--disable-type-inference', passThrough),
new OptionHandler('--terse', passThrough),
new OptionHandler('--disallow-unsafe-eval',
@@ -418,9 +410,9 @@
return new EventSinkWrapper(writeStringSync, onDone);
}
- return api.compile(uri, libraryRoot, packageRoot,
- inputProvider, diagnosticHandler,
- options, outputProvider, environment)
+ return compileFunc(uri, libraryRoot, packageRoot,
+ inputProvider, diagnosticHandler,
+ options, outputProvider, environment)
.then(compilationDone);
}
@@ -458,7 +450,7 @@
} else {
print(message);
}
- exit(1);
+ exitFunc(1);
}
Future compilerMain(List<String> arguments) {
@@ -570,11 +562,6 @@
unsupported category, for example, --categories=help. To enable
all categories, use --categories=all.
- --global-js-name=<name>
- By default, dart2js generates JavaScript output that uses a global
- variable named "$". The name of this global can be overridden
- with this option. The name must match the regular expression "\$[a-z]*".
-
'''.trim());
}
@@ -592,7 +579,7 @@
help();
}
}
- exit(0);
+ exitFunc(0);
}
void helpAndFail(String message) {
@@ -602,11 +589,18 @@
}
void main(List<String> arguments) {
- runZoned(() => compilerMain(arguments), onError: (exception, trace) {
+ internalMain(arguments);
+}
+
+var exitFunc = exit;
+var compileFunc = api.compile;
+
+Future internalMain(List<String> arguments) {
+ onError(exception, trace) {
try {
- print('Internal error: $exception');
+ print('The compiler crashed: $exception');
} catch (ignored) {
- print('Internal error: error while printing exception');
+ print('The compiler crashed: error while printing exception');
}
try {
@@ -614,7 +608,14 @@
print(trace);
}
} finally {
- exit(253); // 253 is recognized as a crash by our test scripts.
+ exitFunc(253); // 253 is recognized as a crash by our test scripts.
}
- });
+ }
+
+ try {
+ return compilerMain(arguments).catchError(onError);
+ } catch (exception, trace) {
+ onError(exception, trace);
+ return new Future.value();
+ }
}
diff --git a/sdk/lib/_internal/compiler/implementation/dart2jslib.dart b/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
index 6499365..ca186dc 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
@@ -23,6 +23,7 @@
import 'scanner/scannerlib.dart';
import 'ssa/ssa.dart';
import 'tree/tree.dart';
+import 'ir/ir_builder.dart' show IrBuilderTask;
import 'universe/universe.dart';
import 'util/util.dart';
import 'util/characters.dart' show $_;
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index 56db7fa..cd9dff9 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -4,11 +4,14 @@
library dart_types;
+import 'dart:math' show min;
+
import 'dart2jslib.dart' show Compiler, invariant, Script, Message;
import 'elements/modelx.dart'
show VoidElementX, LibraryElementX, BaseClassElementX;
import 'elements/elements.dart';
-import 'util/util.dart' show Link, LinkBuilder;
+import 'ordered_typeset.dart' show OrderedTypeSet;
+import 'util/util.dart' show Link, LinkBuilder, CURRENT_ELEMENT_SPANNABLE;
class TypeKind {
final String id;
@@ -1477,6 +1480,157 @@
static List<DartType> sorted(Iterable<DartType> types) {
return types.toList()..sort(compare);
}
+
+ /// Computes the least upper bound of two interface types [a] and [b].
+ InterfaceType computeLeastUpperBoundInterfaces(InterfaceType a,
+ InterfaceType b) {
+
+ /// Returns the set of supertypes of [type] at depth [depth].
+ Set<DartType> getSupertypesAtDepth(InterfaceType type, int depth) {
+ ClassElement cls = type.element;
+ OrderedTypeSet types = cls.allSupertypesAndSelf;
+ Link<DartType> typeVariables = cls.typeVariables;
+ Link<DartType> typeArguments = type.typeArguments;
+ Set<DartType> set = new Set<DartType>();
+ types.forEach(depth, (DartType type) {
+ set.add(type.subst(typeArguments, typeVariables));
+ });
+ return set;
+ }
+
+ ClassElement aClass = a.element;
+ ClassElement bClass = b.element;
+ int maxCommonDepth = min(aClass.hierarchyDepth, bClass.hierarchyDepth);
+ for (int depth = maxCommonDepth; depth >= 0; depth--) {
+ Set<DartType> aTypeSet = getSupertypesAtDepth(a, depth);
+ Set<DartType> bTypeSet = getSupertypesAtDepth(b, depth);
+ Set<DartType> intersection = aTypeSet..retainAll(bTypeSet);
+ if (intersection.length == 1) {
+ return intersection.first;
+ }
+ }
+ assert(invariant(CURRENT_ELEMENT_SPANNABLE, false,
+ message: 'No least upper bound computed for $a and $b.'));
+ }
+
+ /// Computes the least upper bound of the types in the longest prefix of [a]
+ /// and [b].
+ Link<DartType> computeLeastUpperBoundsTypes(Link<DartType> a,
+ Link<DartType> b) {
+ if (a.isEmpty || b.isEmpty) return const Link<DartType>();
+ LinkBuilder<DartType> types = new LinkBuilder<DartType>();
+ while (!a.isEmpty && !b.isEmpty) {
+ types.addLast(computeLeastUpperBound(a.head, b.head));
+ a = a.tail;
+ b = b.tail;
+ }
+ return types.toLink();
+ }
+
+ /// Computes the least upper bound of two function types [a] and [b].
+ ///
+ /// If the required parameter count of [a] and [b] does not match, `Function`
+ /// is returned.
+ ///
+ /// Otherwise, a function type is returned whose return type and
+ /// parameter types are the least upper bound of those of [a] and [b],
+ /// respectively. In addition, the optional parameters are the least upper
+ /// bound of the longest common prefix of the optional parameters of [a] and
+ /// [b], and the named parameters are the least upper bound of those common to
+ /// [a] and [b].
+ DartType computeLeastUpperBoundFunctionTypes(FunctionType a,
+ FunctionType b) {
+ if (a.parameterTypes.slowLength() != b.parameterTypes.slowLength()) {
+ return compiler.functionClass.rawType;
+ }
+ DartType returnType = computeLeastUpperBound(a.returnType, b.returnType);
+ Link<DartType> parameterTypes =
+ computeLeastUpperBoundsTypes(a.parameterTypes, b.parameterTypes);
+ Link<DartType> optionalParameterTypes =
+ computeLeastUpperBoundsTypes(a.optionalParameterTypes,
+ b.optionalParameterTypes);
+ LinkBuilder<String> namedParameters = new LinkBuilder<String>();
+ Link<String> aNamedParameters = a.namedParameters;
+ Link<String> bNamedParameters = b.namedParameters;
+ LinkBuilder<DartType> namedParameterTypes = new LinkBuilder<DartType>();
+ Link<DartType> aNamedParameterTypes = a.namedParameterTypes;
+ Link<DartType> bNamedParameterTypes = b.namedParameterTypes;
+ while (!aNamedParameters.isEmpty && !bNamedParameters.isEmpty) {
+ String aNamedParameter = aNamedParameters.head;
+ String bNamedParameter = bNamedParameters.head;
+ int result = aNamedParameter.compareTo(bNamedParameter);
+ if (result == 0) {
+ namedParameters.addLast(aNamedParameter);
+ namedParameterTypes.addLast(computeLeastUpperBound(
+ aNamedParameterTypes.head, bNamedParameterTypes.head));
+ }
+ if (result <= 0) {
+ aNamedParameters = aNamedParameters.tail;
+ aNamedParameterTypes = aNamedParameterTypes.tail;
+ }
+ if (result >= 0) {
+ bNamedParameters = bNamedParameters.tail;
+ bNamedParameterTypes = bNamedParameterTypes.tail;
+ }
+ }
+ return new FunctionType(compiler.functionClass,
+ returnType,
+ parameterTypes, optionalParameterTypes,
+ namedParameters.toLink(), namedParameterTypes.toLink());
+ }
+
+ /// Computes the least upper bound of two types of which at least one is a
+ /// type variable. The least upper bound of a type variable is defined in
+ /// terms of its bound, but to ensure reflexivity we need to check for common
+ /// bounds transitively.
+ DartType computeLeastUpperBoundTypeVariableTypes(DartType a,
+ DartType b) {
+ Set<DartType> typeVariableBounds = new Set<DartType>();
+ while (a.kind == TypeKind.TYPE_VARIABLE) {
+ if (a == b) return a;
+ typeVariableBounds.add(a);
+ TypeVariableElement element = a.element;
+ a = element.bound;
+ }
+ while (b.kind == TypeKind.TYPE_VARIABLE) {
+ if (typeVariableBounds.contains(b)) return b;
+ TypeVariableElement element = b.element;
+ b = element.bound;
+ }
+ return computeLeastUpperBound(a, b);
+ }
+
+ /// Computes the least upper bound for [a] and [b].
+ DartType computeLeastUpperBound(DartType a, DartType b) {
+ if (a == b) return a;
+
+ if (a.kind == TypeKind.TYPE_VARIABLE ||
+ b.kind == TypeKind.TYPE_VARIABLE) {
+ return computeLeastUpperBoundTypeVariableTypes(a, b);
+ }
+
+ a = a.unalias(compiler);
+ b = b.unalias(compiler);
+
+ if (a.treatAsDynamic || b.treatAsDynamic) return dynamicType;
+ if (a.isVoid || b.isVoid) return voidType;
+
+ if (a.kind == TypeKind.FUNCTION && b.kind == TypeKind.FUNCTION) {
+ return computeLeastUpperBoundFunctionTypes(a, b);
+ }
+
+ if (a.kind == TypeKind.FUNCTION) {
+ a = compiler.functionClass.rawType;
+ }
+ if (b.kind == TypeKind.FUNCTION) {
+ b = compiler.functionClass.rawType;
+ }
+
+ if (a.kind == TypeKind.INTERFACE && b.kind == TypeKind.INTERFACE) {
+ return computeLeastUpperBoundInterfaces(a, b);
+ }
+ return dynamicType;
+ }
}
/**
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index 6e9281c..52c6b30 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -28,6 +28,8 @@
isUserDefinableOperator,
isMinusOperator;
+import '../ordered_typeset.dart' show OrderedTypeSet;
+
const int STATE_NOT_STARTED = 0;
const int STATE_STARTED = 1;
const int STATE_DONE = 2;
@@ -836,12 +838,16 @@
implements ScopeContainerElement {
int get id;
+ /// The length of the longest inheritance path from [:Object:].
+ int get hierarchyDepth;
+
InterfaceType get rawType;
InterfaceType get thisType;
ClassElement get superclass;
DartType get supertype;
+ OrderedTypeSet get allSupertypesAndSelf;
Link<DartType> get allSupertypes;
Link<DartType> get interfaces;
@@ -866,7 +872,6 @@
// TODO(kasperl): These are bit fishy. Do we really need them?
void set thisType(InterfaceType value);
void set supertype(DartType value);
- void set allSupertypes(Link<DartType> value);
void set interfaces(Link<DartType> value);
void set patch(ClassElement value);
void set origin(ClassElement value);
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 8859321..b53316f 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -29,6 +29,7 @@
import '../scanner/scannerlib.dart' show Token, EOF_TOKEN;
+import '../ordered_typeset.dart' show OrderedTypeSet;
class ElementX implements Element {
static int elementHashCode = 0;
@@ -1157,7 +1158,7 @@
DartType computeType(Compiler compiler) {
VariableDefinitions definitions = variables.parseNode(compiler);
- if (definitions.type == null && !definitions.modifiers.isVar()) {
+ if (definitions.type == null) {
return fieldElement.computeType(compiler);
}
return super.computeType(compiler);
@@ -1705,7 +1706,11 @@
// compilation. They don't have any user-side counter-part.
Link<Element> backendMembers = const Link<Element>();
- Link<DartType> allSupertypes;
+ OrderedTypeSet allSupertypesAndSelf;
+
+ Link<DartType> get allSupertypes => allSupertypesAndSelf.supertypes;
+
+ int get hierarchyDepth => allSupertypesAndSelf.maxDepth;
BaseClassElementX(String name,
Element enclosing,
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
index 5663714..3b75903 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
@@ -139,9 +139,9 @@
// The list of found assignments to the container.
final List<TypeInformation> assignments = <TypeInformation>[];
- bool enableLengthTracking = true;
+ bool callsGrowableMethod = false;
bool continueAnalyzing = true;
-
+
static const int MAX_ANALYSIS_COUNT = 16;
final Setlet<Element> analyzedElements = new Setlet<Element>();
@@ -178,7 +178,7 @@
}
if (continueAnalyzing) {
- if (enableLengthTracking && container.inferredLength == null) {
+ if (!callsGrowableMethod && container.inferredLength == null) {
container.inferredLength = container.originalLength;
}
return assignments;
@@ -193,7 +193,7 @@
'because: $reason');
}
continueAnalyzing = false;
- enableLengthTracking = false;
+ callsGrowableMethod = true;
}
visitNarrowTypeInformation(NarrowTypeInformation info) {}
@@ -248,10 +248,10 @@
}
}
if (!doNotChangeLengthSelectorsSet.contains(selectorName)) {
- enableLengthTracking = false;
+ callsGrowableMethod = true;
}
if (selectorName == 'length' && selector.isSetter()) {
- enableLengthTracking = false;
+ callsGrowableMethod = true;
assignments.add(inferrer.types.nullType);
}
} else if (selector.isCall()
@@ -271,5 +271,8 @@
if (isClosure(info.element)) {
bailout('Returned from a closure');
}
+ if (compiler.backend.isNeededForReflection(info.element)) {
+ bailout('Escape in reflection');
+ }
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
index 46170e4..6eb5bb5 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
@@ -10,6 +10,7 @@
import '../tree/tree.dart';
import '../universe/universe.dart';
import '../util/util.dart';
+import '../types/types.dart' show TypeMask;
/**
* The interface [InferrerVisitor] will use when working on types.
@@ -18,6 +19,9 @@
T get dynamicType;
T get nullType;
T get intType;
+ T get uint31Type;
+ T get uint32Type;
+ T get positiveIntType;
T get doubleType;
T get numType;
T get boolType;
@@ -85,6 +89,11 @@
* [receiverType].
*/
T refineReceiver(Selector selector, T receiverType);
+
+ /**
+ * Returns the internal inferrer representation for [mask].
+ */
+ T getConcreteTypeFor(TypeMask mask);
}
/**
@@ -248,8 +257,8 @@
bool hasNoArguments() => positional.isEmpty && named.isEmpty;
- bool hasOnePositionalArgumentWithType(T type) {
- return named.isEmpty && positional.length == 1 && positional[0] == type;
+ bool hasOnePositionalArgumentThatMatches(bool f(T type)) {
+ return named.isEmpty && positional.length == 1 && f(positional[0]);
}
void forEach(void f(T type)) {
@@ -652,22 +661,18 @@
T visitLiteralDouble(LiteralDouble node) {
ConstantSystem constantSystem = compiler.backend.constantSystem;
- Constant constant = constantSystem.createDouble(node.value);
// The JavaScript backend may turn this literal into an integer at
// runtime.
- return constantSystem.isDouble(constant)
- ? types.doubleType
- : types.intType;
+ return types.getConcreteTypeFor(
+ constantSystem.createDouble(node.value).computeMask(compiler));
}
T visitLiteralInt(LiteralInt node) {
ConstantSystem constantSystem = compiler.backend.constantSystem;
- Constant constant = constantSystem.createInt(node.value);
// The JavaScript backend may turn this literal into a double at
// runtime.
- return constantSystem.isDouble(constant)
- ? types.doubleType
- : types.intType;
+ return types.getConcreteTypeFor(
+ constantSystem.createInt(node.value).computeMask(compiler));
}
T visitLiteralList(LiteralList node) {
@@ -692,9 +697,7 @@
}
T visitTypeReferenceSend(Send node) {
- // If [node] is not a type literal is the class name of a static access,
- // in which case we don't use the type mask.
- return elements.isTypeLiteral(node) ? types.typeType : null;
+ return elements.isTypeLiteral(node) ? types.typeType : types.dynamicType;
}
bool isThisOrSuper(Node node) => node.isThis() || node.isSuper();
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/ir_type_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/ir_type_inferrer.dart
new file mode 100644
index 0000000..5591f68
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/ir_type_inferrer.dart
@@ -0,0 +1,77 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.ir_type_inferrer;
+
+import '../ir/ir_nodes.dart';
+import 'inferrer_visitor.dart' show TypeSystem;
+import 'simple_types_inferrer.dart' show InferrerEngine;
+import '../elements/elements.dart' show
+ Element, FunctionElement, FunctionSignature;
+import '../dart2jslib.dart' show Compiler, Constant, ConstantSystem;
+import 'type_graph_inferrer.dart' show TypeInformation;
+
+class IrTypeInferrerVisitor extends IrNodesVisitor {
+ final Compiler compiler;
+ final Element analyzedElement;
+ final TypeSystem<TypeInformation> types;
+ final InferrerEngine<TypeInformation, TypeSystem<TypeInformation>> inferrer;
+
+ IrTypeInferrerVisitor(this.compiler,
+ this.analyzedElement,
+ InferrerEngine<TypeInformation,
+ TypeSystem<TypeInformation>> inferrer)
+ : inferrer = inferrer,
+ types = inferrer.types;
+
+ final Map<IrNode, TypeInformation> analyzed = <IrNode, TypeInformation>{};
+
+ TypeInformation returnType;
+
+ TypeInformation run() {
+ if (analyzedElement.isField()) {
+ // TODO(lry): handle fields.
+ throw "Type infer from IR for field $analyzedElement";
+ }
+ FunctionElement function = analyzedElement;
+ FunctionSignature signature = function.computeSignature(compiler);
+ IrFunction node = compiler.irBuilder.getIr(function);
+ // TODO(lry): handle parameters.
+
+ if (function.isNative()) {
+ // TODO(lry): handle native.
+ throw "Type infer from IR for native $analyzedElement";
+ }
+
+ if (analyzedElement.isGenerativeConstructor()) {
+ // TODO(lry): handle constructors.
+ throw "Type infer from IR for constructor $analyzedElement";
+ }
+
+ if (analyzedElement.isSynthesized) {
+ // TODO(lry): handle synthethics.
+ throw "Type infer from IR for synthetic $analyzedElement";
+ }
+
+ visitAll(node.statements);
+ return returnType;
+ }
+
+ TypeInformation typeOfConstant(Constant constant) {
+ return inferrer.types.getConcreteTypeFor(constant.computeMask(compiler));
+ }
+
+ void visitIrConstant(IrConstant node) {
+ analyzed[node] = typeOfConstant(node.value);
+ }
+
+ void visitIrReturn(IrReturn node) {
+ TypeInformation type = analyzed[node.value];
+ returnType = inferrer.addReturnTypeFor(analyzedElement, returnType, type);
+ }
+
+ void visitNode(IrNode node) {
+ compiler.internalError('Unexpected IrNode $node');
+ }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
index 020c597c..2dbdc3b 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
@@ -74,6 +74,9 @@
TypeMask get dynamicType => compiler.typesTask.dynamicType;
TypeMask get nullType => compiler.typesTask.nullType;
TypeMask get intType => compiler.typesTask.intType;
+ TypeMask get uint32Type => compiler.typesTask.uint32Type;
+ TypeMask get uint31Type => compiler.typesTask.uint31Type;
+ TypeMask get positiveIntType => compiler.typesTask.positiveIntType;
TypeMask get doubleType => compiler.typesTask.doubleType;
TypeMask get numType => compiler.typesTask.numType;
TypeMask get boolType => compiler.typesTask.boolType;
@@ -123,6 +126,8 @@
TypeMask newType = compiler.world.allFunctions.receiverType(selector);
return receiverType.intersection(newType, compiler);
}
+
+ TypeMask getConcreteTypeFor(TypeMask mask) => mask;
}
/**
@@ -680,7 +685,7 @@
T indexType;
if (isIncrementOrDecrement) {
- rhsType = types.intType;
+ rhsType = types.uint31Type;
if (node.isIndex) indexType = visit(node.arguments.head);
} else if (node.isIndex) {
indexType = visit(node.arguments.head);
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
index 833080c..0cd9be4 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
@@ -15,7 +15,8 @@
import '../native_handler.dart' as native;
import '../util/util.dart' show Spannable, Setlet;
import 'simple_types_inferrer.dart';
-import '../dart2jslib.dart' show invariant;
+import 'ir_type_inferrer.dart';
+import '../dart2jslib.dart' show invariant, Constant;
part 'type_graph_nodes.dart';
part 'container_tracer.dart';
@@ -77,6 +78,25 @@
return intTypeCache = getConcreteTypeFor(compiler.typesTask.intType);
}
+ TypeInformation uint32TypeCache;
+ TypeInformation get uint32Type {
+ if (uint32TypeCache != null) return uint32TypeCache;
+ return uint32TypeCache = getConcreteTypeFor(compiler.typesTask.uint32Type);
+ }
+
+ TypeInformation uint31TypeCache;
+ TypeInformation get uint31Type {
+ if (uint31TypeCache != null) return uint31TypeCache;
+ return uint31TypeCache = getConcreteTypeFor(compiler.typesTask.uint31Type);
+ }
+
+ TypeInformation positiveIntTypeCache;
+ TypeInformation get positiveIntType {
+ if (positiveIntTypeCache != null) return positiveIntTypeCache;
+ return positiveIntTypeCache =
+ getConcreteTypeFor(compiler.typesTask.positiveIntType);
+ }
+
TypeInformation doubleTypeCache;
TypeInformation get doubleType {
if (doubleTypeCache != null) return doubleTypeCache;
@@ -224,6 +244,7 @@
}
ConcreteTypeInformation getConcreteTypeFor(TypeMask mask) {
+ assert(mask != null);
return concreteTypes.putIfAbsent(mask, () {
return new ConcreteTypeInformation(mask);
});
@@ -430,6 +451,10 @@
if (newAssignments == null) return;
info.elementType.inferred = true;
+ TypeMask fixedListType = compiler.typesTask.fixedListType;
+ if (info.originalContainerType.forwardTo == fixedListType) {
+ info.checksGrowable = tracer.callsGrowableMethod;
+ }
newAssignments.forEach(info.elementType.addAssignment);
workQueue.add(info);
workQueue.add(info.elementType);
@@ -468,8 +493,12 @@
if (analyzedElements.contains(element)) return;
analyzedElements.add(element);
- SimpleTypeInferrerVisitor visitor =
- new SimpleTypeInferrerVisitor(element, compiler, this);
+ var visitor;
+ if (compiler.irBuilder.hasIr(element)) {
+ visitor = new IrTypeInferrerVisitor(compiler, element, this);
+ } else {
+ visitor = new SimpleTypeInferrerVisitor(element, compiler, this);
+ }
TypeInformation type;
compiler.withCurrentElement(element, () {
type = visitor.run();
@@ -482,6 +511,15 @@
// If [element] is final and has an initializer, we record
// the inferred type.
if (node.asSendSet() != null) {
+ if (type is! ContainerTypeInformation) {
+ // For non-container types, the constant handler does
+ // constant folding that could give more precise results.
+ Constant value =
+ compiler.constantHandler.getConstantForVariable(element);
+ if (value != null) {
+ type = types.getConcreteTypeFor(value.computeMask(compiler));
+ }
+ }
recordType(element, type);
} else if (!element.isInstanceMember()) {
recordType(element, types.nullType);
@@ -680,6 +718,7 @@
void recordReturnType(Element element, TypeInformation type) {
TypeInformation info = types.getInferredTypeOf(element);
if (element.name == '==') {
+ // Even if x.== doesn't return a bool, 'x == null' evaluates to 'false'.
info.addAssignment(types.boolType);
}
// TODO(ngeoffray): Clean up. We do these checks because
@@ -875,6 +914,12 @@
return inferrer.types.allocatedContainers[node].type;
}
+ bool isFixedArrayCheckedForGrowable(Node node) {
+ if (compiler.disableTypeInference) return true;
+ ContainerTypeInformation info = inferrer.types.allocatedContainers[node];
+ return info.checksGrowable;
+ }
+
TypeMask getTypeOfSelector(Selector selector) {
if (compiler.disableTypeInference) return compiler.typesTask.dynamicType;
// Bailout for closure calls. We're not tracking types of
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
index b6a2cab..2598dd3 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
@@ -185,7 +185,7 @@
/**
* A node representing a resolved element of the program. The kind of
- * elements that need an [ElementTypeRepresentation] are:
+ * elements that need an [ElementTypeInformation] are:
*
* - Functions (including getters and setters)
* - Constructors (factory or generative)
@@ -507,12 +507,6 @@
}
}
- bool hasOnePositionalArgumentWithType(TypeMask type) {
- return arguments.named.isEmpty
- && arguments.positional.length == 1
- && arguments.positional[0].type == type;
- }
-
/**
* We optimize certain operations on the [int] class because we know
* more about their return type than the actual Dart code. For
@@ -521,38 +515,72 @@
*/
TypeInformation handleIntrisifiedSelector(Selector selector,
TypeGraphInferrerEngine inferrer) {
- if (!inferrer.compiler.backend.intImplementation.isResolved) return null;
- TypeMask intType = inferrer.compiler.typesTask.intType;
- TypeMask nullableIntType = intType.nullable();
+ Compiler compiler = inferrer.compiler;
+ if (!compiler.backend.intImplementation.isResolved) return null;
TypeMask emptyType = const TypeMask.nonNullEmpty();
- if (selector.mask != intType && selector.mask != nullableIntType) {
+ if (selector.mask == null) return null;
+ if (!selector.mask.containsOnlyInt(compiler)) {
return null;
}
if (!selector.isCall() && !selector.isOperator()) return null;
if (!arguments.named.isEmpty) return null;
if (arguments.positional.length > 1) return null;
+ ClassElement uint31Implementation = compiler.backend.uint31Implementation;
+ bool isInt(info) => info.type.containsOnlyInt(compiler);
+ bool isEmpty(info) => info.type == emptyType;
+ bool isUInt31(info) {
+ return info.type.satisfies(uint31Implementation, compiler);
+ }
+ bool isPositiveInt(info) {
+ return info.type.satisfies(
+ compiler.backend.positiveIntImplementation, compiler);
+ }
+
String name = selector.name;
- if (name == '*' || name == '+' || name == '%' || name == 'remainder') {
- if (hasOnePositionalArgumentWithType(intType)
- || hasOnePositionalArgumentWithType(nullableIntType)) {
+ // We are optimizing for the cases that are not expressed in the
+ // Dart code, for example:
+ // int + int -> int
+ // uint31 | uint31 -> uint31
+ if (name == '*' || name == '+' || name == '%' || name == 'remainder'
+ || name == '~/') {
+ if (isPositiveInt(receiver)
+ && arguments.hasOnePositionalArgumentThatMatches(isPositiveInt)) {
+ return inferrer.types.positiveIntType;
+ } else if (arguments.hasOnePositionalArgumentThatMatches(isInt)) {
return inferrer.types.intType;
- } else if (hasOnePositionalArgumentWithType(emptyType)) {
+ } else if (arguments.hasOnePositionalArgumentThatMatches(isEmpty)) {
return inferrer.types.nonNullEmptyType;
} else {
return null;
}
+ } else if (name == '|' || name == '^') {
+ if (isUInt31(receiver)
+ && arguments.hasOnePositionalArgumentThatMatches(isUInt31)) {
+ return inferrer.types.uint31Type;
+ }
+ } else if (name == '>>') {
+ if (isUInt31(receiver)) {
+ return inferrer.types.uint31Type;
+ }
+ } else if (name == '&') {
+ if (isUInt31(receiver)
+ || arguments.hasOnePositionalArgumentThatMatches(isUInt31)) {
+ return inferrer.types.uint31Type;
+ }
+ } else if (name == 'unary-') {
+ // The receiver being an int, the return value will also be an
+ // int.
+ return inferrer.types.intType;
} else if (name == '-') {
- if (arguments.hasNoArguments()) return inferrer.types.intType;
- if (hasOnePositionalArgumentWithType(intType)
- || hasOnePositionalArgumentWithType(nullableIntType)) {
+ if (arguments.hasOnePositionalArgumentThatMatches(isInt)) {
return inferrer.types.intType;
- } else if (hasOnePositionalArgumentWithType(emptyType)) {
+ } else if (arguments.hasOnePositionalArgumentThatMatches(isEmpty)) {
return inferrer.types.nonNullEmptyType;
}
return null;
} else if (name == 'abs') {
- return arguments.hasNoArguments() ? inferrer.types.intType : null;
+ return arguments.hasNoArguments() ? inferrer.types.positiveIntType : null;
}
return null;
}
@@ -817,6 +845,12 @@
/** The length after the container has been traced. */
int inferredLength;
+ /**
+ * Whether this container goes through a growable check.
+ * We conservatively assume it does.
+ */
+ bool checksGrowable = true;
+
ContainerTypeInformation(this.originalContainerType,
this.elementType,
this.originalLength) {
diff --git a/sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart b/sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart
new file mode 100644
index 0000000..86cdabd
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart
@@ -0,0 +1,335 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.ir_builder;
+
+import 'ir_nodes.dart';
+import '../elements/elements.dart';
+import '../dart2jslib.dart';
+import '../source_file.dart';
+import '../tree/tree.dart';
+import '../scanner/scannerlib.dart' show Token;
+import '../js_backend/js_backend.dart' show JavaScriptBackend;
+import 'ir_pickler.dart' show Unpickler;
+
+/**
+ * This task iterates through all resolved elements and builds [IrNode]s. The
+ * nodes are stored in the [nodes] map and accessible through [hasIr] and
+ * [getIr].
+ *
+ * The functionality of the IrNodes is added gradually, therefore elements might
+ * have an IR or not, depending on the language features that are used. For
+ * elements that do have an IR, the tree [Node]s and the [Token]s are not used
+ * in the rest of the compilation. This is ensured by setting the element's
+ * cached tree to [:null:] and also breaking the token stream to crash future
+ * attempts to parse.
+ *
+ * The type inferrer works on either IR nodes or tree nodes. The IR nodes are
+ * then translated into the SSA form for optimizations and code generation.
+ * Long-term, once the IR supports the full language, the backend can be
+ * re-implemented to work directly on the IR.
+ */
+class IrBuilderTask extends CompilerTask {
+ final Map<Element, IrNode> nodes = new Map<Element, IrNode>();
+
+ IrBuilderTask(Compiler compiler) : super(compiler);
+
+ String get name => 'IR builder';
+
+ bool hasIr(Element element) => nodes.containsKey(element.implementation);
+
+ IrNode getIr(Element element) => nodes[element.implementation];
+
+ void buildNodes() {
+ if (!irEnabled()) return;
+ measure(() {
+ Map<Element, TreeElements> resolved =
+ compiler.enqueuer.resolution.resolvedElements;
+ resolved.forEach((Element element, TreeElements elementsMapping) {
+ if (canBuild(element)) {
+ element = element.implementation;
+
+ SourceFile sourceFile = elementSourceFile(element);
+ IrNodeBuilderVisitor visitor =
+ new IrNodeBuilderVisitor(elementsMapping, compiler, sourceFile);
+ IrNode irNode;
+ ElementKind kind = element.kind;
+ if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
+ // TODO(lry): build ir for constructors.
+ } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY ||
+ kind == ElementKind.FUNCTION ||
+ kind == ElementKind.GETTER ||
+ kind == ElementKind.SETTER) {
+ irNode = visitor.buildMethod(element);
+ } else if (kind == ElementKind.FIELD) {
+ // TODO(lry): build ir for lazy initializers of static fields.
+ } else {
+ compiler.internalErrorOnElement(element,
+ 'unexpected element kind $kind');
+ }
+
+ if (irNode != null) {
+ assert(() {
+ // In host-checked mode, serialize and de-serialize the IrNode.
+ List<int> data = irNode.pickle();
+ irNode = new Unpickler(compiler).unpickle(data);
+ return true;
+ });
+ nodes[element] = irNode;
+ unlinkTreeAndToken(element);
+ }
+ }
+ });
+ });
+ }
+
+ bool irEnabled() {
+ // TODO(lry): support checked-mode checks.
+ if (compiler.enableTypeAssertions ||
+ compiler.backend is !JavaScriptBackend ||
+ compiler.enableConcreteTypeInference) {
+ return false;
+ }
+ return true;
+ }
+
+ bool canBuild(Element element) {
+ // TODO(lry): support lazy initializers.
+ FunctionElement function = element.asFunctionElement();
+ if (function == null) return false;
+
+ // TODO(lry): support functions with parameters.
+ FunctionSignature signature = function.computeSignature(compiler);
+ if (signature.parameterCount > 0) return false;
+
+ // TODO(lry): support intercepted methods. Then the dependency on
+ // JavaScriptBackend will go away.
+ JavaScriptBackend backend = compiler.backend;
+ if (backend.isInterceptedMethod(element)) return false;
+
+ // TODO(lry): support native functions (also in [visitReturn]).
+ if (function.isNative()) return false;
+
+ return true;
+ }
+
+ void unlinkTreeAndToken(element) {
+ element.beginToken.next = null;
+ element.cachedNode = null;
+ }
+
+ SourceFile elementSourceFile(Element element) {
+ if (element is FunctionElement) {
+ FunctionElement functionElement = element;
+ if (functionElement.patch != null) element = functionElement.patch;
+ }
+ return element.getCompilationUnit().script.file;
+ }
+}
+
+/**
+ * A tree visitor that builds [IrNodes]. The visit methods add statements using
+ * to the [builder] and return the last added statement for trees that represent
+ * an expression.
+ */
+class IrNodeBuilderVisitor extends ResolvedVisitor<IrNode> {
+ final SourceFile sourceFile;
+
+ IrNodeBuilderVisitor(
+ TreeElements elements,
+ Compiler compiler,
+ this.sourceFile)
+ : super(elements, compiler);
+
+ IrBuilder builder;
+
+ /**
+ * Builds the [IrFunction] for a function element. In case the function
+ * uses features that cannot be expressed in the IR, this function returns
+ * [:null:].
+ */
+ IrFunction buildMethod(FunctionElement functionElement) {
+ return nullIfGiveup(() => buildMethodInternal(functionElement));
+ }
+
+ IrFunction buildMethodInternal(FunctionElement functionElement) {
+ assert(invariant(functionElement, functionElement.isImplementation));
+ FunctionExpression function = functionElement.parseNode(compiler);
+ assert(function != null);
+ assert(!function.modifiers.isExternal());
+ assert(elements[function] != null);
+
+ int endPosition = function.getEndToken().charOffset;
+ int namePosition = elements[function].position().charOffset;
+ IrFunction result = new IrFunction(
+ nodePosition(function), endPosition, namePosition, <IrNode>[]);
+ builder = new IrBuilder(this);
+ builder.enterBlock();
+ if (function.hasBody()) {
+ function.body.accept(this);
+ ensureReturn(function);
+ result.statements
+ ..addAll(builder.constants.values)
+ ..addAll(builder.block.statements);
+ }
+ builder.exitBlock();
+ return result;
+ }
+
+ ConstantSystem get constantSystem => compiler.backend.constantSystem;
+
+ /* int | PositionWithIdentifierName */ nodePosition(Node node) {
+ Token token = node.getBeginToken();
+ if (token.isIdentifier()) {
+ return new PositionWithIdentifierName(token.charOffset, token.value);
+ } else {
+ return token.charOffset;
+ }
+ }
+
+ bool get blockReturns => builder.block.hasReturn;
+
+ /**
+ * Add an explicit [:return null:] for functions that don't have a return
+ * statement on each branch. This includes functions with an empty body,
+ * such as [:foo(){ }:].
+ */
+ void ensureReturn(FunctionExpression node) {
+ if (blockReturns) return;
+ IrConstant nullValue =
+ builder.addConstant(constantSystem.createNull(), node);
+ builder.addStatement(new IrReturn(nodePosition(node), nullValue));
+ }
+
+ IrNode visitBlock(Block node) {
+ for (Node n in node.statements.nodes) {
+ n.accept(this);
+ if (blockReturns) return null;
+ }
+ }
+
+ IrNode visitReturn(Return node) {
+ assert(!blockReturns);
+ IrNode value;
+ // TODO(lry): support native returns.
+ if (node.beginToken.value == 'native') return giveup();
+ if (node.expression == null) {
+ value = builder.addConstant(constantSystem.createNull(), node);
+ } else {
+ value = node.expression.accept(this);
+ }
+ builder.addStatement(new IrReturn(nodePosition(node), value));
+ builder.block.hasReturn = true;
+ }
+
+ IrConstant visitLiteralBool(LiteralBool node) {
+ return builder.addConstant(constantSystem.createBool(node.value), node);
+ }
+
+ IrConstant visitLiteralDouble(LiteralDouble node) {
+ return builder.addConstant(constantSystem.createDouble(node.value), node);
+ }
+
+ IrConstant visitLiteralInt(LiteralInt node) {
+ return builder.addConstant(constantSystem.createInt(node.value), node);
+ }
+
+ IrConstant visitLiteralString(LiteralString node) {
+ Constant value = constantSystem.createString(node.dartString);
+ return builder.addConstant(value, node);
+ }
+
+ IrConstant visitLiteralNull(LiteralNull node) {
+ return builder.addConstant(constantSystem.createNull(), node);
+ }
+
+// TODO(lry): other literals.
+// IrNode visitLiteralList(LiteralList node) => visitExpression(node);
+// IrNode visitLiteralMap(LiteralMap node) => visitExpression(node);
+// IrNode visitLiteralMapEntry(LiteralMapEntry node) => visitNode(node);
+// IrNode visitLiteralSymbol(LiteralSymbol node) => visitExpression(node);
+
+ IrNode visitAssert(Send node) {
+ return giveup();
+ }
+
+ IrNode visitClosureSend(Send node) {
+ return giveup();
+ }
+
+ IrNode visitDynamicSend(Send node) {
+ return giveup();
+ }
+
+ IrNode visitGetterSend(Send node) {
+ return giveup();
+ }
+
+ IrNode visitOperatorSend(Send node) {
+ return giveup();
+ }
+
+ IrNode visitStaticSend(Send node) {
+ return giveup();
+ }
+
+ IrNode visitSuperSend(Send node) {
+ return giveup();
+ }
+
+ IrNode visitTypeReferenceSend(Send node) {
+ return giveup();
+ }
+
+ static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
+
+ IrNode giveup() => throw ABORT_IRNODE_BUILDER;
+
+ IrNode nullIfGiveup(IrNode action()) {
+ try {
+ return action();
+ } catch(e) {
+ if (e == ABORT_IRNODE_BUILDER) return null;
+ rethrow;
+ }
+ }
+
+ void internalError(String reason, {Node node}) {
+ giveup();
+ }
+}
+
+class IrBuilder {
+ final IrNodeBuilderVisitor visitor;
+ IrBuilder(this.visitor);
+
+ List<BlockBuilder> blockBuilders = <BlockBuilder>[];
+
+ BlockBuilder get block => blockBuilders.last;
+
+ Map<Constant, IrConstant> constants = <Constant, IrConstant>{};
+
+ IrConstant addConstant(Constant value, Node node) {
+ return constants.putIfAbsent(
+ value, () => new IrConstant(visitor.nodePosition(node), value));
+ }
+
+ IrNode addStatement(IrNode statement) {
+ block.statements.add(statement);
+ return statement;
+ }
+
+ void enterBlock() {
+ blockBuilders.add(new BlockBuilder());
+ }
+
+ void exitBlock() {
+ blockBuilders.removeLast();
+ }
+}
+
+class BlockBuilder {
+ List<IrNode> statements = <IrNode>[];
+ bool hasReturn = false;
+}
diff --git a/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart b/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
new file mode 100644
index 0000000..5a0672c
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
@@ -0,0 +1,80 @@
+// 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.
+
+// IrNodes are kept in a separate library to have precise control over their
+// dependencies on other parts of the system.
+library dart2js.ir_nodes;
+
+import '../dart2jslib.dart' show Constant;
+import 'ir_pickler.dart' show Pickler;
+
+/**
+ * A pair of source offset and an identifier name. Identifier names are used in
+ * the Javascript backend to generate source maps.
+ */
+class PositionWithIdentifierName {
+ final int offset;
+ final String sourceName;
+ PositionWithIdentifierName(this.offset, this.sourceName);
+}
+
+abstract class IrNode {
+ static int hashCount = 0;
+ final int hashCode = hashCount = (hashCount + 1) & 0x3fffffff;
+
+ final /* int | PositionWithIdentifierName */ position;
+
+ const IrNode(this.position);
+
+ int get offset => (position is int) ? position : position.offset;
+
+ String get sourceName => (position is int) ? null : position.sourceName;
+
+ List<int> pickle() => new Pickler().pickle(this);
+
+ accept(IrNodesVisitor visitor);
+}
+
+class IrFunction extends IrNode {
+ final List<IrNode> statements;
+
+ final int endOffset;
+ final int namePosition;
+
+ IrFunction(position, this.endOffset, this.namePosition, this.statements)
+ : super(position);
+
+ accept(IrNodesVisitor visitor) => visitor.visitIrFunction(this);
+}
+
+class IrReturn extends IrNode {
+ final IrNode value;
+
+ IrReturn(position, this.value) : super(position);
+
+ accept(IrNodesVisitor visitor) => visitor.visitIrReturn(this);
+}
+
+class IrConstant extends IrNode {
+ final Constant value;
+
+ IrConstant(position, this.value) : super(position);
+
+ accept(IrNodesVisitor visitor) => visitor.visitIrConstant(this);
+}
+
+
+abstract class IrNodesVisitor<T> {
+ T visit(IrNode node) => node.accept(this);
+
+ void visitAll(List<IrNode> nodes) {
+ for (IrNode n in nodes) visit(n);
+ }
+
+ T visitNode(IrNode node);
+
+ T visitIrFunction(IrFunction node) => visitNode(node);
+ T visitIrReturn(IrReturn node) => visitNode(node);
+ T visitIrConstant(IrConstant node) => visitNode(node);
+}
diff --git a/sdk/lib/_internal/compiler/implementation/ir/ir_pickler.dart b/sdk/lib/_internal/compiler/implementation/ir/ir_pickler.dart
new file mode 100644
index 0000000..ff43852
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/ir/ir_pickler.dart
@@ -0,0 +1,354 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.ir_pickler;
+
+import 'ir_nodes.dart';
+import '../dart2jslib.dart' show
+ Constant, FalseConstant, TrueConstant, IntConstant, DoubleConstant,
+ StringConstant, NullConstant, ListConstant, MapConstant,
+ InterceptorConstant, FunctionConstant, TypeConstant, ConstructedConstant,
+ ConstantVisitor, ConstantSystem,
+ Compiler;
+import 'dart:typed_data' show ByteData, Endianness, Uint8List;
+import 'dart:convert' show UTF8;
+import '../tree/tree.dart' show
+ DartString, LiteralDartString, RawSourceDartString, EscapedSourceDartString,
+ ConsDartString;
+
+part 'ir_unpickler.dart';
+
+/* The elementCount only includes elements that might potentially be referred
+ * to in back reference, for example nodes.
+ *
+ * pickle ::= int(elementCount) node(function)
+ *
+ * int ::= see [writeInt] for number encoding
+ *
+ * string ::= byte(STRING_ASCII) int(length) {byte(ascii)}
+ * | byte(STRING_UTF8) int(length) {byte(utf8)}
+ *
+ * node ::= byte(BACK_REFERENCE) int(index)
+ * | byte(NODE_FUNCTION) position int(endSourceOffset)
+ * int(namePosition) int(statements) {node(statement)}
+ * | byte(NODE_RETURN) position node(value)
+ * | byte(NODE_CONST) position constant
+ *
+ * position ::= byte(POSITION_WITH_ID) string(sourceName) int(sourceOffset)
+ * | byte(POSITION_OFFSET) int(sourceOffset)
+ *
+ * constant ::= byte(CONST_BOOL) byte(0 or 1)
+ * | byte(CONST_DOUBLE) byte{8}
+ * | byte(CONST_INT) int(value)
+ * | byte(CONST_STRING_LITERAL) string
+ * | byte(CONST_STRING_RAW) string int(length)
+ * | byte(CONST_STRING_ESCAPED) string int(length)
+ * | byte(CONST_STRING_CONS) constant(left) constant(right)
+ * | byte(CONST_NULL)
+ */
+class Pickles {
+ static const int BACK_REFERENCE = 1;
+
+ static const int STRING_ASCII = BACK_REFERENCE + 1;
+ static const int STRING_UTF8 = STRING_ASCII + 1;
+
+ static const int BEGIN_NODE = STRING_UTF8 + 1;
+ static const int NODE_FUNCTION = BEGIN_NODE;
+ static const int NODE_RETURN = NODE_FUNCTION + 1;
+ static const int NODE_CONST = NODE_RETURN + 1;
+ static const int END_NODE = NODE_CONST;
+
+ static const int BEGIN_POSITION = END_NODE + 1;
+ static const int POSITION_OFFSET = BEGIN_POSITION;
+ static const int POSITION_WITH_ID = POSITION_OFFSET + 1;
+ static const int END_POSITION = POSITION_WITH_ID;
+
+ static const int BEGIN_CONST = END_POSITION + 1;
+ static const int CONST_BOOL = BEGIN_CONST;
+ static const int CONST_INT = CONST_BOOL + 1;
+ static const int CONST_DOUBLE = CONST_INT + 1;
+ static const int CONST_STRING_LITERAL = CONST_DOUBLE + 1;
+ static const int CONST_STRING_RAW = CONST_STRING_LITERAL + 1;
+ static const int CONST_STRING_ESCAPED = CONST_STRING_RAW + 1;
+ static const int CONST_STRING_CONS = CONST_STRING_ESCAPED + 1;
+ static const int CONST_NULL = CONST_STRING_CONS + 1;
+ static const int END_CONST = CONST_NULL;
+
+ static const int END_TAG = END_CONST;
+}
+
+/**
+ * The [Pickler] serializes [IrNode]s to a byte array.
+ */
+class Pickler extends IrNodesVisitor {
+ ConstantPickler constantPickler;
+
+ Pickler() {
+ assert(Pickles.END_TAG <= 0xff);
+ constantPickler = new ConstantPickler(this);
+ }
+
+ static final int INITIAL_SIZE = 8;
+ static final int MAX_GROW_RATE = 4096;
+
+ List<int> data;
+
+ /** Offset of the next byte that will be written. */
+ int offset;
+
+ /** Stores the intex for emitted elements that might be back-referenced. */
+ Map<Object, int> emitted;
+
+ /** A counter for emitted elements. */
+ int index;
+
+ /**
+ * This buffer is used in [writeConstDouble] to obtain a byte representation
+ * for doubles.
+ */
+ ByteData doubleData = new ByteData(8);
+
+ List<int> pickle(IrNode node) {
+ data = new Uint8List(INITIAL_SIZE);
+ offset = 0;
+ emitted = <Object, int>{};
+ index = 0;
+ node.accept(this);
+
+ int sizeOffset = offset;
+ writeInt(emitted.length);
+ int sizeBytes = offset - sizeOffset;
+
+ // The array is longer than necessary, create a copy with the actual size.
+ Uint8List result = new Uint8List(offset);
+ // Emit the number or elements in the beginning.
+ for (int i = 0, j = sizeOffset; i < sizeBytes; i++, j++) {
+ result[i] = data[j];
+ }
+ for (int i = sizeBytes, j = 0; i < offset; i++, j++) {
+ result[i] = data[j];
+ }
+ return result;
+ }
+
+ void resize(int newSize) {
+ Uint8List newData = new Uint8List(newSize);
+ for (int i = 0; i < data.length; i++) {
+ newData[i] = data[i];
+ }
+ data = newData;
+ }
+
+ void ensureCapacity() {
+ // (offset == data.length-1) is still OK, the byte at [offset] has not yet
+ // been written.
+ int size = data.length;
+ if (offset < size) return;
+ if (size > MAX_GROW_RATE) {
+ size += MAX_GROW_RATE;
+ } else {
+ size *= 2;
+ }
+ resize(size);
+ }
+
+ static isByte(int byte) => 0 <= byte && byte <= 0xff;
+
+ void writeByte(int byte) {
+ assert(isByte(byte));
+ ensureCapacity();
+ data[offset++] = byte;
+ }
+
+ /**
+ * Writes integers to the buffer.
+ *
+ * The least significant bit of the serialized data encodes the sign. Each
+ * byte contains 7 bits of data and one bit indicating if it is the last byte
+ * of the number.
+ */
+ void writeInt(int n) {
+ bool isNegative = n < 0;
+ n = isNegative ? -n : n;
+ // Least significant bit is the sign.
+ int bits = (n << 1) | (isNegative ? 1 : 0);
+ do {
+ int next = bits & 0x7f;
+ bits >>= 7;
+ bool hasMore = bits != 0;
+ next = (next << 1) | (hasMore ? 1 : 0);
+ writeByte(next);
+ } while (bits != 0);
+ }
+
+ void writeString(String s) {
+ int startOffset = offset;
+ writeByte(Pickles.STRING_ASCII);
+ writeInt(s.length);
+ for (int i = 0; i < s.length; i++) {
+ int c = s.codeUnitAt(i);
+ if (c < 0x80) {
+ writeByte(c);
+ } else {
+ // Strings with non-ascii characters are encoded using UTF-8.
+ writeUtf8String(s, startOffset);
+ return;
+ }
+ }
+ }
+
+ void writeUtf8String(String s, int startOffset) {
+ offset = startOffset;
+ writeByte(Pickles.STRING_UTF8);
+ List<int> bytes = UTF8.encode(s);
+ writeInt(bytes.length);
+ for (int i = 0; i < bytes.length; i++) {
+ writeByte(bytes[i]);
+ }
+ }
+
+ /**
+ * If [element] has already been emitted, this function writes a back
+ * reference to the buffer and returns [:true:]. Otherwise, it registers the
+ * element in the [emitted] map and the [:false:].
+ */
+ bool writeBackrefIfEmitted(Object element) {
+ int elementIndex = emitted[element];
+ if (elementIndex != null) {
+ writeByte(Pickles.BACK_REFERENCE);
+ writeInt(elementIndex);
+ return true;
+ } else {
+ emitted[element] = index++;
+ return false;
+ }
+ }
+
+ void writePosition(/* int | PositionWithIdentifierName */ position) {
+ if (position is int) {
+ writeByte(Pickles.POSITION_OFFSET);
+ writeInt(position);
+ } else {
+ PositionWithIdentifierName namedPosition = position;
+ writeByte(Pickles.POSITION_WITH_ID);
+ writeString(namedPosition.sourceName);
+ writeInt(namedPosition.offset);
+ }
+ }
+
+ void writeConstBool(bool b) {
+ writeByte(Pickles.CONST_BOOL);
+ writeByte(b ? 1 : 0);
+ }
+
+ void writeConstInt(int n) {
+ writeByte(Pickles.CONST_INT);
+ writeInt(n);
+ }
+
+ void writeConstDouble(double d) {
+ writeByte(Pickles.CONST_DOUBLE);
+ doubleData.setFloat64(0, d, Endianness.BIG_ENDIAN);
+ for (int i = 0; i < 8; i++) {
+ writeByte(doubleData.getUint8(i));
+ }
+ }
+
+ void writeDartString(DartString s) {
+ if (s is LiteralDartString) {
+ writeByte(Pickles.CONST_STRING_LITERAL);
+ writeString(s.string);
+ } else if (s is RawSourceDartString) {
+ writeByte(Pickles.CONST_STRING_RAW);
+ writeString(s.source);
+ writeInt(s.length);
+ } else if (s is EscapedSourceDartString) {
+ writeByte(Pickles.CONST_STRING_ESCAPED);
+ writeString(s.source);
+ writeInt(s.length);
+ } else if (s is ConsDartString) {
+ writeByte(Pickles.CONST_STRING_CONS);
+ writeDartString(s.left);
+ writeDartString(s.right);
+ } else {
+ throw "Unexpected DartString: $s";
+ }
+ }
+
+ void writeConstNull() {
+ writeByte(Pickles.CONST_NULL);
+ }
+
+ void visitIrFunction(IrFunction node) {
+ if (writeBackrefIfEmitted(node)) return;
+ writeByte(Pickles.NODE_FUNCTION);
+ writePosition(node.position);
+ writeInt(node.endOffset);
+ writeInt(node.namePosition);
+ writeInt(node.statements.length);
+ for (int i = 0; i < node.statements.length; i++) {
+ node.statements[i].accept(this);
+ }
+ }
+
+ void visitIrReturn(IrReturn node) {
+ if (writeBackrefIfEmitted(node)) return;
+ writeByte(Pickles.NODE_RETURN);
+ writePosition(node.position);
+ node.value.accept(this);
+ }
+
+ void visitIrConstant(IrConstant node) {
+ if (writeBackrefIfEmitted(node)) return;
+ writeByte(Pickles.NODE_CONST);
+ writePosition(node.position);
+ node.value.accept(constantPickler);
+ }
+
+ void visitNode(IrNode node) {
+ throw "Unexpected $node in pickler.";
+ }
+}
+
+/**
+ * A visitor for constants which writes the constant values to its [Pickler].
+ */
+class ConstantPickler extends ConstantVisitor {
+
+ final Pickler pickler;
+ ConstantPickler(this.pickler);
+
+ void visitFalse(FalseConstant constant) {
+ pickler.writeConstBool(false);
+ }
+
+ void visitTrue(TrueConstant constant) {
+ pickler.writeConstBool(true);
+ }
+
+ void visitInt(IntConstant constant) {
+ pickler.writeConstInt(constant.value);
+ }
+
+ void visitDouble(DoubleConstant constant) {
+ pickler.writeConstDouble(constant.value);
+ }
+
+ void visitString(StringConstant constant) {
+ pickler.writeDartString(constant.value);
+ }
+
+ void visitNull(NullConstant constant) {
+ pickler.writeConstNull();
+ }
+
+ void visitList(ListConstant constant) => abort(constant);
+ void visitMap(MapConstant constant) => abort(constant);
+ void visitInterceptor(InterceptorConstant constant) => abort(constant);
+ void visitFunction(FunctionConstant constant) => abort(constant);
+ void visitType(TypeConstant constant) => abort(constant);
+ void visitConstructed(ConstructedConstant constant) => abort(constant);
+
+ void abort(Constant value) => throw "Can not pickle constant $value";
+}
diff --git a/sdk/lib/_internal/compiler/implementation/ir/ir_unpickler.dart b/sdk/lib/_internal/compiler/implementation/ir/ir_unpickler.dart
new file mode 100644
index 0000000..c1b9f21
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/ir/ir_unpickler.dart
@@ -0,0 +1,174 @@
+// 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.
+
+part of dart2js.ir_pickler;
+
+class Unpickler {
+ final Compiler compiler;
+
+ Unpickler(this.compiler);
+
+ List<int> data;
+
+ int offset;
+
+ /** For each element index, the corresponding unpickled element. */
+ List<Object> unpickled;
+
+ /** Counter for elements in [unpickled]. */
+ int index;
+
+ /**
+ * This buffer is used in [readConstant] to reconstruct a double value from
+ * a sequence of bytes.
+ */
+ ByteData doubleData = new ByteData(8);
+
+ ConstantSystem get constantSystem => compiler.backend.constantSystem;
+
+ IrFunction unpickle(List<int> data) {
+ this.data = data;
+ offset = 0;
+ int numElements = readInt();
+ unpickled = new List<Object>(numElements);
+ index = 0;
+ return readElement();
+ }
+
+ int readByte() {
+ return data[offset++];
+ }
+
+ int readInt() {
+ int result = 0;
+ int next;
+ for (int i = 0; true; i += 7) {
+ next = readByte();
+ result |= (next >> 1) << i;
+ if ((next & 1) == 0) break;
+ }
+ bool isNegative = (result & 1) == 1;
+ result >>= 1;
+ return isNegative ? -result : result;
+ }
+
+ String readString() {
+ int tag = readByte();
+ int length = readInt();
+ List<int> bytes = new Uint8List(length);
+ for (int i = 0; i < length; i++) {
+ bytes[i] = readByte();
+ }
+ if (tag == Pickles.STRING_ASCII) {
+ return new String.fromCharCodes(bytes);
+ } else if (tag == Pickles.STRING_UTF8) {
+ return UTF8.decode(bytes);
+ } else {
+ compiler.internalError("Unexpected string tag: $tag");
+ }
+ }
+
+ /**
+ * Read an element that might be a back reference, or that might be used
+ * in a back reference.
+ */
+ Object readElement() {
+ // Obtain the index of the element before reading its content to ensure
+ // that elements are placed in consecutive order in [unpickled].
+ int elementIndex = index++;
+ int tag = readByte();
+ if (tag == Pickles.BACK_REFERENCE) {
+ int backIndex = readInt();
+ assert(unpickled[backIndex] != null);
+ return unpickled[backIndex];
+ }
+ Object result;
+ if (tag == Pickles.NODE_CONST) {
+ result = readConstantNode();
+ } else if (tag == Pickles.NODE_FUNCTION) {
+ result = readFunctionNode();
+ } else if (tag == Pickles.NODE_RETURN) {
+ result = readReturnNode();
+ } else {
+ compiler.internalError("Unexpected element tag: $tag");
+ }
+ unpickled[elementIndex] = result;
+ return result;
+ }
+
+ IrFunction readFunctionNode() {
+ var position = readPosition();
+ int endOffset = readInt();
+ int namePosition = readInt();
+ int numStatements = readInt();
+ List<IrNode> statements = new List<IrNode>(numStatements);
+ for (int i = 0; i < numStatements; i++) {
+ statements[i] = readElement();
+ }
+ return new IrFunction(position, endOffset, namePosition, statements);
+ }
+
+ IrConstant readConstantNode() {
+ var position = readPosition();
+ Constant constant = readConstant();
+ return new IrConstant(position, constant);
+ }
+
+ IrReturn readReturnNode() {
+ var position = readPosition();
+ IrNode value = readElement();
+ return new IrReturn(position, value);
+ }
+
+ /* int | PositionWithIdentifierName */ readPosition() {
+ if (readByte() == Pickles.POSITION_OFFSET) {
+ return readInt();
+ } else {
+ String sourceName = readString();
+ int offset = readInt();
+ return new PositionWithIdentifierName(offset, sourceName);
+ }
+ }
+
+ Constant readConstant() {
+ int tag = readByte();
+ switch(tag) {
+ case Pickles.CONST_BOOL:
+ return constantSystem.createBool(readByte() == 1);
+ case Pickles.CONST_INT:
+ return constantSystem.createInt(readInt());
+ case Pickles.CONST_DOUBLE:
+ for (int i = 0; i < 8; i++) {
+ doubleData.setUint8(i, readByte());
+ }
+ double value = doubleData.getFloat64(0, Endianness.BIG_ENDIAN);
+ return constantSystem.createDouble(value);
+ case Pickles.CONST_STRING_LITERAL:
+ case Pickles.CONST_STRING_RAW:
+ case Pickles.CONST_STRING_ESCAPED:
+ case Pickles.CONST_STRING_CONS:
+ return constantSystem.createString(readDartString(tag));
+ case Pickles.CONST_NULL:
+ return constantSystem.createNull();
+ default:
+ compiler.internalError("Unexpected constant tag: $tag");
+ }
+ }
+
+ DartString readDartString(int tag) {
+ switch(tag) {
+ case Pickles.CONST_STRING_LITERAL:
+ return new LiteralDartString(readString());
+ case Pickles.CONST_STRING_RAW:
+ return new RawSourceDartString(readString(), readInt());
+ case Pickles.CONST_STRING_ESCAPED:
+ return new EscapedSourceDartString(readString(), readInt());
+ case Pickles.CONST_STRING_CONS:
+ return new ConsDartString(
+ readDartString(readByte()), readDartString(readByte()));
+ default:
+ compiler.internalError("Unexpected dart string tag: $tag");
+ }
+ }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 02e78b7..17c53c0 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -163,6 +163,7 @@
class JavaScriptBackend extends Backend {
SsaBuilderTask builder;
+ SsaFromIrBuilderTask fromIrBuilder;
SsaOptimizerTask optimizer;
SsaCodeGeneratorTask generator;
CodeEmitterTask emitter;
@@ -193,6 +194,9 @@
ClassElement jsMutableArrayClass;
ClassElement jsFixedArrayClass;
ClassElement jsExtendableArrayClass;
+ ClassElement jsPositiveIntClass;
+ ClassElement jsUInt32Class;
+ ClassElement jsUInt31Class;
Element jsIndexableLength;
Element jsArrayTypedConstructor;
@@ -226,6 +230,9 @@
TypeMask get stringType => compiler.typesTask.stringType;
TypeMask get doubleType => compiler.typesTask.doubleType;
TypeMask get intType => compiler.typesTask.intType;
+ TypeMask get uint32Type => compiler.typesTask.uint32Type;
+ TypeMask get uint31Type => compiler.typesTask.uint31Type;
+ TypeMask get positiveIntType => compiler.typesTask.positiveIntType;
TypeMask get numType => compiler.typesTask.numType;
TypeMask get boolType => compiler.typesTask.boolType;
TypeMask get dynamicType => compiler.typesTask.dynamicType;
@@ -419,6 +426,7 @@
super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) {
emitter = new CodeEmitterTask(compiler, namer, generateSourceMap);
builder = new SsaBuilderTask(this);
+ fromIrBuilder = new SsaFromIrBuilderTask(compiler);
optimizer = new SsaOptimizerTask(this);
generator = new SsaCodeGeneratorTask(this);
typeVariableHandler = new TypeVariableHandler(this);
@@ -574,6 +582,9 @@
// The int class must be before the double class, because the
// emitter relies on this list for the order of type checks.
jsIntClass = compiler.findInterceptor('JSInt'),
+ jsPositiveIntClass = compiler.findInterceptor('JSPositiveInt'),
+ jsUInt32Class = compiler.findInterceptor('JSUInt32'),
+ jsUInt31Class = compiler.findInterceptor('JSUInt31'),
jsDoubleClass = compiler.findInterceptor('JSDouble'),
jsNumberClass = compiler.findInterceptor('JSNumber'),
jsNullClass = compiler.findInterceptor('JSNull'),
@@ -845,6 +856,9 @@
addInterceptors(jsExtendableArrayClass, enqueuer, elements);
} else if (cls == compiler.intClass || cls == jsIntClass) {
addInterceptors(jsIntClass, enqueuer, elements);
+ addInterceptors(jsPositiveIntClass, enqueuer, elements);
+ addInterceptors(jsUInt32Class, enqueuer, elements);
+ addInterceptors(jsUInt31Class, enqueuer, elements);
addInterceptors(jsNumberClass, enqueuer, elements);
} else if (cls == compiler.doubleClass || cls == jsDoubleClass) {
addInterceptors(jsDoubleClass, enqueuer, elements);
@@ -855,6 +869,9 @@
addInterceptors(jsNullClass, enqueuer, elements);
} else if (cls == compiler.numClass || cls == jsNumberClass) {
addInterceptors(jsIntClass, enqueuer, elements);
+ addInterceptors(jsPositiveIntClass, enqueuer, elements);
+ addInterceptors(jsUInt32Class, enqueuer, elements);
+ addInterceptors(jsUInt31Class, enqueuer, elements);
addInterceptors(jsDoubleClass, enqueuer, elements);
addInterceptors(jsNumberClass, enqueuer, elements);
} else if (cls == jsPlainJavaScriptObjectClass) {
@@ -1260,8 +1277,9 @@
compiler.enqueuer.codegen.registerStaticUse(getCyclicThrowHelper());
}
}
-
- HGraph graph = builder.build(work);
+ HGraph graph = compiler.irBuilder.hasIr(element)
+ ? fromIrBuilder.build(work)
+ : builder.build(work);
optimizer.optimize(work, graph);
jsAst.Expression code = generator.generateCode(work, graph);
generatedCode[element] = code;
@@ -1412,7 +1430,9 @@
return typeCast
? 'boolTypeCast'
: 'boolTypeCheck';
- } else if (element == jsIntClass || element == compiler.intClass) {
+ } else if (element == jsIntClass || element == compiler.intClass
+ || element == jsUInt32Class || element == jsUInt31Class
+ || element == jsPositiveIntClass) {
if (nativeCheckOnly) return null;
return typeCast
? 'intTypeCast'
@@ -1630,6 +1650,9 @@
}
ClassElement get intImplementation => jsIntClass;
+ ClassElement get uint32Implementation => jsUInt32Class;
+ ClassElement get uint31Implementation => jsUInt31Class;
+ ClassElement get positiveIntImplementation => jsPositiveIntClass;
ClassElement get doubleImplementation => jsDoubleClass;
ClassElement get numImplementation => jsNumberClass;
ClassElement get stringImplementation => jsStringClass;
@@ -1647,6 +1670,7 @@
if (element == disableTreeShakingMarker) {
compiler.disableTypeInferenceForMirrors = true;
isTreeShakingDisabled = true;
+ typeVariableHandler.onTreeShakingDisabled(enqueuer);
} else if (element == preserveNamesMarker) {
mustPreserveNames = true;
} else if (element == preserveMetadataMarker) {
@@ -1872,13 +1896,6 @@
metadataConstants.clear();
}
- if (isTreeShakingDisabled) {
- if (enqueuer.isResolutionQueue) {
- typeVariableHandler.onResolutionQueueEmpty(enqueuer);
- } else {
- typeVariableHandler.onCodegenQueueEmpty();
- }
- }
customElementsAnalysis.onQueueEmpty(enqueuer);
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/constant_system_javascript.dart b/sdk/lib/_internal/compiler/implementation/js_backend/constant_system_javascript.dart
index 8e94149..e966bc2 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_system_javascript.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_system_javascript.dart
@@ -217,8 +217,7 @@
NumConstant createInt32(int i) => new IntConstant(i & BITS32);
NumConstant createDouble(double d)
=> convertToJavaScriptConstant(new DoubleConstant(d));
- StringConstant createString(DartString string, Node diagnosticNode)
- => new StringConstant(string, diagnosticNode);
+ StringConstant createString(DartString string) => new StringConstant(string);
BoolConstant createBool(bool value) => new BoolConstant(value);
NullConstant createNull() => new NullConstant();
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index 40209b2..d137184 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -177,6 +177,11 @@
"Z",
];
+ static const reservedGlobalHelperFunctions = const <String>[
+ "init",
+ "Isolate",
+ ];
+
static final userGlobalObjects = new List.from(reservedGlobalObjectNames)
..remove('C')
..remove('H')
@@ -207,13 +212,12 @@
_jsVariableReserved.addAll(reservedGlobalObjectNames);
// 26 letters in the alphabet, 25 not counting I.
assert(reservedGlobalObjectNames.length == 25);
+ _jsVariableReserved.addAll(reservedGlobalHelperFunctions);
}
return _jsVariableReserved;
}
- final String CURRENT_ISOLATE;
- String get GLOBAL_OBJECT => CURRENT_ISOLATE;
-
+ final String currentIsolate = r'$';
final String getterPrefix = r'get$';
final String setterPrefix = r'set$';
final String metadataField = '@';
@@ -255,7 +259,6 @@
Namer(Compiler compiler)
: compiler = compiler,
- CURRENT_ISOLATE = compiler.globalJsName,
globals = new Map<Element, String>(),
shortPrivateNameOwners = new Map<String, LibraryElement>(),
usedGlobalNames = new Set<String>(),
@@ -828,8 +831,8 @@
// TODO(ahe): Remove this method. Use get getNameOfMember instead.
String getNameOfGlobalFunction(FunctionElement element) => getNameX(element);
- /// Returns true if [element] is stored on CURRENT_ISOLATE ('$'). We intend
- /// to store only mutable static state in [CURRENT_ISOLATE], constants are
+ /// Returns true if [element] is stored on current isolate ('$'). We intend
+ /// to store only mutable static state in [currentIsolate], constants are
/// stored in 'C', and functions, accessors, classes, etc. are stored in one
/// of the other objects in [reservedGlobalObjectNames].
bool isPropertyOfCurrentIsolate(Element element) {
@@ -838,7 +841,7 @@
return
// TODO(ahe): Re-write these tests to be positive (so it only returns
// true for static/top-level mutable fields). Right now, a number of
- // other elements, such as bound closures also live in CURRENT_ISOLATE.
+ // other elements, such as bound closures also live in [currentIsolate].
!element.isAccessor() &&
!element.isClass() &&
!element.isConstructor() &&
@@ -846,9 +849,9 @@
!element.isLibrary();
}
- /// Returns [CURRENT_ISOLATE] or one of [reservedGlobalObjectNames].
+ /// Returns [currentIsolate] or one of [reservedGlobalObjectNames].
String globalObjectFor(Element element) {
- if (isPropertyOfCurrentIsolate(element)) return CURRENT_ISOLATE;
+ if (isPropertyOfCurrentIsolate(element)) return currentIsolate;
LibraryElement library = element.getLibrary();
if (library == compiler.interceptorsLibrary) return 'J';
if (library.isInternalLibrary) return 'H';
@@ -956,11 +959,9 @@
String signatureLocation(FunctionType type) {
ClassElement classElement = Types.getClassContext(type);
- if (classElement != null) {
- return '${isolateAccess(classElement)}';
- } else {
- return '${GLOBAL_OBJECT}';
- }
+ return (classElement != null)
+ ? '${isolateAccess(classElement)}'
+ : currentIsolate;
}
String signatureName(FunctionType type) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/type_variable_handler.dart b/sdk/lib/_internal/compiler/implementation/js_backend/type_variable_handler.dart
index 7ffe862..cae5491 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/type_variable_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/type_variable_handler.dart
@@ -40,31 +40,15 @@
Compiler get compiler => backend.compiler;
void registerClassWithTypeVariables(ClassElement cls) {
- typeVariableClasses.add(cls);
- }
-
- void onResolutionQueueEmpty(Enqueuer enqueuer) {
- if (typeVariableConstructor == null) {
- if (!typeVariableClass.constructors.isEmpty &&
- !typeVariableClass.constructors.tail.isEmpty) {
- compiler.reportInternalError(
- typeVariableClass,
- 'Class $typeVariableClass should only have one constructor');
- }
- typeVariableConstructor = typeVariableClass.constructors.head;
- backend.enqueueClass(
- enqueuer, typeVariableClass, compiler.globalDependencies);
- backend.enqueueInResolution(
- typeVariableConstructor, compiler.globalDependencies);
+ if (!backend.isTreeShakingDisabled || typeVariableConstructor == null) {
+ typeVariableClasses.add(cls);
+ } else {
+ processTypeVariablesOf(cls);
}
}
- void onCodegenQueueEmpty() {
- evaluator = new CompileTimeConstantEvaluator(
- compiler.constantHandler, compiler.globalDependencies, compiler);
-
- for (ClassElement cls in typeVariableClasses) {
- // TODO(zarah): Running through all the members is suboptimal. Change this
+ void processTypeVariablesOf(ClassElement cls) {
+ //TODO(zarah): Running through all the members is suboptimal. Change this
// as part of marking elements for reflection.
bool hasMemberNeededForReflection(ClassElement cls) {
bool result = false;
@@ -75,10 +59,17 @@
}
if (!backend.isNeededForReflection(cls) &&
- !hasMemberNeededForReflection(cls)) continue;
+ !hasMemberNeededForReflection(cls)) {
+ return;
+ }
InterfaceType typeVariableType = typeVariableClass.computeType(compiler);
List<int> constants = <int>[];
+ evaluator = new CompileTimeConstantEvaluator(
+ compiler.constantHandler,
+ compiler.globalDependencies,
+ compiler);
+
for (TypeVariableType currentTypeVariable in cls.typeVariables) {
List<Constant> createArguments(FunctionElement constructor) {
if (constructor != typeVariableConstructor) {
@@ -87,8 +78,7 @@
'Unexpected constructor $constructor');
}
Constant name = backend.constantSystem.createString(
- new DartString.literal(currentTypeVariable.name),
- null);
+ new DartString.literal(currentTypeVariable.name));
Constant bound = backend.constantSystem.createInt(
emitter.reifyType(currentTypeVariable.element.bound));
Constant type = evaluator.makeTypeConstant(cls);
@@ -104,8 +94,26 @@
reifyTypeVariableConstant(c, currentTypeVariable.element));
}
typeVariables[cls] = constants;
+ }
+
+ void onTreeShakingDisabled(Enqueuer enqueuer) {
+ if (!enqueuer.isResolutionQueue || typeVariableClasses == null) return;
+ backend.enqueueClass(
+ enqueuer, typeVariableClass, compiler.globalDependencies);
+ Link constructors = typeVariableClass.ensureResolved(compiler).constructors;
+ if (constructors.isEmpty && constructors.tail.isEmpty) {
+ compiler.reportInternalError(
+ typeVariableClass,
+ "Class '$typeVariableClass' should only have one constructor");
}
- typeVariableClasses.clear();
+ typeVariableConstructor = typeVariableClass.constructors.head;
+ backend.enqueueInResolution(typeVariableConstructor,
+ compiler.globalDependencies);
+ enqueuer.registerInstantiatedType(typeVariableClass.rawType,
+ compiler.globalDependencies);
+ List<ClassElement> worklist = typeVariableClasses;
+ typeVariableClasses = null;
+ worklist.forEach((cls) => processTypeVariablesOf(cls));
}
/**
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
index 156e0de..60db17c 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
@@ -116,7 +116,7 @@
String get name => 'CodeEmitter';
String get currentGenerateAccessorName
- => '${namer.CURRENT_ISOLATE}.\$generateAccessor';
+ => '${namer.currentIsolate}.\$generateAccessor';
String get generateAccessorHolder
=> '$isolatePropertiesName.\$generateAccessor';
String get finishClassesProperty
@@ -539,7 +539,7 @@
}
List addLazyInitializerLogic() {
- String isolate = namer.CURRENT_ISOLATE;
+ String isolate = namer.currentIsolate;
String cyclicThrow = namer.isolateAccess(backend.getCyclicThrowHelper());
var lazies = [];
if (backend.rememberLazies) {
@@ -794,6 +794,14 @@
}
}
+ // These classes are just helpers for the backend's type system.
+ unneededClasses.add(backend.jsMutableArrayClass);
+ unneededClasses.add(backend.jsFixedArrayClass);
+ unneededClasses.add(backend.jsExtendableArrayClass);
+ unneededClasses.add(backend.jsUInt32Class);
+ unneededClasses.add(backend.jsUInt31Class);
+ unneededClasses.add(backend.jsPositiveIntClass);
+
return (ClassElement cls) => !unneededClasses.contains(cls);
}
@@ -1195,7 +1203,7 @@
addComment(HOOKS_API_USAGE, mainBuffer);
if (!areAnyElementsDeferred) {
- mainBuffer.add('(function(${namer.CURRENT_ISOLATE})$_{$n');
+ mainBuffer.add('(function(${namer.currentIsolate})$_{$n');
}
for (String globalObject in Namer.reservedGlobalObjectNames) {
@@ -1211,8 +1219,8 @@
mainBuffer.add('function ${namer.isolateName}()$_{}\n');
mainBuffer.add('init()$N$n');
- // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary.
- isolateProperties = namer.CURRENT_ISOLATE;
+ // Shorten the code by using [namer.currentIsolate] as temporary.
+ isolateProperties = namer.currentIsolate;
mainBuffer.add(
'$isolateProperties$_=$_$isolatePropertiesName$N');
@@ -1385,11 +1393,11 @@
isolateProperties = isolatePropertiesName;
// The following code should not use the short-hand for the
// initialStatics.
- mainBuffer.add('${namer.CURRENT_ISOLATE}$_=${_}null$N');
+ mainBuffer.add('${namer.currentIsolate}$_=${_}null$N');
emitFinishIsolateConstructorInvocation(mainBuffer);
mainBuffer.add(
- '${namer.CURRENT_ISOLATE}$_=${_}new ${namer.isolateName}()$N');
+ '${namer.currentIsolate}$_=${_}new ${namer.isolateName}()$N');
emitConvertToFastObjectFunction();
for (String globalObject in Namer.reservedGlobalObjectNames) {
@@ -1527,13 +1535,13 @@
var buffer = new CodeBuffer()
..write(buildGeneratedBy())
- ..write('var old${namer.CURRENT_ISOLATE}$_='
- '$_${namer.CURRENT_ISOLATE}$N'
+ ..write('var old${namer.currentIsolate}$_='
+ '$_${namer.currentIsolate}$N'
// TODO(ahe): This defines a lot of properties on the
// Isolate.prototype object. We know this will turn it into a
// slow object in V8, so instead we should do something similar
// to Isolate.$finishIsolateConstructor.
- '${namer.CURRENT_ISOLATE}$_='
+ '${namer.currentIsolate}$_='
'$_${namer.isolateName}.prototype$N$n'
// The classesCollector object ($$).
'$classesCollector$_=$_{};$n')
@@ -1544,14 +1552,14 @@
if (!deferredClasses.isEmpty) {
buffer.write(
- '$finishClassesName($classesCollector,$_${namer.CURRENT_ISOLATE},'
+ '$finishClassesName($classesCollector,$_${namer.currentIsolate},'
'$_$isolatePropertiesName)$N');
}
buffer.write(
// Reset the classesCollector ($$).
'$classesCollector$_=${_}null$N$n'
- '${namer.CURRENT_ISOLATE}$_=${_}old${namer.CURRENT_ISOLATE}$N');
+ '${namer.currentIsolate}$_=${_}old${namer.currentIsolate}$N');
classesCollector = oldClassesCollector;
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
index 373b65d..864f130 100644
--- a/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
@@ -68,7 +68,7 @@
'''init.typeInformation[previousProperty] = element;
} else if (firstChar === "@") {
property = property.substring(1);
- ${namer.CURRENT_ISOLATE}[property][$metadataField] = element;
+ ${namer.currentIsolate}[property][$metadataField] = element;
} else if (firstChar === "*") {
globalObject[previousProperty].$defaultValuesField = element;
var optionalMethods = descriptor.$methodsWithOptionalArgumentsField;
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
index 4bb7c50..7dfd10c 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
@@ -1616,8 +1616,7 @@
Dart2JsStringConstantMirror.fromString(Dart2JsMirrorSystem mirrors,
String text)
- : super(mirrors,
- new StringConstant(new DartString.literal(text), null));
+ : super(mirrors, new StringConstant(new DartString.literal(text)));
StringConstant get _constant => super._constant;
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors_used.dart b/sdk/lib/_internal/compiler/implementation/mirrors_used.dart
index a5d6d52..05ddb81 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors_used.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors_used.dart
@@ -105,11 +105,11 @@
void analyzeUsage(LibraryElement mainApp) {
if (compiler.mirrorsLibrary == null) return;
measure(analyzer.run);
- List<String> symbols = analyzer.mergedMirrorUsage.symbols;
+ List /*<String|Element>*/ symbols = analyzer.mergedMirrorUsage.symbols;
List<Element> targets = analyzer.mergedMirrorUsage.targets;
List<Element> metaTargets = analyzer.mergedMirrorUsage.metaTargets;
compiler.backend.registerMirrorUsage(
- symbols == null ? null : new Set<String>.from(symbols),
+ symbols == null ? null : new Set/*<String|Element>*/.from(symbols),
targets == null ? null : new Set<Element>.from(targets),
metaTargets == null ? null : new Set<Element>.from(metaTargets));
librariesWithUsage = analyzer.librariesWithUsage;
@@ -304,7 +304,7 @@
return a;
}
// TODO(ahe): Test the following cases.
- List<String> symbols = a.symbols;
+ List /*<String|Element>*/ symbols = a.symbols;
if (symbols == null) {
symbols = b.symbols;
} else if (b.symbols != null) {
@@ -349,7 +349,7 @@
/// Used to represent a resolved MirrorsUsed constant.
class MirrorUsage {
- final List<String> symbols;
+ final List /* <String|Element> */ symbols;
final List<Element> targets;
final List<Element> metaTargets;
final List<Element> override;
diff --git a/sdk/lib/_internal/compiler/implementation/ordered_typeset.dart b/sdk/lib/_internal/compiler/implementation/ordered_typeset.dart
new file mode 100644
index 0000000..6a68357
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/ordered_typeset.dart
@@ -0,0 +1,203 @@
+// 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.
+
+library resolution.ordered_typeset_builder;
+
+import 'dart2jslib.dart' show Compiler, MessageKind;
+import 'dart_types.dart';
+import 'elements/elements.dart' show ClassElement;
+import 'util/util.dart' show Link, LinkBuilder;
+import 'util/util_implementation.dart' show LinkEntry;
+
+/**
+ * An ordered set of the supertypes of a class. The supertypes of a class are
+ * ordered by decreasing hierarchy depth and by the order they are extended,
+ * mixed in, or implemented.
+ *
+ * For these classes
+ *
+ * class A {} // Depth = 1.
+ * class B {} // Depth = 1.
+ * class C extends B implements A {} // Depth 2.
+ *
+ * the ordered supertypes are
+ *
+ * A: [A, Object]
+ * B: [B, Object]
+ * C: [C, B, A, Object]
+ */
+class OrderedTypeSet {
+ final List<Link<DartType>> _levels;
+ final Link<DartType> types;
+ final Link<DartType> _supertypes;
+
+ OrderedTypeSet._internal(List<Link<DartType>> this._levels,
+ Link<DartType> this.types,
+ Link<DartType> this._supertypes);
+
+ factory OrderedTypeSet.singleton(DartType type) {
+ Link<DartType> types =
+ new LinkEntry<DartType>(type, const Link<DartType>());
+ List<Link<DartType>> list = new List<Link<DartType>>(1);
+ list[0] = types;
+ return new OrderedTypeSet._internal(list, types, const Link<DartType>());
+ }
+
+ /// Creates a new [OrderedTypeSet] for [type] when it directly extends the
+ /// class which this set represents. This is for instance used to create the
+ /// type set for [ClosureClassElement] which extends [Closure].
+ OrderedTypeSet extendClass(InterfaceType type) {
+ assert(type.treatAsRaw);
+ Link<DartType> extendedTypes =
+ new LinkEntry<DartType>(type, types);
+ List<Link<DartType>> list = new List<Link<DartType>>(levels + 1);
+ for (int i = 0; i < levels; i++) {
+ list[i] = _levels[i];
+ }
+ list[levels] = extendedTypes;
+ return new OrderedTypeSet._internal(
+ list, extendedTypes, _supertypes.prepend(types.head));
+ }
+
+ Link<DartType> get supertypes => _supertypes;
+
+ int get levels => _levels.length;
+
+ int get maxDepth => levels - 1;
+
+ Link<DartType> operator [](int index) {
+ if (index < levels) {
+ return _levels[index];
+ }
+ return const Link<DartType>();
+ }
+
+ void forEach(int level, void f(DartType type)) {
+ if (level < levels) {
+ Link<DartType> pointer = _levels[level];
+ Link<DartType> end =
+ level > 0 ? _levels[level - 1] : const Link<DartType>();
+ while (!identical(pointer, end)) {
+ f(pointer.head);
+ pointer = pointer.tail;
+ }
+ }
+ }
+
+ String toString() => types.toString();
+}
+
+/**
+ * Builder for creation an ordered set of the supertypes of a class. The
+ * supertypes are ordered by decreasing hierarchy depth and by the order they
+ * are extended, mixed in, or implemented.
+ *
+ * For these classes
+ *
+ * class A {} // Depth = 1.
+ * class B {} // Depth = 1.
+ * class C extends B implements A {} // Depth 2.
+ *
+ * the ordered supertypes are
+ *
+ * A: [A, Object]
+ * B: [B, Object]
+ * C: [C, B, A, Object]
+ */
+class OrderedTypeSetBuilder {
+ Map<int, LinkEntry<DartType>> map = new Map<int, LinkEntry<DartType>>();
+ // TODO(15296): Avoid computing this order on the side when member
+ // lookup handles multiply inherited members correctly.
+ LinkBuilder<DartType> allSupertypes = new LinkBuilder<DartType>();
+ int maxDepth = -1;
+
+ final ClassElement cls;
+
+ OrderedTypeSetBuilder(this.cls);
+
+ void add(Compiler compiler, InterfaceType type) {
+ if (type.element == cls) {
+ if (type.element != compiler.objectClass) {
+ allSupertypes.addLast(compiler.objectClass.computeType(compiler));
+ }
+ _addAtDepth(compiler, type, maxDepth + 1);
+ } else {
+ if (type.element != compiler.objectClass) {
+ allSupertypes.addLast(type);
+ }
+ _addAtDepth(compiler, type, type.element.hierarchyDepth);
+ }
+ }
+
+ void _addAtDepth(Compiler compiler, InterfaceType type, int depth) {
+ LinkEntry<DartType> prev = null;
+ LinkEntry<DartType> link = map[depth];
+ while (link != null) {
+ DartType existingType = link.head;
+ if (existingType == type) return;
+ if (existingType.element == type.element) {
+ compiler.reportError(cls,
+ MessageKind.MULTI_INHERITANCE,
+ {'thisType': cls.computeType(compiler),
+ 'firstType': existingType,
+ 'secondType': type});
+ return;
+ }
+ prev = link;
+ link = link.tail;
+ }
+ LinkEntry<DartType> next = new LinkEntry<DartType>(type);
+ next.tail = null;
+ if (prev == null) {
+ map[depth] = next;
+ } else {
+ prev.tail = next;
+ }
+ if (depth > maxDepth) {
+ maxDepth = depth;
+ }
+ }
+
+ OrderedTypeSet toTypeSet() {
+ List<Link<DartType>> levels = new List<Link<DartType>>(maxDepth + 1);
+ if (maxDepth < 0) {
+ return new OrderedTypeSet._internal(
+ levels, const Link<DartType>(), const Link<DartType>());
+ }
+ Link<DartType> next = const Link<DartType>();
+ for (int depth = 0; depth <= maxDepth; depth++) {
+ LinkEntry<DartType> first = map[depth];
+ if (first == null) {
+ levels[depth] = next;
+ } else {
+ levels[depth] = first;
+ LinkEntry<DartType> last = first;
+ while (last.tail != null) {
+ last = last.tail;
+ }
+ last.tail = next;
+ next = first;
+ }
+ }
+ return new OrderedTypeSet._internal(
+ levels, levels.last, allSupertypes.toLink());
+ }
+
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ for (int depth = 0; depth <= maxDepth; depth++) {
+ sb.write('$depth: ');
+ LinkEntry<DartType> first = map[depth];
+ if (first != null) {
+ sb.write('${first.head}');
+ while (first.tail != null) {
+ sb.write(', ${first.tail.head}');
+ first = first.tail;
+ }
+ }
+ sb.write('\n');
+ }
+ return sb.toString();
+ }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index aa8b76a..3e04dc9 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -661,16 +661,19 @@
* Warning: do not call this method directly. It should only be
* called by [resolveClass] and [ClassSupertypeResolver].
*/
- void loadSupertypes(ClassElement cls, Spannable from) {
+ void loadSupertypes(BaseClassElementX cls, Spannable from) {
compiler.withCurrentElement(cls, () => measure(() {
if (cls.supertypeLoadState == STATE_DONE) return;
if (cls.supertypeLoadState == STATE_STARTED) {
compiler.reportError(from, MessageKind.CYCLIC_CLASS_HIERARCHY,
{'className': cls.name});
cls.supertypeLoadState = STATE_DONE;
- cls.allSupertypes = const Link<DartType>().prepend(
- compiler.objectClass.computeType(compiler));
+ cls.allSupertypesAndSelf =
+ compiler.objectClass.allSupertypesAndSelf.extendClass(
+ cls.computeType(compiler));
cls.supertype = cls.allSupertypes.head;
+ assert(invariant(from, cls.supertype != null,
+ message: 'Missing supertype on cyclic class $cls.'));
return;
}
cls.supertypeLoadState = STATE_STARTED;
@@ -723,7 +726,8 @@
}
}
- void resolveClassInternal(ClassElement element, TreeElementMapping mapping) {
+ void resolveClassInternal(BaseClassElementX element,
+ TreeElementMapping mapping) {
if (!element.isPatch) {
compiler.withCurrentElement(element, () => measure(() {
assert(element.resolutionState == STATE_NOT_STARTED);
@@ -750,7 +754,7 @@
// Copy class hiearchy from origin.
element.supertype = element.origin.supertype;
element.interfaces = element.origin.interfaces;
- element.allSupertypes = element.origin.allSupertypes;
+ element.allSupertypesAndSelf = element.origin.allSupertypesAndSelf;
// Stepwise assignment to ensure invariant.
element.supertypeLoadState = STATE_STARTED;
element.supertypeLoadState = STATE_DONE;
@@ -2588,7 +2592,7 @@
// type variable expression.
mapping.setType(node, compiler.typeClass.computeType(compiler));
world.registerTypeLiteral(target, mapping);
- } else if (target.impliesType() && !sendIsMemberAccess) {
+ } else if (target.impliesType() && (!sendIsMemberAccess || node.isCall)) {
// Set the type of the node to [Type] to mark this send as a
// type literal.
mapping.setType(node, compiler.typeClass.computeType(compiler));
@@ -2656,6 +2660,14 @@
// dynamic invocation, because we statically know what the target is.
} else if (!selector.applies(target, compiler)) {
warnArgumentMismatch(node, target);
+ if (node.isSuperCall) {
+ // Similar to what we do when we can't find super via selector
+ // in [resolveSend] above, we still need to register the invocation,
+ // because we might call [:super.noSuchMethod:] which calls
+ // [JSInvocationMirror._invokeOn].
+ world.registerDynamicInvocation(selector);
+ compiler.backend.registerSuperNoSuchMethod(mapping);
+ }
}
if (target != null && target.isForeign(compiler)) {
@@ -3940,7 +3952,7 @@
target.name, target, enclosing, false);
}
- void doApplyMixinTo(MixinApplicationElement mixinApplication,
+ void doApplyMixinTo(MixinApplicationElementX mixinApplication,
DartType supertype,
DartType mixinType) {
Node node = mixinApplication.parseNode(compiler);
@@ -3965,12 +3977,14 @@
// The class that is the result of a mixin application implements
// the interface of the class that was mixed in so always prepend
// that to the interface list.
+
interfaces = interfaces.prepend(mixinType);
assert(mixinApplication.interfaces == null);
mixinApplication.interfaces = interfaces;
+ ClassElement superclass = supertype.element;
if (mixinType.kind != TypeKind.INTERFACE) {
- mixinApplication.allSupertypes = const Link<DartType>();
+ mixinApplication.allSupertypesAndSelf = superclass.allSupertypesAndSelf;
return;
}
@@ -3979,7 +3993,6 @@
// Create forwarding constructors for constructor defined in the superclass
// because they are now hidden by the mixin application.
- ClassElement superclass = supertype.element;
superclass.forEachLocalMember((Element member) {
if (!member.isGenerativeConstructor()) return;
FunctionElement forwarder =
@@ -4095,54 +4108,40 @@
* different type arguments, the type used in the most specific class comes
* first.
*/
- void calculateAllSupertypes(ClassElement cls) {
- if (cls.allSupertypes != null) return;
+ void calculateAllSupertypes(BaseClassElementX cls) {
+ if (cls.allSupertypesAndSelf != null) return;
final DartType supertype = cls.supertype;
if (supertype != null) {
- Map<Element, DartType> instantiations = new Map<Element, DartType>();
- LinkBuilder<DartType> allSupertypes = new LinkBuilder<DartType>();
-
- void addSupertype(DartType type) {
- DartType existing =
- instantiations.putIfAbsent(type.element, () => type);
- if (existing != null && existing != type) {
- compiler.reportError(cls,
- MessageKind.MULTI_INHERITANCE,
- {'thisType': cls.computeType(compiler),
- 'firstType': existing,
- 'secondType': type});
- }
- if (type.element != compiler.objectClass) {
- allSupertypes.addLast(type);
- }
- }
-
- addSupertype(supertype);
- for (Link<DartType> interfaces = cls.interfaces;
- !interfaces.isEmpty;
- interfaces = interfaces.tail) {
- addSupertype(interfaces.head);
- }
- addAllSupertypes(addSupertype, supertype);
+ OrderedTypeSetBuilder allSupertypes = new OrderedTypeSetBuilder(cls);
+ // TODO(15296): Collapse these iterations to one when the order is not
+ // needed.
+ allSupertypes.add(compiler, supertype);
for (Link<DartType> interfaces = cls.interfaces;
!interfaces.isEmpty;
interfaces = interfaces.tail) {
- addAllSupertypes(addSupertype, interfaces.head);
+ allSupertypes.add(compiler, interfaces.head);
}
- allSupertypes.addLast(compiler.objectClass.rawType);
- cls.allSupertypes = allSupertypes.toLink();
+ addAllSupertypes(allSupertypes, supertype);
+ for (Link<DartType> interfaces = cls.interfaces;
+ !interfaces.isEmpty;
+ interfaces = interfaces.tail) {
+ addAllSupertypes(allSupertypes, interfaces.head);
+ }
+ allSupertypes.add(compiler, cls.computeType(compiler));
+ cls.allSupertypesAndSelf = allSupertypes.toTypeSet();
} else {
assert(identical(cls, compiler.objectClass));
- cls.allSupertypes = const Link<DartType>();
+ cls.allSupertypesAndSelf =
+ new OrderedTypeSet.singleton(cls.computeType(compiler));
}
- }
+ }
/**
* Adds [type] and all supertypes of [type] to [allSupertypes] while
* substituting type variables.
*/
- void addAllSupertypes(void addSupertype(DartType supertype),
+ void addAllSupertypes(OrderedTypeSetBuilder allSupertypes,
InterfaceType type) {
Link<DartType> typeArguments = type.typeArguments;
ClassElement classElement = type.element;
@@ -4153,10 +4152,8 @@
"during resolution of $element"));
while (!supertypes.isEmpty) {
DartType supertype = supertypes.head;
- if (supertype.element != compiler.objectClass) {
- DartType substituted = supertype.subst(typeArguments, typeVariables);
- addSupertype(substituted);
- }
+ allSupertypes.add(compiler,
+ supertype.subst(typeArguments, typeVariables));
supertypes = supertypes.tail;
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/resolution.dart b/sdk/lib/_internal/compiler/implementation/resolution/resolution.dart
index 9240eb4..136a930 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/resolution.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/resolution.dart
@@ -12,7 +12,8 @@
import '../tree/tree.dart';
import '../elements/elements.dart';
import '../elements/modelx.dart'
- show FunctionElementX,
+ show BaseClassElementX,
+ FunctionElementX,
ErroneousElementX,
VariableElementX,
FieldParameterElementX,
@@ -27,6 +28,7 @@
import '../scanner/scannerlib.dart' show PartialMetadataAnnotation;
import 'secret_tree_element.dart' show getTreeElement, setTreeElement;
+import '../ordered_typeset.dart' show OrderedTypeSet, OrderedTypeSetBuilder;
part 'members.dart';
part 'scope.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/source_map_builder.dart b/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
index 1665d22..a4d2e4b 100644
--- a/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/source_map_builder.dart
@@ -173,28 +173,50 @@
SourceMapEntry(this.sourceLocation, this.targetOffset);
}
-class SourceFileLocation {
+abstract class SourceFileLocation {
SourceFile sourceFile;
- Token token;
- int line;
- SourceFileLocation(this.sourceFile, this.token) {
+ SourceFileLocation(this.sourceFile) {
assert(isValid());
}
+ int line;
+
+ int get offset;
+
String getSourceUrl() => sourceFile.filename;
int getLine() {
- if (line == null) line = sourceFile.getLine(token.charOffset);
+ if (line == null) line = sourceFile.getLine(offset);
return line;
}
- int getColumn() => sourceFile.getColumn(getLine(), token.charOffset);
+ int getColumn() => sourceFile.getColumn(getLine(), offset);
+
+ String getSourceName();
+
+ bool isValid() => offset < sourceFile.length;
+}
+
+class TokenSourceFileLocation extends SourceFileLocation {
+ final Token token;
+
+ TokenSourceFileLocation(SourceFile sourceFile, this.token)
+ : super(sourceFile);
+
+ int get offset => token.charOffset;
String getSourceName() {
if (token.isIdentifier()) return token.value;
return null;
}
+}
- bool isValid() => token.charOffset < sourceFile.length;
+class OffsetSourceFileLocation extends SourceFileLocation {
+ final int offset;
+ final String sourceName;
+ OffsetSourceFileLocation(SourceFile sourceFile, this.offset,
+ [this.sourceName]) : super(sourceFile);
+
+ String getSourceName() => sourceName;
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 3635a62..f556147 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -885,29 +885,12 @@
}
}
-class SsaBuilder extends ResolvedVisitor implements Visitor {
- final SsaBuilderTask builder;
- final JavaScriptBackend backend;
- final CodegenWorkItem work;
- final ConstantSystem constantSystem;
- HGraph graph;
- LocalsHandler localsHandler;
- HInstruction rethrowableException;
- Map<Element, HInstruction> parameters;
- final RuntimeTypes rti;
- HParameterValue lastAddedParameter;
-
- Map<TargetElement, JumpHandler> jumpTargets;
-
- /**
- * Variables stored in the current activation. These variables are
- * being updated in try/catch blocks, and should be
- * accessed indirectly through [HLocalGet] and [HLocalSet].
- */
- Map<Element, HLocalValue> activationVariables;
-
- // We build the Ssa graph by simulating a stack machine.
- List<HInstruction> stack;
+/**
+ * This mixin implements functionality that is shared between the [SsaBuilder]
+ * and the [SsaFromIrBuilder] classes.
+ */
+class SsaGraphBuilderMixin {
+ final HGraph graph = new HGraph();
/**
* The current block to add instructions to. Might be null, if we are
@@ -931,6 +914,88 @@
*/
bool isReachable = true;
+ HBasicBlock get current => _current;
+ void set current(c) {
+ isReachable = c != null;
+ _current = c;
+ }
+
+ HBasicBlock addNewBlock() {
+ HBasicBlock block = graph.addNewBlock();
+ // If adding a new block during building of an expression, it is due to
+ // conditional expressions or short-circuit logical operators.
+ return block;
+ }
+
+ void open(HBasicBlock block) {
+ block.open();
+ current = block;
+ lastOpenedBlock = block;
+ }
+
+ HBasicBlock close(HControlFlow end) {
+ HBasicBlock result = current;
+ current.close(end);
+ current = null;
+ return result;
+ }
+
+ HBasicBlock closeAndGotoExit(HControlFlow end) {
+ HBasicBlock result = current;
+ current.close(end);
+ current = null;
+ result.addSuccessor(graph.exit);
+ return result;
+ }
+
+ void goto(HBasicBlock from, HBasicBlock to) {
+ from.close(new HGoto());
+ from.addSuccessor(to);
+ }
+
+ bool isAborted() {
+ return _current == null;
+ }
+
+ /**
+ * Creates a new block, transitions to it from any current block, and
+ * opens the new block.
+ */
+ HBasicBlock openNewBlock() {
+ HBasicBlock newBlock = addNewBlock();
+ if (!isAborted()) goto(current, newBlock);
+ open(newBlock);
+ return newBlock;
+ }
+
+ void add(HInstruction instruction) {
+ current.add(instruction);
+ }
+}
+
+class SsaBuilder extends ResolvedVisitor with SsaGraphBuilderMixin {
+ final SsaBuilderTask builder;
+ final JavaScriptBackend backend;
+ final CodegenWorkItem work;
+ final ConstantSystem constantSystem;
+ LocalsHandler localsHandler;
+ HInstruction rethrowableException;
+ Map<Element, HInstruction> parameters;
+ final RuntimeTypes rti;
+ HParameterValue lastAddedParameter;
+
+ Map<TargetElement, JumpHandler> jumpTargets;
+
+ /**
+ * Variables stored in the current activation. These variables are
+ * being updated in try/catch blocks, and should be
+ * accessed indirectly through [HLocalGet] and [HLocalSet].
+ */
+ Map<Element, HLocalValue> activationVariables;
+
+ // We build the Ssa graph by simulating a stack machine.
+ List<HInstruction> stack;
+
/**
* True if we are visiting the expression of a throw expression.
*/
@@ -971,7 +1036,6 @@
: this.builder = builder,
this.backend = builder.backend,
this.work = work,
- graph = new HGraph(),
stack = new List<HInstruction>(),
activationVariables = new Map<Element, HLocalValue>(),
jumpTargets = new Map<TargetElement, JumpHandler>(),
@@ -991,12 +1055,6 @@
bool inTryStatement = false;
int loopNesting = 0;
- HBasicBlock get current => _current;
- void set current(c) {
- isReachable = c != null;
- _current = c;
- }
-
Constant getConstantForNode(Node node) {
ConstantHandler handler = compiler.constantHandler;
Constant constant = elements.getConstant(node);
@@ -1225,9 +1283,15 @@
localsHandler, inTryStatement);
inTryStatement = false;
LocalsHandler newLocalsHandler = new LocalsHandler(this);
- newLocalsHandler.closureData =
- compiler.closureToClassMapper.computeClosureToClassMapping(
- function, function.parseNode(compiler), elements);
+ if (compiler.irBuilder.hasIr(function)) {
+ // TODO(lry): handle ir functions with nested closure definitions.
+ newLocalsHandler.closureData =
+ new ClosureClassMap(null, null, null, new ThisElement(function));
+ } else {
+ newLocalsHandler.closureData =
+ compiler.closureToClassMapper.computeClosureToClassMapping(
+ function, function.parseNode(compiler), elements);
+ }
int argumentIndex = 0;
if (isInstanceMember) {
newLocalsHandler.updateLocal(newLocalsHandler.closureData.thisElement,
@@ -1350,7 +1414,7 @@
return true;
}
- bool heuristicSayGoodToGo(FunctionExpression functionExpression) {
+ bool heuristicSayGoodToGo(bool canBeInlined(int maxNodes, bool useMax)) {
// Don't inline recursivly
if (inliningStack.any((entry) => entry.function == function)) {
return false;
@@ -1382,17 +1446,16 @@
(entry) => inferrer.isCalledOnce(entry.function)))) {
useMaxInliningNodes = false;
}
- bool canBeInlined = InlineWeeder.canBeInlined(
- functionExpression, maxInliningNodes, useMaxInliningNodes);
- if (canBeInlined) {
+ bool canInline = canBeInlined(maxInliningNodes, useMaxInliningNodes);
+ if (canInline) {
backend.inlineCache.markAsInlinable(element, insideLoop: insideLoop);
} else {
backend.inlineCache.markAsNonInlinable(element, insideLoop: insideLoop);
}
- return canBeInlined;
+ return canInline;
}
- void doInlining(FunctionExpression functionExpression) {
+ void doInlining(void visitBody()) {
// Add an explicit null check on the receiver before doing the
// inlining. We use [element] to get the same name in the
// NoSuchMethodError message as if we had called it.
@@ -1418,7 +1481,7 @@
if (element.isGenerativeConstructor()) {
buildFactory(element);
} else {
- functionExpression.body.accept(this);
+ visitBody();
}
removeInlinedInstantiation(instantiatedType);
});
@@ -1426,11 +1489,25 @@
}
if (meetsHardConstraints()) {
- FunctionExpression functionExpression = function.parseNode(compiler);
-
- if (heuristicSayGoodToGo(functionExpression)) {
- doInlining(functionExpression);
- return true;
+ if (compiler.irBuilder.hasIr(function)) {
+ IrFunction irFunction = compiler.irBuilder.getIr(function);
+ bool canInline(int n, bool b) {
+ return IrInlineWeeder.canBeInlined(irFunction, n, b);
+ }
+ if (heuristicSayGoodToGo(canInline)) {
+ SsaFromIrInliner irInliner = new SsaFromIrInliner(this);
+ doInlining(() => irInliner.visitAll(irFunction.statements));
+ return true;
+ }
+ } else {
+ FunctionExpression functionNode = function.parseNode(compiler);
+ bool canInline(int n, bool b) {
+ return InlineWeeder.canBeInlined(functionNode, n, b);
+ }
+ if (heuristicSayGoodToGo(canInline)) {
+ doInlining(() => functionNode.body.accept(this));
+ return true;
+ }
}
}
@@ -2040,8 +2117,7 @@
HInstruction subtypeInstruction = analyzeTypeArgument(subtype);
HInstruction supertypeInstruction = analyzeTypeArgument(supertype);
HInstruction messageInstruction =
- graph.addConstantString(new DartString.literal(message),
- node, compiler);
+ graph.addConstantString(new DartString.literal(message), compiler);
Element element = backend.getAssertIsSubtype();
var inputs = <HInstruction>[subtypeInstruction, supertypeInstruction,
messageInstruction];
@@ -2058,58 +2134,6 @@
return graph;
}
- HBasicBlock addNewBlock() {
- HBasicBlock block = graph.addNewBlock();
- // If adding a new block during building of an expression, it is due to
- // conditional expressions or short-circuit logical operators.
- return block;
- }
-
- void open(HBasicBlock block) {
- block.open();
- current = block;
- lastOpenedBlock = block;
- }
-
- HBasicBlock close(HControlFlow end) {
- HBasicBlock result = current;
- current.close(end);
- current = null;
- return result;
- }
-
- HBasicBlock closeAndGotoExit(HControlFlow end) {
- HBasicBlock result = current;
- current.close(end);
- current = null;
- result.addSuccessor(graph.exit);
- return result;
- }
-
- void goto(HBasicBlock from, HBasicBlock to) {
- from.close(new HGoto());
- from.addSuccessor(to);
- }
-
- bool isAborted() {
- return _current == null;
- }
-
- /**
- * Creates a new block, transitions to it from any current block, and
- * opens the new block.
- */
- HBasicBlock openNewBlock() {
- HBasicBlock newBlock = addNewBlock();
- if (!isAborted()) goto(current, newBlock);
- open(newBlock);
- return newBlock;
- }
-
- void add(HInstruction instruction) {
- current.add(instruction);
- }
-
void addWithPosition(HInstruction instruction, Node node) {
add(attachPosition(instruction, node));
}
@@ -2166,7 +2190,8 @@
}
Script script = element.getCompilationUnit().script;
SourceFile sourceFile = script.file;
- SourceFileLocation location = new SourceFileLocation(sourceFile, token);
+ SourceFileLocation location =
+ new TokenSourceFileLocation(sourceFile, token);
if (!location.isValid()) {
throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message(
{'offset': token.charOffset,
@@ -3066,7 +3091,7 @@
HInstruction signatureName = graph.addConstantString(
new DartString.literal(backend.namer.getFunctionTypeName(type)),
- node, compiler);
+ compiler);
HInstruction contextName;
HInstruction context;
@@ -3075,7 +3100,7 @@
ClassElement contextClass = Types.getClassContext(type);
contextName = graph.addConstantString(
new DartString.literal(backend.namer.getNameOfClass(contextClass)),
- node, compiler);
+ compiler);
if (!currentElement.enclosingElement.isClosure()
&& currentElement.isInstanceMember()) {
context = localsHandler.readThis();
@@ -3114,9 +3139,9 @@
add(representations);
String operator =
backend.namer.operatorIs(backend.getImplementationClass(element));
- HInstruction isFieldName = addConstantString(node, operator);
+ HInstruction isFieldName = addConstantString(operator);
HInstruction asFieldName = compiler.world.hasAnySubtype(element)
- ? addConstantString(node, backend.namer.substitutionName(element))
+ ? addConstantString(backend.namer.substitutionName(element))
: graph.addConstantNull(compiler);
List<HInstruction> inputs = <HInstruction>[expression,
isFieldName,
@@ -3282,7 +3307,7 @@
if (!compiler.hasIsolateSupport()) {
// If the isolate library is not used, we just generate code
// to fetch the current isolate.
- String name = backend.namer.CURRENT_ISOLATE;
+ String name = backend.namer.currentIsolate;
push(new HForeign(new js.LiteralString(name),
backend.dynamicType,
<HInstruction>[]));
@@ -3327,7 +3352,6 @@
}
stack.add(
addConstantString(
- argument,
backend.namer.getNameForJsGetName(
argument, string.dartString.slowToString())));
}
@@ -3421,7 +3445,7 @@
node: node.argumentsNode);
}
visit(node.arguments.head);
- String isolateName = backend.namer.CURRENT_ISOLATE;
+ String isolateName = backend.namer.currentIsolate;
SideEffects sideEffects = new SideEffects.empty();
sideEffects.setAllSideEffects();
push(new HForeign(js.js("$isolateName = #"),
@@ -3455,7 +3479,7 @@
if (!node.arguments.isEmpty) {
compiler.cancel('Too many arguments', node: node.argumentsNode);
}
- push(new HForeign(new js.LiteralString(backend.namer.CURRENT_ISOLATE),
+ push(new HForeign(new js.LiteralString(backend.namer.currentIsolate),
backend.dynamicType,
<HInstruction>[]));
}
@@ -3478,46 +3502,44 @@
} else if (name == 'JS_CREATE_ISOLATE') {
handleForeignCreateIsolate(node);
} else if (name == 'JS_OPERATOR_IS_PREFIX') {
- stack.add(addConstantString(node, backend.namer.operatorIsPrefix()));
+ stack.add(addConstantString(backend.namer.operatorIsPrefix()));
} else if (name == 'JS_OBJECT_CLASS_NAME') {
String name = backend.namer.getRuntimeTypeName(compiler.objectClass);
- stack.add(addConstantString(node, name));
+ stack.add(addConstantString(name));
} else if (name == 'JS_NULL_CLASS_NAME') {
String name = backend.namer.getRuntimeTypeName(compiler.nullClass);
- stack.add(addConstantString(node, name));
+ stack.add(addConstantString(name));
} else if (name == 'JS_FUNCTION_CLASS_NAME') {
String name = backend.namer.getRuntimeTypeName(compiler.functionClass);
- stack.add(addConstantString(node, name));
+ stack.add(addConstantString(name));
} else if (name == 'JS_OPERATOR_AS_PREFIX') {
- stack.add(addConstantString(node, backend.namer.operatorAsPrefix()));
+ stack.add(addConstantString(backend.namer.operatorAsPrefix()));
} else if (name == 'JS_SIGNATURE_NAME') {
- stack.add(addConstantString(node, backend.namer.operatorSignature()));
+ stack.add(addConstantString(backend.namer.operatorSignature()));
} else if (name == 'JS_FUNCTION_TYPE_TAG') {
- stack.add(addConstantString(node, backend.namer.functionTypeTag()));
+ stack.add(addConstantString(backend.namer.functionTypeTag()));
} else if (name == 'JS_FUNCTION_TYPE_VOID_RETURN_TAG') {
- stack.add(addConstantString(node,
- backend.namer.functionTypeVoidReturnTag()));
+ stack.add(addConstantString(backend.namer.functionTypeVoidReturnTag()));
} else if (name == 'JS_FUNCTION_TYPE_RETURN_TYPE_TAG') {
- stack.add(addConstantString(node,
- backend.namer.functionTypeReturnTypeTag()));
+ stack.add(addConstantString(backend.namer.functionTypeReturnTypeTag()));
} else if (name ==
'JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG') {
- stack.add(addConstantString(node,
+ stack.add(addConstantString(
backend.namer.functionTypeRequiredParametersTag()));
} else if (name ==
'JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG') {
- stack.add(addConstantString(node,
+ stack.add(addConstantString(
backend.namer.functionTypeOptionalParametersTag()));
} else if (name ==
'JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG') {
- stack.add(addConstantString(node,
+ stack.add(addConstantString(
backend.namer.functionTypeNamedParametersTag()));
} else if (name == 'JS_DART_OBJECT_CONSTRUCTOR') {
handleForeignDartObjectJsConstructorFunction(node);
} else if (name == 'JS_IS_INDEXABLE_FIELD_NAME') {
Element element = compiler.findHelper(
'JavaScriptIndexingBehavior');
- stack.add(addConstantString(node, backend.namer.operatorIs(element)));
+ stack.add(addConstantString(backend.namer.operatorIs(element)));
} else if (name == 'JS_CURRENT_ISOLATE') {
handleForeignJsCurrentIsolate(node);
} else if (name == 'JS_GET_NAME') {
@@ -3550,11 +3572,11 @@
if (selector.isSetter()) publicName += '=';
Constant nameConstant = constantSystem.createString(
- new DartString.literal(publicName), node);
+ new DartString.literal(publicName));
String internalName = backend.namer.invocationName(selector);
Constant internalNameConstant =
- constantSystem.createString(new DartString.literal(internalName), node);
+ constantSystem.createString(new DartString.literal(internalName));
Element createInvocationMirror = backend.getCreateInvocationMirror();
var argumentsInstruction = buildLiteralList(arguments);
@@ -3563,8 +3585,7 @@
var argumentNames = new List<HInstruction>();
for (String argumentName in selector.namedArguments) {
Constant argumentNameConstant =
- constantSystem.createString(new DartString.literal(argumentName),
- node);
+ constantSystem.createString(new DartString.literal(argumentName));
argumentNames.add(graph.addConstant(argumentNameConstant, compiler));
}
var argumentNamesInstruction = buildLiteralList(argumentNames);
@@ -3662,7 +3683,7 @@
// segmentation of '$'.
String substitutionNameString = backend.namer.getNameForRti(cls);
HInstruction substitutionName = graph.addConstantString(
- new LiteralDartString(substitutionNameString), null, compiler);
+ new LiteralDartString(substitutionNameString), compiler);
pushInvokeStatic(null,
backend.getGetRuntimeTypeArgument(),
[target, substitutionName, index],
@@ -3800,10 +3821,12 @@
handleNewSend(NewExpression node) {
Send send = node.send;
bool isFixedList = false;
+ bool isFixedListConstructorCall =
+ Elements.isFixedListConstructorCall(elements[send], send, compiler);
TypeMask computeType(element) {
Element originalElement = elements[send];
- if (Elements.isFixedListConstructorCall(originalElement, send, compiler)
+ if (isFixedListConstructorCall
|| Elements.isFilledListConstructorCall(
originalElement, send, compiler)) {
isFixedList = true;
@@ -3878,31 +3901,66 @@
return;
}
- ClassElement cls = constructor.getEnclosingClass();
- if (cls.isAbstract && constructor.isGenerativeConstructor()) {
- generateAbstractClassInstantiationError(send, cls.name);
- return;
- }
- if (backend.classNeedsRti(cls)) {
- Link<DartType> typeVariable = cls.typeVariables;
- expectedType.typeArguments.forEach((DartType argument) {
- inputs.add(analyzeTypeArgument(argument));
- typeVariable = typeVariable.tail;
- });
- assert(typeVariable.isEmpty);
- }
-
if (constructor.isFactoryConstructor() &&
!expectedType.typeArguments.isEmpty) {
compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements);
}
- TypeMask elementType = computeType(constructor);
- addInlinedInstantiation(expectedType);
- pushInvokeStatic(node, constructor, inputs, elementType);
- removeInlinedInstantiation(expectedType);
- HInstruction newInstance = stack.last;
+ TypeMask elementType = computeType(constructor);
+ if (isFixedListConstructorCall) {
+ if (!inputs[0].isNumber(compiler)) {
+ HTypeConversion conversion = new HTypeConversion(
+ null, HTypeConversion.ARGUMENT_TYPE_CHECK, backend.numType,
+ inputs[0], null);
+ add(conversion);
+ inputs[0] = conversion;
+ }
+ js.Expression code = js.js.parseForeignJS('Array(#)');
+ var behavior = new native.NativeBehavior();
+ behavior.typesReturned.add(expectedType);
+ // The allocation can throw only if the given length is a double
+ // or negative.
+ bool canThrow = true;
+ if (inputs[0].isInteger(compiler) && inputs[0] is HConstant) {
+ var constant = inputs[0];
+ if (constant.constant.value >= 0) canThrow = false;
+ }
+ HForeign foreign = new HForeign(
+ code, elementType, inputs, nativeBehavior: behavior,
+ canThrow: canThrow);
+ push(foreign);
+ TypesInferrer inferrer = compiler.typesTask.typesInferrer;
+ if (inferrer.isFixedArrayCheckedForGrowable(send)) {
+ js.Expression code = js.js.parseForeignJS(r'#.fixed$length = init');
+ // We set the instruction as [canThrow] to avoid it being dead code.
+ // We need a finer grained side effect.
+ add(new HForeign(
+ code, backend.nullType, [stack.last], canThrow: true));
+ }
+ } else {
+ ClassElement cls = constructor.getEnclosingClass();
+ if (cls.isAbstract && constructor.isGenerativeConstructor()) {
+ generateAbstractClassInstantiationError(send, cls.name);
+ return;
+ }
+ if (backend.classNeedsRti(cls)) {
+ Link<DartType> typeVariable = cls.typeVariables;
+ expectedType.typeArguments.forEach((DartType argument) {
+ inputs.add(analyzeTypeArgument(argument));
+ typeVariable = typeVariable.tail;
+ });
+ assert(typeVariable.isEmpty);
+ }
+
+ addInlinedInstantiation(expectedType);
+ pushInvokeStatic(node, constructor, inputs, elementType);
+ removeInlinedInstantiation(expectedType);
+ }
+ HInstruction newInstance = stack.last;
if (isFixedList) {
+ // Overwrite the element type, in case the allocation site has
+ // been inlined.
+ newInstance.instructionType = elementType;
JavaScriptItemCompilationContext context = work.compilationContext;
context.allocatedFixedLists.add(newInstance);
}
@@ -3911,7 +3969,7 @@
// not know about the type argument. Therefore we special case
// this constructor to have the setRuntimeTypeInfo called where
// the 'new' is done.
- if (isJSArrayTypedConstructor &&
+ if ((isFixedListConstructorCall || isJSArrayTypedConstructor) &&
backend.classNeedsRti(compiler.listClass)) {
handleListConstructor(type, send, newInstance);
}
@@ -4034,9 +4092,9 @@
}
}
- HConstant addConstantString(Node node, String string) {
+ HConstant addConstantString(String string) {
DartString dartString = new DartString.literal(string);
- Constant constant = constantSystem.createString(dartString, node);
+ Constant constant = constantSystem.createString(dartString);
return graph.addConstant(constant, compiler);
}
@@ -4088,7 +4146,7 @@
}
void generateError(Node node, String message, Element helper) {
- HInstruction errorMessage = addConstantString(node, message);
+ HInstruction errorMessage = addConstantString(message);
pushInvokeStatic(node, helper, [errorMessage]);
}
@@ -4113,11 +4171,10 @@
List<String> existingArguments}) {
Element helper = backend.getThrowNoSuchMethod();
Constant receiverConstant =
- constantSystem.createString(new DartString.empty(), diagnosticNode);
+ constantSystem.createString(new DartString.empty());
HInstruction receiver = graph.addConstant(receiverConstant, compiler);
DartString dartString = new DartString.literal(methodName);
- Constant nameConstant =
- constantSystem.createString(dartString, diagnosticNode);
+ Constant nameConstant = constantSystem.createString(dartString);
HInstruction name = graph.addConstant(nameConstant, compiler);
if (argumentValues == null) {
argumentValues = <HInstruction>[];
@@ -4134,8 +4191,7 @@
List<HInstruction> existingNames = <HInstruction>[];
for (String name in existingArguments) {
HInstruction nameConstant =
- graph.addConstantString(new DartString.literal(name),
- diagnosticNode, compiler);
+ graph.addConstantString(new DartString.literal(name), compiler);
existingNames.add(nameConstant);
}
existingNamesList = buildLiteralList(existingNames);
@@ -4501,7 +4557,7 @@
}
void visitLiteralString(LiteralString node) {
- stack.add(graph.addConstantString(node.dartString, node, compiler));
+ stack.add(graph.addConstantString(node.dartString, compiler));
}
void visitLiteralSymbol(LiteralSymbol node) {
@@ -4513,7 +4569,7 @@
void visitStringJuxtaposition(StringJuxtaposition node) {
if (!node.isInterpolation) {
// This is a simple string with no interpolations.
- stack.add(graph.addConstantString(node.dartString, node, compiler));
+ stack.add(graph.addConstantString(node.dartString, compiler));
return;
}
StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node);
@@ -5156,7 +5212,6 @@
HBasicBlock expressionEnd = close(switchInstruction);
LocalsHandler savedLocals = localsHandler;
- List<List<Constant>> matchExpressions = <List<Constant>>[];
List<HStatementInformation> statements = <HStatementInformation>[];
bool hasDefault = false;
Element getFallThroughErrorElement = backend.getFallThroughError();
@@ -5164,16 +5219,13 @@
new HasNextIterator<Node>(switchCases.iterator);
while (caseIterator.hasNext) {
SwitchCase switchCase = caseIterator.next();
- List<Constant> caseConstants = <Constant>[];
HBasicBlock block = graph.addNewBlock();
for (Constant constant in getConstants(switchCase)) {
- caseConstants.add(constant);
HConstant hConstant = graph.addConstant(constant, compiler);
switchInstruction.inputs.add(hConstant);
hConstant.usedBy.add(switchInstruction);
expressionEnd.addSuccessor(block);
}
- matchExpressions.add(caseConstants);
if (isDefaultCase(switchCase)) {
// An HSwitch has n inputs and n+1 successors, the last being the
@@ -5231,7 +5283,6 @@
close(new HGoto());
defaultCase.addSuccessor(joinBlock);
caseHandlers.add(savedLocals);
- matchExpressions.add(<Constant>[]);
statements.add(new HSubGraphBlockInformation(new SubGraph(
defaultCase, defaultCase)));
}
@@ -5254,7 +5305,6 @@
expressionEnd));
expressionStart.setBlockFlow(
new HSwitchBlockInformation(expressionInfo,
- matchExpressions,
statements,
jumpHandler.target,
jumpHandler.labels()),
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 68646d9..1af7f49 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -19,23 +19,33 @@
// TODO(sra): Attaching positions might be cleaner if the source position
// was on a wrapping node.
SourceFile sourceFile = sourceFileOfElement(element);
- Node expression = element.implementation.parseNode(backend.compiler);
- Token beginToken;
- Token endToken;
- if (expression == null) {
- // Synthesized node. Use the enclosing element for the location.
- beginToken = endToken = element.position();
+ if (compiler.irBuilder.hasIr(element)) {
+ IrFunction function = compiler.irBuilder.getIr(element);
+ node.sourcePosition = new OffsetSourceFileLocation(
+ sourceFile, function.offset, function.sourceName);
+ node.endSourcePosition = new OffsetSourceFileLocation(
+ sourceFile, function.endOffset);
} else {
- beginToken = expression.getBeginToken();
- endToken = expression.getEndToken();
- }
- // TODO(podivilov): find the right sourceFile here and remove offset checks
- // below.
- if (beginToken.charOffset < sourceFile.length) {
- node.sourcePosition = new SourceFileLocation(sourceFile, beginToken);
- }
- if (endToken.charOffset < sourceFile.length) {
- node.endSourcePosition = new SourceFileLocation(sourceFile, endToken);
+ Node expression = element.implementation.parseNode(backend.compiler);
+ Token beginToken;
+ Token endToken;
+ if (expression == null) {
+ // Synthesized node. Use the enclosing element for the location.
+ beginToken = endToken = element.position();
+ } else {
+ beginToken = expression.getBeginToken();
+ endToken = expression.getEndToken();
+ }
+ // TODO(podivilov): find the right sourceFile here and remove offset
+ // checks below.
+ if (beginToken.charOffset < sourceFile.length) {
+ node.sourcePosition =
+ new TokenSourceFileLocation(sourceFile, beginToken);
+ }
+ if (endToken.charOffset < sourceFile.length) {
+ node.endSourcePosition =
+ new TokenSourceFileLocation(sourceFile, endToken);
+ }
}
return node;
}
@@ -179,18 +189,6 @@
return generateAtUseSite.contains(instruction);
}
- bool isNonNegativeInt32Constant(HInstruction instruction) {
- if (instruction.isConstantInteger()) {
- HConstant constantInstruction = instruction;
- PrimitiveConstant primitiveConstant = constantInstruction.constant;
- int value = primitiveConstant.value;
- if (value >= 0 && value < (1 << 31)) {
- return true;
- }
- }
- return false;
- }
-
bool hasNonBitOpUser(HInstruction instruction, Set<HPhi> phiSet) {
for (HInstruction user in instruction.usedBy) {
if (user is HPhi) {
@@ -205,19 +203,10 @@
return false;
}
- // We want the outcome of bit-operations to be positive. However, if
- // the result of a bit-operation is only used by other bit
- // operations we do not have to convert to an unsigned
- // integer. Also, if we are using & with a positive constant we know
- // that the result is positive already and need no conversion.
- bool requiresUintConversion(HInstruction instruction) {
- if (instruction is HBitAnd) {
- HBitAnd bitAnd = instruction;
- if (isNonNegativeInt32Constant(bitAnd.left) ||
- isNonNegativeInt32Constant(bitAnd.right)) {
- return false;
- }
- }
+ bool requiresUintConversion(instruction) {
+ if (instruction.isUInt31(compiler)) return false;
+ // If the result of a bit-operation is only used by other bit
+ // operations, we do not have to convert to an unsigned integer.
return hasNonBitOpUser(instruction, new Set<HPhi>());
}
@@ -675,20 +664,30 @@
}
js.Expression key = pop();
List<js.SwitchClause> cases = <js.SwitchClause>[];
+ HSwitch switchInstruction = info.expression.end.last;
+ List<HInstruction> inputs = switchInstruction.inputs;
+ List<HBasicBlock> successors = switchInstruction.block.successors;
js.Block oldContainer = currentContainer;
- for (int i = 0; i < info.matchExpressions.length; i++) {
- for (Constant constant in info.matchExpressions[i]) {
- generateConstant(constant);
+ for (int inputIndex = 1, statementIndex = 0;
+ inputIndex < inputs.length;
+ statementIndex++) {
+ HBasicBlock successor = successors[inputIndex - 1];
+ do {
+ visit(inputs[inputIndex]);
currentContainer = new js.Block.empty();
cases.add(new js.Case(pop(), currentContainer));
- }
- if (i == info.matchExpressions.length - 1) {
- currentContainer = new js.Block.empty();
- cases.add(new js.Default(currentContainer));
- }
- generateStatements(info.statements[i]);
+ inputIndex++;
+ } while ((successors[inputIndex - 1] == successor)
+ && (inputIndex < inputs.length));
+
+ generateStatements(info.statements[statementIndex]);
}
+
+ currentContainer = new js.Block.empty();
+ cases.add(new js.Default(currentContainer));
+ generateStatements(info.statements.last);
+
currentContainer = oldContainer;
js.Statement result = new js.Switch(key, cases);
@@ -1198,7 +1197,7 @@
// shift operator to achieve this.
visitBitInvokeBinary(HBinaryBitOp node, String op) {
visitInvokeBinary(node, op);
- if (requiresUintConversion(node)) {
+ if (op != '>>>' && requiresUintConversion(node)) {
push(new js.Binary(">>>", pop(), new js.LiteralNumber("0")), node);
}
}
@@ -1257,6 +1256,7 @@
visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|');
visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^');
visitShiftLeft(HShiftLeft node) => visitBitInvokeBinary(node, '<<');
+ visitShiftRight(HShiftRight node) => visitBitInvokeBinary(node, '>>>');
visitNegate(HNegate node) => visitInvokeUnary(node, '-');
@@ -1983,10 +1983,14 @@
}
js.Call value = new js.Call(jsHelper, arguments);
attachLocation(value, location);
- // BUG(4906): Using throw here adds to the size of the generated code
+ // BUG(4906): Using throw/return here adds to the size of the generated code
// but it has the advantage of explicitly telling the JS engine that
// this code path will terminate abruptly. Needs more work.
- pushStatement(new js.Throw(value));
+ if (helperName == 'wrapException') {
+ pushStatement(new js.Throw(value));
+ } else {
+ pushStatement(new js.Return(value));
+ }
}
visitThrowExpression(HThrowExpression node) {
@@ -2509,7 +2513,7 @@
String methodName =
backend.namer.invocationName(node.receiverTypeCheckSelector);
js.Expression call = jsPropertyCall(pop(), methodName, []);
- pushStatement(new js.Throw(call));
+ pushStatement(new js.Return(call));
}
currentContainer = oldContainer;
body = unwrapStatement(body);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/from_ir_builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/from_ir_builder.dart
new file mode 100644
index 0000000..4d97830
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/ssa/from_ir_builder.dart
@@ -0,0 +1,128 @@
+// 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.
+
+part of ssa;
+
+class SsaFromIrBuilderTask extends CompilerTask {
+ SsaFromIrBuilderTask(Compiler compiler) : super(compiler);
+
+ HGraph build(CodegenWorkItem work) {
+ return measure(() {
+ Element element = work.element.implementation;
+ return compiler.withCurrentElement(element, () {
+ HInstruction.idCounter = 0;
+ SsaFromIrBuilder builder = new SsaFromIrBuilder(compiler, element);
+
+ HGraph graph;
+ ElementKind kind = element.kind;
+ if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
+ throw "Build HGraph for constructor from IR";
+// graph = compileConstructor(builder, work);
+ } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY ||
+ kind == ElementKind.FUNCTION ||
+ kind == ElementKind.GETTER ||
+ kind == ElementKind.SETTER) {
+ graph = builder.buildMethod();
+ } else if (kind == ElementKind.FIELD) {
+ throw "Build HGraph for field from IR";
+// assert(!element.isInstanceMember());
+// graph = builder.buildLazyInitializer(element);
+ } else {
+ compiler.internalErrorOnElement(element,
+ 'unexpected element kind $kind');
+ }
+ assert(graph.isValid());
+ // TODO(lry): for default arguments, register constants in backend.
+ // TODO(lry): tracing (factor out code in SsaBuilderTask).
+ return graph;
+ });
+ });
+ }
+}
+
+/**
+ * This builder generates SSA nodes for elements that have an IR representation.
+ * It mixes in [SsaGraphBuilderMixin] to share functionality with the
+ * [SsaBuilder] that creates SSA nodes from trees.
+ */
+class SsaFromIrBuilder
+ extends IrNodesVisitor<HInstruction> with SsaGraphBuilderMixin {
+ final Compiler compiler;
+
+ final Element sourceElement;
+
+ SsaFromIrBuilder(this.compiler, this.sourceElement);
+
+ /**
+ * Maps IR nodes ot the generated [HInstruction]. Because the IR is itself
+ * in an SSA form, the arguments of an [IrNode] have already been visited
+ * prior to the node. This map is used to obtain the corresponding generated
+ * SSA node.
+ */
+ final Map<IrNode, HInstruction> generated = new Map<IrNode, HInstruction>();
+
+ HInstruction recordGenerated(IrNode irNode, HInstruction ssaNode) {
+ return generated[irNode] = ssaNode;
+ }
+
+ HInstruction attachPosition(HInstruction target, IrNode node) {
+ target.sourcePosition = sourceFileLocation(node);
+ return target;
+ }
+
+ SourceFileLocation sourceFileLocation(IrNode node) {
+ Element element = sourceElement;
+ // TODO(johnniwinther): remove the 'element.patch' hack.
+ if (element is FunctionElement) {
+ FunctionElement functionElement = element;
+ if (functionElement.patch != null) element = functionElement.patch;
+ }
+ Script script = element.getCompilationUnit().script;
+ SourceFile sourceFile = script.file;
+ SourceFileLocation location =
+ new OffsetSourceFileLocation(sourceFile, node.offset, node.sourceName);
+ if (!location.isValid()) {
+ throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message(
+ {'offset': node.offset,
+ 'fileName': sourceFile.filename,
+ 'length': sourceFile.length});
+ }
+ return location;
+ }
+
+ HGraph buildMethod() {
+ graph.calledInLoop = compiler.world.isCalledInLoop(sourceElement);
+
+ open(graph.entry);
+ HBasicBlock block = graph.addNewBlock();
+ close(new HGoto()).addSuccessor(block);
+ open(block);
+
+ IrFunction function = compiler.irBuilder.getIr(sourceElement);
+ visitAll(function.statements);
+ if (!isAborted()) closeAndGotoExit(new HGoto());
+ graph.finalize();
+ return graph;
+ }
+
+ HInstruction visitIrConstant(IrConstant node) {
+ return recordGenerated(node, graph.addConstant(node.value, compiler));
+ }
+
+ HInstruction visitIrReturn(IrReturn node) {
+ assert(isReachable);
+ HInstruction value = generated[node.value];
+ // TODO(lry): add code for dynamic type check.
+ // value = potentiallyCheckType(value, returnType);
+ closeAndGotoExit(attachPosition(new HReturn(value), node));
+ }
+
+ HInstruction visitNode(IrNode node) {
+ abort(node);
+ }
+
+ void abort(IrNode node) {
+ throw 'Cannot build SSA from IR for $node';
+ }
+}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/from_ir_inliner.dart b/sdk/lib/_internal/compiler/implementation/ssa/from_ir_inliner.dart
new file mode 100644
index 0000000..9a67f39
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/ssa/from_ir_inliner.dart
@@ -0,0 +1,76 @@
+// 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.
+
+part of ssa;
+
+class SsaFromIrInliner extends IrNodesVisitor {
+
+ final SsaBuilder builder;
+
+ SsaFromIrInliner(this.builder);
+
+ final Map<IrNode, HInstruction> emitted = new Map<IrNode, HInstruction>();
+
+ Compiler get compiler => builder.compiler;
+
+ void visitIrReturn(IrReturn node) {
+ HInstruction hValue = emitted[node.value];
+ builder.localsHandler.updateLocal(builder.returnElement, hValue);
+ }
+
+ void visitIrConstant(IrConstant node) {
+ emitted[node] = builder.graph.addConstant(node.value, compiler);
+ }
+
+ void visitNode(IrNode node) {
+ compiler.internalError('Unexpected IrNode $node');
+ }
+}
+
+class IrInlineWeeder extends IrNodesVisitor {
+ static bool canBeInlined(IrFunction irFunction,
+ int maxInliningNodes,
+ bool useMaxInliningNodes) {
+ IrInlineWeeder weeder =
+ new IrInlineWeeder(maxInliningNodes, useMaxInliningNodes);
+ weeder.visitAll(irFunction.statements);
+ return !weeder.tooDifficult;
+ }
+
+ final int maxInliningNodes;
+ final bool useMaxInliningNodes;
+
+ IrInlineWeeder(this.maxInliningNodes, this.useMaxInliningNodes);
+
+ bool seenReturn = false;
+ bool tooDifficult = false;
+ int nodeCount = 0;
+
+ bool registerNode() {
+ if (!useMaxInliningNodes) return true;
+ if (nodeCount++ > maxInliningNodes) {
+ tooDifficult = true;
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ void visitNode(IrNode node) {
+ if (!registerNode()) return;
+ if (seenReturn) {
+ tooDifficult = true;
+ }
+ }
+
+ void visitIrReturn(IrReturn node) {
+ visitNode(node);
+ seenReturn = true;
+ }
+
+ void visitIrFunction(IrFunction node) {
+ tooDifficult = true;
+ }
+
+}
\ No newline at end of file
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
index b193fa2..e4a4ad8 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
@@ -268,7 +268,7 @@
node.element,
<HInstruction>[constant, node.inputs[1]],
node.instructionType);
- } else if (node.selector.isSetter()) {
+ } else if (selector.isSetter()) {
instruction = new HInvokeDynamicSetter(
selector,
node.element,
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
index 87088e8..54827a9 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/invoke_dynamic_specializers.dart
@@ -135,7 +135,7 @@
// integer or throw an error.
JavaScriptBackend backend = compiler.backend;
if (instruction.inputs[1].isPrimitiveOrNull(compiler)) {
- return backend.intType;
+ return backend.uint32Type;
}
return super.computeTypeFromInputTypes(instruction, compiler);
}
@@ -145,7 +145,8 @@
JavaScriptBackend backend = compiler.backend;
HInstruction input = instruction.inputs[1];
if (input.isNumber(compiler)) {
- return new HBitNot(input, instruction.selector, backend.intType);
+ return new HBitNot(input, instruction.selector,
+ computeTypeFromInputTypes(instruction, compiler));
}
return null;
}
@@ -208,12 +209,24 @@
// Even if there is no builtin equivalent instruction, we know
// the instruction does not have any side effect, and that it
// can be GVN'ed.
- instruction.sideEffects.clearAllSideEffects();
- instruction.sideEffects.clearAllDependencies();
- instruction.setUseGvn();
+ clearAllSideEffects(instruction);
}
return null;
}
+
+ void clearAllSideEffects(HInstruction instruction) {
+ instruction.sideEffects.clearAllSideEffects();
+ instruction.sideEffects.clearAllDependencies();
+ instruction.setUseGvn();
+ }
+
+ bool inputsArePositiveIntegers(HInstruction instruction, Compiler compiler) {
+ HInstruction left = instruction.inputs[1];
+ HInstruction right = instruction.inputs[2];
+ JavaScriptBackend backend = compiler.backend;
+ return left.isPositiveIntegerOrNull(compiler)
+ && right.isPositiveIntegerOrNull(compiler);
+ }
HInstruction newBuiltinVariant(HInvokeDynamic instruction, Compiler compiler);
}
@@ -221,6 +234,15 @@
class AddSpecializer extends BinaryArithmeticSpecializer {
const AddSpecializer();
+ TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
+ Compiler compiler) {
+ if (inputsArePositiveIntegers(instruction, compiler)) {
+ JavaScriptBackend backend = compiler.backend;
+ return backend.positiveIntType;
+ }
+ return super.computeTypeFromInputTypes(instruction, compiler);
+ }
+
BinaryOperation operation(ConstantSystem constantSystem) {
return constantSystem.add;
}
@@ -262,6 +284,15 @@
class ModuloSpecializer extends BinaryArithmeticSpecializer {
const ModuloSpecializer();
+ TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
+ Compiler compiler) {
+ if (inputsArePositiveIntegers(instruction, compiler)) {
+ JavaScriptBackend backend = compiler.backend;
+ return backend.positiveIntType;
+ }
+ return super.computeTypeFromInputTypes(instruction, compiler);
+ }
+
BinaryOperation operation(ConstantSystem constantSystem) {
return constantSystem.modulo;
}
@@ -280,6 +311,15 @@
return constantSystem.multiply;
}
+ TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
+ Compiler compiler) {
+ if (inputsArePositiveIntegers(instruction, compiler)) {
+ JavaScriptBackend backend = compiler.backend;
+ return backend.positiveIntType;
+ }
+ return super.computeTypeFromInputTypes(instruction, compiler);
+ }
+
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
Compiler compiler) {
return new HMultiply(
@@ -310,6 +350,15 @@
return constantSystem.truncatingDivide;
}
+ TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
+ Compiler compiler) {
+ if (inputsArePositiveIntegers(instruction, compiler)) {
+ JavaScriptBackend backend = compiler.backend;
+ return backend.positiveIntType;
+ }
+ return super.computeTypeFromInputTypes(instruction, compiler);
+ }
+
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
Compiler compiler) {
// Truncating divide does not have a JS equivalent.
@@ -327,10 +376,24 @@
HInstruction left = instruction.inputs[1];
JavaScriptBackend backend = compiler.backend;
if (left.isPrimitiveOrNull(compiler)) {
- return backend.intType;
+ return backend.uint32Type;
}
return super.computeTypeFromInputTypes(instruction, compiler);
}
+
+ bool argumentLessThan32(HInstruction instruction) {
+ if (!instruction.isConstantInteger()) return false;
+ HConstant rightConstant = instruction;
+ IntConstant intConstant = rightConstant.constant;
+ int count = intConstant.value;
+ return count >= 0 && count <= 31;
+ }
+
+ bool isPositive(HInstruction instruction, Compiler compiler) {
+ // TODO: We should use the value range analysis. Currently, ranges
+ // are discarded just after the analysis.
+ return instruction.isPositiveInteger(compiler);
+ }
}
class ShiftLeftSpecializer extends BinaryBitOpSpecializer {
@@ -344,9 +407,14 @@
Compiler compiler) {
HInstruction left = instruction.inputs[1];
HInstruction right = instruction.inputs[2];
- if (!left.isNumber(compiler)) return null;
- if (argumentLessThan32(right)) {
- return newBuiltinVariant(instruction, compiler);
+ if (left.isNumber(compiler)) {
+ if (argumentLessThan32(right)) {
+ return newBuiltinVariant(instruction, compiler);
+ }
+ // Even if there is no builtin equivalent instruction, we know
+ // the instruction does not have any side effect, and that it
+ // can be GVN'ed.
+ clearAllSideEffects(instruction);
}
return null;
}
@@ -356,25 +424,44 @@
JavaScriptBackend backend = compiler.backend;
return new HShiftLeft(
instruction.inputs[1], instruction.inputs[2],
- instruction.selector, backend.intType);
- }
-
- bool argumentLessThan32(HInstruction instruction) {
- if (!instruction.isConstantInteger()) return false;
- HConstant rightConstant = instruction;
- IntConstant intConstant = rightConstant.constant;
- int count = intConstant.value;
- return count >= 0 && count <= 31;
+ instruction.selector, computeTypeFromInputTypes(instruction, compiler));
}
}
class ShiftRightSpecializer extends BinaryBitOpSpecializer {
const ShiftRightSpecializer();
+ TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
+ Compiler compiler) {
+ HInstruction left = instruction.inputs[1];
+ HInstruction right = instruction.inputs[2];
+ JavaScriptBackend backend = compiler.backend;
+ if (left.isUInt32(compiler)) return left.instructionType;
+ return super.computeTypeFromInputTypes(instruction, compiler);
+ }
+
+ HInstruction tryConvertToBuiltin(HInvokeDynamic instruction,
+ Compiler compiler) {
+ HInstruction left = instruction.inputs[1];
+ HInstruction right = instruction.inputs[2];
+ if (left.isNumber(compiler)) {
+ if (argumentLessThan32(right) && isPositive(left, compiler)) {
+ return newBuiltinVariant(instruction, compiler);
+ }
+ // Even if there is no builtin equivalent instruction, we know
+ // the instruction does not have any side effect, and that it
+ // can be GVN'ed.
+ clearAllSideEffects(instruction);
+ }
+ return null;
+ }
+
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
Compiler compiler) {
- // Shift right cannot be mapped to the native operator easily.
- return null;
+ JavaScriptBackend backend = compiler.backend;
+ return new HShiftRight(
+ instruction.inputs[1], instruction.inputs[2],
+ instruction.selector, computeTypeFromInputTypes(instruction, compiler));
}
BinaryOperation operation(ConstantSystem constantSystem) {
@@ -389,12 +476,23 @@
return constantSystem.bitOr;
}
+ TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
+ Compiler compiler) {
+ HInstruction left = instruction.inputs[1];
+ HInstruction right = instruction.inputs[2];
+ JavaScriptBackend backend = compiler.backend;
+ if (left.isUInt31(compiler) && right.isUInt31(compiler)) {
+ return backend.uint31Type;
+ }
+ return super.computeTypeFromInputTypes(instruction, compiler);
+ }
+
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
Compiler compiler) {
JavaScriptBackend backend = compiler.backend;
return new HBitOr(
instruction.inputs[1], instruction.inputs[2],
- instruction.selector, backend.intType);
+ instruction.selector, computeTypeFromInputTypes(instruction, compiler));
}
}
@@ -405,12 +503,23 @@
return constantSystem.bitAnd;
}
+ TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
+ Compiler compiler) {
+ HInstruction left = instruction.inputs[1];
+ HInstruction right = instruction.inputs[2];
+ JavaScriptBackend backend = compiler.backend;
+ if (left.isUInt31(compiler) || right.isUInt31(compiler)) {
+ return backend.uint31Type;
+ }
+ return super.computeTypeFromInputTypes(instruction, compiler);
+ }
+
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
Compiler compiler) {
JavaScriptBackend backend = compiler.backend;
return new HBitAnd(
instruction.inputs[1], instruction.inputs[2],
- instruction.selector, backend.intType);
+ instruction.selector, computeTypeFromInputTypes(instruction, compiler));
}
}
@@ -421,12 +530,23 @@
return constantSystem.bitXor;
}
+ TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction,
+ Compiler compiler) {
+ HInstruction left = instruction.inputs[1];
+ HInstruction right = instruction.inputs[2];
+ JavaScriptBackend backend = compiler.backend;
+ if (left.isUInt31(compiler) && right.isUInt31(compiler)) {
+ return backend.uint31Type;
+ }
+ return super.computeTypeFromInputTypes(instruction, compiler);
+ }
+
HInstruction newBuiltinVariant(HInvokeDynamic instruction,
Compiler compiler) {
JavaScriptBackend backend = compiler.backend;
return new HBitXor(
instruction.inputs[1], instruction.inputs[2],
- instruction.selector, backend.intType);
+ instruction.selector, computeTypeFromInputTypes(instruction, compiler));
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index c319986..9af57d7 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -55,6 +55,7 @@
R visitRangeConversion(HRangeConversion node);
R visitReturn(HReturn node);
R visitShiftLeft(HShiftLeft node);
+ R visitShiftRight(HShiftRight node);
R visitStatic(HStatic node);
R visitStaticStore(HStaticStore node);
R visitStringConcat(HStringConcat node);
@@ -161,30 +162,10 @@
return result;
}
- static TypeMask mapConstantTypeToSsaType(Constant constant,
- Compiler compiler) {
- JavaScriptBackend backend = compiler.backend;
- if (constant.isNull()) return backend.nullType;
- if (constant.isBool()) return backend.boolType;
- if (constant.isInt()) return backend.intType;
- if (constant.isDouble()) return backend.doubleType;
- if (constant.isString()) return backend.stringType;
- if (constant.isList()) return backend.readableArrayType;
- if (constant.isFunction()) return backend.nonNullType;
- if (constant.isSentinel()) return backend.nonNullType;
- // TODO(sra): What is the type of the prototype of an interceptor?
- if (constant.isInterceptor()) return backend.nonNullType;
- ObjectConstant objectConstant = constant;
- if (backend.isInterceptorClass(objectConstant.type.element)) {
- return backend.nonNullType;
- }
- return new TypeMask.nonNullExact(objectConstant.type.element);
- }
-
HConstant addConstant(Constant constant, Compiler compiler) {
HConstant result = constants[constant];
if (result == null) {
- TypeMask type = mapConstantTypeToSsaType(constant, compiler);
+ TypeMask type = constant.computeMask(compiler);
result = new HConstant.internal(constant, type);
entry.addAtExit(result);
constants[constant] = result;
@@ -205,10 +186,9 @@
}
HConstant addConstantString(DartString str,
- Node diagnosticNode,
Compiler compiler) {
return addConstant(
- compiler.backend.constantSystem.createString(str, diagnosticNode),
+ compiler.backend.constantSystem.createString(str),
compiler);
}
@@ -336,6 +316,7 @@
visitRangeConversion(HRangeConversion node) => visitCheck(node);
visitReturn(HReturn node) => visitControlFlow(node);
visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node);
+ visitShiftRight(HShiftRight node) => visitBinaryBitOp(node);
visitSubtract(HSubtract node) => visitBinaryArithmetic(node);
visitSwitch(HSwitch node) => visitControlFlow(node);
visitStatic(HStatic node) => visitInstruction(node);
@@ -801,6 +782,7 @@
static const int INDEX_TYPECODE = 27;
static const int IS_TYPECODE = 28;
static const int INVOKE_DYNAMIC_TYPECODE = 29;
+ static const int SHIFT_RIGHT_TYPECODE = 30;
HInstruction(this.inputs, this.instructionType)
: id = idCounter++, usedBy = <HInstruction>[] {
@@ -918,6 +900,29 @@
&& !instructionType.isNullable;
}
+ bool isUInt32(Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
+ return !instructionType.isNullable
+ && instructionType.satisfies(backend.jsUInt32Class, compiler);
+ }
+
+ bool isUInt31(Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
+ return !instructionType.isNullable
+ && instructionType.satisfies(backend.jsUInt31Class, compiler);
+ }
+
+ bool isPositiveInteger(Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
+ return !instructionType.isNullable
+ && instructionType.satisfies(backend.jsPositiveIntClass, compiler);
+ }
+
+ bool isPositiveIntegerOrNull(Compiler compiler) {
+ JavaScriptBackend backend = compiler.backend;
+ return instructionType.satisfies(backend.jsPositiveIntClass, compiler);
+ }
+
bool isIntegerOrNull(Compiler compiler) {
return instructionType.containsOnlyInt(compiler);
}
@@ -1571,6 +1576,7 @@
class HForeign extends HInstruction {
final js.Node codeAst;
final bool isStatement;
+ final bool _canThrow;
final native.NativeBehavior nativeBehavior;
HForeign(this.codeAst,
@@ -1578,8 +1584,11 @@
List<HInstruction> inputs,
{this.isStatement: false,
SideEffects effects,
- native.NativeBehavior nativeBehavior})
- : this.nativeBehavior = nativeBehavior, super(inputs, type) {
+ native.NativeBehavior nativeBehavior,
+ canThrow: false})
+ : this.nativeBehavior = nativeBehavior,
+ this._canThrow = canThrow,
+ super(inputs, type) {
if (effects == null && nativeBehavior != null) {
effects = nativeBehavior.sideEffects;
}
@@ -1597,7 +1606,9 @@
bool isJsStatement() => isStatement;
bool canThrow() {
- return sideEffects.hasSideEffects() || sideEffects.dependsOnSomething();
+ return _canThrow
+ || sideEffects.hasSideEffects()
+ || sideEffects.dependsOnSomething();
}
}
@@ -1721,6 +1732,17 @@
bool dataEquals(HInstruction other) => true;
}
+class HShiftRight extends HBinaryBitOp {
+ HShiftRight(left, right, selector, type) : super(left, right, selector, type);
+ accept(HVisitor visitor) => visitor.visitShiftRight(this);
+
+ BinaryOperation operation(ConstantSystem constantSystem)
+ => constantSystem.shiftRight;
+ int typeCode() => HInstruction.SHIFT_RIGHT_TYPECODE;
+ bool typeEquals(other) => other is HShiftRight;
+ bool dataEquals(HInstruction other) => true;
+}
+
class HBitOr extends HBinaryBitOp {
HBitOr(left, right, selector, type) : super(left, right, selector, type);
accept(HVisitor visitor) => visitor.visitBitOr(this);
@@ -2806,13 +2828,11 @@
class HSwitchBlockInformation implements HStatementInformation {
final HExpressionInformation expression;
- final List<List<Constant>> matchExpressions;
final List<HStatementInformation> statements;
final TargetElement target;
final List<LabelElement> labels;
HSwitchBlockInformation(this.expression,
- this.matchExpressions,
this.statements,
this.target,
this.labels);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index 364fdc5..89ec2e7 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -214,7 +214,7 @@
Element element = backend.jsIndexableLength;
bool isFixed = isFixedLength(actualReceiver.instructionType, compiler);
HFieldGet result = new HFieldGet(
- element, actualReceiver, backend.intType,
+ element, actualReceiver, backend.positiveIntType,
isAssignable: !isFixed);
return result;
} else if (actualReceiver.isConstantMap()) {
@@ -776,8 +776,7 @@
HInstruction folded = graph.addConstant(
constantSystem.createString(
- new DartString.concat(leftString.value, rightString.value),
- node.node),
+ new DartString.concat(leftString.value, rightString.value)),
compiler);
if (prefix == null) return folded;
return new HStringConcat(prefix, folded, node.node, backend.stringType);
@@ -791,7 +790,7 @@
if (!constant.constant.isPrimitive()) return node;
PrimitiveConstant primitive = constant.constant;
return graph.addConstant(constantSystem.createString(
- primitive.toDartString(), node.node), compiler);
+ primitive.toDartString()), compiler);
}
return node;
}
@@ -831,12 +830,15 @@
HInstruction indexArgument) {
Compiler compiler = backend.compiler;
HFieldGet length = new HFieldGet(
- backend.jsIndexableLength, array, backend.intType,
+ backend.jsIndexableLength, array, backend.positiveIntType,
isAssignable: !isFixedLength(array.instructionType, compiler));
indexNode.block.addBefore(indexNode, length);
+ TypeMask type = indexArgument.isPositiveInteger(compiler)
+ ? indexArgument.instructionType
+ : backend.positiveIntType;
HBoundsCheck check = new HBoundsCheck(
- indexArgument, length, array, backend.intType);
+ indexArgument, length, array, type);
indexNode.block.addBefore(indexNode, check);
// If the index input to the bounds check was not known to be an integer
// then we replace its uses with the bounds check, which is known to be an
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart b/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart
index 5b0cc17..64c9200 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart
@@ -16,6 +16,7 @@
import '../js_backend/js_backend.dart';
import '../native_handler.dart' as native;
import '../tree/tree.dart';
+import '../ir/ir_nodes.dart';
import '../types/types.dart';
import '../universe/universe.dart';
import '../util/util.dart';
@@ -30,6 +31,8 @@
import '../js_emitter/js_emitter.dart' show CodeEmitterTask;
part 'builder.dart';
+part 'from_ir_builder.dart';
+part 'from_ir_inliner.dart';
part 'codegen.dart';
part 'codegen_helpers.dart';
part 'interceptor_simplifier.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
index 3a86a9d..b56cd35 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/tracer.dart
@@ -426,6 +426,7 @@
String visitReturn(HReturn node) => "Return ${temporaryId(node.inputs[0])}";
String visitShiftLeft(HShiftLeft node) => handleInvokeBinary(node, '<<');
+ String visitShiftRight(HShiftRight node) => handleInvokeBinary(node, '>>');
String visitStatic(HStatic node)
=> "Static ${node.element.name}";
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
index 9ff28dc..82b32ba 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
@@ -107,6 +107,24 @@
return backend.numType;
}
+ TypeMask checkPositiveInteger(HBinaryArithmetic instruction) {
+ HInstruction left = instruction.left;
+ HInstruction right = instruction.right;
+ JavaScriptBackend backend = compiler.backend;
+ if (left.isPositiveInteger(compiler) && right.isPositiveInteger(compiler)) {
+ return backend.positiveIntType;
+ }
+ return visitBinaryArithmetic(instruction);
+ }
+
+ TypeMask visitMultiply(HMultiply instruction) {
+ return checkPositiveInteger(instruction);
+ }
+
+ TypeMask visitAdd(HAdd instruction) {
+ return checkPositiveInteger(instruction);
+ }
+
TypeMask visitNegate(HNegate instruction) {
return instruction.operand.instructionType;
}
@@ -249,7 +267,7 @@
if (right.isNumber(compiler)) return false;
JavaScriptBackend backend = compiler.backend;
TypeMask type = right.isIntegerOrNull(compiler)
- ? backend.intType
+ ? right.instructionType.nonNullable()
: backend.numType;
// TODO(ngeoffray): Some number operations don't have a builtin
// variant and will do the check in their method anyway. We
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart b/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
index e36bec1..1e43997 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/value_range_analyzer.dart
@@ -24,8 +24,8 @@
return new InstructionValue(instruction, this);
}
- Value newLengthValue(HInstruction instruction) {
- return new LengthValue(instruction, this);
+ Value newPositiveValue(HInstruction instruction) {
+ return new PositiveValue(instruction, this);
}
Value newAddValue(Value left, Value right) {
@@ -291,14 +291,11 @@
}
/**
- * Special value for instructions that represent the length of an
- * array. The difference with an [InstructionValue] is that we know
- * the value is positive.
+ * Special value for instructions whose type is a positive integer.
*/
-class LengthValue extends InstructionValue {
- LengthValue(HInstruction instruction, info) : super(instruction, info);
+class PositiveValue extends InstructionValue {
+ PositiveValue(HInstruction instruction, info) : super(instruction, info);
bool get isPositive => true;
- String toString() => 'Length: $instruction';
}
/**
@@ -637,13 +634,15 @@
}
Range visitInstruction(HInstruction instruction) {
- return info.newUnboundRange();
- }
-
- Range visitParameterValue(HParameterValue parameter) {
- if (!parameter.isInteger(compiler)) return info.newUnboundRange();
- Value value = info.newInstructionValue(parameter);
- return info.newNormalizedRange(value, value);
+ if (instruction.isPositiveInteger(compiler)) {
+ return info.newNormalizedRange(
+ info.intZero, info.newPositiveValue(instruction));
+ } else if (instruction.isInteger(compiler)) {
+ InstructionValue value = info.newInstructionValue(instruction);
+ return info.newNormalizedRange(value, value);
+ } else {
+ return info.newUnboundRange();
+ }
}
Range visitPhi(HPhi phi) {
@@ -682,7 +681,7 @@
}
JavaScriptBackend backend = compiler.backend;
assert(fieldGet.element == backend.jsIndexableLength);
- LengthValue value = info.newLengthValue(fieldGet);
+ PositiveValue value = info.newPositiveValue(fieldGet);
// We know this range is above zero. To simplify the analysis, we
// put the zero value as the lower bound of this range. This
// allows to easily remove the second bound check in the following
@@ -825,7 +824,7 @@
Range visitCheck(HCheck instruction) {
if (ranges[instruction.checkedInput] == null) {
- return info.newUnboundRange();
+ return visitInstruction(instruction);
}
return ranges[instruction.checkedInput];
}
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart
index d060765..f5eccfd 100644
--- a/sdk/lib/_internal/compiler/implementation/typechecker.dart
+++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
@@ -185,7 +185,7 @@
}
String toString() {
- return 'Promote ${variable} to ${type}';
+ return 'Promote ${variable} to ${type}${isValid ? '' : ' (invalid)'}';
}
}
@@ -410,16 +410,18 @@
}
}
- void reshowTypePromotions(Node node, Node receiver, Node argument) {
- for (TypePromotion typePromotion in getShownTypePromotionsFor(receiver)) {
+ /// Show type promotions from [left] and [right] in [node] given that the
+ /// promoted variables are not potentially mutated in [right].
+ void reshowTypePromotions(Node node, Node left, Node right) {
+ for (TypePromotion typePromotion in getShownTypePromotionsFor(left)) {
typePromotion = typePromotion.copy();
- checkTypePromotion(argument, typePromotion);
+ checkTypePromotion(right, typePromotion);
showTypePromotion(node, typePromotion);
}
- for (TypePromotion typePromotion in getShownTypePromotionsFor(argument)) {
+ for (TypePromotion typePromotion in getShownTypePromotionsFor(right)) {
typePromotion = typePromotion.copy();
- checkTypePromotion(argument, typePromotion);
+ checkTypePromotion(right, typePromotion);
showTypePromotion(node, typePromotion);
}
}
@@ -931,6 +933,17 @@
analyze(node.receiver);
if (!node.isIsNotCheck) {
Element variable = elements[node.receiver];
+ if (variable == null) {
+ // Look for the variable element within parenthesized expressions.
+ ParenthesizedExpression parentheses =
+ node.receiver.asParenthesizedExpression();
+ while (parentheses != null) {
+ variable = elements[parentheses.expression];
+ if (variable != null) break;
+ parentheses = parentheses.expression.asParenthesizedExpression();
+ }
+ }
+
if (variable != null &&
(variable.isVariable() || variable.isParameter())) {
DartType knownType = getKnownType(variable);
@@ -1410,7 +1423,12 @@
}
DartType visitParenthesizedExpression(ParenthesizedExpression node) {
- return analyze(node.expression);
+ Expression expression = node.expression;
+ DartType type = analyze(expression);
+ for (TypePromotion typePromotion in getShownTypePromotionsFor(expression)) {
+ showTypePromotion(node, typePromotion);
+ }
+ return type;
}
DartType visitConditional(Conditional node) {
@@ -1422,13 +1440,7 @@
DartType thenType = analyzeInPromotedContext(condition, thenExpression);
DartType elseType = analyzeNonVoid(node.elseExpression);
- if (types.isSubtype(thenType, elseType)) {
- return thenType;
- } else if (types.isSubtype(elseType, thenType)) {
- return elseType;
- } else {
- return objectType;
- }
+ return compiler.types.computeLeastUpperBound(thenType, elseType);
}
visitStringInterpolation(StringInterpolation node) {
@@ -1496,6 +1508,7 @@
ClassElement cls = type.element;
if (cls == compiler.doubleClass) return true;
if (cls == compiler.intClass || cls == compiler.stringClass) return false;
+ if (cls == compiler.typeClass) return true;
Element equals = cls.lookupMember('==');
return equals.getEnclosingClass() != compiler.objectClass;
}
@@ -1550,7 +1563,8 @@
if (firstCaseType != null &&
invalidSwitchExpressionType(firstCase, firstCaseType)) {
compiler.reportError(firstCase.expression,
- MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS);
+ MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS,
+ {'type': firstCaseType});
}
return StatementType.NOT_RETURNING;
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index d22f263..5a2b13f 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -1083,6 +1083,10 @@
throw new UnsupportedError("");
}
+ bool isFixedArrayCheckedForGrowable(Node node) {
+ throw new UnsupportedError("");
+ }
+
// --- analysis ---
/**
diff --git a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
index c2e7ada..b013f68 100644
--- a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
@@ -92,14 +92,16 @@
return allocationNode == other.allocationNode
&& isNullable == other.isNullable
&& elementType == other.elementType
- && length == other.length;
+ && length == other.length
+ && forwardTo == other.forwardTo;
}
int get hashCode {
- return computeHashCode(allocationNode, isNullable, elementType, length);
+ return computeHashCode(
+ allocationNode, isNullable, elementType, length, forwardTo);
}
String toString() {
- return 'Container mask: $elementType $length';
+ return 'Container mask: $elementType length: $length type: $forwardTo';
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
index 7be08f1..2e99ab4 100644
--- a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
@@ -96,7 +96,11 @@
return cls == compiler.boolClass || cls == backend.boolImplementation;
}
if (containsOnlyInt(compiler)) {
- return cls == compiler.intClass || cls == backend.intImplementation;
+ return cls == compiler.intClass
+ || cls == backend.intImplementation
+ || cls == backend.positiveIntImplementation
+ || cls == backend.uint32Implementation
+ || cls == backend.uint31Implementation;
}
if (containsOnlyDouble(compiler)) {
return cls == compiler.doubleClass
@@ -132,7 +136,10 @@
bool containsOnlyInt(Compiler compiler) {
return base == compiler.intClass
- || base == compiler.backend.intImplementation;
+ || base == compiler.backend.intImplementation
+ || base == compiler.backend.positiveIntImplementation
+ || base == compiler.backend.uint31Implementation
+ || base == compiler.backend.uint32Implementation;
}
bool containsOnlyDouble(Compiler compiler) {
diff --git a/sdk/lib/_internal/compiler/implementation/types/types.dart b/sdk/lib/_internal/compiler/implementation/types/types.dart
index 1d3ac5c..d1ab26c 100644
--- a/sdk/lib/_internal/compiler/implementation/types/types.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/types.dart
@@ -32,6 +32,7 @@
void clear();
Iterable<Element> getCallersOf(Element element);
bool isCalledOnce(Element element);
+ bool isFixedArrayCheckedForGrowable(Node node);
}
/**
@@ -52,8 +53,12 @@
}
TypeMask dynamicTypeCache;
+ TypeMask nonNullTypeCache;
TypeMask nullTypeCache;
TypeMask intTypeCache;
+ TypeMask uint32TypeCache;
+ TypeMask uint31TypeCache;
+ TypeMask positiveIntTypeCache;
TypeMask doubleTypeCache;
TypeMask numTypeCache;
TypeMask boolTypeCache;
@@ -74,14 +79,45 @@
return dynamicTypeCache;
}
+ TypeMask get nonNullType {
+ if (nonNullTypeCache == null) {
+ nonNullTypeCache = new TypeMask.nonNullSubclass(compiler.objectClass);
+ }
+ return nonNullTypeCache;
+ }
+
TypeMask get intType {
if (intTypeCache == null) {
- intTypeCache = new TypeMask.nonNullExact(
+ intTypeCache = new TypeMask.nonNullSubclass(
compiler.backend.intImplementation);
}
return intTypeCache;
}
+ TypeMask get uint32Type {
+ if (uint32TypeCache == null) {
+ uint32TypeCache = new TypeMask.nonNullSubclass(
+ compiler.backend.uint32Implementation);
+ }
+ return uint32TypeCache;
+ }
+
+ TypeMask get uint31Type {
+ if (uint31TypeCache == null) {
+ uint31TypeCache = new TypeMask.nonNullExact(
+ compiler.backend.uint31Implementation);
+ }
+ return uint31TypeCache;
+ }
+
+ TypeMask get positiveIntType {
+ if (positiveIntTypeCache == null) {
+ positiveIntTypeCache = new TypeMask.nonNullSubclass(
+ compiler.backend.positiveIntImplementation);
+ }
+ return positiveIntTypeCache;
+ }
+
TypeMask get doubleType {
if (doubleTypeCache == null) {
doubleTypeCache = new TypeMask.nonNullExact(
diff --git a/sdk/lib/_internal/compiler/implementation/util/util.dart b/sdk/lib/_internal/compiler/implementation/util/util.dart
index dee467d..e1d1406 100644
--- a/sdk/lib/_internal/compiler/implementation/util/util.dart
+++ b/sdk/lib/_internal/compiler/implementation/util/util.dart
@@ -37,7 +37,7 @@
final String message;
SpannableAssertionFailure(this.node, this.message);
- String toString() => 'Compiler crashed: $message';
+ String toString() => 'Assertion failure: $message';
}
/**
@@ -284,9 +284,10 @@
buffer.write(string);
}
-int computeHashCode(part1, [part2, part3, part4]) {
+int computeHashCode(part1, [part2, part3, part4, part5]) {
return (part1.hashCode
^ part2.hashCode
^ part3.hashCode
- ^ part4.hashCode) & 0x3fffffff;
+ ^ part4.hashCode
+ ^ part5.hashCode) & 0x3fffffff;
}
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart
index 6fe713d..62dcce4 100644
--- a/sdk/lib/_internal/compiler/implementation/warnings.dart
+++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -537,7 +537,7 @@
m(T t) => const C<T>();
}
-void main() => new C().m(null);
+void main() => new C().m(null);
"""
]);
@@ -567,7 +567,7 @@
static const MessageKind SWITCH_CASE_VALUE_OVERRIDES_EQUALS =
const MessageKind(
- "Error: 'case' expression type overrides 'operator=='.");
+ "Error: 'case' expression type '#{type}' overrides 'operator =='.");
static const MessageKind INVALID_ARGUMENT_AFTER_NAMED = const MessageKind(
"Error: Unnamed argument after named argument.");
diff --git a/sdk/lib/_internal/lib/isolate_helper.dart b/sdk/lib/_internal/lib/isolate_helper.dart
index 3eb0459..474d6af 100644
--- a/sdk/lib/_internal/lib/isolate_helper.dart
+++ b/sdk/lib/_internal/lib/isolate_helper.dart
@@ -102,10 +102,10 @@
// TODO(eub, sigmund): move the "manager" to be entirely in JS.
// Running any Dart code outside the context of an isolate gives it
// the chance to break the isolate abstraction.
-_Manager get _globalState => JS("_Manager", r"$globalState");
+_Manager get _globalState => JS("_Manager", "init.globalState");
set _globalState(_Manager val) {
- JS("void", r"$globalState = #", val);
+ JS("void", "init.globalState = #", val);
}
/** State associated with the current manager. See [globalState]. */
diff --git a/sdk/lib/_internal/lib/js_array.dart b/sdk/lib/_internal/lib/js_array.dart
index ec5aef9..9ce29f9 100644
--- a/sdk/lib/_internal/lib/js_array.dart
+++ b/sdk/lib/_internal/lib/js_array.dart
@@ -342,7 +342,7 @@
int get hashCode => Primitives.objectHashCode(this);
- int get length => JS('int', r'#.length', this);
+ int get length => JS('JSUInt32', r'#.length', this);
void set length(int newLength) {
if (newLength is !int) throw new ArgumentError(newLength);
diff --git a/sdk/lib/_internal/lib/js_mirrors.dart b/sdk/lib/_internal/lib/js_mirrors.dart
index 002865d..c62ffd2 100644
--- a/sdk/lib/_internal/lib/js_mirrors.dart
+++ b/sdk/lib/_internal/lib/js_mirrors.dart
@@ -278,9 +278,12 @@
var result = new Map();
for (String className in _classes) {
var cls = reflectClassByMangledName(className);
- if (cls is JsClassMirror) {
- result[cls.simpleName] = cls;
- cls._owner = this;
+ if (cls is ClassMirror) {
+ cls = cls.originalDeclaration;
+ if (cls is JsClassMirror) {
+ result[cls.simpleName] = cls;
+ cls._owner = this;
+ }
}
}
return _cachedClasses =
@@ -479,6 +482,7 @@
TypeMirror reflectClassByMangledName(String mangledName) {
String unmangledName = mangledGlobalNames[mangledName];
+ if (mangledName == 'dynamic') return JsMirrorSystem._dynamicType;
if (unmangledName == null) unmangledName = mangledName;
return reflectClassByName(s(unmangledName), mangledName);
}
@@ -492,8 +496,8 @@
disableTreeShaking();
int typeArgIndex = mangledName.indexOf("<");
if (typeArgIndex != -1) {
- mirror = new JsTypeBoundClassMirror(
- reflectClassByMangledName(mangledName.substring(0, typeArgIndex)),
+ mirror = new JsTypeBoundClassMirror(reflectClassByMangledName(
+ mangledName.substring(0, typeArgIndex)).originalDeclaration,
// Remove the angle brackets enclosing the type arguments.
mangledName.substring(typeArgIndex + 1, mangledName.length - 1));
JsCache.update(classMirrors, mangledName, mirror);
@@ -539,8 +543,19 @@
if (mixins.length > 1 && mangledGlobalNames[mangledName] == null) {
mirror = reflectMixinApplication(mixins, mangledName);
} else {
- mirror = new JsClassMirror(
+ ClassMirror classMirror = new JsClassMirror(
symbol, mangledName, constructorOrInterceptor, fields, fieldsMetadata);
+ List typeVariables =
+ JS('JSExtendableArray|Null', '#.prototype["<>"]', constructor);
+ if (typeVariables == null || typeVariables.length == 0) {
+ mirror = classMirror;
+ } else {
+ String typeArguments = 'dynamic';
+ for (int i = 1; i < typeVariables.length; i++) {
+ typeArguments += ',dynamic';
+ }
+ mirror = new JsTypeBoundClassMirror(classMirror, typeArguments);
+ }
}
JsCache.update(classMirrors, mangledName, mirror);
diff --git a/sdk/lib/_internal/lib/js_number.dart b/sdk/lib/_internal/lib/js_number.dart
index 1e3955c..b40aa4b 100644
--- a/sdk/lib/_internal/lib/js_number.dart
+++ b/sdk/lib/_internal/lib/js_number.dart
@@ -224,7 +224,7 @@
// JavaScript only looks at the last 5 bits of the shift-amount. Shifting
// by 33 is hence equivalent to a shift by 1.
if (JS('bool', r'# > 31', other)) return 0;
- return JS('int', r'(# << #) >>> 0', this, other);
+ return JS('JSUInt32', r'(# << #) >>> 0', this, other);
}
num operator >>(num other) {
@@ -238,28 +238,28 @@
// Given that 'a' is positive we must not use '>>'. Otherwise a number
// that has the 31st bit set would be treated as negative and shift in
// ones.
- return JS('int', r'# >>> #', this, other);
+ return JS('JSUInt32', r'# >>> #', this, other);
}
// For negative numbers we just clamp the shift-by amount. 'a' could be
// negative but not have its 31st bit set. The ">>" would then shift in
// 0s instead of 1s. Therefore we cannot simply return 0xFFFFFFFF.
if (JS('num', '#', other) > 31) other = 31;
- return JS('int', r'(# >> #) >>> 0', this, other);
+ return JS('JSUInt32', r'(# >> #) >>> 0', this, other);
}
num operator &(num other) {
if (other is !num) throw new ArgumentError(other);
- return JS('int', r'(# & #) >>> 0', this, other);
+ return JS('JSUInt32', r'(# & #) >>> 0', this, other);
}
num operator |(num other) {
if (other is !num) throw new ArgumentError(other);
- return JS('int', r'(# | #) >>> 0', this, other);
+ return JS('JSUInt32', r'(# | #) >>> 0', this, other);
}
num operator ^(num other) {
if (other is !num) throw new ArgumentError(other);
- return JS('int', r'(# ^ #) >>> 0', this, other);
+ return JS('JSUInt32', r'(# ^ #) >>> 0', this, other);
}
bool operator <(num other) {
@@ -358,10 +358,14 @@
Type get runtimeType => int;
- int operator ~() => JS('int', r'(~#) >>> 0', this);
+ int operator ~() => JS('JSUInt32', r'(~#) >>> 0', this);
}
class JSDouble extends JSNumber implements double {
const JSDouble();
Type get runtimeType => double;
}
+
+class JSPositiveInt extends JSInt {}
+class JSUInt32 extends JSPositiveInt {}
+class JSUInt31 extends JSUInt32 {}
diff --git a/sdk/lib/_internal/lib/js_rti.dart b/sdk/lib/_internal/lib/js_rti.dart
index d8feff5..d090dea 100644
--- a/sdk/lib/_internal/lib/js_rti.dart
+++ b/sdk/lib/_internal/lib/js_rti.dart
@@ -675,11 +675,11 @@
return false;
}
}
- sPos = 0;
- // Check the optional parameters of [t] with the remaing optional parameters
- // of [s]:
+ tPos = 0;
+ // Check the optional parameters of [t] with the remaining optional
+ // parameters of [s]:
for (; tPos < tOptionalParametersLen ; sPos++, tPos++) {
- if (!isAssignable(getIndex(tOptionalParameterTypes, sPos),
+ if (!isAssignable(getIndex(sOptionalParameterTypes, sPos),
getIndex(tOptionalParameterTypes, tPos))) {
return false;
}
diff --git a/sdk/lib/_internal/lib/native_helper.dart b/sdk/lib/_internal/lib/native_helper.dart
index 799960e..bc77c48 100644
--- a/sdk/lib/_internal/lib/native_helper.dart
+++ b/sdk/lib/_internal/lib/native_helper.dart
@@ -389,6 +389,8 @@
hooks = applyHooksTransformer(_operaHooksTransformer, hooks);
hooks = applyHooksTransformer(_safariHooksTransformer, hooks);
+ hooks = applyHooksTransformer(_fixDocumentHooksTransformer, hooks);
+
// TODO(sra): Update ShadowDOM polyfil to use
// [dartNativeDispatchHooksTransformer] and remove this hook.
hooks = applyHooksTransformer(_dartExperimentalFixupGetTagHooksTransformer,
@@ -484,14 +486,9 @@
*/
const _constructorNameFallback = const JS_CONST(r'''
function getTagFallback(o) {
- if (o == null) return "Null";
var constructor = o.constructor;
if (typeof constructor == "function") {
- var name = constructor.builtin$cls;
- if (typeof name == "string") return name;
- // The constructor is not null or undefined at this point. Try
- // to grab hold of its name.
- name = constructor.name;
+ var name = constructor.name;
// If the name is a non-empty string, we use that as the type name of this
// object. On Firefox, we often get "Object" as the constructor name even
// for more specialized objects so we have to fall through to the toString()
@@ -515,11 +512,15 @@
// TODO(sra): Recognize jsshell.
if (typeof navigator != "object") return hooks;
- var userAgent = navigator.userAgent;
+ var ua = navigator.userAgent;
// TODO(antonm): remove a reference to DumpRenderTree.
- if (userAgent.indexOf("Chrome") >= 0 ||
- userAgent.indexOf("DumpRenderTree") >= 0) {
- return hooks;
+ if (ua.indexOf("DumpRenderTree") >= 0) return hooks;
+ if (ua.indexOf("Chrome") >= 0) {
+ // Confirm constructor name is usable for dispatch.
+ function confirm(p) {
+ return typeof window == "object" && window[p] && window[p].name == p;
+ }
+ if (confirm("Window") && confirm("HTMLElement")) return hooks;
}
hooks.getTag = getTagFallback;
@@ -547,14 +548,6 @@
var tag = getTag(o);
var newTag = quickMap[tag];
if (newTag) return newTag;
- if (tag == "Document") {
- // IE calls both HTML and XML documents "Document", so we check for the
- // xmlVersion property, which is the empty string on HTML documents.
- // Since both dart:html classes Document and HtmlDocument share the same
- // type, we must patch the instances and not the prototype.
- if (!!o.xmlVersion) return "!Document";
- return "!HTMLDocument";
- }
// Patches for types which report themselves as Objects.
if (tag == "Object") {
if (window.DataView && (o instanceof window.DataView)) return "DataView";
@@ -563,7 +556,6 @@
}
function prototypeForTagIE(tag) {
- if (tag == "Document") return null; // Do not pre-patch Document.
var constructor = window[tag];
if (constructor == null) return null;
return constructor.prototype;
@@ -573,6 +565,32 @@
hooks.prototypeForTag = prototypeForTagIE;
}''');
+const _fixDocumentHooksTransformer = const JS_CONST(r'''
+function(hooks) {
+ var getTag = hooks.getTag;
+ var prototypeForTag = hooks.prototypeForTag;
+ function getTagFixed(o) {
+ var tag = getTag(o);
+ if (tag == "Document") {
+ // Some browsers and the polymer polyfill call both HTML and XML documents
+ // "Document", so we check for the xmlVersion property, which is the empty
+ // string on HTML documents. Since both dart:html classes Document and
+ // HtmlDocument share the same type, we must patch the instances and not
+ // the prototype.
+ if (!!o.xmlVersion) return "!Document";
+ return "!HTMLDocument";
+ }
+ return tag;
+ }
+
+ function prototypeForTagFixed(tag) {
+ if (tag == "Document") return null; // Do not pre-patch Document.
+ return prototypeForTag(tag);
+ }
+
+ hooks.getTag = getTagFixed;
+ hooks.prototypeForTag = prototypeForTagFixed;
+}''');
const _firefoxHooksTransformer = const JS_CONST(r'''
function(hooks) {
@@ -586,7 +604,7 @@
"DataTransfer": "Clipboard",
"GeoGeolocation": "Geolocation",
"WorkerMessageEvent": "MessageEvent",
- "XMLDocument": "Document"};
+ "XMLDocument": "!Document"};
function getTagFirefox(o) {
var tag = getTag(o);
diff --git a/sdk/lib/_internal/pub/bin/pub.dart b/sdk/lib/_internal/pub/bin/pub.dart
index e19d9a0..06be67a 100644
--- a/sdk/lib/_internal/pub/bin/pub.dart
+++ b/sdk/lib/_internal/pub/bin/pub.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'dart:io';
import 'dart:math' as math;
diff --git a/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart b/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
index 35a4ac2..604a881 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/dart2js_transformer.dart
@@ -4,7 +4,7 @@
library pub.dart2js_transformer;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'dart:io';
import 'package:analyzer/analyzer.dart';
diff --git a/sdk/lib/_internal/pub/lib/src/barback/sources.dart b/sdk/lib/_internal/pub/lib/src/barback/sources.dart
index ece690b..8d2a79a 100644
--- a/sdk/lib/_internal/pub/lib/src/barback/sources.dart
+++ b/sdk/lib/_internal/pub/lib/src/barback/sources.dart
@@ -4,7 +4,7 @@
library pub.barback.sources;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:barback/barback.dart';
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/command.dart b/sdk/lib/_internal/pub/lib/src/command.dart
index 221bc45..ffd7fff 100644
--- a/sdk/lib/_internal/pub/lib/src/command.dart
+++ b/sdk/lib/_internal/pub/lib/src/command.dart
@@ -5,7 +5,7 @@
library pub.command;
import 'dart:io';
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:args/args.dart';
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/command/build.dart b/sdk/lib/_internal/pub/lib/src/command/build.dart
index 1c9e37e..ef2e80b 100644
--- a/sdk/lib/_internal/pub/lib/src/command/build.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/build.dart
@@ -4,7 +4,7 @@
library pub.command.build;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:barback/barback.dart';
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/command/cache.dart b/sdk/lib/_internal/pub/lib/src/command/cache.dart
index 97e5dbe..6479781 100644
--- a/sdk/lib/_internal/pub/lib/src/command/cache.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/cache.dart
@@ -4,7 +4,7 @@
library pub.command.cache;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'dart:convert';
import '../command.dart';
diff --git a/sdk/lib/_internal/pub/lib/src/command/help.dart b/sdk/lib/_internal/pub/lib/src/command/help.dart
index f02841f..9467721 100644
--- a/sdk/lib/_internal/pub/lib/src/command/help.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/help.dart
@@ -4,7 +4,7 @@
library pub.command.help;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import '../command.dart';
import '../exit_codes.dart' as exit_codes;
diff --git a/sdk/lib/_internal/pub/lib/src/command/lish.dart b/sdk/lib/_internal/pub/lib/src/command/lish.dart
index 1cc95ac..6a8b744 100644
--- a/sdk/lib/_internal/pub/lib/src/command/lish.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/lish.dart
@@ -4,7 +4,7 @@
library pub.command.lish;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:http/http.dart' as http;
diff --git a/sdk/lib/_internal/pub/lib/src/command/list_package_dirs.dart b/sdk/lib/_internal/pub/lib/src/command/list_package_dirs.dart
index 31c6916..15fb4da 100644
--- a/sdk/lib/_internal/pub/lib/src/command/list_package_dirs.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/list_package_dirs.dart
@@ -4,7 +4,7 @@
library pub.command.list_package_dirs;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'dart:convert';
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/command/serve.dart b/sdk/lib/_internal/pub/lib/src/command/serve.dart
index f6df4ce..0d07f7b 100644
--- a/sdk/lib/_internal/pub/lib/src/command/serve.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/serve.dart
@@ -4,7 +4,7 @@
library pub.command.serve;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:barback/barback.dart';
diff --git a/sdk/lib/_internal/pub/lib/src/command/uploader.dart b/sdk/lib/_internal/pub/lib/src/command/uploader.dart
index 330efcc..d02472b 100644
--- a/sdk/lib/_internal/pub/lib/src/command/uploader.dart
+++ b/sdk/lib/_internal/pub/lib/src/command/uploader.dart
@@ -4,7 +4,7 @@
library pub.command.uploader;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/dart.dart b/sdk/lib/_internal/pub/lib/src/dart.dart
index 7e1fe28..fcd27b15 100644
--- a/sdk/lib/_internal/pub/lib/src/dart.dart
+++ b/sdk/lib/_internal/pub/lib/src/dart.dart
@@ -5,7 +5,7 @@
/// A library for compiling Dart code and manipulating analyzer parse trees.
library pub.dart;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'dart:isolate';
import 'package:analyzer/analyzer.dart';
@@ -107,7 +107,7 @@
'uri': path.toUri(dartPath).toString(),
'message': message
}).then((_) => port.first).then((response) {
- if (response['type'] == 'success') return;
+ if (response['type'] == 'success') return null;
assert(response['type'] == 'error');
return new Future.error(
new CrossIsolateException.deserialize(response['error']));
diff --git a/sdk/lib/_internal/pub/lib/src/entrypoint.dart b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
index b4ef32b..65cecc3 100644
--- a/sdk/lib/_internal/pub/lib/src/entrypoint.dart
+++ b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
@@ -4,7 +4,7 @@
library pub.entrypoint;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/error_group.dart b/sdk/lib/_internal/pub/lib/src/error_group.dart
index ea924e8..ae0410f 100644
--- a/sdk/lib/_internal/pub/lib/src/error_group.dart
+++ b/sdk/lib/_internal/pub/lib/src/error_group.dart
@@ -194,6 +194,11 @@
return _completer.future.whenComplete(action);
}
+ Future timeout(Duration timeLimit, [void onTimeout()]) {
+ _hasListeners = true;
+ return _completer.future.timeout(timeLimit, onTimeout);
+ }
+
Stream asStream() {
_hasListeners = true;
return _completer.future.asStream();
diff --git a/sdk/lib/_internal/pub/lib/src/git.dart b/sdk/lib/_internal/pub/lib/src/git.dart
index e94e493..e692a47 100644
--- a/sdk/lib/_internal/pub/lib/src/git.dart
+++ b/sdk/lib/_internal/pub/lib/src/git.dart
@@ -5,7 +5,7 @@
/// Helper functionality for invoking Git.
library pub.git;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'io.dart';
import 'log.dart' as log;
diff --git a/sdk/lib/_internal/pub/lib/src/http.dart b/sdk/lib/_internal/pub/lib/src/http.dart
index 017b387..969042f 100644
--- a/sdk/lib/_internal/pub/lib/src/http.dart
+++ b/sdk/lib/_internal/pub/lib/src/http.dart
@@ -5,7 +5,7 @@
/// Helpers for dealing with HTTP.
library pub.http;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'dart:convert';
import 'dart:io';
diff --git a/sdk/lib/_internal/pub/lib/src/io.dart b/sdk/lib/_internal/pub/lib/src/io.dart
index 89179eb..90b06f9 100644
--- a/sdk/lib/_internal/pub/lib/src/io.dart
+++ b/sdk/lib/_internal/pub/lib/src/io.dart
@@ -5,7 +5,7 @@
/// Helper functionality to make working with IO easier.
library pub.io;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
diff --git a/sdk/lib/_internal/pub/lib/src/log.dart b/sdk/lib/_internal/pub/lib/src/log.dart
index 10f220d..83e5edc 100644
--- a/sdk/lib/_internal/pub/lib/src/log.dart
+++ b/sdk/lib/_internal/pub/lib/src/log.dart
@@ -6,7 +6,7 @@
library pub.log;
import 'dart:io';
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'io.dart';
import 'utils.dart';
diff --git a/sdk/lib/_internal/pub/lib/src/oauth2.dart b/sdk/lib/_internal/pub/lib/src/oauth2.dart
index 7146817..1bc1d9f 100644
--- a/sdk/lib/_internal/pub/lib/src/oauth2.dart
+++ b/sdk/lib/_internal/pub/lib/src/oauth2.dart
@@ -4,7 +4,7 @@
library pub.oauth2;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'dart:io';
import 'package:oauth2/oauth2.dart';
diff --git a/sdk/lib/_internal/pub/lib/src/safe_http_server.dart b/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
index e88ee93..f45741f 100644
--- a/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
+++ b/sdk/lib/_internal/pub/lib/src/safe_http_server.dart
@@ -31,8 +31,9 @@
: super(server),
_inner = server;
- Future close() => _inner.close();
+ Future close({bool force: false}) => _inner.close(force: force);
+ InternetAddress get address => _inner.address;
int get port => _inner.port;
set sessionTimeout(int timeout) {
@@ -149,6 +150,7 @@
Future<HttpResponse> addStream(Stream<List<int>> stream) =>
_inner.addStream(stream);
Future close() => _inner.close();
+ Future flush() => _inner.flush();
void write(Object obj) => _inner.write(obj);
void writeAll(Iterable objects, [String separator = ""]) =>
_inner.writeAll(objects, separator);
diff --git a/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart b/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
index 4300909..c38295c 100644
--- a/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
+++ b/sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart
@@ -44,6 +44,8 @@
import '../source_registry.dart';
import '../utils.dart';
import '../version.dart';
+import 'dependency_queue.dart';
+import 'version_queue.dart';
import 'version_solver.dart';
/// The top-level solver. Keeps track of the current potential solution, and
@@ -71,8 +73,8 @@
/// are valid. This keeps track of which versions have been selected so far
/// and which remain to be tried.
///
- /// Each entry in the list is an ordered [Queue] of versions to try for a
- /// single package. The first item in the queue is the currently selected
+ /// Each entry in the list is a [VersionQueue], which is an ordered queue of
+ /// versions to try for a single package. It maintains the currently selected
/// version for that package. When a new dependency is encountered, a queue
/// of versions of that dependency is pushed onto the end of the list. A
/// queue is removed from the list once it's empty, indicating that none of
@@ -83,7 +85,7 @@
/// on an already-selected package, and that constraint doesn't match the
/// selected version, that will cause the current solution to fail and
/// trigger backtracking.
- final _selected = <Queue<PackageId>>[];
+ final _selected = <VersionQueue>[];
/// The number of solutions the solver has tried so far.
int get attemptedSolutions => _attemptedSolutions;
@@ -154,10 +156,10 @@
/// in the list will be the currently selected version of that package.
/// Subsequent items will be tried if it the current selection fails. Returns
/// the first selected version.
- PackageId select(Iterable<PackageId> versions) {
- _selected.add(new Queue<PackageId>.from(versions));
+ PackageId select(VersionQueue versions) {
+ _selected.add(versions);
logSolve();
- return versions.first;
+ return versions.current;
}
/// Returns the the currently selected id for the package [name] or `null` if
@@ -168,7 +170,7 @@
// Look through the current selections.
for (var i = _selected.length - 1; i >= 0; i--) {
- if (_selected[i].first.name == name) return _selected[i].first;
+ if (_selected[i].current.name == name) return _selected[i].current;
}
return null;
@@ -188,13 +190,15 @@
return new Traverser(this).traverse().catchError((error) {
if (error is! SolveFailure) throw error;
- if (_backtrack(error)) {
- _attemptedSolutions++;
- return _traverseSolution();
- }
+ return _backtrack(error).then((canTry) {
+ if (canTry) {
+ _attemptedSolutions++;
+ return _traverseSolution();
+ }
- // All out of solutions, so fail.
- throw error;
+ // All out of solutions, so fail.
+ throw error;
+ });
});
});
@@ -204,40 +208,47 @@
/// the next possible solution.
///
/// Returns `true` if there is a new solution to try.
- bool _backtrack(SolveFailure failure) {
- var dependers = failure.dependencies.map((dep) => dep.depender).toSet();
+ Future<bool> _backtrack(SolveFailure failure) {
+ // Bail if there is nothing to backtrack to.
+ if (_selected.isEmpty) return new Future.value(false);
- while (!_selected.isEmpty) {
- _backjump(failure);
+ // Get the set of packages that may have led to this failure.
+ var dependers = _getTransitiveDependers(failure.package);
- // Advance past the current version of the leaf-most package.
- var previous = _selected.last.removeFirst();
- if (!_selected.last.isEmpty) {
- logSolve();
- return true;
- }
+ // Advance past the current version of the leaf-most package.
+ advanceVersion() {
+ _backjump(failure, dependers);
+ var previous = _selected.last.current;
+ return _selected.last.advance().then((success) {
+ if (success) {
+ logSolve();
+ return true;
+ }
- logSolve('$previous is last version, backtracking');
+ logSolve('$previous is last version, backtracking');
- // That package has no more versions, so pop it and try the next one.
- _selected.removeLast();
+ // That package has no more versions, so pop it and try the next one.
+ _selected.removeLast();
+ if (_selected.isEmpty) return false;
+
+ // If we got here, the leafmost package was discarded so we need to
+ // advance the next one.
+ return advanceVersion();
+ });
}
- return false;
+ return advanceVersion();
}
/// Walks the selected packages from most to least recent to determine which
/// ones can be ignored and jumped over by the backtracker. The only packages
- /// we need to backtrack to are ones that have other versions to try and that
- /// led (possibly indirectly) to the failure. Everything else can be skipped.
- void _backjump(SolveFailure failure) {
+ /// we need to backtrack to are ones that led (possibly indirectly) to the
+ /// failure. Everything else can be skipped.
+ void _backjump(SolveFailure failure, Set<String> dependers) {
for (var i = _selected.length - 1; i >= 0; i--) {
// Each queue will never be empty since it gets discarded by _backtrack()
// when that happens.
- var selected = _selected[i].first;
-
- // If the package has no more versions, we can jump over it.
- if (_selected[i].length == 1) continue;
+ var selected = _selected[i].current;
// If we get to the package that failed, backtrack to here.
if (selected.name == failure.package) {
@@ -248,10 +259,9 @@
// If we get to a package that depends on the failing package, backtrack
// to here.
- var path = _getDependencyPath(selected, failure.package);
- if (path != null) {
+ if (dependers.contains(selected.name)) {
logSolve('backjump to ${selected.name} because it depends on '
- '${failure.package} along $path');
+ '${failure.package}');
_selected.removeRange(i + 1, _selected.length);
return;
}
@@ -264,40 +274,54 @@
_selected.removeRange(1, _selected.length);
}
- /// Determines if [depender] has a direct or indirect dependency on
- /// [dependent] based on the currently selected versions of all packages.
- /// Returns a string describing the dependency chain if it does, or `null` if
- /// there is no dependency.
- String _getDependencyPath(PackageId depender, String dependent) {
- // TODO(rnystrom): This is O(n^2) where n is the number of selected
- // packages. Could store the reverse dependency graph to address that. If
- // we do that, we need to make sure it gets correctly rolled back when
- // backtracking occurs.
- var visited = new Set<String>();
-
- walkDeps(PackageId package, String currentPath) {
- if (visited.contains(package.name)) return null;
- visited.add(package.name);
-
- var pubspec = cache.getCachedPubspec(package);
- if (pubspec == null) return null;
+ /// Gets the set of currently selected packages that depend on [dependency]
+ /// either directly or indirectly.
+ ///
+ /// When backtracking, it's only useful to consider changing the version of
+ /// packages who have a dependency on the failed package that triggered
+ /// backtracking. This is used to determine those packages.
+ ///
+ /// We calculate the full set up front before backtracking because during
+ /// backtracking, we will unselect packages and start to lose this
+ /// information in the middle of the process.
+ ///
+ /// For example, consider dependencies A -> B -> C. We've selected A and B
+ /// then encounter a problem with C. We start backtracking. B has no more
+ /// versions so we discard it and keep backtracking to A. When we get there,
+ /// since we've unselected B, we no longer realize that A had a transitive
+ /// dependency on C. We would end up backjumping over A and failing.
+ ///
+ /// Calculating the dependency set up front before we start backtracking
+ /// solves that.
+ Set<String> _getTransitiveDependers(String dependency) {
+ // Generate a reverse dependency graph. For each package, create edges to
+ // each package that depends on it.
+ var dependers = new Map<String, Set<String>>();
+ for (var i = 0; i < _selected.length; i++) {
+ var id = _selected[i].current;
+ var pubspec = cache.getCachedPubspec(id);
+ if (pubspec == null) continue;
+ dependers.putIfAbsent(id.name, () => new Set<String>());
for (var dep in pubspec.dependencies) {
- if (dep.name == dependent) return currentPath;
-
- var selected = getSelected(dep.name);
- // Ignore unselected dependencies. We haven't traversed into them yet,
- // so they can't affect backjumping.
- if (selected == null) continue;
-
- var depPath = walkDeps(selected, '$currentPath -> ${dep.name}');
- if (depPath != null) return depPath;
+ var depender = dependers.putIfAbsent(dep.name,
+ () => new Set<String>());
+ depender.add(id.name);
}
-
- return null;
}
- return walkDeps(depender, depender.name);
+ // Now walk the depending graph to see which packages transitively depend
+ // on [dependency].
+ var visited = new Set<String>();
+ walk(String package) {
+ // Don't get stuck in cycles.
+ if (visited.contains(package)) return;
+ visited.add(package);
+ var depender = dependers[package].forEach(walk);
+ }
+
+ walk(dependency);
+ return visited;
}
/// Logs the initial parameters to the solver.
@@ -324,8 +348,7 @@
if (_selected.isEmpty) {
message = "* start at root";
} else {
- var count = _selected.last.length;
- message = "* select ${_selected.last.first} ($count versions)";
+ message = "* select ${_selected.last.current}";
}
} else {
// Otherwise, indent it under the current selected package.
@@ -424,79 +447,79 @@
}
}
- // Given a package dep, returns a future that completes to a pair of the
- // dep and the number of versions available for it.
- getNumVersions(PackageDep dep) {
- // There is only ever one version of the root package.
- if (dep.isRoot) {
- return new Future.value(new Pair<PackageDep, int>(dep, 1));
- }
-
- return _solver.cache.getVersions(dep.toRef()).then((versions) {
- return new Pair<PackageDep, int>(dep, versions.length);
- }).catchError((error, trace) {
- // If it fails for any reason, just treat that as no versions. This
- // will sort this reference higher so that we can traverse into it
- // and report the error more properly.
- log.solver("Could not get versions for $dep:\n$error\n\n$trace");
- return new Pair<PackageDep, int>(dep, 0);
- });
- }
-
- return Future.wait(deps.map(getNumVersions)).then((pairs) {
- // Future.wait() returns an immutable list, so make a copy.
- pairs = pairs.toList();
-
- // Sort in best-first order to minimize backtracking.
- pairs.sort((a, b) {
- // Traverse into packages we've already selected first.
- var aIsSelected = _solver.getSelected(a.first.name) != null;
- var bIsSelected = _solver.getSelected(b.first.name) != null;
- if (aIsSelected && !bIsSelected) return -1;
- if (!aIsSelected && bIsSelected) return 1;
-
- // Traverse into packages with fewer versions since they will lead to
- // less backtracking.
- if (a.last != b.last) return a.last.compareTo(b.last);
-
- // Otherwise, just sort by name so that it's deterministic.
- return a.first.name.compareTo(b.first.name);
- });
-
- var queue = new Queue<PackageDep>.from(pairs.map((pair) => pair.first));
- return _traverseDeps(id.name, queue);
- });
+ return _traverseDeps(id.name, new DependencyQueue(_solver, deps));
});
}
/// Traverses the references that [depender] depends on, stored in [deps].
+ ///
/// Desctructively modifies [deps]. Completes to a list of packages if the
/// traversal is complete. Completes it to an error if a failure occurred.
/// Otherwise, recurses.
- Future<List<PackageId>> _traverseDeps(String depender,
- Queue<PackageDep> deps) {
+ Future<List<PackageId>> _traverseDeps(String depender, DependencyQueue deps) {
// Move onto the next package if we've traversed all of these references.
if (deps.isEmpty) return _traversePackage();
return resetStack(() {
- var dep = deps.removeFirst();
+ return deps.advance().then((dep) {
+ _validateDependency(dep, depender);
- _validateDependency(dep, depender);
- var constraint = _addConstraint(dep, depender);
+ // Add the dependency.
+ var dependencies = _getDependencies(dep.name);
+ dependencies.add(new Dependency(depender, dep));
- var selected = _validateSelected(dep, constraint);
- if (selected != null) {
- // The selected package version is good, so enqueue it to traverse into
- // it.
- _packages.add(selected);
- return _traverseDeps(depender, deps);
+ var constraint = _getConstraint(dep.name);
+
+ // See if it's possible for a package to match that constraint.
+ if (constraint.isEmpty) {
+ _solver.logSolve('disjoint constraints on ${dep.name}}');
+ throw new DisjointConstraintException(depender, dependencies);
+ }
+
+ var selected = _validateSelected(dep, constraint);
+ if (selected != null) {
+ // The selected package version is good, so enqueue it to traverse
+ // into it.
+ _packages.add(selected);
+ return _traverseDeps(depender, deps);
+ }
+
+ // We haven't selected a version. Try all of the versions that match
+ // the constraints we currently have for this package.
+ var locked = _getValidLocked(dep.name);
+
+ return VersionQueue.create(locked,
+ () => _getAllowedVersions(dep)).then((versions) {
+ _packages.add(_solver.select(versions));
+ });
+ }).then((_) => _traverseDeps(depender, deps));
+ });
+ }
+
+ /// Gets all versions of [dep] that match the current constraints placed on
+ /// it.
+ Future<Iterable<PackageId>> _getAllowedVersions(PackageDep dep) {
+ var constraint = _getConstraint(dep.name);
+ return _solver.cache.getVersions(dep.toRef()).then((versions) {
+ var allowed = versions.where((id) => constraint.allows(id.version));
+
+ if (allowed.isEmpty) {
+ _solver.logSolve('no versions for ${dep.name} match $constraint');
+ throw new NoVersionException(dep.name, constraint,
+ _getDependencies(dep.name));
}
- // We haven't selected a version. Get all of the versions that match the
- // constraints we currently have for this package and add them to the
- // set of solutions to try.
- return _selectPackage(dep, constraint).then(
- (_) => _traverseDeps(depender, deps));
+ // If we're doing an upgrade on this package, only allow the latest
+ // version.
+ if (_solver._forceLatest.contains(dep.name)) allowed = [allowed.first];
+
+ // Remove the locked version, if any, since that was already handled.
+ var locked = _getValidLocked(dep.name);
+ if (locked != null) {
+ allowed = allowed.where((dep) => dep.version != locked.version);
+ }
+
+ return allowed;
});
}
@@ -527,31 +550,6 @@
}
}
- /// Adds the version constraint that [depender] places on [dep] to the
- /// overall constraint that all shared dependencies place on [dep]. Throws a
- /// [SolveFailure] if that results in an unsolvable constraints.
- ///
- /// Returns the combined [VersionConstraint] that all dependers place on the
- /// package.
- VersionConstraint _addConstraint(PackageDep dep, String depender) {
- // Add the dependency.
- var dependencies = _getDependencies(dep.name);
- dependencies.add(new Dependency(depender, dep));
-
- // Determine the overall version constraint.
- var constraint = dependencies
- .map((dep) => dep.dep.constraint)
- .fold(VersionConstraint.any, (a, b) => a.intersect(b));
-
- // See if it's possible for a package to match that constraint.
- if (constraint.isEmpty) {
- _solver.logSolve('disjoint constraints on ${dep.name}');
- throw new DisjointConstraintException(depender, dependencies);
- }
-
- return constraint;
- }
-
/// Validates the currently selected package against the new dependency that
/// [dep] and [constraint] place on it. Returns `null` if there is no
/// currently selected package, throws a [SolveFailure] if the new reference
@@ -571,42 +569,6 @@
return selected;
}
- /// Tries to select a package that matches [dep] and [constraint]. Updates
- /// the solver state so that we can backtrack from this decision if it turns
- /// out wrong, but continues traversing with the new selection.
- ///
- /// Returns a future that completes with a [SolveFailure] if a version
- /// could not be selected or that completes successfully if a package was
- /// selected and traversing should continue.
- Future _selectPackage(PackageDep dep, VersionConstraint constraint) {
- return _solver.cache.getVersions(dep.toRef()).then((versions) {
- var allowed = versions.where((id) => constraint.allows(id.version));
-
- // See if it's in the lockfile. If so, try that version first. If the
- // locked version doesn't match our constraint, just ignore it.
- var locked = _getValidLocked(dep.name, constraint);
- if (locked != null) {
- allowed = allowed.where((dep) => dep.version != locked.version)
- .toList();
- allowed.insert(0, locked);
- }
-
- if (allowed.isEmpty) {
- _solver.logSolve('no versions for ${dep.name} match $constraint');
- throw new NoVersionException(dep.name, constraint,
- _getDependencies(dep.name));
- }
-
- // If we're doing an upgrade on this package, only allow the latest
- // version.
- if (_solver._forceLatest.contains(dep.name)) allowed = [allowed.first];
-
- // Try the first package in the allowed set and keep track of the list of
- // other possible versions in case that fails.
- _packages.add(_solver.select(allowed));
- });
- }
-
/// Gets the list of dependencies for package [name]. Will create an empty
/// list if needed.
List<Dependency> _getDependencies(String name) {
@@ -629,13 +591,22 @@
.firstWhere((dep) => !dep.dep.isRoot, orElse: () => null);
}
+ /// Gets the combined [VersionConstraint] currently being placed on package
+ /// [name].
+ VersionConstraint _getConstraint(String name) {
+ return _getDependencies(name)
+ .map((dep) => dep.dep.constraint)
+ .fold(VersionConstraint.any, (a, b) => a.intersect(b));
+ }
+
/// Gets the package [name] that's currently contained in the lockfile if it
/// meets [constraint] and has the same source and description as other
/// references to that package. Returns `null` otherwise.
- PackageId _getValidLocked(String name, VersionConstraint constraint) {
+ PackageId _getValidLocked(String name) {
var package = _solver.getLocked(name);
if (package == null) return null;
+ var constraint = _getConstraint(name);
if (!constraint.allows(package.version)) {
_solver.logSolve('$package is locked but does not match $constraint');
return null;
diff --git a/sdk/lib/_internal/pub/lib/src/solver/dependency_queue.dart b/sdk/lib/_internal/pub/lib/src/solver/dependency_queue.dart
new file mode 100644
index 0000000..3c64e53
--- /dev/null
+++ b/sdk/lib/_internal/pub/lib/src/solver/dependency_queue.dart
@@ -0,0 +1,138 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub.solver.dependency_queue;
+
+import 'dart:async';
+import 'dart:collection' show Queue;
+
+import '../log.dart' as log;
+import '../package.dart';
+import 'backtracking_solver.dart';
+
+/// A queue of one package's dependencies, ordered by how the solver should
+/// traverse them.
+///
+/// It prefers locked versions so that they stay locked if possible. Then it
+/// prefers a currently selected package so that it only has to consider a
+/// single version.
+///
+/// After that, it orders the remaining packages by the number of versions they
+/// have so that packages with fewer versions are solved first. (If two
+/// packages have the same number of versions, they are sorted alphabetically
+/// just to be deterministic.)
+///
+/// Critically, this queue will *not* sort the dependencies by number of
+/// versions until actually needed. This ensures we don't do any network
+/// requests until we actually need to. In particular, it means that solving
+/// a package graph with an already up-to-date lockfile will do no network
+/// requests.
+class DependencyQueue {
+ final BacktrackingSolver _solver;
+
+ /// The dependencies for packages that have already been selected.
+ final Queue<PackageDep> _presorted;
+
+ /// The dependencies on the remaining packages.
+ ///
+ /// This is lazily sorted right before the first item is requested.
+ final List<PackageDep> _remaining;
+
+ bool _isSorted = false;
+
+ /// Gets whether there are any dependencies left to iterate over.
+ bool get isEmpty => _presorted.isEmpty && _remaining.isEmpty;
+
+ /// The pending [Future] while the remaining dependencies are being sorted.
+ ///
+ /// This will only be non-null while a sort is in progress.
+ Future _sortFuture;
+
+ factory DependencyQueue(BacktrackingSolver solver,
+ Iterable<PackageDep> deps) {
+ // Separate out the presorted ones.
+ var presorted = <PackageDep>[];
+ var remaining = <PackageDep>[];
+
+ for (var dep in deps) {
+ // Selected or locked packages come first.
+ if (solver.getSelected(dep.name) != null ||
+ solver.getLocked(dep.name) != null) {
+ presorted.add(dep);
+ } else {
+ remaining.add(dep);
+ }
+ }
+
+ return new DependencyQueue._(solver, new Queue<PackageDep>.from(presorted),
+ remaining);
+ }
+
+ DependencyQueue._(this._solver, this._presorted, this._remaining);
+
+ /// Emits the next dependency in priority order.
+ ///
+ /// It is an error to call this if [isEmpty] returns `true`. Note that this
+ /// function is *not* re-entrant. You should only advance after the previous
+ /// advance has completed.
+ Future<PackageDep> advance() {
+ // Emit the sorted ones first.
+ if (_presorted.isNotEmpty) {
+ return new Future.value(_presorted.removeFirst());
+ }
+
+ // Sort the remaining packages when we need the first one.
+ if (!_isSorted) return _sort().then((_) => _remaining.removeAt(0));
+
+ return new Future.value(_remaining.removeAt(0));
+ }
+
+ /// Sorts the unselected packages by number of versions and name.
+ Future _sort() {
+ // Sorting is not re-entrant.
+ assert(_sortFuture == null);
+
+ _sortFuture = Future.wait(_remaining.map(_getNumVersions)).then((versions) {
+ _sortFuture = null;
+
+ // Map deps to the number of versions they have.
+ var versionMap = new Map.fromIterables(_remaining, versions);
+
+ // Sort in best-first order to minimize backtracking.
+ _remaining.sort((a, b) {
+ // Traverse into packages with fewer versions since they will lead to
+ // less backtracking.
+ if (versionMap[a] != versionMap[b]) {
+ return versionMap[a].compareTo(versionMap[b]);
+ }
+
+ // Otherwise, just sort by name so that it's deterministic.
+ return a.name.compareTo(b.name);
+ });
+
+ _isSorted = true;
+ });
+
+ return _sortFuture;
+ }
+
+ /// Given a dependency, returns a future that completes to the number of
+ /// versions available for it.
+ Future<int> _getNumVersions(PackageDep dep) {
+ // There is only ever one version of the root package.
+ if (dep.isRoot) {
+ return new Future.value(1);
+ }
+
+ return _solver.cache.getVersions(dep.toRef()).then((versions) {
+ return versions.length;
+ }).catchError((error, trace) {
+ // If it fails for any reason, just treat that as no versions. This
+ // will sort this reference higher so that we can traverse into it
+ // and report the error more properly.
+ log.solver("Could not get versions for $dep:\n$error\n\n$trace");
+ return 0;
+ });
+ }
+}
diff --git a/sdk/lib/_internal/pub/lib/src/solver/version_queue.dart b/sdk/lib/_internal/pub/lib/src/solver/version_queue.dart
new file mode 100644
index 0000000..529cf74
--- /dev/null
+++ b/sdk/lib/_internal/pub/lib/src/solver/version_queue.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library pub.solver.version_queue;
+
+import 'dart:async';
+import 'dart:collection' show Queue;
+
+import '../package.dart';
+import 'backtracking_solver.dart';
+
+/// A function that asynchronously returns a sequence of package IDs.
+typedef Future<Iterable<PackageId>> PackageIdGenerator();
+
+/// A prioritized, asynchronous queue of the possible versions that can be
+/// selected for one package.
+///
+/// If there is a locked version, that comes first, followed by other versions
+/// in descending order. This avoids requesting the list of versions until
+/// needed (i.e. after any locked version has been consumed) to avoid unneeded
+/// network requests.
+class VersionQueue {
+ /// The set of allowed versions that match [_constraint].
+ ///
+ /// If [_locked] is not `null`, this will initially be `null` until we
+ /// advance past the locked version.
+ Queue<PackageId> _allowed;
+
+ /// The callback that will generate the sequence of packages. This will be
+ /// called as lazily as possible.
+ final PackageIdGenerator _allowedGenerator;
+
+ /// The currently locked version of the package, or `null` if there is none,
+ /// or we have advanced past it.
+ PackageId _locked;
+
+ /// Gets the currently selected version.
+ PackageId get current {
+ if (_locked != null) return _locked;
+ return _allowed.first;
+ }
+
+ /// Creates a new [VersionQueue] queue for starting with the optional
+ /// [locked] package followed by the results of calling [allowedGenerator].
+ ///
+ /// This is asynchronous so that [current] can always be accessed
+ /// synchronously. If there is no locked version, we need to get the list of
+ /// versions asynchronously before we can determine what the first one is.
+ static Future<VersionQueue> create(PackageId locked,
+ PackageIdGenerator allowedGenerator) {
+ var versions = new VersionQueue._(locked, allowedGenerator);
+
+ // If there is a locked version, it's the current one so it's synchronously
+ // available now.
+ if (locked != null) return new Future.value(versions);
+
+ // Otherwise, the current version needs to be calculated before we can
+ // return.
+ return versions._calculateAllowed().then((_) => versions);
+ }
+
+ VersionQueue._(this._locked, this._allowedGenerator);
+
+ /// Tries to advance to the next possible version.
+ ///
+ /// Returns `true` if it moved to a new version (which can be accessed from
+ /// [current]. Returns `false` if there are no more versions.
+ Future<bool> advance() {
+ // If we have a locked version, consume it first.
+ if (_locked != null) {
+ // Advancing past the locked version, so need to load the others now
+ // so that [current] is available.
+ return _calculateAllowed().then((_) {
+ _locked = null;
+ return _allowed.isNotEmpty;
+ });
+ }
+
+ // Move to the next allowed version.
+ _allowed.removeFirst();
+ return new Future.value(_allowed.isNotEmpty);
+ }
+
+ /// Determines the list of allowed versions matching its constraint and places
+ /// them in [_allowed].
+ Future _calculateAllowed() {
+ return _allowedGenerator().then((allowed) {
+ _allowed = new Queue<PackageId>.from(allowed);
+ });
+ }
+}
\ No newline at end of file
diff --git a/sdk/lib/_internal/pub/lib/src/source.dart b/sdk/lib/_internal/pub/lib/src/source.dart
index 676e1a6..78b4450 100644
--- a/sdk/lib/_internal/pub/lib/src/source.dart
+++ b/sdk/lib/_internal/pub/lib/src/source.dart
@@ -4,7 +4,7 @@
library pub.source;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/source/git.dart b/sdk/lib/_internal/pub/lib/src/source/git.dart
index 42e6856..7caf1dae 100644
--- a/sdk/lib/_internal/pub/lib/src/source/git.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/git.dart
@@ -4,7 +4,7 @@
library pub.source.git;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:path/path.dart' as path;
@@ -48,11 +48,11 @@
return _ensureRepoCache(id);
}).then((_) => systemCacheDirectory(id)).then((path) {
revisionCachePath = path;
- if (entryExists(revisionCachePath)) return;
+ if (entryExists(revisionCachePath)) return null;
return _clone(_repoCachePath(id), revisionCachePath, mirror: false);
}).then((_) {
var ref = _getEffectiveRef(id);
- if (ref == 'HEAD') return;
+ if (ref == 'HEAD') return null;
return _checkOut(revisionCachePath, ref);
}).then((_) {
return new Package.load(id.name, revisionCachePath, systemCache.sources);
diff --git a/sdk/lib/_internal/pub/lib/src/source/hosted.dart b/sdk/lib/_internal/pub/lib/src/source/hosted.dart
index 265c844..295d2a5 100644
--- a/sdk/lib/_internal/pub/lib/src/source/hosted.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/hosted.dart
@@ -4,7 +4,7 @@
library pub.source.hosted;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'dart:io' as io;
import "dart:convert";
@@ -75,7 +75,7 @@
expectedName: id.name, location: url);
}).catchError((ex, stackTrace) {
var parsed = _parseDescription(id.description);
- _throwFriendlyError(ex, stackTrace, id, parsed.last);
+ _throwFriendlyError(ex, stackTrace, id.name, parsed.last);
});
}
diff --git a/sdk/lib/_internal/pub/lib/src/source/path.dart b/sdk/lib/_internal/pub/lib/src/source/path.dart
index af752d6..4d57069 100644
--- a/sdk/lib/_internal/pub/lib/src/source/path.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/path.dart
@@ -4,7 +4,7 @@
library pub.source.path;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/system_cache.dart b/sdk/lib/_internal/pub/lib/src/system_cache.dart
index bfc6cea..fe28502 100644
--- a/sdk/lib/_internal/pub/lib/src/system_cache.dart
+++ b/sdk/lib/_internal/pub/lib/src/system_cache.dart
@@ -4,7 +4,7 @@
library pub.system_cache;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/validator/compiled_dartdoc.dart b/sdk/lib/_internal/pub/lib/src/validator/compiled_dartdoc.dart
index d6abf6d..ab98a18 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/compiled_dartdoc.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/compiled_dartdoc.dart
@@ -4,7 +4,7 @@
library pub.validator.compiled_dartdoc;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/validator/directory.dart b/sdk/lib/_internal/pub/lib/src/validator/directory.dart
index 6039fc5..01ddf91 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/directory.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/directory.dart
@@ -4,7 +4,7 @@
library pub.validator.directory;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/validator/lib.dart b/sdk/lib/_internal/pub/lib/src/validator/lib.dart
index 98bed28..622ee03 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/lib.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/lib.dart
@@ -4,7 +4,7 @@
library pub.validator.lib;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/validator/license.dart b/sdk/lib/_internal/pub/lib/src/validator/license.dart
index 222d693..0948860 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/license.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/license.dart
@@ -4,7 +4,7 @@
library pub.validator.license;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/validator/name.dart b/sdk/lib/_internal/pub/lib/src/validator/name.dart
index 1285fb1..d62325d 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/name.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/name.dart
@@ -4,7 +4,7 @@
library pub.validator.name;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/lib/src/validator/utf8_readme.dart b/sdk/lib/_internal/pub/lib/src/validator/utf8_readme.dart
index 9f30d65..d14e674 100644
--- a/sdk/lib/_internal/pub/lib/src/validator/utf8_readme.dart
+++ b/sdk/lib/_internal/pub/lib/src/validator/utf8_readme.dart
@@ -4,7 +4,7 @@
library pub.validator.utf8_readme;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'dart:convert';
import '../entrypoint.dart';
diff --git a/sdk/lib/_internal/pub/pub.status b/sdk/lib/_internal/pub/pub.status
index fd1e29c..bf04ee6 100644
--- a/sdk/lib/_internal/pub/pub.status
+++ b/sdk/lib/_internal/pub/pub.status
@@ -6,6 +6,8 @@
test/hosted/version_negotiation_test: Pass, Timeout # Issue 14346
+test/upgrade/hosted/upgrade_removed_constraints_test: Pass, Fail # Issue 15349
+
[ $runtime == vm && $system == windows ]
test/serve/watch_removed_file_test: Pass, Fail # Issue 13026
diff --git a/sdk/lib/_internal/pub/test/descriptor/tar.dart b/sdk/lib/_internal/pub/test/descriptor/tar.dart
index 2a04a03..f297abb 100644
--- a/sdk/lib/_internal/pub/test/descriptor/tar.dart
+++ b/sdk/lib/_internal/pub/test/descriptor/tar.dart
@@ -4,7 +4,7 @@
library descriptor.tar;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'package:path/path.dart' as path;
import 'package:scheduled_test/scheduled_test.dart';
diff --git a/sdk/lib/_internal/pub/test/get/hosted/avoid_network_requests_test.dart b/sdk/lib/_internal/pub/test/get/hosted/avoid_network_requests_test.dart
new file mode 100644
index 0000000..cd66d84
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/get/hosted/avoid_network_requests_test.dart
@@ -0,0 +1,63 @@
+// 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.
+
+library pub_tests;
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+ initConfig();
+
+ integration('only requests versions that are needed during solving', () {
+ servePackages([
+ packageMap("foo", "1.0.0"),
+ packageMap("foo", "1.1.0"),
+ packageMap("foo", "1.2.0"),
+ packageMap("bar", "1.0.0"),
+ packageMap("bar", "1.1.0"),
+ packageMap("bar", "1.2.0")
+ ]);
+
+ d.appDir({
+ "foo": "any"
+ }).create();
+
+ // Get once so it gets cached.
+ pubGet();
+
+ // Clear the cache. We don't care about anything that was served during
+ // the initial get.
+ getRequestedPaths();
+
+ // Add "bar" to the dependencies.
+ d.appDir({
+ "foo": "any",
+ "bar": "any"
+ }).create();
+
+ // Run the solver again.
+ pubGet();
+
+ d.packagesDir({
+ "foo": "1.2.0",
+ "bar": "1.2.0"
+ }).validate();
+
+ // The get should not have done any network requests since the lock file is
+ // up to date.
+ getRequestedPaths().then((paths) {
+ expect(paths, unorderedEquals([
+ // Bar should be requested because it's new, but not foo.
+ "api/packages/bar",
+ // Should only request the most recent version.
+ "api/packages/bar/versions/1.2.0",
+ // Need to download it.
+ "packages/bar/versions/1.2.0.tar.gz"
+ ]));
+ });
+ });
+}
diff --git a/sdk/lib/_internal/pub/test/get/hosted/does_no_network_requests_when_possible_test.dart b/sdk/lib/_internal/pub/test/get/hosted/does_no_network_requests_when_possible_test.dart
new file mode 100644
index 0000000..44532fd
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/get/hosted/does_no_network_requests_when_possible_test.dart
@@ -0,0 +1,45 @@
+// 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.
+
+library pub_tests;
+
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+main() {
+ initConfig();
+
+ integration('does not request versions if the lockfile is up to date', () {
+ servePackages([
+ packageMap("foo", "1.0.0"),
+ packageMap("foo", "1.1.0"),
+ packageMap("foo", "1.2.0")
+ ]);
+
+ d.appDir({
+ "foo": "any"
+ }).create();
+
+ // Get once so it gets cached.
+ pubGet();
+
+ // Clear the cache. We don't care about anything that was served during
+ // the initial get.
+ getRequestedPaths();
+
+ // Run the solver again now that it's cached.
+ pubGet();
+
+ d.cacheDir({"foo": "1.2.0"}).validate();
+ d.packagesDir({"foo": "1.2.0"}).validate();
+
+ // The get should not have done any network requests since the lock file is
+ // up to date.
+ getRequestedPaths().then((paths) {
+ expect(paths, isEmpty);
+ });
+ });
+}
diff --git a/sdk/lib/_internal/pub/test/io_test.dart b/sdk/lib/_internal/pub/test/io_test.dart
index bc8d708..c4f5151 100644
--- a/sdk/lib/_internal/pub/test/io_test.dart
+++ b/sdk/lib/_internal/pub/test/io_test.dart
@@ -4,7 +4,7 @@
library io_test;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'dart:io';
import 'package:path/path.dart' as path;
diff --git a/sdk/lib/_internal/pub/test/test_pub.dart b/sdk/lib/_internal/pub/test/test_pub.dart
index 59be37c..f398887 100644
--- a/sdk/lib/_internal/pub/test/test_pub.dart
+++ b/sdk/lib/_internal/pub/test/test_pub.dart
@@ -8,7 +8,7 @@
/// tests like that.
library test_pub;
-import 'dart:async';
+import 'dart:async' hide TimeoutException;
import 'dart:convert';
import 'dart:io';
import 'dart:math';
@@ -88,7 +88,7 @@
var paths = _requestedPaths.toList();
_requestedPaths.clear();
return paths;
- });
+ }, "get previous network requests");
}
/// Creates an HTTP server to serve [contents] as static files. This server will
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index 593a775..db26cee 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -408,6 +408,33 @@
* its subscribers. The stream closes after the completion value.
*/
Stream<T> asStream();
+
+ /**
+ * Time-out the future computation after [timeLimit] has passed.
+ *
+ * Returns a new future that completes with the same value as this future,
+ * if this future completes in time.
+ *
+ * If this future does not complete before `timeLimit` has passed,
+ * the [onTimeout] action is executed instead, and its result (whether it
+ * returns or throws) is used as the result of the returned future.
+ *
+ * If `onTimeout` is omitted, a timeout will cause the returned future to
+ * complete with a [TimeoutException].
+ */
+ Future timeout(Duration timeLimit, [void onTimeout()]);
+}
+
+/**
+ * Thrown when a scheduled timeout happens while waiting for an async result.
+ */
+class TimeoutException implements Exception {
+ /** The duration that was exceeded without a result. */
+ final Duration duration;
+
+ TimeoutException(this.duration);
+
+ String toString() => "Timeout after $duration";
}
/**
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 90e9df2..fb1280c 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -537,4 +537,37 @@
source = listener;
}
}
+
+ Future timeout(Duration timeLimit, [void onTimeout()]) {
+ if (_isComplete) return new _Future.immediate(this);
+ _Future result = new _Future();
+ Timer timer;
+ if (onTimeout == null) {
+ timer = new Timer(timeLimit, () {
+ result._completeError(new TimeoutException(timeLimit));
+ });
+ } else {
+ Zone zone = Zone.current;
+ onTimeout = zone.registerCallback(onTimeout);
+ timer = new Timer(timeLimit, () {
+ try {
+ result._complete(zone.run(onTimeout));
+ } catch (e, s) {
+ result._completeError(e, s);
+ }
+ });
+ }
+ this.then((T v) {
+ if (timer.isActive) {
+ timer.cancel();
+ result._complete(v);
+ }
+ }, onError: (e, s) {
+ if (timer.isActive) {
+ timer.cancel();
+ result._completeError(e, s);
+ }
+ });
+ return result;
+ }
}
diff --git a/sdk/lib/async/timer.dart b/sdk/lib/async/timer.dart
index 0fb0cea..8b2b115 100644
--- a/sdk/lib/async/timer.dart
+++ b/sdk/lib/async/timer.dart
@@ -60,7 +60,7 @@
* canceled with the [cancel] function.
*/
factory Timer.periodic(Duration duration,
- void callback(Timer timer)) {
+ void callback(Timer timer)) {
if (Zone.current == Zone.ROOT) {
// No need to bind the callback. We know that the root's timer will
// be invoked in the root zone.
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index 471a7d3..88b3054 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -359,7 +359,7 @@
f(arg1, arg2), { bool runGuarded: true });
/**
- * Runs [f] asynchronously.
+ * Runs [f] asynchronously in this zone.
*/
void scheduleMicrotask(void f());
@@ -732,20 +732,29 @@
}
void _rootScheduleMicrotask(Zone self, ZoneDelegate parent, Zone zone, f()) {
+ if (Zone.ROOT != zone) {
+ f = zone.bindCallback(f);
+ }
_scheduleAsyncCallback(f);
}
Timer _rootCreateTimer(Zone self, ZoneDelegate parent, Zone zone,
Duration duration, void callback()) {
+ if (Zone.ROOT != zone) {
+ callback = zone.bindCallback(callback);
+ }
return _createTimer(duration, callback);
}
Timer _rootCreatePeriodicTimer(
Zone self, ZoneDelegate parent, Zone zone,
Duration duration, void callback(Timer timer)) {
+ if (Zone.ROOT != zone) {
+ callback = zone.bindUnaryCallback(callback);
+ }
return _createPeriodicTimer(duration, callback);
-
}
+
void _rootPrint(Zone self, ZoneDelegate parent, Zone zone, String line) {
printToConsole(line);
}
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index 4c901a3..ca2b39e 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.dart
@@ -12,6 +12,15 @@
*
* All operations are defined in terms of `length`, `operator[]`,
* `operator[]=` and `length=`, which need to be implemented.
+ *
+ * *NOTICE*: Forwarding just these four operations to a normal growable [List]
+ * (as created by `new List()`) will give very bad performance for `add` and
+ * `addAll` operations of `ListBase`. These operations are implemented by
+ * increasing the length of the list by one for each `add` operation, and
+ * repeatedly increasing the length of a growable list is not efficient.
+ * To avoid this, either override 'add' and 'addAll' to also forward directly
+ * to the growable list, or, preferably, use `DelegatingList` from
+ * "package:collection_helpers/wrappers.dart" instead.
*/
abstract class ListBase<E> = Object with ListMixin<E>;
@@ -23,6 +32,15 @@
* This implements all read operations using only the `length` and
* `operator[]` members. It implements write operations using those and
* `length=` and `operator[]=`
+ *
+ * *NOTICE*: Forwarding just these four operations to a normal growable [List]
+ * (as created by `new List()`) will give very bad performance for `add` and
+ * `addAll` operations of `ListBase`. These operations are implemented by
+ * increasing the length of the list by one for each `add` operation, and
+ * repeatedly increasing the length of a growable list is not efficient.
+ * To avoid this, either override 'add' and 'addAll' to also forward directly
+ * to the growable list, or, if possible, use `DelegatingList` from
+ * "package:collection_helpers/wrappers.dart" instead.
*/
abstract class ListMixin<E> implements List<E> {
diff --git a/sdk/lib/core/int.dart b/sdk/lib/core/int.dart
index c06a3ee..6ca2718 100644
--- a/sdk/lib/core/int.dart
+++ b/sdk/lib/core/int.dart
@@ -246,8 +246,9 @@
* first the decimal digits 0..9, and then the letters 'a'..'z'.
* Accepts capital letters as well.
*
- * If no [radix] is given then it defaults to 16 if the string starts
- * with "0x", "-0x" or "+0x" and 10 otherwise.
+ * If no [radix] is given then it defaults to 10, unless the string starts
+ * with "0x", "-0x" or "+0x", in which case the radix is set to 16 and the
+ * "0x" is ignored.
*
* The [source] must be a non-empty sequence of base-[radix] digits,
* optionally prefixed with a minus or plus sign ('-' or '+').
diff --git a/sdk/lib/core/num.dart b/sdk/lib/core/num.dart
index 674ab2a..c6bb4f8 100644
--- a/sdk/lib/core/num.dart
+++ b/sdk/lib/core/num.dart
@@ -359,4 +359,33 @@
*
*/
String toString();
+
+ /**
+ * Parses a string containing a number literal into a number.
+ *
+ * The method first tries to read the [input] as integer (similar to
+ * [int.parse] without a radix).
+ * If that fails, it tries to parse the [input] as a double (similar to
+ * [double.parse]).
+ * If that fails, too, it invokes [onError] with [input].
+ *
+ * If no [onError] is supplied, it defaults to a function that throws a
+ * [FormatException].
+ *
+ * For any number `n`, this function satisfies
+ * `identical(n, num.parse(n.toString()))`.
+ */
+ static num parse(String input, [num onError(String input)]) {
+ String source = input.trim();
+ // TODO(lrn): Optimize to detect format and result type in one check.
+ num result = int.parse(source, onError: _returnNull);
+ if (result != null) return result;
+ result = double.parse(source, _returnNull);
+ if (result != null) return result;
+ if (onError == null) throw new FormatException(input);
+ return onError(input);
+ }
+
+ /** Helper function for [parse]. */
+ static _returnNull(_) => null;
}
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 6ff1c32..18735d0 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -36896,6 +36896,11 @@
static String addTrailingDot(String str) => '${str}.';
+ static String demangle(String str) {
+ var atPos = str.indexOf('@');
+ return atPos == -1 ? str : str.substring(0, atPos);
+ }
+
static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError;
static bool _isBuiltinType(ClassMirror cls) {
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 8a7ce39..cb1efe3 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -257,8 +257,9 @@
FileStat statSync() => FileStat.statSync(path);
Future<File> create({bool recursive: false}) {
- return (recursive ? parent.create(recursive: true)
- : new Future.value(null))
+ var result = recursive ? parent.create(recursive: true)
+ : new Future.value(null);
+ return result
.then((_) => _IOService.dispatch(_FILE_CREATE, [path]))
.then((response) {
if (_isErrorResponse(response)) {
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index 81d406d..896ef26 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.dart
@@ -353,8 +353,6 @@
* as expected.
* * `Mac OS`: Uses `FSEvents`. The implementation supports watching both
* files and directories. Recursive watching is supported.
- * Note: events happened slightly before calling [watch], may be part of
- * the returned stream, on Mac OS.
*
* The system will start listening for events once the returned [Stream] is
* being listened to, not when the call to [watch] is issued.
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index e4960fa..756db60 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -1749,13 +1749,13 @@
bool callback(X509Certificate certificate) =>
currentBadCertificateCallback == null ? false :
currentBadCertificateCallback(certificate, uriHost, uriPort);
- return (isSecure && proxy.isDirect
- ? SecureSocket.connect(host,
- port,
- sendClientCertificate: true,
- onBadCertificate: callback)
- : Socket.connect(host, port))
- .then((socket) {
+ Future socketFuture = (isSecure && proxy.isDirect
+ ? SecureSocket.connect(host,
+ port,
+ sendClientCertificate: true,
+ onBadCertificate: callback)
+ : Socket.connect(host, port));
+ return socketFuture.then((socket) {
socket.setOption(SocketOption.TCP_NODELAY, true);
var connection = new _HttpClientConnection(key, socket, this);
if (isSecure && !proxy.isDirect) {
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index 99bc7c7..de55780 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -842,7 +842,7 @@
return byte > 31 && byte < 128 && !_Const.SEPARATOR_MAP[byte];
}
- List<String> _tokenizeFieldValue(String headerValue) {
+ static List<String> _tokenizeFieldValue(String headerValue) {
List<String> tokens = new List<String>();
int start = 0;
int index = 0;
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index 7f07234..0ffcf0e 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.dart
@@ -166,8 +166,9 @@
if (Platform.operatingSystem == 'windows') {
target = _makeWindowsLinkTarget(target);
}
- return (recursive ? parent.create(recursive: true)
- : new Future.value(null))
+ var result = recursive ? parent.create(recursive: true)
+ : new Future.value(null);
+ return result
.then((_) => _IOService.dispatch(_FILE_CREATE_LINK, [path, target]))
.then((response) {
if (_isErrorResponse(response)) {
diff --git a/sdk/lib/io/websocket.dart b/sdk/lib/io/websocket.dart
index a3f2b25..1e2d0fa 100644
--- a/sdk/lib/io/websocket.dart
+++ b/sdk/lib/io/websocket.dart
@@ -53,7 +53,18 @@
*/
abstract class WebSocketTransformer
implements StreamTransformer<HttpRequest, WebSocket> {
- factory WebSocketTransformer() => new _WebSocketTransformerImpl();
+
+ /**
+ * Create a new [WebSocketTransformer].
+ *
+ * If [protocolSelector] is provided, [protocolSelector] will be called to
+ * select what protocol to use, if any were provided by the client.
+ * [protocolSelector] is should return either a [String] or a [Future]
+ * completing with a [String]. The [String] must exist in the list of
+ * protocols.
+ */
+ factory WebSocketTransformer({protocolSelector(List<String> protocols)})
+ => new _WebSocketTransformerImpl(protocolSelector);
/**
* Upgrades a [HttpRequest] to a [WebSocket] connection. If the
@@ -61,9 +72,16 @@
* with status code 500 will be returned. Otherwise the returned
* future will complete with the [WebSocket] when the upgrade pocess
* is complete.
+ *
+ * If [protocolSelector] is provided, [protocolSelector] will be called to
+ * select what protocol to use, if any were provided by the client.
+ * [protocolSelector] is should return either a [String] or a [Future]
+ * completing with a [String]. The [String] must exist in the list of
+ * protocols.
*/
- static Future<WebSocket> upgrade(HttpRequest request) {
- return _WebSocketTransformerImpl._upgrade(request);
+ static Future<WebSocket> upgrade(HttpRequest request,
+ {protocolSelector(List<String> protocols)}) {
+ return _WebSocketTransformerImpl._upgrade(request, protocolSelector);
}
/**
@@ -78,7 +96,7 @@
/**
* A two-way HTTP communication object for client or server applications.
*
- * The stream exposes the messages received. A text message will be of type
+ * The stream exposes the messages received. A text message will be of type
* [:String:] and a binary message will be of type [:List<int>:].
*/
abstract class WebSocket implements Stream, StreamSink {
@@ -92,11 +110,11 @@
/**
* Create a new web socket connection. The URL supplied in [url]
- * must use the scheme [:ws:] or [:wss:]. The [protocols] argument is either
- * a [:String:] or [:List<String>:] specifying the subprotocols the
- * client is willing to speak.
+ * must use the scheme [:ws:] or [:wss:]. The [protocols] argument is
+ * specifying the subprotocols the client is willing to speak.
*/
- static Future<WebSocket> connect(String url, [protocols]) =>
+ static Future<WebSocket> connect(String url,
+ {List<String> protocols: const []}) =>
_WebSocketImpl.connect(url, protocols);
/**
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index 6a62609..556de41 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -393,10 +393,13 @@
class _WebSocketTransformerImpl implements WebSocketTransformer {
final StreamController<WebSocket> _controller =
new StreamController<WebSocket>(sync: true);
+ final Function _protocolSelector;
+
+ _WebSocketTransformerImpl(this._protocolSelector);
Stream<WebSocket> bind(Stream<HttpRequest> stream) {
stream.listen((request) {
- _upgrade(request)
+ _upgrade(request, _protocolSelector)
.then((WebSocket webSocket) => _controller.add(webSocket))
.catchError(_controller.addError);
});
@@ -404,31 +407,58 @@
return _controller.stream;
}
- static Future<WebSocket> _upgrade(HttpRequest request) {
+ static Future<WebSocket> _upgrade(HttpRequest request, _protocolSelector) {
var response = request.response;
if (!_isUpgradeRequest(request)) {
- // Send error response and drain the request.
- request.listen((_) {}, onDone: () {
- response.statusCode = HttpStatus.BAD_REQUEST;
- response.contentLength = 0;
- response.close();
- });
+ // Send error response.
+ response.statusCode = HttpStatus.BAD_REQUEST;
+ response.close();
return new Future.error(
new WebSocketException("Invalid WebSocket upgrade request"));
}
- // Send the upgrade response.
- response.statusCode = HttpStatus.SWITCHING_PROTOCOLS;
- response.headers.add(HttpHeaders.CONNECTION, "Upgrade");
- response.headers.add(HttpHeaders.UPGRADE, "websocket");
- String key = request.headers.value("Sec-WebSocket-Key");
- _SHA1 sha1 = new _SHA1();
- sha1.add("$key$_webSocketGUID".codeUnits);
- String accept = _CryptoUtils.bytesToBase64(sha1.close());
- response.headers.add("Sec-WebSocket-Accept", accept);
- response.headers.contentLength = 0;
- return response.detachSocket()
- .then((socket) => new _WebSocketImpl._fromSocket(socket, true));
+ Future upgrade(String protocol) {
+ // Send the upgrade response.
+ response.statusCode = HttpStatus.SWITCHING_PROTOCOLS;
+ response.headers.add(HttpHeaders.CONNECTION, "Upgrade");
+ response.headers.add(HttpHeaders.UPGRADE, "websocket");
+ String key = request.headers.value("Sec-WebSocket-Key");
+ _SHA1 sha1 = new _SHA1();
+ sha1.add("$key$_webSocketGUID".codeUnits);
+ String accept = _CryptoUtils.bytesToBase64(sha1.close());
+ response.headers.add("Sec-WebSocket-Accept", accept);
+ if (protocol != null && protocol.isNotEmpty) {
+ response.headers.add("Sec-WebSocket-Protocol", protocol);
+ }
+ response.headers.contentLength = 0;
+ return response.detachSocket()
+ .then((socket) => new _WebSocketImpl._fromSocket(
+ socket, protocol, true));
+ }
+
+ var protocols = request.headers['Sec-WebSocket-Protocol'];
+ if (protocols != null && _protocolSelector != null) {
+ // The suggested protocols can be spread over multiple lines, each
+ // consisting of multiple protocols. To unify all of them, first join
+ // the lists with ', ' and then tokenize.
+ protocols = _HttpParser._tokenizeFieldValue(protocols.join(', '));
+ return new Future(() => _protocolSelector(protocols))
+ .then((protocol) {
+ if (protocols.indexOf(protocol) < 0) {
+ throw new WebSocketException(
+ "Selected protocol is not in the list of available protocols");
+ }
+ return protocol;
+ })
+ .catchError((error) {
+ response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
+ response.close();
+ throw error;
+ })
+ .then(upgrade);
+ } else {
+ return upgrade(null);
+ }
}
static bool _isUpgradeRequest(HttpRequest request) {
@@ -724,6 +754,8 @@
class _WebSocketImpl extends Stream implements WebSocket {
+ final String protocol;
+
StreamController _controller;
StreamSubscription _subscription;
StreamSink _sink;
@@ -743,7 +775,7 @@
static final HttpClient _httpClient = new HttpClient();
- static Future<WebSocket> connect(String url, [protocols]) {
+ static Future<WebSocket> connect(String url, List<String> protocols) {
Uri uri = Uri.parse(url);
if (uri.scheme != "ws" && uri.scheme != "wss") {
throw new WebSocketException("Unsupported URL scheme '${uri.scheme}'");
@@ -774,6 +806,9 @@
request.headers.set(HttpHeaders.UPGRADE, "websocket");
request.headers.set("Sec-WebSocket-Key", nonce);
request.headers.set("Sec-WebSocket-Version", "13");
+ if (protocols.isNotEmpty) {
+ request.headers.add("Sec-WebSocket-Protocol", protocols);
+ }
return request.close();
})
.then((response) {
@@ -808,12 +843,14 @@
error("Bad response 'Sec-WebSocket-Accept' header");
}
}
+ var protocol = response.headers.value('Sec-WebSocket-Protocol');
return response.detachSocket()
- .then((socket) => new _WebSocketImpl._fromSocket(socket));
+ .then((socket) => new _WebSocketImpl._fromSocket(socket, protocol));
});
}
_WebSocketImpl._fromSocket(Socket this._socket,
+ String this.protocol,
[bool this._serverSide = false]) {
_consumer = new _WebSocketConsumer(this, _socket);
_sink = new _StreamSinkImpl(_consumer);
@@ -893,7 +930,6 @@
int get readyState => _readyState;
String get extensions => null;
- String get protocol => null;
int get closeCode => _closeCode;
String get closeReason => _closeReason;
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index c6b9253..efc6ca2 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -208,7 +208,7 @@
void close();
/**
- * Returns a [SendPort] that sends to this receive port.
+ * Returns a [SendPort] that sends to this raw receive port.
*/
SendPort get sendPort;
}
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index 027b197..ce9c8e7 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -538,7 +538,8 @@
* If the invocation returns a result *r*, this method returns
* the result of calling [reflect](*r*).
* If the invocation causes a compilation error
- * this method throws a [MirrorError].
+ * the effect is the same as if a non-reflective compilation error
+ * had been encountered.
* If the invocation throws an exception *e* (that it does not catch)
* this method throws *e*.
*/
diff --git a/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart b/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
index 6bcb22e..6a4e0f1 100644
--- a/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
+++ b/sdk/lib/typed_data/dart2js/typed_data_dart2js.dart
@@ -10,7 +10,7 @@
import 'dart:collection';
import 'dart:_collection-dev';
-import 'dart:_interceptors' show JSIndexable;
+import 'dart:_interceptors' show JSIndexable, JSUInt32, JSUInt31;
import 'dart:_js_helper'
show Creates, JavaScriptIndexingBehavior, JSName, Null, Returns;
import 'dart:_foreign_helper' show JS, JS_CONST;
@@ -259,7 +259,7 @@
_getUint16(byteOffset, endian._littleEndian);
@JSName('getUint16')
- @Returns('int')
+ @Returns('JSUInt31')
int _getUint16(int byteOffset, [bool littleEndian]) native;
/**
@@ -268,12 +268,14 @@
* 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]) =>
_getUint32(byteOffset, endian._littleEndian);
@JSName('getUint32')
- @Returns('int')
+ @Returns('JSUInt32')
int _getUint32(int byteOffset, [bool littleEndian]) native;
/**
@@ -500,7 +502,7 @@
static const int BYTES_PER_ELEMENT = 4;
- int get length => JS("int", '#.length', this);
+ int get length => JS("JSUInt32", '#.length', this);
num operator[](int index) {
_checkIndex(index, length);
@@ -575,7 +577,7 @@
static const int BYTES_PER_ELEMENT = 8;
- int get length => JS("int", '#.length', this);
+ int get length => JS("JSUInt32", '#.length', this);
num operator[](int index) {
_checkIndex(index, length);
@@ -651,7 +653,7 @@
static const int BYTES_PER_ELEMENT = 2;
- int get length => JS("int", '#.length', this);
+ int get length => JS("JSUInt32", '#.length', this);
int operator[](int index) {
_checkIndex(index, length);
@@ -724,7 +726,7 @@
static const int BYTES_PER_ELEMENT = 4;
- int get length => JS("int", '#.length', this);
+ int get length => JS("JSUInt32", '#.length', this);
int operator[](int index) {
_checkIndex(index, length);
@@ -794,7 +796,7 @@
static const int BYTES_PER_ELEMENT = 1;
- int get length => JS("int", '#.length', this);
+ int get length => JS("JSUInt32", '#.length', this);
int operator[](int index) {
_checkIndex(index, length);
@@ -868,11 +870,11 @@
static const int BYTES_PER_ELEMENT = 2;
- int get length => JS("int", '#.length', this);
+ int get length => JS("JSUInt32", '#.length', this);
int operator[](int index) {
_checkIndex(index, length);
- return JS("int", "#[#]", this, index);
+ return JS("JSUInt31", "#[#]", this, index);
}
void operator[]=(int index, int value) {
@@ -942,11 +944,11 @@
static const int BYTES_PER_ELEMENT = 4;
- int get length => JS("int", '#.length', this);
+ int get length => JS("JSUInt32", '#.length', this);
int operator[](int index) {
_checkIndex(index, length);
- return JS("int", "#[#]", this, index);
+ return JS("JSUInt32", "#[#]", this, index);
}
void operator[]=(int index, int value) {
@@ -1013,11 +1015,11 @@
static const int BYTES_PER_ELEMENT = 1;
- int get length => JS("int", '#.length', this);
+ int get length => JS("JSUInt32", '#.length', this);
int operator[](int index) {
_checkIndex(index, length);
- return JS("int", "#[#]", this, index);
+ return JS("JSUInt31", "#[#]", this, index);
}
void operator[]=(int index, int value) {
@@ -1089,11 +1091,11 @@
static const int BYTES_PER_ELEMENT = 1;
- int get length => JS("int", '#.length', this);
+ int get length => JS("JSUInt32", '#.length', this);
int operator[](int index) {
_checkIndex(index, length);
- return JS("int", "#[#]", this, index);
+ return JS("JSUInt31", "#[#]", this, index);
}
void operator[]=(int index, int value) {
@@ -1362,7 +1364,8 @@
}
void _checkIndex(int index, int length) {
- if (JS('bool', '(# >>> 0 != #)', index, index) || index >= length) {
+ if (JS('bool', '(# >>> 0 != #)', index, index)
+ || JS('bool', '# >= #', index, length)) {
_invalidIndex(index, length);
}
}
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index 4464fea..9d37eb6 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.dart
@@ -229,6 +229,8 @@
* 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]);
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index c35487e..3212583 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -15,18 +15,18 @@
LibTest/core/Stopwatch/start_A01_t02: PASS, FAIL, OK # co19 issue 657
LibTest/core/Stopwatch/elapsedTicks_A01_t01: PASS, FAIL, OK # co19 issue 657
-LibTest/isolate/Isolate/spawnUri_A01_t01: Fail # co19-roll r667: Please triage this failure
-LibTest/isolate/Isolate/spawnUri_A01_t02: Fail # co19-roll r667: Please triage this failure
-LibTest/isolate/Isolate/spawnUri_A01_t03: Fail # co19-roll r667: Please triage this failure
-LibTest/isolate/Isolate/spawnUri_A01_t04: Fail # co19-roll r667: Please triage this failure
-LibTest/isolate/Isolate/spawnUri_A01_t05: Fail # co19-roll r667: Please triage this failure
-LibTest/isolate/Isolate/spawnFunction_A02_t01: Fail # co19-roll r667: Please triage this failure
-LibTest/isolate/Isolate/spawnFunction_A03_t01: Fail # co19-roll r667: Please triage this failure
-LibTest/isolate/Isolate/spawnFunction_A04_t01: Fail # co19-roll r667: Please triage this failure
-LibTest/isolate/Isolate/spawnFunction_A04_t02: Fail # co19-roll r667: Please triage this failure
-LibTest/isolate/Isolate/spawnFunction_A04_t03: Fail # co19-roll r667: Please triage this failure
-LibTest/isolate/Isolate/spawnUri_A02_t02: Fail # co19-roll r667: Please triage this failure
-LibTest/isolate/Isolate/spawnUri_A02_t03: Fail # co19-roll r667: Please triage this failure
+LibTest/isolate/Isolate/spawnUri_A01_t01: Fail, OK # co19 issue 639
+LibTest/isolate/Isolate/spawnUri_A01_t02: Fail, OK # co19 issue 639
+LibTest/isolate/Isolate/spawnUri_A01_t03: Fail, OK # co19 issue 639
+LibTest/isolate/Isolate/spawnUri_A01_t04: Fail, OK # co19 issue 639
+LibTest/isolate/Isolate/spawnUri_A01_t05: Fail, OK # co19 issue 639
+LibTest/isolate/Isolate/spawnFunction_A02_t01: Fail, OK # co19 issue 639
+LibTest/isolate/Isolate/spawnFunction_A03_t01: Fail, OK # co19 issue 639
+LibTest/isolate/Isolate/spawnFunction_A04_t01: Fail, OK # co19 issue 639
+LibTest/isolate/Isolate/spawnFunction_A04_t02: Fail, OK # co19 issue 639
+LibTest/isolate/Isolate/spawnFunction_A04_t03: Fail, OK # co19 issue 639
+LibTest/isolate/Isolate/spawnUri_A02_t02: Fail, OK # co19 issue 639
+LibTest/isolate/Isolate/spawnUri_A02_t03: Fail, OK # co19 issue 639
[ $runtime == vm || $runtime == dartium || $compiler == dart2dart || $compiler == dart2js ]
@@ -38,7 +38,8 @@
Language/07_Classes/6_Constructors/1_Generative_Constructors_A12_t02: fail # co19-roll r587: Please triage this failure
Language/07_Classes/6_Constructors/1_Generative_Constructors_A20_t02: fail # co19-roll r587: Please triage this failure
-LibTest/collection/LinkedList/forEach_A02_t01: RuntimeError # co19-roll r607: Please triage this failure
+LibTest/collection/LinkedList/forEach_A02_t01: RuntimeError, OK # co19 issue 662
+
LibTest/core/Invocation/namedArguments_A01_t01: RuntimeError # co19-roll r607: Please triage this failure
LibTest/core/Symbol/Symbol_A01_t04: RuntimeError # co19-roll r607: Please triage this failure
LibTest/core/Set/intersection_A02_t01: Fail, OK # Issue 659
@@ -46,14 +47,15 @@
Language/07_Classes/07_Classes_A13_t01: Pass, MissingCompileTimeError, Fail # co19-roll r623: Please triage this failure
Language/07_Classes/07_Classes_A13_t04: Pass, MissingCompileTimeError, Fail # co19-roll r623: Please triage this failure
Language/07_Classes/07_Classes_A13_t07: Pass, MissingCompileTimeError, Fail # co19-roll r623: Please triage this failure
-LibTest/collection/HashSet/HashSet_class_A01_t01: RuntimeError # co19-roll r623: Please triage this failure
-LibTest/collection/LinkedHashSet/LinkedHashSet_class_A01_t01: RuntimeError # co19-roll r623: Please triage this failure
-LibTest/core/Set/IterableBase_A01_t01: RuntimeError # co19-roll r623: Please triage this failure
+
+LibTest/collection/HashSet/HashSet_class_A01_t01: RuntimeError, OK # co19 issue 663
+LibTest/collection/LinkedHashSet/LinkedHashSet_class_A01_t01: RuntimeError, OK # co19 issue 663
+LibTest/core/Set/IterableBase_A01_t01: RuntimeError, OK # co19 issue 663
LibTest/core/Uri/toFilePath_A01_t01: pass, fail, ok # co19 Issue 592
-LibTest/collection/ListBase/ListBase_class_A01_t01: Fail, Timeout # co19-roll r641: Please triage this failure
-LibTest/collection/ListMixin/ListMixin_class_A01_t01: Fail, Timeout # co19-roll r641: Please triage this failure
+LibTest/collection/ListBase/ListBase_class_A01_t01: Skip, OK # co19 issue 661
+LibTest/collection/ListMixin/ListMixin_class_A01_t01: Skip, OK # co19 issue 661
[ $runtime == vm || $runtime == dartium || $compiler == dart2js ]
LibTest/math/acos_A01_t01: PASS, FAIL, OK # co19 issue 44
@@ -61,6 +63,7 @@
LibTest/math/atan_A01_t01: PASS, FAIL, OK # co19 issue 44
LibTest/math/cos_A01_t01: PASS, FAIL, OK # co19 issue 44
+LibTest/math/tan_A01_t01: PASS, FAIL, OK # co19 issue 44
LibTest/core/double/ceil_A01_t03: FAIL, OK # co19 issue 389
LibTest/core/double/ceil_A01_t04: FAIL, OK # co19 issue 389
@@ -83,7 +86,6 @@
LibTest/math/exp_A01_t01: PASS, FAIL, OK # co19 issue 44
LibTest/math/sin_A01_t01: PASS, FAIL, OK # co19 issue 44
-LibTest/math/tan_A01_t01: PASS, FAIL, OK # co19 issue 44
LibTest/async/Stream/Stream.periodic_A03_t01: PASS, FAIL, OK # co19 issue 538
LibTest/async/Timer/run_A01_t01: PASS, FAIL, OK # co19 issue 538
@@ -137,7 +139,6 @@
Language/13_Statements/09_Switch_A09_t01: PASS, FAIL, OK # co19 issue 633
LibTest/collection/DoubleLinkedQueue/removeFirst_A01_t01: RuntimeError # co19-roll r607: Please triage this failure
LibTest/collection/LinkedList/LinkedList_A01_t01: RuntimeError # co19-roll r623: Please triage this failure
-LibTest/typed_data/Float32x4List/reduce_A01_t01: Fail # co19-roll r623: Please triage this failure
[ ($runtime == vm || $compiler == dart2js) && $checked]
Language/14_Libraries_and_Scripts/1_Imports_A03_t46: PASS, FAIL, OK # co19 issue 560
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index bcc9b79..ce36919 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -27,7 +27,6 @@
Language/05_Variables/05_Variables_A11_t01: fail
LibTest/core/double/INFINITY_A01_t04: RuntimeError # TODO(ahe): Please triage this failure.
LibTest/core/double/NEGATIVE_INFINITY_A01_t04: RuntimeError # TODO(ahe): Please triage this failure.
-LibTest/core/List/List_A03_t01: RuntimeError # TODO(kasperl): Please triage this failure.
LibTest/typed_data/ByteData/getFloat32_A02_t02: fail # co19-roll r569: Please triage this failure
LibTest/typed_data/ByteData/getFloat64_A02_t02: fail # co19-roll r569: Please triage this failure
@@ -115,7 +114,7 @@
Language/15_Types/2_Dynamic_Type_System_A01_t02: RuntimeError # co19-roll r607: Please triage this failure
Language/15_Types/8_Parameterized_Types_A03_t07: RuntimeError # co19-roll r607: Please triage this failure
Language/15_Types/1_Static_Types_A03_t01: RuntimeError # co19-roll r623: Please triage this failure
-
+LibTest/typed_data/Float32x4List/reduce_A01_t01: RuntimeError # co19-roll r623: Please triage this failure
[ $compiler == dart2js ]
LibTest/core/int/operator_GT_A01_t01: RuntimeError, OK # co19 issue 200
@@ -152,6 +151,52 @@
LibTest/core/RegExp/Pattern_semantics/firstMatch_Term_A04_t01: RuntimeError, OK # co19 issue 212
+[ $compiler == dart2js || $compiler == dart2dart ]
+
+Language/12_Expressions/05_Strings_A02_t02: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t03: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t04: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t05: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t06: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t07: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t08: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t09: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t10: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t11: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t12: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t13: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t14: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t15: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t16: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t17: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t18: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t19: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t20: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t21: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t22: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t23: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t24: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t25: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t28: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t29: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t32: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t32: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t33: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t34: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t36: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t38: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t40: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t42: Crash # Issue 15237
+Language/12_Expressions/05_Strings_A02_t44: Crash # Issue 15237
+
+
+Language/13_Statements/05_If_A01_t04: Crash # Issue 15237
+Language/13_Statements/07_While_A01_t01: Crash # Issue 15237
+Language/13_Statements/08_Do_A01_t03: Crash # Issue 15237
+Language/13_Statements/09_Switch_A01_t04: Crash # Issue 15237
+Language/16_Reference/1_Lexical_Rules/1_Reserved_Words_A15_t06: Crash # Issue 15237
+Language/16_Reference/1_Lexical_Rules/1_Reserved_Words_A22_t06: Crash # Issue 15237
+Language/16_Reference/1_Lexical_Rules/1_Reserved_Words_A29_t06: Crash # Issue 15237
#
# Issues with co19 test suite.
@@ -439,7 +484,6 @@
LibTest/core/DateTime/DateTime_A01_t03: fail # co19-roll r546: Please triage this failure
LibTest/core/DateTime/parse_A03_t01: fail # co19-roll r546: Please triage this failure
LibTest/core/Duration/operator_div_A01_t01: fail # co19-roll r546: Please triage this failure
-LibTest/core/List/List_A02_t01: fail # co19-roll r546: Please triage this failure
LibTest/core/Match/pattern_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/core/RegExp/allMatches_A01_t01: fail # co19-roll r559: Please triage this failure
LibTest/isolate/IsolateStream/any_A02_t01: fail # co19-roll r546: Please triage this failure
@@ -486,7 +530,6 @@
LibTest/typed_data/Uint8List/Uint8List.view_A05_t02: RuntimeError # co19-roll r559: Please triage this failure
LibTest/typed_data/Uint8List/Uint8List.view_A05_t03: RuntimeError # co19-roll r559: Please triage this failure
Utils/tests/Expect/identical_A01_t01: fail # co19-roll r546: Please triage this failure
-Language/12_Expressions/15_Method_Invocation/4_Super_Invocation_A02_t05: CompileTimeError # co19-roll r607: Please triage this failure
[ $compiler == dart2js && $checked ]
Language/12_Expressions/03_Numbers_A05_t02: fail # co19-roll r546: Please triage this failure
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index b9241e7..df0e9c9 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -84,27 +84,6 @@
LibTest/core/Uri/Uri_A06_t03: Pass, Timeout # co19-roll r576: Please triage this failure
[ $compiler == none && $checked && ($runtime == vm || $runtime == dartium) ]
-LibTest/typed_data/Float32x4List/elementAt_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/fillRange_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/first_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/first_A03_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/firstWhere_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/firstWhere_A02_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/getRange_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/getRange_A02_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/last_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/lastWhere_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/map_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/map_A02_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/map_A03_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/operator_subscript_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/operator_subscripted_assignment_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/reversed_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/single_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/singleWhere_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/skip_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/take_A01_t01: Fail # Dart issue 12861
-LibTest/typed_data/Float32x4List/take_A02_t01: Fail # Dart issue 12861
Language/15_Types/1_Static_Types_A03_t01: RuntimeError # co19-roll r667: Please triage this failure
[ $compiler == none && $runtime == vm && $system == windows && $mode == debug ]
diff --git a/tests/co19/test_config.dart b/tests/co19/test_config.dart
index d37b5fa..b21a49c 100644
--- a/tests/co19/test_config.dart
+++ b/tests/co19/test_config.dart
@@ -4,7 +4,6 @@
library co19_test_config;
-import 'dart:io';
import '../../tools/testing/dart/test_suite.dart';
import '../../tools/testing/dart/utils.dart' show Path;
diff --git a/tests/compiler/dart2js/array_tracing_mirror_test.dart b/tests/compiler/dart2js/array_tracing_mirror_test.dart
new file mode 100644
index 0000000..fe5324c
--- /dev/null
+++ b/tests/compiler/dart2js/array_tracing_mirror_test.dart
@@ -0,0 +1,41 @@
+// 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.
+
+// Make sure that limiting mirrors through @MirrorsUsed does not
+// affect optimizations done on arrays.
+
+import 'package:expect/expect.dart';
+import "package:async_helper/async_helper.dart";
+import 'memory_compiler.dart';
+
+const MEMORY_SOURCE_FILES = const {
+ 'main.dart': '''
+
+@MirrorsUsed(targets: 'main')
+import 'dart:mirrors';
+class A {
+ var field;
+}
+
+main() {
+ var a = new A();
+ var mirror = reflect(a);
+ var array = [42, 42];
+ a.field = array;
+ var field = mirror.getField(#field);
+ field.invoke(#clear, []);
+ return array.length;
+}
+''',
+};
+
+main() {
+ var compiler = compilerFor(MEMORY_SOURCE_FILES);
+ asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+ var element = compiler.mainApp.findExported('main');
+ var code = compiler.backend.assembleCode(element);
+ Expect.isTrue(code.contains('return 2'));
+ }));
+}
+
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 04e6b13..6d56f4f 100644
--- a/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
+++ b/tests/compiler/dart2js/call_site_simple_type_inferer_test.dart
@@ -225,7 +225,8 @@
var inferrer = compiler.typesTask.typesInferrer;
signature.forEachParameter((Element element) {
Expect.equals(expectedTypes[index++],
- inferrer.getTypeOfElement(element).simplify(compiler));
+ inferrer.getTypeOfElement(element).simplify(compiler),
+ test);
});
Expect.equals(index, expectedTypes.length);
});
@@ -242,7 +243,7 @@
void test() {
runTest(TEST_1, (compiler) => [compiler.typesTask.stringType]);
- runTest(TEST_2, (compiler) => [compiler.typesTask.intType]);
+ runTest(TEST_2, (compiler) => [compiler.typesTask.uint31Type]);
runTest(TEST_3, (compiler) => [compiler.typesTask.intType]);
runTest(TEST_4, (compiler) => [compiler.typesTask.numType]);
runTest(TEST_5, (compiler) => [compiler.typesTask.numType]);
@@ -251,32 +252,32 @@
runTest(TEST_7b,
(compiler) => [compiler.typesTask.dynamicType.nonNullable()]);
- runTest(TEST_8, (compiler) => [compiler.typesTask.intType,
+ runTest(TEST_8, (compiler) => [compiler.typesTask.uint31Type,
subclassOfInterceptor(compiler),
compiler.typesTask.dynamicType.nonNullable()]);
- runTest(TEST_9, (compiler) => [compiler.typesTask.intType,
- compiler.typesTask.intType]);
- runTest(TEST_10, (compiler) => [compiler.typesTask.intType,
- compiler.typesTask.intType]);
+ runTest(TEST_9, (compiler) => [compiler.typesTask.uint31Type,
+ compiler.typesTask.uint31Type]);
+ runTest(TEST_10, (compiler) => [compiler.typesTask.uint31Type,
+ compiler.typesTask.uint31Type]);
runTest(TEST_11, (compiler) => [subclassOfInterceptor(compiler),
subclassOfInterceptor(compiler)]);
runTest(TEST_12, (compiler) => [compiler.typesTask.stringType,
- compiler.typesTask.intType]);
+ compiler.typesTask.uint31Type]);
runTest(TEST_13, (compiler) => [compiler.typesTask.numType]);
- runTest(TEST_14, (compiler) => [compiler.typesTask.intType,
+ runTest(TEST_14, (compiler) => [compiler.typesTask.uint31Type,
compiler.typesTask.stringType]);
runTest(TEST_15, (compiler) => [compiler.typesTask.stringType,
compiler.typesTask.boolType]);
- runTest(TEST_16, (compiler) => [compiler.typesTask.intType,
- compiler.typesTask.intType,
+ runTest(TEST_16, (compiler) => [compiler.typesTask.uint31Type,
+ compiler.typesTask.uint31Type,
compiler.typesTask.stringType]);
- runTest(TEST_17, (compiler) => [compiler.typesTask.intType,
+ runTest(TEST_17, (compiler) => [compiler.typesTask.uint31Type,
compiler.typesTask.boolType,
compiler.typesTask.doubleType]);
diff --git a/tests/compiler/dart2js/concrete_type_inference_test.dart b/tests/compiler/dart2js/concrete_type_inference_test.dart
index b01868b..746a502 100644
--- a/tests/compiler/dart2js/concrete_type_inference_test.dart
+++ b/tests/compiler/dart2js/concrete_type_inference_test.dart
@@ -63,7 +63,7 @@
});
checkPrintType('1', (compiler, type) {
var inferrer = compiler.typesTask.typesInferrer;
- Expect.identical(compiler.typesTask.intType, type);
+ Expect.identical(compiler.typesTask.uint31Type, type);
});
checkPrintType('[]', (compiler, type) {
var inferrer = compiler.typesTask.typesInferrer;
@@ -94,7 +94,7 @@
var typesTask = compiler.typesTask;
var inferrer = typesTask.typesInferrer;
Expect.identical(
- typesTask.intType,
+ typesTask.uint31Type,
typesTask.getGuaranteedTypeOfElement(firstParameter));
Expect.identical(
typesTask.nullType,
diff --git a/tests/compiler/dart2js/constant_folding_test.dart b/tests/compiler/dart2js/constant_folding_test.dart
index 44f2e06..cdf4c1d 100644
--- a/tests/compiler/dart2js/constant_folding_test.dart
+++ b/tests/compiler/dart2js/constant_folding_test.dart
@@ -81,11 +81,11 @@
LIST_INDEX_FOLDING, 'foo', new RegExp(r"return 1"));
compileAndDoNotMatch(
- LIST_INDEX_FOLDING, 'foo', new RegExp(r"throw"));
+ LIST_INDEX_FOLDING, 'foo', new RegExp(r"ioore"));
compileAndMatch(
STRING_LENGTH_FOLDING, 'foo', new RegExp(r"return 3"));
compileAndMatch(
- RANGE_ERROR_INDEX_FOLDING, 'foo', new RegExp(r"throw"));
+ RANGE_ERROR_INDEX_FOLDING, 'foo', new RegExp(r"ioore"));
}
diff --git a/tests/compiler/dart2js/container_mask_equal_test.dart b/tests/compiler/dart2js/container_mask_equal_test.dart
new file mode 100644
index 0000000..f082bef
--- /dev/null
+++ b/tests/compiler/dart2js/container_mask_equal_test.dart
@@ -0,0 +1,49 @@
+// 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.
+
+// Regression test for dart2js that used to have a bogus
+// implementation of var.== and
+// var.hashCode.
+
+import 'package:expect/expect.dart';
+import "package:async_helper/async_helper.dart";
+import 'memory_compiler.dart';
+
+const MEMORY_SOURCE_FILES = const {
+ 'main.dart': '''
+
+import 'dart:typed_data';
+
+a() => [0];
+b() => [1, 2];
+c() => new Uint8List(1);
+d() => new Uint8List(2);
+
+main() {
+ print(a); print(b); print(c); print(d);
+}
+''',
+};
+
+main() {
+ var compiler = compilerFor(MEMORY_SOURCE_FILES);
+ asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+ var typesInferrer = compiler.typesTask.typesInferrer;
+
+ var element = compiler.mainApp.find('a');
+ var mask1 = typesInferrer.getReturnTypeOfElement(element);
+
+ element = compiler.mainApp.find('b');
+ var mask2 = typesInferrer.getReturnTypeOfElement(element);
+
+ element = compiler.mainApp.find('c');
+ var mask3 = typesInferrer.getReturnTypeOfElement(element);
+
+ element = compiler.mainApp.find('d');
+ var mask4 = typesInferrer.getReturnTypeOfElement(element);
+
+ Expect.notEquals(mask1.union(mask2, compiler),
+ mask3.union(mask4, compiler));
+ }));
+}
diff --git a/tests/compiler/dart2js/exit_code_helper.dart b/tests/compiler/dart2js/exit_code_helper.dart
new file mode 100644
index 0000000..d3c6121
--- /dev/null
+++ b/tests/compiler/dart2js/exit_code_helper.dart
@@ -0,0 +1,3 @@
+void main() {
+
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js/exit_code_test.dart b/tests/compiler/dart2js/exit_code_test.dart
new file mode 100644
index 0000000..68cfa76
--- /dev/null
+++ b/tests/compiler/dart2js/exit_code_test.dart
@@ -0,0 +1,232 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test the exit code of dart2js in case of exceptions, fatal errors, errors,
+// warnings, etc.
+
+
+import 'dart:async';
+import 'dart:io' show Platform;
+
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
+
+import '../../../sdk/lib/_internal/compiler/compiler.dart' as api;
+import '../../../sdk/lib/_internal/compiler/implementation/dart2js.dart' as entry;
+import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/apiimpl.dart' as apiimpl;
+import '../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/scanner/scannerlib.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/util/util.dart';
+
+class TestCompiler extends apiimpl.Compiler {
+ final String testMarker;
+ final String testType;
+ final Function onTest;
+
+ TestCompiler(api.CompilerInputProvider inputProvider,
+ api.CompilerOutputProvider outputProvider,
+ api.DiagnosticHandler handler,
+ Uri libraryRoot,
+ Uri packageRoot,
+ List<String> options,
+ Map<String, dynamic> environment,
+ String this.testMarker,
+ String this.testType,
+ Function this.onTest)
+ : super(inputProvider, outputProvider, handler, libraryRoot,
+ packageRoot, options, environment) {
+ scanner = new TestScanner(this);
+ test('Compiler');
+ }
+
+ Future<bool> run(Uri uri) {
+ test('Compiler.run');
+ return super.run(uri);
+ }
+
+ TreeElements analyzeElement(Element element) {
+ test('Compiler.analyzeElement');
+ return super.analyzeElement(element);
+ }
+
+ void codegen(CodegenWorkItem work, CodegenEnqueuer world) {
+ test('Compiler.codegen');
+ super.codegen(work, world);
+ }
+
+ withCurrentElement(Element element, f()) {
+ return super.withCurrentElement(element, () {
+ test('Compiler.withCurrentElement');
+ return f();
+ });
+ }
+
+ test(String marker) {
+ if (marker == testMarker) {
+ switch (testType) {
+ case 'assert':
+ onTest(testMarker, testType);
+ assert(false);
+ break;
+ case 'invariant':
+ onTest(testMarker, testType);
+ invariant(CURRENT_ELEMENT_SPANNABLE, false, message: marker);
+ break;
+ case 'warning':
+ onTest(testMarker, testType);
+ reportWarningCode(CURRENT_ELEMENT_SPANNABLE,
+ MessageKind.GENERIC, {'text': marker});
+ break;
+ case 'error':
+ onTest(testMarker, testType);
+ reportError(CURRENT_ELEMENT_SPANNABLE,
+ MessageKind.GENERIC, {'text': marker});
+ break;
+ case 'fatalError':
+ onTest(testMarker, testType);
+ reportFatalError(CURRENT_ELEMENT_SPANNABLE,
+ MessageKind.GENERIC, {'text': marker});
+ break;
+ case 'NoSuchMethodError':
+ onTest(testMarker, testType);
+ null.foo;
+ break;
+ case '':
+ onTest(testMarker, testType);
+ break;
+ }
+ }
+ }
+}
+
+class TestScanner extends ScannerTask {
+ TestScanner(TestCompiler compiler) : super(compiler);
+
+ TestCompiler get compiler => super.compiler;
+
+ void scanElements(CompilationUnitElement compilationUnit) {
+ compiler.test('ScannerTask.scanElements');
+ super.scanElements(compilationUnit);
+ }
+}
+
+int checkedResults = 0;
+
+Future testExitCode(String marker, String type, int expectedExitCode) {
+ bool testOccurred = false;
+
+ void onTest(String testMarker, String testType) {
+ if (testMarker == marker && testType == type) {
+ testOccurred = true;
+ }
+ }
+ return new Future(() {
+ Future<String> compile(Uri script,
+ Uri libraryRoot,
+ Uri packageRoot,
+ api.CompilerInputProvider inputProvider,
+ api.DiagnosticHandler handler,
+ [List<String> options = const [],
+ api.CompilerOutputProvider outputProvider,
+ Map<String, dynamic> environment = const {}]) {
+ libraryRoot = Platform.script.resolve('../../../sdk/');
+ outputProvider = NullSink.outputProvider;
+ handler = (uri, begin, end, message, kind) {};
+ Compiler compiler = new TestCompiler(inputProvider,
+ outputProvider,
+ handler,
+ libraryRoot,
+ packageRoot,
+ options,
+ environment,
+ marker,
+ type,
+ onTest);
+ return compiler.run(script).then((_) {
+ String code = compiler.assembledCode;
+ if (code != null && outputProvider != null) {
+ String outputType = 'js';
+ if (options.contains('--output-type=dart')) {
+ outputType = 'dart';
+ }
+ outputProvider('', outputType)
+ ..add(code)
+ ..close();
+ code = ''; // Non-null signals success.
+ }
+ return code;
+ });
+ }
+
+ int foundExitCode;
+
+ checkResult() {
+ Expect.isTrue(testOccurred, 'testExitCode($marker, $type) did not occur');
+ if (foundExitCode == null) foundExitCode = 0;
+ print('testExitCode($marker, $type) '
+ 'exitCode=$foundExitCode expected=$expectedExitCode');
+ Expect.equals(expectedExitCode, foundExitCode,
+ 'testExitCode($marker, $type) '
+ 'exitCode=$foundExitCode expected=${expectedExitCode}');
+ checkedResults++;
+ }
+
+ void exit(exitCode) {
+ if (foundExitCode == null) {
+ foundExitCode = exitCode;
+ }
+ };
+
+ entry.exitFunc = exit;
+ entry.compileFunc = compile;
+
+ Future result = entry.internalMain(
+ ["tests/compiler/dart2js/exit_code_helper.dart"]);
+ return result.whenComplete(checkResult);
+ });
+}
+
+Future testExitCodes(String marker, Map<String,int> expectedExitCodes) {
+ return Future.forEach(expectedExitCodes.keys, (String type) {
+ return testExitCode(marker, type, expectedExitCodes[type]);
+ });
+}
+
+void main() {
+ const beforeRun = const {
+ '': 0,
+ 'NoSuchMethodError': 253,
+ 'assert': 253,
+ 'invariant': 253
+ };
+
+ const duringRun = const {
+ '': 0,
+ 'NoSuchMethodError': 253,
+ 'assert': 253,
+ 'invariant': 253,
+ 'warning': 0,
+ 'error': 1,
+ 'fatalError': 1,
+ };
+
+ const tests = const {
+ 'Compiler': beforeRun,
+ 'Compiler.run': beforeRun,
+ 'ScannerTask.scanElements': duringRun,
+ 'Compiler.withCurrentElement': duringRun,
+ 'Compiler.analyzeElement': duringRun,
+ 'Compiler.codegen': duringRun,
+ };
+
+ asyncStart();
+ Future.forEach(tests.keys, (marker) {
+ return testExitCodes(marker, tests[marker]);
+ }).then((_) {
+ Expect.equals(beforeRun.length * 2 + duringRun.length * 4,
+ checkedResults);
+ asyncEnd();
+ });
+}
diff --git a/tests/compiler/dart2js/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
index d6dd1f6..b7181c4 100644
--- a/tests/compiler/dart2js/field_type_simple_inferer_test.dart
+++ b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
@@ -484,11 +484,11 @@
name,
disableInlining,
(compiler, field) {
- TypeMask type = f(compiler);
+ TypeMask type = f(compiler.typesTask);
var inferrer = compiler.typesTask.typesInferrer;
TypeMask inferredType =
inferrer.getTypeOfElement(field).simplify(inferrer.compiler);
- Expect.equals(type, inferredType, name);
+ Expect.equals(type, inferredType, test);
});
});
}
@@ -499,16 +499,16 @@
}
void test() {
- subclassOfInterceptor(compiler) =>
- findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
+ subclassOfInterceptor(types) =>
+ findTypeMask(types.compiler, 'Interceptor', 'nonNullSubclass');
- runTest(TEST_1, {'f': (compiler) => compiler.typesTask.nullType});
- runTest(TEST_2, {'f1': (compiler) => compiler.typesTask.nullType,
- 'f2': (compiler) => compiler.typesTask.intType});
- runTest(TEST_3, {'f1': (compiler) => compiler.typesTask.intType,
- 'f2': (compiler) => compiler.typesTask.intType.nullable()});
+ runTest(TEST_1, {'f': (types) => types.nullType});
+ runTest(TEST_2, {'f1': (types) => types.nullType,
+ 'f2': (types) => types.uint31Type});
+ runTest(TEST_3, {'f1': (types) => types.uint31Type,
+ 'f2': (types) => types.uint31Type.nullable()});
runTest(TEST_4, {'f1': subclassOfInterceptor,
- 'f2': (compiler) => compiler.typesTask.stringType.nullable()});
+ 'f2': (types) => types.stringType.nullable()});
// TODO(ngeoffray): We should try to infer that the initialization
// code at the declaration site of the fields does not matter.
@@ -519,53 +519,53 @@
runTest(TEST_7, {'f1': subclassOfInterceptor,
'f2': subclassOfInterceptor});
- runTest(TEST_8, {'f': (compiler) => compiler.typesTask.stringType.nullable()});
- runTest(TEST_9, {'f': (compiler) => compiler.typesTask.stringType.nullable()});
- runTest(TEST_10, {'f': (compiler) => compiler.typesTask.intType});
- runTest(TEST_11, {'fs': (compiler) => compiler.typesTask.intType});
+ runTest(TEST_8, {'f': (types) => types.stringType.nullable()});
+ runTest(TEST_9, {'f': (types) => types.stringType.nullable()});
+ runTest(TEST_10, {'f': (types) => types.uint31Type});
+ runTest(TEST_11, {'fs': (types) => types.uint31Type});
// TODO(ngeoffray): We should try to infer that the initialization
// code at the declaration site of the fields does not matter.
runTest(TEST_12, {'fs': subclassOfInterceptor});
- runTest(TEST_13, {'fs': (compiler) => compiler.typesTask.intType});
- runTest(TEST_14, {'f': (compiler) => compiler.typesTask.intType});
- runTest(TEST_15, {'f': (compiler) {
+ runTest(TEST_13, {'fs': (types) => types.uint31Type});
+ runTest(TEST_14, {'f': (types) => types.uint31Type});
+ runTest(TEST_15, {'f': (types) {
ClassElement cls =
- compiler.typesTask.compiler.backend.jsIndexableClass;
+ types.compiler.backend.jsIndexableClass;
return new TypeMask.nonNullSubtype(cls);
}});
runTest(TEST_16, {'f': subclassOfInterceptor});
- runTest(TEST_17, {'f': (compiler) => compiler.typesTask.intType.nullable()});
- runTest(TEST_18, {'f1': (compiler) => compiler.typesTask.intType,
- 'f2': (compiler) => compiler.typesTask.stringType,
- 'f3': (compiler) => compiler.typesTask.dynamicType});
- runTest(TEST_19, {'f1': (compiler) => compiler.typesTask.intType,
- 'f2': (compiler) => compiler.typesTask.stringType,
- 'f3': (compiler) => compiler.typesTask.dynamicType});
- runTest(TEST_20, {'f': (compiler) => compiler.typesTask.intType.nullable()});
- runTest(TEST_21, {'f': (compiler) => compiler.typesTask.intType.nullable()});
+ runTest(TEST_17, {'f': (types) => types.uint31Type.nullable()});
+ runTest(TEST_18, {'f1': (types) => types.uint31Type,
+ 'f2': (types) => types.stringType,
+ 'f3': (types) => types.dynamicType});
+ runTest(TEST_19, {'f1': (types) => types.uint31Type,
+ 'f2': (types) => types.stringType,
+ 'f3': (types) => types.dynamicType});
+ runTest(TEST_20, {'f': (types) => types.uint31Type.nullable()});
+ runTest(TEST_21, {'f': (types) => types.uint31Type.nullable()});
- runTest(TEST_22, {'f1': (compiler) => compiler.typesTask.intType,
- 'f2': (compiler) => compiler.typesTask.intType,
- 'f3': (compiler) => compiler.typesTask.stringType.nullable()});
+ runTest(TEST_22, {'f1': (types) => types.uint31Type,
+ 'f2': (types) => types.uint31Type,
+ 'f3': (types) => types.stringType.nullable()});
- runTest(TEST_23, {'f1': (compiler) => compiler.typesTask.intType.nullable(),
- 'f2': (compiler) => compiler.typesTask.intType.nullable(),
- 'f3': (compiler) => compiler.typesTask.intType.nullable(),
- 'f4': (compiler) => compiler.typesTask.intType.nullable()});
+ runTest(TEST_23, {'f1': (types) => types.uint31Type.nullable(),
+ 'f2': (types) => types.uint31Type.nullable(),
+ 'f3': (types) => types.uint31Type.nullable(),
+ 'f4': (types) => types.uint31Type.nullable()});
- runTest(TEST_24, {'f1': (compiler) => compiler.typesTask.intType,
- 'f2': (compiler) => compiler.typesTask.intType,
- 'f3': (compiler) => compiler.typesTask.intType,
- 'f4': (compiler) => compiler.typesTask.intType,
- 'f5': (compiler) => compiler.typesTask.numType.nullable(),
- 'f6': (compiler) => compiler.typesTask.stringType.nullable()});
+ runTest(TEST_24, {'f1': (types) => types.positiveIntType,
+ 'f2': (types) => types.positiveIntType,
+ 'f3': (types) => types.uint31Type,
+ 'f4': (types) => types.uint31Type,
+ 'f5': (types) => types.numType.nullable(),
+ 'f6': (types) => types.stringType.nullable()});
- runTest(TEST_25, {'f1': (compiler) => compiler.typesTask.intType });
- runTest(TEST_26, {'f1': (compiler) => compiler.typesTask.intType });
- runTest(TEST_27, {'f1': (compiler) => compiler.typesTask.intType,
- 'f2': (compiler) => compiler.typesTask.intType.nullable()});
+ runTest(TEST_25, {'f1': (types) => types.uint31Type });
+ runTest(TEST_26, {'f1': (types) => types.positiveIntType });
+ runTest(TEST_27, {'f1': (types) => types.uint31Type,
+ 'f2': (types) => types.uint31Type.nullable()});
}
void main() {
diff --git a/tests/compiler/dart2js/issue13354_test.dart b/tests/compiler/dart2js/issue13354_test.dart
index d9342b6..7cc2f55 100644
--- a/tests/compiler/dart2js/issue13354_test.dart
+++ b/tests/compiler/dart2js/issue13354_test.dart
@@ -47,10 +47,10 @@
typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
}
- checkReturn('bar', typesTask.intType);
+ checkReturn('bar', typesTask.uint31Type);
checkReturn('baz', typesTask.functionType);
- checkReturnInClass('A', 'foo', typesTask.intType);
+ checkReturnInClass('A', 'foo', typesTask.uint31Type);
checkReturnInClass('B', 'foo', typesTask.functionType);
}));
}
diff --git a/tests/compiler/dart2js/least_upper_bound_language_test.dart b/tests/compiler/dart2js/least_upper_bound_language_test.dart
new file mode 100644
index 0000000..f75c32c
--- /dev/null
+++ b/tests/compiler/dart2js/least_upper_bound_language_test.dart
@@ -0,0 +1,22 @@
+// 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.
+
+// Test that dart2js produces the expected static type warnings for least upper
+// bound language tests. This ensures that the analyzer and dart2js agrees
+// on these tests.
+
+import 'warnings_checker.dart';
+
+/// Map from test files to a map of their expected status. If the status map is
+/// `null` no warnings must be missing or unexpected, otherwise the status map
+/// can contain a list of line numbers for keys 'missing' and 'unexpected' for
+/// the warnings of each category.
+const Map<String, dynamic> TESTS = const {
+ 'language/least_upper_bound_test.dart': null,
+ 'language/least_upper_bound_expansive_test.dart': null,
+};
+
+void main() {
+ checkWarnings(TESTS);
+}
diff --git a/tests/compiler/dart2js/least_upper_bound_test.dart b/tests/compiler/dart2js/least_upper_bound_test.dart
new file mode 100644
index 0000000..f263f3b
--- /dev/null
+++ b/tests/compiler/dart2js/least_upper_bound_test.dart
@@ -0,0 +1,853 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library subtype_test;
+
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+import 'type_test_helper.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/dart_types.dart';
+import "../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart"
+ show Element, ClassElement;
+import '../../../sdk/lib/_internal/compiler/implementation/util/util.dart'
+ show Link;
+
+void main() {
+ testInterface1();
+ testInterface2();
+ testGeneric();
+ testMixin();
+ testFunction();
+ testTypeVariable();
+}
+
+void testInterface1() {
+ asyncTest(() => TypeEnvironment.create(r"""
+ class A {} // A and B have equal depth.
+ class B {}
+ class I implements A, B {}
+ class J implements A, B {}
+ """).then((env) {
+
+ DartType Object_ = env['Object'];
+ DartType A = env['A'];
+ DartType B = env['B'];
+ DartType I = env['I'];
+ DartType J = env['J'];
+
+ checkLub(DartType a, DartType b, DartType expect) {
+ DartType lub = env.computeLeastUpperBound(a, b);
+ Expect.equals(expect, lub,
+ 'Unexpected lub($a,$b) = $lub, expected $expect.');
+ }
+
+ checkLub(Object_, Object_, Object_);
+ checkLub(Object_, A, Object_);
+ checkLub(Object_, B, Object_);
+ checkLub(Object_, I, Object_);
+ checkLub(Object_, J, Object_);
+
+ checkLub(A, Object_, Object_);
+ checkLub(A, A, A);
+ checkLub(A, B, Object_);
+ checkLub(A, I, A);
+ checkLub(A, J, A);
+
+ checkLub(B, Object_, Object_);
+ checkLub(B, A, Object_);
+ checkLub(B, B, B);
+ checkLub(B, I, B);
+ checkLub(B, J, B);
+
+ checkLub(I, Object_, Object_);
+ checkLub(I, A, A);
+ checkLub(I, B, B);
+ checkLub(I, I, I);
+ checkLub(I, J, Object_);
+
+ checkLub(J, Object_, Object_);
+ checkLub(J, A, A);
+ checkLub(J, B, B);
+ checkLub(J, I, Object_);
+ checkLub(J, J, J);
+ }));
+}
+
+void testInterface2() {
+ asyncTest(() => TypeEnvironment.create(r"""
+ class A {}
+ class B {}
+ class C extends B {} // This makes C have higher depth than A.
+ class I implements A, C {}
+ class J implements A, C {}
+ """).then((env) {
+
+ DartType Object_ = env['Object'];
+ DartType A = env['A'];
+ DartType B = env['B'];
+ DartType C = env['C'];
+ DartType I = env['I'];
+ DartType J = env['J'];
+
+ checkLub(DartType a, DartType b, DartType expectedLub) {
+ DartType lub = env.computeLeastUpperBound(a, b);
+ Expect.equals(expectedLub, lub,
+ 'Unexpected lub($a,$b) = $lub, expected $expectedLub');
+ }
+
+ checkLub(Object_, Object_, Object_);
+ checkLub(Object_, A, Object_);
+ checkLub(Object_, B, Object_);
+ checkLub(Object_, C, Object_);
+ checkLub(Object_, I, Object_);
+ checkLub(Object_, J, Object_);
+
+ checkLub(A, Object_, Object_);
+ checkLub(A, A, A);
+ checkLub(A, B, Object_);
+ checkLub(A, C, Object_);
+ checkLub(A, I, A);
+ checkLub(A, J, A);
+
+ checkLub(B, Object_, Object_);
+ checkLub(B, A, Object_);
+ checkLub(B, B, B);
+ checkLub(B, C, B);
+ checkLub(B, I, B);
+ checkLub(B, J, B);
+
+ checkLub(C, Object_, Object_);
+ checkLub(C, A, Object_);
+ checkLub(C, B, B);
+ checkLub(C, C, C);
+ checkLub(C, I, C);
+ checkLub(C, J, C);
+
+ checkLub(I, Object_, Object_);
+ checkLub(I, A, A);
+ checkLub(I, B, B);
+ checkLub(I, C, C);
+ checkLub(I, I, I);
+ checkLub(I, J, C);
+
+ checkLub(J, Object_, Object_);
+ checkLub(J, A, A);
+ checkLub(J, B, B);
+ checkLub(J, C, C);
+ checkLub(J, I, C);
+ checkLub(J, J, J);
+ }));
+}
+
+void testGeneric() {
+ asyncTest(() => TypeEnvironment.create(r"""
+ class A {}
+ class B {}
+ class C extends B {}
+ class I<T> {}
+ """).then((env) {
+
+ DartType Object_ = env['Object'];
+ DartType A = env['A'];
+ DartType B = env['B'];
+ DartType C = env['C'];
+ ClassElement I = env.getElement('I');
+ DartType I_A = instantiate(I, [A]);
+ DartType I_B = instantiate(I, [B]);
+ DartType I_C = instantiate(I, [C]);
+
+ checkLub(DartType a, DartType b, DartType expectedLub) {
+ DartType lub = env.computeLeastUpperBound(a, b);
+ Expect.equals(expectedLub, lub,
+ 'Unexpected lub($a,$b) = $lub, expected $expectedLub');
+ }
+
+ checkLub(Object_, Object_, Object_);
+ checkLub(Object_, A, Object_);
+ checkLub(Object_, B, Object_);
+ checkLub(Object_, C, Object_);
+ checkLub(Object_, I_A, Object_);
+ checkLub(Object_, I_B, Object_);
+ checkLub(Object_, I_C, Object_);
+
+ checkLub(A, Object_, Object_);
+ checkLub(A, A, A);
+ checkLub(A, B, Object_);
+ checkLub(A, C, Object_);
+ checkLub(A, I_A, Object_);
+ checkLub(A, I_B, Object_);
+ checkLub(A, I_C, Object_);
+
+ checkLub(B, Object_, Object_);
+ checkLub(B, A, Object_);
+ checkLub(B, B, B);
+ checkLub(B, C, B);
+ checkLub(B, I_A, Object_);
+ checkLub(B, I_B, Object_);
+ checkLub(B, I_C, Object_);
+
+ checkLub(C, Object_, Object_);
+ checkLub(C, A, Object_);
+ checkLub(C, B, B);
+ checkLub(C, C, C);
+ checkLub(C, I_A, Object_);
+ checkLub(C, I_B, Object_);
+ checkLub(C, I_C, Object_);
+
+ checkLub(I_A, Object_, Object_);
+ checkLub(I_A, A, Object_);
+ checkLub(I_A, B, Object_);
+ checkLub(I_A, C, Object_);
+ checkLub(I_A, I_A, I_A);
+ checkLub(I_A, I_B, Object_);
+ checkLub(I_A, I_C, Object_);
+
+ checkLub(I_B, Object_, Object_);
+ checkLub(I_B, A, Object_);
+ checkLub(I_B, B, Object_);
+ checkLub(I_B, C, Object_);
+ checkLub(I_B, I_A, Object_);
+ checkLub(I_B, I_B, I_B);
+ checkLub(I_B, I_C, Object_);
+
+ checkLub(I_C, Object_, Object_);
+ checkLub(I_C, A, Object_);
+ checkLub(I_C, B, Object_);
+ checkLub(I_C, C, Object_);
+ checkLub(I_C, I_A, Object_);
+ checkLub(I_C, I_B, Object_);
+ checkLub(I_C, I_C, I_C);
+ }));
+}
+
+void testMixin() {
+ asyncTest(() => TypeEnvironment.create(r"""
+ class A {}
+ class B {}
+ class C extends B {}
+ class D extends C {} // This makes D have higher depth than Object+A.
+ class I extends Object with A, B implements A, D {}
+ class I2 extends Object with A, B implements A, D {}
+ class J extends Object with B, A implements A, D {}
+ """).then((env) {
+
+ DartType Object_ = env['Object'];
+ DartType A = env['A'];
+ DartType B = env['B'];
+ DartType C = env['C'];
+ DartType D = env['D'];
+ DartType I = env['I'];
+ DartType I2 = env['I2'];
+ DartType J = env['J'];
+
+ checkLub(DartType a, DartType b, DartType expectedLub) {
+ DartType lub = env.computeLeastUpperBound(a, b);
+ Expect.equals(expectedLub, lub,
+ 'Unexpected lub($a,$b) = $lub, expected $expectedLub');
+ }
+
+ checkLub(Object_, Object_, Object_);
+ checkLub(Object_, A, Object_);
+ checkLub(Object_, B, Object_);
+ checkLub(Object_, C, Object_);
+ checkLub(Object_, D, Object_);
+ checkLub(Object_, I, Object_);
+ checkLub(Object_, I2, Object_);
+ checkLub(Object_, J, Object_);
+
+ checkLub(A, Object_, Object_);
+ checkLub(A, A, A);
+ checkLub(A, B, Object_);
+ checkLub(A, C, Object_);
+ checkLub(A, D, Object_);
+ checkLub(A, I, A);
+ checkLub(A, I2, A);
+ checkLub(A, J, A);
+
+ checkLub(B, Object_, Object_);
+ checkLub(B, A, Object_);
+ checkLub(B, B, B);
+ checkLub(B, C, B);
+ checkLub(B, D, B);
+ checkLub(B, I, B);
+ checkLub(B, I2, B);
+ checkLub(B, J, B);
+
+ checkLub(C, Object_, Object_);
+ checkLub(C, A, Object_);
+ checkLub(C, B, B);
+ checkLub(C, C, C);
+ checkLub(C, D, C);
+ checkLub(C, I, C);
+ checkLub(C, I2, C);
+ checkLub(C, J, C);
+
+ checkLub(D, Object_, Object_);
+ checkLub(D, A, Object_);
+ checkLub(D, B, B);
+ checkLub(D, C, C);
+ checkLub(D, D, D);
+ checkLub(D, I, D);
+ checkLub(D, I2, D);
+ checkLub(D, J, D);
+
+ checkLub(I, Object_, Object_);
+ checkLub(I, A, A);
+ checkLub(I, B, B);
+ checkLub(I, C, C);
+ checkLub(I, D, D);
+ checkLub(I, I, I);
+ checkLub(I, I2, D);
+ checkLub(I, J, D);
+
+ checkLub(I2, Object_, Object_);
+ checkLub(I2, A, A);
+ checkLub(I2, B, B);
+ checkLub(I2, C, C);
+ checkLub(I2, D, D);
+ checkLub(I2, I, D);
+ checkLub(I2, I2, I2);
+ checkLub(I2, J, D);
+
+ checkLub(J, Object_, Object_);
+ checkLub(J, A, A);
+ checkLub(J, B, B);
+ checkLub(J, C, C);
+ checkLub(J, D, D);
+ checkLub(J, I, D);
+ checkLub(J, I2, D);
+ checkLub(J, J, J);
+ }));
+}
+
+void testFunction() {
+ asyncTest(() => TypeEnvironment.create(r"""
+ class A {}
+ class B {}
+ class C extends B {}
+
+ typedef dynamic__();
+ typedef void void__();
+ typedef A A__();
+ typedef B B__();
+ typedef C C__();
+
+ typedef void void__A_B(A a, B b);
+ typedef void void__A_C(A a, C b);
+ typedef void void__B_A(B a, A b);
+ typedef void void__B_C(B a, C b);
+
+ typedef void void___B([B a]);
+ typedef void void___B_C([B a, C b]);
+ typedef void void___C_C([C a, C b]);
+
+ typedef void void____B({B a});
+ typedef void void____B_C({B a, C b});
+ typedef void void____C_C({C a, C b});
+ """).then((env) {
+
+ DartType Object_ = env['Object'];
+ DartType Function_ = env['Function'];
+ DartType dynamic__ = env['dynamic__'];
+ DartType void__ = env['void__'];
+ DartType A__ = env['A__'];
+ DartType B__ = env['B__'];
+ DartType C__ = env['C__'];
+ DartType void__A_B = env['void__A_B'];
+ DartType void__A_C = env['void__A_C'];
+ DartType void__B_A = env['void__B_A'];
+ DartType void__B_C = env['void__B_C'];
+ DartType void___B = env['void___B'];
+ DartType void___B_C = env['void___B_C'];
+ DartType void___C_C = env['void___C_C'];
+ DartType void____B = env['void____B'];
+ DartType void____B_C = env['void____B_C'];
+ DartType void____C_C = env['void____C_C'];
+
+ // Types used only for checking results.
+ DartType void_ = env['void'];
+ DartType B = env['B'];
+ DartType C = env['C'];
+ FunctionType Object__ = env.functionType(Object_, []);
+ FunctionType void__Object_Object =
+ env.functionType(void_, [Object_, Object_]);
+ FunctionType void__Object_B =
+ env.functionType(void_, [Object_, B]);
+ FunctionType void__Object_C =
+ env.functionType(void_, [Object_, C]);
+ FunctionType void__B_Object =
+ env.functionType(void_, [B, Object_]);
+
+ checkLub(DartType a, DartType b, DartType expectedLub) {
+ DartType lub = env.computeLeastUpperBound(a, b);
+ if (a != b) {
+ expectedLub = expectedLub.unalias(env.compiler);
+ lub = lub.unalias(env.compiler);
+ }
+ Expect.equals(expectedLub, lub,
+ 'Unexpected lub(${a.unalias(env.compiler)},'
+ '${b.unalias(env.compiler)}) = '
+ '${lub}, expected ${expectedLub}');
+ }
+
+ checkLub(Object_, Object_, Object_);
+ checkLub(Object_, Function_, Object_);
+ checkLub(Object_, dynamic__, Object_);
+ checkLub(Object_, void__, Object_);
+ checkLub(Object_, A__, Object_);
+ checkLub(Object_, B__, Object_);
+ checkLub(Object_, C__, Object_);
+ checkLub(Object_, void__A_B, Object_);
+ checkLub(Object_, void__A_C, Object_);
+ checkLub(Object_, void__B_A, Object_);
+ checkLub(Object_, void__B_C, Object_);
+ checkLub(Object_, void___B, Object_);
+ checkLub(Object_, void___B_C, Object_);
+ checkLub(Object_, void___C_C, Object_);
+ checkLub(Object_, void____B, Object_);
+ checkLub(Object_, void____B_C, Object_);
+ checkLub(Object_, void____C_C, Object_);
+
+ checkLub(Function_, Object_, Object_);
+ checkLub(Function_, Function_, Function_);
+ checkLub(Function_, dynamic__, Function_);
+ checkLub(Function_, void__, Function_);
+ checkLub(Function_, A__, Function_);
+ checkLub(Function_, B__, Function_);
+ checkLub(Function_, C__, Function_);
+ checkLub(Function_, void__A_B, Function_);
+ checkLub(Function_, void__A_C, Function_);
+ checkLub(Function_, void__B_A, Function_);
+ checkLub(Function_, void__B_C, Function_);
+ checkLub(Function_, void___B, Function_);
+ checkLub(Function_, void___B_C, Function_);
+ checkLub(Function_, void___C_C, Function_);
+ checkLub(Function_, void____B, Function_);
+ checkLub(Function_, void____B_C, Function_);
+ checkLub(Function_, void____C_C, Function_);
+
+ checkLub(dynamic__, Object_, Object_);
+ checkLub(dynamic__, Function_, Function_);
+ checkLub(dynamic__, dynamic__, dynamic__);
+ checkLub(dynamic__, void__, dynamic__);
+ checkLub(dynamic__, A__, dynamic__);
+ checkLub(dynamic__, B__, dynamic__);
+ checkLub(dynamic__, C__, dynamic__);
+ checkLub(dynamic__, void__A_B, Function_);
+ checkLub(dynamic__, void__A_C, Function_);
+ checkLub(dynamic__, void__B_A, Function_);
+ checkLub(dynamic__, void__B_C, Function_);
+ checkLub(dynamic__, void___B, dynamic__);
+ checkLub(dynamic__, void___B_C, dynamic__);
+ checkLub(dynamic__, void___C_C, dynamic__);
+ checkLub(dynamic__, void____B, dynamic__);
+ checkLub(dynamic__, void____B_C, dynamic__);
+ checkLub(dynamic__, void____C_C, dynamic__);
+
+ checkLub(void__, Object_, Object_);
+ checkLub(void__, Function_, Function_);
+ checkLub(void__, dynamic__, dynamic__);
+ checkLub(void__, void__, void__);
+ checkLub(void__, A__, void__);
+ checkLub(void__, B__, void__);
+ checkLub(void__, C__, void__);
+ checkLub(void__, void__A_B, Function_);
+ checkLub(void__, void__A_C, Function_);
+ checkLub(void__, void__B_A, Function_);
+ checkLub(void__, void__B_C, Function_);
+ checkLub(void__, void___B, void__);
+ checkLub(void__, void___B_C, void__);
+ checkLub(void__, void___C_C, void__);
+ checkLub(void__, void____B, void__);
+ checkLub(void__, void____B_C, void__);
+ checkLub(void__, void____C_C, void__);
+
+ checkLub(A__, Object_, Object_);
+ checkLub(A__, Function_, Function_);
+ checkLub(A__, dynamic__, dynamic__);
+ checkLub(A__, void__, void__);
+ checkLub(A__, A__, A__);
+ checkLub(A__, B__, Object__);
+ checkLub(A__, C__, Object__);
+ checkLub(A__, void__A_B, Function_);
+ checkLub(A__, void__A_C, Function_);
+ checkLub(A__, void__B_A, Function_);
+ checkLub(A__, void__B_C, Function_);
+ checkLub(A__, void___B, void__);
+ checkLub(A__, void___B_C, void__);
+ checkLub(A__, void___C_C, void__);
+ checkLub(A__, void____B, void__);
+ checkLub(A__, void____B_C, void__);
+ checkLub(A__, void____C_C, void__);
+
+ checkLub(B__, Object_, Object_);
+ checkLub(B__, Function_, Function_);
+ checkLub(B__, dynamic__, dynamic__);
+ checkLub(B__, void__, void__);
+ checkLub(B__, A__, Object__);
+ checkLub(B__, B__, B__);
+ checkLub(B__, C__, B__);
+ checkLub(B__, void__A_B, Function_);
+ checkLub(B__, void__A_C, Function_);
+ checkLub(B__, void__B_A, Function_);
+ checkLub(B__, void__B_C, Function_);
+ checkLub(B__, void___B, void__);
+ checkLub(B__, void___B_C, void__);
+ checkLub(B__, void___C_C, void__);
+ checkLub(B__, void____B, void__);
+ checkLub(B__, void____B_C, void__);
+ checkLub(B__, void____C_C, void__);
+
+ checkLub(C__, Object_, Object_);
+ checkLub(C__, Function_, Function_);
+ checkLub(C__, dynamic__, dynamic__);
+ checkLub(C__, void__, void__);
+ checkLub(C__, A__, Object__);
+ checkLub(C__, B__, B__);
+ checkLub(C__, C__, C__);
+ checkLub(C__, void__A_B, Function_);
+ checkLub(C__, void__A_C, Function_);
+ checkLub(C__, void__B_A, Function_);
+ checkLub(C__, void__B_C, Function_);
+ checkLub(C__, void___B, void__);
+ checkLub(C__, void___B_C, void__);
+ checkLub(C__, void___C_C, void__);
+ checkLub(C__, void____B, void__);
+ checkLub(C__, void____B_C, void__);
+ checkLub(C__, void____C_C, void__);
+
+ checkLub(void__A_B, Object_, Object_);
+ checkLub(void__A_B, Function_, Function_);
+ checkLub(void__A_B, dynamic__, Function_);
+ checkLub(void__A_B, void__, Function_);
+ checkLub(void__A_B, A__, Function_);
+ checkLub(void__A_B, B__, Function_);
+ checkLub(void__A_B, C__, Function_);
+ checkLub(void__A_B, void__A_B, void__A_B);
+ checkLub(void__A_B, void__A_C, void__A_B);
+ checkLub(void__A_B, void__B_A, void__Object_Object);
+ checkLub(void__A_B, void__B_C, void__Object_B);
+ checkLub(void__A_B, void___B, Function_);
+ checkLub(void__A_B, void___B_C, Function_);
+ checkLub(void__A_B, void___C_C, Function_);
+ checkLub(void__A_B, void____B, Function_);
+ checkLub(void__A_B, void____B_C, Function_);
+ checkLub(void__A_B, void____C_C, Function_);
+
+ checkLub(void__A_C, Object_, Object_);
+ checkLub(void__A_C, Function_, Function_);
+ checkLub(void__A_C, dynamic__, Function_);
+ checkLub(void__A_C, void__, Function_);
+ checkLub(void__A_C, A__, Function_);
+ checkLub(void__A_C, B__, Function_);
+ checkLub(void__A_C, C__, Function_);
+ checkLub(void__A_C, void__A_B, void__A_B);
+ checkLub(void__A_C, void__A_C, void__A_C);
+ checkLub(void__A_C, void__B_A, void__Object_Object);
+ checkLub(void__A_C, void__B_C, void__Object_C);
+ checkLub(void__A_C, void___B, Function_);
+ checkLub(void__A_C, void___B_C, Function_);
+ checkLub(void__A_C, void___C_C, Function_);
+ checkLub(void__A_C, void____B, Function_);
+ checkLub(void__A_C, void____B_C, Function_);
+ checkLub(void__A_C, void____C_C, Function_);
+
+ checkLub(void__B_A, Object_, Object_);
+ checkLub(void__B_A, Function_, Function_);
+ checkLub(void__B_A, dynamic__, Function_);
+ checkLub(void__B_A, void__, Function_);
+ checkLub(void__B_A, A__, Function_);
+ checkLub(void__B_A, B__, Function_);
+ checkLub(void__B_A, C__, Function_);
+ checkLub(void__B_A, void__A_B, void__Object_Object);
+ checkLub(void__B_A, void__A_C, void__Object_Object);
+ checkLub(void__B_A, void__B_A, void__B_A);
+ checkLub(void__B_A, void__B_C, void__B_Object);
+ checkLub(void__B_A, void___B, Function_);
+ checkLub(void__B_A, void___B_C, Function_);
+ checkLub(void__B_A, void___C_C, Function_);
+ checkLub(void__B_A, void____B, Function_);
+ checkLub(void__B_A, void____B_C, Function_);
+ checkLub(void__B_A, void____C_C, Function_);
+
+ checkLub(void__B_C, Object_, Object_);
+ checkLub(void__B_C, Function_, Function_);
+ checkLub(void__B_C, dynamic__, Function_);
+ checkLub(void__B_C, void__, Function_);
+ checkLub(void__B_C, A__, Function_);
+ checkLub(void__B_C, B__, Function_);
+ checkLub(void__B_C, C__, Function_);
+ checkLub(void__B_C, void__A_B, void__Object_B);
+ checkLub(void__B_C, void__A_C, void__Object_C);
+ checkLub(void__B_C, void__B_A, void__B_Object);
+ checkLub(void__B_C, void__B_C, void__B_C);
+ checkLub(void__B_C, void___B, Function_);
+ checkLub(void__B_C, void___B_C, Function_);
+ checkLub(void__B_C, void___C_C, Function_);
+ checkLub(void__B_C, void____B, Function_);
+ checkLub(void__B_C, void____B_C, Function_);
+ checkLub(void__B_C, void____C_C, Function_);
+
+ checkLub(void___B, Object_, Object_);
+ checkLub(void___B, Function_, Function_);
+ checkLub(void___B, dynamic__, dynamic__);
+ checkLub(void___B, void__, void__);
+ checkLub(void___B, A__, void__);
+ checkLub(void___B, B__, void__);
+ checkLub(void___B, C__, void__);
+ checkLub(void___B, void__A_B, Function_);
+ checkLub(void___B, void__A_C, Function_);
+ checkLub(void___B, void__B_A, Function_);
+ checkLub(void___B, void__B_C, Function_);
+ checkLub(void___B, void___B, void___B);
+ checkLub(void___B, void___B_C, void___B);
+ checkLub(void___B, void___C_C, void___B);
+ checkLub(void___B, void____B, void__);
+ checkLub(void___B, void____B_C, void__);
+ checkLub(void___B, void____C_C, void__);
+
+ checkLub(void___B_C, Object_, Object_);
+ checkLub(void___B_C, Function_, Function_);
+ checkLub(void___B_C, dynamic__, dynamic__);
+ checkLub(void___B_C, void__, void__);
+ checkLub(void___B_C, A__, void__);
+ checkLub(void___B_C, B__, void__);
+ checkLub(void___B_C, C__, void__);
+ checkLub(void___B_C, void__A_B, Function_);
+ checkLub(void___B_C, void__A_C, Function_);
+ checkLub(void___B_C, void__B_A, Function_);
+ checkLub(void___B_C, void__B_C, Function_);
+ checkLub(void___B_C, void___B, void___B);
+ checkLub(void___B_C, void___B_C, void___B_C);
+ checkLub(void___B_C, void___C_C, void___B_C);
+ checkLub(void___B_C, void____B, void__);
+ checkLub(void___B_C, void____B_C, void__);
+ checkLub(void___B_C, void____C_C, void__);
+
+ checkLub(void___C_C, Object_, Object_);
+ checkLub(void___C_C, Function_, Function_);
+ checkLub(void___C_C, dynamic__, dynamic__);
+ checkLub(void___C_C, void__, void__);
+ checkLub(void___C_C, A__, void__);
+ checkLub(void___C_C, B__, void__);
+ checkLub(void___C_C, C__, void__);
+ checkLub(void___C_C, void__A_B, Function_);
+ checkLub(void___C_C, void__A_C, Function_);
+ checkLub(void___C_C, void__B_A, Function_);
+ checkLub(void___C_C, void__B_C, Function_);
+ checkLub(void___C_C, void___B, void___B);
+ checkLub(void___C_C, void___B_C, void___B_C);
+ checkLub(void___C_C, void___C_C, void___C_C);
+ checkLub(void___C_C, void____B, void__);
+ checkLub(void___C_C, void____B_C, void__);
+ checkLub(void___C_C, void____C_C, void__);
+
+ checkLub(void____B, Object_, Object_);
+ checkLub(void____B, Function_, Function_);
+ checkLub(void____B, dynamic__, dynamic__);
+ checkLub(void____B, void__, void__);
+ checkLub(void____B, A__, void__);
+ checkLub(void____B, B__, void__);
+ checkLub(void____B, C__, void__);
+ checkLub(void____B, void__A_B, Function_);
+ checkLub(void____B, void__A_C, Function_);
+ checkLub(void____B, void__B_A, Function_);
+ checkLub(void____B, void__B_C, Function_);
+ checkLub(void____B, void___B, void__);
+ checkLub(void____B, void___B_C, void__);
+ checkLub(void____B, void___C_C, void__);
+ checkLub(void____B, void____B, void____B);
+ checkLub(void____B, void____B_C, void____B);
+ checkLub(void____B, void____C_C, void____B);
+
+ checkLub(void____B_C, Object_, Object_);
+ checkLub(void____B_C, Function_, Function_);
+ checkLub(void____B_C, dynamic__, dynamic__);
+ checkLub(void____B_C, void__, void__);
+ checkLub(void____B_C, A__, void__);
+ checkLub(void____B_C, B__, void__);
+ checkLub(void____B_C, C__, void__);
+ checkLub(void____B_C, void__A_B, Function_);
+ checkLub(void____B_C, void__A_C, Function_);
+ checkLub(void____B_C, void__B_A, Function_);
+ checkLub(void____B_C, void__B_C, Function_);
+ checkLub(void____B_C, void___B, void__);
+ checkLub(void____B_C, void___B_C, void__);
+ checkLub(void____B_C, void___C_C, void__);
+ checkLub(void____B_C, void____B, void____B);
+ checkLub(void____B_C, void____B_C, void____B_C);
+ checkLub(void____B_C, void____C_C, void____B_C);
+
+ checkLub(void____C_C, Object_, Object_);
+ checkLub(void____C_C, Function_, Function_);
+ checkLub(void____C_C, dynamic__, dynamic__);
+ checkLub(void____C_C, void__, void__);
+ checkLub(void____C_C, A__, void__);
+ checkLub(void____C_C, B__, void__);
+ checkLub(void____C_C, C__, void__);
+ checkLub(void____C_C, void__A_B, Function_);
+ checkLub(void____C_C, void__A_C, Function_);
+ checkLub(void____C_C, void__B_A, Function_);
+ checkLub(void____C_C, void__B_C, Function_);
+ checkLub(void____C_C, void___B, void__);
+ checkLub(void____C_C, void___B_C, void__);
+ checkLub(void____C_C, void___C_C, void__);
+ checkLub(void____C_C, void____B, void____B);
+ checkLub(void____C_C, void____B_C, void____B_C);
+ checkLub(void____C_C, void____C_C, void____C_C);
+ }));
+}
+
+void testTypeVariable() {
+ asyncTest(() => TypeEnvironment.create(r"""
+ class A {}
+ class B {}
+ class C extends B {}
+ class I<S extends A,
+ T extends B,
+ U extends C,
+ V extends T,
+ W extends V,
+ X extends T> {}
+ """).then((env) {
+
+ // A B
+ // | / \
+ // S T C
+ // / \ \
+ // V X U
+ // /
+ // W
+
+ DartType Object_ = env['Object'];
+ DartType A = env['A'];
+ DartType B = env['B'];
+ DartType C = env['C'];
+ ClassElement I = env.getElement('I');
+ DartType S = I.typeVariables.head;
+ DartType T = I.typeVariables.tail.head;
+ DartType U = I.typeVariables.tail.tail.head;
+ DartType V = I.typeVariables.tail.tail.tail.head;
+ DartType W = I.typeVariables.tail.tail.tail.tail.head;
+ DartType X = I.typeVariables.tail.tail.tail.tail.tail.head;
+
+ checkLub(DartType a, DartType b, DartType expectedLub) {
+ DartType lub = env.computeLeastUpperBound(a, b);
+ Expect.equals(expectedLub, lub,
+ 'Unexpected lub($a,$b) = $lub, expected $expectedLub');
+ }
+
+ checkLub(Object_, Object_, Object_);
+ checkLub(Object_, A, Object_);
+ checkLub(Object_, B, Object_);
+ checkLub(Object_, C, Object_);
+ checkLub(Object_, S, Object_);
+ checkLub(Object_, T, Object_);
+ checkLub(Object_, U, Object_);
+ checkLub(Object_, V, Object_);
+ checkLub(Object_, W, Object_);
+ checkLub(Object_, X, Object_);
+
+ checkLub(A, Object_, Object_);
+ checkLub(A, A, A);
+ checkLub(A, B, Object_);
+ checkLub(A, C, Object_);
+ checkLub(A, S, A);
+ checkLub(A, T, Object_);
+ checkLub(A, U, Object_);
+ checkLub(A, V, Object_);
+ checkLub(A, W, Object_);
+ checkLub(A, X, Object_);
+
+ checkLub(B, Object_, Object_);
+ checkLub(B, A, Object_);
+ checkLub(B, B, B);
+ checkLub(B, C, B);
+ checkLub(B, S, Object_);
+ checkLub(B, T, B);
+ checkLub(B, U, B);
+ checkLub(B, V, B);
+ checkLub(B, W, B);
+ checkLub(B, X, B);
+
+ checkLub(C, Object_, Object_);
+ checkLub(C, A, Object_);
+ checkLub(C, B, B);
+ checkLub(C, C, C);
+ checkLub(C, S, Object_);
+ checkLub(C, T, B);
+ checkLub(C, U, C);
+ checkLub(C, V, B);
+ checkLub(C, W, B);
+ checkLub(C, X, B);
+
+ checkLub(S, Object_, Object_);
+ checkLub(S, A, A);
+ checkLub(S, B, Object_);
+ checkLub(S, C, Object_);
+ checkLub(S, S, S);
+ checkLub(S, T, Object_);
+ checkLub(S, U, Object_);
+ checkLub(S, V, Object_);
+ checkLub(S, W, Object_);
+ checkLub(S, X, Object_);
+
+ checkLub(T, Object_, Object_);
+ checkLub(T, A, Object_);
+ checkLub(T, B, B);
+ checkLub(T, C, B);
+ checkLub(T, S, Object_);
+ checkLub(T, T, T);
+ checkLub(T, U, B);
+ checkLub(T, V, T);
+ checkLub(T, W, T);
+ checkLub(T, X, T);
+
+ checkLub(U, Object_, Object_);
+ checkLub(U, A, Object_);
+ checkLub(U, B, B);
+ checkLub(U, C, C);
+ checkLub(U, S, Object_);
+ checkLub(U, T, B);
+ checkLub(U, U, U);
+ checkLub(U, V, B);
+ checkLub(U, W, B);
+ checkLub(U, X, B);
+
+ checkLub(V, Object_, Object_);
+ checkLub(V, A, Object_);
+ checkLub(V, B, B);
+ checkLub(V, C, B);
+ checkLub(V, S, Object_);
+ checkLub(V, T, T);
+ checkLub(V, U, B);
+ checkLub(V, V, V);
+ checkLub(V, W, V);
+ checkLub(V, X, T);
+
+ checkLub(W, Object_, Object_);
+ checkLub(W, A, Object_);
+ checkLub(W, B, B);
+ checkLub(W, C, B);
+ checkLub(W, S, Object_);
+ checkLub(W, T, T);
+ checkLub(W, U, B);
+ checkLub(W, V, V);
+ checkLub(W, W, W);
+ checkLub(W, X, T);
+
+ checkLub(X, Object_, Object_);
+ checkLub(X, A, Object_);
+ checkLub(X, B, B);
+ checkLub(X, C, B);
+ checkLub(X, S, Object_);
+ checkLub(X, T, T);
+ checkLub(X, U, B);
+ checkLub(X, V, T);
+ checkLub(X, W, T);
+ checkLub(X, X, X);
+ }));
+}
+
+
diff --git a/tests/compiler/dart2js/list_tracer2_test.dart b/tests/compiler/dart2js/list_tracer2_test.dart
index cb7734d..56c5fff 100644
--- a/tests/compiler/dart2js/list_tracer2_test.dart
+++ b/tests/compiler/dart2js/list_tracer2_test.dart
@@ -35,6 +35,6 @@
Expect.equals(type, mask.elementType.simplify(compiler), name);
}
- checkType('myList', compiler.typesTask.intType);
+ checkType('myList', compiler.typesTask.uint31Type);
}));
}
diff --git a/tests/compiler/dart2js/list_tracer_test.dart b/tests/compiler/dart2js/list_tracer_test.dart
index aaa56b5..e599732 100644
--- a/tests/compiler/dart2js/list_tracer_test.dart
+++ b/tests/compiler/dart2js/list_tracer_test.dart
@@ -209,15 +209,15 @@
checkType('listPassedToSelector', typesTask.numType);
checkType('listReturnedFromSelector', typesTask.numType);
checkType('listUsedWithAddAndInsert', typesTask.numType);
- checkType('listUsedWithConstraint', typesTask.intType);
+ checkType('listUsedWithConstraint', typesTask.positiveIntType);
checkType('listEscapingFromSetter', typesTask.numType);
checkType('listUsedInLocal', typesTask.numType);
checkType('listEscapingInSetterValue', typesTask.numType);
checkType('listEscapingInIndex', typesTask.numType);
- checkType('listEscapingInIndexSet', typesTask.intType);
+ checkType('listEscapingInIndexSet', typesTask.uint31Type);
checkType('listEscapingTwiceInIndexSet', typesTask.numType);
checkType('listSetInNonFinalField', typesTask.numType);
- checkType('listWithChangedLength', typesTask.intType.nullable());
+ checkType('listWithChangedLength', typesTask.uint31Type.nullable());
checkType('listPassedToClosure', typesTask.dynamicType);
checkType('listReturnedFromClosure', typesTask.dynamicType);
@@ -227,8 +227,7 @@
if (!allocation.contains('filled')) {
checkType('listUnset', new TypeMask.nonNullEmpty());
- // TODO(ngeoffray): Re-enable this test.
- // checkType('listOnlySetWithConstraint', new TypeMask.nonNullEmpty());
+ checkType('listOnlySetWithConstraint', new TypeMask.nonNullEmpty());
}
}));
}
diff --git a/tests/compiler/dart2js/mirror_final_field_inferrer2_test.dart b/tests/compiler/dart2js/mirror_final_field_inferrer2_test.dart
index fcedf81..95c7e6b 100644
--- a/tests/compiler/dart2js/mirror_final_field_inferrer2_test.dart
+++ b/tests/compiler/dart2js/mirror_final_field_inferrer2_test.dart
@@ -28,7 +28,7 @@
var element = findElement(compiler, 'field');
var typesTask = compiler.typesTask;
var typesInferrer = typesTask.typesInferrer;
- Expect.equals(typesTask.intType,
+ Expect.equals(typesTask.uint31Type,
typesInferrer.getTypeOfElement(element).simplify(compiler),
'field');
}));
diff --git a/tests/compiler/dart2js/mirror_final_field_inferrer_test.dart b/tests/compiler/dart2js/mirror_final_field_inferrer_test.dart
index fb0c0a1..0dccbe2 100644
--- a/tests/compiler/dart2js/mirror_final_field_inferrer_test.dart
+++ b/tests/compiler/dart2js/mirror_final_field_inferrer_test.dart
@@ -28,7 +28,7 @@
var element = findElement(compiler, 'field');
var typesTask = compiler.typesTask;
var typesInferrer = typesTask.typesInferrer;
- Expect.equals(typesTask.intType,
+ Expect.equals(typesTask.uint31Type,
typesInferrer.getTypeOfElement(element).simplify(compiler),
'field');
}));
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 15ce07c..8269768 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -122,6 +122,9 @@
toString() {}
operator+(other) => this;
}
+ class JSPositiveInt extends JSInt {}
+ class JSUInt32 extends JSPositiveInt {}
+ class JSUInt31 extends JSUInt32 {}
class JSNumber extends Interceptor implements num {
// All these methods return a number to please type inferencing.
operator-() => (this is JSInt) ? 42 : 42.2;
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index 9081c3d..72277c8 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -646,10 +646,20 @@
testClassHierarchy() {
final MAIN = "main";
MockCompiler compiler = new MockCompiler();
+ compiler.parseScript("""class A extends A {}
+ main() { return new A(); }""");
+ FunctionElement mainElement = compiler.mainApp.find(MAIN);
+ compiler.resolver.resolve(mainElement);
+ Expect.equals(0, compiler.warnings.length);
+ Expect.equals(1, compiler.errors.length);
+ Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY,
+ compiler.errors[0].message.kind);
+
+ compiler = new MockCompiler();
compiler.parseScript("""class A extends B {}
class B extends A {}
main() { return new A(); }""");
- FunctionElement mainElement = compiler.mainApp.find(MAIN);
+ mainElement = compiler.mainApp.find(MAIN);
compiler.resolver.resolve(mainElement);
Expect.equals(0, compiler.warnings.length);
Expect.equals(2, compiler.errors.length);
@@ -714,6 +724,17 @@
supertypes = aElement.allSupertypes;
Expect.equals(<String>['A<E>', 'D', 'Object'].toString(),
asSortedStrings(supertypes).toString());
+
+ compiler = new MockCompiler();
+ compiler.parseScript("""class A<T> {}
+ class D extends A<int> implements A<double> {}
+ main() { return new D(); }""");
+ mainElement = compiler.mainApp.find(MAIN);
+ compiler.resolver.resolve(mainElement);
+ Expect.equals(0, compiler.warnings.length);
+ Expect.equals(1, compiler.errors.length);
+ Expect.equals(MessageKind.MULTI_INHERITANCE,
+ compiler.errors[0].message.kind);
}
testInitializers() {
diff --git a/tests/compiler/dart2js/simple_inferrer_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
index e087982..3476096 100644
--- a/tests/compiler/dart2js/simple_inferrer_closure_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
@@ -123,14 +123,15 @@
checkReturn(String name, type) {
var element = findElement(compiler, name);
Expect.equals(type,
- typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
+ typesInferrer.getReturnTypeOfElement(element).simplify(compiler),
+ name);
}
- checkReturn('returnInt1', compiler.typesTask.intType);
- checkReturn('returnInt2', compiler.typesTask.intType);
- checkReturn('returnInt3', compiler.typesTask.intType);
- checkReturn('returnInt4', compiler.typesTask.intType);
- checkReturn('returnIntOrNull', compiler.typesTask.intType.nullable());
+ checkReturn('returnInt1', compiler.typesTask.uint31Type);
+ checkReturn('returnInt2', compiler.typesTask.uint31Type);
+ checkReturn('returnInt3', compiler.typesTask.uint31Type);
+ checkReturn('returnInt4', compiler.typesTask.uint31Type);
+ checkReturn('returnIntOrNull', compiler.typesTask.uint31Type.nullable());
checkReturn('returnDyn1', compiler.typesTask.dynamicType.nonNullable());
checkReturn('returnDyn2', compiler.typesTask.dynamicType.nonNullable());
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
index a18aa9a..9447cfb 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field2_test.dart
@@ -36,7 +36,7 @@
Expect.equals(type, typesInferrer.getTypeOfElement(element));
}
- checkFieldTypeInClass('A', 'intField', compiler.typesTask.intType);
+ checkFieldTypeInClass('A', 'intField', compiler.typesTask.uint31Type);
checkFieldTypeInClass('A', 'stringField', compiler.typesTask.stringType);
}));
}
diff --git a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
index 7c195c3..15f77ab 100644
--- a/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_final_field_test.dart
@@ -39,11 +39,11 @@
typesInferrer.getTypeOfElement(element).simplify(compiler));
}
- checkFieldTypeInClass('A', 'intField', compiler.typesTask.intType);
+ checkFieldTypeInClass('A', 'intField', compiler.typesTask.uint31Type);
checkFieldTypeInClass('A', 'giveUpField1',
findTypeMask(compiler, 'Interceptor', 'nonNullSubclass'));
checkFieldTypeInClass('A', 'giveUpField2',
compiler.typesTask.dynamicType.nonNullable());
- checkFieldTypeInClass('A', 'fieldParameter', compiler.typesTask.intType);
+ checkFieldTypeInClass('A', 'fieldParameter', compiler.typesTask.uint31Type);
}));
}
diff --git a/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart b/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
index bc17e71..3daef45 100644
--- a/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_no_such_method_test.dart
@@ -107,10 +107,10 @@
var compiler1 = compilerFor(TEST1, uri);
asyncTest(() => compiler1.runCompiler(uri).then((_) {
- checkReturn(compiler1, 'test1', compiler1.typesTask.intType);
+ checkReturn(compiler1, 'test1', compiler1.typesTask.uint31Type);
checkReturn(compiler1, 'test2',
compiler1.typesTask.dynamicType.nonNullable());
- checkReturn(compiler1, 'test3', compiler1.typesTask.intType);
+ checkReturn(compiler1, 'test3', compiler1.typesTask.uint31Type);
checkReturn(compiler1, 'test4', compiler1.typesTask.mapType);
checkReturn(compiler1, 'test5',
compiler1.typesTask.dynamicType.nonNullable());
@@ -127,9 +127,9 @@
checkReturn(compiler2, 'test5', compiler2.typesTask.mapType);
checkReturn(compiler2, 'test6', compiler2.typesTask.numType);
- checkReturn(compiler2, 'test7', compiler2.typesTask.intType);
- checkReturn(compiler2, 'test8', compiler2.typesTask.intType);
- checkReturn(compiler2, 'test9', compiler2.typesTask.intType);
+ checkReturn(compiler2, 'test7', compiler2.typesTask.uint31Type);
+ checkReturn(compiler2, 'test8', compiler2.typesTask.uint31Type);
+ checkReturn(compiler2, 'test9', compiler2.typesTask.uint31Type);
checkReturn(compiler2, 'test10', compiler2.typesTask.numType);
checkReturn(compiler2, 'test11', compiler2.typesTask.doubleType);
}));
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart
index 93d2737..81007d0 100644
--- a/tests/compiler/dart2js/simple_inferrer_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -717,18 +717,18 @@
checkReturn('returnNum1', typesTask.numType);
checkReturn('returnNum2', typesTask.numType);
- checkReturn('returnInt1', typesTask.intType);
- checkReturn('returnInt2', typesTask.intType);
+ checkReturn('returnInt1', typesTask.uint31Type);
+ checkReturn('returnInt2', typesTask.uint31Type);
checkReturn('returnDouble', typesTask.doubleType);
checkReturn('returnGiveUp', interceptorType);
- checkReturn('returnInt5', typesTask.intType);
- checkReturn('returnInt6', typesTask.intType);
- checkReturn('returnIntOrNull', typesTask.intType.nullable());
- checkReturn('returnInt3', typesTask.intType);
+ checkReturn('returnInt5', typesTask.positiveIntType);
+ checkReturn('returnInt6', typesTask.positiveIntType);
+ checkReturn('returnIntOrNull', typesTask.uint31Type.nullable());
+ checkReturn('returnInt3', typesTask.uint31Type);
checkReturn('returnDynamic', typesTask.dynamicType);
- checkReturn('returnInt4', typesTask.intType);
- checkReturn('returnInt7', typesTask.intType);
- checkReturn('returnInt8', typesTask.intType);
+ checkReturn('returnInt4', typesTask.uint31Type);
+ checkReturn('returnInt7', typesTask.positiveIntType);
+ checkReturn('returnInt8', typesTask.positiveIntType);
checkReturn('returnEmpty1', const TypeMask.nonNullEmpty());
checkReturn('returnEmpty2', const TypeMask.nonNullEmpty());
TypeMask intType = new TypeMask.nonNullSubtype(compiler.intClass);
@@ -761,60 +761,61 @@
checkReturn('testIsCheck27', intType);
checkReturn('testIsCheck28', typesTask.dynamicType);
checkReturn('testIsCheck29', typesTask.dynamicType);
- checkReturn('testIf1', typesTask.intType.nullable());
- checkReturn('testIf2', typesTask.intType.nullable());
+ checkReturn('testIf1', typesTask.uint31Type.nullable());
+ checkReturn('testIf2', typesTask.uint31Type.nullable());
checkReturn('returnAsString',
new TypeMask.subtype(compiler.stringClass));
- checkReturn('returnIntAsNum', typesTask.intType);
+ checkReturn('returnIntAsNum', typesTask.uint31Type);
checkReturn('returnAsTypedef', typesTask.functionType.nullable());
- checkReturn('returnTopLevelGetter', typesTask.intType);
- checkReturn('testDeadCode', typesTask.intType);
- checkReturn('testLabeledIf', typesTask.intType.nullable());
+ checkReturn('returnTopLevelGetter', typesTask.uint31Type);
+ checkReturn('testDeadCode', typesTask.uint31Type);
+ checkReturn('testLabeledIf', typesTask.uint31Type.nullable());
checkReturn('testSwitch1', typesTask.intType
.union(typesTask.doubleType, compiler)
.nullable().simplify(compiler));
- checkReturn('testSwitch2', typesTask.intType);
+ checkReturn('testSwitch2', typesTask.uint31Type);
checkReturn('testSwitch3', interceptorType.nullable());
- checkReturn('testSwitch4', typesTask.intType);
- checkReturn('testSwitch5', typesTask.intType);
+ checkReturn('testSwitch4', typesTask.uint31Type);
+ checkReturn('testSwitch5', typesTask.uint31Type);
checkReturn('testContinue1', interceptorType.nullable());
checkReturn('testBreak1', interceptorType.nullable());
checkReturn('testContinue2', interceptorType.nullable());
- checkReturn('testBreak2', typesTask.intType.nullable());
- checkReturn('testReturnElementOfConstList1', typesTask.intType);
- checkReturn('testReturnElementOfConstList2', typesTask.intType);
- checkReturn('testReturnItselfOrInt', typesTask.intType);
+ checkReturn('testBreak2', typesTask.positiveIntType.nullable());
+ checkReturn('testReturnElementOfConstList1', typesTask.uint31Type);
+ checkReturn('testReturnElementOfConstList2', typesTask.uint31Type);
+ checkReturn('testReturnItselfOrInt', typesTask.uint31Type);
checkReturn('testReturnInvokeDynamicGetter', typesTask.dynamicType);
checkReturn('testDoWhile1', typesTask.stringType);
checkReturn('testDoWhile2', typesTask.nullType);
- checkReturn('testDoWhile3', typesTask.intType);
+ checkReturn('testDoWhile3', typesTask.uint31Type);
checkReturn('testDoWhile4', typesTask.numType);
checkReturnInClass(String className, String methodName, type) {
var cls = findElement(compiler, className);
var element = cls.lookupLocalMember(methodName);
Expect.equals(type,
- typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
+ typesInferrer.getReturnTypeOfElement(element).simplify(compiler),
+ '$className:$methodName');
}
- checkReturnInClass('A', 'returnInt1', typesTask.intType);
- checkReturnInClass('A', 'returnInt2', typesTask.intType);
- checkReturnInClass('A', 'returnInt3', typesTask.intType);
- checkReturnInClass('A', 'returnInt4', typesTask.intType);
- checkReturnInClass('A', 'returnInt5', typesTask.intType);
- checkReturnInClass('A', 'returnInt6', typesTask.intType);
+ checkReturnInClass('A', 'returnInt1', typesTask.positiveIntType);
+ checkReturnInClass('A', 'returnInt2', typesTask.positiveIntType);
+ checkReturnInClass('A', 'returnInt3', typesTask.positiveIntType);
+ checkReturnInClass('A', 'returnInt4', typesTask.positiveIntType);
+ checkReturnInClass('A', 'returnInt5', typesTask.positiveIntType);
+ checkReturnInClass('A', 'returnInt6', typesTask.positiveIntType);
checkReturnInClass('A', '==', interceptorType);
- checkReturnInClass('B', 'returnInt1', typesTask.intType);
- checkReturnInClass('B', 'returnInt2', typesTask.intType);
- checkReturnInClass('B', 'returnInt3', typesTask.intType);
- checkReturnInClass('B', 'returnInt4', typesTask.intType);
- checkReturnInClass('B', 'returnInt5', typesTask.intType);
- checkReturnInClass('B', 'returnInt6', typesTask.intType);
- checkReturnInClass('B', 'returnInt7', typesTask.intType);
- checkReturnInClass('B', 'returnInt8', typesTask.intType);
- checkReturnInClass('B', 'returnInt9', typesTask.intType);
+ checkReturnInClass('B', 'returnInt1', typesTask.positiveIntType);
+ checkReturnInClass('B', 'returnInt2', typesTask.positiveIntType);
+ checkReturnInClass('B', 'returnInt3', typesTask.positiveIntType);
+ checkReturnInClass('B', 'returnInt4', typesTask.positiveIntType);
+ checkReturnInClass('B', 'returnInt5', typesTask.positiveIntType);
+ checkReturnInClass('B', 'returnInt6', typesTask.positiveIntType);
+ checkReturnInClass('B', 'returnInt7', typesTask.positiveIntType);
+ checkReturnInClass('B', 'returnInt8', typesTask.positiveIntType);
+ checkReturnInClass('B', 'returnInt9', typesTask.uint31Type);
checkFactoryConstructor(String className, String factoryName) {
var cls = findElement(compiler, className);
@@ -829,7 +830,7 @@
findElement(compiler, 'CascadeHelper')));
checkReturn('testSpecialization1', typesTask.numType);
checkReturn('testSpecialization2', typesTask.dynamicType);
- checkReturn('testSpecialization3', typesTask.intType.nullable());
+ checkReturn('testSpecialization3', typesTask.uint31Type.nullable());
checkReturn('testReturnNull1', typesTask.nullType);
checkReturn('testReturnNull2', typesTask.nullType);
checkReturn('testReturnNull3', typesTask.dynamicType);
diff --git a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
index 55ed3a7..331f76a 100644
--- a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
@@ -177,11 +177,11 @@
typesInferrer.getReturnTypeOfElement(element).simplify(compiler));
}
- checkReturn('returnInt1', typesTask.intType);
- checkReturn('returnInt2', typesTask.intType);
- checkReturn('returnInt3', typesTask.intType);
- checkReturn('returnInt4', typesTask.intType);
- checkReturn('returnInt5', typesTask.intType);
+ checkReturn('returnInt1', typesTask.uint31Type);
+ checkReturn('returnInt2', typesTask.uint31Type);
+ checkReturn('returnInt3', typesTask.uint31Type);
+ checkReturn('returnInt4', typesTask.uint31Type);
+ checkReturn('returnInt5', typesTask.uint31Type);
checkReturn('returnInt6',
new TypeMask.nonNullSubtype(compiler.intClass));
diff --git a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
index 3244287..5c2e11f 100644
--- a/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
+++ b/tests/compiler/dart2js/simple_inferrer_unregister_call_test.dart
@@ -41,6 +41,6 @@
Expect.equals(type, typesInferrer.getReturnTypeOfElement(element));
}
- checkReturnInClass('A', '+', compiler.typesTask.intType);
+ checkReturnInClass('A', '+', compiler.typesTask.uint31Type);
}));
}
diff --git a/tests/compiler/dart2js/type_promotion_test.dart b/tests/compiler/dart2js/type_promotion_test.dart
index a25c221..8739394 100644
--- a/tests/compiler/dart2js/type_promotion_test.dart
+++ b/tests/compiler/dart2js/type_promotion_test.dart
@@ -3,18 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
// Test that dart2js produces the expected static type warnings for type
-// promotion langauge tests. This ensures that the analyzer and dart2js agrees
+// promotion language tests. This ensures that the analyzer and dart2js agrees
// on these tests.
-import 'dart:async';
-import 'dart:io';
-import 'package:expect/expect.dart';
-import 'memory_compiler.dart';
-import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart';
-import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart';
-import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider.dart';
-import '../../../sdk/lib/_internal/compiler/implementation/util/uri_extras.dart';
-import 'dart:convert';
+import 'warnings_checker.dart';
/// Map from test files to a map of their expected status. If the status map is
/// `null` no warnings must be missing or unexpected, otherwise the status map
@@ -33,64 +25,5 @@
};
void main() {
- bool isWindows = Platform.isWindows;
- Uri script = currentDirectory.resolveUri(Platform.script);
- bool warningsMismatch = false;
- Future.forEach(TESTS.keys, (String test) {
- Uri uri = script.resolve('../../$test');
- String source = UTF8.decode(readAll(uriPathToNative(uri.path)));
- SourceFile file = new StringSourceFile(
- relativize(currentDirectory, uri, isWindows), source);
- Map<int,String> expectedWarnings = {};
- int lineNo = 0;
- for (String line in source.split('\n')) {
- if (line.contains('///') && line.contains('static type warning')) {
- expectedWarnings[lineNo] = line;
- }
- lineNo++;
- }
- Set<int> unseenWarnings = new Set<int>.from(expectedWarnings.keys);
- DiagnosticCollector collector = new DiagnosticCollector();
- var compiler = compilerFor(const {},
- diagnosticHandler: collector,
- options: ['--analyze-only'],
- showDiagnostics: false);
- return compiler.run(uri).then((_) {
- Map<String, List<int>> statusMap = TESTS[test];
- // Line numbers with known unexpected warnings.
- List<int> unexpectedStatus = [];
- if (statusMap != null && statusMap.containsKey('unexpected')) {
- unexpectedStatus = statusMap['unexpected'];
- }
- // Line numbers with known missing warnings.
- List<int> missingStatus = [];
- if (statusMap != null && statusMap.containsKey('missing')) {
- missingStatus = statusMap['missing'];
- }
- for (DiagnosticMessage message in collector.warnings) {
- Expect.equals(uri, message.uri);
- int lineNo = file.getLine(message.begin);
- if (expectedWarnings.containsKey(lineNo)) {
- unseenWarnings.remove(lineNo);
- } else if (!unexpectedStatus.contains(lineNo+1)) {
- warningsMismatch = true;
- print(file.getLocationMessage(
- 'Unexpected warning: ${message.message}',
- message.begin, message.end, true, (x) => x));
- }
- }
- if (!unseenWarnings.isEmpty) {
- for (int lineNo in unseenWarnings) {
- if (!missingStatus.contains(lineNo+1)) {
- warningsMismatch = true;
- String line = expectedWarnings[lineNo];
- print('$uri [${lineNo+1}]: Missing static type warning.');
- print(line);
- }
- }
- }
- });
- }).then((_) {
- Expect.isFalse(warningsMismatch);
- });
+ checkWarnings(TESTS);
}
diff --git a/tests/compiler/dart2js/type_test_helper.dart b/tests/compiler/dart2js/type_test_helper.dart
index 7f2a8fd..d616835 100644
--- a/tests/compiler/dart2js/type_test_helper.dart
+++ b/tests/compiler/dart2js/type_test_helper.dart
@@ -71,6 +71,10 @@
return compiler.types.isMoreSpecific(T, S);
}
+ DartType computeLeastUpperBound(DartType T, DartType S) {
+ return compiler.types.computeLeastUpperBound(T, S);
+ }
+
FunctionType functionType(DartType returnType,
List<DartType> parameters,
{List<DartType> optionalParameter,
@@ -88,7 +92,7 @@
namedParameterTypes.addLast(type);
});
}
- FunctionType type = new FunctionType(
+ return new FunctionType(
compiler.functionClass,
returnType, parameterTypes, optionalParameterTypes,
namedParameterNames.toLink(), namedParameterTypes.toLink());
diff --git a/tests/compiler/dart2js/value_range2_test.dart b/tests/compiler/dart2js/value_range2_test.dart
index 3b5bfeb..df274a8 100644
--- a/tests/compiler/dart2js/value_range2_test.dart
+++ b/tests/compiler/dart2js/value_range2_test.dart
@@ -10,7 +10,7 @@
ValueRangeInfo info = new ValueRangeInfo(const JavaScriptConstantSystem());
Value instructionValue = info.newInstructionValue(new HBreak(null));
-Value lengthValue = info.newLengthValue(new HBreak(null));
+Value lengthValue = info.newPositiveValue(new HBreak(null));
Range createSingleRange(Value value) => info.newNormalizedRange(value, value);
diff --git a/tests/compiler/dart2js/value_range3_test.dart b/tests/compiler/dart2js/value_range3_test.dart
new file mode 100644
index 0000000..d2c95c8
--- /dev/null
+++ b/tests/compiler/dart2js/value_range3_test.dart
@@ -0,0 +1,33 @@
+// 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.
+
+// Test that global analysis in dart2js propagates positive integers.
+
+import 'package:expect/expect.dart';
+import "package:async_helper/async_helper.dart";
+import 'memory_compiler.dart';
+
+const MEMORY_SOURCE_FILES = const {
+ 'main.dart': '''
+
+var a = [42];
+
+main() {
+ var value = a[0];
+ if (value < 42) {
+ return new List(42)[value];
+ }
+}
+''',
+};
+
+main() {
+ var compiler = compilerFor(MEMORY_SOURCE_FILES);
+ asyncTest(() => compiler.run(Uri.parse('memory:main.dart')).then((_) {
+ var element = compiler.mainApp.findExported('main');
+ var code = compiler.backend.assembleCode(element);
+ Expect.isFalse(code.contains('ioore'));
+ }));
+}
+
diff --git a/tests/compiler/dart2js/value_range_test.dart b/tests/compiler/dart2js/value_range_test.dart
index e4b9572..92ae4c4 100644
--- a/tests/compiler/dart2js/value_range_test.dart
+++ b/tests/compiler/dart2js/value_range_test.dart
@@ -334,6 +334,9 @@
}
class ObjectInterceptor {
}
+ class JSPositiveInt extends JSInt {}
+ class JSUInt32 extends JSPositiveInt {}
+ class JSUInt31 extends JSUInt32 {}
getInterceptor(x) {}''';
expect(String code, int kind) {
diff --git a/tests/compiler/dart2js/warnings_checker.dart b/tests/compiler/dart2js/warnings_checker.dart
new file mode 100644
index 0000000..1105b38
--- /dev/null
+++ b/tests/compiler/dart2js/warnings_checker.dart
@@ -0,0 +1,80 @@
+// 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.
+
+// Test that dart2js produces the expected static type warnings to ensures that
+// the analyzer and dart2js agrees on the tests.
+
+import 'dart:async';
+import 'dart:io';
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+import 'memory_compiler.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/source_file.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/util/uri_extras.dart';
+import 'dart:convert';
+
+void checkWarnings(Map<String, dynamic> tests) {
+ bool isWindows = Platform.isWindows;
+ Uri script = currentDirectory.resolveUri(Platform.script);
+ bool warningsMismatch = false;
+ asyncTest(() => Future.forEach(tests.keys, (String test) {
+ Uri uri = script.resolve('../../$test');
+ String source = UTF8.decode(readAll(uriPathToNative(uri.path)));
+ SourceFile file = new StringSourceFile(
+ relativize(currentDirectory, uri, isWindows), source);
+ Map<int,String> expectedWarnings = {};
+ int lineNo = 0;
+ for (String line in source.split('\n')) {
+ if (line.contains('///') && line.contains('static type warning')) {
+ expectedWarnings[lineNo] = line;
+ }
+ lineNo++;
+ }
+ Set<int> unseenWarnings = new Set<int>.from(expectedWarnings.keys);
+ DiagnosticCollector collector = new DiagnosticCollector();
+ var compiler = compilerFor(const {},
+ diagnosticHandler: collector,
+ options: ['--analyze-only'],
+ showDiagnostics: false);
+ return compiler.run(uri).then((_) {
+ Map<String, List<int>> statusMap = tests[test];
+ // Line numbers with known unexpected warnings.
+ List<int> unexpectedStatus = [];
+ if (statusMap != null && statusMap.containsKey('unexpected')) {
+ unexpectedStatus = statusMap['unexpected'];
+ }
+ // Line numbers with known missing warnings.
+ List<int> missingStatus = [];
+ if (statusMap != null && statusMap.containsKey('missing')) {
+ missingStatus = statusMap['missing'];
+ }
+ for (DiagnosticMessage message in collector.warnings) {
+ Expect.equals(uri, message.uri);
+ int lineNo = file.getLine(message.begin);
+ if (expectedWarnings.containsKey(lineNo)) {
+ unseenWarnings.remove(lineNo);
+ } else if (!unexpectedStatus.contains(lineNo+1)) {
+ warningsMismatch = true;
+ print(file.getLocationMessage(
+ 'Unexpected warning: ${message.message}',
+ message.begin, message.end, true, (x) => x));
+ }
+ }
+ if (!unseenWarnings.isEmpty) {
+ for (int lineNo in unseenWarnings) {
+ if (!missingStatus.contains(lineNo+1)) {
+ warningsMismatch = true;
+ String line = expectedWarnings[lineNo];
+ print('$uri [${lineNo+1}]: Missing static type warning.');
+ print(line);
+ }
+ }
+ }
+ });
+ }).then((_) {
+ Expect.isFalse(warningsMismatch);
+ }));
+}
diff --git a/tests/compiler/dart2js_extra/mirrors_used_native_test.dart b/tests/compiler/dart2js_extra/mirrors_used_native_test.dart
index f040e5b..a546682 100644
--- a/tests/compiler/dart2js_extra/mirrors_used_native_test.dart
+++ b/tests/compiler/dart2js_extra/mirrors_used_native_test.dart
@@ -8,7 +8,6 @@
import 'package:expect/expect.dart';
main() {
- List; // work-around for a bug in the type-variable handler. TODO(zarah): remove.
Expect.equals(3, reflect([1, 2, 3]).getField(#length).reflectee);
Expect.throws(() => reflect({"hest": 42}).getField(#length),
(e) => e is UnsupportedError);
diff --git a/tests/compiler/dart2js_extra/type_constant_switch_test.dart b/tests/compiler/dart2js_extra/type_constant_switch_test.dart
new file mode 100644
index 0000000..b28d6dc
--- /dev/null
+++ b/tests/compiler/dart2js_extra/type_constant_switch_test.dart
@@ -0,0 +1,16 @@
+// 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.
+
+// Test that switching on type literals leads to a compile time error in
+// dart2js since its implementation of [Type] implements 'operator =='.
+
+class C {}
+
+var v;
+
+main() {
+ switch (v) {
+ case C: break; /// 01: compile-time error
+ }
+}
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 7e0a5e1..944143f 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -86,8 +86,6 @@
string_base_vm_test: RuntimeError, OK # VM specific test.
nan_infinity_test/01: Fail # Issue 11551
-list_test/01: RuntimeError # Issue 14616
-
[ $compiler == dart2js && $runtime == none ]
*: Fail, Pass # TODO(ahe): Triage these tests.
@@ -136,6 +134,9 @@
[ $arch == simmips && $checked ]
collection_length_test: Pass, Timeout
+[ $arch == simarm && $checked ]
+num_parse_test: Pass, Timeout
+
[ $arch == simmips && $mode == debug ]
collection_to_string_test: Pass, Crash # Issue: 11207
@@ -144,3 +145,10 @@
iterable_element_at_test: StaticWarning, OK # Test generates errors on purpose.
num_clamp_test: StaticWarning, OK # Test generates errors on purpose.
string_test: StaticWarning, OK # Test generates error on purpose.
+
+[ $compiler == dart2js && $runtime == safari ]
+list_test/01: Fail # Safari bug: Array(-2) seen as dead code.
+
+[ $runtime == ie9 || $runtime == ie10 ]
+num_parse_test: RuntimeError # Issue 15316
+num_parse_test/01: RuntimeError # Issue 15316
diff --git a/tests/corelib/list_test.dart b/tests/corelib/list_test.dart
index bdd449a..5187ee8 100644
--- a/tests/corelib/list_test.dart
+++ b/tests/corelib/list_test.dart
@@ -497,8 +497,8 @@
void testListConstructor() {
Expect.throws(() { new List(0).add(4); }); // Is fixed-length.
- Expect.throws(() { new List(-2); }); // Not negative.
- Expect.throws(() { new List(null); }); // Not null. /// 01: ok
+ Expect.throws(() { new List(-2); }); // Not negative. /// 01: ok
+ Expect.throws(() { new List(null); }); // Not null.
Expect.listEquals([4], new List()..add(4));
Expect.throws(() { new List.filled(0, 42).add(4); }); // Is fixed-length.
Expect.throws(() { new List.filled(-2, 42); }); // Not negative.
diff --git a/tests/corelib/num_parse_test.dart b/tests/corelib/num_parse_test.dart
new file mode 100644
index 0000000..c0b80e4
--- /dev/null
+++ b/tests/corelib/num_parse_test.dart
@@ -0,0 +1,235 @@
+// Copyright (c) 2013 the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+const whiteSpace = const [
+ "",
+ "\x09",
+ "\x0a",
+ "\x0b",
+ "\x0c",
+ "\x0d",
+ "\x85",
+ "\xa0",
+ "\u1680",
+ "\u180e",
+ "\u2000",
+ "\u2001",
+ "\u2002",
+ "\u2003",
+ "\u2004",
+ "\u2005",
+ "\u2006",
+ "\u2007",
+ "\u2008",
+ "\u2009",
+ "\u200a",
+ "\u2028",
+ "\u2029",
+ "\u202f",
+ "\u205f",
+ "\u3000",
+ "\uFEFF"
+];
+
+void expectNumEquals(num expect, num actual, String message) {
+ if (expect is double && expect.isNaN) {
+ Expect.isTrue(actual is double && actual.isNaN, "isNaN: $message");
+ } else {
+ Expect.identical(expect, actual, message);
+ }
+}
+
+// Test source surrounded by any combination of whitespace.
+void testParseAllWhitespace(String source, num result) {
+ for (String ws1 in whiteSpace) {
+ for (String ws2 in whiteSpace) {
+ String padded = "$ws1$source$ws2";
+ // Use Expect.identical because it also handles NaN and 0.0/-0.0.
+ // Except on dart2js: http://dartbug.com/11551
+ expectNumEquals(result, num.parse(padded), "parse '$padded'");
+ padded = "$ws1$ws2$source";
+ expectNumEquals(result, num.parse(padded), "parse '$padded'");
+ padded = "$source$ws1$ws2";
+ expectNumEquals(result, num.parse(padded), "parse '$padded'");
+ }
+ }
+}
+
+// Test source and -source surrounded by any combination of whitespace.
+void testParseWhitespace(String source, num result) {
+ assert(result >= 0);
+ testParseAllWhitespace(source, result);
+ testParseAllWhitespace("-$source", -result);
+}
+
+// Test parsing source, optionally preceeded and/or followed by whitespace.
+void testParse(String source, num result) {
+ expectNumEquals(result, num.parse(source), "parse '$source'");
+ expectNumEquals(result, num.parse(" $source"), "parse ' $source'");
+ expectNumEquals(result, num.parse("$source "), "parse '$source '");
+ expectNumEquals(result, num.parse(" $source "), "parse ' $source '");
+}
+
+// Test parsing an integer in decimal or hex format, with or without signs.
+void testInt(int value) {
+ testParse("$value", value);
+ testParse("+$value", value);
+ testParse("-$value", -value);
+ var hex = "0x${value.toRadixString(16)}";
+ var lchex = hex.toLowerCase();
+ testParse(lchex, value);
+ testParse("+$lchex", value);
+ testParse("-$lchex", -value);
+ var uchex = hex.toUpperCase();
+ testParse(uchex, value);
+ testParse("+$uchex", value);
+ testParse("-$uchex", -value);
+}
+
+// Test parsing an integer, and the integers just around it.
+void testIntAround(int value) {
+ testInt(value - 1);
+ testInt(value);
+ testInt(value + 1);
+}
+
+void testDouble(double value) {
+ testParse("$value", value);
+ testParse("+$value", value);
+ testParse("-$value", -value);
+ if (value.isFinite) {
+ String exp = value.toStringAsExponential();
+ String lcexp = exp.toLowerCase();
+ testParse(lcexp, value);
+ testParse("+$lcexp", value);
+ testParse("-$lcexp", -value);
+ String ucexp = exp.toUpperCase();
+ testParse(ucexp, value);
+ testParse("+$ucexp", value);
+ testParse("-$ucexp", -value);
+ }
+}
+
+void testFail(String source) {
+ var object = new Object();
+ Expect.throws(() {
+ num.parse(source, (s) {
+ Expect.equals(source, s);
+ throw object;
+ });
+ }, (e) => identical(object, e), "Fail: '$source'");
+}
+
+void main() {
+ testInt(0);
+ testInt(1);
+ testInt(9);
+ testInt(10);
+ testInt(99);
+ testInt(100);
+ testIntAround(256);
+ testIntAround(0x80000000); // 2^31
+ testIntAround(0x100000000); // 2^32
+ testIntAround(0x10000000000000); // 2^52
+ testIntAround(0x20000000000000); // 2^53
+ testIntAround(0x40000000000000); // 2^54
+ testIntAround(0x8000000000000000); // 2^63
+ testIntAround(0x10000000000000000); // 2^64
+ testIntAround(0x100000000000000000000); // 2^80
+
+ testDouble(0.0);
+ testDouble(5e-324);
+ testDouble(2.225073858507201e-308);
+ testDouble(2.2250738585072014e-308);
+ testDouble(0.49999999999999994);
+ testDouble(0.5);
+ testDouble(0.50000000000000006);
+ testDouble(0.9999999999999999);
+ testDouble(1.0);
+ testDouble(1.0000000000000002);
+ testDouble(4294967295.0);
+ testDouble(4294967296.0);
+ testDouble(4503599627370495.5);
+ testDouble(4503599627370497.0);
+ testDouble(9007199254740991.0);
+ testDouble(9007199254740992.0);
+ testDouble(1.7976931348623157e+308);
+ testDouble(double.INFINITY);
+ testDouble(double.NAN); /// 01: ok
+
+ // Strings that cannot occur from toString of a number.
+ testParse("000000000000", 0);
+ testParse("000000000001", 1);
+ testParse("000000000000.0000000000000", 0.0);
+ testParse("000000000001.0000000000000", 1.0);
+ testParse("0x0000000000", 0);
+ testParse("0e0", 0.0);
+ testParse("0e+0", 0.0);
+ testParse("0e-0", 0.0);
+ testParse("-0e0", -0.0);
+ testParse("-0e+0", -0.0);
+ testParse("-0e-0", -0.0);
+ testParse("1e0", 1.0);
+ testParse("1e+0", 1.0);
+ testParse("1e-0", 1.0);
+ testParse("-1e0", -1.0);
+ testParse("-1e+0", -1.0);
+ testParse("-1e-0", -1.0);
+ testParse("1.", 1.0);
+ testParse(".1", 0.1);
+ testParse("1.e1", 10.0);
+ testParse(".1e1", 1.0);
+
+ testParseWhitespace("0x1", 1);
+ testParseWhitespace("1", 1);
+ testParseWhitespace("1.0", 1.0);
+ testParseWhitespace("1e1", 10.0);
+ testParseWhitespace(".1e1", 1.0);
+ testParseWhitespace("1.e1", 10.0);
+ testParseWhitespace("1e+1", 10.0);
+ testParseWhitespace("1e-1", 0.1);
+
+ // Negative tests - things not to allow.
+
+ // Spaces inside the numeral.
+ testFail("- 1");
+ testFail("+ 1");
+ testFail("2 2");
+ testFail("0x 42");
+ testFail("1 .");
+ testFail(". 1");
+ testFail("1e 2");
+ testFail("1 e2");
+ // Invalid characters.
+ testFail("0x1H");
+ testFail("12H");
+ testFail("1x2");
+ testFail("00x2");
+ testFail("0x2.2");
+ // Empty hex number.
+ testFail("0x");
+ testFail("-0x");
+ testFail("+0x");
+ // Double exponent without value.
+ testFail(".e1");
+ testFail("e1");
+ testFail("e+1");
+ testFail("e-1");
+ testFail("-e1");
+ testFail("-e+1");
+ testFail("-e-1");
+ // Incorrect ways to write NaN/Infinity.
+ testFail("infinity");
+ testFail("INFINITY");
+ testFail("1.#INF");
+ testFail("inf");
+ testFail("nan");
+ testFail("NAN");
+ testFail("1.#IND");
+ testFail("indef");
+ testFail("qnan");
+ testFail("snan");
+}
diff --git a/tests/html/async_window_test.dart b/tests/html/async_window_test.dart
deleted file mode 100644
index 6cdb5dd..0000000
--- a/tests/html/async_window_test.dart
+++ /dev/null
@@ -1,33 +0,0 @@
-library AsyncWindowTest;
-import '../../pkg/unittest/lib/unittest.dart';
-import '../../pkg/unittest/lib/html_config.dart';
-import 'dart:html';
-import 'dart:async';
-
-main() {
- useHtmlConfiguration();
- test('Timer', () {
- new Timer(const Duration(milliseconds: 10), expectAsync0((){}));
- });
- test('Timer.periodic', () {
- int counter = 0;
- int id = null;
- new Timer.periodic(const Duration(milliseconds: 10),
- expectAsyncUntil1(
- (timer) {
- if (counter == 3) {
- counter = 1024;
- timer.cancel();
- // Wait some more time to be sure callback won't be invoked any
- // more.
- new Timer(const Duration(milliseconds: 50), expectAsync0((){}));
- return;
- }
- // As callback should have been cleared on 4th invocation, counter
- // should never be greater than 3.
- assert(counter < 3);
- counter++;
- },
- () => counter == 3));
- });
-}
diff --git a/tests/html/html.status b/tests/html/html.status
index 850c938..4117007 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -2,7 +2,6 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-async_window_test: Skip #TODO(gram): investigating
event_test: Skip # Issue 1996
interactive_test: Skip # Must be run manually.
dromaeo_smoke_test: Skip # Issue 14521, 8257
@@ -89,6 +88,8 @@
xhr_test: Pass, Fail # Issue 11884
xhr_cross_origin_test: Pass, Fail # Issue 11884
+fileapi_test/fileEntry: Pass, Fail # Issue 15355
+
[$runtime == drt || $runtime == dartium || $runtime == chrome || $runtime == chromeOnAndroid]
webgl_1_test: Pass, Fail # Issue 8219
diff --git a/tests/isolate/browser/compute_this_script_browser_test.dart b/tests/isolate/browser/compute_this_script_browser_test.dart
index 2b71451..63a886d 100644
--- a/tests/isolate/browser/compute_this_script_browser_test.dart
+++ b/tests/isolate/browser/compute_this_script_browser_test.dart
@@ -11,6 +11,7 @@
import 'dart:isolate';
import 'package:unittest/unittest.dart';
import 'package:unittest/html_config.dart';
+import "../remote_unittest_helper.dart";
child(var message) {
var data = message[0];
@@ -18,7 +19,8 @@
reply.send('re: $data');
}
-main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
useHtmlConfiguration();
var script = new ScriptElement();
document.body.append(script);
diff --git a/tests/isolate/browser/typed_data_message_test.dart b/tests/isolate/browser/typed_data_message_test.dart
index 9432290..61954b9 100644
--- a/tests/isolate/browser/typed_data_message_test.dart
+++ b/tests/isolate/browser/typed_data_message_test.dart
@@ -9,6 +9,7 @@
import 'dart:isolate';
import 'dart:typed_data';
import 'package:unittest/unittest.dart';
+import "../remote_unittest_helper.dart";
// ---------------------------------------------------------------------------
// Message passing test.
@@ -86,7 +87,8 @@
return response.first;
}
-main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
initializeList();
test("send objects and receive them back", () {
ReceivePort response = new ReceivePort();
diff --git a/tests/isolate/compile_time_error_test.dart b/tests/isolate/compile_time_error_test.dart
new file mode 100644
index 0000000..4bb70c7
--- /dev/null
+++ b/tests/isolate/compile_time_error_test.dart
@@ -0,0 +1,35 @@
+// 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.
+
+// Dart test program for testing that errors thrown from isolates are
+// processed correctly and don't result in crashes.
+
+library Isolate3NegativeTest;
+import 'dart:isolate';
+import 'dart:async';
+import "package:async_helper/async_helper.dart";
+
+class TestClass {
+ TestClass.named(num this.fld1)
+ // Should cause a compilation error (for the spawned isolate). It is a
+ // runtime error for the test.
+ : fld2 = fld1 /// 01: compile-time error
+ ;
+ num fld1;
+ num fld2;
+}
+
+void entry(SendPort replyTo) {
+ var tmp = new TestClass.named(10);
+ replyTo.send("done");
+}
+
+main() {
+ asyncStart();
+ ReceivePort response = new ReceivePort();
+ Isolate.spawn(entry, response.sendPort);
+ response.first.then((_) {
+ asyncEnd();
+ });
+}
diff --git a/tests/isolate/count_test.dart b/tests/isolate/count_test.dart
index c0cbde3..881ac6b 100644
--- a/tests/isolate/count_test.dart
+++ b/tests/isolate/count_test.dart
@@ -3,8 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
library CountTest;
-import '../../pkg/unittest/lib/unittest.dart';
import 'dart:isolate';
+import 'package:unittest/unittest.dart';
+import "remote_unittest_helper.dart";
void countMessages(replyTo) {
int count = 0;
@@ -23,7 +24,8 @@
});
}
-void main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
test("count 10 consecutive messages", () {
ReceivePort local = new ReceivePort();
Isolate.spawn(countMessages, local.sendPort);
diff --git a/tests/isolate/cross_isolate_message_test.dart b/tests/isolate/cross_isolate_message_test.dart
index 00874d0..56181c8 100644
--- a/tests/isolate/cross_isolate_message_test.dart
+++ b/tests/isolate/cross_isolate_message_test.dart
@@ -7,7 +7,8 @@
library CrossIsolateMessageTest;
import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import "remote_unittest_helper.dart";
/*
* Everything starts in the main-isolate (in the main-method).
@@ -34,7 +35,8 @@
toIsolate1.send(["fromIsolate2", 42]);
}
-main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
test("send message cross isolates ", () {
ReceivePort fromIsolate1 = new ReceivePort();
Isolate.spawn(crossIsolate1, fromIsolate1.sendPort);
diff --git a/tests/isolate/illegal_msg_function_test.dart b/tests/isolate/illegal_msg_function_test.dart
index f967afd..8767994 100644
--- a/tests/isolate/illegal_msg_function_test.dart
+++ b/tests/isolate/illegal_msg_function_test.dart
@@ -4,10 +4,10 @@
library illegal_msg_function_test;
-import "package:expect/expect.dart";
import "dart:isolate";
import "dart:async" show Future;
-import "package:async_helper/async_helper.dart";
+import "package:unittest/unittest.dart";
+import "remote_unittest_helper.dart";
funcFoo(x) => x + 2;
@@ -19,31 +19,29 @@
});
}
-main() {
- var function = funcFoo;
+void main([args, port]) {
+ if (testRemote(main, port)) return;
+ test("msg_function", () {
+ var function = funcFoo;
+ ReceivePort port = new ReceivePort();
+ Future spawn = Isolate.spawn(echo, port.sendPort);
+ var caught_exception = false;
+ var stream = port.asBroadcastStream();
+ stream.first.then(expectAsync1((snd) {
+ try {
+ snd.send(function);
+ } catch (e) {
+ caught_exception = true;
+ }
- ReceivePort port = new ReceivePort();
- Future spawn = Isolate.spawn(echo, port.sendPort);
- var caught_exception = false;
- var stream = port.asBroadcastStream();
- asyncStart();
- stream.first.then((snd) {
- try {
- snd.send(function);
- } catch (e) {
- caught_exception = true;
- }
-
- if (caught_exception) {
- port.close();
- } else {
- asyncStart();
- stream.first.then((msg) {
- print("from worker ${msg}");
- asyncEnd();
- });
- }
- Expect.isTrue(caught_exception);
- asyncEnd();
+ if (caught_exception) {
+ port.close();
+ } else {
+ stream.first.then(expectAsync1((msg) {
+ print("from worker ${msg}");
+ }));
+ }
+ expect(caught_exception, isTrue);
+ }));
});
}
diff --git a/tests/isolate/illegal_msg_mirror_test.dart b/tests/isolate/illegal_msg_mirror_test.dart
index eed2981..dcf80a01 100644
--- a/tests/isolate/illegal_msg_mirror_test.dart
+++ b/tests/isolate/illegal_msg_mirror_test.dart
@@ -4,11 +4,12 @@
library illegal_msg_mirror_test;
-import "package:expect/expect.dart";
import "dart:isolate";
import "dart:async" show Future;
-import "package:async_helper/async_helper.dart";
+@MirrorsUsed(targets: "Class")
import "dart:mirrors";
+import "package:unittest/unittest.dart";
+import "remote_unittest_helper.dart";
class Class {
method() {}
@@ -22,31 +23,30 @@
});
}
-main() {
- var methodMirror = reflectClass(Class).declarations[#method];
+void main([args, port]) {
+ if (testRemote(main, port)) return;
+ test("msg-mirror", () {
+ var methodMirror = reflectClass(Class).declarations[#method];
- ReceivePort port = new ReceivePort();
- Future spawn = Isolate.spawn(echo, port.sendPort);
- var caught_exception = false;
- var stream = port.asBroadcastStream();
- asyncStart();
- stream.first.then((snd) {
- try {
- snd.send(methodMirror);
- } catch (e) {
- caught_exception = true;
- }
+ ReceivePort port = new ReceivePort();
+ Future spawn = Isolate.spawn(echo, port.sendPort);
+ var caught_exception = false;
+ var stream = port.asBroadcastStream();
+ stream.first.then(expectAsync1((snd) {
+ try {
+ snd.send(methodMirror);
+ } catch (e) {
+ caught_exception = true;
+ }
- if (caught_exception) {
- port.close();
- } else {
- asyncStart();
- stream.first.then((msg) {
- print("from worker ${msg}");
- asyncEnd();
- });
- }
- Expect.isTrue(caught_exception);
- asyncEnd();
+ if (caught_exception) {
+ port.close();
+ } else {
+ stream.first.then(expectAsync1((msg) {
+ print("from worker ${msg}");
+ }));
+ }
+ expect(caught_exception, isTrue);
+ }));
});
}
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index e87e71a..4338e96 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -8,19 +8,13 @@
[ $compiler == none ]
serialization_test: SkipByDesign # Tests dart2js-specific serialization code
-isolate2_negative_test: Skip # Issue 12587.
-isolate3_negative_test: Skip # Issue 12587.
-
-[ $analyzer ]
-isolate2_negative_test: Fail
-isolate_import_negative_test: Fail
-unresolved_ports_test: Pass
+isolate_throws_test/01: Skip # Issue 12587
+compile_time_error_test/01: Skip # Issue 12587
[ $compiler == dart2js && $jscl ]
browser/*: SkipByDesign # Browser specific tests
[ $compiler == dart2js && $runtime == drt ]
-unresolved_ports_negative_test: Pass, Crash # Issue 10613
isolate_stress_test: Pass, Crash # Issue 14438
[ $compiler == dart2js ]
@@ -33,17 +27,9 @@
cross_isolate_message_test: Skip # Issue 12627
message_test: Skip # Issue 12627
-[ $compiler == dart2js && $runtime == opera ]
-isolate2_negative_test: Skip # Issue 12625
-unresolved_ports_negative_test: Skip # Issue 12626
-
[ $compiler == dart2js ]
spawn_uri_vm_test: SkipByDesign # Test uses a ".dart" URI.
spawn_uri_nested_vm_test: SkipByDesign # Test uses a ".dart" URI.
-spawn_uri_vm_negative_test: SkipByDesign # Test uses a ".dart" URI.
-
-[ $compiler == dart2js && $browser ]
-isolate2_negative_test: Fail, Pass # Issue 7769
[ $compiler == dart2js && $jscl ]
spawn_uri_test: SkipByDesign # Loading another file is not supported in JS shell
@@ -52,12 +38,7 @@
spawn_uri_test: Fail # Issue 12630
[ $compiler == dart2js && $runtime == none ]
-spawn_function_negative_test: Fail # Issue 12628
-unresolved_ports_negative_test: Fail # Issue 12628
-isolate_negative_test: Fail # Issue 12628
serialization_test: Pass # Issue 12628
-isolate_import_negative_test: Fail # Issue 12628
-isolate2_negative_test: Fail # Issue 12628
illegal_msg_function_test: Pass # Issue 12628
illegal_msg_mirror_test: Pass # Issue 12628
@@ -90,35 +71,16 @@
[ $compiler == none && $runtime == dartium ]
spawn_uri_nested_vm_test: Skip # Issue 14479: This test is timing out.
-[ $compiler == none && ($runtime == drt || $runtime == dartium) ]
-# Issue 13921: spawnFunction is not allowed on Dartium's DOM thread.
-browser/compute_this_script_browser_test: Fail
-browser/typed_data_message_test: Skip # 13961
-count_test: Fail
-cross_isolate_message_test: Fail
-illegal_msg_function_test: Fail
-illegal_msg_mirror_test: Fail
-isolate_complex_messages_test: Fail
-isolate_stress_test: Fail
-mandel_isolate_test: Fail
-message2_test: Fail
-message_test: Fail
-mint_maker_test: Fail
-nested_spawn2_test: Fail
-nested_spawn_test: Fail
-raw_port_test: Fail
-request_reply_test: Fail
-spawn_function_custom_class_test: Fail
-spawn_function_test: Fail
-stacktrace_message_test: Fail
-unresolved_ports_test: Fail
-static_function_test: Fail
+[ $compiler == none && $runtime == dartium ]
+isolate_stress_test: Skip # Issue 14463
+
+[ $compiler == none && ( $runtime == dartium || $runtime == drt ) ]
+compile_time_error_test/none: Fail, OK # Issue 13921 Dom isolates don't support spawnFunction
+isolate_import_test/none: Fail, OK # Issue 13921 Dom isolates don't support spawnFunction
+isolate_throws_test/none: Fail, OK # Issue 13921 Dom isolates don't support spawnFunction
+simple_message_test/none: Fail, OK # Issue 13921 Dom isolates don't support spawnFunction
[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
browser/typed_data_message_test: StaticWarning
-isolate3_negative_test: CompileTimeError
-isolate_import_negative_test: CompileTimeError
mint_maker_test: StaticWarning
serialization_test: StaticWarning
-unresolved_ports_test: StaticWarning
-
diff --git a/tests/isolate/isolate2_negative_test.dart b/tests/isolate/isolate2_negative_test.dart
deleted file mode 100644
index 03fdb3c..0000000
--- a/tests/isolate/isolate2_negative_test.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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.
-
-// Dart test program for testing that exceptions in other isolates bring down
-// the program.
-
-library isolate2_negative_test;
-import 'dart:isolate';
-import "package:async_helper/async_helper.dart";
-
-void entry(msg) {
- throw "foo";
-}
-
-main() {
- // We start an asynchronous operation, but since we don't expect to get
- // anything back except an exception there is no asyncEnd().
- // If the exception is not thrown this test will timeout.
- asyncStart();
- Isolate.spawn(entry);
-}
diff --git a/tests/isolate/isolate3_negative_test.dart b/tests/isolate/isolate3_negative_test.dart
deleted file mode 100644
index ed46f27..0000000
--- a/tests/isolate/isolate3_negative_test.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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.
-
-// Dart test program for testing that errors thrown from isolates are
-// processed correctly and don't result in crashes.
-
-library Isolate3NegativeTest;
-import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
-
-class TestClass {
- TestClass.named(num this.fld1) : fld2=fld1 {
- TestClass.i = 0; // Should cause a compilation error.
- }
- num fld1;
- num fld2;
-}
-
-void entry(SendPort replyTo) {
- var tmp = new TestClass.named(10);
- replyTo.send(tmp);
-}
-
-main() {
- test("child isolate compilation errors propagate correctly. ", () {
- void msg_callback(var message) {
- // This test is a negative test and should not complete successfully.
- }
- ReceivePort response = new ReceivePort();
- Isolate.spawn(entry, response.sendPort);
- response.first.then(expectAsync1(msg_callback));
- });
-}
diff --git a/tests/isolate/isolate_complex_messages_test.dart b/tests/isolate/isolate_complex_messages_test.dart
index 3a18ec5..92c26d9 100644
--- a/tests/isolate/isolate_complex_messages_test.dart
+++ b/tests/isolate/isolate_complex_messages_test.dart
@@ -7,9 +7,11 @@
library IsolateComplexMessagesTest;
import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import "remote_unittest_helper.dart";
-main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
test("complex messages are serialized correctly", () {
ReceivePort local = new ReceivePort();
Isolate.spawn(logMessages, local.sendPort);
diff --git a/tests/isolate/isolate_import_negative_test.dart b/tests/isolate/isolate_import_test.dart
similarity index 72%
rename from tests/isolate/isolate_import_negative_test.dart
rename to tests/isolate/isolate_import_test.dart
index 1ea9102..5fa0f32 100644
--- a/tests/isolate/isolate_import_negative_test.dart
+++ b/tests/isolate/isolate_import_test.dart
@@ -4,11 +4,13 @@
library IsolateImportNegativeTest;
// Omitting the following import is an error:
-// import 'dart:isolate';
+/* /// 01: runtime error, static type warning
+import 'dart:isolate';
+*/ /// 01: continued
void entry(msg) {}
main() {
- Isolate.spawn(entry);
+ Isolate.spawn(entry, null);
}
diff --git a/tests/isolate/isolate_negative_test.dart b/tests/isolate/isolate_negative_test.dart
deleted file mode 100644
index e40d23e..0000000
--- a/tests/isolate/isolate_negative_test.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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.
-
-// Dart test program for testing that isolates are spawned.
-
-library IsolateNegativeTest;
-import "package:expect/expect.dart";
-import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
-
-void entry(SendPort replyTo) {
- replyTo.send("foo");
-}
-
-main() {
- test("ensure isolate code is executed", () {
- ReceivePort response = new ReceivePort();
- Isolate.spawn(entry, response.sendPort);
- response.first.then(expectAsync1((message) {
- expect("Expected fail", isTrue); // <=-------- Should fail here.
- }));
- });
-}
diff --git a/tests/isolate/isolate_throws_test.dart b/tests/isolate/isolate_throws_test.dart
new file mode 100644
index 0000000..aecbe6e
--- /dev/null
+++ b/tests/isolate/isolate_throws_test.dart
@@ -0,0 +1,26 @@
+// 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.
+
+// Dart test program for testing that exceptions in other isolates bring down
+// the program.
+
+import 'dart:async';
+import 'dart:isolate';
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+void entry(SendPort replyTo) {
+ throw "foo"; /// 01: runtime error
+ replyTo.send("done");
+}
+
+main() {
+ asyncStart();
+ ReceivePort rp = new ReceivePort();
+ Isolate.spawn(entry, rp.sendPort);
+ rp.first.then((msg) {
+ Expect.equals("done", msg);
+ asyncEnd();
+ });
+}
diff --git a/tests/isolate/mandel_isolate_test.dart b/tests/isolate/mandel_isolate_test.dart
index b1e3656..7099abe 100644
--- a/tests/isolate/mandel_isolate_test.dart
+++ b/tests/isolate/mandel_isolate_test.dart
@@ -6,15 +6,17 @@
import 'dart:async';
import 'dart:isolate';
import 'dart:math';
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import "remote_unittest_helper.dart";
const TERMINATION_MESSAGE = -1;
const N = 100;
const ISOLATES = 20;
-main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
// Test is really slow in debug builds of the VM.
- SimpleConfiguration configuration = unittestConfiguration;
+ var configuration = unittestConfiguration;
configuration.timeout = const Duration(seconds: 480);
test("Render Mandelbrot in parallel", () {
final state = new MandelbrotState();
diff --git a/tests/isolate/message2_test.dart b/tests/isolate/message2_test.dart
index 334ae04..eaa5c956 100644
--- a/tests/isolate/message2_test.dart
+++ b/tests/isolate/message2_test.dart
@@ -7,7 +7,8 @@
library Message2Test;
import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import "remote_unittest_helper.dart";
// ---------------------------------------------------------------------------
// Message passing test 2.
@@ -55,7 +56,8 @@
replyPort.send(port.sendPort);
}
-main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
test("map is equal after it is sent back and forth", () {
ReceivePort port = new ReceivePort();
Isolate.spawn(pingPong, port.sendPort);
diff --git a/tests/isolate/message_test.dart b/tests/isolate/message_test.dart
index de252c5..ead8cfe 100644
--- a/tests/isolate/message_test.dart
+++ b/tests/isolate/message_test.dart
@@ -8,7 +8,8 @@
library MessageTest;
import 'dart:isolate';
import 'dart:async';
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import "remote_unittest_helper.dart";
// ---------------------------------------------------------------------------
// Message passing test.
@@ -93,7 +94,8 @@
return receivePort.first;
}
-main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
test("send objects and receive them back", () {
ReceivePort port = new ReceivePort();
Isolate.spawn(pingPong, port.sendPort);
diff --git a/tests/isolate/mint_maker_test.dart b/tests/isolate/mint_maker_test.dart
index 3607df4..60b430f 100644
--- a/tests/isolate/mint_maker_test.dart
+++ b/tests/isolate/mint_maker_test.dart
@@ -5,7 +5,8 @@
library MintMakerTest;
import 'dart:async';
import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import "remote_unittest_helper.dart";
class Mint {
Map<SendPort, Purse> _registry;
@@ -154,7 +155,8 @@
}));
}
-main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
test("creating purse, deposit, and query balance", () {
MintMakerWrapper.create().then(expectAsync1((mintMaker) {
mintMaker.makeMint(expectAsync1((MintWrapper mint) {
diff --git a/tests/isolate/nested_spawn2_test.dart b/tests/isolate/nested_spawn2_test.dart
index 0c477dd..ea6331e 100644
--- a/tests/isolate/nested_spawn2_test.dart
+++ b/tests/isolate/nested_spawn2_test.dart
@@ -8,7 +8,8 @@
library NestedSpawn2Test;
import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import "remote_unittest_helper.dart";
void isolateA(SendPort init) {
ReceivePort port = new ReceivePort();
@@ -51,7 +52,8 @@
}));
}
-main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
test("spawned isolate can spawn other isolates", () {
ReceivePort init = new ReceivePort();
Isolate.spawn(isolateA, init.sendPort);
diff --git a/tests/isolate/nested_spawn_test.dart b/tests/isolate/nested_spawn_test.dart
index 51157f3..0dc35a0 100644
--- a/tests/isolate/nested_spawn_test.dart
+++ b/tests/isolate/nested_spawn_test.dart
@@ -6,7 +6,8 @@
library NestedSpawnTest;
import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import "remote_unittest_helper.dart";
void isolateA(message) {
message.add("isolateA");
@@ -18,7 +19,8 @@
message[0].send(message);
}
-main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
test("spawned isolates can spawn nested isolates", () {
ReceivePort port = new ReceivePort();
Isolate.spawn(isolateA, [port.sendPort, "main"]);
diff --git a/tests/isolate/raw_port_test.dart b/tests/isolate/raw_port_test.dart
index 8e334ca..a7cd2fb 100644
--- a/tests/isolate/raw_port_test.dart
+++ b/tests/isolate/raw_port_test.dart
@@ -6,17 +6,22 @@
library raw_port_test;
import 'dart:isolate';
-import 'dart:async';
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import 'remote_unittest_helper.dart';
-void remote(SendPort port) { port.send("reply"); }
+void remote(SendPort port) {
+ port.send("reply");
+}
+
void remote2(SendPort port) {
port.send("reply 1");
port.send("reply 2");
}
-main() {
+main([args, port]) {
+ if (testRemote(main, port)) return;
+
test("raw receive", () {
RawReceivePort port = new RawReceivePort();
Isolate.spawn(remote, port.sendPort);
@@ -25,6 +30,7 @@
port.close();
});
});
+
test("raw receive twice - change handler", () {
RawReceivePort port = new RawReceivePort();
Isolate.spawn(remote2, port.sendPort);
@@ -36,6 +42,7 @@
});
});
});
+
test("from-raw-port", () {
RawReceivePort rawPort = new RawReceivePort();
Isolate.spawn(remote, rawPort.sendPort);
@@ -53,5 +60,4 @@
onDone: expectAsync0((){}));
});
});
-
}
diff --git a/tests/isolate/remote_unittest_helper.dart b/tests/isolate/remote_unittest_helper.dart
new file mode 100644
index 0000000..edc90ef
--- /dev/null
+++ b/tests/isolate/remote_unittest_helper.dart
@@ -0,0 +1,134 @@
+// 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.
+
+// Helper functions and classes for running a set of unittests in a
+// remote isolate.
+// Used to test Isolate.spawn because dartium/drt does not allow it in the DOM
+// isolate.
+
+import "dart:isolate";
+import "package:unittest/unittest.dart";
+@MirrorsUsed(symbols: "main", targets: "main", override: "*")
+import "dart:mirrors";
+
+/**
+ * Use this function at the beginning of the main method:
+ *
+ * void main([args, port]) {
+ * if (testRemote(main, port)) return;
+ * // the usual test.
+ * }
+ *
+ * Remember to import unittest using the URI `package:inittest/unittest.dart`.
+ * Otherwise it won't be sharing the `unittestConfiguration` with this library,
+ * and the override set below won't work.
+ *
+ * Returns `true` if the tests are being run remotely, and
+ * `false` if the tests should be run locally.
+ */
+bool testRemote(Function main, SendPort port) {
+ if (port != null) {
+ unittestConfiguration = new RemoteConfiguration(port);
+ return false;
+ }
+ var testResponses = new Map<String, List>();
+
+
+ ClosureMirror closure = reflect(main);
+ LibraryMirror library = closure.function.owner;
+
+ var receivePort = new ReceivePort();
+ void remoteAction(message) {
+ switch (message[0]) {
+ case "testStart":
+ String name = message[1];
+ testResponses[name] = null;
+ break;
+ case "testResult":
+ case "testResultChanged":
+ String name = message[1];
+ testResponses[name] = message;
+ break;
+ case "logMessage":
+ break; // Ignore.
+ case "summary":
+ throw message[1]; // Uncaught error.
+ case "done":
+ receivePort.close();
+ _simulateTests(testResponses);
+ break;
+ }
+ }
+ try {
+ Isolate.spawnUri(library.uri, null, receivePort.sendPort);
+ receivePort.listen(remoteAction);
+ return true;
+ } catch (e) {
+ // spawnUri is only supported by dart2js if web workers are available.
+ // If the spawnUri fails, run the tests locally instead, since we are
+ // not in a browser anyway.
+ //
+ // That is, we assume that either Isolate.spawn or Isolate.spawnUri must
+ // work, so if spawnUri doesn't work, we can run the tests directly.
+ receivePort.close();
+ return false;
+ }
+}
+
+class RemoteConfiguration implements Configuration {
+ final SendPort _port;
+ Duration timeout = const Duration(minutes: 2);
+
+ RemoteConfiguration(this._port);
+
+ bool get autoStart => true;
+
+ void onInit() { }
+
+ void onStart() { }
+
+ void onTestStart(TestCase testCase) {
+ _port.send(["testStart", testCase.description]);
+ }
+
+ void onTestResult(TestCase testCase) {
+ _port.send(["testResult", testCase.description,
+ testCase.result, testCase.message]);
+ }
+
+ void onTestResultChanged(TestCase testCase) {
+ _port.send(["testResultChanged", testCase.description,
+ testCase.result, testCase.message]);
+ }
+
+ void onLogMessage(TestCase testCase, String message) {
+ _port.send(["logMessage", testCase.description, message]);
+ }
+
+ void onDone(bool success) {
+ _port.send(["done", success]);
+ }
+
+ void onSummary(int passed, int failed, int errors, List<TestCase> results,
+ String uncaughtError) {
+ if (uncaughtError != null) {
+ _port.send(["summary", uncaughtError]);
+ }
+ }
+}
+
+void _simulateTests(Map<String, List> responses) {
+ // Start all unit tests in the same event.
+ responses.forEach((name, response) {
+ test(name, () {
+ var result = response[2];
+ var message = response[3];
+ if (result == FAIL) {
+ fail(message);
+ } else if (result == ERROR) {
+ throw message;
+ }
+ });
+ });
+}
diff --git a/tests/isolate/request_reply_test.dart b/tests/isolate/request_reply_test.dart
index f70fb5a..713f7bb 100644
--- a/tests/isolate/request_reply_test.dart
+++ b/tests/isolate/request_reply_test.dart
@@ -5,7 +5,8 @@
library RequestReplyTest;
import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import "remote_unittest_helper.dart";
void entry(initPort) {
ReceivePort port = new ReceivePort();
@@ -18,7 +19,8 @@
});
}
-void main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
test("send", () {
ReceivePort init = new ReceivePort();
Isolate.spawn(entry, init.sendPort);
diff --git a/tests/isolate/simple_message_test.dart b/tests/isolate/simple_message_test.dart
new file mode 100644
index 0000000..8338bd6
--- /dev/null
+++ b/tests/isolate/simple_message_test.dart
@@ -0,0 +1,26 @@
+// 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.
+
+// Dart test program for testing that isolates are spawned.
+
+library IsolateNegativeTest;
+import "package:expect/expect.dart";
+import 'dart:isolate';
+import "package:async_helper/async_helper.dart";
+
+void entry(SendPort replyTo) {
+ var message = "foo";
+ message = "bar"; /// 01: runtime error
+ replyTo.send(message);
+}
+
+main() {
+ asyncStart();
+ ReceivePort response = new ReceivePort();
+ Isolate.spawn(entry, response.sendPort);
+ response.first.then((message) {
+ Expect.equals("foo", message);
+ asyncEnd();
+ });
+}
diff --git a/tests/isolate/spawn_function_custom_class_test.dart b/tests/isolate/spawn_function_custom_class_test.dart
index 9e83b6f..75c992d 100644
--- a/tests/isolate/spawn_function_custom_class_test.dart
+++ b/tests/isolate/spawn_function_custom_class_test.dart
@@ -9,7 +9,8 @@
library spawn_tests;
import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import "remote_unittest_helper.dart";
class MyClass {
var myVar = 'there';
@@ -24,7 +25,8 @@
reply.send('re: ${new MyClass().myFunc(msg)}');
}
-main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
test('message - reply chain', () {
ReceivePort port = new ReceivePort();
Isolate.spawn(child, ['hi', port.sendPort]);
diff --git a/tests/isolate/spawn_function_negative_test.dart b/tests/isolate/spawn_function_negative_test.dart
deleted file mode 100644
index 1806312..0000000
--- a/tests/isolate/spawn_function_negative_test.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-// 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.
-
-// Negative test to make sure that we are reaching all assertions.
-library spawn_tests;
-import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
-
-child(args) {
- var msg = args[0];
- var reply = args[1];
- reply.send('re: $msg');
-}
-
-main() {
- test('message - reply chain', () {
- ReceivePort port = new ReceivePort();
- Isolate.spawn(child, ['hi', port.sendPort]);
- port.listen(expectAsync1((msg) {
- port.close();
- expect(msg, equals('re: hello')); // should be hi, not hello
- }));
- });
-}
diff --git a/tests/isolate/spawn_function_test.dart b/tests/isolate/spawn_function_test.dart
index a452477..54cfb5a 100644
--- a/tests/isolate/spawn_function_test.dart
+++ b/tests/isolate/spawn_function_test.dart
@@ -5,7 +5,8 @@
// Example of spawning an isolate from a function.
library spawn_tests;
import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import "remote_unittest_helper.dart";
child(args) {
var msg = args[0];
@@ -13,7 +14,8 @@
reply.send('re: $msg');
}
-main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
test('message - reply chain', () {
ReceivePort port = new ReceivePort();
Isolate.spawn(child, ['hi', port.sendPort]);
diff --git a/tests/isolate/spawn_uri_vm_negative_test.dart b/tests/isolate/spawn_uri_vm_negative_test.dart
deleted file mode 100644
index 9bc6111..0000000
--- a/tests/isolate/spawn_uri_vm_negative_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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.
-
-// Negative test to make sure that we are reaching all assertions.
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=spawn_uri_child_isolate.dart
-library spawn_tests;
-import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
-
-main() {
- test('isolate fromUri - negative test', () {
- ReceivePort port = new ReceivePort();
- port.first.then(expectAsync1((msg) {
- expect(msg, equals('re: hello')); // should be hi, not hello
- }));
-
- Isolate.spawnUri(Uri.parse('spawn_uri_child_isolate.dart'),
- ['hi'], port.sendPort);
- });
-}
diff --git a/tests/isolate/stacktrace_message_test.dart b/tests/isolate/stacktrace_message_test.dart
index 56ec95f..c22fa01 100644
--- a/tests/isolate/stacktrace_message_test.dart
+++ b/tests/isolate/stacktrace_message_test.dart
@@ -3,12 +3,17 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:isolate';
+import "package:unittest/unittest.dart";
+import "remote_unittest_helper.dart";
-main() {
- ReceivePort reply = new ReceivePort();
- Isolate.spawn(runTest, reply.sendPort);
- reply.first.then((StackTrace stack) {
- print(stack);
+void main([args, port]) {
+ if (testRemote(main, port)) return;
+ test("stacktrace_message", () {
+ ReceivePort reply = new ReceivePort();
+ Isolate.spawn(runTest, reply.sendPort);
+ reply.first.then(expectAsync1((StackTrace stack) {
+ print(stack);
+ }));
});
}
diff --git a/tests/isolate/static_function_test.dart b/tests/isolate/static_function_test.dart
index d5745cc..db0beba 100644
--- a/tests/isolate/static_function_test.dart
+++ b/tests/isolate/static_function_test.dart
@@ -8,7 +8,8 @@
import 'dart:isolate';
import 'dart:async';
import 'static_function_lib.dart' as lib;
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import 'remote_unittest_helper.dart';
void function(SendPort port) { port.send("TOP"); }
void _function(SendPort port) { port.send("_TOP"); }
@@ -75,7 +76,8 @@
});
}
-void main() {
+void main([args, port]) {
+ if (testRemote(main, port)) return;
// Sanity check.
spawnTest("function", function, "TOP");
spawnTest("_function", _function, "_TOP");
diff --git a/tests/isolate/unresolved_ports_negative_test.dart b/tests/isolate/unresolved_ports_negative_test.dart
deleted file mode 100644
index 3007645..0000000
--- a/tests/isolate/unresolved_ports_negative_test.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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.
-
-// negative test to ensure that unresolved_ports works.
-library unresolved_ports_negative;
-import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
-import 'unresolved_ports_test.dart' as positive_test;
-
-main() {
- positive_test.baseTest(failForNegativeTest: true);
-}
diff --git a/tests/isolate/unresolved_ports_test.dart b/tests/isolate/unresolved_ports_test.dart
index c7fdb41..8fe11c9 100644
--- a/tests/isolate/unresolved_ports_test.dart
+++ b/tests/isolate/unresolved_ports_test.dart
@@ -6,7 +6,8 @@
library unresolved_ports;
import 'dart:async';
import 'dart:isolate';
-import '../../pkg/unittest/lib/unittest.dart';
+import 'package:unittest/unittest.dart';
+import "remote_unittest_helper.dart";
// This test does the following:
// - main spawns two isolates: 'tim' and 'beth'
@@ -72,4 +73,7 @@
});
}
-main() => baseTest();
+void main([args, port]) {
+ if (testRemote(main, port)) return;
+ baseTest();
+}
diff --git a/tests/language/call_type_literal_test.dart b/tests/language/call_type_literal_test.dart
new file mode 100644
index 0000000..d24e778
--- /dev/null
+++ b/tests/language/call_type_literal_test.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class C { void a() {} }
+
+void main() {
+ Expect.throws(() => C().a(), (e) => e is NoSuchMethodError); /// 01: static type warning
+}
diff --git a/tests/language/function_subtype2_test.dart b/tests/language/function_subtype2_test.dart
new file mode 100644
index 0000000..861b465
--- /dev/null
+++ b/tests/language/function_subtype2_test.dart
@@ -0,0 +1,140 @@
+// 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.
+// Dart test program for constructors and initializers.
+
+// Check function subtyping for optional parameters.
+
+import 'package:expect/expect.dart';
+
+typedef void T1(int a, int b);
+typedef void T2(int a, [int b]);
+typedef void T3([int a, int b]);
+typedef void T4(int a, [int b, int c]);
+typedef void T5([int a, int b, int c]);
+
+class C<T, S, U> {
+ void m1(T a, S b) {}
+ void m2(T a, [S b]) {}
+ void m3([T a, S b]) {}
+ void m4(T a, [S b, U c]) {}
+ void m5([T a, S b, U c]) {}
+}
+
+main() {
+ var c1 = new C<int, int, int>();
+ Expect.isTrue(c1.m1 is T1, "(int,int)->void is (int,int)->void");
+ Expect.isFalse(c1.m1 is T2, "(int,int)->void is not (int,[int])->void");
+ Expect.isFalse(c1.m1 is T3, "(int,int)->void is not ([int,int])->void");
+ Expect.isFalse(c1.m1 is T4, "(int,int)->void is not (int,[int,int])->void");
+ Expect.isFalse(c1.m1 is T5, "(int,int)->void is not ([int,int,int])->void");
+
+ Expect.isTrue(c1.m2 is T1, "(int,[int])->void is (int,int)->void");
+ Expect.isTrue(c1.m2 is T2, "(int,[int])->void is (int,[int])->void");
+ Expect.isFalse(c1.m2 is T3, "(int,[int])->void is not ([int,int])->void");
+ Expect.isFalse(c1.m2 is T4, "(int,[int])->void is not (int,[int,int])->void");
+ Expect.isFalse(c1.m2 is T5, "(int,[int])->void is not ([int,int,int])->void");
+
+ Expect.isTrue(c1.m3 is T1, "([int,int])->void is (int,int)->void");
+ Expect.isTrue(c1.m3 is T2, "([int,int])->void is (int,[int])->void");
+ Expect.isTrue(c1.m3 is T3, "([int,int])->void is ([int,int])->void");
+ Expect.isFalse(c1.m3 is T4, "([int,int])->void is not (int,[int,int])->void");
+ Expect.isFalse(c1.m3 is T5, "([int,int])->void is not ([int,int,int])->void");
+
+ Expect.isTrue(c1.m4 is T1, "(int,[int,int])->void is (int,int)->void");
+ Expect.isTrue(c1.m4 is T2, "(int,[int,int])->void is (int,[int])->void");
+ Expect.isFalse(c1.m4 is T3, "(int,[int,int])->void is not ([int,int])->void");
+ Expect.isTrue(c1.m4 is T4, "(int,[int,int])->void is (int,[int,int])->void");
+ Expect.isFalse(c1.m4 is T5,
+ "(int,[int,int])->void is not ([int,int,int])->void");
+
+ Expect.isTrue(c1.m5 is T1, "([int,int,int])->void is (int,int)->void");
+ Expect.isTrue(c1.m5 is T2, "([int,int,int])->void is (int,[int])->void");
+ Expect.isTrue(c1.m5 is T3, "([int,int,int])->void is ([int,int])->void");
+ Expect.isTrue(c1.m5 is T4, "([int,int,int])->void is (int,[int,int])->void");
+ Expect.isTrue(c1.m5 is T5, "([int,int,int])->void is ([int,int,int])->void");
+
+ var c2 = new C<int, double, int>();
+ Expect.isFalse(c2.m1 is T1, "(int,double)->void is not (int,int)->void");
+ Expect.isFalse(c2.m1 is T2,
+ "(int,double)->void is not not (int,[int])->void");
+ Expect.isFalse(c2.m1 is T3, "(int,double)->void is not ([int,int])->void");
+ Expect.isFalse(c2.m1 is T4,
+ "(int,double)->void is not (int,[int,int])->void");
+ Expect.isFalse(c2.m1 is T5,
+ "(int,double)->void is not ([int,int,int])->void");
+
+ Expect.isFalse(c2.m2 is T1, "(int,[double])->void is not (int,int)->void");
+ Expect.isFalse(c2.m2 is T2, "(int,[double])->void is not (int,[int])->void");
+ Expect.isFalse(c2.m2 is T3, "(int,[double])->void is not ([int,int])->void");
+ Expect.isFalse(c2.m2 is T4,
+ "(int,[double])->void is not (int,[int,int])->void");
+ Expect.isFalse(c2.m2 is T5,
+ "(int,[double])->void is not ([int,int,int])->void");
+
+ Expect.isFalse(c2.m3 is T1, "([int,double])->void is not (int,int)->void");
+ Expect.isFalse(c2.m3 is T2, "([int,double])->void is not (int,[int])->void");
+ Expect.isFalse(c2.m3 is T3, "([int,double])->void is not ([int,int])->void");
+ Expect.isFalse(c2.m3 is T4,
+ "([int,double])->void is not (int,[int,int])->void");
+ Expect.isFalse(c2.m3 is T5,
+ "([int,double])->void is not ([int,int,int])->void");
+
+ Expect.isFalse(c2.m4 is T1,
+ "(int,[double,int])->void is not (int,int)->void");
+ Expect.isFalse(c2.m4 is T2,
+ "(int,[double,int])->void is not (int,[int])->void");
+ Expect.isFalse(c2.m4 is T3,
+ "(int,[double,int])->void is not ([int,int])->void");
+ Expect.isFalse(c2.m4 is T4,
+ "(int,[double,int])->void is (int,[int,int])->void");
+ Expect.isFalse(c2.m4 is T5,
+ "(int,[double,int])->void is ([int,int,int])->void");
+
+ Expect.isFalse(c2.m5 is T1,
+ "([int,double,int])->void is not (int,int)->void");
+ Expect.isFalse(c2.m5 is T2,
+ "([int,double,int])->void is not (int,[int])->void");
+ Expect.isFalse(c2.m5 is T3,
+ "([int,double,int])->void is not ([int,int])->void");
+ Expect.isFalse(c2.m5 is T4,
+ "([int,double,int])->void is (int,[int,int])->void");
+ Expect.isFalse(c2.m5 is T5,
+ "([int,double,int])->void is ([int,int,int])->void");
+
+ var c3 = new C<int, int, double>();
+ Expect.isTrue(c3.m1 is T1, "(int,int)->void is (int,int)->void");
+ Expect.isFalse(c3.m1 is T2, "(int,int)->void is not (int,[int])->void");
+ Expect.isFalse(c3.m1 is T3, "(int,int)->void is not ([int,int])->void");
+ Expect.isFalse(c3.m1 is T4, "(int,int)->void is not (int,[int,int])->void");
+ Expect.isFalse(c3.m1 is T5, "(int,int)->void is not ([int,int,int])->void");
+
+ Expect.isTrue(c3.m2 is T1, "(int,[int])->void is (int,int)->void");
+ Expect.isTrue(c3.m2 is T2, "(int,[int])->void is (int,[int])->void");
+ Expect.isFalse(c3.m2 is T3, "(int,[int])->void is not ([int,int])->void");
+ Expect.isFalse(c3.m2 is T4, "(int,[int])->void is not (int,[int,int])->void");
+ Expect.isFalse(c3.m2 is T5, "(int,[int])->void is not ([int,int,int])->void");
+
+ Expect.isTrue(c3.m3 is T1, "([int,int])->void is (int,int)->void");
+ Expect.isTrue(c3.m3 is T2, "([int,int])->void is (int,[int])->void");
+ Expect.isTrue(c3.m3 is T3, "([int,int])->void is ([int,int])->void");
+ Expect.isFalse(c3.m3 is T4, "([int,int])->void is not (int,[int,int])->void");
+ Expect.isFalse(c3.m3 is T5, "([int,int])->void is not ([int,int,int])->void");
+
+ Expect.isTrue(c3.m4 is T1, "(int,[int,double])->void is (int,int)->void");
+ Expect.isTrue(c3.m4 is T2, "(int,[int,double])->void is (int,[int])->void");
+ Expect.isFalse(c3.m4 is T3,
+ "(int,[int,double])->void is not ([int,int])->void");
+ Expect.isFalse(c3.m4 is T4,
+ "(int,[int,double])->void is (int,[int,int])->void");
+ Expect.isFalse(c3.m4 is T5,
+ "(int,[int,double])->void is ([int,int,int])->void");
+
+ Expect.isTrue(c3.m5 is T1, "([int,int,double])->void is (int,int)->void");
+ Expect.isTrue(c3.m5 is T2, "([int,int,double])->void is (int,[int])->void");
+ Expect.isTrue(c3.m5 is T3, "([int,int,double])->void is ([int,int])->void");
+ Expect.isFalse(c3.m5 is T4,
+ "([int,int,double])->void is (int,[int,int])->void");
+ Expect.isFalse(c3.m5 is T5,
+ "([int,int,double])->void is ([int,int,int])->void");
+}
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index 1ce4a22..aecedf1 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -9,9 +9,10 @@
# Test issue 12694 (was analyzer issue), (1) when "abstract" is import prefix using it as type is warning; (2) currently analyzer resolves prefix as field (don't ask)
built_in_identifier_prefix_test: CompileTimeError # Issue 12694
-# TBD: these look like bad tests, no issue number
+# Issue 15315
class_literal_test: fail
constructor_call_as_function_test/01: fail
+call_type_literal_test/01: fail
# TBF: we should check conflicts not only for methods, but for accessors too
override_field_test/03: fail
@@ -151,8 +152,22 @@
# test issue 14736, It is a static warning if a class C declares an instance method named n and has a setter named n=.
setter4_test: StaticWarning
-
-
+# test issue 15060
+least_upper_bound_test/23: StaticWarning # Issue 15060
+least_upper_bound_test/24: StaticWarning # Issue 15060
+least_upper_bound_test/25: MissingStaticWarning # Issue 15060
+least_upper_bound_test/26: MissingStaticWarning # Issue 15060
+least_upper_bound_test/29: StaticWarning # Issue 15060
+least_upper_bound_test/30: StaticWarning # Issue 15060
+least_upper_bound_test/31: MissingStaticWarning # Issue 15060
+least_upper_bound_expansive_test/02: MissingStaticWarning # Issue 15060
+least_upper_bound_expansive_test/04: MissingStaticWarning # Issue 15060
+least_upper_bound_expansive_test/05: MissingStaticWarning # Issue 15060
+least_upper_bound_expansive_test/06: MissingStaticWarning # Issue 15060
+least_upper_bound_expansive_test/08: MissingStaticWarning # Issue 15060
+least_upper_bound_expansive_test/10: MissingStaticWarning # Issue 15060
+least_upper_bound_expansive_test/11: MissingStaticWarning # Issue 15060
+least_upper_bound_expansive_test/12: MissingStaticWarning # Issue 15060
abstract_exact_selector_test: StaticWarning
abstract_getter_test: StaticWarning
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 42c7dd2..408d7a0 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -134,6 +134,7 @@
mixin_mixin7_test: RuntimeError # Issue 13109.
mixin_regress_13688_test: RuntimeError # Issue 13109.
modulo_test: RuntimeError # Issue 15246
+truncdiv_test: RuntimeError # Issue 15246
# Compilation errors.
const_var_test: CompileTimeError # Issue 12793
@@ -153,6 +154,19 @@
null_test/none: RuntimeError # Issue 12482
+[ $compiler == dart2js || $compiler == dart2dart ]
+
+function_type_alias9_test/00: Crash # Issue 15237
+string_interpolation9_test/11: Crash # Issue 15237
+string_interpolation9_test/12: Crash # Issue 15237
+string_interpolation9_test/13: Crash # Issue 15237
+string_interpolation9_test/16: Crash # Issue 15237
+string_interpolation9_test/17: Crash # Issue 15237
+string_interpolation9_test/18: Crash # Issue 15237
+mixin_invalid_inheritance2_test/03: Crash # Issue 15237
+
+[ ($compiler == dart2js || $compiler == dart2dart) && $checked ]
+cyclic_typedef_test/07: Crash # Issue 15237
[ $compiler == dart2js && $runtime == none ]
*: Fail, Pass # TODO(ahe): Triage these tests.
diff --git a/tests/language/least_upper_bound_expansive_test.dart b/tests/language/least_upper_bound_expansive_test.dart
new file mode 100644
index 0000000..704b2a3
--- /dev/null
+++ b/tests/language/least_upper_bound_expansive_test.dart
@@ -0,0 +1,101 @@
+// 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.
+
+// Test least upper bound through type checking of conditionals.
+
+class N<T> {
+ T get n => null;
+}
+
+class C1<T> extends N<N<C1<T>>> {
+ T get c1 => null;
+}
+
+class C2<T> extends N<N<C2<N<C2<T>>>>> {
+ T get c2 => null;
+}
+
+/**
+ * Test that we don't try to find the least upper bound by applying the
+ * algorithm for finding the most specific common declaration recursively on
+ * type arguments.
+ *
+ * For C1<int> and N<C1<String>> this would result in this infinite chain of
+ * computations:
+ *
+ * lub(C1<int>, N<C1<String>>) = lub(N<N<C1<int>>>, N<C1<String>>)
+ * =>
+ * lub(N<C1<int>>, C1<String>) = lub(N<C1<int>>, N<N<C1<String>>>)
+ * =>
+ * lub(C1<int>, N<C1<String>>) = lub(N<N<C1<int>>>, N<C1<String>>>)
+ * => ...
+ */
+void testC1(bool z, C1<int> a, N<C1<String>> b) {
+ if (z) {
+ // The least upper bound of C1<int> and N<C1<String>> is Object since the
+ // supertypes are
+ // {C1<int>, N<N<C1<int>>>, Object} for C1<int> and
+ // {N<C1<String>>, Object} for N<C1<String>> and
+ // Object is the most specific type in the intersection of the supertypes.
+
+ // Is least upper bound dynamic?
+ (z ? a : b).z; /// 01: static type warning
+ // Is least upper bound N<...> ?
+ (z ? a : b).n; /// 02: static type warning
+ // Is least upper bound C1<...> ?
+ (z ? a : b).c1; /// 03: static type warning
+ // Is least upper bound N<dynamic> ?
+ (z ? a : b).n.z; /// 04: static type warning
+ // Is least upper bound N<N<...>> ?
+ (z ? a : b).n.n; /// 05: static type warning
+ // Is least upper bound N<C1<...>> ?
+ (z ? a : b).n.c1; /// 06: static type warning
+ }
+}
+
+/**
+ * Test that we don't try to find the least upper bound by applying the
+ * algorithm for finding the most specific common declaration recursively on
+ * type arguments.
+ *
+ * For C1<int> and N<C1<String>> this would result in this infinite and
+ * expanding chain of computations:
+ *
+ * lub(C2<int>, N<C2<String>>) = lub(N<N<C2<N<C2<int>>>>>, N<C2<String>>)
+ * =>
+ * lub(N<C2<N<C2<int>>>>, C2<String>) =
+ * lub(N<C2<N<C2<int>>>>, N<N<C2<N<C2<String>>>>>)
+ * =>
+ * lub(C2<N<C2<int>>>, N<C2<N<C2<String>>>>) =
+ * lub(N<N<C2<N<C2<int>>>>>, N<C2<N<C2<String>>>>>)
+ * => ...
+ */
+
+void testC2(bool z, C2<int> a, N<C2<String>> b) {
+ if (z) {
+ // The least upper bound of C2<int> and N<C2<String>> is Object since the
+ // supertypes are
+ // {C2<int>, N<N<C2<N<C2<int>>>>>, Object} for C1<int> and
+ // {N<C2<String>>, Object} for N<C1<String>> and
+ // Object is the most specific type in the intersection of the supertypes.
+
+ // Is least upper bound dynamic?
+ (z ? a : b).z; /// 07: static type warning
+ // Is least upper bound N<...> ?
+ (z ? a : b).n; /// 08: static type warning
+ // Is least upper bound C2<...> ?
+ (z ? a : b).c2; /// 09: static type warning
+ // Is least upper bound N<dynamic> ?
+ (z ? a : b).n.z; /// 10: static type warning
+ // Is least upper bound N<N<...>> ?
+ (z ? a : b).n.n; /// 11: static type warning
+ // Is least upper bound N<C2<...>> ?
+ (z ? a : b).n.c2; /// 12: static type warning
+ }
+}
+
+void main() {
+ testC1(false, null, null);
+ testC2(false, null, null);
+}
\ No newline at end of file
diff --git a/tests/language/least_upper_bound_test.dart b/tests/language/least_upper_bound_test.dart
new file mode 100644
index 0000000..410671a
--- /dev/null
+++ b/tests/language/least_upper_bound_test.dart
@@ -0,0 +1,103 @@
+// 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.
+
+// Test least upper bound through type checking of conditionals.
+
+class A {
+ var a;
+}
+class B {
+ var b;
+}
+class C extends B {
+ var c;
+}
+class D extends B {
+ var d;
+}
+
+class E<T> {
+ T e;
+
+ E(this.e);
+}
+class F<T> extends E<T> {
+ T f;
+
+ F(T f) : this.f = f, super(f);
+}
+
+void main() {
+ testAB(new A(), new B());
+ testBC(new C(), new C());
+ testCD(new C(), new D());
+ testEE(new F<C>(new C()), new F<C>(new C()));
+ testEF(new F<C>(new C()), new F<C>(new C()));
+}
+
+void testAB(A a, B b) {
+ A r1 = true ? a : b; /// 01: ok
+ B r2 = false ? a : b; /// 02: ok
+ (true ? a : b).a = 0; /// 03: static type warning
+ (false ? a : b).b = 0; /// 04: static type warning
+ var c = new C();
+ (true ? a : c).a = 0; /// 05: ok
+ (false ? c : b).b = 0; /// 06: ok
+}
+
+void testBC(B b, C c) {
+ B r1 = true ? b : c; /// 07: ok
+ C r2 = false ? b : c; /// 08: ok
+ (true ? b : c).b = 0; /// 09: ok
+ (false ? b : c).c = 0; /// 10: static type warning
+ var a = null;
+ (true ? b : a).b = 0; /// 11: ok
+ (false ? a : b).c = 0; /// 12: ok
+ (true ? c : a).b = 0; /// 13: ok
+ (false ? a : c).c = 0; /// 14: ok
+}
+
+void testCD(C c, D d) {
+ C r1 = true ? c : d; /// 15: ok
+ D r2 = false ? c : d; /// 16: ok
+ (true ? c : d).b = 0; /// 17: ok
+ (false ? c : d).b = 0; /// 18: ok
+ (true ? c : d).c = 0; /// 19: static type warning
+ (false ? c : d).d = 0; /// 20: static type warning
+}
+
+void testEE(E<B> e, E<C> f) {
+ // The least upper bound of E<B> and E<C> is Object since the supertypes are
+ // {E<B>, Object} for E<B> and
+ // {E<C>, Object} for E<C> and
+ // Object is the most specific type in the intersection of the supertypes.
+ E<B> r1 = true ? e : f; /// 21: ok
+ F<C> r2 = false ? e : f; /// 22: ok
+ try {
+ A r3 = true ? e : f; /// 23: ok
+ B r4 = false ? e : f; /// 24: ok
+ } catch (e) {
+ // Type error in checked mode.
+ }
+ (true ? e : f).e = null; /// 25: static type warning
+ (false ? e : f).e = null; /// 26: static type warning
+}
+
+void testEF(E<B> e, F<C> f) {
+ // The least upper bound of E<B> and F<C> is Object since the supertypes are
+ // {E<B>, Object} for E<B> and
+ // {F<C>, E<C>, Object} for F<C> and
+ // Object is the most specific type in the intersection of the supertypes.
+ E<B> r1 = true ? e : f; /// 27: ok
+ F<C> r2 = false ? e : f; /// 28: ok
+ try {
+ A r3 = true ? e : f; /// 29: ok
+ B r4 = false ? e : f; /// 30: ok
+ } catch (e) {
+ // Type error in checked mode.
+ }
+ var r5;
+ r5 = (true ? e : f).e; /// 31: static type warning
+ r5 = (false ? e : f).f; /// 32: static type warning
+}
\ No newline at end of file
diff --git a/tests/language/modulo_test.dart b/tests/language/modulo_test.dart
index 939d7c0..6dc22cf 100644
--- a/tests/language/modulo_test.dart
+++ b/tests/language/modulo_test.dart
@@ -26,7 +26,18 @@
}
Expect.equals((i ~/ 10) + (i ~/ 10) + (i % 10), threeOp(i));
Expect.equals((i ~/ 10) + (i ~/ 12) + (i % 10) + (i % 12), fourOp(i));
+
+ // Zero test is done outside the loop.
+ if (i < 0) {
+ Expect.equals(i % -i, foo2(i));
+ Expect.equals(i ~/ -i + i % -i, fooTwo2(i));
+ } else if (i > 0) {
+ Expect.equals(i % i, foo2(i));
+ Expect.equals(i ~/ i + i % i, fooTwo2(i));
+ }
}
+ Expect.throws(() => foo2(0), (e) => e is IntegerDivisionByZeroException);
+ Expect.throws(() => fooTwo2(0), (e) => e is IntegerDivisionByZeroException);
}
foo(i) => i % 256; // This will get optimized to AND instruction.
@@ -61,4 +72,27 @@
var y0 = a % 10;
var y1 = a % 12;
return x0 + x1 + y0 + y1;
-}
\ No newline at end of file
+}
+
+foo2(i) {
+ // Make sure x has a range computed.
+ var x = 0;
+ if (i < 0) {
+ x = -i;
+ } else {
+ x = i;
+ }
+ return i % x;
+}
+
+
+fooTwo2(i) {
+ // Make sure x has a range computed.
+ var x = 0;
+ if (i < 0) {
+ x = -i;
+ } else {
+ x = i;
+ }
+ return i ~/ x + i % x;
+}
diff --git a/tests/language/switch8_test.dart b/tests/language/switch8_test.dart
new file mode 100644
index 0000000..fd3b5cc
--- /dev/null
+++ b/tests/language/switch8_test.dart
@@ -0,0 +1,16 @@
+// 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.
+
+// Regression test for dart2js that used to not generate code for
+// compile-time constants only seen in case expressions.
+
+class A {
+ const A();
+}
+
+main() {
+ switch (new List(1)[0]) {
+ case const A(): throw 'Test failed';
+ }
+}
diff --git a/tests/language/truncdiv_test.dart b/tests/language/truncdiv_test.dart
new file mode 100644
index 0000000..8a00c73
--- /dev/null
+++ b/tests/language/truncdiv_test.dart
@@ -0,0 +1,35 @@
+// 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.
+// Dart test optimization of modulo operator on Smi.
+// VMOptions=--optimization-counter-threshold=10 --no-use-osr
+
+import "package:expect/expect.dart";
+
+
+main() {
+ for (int i = -30; i < 30; i++) {
+ Expect.equals(i % 9, foo(i, 9));
+ // Zero test is done outside the loop.
+ if (i < 0) {
+ Expect.equals(i ~/ -i, foo2(i));
+ } else if (i > 0) {
+ Expect.equals(i ~/ i, foo2(i));
+ }
+ }
+ Expect.throws(() => foo(12, 0), (e) => e is IntegerDivisionByZeroException);
+ Expect.throws(() => foo2(0), (e) => e is IntegerDivisionByZeroException);
+}
+
+foo(i, x) => i % x;
+
+foo2(i) {
+ // Make sure x has a range computed.
+ var x = 0;
+ if (i < 0) {
+ x = -i;
+ } else {
+ x = i;
+ }
+ return i ~/ x;
+}
\ No newline at end of file
diff --git a/tests/language/type_promotion_closure_test.dart b/tests/language/type_promotion_closure_test.dart
index bb514da..5c59443 100644
--- a/tests/language/type_promotion_closure_test.dart
+++ b/tests/language/type_promotion_closure_test.dart
@@ -30,9 +30,11 @@
test1();
test2();
test3();
+ test3a();
test4();
test5();
test6();
+ test6a();
test7();
test8();
test9();
@@ -79,6 +81,22 @@
}
}
+void test3a() {
+ A a = new E();
+ void foo() {
+ a = new D();
+ }
+ if ((((a)) is B)) {
+ print(a.a);
+ print(a.b); /// 15: static type warning
+ void foo() {
+ a = new D();
+ }
+ print(a.a);
+ print(a.b); /// 16: static type warning
+ }
+}
+
void test4() {
A a = new E();
if (a is B) {
@@ -107,6 +125,16 @@
a = null;
}
+void test6a() {
+ A a = new E();
+ if (((a) is B)) {
+ func(() => a);
+ print(a.a);
+ print(a.b); /// 14: static type warning
+ }
+ a = null;
+}
+
void test7() {
A a = new E();
if (a is B && func(() => a)) {
diff --git a/tests/language/type_promotion_logical_and_test.dart b/tests/language/type_promotion_logical_and_test.dart
index 92a4758..1ee6296 100644
--- a/tests/language/type_promotion_logical_and_test.dart
+++ b/tests/language/type_promotion_logical_and_test.dart
@@ -33,6 +33,10 @@
b = a.d; /// 02: static type warning
a = null;
}
+ if ((((a) is D) && (b = (a).d))) {
+ b = a.d; /// 03: static type warning
+ a = null;
+ }
if (f(a = null) && a is D) {
b = a.d;
}
diff --git a/tests/language/type_promotion_parameter_test.dart b/tests/language/type_promotion_parameter_test.dart
index b390ede..6fe7ecc 100644
--- a/tests/language/type_promotion_parameter_test.dart
+++ b/tests/language/type_promotion_parameter_test.dart
@@ -190,8 +190,14 @@
}
if ((a is B)) {
print(a.a);
- print(a.b); /// 53: static type warning
+ print(a.b);
print(a.c); /// 54: static type warning
print(a.d); /// 55: static type warning
}
+ if ((a is B && (a) is C) && a is B) {
+ print(a.a);
+ print(a.b);
+ print(a.c);
+ print(a.d); /// 56: static type warning
+ }
}
diff --git a/tests/language/vm/if_conversion_vm_test.dart b/tests/language/vm/if_conversion_vm_test.dart
index 0837030..2d97d4d 100644
--- a/tests/language/vm/if_conversion_vm_test.dart
+++ b/tests/language/vm/if_conversion_vm_test.dart
@@ -42,6 +42,15 @@
f19(i) => i == 0 ? 0 : 0;
+f20(i) => i > 0 ? 0 : 1;
+f21(i) => i > 0 ? 2 : 3;
+f22(i) => i & 1 == 0 ? 0 : 1;
+f23(i) => i & 1 != 0 ? 1 : 0;
+
+f24(i) => i >= 0 ? 0 : 1;
+f25(i) => i < 0 ? 0 : 1;
+f26(i) => i <= 0 ? 0 : 1;
+
main() {
for (var i = 0; i < 20; i++) {
f1(i);
@@ -65,6 +74,13 @@
f17(true);
f18(true);
f19(i);
+ f20(i);
+ f21(i);
+ f22(i);
+ f23(i);
+ f24(i);
+ f25(i);
+ f26(i);
}
Expect.equals(0, f1(0));
@@ -117,4 +133,20 @@
Expect.equals(0, f19(0));
Expect.equals(0, f19(1));
+
+ Expect.equals(0, f20(123));
+ Expect.equals(2, f21(123));
+ Expect.equals(0, f22(122));
+ Expect.equals(1, f22(123));
+ Expect.equals(0, f23(122));
+ Expect.equals(1, f23(123));
+
+ Expect.equals(0, f24(0));
+ Expect.equals(1, f24(-1));
+
+ Expect.equals(0, f25(-1));
+ Expect.equals(1, f25(0));
+
+ Expect.equals(0, f26(0));
+ Expect.equals(1, f26(1));
}
diff --git a/tests/language/vm/optimized_testsmi_test.dart b/tests/language/vm/optimized_testsmi_test.dart
new file mode 100644
index 0000000..d538f20
--- /dev/null
+++ b/tests/language/vm/optimized_testsmi_test.dart
@@ -0,0 +1,30 @@
+// 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.
+// VMOptions=--optimization_counter_threshold=10
+
+// Test branch optimization for TestSmiInstr
+
+import "package:expect/expect.dart";
+
+test(bool b) {
+ var a = 0;
+ if (b) {
+ a++;
+ } else {
+ a += 2;
+ }
+ if (a & 1 == 0) {
+ return "even";
+ }
+ return "odd";
+}
+
+main() {
+ Expect.equals("odd", test(true));
+ Expect.equals("even", test(false));
+ for (var i=0; i<20; i++) test(false);
+ Expect.equals("odd", test(true));
+ Expect.equals("even", test(false));
+}
+
diff --git a/tests/lib/analyzer/analyze_library.status b/tests/lib/analyzer/analyze_library.status
index b3c0c30..d0eed98 100644
--- a/tests/lib/analyzer/analyze_library.status
+++ b/tests/lib/analyzer/analyze_library.status
@@ -27,7 +27,6 @@
lib/_internal/dartdoc/lib/src/client/dropdown: CompileTimeError
lib/_internal/dartdoc/lib/src/client/search: CompileTimeError
lib/_internal/dartdoc/lib/universe_serializer: CompileTimeError
-lib/_internal/pub/bin/pub: CompileTimeError
lib/_internal/pub/lib/src/barback: Pass, CompileTimeError # Pass necessary, since CompileTimeError is valid for everything in that directory (not only for src/barback.dart)
lib/_internal/pub/lib/src/barback/dart2js_transformer: CompileTimeError
lib/_internal/pub/lib/src/barback/dart_forwarding_transformer: CompileTimeError
@@ -41,43 +40,7 @@
lib/_internal/pub/lib/src/command/list_package_dirs: CompileTimeError
lib/_internal/pub/lib/src/command: Pass, CompileTimeError # Pass necessary, since CompileTimeError is valid for everything in that directory (not only for src/command.dart)
lib/_internal/pub/lib/src/command/uploader: CompileTimeError
-lib/_internal/pub/lib/src/dart: CompileTimeError
-lib/_internal/pub/lib/src/directory_tree: CompileTimeError
-lib/_internal/pub/lib/src/entrypoint: CompileTimeError
-lib/_internal/pub/lib/src/git: CompileTimeError
-lib/_internal/pub/lib/src/http: CompileTimeError
-lib/_internal/pub/lib/src/io: CompileTimeError
-lib/_internal/pub/lib/src/lock_file: CompileTimeError
-lib/_internal/pub/lib/src/log: CompileTimeError
-lib/_internal/pub/lib/src/oauth2: CompileTimeError
-lib/_internal/pub/lib/src/package: CompileTimeError
-lib/_internal/pub/lib/src/package_graph: CompileTimeError
-lib/_internal/pub/lib/src/pubspec: CompileTimeError
-lib/_internal/pub/lib/src/safe_http_server: CompileTimeError
-lib/_internal/pub/lib/src/sdk: CompileTimeError
-lib/_internal/pub/lib/src/solver/backtracking_solver: CompileTimeError
-lib/_internal/pub/lib/src/solver/version_solver: CompileTimeError
-lib/_internal/pub/lib/src/source: CompileTimeError
-lib/_internal/pub/lib/src/source/git: CompileTimeError
-lib/_internal/pub/lib/src/source/hosted: CompileTimeError
-lib/_internal/pub/lib/src/source/path: CompileTimeError
-lib/_internal/pub/lib/src/source_registry: CompileTimeError
-lib/_internal/pub/lib/src/system_cache: CompileTimeError
-lib/_internal/pub/lib/src/utils: CompileTimeError
-lib/_internal/pub/lib/src/validator/compiled_dartdoc: CompileTimeError
-lib/_internal/pub/lib/src/validator: CompileTimeError
-lib/_internal/pub/lib/src/validator/dependency: CompileTimeError
-lib/_internal/pub/lib/src/validator/dependency_override: CompileTimeError
-lib/_internal/pub/lib/src/validator/directory: CompileTimeError
-lib/_internal/pub/lib/src/validator/lib: CompileTimeError
-lib/_internal/pub/lib/src/validator/license: CompileTimeError
-lib/_internal/pub/lib/src/validator/name: CompileTimeError
-lib/_internal/pub/lib/src/validator/pubspec_field: CompileTimeError
-lib/_internal/pub/lib/src/validator/size: CompileTimeError
-lib/_internal/pub/lib/src/validator/utf8_readme: CompileTimeError
-lib/_internal/pub/test/descriptor: CompileTimeError
-lib/_internal/pub/test/descriptor/git: CompileTimeError
-lib/_internal/pub/test/descriptor/tar: CompileTimeError
+lib/_internal/pub/test/descriptor: Pass, CompileTimeError # Pass necessary, since CompileTimeError is valid for everything in that directory (not only for test/descriptor.dart)
lib/_internal/pub/test/lish/utils: CompileTimeError
lib/_internal/pub/test/oauth2/utils: CompileTimeError
lib/_internal/pub/test/serve/utils: CompileTimeError
diff --git a/tests/lib/async/future_test.dart b/tests/lib/async/future_test.dart
index ed342bc..20ae1c5 100644
--- a/tests/lib/async/future_test.dart
+++ b/tests/lib/async/future_test.dart
@@ -808,6 +808,8 @@
Future catchError(Function onError, {bool test(e)}) =>
_realFuture.catchError(onError, test: test);
Future whenComplete(action()) => _realFuture.whenComplete(action);
+ Future timeout(Duration timeLimit, [void onTimeout()]) =>
+ _realFuture.timeout(timeLimit, onTimeout);
Stream asStream() => _realFuture.asStream();
String toString() => "CustomFuture@${_realFuture.hashCode}";
int get hashCode => _realFuture.hashCode;
diff --git a/tests/lib/async/future_timeout_test.dart b/tests/lib/async/future_timeout_test.dart
new file mode 100644
index 0000000..f123118
--- /dev/null
+++ b/tests/lib/async/future_timeout_test.dart
@@ -0,0 +1,187 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library future_timeout_test;
+
+import 'dart:async';
+import '../../../pkg/unittest/lib/unittest.dart';
+
+main() {
+ test("timeoutNoComplete", () {
+ Completer completer = new Completer();
+ Future timedOut = completer.future.timeout(
+ const Duration(milliseconds: 5), () => 42);
+ timedOut.then(expectAsync1((v) {
+ expect(v, 42);
+ }));
+ });
+
+ test("timeoutCompleteAfterTimeout", () {
+ Completer completer = new Completer();
+ Future timedOut = completer.future.timeout(
+ const Duration(milliseconds: 5), () => 42);
+ Timer timer = new Timer(const Duration(seconds: 1), () {
+ completer.complete(-1);
+ });
+ timedOut.then(expectAsync1((v) {
+ expect(v, 42);
+ }));
+ });
+
+ test("timeoutCompleteBeforeTimeout", () {
+ Completer completer = new Completer();
+ Timer timer = new Timer(const Duration(milliseconds: 5), () {
+ completer.complete(42);
+ });
+ Future timedOut = completer.future.timeout(
+ const Duration(seconds: 1), () => -1);
+ timedOut.then(expectAsync1((v) {
+ expect(v, 42);
+ }));
+ });
+
+ test("timeoutCompleteBeforeCreate", () {
+ Completer completer = new Completer.sync();
+ completer.complete(42);
+ Future timedOut = completer.future.timeout(
+ const Duration(milliseconds: 5), () => -1);
+ timedOut.then(expectAsync1((v) {
+ expect(v, 42);
+ }));
+ });
+
+ test("timeoutThrows", () {
+ Completer completer = new Completer();
+ Future timedOut = completer.future.timeout(
+ const Duration(milliseconds: 5), () { throw "EXN1"; });
+ timedOut.catchError(expectAsync2((e, s) {
+ expect(e, "EXN1");
+ }));
+ });
+
+ test("timeoutThrowAfterTimeout", () {
+ Completer completer = new Completer();
+ Future timedOut = completer.future.timeout(
+ const Duration(milliseconds: 5), () => 42);
+ Timer timer = new Timer(const Duration(seconds: 1), () {
+ completer.completeError("EXN2");
+ });
+ timedOut.then(expectAsync1((v) {
+ expect(v, 42);
+ }));
+ });
+
+ test("timeoutThrowBeforeTimeout", () {
+ Completer completer = new Completer();
+ Timer timer = new Timer(const Duration(milliseconds: 5), () {
+ completer.completeError("EXN3");
+ });
+ Future timedOut = completer.future.timeout(
+ const Duration(seconds: 1), () => -1);
+ timedOut.catchError(expectAsync2((e, s) {
+ expect(e, "EXN3");
+ }));
+ });
+
+ test("timeoutThrowBeforeCreate", () {
+ // Prevent uncaught error when we create the error.
+ Completer completer = new Completer.sync()..future.catchError((e){});
+ completer.completeError("EXN4");
+ Future timedOut = completer.future.timeout(
+ const Duration(milliseconds: 5), () => -1);
+ timedOut.catchError(expectAsync2((e, s) {
+ expect(e, "EXN4");
+ }));
+ });
+
+ test("timeoutReturnFutureValue", () {
+ Future result = new Future.value(42);
+ Completer completer = new Completer();
+ Future timedOut = completer.future.timeout(
+ const Duration(milliseconds: 5), () => result);
+ timedOut.then(expectAsync1((v) {
+ expect(v, 42);
+ }));
+ });
+
+ test("timeoutReturnFutureError", () {
+ Future result = new Future.error("EXN5")..catchError((e){});
+ Completer completer = new Completer();
+ Future timedOut = completer.future.timeout(
+ const Duration(milliseconds: 5), () => result);
+ timedOut.catchError(expectAsync2((e, s) {
+ expect(e, "EXN5");
+ }));
+ });
+
+ test("timeoutReturnFutureValueLater", () {
+ Completer result = new Completer();
+ Completer completer = new Completer();
+ Future timedOut = completer.future.timeout(
+ const Duration(milliseconds: 5), () {
+ result.complete(42);
+ return result.future;
+ });
+ timedOut.then(expectAsync1((v) {
+ expect(v, 42);
+ }));
+ });
+
+ test("timeoutReturnFutureErrorLater", () {
+ Completer result = new Completer();
+ Completer completer = new Completer();
+ Future timedOut = completer.future.timeout(
+ const Duration(milliseconds: 5), () {
+ result.completeError("EXN6");
+ return result.future;
+ });
+ timedOut.catchError(expectAsync2((e, s) {
+ expect(e, "EXN6");
+ }));
+ });
+
+ test("timeoutZone", () {
+ Zone forked;
+ int registerCallDelta = 0;
+ bool callbackCalled = false;
+ Function callback = () {
+ expect(callbackCalled, false);
+ callbackCalled = true;
+ expect(Zone.current, forked);
+ return 42;
+ };
+ forked = Zone.current.fork(specification: new ZoneSpecification(
+ registerCallback: (Zone self, ZoneDelegate parent, Zone origin, f()) {
+ if (!identical(f, callback)) return f;
+ registerCallDelta++; // Increment calls to register.
+ expect(origin, forked);
+ expect(self, forked);
+ return expectAsync0(() { registerCallDelta--; return f(); });
+ }
+ ));
+ Completer completer = new Completer();
+ Future timedOut;
+ forked.run(() {
+ timedOut = completer.future.timeout(const Duration(milliseconds: 5),
+ callback);
+ });
+ timedOut.then(expectAsync1((v) {
+ expect(callbackCalled, true);
+ expect(registerCallDelta, 0);
+ expect(Zone.current, Zone.ROOT);
+ expect(v, 42);
+ }));
+ });
+
+ test("timeoutNoFunction", () {
+ Completer completer = new Completer();
+ Future timedOut = completer.future.timeout(
+ const Duration(milliseconds: 5));
+ timedOut.catchError(expectAsync2((e, s) {
+ expect(e, new isInstanceOf<TimeoutException>());
+ expect(e.duration, const Duration(milliseconds: 5));
+ expect(s, null);
+ }));
+ });
+}
diff --git a/tests/lib/async/future_value_chain4_test.dart b/tests/lib/async/future_value_chain4_test.dart
index 8e640b5..926e1b4 100644
--- a/tests/lib/async/future_value_chain4_test.dart
+++ b/tests/lib/async/future_value_chain4_test.dart
@@ -13,6 +13,7 @@
catchError(_, {test}) => null;
whenComplete(_) => null;
asStream() => null;
+ timeout(Duration timeLimit, [void onTimeout()]) => null;
}
main() {
diff --git a/tests/lib/async/zone_bind_test.dart b/tests/lib/async/zone_bind_test.dart
new file mode 100644
index 0000000..fcca4c0
--- /dev/null
+++ b/tests/lib/async/zone_bind_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+import 'dart:async';
+
+main() {
+ Completer done = new Completer();
+
+ Expect.identical(Zone.ROOT, Zone.current);
+ // New zone, does nothing by itself.
+ Zone forked = Zone.current.fork(specification: new ZoneSpecification());
+
+ int ctr = 0;
+ void expectZone([timer]) {
+ Expect.identical(forked, Zone.current);
+ if (timer != null) timer.cancel();
+ if (++ctr == 3) {
+ asyncEnd();
+ }
+ }
+
+ asyncStart();
+ Duration now = const Duration(seconds: 0);
+ // Check that the callback is bound to the zone.
+ forked.scheduleMicrotask(expectZone);
+ forked.createTimer(now, expectZone);
+ forked.createPeriodicTimer(now, expectZone);
+}
diff --git a/tests/lib/async/zone_empty_description2_test.dart b/tests/lib/async/zone_empty_description2_test.dart
index 68e1453..ce123e9 100644
--- a/tests/lib/async/zone_empty_description2_test.dart
+++ b/tests/lib/async/zone_empty_description2_test.dart
@@ -14,8 +14,8 @@
asyncStart();
bool timerDidRun = false;
forked.createTimer(const Duration(milliseconds: 20), () {
- // The createTimer functions on the Zone don't bind the closures.
- Expect.identical(Zone.ROOT, Zone.current);
+ // The createTimer function on the Zone binds the closures.
+ Expect.identical(forked, Zone.current);
timerDidRun = true;
asyncEnd();
});
@@ -29,8 +29,8 @@
timer.cancel();
asyncEnd();
}
- // The createPeriodicTimer functions on the Zone don't bind the closures.
- Expect.identical(Zone.ROOT, Zone.current);
+ // The createPeriodicTimer function on the Zone binds the closures.
+ Expect.identical(forked, Zone.current);
});
Expect.identical(Zone.ROOT, Zone.current);
}
diff --git a/tests/lib/async/zone_empty_description_test.dart b/tests/lib/async/zone_empty_description_test.dart
index 1a35dc0..30e494f 100644
--- a/tests/lib/async/zone_empty_description_test.dart
+++ b/tests/lib/async/zone_empty_description_test.dart
@@ -51,8 +51,7 @@
asyncStart();
bool asyncDidRun = false;
forked.scheduleMicrotask(() {
- // The scheduleMicrotask functions on the Zone don't bind the closures.
- Expect.identical(Zone.ROOT, Zone.current);
+ Expect.identical(forked, Zone.current);
asyncDidRun = true;
asyncEnd();
});
@@ -62,8 +61,7 @@
asyncStart();
bool timerDidRun = false;
forked.createTimer(const Duration(milliseconds: 0), () {
- // The createTimer functions on the Zone don't bind the closures.
- Expect.identical(Zone.ROOT, Zone.current);
+ Expect.identical(forked, Zone.current);
timerDidRun = true;
asyncEnd();
});
diff --git a/tests/lib/async/zone_run_guarded_test.dart b/tests/lib/async/zone_run_guarded_test.dart
index 60ffe5a..4145443 100644
--- a/tests/lib/async/zone_run_guarded_test.dart
+++ b/tests/lib/async/zone_run_guarded_test.dart
@@ -57,7 +57,7 @@
result = forked.runGuarded(() {
Expect.identical(forked, Zone.current);
events.add("run closure");
- scheduleMicrotask(() {
+ forked.scheduleMicrotask(() {
events.add("run closure 2");
Expect.identical(forked, Zone.current);
done.complete(true);
@@ -76,4 +76,4 @@
events);
asyncEnd();
});
-}
\ No newline at end of file
+}
diff --git a/tests/lib/async/zone_run_test.dart b/tests/lib/async/zone_run_test.dart
index 2af32df..3c13c46 100644
--- a/tests/lib/async/zone_run_test.dart
+++ b/tests/lib/async/zone_run_test.dart
@@ -44,7 +44,7 @@
result = forked.run(() {
Expect.identical(forked, Zone.current);
events.add("run closure 2");
- scheduleMicrotask(() {
+ forked.scheduleMicrotask(() {
events.add("run closure 3");
Expect.identical(forked, Zone.current);
done.complete(true);
@@ -62,4 +62,4 @@
events);
asyncEnd();
});
-}
\ No newline at end of file
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 75bf9c5..d0c4728 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -24,7 +24,6 @@
mirrors/find_in_context_private_test: Fail # Issue 6490
mirrors/find_in_context_fake_function_test: Fail # Issue 6490
mirrors/function_type_mirror_test: RuntimeError # Issue 12166
-mirrors/generics_test/01: RuntimeError # Issue 12087
mirrors/generic_f_bounded_mixin_application_test: RuntimeError # Issue 12087
mirrors/generic_function_typedef_test: RuntimeError # Issue 12333
mirrors/generic_interface_test: RuntimeError # Issue 12087
@@ -35,7 +34,6 @@
mirrors/hierarchy_invariants_test: RuntimeError # Issue 11863
mirrors/immutable_collections_test: RuntimeError # Issue 14030
mirrors/initializing_formals_test/01: RuntimeError # Issue 6490
-mirrors/initializing_formals_test/02: RuntimeError # Issue 12087
mirrors/initializing_formals_test/03: CompileTimeError # Issue 12164
mirrors/instance_members_test: RuntimeError # Issue 14633
mirrors/instance_members_with_override_test: RuntimeError # Issue 14633
@@ -128,7 +126,8 @@
async/catch_errors28_test: Fail # Timer interface not supported: dartbug.com/7728.
async/catch_errors8_test: Fail # Timer interface not supported: dartbug.com/7728.
async/run_zoned8_test: Fail # Timer interface not supported: dartbug.com/7728.
-
+async/zone_bind_test: Fail # Timer interface not supported: dartbug.com/7728.
+async/future_timeout_test: Fail # Timer interface not supported: dartbug.com/7728.
[ $compiler == dart2js && $checked ]
convert/utf85_test: Pass, Slow # Issue 12029.
@@ -168,6 +167,7 @@
[ $compiler == dart2js ]
typed_data/typed_data_hierarchy_int64_test: RuntimeError # Issue 10275
+typed_data/int32x4_bigint_test: RuntimeError # Issue 1533
[ $runtime == opera ]
async/multiple_timer_test: Pass, Fail # Probably issue 14734
diff --git a/tests/lib/math/double_pow_test.dart b/tests/lib/math/double_pow_test.dart
index c3ce04c..ca35db0 100644
--- a/tests/lib/math/double_pow_test.dart
+++ b/tests/lib/math/double_pow_test.dart
@@ -66,18 +66,18 @@
}
for (var d in samples) {
// otherwise, if either `x` or `y` is NaN then the result is NaN.
- if (d != 0.0) Expect.identical(NaN, pow(NaN, d), "$d");
- if (d != 1.0) Expect.identical(NaN, pow(d, NaN), "$d");
+ if (d != 0.0) Expect.isTrue(pow(NaN, d).isNaN, "$d");
+ if (d != 1.0) Expect.isTrue(pow(d, NaN).isNaN, "$d");
}
for (var d in samples) {
// if `x` is a finite and strictly negative and `y` is a finite non-integer,
// the result is NaN.
if (d < 0 && !d.isInfinite) {
- Expect.identical(NaN, pow(d, 0.5), "$d");
- Expect.identical(NaN, pow(d, -0.5), "$d");
- Expect.identical(NaN, pow(d, 1.5), "$d");
- Expect.identical(NaN, pow(d, -1.5), "$d");
+ Expect.isTrue(pow(d, 0.5).isNaN, "$d");
+ Expect.isTrue(pow(d, -0.5).isNaN, "$d");
+ Expect.isTrue(pow(d, 1.5).isNaN, "$d");
+ Expect.isTrue(pow(d, -1.5).isNaN, "$d");
}
}
diff --git a/tests/lib/mirrors/array_tracing2_test.dart b/tests/lib/mirrors/array_tracing2_test.dart
new file mode 100644
index 0000000..39411a1
--- /dev/null
+++ b/tests/lib/mirrors/array_tracing2_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:mirrors';
+
+class A {
+ var field;
+}
+
+main() {
+ var a = new A();
+ var mirror = reflect(a);
+ var array = [42];
+ a.field = array;
+ var field = mirror.getField(#field);
+ field.invoke(#clear, []);
+ if (array.length == 1) throw 'Test failed';
+}
diff --git a/tests/lib/mirrors/array_tracing3_test.dart b/tests/lib/mirrors/array_tracing3_test.dart
new file mode 100644
index 0000000..38a6a61
--- /dev/null
+++ b/tests/lib/mirrors/array_tracing3_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+@MirrorsUsed(targets: 'A, List')
+import 'dart:mirrors';
+
+class A {
+ static var field;
+}
+
+main() {
+ MirrorSystem mirrors = currentMirrorSystem();
+ ClassMirror a = reflectClass(A);
+ var array = [42];
+ A.field = array;
+ var field = a.getField(#field);
+ field.invoke(#clear, []);
+ if (array.length == 1) throw 'Test failed';
+}
diff --git a/tests/lib/mirrors/array_tracing_test.dart b/tests/lib/mirrors/array_tracing_test.dart
new file mode 100644
index 0000000..092feac
--- /dev/null
+++ b/tests/lib/mirrors/array_tracing_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:mirrors';
+
+class A {
+ static var field;
+}
+
+main() {
+ MirrorSystem mirrors = currentMirrorSystem();
+ ClassMirror a = reflectClass(A);
+ var array = [42];
+ A.field = array;
+ var field = a.getField(#field);
+ field.invoke(#clear, []);
+ if (array.length == 1) throw 'Test failed';
+}
diff --git a/tests/lib/mirrors/generics_dynamic_test.dart b/tests/lib/mirrors/generics_dynamic_test.dart
new file mode 100644
index 0000000..b8abf53
--- /dev/null
+++ b/tests/lib/mirrors/generics_dynamic_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:mirrors';
+import 'package:expect/expect.dart';
+
+class A<T> {}
+class B<T extends A> extends A implements C{
+ A m(A a) {}
+ A field;
+}
+class C<S,T> {}
+class D extends A<int> {}
+
+main() {
+ ClassMirror aDecl = reflectClass(A);
+ ClassMirror bDecl = reflectClass(B);
+ ClassMirror cDecl = reflectClass(C);
+ TypeMirror aInstance = reflect(new A()).type;
+ TypeMirror aInstanceDynamic = reflect(new A<dynamic>()).type;
+ TypeMirror dInstance = reflect(new D()).type;
+ TypeMirror cInstance = reflect(new C<dynamic, dynamic>()).type;
+ TypeMirror cNestedInstance = reflect(new C<C, dynamic>()).type;
+ TypeMirror cTypeArgument = cNestedInstance.typeArguments.first;
+ TypeMirror superA = bDecl.superclass;
+ TypeMirror superC = bDecl.superinterfaces.single;
+ MethodMirror m = bDecl.declarations[#m];
+ VariableMirror field = bDecl.declarations[#field];
+ TypeMirror returnTypeA = m.returnType;
+ TypeMirror parameterTypeA = m.parameters.first.type;
+ TypeMirror fieldTypeA = field.type;
+ TypeMirror upperBoundA = bDecl.typeVariables.single.upperBound;
+ TypeMirror dynamicMirror = currentMirrorSystem().dynamicType;
+
+ Expect.isTrue(aDecl.isOriginalDeclaration);
+ Expect.isTrue(reflect(dInstance).type.isOriginalDeclaration);
+ Expect.isFalse(aInstance.isOriginalDeclaration);
+ Expect.isFalse(aInstanceDynamic.isOriginalDeclaration);
+ Expect.isFalse(superA.isOriginalDeclaration);
+ Expect.isFalse(superC.isOriginalDeclaration);
+ Expect.isFalse(returnTypeA.isOriginalDeclaration);
+ Expect.isFalse(parameterTypeA.isOriginalDeclaration);
+ Expect.isFalse(fieldTypeA.isOriginalDeclaration);
+ Expect.isFalse(upperBoundA.isOriginalDeclaration);
+ Expect.isFalse(cInstance.isOriginalDeclaration);
+ Expect.isFalse(cNestedInstance.isOriginalDeclaration);
+ Expect.isFalse(cTypeArgument.isOriginalDeclaration);
+
+ Expect.isTrue(aDecl.typeArguments.isEmpty);
+ Expect.isTrue(dInstance.typeArguments.isEmpty);
+ Expect.equals(dynamicMirror, aInstance.typeArguments.single);
+ Expect.equals(dynamicMirror, aInstanceDynamic.typeArguments.single);
+ Expect.equals(dynamicMirror, superA.typeArguments.single);
+ Expect.equals(dynamicMirror, superC.typeArguments.first);
+ Expect.equals(dynamicMirror, superC.typeArguments.last);
+ Expect.equals(dynamicMirror, returnTypeA.typeArguments.single);
+ Expect.equals(dynamicMirror, parameterTypeA.typeArguments.single);
+ Expect.equals(dynamicMirror, fieldTypeA.typeArguments.single);
+ Expect.equals(dynamicMirror, upperBoundA.typeArguments.single);
+ Expect.equals(dynamicMirror, cInstance.typeArguments.first);
+ Expect.equals(dynamicMirror, cInstance.typeArguments.last);
+ Expect.equals(dynamicMirror, cNestedInstance.typeArguments.last);
+ Expect.equals(dynamicMirror, cTypeArgument.typeArguments.first);
+ Expect.equals(dynamicMirror, cTypeArgument.typeArguments.last);
+}
\ No newline at end of file
diff --git a/tests/lib/mirrors/generics_test.dart b/tests/lib/mirrors/generics_test.dart
index 085dc37..10fe2e3 100644
--- a/tests/lib/mirrors/generics_test.dart
+++ b/tests/lib/mirrors/generics_test.dart
@@ -79,20 +79,20 @@
var numMirror = reflectClass(num);
var dynamicMirror = currentMirrorSystem().dynamicType;
typeArguments(reflect(new A<num>()).type, [numMirror]);
- typeArguments(reflect(new A<dynamic>()).type, [dynamicMirror]); /// 01: ok
- typeArguments(reflect(new A()).type, [dynamicMirror]); /// 01: ok
+ typeArguments(reflect(new A<dynamic>()).type, [dynamicMirror]);
+ typeArguments(reflect(new A()).type, [dynamicMirror]);
typeArguments(reflect(new B()).type, []);
typeArguments(reflect(new C()).type, []);
typeArguments(reflect(new D()).type, []);
typeArguments(reflect(new E<num>()).type, [numMirror]);
- typeArguments(reflect(new E<dynamic>()).type, [dynamicMirror]); /// 01: ok
- typeArguments(reflect(new E()).type, [dynamicMirror]); /// 01: ok
+ typeArguments(reflect(new E<dynamic>()).type, [dynamicMirror]);
+ typeArguments(reflect(new E()).type, [dynamicMirror]);
typeArguments(reflect(new F<num>()).type, [numMirror]);
- typeArguments(reflect(new F<dynamic>()).type, [dynamicMirror]); /// 01: ok
- typeArguments(reflect(new F()).type, [dynamicMirror]); /// 01: ok
+ typeArguments(reflect(new F<dynamic>()).type, [dynamicMirror]);
+ typeArguments(reflect(new F()).type, [dynamicMirror]);
typeArguments(reflect(new G()).type, []);
- typeArguments(reflect(new H<dynamic, num, dynamic>()).type, /// 01: ok
- [dynamicMirror, numMirror, dynamicMirror]); /// 01: ok
+ typeArguments(reflect(new H<dynamic, num, dynamic>()).type,
+ [dynamicMirror, numMirror, dynamicMirror]);
typeArguments(reflect(new I()).type, []);
Expect.isFalse(reflect(new A<num>()).type.isOriginalDeclaration);
@@ -102,7 +102,7 @@
Expect.isFalse(reflect(new E<num>()).type.isOriginalDeclaration);
Expect.isFalse(reflect(new F<num>()).type.isOriginalDeclaration);
Expect.isTrue(reflect(new G()).type.isOriginalDeclaration);
- Expect.isFalse(reflect(new H()).type.isOriginalDeclaration); /// 01: ok
+ Expect.isFalse(reflect(new H()).type.isOriginalDeclaration);
Expect.isTrue(reflect(new I()).type.isOriginalDeclaration);
Expect.equals(reflectClass(A),
@@ -138,8 +138,8 @@
reflect(new F<num>()).type.originalDeclaration);
Expect.equals(reflect(new G()).type,
reflect(new G()).type.originalDeclaration);
- Expect.notEquals(reflect(new H()).type, /// 01: ok
- reflect(new H()).type.originalDeclaration); /// 01: ok
+ Expect.notEquals(reflect(new H()).type,
+ reflect(new H()).type.originalDeclaration);
Expect.equals(reflect(new I()).type,
reflect(new I()).type.originalDeclaration);
diff --git a/tests/lib/mirrors/initializing_formals_test.dart b/tests/lib/mirrors/initializing_formals_test.dart
index 3afb39d..2729524 100644
--- a/tests/lib/mirrors/initializing_formals_test.dart
+++ b/tests/lib/mirrors/initializing_formals_test.dart
@@ -75,7 +75,7 @@
mm = reflectClass(Class).declarations[#Class.generic];
pm = mm.parameters.single;
Expect.equals(#tField, pm.simpleName);
- Expect.equals(reflectClass(Class).typeVariables.single, pm.type); /// 02: ok
+ Expect.equals(reflectClass(Class).typeVariables.single, pm.type);
Expect.isFalse(pm.isNamed); /// 01: ok
Expect.isFalse(pm.isFinal); /// 01: ok
Expect.isFalse(pm.isOptional); /// 01: ok
@@ -111,7 +111,7 @@
mm = reflectClass(Class).declarations[#Class.withVar];
pm = mm.parameters.single;
Expect.equals(#intField, pm.simpleName);
- Expect.equals(reflectClass(int), pm.type); // N.B. /// 02: ok
+ Expect.equals(reflectClass(int), pm.type);
Expect.isFalse(pm.isNamed); /// 01: ok
Expect.isFalse(pm.isFinal); /// 01: ok
Expect.isFalse(pm.isOptional); /// 01: ok
diff --git a/tests/lib/mirrors/private_symbol_test.dart b/tests/lib/mirrors/private_symbol_test.dart
index 156381a..be4f5fe 100644
--- a/tests/lib/mirrors/private_symbol_test.dart
+++ b/tests/lib/mirrors/private_symbol_test.dart
@@ -7,7 +7,7 @@
import 'dart:mirrors';
import 'package:expect/expect.dart';
-typedef int _F(int);
+typedef int _F(int i);
class _C<_T> {
get g {}
diff --git a/tests/lib/typed_data/int32x4_bigint_test.dart b/tests/lib/typed_data/int32x4_bigint_test.dart
new file mode 100644
index 0000000..539b23f
--- /dev/null
+++ b/tests/lib/typed_data/int32x4_bigint_test.dart
@@ -0,0 +1,16 @@
+// 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.
+// VMOptions=--deoptimization_counter_threshold=1000 --optimization-counter-threshold=10
+
+// Library tag to be able to run in html test framework.
+library int32x4_bigint_test;
+
+import 'package:expect/expect.dart';
+import 'dart:typed_data';
+
+main() {
+ var n = 18446744073709551617;
+ var x = new Int32x4(n, 0, 0, 0);
+ Expect.equals(x.x, 1);
+}
diff --git a/tests/standalone/io/file_system_watcher_test.dart b/tests/standalone/io/file_system_watcher_test.dart
index 2cc97b7..a28d7ed 100644
--- a/tests/standalone/io/file_system_watcher_test.dart
+++ b/tests/standalone/io/file_system_watcher_test.dart
@@ -86,6 +86,8 @@
void testWatchMoveFile() {
+ // Mac OS doesn't report move events.
+ if (Platform.isMacOS) return;
var dir = Directory.systemTemp.createTempSync('dart_file_system_watcher');
var file = new File(join(dir.path, 'file'));
file.createSync();
diff --git a/tests/standalone/io/http_cookie_date_test.dart b/tests/standalone/io/http_cookie_date_test.dart
index 56bee7a..08288b6 100644
--- a/tests/standalone/io/http_cookie_date_test.dart
+++ b/tests/standalone/io/http_cookie_date_test.dart
@@ -2,17 +2,38 @@
// 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 dart.io;
+
import "package:expect/expect.dart";
import "dart:async";
-import "dart:math";
import "dart:collection";
+import "dart:convert";
+import "dart:math";
+import "dart:typed_data";
+import "dart:isolate";
+part "../../../sdk/lib/io/bytes_builder.dart";
part "../../../sdk/lib/io/common.dart";
-part "../../../sdk/lib/io/io_sink.dart";
+part "../../../sdk/lib/io/crypto.dart";
+part "../../../sdk/lib/io/data_transformer.dart";
+part "../../../sdk/lib/io/directory.dart";
+part "../../../sdk/lib/io/directory_impl.dart";
+part "../../../sdk/lib/io/file.dart";
+part "../../../sdk/lib/io/file_impl.dart";
+part "../../../sdk/lib/io/file_system_entity.dart";
+part "../../../sdk/lib/io/link.dart";
part "../../../sdk/lib/io/http.dart";
part "../../../sdk/lib/io/http_impl.dart";
-part "../../../sdk/lib/io/http_parser.dart";
part "../../../sdk/lib/io/http_date.dart";
+part "../../../sdk/lib/io/http_parser.dart";
+part "../../../sdk/lib/io/http_headers.dart";
+part "../../../sdk/lib/io/http_session.dart";
+part "../../../sdk/lib/io/io_service.dart";
+part "../../../sdk/lib/io/io_sink.dart";
+part "../../../sdk/lib/io/platform.dart";
+part "../../../sdk/lib/io/platform_impl.dart";
+part "../../../sdk/lib/io/secure_socket.dart";
+part "../../../sdk/lib/io/secure_server_socket.dart";
part "../../../sdk/lib/io/socket.dart";
void testParseHttpCookieDate() {
diff --git a/tests/standalone/io/http_headers_test.dart b/tests/standalone/io/http_headers_test.dart
index 87dd27b..d1d261f 100644
--- a/tests/standalone/io/http_headers_test.dart
+++ b/tests/standalone/io/http_headers_test.dart
@@ -2,18 +2,38 @@
// 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:expect/expect.dart";
-import 'dart:async';
-import 'dart:math';
-import 'dart:collection';
+library dart.io;
-part '../../../sdk/lib/io/common.dart';
-part "../../../sdk/lib/io/io_sink.dart";
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:collection";
+import "dart:convert";
+import "dart:math";
+import "dart:typed_data";
+import "dart:isolate";
+
+part "../../../sdk/lib/io/bytes_builder.dart";
+part "../../../sdk/lib/io/common.dart";
+part "../../../sdk/lib/io/crypto.dart";
+part "../../../sdk/lib/io/data_transformer.dart";
+part "../../../sdk/lib/io/directory.dart";
+part "../../../sdk/lib/io/directory_impl.dart";
+part "../../../sdk/lib/io/file.dart";
+part "../../../sdk/lib/io/file_impl.dart";
+part "../../../sdk/lib/io/file_system_entity.dart";
+part "../../../sdk/lib/io/link.dart";
part "../../../sdk/lib/io/http.dart";
-part "../../../sdk/lib/io/http_date.dart";
-part "../../../sdk/lib/io/http_headers.dart";
part "../../../sdk/lib/io/http_impl.dart";
+part "../../../sdk/lib/io/http_date.dart";
part "../../../sdk/lib/io/http_parser.dart";
+part "../../../sdk/lib/io/http_headers.dart";
+part "../../../sdk/lib/io/http_session.dart";
+part "../../../sdk/lib/io/io_service.dart";
+part "../../../sdk/lib/io/io_sink.dart";
+part "../../../sdk/lib/io/platform.dart";
+part "../../../sdk/lib/io/platform_impl.dart";
+part "../../../sdk/lib/io/secure_socket.dart";
+part "../../../sdk/lib/io/secure_server_socket.dart";
part "../../../sdk/lib/io/socket.dart";
void testMultiValue() {
diff --git a/tests/standalone/io/http_parser_test.dart b/tests/standalone/io/http_parser_test.dart
index c35fcfb..2c5e508 100644
--- a/tests/standalone/io/http_parser_test.dart
+++ b/tests/standalone/io/http_parser_test.dart
@@ -2,21 +2,39 @@
// 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:expect/expect.dart";
-import 'dart:async';
-import 'dart:math';
-import 'dart:typed_data';
-import 'dart:isolate';
-import 'dart:collection';
+library dart.io;
-part '../../../sdk/lib/io/common.dart';
-part '../../../sdk/lib/io/io_sink.dart';
-part '../../../sdk/lib/io/http.dart';
-part '../../../sdk/lib/io/http_date.dart';
-part '../../../sdk/lib/io/http_impl.dart';
-part '../../../sdk/lib/io/http_headers.dart';
-part '../../../sdk/lib/io/http_parser.dart';
-part '../../../sdk/lib/io/socket.dart';
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:collection";
+import "dart:convert";
+import "dart:math";
+import "dart:typed_data";
+import "dart:isolate";
+
+part "../../../sdk/lib/io/bytes_builder.dart";
+part "../../../sdk/lib/io/common.dart";
+part "../../../sdk/lib/io/crypto.dart";
+part "../../../sdk/lib/io/data_transformer.dart";
+part "../../../sdk/lib/io/directory.dart";
+part "../../../sdk/lib/io/directory_impl.dart";
+part "../../../sdk/lib/io/file.dart";
+part "../../../sdk/lib/io/file_impl.dart";
+part "../../../sdk/lib/io/file_system_entity.dart";
+part "../../../sdk/lib/io/link.dart";
+part "../../../sdk/lib/io/http.dart";
+part "../../../sdk/lib/io/http_impl.dart";
+part "../../../sdk/lib/io/http_date.dart";
+part "../../../sdk/lib/io/http_parser.dart";
+part "../../../sdk/lib/io/http_headers.dart";
+part "../../../sdk/lib/io/http_session.dart";
+part "../../../sdk/lib/io/io_service.dart";
+part "../../../sdk/lib/io/io_sink.dart";
+part "../../../sdk/lib/io/platform.dart";
+part "../../../sdk/lib/io/platform_impl.dart";
+part "../../../sdk/lib/io/secure_socket.dart";
+part "../../../sdk/lib/io/secure_server_socket.dart";
+part "../../../sdk/lib/io/socket.dart";
class HttpParserTest {
static void runAllTests() {
diff --git a/tests/standalone/io/resolve_symbolic_links_test.dart b/tests/standalone/io/resolve_symbolic_links_test.dart
index 252e65f..690cbc5 100644
--- a/tests/standalone/io/resolve_symbolic_links_test.dart
+++ b/tests/standalone/io/resolve_symbolic_links_test.dart
@@ -23,7 +23,6 @@
asyncTest(() => testDir(join(testsDir, 'standalone', 'io')));
asyncTest(() => testDir(join(testsDir, 'lib', '..', 'standalone', 'io')));
// Test a relative path.
- asyncTest(() => testDir('.'));
if (Platform.isWindows) {
asyncTest(() =>testFile(join('\\\\?\\$testsDir', 'standalone', 'io',
'resolve_symbolic_links_test.dart')));
@@ -37,7 +36,8 @@
testFile(join(temp, 'link1', 'file2')),
testDir(join(temp, 'dir1', 'dir2', '..', '.', '..', 'dir1')),
testDir(join(temp, 'dir1', 'dir2', '..', '.', '..', 'dir1')),
- testLink(join(temp, 'link1'))]))
+ testLink(join(temp, 'link1')),
+ testDir('.')]))
.then((_) {
if (Platform.isWindows) {
// Windows applies '..' to a link without resolving the link first.
diff --git a/tests/standalone/io/socket_test.dart b/tests/standalone/io/socket_test.dart
index beec587..56a76bb 100644
--- a/tests/standalone/io/socket_test.dart
+++ b/tests/standalone/io/socket_test.dart
@@ -210,8 +210,22 @@
});
}
-main() {
+void testCloseWriteNoListen() {
asyncStart();
+ ServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0).then((server) {
+ server.listen(
+ (client) {
+ client.close();
+ });
+ Socket.connect("127.0.0.1", server.port).then((socket) {
+ socket.close();
+ server.close();
+ asyncEnd();
+ });
+ });
+}
+
+main() {
testArguments();
testSimpleBind();
testInvalidBind();
@@ -224,5 +238,5 @@
testConnectStreamDataClose(false);
testConnectStreamDataCloseCancel(true);
testConnectStreamDataCloseCancel(false);
- asyncEnd();
+ testCloseWriteNoListen();
}
diff --git a/tests/standalone/io/test_harness_analyzer_test.dart b/tests/standalone/io/test_harness_analyzer_test.dart
new file mode 100644
index 0000000..f2a2b40
--- /dev/null
+++ b/tests/standalone/io/test_harness_analyzer_test.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../../../tools/test.dart' as test_dart;
+import '../../../tools/testing/dart/launch_browser.dart' as launch_browser;
+
+// The purpose of this test is to run the analyzer on it and make sure our
+// testing scripts are free of warnings/errors.
+
+void main() {}
diff --git a/tests/standalone/io/test_runner_test.dart b/tests/standalone/io/test_runner_test.dart
index 5b540af..4b2fe2a 100644
--- a/tests/standalone/io/test_runner_test.dart
+++ b/tests/standalone/io/test_runner_test.dart
@@ -12,7 +12,7 @@
import "../../../tools/testing/dart/test_options.dart";
import "process_test_util.dart";
-final DEFAULT_TIMEOUT = 2;
+final DEFAULT_TIMEOUT = 10;
final LONG_TIMEOUT = 30;
class TestController {
@@ -140,8 +140,8 @@
throw "This test always fails, to test the test scripts.";
break;
case 'timeout':
- // Run for 10 seconds, then exit. This tests a 2 second timeout.
- new Timer(new Duration(seconds: 10), (){ });
+ // This process should be killed by the test after DEFAULT_TIMEOUT
+ new Timer(new Duration(hours: 42), (){ });
break;
default:
throw "Unknown option ${arguments[0]} passed to test_runner_test";
diff --git a/tests/standalone/io/web_socket_protocol_processor_test.dart b/tests/standalone/io/web_socket_protocol_processor_test.dart
index ff5de75..b14a37d 100644
--- a/tests/standalone/io/web_socket_protocol_processor_test.dart
+++ b/tests/standalone/io/web_socket_protocol_processor_test.dart
@@ -2,21 +2,40 @@
// 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";
-import "dart:math";
-import "dart:async";
-import "dart:collection";
-import "dart:typed_data";
-import "dart:isolate";
+library dart.io;
import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
+import "dart:async";
+import "dart:collection";
+import "dart:convert";
+import "dart:math";
+import "dart:typed_data";
+import "dart:isolate";
-part '../../../sdk/lib/io/common.dart';
-part "../../../sdk/lib/io/http.dart";
part "../../../sdk/lib/io/bytes_builder.dart";
+part "../../../sdk/lib/io/common.dart";
+part "../../../sdk/lib/io/crypto.dart";
+part "../../../sdk/lib/io/data_transformer.dart";
+part "../../../sdk/lib/io/directory.dart";
+part "../../../sdk/lib/io/directory_impl.dart";
+part "../../../sdk/lib/io/file.dart";
+part "../../../sdk/lib/io/file_impl.dart";
+part "../../../sdk/lib/io/file_system_entity.dart";
+part "../../../sdk/lib/io/link.dart";
+part "../../../sdk/lib/io/http.dart";
+part "../../../sdk/lib/io/http_impl.dart";
+part "../../../sdk/lib/io/http_date.dart";
+part "../../../sdk/lib/io/http_parser.dart";
+part "../../../sdk/lib/io/http_headers.dart";
+part "../../../sdk/lib/io/http_session.dart";
+part "../../../sdk/lib/io/io_service.dart";
part "../../../sdk/lib/io/io_sink.dart";
-part "../../../sdk/lib/io/string_transformer.dart";
+part "../../../sdk/lib/io/platform.dart";
+part "../../../sdk/lib/io/platform_impl.dart";
+part "../../../sdk/lib/io/secure_socket.dart";
+part "../../../sdk/lib/io/secure_server_socket.dart";
+part "../../../sdk/lib/io/socket.dart";
part "../../../sdk/lib/io/websocket.dart";
part "../../../sdk/lib/io/websocket_impl.dart";
diff --git a/tests/standalone/io/web_socket_protocol_test.dart b/tests/standalone/io/web_socket_protocol_test.dart
new file mode 100644
index 0000000..e81cc27
--- /dev/null
+++ b/tests/standalone/io/web_socket_protocol_test.dart
@@ -0,0 +1,109 @@
+// 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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+
+import "package:expect/expect.dart";
+import "dart:async";
+import "dart:io";
+
+
+testEmptyProtocol() {
+ HttpServer.bind("127.0.0.1", 0).then((server) {
+ server.listen((request) {
+ WebSocketTransformer.upgrade(request).then((websocket) {
+ websocket.close();
+ });
+ });
+ WebSocket.connect("ws://127.0.0.1:${server.port}/",
+ protocols: []).then((client) {
+ Expect.isNull(client.protocol);
+ client.close();
+ server.close();
+ });
+ });
+}
+
+
+testProtocol(List<String> protocols, String used) {
+ selector(List<String> receivedProtocols) {
+ Expect.listEquals(protocols, receivedProtocols);
+ return used;
+ }
+ HttpServer.bind("127.0.0.1", 0).then((server) {
+ server.listen((request) {
+ WebSocketTransformer.upgrade(request,
+ protocolSelector: selector)
+ .then((websocket) {
+ Expect.equals(used, websocket.protocol);
+ websocket.close();
+ });
+ });
+ WebSocket.connect("ws://127.0.0.1:${server.port}/",
+ protocols: protocols).then((client) {
+ Expect.equals(used, client.protocol);
+ client.close();
+ server.close();
+ });
+ });
+}
+
+
+testProtocolHandler() {
+ // Test throwing an error.
+ HttpServer.bind("127.0.0.1", 0).then((server) {
+ server.listen((request) {
+ selector(List<String> receivedProtocols) {
+ throw "error";
+ }
+ WebSocketTransformer.upgrade(request,
+ protocolSelector: selector)
+ .then((websocket) {
+ Expect.fail('error expected');
+ }, onError: (error) {
+ Expect.equals('error', error);
+ });
+ });
+ WebSocket.connect("ws://127.0.0.1:${server.port}/",
+ protocols: ["v1.example.com"])
+ .then((client) {
+ Expect.fail('error expected');
+ }, onError: (error) {
+ server.close();
+ });
+ });
+
+ // Test returning another protocol.
+ HttpServer.bind("127.0.0.1", 0).then((server) {
+ server.listen((request) {
+ selector(List<String> receivedProtocols) => "v2.example.com";
+ WebSocketTransformer.upgrade(request,
+ protocolSelector: selector)
+ .then((websocket) {
+ Expect.fail('error expected');
+ }, onError: (error) {
+ Expect.isTrue(error is WebSocketException);
+ });
+ });
+ WebSocket.connect("ws://127.0.0.1:${server.port}/",
+ protocols: ["v1.example.com"])
+ .then((client) {
+ Expect.fail('error expected');
+ }, onError: (error) {
+ server.close();
+ });
+ });
+}
+
+
+void main() {
+ testEmptyProtocol();
+ testProtocol(["v1.example.com", "v2.example.com"], "v1.example.com");
+ testProtocol(["v1.example.com", "v2.example.com"], "v2.example.com");
+ testProtocolHandler();
+}
+
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 7bf4ccf..570c988 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -56,43 +56,16 @@
issue14236_test: Skip # Issue 14236 Script snapshots do not work in the browser.
-[ $compiler == dartanalyzer ]
+[ $compiler == dartanalyzer || $compiler == dart2analyzer ]
javascript_int_overflow_literal_test/01: fail, ok
issue14236_test: Skip # Analyzer can't handle Script snapshots.
# test issue https://code.google.com/p/dart/issues/detail?id=11518
io/file_constructor_test: fail
-# The dart:io library is created at build time from separate files, and
-# there is no language-spec compatible way to run unit tests on the private
-# members and methods of dart:io.
-# Dart analyzer spots the misuse of 'part' directives in these unit tests.
-io/http_headers_test: Skip
-io/http_cookie_date_test: Skip
-io/http_parser_test: Skip
-io/web_socket_protocol_processor_test: Skip
-
# This is runtime test.
io/process_exit_negative_test: Skip
-[ $compiler == dart2analyzer ]
-javascript_int_overflow_literal_test/01: fail, ok
-issue14236_test: Skip # Analyzer can't handle Script snapshots.
-
-# test issue https://code.google.com/p/dart/issues/detail?id=11518
-io/file_constructor_test: fail
-
-# The dart:io library is created at build time from separate files, and
-# there is no language-spec compatible way to run unit tests on the private
-# members and methods of dart:io.
-# Dart analyzer spots the misuse of 'part' directives in these unit tests.
-io/http_headers_test: Skip
-io/http_cookie_date_test: Skip
-io/http_parser_test: Skip
-io/web_socket_protocol_processor_test: Skip
-
-# This is runtime test.
-io/process_exit_negative_test: Skip
[ $compiler == dart2js ]
number_identity_test: Skip # Bigints and int/double diff. not supported.
@@ -174,9 +147,7 @@
io/process_invalid_arguments_test: StaticWarning
io/raw_secure_server_socket_argument_test: StaticWarning
io/secure_socket_argument_test: StaticWarning
-io/skipping_dart2js_compilations_test: CompileTimeError, StaticWarning
io/stdout_bad_argument_test: StaticWarning
-io/test_runner_test: CompileTimeError, StaticWarning
package/package1_test: StaticWarning
package/package_test: StaticWarning
typed_data_test: StaticWarning
diff --git a/tests/standalone/vmservice/isolate_class_test.dart b/tests/standalone/vmservice/isolate_class_test.dart
index 086ae5e..9650443 100644
--- a/tests/standalone/vmservice/isolate_class_test.dart
+++ b/tests/standalone/vmservice/isolate_class_test.dart
@@ -28,10 +28,10 @@
onRequestCompleted(Map reply) {
Expect.equals('Library', reply['type']);
Expect.equals('isolate_stacktrace_command_script', reply['name']);
- Expect.equals(2, reply['classes'].length);
- Expect.equals('@Class', reply['classes'][1]['type']);
- Expect.equals('C', reply['classes'][1]['name']);
- _classId = reply['classes'][1]['id'];
+ Expect.equals(1, reply['classes'].length);
+ Expect.equals('@Class', reply['classes'][0]['type']);
+ Expect.equals('C', reply['classes'][0]['name']);
+ _classId = reply['classes'][0]['id'];
}
}
diff --git a/tests/utils/dummy_compiler_test.dart b/tests/utils/dummy_compiler_test.dart
index aad4e49..b66f951 100644
--- a/tests/utils/dummy_compiler_test.dart
+++ b/tests/utils/dummy_compiler_test.dart
@@ -74,6 +74,9 @@
}
class JSFunction {}
class JSInt {}
+class JSPositiveInt {}
+class JSUInt31 {}
+class JSUInt32 {}
class JSDouble {}
class JSNumber {}
class JSNull {}
diff --git a/tools/VERSION b/tools/VERSION
index 5e01d86..23e911a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,5 +1,5 @@
CHANNEL dev
MAJOR 1
MINOR 0
-BUILD 1
-PATCH 3
+BUILD 2
+PATCH 0
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py
index 7f730cb..0ed83e6 100644
--- a/tools/bots/compiler.py
+++ b/tools/bots/compiler.py
@@ -257,47 +257,6 @@
TestStep("dart2js_extra", mode, system, 'dart2js', runtime, extras,
extras_flags, arch)
-
-def _DeleteTempWebdriverProfiles(directory):
- """Find all the firefox profiles in a particular directory and delete them."""
- for f in os.listdir(directory):
- item = os.path.join(directory, f)
- if os.path.isdir(item) and (f.startswith('tmp') or f.startswith('opera')):
- subprocess.Popen('rm -rf %s' % item, shell=True)
-
-
-def CleanUpTemporaryFiles(system, browser):
- """For some browser (selenium) tests, the browser creates a temporary profile
- on each browser session start. On Windows, generally these files are
- automatically deleted when all python processes complete. However, since our
- buildbot slave script also runs on python, we never get the opportunity to
- clear out the temp files, so we do so explicitly here. Our batch browser
- testing will make this problem occur much less frequently, but will still
- happen eventually unless we do this.
-
- This problem also occurs with batch tests in Firefox. For some reason selenium
- automatically deletes the temporary profiles for Firefox for one browser,
- but not multiple ones when we have many open batch tasks running. This
- behavior has not been reproduced outside of the buildbots.
-
- Args:
- - system: either 'linux', 'mac', 'windows'
- - browser: one of the browsers, see GetBuildInfo
- """
- if system == 'windows':
- temp_dir = 'C:\\Users\\chrome-bot\\AppData\\Local\\Temp'
- for name in os.listdir(temp_dir):
- fullname = os.path.join(temp_dir, name)
- if os.path.isdir(fullname):
- shutil.rmtree(fullname, ignore_errors=True)
- elif browser == 'ff' or 'opera':
- # Note: the buildbots run as root, so we can do this without requiring a
- # password. The command won't actually work on regular machines without
- # root permissions.
- _DeleteTempWebdriverProfiles('/tmp')
- _DeleteTempWebdriverProfiles('/var/tmp')
-
-
def GetHasHardCodedCheckedMode(build_info):
# TODO(ricow): We currently run checked mode tests on chrome on linux and
# on the slow (all) IE windows bots. This is a hack and we should use the
@@ -364,9 +323,6 @@
build_info.test_set, build_info.arch,
compiler=build_info.compiler)
- if build_info.runtime != 'd8':
- CleanUpTemporaryFiles(build_info.system, build_info.runtime)
-
def BuildCompiler(build_info):
"""
diff --git a/tools/ddbg.dart b/tools/ddbg.dart
index 38433dd..4248459 100644
--- a/tools/ddbg.dart
+++ b/tools/ddbg.dart
@@ -9,21 +9,34 @@
import "dart:io";
import "dart:async";
+import "ddbg/lib/commando.dart";
+
+class TargetIsolate {
+ int id;
+ // The location of the last paused event.
+ Map pausedLocation = null;
+
+ TargetIsolate(this.id);
+ bool get isPaused => pausedLocation != null;
+}
+
+Map<int, TargetIsolate> targetIsolates= new Map<int, TargetIsolate>();
Map<int, Completer> outstandingCommands;
Socket vmSock;
String vmData;
-var stdinSubscription;
+Commando cmdo;
var vmSubscription;
int seqNum = 0;
-int isolate_id = -1;
+
+Process targetProcess;
final verbose = false;
final printMessages = false;
-// The location of the last paused event.
-Map pausedLocation = null;
+TargetIsolate currentIsolate;
+TargetIsolate mainIsolate;
void printHelp() {
@@ -51,21 +64,29 @@
tok <lib_id> <script_url> Get line and token table of script in library
epi <none|all|unhandled> Set exception pause info
li List ids of all isolates in the VM
+ sci <id> Set current target isolate
i <id> Interrupt execution of given isolate id
h Print help
""");
}
+String formatLocation(Map location) {
+ if (location == null) return "";
+ var fileName = location["url"].split("/").last;
+ return "file: $fileName lib: ${location['libraryId']} token: ${location['tokenOffset']}";
+}
+
+
void quitShell() {
vmSubscription.cancel();
vmSock.close();
- stdinSubscription.cancel();
+ cmdo.done();
}
Future sendCmd(Map<String, dynamic> cmd) {
- var completer = new Completer();
+ var completer = new Completer.sync();
int id = cmd["id"];
outstandingCommands[id] = completer;
if (verbose) {
@@ -75,6 +96,34 @@
return completer.future;
}
+
+bool checkCurrentIsolate() {
+ if (currentIsolate != null) {
+ return true;
+ }
+ print("Need valid current isolate");
+ return false;
+}
+
+
+bool checkPaused() {
+ if (!checkCurrentIsolate()) return false;
+ if (currentIsolate.isPaused) return true;
+ print("Current isolate must be paused");
+ return false;
+}
+
+typedef void HandlerType(Map response);
+
+HandlerType showPromptAfter(void handler(Map response)) {
+ // Hide the command prompt immediately.
+ return (response) {
+ handler(response);
+ cmdo.show();
+ };
+}
+
+
void processCommand(String cmdLine) {
void huh() {
@@ -82,32 +131,37 @@
}
seqNum++;
+ cmdLine = cmdLine.trim();
var args = cmdLine.split(' ');
if (args.length == 0) {
return;
}
var command = args[0];
- var simple_commands =
+ var resume_commands =
{ 'r':'resume', 's':'stepOver', 'si':'stepInto', 'so':'stepOut'};
- if (simple_commands[command] != null) {
+ if (resume_commands[command] != null) {
+ if (!checkPaused()) return;
var cmd = { "id": seqNum,
- "command": simple_commands[command],
- "params": { "isolateId" : isolate_id } };
- sendCmd(cmd).then((result) => handleGenericResponse(result));
+ "command": resume_commands[command],
+ "params": { "isolateId" : currentIsolate.id } };
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleResumedResponse));
} else if (command == "bt") {
var cmd = { "id": seqNum,
"command": "getStackTrace",
- "params": { "isolateId" : isolate_id } };
- sendCmd(cmd).then((result) => handleStackTraceResponse(result));
+ "params": { "isolateId" : currentIsolate.id } };
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleStackTraceResponse));
} else if (command == "ll") {
var cmd = { "id": seqNum,
"command": "getLibraries",
- "params": { "isolateId" : isolate_id } };
- sendCmd(cmd).then((result) => handleGetLibraryResponse(result));
+ "params": { "isolateId" : currentIsolate.id } };
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleGetLibraryResponse));
} else if (command == "sbp" && args.length >= 2) {
var url, line;
- if (args.length == 2 && pausedLocation != null) {
- url = pausedLocation["url"];
+ if (args.length == 2 && currentIsolate.pausedLocation != null) {
+ url = currentIsolate.pausedLocation["url"];
assert(url != null);
line = int.parse(args[1]);
} else {
@@ -116,22 +170,25 @@
}
var cmd = { "id": seqNum,
"command": "setBreakpoint",
- "params": { "isolateId" : isolate_id,
+ "params": { "isolateId" : currentIsolate.id,
"url": url,
"line": line }};
- sendCmd(cmd).then((result) => handleSetBpResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleSetBpResponse));
} else if (command == "rbp" && args.length == 2) {
var cmd = { "id": seqNum,
"command": "removeBreakpoint",
- "params": { "isolateId" : isolate_id,
+ "params": { "isolateId" : currentIsolate.id,
"breakpointId": int.parse(args[1]) } };
- sendCmd(cmd).then((result) => handleGenericResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleGenericResponse));
} else if (command == "ls" && args.length == 2) {
var cmd = { "id": seqNum,
"command": "getScriptURLs",
- "params": { "isolateId" : isolate_id,
+ "params": { "isolateId" : currentIsolate.id,
"libraryId": int.parse(args[1]) } };
- sendCmd(cmd).then((result) => handleGetScriptsResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleGetScriptsResponse));
} else if (command == "eval" && args.length > 3) {
var expr = args.getRange(3, args.length).join(" ");
var target = args[1];
@@ -147,86 +204,106 @@
}
var cmd = { "id": seqNum,
"command": "evaluateExpr",
- "params": { "isolateId": isolate_id,
+ "params": { "isolateId": currentIsolate.id,
target: int.parse(args[2]),
"expression": expr } };
- sendCmd(cmd).then((result) => handleEvalResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleEvalResponse));
} else if (command == "po" && args.length == 2) {
var cmd = { "id": seqNum,
"command": "getObjectProperties",
- "params": { "isolateId" : isolate_id,
+ "params": { "isolateId" : currentIsolate.id,
"objectId": int.parse(args[1]) } };
- sendCmd(cmd).then((result) => handleGetObjPropsResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleGetObjPropsResponse));
} else if (command == "pl" && args.length >= 3) {
- var cmd;
- if (args.length == 3) {
- cmd = { "id": seqNum,
- "command": "getListElements",
- "params": { "isolateId" : isolate_id,
- "objectId": int.parse(args[1]),
- "index": int.parse(args[2]) } };
+ var cmd;
+ if (args.length == 3) {
+ cmd = { "id": seqNum,
+ "command": "getListElements",
+ "params": { "isolateId" : currentIsolate.id,
+ "objectId": int.parse(args[1]),
+ "index": int.parse(args[2]) } };
} else {
- cmd = { "id": seqNum,
- "command": "getListElements",
- "params": { "isolateId" : isolate_id,
- "objectId": int.parse(args[1]),
- "index": int.parse(args[2]),
- "length": int.parse(args[3]) } };
+ cmd = { "id": seqNum,
+ "command": "getListElements",
+ "params": { "isolateId" : currentIsolate.id,
+ "objectId": int.parse(args[1]),
+ "index": int.parse(args[2]),
+ "length": int.parse(args[3]) } };
}
- sendCmd(cmd).then((result) => handleGetListResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleGetListResponse));
} else if (command == "pc" && args.length == 2) {
var cmd = { "id": seqNum,
"command": "getClassProperties",
- "params": { "isolateId" : isolate_id,
+ "params": { "isolateId" : currentIsolate.id,
"classId": int.parse(args[1]) } };
- sendCmd(cmd).then((result) => handleGetClassPropsResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleGetClassPropsResponse));
} else if (command == "plib" && args.length == 2) {
var cmd = { "id": seqNum,
"command": "getLibraryProperties",
- "params": {"isolateId" : isolate_id,
+ "params": {"isolateId" : currentIsolate.id,
"libraryId": int.parse(args[1]) } };
- sendCmd(cmd).then((result) => handleGetLibraryPropsResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleGetLibraryPropsResponse));
} else if (command == "slib" && args.length == 3) {
var cmd = { "id": seqNum,
"command": "setLibraryProperties",
- "params": {"isolateId" : isolate_id,
+ "params": {"isolateId" : currentIsolate.id,
"libraryId": int.parse(args[1]),
"debuggingEnabled": args[2] } };
- sendCmd(cmd).then((result) => handleSetLibraryPropsResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleSetLibraryPropsResponse));
} else if (command == "pg" && args.length == 2) {
var cmd = { "id": seqNum,
"command": "getGlobalVariables",
- "params": { "isolateId" : isolate_id,
+ "params": { "isolateId" : currentIsolate.id,
"libraryId": int.parse(args[1]) } };
- sendCmd(cmd).then((result) => handleGetGlobalVarsResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleGetGlobalVarsResponse));
} else if (command == "gs" && args.length == 3) {
var cmd = { "id": seqNum,
"command": "getScriptSource",
- "params": { "isolateId" : isolate_id,
+ "params": { "isolateId" : currentIsolate.id,
"libraryId": int.parse(args[1]),
"url": args[2] } };
- sendCmd(cmd).then((result) => handleGetSourceResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleGetSourceResponse));
} else if (command == "tok" && args.length == 3) {
var cmd = { "id": seqNum,
"command": "getLineNumberTable",
- "params": { "isolateId" : isolate_id,
+ "params": { "isolateId" : currentIsolate.id,
"libraryId": int.parse(args[1]),
"url": args[2] } };
- sendCmd(cmd).then((result) => handleGetLineTableResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleGetLineTableResponse));
} else if (command == "epi" && args.length == 2) {
var cmd = { "id": seqNum,
"command": "setPauseOnException",
- "params": { "isolateId" : isolate_id,
+ "params": { "isolateId" : currentIsolate.id,
"exceptions": args[1] } };
- sendCmd(cmd).then((result) => handleGenericResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleGenericResponse));
} else if (command == "li") {
var cmd = { "id": seqNum, "command": "getIsolateIds" };
- sendCmd(cmd).then((result) => handleGetIsolatesResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleGetIsolatesResponse));
+ } else if (command == "sci" && args.length == 2) {
+ var id = int.parse(args[1]);
+ if (targetIsolates[id] != null) {
+ currentIsolate = targetIsolates[id];
+ print("Setting current target isolate to $id");
+ } else {
+ print("$id is not a valid isolate id");
+ }
} else if (command == "i" && args.length == 2) {
var cmd = { "id": seqNum,
"command": "interrupt",
"params": { "isolateId": int.parse(args[1]) } };
- sendCmd(cmd).then((result) => handleGenericResponse(result));
+ cmdo.hide();
+ sendCmd(cmd).then(showPromptAfter(handleGenericResponse));
} else if (command == "q") {
quitShell();
} else if (command == "h") {
@@ -249,10 +326,7 @@
} else if (kind == "object") {
return "(obj, id $id) $text";
} else if (kind == "function") {
- var location = value['location'] != null
- ? ", file '${value['location']['url']}'"
- ", token pos ${value['location']['tokenOffset']}"
- : "";
+ var location = formatLocation(value['location']);
var name = value['name'];
var signature = value['signature'];
return "(closure ${name}${signature} $location)";
@@ -269,7 +343,7 @@
}
-handleGetObjPropsResponse(response) {
+handleGetObjPropsResponse(Map response) {
Map props = response["result"];
int class_id = props["classId"];
if (class_id == -1) {
@@ -283,7 +357,7 @@
}
}
-handleGetListResponse(response) {
+handleGetListResponse(Map response) {
Map result = response["result"];
if (result["elements"] != null) {
// List slice.
@@ -304,7 +378,7 @@
}
-handleGetClassPropsResponse(response) {
+handleGetClassPropsResponse(Map response) {
Map props = response["result"];
assert(props["name"] != null);
int libId = props["libraryId"];
@@ -320,7 +394,7 @@
}
-handleGetLibraryPropsResponse(response) {
+handleGetLibraryPropsResponse(Map response) {
Map props = response["result"];
assert(props["url"] != null);
print(" library url: ${props["url"]}");
@@ -345,14 +419,14 @@
}
-handleSetLibraryPropsResponse(response) {
+handleSetLibraryPropsResponse(Map response) {
Map props = response["result"];
assert(props["debuggingEnabled"] != null);
print(" debugging enabled: ${props["debuggingEnabled"]}");
}
-handleGetGlobalVarsResponse(response) {
+handleGetGlobalVarsResponse(Map response) {
List globals = response["result"]["globals"];
for (int i = 0; i < globals.length; i++) {
printNamedObject(globals[i]);
@@ -360,27 +434,42 @@
}
-handleGetSourceResponse(response) {
+handleGetSourceResponse(Map response) {
Map result = response["result"];
String source = result["text"];
print("Source text:\n$source\n--------");
}
-handleGetLineTableResponse(response) {
+handleGetLineTableResponse(Map response) {
Map result = response["result"];
var info = result["lines"];
print("Line info table:\n$info");
}
-handleGetIsolatesResponse(response) {
+void handleGetIsolatesResponse(Map response) {
Map result = response["result"];
- print("Isolates: ${result["isolateIds"]}");
+ List ids = result["isolateIds"];
+ assert(ids != null);
+ print("List of isolates:");
+ for (int id in ids) {
+ TargetIsolate isolate = targetIsolates[id];
+ var state = (isolate != null) ? "running" : "<unknown isolate>";
+ if (isolate != null && isolate.isPaused) {
+ var loc = formatLocation(isolate.pausedLocation);
+ state = "paused at $loc";
+ }
+ var marker = " ";
+ if (currentIsolate != null && id == currentIsolate.id) {
+ marker = "*";
+ }
+ print("$marker $id $state");
+ }
}
-void handleGetLibraryResponse(response) {
+void handleGetLibraryResponse(Map response) {
Map result = response["result"];
List libs = result["libraries"];
print("Loaded libraries:");
@@ -391,7 +480,7 @@
}
-void handleGetScriptsResponse(response) {
+void handleGetScriptsResponse(Map response) {
Map result = response["result"];
List urls = result["urls"];
print("Loaded scripts:");
@@ -401,13 +490,13 @@
}
-void handleEvalResponse(response) {
+void handleEvalResponse(Map response) {
Map result = response["result"];
print(remoteObject(result));
}
-void handleSetBpResponse(response) {
+void handleSetBpResponse(Map response) {
Map result = response["result"];
var id = result["breakpointId"];
assert(id != null);
@@ -415,14 +504,23 @@
}
-void handleGenericResponse(response) {
+void handleGenericResponse(Map response) {
if (response["error"] != null) {
print("Error: ${response["error"]}");
}
}
+void handleResumedResponse(Map response) {
+ if (response["error"] != null) {
+ print("Error: ${response["error"]}");
+ return;
+ }
+ assert(currentIsolate != null);
+ currentIsolate.pausedLocation = null;
+}
-void handleStackTraceResponse(response) {
+
+void handleStackTraceResponse(Map response) {
Map result = response["result"];
List callFrames = result["callFrames"];
assert(callFrames != null);
@@ -432,10 +530,8 @@
void printStackFrame(frame_num, Map frame) {
var fname = frame["functionName"];
- var libId = frame["location"]["libraryId"];
- var url = frame["location"]["url"];
- var toff = frame["location"]["tokenOffset"];
- print("$frame_num $fname (url: $url token: $toff lib: $libId)");
+ var loc = formatLocation(frame["location"]);
+ print("$frame_num $fname ($loc)");
List locals = frame["locals"];
for (int i = 0; i < locals.length; i++) {
printNamedObject(locals[i]);
@@ -453,23 +549,65 @@
void handlePausedEvent(msg) {
assert(msg["params"] != null);
var reason = msg["params"]["reason"];
- isolate_id = msg["params"]["isolateId"];
- assert(isolate_id != null);
- pausedLocation = msg["params"]["location"];
- assert(pausedLocation != null);
+ int isolateId = msg["params"]["isolateId"];
+ assert(isolateId != null);
+ var isolate = targetIsolates[isolateId];
+ assert(isolate != null);
+ assert(!isolate.isPaused);
+ var location = msg["params"]["location"];;
+ assert(location != null);
+ isolate.pausedLocation = location;
if (reason == "breakpoint") {
- print("Isolate $isolate_id paused on breakpoint");
- print("location: $pausedLocation");
+ print("Isolate $isolateId paused on breakpoint");
+ print("location: ${formatLocation(location)}");
} else if (reason == "interrupted") {
- print("Isolate $isolate_id paused due to an interrupt");
+ print("Isolate $isolateId paused due to an interrupt");
+ print("location: ${formatLocation(location)}");
} else {
assert(reason == "exception");
var excObj = msg["params"]["exception"];
- print("Isolate $isolate_id paused on exception");
+ print("Isolate $isolateId paused on exception");
print(remoteObject(excObj));
}
}
+void handleIsolateEvent(msg) {
+ Map params = msg["params"];
+ assert(params != null);
+ var isolateId = params["id"];
+ var reason = params["reason"];
+ if (reason == "created") {
+ print("Isolate $isolateId has been created.");
+ assert(targetIsolates[isolateId] == null);
+ targetIsolates[isolateId] = new TargetIsolate(isolateId);
+ if (mainIsolate == null) {
+ mainIsolate = targetIsolates[isolateId];
+ currentIsolate = mainIsolate;
+ print("Current isolate set to ${currentIsolate.id}.");
+ }
+ } else {
+ assert(reason == "shutdown");
+ var isolate = targetIsolates.remove(isolateId);
+ assert(isolate != null);
+ if (isolate == mainIsolate) {
+ mainIsolate = null;
+ print("Main isolate ${isolate.id} has terminated.");
+ } else {
+ print("Isolate ${isolate.id} has terminated.");
+ }
+ if (isolate == currentIsolate) {
+ currentIsolate = mainIsolate;
+ if (currentIsolate == null && !targetIsolates.isEmpty) {
+ currentIsolate = targetIsolates.first;
+ }
+ if (currentIsolate != null) {
+ print("Setting current isolate to ${currentIsolate.id}.");
+ } else {
+ print("All isolates have terminated.");
+ }
+ }
+ }
+}
void processVmMessage(String jsonString) {
var msg = JSON.decode(jsonString);
@@ -477,33 +615,41 @@
return;
}
var event = msg["event"];
+ if (event == "isolate") {
+ cmdo.hide();
+ handleIsolateEvent(msg);
+ cmdo.show();
+ return;
+ }
if (event == "paused") {
+ cmdo.hide();
handlePausedEvent(msg);
+ cmdo.show();
return;
}
if (event == "breakpointResolved") {
Map params = msg["params"];
assert(params != null);
- print("BP ${params["breakpointId"]} resolved and "
- "set at line ${params["line"]}.");
- return;
- }
- if (event == "isolate") {
- Map params = msg["params"];
- assert(params != null);
- print("Isolate ${params["id"]} has been ${params["reason"]}.");
+ var isolateId = params["isolateId"];
+ var location = formatLocation(params["location"]);
+ cmdo.hide();
+ print("BP ${params["breakpointId"]} resolved in isolate $isolateId"
+ " at $location.");
+ cmdo.show();
return;
}
if (msg["id"] != null) {
var id = msg["id"];
if (outstandingCommands.containsKey(id)) {
+ var completer = outstandingCommands.remove(id);
if (msg["error"] != null) {
print("VM says: ${msg["error"]}");
+ // TODO(turnidge): Rework how hide/show happens. For now we
+ // show here explicitly.
+ cmdo.show();
} else {
- var completer = outstandingCommands[id];
completer.complete(msg);
}
- outstandingCommands.remove(id);
}
}
}
@@ -608,6 +754,30 @@
return 0;
}
+List<String> debuggerCommandCompleter(List<String> commandParts) {
+ List<String> completions = new List<String>();
+
+ // TODO(turnidge): Have a global command table and use it to for
+ // help messages, command completion, and command dispatching. For now
+ // we hardcode the list here.
+ //
+ // TODO(turnidge): Implement completion for arguments as well.
+ List<String> allCommands = ['q', 'bt', 'r', 's', 'so', 'si', 'sbp', 'rbp',
+ 'po', 'eval', 'pl', 'pc', 'll', 'plib', 'slib',
+ 'pg', 'ls', 'gs', 'tok', 'epi', 'li', 'i', 'h'];
+
+ // Completion of first word in the command.
+ if (commandParts.length == 1) {
+ String prefix = commandParts.last;
+ for (String command in allCommands) {
+ if (command.startsWith(prefix)) {
+ completions.add(command);
+ }
+ }
+ }
+
+ return completions;
+}
void debuggerMain() {
outstandingCommands = new Map<int, Completer>();
@@ -628,20 +798,46 @@
// TODO(floitsch): do we want to print the stack trace?
quitShell();
});
- stdinSubscription = stdin.transform(UTF8.decoder)
- .transform(new LineSplitter())
- .listen((String line) => processCommand(line));
+ cmdo = new Commando(stdin, stdout, processCommand,
+ completer : debuggerCommandCompleter);
});
}
-void main(List<String> arguments) {
- if (arguments.length > 0) {
- arguments = <String>['--debug', '--verbose_debug']..addAll(arguments);
- Process.start(Platform.executable, arguments).then((Process process) {
- process.stdin.close();
- process.exitCode.then((int exitCode) {
- print('${arguments.join(" ")} exited with $exitCode');
- });
+void main(List<String> args) {
+ if (args.length > 0) {
+ if (verbose) {
+ args = <String>['--debug', '--verbose_debug']..addAll(args);
+ } else {
+ args = <String>['--debug']..addAll(args);
+ }
+ Process.start(Platform.executable, args).then((Process process) {
+ targetProcess = process;
+ process.stdin.close();
+
+ // TODO(turnidge): For now we only show full lines of output
+ // from the debugged process. Should show each character.
+ process.stdout
+ .transform(UTF8.decoder)
+ .transform(new LineSplitter())
+ .listen((String line) {
+ // Hide/show command prompt across asynchronous output.
+ if (cmdo != null) {
+ cmdo.hide();
+ }
+ print("$line");
+ if (cmdo != null) {
+ cmdo.show();
+ }
+ });
+
+ process.exitCode.then((int exitCode) {
+ if (exitCode == 0) {
+ print('Program exited normally.');
+ } else {
+ print('Program exited with code $exitCode.');
+ }
+ });
+
debuggerMain();
});
} else {
diff --git a/tools/ddbg/lib/commando.dart b/tools/ddbg/lib/commando.dart
new file mode 100644
index 0000000..cb1fef2
--- /dev/null
+++ b/tools/ddbg/lib/commando.dart
@@ -0,0 +1,712 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:math';
+
+import 'terminfo.dart';
+
+typedef List<String> CommandCompleter(List<String> commandParts);
+
+class Commando {
+ // Ctrl keys
+ static const runeCtrlA = 0x01;
+ static const runeCtrlB = 0x02;
+ static const runeCtrlD = 0x04;
+ static const runeCtrlE = 0x05;
+ static const runeCtrlF = 0x06;
+ static const runeTAB = 0x09;
+ static const runeNewline = 0x0a;
+ static const runeCtrlK = 0x0b;
+ static const runeCtrlL = 0x0c;
+ static const runeCtrlN = 0x0e;
+ static const runeCtrlP = 0x10;
+ static const runeCtrlU = 0x15;
+ static const runeCtrlY = 0x19;
+ static const runeESC = 0x1b;
+ static const runeSpace = 0x20;
+ static const runeDEL = 0x7F;
+
+ Commando(this._stdin,
+ this._stdout,
+ this._handleCommand,
+ {this.prompt : '> ', this.completer : null}) {
+ _stdin.echoMode = false;
+ _stdin.lineMode = false;
+ _screenWidth = _term.cols - 1;
+ _writePrompt();
+ _stdinSubscription =
+ _stdin.transform(UTF8.decoder).listen(_handleText, onDone:done);
+ }
+
+ void _handleText(String text) {
+ try {
+ if (!_promptShown) {
+ _bufferedInput.write(text);
+ return;
+ }
+
+ var runes = text.runes.toList();
+ var pos = 0;
+ while (pos < runes.length) {
+ if (!_promptShown) {
+ // A command was processed which hid the prompt. Buffer
+ // the rest of the input.
+ //
+ // TODO(turnidge): Here and elsewhere in the file I pass
+ // runes to String.fromCharCodes. Does this work?
+ _bufferedInput.write(
+ new String.fromCharCodes(runes.skip(pos)));
+ return;
+ }
+
+ var rune = runes[pos];
+
+ // Count consecutive tabs because double-tab is meaningful.
+ if (rune == runeTAB) {
+ _tabCount++;
+ } else {
+ _tabCount = 0;
+ }
+
+ if (_isControlRune(rune)) {
+ pos += _handleControlSequence(runes, pos);
+ } else {
+ pos += _handleRegularSequence(runes, pos);
+ }
+ }
+ } catch(e, trace) {
+ stderr.writeln('\nUnexpected exception: $e');
+ stderr.writeln(trace);
+ stderr.close().then((_) {
+ done();
+ });
+ }
+ }
+
+ int _handleControlSequence(List<int> runes, int pos) {
+ var runesConsumed = 1; // Most common result.
+ var char = runes[pos];
+ switch (char) {
+ case runeCtrlA:
+ _home();
+ break;
+
+ case runeCtrlB:
+ _leftArrow();
+ break;
+
+ case runeCtrlD:
+ if (_currentLine.length == 0) {
+ // ^D on an empty line means quit.
+ _stdout.writeln();
+ done();
+ } else {
+ _delete();
+ }
+ break;
+
+ case runeCtrlE:
+ _end();
+ break;
+
+ case runeCtrlF:
+ _rightArrow();
+ break;
+
+ case runeTAB:
+ if (_complete(_tabCount > 1)) {
+ _tabCount = 0;
+ }
+ break;
+
+ case runeNewline:
+ _newline();
+ break;
+
+ case runeCtrlK:
+ _kill();
+ break;
+
+ case runeCtrlL:
+ _clearScreen();
+ break;
+
+ case runeCtrlN:
+ _historyNext();
+ break;
+
+ case runeCtrlP:
+ _historyPrevious();
+ break;
+
+ case runeCtrlU:
+ _clearLine();
+ break;
+
+ case runeCtrlY:
+ _yank();
+ break;
+
+ case runeESC:
+ // Check to see if this is an arrow key.
+ if (pos + 2 < runes.length && // must be a 3 char sequence.
+ runes[pos + 1] == 0x5b) { // second char must be '['.
+ switch (runes[pos + 2]) {
+ case 0x41: // ^[[A = up arrow
+ _historyPrevious();
+ runesConsumed = 3;
+ break;
+
+ case 0x42: // ^[[B = down arrow
+ _historyNext();
+ runesConsumed = 3;
+ break;
+
+ case 0x43: // ^[[C = right arrow
+ _rightArrow();
+ runesConsumed = 3;
+ break;
+
+ case 0x44: // ^[[D = left arrow
+ _leftArrow();
+ runesConsumed = 3;
+ break;
+
+ default:
+ // Ignore the escape character.
+ break;
+ }
+ }
+ break;
+
+ case runeDEL:
+ _backspace();
+ break;
+
+ default:
+ // Ignore the escape character.
+ break;
+ }
+ return runesConsumed;
+ }
+
+ int _handleRegularSequence(List<int> runes, int pos) {
+ var len = pos + 1;
+ while (len < runes.length && !_isControlRune(runes[len])) {
+ len++;
+ }
+ _addChars(runes.getRange(pos, len));
+ return len;
+ }
+
+ bool _isControlRune(int char) {
+ return (char >= 0x00 && char < 0x20) || (char == 0x7f);
+ }
+
+ void done() {
+ _stdin.echoMode = true;
+ _stdin.lineMode = true;
+ _stdinSubscription.cancel();
+ }
+
+ void _writePromptAndLine() {
+ _writePrompt();
+ var pos = _writeRange(_currentLine, 0, _currentLine.length);
+ _cursorPos = _move(pos, _cursorPos);
+ }
+
+ void _writePrompt() {
+ _stdout.write(prompt);
+ }
+
+ void _addChars(Iterable<int> chars) {
+ var newLine = [];
+ newLine..addAll(_currentLine.take(_cursorPos))
+ ..addAll(chars)
+ ..addAll(_currentLine.skip(_cursorPos));
+ _update(newLine, (_cursorPos + chars.length));
+ }
+
+ void _backspace() {
+ if (_cursorPos == 0) {
+ return;
+ }
+
+ var newLine = [];
+ newLine..addAll(_currentLine.take(_cursorPos - 1))
+ ..addAll(_currentLine.skip(_cursorPos));
+ _update(newLine, (_cursorPos - 1));
+ }
+
+ void _delete() {
+ if (_cursorPos == _currentLine.length) {
+ return;
+ }
+
+ var newLine = [];
+ newLine..addAll(_currentLine.take(_cursorPos))
+ ..addAll(_currentLine.skip(_cursorPos + 1));
+ _update(newLine, _cursorPos);
+ }
+
+ void _home() {
+ _updatePos(0);
+ }
+
+ void _end() {
+ _updatePos(_currentLine.length);
+ }
+
+ void _clearScreen() {
+ _stdout.write(_term.clear);
+ _writePromptAndLine();
+ }
+
+ void _kill() {
+ var newLine = [];
+ newLine.addAll(_currentLine.take(_cursorPos));
+ _killBuffer = _currentLine.skip(_cursorPos).toList();
+ _update(newLine, _cursorPos);
+ }
+
+ void _clearLine() {
+ _update([], 0);
+ }
+
+ void _yank() {
+ var newLine = [];
+ newLine..addAll(_currentLine.take(_cursorPos))
+ ..addAll(_killBuffer)
+ ..addAll(_currentLine.skip(_cursorPos));
+ _update(newLine, (_cursorPos + _killBuffer.length));
+ }
+
+ static String _trimLeadingSpaces(String line) {
+ bool _isSpace(int rune) {
+ return rune == runeSpace;
+ }
+ return new String.fromCharCodes(line.runes.skipWhile(_isSpace));
+ }
+
+ static String _sharedPrefix(String one, String two) {
+ var len = min(one.length, two.length);
+ var runesOne = one.runes.toList();
+ var runesTwo = two.runes.toList();
+ var pos;
+ for (pos = 0; pos < len; pos++) {
+ if (runesOne[pos] != runesTwo[pos]) {
+ break;
+ }
+ }
+ var shared = new String.fromCharCodes(runesOne.take(pos));
+ return shared;
+ }
+
+ bool _complete(bool showCompletions) {
+ if (completer == null) {
+ return false;
+ }
+
+ var linePrefix = _currentLine.take(_cursorPos).toList();
+ List<String> commandParts =
+ _trimLeadingSpaces(new String.fromCharCodes(linePrefix)).split(' ');
+ List<String> completionList = completer(commandParts);
+ var completion = '';
+
+ if (completionList.length == 0) {
+ // The current line admits no possible completion.
+ return false;
+
+ } else if (completionList.length == 1) {
+ // There is a single, non-ambiguous completion for the current line.
+ completion = completionList[0];
+
+ // If we are at the end of the line, add a space to signal that
+ // the completion is unambiguous.
+ if (_currentLine.length == _cursorPos) {
+ completion = completion + ' ';
+ }
+ } else {
+ // There are ambiguous completions. Find the longest common
+ // shared prefix of all of the completions.
+ completion = completionList.fold(completionList[0], _sharedPrefix);
+ }
+
+ var lastWord = commandParts.last;
+ if (completion == lastWord) {
+ // The completion does not add anything.
+ if (showCompletions) {
+ // User hit double-TAB. Show them all possible completions.
+ _move(_cursorPos, _currentLine.length);
+ _stdout.writeln();
+ _stdout.writeln(completionList);
+ _writePromptAndLine();
+ }
+ return false;
+ } else {
+ // Apply the current completion.
+ var completionRunes = completion.runes.toList();
+
+ var newLine = [];
+ newLine..addAll(linePrefix)
+ ..addAll(completionRunes.skip(lastWord.length))
+ ..addAll(_currentLine.skip(_cursorPos));
+ _update(newLine, _cursorPos + completionRunes.length - lastWord.length);
+ return true;
+ }
+ }
+
+ void _newline() {
+ _addLineToHistory(_currentLine);
+ _linePos = _lines.length;
+
+ _end();
+ _stdout.writeln();
+
+ // Call the user's command handler.
+ _handleCommand(new String.fromCharCodes(_currentLine));
+
+ _currentLine = [];
+ _cursorPos = 0;
+ _linePos = _lines.length;
+ if (_promptShown) {
+ _writePrompt();
+ }
+ }
+
+ void _leftArrow() {
+ _updatePos(_cursorPos - 1);
+ }
+
+ void _rightArrow() {
+ _updatePos(_cursorPos + 1);
+ }
+
+ void _addLineToHistory(List<int> line) {
+ if (_tempLineAdded) {
+ _lines.removeLast();
+ _tempLineAdded = false;
+ }
+ if (line.length > 0) {
+ _lines.add(line);
+ }
+ }
+
+ void _addTempLineToHistory(List<int> line) {
+ _lines.add(line);
+ _tempLineAdded = true;
+ }
+
+ void _replaceHistory(List<int> line, int linePos) {
+ _lines[linePos] = line;
+ }
+
+ void _historyPrevious() {
+ if (_linePos == 0) {
+ return;
+ }
+
+ if (_linePos == _lines.length) {
+ // The current in-progress line gets temporarily stored in history.
+ _addTempLineToHistory(_currentLine);
+ } else {
+ // Any edits get committed to history.
+ _replaceHistory(_currentLine, _linePos);
+ }
+
+ _linePos -= 1;
+ var line = _lines[_linePos];
+ _update(line, line.length);
+ }
+
+ void _historyNext() {
+ // For the very first command, _linePos (0) will exceed
+ // (_lines.length - 1) (-1) so we use a ">=" here instead of an "==".
+ if (_linePos >= (_lines.length - 1)) {
+ return;
+ }
+
+ // Any edits get committed to history.
+ _replaceHistory(_currentLine, _linePos);
+
+ _linePos += 1;
+ var line = _lines[_linePos];
+ _update(line, line.length);
+ }
+
+ void _updatePos(int newCursorPos) {
+ if (newCursorPos < 0) {
+ return;
+ }
+ if (newCursorPos > _currentLine.length) {
+ return;
+ }
+
+ _cursorPos = _move(_cursorPos, newCursorPos);
+ }
+
+ void _update(List<int> newLine, int newCursorPos) {
+ var pos = _cursorPos;
+ var diffPos;
+ var sharedLen = min(_currentLine.length, newLine.length);
+
+ // Find first difference.
+ for (diffPos = 0; diffPos < sharedLen; diffPos++) {
+ if (_currentLine[diffPos] != newLine[diffPos]) {
+ break;
+ }
+ }
+
+ // Move the cursor to where the difference begins.
+ pos = _move(pos, diffPos);
+
+ // Write the new text.
+ pos = _writeRange(newLine, pos, newLine.length);
+
+ // Clear any extra characters at the end.
+ pos = _clearRange(pos, _currentLine.length);
+
+ // Move the cursor back to the input point.
+ _cursorPos = _move(pos, newCursorPos);
+ _currentLine = newLine;
+ }
+
+ void hide() {
+ if (!_promptShown) {
+ return;
+ }
+ _promptShown = false;
+ // We need to erase everything, including the prompt.
+ var curLine = _getLine(_cursorPos);
+ var lastLine = _getLine(_currentLine.length);
+
+ // Go to last line.
+ if (curLine < lastLine) {
+ for (var i = 0; i < (lastLine - curLine); i++) {
+ // This moves us to column 0.
+ _stdout.write(_term.cursorDown);
+ }
+ curLine = lastLine;
+ } else {
+ // Move to column 0.
+ _stdout.write('\r');
+ }
+
+ // Work our way up, clearing lines.
+ while (true) {
+ _stdout.write(_term.clrEOL);
+ if (curLine > 0) {
+ _stdout.write(_term.cursorUp);
+ } else {
+ break;
+ }
+ }
+ }
+
+ void show() {
+ if (_promptShown) {
+ return;
+ }
+ _promptShown = true;
+ _writePromptAndLine();
+
+ // If input was buffered while the prompt was hidden, process it
+ // now.
+ if (!_bufferedInput.isEmpty) {
+ var input = _bufferedInput.toString();
+ _bufferedInput.clear();
+ _handleText(input);
+ }
+ }
+
+ int _writeRange(List<int> text, int pos, int writeToPos) {
+ if (pos >= writeToPos) {
+ return pos;
+ }
+ while (pos < writeToPos) {
+ var margin = _nextMargin(pos);
+ var limit = min(writeToPos, margin);
+ _stdout.write(new String.fromCharCodes(text.getRange(pos, limit)));
+ pos = limit;
+ if (pos == margin) {
+ _stdout.write('\n');
+ }
+ }
+ return pos;
+ }
+
+ int _clearRange(int pos, int clearToPos) {
+ if (pos >= clearToPos) {
+ return pos;
+ }
+ while (true) {
+ var limit = _nextMargin(pos);
+ _stdout.write(_term.clrEOL);
+ if (limit >= clearToPos) {
+ return pos;
+ }
+ _stdout.write('\n');
+ pos = limit;
+ }
+ }
+
+ int _move(int pos, int newPos) {
+ if (pos == newPos) {
+ return pos;
+ }
+
+ var curCol = _getCol(pos);
+ var curLine = _getLine(pos);
+ var newCol = _getCol(newPos);
+ var newLine = _getLine(newPos);
+
+ if (curLine > newLine) {
+ for (var i = 0; i < (curLine - newLine); i++) {
+ _stdout.write(_term.cursorUp);
+ }
+ }
+ if (curLine < newLine) {
+ for (var i = 0; i < (newLine - curLine); i++) {
+ _stdout.write(_term.cursorDown);
+ }
+
+ // Moving down resets column to zero, oddly.
+ curCol = 0;
+ }
+ if (curCol > newCol) {
+ for (var i = 0; i < (curCol - newCol); i++) {
+ _stdout.write(_term.cursorBack);
+ }
+ }
+ if (curCol < newCol) {
+ for (var i = 0; i < (newCol - curCol); i++) {
+ _stdout.write(_term.cursorForward);
+ }
+ }
+
+ return newPos;
+ }
+
+ int _nextMargin(int pos) {
+ var truePos = pos + prompt.length;
+ var curLine = _getLine(pos);
+ return ((truePos ~/ _screenWidth) + 1) * _screenWidth - prompt.length;
+ }
+
+ int _getLine(int pos) {
+ var truePos = pos + prompt.length;
+ return truePos ~/ _screenWidth;
+ }
+
+ int _getCol(int pos) {
+ var truePos = pos + prompt.length;
+ return truePos % _screenWidth;
+ }
+
+ Stdin _stdin;
+ StreamSubscription _stdinSubscription;
+ IOSink _stdout;
+ final _handleCommand;
+ final String prompt;
+ bool _promptShown = true;
+ final CommandCompleter completer;
+ TermInfo _term = new TermInfo();
+
+ // TODO(turnidge): Update screenwidth when we clear the screen. See
+ // if we can get screen resize events too.
+ int _screenWidth;
+ List<int> _currentLine = []; // A list of runes.
+ StringBuffer _bufferedInput = new StringBuffer();
+ List<List<int>> _lines = [];
+
+ // When using the command history, the current line is temporarily
+ // added to the history to allow the user to return to it. This
+ // values tracks whether the history has a temporary line at the end.
+ bool _tempLineAdded = false;
+ int _linePos = 0;
+ int _cursorPos = 0;
+ int _tabCount = 0;
+ List<int> _killBuffer = [];
+}
+
+
+// Demo code.
+
+
+List<String> _myCompleter(List<String> commandTokens) {
+ List<String> completions = new List<String>();
+
+ // First word completions.
+ if (commandTokens.length <= 1) {
+ String prefix = '';
+ if (commandTokens.length == 1) {
+ prefix = commandTokens.first;
+ }
+ if ('quit'.startsWith(prefix)) {
+ completions.add('quit');
+ }
+ if ('help'.startsWith(prefix)) {
+ completions.add('help');
+ }
+ if ('happyface'.startsWith(prefix)) {
+ completions.add('happyface');
+ }
+ }
+
+ // Complete 'foobar' or 'gondola' anywhere in string.
+ String lastWord = commandTokens.last;
+ if ('foobar'.startsWith(lastWord)) {
+ completions.add('foobar');
+ }
+ if ('gondola'.startsWith(lastWord)) {
+ completions.add('gondola');
+ }
+
+ return completions;
+}
+
+
+int _helpCount = 0;
+Commando cmdo;
+
+
+void _handleCommand(String rawCommand) {
+ String command = rawCommand.trim();
+ if (command == 'quit') {
+ cmdo.done();
+ } else if (command == 'help') {
+ switch (_helpCount) {
+ case 0:
+ print('I will not help you.');
+ break;
+ case 1:
+ print('I mean it.');
+ break;
+ case 2:
+ print('Seriously.');
+ break;
+ case 100:
+ print('Well now.');
+ break;
+ default:
+ print("Okay. Type 'quit' to quit");
+ break;
+ }
+ _helpCount++;
+ } else if (command == 'happyface') {
+ print(':-)');
+ } else {
+ print('Received command($command)');
+ }
+}
+
+
+void main() {
+ stdout.writeln('[Commando demo]');
+ cmd = new Commando(stdin, stdout, _handleCommand,
+ completer:_myCompleter);
+}
diff --git a/tools/ddbg/lib/terminfo.dart b/tools/ddbg/lib/terminfo.dart
new file mode 100644
index 0000000..4521031
--- /dev/null
+++ b/tools/ddbg/lib/terminfo.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import 'dart:io';
+
+int _tputGetInteger(String capName) {
+ var result = Process.runSync('tput', ['$capName'], stdoutEncoding:UTF8);
+ if (result.exitCode != 0) {
+ return 0;
+ }
+ return int.parse(result.stdout);
+}
+
+String _tputGetSequence(String capName) {
+ var result = Process.runSync('tput', ['$capName'], stdoutEncoding:UTF8);
+ if (result.exitCode != 0) {
+ return '';
+ }
+ return result.stdout;
+}
+
+class TermInfo {
+ TermInfo() {
+ resize();
+ }
+
+ int get lines => _lines;
+ int get cols => _cols;
+
+ int _lines;
+ int _cols;
+
+ void resize() {
+ _lines = _tputGetInteger('lines');
+ _cols = _tputGetInteger('cols');
+ }
+
+ // Back one character.
+ final String cursorBack = _tputGetSequence('cub1');
+
+ // Forward one character.
+ final String cursorForward = _tputGetSequence('cuf1');
+
+ // Up one character.
+ final String cursorUp = _tputGetSequence('cuu1');
+
+ // Down one character.
+ final String cursorDown = _tputGetSequence('cud1');
+
+ // Clear to end of line.
+ final String clrEOL = _tputGetSequence('el');
+
+ // Clear screen and home cursor.
+ final String clear = _tputGetSequence('clear');
+}
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart
index 5cf230b..75c699c 100644
--- a/tools/dom/src/native_DOMImplementation.dart
+++ b/tools/dom/src/native_DOMImplementation.dart
@@ -387,6 +387,11 @@
static String addTrailingDot(String str) => '${str}.';
+ static String demangle(String str) {
+ var atPos = str.indexOf('@');
+ return atPos == -1 ? str : str.substring(0, atPos);
+ }
+
static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError;
static bool _isBuiltinType(ClassMirror cls) {
diff --git a/tools/publish_barback.py b/tools/publish_barback.py
index a4b9c3d..87752b0 100755
--- a/tools/publish_barback.py
+++ b/tools/publish_barback.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+# 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.
#
@@ -31,24 +31,21 @@
HOME = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
BARBACK = os.path.join(HOME, 'pkg', 'barback')
- (channel, major, minor, build, patch) = utils.ReadVersionFile()
+ (channel, major, minor, service, qualifier) = utils.ReadVersionFile()
+ major = int(major)
+ minor = int(minor)
+ service = int(service)
# The bleeding_edge branch has a fixed version number of 0.1.x.y. Don't allow
# users to publish packages from there.
if (major == 0 and minor <= 1) or channel == 'be':
print 'Error: Do not run this script from a bleeding_edge checkout.'
- return -1
+ #return -1
# Convert the version to semver syntax.
- # TODO(rnystrom): Change this when the SDK's version numbering scheme is
- # decided.
- if patch != 0:
- version = '%d.%d.%d+%d' % (major, minor, build, patch)
- else:
- version = '%d.%d.%d' % (major, minor, build)
+ version = '%d.%d.%d+%s' % (major, minor, service, qualifier)
- # Copy the package to a temp directory so we can fill in the versions in its
- # pubspec.
+ # Copy the package to a temp directory so we can fill in its pubspec.
tmpDir = tempfile.mkdtemp()
shutil.copytree(os.path.join(HOME, BARBACK), os.path.join(tmpDir, 'barback'))
@@ -58,16 +55,21 @@
# Fill in the SDK version constraint. It pins barback to the current version
# of the SDK with a small amount of wiggle room for hotfixes.
- if major < 1:
- # No breaking changes until after 1.0.
- # TODO(rnystrom): Remove this once 1.0 has shipped.
- constraint = '>=%d.%d.%d <1.1.0' % (major, minor, build)
- else:
- constraint = '>=%d.%d.%d <%d.%d.0' % (major, minor, build, major, minor + 1)
+ constraint = '>=%d.%d.%d <%d.%d.0' % (major, minor, service, major, minor + 1)
# Fill in the SDK version constraint.
pubspec = pubspec.replace('$SDK_CONSTRAINT$', constraint)
+ # Give barback a new version that roughly mirrors the SDK, like so:
+ # SDK 1.2.3+4 --> barback 0.12.3+4.
+ barback_version = 'version: 0.%d.%d+%s # Set by publish_barback.py.' % (
+ 10 + minor, service, qualifier)
+ pubspec = pubspec.replace(
+ 'version: 0.9.0 # Replaced by publish_barback.py. Do not edit.',
+ barback_version)
+
+ return
+
with open(pubspecPath, 'w') as pubspecFile:
pubspecFile.write(pubspec)
diff --git a/tools/test.dart b/tools/test.dart
index 4d71459..c96084d 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -178,7 +178,9 @@
for (String key in selectors.keys) {
if (key == 'co19') {
testSuites.add(new Co19TestSuite(conf));
- } else if (conf['runtime'] == 'vm' && key == 'vm') {
+ } else if (conf['compiler'] == 'none' &&
+ conf['runtime'] == 'vm' &&
+ key == 'vm') {
// vm tests contain both cc tests (added here) and dart tests (added
// in [TEST_SUITE_DIRECTORIES]).
testSuites.add(new VMTestSuite(conf));
@@ -282,10 +284,10 @@
return completer.future;
}
-void main() {
+void main(List<String> arguments) {
deleteTemporaryDartDirectories().then((_) {
var optionsParser = new TestOptionsParser();
- var configurations = optionsParser.parse(new Options().arguments);
+ var configurations = optionsParser.parse(arguments);
if (configurations != null && configurations.length > 0) {
testConfigurations(configurations);
}
diff --git a/tools/testing/dart/android.dart b/tools/testing/dart/android.dart
index 940d47c..6a2fc4a 100644
--- a/tools/testing/dart/android.dart
+++ b/tools/testing/dart/android.dart
@@ -205,7 +205,7 @@
*/
Future adbRoot() {
var adbRootCompleter = new Completer();
- return _adbCommand(['root']).then((_) {
+ _adbCommand(['root']).then((_) {
// TODO: Figure out a way to wait until the adb daemon was restarted in
// 'root mode' on the device.
new Timer(_adbServerStartupTime, () => adbRootCompleter.complete(true));
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart
index 8cdc3cd..501f765 100644
--- a/tools/testing/dart/browser_controller.dart
+++ b/tools/testing/dart/browser_controller.dart
@@ -315,7 +315,7 @@
// Get the version and log that.
return getVersion().then((version) {
_logEvent("Got version: $version");
- return new Directory('').createTemp().then((userDir) {
+ return Directory.systemTemp.createTemp().then((userDir) {
_cleanup = () { userDir.deleteSync(recursive: true); };
_createLaunchHTML(userDir.path, url);
var args = ["${userDir.path}/launch.html"];
@@ -379,7 +379,7 @@
if (!success) return false;
_logEvent("Got version: $_version");
- return new Directory('').createTemp().then((userDir) {
+ return Directory.systemTemp.createTemp().then((userDir) {
_cleanup = () { userDir.deleteSync(recursive: true); };
var args = ["--user-data-dir=${userDir.path}", url,
"--disable-extensions", "--disable-popup-blocking",
@@ -608,7 +608,7 @@
version = versionResult.stdout;
_logEvent("Got version: $version");
- return new Directory('').createTemp().then((userDir) {
+ return Directory.systemTemp.createTemp().then((userDir) {
_createPreferenceFile(userDir.path);
_cleanup = () { userDir.deleteSync(recursive: true); };
var args = ["-profile", "${userDir.path}",
@@ -854,7 +854,7 @@
// We don't do anything, this browser is currently being killed and
// replaced. The browser here can be null if we decided to kill the
// browser.
- } else if (status.currentTest != null && status.currentTest.id != testId) {
+ } else if (status.currentTest != null && status.currentTest.id == testId) {
status.currentTest.lastKnownMessage = output;
}
}
diff --git a/tools/testing/dart/http_server.dart b/tools/testing/dart/http_server.dart
index 9348763..5a55119 100644
--- a/tools/testing/dart/http_server.dart
+++ b/tools/testing/dart/http_server.dart
@@ -6,7 +6,6 @@
import 'dart:async';
import 'dart:io';
-import 'dart:isolate';
import 'test_suite.dart'; // For TestUtils.
// TODO(efortuna): Rewrite to not use the args library and simply take an
// expected number of arguments, so test.dart doesn't rely on the args library?
@@ -38,7 +37,7 @@
// http://host:port/root_packages/X -> $BuildDir/packages/X
// Issue: 8368
-main() {
+main(List<String> arguments) {
/** Convenience method for local testing. */
var parser = new ArgParser();
parser.addOption('port', abbr: 'p',
@@ -57,14 +56,14 @@
parser.addOption('runtime', help: 'The runtime we are using (for csp flags).',
defaultsTo: 'none');
- var args = parser.parse(new Options().arguments);
+ var args = parser.parse(arguments);
if (args['help']) {
print(parser.getUsage());
} else {
// Pretend we're running test.dart so that TestUtils doesn't get confused
// about the "current directory." This is only used if we're trying to run
// this file independently for local testing.
- TestUtils.testScriptPath = new Path(new Options().script)
+ TestUtils.testScriptPath = new Path(Platform.script.path)
.directoryPath
.join(new Path('../../test.dart'))
.canonicalize()
diff --git a/tools/testing/dart/launch_browser.dart b/tools/testing/dart/launch_browser.dart
index 0b752d3..269d151 100644
--- a/tools/testing/dart/launch_browser.dart
+++ b/tools/testing/dart/launch_browser.dart
@@ -20,14 +20,13 @@
print("Supported browsers: ${Browser.SUPPORTED_BROWSERS}");
}
-void main() {
- var args = new Options().arguments;
- if (args.length != 2) {
+void main(List<String> arguments) {
+ if (arguments.length != 2) {
print("Wrong number of arguments, please pass in exactly two arguments");
printHelp();
return;
}
- var name = args[0];
+ var name = arguments[0];
if (!Browser.supportedBrowser(name)) {
print("Specified browser not supported");
@@ -37,5 +36,5 @@
var executable = Locations.getBrowserLocation(name, {});
var browser = new Browser.byName(name, executable);
- browser.start(args[1]);
+ browser.start(arguments[1]);
}
diff --git a/tools/testing/dart/multitest.dart b/tools/testing/dart/multitest.dart
index e61f21b..5541564 100644
--- a/tools/testing/dart/multitest.dart
+++ b/tools/testing/dart/multitest.dart
@@ -276,5 +276,5 @@
if (!dir.existsSync()) {
dir.createSync();
}
- return new Path(new File(path).fullPathSync());
+ return new Path(new File(path).absolute.path);
}
diff --git a/tools/testing/dart/record_and_replay.dart b/tools/testing/dart/record_and_replay.dart
index 90af781..f60be45 100644
--- a/tools/testing/dart/record_and_replay.dart
+++ b/tools/testing/dart/record_and_replay.dart
@@ -6,7 +6,6 @@
import 'dart:io';
import 'dart:convert';
-import 'dart:convert';
import 'test_runner.dart';
import 'utils.dart' show Path;
diff --git a/tools/testing/dart/test_controller.js b/tools/testing/dart/test_controller.js
index 1b03546..806a7f9 100644
--- a/tools/testing/dart/test_controller.js
+++ b/tools/testing/dart/test_controller.js
@@ -34,7 +34,7 @@
var recordedEventList = [];
var timestampOfFirstEvent = null;
-var STATUS_UPDATE_INTERVALL = 5000; // Every 10 seconds.
+var STATUS_UPDATE_INTERVALL = 10000;
function getCurrentTimestamp() {
if (timestampOfFirstEvent == null) {
@@ -74,9 +74,7 @@
function printToConsole(message) {
var consoleAvailable = typeof console === 'object';
- if (!consoleAvailable) {
- printToDOM(message);
- } else {
+ if (consoleAvailable) {
console.log(message);
}
}
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart
index feda5b9..48f1310 100644
--- a/tools/testing/dart/test_options.dart
+++ b/tools/testing/dart/test_options.dart
@@ -5,7 +5,6 @@
library test_options_parser;
import "dart:io";
-import "dart:math";
import "drt_updater.dart";
import "test_suite.dart";
diff --git a/tools/testing/dart/test_progress.dart b/tools/testing/dart/test_progress.dart
index 80b00a0..ea31bfc 100644
--- a/tools/testing/dart/test_progress.dart
+++ b/tools/testing/dart/test_progress.dart
@@ -7,7 +7,6 @@
import "dart:async";
import "dart:io";
import "dart:io" as io;
-import "http_server.dart" as http_server;
import "status_file_parser.dart";
import "test_runner.dart";
import "test_suite.dart";
@@ -323,17 +322,9 @@
class LeftOverTempDirPrinter extends EventListener {
final MIN_NUMBER_OF_TEMP_DIRS = 50;
- static Directory _getTemporaryDirectory() {
- // Dir will be located in the system temporary directory.
- var dir = new Directory('').createTempSync();
- var path = new Path(dir.path).directoryPath;
- dir.deleteSync();
- return new Directory(path.toNativePath());
- }
-
static RegExp _getTemporaryDirectoryRegexp() {
// These are the patterns of temporary directory names created by
- // 'Directory.createTempSync()' on linux/macos and windows.
+ // 'Directory.systemTemp.createTemp()' on linux/macos and windows.
if (['macos', 'linux'].contains(Platform.operatingSystem)) {
return new RegExp(r'^temp_dir1_......$');
} else {
@@ -343,7 +334,7 @@
static Stream<Directory> getLeftOverTemporaryDirectories() {
var regExp = _getTemporaryDirectoryRegexp();
- return _getTemporaryDirectory().list().where(
+ return Directory.systemTemp.list().where(
(FileSystemEntity fse) {
if (fse is Directory) {
if (regExp.hasMatch(new Path(fse.path).filename)) {
@@ -359,7 +350,7 @@
if (count > MIN_NUMBER_OF_TEMP_DIRS) {
DebugLogger.warning("There are ${count} directories "
"in the system tempdir "
- "('${_getTemporaryDirectory().path}')! "
+ "('${Directory.systemTemp.path}')! "
"Maybe left over directories?\n");
}
}).catchError((error) {
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index e5205b1..38f500b 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -700,6 +700,12 @@
}
class BrowserCommandOutputImpl extends CommandOutputImpl {
+ // Although tests are reported as passing, content shell sometimes exits with
+ // a nonzero exitcode which makes our dartium builders extremely falky.
+ // See: http://dartbug.com/15139.
+ static int WHITELISTED_CONTENTSHELL_EXITCODE = -1073740022;
+ static bool isWindows = io.Platform.operatingSystem == 'windows';
+
bool _failedBecauseOfMissingXDisplay;
BrowserCommandOutputImpl(
@@ -832,7 +838,9 @@
DebugLogger.warning(message);
diagnostics.add(message);
}
- return (exitCode != 0 && !hasCrashed);
+ return (!hasCrashed &&
+ exitCode != 0 &&
+ (!isWindows || exitCode != WHITELISTED_CONTENTSHELL_EXITCODE));
}
DebugLogger.warning("Couldn't find 'Content-Type: text/plain' in output. "
"($command).");
@@ -1247,8 +1255,10 @@
static const DART2JS_EXITCODE_CRASH = 253;
CompilationCommandOutputImpl(Command command, int exitCode, bool timedOut,
- List<int> stdout, List<int> stderr, Duration time)
- : super(command, exitCode, timedOut, stdout, stderr, time, false);
+ List<int> stdout, List<int> stderr, Duration time,
+ bool compilationSkipped)
+ : super(command, exitCode, timedOut, stdout, stderr, time,
+ compilationSkipped);
Expectation result(TestCase testCase) {
// Handle general crash/timeout detection.
@@ -1334,7 +1344,7 @@
command, exitCode, timedOut, stdout, stderr, time);
} else if (command is CompilationCommand) {
return new CompilationCommandOutputImpl(
- command, exitCode, timedOut, stdout, stderr, time);
+ command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
} else if (command is JSCommandlineCommand) {
return new JsCommandlineOutputImpl(
command, exitCode, timedOut, stdout, stderr, time);
@@ -2314,7 +2324,57 @@
});
}
+ var testCaseEnqueuer;
void setupForRunning(TestCaseEnqueuer testCaseEnqueuer) {
+ Timer _debugTimer;
+ // If we haven't seen a single test finishing during a 10 minute period
+ // something is definitly wrong, so we dump the debugging information.
+ final debugTimerDuration = const Duration(minutes: 10);
+
+ void cancelDebugTimer() {
+ if (_debugTimer != null) {
+ _debugTimer.cancel();
+ }
+ }
+
+ void resetDebugTimer() {
+ cancelDebugTimer();
+ _debugTimer = new Timer(debugTimerDuration, () {
+ print("The debug timer of test.dart expired. Please report this issue"
+ " to ricow/kustermann and provide the following information:");
+ print("");
+ _graph.DumpCounts();
+ print("");
+ var unfinishedNodeStates = [
+ dgraph.NodeState.Initialized,
+ dgraph.NodeState.Waiting,
+ dgraph.NodeState.Enqueuing,
+ dgraph.NodeState.Processing];
+
+ for (var nodeState in unfinishedNodeStates) {
+ if (_graph.stateCount(nodeState) > 0) {
+ print("Commands in state '$nodeState':");
+ print("=================================");
+ print("");
+ for (var node in _graph.nodes) {
+ if (node.state == nodeState) {
+ var command = node.userData;
+ var testCases = testCaseEnqueuer.command2testCases[command];
+ print(" Command: $command");
+ for (var testCase in testCases) {
+ print(" Enqueued by: ${testCase.configurationString} "
+ "-- ${testCase.displayName}");
+ }
+ print("");
+ }
+ }
+ print("");
+ print("");
+ }
+ }
+ });
+ }
+
bool recording = recordingOutputFile != null;
bool replaying = recordedInputFile != null;
@@ -2349,6 +2409,8 @@
new TestCaseCompleter(_graph, testCaseEnqueuer, commandQueue);
testCaseCompleter.finishedTestCases.listen(
(TestCase finishedTestCase) {
+ resetDebugTimer();
+
// If we're recording, we don't report any TestCases to listeners.
if (!recording) {
eventFinishedTestCase(finishedTestCase);
@@ -2357,12 +2419,17 @@
onDone: () {
// Wait until the commandQueue/execturo is done (it may need to stop
// batch runners, browser controllers, ....)
- commandQueue.done.then((_) => eventAllTestsDone());
+ commandQueue.done.then((_) {
+ cancelDebugTimer();
+ eventAllTestsDone();
+ });
});
+
+ resetDebugTimer();
}
// Build up the dependency graph
- var testCaseEnqueuer = new TestCaseEnqueuer(_graph, (TestCase newTestCase) {
+ testCaseEnqueuer = new TestCaseEnqueuer(_graph, (TestCase newTestCase) {
eventTestAdded(newTestCase);
});
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 1d4c4dc..867d374 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -17,7 +17,6 @@
import "dart:async";
import "dart:convert" show LineSplitter, UTF8;
import "dart:io";
-import "dart:isolate";
import "drt_updater.dart";
import "multitest.dart";
import "status_file_parser.dart";
@@ -327,45 +326,16 @@
}
-void ccTestLister() {
- port.receive((String runnerPath, SendPort replyTo) {
- Future processFuture = Process.start(runnerPath, ["--list"]);
- processFuture.then((Process p) {
- // Drain stderr to not leak resources.
- p.stderr.listen((_) { });
- Stream<String> stdoutStream =
- p.stdout.transform(UTF8.decoder)
- .transform(new LineSplitter());
- var streamDone = false;
- var processExited = false;
- checkDone() {
- if (streamDone && processExited) {
- replyTo.send("");
- }
- }
- stdoutStream.listen((String line) {
- replyTo.send(line);
- },
- onDone: () {
- streamDone = true;
- checkDone();
- });
-
- p.exitCode.then((code) {
- if (code < 0) {
- print("Failed to list tests: $runnerPath --list");
- replyTo.send("");
- } else {
- processExited = true;
- checkDone();
- }
- });
- port.close();
- }).catchError((e) {
- print("Failed to list tests: $runnerPath --list");
- replyTo.send("");
- return true;
- });
+Future<Iterable<String>> ccTestLister(String runnerPath) {
+ return Process.run(runnerPath, ["--list"]).then((ProcessResult result) {
+ if (result.exitCode != 0) {
+ throw "Failed to list tests: '$runnerPath --list'. "
+ "Process exited with ${result.exitCode}";
+ }
+ return result.stdout
+ .split('\n')
+ .map((line) => line.trim())
+ .where((name) => name.length > 0);
});
}
@@ -385,7 +355,6 @@
final String dartDir;
List<String> statusFilePaths;
VoidFunction doDone;
- ReceivePort receiveTestName;
TestExpectations testExpectations;
CCTestSuite(Map configuration,
@@ -409,30 +378,21 @@
}
}
- void testNameHandler(String testName, ignore) {
- if (testName == "") {
- receiveTestName.close();
+ void testNameHandler(String testName) {
+ // Only run the tests that match the pattern. Use the name
+ // "suiteName/testName" for cc tests.
+ String constructedName = '$suiteName/$testPrefix$testName';
- if (doDone != null) doDone();
- } else {
- // Only run the tests that match the pattern. Use the name
- // "suiteName/testName" for cc tests.
- String constructedName = '$suiteName/$testPrefix$testName';
+ var expectations = testExpectations.expectations(
+ '$testPrefix$testName');
- var expectations = testExpectations.expectations(
- '$testPrefix$testName');
+ var args = TestUtils.standardOptions(configuration);
+ args.add(testName);
- var args = TestUtils.standardOptions(configuration);
- args.add(testName);
-
- var command = CommandBuilder.instance.getCommand(
- 'run_vm_unittest', targetRunnerPath, args, configurationDir);
- enqueueNewTestCase(
- new TestCase(constructedName,
- [command],
- configuration,
- expectations));
- }
+ var command = CommandBuilder.instance.getCommand(
+ 'run_vm_unittest', targetRunnerPath, args, configurationDir);
+ enqueueNewTestCase(
+ new TestCase(constructedName, [command], configuration, expectations));
}
void forEachTest(Function onTest, Map testCache, [VoidFunction onDone]) {
@@ -443,10 +403,13 @@
void statusFileRead() {
filesRead++;
if (filesRead == statusFilePaths.length) {
- receiveTestName = new ReceivePort();
- var port = spawnFunction(ccTestLister);
- port.send(hostRunnerPath, receiveTestName.toSendPort());
- receiveTestName.receive(testNameHandler);
+ ccTestLister(hostRunnerPath).then((Iterable<String> names) {
+ names.forEach(testNameHandler);
+ onDone();
+ }).catchError((error) {
+ print("Fatal error occured: $error");
+ exit(1);
+ });
}
}
@@ -540,8 +503,7 @@
* The [StandardTestSuite] also optionally takes a list of servers that have
* been started up by the test harness, to be used by browser tests.
*/
- factory StandardTestSuite.forDirectory(
- Map configuration, Path directory) {
+ factory StandardTestSuite.forDirectory(Map configuration, Path directory) {
final name = directory.filename;
return new StandardTestSuite(configuration,
@@ -1233,7 +1195,7 @@
.append(testUniqueName);
TestUtils.mkdirRecursive(new Path('.'), generatedTestPath);
- return new File(generatedTestPath.toNativePath()).fullPathSync()
+ return new File(generatedTestPath.toNativePath()).absolute.path
.replaceAll('\\', '/');
}
@@ -1533,24 +1495,9 @@
bool hasCompileError = contents.contains("@compile-error");
bool hasRuntimeError = contents.contains("@runtime-error");
- bool hasDynamicTypeError = contents.contains("@dynamic-type-error");
bool hasStaticWarning = contents.contains("@static-warning");
bool isMultitest = multiTestRegExp.hasMatch(contents);
- if (hasDynamicTypeError) {
- // TODO(ahe): Remove this warning when co19 no longer uses this tag.
-
- // @dynamic-type-error has been replaced by tests that use
- // tests/co19/src/Utils/dynamic_check.dart to dynamically detect
- // if a test is running in checked mode or not and change its
- // expectations accordingly.
-
- // Using stderr.writeString to avoid breaking dartc/junit_tests
- // which parses the output of the --list option.
- stderr.writeln(
- "Warning: deprecated @dynamic-type-error tag used in $filePath");
- }
-
return {
"vmOptions": <List>[[]],
"sharedOptions": <String>[],
@@ -1724,10 +1671,11 @@
updatedConfiguration['timeout'] *= 3;
var command = CommandBuilder.instance.getCommand(
'junit_test', 'java', args, configurationDir);
- enqueueNewTestCase(new TestCase(suiteName,
- [command],
- updatedConfiguration,
- new Set<String>.from([PASS])));
+ enqueueNewTestCase(
+ new TestCase(suiteName,
+ [command],
+ updatedConfiguration,
+ new Set<Expectation>.from([Expectation.PASS])));
doDone();
}
@@ -1780,7 +1728,7 @@
* the main script using 'test_suite.dart' is not there, the main
* script must set this to '.../dart/tools/test.dart'.
*/
- static String testScriptPath = new Options().script;
+ static String testScriptPath = new Path(Platform.script.path).toNativePath();
static LastModifiedCache lastModifiedCache = new LastModifiedCache();
static Path currentWorkingDirectory =
new Path(Directory.current.path);
@@ -1862,7 +1810,7 @@
static Path dartDir() {
File scriptFile = new File(testScriptPath);
- Path scriptPath = new Path(scriptFile.fullPathSync());
+ Path scriptPath = new Path(scriptFile.absolute.path);
return scriptPath.directoryPath.directoryPath;
}
diff --git a/tools/testing/dart/utils.dart b/tools/testing/dart/utils.dart
index fb71f3f..ab81b51 100644
--- a/tools/testing/dart/utils.dart
+++ b/tools/testing/dart/utils.dart
@@ -4,7 +4,6 @@
library utils;
-import 'dart:async';
import 'dart:io';
import 'dart:math' show min;
import 'dart:convert';
diff --git a/tools/upload_sdk.py b/tools/upload_sdk.py
deleted file mode 100644
index 67f7131..0000000
--- a/tools/upload_sdk.py
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/python
-
-# Copyright (c) 2011 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This zips the SDK and uploads it to Google Storage when run on a buildbot.
-#
-# Usage: upload_sdk.py path_to_sdk
-
-import os
-import os.path
-import platform
-import subprocess
-import sys
-import utils
-
-
-GSUTIL = utils.GetBuildbotGSUtilPath()
-HAS_SHELL = False
-if platform.system() == 'Windows':
- HAS_SHELL = True
-GS_SITE = 'gs://'
-GS_DIR = 'dart-dump-render-tree'
-GS_SDK_DIR = 'sdk'
-SDK_LOCAL_ZIP = "dart-sdk.zip"
-SDK_LOCAL_TARGZ = "dart-sdk.tar.gz"
-
-def ExecuteCommand(cmd):
- """Execute a command in a subprocess.
- """
- print 'Executing: ' + ' '.join(cmd)
- pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- shell=HAS_SHELL)
- output = pipe.communicate()
- if pipe.returncode != 0:
- print 'Execution failed: ' + str(output)
- return (pipe.returncode, output)
-
-
-def UploadArchive(source, target):
- """Upload an archive zip file to Google storage.
- """
- # Upload file.
- cmd = [GSUTIL, 'cp', source, target]
- (status, output) = ExecuteCommand(cmd)
- if status != 0:
- return status
- print 'Uploaded: ' + output[0]
-
- cmd = [GSUTIL, 'setacl', 'public-read', target]
- (status, output) = ExecuteCommand(cmd)
- return status
-
-
-def Usage(progname):
- sys.stderr.write('Usage: %s path_to_sdk\n' % progname)
-
-
-def main(argv):
- #allow local editor builds to deploy to a different bucket
- if os.environ.has_key('DART_LOCAL_BUILD'):
- gsdir = os.environ['DART_LOCAL_BUILD']
- else:
- gsdir = GS_DIR
-
- if not os.path.exists(argv[1]):
- sys.stderr.write('Path not found: %s\n' % argv[1])
- Usage(argv[0])
- return 1
-
- if not os.path.exists(GSUTIL):
- #TODO: Determine where we are running, if we're running on a buildbot we
- #should fail with a message.
- #If we are not on a buildbot then fail silently.
- utils.Touch(os.path.join(argv[1], 'upload.stamp'))
- exit(0)
-
- revision = utils.GetSVNRevision()
- if revision is None:
- sys.stderr.write('Unable to find SVN revision.\n')
- return 1
-
- os.chdir(os.path.dirname(argv[1]))
-
- if (os.path.basename(os.path.dirname(argv[1])) ==
- utils.GetBuildConf('release', 'ia32')):
- sdk_suffix = ''
- else:
- sdk_suffix = '-debug'
- # TODO(dgrove) - deal with architectures that are not ia32.
- sdk_file_zip = 'dart-%s-%s%s.zip' % (utils.GuessOS(), revision, sdk_suffix)
- sdk_file_targz = 'dart-%s-%s%s.tar.gz' % (utils.GuessOS(), revision,
- sdk_suffix)
- if (os.path.exists(SDK_LOCAL_ZIP)):
- os.remove(SDK_LOCAL_ZIP)
- if (os.path.exists(SDK_LOCAL_TARGZ)):
- os.remove(SDK_LOCAL_TARGZ)
- if platform.system() == 'Windows':
- # Windows does not have zip. We use the 7 zip utility in third party.
- ExecuteCommand([os.path.join('..', 'third_party', '7zip', '7za'), 'a',
- '-tzip', SDK_LOCAL_ZIP, os.path.basename(argv[1])])
- else:
- ExecuteCommand(['zip', '-yr', SDK_LOCAL_ZIP, os.path.basename(argv[1])])
- ExecuteCommand(['tar', 'czf', SDK_LOCAL_TARGZ, os.path.basename(argv[1])])
- UploadArchive(SDK_LOCAL_ZIP,
- GS_SITE + '/'.join([gsdir, GS_SDK_DIR, sdk_file_zip]))
- if (os.path.exists(SDK_LOCAL_TARGZ)):
- UploadArchive(SDK_LOCAL_TARGZ,
- GS_SITE + '/'.join([gsdir, GS_SDK_DIR, sdk_file_targz]))
- latest_name_zip = 'dart-%s-latest%s.zip' % (utils.GuessOS(), sdk_suffix)
- latest_name_targz = 'dart-%s-latest%s.tar.gz' % (utils.GuessOS(), sdk_suffix)
- UploadArchive(SDK_LOCAL_ZIP,
- GS_SITE + '/'.join([gsdir, GS_SDK_DIR, latest_name_zip]))
- if (os.path.exists(SDK_LOCAL_TARGZ)):
- UploadArchive(SDK_LOCAL_TARGZ,
- GS_SITE + '/'.join([gsdir, GS_SDK_DIR, latest_name_targz]))
- utils.Touch('upload.stamp')
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv))
diff --git a/tools/utils.py b/tools/utils.py
index ab83b46..89da10f 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -455,6 +455,17 @@
os.utime(name, None)
+def ExecuteCommand(cmd):
+ """Execute a command in a subprocess."""
+ print 'Executing: ' + ' '.join(cmd)
+ pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ shell=IsWindows())
+ output = pipe.communicate()
+ if pipe.returncode != 0:
+ raise Exception('Execution failed: ' + str(output))
+ return (pipe.returncode, output)
+
+
def DartBinary():
tools_dir = os.path.dirname(os.path.realpath(__file__))
dart_binary_prefix = os.path.join(tools_dir, 'testing', 'bin')