From 2b55297c6856ea07bf83c6bbd9f0a2af37615f63 Mon Sep 17 00:00:00 2001 From: John Messerly Date: Tue, 2 Jun 2015 12:39:25 -0700 Subject: [PATCH] remove generated_sdk from checked in code R=leafp@google.com Review URL: https://codereview.chromium.org/1162723007 --- pkg/dev_compiler/.gitignore | 4 +- .../compiler/js_lib/annotations.dart | 36 - .../compiler/js_lib/constant_map.dart | 147 - .../compiler/js_lib/foreign_helper.dart | 296 -- .../compiler/js_lib/interceptors.dart | 406 -- .../compiler/js_lib/isolate_helper.dart | 1460 ------- .../js_lib/isolate_serialization.dart | 361 -- .../_internal/compiler/js_lib/js_array.dart | 390 -- .../_internal/compiler/js_lib/js_helper.dart | 3468 ----------------- .../_internal/compiler/js_lib/js_mirrors.dart | 3034 -------------- .../_internal/compiler/js_lib/js_names.dart | 115 - .../_internal/compiler/js_lib/js_number.dart | 422 -- .../compiler/js_lib/js_primitives.dart | 50 - .../lib/_internal/compiler/js_lib/js_rti.dart | 688 ---- .../_internal/compiler/js_lib/js_string.dart | 471 --- .../compiler/js_lib/mirror_helper.dart | 25 - .../compiler/js_lib/native_helper.dart | 652 ---- .../compiler/js_lib/native_typed_data.dart | 2013 ---------- .../compiler/js_lib/regexp_helper.dart | 237 -- .../js_lib/shared/embedded_names.dart | 52 - .../compiler/js_lib/string_helper.dart | 215 - .../lib/_internal/libraries.dart | 329 -- .../test/generated_sdk/lib/async/async.dart | 123 - .../generated_sdk/lib/async/async_error.dart | 44 - .../async/broadcast_stream_controller.dart | 512 --- .../lib/async/deferred_load.dart | 39 - .../test/generated_sdk/lib/async/future.dart | 729 ---- .../generated_sdk/lib/async/future_impl.dart | 651 ---- .../lib/async/schedule_microtask.dart | 210 - .../test/generated_sdk/lib/async/stream.dart | 1669 -------- .../lib/async/stream_controller.dart | 803 ---- .../generated_sdk/lib/async/stream_impl.dart | 1082 ----- .../generated_sdk/lib/async/stream_pipe.dart | 438 --- .../lib/async/stream_transformers.dart | 311 -- .../test/generated_sdk/lib/async/timer.dart | 119 - .../test/generated_sdk/lib/async/zone.dart | 1253 ------ .../lib/collection/collection.dart | 1683 -------- .../lib/collection/collections.dart | 19 - .../lib/collection/hash_map.dart | 152 - .../lib/collection/hash_set.dart | 139 - .../lib/collection/iterable.dart | 600 --- .../lib/collection/iterator.dart | 45 - .../lib/collection/linked_hash_map.dart | 149 - .../lib/collection/linked_hash_set.dart | 126 - .../lib/collection/linked_list.dart | 283 -- .../generated_sdk/lib/collection/list.dart | 500 --- .../generated_sdk/lib/collection/maps.dart | 353 -- .../generated_sdk/lib/collection/queue.dart | 742 ---- .../generated_sdk/lib/collection/set.dart | 311 -- .../lib/collection/splay_tree.dart | 836 ---- .../test/generated_sdk/lib/convert/ascii.dart | 311 -- .../lib/convert/byte_conversion.dart | 116 - .../lib/convert/chunked_conversion.dart | 94 - .../test/generated_sdk/lib/convert/codec.dart | 102 - .../generated_sdk/lib/convert/convert.dart | 414 -- .../generated_sdk/lib/convert/converter.dart | 63 - .../generated_sdk/lib/convert/encoding.dart | 76 - .../lib/convert/html_escape.dart | 100 - .../test/generated_sdk/lib/convert/json.dart | 1058 ----- .../generated_sdk/lib/convert/latin1.dart | 172 - .../lib/convert/line_splitter.dart | 93 - .../lib/convert/string_conversion.dart | 343 -- .../test/generated_sdk/lib/convert/utf.dart | 566 --- .../generated_sdk/lib/core/annotations.dart | 167 - .../test/generated_sdk/lib/core/bool.dart | 45 - .../generated_sdk/lib/core/comparable.dart | 94 - .../test/generated_sdk/lib/core/core.dart | 220 -- .../generated_sdk/lib/core/date_time.dart | 696 ---- .../test/generated_sdk/lib/core/double.dart | 208 - .../test/generated_sdk/lib/core/duration.dart | 289 -- .../test/generated_sdk/lib/core/errors.dart | 603 --- .../generated_sdk/lib/core/exceptions.dart | 180 - .../test/generated_sdk/lib/core/expando.dart | 89 - .../test/generated_sdk/lib/core/function.dart | 80 - .../generated_sdk/lib/core/identical.dart | 23 - .../test/generated_sdk/lib/core/int.dart | 283 -- .../generated_sdk/lib/core/invocation.dart | 52 - .../test/generated_sdk/lib/core/iterable.dart | 380 -- .../test/generated_sdk/lib/core/iterator.dart | 51 - .../test/generated_sdk/lib/core/list.dart | 748 ---- .../test/generated_sdk/lib/core/map.dart | 254 -- .../test/generated_sdk/lib/core/null.dart | 21 - .../test/generated_sdk/lib/core/num.dart | 462 --- .../test/generated_sdk/lib/core/object.dart | 102 - .../test/generated_sdk/lib/core/pattern.dart | 42 - .../test/generated_sdk/lib/core/print.dart | 15 - .../test/generated_sdk/lib/core/regexp.dart | 179 - .../test/generated_sdk/lib/core/set.dart | 188 - .../test/generated_sdk/lib/core/sink.dart | 31 - .../generated_sdk/lib/core/stacktrace.dart | 27 - .../generated_sdk/lib/core/stopwatch.dart | 146 - .../test/generated_sdk/lib/core/string.dart | 817 ---- .../generated_sdk/lib/core/string_buffer.dart | 80 - .../generated_sdk/lib/core/string_sink.dart | 32 - .../test/generated_sdk/lib/core/symbol.dart | 53 - .../test/generated_sdk/lib/core/type.dart | 10 - .../test/generated_sdk/lib/core/uri.dart | 2412 ------------ .../generated_sdk/lib/internal/internal.dart | 50 - .../generated_sdk/lib/internal/iterable.dart | 1169 ------ .../test/generated_sdk/lib/internal/list.dart | 379 -- .../generated_sdk/lib/internal/lists.dart | 90 - .../generated_sdk/lib/internal/print.dart | 19 - .../test/generated_sdk/lib/internal/sort.dart | 344 -- .../generated_sdk/lib/internal/symbol.dart | 146 - .../generated_sdk/lib/isolate/capability.dart | 34 - .../generated_sdk/lib/isolate/isolate.dart | 703 ---- .../lib/math/jenkins_smi_hash.dart | 41 - .../test/generated_sdk/lib/math/math.dart | 443 --- .../test/generated_sdk/lib/math/point.dart | 88 - .../test/generated_sdk/lib/math/random.dart | 41 - .../generated_sdk/lib/math/rectangle.dart | 276 -- .../lib/typed_data/typed_data.dart | 1779 --------- pkg/dev_compiler/test/generated_sdk/version | 1 - pkg/dev_compiler/tool/README.md | 15 +- pkg/dev_compiler/tool/build_sdk.sh | 12 +- 115 files changed, 17 insertions(+), 46992 deletions(-) delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/annotations.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/constant_map.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/foreign_helper.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/interceptors.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/isolate_helper.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/isolate_serialization.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_array.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_helper.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_mirrors.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_names.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_number.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_primitives.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_rti.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_string.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/mirror_helper.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/native_helper.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/native_typed_data.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/regexp_helper.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/string_helper.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/_internal/libraries.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/async.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/async_error.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/broadcast_stream_controller.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/deferred_load.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/future.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/future_impl.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/schedule_microtask.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/stream.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/stream_controller.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/stream_impl.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/stream_pipe.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/stream_transformers.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/timer.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/async/zone.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/collection.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/collections.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/hash_map.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/hash_set.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/iterable.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/iterator.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/linked_hash_map.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/linked_hash_set.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/linked_list.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/list.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/maps.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/queue.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/set.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/collection/splay_tree.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/convert/ascii.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/convert/byte_conversion.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/convert/chunked_conversion.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/convert/codec.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/convert/convert.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/convert/converter.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/convert/encoding.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/convert/html_escape.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/convert/json.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/convert/latin1.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/convert/line_splitter.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/convert/string_conversion.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/convert/utf.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/annotations.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/bool.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/comparable.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/core.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/date_time.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/double.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/duration.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/errors.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/exceptions.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/expando.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/function.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/identical.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/int.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/invocation.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/iterable.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/iterator.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/list.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/map.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/null.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/num.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/object.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/pattern.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/print.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/regexp.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/set.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/sink.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/stacktrace.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/stopwatch.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/string.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/string_buffer.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/string_sink.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/symbol.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/type.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/core/uri.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/internal/internal.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/internal/iterable.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/internal/list.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/internal/lists.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/internal/print.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/internal/sort.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/internal/symbol.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/isolate/capability.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/isolate/isolate.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/math/jenkins_smi_hash.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/math/math.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/math/point.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/math/random.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/math/rectangle.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/lib/typed_data/typed_data.dart delete mode 100644 pkg/dev_compiler/test/generated_sdk/version diff --git a/pkg/dev_compiler/.gitignore b/pkg/dev_compiler/.gitignore index 4fea88e56e72..1aee2692fe0c 100644 --- a/pkg/dev_compiler/.gitignore +++ b/pkg/dev_compiler/.gitignore @@ -12,10 +12,12 @@ packages .pub/ node_modules +# Created by ./tool/build_sdk.sh +tool/generated_sdk/ + # Or our test outputs test/codegen/actual/ test/dart_codegen/actual/ -test/generated_sdk/sdk_errors.txt # Include when developing application packages. pubspec.lock diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/annotations.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/annotations.dart deleted file mode 100644 index 1e63cf99a61c..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/annotations.dart +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of _js_helper; - -/// Tells the optimizing compiler that the annotated method has no -/// side-effects. -/// Requires @NoInline() to function correctly. -class NoSideEffects { - const NoSideEffects(); -} - -/// Tells the optimizing compiler that the annotated method cannot throw. -/// Requires @NoInline() to function correctly. -class NoThrows { - const NoThrows(); -} - -/// Tells the optimizing compiler to not inline the annotated method. -class NoInline { - const NoInline(); -} - -// Ensures that the annotated method is represented internally using -// IR nodes ([:value == true:]) or AST nodes ([:value == false:]). -class IrRepresentation { - final bool value; - const IrRepresentation(this.value); -} - -/// Marks a class as native and defines its JavaScript name(s). -class Native { - final String name; - const Native(this.name); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/constant_map.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/constant_map.dart deleted file mode 100644 index 0d66acac104c..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/constant_map.dart +++ /dev/null @@ -1,147 +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. - -part of _js_helper; - -abstract class ConstantMap implements Map { - const ConstantMap._(); - - bool get isEmpty => length == 0; - - bool get isNotEmpty => !isEmpty; - - String toString() => Maps.mapToString(this); - - _throwUnmodifiable() { - throw new UnsupportedError("Cannot modify unmodifiable Map"); - } - void operator []=(K key, V val) => _throwUnmodifiable(); - V putIfAbsent(K key, V ifAbsent()) => _throwUnmodifiable(); - V remove(Object key) => _throwUnmodifiable(); - void clear() => _throwUnmodifiable(); - void addAll(Map other) => _throwUnmodifiable(); -} - -class ConstantStringMap extends ConstantMap - implements _symbol_dev.EfficientLength { - - // This constructor is not used. The instantiation is shortcut by the - // compiler. It is here to make the uninitialized final fields legal. - const ConstantStringMap._(this.length, this._jsObject, this._keys) - : super._(); - - final int length; - // A constant map is backed by a JavaScript object. - final _jsObject; - final List _keys; - - bool containsValue(Object needle) { - return values.any((V value) => value == needle); - } - - bool containsKey(Object key) { - if (key is! String) return false; - if ('__proto__' == key) return false; - return jsHasOwnProperty(_jsObject, key); - } - - V operator [](Object key) { - if (!containsKey(key)) return null; - return _fetch(key); - } - - // [_fetch] is the indexer for keys for which `containsKey(key)` is true. - _fetch(key) => jsPropertyAccess(_jsObject, key); - - void forEach(void f(K key, V value)) { - // Use a JS 'cast' to get efficient loop. Type inferrence doesn't get this - // since constant map representation is chosen after type inferrence and the - // instantiation is shortcut by the compiler. - var keys = JS('JSArray', '#', _keys); - for (int i = 0; i < keys.length; i++) { - var key = keys[i]; - f(key, _fetch(key)); - } - } - - Iterable get keys { - return new _ConstantMapKeyIterable(this); - } - - Iterable get values { - return new MappedIterable(_keys, (key) => _fetch(key)); - } -} - -class ConstantProtoMap extends ConstantStringMap { - // This constructor is not used. The instantiation is shortcut by the - // compiler. It is here to make the uninitialized final fields legal. - ConstantProtoMap._(length, jsObject, keys, this._protoValue) - : super._(length, jsObject, keys); - - final V _protoValue; - - bool containsKey(Object key) { - if (key is! String) return false; - if ('__proto__' == key) return true; - return jsHasOwnProperty(_jsObject, key); - } - - _fetch(key) => - '__proto__' == key ? _protoValue : jsPropertyAccess(_jsObject, key); -} - -class _ConstantMapKeyIterable extends IterableBase { - ConstantStringMap _map; - _ConstantMapKeyIterable(this._map); - - Iterator get iterator => _map._keys.iterator; - - int get length => _map._keys.length; -} - -class GeneralConstantMap extends ConstantMap { - // This constructor is not used. The instantiation is shortcut by the - // compiler. It is here to make the uninitialized final fields legal. - GeneralConstantMap(this._jsData) : super._(); - - // [_jsData] holds a key-value pair list. - final _jsData; - - // We cannot create the backing map on creation since hashCode interceptors - // have not been defined when constants are created. - Map _getMap() { - if (JS('bool', r'!this.$map')) { - Map backingMap = new LinkedHashMap(); - JS('', r'this.$map = #', fillLiteralMap(_jsData, backingMap)); - } - return JS('Map', r'this.$map'); - } - - bool containsValue(Object needle) { - return _getMap().containsValue(needle); - } - - bool containsKey(Object key) { - return _getMap().containsKey(key); - } - - V operator [](Object key) { - return _getMap()[key]; - } - - void forEach(void f(K key, V value)) { - _getMap().forEach(f); - } - - Iterable get keys { - return _getMap().keys; - } - - Iterable get values { - return _getMap().values; - } - - int get length => _getMap().length; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/foreign_helper.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/foreign_helper.dart deleted file mode 100644 index 156ab6303339..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/foreign_helper.dart +++ /dev/null @@ -1,296 +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. - -library _foreign_helper; - -/** - * Emits a JavaScript code fragment parameterized by arguments. - * - * Hash characters `#` in the [codeTemplate] are replaced in left-to-right order - * with expressions that contain the values of, or evaluate to, the arguments. - * The number of hash marks must match the number or arguments. Although - * declared with arguments [arg0] through [arg2], the form actually has no limit - * on the number of arguments. - * - * The [typeDescription] argument is interpreted as a description of the - * behavior of the JavaScript code. Currently it describes the types that may - * be returned by the expression, with the additional behavior that the returned - * values may be fresh instances of the types. The type information must be - * correct as it is trusted by the compiler in optimizations, and it must be - * precise as possible since it is used for native live type analysis to - * tree-shake large parts of the DOM libraries. If poorly written, the - * [typeDescription] will cause unnecessarily bloated programs. (You can check - * for this by compiling with `--verbose`; there is an info message describing - * the number of native (DOM) types that can be removed, which usually should be - * greater than zero.) - * - * The [typeDescription] is a [String] which contains a union of types separated - * by vertical bar `|` symbols, e.g. `"num|String"` describes the union of - * numbers and Strings. There is no type in Dart that is this precise. The - * Dart alternative would be `Object` or `dynamic`, but these types imply that - * the JS-code might also be creating instances of all the DOM types. If `null` - * is possible, it must be specified explicitly, e.g. `"String|Null"`. - * [typeDescription] has several extensions to help describe the behavior more - * accurately. In addition to the union type already described: - * - * + `=Object` is a plain JavaScript object. Some DOM methods return instances - * that have no corresponing Dart type (e.g. cross-frame documents), - * `=Object` can be used to describe these untyped' values. - * - * + `var` (or empty string). If the entire [typeDescription] is `var` (or - * empty string) then the type is `dynamic` but the code is known to not - * create any instances. - * - * Examples: - * - * // Parent window might be an opaque cross-frame window. - * var thing = JS('=Object|Window', '#.parent', myWindow); - * - * Guidelines: - * - * + Do not use any parameter, local, method or field names in the - * [codeTemplate]. These names are all subject to arbitrary renaming by the - * compiler. Pass the values in via `#` substition, and test with the - * `--minify` dart2js command-line option. - * - * + The substituted expressions are values, not locations. - * - * JS('void', '# += "x"', this.field); - * - * `this.field` might not be a substituted as a reference to the field. The - * generated code might accidentally work as intended, but it also might be - * - * var t1 = this.field; - * t1 += "x"; - * - * or - * - * this.get$field() += "x"; - * - * The remedy in this case is to expand the `+=` operator, leaving all - * references to the Dart field as Dart code: - * - * this.field = JS('String', '# + "x"', this.field); - * - * + Never use `#` in function bodies. - * - * This is a variation on the previous guideline. Since `#` is replaced with - * an *expression* and the expression is only valid in the immediate context, - * `#` should never appear in a function body. Doing so might defer the - * evaluation of the expression, and its side effects, until the function is - * called. - * - * For example, - * - * var value = foo(); - * var f = JS('', 'function(){return #}', value) - * - * might result in no immediate call to `foo` and a call to `foo` on every - * call to the JavaScript function bound to `f`. This is better: - * - * var f = JS('', - * '(function(val) { return function(){return val}; })(#)', value); - * - * Since `#` occurs in the immediately evaluated expression, the expression - * is immediately evaluated and bound to `val` in the immediate call. - * - * - * Additional notes. - * - * In the future we may extend [typeDescription] to include other aspects of the - * behavior, for example, separating the returned types from the instantiated - * types, or including effects to allow the compiler to perform more - * optimizations around the code. This might be an extension of [JS] or a new - * function similar to [JS] with additional arguments for the new information. - */ -// Add additional optional arguments if needed. The method is treated internally -// as a variable argument method. -JS(String typeDescription, String codeTemplate, - [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11]) -{} - -/** - * Returns the isolate in which this code is running. - */ -IsolateContext JS_CURRENT_ISOLATE_CONTEXT() {} - -abstract class IsolateContext { - /// Holds a (native) JavaScript instance of Isolate, see - /// finishIsolateConstructorFunction in emitter.dart. - get isolateStatics; -} - -/** - * Invokes [function] in the context of [isolate]. - */ -JS_CALL_IN_ISOLATE(isolate, Function function) {} - -/** - * Converts the Dart closure [function] into a JavaScript closure. - * - * Warning: This is no different from [RAW_DART_FUNCTION_REF] which means care - * must be taken to store the current isolate. - */ -DART_CLOSURE_TO_JS(Function function) {} - -/** - * Returns a raw reference to the JavaScript function which implements - * [function]. - * - * Warning: this is dangerous, you should probably use - * [DART_CLOSURE_TO_JS] instead. The returned object is not a valid - * Dart closure, does not store the isolate context or arity. - * - * A valid example of where this can be used is as the second argument - * to V8's Error.captureStackTrace. See - * https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi. - */ -RAW_DART_FUNCTION_REF(Function function) {} - -/** - * Sets the current isolate to [isolate]. - */ -void JS_SET_CURRENT_ISOLATE(isolate) {} - -/** - * Creates an isolate and returns it. - */ -JS_CREATE_ISOLATE() {} - -/** - * Returns the JavaScript constructor function for Dart's Object class. - * This can be used for type tests, as in - * - * if (JS('bool', '# instanceof #', obj, JS_DART_OBJECT_CONSTRUCTOR())) - * ... - */ -JS_DART_OBJECT_CONSTRUCTOR() {} - -/** - * Returns the interceptor for class [type]. The interceptor is the type's - * constructor's `prototype` property. [type] will typically be the class, not - * an interface, e.g. `JS_INTERCEPTOR_CONSTANT(JSInt)`, not - * `JS_INTERCEPTOR_CONSTANT(int)`. - */ -JS_INTERCEPTOR_CONSTANT(Type type) {} - -/** - * Returns the prefix used for generated is checks on classes. - */ -String JS_OPERATOR_IS_PREFIX() {} - -/** - * Returns the prefix used for generated type argument substitutions on classes. - */ -String JS_OPERATOR_AS_PREFIX() {} - -/// Returns the name of the class `Object` in the generated code. -String JS_OBJECT_CLASS_NAME() {} - -/// Returns the name of the class `Null` in the generated code. -String JS_NULL_CLASS_NAME() {} - -/// Returns the name of the class `Function` in the generated code. -String JS_FUNCTION_CLASS_NAME() {} - -/** - * Returns the field name used for determining if an object or its - * interceptor has JavaScript indexing behavior. - */ -String JS_IS_INDEXABLE_FIELD_NAME() {} - -/** - * Returns the object corresponding to Namer.CURRENT_ISOLATE. - */ -JS_CURRENT_ISOLATE() {} - -/// Returns the name used for generated function types on classes and methods. -String JS_SIGNATURE_NAME() {} - -/// Returns the name used to tag typedefs. -String JS_TYPEDEF_TAG() {} - -/// Returns the name used to tag function type representations in JavaScript. -String JS_FUNCTION_TYPE_TAG() {} - -/** - * Returns the name used to tag void return in function type representations - * in JavaScript. - */ -String JS_FUNCTION_TYPE_VOID_RETURN_TAG() {} - -/** - * Returns the name used to tag return types in function type representations - * in JavaScript. - */ -String JS_FUNCTION_TYPE_RETURN_TYPE_TAG() {} - -/** - * Returns the name used to tag required parameters in function type - * representations in JavaScript. - */ -String JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG() {} - -/** - * Returns the name used to tag optional parameters in function type - * representations in JavaScript. - */ -String JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG() {} - -/** - * Returns the name used to tag named parameters in function type - * representations in JavaScript. - */ -String JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG() {} - -/// Returns the JS name for [name] from the Namer. -String JS_GET_NAME(String name) {} - -/// Reads an embedded global. -/// -/// The [name] should be a constant defined in the `_embedded_names` library. -JS_EMBEDDED_GLOBAL(String typeDescription, String name) {} - -/// Returns the state of a flag that is determined by the state of the compiler -/// when the program has been analyzed. -bool JS_GET_FLAG(String name) {} - -/** - * Pretend [code] is executed. Generates no executable code. This is used to - * model effects at some other point in external code. For example, the - * following models an assignment to foo with an unknown value. - * - * var foo; - * - * main() { - * JS_EFFECT((_){ foo = _; }) - * } - * - * TODO(sra): Replace this hack with something to mark the volatile or - * externally initialized elements. - */ -void JS_EFFECT(Function code) { code(null); } - -/** - * Use this class for creating constants that hold JavaScript code. - * For example: - * - * const constant = JS_CONST('typeof window != "undefined"); - * - * This code will generate: - * $.JS_CONST_1 = typeof window != "undefined"; - */ -class JS_CONST { - final String code; - const JS_CONST(this.code); -} - -/** - * JavaScript string concatenation. Inputs must be Strings. Corresponds to the - * HStringConcat SSA instruction and may be constant-folded. - */ -String JS_STRING_CONCAT(String a, String b) { - // This body is unused, only here for type analysis. - return JS('String', '# + #', a, b); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/interceptors.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/interceptors.dart deleted file mode 100644 index 566d1f6c106b..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/interceptors.dart +++ /dev/null @@ -1,406 +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. - -library _interceptors; - -import 'dart:_js_embedded_names' show - DISPATCH_PROPERTY_NAME, - MAP_TYPE_TO_INTERCEPTOR; - -import 'dart:collection'; -import 'dart:_internal' hide Symbol; -import "dart:_internal" as _symbol_dev show Symbol; -import 'dart:_js_helper' show allMatchesInStringUnchecked, - Null, - JSSyntaxRegExp, - Primitives, - checkInt, - checkNull, - checkNum, - checkString, - defineProperty, - getRuntimeType, - initNativeDispatch, - initNativeDispatchFlag, - regExpGetNative, - regExpCaptureCount, - stringContainsUnchecked, - stringLastIndexOfUnchecked, - stringReplaceAllFuncUnchecked, - stringReplaceAllUnchecked, - stringReplaceFirstUnchecked, - lookupAndCacheInterceptor, - lookupDispatchRecord, - StringMatch, - firstMatchAfter, - NoInline; -import 'dart:_foreign_helper' show - JS, - JS_EFFECT, - JS_EMBEDDED_GLOBAL, - JS_INTERCEPTOR_CONSTANT, - JS_STRING_CONCAT; -import 'dart:math' show Random; - -part 'js_array.dart'; -part 'js_number.dart'; -part 'js_string.dart'; - -String _symbolToString(Symbol symbol) => _symbol_dev.Symbol.getName(symbol); - -_symbolMapToStringMap(Map map) { - if (map == null) return null; - var result = new Map(); - map.forEach((Symbol key, value) { - result[_symbolToString(key)] = value; - }); - return result; -} - -/** - * Get the interceptor for [object]. Called by the compiler when it needs - * to emit a call to an intercepted method, that is a method that is - * defined in an interceptor class. - */ -getInterceptor(object) { - // This is a magic method: the compiler does specialization of it - // depending on the uses of intercepted methods and instantiated - // primitive types. - - // The [JS] call prevents the type analyzer from making assumptions about the - // return type. - return JS('', 'void 0'); -} - -getDispatchProperty(object) { - return JS('', '#[#]', - object, JS_EMBEDDED_GLOBAL('String', DISPATCH_PROPERTY_NAME)); -} - -setDispatchProperty(object, value) { - defineProperty(object, - JS_EMBEDDED_GLOBAL('String', DISPATCH_PROPERTY_NAME), - value); -} - -// Avoid inlining this method because inlining gives us multiple allocation -// points for records which is bad because it leads to polymorphic access. -@NoInline() -makeDispatchRecord(interceptor, proto, extension, indexability) { - // Dispatch records are stored in the prototype chain, and in some cases, on - // instances. - // - // The record layout and field usage is designed to minimize the number of - // operations on the common paths. - // - // [interceptor] is the interceptor - a holder of methods for the object, - // i.e. the prototype of the interceptor class. - // - // [proto] is usually the prototype, used to check that the dispatch record - // matches the object and is not the dispatch record of a superclass. Other - // values: - // - `false` for leaf classes that need no check. - // - `true` for Dart classes where the object is its own interceptor (unused) - // - a function used to continue matching. - // - // [extension] is used for irregular cases. - // - // [indexability] is used to cache whether or not the object - // implements JavaScriptIndexingBehavior. - // - // proto interceptor extension action - // ----- ----------- --------- ------ - // false I use interceptor I - // true - use object - // P I if object's prototype is P, use I - // F - P if object's prototype is P, call F - - return JS('', '{i: #, p: #, e: #, x: #}', - interceptor, proto, extension, indexability); -} - -dispatchRecordInterceptor(record) => JS('', '#.i', record); -dispatchRecordProto(record) => JS('', '#.p', record); -dispatchRecordExtension(record) => JS('', '#.e', record); -dispatchRecordIndexability(record) => JS('bool|Null', '#.x', record); - -/** - * Returns the interceptor for a native class instance. Used by - * [getInterceptor]. - */ -getNativeInterceptor(object) { - var record = getDispatchProperty(object); - - if (record == null) { - if (initNativeDispatchFlag == null) { - initNativeDispatch(); - record = getDispatchProperty(object); - } - } - - if (record != null) { - var proto = dispatchRecordProto(record); - if (false == proto) return dispatchRecordInterceptor(record); - if (true == proto) return object; - var objectProto = JS('', 'Object.getPrototypeOf(#)', object); - if (JS('bool', '# === #', proto, objectProto)) { - return dispatchRecordInterceptor(record); - } - - var extension = dispatchRecordExtension(record); - if (JS('bool', '# === #', extension, objectProto)) { - // TODO(sra): The discriminator returns a tag. The tag is an uncached or - // instance-cached tag, defaulting to instance-cached if caching - // unspecified. - var discriminatedTag = JS('', '(#)(#, #)', proto, object, record); - throw new UnimplementedError('Return interceptor for $discriminatedTag'); - } - } - - var interceptor = lookupAndCacheInterceptor(object); - if (interceptor == null) { - // JavaScript Objects created via object literals and `Object.create(null)` - // are 'plain' Objects. This test could be simplified and the dispatch path - // be faster if Object.prototype was pre-patched with a non-leaf dispatch - // record. - var proto = JS('', 'Object.getPrototypeOf(#)', object); - if (JS('bool', '# == null || # === Object.prototype', proto, proto)) { - return JS_INTERCEPTOR_CONSTANT(PlainJavaScriptObject); - } else { - return JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject); - } - } - - return interceptor; -} - -/** - * Data structure used to map a [Type] to the [Interceptor] and constructors for - * that type. It is JavaScript array of 3N entries of adjacent slots containing - * a [Type], followed by an [Interceptor] class for the type, followed by a - * JavaScript object map for the constructors. - * - * The value of this variable is set by the compiler and contains only types - * that are user extensions of native classes where the type occurs as a - * constant in the program. - * - * The compiler, in CustomElementsAnalysis, assumes that [mapTypeToInterceptor] - * is accessed only by code that also calls [findIndexForWebComponentType]. If - * this assumption is invalidated, the compiler will have to be updated. - */ -get mapTypeToInterceptor { - return JS_EMBEDDED_GLOBAL('', MAP_TYPE_TO_INTERCEPTOR); -} - -int findIndexForNativeSubclassType(Type type) { - if (JS('bool', '# == null', mapTypeToInterceptor)) return null; - List map = JS('JSFixedArray', '#', mapTypeToInterceptor); - for (int i = 0; i + 1 < map.length; i += 3) { - if (type == map[i]) { - return i; - } - } - return null; -} - -findInterceptorConstructorForType(Type type) { - var index = findIndexForNativeSubclassType(type); - if (index == null) return null; - List map = JS('JSFixedArray', '#', mapTypeToInterceptor); - return map[index + 1]; -} - -/** - * Returns a JavaScript function that runs the constructor on its argument, or - * `null` if there is no such constructor. - * - * The returned function takes one argument, the web component object. - */ -findConstructorForNativeSubclassType(Type type, String name) { - var index = findIndexForNativeSubclassType(type); - if (index == null) return null; - List map = JS('JSFixedArray', '#', mapTypeToInterceptor); - var constructorMap = map[index + 2]; - var constructorFn = JS('', '#[#]', constructorMap, name); - return constructorFn; -} - -findInterceptorForType(Type type) { - var constructor = findInterceptorConstructorForType(type); - if (constructor == null) return null; - return JS('', '#.prototype', constructor); -} - -/** - * The base interceptor class. - * - * The code `r.foo(a)` is compiled to `getInterceptor(r).foo$1(r, a)`. The - * value returned by [getInterceptor] holds the methods separately from the - * state of the instance. The compiler converts the methods on an interceptor - * to take the Dart `this` argument as an explicit `receiver` argument. The - * JavaScript `this` parameter is bound to the interceptor. - * - * In order to have uniform call sites, if a method is defined on an - * interceptor, methods of that name on plain unintercepted classes also use the - * interceptor calling convention. The plain classes are _self-interceptors_, - * and for them, `getInterceptor(r)` returns `r`. Methods on plain - * unintercepted classes have a redundant `receiver` argument and should ignore - * it in favour of `this`. - * - * In the case of mixins, a method may be placed on both an intercepted class - * and an unintercepted class. In this case, the method must use the `receiver` - * parameter. - * - * - * There are various optimizations of the general call pattern. - * - * When the interceptor can be statically determined, it can be used directly: - * - * CONSTANT_INTERCEPTOR.foo$1(r, a) - * - * If there are only a few classes, [getInterceptor] can be specialized with a - * more efficient dispatch: - * - * getInterceptor$specialized(r).foo$1(r, a) - * - * If it can be determined that the receiver is an unintercepted class, it can - * be called directly: - * - * r.foo$1(r, a) - * - * If, further, it is known that the call site cannot call a foo that is - * mixed-in to a native class, then it is known that the explicit receiver is - * ignored, and space-saving dummy value can be passed instead: - * - * r.foo$1(0, a) - * - * This class defines implementations of *all* methods on [Object] so no - * interceptor inherits an implementation from [Object]. This enables the - * implementations on Object to ignore the explicit receiver argument, which - * allows dummy receiver optimization. - */ -abstract class Interceptor { - const Interceptor(); - - bool operator ==(Object other) => identical(this, other); - - int get hashCode => Primitives.objectHashCode(this); - - String toString() => Primitives.objectToString(this); - - dynamic noSuchMethod(Invocation invocation) { - throw new NoSuchMethodError( - this, - invocation.memberName, - invocation.positionalArguments, - invocation.namedArguments); - } - - Type get runtimeType => getRuntimeType(this); -} - -/** - * The interceptor class for [bool]. - */ -class JSBool extends Interceptor implements bool { - const JSBool(); - - // Note: if you change this, also change the function [S]. - String toString() => JS('String', r'String(#)', this); - - // The values here are SMIs, co-prime and differ about half of the bit - // positions, including the low bit, so they are different mod 2^k. - int get hashCode => this ? (2 * 3 * 23 * 3761) : (269 * 811); - - Type get runtimeType => bool; -} - -/** - * The interceptor class for [Null]. - * - * This class defines implementations for *all* methods on [Object] since - * the methods on Object assume the receiver is non-null. This means that - * JSNull will always be in the interceptor set for methods defined on Object. - */ -class JSNull extends Interceptor implements Null { - const JSNull(); - - bool operator ==(other) => identical(null, other); - - // Note: if you change this, also change the function [S]. - String toString() => 'null'; - - int get hashCode => 0; - - // The spec guarantees that `null` is the singleton instance of the `Null` - // class. In the mirrors library we also have to patch the `type` getter to - // special case `null`. - Type get runtimeType => Null; - - dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); -} - -/** - * The supertype for JSString and JSArray. Used by the backend as to - * have a type mask that contains the objects that we can use the - * native JS [] operator and length on. - */ -abstract class JSIndexable { - int get length; - operator[](int index); -} - -/** - * The supertype for JSMutableArray and - * JavaScriptIndexingBehavior. Used by the backend to have a type mask - * that contains the objects we can use the JS []= operator on. - */ -abstract class JSMutableIndexable extends JSIndexable { - operator[]=(int index, var value); -} - -/** - * The interface implemented by JavaScript objects. These are methods in - * addition to the regular Dart Object methods like [Object.hashCode]. - * - * This is the type that should be exported by a JavaScript interop library. - */ -abstract class JSObject { -} - - -/** - * Interceptor base class for JavaScript objects not recognized as some more - * specific native type. - */ -abstract class JavaScriptObject extends Interceptor implements JSObject { - const JavaScriptObject(); - - // It would be impolite to stash a property on the object. - int get hashCode => 0; - - Type get runtimeType => JSObject; -} - - -/** - * Interceptor for plain JavaScript objects created as JavaScript object - * literals or `new Object()`. - */ -class PlainJavaScriptObject extends JavaScriptObject { - const PlainJavaScriptObject(); -} - - -/** - * Interceptor for unclassified JavaScript objects, typically objects with a - * non-trivial prototype chain. - * - * This class also serves as a fallback for unknown JavaScript exceptions. - */ -class UnknownJavaScriptObject extends JavaScriptObject { - const UnknownJavaScriptObject(); - - String toString() => JS('String', 'String(#)', this); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/isolate_helper.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/isolate_helper.dart deleted file mode 100644 index ceac6601b26a..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/isolate_helper.dart +++ /dev/null @@ -1,1460 +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. - -library _isolate_helper; - -import 'dart:_js_embedded_names' show - CLASS_ID_EXTRACTOR, - CLASS_FIELDS_EXTRACTOR, - CURRENT_SCRIPT, - GLOBAL_FUNCTIONS, - INITIALIZE_EMPTY_INSTANCE, - INSTANCE_FROM_CLASS_ID; - -import 'dart:async'; -import 'dart:collection' show Queue, HashMap; -import 'dart:isolate'; -import 'dart:_native_typed_data' show NativeByteBuffer, NativeTypedData; - -import 'dart:_js_helper' show - Closure, - InternalMap, - Null, - Primitives, - convertDartClosureToJS, - random64, - requiresPreamble; - -import 'dart:_foreign_helper' show DART_CLOSURE_TO_JS, - JS, - JS_CREATE_ISOLATE, - JS_CURRENT_ISOLATE_CONTEXT, - JS_CURRENT_ISOLATE, - JS_EMBEDDED_GLOBAL, - JS_SET_CURRENT_ISOLATE, - IsolateContext; - -import 'dart:_interceptors' show Interceptor, - JSArray, - JSExtendableArray, - JSFixedArray, - JSIndexable, - JSMutableArray, - JSObject; - - -part 'isolate_serialization.dart'; - -/** - * Called by the compiler to support switching - * between isolates when we get a callback from the DOM. - */ -_callInIsolate(_IsolateContext isolate, Function function) { - var result = isolate.eval(function); - _globalState.topEventLoop.run(); - return result; -} - -/// Marks entering a JavaScript async operation to keep the worker alive. -/// -/// To be called by library code before starting an async operation controlled -/// by the JavaScript event handler. -/// -/// Also call [leaveJsAsync] in all callback handlers marking the end of that -/// async operation (also error handlers) so the worker can be released. -/// -/// These functions only has to be called for code that can be run from a -/// worker-isolate (so not for general dom operations). -enterJsAsync() { - _globalState.topEventLoop._activeJsAsyncCount++; -} - -/// Marks leaving a javascript async operation. -/// -/// See [enterJsAsync]. -leaveJsAsync() { - _globalState.topEventLoop._activeJsAsyncCount--; - assert(_globalState.topEventLoop._activeJsAsyncCount >= 0); -} - -/// Returns true if we are currently in a worker context. -bool isWorker() => _globalState.isWorker; - -/** - * Called by the compiler to fetch the current isolate context. - */ -_IsolateContext _currentIsolate() => _globalState.currentContext; - -/** - * Wrapper that takes the dart entry point and runs it within an isolate. The - * dart2js compiler will inject a call of the form - * [: startRootIsolate(main); :] when it determines that this wrapping - * is needed. For single-isolate applications (e.g. hello world), this - * call is not emitted. - */ -void startRootIsolate(entry, args) { - // The dartMainRunner can inject a new arguments array. We pass the arguments - // through a "JS", so that the type-inferrer loses track of it. - args = JS("", "#", args); - if (args == null) args = []; - if (args is! List) { - throw new ArgumentError("Arguments to main must be a List: $args"); - } - _globalState = new _Manager(entry); - - // Don't start the main loop again, if we are in a worker. - if (_globalState.isWorker) return; - final rootContext = new _IsolateContext(); - _globalState.rootContext = rootContext; - - // BUG(5151491): Setting currentContext should not be necessary, but - // because closures passed to the DOM as event handlers do not bind their - // isolate automatically we try to give them a reasonable context to live in - // by having a "default" isolate (the first one created). - _globalState.currentContext = rootContext; - if (entry is _MainFunctionArgs) { - rootContext.eval(() { entry(args); }); - } else if (entry is _MainFunctionArgsMessage) { - rootContext.eval(() { entry(args, null); }); - } else { - rootContext.eval(entry); - } - _globalState.topEventLoop.run(); -} - -/******************************************************** - Inserted from lib/isolate/dart2js/isolateimpl.dart - ********************************************************/ - -/** - * Concepts used here: - * - * "manager" - A manager contains one or more isolates, schedules their - * execution, and performs other plumbing on their behalf. The isolate - * present at the creation of the manager is designated as its "root isolate". - * A manager may, for example, be implemented on a web Worker. - * - * [_Manager] - State present within a manager (exactly once, as a global). - * - * [_ManagerStub] - A handle held within one manager that allows interaction - * with another manager. A target manager may be addressed by zero or more - * [_ManagerStub]s. - * TODO(ahe): The _ManagerStub concept is broken. It was an attempt - * to create a common interface between the native Worker class and - * _MainManagerStub. - */ - -/** - * A native object that is shared across isolates. This object is visible to all - * isolates running under the same manager (either UI or background web worker). - * - * This is code that is intended to 'escape' the isolate boundaries in order to - * implement the semantics of isolates in JavaScript. Without this we would have - * been forced to implement more code (including the top-level event loop) in - * JavaScript itself. - */ -// 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. -// TODO(vsm): This was changed from init.globalState. -// See: https://github.com/dart-lang/dev_compiler/issues/164 -_Manager get _globalState => JS("_Manager", "dart.globalState"); - -set _globalState(_Manager val) { - // TODO(vsm): This was changed from init.globalState. - // See: https://github.com/dart-lang/dev_compiler/issues/164 - JS("void", "dart.globalState = #", val); -} - -/** State associated with the current manager. See [globalState]. */ -// TODO(sigmund): split in multiple classes: global, thread, main-worker states? -class _Manager { - - /** Next available isolate id within this [_Manager]. */ - int nextIsolateId = 0; - - /** id assigned to this [_Manager]. */ - int currentManagerId = 0; - - /** - * Next available manager id. Only used by the main manager to assign a unique - * id to each manager created by it. - */ - int nextManagerId = 1; - - /** Context for the currently running [Isolate]. */ - _IsolateContext currentContext = null; - - /** Context for the root [Isolate] that first run in this [_Manager]. */ - _IsolateContext rootContext = null; - - /** The top-level event loop. */ - _EventLoop topEventLoop; - - /** Whether this program is running from the command line. */ - bool fromCommandLine; - - /** Whether this [_Manager] is running as a web worker. */ - bool isWorker; - - /** Whether we support spawning web workers. */ - bool supportsWorkers; - - /** - * Whether to use web workers when implementing isolates. Set to false for - * debugging/testing. - */ - bool get useWorkers => supportsWorkers; - - /** - * Registry of isolates. Isolates must be registered if, and only if, receive - * ports are alive. Normally no open receive-ports means that the isolate is - * dead, but DOM callbacks could resurrect it. - */ - Map isolates; - - /** Reference to the main [_Manager]. Null in the main [_Manager] itself. */ - _MainManagerStub mainManager; - - /// Registry of active Web Workers. Only used in the main [_Manager]. - Map managers; - - /** The entry point given by [startRootIsolate]. */ - final Function entry; - - _Manager(this.entry) { - _nativeDetectEnvironment(); - topEventLoop = new _EventLoop(); - isolates = new Map(); - managers = new Map(); - if (isWorker) { // "if we are not the main manager ourself" is the intent. - mainManager = new _MainManagerStub(); - _nativeInitWorkerMessageHandler(); - } - } - - void _nativeDetectEnvironment() { - bool isWindowDefined = globalWindow != null; - bool isWorkerDefined = globalWorker != null; - - isWorker = !isWindowDefined && globalPostMessageDefined; - supportsWorkers = isWorker - || (isWorkerDefined && IsolateNatives.thisScript != null); - fromCommandLine = !isWindowDefined && !isWorker; - } - - void _nativeInitWorkerMessageHandler() { - var function = JS('', - "(function (f, a) { return function (e) { f(a, e); }})(#, #)", - DART_CLOSURE_TO_JS(IsolateNatives._processWorkerMessage), - mainManager); - JS("void", r"self.onmessage = #", function); - // We ensure dartPrint is defined so that the implementation of the Dart - // print method knows what to call. - JS('', '''self.dartPrint = self.dartPrint || (function(serialize) { - return function (object) { - if (self.console && self.console.log) { - self.console.log(object) - } else { - self.postMessage(serialize(object)); - } - } -})(#)''', DART_CLOSURE_TO_JS(_serializePrintMessage)); - } - - static _serializePrintMessage(object) { - return _serializeMessage({"command": "print", "msg": object}); - } - - /** - * Close the worker running this code if all isolates are done and - * there are no active async JavaScript tasks still running. - */ - void maybeCloseWorker() { - if (isWorker - && isolates.isEmpty - && topEventLoop._activeJsAsyncCount == 0) { - mainManager.postMessage(_serializeMessage({'command': 'close'})); - } - } -} - -/** Context information tracked for each isolate. */ -class _IsolateContext implements IsolateContext { - /** Current isolate id. */ - final int id = _globalState.nextIsolateId++; - - /** Registry of receive ports currently active on this isolate. */ - final Map ports = new Map(); - - /** Registry of weak receive ports currently active on this isolate. */ - final Set weakPorts = new Set(); - - /** Holds isolate globals (statics and top-level properties). */ - // native object containing all globals of an isolate. - final isolateStatics = JS_CREATE_ISOLATE(); - - final RawReceivePortImpl controlPort = new RawReceivePortImpl._controlPort(); - - final Capability pauseCapability = new Capability(); - final Capability terminateCapability = new Capability(); // License to kill. - - /// Boolean flag set when the initial method of the isolate has been executed. - /// - /// Used to avoid considering the isolate dead when it has no open - /// receive ports and no scheduled timers, because it hasn't had time to - /// create them yet. - bool initialized = false; - - // TODO(lrn): Store these in single "PauseState" object, so they don't take - // up as much room when not pausing. - bool isPaused = false; - List<_IsolateEvent> delayedEvents = []; - Set pauseTokens = new Set(); - - // Container with the "on exit" handler send-ports. - var doneHandlers; - - /** - * Queue of functions to call when the current event is complete. - * - * These events are not just put at the front of the event queue, because - * they represent control messages, and should be handled even if the - * event queue is paused. - */ - var _scheduledControlEvents; - bool _isExecutingEvent = false; - - /** Whether uncaught errors are considered fatal. */ - bool errorsAreFatal = true; - - // Set of ports that listen to uncaught errors. - Set errorPorts = new Set(); - - _IsolateContext() { - this.registerWeak(controlPort._id, controlPort); - } - - void addPause(Capability authentification, Capability resume) { - if (pauseCapability != authentification) return; - if (pauseTokens.add(resume) && !isPaused) { - isPaused = true; - } - _updateGlobalState(); - } - - void removePause(Capability resume) { - if (!isPaused) return; - pauseTokens.remove(resume); - if (pauseTokens.isEmpty) { - while(delayedEvents.isNotEmpty) { - _IsolateEvent event = delayedEvents.removeLast(); - _globalState.topEventLoop.prequeue(event); - } - isPaused = false; - } - _updateGlobalState(); - } - - void addDoneListener(SendPort responsePort) { - if (doneHandlers == null) { - doneHandlers = []; - } - // If necessary, we can switch doneHandlers to a Set if it gets larger. - // That is not expected to happen in practice. - if (doneHandlers.contains(responsePort)) return; - doneHandlers.add(responsePort); - } - - void removeDoneListener(SendPort responsePort) { - if (doneHandlers == null) return; - doneHandlers.remove(responsePort); - } - - void setErrorsFatal(Capability authentification, bool errorsAreFatal) { - if (terminateCapability != authentification) return; - this.errorsAreFatal = errorsAreFatal; - } - - void handlePing(SendPort responsePort, int pingType) { - if (pingType == Isolate.IMMEDIATE || - (pingType == Isolate.BEFORE_NEXT_EVENT && - !_isExecutingEvent)) { - responsePort.send(null); - return; - } - void respond() { responsePort.send(null); } - if (pingType == Isolate.AS_EVENT) { - _globalState.topEventLoop.enqueue(this, respond, "ping"); - return; - } - assert(pingType == Isolate.BEFORE_NEXT_EVENT); - if (_scheduledControlEvents == null) { - _scheduledControlEvents = new Queue(); - } - _scheduledControlEvents.addLast(respond); - } - - void handleKill(Capability authentification, int priority) { - if (this.terminateCapability != authentification) return; - if (priority == Isolate.IMMEDIATE || - (priority == Isolate.BEFORE_NEXT_EVENT && - !_isExecutingEvent)) { - kill(); - return; - } - if (priority == Isolate.AS_EVENT) { - _globalState.topEventLoop.enqueue(this, kill, "kill"); - return; - } - assert(priority == Isolate.BEFORE_NEXT_EVENT); - if (_scheduledControlEvents == null) { - _scheduledControlEvents = new Queue(); - } - _scheduledControlEvents.addLast(kill); - } - - void addErrorListener(SendPort port) { - errorPorts.add(port); - } - - void removeErrorListener(SendPort port) { - errorPorts.remove(port); - } - - /** Function called with an uncaught error. */ - void handleUncaughtError(error, StackTrace stackTrace) { - // Just print the error if there is no error listener registered. - if (errorPorts.isEmpty) { - // An uncaught error in the root isolate will terminate the program? - if (errorsAreFatal && identical(this, _globalState.rootContext)) { - // The error will be rethrown to reach the global scope, so - // don't print it. - return; - } - if (JS('bool', 'self.console && self.console.error')) { - JS('void', 'self.console.error(#, #)', error, stackTrace); - } else { - print(error); - if (stackTrace != null) print(stackTrace); - } - return; - } - List message = new List(2) - ..[0] = error.toString() - ..[1] = (stackTrace == null) ? null : stackTrace.toString(); - for (SendPort port in errorPorts) port.send(message); - } - - /** - * Run [code] in the context of the isolate represented by [this]. - */ - dynamic eval(Function code) { - var old = _globalState.currentContext; - _globalState.currentContext = this; - this._setGlobals(); - var result = null; - _isExecutingEvent = true; - try { - result = code(); - } catch (e, s) { - handleUncaughtError(e, s); - if (errorsAreFatal) { - kill(); - // An uncaught error in the root context terminates all isolates. - if (identical(this, _globalState.rootContext)) { - rethrow; - } - } - } finally { - _isExecutingEvent = false; - _globalState.currentContext = old; - if (old != null) old._setGlobals(); - if (_scheduledControlEvents != null) { - while (_scheduledControlEvents.isNotEmpty) { - (_scheduledControlEvents.removeFirst())(); - } - } - } - return result; - } - - void _setGlobals() { - JS_SET_CURRENT_ISOLATE(isolateStatics); - } - - /** - * Handle messages comming in on the control port. - * - * These events do not go through the event queue. - * The `_globalState.currentContext` context is not set to this context - * during the handling. - */ - void handleControlMessage(message) { - switch (message[0]) { - case "pause": - addPause(message[1], message[2]); - break; - case "resume": - removePause(message[1]); - break; - case 'add-ondone': - addDoneListener(message[1]); - break; - case 'remove-ondone': - removeDoneListener(message[1]); - break; - case 'set-errors-fatal': - setErrorsFatal(message[1], message[2]); - break; - case "ping": - handlePing(message[1], message[2]); - break; - case "kill": - handleKill(message[1], message[2]); - break; - case "getErrors": - addErrorListener(message[1]); - break; - case "stopErrors": - removeErrorListener(message[1]); - break; - default: - } - } - - /** Looks up a port registered for this isolate. */ - RawReceivePortImpl lookup(int portId) => ports[portId]; - - void _addRegistration(int portId, RawReceivePortImpl port) { - if (ports.containsKey(portId)) { - throw new Exception("Registry: ports must be registered only once."); - } - ports[portId] = port; - } - - /** Registers a port on this isolate. */ - void register(int portId, RawReceivePortImpl port) { - _addRegistration(portId, port); - _updateGlobalState(); - } - - /** - * Registers a weak port on this isolate. - * - * The port does not keep the isolate active. - */ - void registerWeak(int portId, RawReceivePortImpl port) { - weakPorts.add(portId); - _addRegistration(portId, port); - } - - void _updateGlobalState() { - if (ports.length - weakPorts.length > 0 || isPaused || !initialized) { - _globalState.isolates[id] = this; // indicate this isolate is active - } else { - kill(); - } - } - - void kill() { - if (_scheduledControlEvents != null) { - // Kill all pending events. - _scheduledControlEvents.clear(); - } - // Stop listening on all ports. - // This should happen before sending events to done handlers, in case - // we are listening on ourselves. - // Closes all ports, including control port. - for (var port in ports.values) { - port._close(); - } - ports.clear(); - weakPorts.clear(); - _globalState.isolates.remove(id); // indicate this isolate is not active - errorPorts.clear(); - if (doneHandlers != null) { - for (SendPort port in doneHandlers) { - port.send(null); - } - doneHandlers = null; - } - } - - /** Unregister a port on this isolate. */ - void unregister(int portId) { - ports.remove(portId); - weakPorts.remove(portId); - _updateGlobalState(); - } -} - -/** Represent the event loop on a javascript thread (DOM or worker). */ -class _EventLoop { - final Queue<_IsolateEvent> events = new Queue<_IsolateEvent>(); - - /// The number of waiting callbacks not controlled by the dart event loop. - /// - /// This could be timers or http requests. The worker will only be killed if - /// this count reaches 0. - /// Access this by using [enterJsAsync] before starting a JavaScript async - /// operation and [leaveJsAsync] when the callback has fired. - int _activeJsAsyncCount = 0; - - _EventLoop(); - - void enqueue(isolate, fn, msg) { - events.addLast(new _IsolateEvent(isolate, fn, msg)); - } - - void prequeue(_IsolateEvent event) { - events.addFirst(event); - } - - _IsolateEvent dequeue() { - if (events.isEmpty) return null; - return events.removeFirst(); - } - - void checkOpenReceivePortsFromCommandLine() { - if (_globalState.rootContext != null - && _globalState.isolates.containsKey(_globalState.rootContext.id) - && _globalState.fromCommandLine - && _globalState.rootContext.ports.isEmpty) { - // We want to reach here only on the main [_Manager] and only - // on the command-line. In the browser the isolate might - // still be alive due to DOM callbacks, but the presumption is - // that on the command-line, no future events can be injected - // into the event queue once it's empty. Node has setTimeout - // so this presumption is incorrect there. We think(?) that - // in d8 this assumption is valid. - throw new Exception("Program exited with open ReceivePorts."); - } - } - - /** Process a single event, if any. */ - bool runIteration() { - final event = dequeue(); - if (event == null) { - checkOpenReceivePortsFromCommandLine(); - _globalState.maybeCloseWorker(); - return false; - } - event.process(); - return true; - } - - /** - * Runs multiple iterations of the run-loop. If possible, each iteration is - * run asynchronously. - */ - void _runHelper() { - if (globalWindow != null) { - // Run each iteration from the browser's top event loop. - next() { - if (!runIteration()) return; - Timer.run(next); - } - next(); - } else { - // Run synchronously until no more iterations are available. - while (runIteration()) {} - } - } - - /** - * Call [_runHelper] but ensure that worker exceptions are propragated. - */ - void run() { - if (!_globalState.isWorker) { - _runHelper(); - } else { - try { - _runHelper(); - } catch (e, trace) { - _globalState.mainManager.postMessage(_serializeMessage( - {'command': 'error', 'msg': '$e\n$trace' })); - } - } - } -} - -/** An event in the top-level event queue. */ -class _IsolateEvent { - _IsolateContext isolate; - Function fn; - String message; - - _IsolateEvent(this.isolate, this.fn, this.message); - - void process() { - if (isolate.isPaused) { - isolate.delayedEvents.add(this); - return; - } - isolate.eval(fn); - } -} - -/** A stub for interacting with the main manager. */ -class _MainManagerStub { - void postMessage(msg) { - // "self" is a way to refer to the global context object that - // works in HTML pages and in Web Workers. It does not work in d8 - // and Firefox jsshell, because that would have been too easy. - // - // See: http://www.w3.org/TR/workers/#the-global-scope - // and: http://www.w3.org/TR/Window/#dfn-self-attribute - requiresPreamble(); - JS("void", r"self.postMessage(#)", msg); - } -} - -const String _SPAWNED_SIGNAL = "spawned"; -const String _SPAWN_FAILED_SIGNAL = "spawn failed"; - -get globalWindow { - requiresPreamble(); - return JS('', "self.window"); -} - -get globalWorker { - requiresPreamble(); - return JS('', "self.Worker"); -} -bool get globalPostMessageDefined { - requiresPreamble(); - return JS('bool', "!!self.postMessage"); -} - -typedef _MainFunction(); -typedef _MainFunctionArgs(args); -typedef _MainFunctionArgsMessage(args, message); - -/// Note: IsolateNatives depends on _globalState which is only set up correctly -/// when 'dart:isolate' has been imported. -class IsolateNatives { - - // We set [enableSpawnWorker] to true (not null) when calling isolate - // primitives that require support for spawning workers. The field starts out - // by being null, and dart2js' type inference will track if it can have a - // non-null value. So by testing if this value is not null, we generate code - // that dart2js knows is dead when worker support isn't needed. - // TODO(herhut): Initialize this to false when able to track compile-time - // constants. - static var enableSpawnWorker; - - static String thisScript = computeThisScript(); - - /// Associates an ID with a native worker object. - static final Expando workerIds = new Expando(); - - /** - * The src url for the script tag that loaded this Used to create - * JavaScript workers. - */ - static String computeThisScript() { - // See: https://github.com/dart-lang/dev_compiler/issues/164 - // var currentScript = JS_EMBEDDED_GLOBAL('', CURRENT_SCRIPT); - var currentScript = JS('var', 'document.currentScript'); - if (currentScript != null) { - return JS('String', 'String(#.src)', currentScript); - } - if (Primitives.isD8) return computeThisScriptD8(); - if (Primitives.isJsshell) return computeThisScriptJsshell(); - // A worker has no script tag - so get an url from a stack-trace. - if (_globalState.isWorker) return computeThisScriptFromTrace(); - return null; - } - - static String computeThisScriptJsshell() { - return JS('String|Null', 'thisFilename()'); - } - - // TODO(ahe): The following is for supporting D8. We should move this code - // to a helper library that is only loaded when testing on D8. - static String computeThisScriptD8() => computeThisScriptFromTrace(); - - static String computeThisScriptFromTrace() { - var stack = JS('String|Null', 'new Error().stack'); - if (stack == null) { - // According to Internet Explorer documentation, the stack - // property is not set until the exception is thrown. The stack - // property was not provided until IE10. - stack = JS('String|Null', - '(function() {' - 'try { throw new Error() } catch(e) { return e.stack }' - '})()'); - if (stack == null) throw new UnsupportedError('No stack trace'); - } - var pattern, matches; - - // This pattern matches V8, Chrome, and Internet Explorer stack - // traces that look like this: - // Error - // at methodName (URI:LINE:COLUMN) - pattern = JS('', - r'new RegExp("^ *at [^(]*\\((.*):[0-9]*:[0-9]*\\)$", "m")'); - - - matches = JS('JSExtendableArray|Null', '#.match(#)', stack, pattern); - if (matches != null) return JS('String', '#[1]', matches); - - // This pattern matches Firefox stack traces that look like this: - // methodName@URI:LINE - pattern = JS('', r'new RegExp("^[^@]*@(.*):[0-9]*$", "m")'); - - matches = JS('JSExtendableArray|Null', '#.match(#)', stack, pattern); - if (matches != null) return JS('String', '#[1]', matches); - - throw new UnsupportedError('Cannot extract URI from "$stack"'); - } - - /** - * Assume that [e] is a browser message event and extract its message data. - * We don't import the dom explicitly so, when workers are disabled, this - * library can also run on top of nodejs. - */ - static _getEventData(e) => JS("", "#.data", e); - - /** - * Process messages on a worker, either to control the worker instance or to - * pass messages along to the isolate running in the worker. - */ - static void _processWorkerMessage(/* Worker */ sender, e) { - var msg = _deserializeMessage(_getEventData(e)); - switch (msg['command']) { - case 'start': - _globalState.currentManagerId = msg['id']; - String functionName = msg['functionName']; - Function entryPoint = (functionName == null) - ? _globalState.entry - : _getJSFunctionFromName(functionName); - var args = msg['args']; - var message = _deserializeMessage(msg['msg']); - var isSpawnUri = msg['isSpawnUri']; - var startPaused = msg['startPaused']; - var replyTo = _deserializeMessage(msg['replyTo']); - var context = new _IsolateContext(); - _globalState.topEventLoop.enqueue(context, () { - _startIsolate(entryPoint, args, message, - isSpawnUri, startPaused, replyTo); - }, 'worker-start'); - // Make sure we always have a current context in this worker. - // TODO(7907): This is currently needed because we're using - // Timers to implement Futures, and this isolate library - // implementation uses Futures. We should either stop using - // Futures in this library, or re-adapt if Futures get a - // different implementation. - _globalState.currentContext = context; - _globalState.topEventLoop.run(); - break; - case 'spawn-worker': - if (enableSpawnWorker != null) handleSpawnWorkerRequest(msg); - break; - case 'message': - SendPort port = msg['port']; - // If the port has been closed, we ignore the message. - if (port != null) { - msg['port'].send(msg['msg']); - } - _globalState.topEventLoop.run(); - break; - case 'close': - _globalState.managers.remove(workerIds[sender]); - JS('void', '#.terminate()', sender); - _globalState.topEventLoop.run(); - break; - case 'log': - _log(msg['msg']); - break; - case 'print': - if (_globalState.isWorker) { - _globalState.mainManager.postMessage( - _serializeMessage({'command': 'print', 'msg': msg})); - } else { - print(msg['msg']); - } - break; - case 'error': - throw msg['msg']; - } - } - - static handleSpawnWorkerRequest(msg) { - var replyPort = msg['replyPort']; - spawn(msg['functionName'], msg['uri'], - msg['args'], msg['msg'], - false, msg['isSpawnUri'], msg['startPaused']).then((msg) { - replyPort.send(msg); - }, onError: (String errorMessage) { - replyPort.send([_SPAWN_FAILED_SIGNAL, errorMessage]); - }); - } - - /** Log a message, forwarding to the main [_Manager] if appropriate. */ - static _log(msg) { - if (_globalState.isWorker) { - _globalState.mainManager.postMessage( - _serializeMessage({'command': 'log', 'msg': msg })); - } else { - try { - _consoleLog(msg); - } catch (e, trace) { - throw new Exception(trace); - } - } - } - - static void _consoleLog(msg) { - requiresPreamble(); - JS("void", r"self.console.log(#)", msg); - } - - static _getJSFunctionFromName(String functionName) { - var globalFunctionsContainer = JS_EMBEDDED_GLOBAL("", GLOBAL_FUNCTIONS); - return JS("", "#[#]()", globalFunctionsContainer, functionName); - } - - /** - * Get a string name for the function, if possible. The result for - * anonymous functions is browser-dependent -- it may be "" or "anonymous" - * but you should probably not count on this. - */ - static String _getJSFunctionName(Function f) { - return (f is Closure) ? JS("String|Null", r'#.$name', f) : null; - } - - /** Create a new JavaScript object instance given its constructor. */ - static dynamic _allocate(var ctor) { - return JS("", "new #()", ctor); - } - - static Future spawnFunction(void topLevelFunction(message), - var message, - bool startPaused) { - IsolateNatives.enableSpawnWorker = true; - final name = _getJSFunctionName(topLevelFunction); - if (name == null) { - throw new UnsupportedError( - "only top-level functions can be spawned."); - } - bool isLight = false; - bool isSpawnUri = false; - return spawn(name, null, null, message, isLight, isSpawnUri, startPaused); - } - - static Future spawnUri(Uri uri, List args, var message, - bool startPaused) { - IsolateNatives.enableSpawnWorker = true; - bool isLight = false; - bool isSpawnUri = true; - return spawn(null, uri.toString(), args, message, - isLight, isSpawnUri, startPaused); - } - - // TODO(sigmund): clean up above, after we make the new API the default: - - /// If [uri] is `null` it is replaced with the current script. - static Future spawn(String functionName, String uri, - List args, message, - bool isLight, bool isSpawnUri, bool startPaused) { - // Assume that the compiled version of the Dart file lives just next to the - // dart file. - // TODO(floitsch): support precompiled version of dart2js output. - if (uri != null && uri.endsWith(".dart")) uri += ".js"; - - ReceivePort port = new ReceivePort(); - Completer completer = new Completer(); - port.first.then((msg) { - if (msg[0] == _SPAWNED_SIGNAL) { - completer.complete(msg); - } else { - assert(msg[0] == _SPAWN_FAILED_SIGNAL); - completer.completeError(msg[1]); - } - }); - - SendPort signalReply = port.sendPort; - - if (_globalState.useWorkers && !isLight) { - _startWorker( - functionName, uri, args, message, isSpawnUri, startPaused, - signalReply, (String message) => completer.completeError(message)); - } else { - _startNonWorker( - functionName, uri, args, message, isSpawnUri, startPaused, - signalReply); - } - return completer.future; - } - - static void _startWorker( - String functionName, String uri, - List args, message, - bool isSpawnUri, - bool startPaused, - SendPort replyPort, - void onError(String message)) { - // Make sure that the args list is a fresh generic list. A newly spawned - // isolate should be able to assume that the arguments list is an - // extendable list. - if (args != null) args = new List.from(args); - if (_globalState.isWorker) { - _globalState.mainManager.postMessage(_serializeMessage({ - 'command': 'spawn-worker', - 'functionName': functionName, - 'args': args, - 'msg': message, - 'uri': uri, - 'isSpawnUri': isSpawnUri, - 'startPaused': startPaused, - 'replyPort': replyPort})); - } else { - _spawnWorker(functionName, uri, args, message, - isSpawnUri, startPaused, replyPort, onError); - } - } - - static void _startNonWorker( - String functionName, String uri, - List args, var message, - bool isSpawnUri, - bool startPaused, - SendPort replyPort) { - // TODO(eub): support IE9 using an iframe -- Dart issue 1702. - if (uri != null) { - throw new UnsupportedError( - "Currently spawnUri is not supported without web workers."); - } - // Clone the message to enforce the restrictions we have on isolate - // messages. - message = _clone(message); - // Make sure that the args list is a fresh generic list. A newly spawned - // isolate should be able to assume that the arguments list is an - // extendable list. - if (args != null) args = new List.from(args); - _globalState.topEventLoop.enqueue(new _IsolateContext(), () { - final func = _getJSFunctionFromName(functionName); - _startIsolate(func, args, message, isSpawnUri, startPaused, replyPort); - }, 'nonworker start'); - } - - static Isolate get currentIsolate { - _IsolateContext context = JS_CURRENT_ISOLATE_CONTEXT(); - return new Isolate(context.controlPort.sendPort, - pauseCapability: context.pauseCapability, - terminateCapability: context.terminateCapability); - } - - static void _startIsolate(Function topLevel, - List args, message, - bool isSpawnUri, - bool startPaused, - SendPort replyTo) { - _IsolateContext context = JS_CURRENT_ISOLATE_CONTEXT(); - Primitives.initializeStatics(context.id); - // The isolate's port does not keep the isolate open. - replyTo.send([_SPAWNED_SIGNAL, - context.controlPort.sendPort, - context.pauseCapability, - context.terminateCapability]); - - void runStartFunction() { - context.initialized = true; - if (!isSpawnUri) { - topLevel(message); - } else if (topLevel is _MainFunctionArgsMessage) { - topLevel(args, message); - } else if (topLevel is _MainFunctionArgs) { - topLevel(args); - } else { - topLevel(); - } - } - - if (startPaused) { - context.addPause(context.pauseCapability, context.pauseCapability); - _globalState.topEventLoop.enqueue(context, runStartFunction, - 'start isolate'); - } else { - runStartFunction(); - } - } - - /** - * Spawns an isolate in a worker. [factoryName] is the Javascript constructor - * name for the isolate entry point class. - */ - static void _spawnWorker(functionName, String uri, - List args, message, - bool isSpawnUri, - bool startPaused, - SendPort replyPort, - void onError(String message)) { - if (uri == null) uri = thisScript; - final worker = JS('var', 'new Worker(#)', uri); - // Trampolines are used when wanting to call a Dart closure from - // JavaScript. The helper function DART_CLOSURE_TO_JS only accepts - // top-level or static methods, and the trampoline allows us to capture - // arguments and values which can be passed to a static method. - final onerrorTrampoline = JS( - '', - ''' -(function (f, u, c) { - return function(e) { - return f(e, u, c) - } -})(#, #, #)''', - DART_CLOSURE_TO_JS(workerOnError), uri, onError); - JS('void', '#.onerror = #', worker, onerrorTrampoline); - - var processWorkerMessageTrampoline = JS( - '', - """ -(function (f, a) { - return function (e) { - // We can stop listening for errors when the first message is received as - // we only listen for messages to determine if the uri was bad. - e.onerror = null; - return f(a, e); - } -})(#, #)""", - DART_CLOSURE_TO_JS(_processWorkerMessage), - worker); - JS('void', '#.onmessage = #', worker, processWorkerMessageTrampoline); - var workerId = _globalState.nextManagerId++; - // We also store the id on the worker itself so that we can unregister it. - workerIds[worker] = workerId; - _globalState.managers[workerId] = worker; - JS('void', '#.postMessage(#)', worker, _serializeMessage({ - 'command': 'start', - 'id': workerId, - // Note: we serialize replyPort twice because the child worker needs to - // first deserialize the worker id, before it can correctly deserialize - // the port (port deserialization is sensitive to what is the current - // workerId). - 'replyTo': _serializeMessage(replyPort), - 'args': args, - 'msg': _serializeMessage(message), - 'isSpawnUri': isSpawnUri, - 'startPaused': startPaused, - 'functionName': functionName })); - } - - static bool workerOnError( - /* Event */ event, - String uri, - void onError(String message)) { - // Attempt to shut up the browser, as the error has been handled. Chrome - // ignores this :-( - JS('void', '#.preventDefault()', event); - String message = JS('String|Null', '#.message', event); - if (message == null) { - // Some browsers, including Chrome, fail to provide a proper error - // event. - message = 'Error spawning worker for $uri'; - } else { - message = 'Error spawning worker for $uri ($message)'; - } - onError(message); - return true; - } -} - -/******************************************************** - Inserted from lib/isolate/dart2js/ports.dart - ********************************************************/ - -/** Common functionality to all send ports. */ -abstract class _BaseSendPort implements SendPort { - /** Id for the destination isolate. */ - final int _isolateId; - - const _BaseSendPort(this._isolateId); - - void _checkReplyTo(SendPort replyTo) { - if (replyTo != null - && replyTo is! _NativeJsSendPort - && replyTo is! _WorkerSendPort) { - throw new Exception("SendPort.send: Illegal replyTo port type"); - } - } - - void send(var message); - bool operator ==(var other); - int get hashCode; -} - -/** A send port that delivers messages in-memory via native JavaScript calls. */ -class _NativeJsSendPort extends _BaseSendPort implements SendPort { - final RawReceivePortImpl _receivePort; - - const _NativeJsSendPort(this._receivePort, int isolateId) : super(isolateId); - - void send(var message) { - // Check that the isolate still runs and the port is still open - final isolate = _globalState.isolates[_isolateId]; - if (isolate == null) return; - if (_receivePort._isClosed) return; - // Clone the message to enforce the restrictions we have on isolate - // messages. - var msg = _clone(message); - if (isolate.controlPort == _receivePort) { - isolate.handleControlMessage(msg); - return; - } - _globalState.topEventLoop.enqueue(isolate, () { - if (!_receivePort._isClosed) { - _receivePort._add(msg); - } - }, 'receive $message'); - } - - bool operator ==(var other) => (other is _NativeJsSendPort) && - (_receivePort == other._receivePort); - - int get hashCode => _receivePort._id; -} - -/** A send port that delivers messages via worker.postMessage. */ -// TODO(eub): abstract this for iframes. -class _WorkerSendPort extends _BaseSendPort implements SendPort { - final int _workerId; - final int _receivePortId; - - const _WorkerSendPort(this._workerId, int isolateId, this._receivePortId) - : super(isolateId); - - void send(var message) { - final workerMessage = _serializeMessage({ - 'command': 'message', - 'port': this, - 'msg': message}); - - if (_globalState.isWorker) { - // Communication from one worker to another go through the - // main worker. - _globalState.mainManager.postMessage(workerMessage); - } else { - // Deliver the message only if the worker is still alive. - /* Worker */ var manager = _globalState.managers[_workerId]; - if (manager != null) { - JS('void', '#.postMessage(#)', manager, workerMessage); - } - } - } - - bool operator ==(var other) { - return (other is _WorkerSendPort) && - (_workerId == other._workerId) && - (_isolateId == other._isolateId) && - (_receivePortId == other._receivePortId); - } - - int get hashCode { - // TODO(sigmund): use a standard hash when we get one available in corelib. - return (_workerId << 16) ^ (_isolateId << 8) ^ _receivePortId; - } -} - -class RawReceivePortImpl implements RawReceivePort { - static int _nextFreeId = 1; - - final int _id; - Function _handler; - bool _isClosed = false; - - RawReceivePortImpl(this._handler) : _id = _nextFreeId++ { - _globalState.currentContext.register(_id, this); - } - - RawReceivePortImpl.weak(this._handler) : _id = _nextFreeId++ { - _globalState.currentContext.registerWeak(_id, this); - } - - // Creates the control port of an isolate. - // This is created before the isolate context object itself, - // so it cannot access the static _nextFreeId field. - RawReceivePortImpl._controlPort() : _handler = null, _id = 0; - - void set handler(Function newHandler) { - _handler = newHandler; - } - - // Close the port without unregistering it. - // Used by an isolate context to close all ports when shutting down. - void _close() { - _isClosed = true; - _handler = null; - } - - void close() { - if (_isClosed) return; - _isClosed = true; - _handler = null; - _globalState.currentContext.unregister(_id); - } - - void _add(dataEvent) { - if (_isClosed) return; - _handler(dataEvent); - } - - SendPort get sendPort { - return new _NativeJsSendPort(this, _globalState.currentContext.id); - } -} - -class ReceivePortImpl extends Stream implements ReceivePort { - final RawReceivePort _rawPort; - StreamController _controller; - - ReceivePortImpl() : this.fromRawReceivePort(new RawReceivePortImpl(null)); - - ReceivePortImpl.weak() - : this.fromRawReceivePort(new RawReceivePortImpl.weak(null)); - - ReceivePortImpl.fromRawReceivePort(this._rawPort) { - _controller = new StreamController(onCancel: close, sync: true); - _rawPort.handler = _controller.add; - } - - StreamSubscription listen(void onData(var event), - {Function onError, - void onDone(), - bool cancelOnError}) { - return _controller.stream.listen(onData, onError: onError, onDone: onDone, - cancelOnError: cancelOnError); - } - - void close() { - _rawPort.close(); - _controller.close(); - } - - SendPort get sendPort => _rawPort.sendPort; -} - -class TimerImpl implements Timer { - final bool _once; - bool _inEventLoop = false; - int _handle; - - TimerImpl(int milliseconds, void callback()) - : _once = true { - if (milliseconds == 0 && (!hasTimer() || _globalState.isWorker)) { - - void internalCallback() { - _handle = null; - callback(); - } - - // Setting _handle to something different from null indicates that the - // callback has not been run. Hence, the choice of 1 is arbitrary. - _handle = 1; - - // This makes a dependency between the async library and the - // event loop of the isolate library. The compiler makes sure - // that the event loop is compiled if [Timer] is used. - // TODO(7907): In case of web workers, we need to use the event - // loop instead of setTimeout, to make sure the futures get executed in - // order. - _globalState.topEventLoop.enqueue( - _globalState.currentContext, internalCallback, 'timer'); - _inEventLoop = true; - } else if (hasTimer()) { - - void internalCallback() { - _handle = null; - leaveJsAsync(); - callback(); - } - - enterJsAsync(); - - _handle = JS('int', 'self.setTimeout(#, #)', - convertDartClosureToJS(internalCallback, 0), - milliseconds); - } else { - assert(milliseconds > 0); - throw new UnsupportedError("Timer greater than 0."); - } - } - - TimerImpl.periodic(int milliseconds, void callback(Timer timer)) - : _once = false { - if (hasTimer()) { - enterJsAsync(); - _handle = JS('int', 'self.setInterval(#, #)', - convertDartClosureToJS(() { callback(this); }, 0), - milliseconds); - } else { - throw new UnsupportedError("Periodic timer."); - } - } - - void cancel() { - if (hasTimer()) { - if (_inEventLoop) { - throw new UnsupportedError("Timer in event loop cannot be canceled."); - } - if (_handle == null) return; - leaveJsAsync(); - if (_once) { - JS('void', 'self.clearTimeout(#)', _handle); - } else { - JS('void', 'self.clearInterval(#)', _handle); - } - _handle = null; - } else { - throw new UnsupportedError("Canceling a timer."); - } - } - - bool get isActive => _handle != null; -} - -bool hasTimer() { - requiresPreamble(); - return JS('', 'self.setTimeout') != null; -} - - -/** - * Implementation class for [Capability]. - * - * It has the same name to make it harder for users to distinguish. - */ -class CapabilityImpl implements Capability { - /** Internal random secret identifying the capability. */ - final int _id; - - CapabilityImpl() : this._internal(random64()); - - CapabilityImpl._internal(this._id); - - int get hashCode { - // Thomas Wang 32 bit Mix. - // http://www.concentric.net/~Ttwang/tech/inthash.htm - // (via https://gist.github.com/badboy/6267743) - int hash = _id; - hash = (hash >> 0) ^ (hash ~/ 0x100000000); // To 32 bit from ~64. - hash = (~hash + (hash << 15)) & 0xFFFFFFFF; - hash ^= hash >> 12; - hash = (hash * 5) & 0xFFFFFFFF; - hash ^= hash >> 4; - hash = (hash * 2057) & 0xFFFFFFFF; - hash ^= hash >> 16; - return hash; - } - - bool operator==(Object other) { - if (identical(other, this)) return true; - if (other is CapabilityImpl) { - return identical(_id, other._id); - } - return false; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/isolate_serialization.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/isolate_serialization.dart deleted file mode 100644 index 51a294393e90..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/isolate_serialization.dart +++ /dev/null @@ -1,361 +0,0 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of _isolate_helper; - -/// Serialize [message]. -_serializeMessage(message) { - return new _Serializer().serialize(message); -} - -/// Deserialize [message]. -_deserializeMessage(message) { - return new _Deserializer().deserialize(message); -} - -/// Clones the message. -/// -/// Contrary to a `_deserializeMessage(_serializeMessage(x))` the `_clone` -/// function will not try to adjust SendPort values and pass them through. -_clone(message) { - _Serializer serializer = new _Serializer(serializeSendPorts: false); - _Deserializer deserializer = new _Deserializer(); - return deserializer.deserialize(serializer.serialize(message)); -} - -class _Serializer { - final bool _serializeSendPorts; - Map serializedObjectIds = new Map.identity(); - - _Serializer({serializeSendPorts: true}) - : _serializeSendPorts = serializeSendPorts; - - /// Returns a message that can be transmitted through web-worker channels. - serialize(x) { - if (isPrimitive(x)) return serializePrimitive(x); - - int serializationId = serializedObjectIds[x]; - if (serializationId != null) return makeRef(serializationId); - - serializationId = serializedObjectIds.length; - serializedObjectIds[x] = serializationId; - - if (x is NativeByteBuffer) return serializeByteBuffer(x); - if (x is NativeTypedData) return serializeTypedData(x); - if (x is JSIndexable) return serializeJSIndexable(x); - if (x is InternalMap) return serializeMap(x); - - if (x is JSObject) return serializeJSObject(x); - - // We should not have any interceptors any more. - if (x is Interceptor) unsupported(x); - - if (x is RawReceivePort) { - unsupported(x, "RawReceivePorts can't be transmitted:"); - } - - // SendPorts need their workerIds adjusted (either during serialization or - // deserialization). - if (x is _NativeJsSendPort) return serializeJsSendPort(x); - if (x is _WorkerSendPort) return serializeWorkerSendPort(x); - - if (x is Closure) return serializeClosure(x); - - return serializeDartObject(x); - } - - void unsupported(x, [String message]) { - if (message == null) message = "Can't transmit:"; - throw new UnsupportedError("$message $x"); - } - - makeRef(int serializationId) => ["ref", serializationId]; - - bool isPrimitive(x) => x == null || x is String || x is num || x is bool; - serializePrimitive(primitive) => primitive; - - serializeByteBuffer(NativeByteBuffer buffer) { - return ["buffer", buffer]; - } - - serializeTypedData(NativeTypedData data) { - return ["typed", data]; - } - - serializeJSIndexable(JSIndexable indexable) { - // Strings are JSIndexable but should have been treated earlier. - assert(indexable is! String); - List serialized = serializeArray(indexable); - if (indexable is JSFixedArray) return ["fixed", serialized]; - if (indexable is JSExtendableArray) return ["extendable", serialized]; - // MutableArray check must be last, since JSFixedArray and JSExtendableArray - // extend JSMutableArray. - if (indexable is JSMutableArray) return ["mutable", serialized]; - // The only JSArrays left are the const Lists (as in `const [1, 2]`). - if (indexable is JSArray) return ["const", serialized]; - unsupported(indexable, "Can't serialize indexable: "); - return null; - } - - serializeArray(JSArray x) { - List serialized = []; - serialized.length = x.length; - for (int i = 0; i < x.length; i++) { - serialized[i] = serialize(x[i]); - } - return serialized; - } - - serializeArrayInPlace(JSArray x) { - for (int i = 0; i < x.length; i++) { - x[i] = serialize(x[i]); - } - return x; - } - - serializeMap(Map x) { - Function serializeTearOff = serialize; - return ['map', - x.keys.map(serializeTearOff).toList(), - x.values.map(serializeTearOff).toList()]; - } - - serializeJSObject(JSObject x) { - // Don't serialize objects if their `constructor` property isn't `Object` - // or undefined/null. - // A different constructor is taken as a sign that the object has complex - // internal state, or that it is a function, and won't be serialized. - if (JS('bool', '!!(#.constructor)', x) && - JS('bool', 'x.constructor !== Object')) { - unsupported(x, "Only plain JS Objects are supported:"); - } - List keys = JS('JSArray', 'Object.keys(#)', x); - List values = []; - values.length = keys.length; - for (int i = 0; i < keys.length; i++) { - values[i] = serialize(JS('', '#[#]', x, keys[i])); - } - return ['js-object', keys, values]; - } - - serializeWorkerSendPort(_WorkerSendPort x) { - if (_serializeSendPorts) { - return ['sendport', x._workerId, x._isolateId, x._receivePortId]; - } - return ['raw sendport', x]; - } - - serializeJsSendPort(_NativeJsSendPort x) { - if (_serializeSendPorts) { - int workerId = _globalState.currentManagerId; - return ['sendport', workerId, x._isolateId, x._receivePort._id]; - } - return ['raw sendport', x]; - } - - serializeCapability(CapabilityImpl x) => ['capability', x._id]; - - serializeClosure(Closure x) { - final name = IsolateNatives._getJSFunctionName(x); - if (name == null) { - unsupported(x, "Closures can't be transmitted:"); - } - return ['function', name]; - } - - serializeDartObject(x) { - var classExtractor = JS_EMBEDDED_GLOBAL('', CLASS_ID_EXTRACTOR); - var fieldsExtractor = JS_EMBEDDED_GLOBAL('', CLASS_FIELDS_EXTRACTOR); - String classId = JS('String', '#(#)', classExtractor, x); - List fields = JS('JSArray', '#(#)', fieldsExtractor, x); - return ['dart', classId, serializeArrayInPlace(fields)]; - } -} - -class _Deserializer { - /// When `true`, encodes sendports specially so that they can be adjusted on - /// the receiving end. - /// - /// When `false`, sendports are cloned like any other object. - final bool _adjustSendPorts; - - List deserializedObjects = new List(); - - _Deserializer({adjustSendPorts: true}) : _adjustSendPorts = adjustSendPorts; - - /// Returns a message that can be transmitted through web-worker channels. - deserialize(x) { - if (isPrimitive(x)) return deserializePrimitive(x); - - if (x is! JSArray) throw new ArgumentError("Bad serialized message: $x"); - - switch (x.first) { - case "ref": return deserializeRef(x); - case "buffer": return deserializeByteBuffer(x); - case "typed": return deserializeTypedData(x); - case "fixed": return deserializeFixed(x); - case "extendable": return deserializeExtendable(x); - case "mutable": return deserializeMutable(x); - case "const": return deserializeConst(x); - case "map": return deserializeMap(x); - case "sendport": return deserializeSendPort(x); - case "raw sendport": return deserializeRawSendPort(x); - case "js-object": return deserializeJSObject(x); - case "function": return deserializeClosure(x); - case "dart": return deserializeDartObject(x); - default: throw "couldn't deserialize: $x"; - } - } - - bool isPrimitive(x) => x == null || x is String || x is num || x is bool; - deserializePrimitive(x) => x; - - // ['ref', id]. - deserializeRef(x) { - assert(x[0] == 'ref'); - int serializationId = x[1]; - return deserializedObjects[serializationId]; - } - - // ['buffer', ]. - NativeByteBuffer deserializeByteBuffer(x) { - assert(x[0] == 'buffer'); - NativeByteBuffer result = x[1]; - deserializedObjects.add(result); - return result; - } - - // ['typed', ]. - NativeTypedData deserializeTypedData(x) { - assert(x[0] == 'typed'); - NativeTypedData result = x[1]; - deserializedObjects.add(result); - return result; - } - - // Updates the given array in place with its deserialized content. - List deserializeArrayInPlace(JSArray x) { - for (int i = 0; i < x.length; i++) { - x[i] = deserialize(x[i]); - } - return x; - } - - // ['fixed', ]. - List deserializeFixed(x) { - assert(x[0] == 'fixed'); - List result = x[1]; - deserializedObjects.add(result); - return new JSArray.markFixed(deserializeArrayInPlace(result)); - } - - // ['extendable', ]. - List deserializeExtendable(x) { - assert(x[0] == 'extendable'); - List result = x[1]; - deserializedObjects.add(result); - return new JSArray.markGrowable(deserializeArrayInPlace(result)); - } - - // ['mutable', ]. - List deserializeMutable(x) { - assert(x[0] == 'mutable'); - List result = x[1]; - deserializedObjects.add(result); - return deserializeArrayInPlace(result); - } - - // ['const', ]. - List deserializeConst(x) { - assert(x[0] == 'const'); - List result = x[1]; - deserializedObjects.add(result); - // TODO(floitsch): need to mark list as non-changeable. - return new JSArray.markFixed(deserializeArrayInPlace(result)); - } - - // ['map', , ]. - Map deserializeMap(x) { - assert(x[0] == 'map'); - List keys = x[1]; - List values = x[2]; - Map result = {}; - deserializedObjects.add(result); - // We need to keep the order of how objects were serialized. - // First deserialize all keys, and then only deserialize the values. - keys = keys.map(deserialize).toList(); - - for (int i = 0; i < keys.length; i++) { - result[keys[i]] = deserialize(values[i]); - } - return result; - } - - // ['sendport', , , ]. - SendPort deserializeSendPort(x) { - assert(x[0] == 'sendport'); - int managerId = x[1]; - int isolateId = x[2]; - int receivePortId = x[3]; - SendPort result; - // If two isolates are in the same manager, we use NativeJsSendPorts to - // deliver messages directly without using postMessage. - if (managerId == _globalState.currentManagerId) { - var isolate = _globalState.isolates[isolateId]; - if (isolate == null) return null; // Isolate has been closed. - var receivePort = isolate.lookup(receivePortId); - if (receivePort == null) return null; // Port has been closed. - result = new _NativeJsSendPort(receivePort, isolateId); - } else { - result = new _WorkerSendPort(managerId, isolateId, receivePortId); - } - deserializedObjects.add(result); - return result; - } - - // ['raw sendport', ]. - SendPort deserializeRawSendPort(x) { - assert(x[0] == 'raw sendport'); - SendPort result = x[1]; - deserializedObjects.add(result); - return result; - } - - // ['js-object', , ]. - deserializeJSObject(x) { - assert(x[0] == 'js-object'); - List keys = x[1]; - List values = x[2]; - var o = JS('', '{}'); - deserializedObjects.add(o); - for (int i = 0; i < keys.length; i++) { - JS('', '#[#]=#', o, keys[i], deserialize(values[i])); - } - return o; - } - - // ['function', ]. - Function deserializeClosure(x) { - assert(x[0] == 'function'); - String name = x[1]; - Function result = IsolateNatives._getJSFunctionFromName(name); - deserializedObjects.add(result); - return result; - } - - // ['dart', , ]. - deserializeDartObject(x) { - assert(x[0] == 'dart'); - String classId = x[1]; - List fields = x[2]; - var instanceFromClassId = JS_EMBEDDED_GLOBAL('', INSTANCE_FROM_CLASS_ID); - var initializeObject = JS_EMBEDDED_GLOBAL('', INITIALIZE_EMPTY_INSTANCE); - - var emptyInstance = JS('', '#(#)', instanceFromClassId, classId); - deserializedObjects.add(emptyInstance); - deserializeArrayInPlace(fields); - return JS('', '#(#, #, #)', - initializeObject, classId, emptyInstance, fields); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_array.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_array.dart deleted file mode 100644 index fae79523869f..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_array.dart +++ /dev/null @@ -1,390 +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. - -part of _interceptors; - -/** - * The interceptor class for [List]. The compiler recognizes this - * class as an interceptor, and changes references to [:this:] to - * actually use the receiver of the method, which is generated as an extra - * argument added to each member. - */ -@JsName(name: 'Array') -class JSArray implements List, JSIndexable { - - const JSArray(); - - /** - * Returns a fresh JavaScript Array, marked as fixed-length. - * - * [length] must be a non-negative integer. - */ - factory JSArray.fixed(int length) { - // Explicit type test is necessary to guard against JavaScript conversions - // in unchecked mode. - if ((length is !int) || (length < 0)) { - throw new ArgumentError("Length must be a non-negative integer: $length"); - } - return new JSArray.markFixed(JS('', 'new Array(#)', length)); - } - - /** - * Returns a fresh growable JavaScript Array of zero length length. - */ - factory JSArray.emptyGrowable() => new JSArray.markGrowable(JS('', '[]')); - - /** - * Returns a fresh growable JavaScript Array with initial length. - * - * [validatedLength] must be a non-negative integer. - */ - factory JSArray.growable(int length) { - // Explicit type test is necessary to guard against JavaScript conversions - // in unchecked mode. - if ((length is !int) || (length < 0)) { - throw new ArgumentError("Length must be a non-negative integer: $length"); - } - return new JSArray.markGrowable(JS('', 'new Array(#)', length)); - } - - /** - * Constructor for adding type parameters to an existing JavaScript Array. - * The compiler specially recognizes this constructor. - * - * var a = new JSArray.typed(JS('JSExtendableArray', '[]')); - * a is List --> true - * a is List --> false - * - * Usually either the [JSArray.markFixed] or [JSArray.markGrowable] - * constructors is used instead. - * - * The input must be a JavaScript Array. The JS form is just a re-assertion - * to help type analysis when the input type is sloppy. - */ - factory JSArray.typed(allocation) => JS('JSArray', '#', allocation); - - factory JSArray.markFixed(allocation) => - JS('JSFixedArray', '#', markFixedList(new JSArray.typed(allocation))); - - factory JSArray.markGrowable(allocation) => - JS('JSExtendableArray', '#', new JSArray.typed(allocation)); - - static List markFixedList(List list) { - // Functions are stored in the hidden class and not as properties in - // the object. We never actually look at the value, but only want - // to know if the property exists. - JS('void', r'#.fixed$length = Array', list); - return JS('JSFixedArray', '#', list); - } - - checkMutable(reason) { - if (this is !JSMutableArray) { - throw new UnsupportedError(reason); - } - } - - checkGrowable(reason) { - if (JS('bool', r'#.fixed$length', this)) { - throw new UnsupportedError(reason); - } - } - - void add(E value) { - checkGrowable('add'); - JS('void', r'#.push(#)', this, value); - } - - E removeAt(int index) { - if (index is !int) throw new ArgumentError(index); - if (index < 0 || index >= length) { - throw new RangeError.value(index); - } - checkGrowable('removeAt'); - return JS('var', r'#.splice(#, 1)[0]', this, index); - } - - void insert(int index, E value) { - if (index is !int) throw new ArgumentError(index); - if (index < 0 || index > length) { - throw new RangeError.value(index); - } - checkGrowable('insert'); - JS('void', r'#.splice(#, 0, #)', this, index, value); - } - - void insertAll(int index, Iterable iterable) { - checkGrowable('insertAll'); - IterableMixinWorkaround.insertAllList(this, index, iterable); - } - - void setAll(int index, Iterable iterable) { - checkMutable('setAll'); - IterableMixinWorkaround.setAllList(this, index, iterable); - } - - E removeLast() { - checkGrowable('removeLast'); - if (length == 0) throw new RangeError.value(-1); - return JS('var', r'#.pop()', this); - } - - bool remove(Object element) { - checkGrowable('remove'); - for (int i = 0; i < this.length; i++) { - if (this[i] == element) { - JS('var', r'#.splice(#, 1)', this, i); - return true; - } - } - return false; - } - - void removeWhere(bool test(E element)) { - // This could, and should, be optimized. - IterableMixinWorkaround.removeWhereList(this, test); - } - - void retainWhere(bool test(E element)) { - IterableMixinWorkaround.removeWhereList(this, - (E element) => !test(element)); - } - - Iterable where(bool f(E element)) { - return new IterableMixinWorkaround().where(this, f); - } - - Iterable expand(Iterable f(E element)) { - return IterableMixinWorkaround.expand(this, f); - } - - void addAll(Iterable collection) { - for (E e in collection) { - this.add(e); - } - } - - void clear() { - length = 0; - } - - void forEach(void f(E element)) { - int length = this.length; - for (int i = 0; i < length; i++) { - f(JS('', '#[#]', this, i)); - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - } - - Iterable map(f(E element)) { - return IterableMixinWorkaround.mapList(this, f); - } - - String join([String separator = ""]) { - var list = new List(this.length); - for (int i = 0; i < this.length; i++) { - list[i] = "${this[i]}"; - } - return JS('String', "#.join(#)", list, separator); - } - - Iterable take(int n) { - return new IterableMixinWorkaround().takeList(this, n); - } - - Iterable takeWhile(bool test(E value)) { - return new IterableMixinWorkaround().takeWhile(this, test); - } - - Iterable skip(int n) { - return new IterableMixinWorkaround().skipList(this, n); - } - - Iterable skipWhile(bool test(E value)) { - return new IterableMixinWorkaround().skipWhile(this, test); - } - - E reduce(E combine(E value, E element)) { - return IterableMixinWorkaround.reduce(this, combine); - } - - fold(initialValue, combine(previousValue, E element)) { - return IterableMixinWorkaround.fold(this, initialValue, combine); - } - - E firstWhere(bool test(E value), {E orElse()}) { - return IterableMixinWorkaround.firstWhere(this, test, orElse); - } - - E lastWhere(bool test(E value), {E orElse()}) { - return IterableMixinWorkaround.lastWhereList(this, test, orElse); - } - - E singleWhere(bool test(E value)) { - return IterableMixinWorkaround.singleWhere(this, test); - } - - E elementAt(int index) { - return this[index]; - } - - List sublist(int start, [int end]) { - checkNull(start); // TODO(ahe): This is not specified but co19 tests it. - if (start is !int) throw new ArgumentError(start); - if (start < 0 || start > length) { - throw new RangeError.range(start, 0, length); - } - if (end == null) { - end = length; - } else { - if (end is !int) throw new ArgumentError(end); - if (end < start || end > length) { - throw new RangeError.range(end, start, length); - } - } - if (start == end) return []; - return new JSArray.markGrowable( - JS('', r'#.slice(#, #)', this, start, end)); - } - - - Iterable getRange(int start, int end) { - return new IterableMixinWorkaround().getRangeList(this, start, end); - } - - E get first { - if (length > 0) return this[0]; - throw new StateError("No elements"); - } - - E get last { - if (length > 0) return this[length - 1]; - throw new StateError("No elements"); - } - - E get single { - if (length == 1) return this[0]; - if (length == 0) throw new StateError("No elements"); - throw new StateError("More than one element"); - } - - void removeRange(int start, int end) { - checkGrowable('removeRange'); - int receiverLength = this.length; - if (start < 0 || start > receiverLength) { - throw new RangeError.range(start, 0, receiverLength); - } - if (end < start || end > receiverLength) { - throw new RangeError.range(end, start, receiverLength); - } - Lists.copy(this, - end, - this, - start, - receiverLength - end); - this.length = receiverLength - (end - start); - } - - void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { - checkMutable('set range'); - IterableMixinWorkaround.setRangeList(this, start, end, iterable, skipCount); - } - - void fillRange(int start, int end, [E fillValue]) { - checkMutable('fill range'); - IterableMixinWorkaround.fillRangeList(this, start, end, fillValue); - } - - void replaceRange(int start, int end, Iterable iterable) { - checkGrowable('removeRange'); - IterableMixinWorkaround.replaceRangeList(this, start, end, iterable); - } - - bool any(bool f(E element)) => IterableMixinWorkaround.any(this, f); - - bool every(bool f(E element)) => IterableMixinWorkaround.every(this, f); - - Iterable get reversed => - new IterableMixinWorkaround().reversedList(this); - - void sort([int compare(E a, E b)]) { - checkMutable('sort'); - IterableMixinWorkaround.sortList(this, compare); - } - - void shuffle([Random random]) { - IterableMixinWorkaround.shuffleList(this, random); - } - - int indexOf(Object element, [int start = 0]) { - return IterableMixinWorkaround.indexOfList(this, element, start); - } - - int lastIndexOf(Object element, [int start]) { - return IterableMixinWorkaround.lastIndexOfList(this, element, start); - } - - bool contains(Object other) { - for (int i = 0; i < length; i++) { - if (this[i] == other) return true; - } - return false; - } - - bool get isEmpty => length == 0; - - bool get isNotEmpty => !isEmpty; - - String toString() => ListBase.listToString(this); - - List toList({ bool growable: true }) { - if (growable) { - return new JSArray.markGrowable(JS('', '#.slice()', this)); - } else { - return new JSArray.markFixed(JS('', '#.slice()', this)); - } - } - - Set toSet() => new Set.from(this); - - Iterator get iterator => new ListIterator(this); - - int get hashCode => Primitives.objectHashCode(this); - - int get length => JS('JSUInt32', r'#.length', this); - - void set length(int newLength) { - if (newLength is !int) throw new ArgumentError(newLength); - if (newLength < 0) throw new RangeError.value(newLength); - checkGrowable('set length'); - JS('void', r'#.length = #', this, newLength); - } - - E operator [](int index) { - if (index is !int) throw new ArgumentError(index); - if (index >= length || index < 0) throw new RangeError.value(index); - return JS('var', '#[#]', this, index); - } - - void operator []=(int index, E value) { - checkMutable('indexed set'); - if (index is !int) throw new ArgumentError(index); - if (index >= length || index < 0) throw new RangeError.value(index); - JS('void', r'#[#] = #', this, index, value); - } - - Map asMap() { - return new IterableMixinWorkaround().asMapList(this); - } -} - -/** - * Dummy subclasses that allow the backend to track more precise - * information about arrays through their type. The CPA type inference - * relies on the fact that these classes do not override [] nor []=. - */ -class JSMutableArray extends JSArray implements JSMutableIndexable {} -class JSFixedArray extends JSMutableArray {} -class JSExtendableArray extends JSMutableArray {} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_helper.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_helper.dart deleted file mode 100644 index d60bbc08a4ad..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_helper.dart +++ /dev/null @@ -1,3468 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -library _js_helper; - -import 'dart:_js_embedded_names' show - ALL_CLASSES, - GET_ISOLATE_TAG, - INTERCEPTED_NAMES, - INTERCEPTORS_BY_TAG, - LEAF_TAGS, - METADATA, - DEFERRED_LIBRARY_URIS, - DEFERRED_LIBRARY_HASHES, - INITIALIZE_LOADED_HUNK, - IS_HUNK_LOADED, - IS_HUNK_INITIALIZED, - NATIVE_SUPERCLASS_TAG_NAME; - -import 'dart:collection'; -import 'dart:_isolate_helper' show - IsolateNatives, - leaveJsAsync, - enterJsAsync, - isWorker; - -import 'dart:async' show Future, DeferredLoadException, Completer; - -import 'dart:_foreign_helper' show - DART_CLOSURE_TO_JS, - JS, - JS_CALL_IN_ISOLATE, - JS_CONST, - JS_CURRENT_ISOLATE, - JS_CURRENT_ISOLATE_CONTEXT, - JS_DART_OBJECT_CONSTRUCTOR, - JS_EFFECT, - JS_EMBEDDED_GLOBAL, - JS_FUNCTION_CLASS_NAME, - JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG, - JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG, - JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG, - JS_FUNCTION_TYPE_RETURN_TYPE_TAG, - JS_FUNCTION_TYPE_TAG, - JS_FUNCTION_TYPE_VOID_RETURN_TAG, - JS_GET_NAME, - JS_GET_FLAG, - JS_HAS_EQUALS, - JS_IS_INDEXABLE_FIELD_NAME, - JS_NULL_CLASS_NAME, - JS_OBJECT_CLASS_NAME, - JS_OPERATOR_AS_PREFIX, - JS_OPERATOR_IS_PREFIX, - JS_SIGNATURE_NAME, - JS_STRING_CONCAT, - RAW_DART_FUNCTION_REF; - -import 'dart:_interceptors'; -import 'dart:_internal' as _symbol_dev; -import 'dart:_internal' show MappedIterable; - -import 'dart:_js_names' show - extractKeys, - mangledNames; - -part 'annotations.dart'; -part 'constant_map.dart'; -part 'native_helper.dart'; -part 'regexp_helper.dart'; -part 'string_helper.dart'; -part 'js_rti.dart'; - -// TODO(jacobr): remove. -String unmangleGlobalNameIfPreservedAnyways(String str) => str; -// TODO(jacobr): remove. -String unmangleAllIdentifiersIfPreservedAnyways(String str) => str; - -class _Patch { - const _Patch(); -} - -const _Patch patch = const _Patch(); - - -/// Marks the internal map in dart2js, so that internal libraries can is-check -// them. -abstract class InternalMap { -} - -/// No-op method that is called to inform the compiler that preambles might -/// be needed when executing the resulting JS file in a command-line -/// JS engine. -requiresPreamble() {} - -bool isJsIndexable(var object, var record) { - if (record != null) { - var result = dispatchRecordIndexability(record); - if (result != null) return result; - } - return object is JavaScriptIndexingBehavior; -} - -String S(value) { - if (value is String) return value; - if (value is num) { - if (value != 0) { - // ""+x is faster than String(x) for integers on most browsers. - return JS('String', r'"" + (#)', value); - } - } else if (true == value) { - return 'true'; - } else if (false == value) { - return 'false'; - } else if (value == null) { - return 'null'; - } - var res = value.toString(); - if (res is !String) throw new ArgumentError(value); - return res; -} - -createInvocationMirror(String name, internalName, kind, arguments, - argumentNames) { - return new JSInvocationMirror(name, - internalName, - kind, - arguments, - argumentNames); -} - -createUnmangledInvocationMirror(Symbol symbol, internalName, kind, arguments, - argumentNames) { - return new JSInvocationMirror(symbol, - internalName, - kind, - arguments, - argumentNames); -} - -void throwInvalidReflectionError(String memberName) { - throw new UnsupportedError("Can't use '$memberName' in reflection " - "because it is not included in a @MirrorsUsed annotation."); -} - -/// Helper to print the given method information to the console the first -/// time it is called with it. -@NoInline() -void traceHelper(String method) { - if (JS('bool', '!this.cache')) { - JS('', 'this.cache = Object.create(null)'); - } - if (JS('bool', '!this.cache[#]', method)) { - JS('', 'console.log(#)', method); - JS('', 'this.cache[#] = true', method); - } -} - -class JSInvocationMirror implements Invocation { - static const METHOD = 0; - static const GETTER = 1; - static const SETTER = 2; - - /// When [_memberName] is a String, it holds the mangled name of this - /// invocation. When it is a Symbol, it holds the unmangled name. - var /* String or Symbol */ _memberName; - final String _internalName; - final int _kind; - final List _arguments; - final List _namedArgumentNames; - /** Map from argument name to index in _arguments. */ - Map _namedIndices = null; - - JSInvocationMirror(this._memberName, - this._internalName, - this._kind, - this._arguments, - this._namedArgumentNames); - - Symbol get memberName { - if (_memberName is Symbol) return _memberName; - String name = _memberName; - String unmangledName = mangledNames[name]; - if (unmangledName != null) { - name = unmangledName.split(':')[0]; - } else { - if (mangledNames[_internalName] == null) { - print("Warning: '$name' is used reflectively but not in MirrorsUsed. " - "This will break minified code."); - } - } - _memberName = new _symbol_dev.Symbol.unvalidated(name); - return _memberName; - } - - bool get isMethod => _kind == METHOD; - bool get isGetter => _kind == GETTER; - bool get isSetter => _kind == SETTER; - bool get isAccessor => _kind != METHOD; - - List get positionalArguments { - if (isGetter) return const []; - var argumentCount = _arguments.length - _namedArgumentNames.length; - if (argumentCount == 0) return const []; - var list = []; - for (var index = 0 ; index < argumentCount ; index++) { - list.add(_arguments[index]); - } - return makeLiteralListConst(list); - } - - Map get namedArguments { - // TODO: Make maps const (issue 10471) - if (isAccessor) return {}; - int namedArgumentCount = _namedArgumentNames.length; - int namedArgumentsStartIndex = _arguments.length - namedArgumentCount; - if (namedArgumentCount == 0) return {}; - var map = new Map(); - for (int i = 0; i < namedArgumentCount; i++) { - map[new _symbol_dev.Symbol.unvalidated(_namedArgumentNames[i])] = - _arguments[namedArgumentsStartIndex + i]; - } - return map; - } - - _getCachedInvocation(Object object) { - var interceptor = getInterceptor(object); - var receiver = object; - var name = _internalName; - var arguments = _arguments; - var interceptedNames = JS_EMBEDDED_GLOBAL('', INTERCEPTED_NAMES); - bool isIntercepted = - JS("bool", 'Object.prototype.hasOwnProperty.call(#, #)', - interceptedNames, name); - if (isIntercepted) { - receiver = interceptor; - if (JS('bool', '# === #', object, interceptor)) { - interceptor = null; - } - } else { - interceptor = null; - } - bool isCatchAll = false; - var method = JS('var', '#[#]', receiver, name); - if (JS('bool', 'typeof # != "function"', method) ) { - String baseName = _symbol_dev.Symbol.getName(memberName); - method = JS('', '#[# + "*"]', receiver, baseName); - if (method == null) { - interceptor = getInterceptor(object); - method = JS('', '#[# + "*"]', interceptor, baseName); - if (method != null) { - isIntercepted = true; - receiver = interceptor; - } else { - interceptor = null; - } - } - isCatchAll = true; - } - if (JS('bool', 'typeof # == "function"', method)) { - if (isCatchAll) { - return new CachedCatchAllInvocation( - name, method, isIntercepted, interceptor); - } else { - return new CachedInvocation(name, method, isIntercepted, interceptor); - } - } else { - // In this case, receiver doesn't implement name. So we should - // invoke noSuchMethod instead (which will often throw a - // NoSuchMethodError). - return new CachedNoSuchMethodInvocation(interceptor); - } - } - - /// This method is called by [InstanceMirror.delegate]. - static invokeFromMirror(JSInvocationMirror invocation, Object victim) { - var cached = invocation._getCachedInvocation(victim); - if (cached.isNoSuchMethod) { - return cached.invokeOn(victim, invocation); - } else { - return cached.invokeOn(victim, invocation._arguments); - } - } - - static getCachedInvocation(JSInvocationMirror invocation, Object victim) { - return invocation._getCachedInvocation(victim); - } -} - -class CachedInvocation { - // The mangled name of this invocation. - String mangledName; - - /// The JS function to call. - var jsFunction; - - /// True if this is an intercepted call. - bool isIntercepted; - - /// Non-null interceptor if this is an intercepted call through an - /// [Interceptor]. - Interceptor cachedInterceptor; - - CachedInvocation(this.mangledName, - this.jsFunction, - this.isIntercepted, - this.cachedInterceptor); - - bool get isNoSuchMethod => false; - bool get isGetterStub => JS("bool", "!!#.\$getterStub", jsFunction); - - /// Applies [jsFunction] to [victim] with [arguments]. - /// Users of this class must take care to check the arguments first. - invokeOn(Object victim, List arguments) { - var receiver = victim; - if (!isIntercepted) { - if (arguments is! JSArray) arguments = new List.from(arguments); - } else { - arguments = [victim]..addAll(arguments); - if (cachedInterceptor != null) receiver = cachedInterceptor; - } - return JS("var", "#.apply(#, #)", jsFunction, receiver, arguments); - } -} - -class CachedCatchAllInvocation extends CachedInvocation { - final ReflectionInfo info; - - CachedCatchAllInvocation(String name, - jsFunction, - bool isIntercepted, - Interceptor cachedInterceptor) - : info = new ReflectionInfo(jsFunction), - super(name, jsFunction, isIntercepted, cachedInterceptor); - - bool get isGetterStub => false; - - invokeOn(Object victim, List arguments) { - var receiver = victim; - int providedArgumentCount; - int fullParameterCount = - info.requiredParameterCount + info.optionalParameterCount; - if (!isIntercepted) { - if (arguments is JSArray) { - providedArgumentCount = arguments.length; - // If we need to add extra arguments before calling, we have - // to copy the arguments array. - if (providedArgumentCount < fullParameterCount) { - arguments = new List.from(arguments); - } - } else { - arguments = new List.from(arguments); - providedArgumentCount = arguments.length; - } - } else { - arguments = [victim]..addAll(arguments); - if (cachedInterceptor != null) receiver = cachedInterceptor; - providedArgumentCount = arguments.length - 1; - } - if (info.areOptionalParametersNamed && - (providedArgumentCount > info.requiredParameterCount)) { - throw new UnimplementedNoSuchMethodError( - "Invocation of unstubbed method '${info.reflectionName}'" - " with ${arguments.length} arguments."); - } else if (providedArgumentCount < info.requiredParameterCount) { - throw new UnimplementedNoSuchMethodError( - "Invocation of unstubbed method '${info.reflectionName}'" - " with $providedArgumentCount arguments (too few)."); - } else if (providedArgumentCount > fullParameterCount) { - throw new UnimplementedNoSuchMethodError( - "Invocation of unstubbed method '${info.reflectionName}'" - " with $providedArgumentCount arguments (too many)."); - } - for (int i = providedArgumentCount; i < fullParameterCount; i++) { - arguments.add(getMetadata(info.defaultValue(i))); - } - return JS("var", "#.apply(#, #)", jsFunction, receiver, arguments); - } -} - -class CachedNoSuchMethodInvocation { - /// Non-null interceptor if this is an intercepted call through an - /// [Interceptor]. - var interceptor; - - CachedNoSuchMethodInvocation(this.interceptor); - - bool get isNoSuchMethod => true; - bool get isGetterStub => false; - - invokeOn(Object victim, Invocation invocation) { - var receiver = (interceptor == null) ? victim : interceptor; - return receiver.noSuchMethod(invocation); - } -} - -class ReflectionInfo { - static const int REQUIRED_PARAMETERS_INFO = 0; - static const int OPTIONAL_PARAMETERS_INFO = 1; - static const int FUNCTION_TYPE_INDEX = 2; - static const int FIRST_DEFAULT_ARGUMENT = 3; - - /// A JavaScript function object. - final jsFunction; - - /// Raw reflection information. - final List data; - - /// Is this a getter or a setter. - final bool isAccessor; - - /// Number of required parameters. - final int requiredParameterCount; - - /// Number of optional parameters. - final int optionalParameterCount; - - /// Are optional parameters named. - final bool areOptionalParametersNamed; - - /// Either an index to the function type in the embedded `metadata` global or - /// a JavaScript function object which can compute such a type (presumably - /// due to free type variables). - final functionType; - - List cachedSortedIndices; - - ReflectionInfo.internal(this.jsFunction, - this.data, - this.isAccessor, - this.requiredParameterCount, - this.optionalParameterCount, - this.areOptionalParametersNamed, - this.functionType); - - factory ReflectionInfo(jsFunction) { - List data = JS('JSExtendableArray|Null', r'#.$reflectionInfo', jsFunction); - if (data == null) return null; - data = JSArray.markFixedList(data); - - int requiredParametersInfo = - JS('int', '#[#]', data, REQUIRED_PARAMETERS_INFO); - int requiredParameterCount = JS('int', '# >> 1', requiredParametersInfo); - bool isAccessor = (requiredParametersInfo & 1) == 1; - - int optionalParametersInfo = - JS('int', '#[#]', data, OPTIONAL_PARAMETERS_INFO); - int optionalParameterCount = JS('int', '# >> 1', optionalParametersInfo); - bool areOptionalParametersNamed = (optionalParametersInfo & 1) == 1; - - var functionType = JS('', '#[#]', data, FUNCTION_TYPE_INDEX); - return new ReflectionInfo.internal( - jsFunction, data, isAccessor, requiredParameterCount, - optionalParameterCount, areOptionalParametersNamed, functionType); - } - - String parameterName(int parameter) { - int metadataIndex; - if (JS_GET_FLAG('MUST_RETAIN_METADATA')) { - metadataIndex = JS('int', '#[2 * # + # + #]', data, - parameter, optionalParameterCount, FIRST_DEFAULT_ARGUMENT); - } else { - metadataIndex = JS('int', '#[# + # + #]', data, - parameter, optionalParameterCount, FIRST_DEFAULT_ARGUMENT); - } - var metadata = JS_EMBEDDED_GLOBAL('', METADATA); - return JS('String', '#[#]', metadata, metadataIndex); - } - - List parameterMetadataAnnotations(int parameter) { - if (!JS_GET_FLAG('MUST_RETAIN_METADATA')) { - throw new StateError('metadata has not been preserved'); - } else { - return JS('', '#[2 * # + # + # + 1]', data, parameter, - optionalParameterCount, FIRST_DEFAULT_ARGUMENT); - } - } - - int defaultValue(int parameter) { - if (parameter < requiredParameterCount) return null; - return JS('int', '#[# + # - #]', data, - FIRST_DEFAULT_ARGUMENT, parameter, requiredParameterCount); - } - - /// Returns the default value of the [parameter]th entry of the list of - /// parameters sorted by name. - int defaultValueInOrder(int parameter) { - if (parameter < requiredParameterCount) return null; - - if (!areOptionalParametersNamed || optionalParameterCount == 1) { - return defaultValue(parameter); - } - - int index = sortedIndex(parameter - requiredParameterCount); - return defaultValue(index); - } - - /// Returns the default value of the [parameter]th entry of the list of - /// parameters sorted by name. - String parameterNameInOrder(int parameter) { - if (parameter < requiredParameterCount) return null; - - if (!areOptionalParametersNamed || - optionalParameterCount == 1) { - return parameterName(parameter); - } - - int index = sortedIndex(parameter - requiredParameterCount); - return parameterName(index); - } - - /// Computes the index of the parameter in the list of named parameters sorted - /// by their name. - int sortedIndex(int unsortedIndex) { - if (cachedSortedIndices == null) { - // TODO(karlklose): cache this between [ReflectionInfo] instances or cache - // [ReflectionInfo] instances by [jsFunction]. - cachedSortedIndices = new List(optionalParameterCount); - Map positions = {}; - for (int i = 0; i < optionalParameterCount; i++) { - int index = requiredParameterCount + i; - positions[parameterName(index)] = index; - } - int index = 0; - (positions.keys.toList()..sort()).forEach((String name) { - cachedSortedIndices[index++] = positions[name]; - }); - } - return cachedSortedIndices[unsortedIndex]; - } - - @NoInline() - computeFunctionRti(jsConstructor) { - if (JS('bool', 'typeof # == "number"', functionType)) { - return getMetadata(functionType); - } else if (JS('bool', 'typeof # == "function"', functionType)) { - var fakeInstance = JS('', 'new #()', jsConstructor); - setRuntimeTypeInfo( - fakeInstance, JS('JSExtendableArray', '#["<>"]', fakeInstance)); - return JS('=Object|Null', r'#.apply({$receiver:#})', - functionType, fakeInstance); - } else { - throw new RuntimeError('Unexpected function type'); - } - } - - String get reflectionName => JS('String', r'#.$reflectionName', jsFunction); -} - -getMetadata(int index) { - var metadata = JS_EMBEDDED_GLOBAL('', METADATA); - return JS('', '#[#]', metadata, index); -} - -class Primitives { - /// Isolate-unique ID for caching [JsClosureMirror.function]. - /// Note the initial value is used by the first isolate (or if there are no - /// isolates), new isolates will update this value to avoid conflicts by - /// calling [initializeStatics]. - static String mirrorFunctionCacheName = '\$cachedFunction'; - - /// Isolate-unique ID for caching [JsInstanceMirror._invoke]. - static String mirrorInvokeCacheName = '\$cachedInvocation'; - - /// Called when creating a new isolate (see _IsolateContext constructor in - /// isolate_helper.dart). - /// Please don't add complicated code to this method, as it will impact - /// start-up performance. - static void initializeStatics(int id) { - // Benchmarking shows significant performance improvements if this is a - // fixed value. - mirrorFunctionCacheName += '_$id'; - mirrorInvokeCacheName += '_$id'; - } - - static int objectHashCode(object) { - int hash = JS('int|Null', r'#.$identityHash', object); - if (hash == null) { - hash = JS('int', '(Math.random() * 0x3fffffff) | 0'); - JS('void', r'#.$identityHash = #', object, hash); - } - return JS('int', '#', hash); - } - - static _throwFormatException(String string) { - throw new FormatException(string); - } - - static int parseInt(String source, - int radix, - int handleError(String source)) { - // TODO(vsm): Make _throwFormatException generic and use directly - // to avoid closure allocation. - if (handleError == null) handleError = (s) => _throwFormatException(s); - - checkString(source); - var match = JS('JSExtendableArray|Null', - r'/^\s*[+-]?((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$/i.exec(#)', - source); - int digitsIndex = 1; - int hexIndex = 2; - int decimalIndex = 3; - int nonDecimalHexIndex = 4; - if (radix == null) { - radix = 10; - if (match != null) { - if (match[hexIndex] != null) { - // Cannot fail because we know that the digits are all hex. - return JS('num', r'parseInt(#, 16)', source); - } - if (match[decimalIndex] != null) { - // Cannot fail because we know that the digits are all decimal. - return JS('num', r'parseInt(#, 10)', source); - } - return handleError(source); - } - } else { - if (radix is! int) throw new ArgumentError("Radix is not an integer"); - if (radix < 2 || radix > 36) { - throw new RangeError("Radix $radix not in range 2..36"); - } - if (match != null) { - if (radix == 10 && match[decimalIndex] != null) { - // Cannot fail because we know that the digits are all decimal. - return JS('num', r'parseInt(#, 10)', source); - } - if (radix < 10 || match[decimalIndex] == null) { - // We know that the characters must be ASCII as otherwise the - // regexp wouldn't have matched. Lowercasing by doing `| 0x20` is thus - // guaranteed to be a safe operation, since it preserves digits - // and lower-cases ASCII letters. - int maxCharCode; - if (radix <= 10) { - // Allow all digits less than the radix. For example 0, 1, 2 for - // radix 3. - // "0".codeUnitAt(0) + radix - 1; - maxCharCode = 0x30 + radix - 1; - } else { - // Letters are located after the digits in ASCII. Therefore we - // only check for the character code. The regexp above made already - // sure that the string does not contain anything but digits or - // letters. - // "a".codeUnitAt(0) + (radix - 10) - 1; - maxCharCode = 0x61 + radix - 10 - 1; - } - String digitsPart = match[digitsIndex]; - for (int i = 0; i < digitsPart.length; i++) { - int characterCode = digitsPart.codeUnitAt(0) | 0x20; - if (digitsPart.codeUnitAt(i) > maxCharCode) { - return handleError(source); - } - } - } - } - } - if (match == null) return handleError(source); - return JS('num', r'parseInt(#, #)', source, radix); - } - - static double parseDouble(String source, double handleError(String source)) { - checkString(source); - // TODO(vsm): Make _throwFormatException generic and use directly - // to avoid closure allocation. - if (handleError == null) handleError = (s) => _throwFormatException(s); - // Notice that JS parseFloat accepts garbage at the end of the string. - // Accept only: - // - [+/-]NaN - // - [+/-]Infinity - // - a Dart double literal - // We do allow leading or trailing whitespace. - if (!JS('bool', - r'/^\s*[+-]?(?:Infinity|NaN|' - r'(?:\.\d+|\d+(?:\.\d*)?)(?:[eE][+-]?\d+)?)\s*$/.test(#)', - source)) { - return handleError(source); - } - var result = JS('num', r'parseFloat(#)', source); - if (result.isNaN) { - var trimmed = source.trim(); - if (trimmed == 'NaN' || trimmed == '+NaN' || trimmed == '-NaN') { - return result; - } - return handleError(source); - } - return result; - } - - /** [: r"$".codeUnitAt(0) :] */ - static const int DOLLAR_CHAR_VALUE = 36; - - // TODO(jmesserly): remove this method. - static var constructorNameFallback = JS('Function', r''' - function getTagFallback(o) { - var constructor = o.constructor; - if (typeof constructor == "function") { - var name = constructor.name; - // If the name is a non-empty string, we use that as the type name of this - // object. There are various cases where that does not work, so we have to - // detect them and fall through to the toString() based implementation. - - if (typeof name == "string" && - - // Sometimes the string is empty. This test also catches minified - // shadow dom polyfil wrapper for Window on Firefox where the faked - // constructor name does not 'stick'. The shortest real DOM object - // names have three characters (e.g. URL, CSS). - name.length > 2 && - - // On Firefox we often get "Object" as the constructor name, even for - // more specialized DOM objects. - name !== "Object" && - - // This can happen in Opera. - name !== "Function.prototype") { - return name; - } - } - var s = Object.prototype.toString.call(o); - return s.substring(8, s.length - 1); - }'''); - - /// Creates a string containing the complete type for the class [className] - /// with the given type arguments. - /// - /// In minified mode, uses the unminified names if available. - static String formatType(String className, List typeArguments) { - return unmangleAllIdentifiersIfPreservedAnyways - ('$className${joinArguments(typeArguments, 0)}'); - } - - /// Returns the type of [object] as a string (including type arguments). - /// - /// In minified mode, uses the unminified names if available. - static String objectTypeName(Object object) { - String name = JS('String', '#(#)', constructorNameFallback, object); - if (name == 'Object') { - // Try to decompile the constructor by turning it into a string and get - // the name out of that. If the decompiled name is a string containing an - // identifier, we use that instead of the very generic 'Object'. - var decompiled = - JS('var', r'#.match(/^\s*function\s*(\S*)\s*\(/)[1]', - JS('var', r'String(#.constructor)', object)); - if (decompiled is String) - if (JS('bool', r'/^\w+$/.test(#)', decompiled)) - name = decompiled; - } - // TODO(kasperl): If the namer gave us a fresh global name, we may - // want to remove the numeric suffix that makes it unique too. - // TODO(jacobr): commented this out as it seems bogus and it breaks as - // codeUnitAt is not yet supported. - /* - if (name.length > 1 && identical(name.codeUnitAt(0), DOLLAR_CHAR_VALUE)) { - name = name.substring(1); - } - */ - return formatType(name, getRuntimeTypeInfo(object)); - } - - /// In minified mode, uses the unminified names if available. - static String objectToString(Object object) { - // String name = objectTypeName(object); - String name = JS('String', 'dart.typeName(dart.realRuntimeType(#))', object); - return "Instance of '$name'"; - } - - static num dateNow() => JS('int', r'Date.now()'); - - static void initTicker() { - if (timerFrequency != null) return; - // Start with low-resolution. We overwrite the fields if we find better. - timerFrequency = 1000; - timerTicks = dateNow; - if (JS('bool', 'typeof window == "undefined"')) return; - var window = JS('var', 'window'); - if (window == null) return; - var performance = JS('var', '#.performance', window); - if (performance == null) return; - if (JS('bool', 'typeof #.now != "function"', performance)) return; - timerFrequency = 1000000; - timerTicks = () => (1000 * JS('num', '#.now()', performance)).floor(); - } - - static int timerFrequency; - static Function timerTicks; - - static bool get isD8 { - return JS('bool', - 'typeof version == "function"' - ' && typeof os == "object" && "system" in os'); - } - - static bool get isJsshell { - return JS('bool', - 'typeof version == "function" && typeof system == "function"'); - } - - static String currentUri() { - requiresPreamble(); - // In a browser return self.location.href. - if (JS('bool', '!!self.location')) { - return JS('String', 'self.location.href'); - } - - return null; - } - - // This is to avoid stack overflows due to very large argument arrays in - // apply(). It fixes http://dartbug.com/6919 - static String _fromCharCodeApply(List array) { - String result = ""; - const kMaxApply = 500; - int end = array.length; - for (var i = 0; i < end; i += kMaxApply) { - var subarray; - if (end <= kMaxApply) { - subarray = array; - } else { - subarray = JS('JSExtendableArray', r'#.slice(#, #)', array, - i, i + kMaxApply < end ? i + kMaxApply : end); - } - result = JS('String', '# + String.fromCharCode.apply(#, #)', - result, null, subarray); - } - return result; - } - - static String stringFromCodePoints(codePoints) { - List a = []; - for (var i in codePoints) { - if (i is !int) throw new ArgumentError(i); - if (i <= 0xffff) { - a.add(i); - } else if (i <= 0x10ffff) { - a.add(0xd800 + ((((i - 0x10000) >> 10) & 0x3ff))); - a.add(0xdc00 + (i & 0x3ff)); - } else { - throw new ArgumentError(i); - } - } - return _fromCharCodeApply(a); - } - - static String stringFromCharCodes(charCodes) { - for (var i in charCodes) { - if (i is !int) throw new ArgumentError(i); - if (i < 0) throw new ArgumentError(i); - if (i > 0xffff) return stringFromCodePoints(charCodes); - } - return _fromCharCodeApply(charCodes); - } - - static String stringFromCharCode(charCode) { - if (0 <= charCode) { - if (charCode <= 0xffff) { - return JS('String', 'String.fromCharCode(#)', charCode); - } - if (charCode <= 0x10ffff) { - var bits = charCode - 0x10000; - var low = 0xDC00 | (bits & 0x3ff); - var high = 0xD800 | (bits >> 10); - return JS('String', 'String.fromCharCode(#, #)', high, low); - } - } - throw new RangeError.range(charCode, 0, 0x10ffff); - } - - static String stringConcatUnchecked(String string1, String string2) { - return JS_STRING_CONCAT(string1, string2); - } - - static String flattenString(String str) { - return JS('String', "#.charCodeAt(0) == 0 ? # : #", str, str, str); - } - - static String getTimeZoneName(receiver) { - // Firefox and Chrome emit the timezone in parenthesis. - // Example: "Wed May 16 2012 21:13:00 GMT+0200 (CEST)". - // We extract this name using a regexp. - var d = lazyAsJsDate(receiver); - List match = JS('JSArray|Null', r'/\((.*)\)/.exec(#.toString())', d); - if (match != null) return match[1]; - - // Internet Explorer 10+ emits the zone name without parenthesis: - // Example: Thu Oct 31 14:07:44 PDT 2013 - match = JS('JSArray|Null', - // Thu followed by a space. - r'/^[A-Z,a-z]{3}\s' - // Oct 31 followed by space. - r'[A-Z,a-z]{3}\s\d+\s' - // Time followed by a space. - r'\d{2}:\d{2}:\d{2}\s' - // The time zone name followed by a space. - r'([A-Z]{3,5})\s' - // The year. - r'\d{4}$/' - '.exec(#.toString())', - d); - if (match != null) return match[1]; - - // IE 9 and Opera don't provide the zone name. We fall back to emitting the - // UTC/GMT offset. - // Example (IE9): Wed Nov 20 09:51:00 UTC+0100 2013 - // (Opera): Wed Nov 20 2013 11:03:38 GMT+0100 - match = JS('JSArray|Null', r'/(?:GMT|UTC)[+-]\d{4}/.exec(#.toString())', d); - if (match != null) return match[0]; - return ""; - } - - static int getTimeZoneOffsetInMinutes(receiver) { - // Note that JS and Dart disagree on the sign of the offset. - return -JS('int', r'#.getTimezoneOffset()', lazyAsJsDate(receiver)); - } - - static valueFromDecomposedDate(years, month, day, hours, minutes, seconds, - milliseconds, isUtc) { - final int MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000; - checkInt(years); - checkInt(month); - checkInt(day); - checkInt(hours); - checkInt(minutes); - checkInt(seconds); - checkInt(milliseconds); - checkBool(isUtc); - var jsMonth = month - 1; - var value; - if (isUtc) { - value = JS('num', r'Date.UTC(#, #, #, #, #, #, #)', - years, jsMonth, day, hours, minutes, seconds, milliseconds); - } else { - value = JS('num', r'new Date(#, #, #, #, #, #, #).valueOf()', - years, jsMonth, day, hours, minutes, seconds, milliseconds); - } - if (value.isNaN || - value < -MAX_MILLISECONDS_SINCE_EPOCH || - value > MAX_MILLISECONDS_SINCE_EPOCH) { - return null; - } - if (years <= 0 || years < 100) return patchUpY2K(value, years, isUtc); - return value; - } - - static patchUpY2K(value, years, isUtc) { - var date = JS('', r'new Date(#)', value); - if (isUtc) { - JS('num', r'#.setUTCFullYear(#)', date, years); - } else { - JS('num', r'#.setFullYear(#)', date, years); - } - return JS('num', r'#.valueOf()', date); - } - - // Lazily keep a JS Date stored in the JS object. - static lazyAsJsDate(receiver) { - if (JS('bool', r'#.date === (void 0)', receiver)) { - JS('void', r'#.date = new Date(#)', receiver, - receiver.millisecondsSinceEpoch); - } - return JS('var', r'#.date', receiver); - } - - // The getters for date and time parts below add a positive integer to ensure - // that the result is really an integer, because the JavaScript implementation - // may return -0.0 instead of 0. - - static getYear(receiver) { - return (receiver.isUtc) - ? JS('int', r'(#.getUTCFullYear() + 0)', lazyAsJsDate(receiver)) - : JS('int', r'(#.getFullYear() + 0)', lazyAsJsDate(receiver)); - } - - static getMonth(receiver) { - return (receiver.isUtc) - ? JS('int', r'#.getUTCMonth() + 1', lazyAsJsDate(receiver)) - : JS('int', r'#.getMonth() + 1', lazyAsJsDate(receiver)); - } - - static getDay(receiver) { - return (receiver.isUtc) - ? JS('int', r'(#.getUTCDate() + 0)', lazyAsJsDate(receiver)) - : JS('int', r'(#.getDate() + 0)', lazyAsJsDate(receiver)); - } - - static getHours(receiver) { - return (receiver.isUtc) - ? JS('int', r'(#.getUTCHours() + 0)', lazyAsJsDate(receiver)) - : JS('int', r'(#.getHours() + 0)', lazyAsJsDate(receiver)); - } - - static getMinutes(receiver) { - return (receiver.isUtc) - ? JS('int', r'(#.getUTCMinutes() + 0)', lazyAsJsDate(receiver)) - : JS('int', r'(#.getMinutes() + 0)', lazyAsJsDate(receiver)); - } - - static getSeconds(receiver) { - return (receiver.isUtc) - ? JS('int', r'(#.getUTCSeconds() + 0)', lazyAsJsDate(receiver)) - : JS('int', r'(#.getSeconds() + 0)', lazyAsJsDate(receiver)); - } - - static getMilliseconds(receiver) { - return (receiver.isUtc) - ? JS('int', r'(#.getUTCMilliseconds() + 0)', lazyAsJsDate(receiver)) - : JS('int', r'(#.getMilliseconds() + 0)', lazyAsJsDate(receiver)); - } - - static getWeekday(receiver) { - int weekday = (receiver.isUtc) - ? JS('int', r'#.getUTCDay() + 0', lazyAsJsDate(receiver)) - : JS('int', r'#.getDay() + 0', lazyAsJsDate(receiver)); - // Adjust by one because JS weeks start on Sunday. - return (weekday + 6) % 7 + 1; - } - - static valueFromDateString(str) { - if (str is !String) throw new ArgumentError(str); - var value = JS('num', r'Date.parse(#)', str); - if (value.isNaN) throw new ArgumentError(str); - return value; - } - - static getProperty(object, key) { - if (object == null || object is bool || object is num || object is String) { - throw new ArgumentError(object); - } - return JS('var', '#[#]', object, key); - } - - static void setProperty(object, key, value) { - if (object == null || object is bool || object is num || object is String) { - throw new ArgumentError(object); - } - JS('void', '#[#] = #', object, key, value); - } - - static functionNoSuchMethod(function, - List positionalArguments, - Map namedArguments) { - int argumentCount = 0; - List arguments = []; - List namedArgumentList = []; - - if (positionalArguments != null) { - argumentCount += positionalArguments.length; - arguments.addAll(positionalArguments); - } - - String names = ''; - if (namedArguments != null && !namedArguments.isEmpty) { - namedArguments.forEach((String name, argument) { - names = '$names\$$name'; - namedArgumentList.add(name); - arguments.add(argument); - argumentCount++; - }); - } - - String selectorName = - '${JS_GET_NAME("CALL_PREFIX")}\$$argumentCount$names'; - - return function.noSuchMethod( - createUnmangledInvocationMirror( - #call, - selectorName, - JSInvocationMirror.METHOD, - arguments, - namedArgumentList)); - } - - static applyFunction(Function function, - List positionalArguments, - Map namedArguments) { - // Dispatch on presence of named arguments to improve tree-shaking. - // - // This dispatch is as simple as possible to help the compiler detect the - // common case of `null` namedArguments, either via inlining or - // specialization. - return namedArguments == null - ? applyFunctionWithPositionalArguments( - function, positionalArguments) - : applyFunctionWithNamedArguments( - function, positionalArguments, namedArguments); - } - - static applyFunctionWithPositionalArguments(Function function, - List positionalArguments) { - int argumentCount = 0; - List arguments; - - if (positionalArguments != null) { - if (JS('bool', '# instanceof Array', positionalArguments)) { - arguments = positionalArguments; - } else { - arguments = new List.from(positionalArguments); - } - argumentCount = JS('int', '#.length', arguments); - } else { - arguments = []; - } - - String selectorName = '${JS_GET_NAME("CALL_PREFIX")}\$$argumentCount'; - var jsFunction = JS('var', '#[#]', function, selectorName); - if (jsFunction == null) { - - // TODO(ahe): This might occur for optional arguments if there is no call - // selector with that many arguments. - - return functionNoSuchMethod(function, positionalArguments, null); - } - // We bound 'this' to [function] because of how we compile - // closures: escaped local variables are stored and accessed through - // [function]. - return JS('var', '#.apply(#, #)', jsFunction, function, arguments); - } - - static applyFunctionWithNamedArguments(Function function, - List positionalArguments, - Map namedArguments) { - if (namedArguments.isEmpty) { - return applyFunctionWithPositionalArguments( - function, positionalArguments); - } - // TODO(ahe): The following code can be shared with - // JsInstanceMirror.invoke. - var interceptor = getInterceptor(function); - var jsFunction = JS('', '#["call*"]', interceptor); - - if (jsFunction == null) { - return functionNoSuchMethod( - function, positionalArguments, namedArguments); - } - ReflectionInfo info = new ReflectionInfo(jsFunction); - if (info == null || !info.areOptionalParametersNamed) { - return functionNoSuchMethod( - function, positionalArguments, namedArguments); - } - - if (positionalArguments != null) { - positionalArguments = new List.from(positionalArguments); - } else { - positionalArguments = []; - } - // Check the number of positional arguments is valid. - if (info.requiredParameterCount != positionalArguments.length) { - return functionNoSuchMethod( - function, positionalArguments, namedArguments); - } - var defaultArguments = new Map(); - for (int i = 0; i < info.optionalParameterCount; i++) { - int index = i + info.requiredParameterCount; - var parameterName = info.parameterNameInOrder(index); - var value = info.defaultValueInOrder(index); - var defaultValue = getMetadata(value); - defaultArguments[parameterName] = defaultValue; - } - bool bad = false; - namedArguments.forEach((String parameter, value) { - if (defaultArguments.containsKey(parameter)) { - defaultArguments[parameter] = value; - } else { - // Extraneous named argument. - bad = true; - } - }); - if (bad) { - return functionNoSuchMethod( - function, positionalArguments, namedArguments); - } - positionalArguments.addAll(defaultArguments.values); - return JS('', '#.apply(#, #)', jsFunction, function, positionalArguments); - } - - static _mangledNameMatchesType(String mangledName, TypeImpl type) { - return JS('bool', '# == #', mangledName, type._typeName); - } - - static bool identicalImplementation(a, b) { - return JS('bool', '# == null', a) - ? JS('bool', '# == null', b) - : JS('bool', '# === #', a, b); - } - - static StackTrace extractStackTrace(Error error) { - return getTraceFromException(JS('', r'#.$thrownJsError', error)); - } -} - -/// Helper class for allocating and using JS object literals as caches. -class JsCache { - /// Returns a JavaScript object suitable for use as a cache. - static allocate() { - var result = JS('=Object', 'Object.create(null)'); - // Deleting a property makes V8 assume that it shouldn't create a hidden - // class for [result] and map transitions. Although these map transitions - // pay off if there are many cache hits for the same keys, it becomes - // really slow when there aren't many repeated hits. - JS('void', '#.x=0', result); - JS('void', 'delete #.x', result); - return result; - } - - static fetch(cache, String key) { - return JS('', '#[#]', cache, key); - } - - static void update(cache, String key, value) { - JS('void', '#[#] = #', cache, key, value); - } -} - -/** - * Called by generated code to throw an illegal-argument exception, - * for example, if a non-integer index is given to an optimized - * indexed access. - */ -iae(argument) { - throw new ArgumentError(argument); -} - -/** - * Called by generated code to throw an index-out-of-range exception, - * for example, if a bounds check fails in an optimized indexed - * access. This may also be called when the index is not an integer, in - * which case it throws an illegal-argument exception instead, like - * [iae], or when the receiver is null. - */ -ioore(receiver, index) { - if (receiver == null) receiver.length; // Force a NoSuchMethodError. - if (index is !int) iae(index); - throw new RangeError.value(index); -} - -stringLastIndexOfUnchecked(receiver, element, start) - => JS('int', r'#.lastIndexOf(#, #)', receiver, element, start); - - -checkNull(object) { - if (object == null) throw new ArgumentError(null); - return object; -} - -checkNum(value) { - if (value is !num) { - throw new ArgumentError(value); - } - return value; -} - -checkInt(value) { - if (value is !int) { - throw new ArgumentError(value); - } - return value; -} - -checkBool(value) { - if (value is !bool) { - throw new ArgumentError(value); - } - return value; -} - -checkString(value) { - if (value is !String) { - throw new ArgumentError(value); - } - return value; -} - -/** - * Wrap the given Dart object and record a stack trace. - * - * The code in [unwrapException] deals with getting the original Dart - * object out of the wrapper again. - */ -@NoInline() -wrapException(ex) { - if (ex == null) ex = new NullThrownError(); - var wrapper = JS('', 'new Error()'); - // [unwrapException] looks for the property 'dartException'. - JS('void', '#.dartException = #', wrapper, ex); - - if (JS('bool', '"defineProperty" in Object')) { - // Define a JavaScript getter for 'message'. This is to work around V8 bug - // (https://code.google.com/p/v8/issues/detail?id=2519). The default - // toString on Error returns the value of 'message' if 'name' is - // empty. Setting toString directly doesn't work, see the bug. - JS('void', 'Object.defineProperty(#, "message", { get: # })', - wrapper, DART_CLOSURE_TO_JS(toStringWrapper)); - JS('void', '#.name = ""', wrapper); - } else { - // In the unlikely event the browser doesn't support Object.defineProperty, - // hope that it just calls toString. - JS('void', '#.toString = #', wrapper, DART_CLOSURE_TO_JS(toStringWrapper)); - } - - return wrapper; -} - -/// Do not call directly. -toStringWrapper() { - // This method gets installed as toString on a JavaScript object. Due to the - // weird scope rules of JavaScript, JS 'this' will refer to that object. - return JS('', r'this.dartException').toString(); -} - -/** - * This wraps the exception and does the throw. It is possible to call this in - * a JS expression context, where the throw statement is not allowed. Helpers - * are never inlined, so we don't risk inlining the throw statement into an - * expression context. - */ -throwExpression(ex) { - JS('void', 'throw #', wrapException(ex)); -} - -makeLiteralListConst(list) { - JS('bool', r'#.immutable$list = #', list, true); - JS('bool', r'#.fixed$length = #', list, true); - return list; -} - -throwRuntimeError(message) { - throw new RuntimeError(message); -} - -throwAbstractClassInstantiationError(className) { - throw new AbstractClassInstantiationError(className); -} - - -/** - * Helper class for building patterns recognizing native type errors. - */ -class TypeErrorDecoder { - // Field names are private to help tree-shaking. - - /// A regular expression which matches is matched against an error message. - final String _pattern; - - /// The group index of "arguments" in [_pattern], or -1 if _pattern has no - /// match for "arguments". - final int _arguments; - - /// The group index of "argumentsExpr" in [_pattern], or -1 if _pattern has - /// no match for "argumentsExpr". - final int _argumentsExpr; - - /// The group index of "expr" in [_pattern], or -1 if _pattern has no match - /// for "expr". - final int _expr; - - /// The group index of "method" in [_pattern], or -1 if _pattern has no match - /// for "method". - final int _method; - - /// The group index of "receiver" in [_pattern], or -1 if _pattern has no - /// match for "receiver". - final int _receiver; - - /// Pattern used to recognize a NoSuchMethodError error (and - /// possibly extract the method name). - static final TypeErrorDecoder noSuchMethodPattern = - extractPattern(provokeCallErrorOn(buildJavaScriptObject())); - - /// Pattern used to recognize an "object not a closure" error (and - /// possibly extract the method name). - static final TypeErrorDecoder notClosurePattern = - extractPattern(provokeCallErrorOn(buildJavaScriptObjectWithNonClosure())); - - /// Pattern used to recognize a NoSuchMethodError on JavaScript null - /// call. - static final TypeErrorDecoder nullCallPattern = - extractPattern(provokeCallErrorOn(JS('', 'null'))); - - /// Pattern used to recognize a NoSuchMethodError on JavaScript literal null - /// call. - static final TypeErrorDecoder nullLiteralCallPattern = - extractPattern(provokeCallErrorOnNull()); - - /// Pattern used to recognize a NoSuchMethodError on JavaScript - /// undefined call. - static final TypeErrorDecoder undefinedCallPattern = - extractPattern(provokeCallErrorOn(JS('', 'void 0'))); - - /// Pattern used to recognize a NoSuchMethodError on JavaScript literal - /// undefined call. - static final TypeErrorDecoder undefinedLiteralCallPattern = - extractPattern(provokeCallErrorOnUndefined()); - - /// Pattern used to recognize a NoSuchMethodError on JavaScript null - /// property access. - static final TypeErrorDecoder nullPropertyPattern = - extractPattern(provokePropertyErrorOn(JS('', 'null'))); - - /// Pattern used to recognize a NoSuchMethodError on JavaScript literal null - /// property access. - static final TypeErrorDecoder nullLiteralPropertyPattern = - extractPattern(provokePropertyErrorOnNull()); - - /// Pattern used to recognize a NoSuchMethodError on JavaScript - /// undefined property access. - static final TypeErrorDecoder undefinedPropertyPattern = - extractPattern(provokePropertyErrorOn(JS('', 'void 0'))); - - /// Pattern used to recognize a NoSuchMethodError on JavaScript literal - /// undefined property access. - static final TypeErrorDecoder undefinedLiteralPropertyPattern = - extractPattern(provokePropertyErrorOnUndefined()); - - TypeErrorDecoder(this._arguments, - this._argumentsExpr, - this._expr, - this._method, - this._receiver, - this._pattern); - - /// Returns a JavaScript object literal (map) with at most the - /// following keys: - /// - /// * arguments: The arguments as formatted by the JavaScript - /// engine. No browsers are known to provide this information. - /// - /// * argumentsExpr: The syntax of the arguments (JavaScript source - /// code). No browsers are known to provide this information. - /// - /// * expr: The syntax of the receiver expression (JavaScript source - /// code). Firefox provides this information, for example: "$expr$.$method$ - /// is not a function". - /// - /// * method: The name of the called method (mangled name). At least Firefox - /// and Chrome/V8 provides this information, for example, "Object [object - /// Object] has no method '$method$'". - /// - /// * receiver: The string representation of the receiver. Chrome/V8 - /// used to provide this information (by calling user-defined - /// JavaScript toString on receiver), but it has degenerated into - /// "[object Object]" in recent versions. - matchTypeError(message) { - var match = JS('JSExtendableArray|Null', - 'new RegExp(#).exec(#)', _pattern, message); - if (match == null) return null; - var result = JS('', 'Object.create(null)'); - if (_arguments != -1) { - JS('', '#.arguments = #[# + 1]', result, match, _arguments); - } - if (_argumentsExpr != -1) { - JS('', '#.argumentsExpr = #[# + 1]', result, match, _argumentsExpr); - } - if (_expr != -1) { - JS('', '#.expr = #[# + 1]', result, match, _expr); - } - if (_method != -1) { - JS('', '#.method = #[# + 1]', result, match, _method); - } - if (_receiver != -1) { - JS('', '#.receiver = #[# + 1]', result, match, _receiver); - } - - return result; - } - - /// Builds a JavaScript Object with a toString method saying - /// r"$receiver$". - static buildJavaScriptObject() { - return JS('', r'{ toString: function() { return "$receiver$"; } }'); - } - - /// Builds a JavaScript Object with a toString method saying - /// r"$receiver$". The property "$method" is defined, but is not a function. - static buildJavaScriptObjectWithNonClosure() { - return JS('', r'{ $method$: null, ' - r'toString: function() { return "$receiver$"; } }'); - } - - /// Extract a pattern from a JavaScript TypeError message. - /// - /// The patterns are extracted by forcing TypeErrors on known - /// objects thus forcing known strings into the error message. The - /// known strings are then replaced with wildcards which in theory - /// makes it possible to recognize the desired information even if - /// the error messages are reworded or translated. - static extractPattern(String message) { - // Some JavaScript implementations (V8 at least) include a - // representation of the receiver in the error message, however, - // this representation is not always [: receiver.toString() :], - // sometimes it is [: Object.prototype.toString(receiver) :], and - // sometimes it is an implementation specific method (but that - // doesn't seem to happen for object literals). So sometimes we - // get the text "[object Object]". The shortest way to get that - // string is using "String({})". - // See: http://code.google.com/p/v8/issues/detail?id=2519. - message = JS('String', r"#.replace(String({}), '$receiver$')", message); - - // Since we want to create a new regular expression from an unknown string, - // we must escape all regular expression syntax. - message = JS('String', r"#.replace(new RegExp(#, 'g'), '\\$&')", - message, ESCAPE_REGEXP); - - // Look for the special pattern \$camelCase\$ (all the $ symbols - // have been escaped already), as we will soon be inserting - // regular expression syntax that we want interpreted by RegExp. - List match = - JS('JSExtendableArray|Null', r"#.match(/\\\$[a-zA-Z]+\\\$/g)", message); - if (match == null) match = []; - - // Find the positions within the substring matches of the error message - // components. This will help us extract information later, such as the - // method name. - int arguments = JS('int', '#.indexOf(#)', match, r'\$arguments\$'); - int argumentsExpr = JS('int', '#.indexOf(#)', match, r'\$argumentsExpr\$'); - int expr = JS('int', '#.indexOf(#)', match, r'\$expr\$'); - int method = JS('int', '#.indexOf(#)', match, r'\$method\$'); - int receiver = JS('int', '#.indexOf(#)', match, r'\$receiver\$'); - - // Replace the patterns with a regular expression wildcard. - // Note: in a perfect world, one would use "(.*)", but not in - // JavaScript, "." does not match newlines. - String pattern = JS('String', - r"#.replace('\\$arguments\\$', '((?:x|[^x])*)')" - r".replace('\\$argumentsExpr\\$', '((?:x|[^x])*)')" - r".replace('\\$expr\\$', '((?:x|[^x])*)')" - r".replace('\\$method\\$', '((?:x|[^x])*)')" - r".replace('\\$receiver\\$', '((?:x|[^x])*)')", - message); - - return new TypeErrorDecoder(arguments, - argumentsExpr, - expr, - method, - receiver, - pattern); - } - - /// Provokes a TypeError and returns its message. - /// - /// The error is provoked so all known variable content can be recognized and - /// a pattern can be inferred. - static String provokeCallErrorOn(expression) { - // This function is carefully created to maximize the possibility - // of decoding the TypeError message and turning it into a general - // pattern. - // - // The idea is to inject something known into something unknown. The - // unknown entity is the error message that the browser provides with a - // TypeError. It is a human readable message, possibly localized in a - // language no dart2js engineer understand. We assume that $name$ would - // never naturally occur in a human readable error message, yet it is easy - // to decode. - // - // For example, evaluate this in V8 version 3.13.7.6: - // - // var $expr$ = null; $expr$.$method$() - // - // The VM throws an instance of TypeError whose message property contains - // "Cannot call method '$method$' of null". We can then reasonably assume - // that if the string contains $method$, that's where the method name will - // be in general. Call this automatically reverse engineering the error - // format string in V8. - // - // So the error message from V8 is turned into this regular expression: - // - // "Cannot call method '(.*)' of null" - // - // Similarly, if we evaluate: - // - // var $expr$ = {toString: function() { return '$receiver$'; }}; - // $expr$.$method$() - // - // We get this message: "Object $receiver$ has no method '$method$'" - // - // Which is turned into this regular expression: - // - // "Object (.*) has no method '(.*)'" - // - // Firefox/jsshell is slightly different, it tries to include the source - // code that caused the exception, so we get this message: "$expr$.$method$ - // is not a function" which is turned into this regular expression: - // - // "(.*)\\.(.*) is not a function" - - var function = JS('', r"""function($expr$) { - var $argumentsExpr$ = '$arguments$'; - try { - $expr$.$method$($argumentsExpr$); - } catch (e) { - return e.message; - } -}"""); - return JS('String', '(#)(#)', function, expression); - } - - /// Similar to [provokeCallErrorOn], but provokes an error directly on - /// literal "null" expression. - static String provokeCallErrorOnNull() { - // See [provokeCallErrorOn] for a detailed explanation. - var function = JS('', r"""function() { - var $argumentsExpr$ = '$arguments$'; - try { - null.$method$($argumentsExpr$); - } catch (e) { - return e.message; - } -}"""); - return JS('String', '(#)()', function); - } - - /// Similar to [provokeCallErrorOnNull], but provokes an error directly on - /// (void 0), that is, "undefined". - static String provokeCallErrorOnUndefined() { - // See [provokeCallErrorOn] for a detailed explanation. - var function = JS('', r"""function() { - var $argumentsExpr$ = '$arguments$'; - try { - (void 0).$method$($argumentsExpr$); - } catch (e) { - return e.message; - } -}"""); - return JS('String', '(#)()', function); - } - - /// Similar to [provokeCallErrorOn], but provokes a property access - /// error. - static String provokePropertyErrorOn(expression) { - // See [provokeCallErrorOn] for a detailed explanation. - var function = JS('', r"""function($expr$) { - try { - $expr$.$method$; - } catch (e) { - return e.message; - } -}"""); - return JS('String', '(#)(#)', function, expression); - } - - /// Similar to [provokePropertyErrorOn], but provokes an property access - /// error directly on literal "null" expression. - static String provokePropertyErrorOnNull() { - // See [provokeCallErrorOn] for a detailed explanation. - var function = JS('', r"""function() { - try { - null.$method$; - } catch (e) { - return e.message; - } -}"""); - return JS('String', '(#)()', function); - } - - /// Similar to [provokePropertyErrorOnNull], but provokes an property access - /// error directly on (void 0), that is, "undefined". - static String provokePropertyErrorOnUndefined() { - // See [provokeCallErrorOn] for a detailed explanation. - var function = JS('', r"""function() { - try { - (void 0).$method$; - } catch (e) { - return e.message; - } -}"""); - return JS('String', '(#)()', function); - } -} - -class NullError extends Error implements NoSuchMethodError { - final String _message; - final String _method; - - NullError(this._message, match) - : _method = match == null ? null : JS('', '#.method', match); - - String toString() { - if (_method == null) return 'NullError: $_message'; - return 'NullError: Cannot call "$_method" on null'; - } -} - -class JsNoSuchMethodError extends Error implements NoSuchMethodError { - final String _message; - final String _method; - final String _receiver; - - JsNoSuchMethodError(this._message, match) - : _method = match == null ? null : JS('String|Null', '#.method', match), - _receiver = - match == null ? null : JS('String|Null', '#.receiver', match); - - String toString() { - if (_method == null) return 'NoSuchMethodError: $_message'; - if (_receiver == null) { - return 'NoSuchMethodError: Cannot call "$_method" ($_message)'; - } - return 'NoSuchMethodError: Cannot call "$_method" on "$_receiver" ' - '($_message)'; - } -} - -class UnknownJsTypeError extends Error { - final String _message; - - UnknownJsTypeError(this._message); - - String toString() => _message.isEmpty ? 'Error' : 'Error: $_message'; -} - -/** - * Called from catch blocks in generated code to extract the Dart - * exception from the thrown value. The thrown value may have been - * created by [wrapException] or it may be a 'native' JS exception. - * - * Some native exceptions are mapped to new Dart instances, others are - * returned unmodified. - */ -unwrapException(ex) { - /// If error implements Error, save [ex] in [error.$thrownJsError]. - /// Otherwise, do nothing. Later, the stack trace can then be extraced from - /// [ex]. - saveStackTrace(error) { - if (error is Error) { - var thrownStackTrace = JS('', r'#.$thrownJsError', error); - if (thrownStackTrace == null) { - JS('void', r'#.$thrownJsError = #', error, ex); - } - } - return error; - } - - // Note that we are checking if the object has the property. If it - // has, it could be set to null if the thrown value is null. - if (ex == null) return null; - if (JS('bool', 'typeof # !== "object"', ex)) return ex; - - if (JS('bool', r'"dartException" in #', ex)) { - return saveStackTrace(JS('', r'#.dartException', ex)); - } else if (!JS('bool', r'"message" in #', ex)) { - return ex; - } - - // Grab hold of the exception message. This field is available on - // all supported browsers. - var message = JS('var', r'#.message', ex); - - // Internet Explorer has an error number. This is the most reliable way to - // detect specific errors, so check for this first. - if (JS('bool', '"number" in #', ex) - && JS('bool', 'typeof #.number == "number"', ex)) { - int number = JS('int', '#.number', ex); - - // From http://msdn.microsoft.com/en-us/library/ie/hc53e755(v=vs.94).aspx - // "number" is a 32-bit word. The error code is the low 16 bits, and the - // facility code is the upper 16 bits. - var ieErrorCode = number & 0xffff; - var ieFacilityNumber = (number >> 16) & 0x1fff; - - // http://msdn.microsoft.com/en-us/library/aa264975(v=vs.60).aspx - // http://msdn.microsoft.com/en-us/library/ie/1dk3k160(v=vs.94).aspx - if (ieFacilityNumber == 10) { - switch (ieErrorCode) { - case 438: - return saveStackTrace( - new JsNoSuchMethodError('$message (Error $ieErrorCode)', null)); - case 445: - case 5007: - return saveStackTrace( - new NullError('$message (Error $ieErrorCode)', null)); - } - } - } - - if (JS('bool', r'# instanceof TypeError', ex)) { - var match; - // Using JS to give type hints to the compiler to help tree-shaking. - // TODO(ahe): That should be unnecessary due to type inference. - var nsme = - JS('TypeErrorDecoder', '#', TypeErrorDecoder.noSuchMethodPattern); - var notClosure = - JS('TypeErrorDecoder', '#', TypeErrorDecoder.notClosurePattern); - var nullCall = - JS('TypeErrorDecoder', '#', TypeErrorDecoder.nullCallPattern); - var nullLiteralCall = - JS('TypeErrorDecoder', '#', TypeErrorDecoder.nullLiteralCallPattern); - var undefCall = - JS('TypeErrorDecoder', '#', TypeErrorDecoder.undefinedCallPattern); - var undefLiteralCall = - JS('TypeErrorDecoder', '#', - TypeErrorDecoder.undefinedLiteralCallPattern); - var nullProperty = - JS('TypeErrorDecoder', '#', TypeErrorDecoder.nullPropertyPattern); - var nullLiteralProperty = - JS('TypeErrorDecoder', '#', - TypeErrorDecoder.nullLiteralPropertyPattern); - var undefProperty = - JS('TypeErrorDecoder', '#', TypeErrorDecoder.undefinedPropertyPattern); - var undefLiteralProperty = - JS('TypeErrorDecoder', '#', - TypeErrorDecoder.undefinedLiteralPropertyPattern); - if ((match = nsme.matchTypeError(message)) != null) { - return saveStackTrace(new JsNoSuchMethodError(message, match)); - } else if ((match = notClosure.matchTypeError(message)) != null) { - // notClosure may match "({c:null}).c()" or "({c:1}).c()", so we - // cannot tell if this an attempt to invoke call on null or a - // non-function object. - // But we do know the method name is "call". - JS('', '#.method = "call"', match); - return saveStackTrace(new JsNoSuchMethodError(message, match)); - } else if ((match = nullCall.matchTypeError(message)) != null || - (match = nullLiteralCall.matchTypeError(message)) != null || - (match = undefCall.matchTypeError(message)) != null || - (match = undefLiteralCall.matchTypeError(message)) != null || - (match = nullProperty.matchTypeError(message)) != null || - (match = nullLiteralCall.matchTypeError(message)) != null || - (match = undefProperty.matchTypeError(message)) != null || - (match = undefLiteralProperty.matchTypeError(message)) != null) { - return saveStackTrace(new NullError(message, match)); - } - - // If we cannot determine what kind of error this is, we fall back - // to reporting this as a generic error. It's probably better than - // nothing. - return saveStackTrace( - new UnknownJsTypeError(message is String ? message : '')); - } - - if (JS('bool', r'# instanceof RangeError', ex)) { - if (message is String && contains(message, 'call stack')) { - return new StackOverflowError(); - } - - // In general, a RangeError is thrown when trying to pass a number - // as an argument to a function that does not allow a range that - // includes that number. - return saveStackTrace(new ArgumentError()); - } - - // Check for the Firefox specific stack overflow signal. - if (JS('bool', - r'typeof InternalError == "function" && # instanceof InternalError', - ex)) { - if (message is String && message == 'too much recursion') { - return new StackOverflowError(); - } - } - - // Just return the exception. We should not wrap it because in case - // the exception comes from the DOM, it is a JavaScript - // object backed by a native Dart class. - return ex; -} - -/** - * Called by generated code to fetch the stack trace from an - * exception. Should never return null. - */ -StackTrace getTraceFromException(exception) => new _StackTrace(exception); - -class _StackTrace implements StackTrace { - var _exception; - String _trace; - _StackTrace(this._exception); - - String toString() { - if (_trace != null) return _trace; - - String trace; - if (JS('bool', 'typeof # === "object"', _exception)) { - trace = JS("String|Null", r"#.stack", _exception); - } - return _trace = (trace == null) ? '' : trace; - } -} - -int objectHashCode(var object) { - if (object == null || JS('bool', "typeof # != 'object'", object)) { - return object.hashCode; - } else { - return Primitives.objectHashCode(object); - } -} - -/** - * Called by generated code to build a map literal. [keyValuePairs] is - * a list of key, value, key, value, ..., etc. - */ -fillLiteralMap(keyValuePairs, Map result) { - // TODO(johnniwinther): Use JSArray to optimize this code instead of calling - // [getLength] and [getIndex]. - int index = 0; - int length = getLength(keyValuePairs); - while (index < length) { - var key = getIndex(keyValuePairs, index++); - var value = getIndex(keyValuePairs, index++); - result[key] = value; - } - return result; -} - -invokeClosure(Function closure, - var isolate, - int numberOfArguments, - var arg1, - var arg2, - var arg3, - var arg4) { - if (numberOfArguments == 0) { - return JS_CALL_IN_ISOLATE(isolate, () => closure()); - } else if (numberOfArguments == 1) { - return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1)); - } else if (numberOfArguments == 2) { - return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2)); - } else if (numberOfArguments == 3) { - return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2, arg3)); - } else if (numberOfArguments == 4) { - return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2, arg3, arg4)); - } else { - throw new Exception( - 'Unsupported number of arguments for wrapped closure'); - } -} - -/** - * Called by generated code to convert a Dart closure to a JS - * closure when the Dart closure is passed to the DOM. - */ -convertDartClosureToJS(closure, int arity) { - // TODO(vsm): Dart2JS wraps closures to: - // (a) adjust the calling convention, and - // (b) record the source isolate - // Do we need either? - // See: https://github.com/dart-lang/dev_compiler/issues/164 - return closure; -} - -/** - * Super class for Dart closures. - */ -abstract class Closure implements Function { - // TODO(ahe): These constants must be in sync with - // reflection_data_parser.dart. - static const FUNCTION_INDEX = 0; - static const NAME_INDEX = 1; - static const CALL_NAME_INDEX = 2; - static const REQUIRED_PARAMETER_INDEX = 3; - static const OPTIONAL_PARAMETER_INDEX = 4; - static const DEFAULT_ARGUMENTS_INDEX = 5; - - /** - * Global counter to prevent reusing function code objects. - * - * V8 will share the underlying function code objects when the same string is - * passed to "new Function". Shared function code objects can lead to - * sub-optimal performance due to polymorhism, and can be prevented by - * ensuring the strings are different. - */ - static int functionCounter = 0; - - Closure(); - - /** - * Creates a new closure class for use by implicit getters associated with a - * method. - * - * In other words, creates a tear-off closure. - * - * Called from [closureFromTearOff] as well as from reflection when tearing - * of a method via [:getField:]. - * - * This method assumes that [functions] was created by the JavaScript function - * `addStubs` in `reflection_data_parser.dart`. That is, a list of JavaScript - * function objects with properties `$stubName` and `$callName`. - * - * Further assumes that [reflectionInfo] is the end of the array created by - * [dart2js.js_emitter.ContainerBuilder.addMemberMethod] starting with - * required parameter count. - * - * Caution: this function may be called when building constants. - * TODO(ahe): Don't call this function when building constants. - */ - static fromTearOff(receiver, - List functions, - List reflectionInfo, - bool isStatic, - jsArguments, - String propertyName) { - JS_EFFECT(() { - BoundClosure.receiverOf(JS('BoundClosure', 'void 0')); - BoundClosure.selfOf(JS('BoundClosure', 'void 0')); - }); - // TODO(ahe): All the place below using \$ should be rewritten to go - // through the namer. - var function = JS('', '#[#]', functions, 0); - String name = JS('String|Null', '#.\$stubName', function); - String callName = JS('String|Null', '#.\$callName', function); - - JS('', '#.\$reflectionInfo = #', function, reflectionInfo); - ReflectionInfo info = new ReflectionInfo(function); - - var functionType = info.functionType; - - // function tmp() {}; - // tmp.prototype = BC.prototype; - // var proto = new tmp; - // for each computed prototype property: - // proto[property] = ...; - // proto._init = BC; - // var dynClosureConstructor = - // new Function('self', 'target', 'receiver', 'name', - // 'this._init(self, target, receiver, name)'); - // proto.constructor = dynClosureConstructor; - // dynClosureConstructor.prototype = proto; - // return dynClosureConstructor; - - // We need to create a new subclass of either TearOffClosure or - // BoundClosure. For this, we need to create an object whose prototype is - // the prototype is either TearOffClosure.prototype or - // BoundClosure.prototype, respectively in pseudo JavaScript code. The - // simplest way to access the JavaScript construction function of a Dart - // class is to create an instance and access its constructor property. The - // newly created instance could in theory be used directly as the - // prototype, but it might include additional fields that we don't need. - // So we only use the new instance to access the constructor property and - // use Object.create to create the desired prototype. - var prototype = isStatic - ? JS('TearOffClosure', 'Object.create(#.constructor.prototype)', - new TearOffClosure()) - : JS('BoundClosure', 'Object.create(#.constructor.prototype)', - new BoundClosure(null, null, null, null)); - - JS('', '#.\$initialize = #', prototype, JS('', '#.constructor', prototype)); - var constructor = isStatic - ? JS('', 'function(){this.\$initialize()}') - : isCsp - ? JS('', 'function(a,b,c,d) {this.\$initialize(a,b,c,d)}') - : JS('', - 'new Function("a","b","c","d",' - '"this.\$initialize(a,b,c,d);"+#)', - functionCounter++); - - // It is necessary to set the constructor property, otherwise it will be - // "Object". - JS('', '#.constructor = #', prototype, constructor); - - JS('', '#.prototype = #', constructor, prototype); - - // Create a closure and "monkey" patch it with call stubs. - var trampoline = function; - var isIntercepted = false; - if (!isStatic) { - if (JS('bool', '#.length == 1', jsArguments)) { - // Intercepted call. - isIntercepted = true; - } - trampoline = forwardCallTo(receiver, function, isIntercepted); - JS('', '#.\$reflectionInfo = #', trampoline, reflectionInfo); - } else { - JS('', '#.\$name = #', prototype, propertyName); - } - - var signatureFunction; - if (JS('bool', 'typeof # == "number"', functionType)) { - var metadata = JS_EMBEDDED_GLOBAL('', METADATA); - // It is ok, if the access is inlined into the JS. The access is safe in - // and outside the function. In fact we prefer if there is a textual - // inlining. - signatureFunction = - JS('', '(function(s){return function(){return #[s]}})(#)', - metadata, - functionType); - } else if (!isStatic - && JS('bool', 'typeof # == "function"', functionType)) { - var getReceiver = isIntercepted - ? RAW_DART_FUNCTION_REF(BoundClosure.receiverOf) - : RAW_DART_FUNCTION_REF(BoundClosure.selfOf); - signatureFunction = JS( - '', - 'function(f,r){' - 'return function(){' - 'return f.apply({\$receiver:r(this)},arguments)' - '}' - '}(#,#)', functionType, getReceiver); - } else { - throw 'Error in reflectionInfo.'; - } - - JS('', '#[#] = #', prototype, JS_SIGNATURE_NAME(), signatureFunction); - - JS('', '#[#] = #', prototype, callName, trampoline); - for (int i = 1; i < functions.length; i++) { - var stub = functions[i]; - var stubCallName = JS('String|Null', '#.\$callName', stub); - if (stubCallName != null) { - JS('', '#[#] = #', prototype, stubCallName, - isStatic ? stub : forwardCallTo(receiver, stub, isIntercepted)); - } - } - - JS('', '#["call*"] = #', prototype, trampoline); - - return constructor; - } - - static cspForwardCall(int arity, bool isSuperCall, String stubName, - function) { - var getSelf = RAW_DART_FUNCTION_REF(BoundClosure.selfOf); - // Handle intercepted stub-names with the default slow case. - if (isSuperCall) arity = -1; - switch (arity) { - case 0: - return JS( - '', - 'function(n,S){' - 'return function(){' - 'return S(this)[n]()' - '}' - '}(#,#)', stubName, getSelf); - case 1: - return JS( - '', - 'function(n,S){' - 'return function(a){' - 'return S(this)[n](a)' - '}' - '}(#,#)', stubName, getSelf); - case 2: - return JS( - '', - 'function(n,S){' - 'return function(a,b){' - 'return S(this)[n](a,b)' - '}' - '}(#,#)', stubName, getSelf); - case 3: - return JS( - '', - 'function(n,S){' - 'return function(a,b,c){' - 'return S(this)[n](a,b,c)' - '}' - '}(#,#)', stubName, getSelf); - case 4: - return JS( - '', - 'function(n,S){' - 'return function(a,b,c,d){' - 'return S(this)[n](a,b,c,d)' - '}' - '}(#,#)', stubName, getSelf); - case 5: - return JS( - '', - 'function(n,S){' - 'return function(a,b,c,d,e){' - 'return S(this)[n](a,b,c,d,e)' - '}' - '}(#,#)', stubName, getSelf); - default: - return JS( - '', - 'function(f,s){' - 'return function(){' - 'return f.apply(s(this),arguments)' - '}' - '}(#,#)', function, getSelf); - } - } - - static bool get isCsp => JS('bool', 'typeof dart_precompiled == "function"'); - - static forwardCallTo(receiver, function, bool isIntercepted) { - if (isIntercepted) return forwardInterceptedCallTo(receiver, function); - String stubName = JS('String|Null', '#.\$stubName', function); - int arity = JS('int', '#.length', function); - var lookedUpFunction = JS("", "#[#]", receiver, stubName); - // The receiver[stubName] may not be equal to the function if we try to - // forward to a super-method. Especially when we create a bound closure - // of a super-call we need to make sure that we don't forward back to the - // dynamically looked up function. - bool isSuperCall = !identical(function, lookedUpFunction); - - if (isCsp || isSuperCall || arity >= 27) { - return cspForwardCall(arity, isSuperCall, stubName, function); - } - - if (arity == 0) { - return JS( - '', - '(new Function(#))()', - 'return function(){' - 'return this.${BoundClosure.selfFieldName()}.$stubName();' - '${functionCounter++}' - '}'); - } - assert (1 <= arity && arity < 27); - String arguments = JS( - 'String', - '"abcdefghijklmnopqrstuvwxyz".split("").splice(0,#).join(",")', - arity); - return JS( - '', - '(new Function(#))()', - 'return function($arguments){' - 'return this.${BoundClosure.selfFieldName()}.$stubName($arguments);' - '${functionCounter++}' - '}'); - } - - static cspForwardInterceptedCall(int arity, bool isSuperCall, - String name, function) { - var getSelf = RAW_DART_FUNCTION_REF(BoundClosure.selfOf); - var getReceiver = RAW_DART_FUNCTION_REF(BoundClosure.receiverOf); - // Handle intercepted stub-names with the default slow case. - if (isSuperCall) arity = -1; - switch (arity) { - case 0: - // Intercepted functions always takes at least one argument (the - // receiver). - throw new RuntimeError('Intercepted function with no arguments.'); - case 1: - return JS( - '', - 'function(n,s,r){' - 'return function(){' - 'return s(this)[n](r(this))' - '}' - '}(#,#,#)', name, getSelf, getReceiver); - case 2: - return JS( - '', - 'function(n,s,r){' - 'return function(a){' - 'return s(this)[n](r(this),a)' - '}' - '}(#,#,#)', name, getSelf, getReceiver); - case 3: - return JS( - '', - 'function(n,s,r){' - 'return function(a,b){' - 'return s(this)[n](r(this),a,b)' - '}' - '}(#,#,#)', name, getSelf, getReceiver); - case 4: - return JS( - '', - 'function(n,s,r){' - 'return function(a,b,c){' - 'return s(this)[n](r(this),a,b,c)' - '}' - '}(#,#,#)', name, getSelf, getReceiver); - case 5: - return JS( - '', - 'function(n,s,r){' - 'return function(a,b,c,d){' - 'return s(this)[n](r(this),a,b,c,d)' - '}' - '}(#,#,#)', name, getSelf, getReceiver); - case 6: - return JS( - '', - 'function(n,s,r){' - 'return function(a,b,c,d,e){' - 'return s(this)[n](r(this),a,b,c,d,e)' - '}' - '}(#,#,#)', name, getSelf, getReceiver); - default: - return JS( - '', - 'function(f,s,r,a){' - 'return function(){' - 'a=[r(this)];' - 'Array.prototype.push.apply(a,arguments);' - 'return f.apply(s(this),a)' - '}' - '}(#,#,#)', function, getSelf, getReceiver); - } - } - - static forwardInterceptedCallTo(receiver, function) { - String selfField = BoundClosure.selfFieldName(); - String receiverField = BoundClosure.receiverFieldName(); - String stubName = JS('String|Null', '#.\$stubName', function); - int arity = JS('int', '#.length', function); - bool isCsp = JS('bool', 'typeof dart_precompiled == "function"'); - var lookedUpFunction = JS("", "#[#]", receiver, stubName); - // The receiver[stubName] may not be equal to the function if we try to - // forward to a super-method. Especially when we create a bound closure - // of a super-call we need to make sure that we don't forward back to the - // dynamically looked up function. - bool isSuperCall = !identical(function, lookedUpFunction); - - if (isCsp || isSuperCall || arity >= 28) { - return cspForwardInterceptedCall(arity, isSuperCall, stubName, - function); - } - if (arity == 1) { - return JS( - '', - '(new Function(#))()', - 'return function(){' - 'return this.$selfField.$stubName(this.$receiverField);' - '${functionCounter++}' - '}'); - } - assert(1 < arity && arity < 28); - String arguments = JS( - 'String', - '"abcdefghijklmnopqrstuvwxyz".split("").splice(0,#).join(",")', - arity - 1); - return JS( - '', - '(new Function(#))()', - 'return function($arguments){' - 'return this.$selfField.$stubName(this.$receiverField, $arguments);' - '${functionCounter++}' - '}'); - } - - // The backend adds a special getter of the form - // - // Closure get call => this; - // - // to allow tearing off a closure from itself. We do this magically in the - // backend rather than simply adding it here, as we do not want this getter - // to be visible to resolution and the generation of extra stubs. - - String toString() => "Closure"; -} - -/// Called from implicit method getter (aka tear-off). -closureFromTearOff(receiver, - functions, - reflectionInfo, - isStatic, - jsArguments, - name) { - return Closure.fromTearOff( - receiver, - JSArray.markFixedList(functions), - JSArray.markFixedList(reflectionInfo), - JS('bool', '!!#', isStatic), - jsArguments, - JS('String', '#', name)); -} - -/// Represents an implicit closure of a function. -class TearOffClosure extends Closure { -} - -/// Represents a 'tear-off' closure, that is an instance method bound -/// to a specific receiver (instance). -class BoundClosure extends TearOffClosure { - /// The receiver or interceptor. - // TODO(ahe): This could just be the interceptor, we always know if - // we need the interceptor when generating the call method. - final _self; - - /// The method. - final _target; - - /// The receiver. Null if [_self] is not an interceptor. - final _receiver; - - /// The name of the function. Only used by the mirror system. - final String _name; - - BoundClosure(this._self, this._target, this._receiver, this._name); - - bool operator==(other) { - if (identical(this, other)) return true; - if (other is! BoundClosure) return false; - return JS('bool', '# === # && # === # && # === #', - _self, other._self, - _target, other._target, - _receiver, other._receiver); - } - - int get hashCode { - int receiverHashCode; - if (_receiver == null) { - // A bound closure on a regular Dart object, just use the - // identity hash code. - receiverHashCode = Primitives.objectHashCode(_self); - } else if (JS('String', 'typeof #', _receiver) != 'object') { - // A bound closure on a primitive JavaScript type. We - // use the hashCode method we define for those primitive types. - receiverHashCode = _receiver.hashCode; - } else { - // A bound closure on an intercepted native class, just use the - // identity hash code. - receiverHashCode = Primitives.objectHashCode(_receiver); - } - return receiverHashCode ^ Primitives.objectHashCode(_target); - } - - @NoInline() - static selfOf(BoundClosure closure) => closure._self; - - static targetOf(BoundClosure closure) => closure._target; - - @NoInline() - static receiverOf(BoundClosure closure) => closure._receiver; - - static nameOf(BoundClosure closure) => closure._name; - - static String selfFieldNameCache; - - static String selfFieldName() { - if (selfFieldNameCache == null) { - selfFieldNameCache = computeFieldNamed('self'); - } - return selfFieldNameCache; - } - - static String receiverFieldNameCache; - - static String receiverFieldName() { - if (receiverFieldNameCache == null) { - receiverFieldNameCache = computeFieldNamed('receiver'); - } - return receiverFieldNameCache; - } - - @NoInline() @NoSideEffects() - static String computeFieldNamed(String fieldName) { - var template = new BoundClosure('self', 'target', 'receiver', 'name'); - var names = JSArray.markFixedList( - JS('', 'Object.getOwnPropertyNames(#)', template)); - for (int i = 0; i < names.length; i++) { - var name = names[i]; - if (JS('bool', '#[#] === #', template, name, fieldName)) { - return JS('String', '#', name); - } - } - } -} - -bool jsHasOwnProperty(var jsObject, String property) { - return JS('bool', r'#.hasOwnProperty(#)', jsObject, property); -} - -jsPropertyAccess(var jsObject, String property) { - return JS('var', r'#[#]', jsObject, property); -} - -/** - * Called at the end of unaborted switch cases to get the singleton - * FallThroughError exception that will be thrown. - */ -getFallThroughError() => new FallThroughErrorImplementation(); - -/** - * A metadata annotation describing the types instantiated by a native element. - * - * The annotation is valid on a native method and a field of a native class. - * - * By default, a field of a native class is seen as an instantiation point for - * all native classes that are a subtype of the field's type, and a native - * method is seen as an instantiation point fo all native classes that are a - * subtype of the method's return type, or the argument types of the declared - * type of the method's callback parameter. - * - * An @[Creates] annotation overrides the default set of instantiated types. If - * one or more @[Creates] annotations are present, the type of the native - * element is ignored, and the union of @[Creates] annotations is used instead. - * The names in the strings are resolved and the program will fail to compile - * with dart2js if they do not name types. - * - * The argument to [Creates] is a string. The string is parsed as the names of - * one or more types, separated by vertical bars `|`. There are some special - * names: - * - * * `=Object`. This means 'exactly Object', which is a plain JavaScript object - * with properties and none of the subtypes of Object. - * - * Example: we may know that a method always returns a specific implementation: - * - * @Creates('_NodeList') - * List getElementsByTagName(String tag) native; - * - * Useful trick: A method can be marked as not instantiating any native classes - * with the annotation `@Creates('Null')`. This is useful for fields on native - * classes that are used only in Dart code. - * - * @Creates('Null') - * var _cachedFoo; - */ -class Creates { - final String types; - const Creates(this.types); -} - -/** - * A metadata annotation describing the types returned or yielded by a native - * element. - * - * The annotation is valid on a native method and a field of a native class. - * - * By default, a native method or field is seen as returning or yielding all - * subtypes if the method return type or field type. This annotation allows a - * more precise set of types to be specified. - * - * See [Creates] for the syntax of the argument. - * - * Example: IndexedDB keys are numbers, strings and JavaScript Arrays of keys. - * - * @Returns('String|num|JSExtendableArray') - * dynamic key; - * - * // Equivalent: - * @Returns('String') @Returns('num') @Returns('JSExtendableArray') - * dynamic key; - */ -class Returns { - final String types; - const Returns(this.types); -} - -/** - * A metadata annotation placed on native methods and fields of native classes - * to specify the JavaScript name. - * - * This example declares a Dart field + getter + setter called `$dom_title` that - * corresponds to the JavaScript property `title`. - * - * class Docmument native "*Foo" { - * @JSName('title') - * String $dom_title; - * } - */ -class JSName { - final String name; - const JSName(this.name); -} - -/** - * The following methods are called by the runtime to implement - * checked mode and casts. We specialize each primitive type (eg int, bool), and - * use the compiler's convention to do is-checks on regular objects. - */ -boolConversionCheck(value) { - if (value is bool) return value; - // One of the following checks will always fail. - boolTypeCheck(value); - assert(value != null); - return false; -} - -stringTypeCheck(value) { - if (value == null) return value; - if (value is String) return value; - throw new TypeErrorImplementation(value, 'String'); -} - -stringTypeCast(value) { - if (value is String || value == null) return value; - // TODO(lrn): When reified types are available, pass value.class and String. - throw new CastErrorImplementation( - Primitives.objectTypeName(value), 'String'); -} - -doubleTypeCheck(value) { - if (value == null) return value; - if (value is double) return value; - throw new TypeErrorImplementation(value, 'double'); -} - -doubleTypeCast(value) { - if (value is double || value == null) return value; - throw new CastErrorImplementation( - Primitives.objectTypeName(value), 'double'); -} - -numTypeCheck(value) { - if (value == null) return value; - if (value is num) return value; - throw new TypeErrorImplementation(value, 'num'); -} - -numTypeCast(value) { - if (value is num || value == null) return value; - throw new CastErrorImplementation( - Primitives.objectTypeName(value), 'num'); -} - -boolTypeCheck(value) { - if (value == null) return value; - if (value is bool) return value; - throw new TypeErrorImplementation(value, 'bool'); -} - -boolTypeCast(value) { - if (value is bool || value == null) return value; - throw new CastErrorImplementation( - Primitives.objectTypeName(value), 'bool'); -} - -intTypeCheck(value) { - if (value == null) return value; - if (value is int) return value; - throw new TypeErrorImplementation(value, 'int'); -} - -intTypeCast(value) { - if (value is int || value == null) return value; - throw new CastErrorImplementation( - Primitives.objectTypeName(value), 'int'); -} - -void propertyTypeError(value, property) { - // Cuts the property name to the class name. - String name = property.substring(3, property.length); - throw new TypeErrorImplementation(value, name); -} - -void propertyTypeCastError(value, property) { - // Cuts the property name to the class name. - String actualType = Primitives.objectTypeName(value); - String expectedType = property.substring(3, property.length); - throw new CastErrorImplementation(actualType, expectedType); -} - -/** - * For types that are not supertypes of native (eg DOM) types, - * we emit a simple property check to check that an object implements - * that type. - */ -propertyTypeCheck(value, property) { - if (value == null) return value; - if (JS('bool', '!!#[#]', value, property)) return value; - propertyTypeError(value, property); -} - -/** - * For types that are not supertypes of native (eg DOM) types, - * we emit a simple property check to check that an object implements - * that type. - */ -propertyTypeCast(value, property) { - if (value == null || JS('bool', '!!#[#]', value, property)) return value; - propertyTypeCastError(value, property); -} - -/** - * For types that are supertypes of native (eg DOM) types, we use the - * interceptor for the class because we cannot add a JS property to the - * prototype at load time. - */ -interceptedTypeCheck(value, property) { - if (value == null) return value; - if ((identical(JS('String', 'typeof #', value), 'object')) - && JS('bool', '#[#]', getInterceptor(value), property)) { - return value; - } - propertyTypeError(value, property); -} - -/** - * For types that are supertypes of native (eg DOM) types, we use the - * interceptor for the class because we cannot add a JS property to the - * prototype at load time. - */ -interceptedTypeCast(value, property) { - if (value == null - || ((JS('bool', 'typeof # === "object"', value)) - && JS('bool', '#[#]', getInterceptor(value), property))) { - return value; - } - propertyTypeCastError(value, property); -} - -/** - * Specialization of the type check for num and String and their - * supertype since [value] can be a JS primitive. - */ -numberOrStringSuperTypeCheck(value, property) { - if (value == null) return value; - if (value is String) return value; - if (value is num) return value; - if (JS('bool', '!!#[#]', value, property)) return value; - propertyTypeError(value, property); -} - -numberOrStringSuperTypeCast(value, property) { - if (value is String) return value; - if (value is num) return value; - return propertyTypeCast(value, property); -} - -numberOrStringSuperNativeTypeCheck(value, property) { - if (value == null) return value; - if (value is String) return value; - if (value is num) return value; - if (JS('bool', '#[#]', getInterceptor(value), property)) return value; - propertyTypeError(value, property); -} - -numberOrStringSuperNativeTypeCast(value, property) { - if (value == null) return value; - if (value is String) return value; - if (value is num) return value; - if (JS('bool', '#[#]', getInterceptor(value), property)) return value; - propertyTypeCastError(value, property); -} - -/** - * Specialization of the type check for String and its supertype - * since [value] can be a JS primitive. - */ -stringSuperTypeCheck(value, property) { - if (value == null) return value; - if (value is String) return value; - if (JS('bool', '!!#[#]', value, property)) return value; - propertyTypeError(value, property); -} - -stringSuperTypeCast(value, property) { - if (value is String) return value; - return propertyTypeCast(value, property); -} - -stringSuperNativeTypeCheck(value, property) { - if (value == null) return value; - if (value is String) return value; - if (JS('bool', '#[#]', getInterceptor(value), property)) return value; - propertyTypeError(value, property); -} - -stringSuperNativeTypeCast(value, property) { - if (value is String || value == null) return value; - if (JS('bool', '#[#]', getInterceptor(value), property)) return value; - propertyTypeCastError(value, property); -} - -/** - * Specialization of the type check for List and its supertypes, - * since [value] can be a JS array. - */ -listTypeCheck(value) { - if (value == null) return value; - if (value is List) return value; - throw new TypeErrorImplementation(value, 'List'); -} - -listTypeCast(value) { - if (value is List || value == null) return value; - throw new CastErrorImplementation( - Primitives.objectTypeName(value), 'List'); -} - -listSuperTypeCheck(value, property) { - if (value == null) return value; - if (value is List) return value; - if (JS('bool', '!!#[#]', value, property)) return value; - propertyTypeError(value, property); -} - -listSuperTypeCast(value, property) { - if (value is List) return value; - return propertyTypeCast(value, property); -} - -listSuperNativeTypeCheck(value, property) { - if (value == null) return value; - if (value is List) return value; - if (JS('bool', '#[#]', getInterceptor(value), property)) return value; - propertyTypeError(value, property); -} - -listSuperNativeTypeCast(value, property) { - if (value is List || value == null) return value; - if (JS('bool', '#[#]', getInterceptor(value), property)) return value; - propertyTypeCastError(value, property); -} - -voidTypeCheck(value) { - if (value == null) return value; - throw new TypeErrorImplementation(value, 'void'); -} - -checkMalformedType(value, message) { - if (value == null) return value; - throw new TypeErrorImplementation.fromMessage(message); -} - -@NoInline() -void checkDeferredIsLoaded(String loadId, String uri) { - if (!_loadedLibraries.contains(loadId)) { - throw new DeferredNotLoadedError(uri); - } -} - -/** - * Special interface recognized by the compiler and implemented by DOM - * objects that support integer indexing. This interface is not - * visible to anyone, and is only injected into special libraries. - */ -abstract class JavaScriptIndexingBehavior extends JSMutableIndexable { -} - -// TODO(lrn): These exceptions should be implemented in core. -// When they are, remove the 'Implementation' here. - -/** Thrown by type assertions that fail. */ -class TypeErrorImplementation extends Error implements TypeError { - final String message; - - /** - * Normal type error caused by a failed subtype test. - */ - TypeErrorImplementation(Object value, String type) - : message = "type '${Primitives.objectTypeName(value)}' is not a subtype " - "of type '$type'"; - - TypeErrorImplementation.fromMessage(String this.message); - - String toString() => message; -} - -/** Thrown by the 'as' operator if the cast isn't valid. */ -class CastErrorImplementation extends Error implements CastError { - // TODO(lrn): Rename to CastError (and move implementation into core). - final String message; - - /** - * Normal cast error caused by a failed type cast. - */ - CastErrorImplementation(Object actualType, Object expectedType) - : message = "CastError: Casting value of type $actualType to" - " incompatible type $expectedType"; - - String toString() => message; -} - -class FallThroughErrorImplementation extends FallThroughError { - FallThroughErrorImplementation(); - String toString() => "Switch case fall-through."; -} - -/** - * Helper function for implementing asserts. The compiler treats this specially. - */ -void assertHelper(condition) { - // Do a bool check first because it is common and faster than 'is Function'. - if (condition is !bool) { - if (condition is Function) condition = condition(); - if (condition is !bool) { - throw new TypeErrorImplementation(condition, 'bool'); - } - } - // Compare to true to avoid boolean conversion check in checked - // mode. - if (true != condition) throw new AssertionError(); -} - -/** - * Called by generated code when a method that must be statically - * resolved cannot be found. - */ -void throwNoSuchMethod(obj, name, arguments, expectedArgumentNames) { - Symbol memberName = new _symbol_dev.Symbol.unvalidated(name); - throw new NoSuchMethodError(obj, memberName, arguments, - new Map(), - expectedArgumentNames); -} - -/** - * Called by generated code when a static field's initializer references the - * field that is currently being initialized. - */ -void throwCyclicInit(String staticName) { - throw new CyclicInitializationError( - "Cyclic initialization for static $staticName"); -} - -/** - * Error thrown when a runtime error occurs. - */ -class RuntimeError extends Error { - final message; - RuntimeError(this.message); - String toString() => "RuntimeError: $message"; -} - -class DeferredNotLoadedError extends Error implements NoSuchMethodError { - String libraryName; - - DeferredNotLoadedError(this.libraryName); - - String toString() { - return "Deferred library $libraryName was not loaded."; - } -} - -abstract class RuntimeType { - const RuntimeType(); - - toRti(); -} - -class RuntimeFunctionType extends RuntimeType { - final RuntimeType returnType; - final List parameterTypes; - final List optionalParameterTypes; - final namedParameters; - - static var /* bool */ inAssert = false; - - RuntimeFunctionType(this.returnType, - this.parameterTypes, - this.optionalParameterTypes, - this.namedParameters); - - bool get isVoid => returnType is VoidRuntimeType; - - /// Called from generated code. [expression] is a Dart object and this method - /// returns true if [this] is a supertype of [expression]. - @NoInline() @NoSideEffects() - bool _isTest(expression) { - var functionTypeObject = _extractFunctionTypeObjectFrom(expression); - return functionTypeObject == null - ? false - : isFunctionSubtype(functionTypeObject, toRti()); - } - - @NoInline() @NoSideEffects() - _asCheck(expression) { - // Type inferrer doesn't think this is called with dynamic arguments. - return _check(JS('', '#', expression), true); - } - - @NoInline() @NoSideEffects() - _assertCheck(expression) { - if (inAssert) return null; - inAssert = true; // Don't try to check this library itself. - try { - // Type inferrer don't think this is called with dynamic arguments. - return _check(JS('', '#', expression), false); - } finally { - inAssert = false; - } - } - - _check(expression, bool isCast) { - if (expression == null) return null; - if (_isTest(expression)) return expression; - - var self = new FunctionTypeInfoDecoderRing(toRti()).toString(); - if (isCast) { - var functionTypeObject = _extractFunctionTypeObjectFrom(expression); - var pretty; - if (functionTypeObject != null) { - pretty = new FunctionTypeInfoDecoderRing(functionTypeObject).toString(); - } else { - pretty = Primitives.objectTypeName(expression); - } - throw new CastErrorImplementation(pretty, self); - } else { - // TODO(ahe): Pass "pretty" function-type to TypeErrorImplementation? - throw new TypeErrorImplementation(expression, self); - } - } - - _extractFunctionTypeObjectFrom(o) { - var interceptor = getInterceptor(o); - return JS('bool', '# in #', JS_SIGNATURE_NAME(), interceptor) - ? JS('', '#[#]()', interceptor, JS_SIGNATURE_NAME()) - : null; - } - - toRti() { - var result = JS('=Object', '{ #: "dynafunc" }', JS_FUNCTION_TYPE_TAG()); - if (isVoid) { - JS('', '#[#] = true', result, JS_FUNCTION_TYPE_VOID_RETURN_TAG()); - } else { - if (returnType is! DynamicRuntimeType) { - JS('', '#[#] = #', result, JS_FUNCTION_TYPE_RETURN_TYPE_TAG(), - returnType.toRti()); - } - } - if (parameterTypes != null && !parameterTypes.isEmpty) { - JS('', '#[#] = #', result, JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG(), - listToRti(parameterTypes)); - } - - if (optionalParameterTypes != null && !optionalParameterTypes.isEmpty) { - JS('', '#[#] = #', result, JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG(), - listToRti(optionalParameterTypes)); - } - - if (namedParameters != null) { - var namedRti = JS('=Object', 'Object.create(null)'); - var keys = extractKeys(namedParameters); - for (var i = 0; i < keys.length; i++) { - var name = keys[i]; - var rti = JS('', '#[#]', namedParameters, name).toRti(); - JS('', '#[#] = #', namedRti, name, rti); - } - JS('', '#[#] = #', result, JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG(), - namedRti); - } - - return result; - } - - static listToRti(list) { - list = JS('JSFixedArray', '#', list); - var result = JS('JSExtendableArray', '[]'); - for (var i = 0; i < list.length; i++) { - JS('', '#.push(#)', result, list[i].toRti()); - } - return result; - } - - String toString() { - String result = '('; - bool needsComma = false; - if (parameterTypes != null) { - for (var i = 0; i < parameterTypes.length; i++) { - RuntimeType type = parameterTypes[i]; - if (needsComma) result += ', '; - result += '$type'; - needsComma = true; - } - } - if (optionalParameterTypes != null && !optionalParameterTypes.isEmpty) { - if (needsComma) result += ', '; - needsComma = false; - result += '['; - for (var i = 0; i < optionalParameterTypes.length; i++) { - RuntimeType type = optionalParameterTypes[i]; - if (needsComma) result += ', '; - result += '$type'; - needsComma = true; - } - result += ']'; - } else if (namedParameters != null) { - if (needsComma) result += ', '; - needsComma = false; - result += '{'; - var keys = extractKeys(namedParameters); - for (var i = 0; i < keys.length; i++) { - var name = keys[i]; - if (needsComma) result += ', '; - var rti = JS('', '#[#]', namedParameters, name).toRti(); - result += '$rti ${JS("String", "#", name)}'; - needsComma = true; - } - result += '}'; - } - - result += ') -> $returnType'; - return result; - } -} - -RuntimeFunctionType buildFunctionType(returnType, - parameterTypes, - optionalParameterTypes) { - return new RuntimeFunctionType( - returnType, - parameterTypes, - optionalParameterTypes, - null); -} - -RuntimeFunctionType buildNamedFunctionType(returnType, - parameterTypes, - namedParameters) { - return new RuntimeFunctionType( - returnType, - parameterTypes, - null, - namedParameters); -} - -RuntimeType buildInterfaceType(rti, typeArguments) { - String name = JS('String|Null', r'#.name', rti); - if (typeArguments == null || typeArguments.isEmpty) { - return new RuntimeTypePlain(name); - } - return new RuntimeTypeGeneric(name, typeArguments, null); -} - -class DynamicRuntimeType extends RuntimeType { - const DynamicRuntimeType(); - - String toString() => 'dynamic'; - - toRti() => null; -} - -RuntimeType getDynamicRuntimeType() => const DynamicRuntimeType(); - -class VoidRuntimeType extends RuntimeType { - const VoidRuntimeType(); - - String toString() => 'void'; - - toRti() => throw 'internal error'; -} - -RuntimeType getVoidRuntimeType() => const VoidRuntimeType(); - -/** - * Meta helper for function type tests. - * - * A "meta helper" is a helper function that is never called but simulates how - * generated code behaves as far as resolution and type inference is concerned. - */ -functionTypeTestMetaHelper() { - var dyn = JS('', 'x'); - var dyn2 = JS('', 'x'); - List fixedListOrNull = JS('JSFixedArray|Null', 'x'); - List fixedListOrNull2 = JS('JSFixedArray|Null', 'x'); - List fixedList = JS('JSFixedArray', 'x'); - // TODO(ahe): Can we use [UnknownJavaScriptObject] below? - var /* UnknownJavaScriptObject */ jsObject = JS('=Object', 'x'); - - buildFunctionType(dyn, fixedListOrNull, fixedListOrNull2); - buildNamedFunctionType(dyn, fixedList, jsObject); - buildInterfaceType(dyn, fixedListOrNull); - getDynamicRuntimeType(); - getVoidRuntimeType(); - convertRtiToRuntimeType(dyn); - dyn._isTest(dyn2); - dyn._asCheck(dyn2); - dyn._assertCheck(dyn2); -} - -RuntimeType convertRtiToRuntimeType(rti) { - if (rti == null) { - return getDynamicRuntimeType(); - } else if (JS('bool', 'typeof # == "function"', rti)) { - return new RuntimeTypePlain(JS('String', r'rti.name')); - } else if (JS('bool', '#.constructor == Array', rti)) { - List list = JS('JSFixedArray', '#', rti); - String name = JS('String', r'#.name', list[0]); - List arguments = []; - for (int i = 1; i < list.length; i++) { - arguments.add(convertRtiToRuntimeType(list[i])); - } - return new RuntimeTypeGeneric(name, arguments, rti); - } else if (JS('bool', '"func" in #', rti)) { - return new FunctionTypeInfoDecoderRing(rti).toRuntimeType(); - } else { - throw new RuntimeError( - "Cannot convert " - "'${JS('String', 'JSON.stringify(#)', rti)}' to RuntimeType."); - } -} - -class RuntimeTypePlain extends RuntimeType { - final String name; - - RuntimeTypePlain(this.name); - - toRti() { - var allClasses = JS_EMBEDDED_GLOBAL('', ALL_CLASSES); - var rti = JS('', '#[#]', allClasses, name); - if (rti == null) throw "no type for '$name'"; - return rti; - } - - String toString() => name; -} - -class RuntimeTypeGeneric extends RuntimeType { - final String name; - final List arguments; - var rti; - - RuntimeTypeGeneric(this.name, this.arguments, this.rti); - - toRti() { - if (rti != null) return rti; - var allClasses = JS_EMBEDDED_GLOBAL('', ALL_CLASSES); - var result = JS('JSExtendableArray', '[#[#]]', allClasses, name); - if (result[0] == null) { - throw "no type for '$name<...>'"; - } - for (RuntimeType argument in arguments) { - JS('', '#.push(#)', result, argument.toRti()); - } - return rti = result; - } - - String toString() => '$name<${arguments.join(", ")}>'; -} - -class FunctionTypeInfoDecoderRing { - final _typeData; - String _cachedToString; - - FunctionTypeInfoDecoderRing(this._typeData); - - bool get _hasReturnType => JS('bool', '"ret" in #', _typeData); - get _returnType => JS('', '#.ret', _typeData); - - bool get _isVoid => JS('bool', '!!#.void', _typeData); - - bool get _hasArguments => JS('bool', '"args" in #', _typeData); - List get _arguments => JS('JSExtendableArray', '#.args', _typeData); - - bool get _hasOptionalArguments => JS('bool', '"opt" in #', _typeData); - List get _optionalArguments => JS('JSExtendableArray', '#.opt', _typeData); - - bool get _hasNamedArguments => JS('bool', '"named" in #', _typeData); - get _namedArguments => JS('=Object', '#.named', _typeData); - - RuntimeType toRuntimeType() { - // TODO(ahe): Implement this (and update return type). - return const DynamicRuntimeType(); - } - - String _convert(type) { - String result = runtimeTypeToString(type); - if (result != null) return result; - if (JS('bool', '"func" in #', type)) { - return new FunctionTypeInfoDecoderRing(type).toString(); - } else { - throw 'bad type'; - } - } - - String toString() { - if (_cachedToString != null) return _cachedToString; - var s = "("; - var sep = ''; - if (_hasArguments) { - for (var argument in _arguments) { - s += sep; - s += _convert(argument); - sep = ', '; - } - } - if (_hasOptionalArguments) { - s += '$sep['; - sep = ''; - for (var argument in _optionalArguments) { - s += sep; - s += _convert(argument); - sep = ', '; - } - s += ']'; - } - if (_hasNamedArguments) { - s += '$sep{'; - sep = ''; - for (var name in extractKeys(_namedArguments)) { - s += sep; - s += '$name: '; - s += _convert(JS('', '#[#]', _namedArguments, name)); - sep = ', '; - } - s += '}'; - } - s += ') -> '; - if (_isVoid) { - s += 'void'; - } else if (_hasReturnType) { - s += _convert(_returnType); - } else { - s += 'dynamic'; - } - return _cachedToString = "$s"; - } -} - -// TODO(ahe): Remove this class and call noSuchMethod instead. -class UnimplementedNoSuchMethodError extends Error - implements NoSuchMethodError { - final String _message; - - UnimplementedNoSuchMethodError(this._message); - - String toString() => "Unsupported operation: $_message"; -} - -/** - * Creates a random number with 64 bits of randomness. - * - * This will be truncated to the 53 bits available in a double. - */ -int random64() { - // TODO(lrn): Use a secure random source. - int int32a = JS("int", "(Math.random() * 0x100000000) >>> 0"); - int int32b = JS("int", "(Math.random() * 0x100000000) >>> 0"); - return int32a + int32b * 0x100000000; -} - -String jsonEncodeNative(String string) { - return JS("String", "JSON.stringify(#)", string); -} - -/** - * Returns a property name for placing data on JavaScript objects shared between - * DOM isolates. This happens when multiple programs are loaded in the same - * JavaScript context (i.e. page). The name is based on [name] but with an - * additional part that is unique for each isolate. - * - * The form of the name is '___dart_$name_$id'. - */ -String getIsolateAffinityTag(String name) { - var isolateTagGetter = - JS_EMBEDDED_GLOBAL('', GET_ISOLATE_TAG); - return JS('String', '#(#)', isolateTagGetter, name); -} - -typedef Future LoadLibraryFunctionType(); - -LoadLibraryFunctionType _loadLibraryWrapper(String loadId) { - return () => loadDeferredLibrary(loadId); -} - -final Map> _loadingLibraries = >{}; -final Set _loadedLibraries = new Set(); - -typedef void DeferredLoadCallback(); - -// Function that will be called every time a new deferred import is loaded. -DeferredLoadCallback deferredLoadHook; - -Future loadDeferredLibrary(String loadId) { - // For each loadId there is a list of hunk-uris to load, and a corresponding - // list of hashes. These are stored in the app-global scope. - var urisMap = JS_EMBEDDED_GLOBAL('', DEFERRED_LIBRARY_URIS); - List uris = JS('JSExtendableArray|Null', '#[#]', urisMap, loadId); - var hashesMap = JS_EMBEDDED_GLOBAL('', DEFERRED_LIBRARY_HASHES); - List hashes = JS('JSExtendableArray|Null', '#[#]', hashesMap, loadId); - if (uris == null) return new Future.value(null); - // The indices into `uris` and `hashes` that we want to load. - List indices = new List.generate(uris.length, (i) => i); - var isHunkLoaded = JS_EMBEDDED_GLOBAL('', IS_HUNK_LOADED); - var isHunkInitialized = JS_EMBEDDED_GLOBAL('', IS_HUNK_INITIALIZED); - // Filter away indices for hunks that have already been loaded. - List indicesToLoad = indices - .where((int i) => !JS('bool','#(#)', isHunkLoaded, hashes[i])) - .toList(); - return Future.wait(indicesToLoad - .map((int i) => _loadHunk(uris[i]))).then((_) { - // Now all hunks have been loaded, we run the needed initializers. - List indicesToInitialize = indices - .where((int i) => !JS('bool','#(#)', isHunkInitialized, hashes[i])) - .toList(); // Load the needed hunks. - for (int i in indicesToInitialize) { - var initializer = JS_EMBEDDED_GLOBAL('', INITIALIZE_LOADED_HUNK); - JS('void', '#(#)', initializer, hashes[i]); - } - bool updated = _loadedLibraries.add(loadId); - if (updated && deferredLoadHook != null) { - deferredLoadHook(); - } - }); -} - -Future _loadHunk(String hunkName) { - // TODO(ahe): Validate libraryName. Kasper points out that you want - // to be able to experiment with the effect of toggling @DeferLoad, - // so perhaps we should silently ignore "bad" library names. - Future future = _loadingLibraries[hunkName]; - if (future != null) { - return future.then((_) => null); - } - - String uri = IsolateNatives.thisScript; - - int index = uri.lastIndexOf('/'); - uri = '${uri.substring(0, index + 1)}$hunkName'; - - if (Primitives.isJsshell || Primitives.isD8) { - // TODO(ahe): Move this code to a JavaScript command helper script that is - // not included in generated output. - return _loadingLibraries[hunkName] = new Future(() { - try { - // Create a new function to avoid getting access to current function - // context. - JS('void', '(new Function(#))()', 'load("$uri")'); - } catch (error, stackTrace) { - throw new DeferredLoadException("Loading $uri failed."); - } - return null; - }); - } else if (isWorker()) { - // We are in a web worker. Load the code with an XMLHttpRequest. - return _loadingLibraries[hunkName] = new Future(() { - Completer completer = new Completer(); - enterJsAsync(); - Future leavingFuture = completer.future.whenComplete(() { - leaveJsAsync(); - }); - - int index = uri.lastIndexOf('/'); - uri = '${uri.substring(0, index + 1)}$hunkName'; - var xhr = JS('dynamic', 'new XMLHttpRequest()'); - JS('void', '#.open("GET", #)', xhr, uri); - JS('void', '#.addEventListener("load", #, false)', - xhr, convertDartClosureToJS((event) { - if (JS('int', '#.status', xhr) != 200) { - completer.completeError( - new DeferredLoadException("Loading $uri failed.")); - return; - } - String code = JS('String', '#.responseText', xhr); - try { - // Create a new function to avoid getting access to current function - // context. - JS('void', '(new Function(#))()', code); - } catch (error, stackTrace) { - completer.completeError( - new DeferredLoadException("Evaluating $uri failed.")); - return; - } - completer.complete(null); - }, 1)); - - var fail = convertDartClosureToJS((event) { - new DeferredLoadException("Loading $uri failed."); - }, 1); - JS('void', '#.addEventListener("error", #, false)', xhr, fail); - JS('void', '#.addEventListener("abort", #, false)', xhr, fail); - - JS('void', '#.send()', xhr); - return leavingFuture; - }); - } - // We are in a dom-context. - return _loadingLibraries[hunkName] = new Future(() { - Completer completer = new Completer(); - // Inject a script tag. - var script = JS('', 'document.createElement("script")'); - JS('', '#.type = "text/javascript"', script); - JS('', '#.src = #', script, uri); - JS('', '#.addEventListener("load", #, false)', - script, convertDartClosureToJS((event) { - completer.complete(null); - }, 1)); - JS('', '#.addEventListener("error", #, false)', - script, convertDartClosureToJS((event) { - completer.completeError( - new DeferredLoadException("Loading $uri failed.")); - }, 1)); - JS('', 'document.body.appendChild(#)', script); - - return completer.future; - }); -} - -class MainError extends Error implements NoSuchMethodError { - final String _message; - - MainError(this._message); - - String toString() => 'NoSuchMethodError: $_message'; -} - -void missingMain() { - throw new MainError("No top-level function named 'main'."); -} - -void badMain() { - throw new MainError("'main' is not a function."); -} - -void mainHasTooManyParameters() { - throw new MainError("'main' expects too many parameters."); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_mirrors.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_mirrors.dart deleted file mode 100644 index 9d55eed28348..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_mirrors.dart +++ /dev/null @@ -1,3034 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -library dart._js_mirrors; - -import 'dart:_js_embedded_names' show - ALL_CLASSES, - LAZIES, - LIBRARIES, - STATICS, - TYPE_INFORMATION, - TYPEDEF_PREDICATE_PROPERTY_NAME, - TYPEDEF_TYPE_PROPERTY_NAME; - -import 'dart:collection' show - UnmodifiableListView, - UnmodifiableMapView; - -import 'dart:mirrors'; - -import 'dart:_foreign_helper' show - JS, - JS_CURRENT_ISOLATE, - JS_CURRENT_ISOLATE_CONTEXT, - JS_EMBEDDED_GLOBAL, - JS_GET_NAME, - JS_TYPEDEF_TAG, - JS_FUNCTION_TYPE_TAG, - JS_FUNCTION_TYPE_RETURN_TYPE_TAG, - JS_FUNCTION_TYPE_VOID_RETURN_TAG, - JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG, - JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG, - JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG; - - -import 'dart:_internal' as _symbol_dev; - -import 'dart:_js_helper' show - BoundClosure, - CachedInvocation, - Closure, - JSInvocationMirror, - JsCache, - Null, - Primitives, - ReflectionInfo, - RuntimeError, - TearOffClosure, - TypeVariable, - UnimplementedNoSuchMethodError, - createRuntimeType, - createUnmangledInvocationMirror, - getMangledTypeName, - getMetadata, - getRuntimeType, - runtimeTypeToString, - setRuntimeTypeInfo, - throwInvalidReflectionError, - TypeImpl, - deferredLoadHook; - -import 'dart:_interceptors' show - Interceptor, - JSArray, - JSExtendableArray, - getInterceptor; - -import 'dart:_js_names'; - -const String METHODS_WITH_OPTIONAL_ARGUMENTS = r'$methodsWithOptionalArguments'; - -bool hasReflectableProperty(var jsFunction) { - return JS('bool', '# in #', JS_GET_NAME("REFLECTABLE"), jsFunction); -} - -/// No-op method that is called to inform the compiler that tree-shaking needs -/// to be disabled. -disableTreeShaking() => preserveNames(); - -/// No-op method that is called to inform the compiler that metadata must be -/// preserved at runtime. -preserveMetadata() {} - -/// No-op method that is called to inform the compiler that the compiler must -/// preserve the URIs. -preserveUris() {} - -/// No-op method that is called to inform the compiler that the compiler must -/// preserve the library names. -preserveLibraryNames() {} - -String getName(Symbol symbol) { - preserveNames(); - return n(symbol); -} - -class JsMirrorSystem implements MirrorSystem { - UnmodifiableMapView _cachedLibraries; - - final IsolateMirror isolate = new JsIsolateMirror(); - - JsTypeMirror get dynamicType => _dynamicType; - JsTypeMirror get voidType => _voidType; - - static final JsTypeMirror _dynamicType = - new JsTypeMirror(const Symbol('dynamic')); - static final JsTypeMirror _voidType = new JsTypeMirror(const Symbol('void')); - - static Map> _librariesByName; - - // Will be set to `true` when we have installed a hook on [deferredLoadHook] - // to avoid installing it multiple times. - static bool _hasInstalledDeferredLoadHook = false; - - static Map> get librariesByName { - if (_librariesByName == null) { - _librariesByName = computeLibrariesByName(); - if (!_hasInstalledDeferredLoadHook) { - _hasInstalledDeferredLoadHook = true; - // After a deferred import has been loaded new libraries might have - // been created, so in the hook we erase _librariesByName, so it will be - // recomputed on the next access. - deferredLoadHook = () => _librariesByName = null; - } - } - return _librariesByName; - } - - Map get libraries { - if (_cachedLibraries != null) return _cachedLibraries; - Map result = new Map(); - for (List list in librariesByName.values) { - for (LibraryMirror library in list) { - result[library.uri] = library; - } - } - return _cachedLibraries = - new UnmodifiableMapView(result); - } - - LibraryMirror findLibrary(Symbol libraryName) { - return librariesByName[n(libraryName)].single; - } - - static Map> computeLibrariesByName() { - disableTreeShaking(); - var result = new Map>(); - var jsLibraries = JS_EMBEDDED_GLOBAL('JSExtendableArray|Null', LIBRARIES); - if (jsLibraries == null) return result; - for (List data in jsLibraries) { - String name = data[0]; - String uriString = data[1]; - Uri uri; - // The Uri has been compiled out. Create a URI from the simple name. - if (uriString != "") { - uri = Uri.parse(uriString); - } else { - uri = new Uri(scheme: 'https', - host: 'dartlang.org', - path: 'dart2js-stripped-uri', - queryParameters: { 'lib': name }); - } - List classes = data[2]; - List functions = data[3]; - var metadataFunction = data[4]; - var fields = data[5]; - bool isRoot = data[6]; - var globalObject = data[7]; - List metadata = (metadataFunction == null) - ? const [] : JS('List', '#()', metadataFunction); - var libraries = result.putIfAbsent(name, () => []); - libraries.add( - new JsLibraryMirror( - s(name), uri, classes, functions, metadata, fields, isRoot, - globalObject)); - } - return result; - } -} - -abstract class JsMirror implements Mirror { - const JsMirror(); - - String get _prettyName; - - String toString() => _prettyName; - - // TODO(ahe): Remove this method from the API. - MirrorSystem get mirrors => currentJsMirrorSystem; - - _getField(JsMirror receiver) { - throw new UnimplementedError(); - } - - void _setField(JsMirror receiver, Object arg) { - throw new UnimplementedError(); - } - - _loadField(String name) { - throw new UnimplementedError(); - } - - void _storeField(String name, Object arg) { - throw new UnimplementedError(); - } -} - -// This class is somewhat silly in the current implementation. -class JsIsolateMirror extends JsMirror implements IsolateMirror { - final _isolateContext = JS_CURRENT_ISOLATE_CONTEXT(); - - String get _prettyName => 'Isolate'; - - String get debugName { - String id = _isolateContext == null ? 'X' : _isolateContext.id.toString(); - // Using name similar to what the VM uses. - return '${n(rootLibrary.simpleName)}-$id'; - } - - bool get isCurrent => JS_CURRENT_ISOLATE_CONTEXT() == _isolateContext; - - LibraryMirror get rootLibrary { - return currentJsMirrorSystem.libraries.values.firstWhere( - (JsLibraryMirror library) => library._isRoot); - } -} - -abstract class JsDeclarationMirror extends JsMirror - implements DeclarationMirror { - final Symbol simpleName; - - const JsDeclarationMirror(this.simpleName); - - Symbol get qualifiedName => computeQualifiedName(owner, simpleName); - - bool get isPrivate => n(simpleName).startsWith('_'); - - bool get isTopLevel => owner != null && owner is LibraryMirror; - - // TODO(ahe): This should use qualifiedName. - String toString() => "$_prettyName on '${n(simpleName)}'"; - - List get _methods { - throw new RuntimeError('Should not call _methods'); - } - - _invoke(List positionalArguments, Map namedArguments) { - throw new RuntimeError('Should not call _invoke'); - } - - // TODO(ahe): Implement this. - SourceLocation get location => throw new UnimplementedError(); -} - -class JsTypeVariableMirror extends JsTypeMirror implements TypeVariableMirror { - final DeclarationMirror owner; - final TypeVariable _typeVariable; - final int _metadataIndex; - TypeMirror _cachedUpperBound; - - JsTypeVariableMirror(TypeVariable typeVariable, this.owner, - this._metadataIndex) - : this._typeVariable = typeVariable, - super(s(typeVariable.name)); - - bool operator ==(other) { - return (other is JsTypeVariableMirror && - simpleName == other.simpleName && - owner == other.owner); - } - - int get hashCode { - int code = 0x3FFFFFFF & (JsTypeVariableMirror).hashCode; - code ^= 17 * simpleName.hashCode; - code ^= 19 * owner.hashCode; - return code; - } - - String get _prettyName => 'TypeVariableMirror'; - - bool get isTopLevel => false; - bool get isStatic => false; - - TypeMirror get upperBound { - if (_cachedUpperBound != null) return _cachedUpperBound; - return _cachedUpperBound = typeMirrorFromRuntimeTypeRepresentation( - owner, getMetadata(_typeVariable.bound)); - } - - bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError(); - bool isAssignableTo(TypeMirror other) => throw new UnimplementedError(); - - _asRuntimeType() => _metadataIndex; -} - -class JsTypeMirror extends JsDeclarationMirror implements TypeMirror { - JsTypeMirror(Symbol simpleName) - : super(simpleName); - - String get _prettyName => 'TypeMirror'; - - DeclarationMirror get owner => null; - - // TODO(ahe): Doesn't match the specification, see http://dartbug.com/11569. - bool get isTopLevel => true; - - // TODO(ahe): Implement these. - List get metadata => throw new UnimplementedError(); - - bool get hasReflectedType => false; - Type get reflectedType { - throw new UnsupportedError("This type does not support reflectedType"); - } - - List get typeVariables => const []; - List get typeArguments => const []; - - bool get isOriginalDeclaration => true; - TypeMirror get originalDeclaration => this; - - bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError(); - bool isAssignableTo(TypeMirror other) => throw new UnimplementedError(); - - _asRuntimeType() { - if (this == JsMirrorSystem._dynamicType) return null; - if (this == JsMirrorSystem._voidType) return null; - throw new RuntimeError('Should not call _asRuntimeType'); - } -} - -class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror - implements LibraryMirror { - final Uri _uri; - final List _classes; - final List _functions; - final List _metadata; - final String _compactFieldSpecification; - final bool _isRoot; - final _globalObject; - List _cachedFunctionMirrors; - List _cachedFields; - UnmodifiableMapView _cachedClasses; - UnmodifiableMapView _cachedFunctions; - UnmodifiableMapView _cachedGetters; - UnmodifiableMapView _cachedSetters; - UnmodifiableMapView _cachedVariables; - UnmodifiableMapView _cachedMembers; - UnmodifiableMapView _cachedDeclarations; - UnmodifiableListView _cachedMetadata; - - JsLibraryMirror(Symbol simpleName, - this._uri, - this._classes, - this._functions, - this._metadata, - this._compactFieldSpecification, - this._isRoot, - this._globalObject) - : super(simpleName) { - preserveLibraryNames(); - } - - String get _prettyName => 'LibraryMirror'; - - Uri get uri { - preserveUris(); - return _uri; - } - - Symbol get qualifiedName => simpleName; - - List get _methods => _functionMirrors; - - Map get __classes { - if (_cachedClasses != null) return _cachedClasses; - var result = new Map(); - for (String className in _classes) { - var cls = reflectClassByMangledName(className); - if (cls is ClassMirror) { - cls = cls.originalDeclaration; - } - if (cls is JsClassMirror) { - result[cls.simpleName] = cls; - cls._owner = this; - } else if (cls is JsTypedefMirror) { - result[cls.simpleName] = cls; - } - } - return _cachedClasses = - new UnmodifiableMapView(result); - } - - InstanceMirror setField(Symbol fieldName, Object arg) { - String name = n(fieldName); - if (name.endsWith('=')) throw new ArgumentError(''); - var mirror = __functions[s('$name=')]; - if (mirror == null) mirror = __variables[fieldName]; - if (mirror == null) { - throw new NoSuchStaticMethodError.method( - null, setterSymbol(fieldName), [arg], null); - } - mirror._setField(this, arg); - return reflect(arg); - } - - InstanceMirror getField(Symbol fieldName) { - JsMirror mirror = __members[fieldName]; - if (mirror == null) { - throw new NoSuchStaticMethodError.method(null, fieldName, [], null); - } - if (mirror is! MethodMirror) return reflect(mirror._getField(this)); - JsMethodMirror methodMirror = mirror; - if (methodMirror.isGetter) return reflect(mirror._getField(this)); - assert(methodMirror.isRegularMethod); - var getter = JS("", "#['\$getter']", methodMirror._jsFunction); - if (getter == null) throw new UnimplementedError(); - return reflect(JS("", "#()", getter)); - } - - InstanceMirror invoke(Symbol memberName, - List positionalArguments, - [Map namedArguments]) { - if (namedArguments != null && !namedArguments.isEmpty) { - throw new UnsupportedError('Named arguments are not implemented.'); - } - JsDeclarationMirror mirror = __members[memberName]; - - if (mirror is JsMethodMirror && !mirror.canInvokeReflectively()) { - throwInvalidReflectionError(n(memberName)); - } - if (mirror == null || mirror is JsMethodMirror && mirror.isSetter) { - throw new NoSuchStaticMethodError.method( - null, memberName, positionalArguments, namedArguments); - } - if (mirror is JsMethodMirror && !mirror.isGetter) { - return reflect(mirror._invoke(positionalArguments, namedArguments)); - } - return getField(memberName) - .invoke(#call, positionalArguments, namedArguments); - } - - _loadField(String name) { - // TODO(ahe): What about lazily initialized fields? See - // [JsClassMirror.getField]. - - // '$' (JS_CURRENT_ISOLATE()) stores state which is read directly, so we - // shouldn't use [_globalObject] here. - assert(JS('bool', '# in #', name, JS_CURRENT_ISOLATE())); - return JS('', '#[#]', JS_CURRENT_ISOLATE(), name); - } - - void _storeField(String name, Object arg) { - // '$' (JS_CURRENT_ISOLATE()) stores state which is stored directly, so we - // shouldn't use [_globalObject] here. - assert(JS('bool', '# in #', name, JS_CURRENT_ISOLATE())); - JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), name, arg); - } - - List get _functionMirrors { - if (_cachedFunctionMirrors != null) return _cachedFunctionMirrors; - var result = new List(); - for (int i = 0; i < _functions.length; i++) { - String name = _functions[i]; - var jsFunction = JS('', '#[#]', _globalObject, name); - String unmangledName = mangledGlobalNames[name]; - if (unmangledName == null || - JS('bool', "!!#['\$getterStub']", jsFunction)) { - // If there is no unmangledName, [jsFunction] is either a synthetic - // implementation detail, or something that is excluded - // by @MirrorsUsed. - // If it has a getterStub property it is a synthetic stub. - // TODO(floitsch): Remove the getterStub hack. - continue; - } - bool isConstructor = unmangledName.startsWith('new '); - bool isStatic = !isConstructor; // Top-level functions are static, but - // constructors are not. - if (isConstructor) { - unmangledName = unmangledName.substring(4).replaceAll(r'$', '.'); - } - JsMethodMirror mirror = - new JsMethodMirror.fromUnmangledName( - unmangledName, jsFunction, isStatic, isConstructor); - result.add(mirror); - mirror._owner = this; - } - return _cachedFunctionMirrors = result; - } - - List get _fields { - if (_cachedFields != null) return _cachedFields; - var result = []; - parseCompactFieldSpecification( - this, _compactFieldSpecification, true, result); - return _cachedFields = result; - } - - Map get __functions { - if (_cachedFunctions != null) return _cachedFunctions; - var result = new Map(); - for (JsMethodMirror mirror in _functionMirrors) { - if (!mirror.isConstructor) result[mirror.simpleName] = mirror; - } - return _cachedFunctions = - new UnmodifiableMapView(result); - } - - Map get __getters { - if (_cachedGetters != null) return _cachedGetters; - var result = new Map(); - // TODO(ahe): Implement this. - return _cachedGetters = - new UnmodifiableMapView(result); - } - - Map get __setters { - if (_cachedSetters != null) return _cachedSetters; - var result = new Map(); - // TODO(ahe): Implement this. - return _cachedSetters = - new UnmodifiableMapView(result); - } - - Map get __variables { - if (_cachedVariables != null) return _cachedVariables; - var result = new Map(); - for (JsVariableMirror mirror in _fields) { - result[mirror.simpleName] = mirror; - } - return _cachedVariables = - new UnmodifiableMapView(result); - } - - Map get __members { - if (_cachedMembers != null) return _cachedMembers; - Map result = new Map.from(__classes); - addToResult(Symbol key, Mirror value) { - result[key] = value; - } - __functions.forEach(addToResult); - __getters.forEach(addToResult); - __setters.forEach(addToResult); - __variables.forEach(addToResult); - return _cachedMembers = new UnmodifiableMapView(result); - } - - Map get declarations { - if (_cachedDeclarations != null) return _cachedDeclarations; - var result = new Map(); - addToResult(Symbol key, Mirror value) { - result[key] = value; - } - __members.forEach(addToResult); - return _cachedDeclarations = - new UnmodifiableMapView(result); - } - - List get metadata { - if (_cachedMetadata != null) return _cachedMetadata; - preserveMetadata(); - return _cachedMetadata = - new UnmodifiableListView(_metadata.map(reflect)); - } - - // TODO(ahe): Test this getter. - DeclarationMirror get owner => null; - - List get libraryDependencies - => throw new UnimplementedError(); -} - -String n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol); - -Symbol s(String name) { - if (name == null) return null; - return new _symbol_dev.Symbol.unvalidated(name); -} - -Symbol setterSymbol(Symbol symbol) => s("${n(symbol)}="); - -final JsMirrorSystem currentJsMirrorSystem = new JsMirrorSystem(); - -InstanceMirror reflect(Object reflectee) { - if (reflectee is Closure) { - return new JsClosureMirror(reflectee); - } else { - return new JsInstanceMirror(reflectee); - } -} - -TypeMirror reflectType(Type key) { - return reflectClassByMangledName(getMangledTypeName(key)); -} - -TypeMirror reflectClassByMangledName(String mangledName) { - String unmangledName = mangledGlobalNames[mangledName]; - if (mangledName == 'dynamic') return JsMirrorSystem._dynamicType; - if (mangledName == 'void') return JsMirrorSystem._voidType; - if (unmangledName == null) unmangledName = mangledName; - return reflectClassByName(s(unmangledName), mangledName); -} - -var classMirrors; - -TypeMirror reflectClassByName(Symbol symbol, String mangledName) { - if (classMirrors == null) classMirrors = JsCache.allocate(); - var mirror = JsCache.fetch(classMirrors, mangledName); - if (mirror != null) return mirror; - disableTreeShaking(); - int typeArgIndex = mangledName.indexOf("<"); - if (typeArgIndex != -1) { - TypeMirror originalDeclaration = - reflectClassByMangledName(mangledName.substring(0, typeArgIndex)) - .originalDeclaration; - if (originalDeclaration is JsTypedefMirror) { - throw new UnimplementedError(); - } - mirror = new JsTypeBoundClassMirror(originalDeclaration, - // Remove the angle brackets enclosing the type arguments. - mangledName.substring(typeArgIndex + 1, mangledName.length - 1)); - JsCache.update(classMirrors, mangledName, mirror); - return mirror; - } - var allClasses = JS_EMBEDDED_GLOBAL('', ALL_CLASSES); - var constructor = JS('var', '#[#]', allClasses, mangledName); - if (constructor == null) { - // Probably an intercepted class. - // TODO(ahe): How to handle intercepted classes? - throw new UnsupportedError('Cannot find class for: ${n(symbol)}'); - } - var descriptor = JS('', '#["@"]', constructor); - var fields; - var fieldsMetadata; - if (descriptor == null) { - // This is a native class, or an intercepted class. - // TODO(ahe): Preserve descriptor for such classes. - } else if (JS('bool', '# in #', - TYPEDEF_PREDICATE_PROPERTY_NAME, descriptor)) { - // Typedefs are represented as normal classes with two special properties: - // TYPEDEF_PREDICATE_PROPERTY_NAME and TYPEDEF_TYPE_PROPERTY_NAME. - // For example: - // MyTypedef: { - // "^": "Object;", - // $typedefType: 58, - // $$isTypedef: true - // } - // The typedefType is the index into the metadata table. - int index = JS('int', '#[#]', descriptor, TYPEDEF_TYPE_PROPERTY_NAME); - mirror = new JsTypedefMirror(symbol, mangledName, getMetadata(index)); - } else { - fields = JS('', '#[#]', descriptor, - JS_GET_NAME('CLASS_DESCRIPTOR_PROPERTY')); - if (fields is List) { - fieldsMetadata = fields.getRange(1, fields.length).toList(); - fields = fields[0]; - } - if (fields is! String) { - // TODO(ahe): This is CSP mode. Find a way to determine the - // fields of this class. - fields = ''; - } - } - - if (mirror == null) { - var superclassName = fields.split(';')[0]; - var mixins = superclassName.split('+'); - if (mixins.length > 1 && mangledGlobalNames[mangledName] == null) { - mirror = reflectMixinApplication(mixins, mangledName); - } else { - ClassMirror classMirror = new JsClassMirror( - symbol, mangledName, constructor, 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); - return mirror; -} - -Map filterMethods(List methods) { - var result = new Map(); - for (JsMethodMirror method in methods) { - if (!method.isConstructor && !method.isGetter && !method.isSetter) { - result[method.simpleName] = method; - } - } - return result; -} - -Map filterConstructors(methods) { - var result = new Map(); - for (JsMethodMirror method in methods) { - if (method.isConstructor) { - result[method.simpleName] = method; - } - } - return result; -} - -Map filterGetters(List methods, - Map fields) { - var result = new Map(); - for (JsMethodMirror method in methods) { - if (method.isGetter) { - - // TODO(ahe): This is a hack to remove getters corresponding to a field. - if (fields[method.simpleName] != null) continue; - - result[method.simpleName] = method; - } - } - return result; -} - -Map filterSetters(List methods, - Map fields) { - var result = new Map(); - for (JsMethodMirror method in methods) { - if (method.isSetter) { - - // TODO(ahe): This is a hack to remove setters corresponding to a field. - String name = n(method.simpleName); - name = name.substring(0, name.length - 1); // Remove '='. - if (fields[s(name)] != null) continue; - - result[method.simpleName] = method; - } - } - return result; -} - -Map filterMembers(List methods, - Map variables) { - Map result = new Map.from(variables); - for (JsMethodMirror method in methods) { - if (method.isSetter) { - String name = n(method.simpleName); - name = name.substring(0, name.length - 1); - // Filter-out setters corresponding to variables. - if (result[s(name)] is VariableMirror) continue; - } - // Constructors aren't 'members'. - if (method.isConstructor) continue; - // Filter out synthetic tear-off stubs - if (JS('bool', r'!!#.$getterStub', method._jsFunction)) continue; - // Use putIfAbsent to filter-out getters corresponding to variables. - result.putIfAbsent(method.simpleName, () => method); - } - return result; -} - -int counter = 0; - -ClassMirror reflectMixinApplication(mixinNames, String mangledName) { - disableTreeShaking(); - var mixins = []; - for (String mangledName in mixinNames) { - mixins.add(reflectClassByMangledName(mangledName)); - } - var it = mixins.iterator; - it.moveNext(); - var superclass = it.current; - while (it.moveNext()) { - superclass = new JsMixinApplication(superclass, it.current, mangledName); - } - return superclass; -} - -class JsMixinApplication extends JsTypeMirror with JsObjectMirror - implements ClassMirror { - final ClassMirror superclass; - final ClassMirror mixin; - Symbol _cachedSimpleName; - Map _cachedInstanceMembers; - - JsMixinApplication(ClassMirror superclass, ClassMirror mixin, - String mangledName) - : this.superclass = superclass, - this.mixin = mixin, - super(s(mangledName)); - - String get _prettyName => 'ClassMirror'; - - Symbol get simpleName { - if (_cachedSimpleName != null) return _cachedSimpleName; - String superName = n(superclass.qualifiedName); - return _cachedSimpleName = (superName.contains(' with ')) - ? s('$superName, ${n(mixin.qualifiedName)}') - : s('$superName with ${n(mixin.qualifiedName)}'); - } - - Symbol get qualifiedName => simpleName; - - // TODO(ahe): Remove this method, only here to silence warning. - get _mixin => mixin; - - Map get __members => _mixin.__members; - - Map get __methods => _mixin.__methods; - - Map get __getters => _mixin.__getters; - - Map get __setters => _mixin.__setters; - - Map get __variables => _mixin.__variables; - - Map get declarations => mixin.declarations; - - Map get instanceMembers { - if (_cachedInstanceMembers == null) { - var result = new Map(); - if (superclass != null) { - result.addAll(superclass.instanceMembers); - } - result.addAll(mixin.instanceMembers); - _cachedInstanceMembers = result; - } - return _cachedInstanceMembers; - } - - Map get staticMembers => mixin.staticMembers; - - _asRuntimeType() => null; - - InstanceMirror invoke( - Symbol memberName, - List positionalArguments, - [Map namedArguments]) { - throw new NoSuchStaticMethodError.method( - null, memberName, positionalArguments, namedArguments); - } - - InstanceMirror getField(Symbol fieldName) { - throw new NoSuchStaticMethodError.method(null, fieldName, null, null); - } - - InstanceMirror setField(Symbol fieldName, Object arg) { - throw new NoSuchStaticMethodError.method( - null, setterSymbol(fieldName), [arg], null); - } - - List get superinterfaces => [mixin]; - - Map get __constructors => _mixin.__constructors; - - InstanceMirror newInstance( - Symbol constructorName, - List positionalArguments, - [Map namedArguments]) { - throw new UnsupportedError( - "Can't instantiate mixin application '${n(qualifiedName)}'"); - } - - bool get isOriginalDeclaration => true; - - ClassMirror get originalDeclaration => this; - - // TODO(ahe): Implement this. - List get typeVariables { - throw new UnimplementedError(); - } - - List get typeArguments => const []; - - bool get isAbstract => throw new UnimplementedError(); - - bool isSubclassOf(ClassMirror other) { - superclass.isSubclassOf(other) || mixin.isSubclassOf(other); - } - - bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError(); - - bool isAssignableTo(TypeMirror other) => throw new UnimplementedError(); -} - -abstract class JsObjectMirror implements ObjectMirror { -} - -class JsInstanceMirror extends JsObjectMirror implements InstanceMirror { - final reflectee; - - JsInstanceMirror(this.reflectee); - - bool get hasReflectee => true; - - ClassMirror get type { - // The spec guarantees that `null` is the singleton instance of the `Null` - // class. - if (reflectee == null) return reflectClass(Null); - return reflectType(getRuntimeType(reflectee)); - } - - InstanceMirror invoke(Symbol memberName, - List positionalArguments, - [Map namedArguments]) { - if (namedArguments == null) namedArguments = const {}; - // We can safely pass positionalArguments to _invoke as it will wrap it in - // a JSArray if needed. - return _invoke(memberName, JSInvocationMirror.METHOD, - positionalArguments, namedArguments); - } - - InstanceMirror _invokeMethodWithNamedArguments( - String reflectiveName, - List positionalArguments, Map namedArguments) { - assert(namedArguments.isNotEmpty); - var interceptor = getInterceptor(reflectee); - - var jsFunction = JS('', '#[#]', interceptor, reflectiveName); - if (jsFunction == null) { - // TODO(ahe): Invoke noSuchMethod. - throw new UnimplementedNoSuchMethodError( - 'Invoking noSuchMethod with named arguments not implemented'); - } - ReflectionInfo info = new ReflectionInfo(jsFunction); - if (jsFunction == null) { - // TODO(ahe): Invoke noSuchMethod. - throw new UnimplementedNoSuchMethodError( - 'Invoking noSuchMethod with named arguments not implemented'); - } - - positionalArguments = new List.from(positionalArguments); - // Check the number of positional arguments is valid. - if (info.requiredParameterCount != positionalArguments.length) { - // TODO(ahe): Invoke noSuchMethod. - throw new UnimplementedNoSuchMethodError( - 'Invoking noSuchMethod with named arguments not implemented'); - } - var defaultArguments = new Map(); - for (int i = 0; i < info.optionalParameterCount; i++) { - var parameterName = info.parameterName(i + info.requiredParameterCount); - var defaultValue = - getMetadata(info.defaultValue(i + info.requiredParameterCount)); - defaultArguments[parameterName] = defaultValue; - } - namedArguments.forEach((Symbol symbol, value) { - String parameter = n(symbol); - if (defaultArguments.containsKey(parameter)) { - defaultArguments[parameter] = value; - } else { - // Extraneous named argument. - // TODO(ahe): Invoke noSuchMethod. - throw new UnimplementedNoSuchMethodError( - 'Invoking noSuchMethod with named arguments not implemented'); - } - }); - positionalArguments.addAll(defaultArguments.values); - // TODO(ahe): Handle intercepted methods. - return reflect( - JS('', '#.apply(#, #)', jsFunction, reflectee, positionalArguments)); - } - - /// Grabs hold of the class-specific invocation cache for the reflectee. - /// All reflectees with the same class share the same cache. The cache - /// maps reflective names to cached invocation objects with enough decoded - /// reflective information to know how to to invoke a specific member. - get _classInvocationCache { - String cacheName = Primitives.mirrorInvokeCacheName; - var cacheHolder = (reflectee == null) ? getInterceptor(null) : reflectee; - var cache = JS('', r'#.constructor[#]', cacheHolder, cacheName); - if (cache == null) { - cache = JsCache.allocate(); - JS('void', r'#.constructor[#] = #', cacheHolder, cacheName, cache); - } - return cache; - } - - String _computeReflectiveName(Symbol symbolName, int type, - List positionalArguments, - Map namedArguments) { - String name = n(symbolName); - switch (type) { - case JSInvocationMirror.GETTER: return name; - case JSInvocationMirror.SETTER: return '$name='; - case JSInvocationMirror.METHOD: - if (namedArguments.isNotEmpty) return '$name*'; - int nbArgs = positionalArguments.length as int; - return "$name:$nbArgs:0"; - } - throw new RuntimeError("Could not compute reflective name for $name"); - } - - /** - * Returns a `CachedInvocation` or `CachedNoSuchMethodInvocation` for the - * given member. - * - * Caches the result. - */ - _getCachedInvocation(Symbol name, int type, String reflectiveName, - List positionalArguments, Map namedArguments) { - - var cache = _classInvocationCache; - var cacheEntry = JsCache.fetch(cache, reflectiveName); - var result; - if (cacheEntry == null) { - disableTreeShaking(); - String mangledName = reflectiveNames[reflectiveName]; - List argumentNames = const []; - - // TODO(ahe): We don't need to create an invocation mirror here. The - // logic from JSInvocationMirror.getCachedInvocation could easily be - // inlined here. - Invocation invocation = createUnmangledInvocationMirror( - name, mangledName, type, positionalArguments, argumentNames); - - cacheEntry = - JSInvocationMirror.getCachedInvocation(invocation, reflectee); - JsCache.update(cache, reflectiveName, cacheEntry); - } - return cacheEntry; - } - - bool _isReflectable(CachedInvocation cachedInvocation) { - // TODO(floitsch): tear-off closure does not guarantee that the - // function is reflectable. - var method = cachedInvocation.jsFunction; - return hasReflectableProperty(method) || reflectee is TearOffClosure; - } - - /// Invoke the member specified through name and type on the reflectee. - /// As a side-effect, this populates the class-specific invocation cache - /// for the reflectee. - InstanceMirror _invoke(Symbol name, - int type, - List positionalArguments, - Map namedArguments) { - String reflectiveName = - _computeReflectiveName(name, type, positionalArguments, namedArguments); - - if (namedArguments.isNotEmpty) { - // TODO(floitsch): first, make sure it's not a getter. - return _invokeMethodWithNamedArguments( - reflectiveName, positionalArguments, namedArguments); - } - var cacheEntry = _getCachedInvocation( - name, type, reflectiveName, positionalArguments, namedArguments); - - if (cacheEntry.isNoSuchMethod || !_isReflectable(cacheEntry)) { - // Could be that we want to invoke a getter, or get a method. - if (type == JSInvocationMirror.METHOD && _instanceFieldExists(name)) { - return getField(name).invoke( - #call, positionalArguments, namedArguments); - } - - if (type == JSInvocationMirror.SETTER) { - // For setters we report the setter name "field=". - name = s("${n(name)}="); - } - - if (!cacheEntry.isNoSuchMethod) { - // Not reflectable. - throwInvalidReflectionError(reflectiveName); - } - - String mangledName = reflectiveNames[reflectiveName]; - // TODO(ahe): Get the argument names. - List argumentNames = []; - Invocation invocation = createUnmangledInvocationMirror( - name, mangledName, type, positionalArguments, argumentNames); - return reflect(cacheEntry.invokeOn(reflectee, invocation)); - } else { - return reflect(cacheEntry.invokeOn(reflectee, positionalArguments)); - } - } - - InstanceMirror setField(Symbol fieldName, Object arg) { - _invoke(fieldName, JSInvocationMirror.SETTER, [arg], const {}); - return reflect(arg); - } - - // JS helpers for getField optimizations. - static bool isUndefined(x) - => JS('bool', 'typeof # == "undefined"', x); - static bool isMissingCache(x) - => JS('bool', 'typeof # == "number"', x); - static bool isMissingProbe(Symbol symbol) - => JS('bool', 'typeof #.\$p == "undefined"', symbol); - static bool isEvalAllowed() - => JS('bool', 'typeof dart_precompiled != "function"'); - - - /// The getter cache is lazily allocated after a couple - /// of invocations of [InstanceMirror.getField]. The delay is - /// used to avoid too aggressive caching and dynamic function - /// generation for rarely used mirrors. The cache is specific to - /// this [InstanceMirror] and maps reflective names to functions - /// that will invoke the corresponding getter on the reflectee. - /// The reflectee is passed to the function as the first argument - /// to avoid the overhead of fetching it from this mirror repeatedly. - /// The cache is lazily initialized to a JS object so we can - /// benefit from "map transitions" in the underlying JavaScript - /// engine to speed up cache probing. - var _getterCache = 4; - - bool _instanceFieldExists(Symbol name) { - int getterType = JSInvocationMirror.GETTER; - String getterName = - _computeReflectiveName(name, getterType, const [], const {}); - var getterCacheEntry = _getCachedInvocation( - name, getterType, getterName, const [], const {}); - return !getterCacheEntry.isNoSuchMethod && !getterCacheEntry.isGetterStub; - } - - InstanceMirror getField(Symbol fieldName) { - FASTPATH: { - var cache = _getterCache; - if (isMissingCache(cache) || isMissingProbe(fieldName)) break FASTPATH; - // If the [fieldName] has an associated probe function, we can use - // it to read from the getter cache specific to this [InstanceMirror]. - var getter = JS('', '#.\$p(#)', fieldName, cache); - if (isUndefined(getter)) break FASTPATH; - // Call the getter passing the reflectee as the first argument. - var value = JS('', '#(#)', getter, reflectee); - // The getter has an associate cache of the last [InstanceMirror] - // returned to avoid repeated invocations of [reflect]. To validate - // the cache, we check that the value returned by the getter is the - // same value as last time. - if (JS('bool', '# === #.v', value, getter)) { - return JS('InstanceMirror', '#.m', getter); - } else { - var result = reflect(value); - JS('void', '#.v = #', getter, value); - JS('void', '#.m = #', getter, result); - return result; - } - } - return _getFieldSlow(fieldName); - } - - InstanceMirror _getFieldSlow(Symbol fieldName) { - // First do the slow-case getter invocation. As a side-effect of this, - // the invocation cache is filled in so we can query it afterwards. - var result = - _invoke(fieldName, JSInvocationMirror.GETTER, const [], const {}); - String name = n(fieldName); - var cacheEntry = JsCache.fetch(_classInvocationCache, name); - if (cacheEntry.isNoSuchMethod) { - return result; - } - - // Make sure we have a getter cache in this [InstanceMirror]. - var cache = _getterCache; - if (isMissingCache(cache)) { - if ((_getterCache = --cache) != 0) return result; - cache = _getterCache = JS('=Object', 'Object.create(null)'); - } - - // Make sure that symbol [fieldName] has a cache probing function ($p). - bool useEval = isEvalAllowed(); - if (isMissingProbe(fieldName)) { - var probe = _newProbeFn(name, useEval); - JS('void', '#.\$p = #', fieldName, probe); - } - - // Create a new getter function and install it in the cache. - var mangledName = cacheEntry.mangledName; - var getter = (cacheEntry.isIntercepted) - ? _newInterceptedGetterFn(mangledName, useEval) - : _newGetterFn(mangledName, useEval); - JS('void', '#[#] = #', cache, name, getter); - - // Initialize the last value (v) and last mirror (m) on the - // newly generated getter to be a sentinel value that is hard - // to get hold of through user code. - JS('void', '#.v = #.m = #', getter, getter, cache); - - // Return the result of the slow-path getter invocation. - return result; - } - - _newProbeFn(String id, bool useEval) { - if (useEval) { - // We give the probe function a name to make it appear nicely in - // profiles and when debugging. The name also makes the source code - // for the function more "unique" so the underlying JavaScript - // engine is less likely to re-use an existing piece of generated - // code as the result of calling eval. In return, this leads to - // less polymorphic access in the probe function. - var body = "(function probe\$$id(c){return c.$id})"; - return JS('', '(function(b){return eval(b)})(#)', body); - } else { - return JS('', '(function(n){return(function(c){return c[n]})})(#)', id); - } - } - - _newGetterFn(String name, bool useEval) { - if (!useEval) return _newGetterNoEvalFn(name); - // We give the getter function a name that associates it with the - // class of the reflectee. This makes it easier to spot in profiles - // and when debugging, but it also means that the underlying JavaScript - // engine will only share the generated code for accessors on the - // same class (through caching of eval'ed code). This makes the - // generated call to the getter - e.g. o.get$foo() - much more likely - // to be monomorphic and inlineable. - String className = JS('String', '#.constructor.name', reflectee); - var body = "(function $className\$$name(o){return o.$name()})"; - return JS('', '(function(b){return eval(b)})(#)', body); - } - - _newGetterNoEvalFn(n) => JS('', - '(function(n){return(function(o){return o[n]()})})(#)', n); - - _newInterceptedGetterFn(String name, bool useEval) { - var object = reflectee; - // It is possible that the interceptor for a given object is the object - // itself, so it is important not to share the code that captures the - // interceptor between multiple different instances of [InstanceMirror]. - var interceptor = getInterceptor(object); - if (!useEval) return _newInterceptGetterNoEvalFn(name, interceptor); - String className = JS('String', '#.constructor.name', interceptor); - String functionName = '$className\$$name'; - var body = - '(function(i) {' - ' function $functionName(o){return i.$name(o)}' - ' return $functionName;' - '})'; - return JS('', '(function(b){return eval(b)})(#)(#)', body, interceptor); - } - - _newInterceptGetterNoEvalFn(n, i) => JS('', - '(function(n,i){return(function(o){return i[n](o)})})(#,#)', n, i); - - delegate(Invocation invocation) { - return JSInvocationMirror.invokeFromMirror(invocation, reflectee); - } - - operator ==(other) { - return other is JsInstanceMirror && - identical(reflectee, other.reflectee); - } - - int get hashCode { - // Avoid hash collisions with the reflectee. This constant is in Smi range - // and happens to be the inner padding from RFC 2104. - return identityHashCode(reflectee) ^ 0x36363636; - } - - String toString() => 'InstanceMirror on ${Error.safeToString(reflectee)}'; - - // TODO(ahe): Remove this method from the API. - MirrorSystem get mirrors => currentJsMirrorSystem; -} - -/** - * ClassMirror for generic classes where the type parameters are bound. - * - * [typeArguments] will return a list of the type arguments, in constrast - * to JsCLassMirror that returns an empty list since it represents original - * declarations and classes that are not generic. - */ -class JsTypeBoundClassMirror extends JsDeclarationMirror - implements ClassMirror { - final JsClassMirror _class; - - /** - * When instantiated this field will hold a string representing the list of - * type arguments for the class, i.e. what is inside the outermost angle - * brackets. Then, when get typeArguments is called the first time, the string - * is parsed into the actual list of TypeMirrors, and stored in - * [_cachedTypeArguments]. Due to type substitution of, for instance, - * superclasses the mangled name of the class and hence this string is needed - * after [_cachedTypeArguments] has been computed. - * - * If an integer is encountered as a type argument, it represents the type - * variable at the corresponding entry in [emitter.globalMetadata]. - */ - String _typeArguments; - - UnmodifiableListView _cachedTypeArguments; - UnmodifiableMapView _cachedDeclarations; - UnmodifiableMapView _cachedMembers; - UnmodifiableMapView _cachedConstructors; - Map _cachedVariables; - Map _cachedGetters; - Map _cachedSetters; - Map _cachedMethodsMap; - List _cachedMethods; - ClassMirror _superclass; - List _cachedSuperinterfaces; - Map _cachedInstanceMembers; - Map _cachedStaticMembers; - - JsTypeBoundClassMirror(JsClassMirror originalDeclaration, this._typeArguments) - : _class = originalDeclaration, - super(originalDeclaration.simpleName); - - String get _prettyName => 'ClassMirror'; - - String toString() { - String result = '$_prettyName on ${n(simpleName)}'; - if (typeArguments != null) { - result = "$result<${typeArguments.join(', ')}>"; - } - return result; - } - - String get _mangledName { - for (TypeMirror typeArgument in typeArguments) { - if (typeArgument != JsMirrorSystem._dynamicType) { - return '${_class._mangledName}<$_typeArguments>'; - } - } - // When all type arguments are dynamic, the canonical representation is to - // drop them. - return _class._mangledName; - } - - List get typeVariables => _class.typeVariables; - - List get typeArguments { - if (_cachedTypeArguments != null) return _cachedTypeArguments; - List result = new List(); - - addTypeArgument(String typeArgument) { - int parsedIndex = int.parse(typeArgument, onError: (_) => -1); - if (parsedIndex == -1) { - result.add(reflectClassByMangledName(typeArgument.trim())); - } else { - TypeVariable typeVariable = getMetadata(parsedIndex); - TypeMirror owner = reflectClass(typeVariable.owner); - TypeVariableMirror typeMirror = - new JsTypeVariableMirror(typeVariable, owner, parsedIndex); - result.add(typeMirror); - } - } - - if (_typeArguments.indexOf('<') == -1) { - _typeArguments.split(',').forEach((t) => addTypeArgument(t)); - } else { - int level = 0; - String currentTypeArgument = ''; - - for (int i = 0; i < _typeArguments.length; i++) { - var character = _typeArguments[i]; - if (character == ' ') { - continue; - } else if (character == '<') { - currentTypeArgument += character; - level++; - } else if (character == '>') { - currentTypeArgument += character; - level--; - } else if (character == ',') { - if (level > 0) { - currentTypeArgument += character; - } else { - addTypeArgument(currentTypeArgument); - currentTypeArgument = ''; - } - } else { - currentTypeArgument += character; - } - } - addTypeArgument(currentTypeArgument); - } - return _cachedTypeArguments = new UnmodifiableListView(result); - } - - List get _methods { - if (_cachedMethods != null) return _cachedMethods; - return _cachedMethods =_class._getMethodsWithOwner(this); - } - - Map get __methods { - if (_cachedMethodsMap != null) return _cachedMethodsMap; - return _cachedMethodsMap = new UnmodifiableMapView( - filterMethods(_methods)); - } - - Map get __constructors { - if (_cachedConstructors != null) return _cachedConstructors; - return _cachedConstructors = - new UnmodifiableMapView( - filterConstructors(_methods)); - } - - Map get __getters { - if (_cachedGetters != null) return _cachedGetters; - return _cachedGetters = new UnmodifiableMapView( - filterGetters(_methods, __variables)); - } - - Map get __setters { - if (_cachedSetters != null) return _cachedSetters; - return _cachedSetters = new UnmodifiableMapView( - filterSetters(_methods, __variables)); - } - - Map get __variables { - if (_cachedVariables != null) return _cachedVariables; - var result = new Map(); - for (JsVariableMirror mirror in _class._getFieldsWithOwner(this)) { - result[mirror.simpleName] = mirror; - } - return _cachedVariables = - new UnmodifiableMapView(result); - } - - Map get __members { - if (_cachedMembers != null) return _cachedMembers; - return _cachedMembers = new UnmodifiableMapView( - filterMembers(_methods, __variables)); - } - - Map get declarations { - if (_cachedDeclarations != null) return _cachedDeclarations; - Map result = - new Map(); - result.addAll(__members); - result.addAll(__constructors); - typeVariables.forEach((tv) => result[tv.simpleName] = tv); - return _cachedDeclarations = - new UnmodifiableMapView(result); - } - - Map get staticMembers { - if (_cachedStaticMembers == null) { - var result = new Map(); - declarations.values.forEach((decl) { - if (decl is MethodMirror && decl.isStatic && !decl.isConstructor) { - result[decl.simpleName] = decl; - } - if (decl is VariableMirror && decl.isStatic) { - var getterName = decl.simpleName; - result[getterName] = new JsSyntheticAccessor( - this, getterName, true, true, false, decl); - if (!decl.isFinal) { - var setterName = setterSymbol(decl.simpleName); - result[setterName] = new JsSyntheticAccessor( - this, setterName, false, true, false, decl); - } - } - }); - _cachedStaticMembers = result; - } - return _cachedStaticMembers; - } - - Map get instanceMembers { - if (_cachedInstanceMembers == null) { - var result = new Map(); - if (superclass != null) { - result.addAll(superclass.instanceMembers); - } - declarations.values.forEach((decl) { - if (decl is MethodMirror && !decl.isStatic && - !decl.isConstructor && !decl.isAbstract) { - result[decl.simpleName] = decl; - } - if (decl is VariableMirror && !decl.isStatic) { - var getterName = decl.simpleName; - result[getterName] = new JsSyntheticAccessor( - this, getterName, true, false, false, decl); - if (!decl.isFinal) { - var setterName = setterSymbol(decl.simpleName); - result[setterName] = new JsSyntheticAccessor( - this, setterName, false, false, false, decl); - } - } - }); - _cachedInstanceMembers = result; - } - return _cachedInstanceMembers; - } - - InstanceMirror setField(Symbol fieldName, Object arg) { - return _class.setField(fieldName, arg); - } - - InstanceMirror getField(Symbol fieldName) => _class.getField(fieldName); - - InstanceMirror newInstance(Symbol constructorName, - List positionalArguments, - [Map namedArguments]) { - var instance = _class._getInvokedInstance(constructorName, - positionalArguments, - namedArguments); - return reflect(setRuntimeTypeInfo( - instance, typeArguments.map((t) => t._asRuntimeType()).toList())); - } - - _asRuntimeType() { - return [_class._jsConstructor].addAll( - typeArguments.map((t) => t._asRuntimeType())); - } - - JsLibraryMirror get owner => _class.owner; - - List get metadata => _class.metadata; - - ClassMirror get superclass { - if (_superclass != null) return _superclass; - - var typeInformationContainer = JS_EMBEDDED_GLOBAL('', TYPE_INFORMATION); - List typeInformation = - JS('List|Null', '#[#]', typeInformationContainer, _class._mangledName); - assert(typeInformation != null); - var type = getMetadata(typeInformation[0]); - return _superclass = typeMirrorFromRuntimeTypeRepresentation(this, type); - } - - InstanceMirror invoke(Symbol memberName, - List positionalArguments, - [Map namedArguments]) { - return _class.invoke(memberName, positionalArguments, namedArguments); - } - - bool get isOriginalDeclaration => false; - - ClassMirror get originalDeclaration => _class; - - List get superinterfaces { - if (_cachedSuperinterfaces != null) return _cachedSuperinterfaces; - return _cachedSuperinterfaces = _class._getSuperinterfacesWithOwner(this); - } - - bool get isPrivate => _class.isPrivate; - - bool get isTopLevel => _class.isTopLevel; - - bool get isAbstract => _class.isAbstract; - - bool isSubclassOf(ClassMirror other) => _class.isSubclassOf(other); - - SourceLocation get location => _class.location; - - MirrorSystem get mirrors => _class.mirrors; - - Symbol get qualifiedName => _class.qualifiedName; - - bool get hasReflectedType => true; - - Type get reflectedType => createRuntimeType(_mangledName); - - Symbol get simpleName => _class.simpleName; - - // TODO(ahe): Implement this. - ClassMirror get mixin => throw new UnimplementedError(); - - bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError(); - - bool isAssignableTo(TypeMirror other) => throw new UnimplementedError(); -} - -class JsSyntheticAccessor implements MethodMirror { - final DeclarationMirror owner; - final Symbol simpleName; - final bool isGetter; - final bool isStatic; - final bool isTopLevel; - final _target; /// The field or type that introduces the synthetic accessor. - - JsSyntheticAccessor(this.owner, - this.simpleName, - this.isGetter, - this.isStatic, - this.isTopLevel, - this._target); - - bool get isSynthetic => true; - bool get isRegularMethod => false; - bool get isOperator => false; - bool get isConstructor => false; - bool get isConstConstructor => false; - bool get isGenerativeConstructor => false; - bool get isFactoryConstructor => false; - bool get isRedirectingConstructor => false; - bool get isAbstract => false; - - bool get isSetter => !isGetter; - bool get isPrivate => n(simpleName).startsWith('_'); - - Symbol get qualifiedName => computeQualifiedName(owner, simpleName); - Symbol get constructorName => const Symbol(''); - - TypeMirror get returnType => _target.type; - List get parameters { - if (isGetter) return const []; - return new UnmodifiableListView( - [new JsSyntheticSetterParameter(this, this._target)]); - } - - List get metadata => const []; - String get source => null; - SourceLocation get location => throw new UnimplementedError(); -} - -class JsSyntheticSetterParameter implements ParameterMirror { - final DeclarationMirror owner; - final VariableMirror _target; - - JsSyntheticSetterParameter(this.owner, this._target); - - Symbol get simpleName => _target.simpleName; - Symbol get qualifiedName => computeQualifiedName(owner, simpleName); - TypeMirror get type => _target.type; - - bool get isOptional => false; - bool get isNamed => false; - bool get isStatic => false; - bool get isTopLevel => false; - bool get isConst => false; - bool get isFinal => true; - bool get isPrivate => false; - bool get hasDefaultValue => false; - InstanceMirror get defaultValue => null; - List get metadata => const []; - SourceLocation get location => throw new UnimplementedError(); -} - -class JsClassMirror extends JsTypeMirror with JsObjectMirror - implements ClassMirror { - final String _mangledName; - final _jsConstructor; - final String _fieldsDescriptor; - final List _fieldsMetadata; - final _jsConstructorCache = JsCache.allocate(); - List _metadata; - ClassMirror _superclass; - List _cachedMethods; - List _cachedFields; - UnmodifiableMapView _cachedConstructors; - UnmodifiableMapView _cachedMethodsMap; - UnmodifiableMapView _cachedGetters; - UnmodifiableMapView _cachedSetters; - UnmodifiableMapView _cachedVariables; - UnmodifiableMapView _cachedMembers; - UnmodifiableMapView _cachedDeclarations; - UnmodifiableListView _cachedMetadata; - UnmodifiableListView _cachedSuperinterfaces; - UnmodifiableListView _cachedTypeVariables; - Map _cachedInstanceMembers; - Map _cachedStaticMembers; - - // Set as side-effect of accessing JsLibraryMirror.classes. - JsLibraryMirror _owner; - - JsClassMirror(Symbol simpleName, - this._mangledName, - this._jsConstructor, - this._fieldsDescriptor, - this._fieldsMetadata) - : super(simpleName); - - String get _prettyName => 'ClassMirror'; - - Map get __constructors { - if (_cachedConstructors != null) return _cachedConstructors; - return _cachedConstructors = - new UnmodifiableMapView( - filterConstructors(_methods)); - } - - _asRuntimeType() { - if (typeVariables.isEmpty) return _jsConstructor; - var type = [_jsConstructor]; - for (int i = 0; i < typeVariables.length; i ++) { - type.add(JsMirrorSystem._dynamicType._asRuntimeType); - } - return type; - } - - List _getMethodsWithOwner(DeclarationMirror methodOwner) { - var prototype = JS('', '#.prototype', _jsConstructor); - List keys = extractKeys(prototype); - var result = []; - for (String key in keys) { - if (isReflectiveDataInPrototype(key)) continue; - String simpleName = mangledNames[key]; - // [simpleName] can be null if [key] represents an implementation - // detail, for example, a bailout method, or runtime type support. - // It might also be null if the user has limited what is reified for - // reflection with metadata. - if (simpleName == null) continue; - var function = JS('', '#[#]', prototype, key); - if (isNoSuchMethodStub(function)) continue; - if (isAliasedSuperMethod(function, key)) continue; - var mirror = - new JsMethodMirror.fromUnmangledName( - simpleName, function, false, false); - result.add(mirror); - mirror._owner = methodOwner; - } - - var statics = JS_EMBEDDED_GLOBAL('', STATICS); - keys = extractKeys(JS('', '#[#]', statics, _mangledName)); - for (String mangledName in keys) { - if (isReflectiveDataInPrototype(mangledName)) continue; - String unmangledName = mangledName; - var jsFunction = JS('', '#[#]', owner._globalObject, mangledName); - - bool isConstructor = false; - if (hasReflectableProperty(jsFunction)) { - String reflectionName = - JS('String|Null', r'#.$reflectionName', jsFunction); - if (reflectionName == null) continue; - isConstructor = reflectionName.startsWith('new '); - if (isConstructor) { - reflectionName = reflectionName.substring(4).replaceAll(r'$', '.'); - } - unmangledName = reflectionName; - } else { - continue; - } - bool isStatic = !isConstructor; // Constructors are not static. - JsMethodMirror mirror = - new JsMethodMirror.fromUnmangledName( - unmangledName, jsFunction, isStatic, isConstructor); - result.add(mirror); - mirror._owner = methodOwner; - } - - return result; - } - - List get _methods { - if (_cachedMethods != null) return _cachedMethods; - return _cachedMethods = _getMethodsWithOwner(this); - } - - List _getFieldsWithOwner(DeclarationMirror fieldOwner) { - var result = []; - - var instanceFieldSpecfication = _fieldsDescriptor.split(';')[1]; - if (_fieldsMetadata != null) { - instanceFieldSpecfication = - [instanceFieldSpecfication]..addAll(_fieldsMetadata); - } - parseCompactFieldSpecification( - fieldOwner, instanceFieldSpecfication, false, result); - - var statics = JS_EMBEDDED_GLOBAL('', STATICS); - var staticDescriptor = JS('', '#[#]', statics, _mangledName); - if (staticDescriptor != null) { - parseCompactFieldSpecification( - fieldOwner, - JS('', '#[#]', - staticDescriptor, JS_GET_NAME('CLASS_DESCRIPTOR_PROPERTY')), - true, result); - } - return result; - } - - List get _fields { - if (_cachedFields != null) return _cachedFields; - return _cachedFields = _getFieldsWithOwner(this); - } - - Map get __methods { - if (_cachedMethodsMap != null) return _cachedMethodsMap; - return _cachedMethodsMap = - new UnmodifiableMapView(filterMethods(_methods)); - } - - Map get __getters { - if (_cachedGetters != null) return _cachedGetters; - return _cachedGetters = new UnmodifiableMapView( - filterGetters(_methods, __variables)); - } - - Map get __setters { - if (_cachedSetters != null) return _cachedSetters; - return _cachedSetters = new UnmodifiableMapView( - filterSetters(_methods, __variables)); - } - - Map get __variables { - if (_cachedVariables != null) return _cachedVariables; - var result = new Map(); - for (JsVariableMirror mirror in _fields) { - result[mirror.simpleName] = mirror; - } - return _cachedVariables = - new UnmodifiableMapView(result); - } - - Map get __members { - if (_cachedMembers != null) return _cachedMembers; - return _cachedMembers = new UnmodifiableMapView( - filterMembers(_methods, __variables)); - } - - Map get declarations { - if (_cachedDeclarations != null) return _cachedDeclarations; - var result = new Map(); - addToResult(Symbol key, Mirror value) { - result[key] = value; - } - __members.forEach(addToResult); - __constructors.forEach(addToResult); - typeVariables.forEach((tv) => result[tv.simpleName] = tv); - return _cachedDeclarations = - new UnmodifiableMapView(result); - } - - Map get staticMembers { - if (_cachedStaticMembers == null) { - var result = new Map(); - declarations.values.forEach((decl) { - if (decl is MethodMirror && decl.isStatic && !decl.isConstructor) { - result[decl.simpleName] = decl; - } - if (decl is VariableMirror && decl.isStatic) { - var getterName = decl.simpleName; - result[getterName] = new JsSyntheticAccessor( - this, getterName, true, true, false, decl); - if (!decl.isFinal) { - var setterName = setterSymbol(decl.simpleName); - result[setterName] = new JsSyntheticAccessor( - this, setterName, false, true, false, decl); - } - } - }); - _cachedStaticMembers = result; - } - return _cachedStaticMembers; - } - - Map get instanceMembers { - if (_cachedInstanceMembers == null) { - var result = new Map(); - if (superclass != null) { - result.addAll(superclass.instanceMembers); - } - declarations.values.forEach((decl) { - if (decl is MethodMirror && !decl.isStatic && - !decl.isConstructor && !decl.isAbstract) { - result[decl.simpleName] = decl; - } - if (decl is VariableMirror && !decl.isStatic) { - var getterName = decl.simpleName; - result[getterName] = new JsSyntheticAccessor( - this, getterName, true, false, false, decl); - if (!decl.isFinal) { - var setterName = setterSymbol(decl.simpleName); - result[setterName] = new JsSyntheticAccessor( - this, setterName, false, false, false, decl); - } - } - }); - _cachedInstanceMembers = result; - } - return _cachedInstanceMembers; - } - - InstanceMirror setField(Symbol fieldName, Object arg) { - JsVariableMirror mirror = __variables[fieldName]; - if (mirror != null && mirror.isStatic && !mirror.isFinal) { - // '$' (JS_CURRENT_ISOLATE()) stores state which is stored directly, so - // we shouldn't use [JsLibraryMirror._globalObject] here. - String jsName = mirror._jsName; - if (!JS('bool', '# in #', jsName, JS_CURRENT_ISOLATE())) { - throw new RuntimeError('Cannot find "$jsName" in current isolate.'); - } - JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), jsName, arg); - return reflect(arg); - } - Symbol setterName = setterSymbol(fieldName); - if (mirror == null) { - JsMethodMirror setter = __setters[setterName]; - if (setter != null) { - setter._invoke([arg], const {}); - return reflect(arg); - } - } - throw new NoSuchStaticMethodError.method(null, setterName, [arg], null); - } - - bool _staticFieldExists(Symbol fieldName) { - JsVariableMirror mirror = __variables[fieldName]; - if (mirror != null) return mirror.isStatic; - JsMethodMirror getter = __getters[fieldName]; - return getter != null && getter.isStatic; - } - - InstanceMirror getField(Symbol fieldName) { - JsVariableMirror mirror = __variables[fieldName]; - if (mirror != null && mirror.isStatic) { - String jsName = mirror._jsName; - // '$' (JS_CURRENT_ISOLATE()) stores state which is read directly, so - // we shouldn't use [JsLibraryMirror._globalObject] here. - if (!JS('bool', '# in #', jsName, JS_CURRENT_ISOLATE())) { - throw new RuntimeError('Cannot find "$jsName" in current isolate.'); - } - var lazies = JS_EMBEDDED_GLOBAL('', LAZIES); - if (JS('bool', '# in #', jsName, lazies)) { - String getterName = JS('String', '#[#]', lazies, jsName); - return reflect(JS('', '#[#]()', JS_CURRENT_ISOLATE(), getterName)); - } else { - return reflect(JS('', '#[#]', JS_CURRENT_ISOLATE(), jsName)); - } - } - JsMethodMirror getter = __getters[fieldName]; - if (getter != null && getter.isStatic) { - return reflect(getter._invoke(const [], const {})); - } - // If the fieldName designates a static function we have to return - // its closure. - JsMethodMirror method = __methods[fieldName]; - if (method != null && method.isStatic) { - // We invoke the same getter that Dart code would execute. During - // initialization we have stored that getter on the function (so that - // we can find it more easily here). - var getter = JS("", "#['\$getter']", method._jsFunction); - if (getter == null) throw new UnimplementedError(); - return reflect(JS("", "#()", getter)); - } - throw new NoSuchStaticMethodError.method(null, fieldName, null, null); - } - - _getInvokedInstance(Symbol constructorName, - List positionalArguments, - [Map namedArguments]) { - if (namedArguments != null && !namedArguments.isEmpty) { - throw new UnsupportedError('Named arguments are not implemented.'); - } - JsMethodMirror mirror = - JsCache.fetch(_jsConstructorCache, n(constructorName)); - if (mirror == null) { - mirror = __constructors.values.firstWhere( - (m) => m.constructorName == constructorName, - orElse: () { - throw new NoSuchStaticMethodError.method( - null, constructorName, positionalArguments, namedArguments); - }); - JsCache.update(_jsConstructorCache, n(constructorName), mirror); - } - return mirror._invoke(positionalArguments, namedArguments); - } - - InstanceMirror newInstance(Symbol constructorName, - List positionalArguments, - [Map namedArguments]) { - return reflect(_getInvokedInstance(constructorName, - positionalArguments, - namedArguments)); - } - - JsLibraryMirror get owner { - if (_owner == null) { - for (var list in JsMirrorSystem.librariesByName.values) { - for (JsLibraryMirror library in list) { - // This will set _owner field on all classes as a side - // effect. This gives us a fast path to reflect on a - // class without parsing reflection data. - library.__classes; - } - } - if (_owner == null) { - throw new StateError('Class "${n(simpleName)}" has no owner'); - } - } - return _owner; - } - - List get metadata { - if (_cachedMetadata != null) return _cachedMetadata; - if (_metadata == null) { - _metadata = extractMetadata(JS('', '#.prototype', _jsConstructor)); - } - return _cachedMetadata = - new UnmodifiableListView(_metadata.map(reflect)); - } - - ClassMirror get superclass { - if (_superclass == null) { - var typeInformationContainer = JS_EMBEDDED_GLOBAL('', TYPE_INFORMATION); - List typeInformation = - JS('List|Null', '#[#]', typeInformationContainer, _mangledName); - if (typeInformation != null) { - var type = getMetadata(typeInformation[0]); - _superclass = typeMirrorFromRuntimeTypeRepresentation(this, type); - } else { - var superclassName = _fieldsDescriptor.split(';')[0]; - // TODO(zarah): Remove special handing of mixins. - var mixins = superclassName.split('+'); - if (mixins.length > 1) { - if (mixins.length != 2) { - throw new RuntimeError('Strange mixin: $_fieldsDescriptor'); - } - _superclass = reflectClassByMangledName(mixins[0]); - } else { - // Use _superclass == this to represent class with no superclass - // (Object). - _superclass = (superclassName == '') - ? this : reflectClassByMangledName(superclassName); - } - } - } - return _superclass == this ? null : _superclass; - } - - InstanceMirror invoke(Symbol memberName, - List positionalArguments, - [Map namedArguments]) { - // Mirror API gotcha: Calling [invoke] on a ClassMirror means invoke a - // static method. - - if (namedArguments != null && !namedArguments.isEmpty) { - throw new UnsupportedError('Named arguments are not implemented.'); - } - JsMethodMirror mirror = __methods[memberName]; - - if (mirror == null && _staticFieldExists(memberName)) { - return getField(memberName) - .invoke(#call, positionalArguments, namedArguments); - } - if (mirror == null || !mirror.isStatic) { - throw new NoSuchStaticMethodError.method( - null, memberName, positionalArguments, namedArguments); - } - if (!mirror.canInvokeReflectively()) { - throwInvalidReflectionError(n(memberName)); - } - return reflect(mirror._invoke(positionalArguments, namedArguments)); - } - - bool get isOriginalDeclaration => true; - - ClassMirror get originalDeclaration => this; - - List _getSuperinterfacesWithOwner(DeclarationMirror owner) { - var typeInformationContainer = JS_EMBEDDED_GLOBAL('', TYPE_INFORMATION); - List typeInformation = - JS('List|Null', '#[#]', typeInformationContainer, _mangledName); - List result = const []; - if (typeInformation != null) { - ClassMirror lookupType(int i) { - var type = getMetadata(i); - return typeMirrorFromRuntimeTypeRepresentation(owner, type); - } - - //We skip the first since it is the supertype. - result = typeInformation.skip(1).map(lookupType).toList(); - } - - return new UnmodifiableListView(result); - } - - List get superinterfaces { - if (_cachedSuperinterfaces != null) return _cachedSuperinterfaces; - return _cachedSuperinterfaces = _getSuperinterfacesWithOwner(this); - } - - List get typeVariables { - if (_cachedTypeVariables != null) return _cachedTypeVariables; - List result = new List(); - List typeVariables = - JS('JSExtendableArray|Null', '#.prototype["<>"]', _jsConstructor); - if (typeVariables == null) return result; - for (int i = 0; i < typeVariables.length; i++) { - TypeVariable typeVariable = getMetadata(typeVariables[i]); - result.add(new JsTypeVariableMirror(typeVariable, this, - typeVariables[i])); - } - return _cachedTypeVariables = new UnmodifiableListView(result); - } - - List get typeArguments => const []; - - bool get hasReflectedType => typeVariables.length == 0; - - Type get reflectedType { - if (!hasReflectedType) { - throw new UnsupportedError( - "Declarations of generics have no reflected type"); - } - return createRuntimeType(_mangledName); - } - - // TODO(ahe): Implement this. - ClassMirror get mixin => throw new UnimplementedError(); - - bool get isAbstract => throw new UnimplementedError(); - - bool isSubclassOf(ClassMirror other) { - if (other is! ClassMirror) { - throw new ArgumentError(other); - } - if (other is JsFunctionTypeMirror) { - return false; - } if (other is JsClassMirror && - JS('bool', '# == #', other._jsConstructor, _jsConstructor)) { - return true; - } else if (superclass == null) { - return false; - } else { - return superclass.isSubclassOf(other); - } - } -} - -class JsVariableMirror extends JsDeclarationMirror implements VariableMirror { - - // TODO(ahe): The values in these fields are virtually untested. - final String _jsName; - final bool isFinal; - final bool isStatic; - final _metadataFunction; - final DeclarationMirror _owner; - final int _type; - List _metadata; - - JsVariableMirror(Symbol simpleName, - this._jsName, - this._type, - this.isFinal, - this.isStatic, - this._metadataFunction, - this._owner) - : super(simpleName); - - factory JsVariableMirror.from(String descriptor, - metadataFunction, - JsDeclarationMirror owner, - bool isStatic) { - List fieldInformation = descriptor.split('-'); - if (fieldInformation.length == 1) { - // The field is not available for reflection. - // TODO(ahe): Should return an unreflectable field. - return null; - } - - String field = fieldInformation[0]; - int length = field.length; - var code = fieldCode(field.codeUnitAt(length - 1)); - bool isFinal = false; - if (code == 0) return null; // Inherited field. - bool hasGetter = (code & 3) != 0; - bool hasSetter = (code >> 2) != 0; - isFinal = !hasSetter; - length--; - String jsName; - String accessorName = jsName = field.substring(0, length); - int divider = field.indexOf(':'); - if (divider > 0) { - accessorName = accessorName.substring(0, divider); - jsName = field.substring(divider + 1); - } - var unmangledName; - if (isStatic) { - unmangledName = mangledGlobalNames[accessorName]; - } else { - String getterPrefix = JS_GET_NAME('GETTER_PREFIX'); - unmangledName = mangledNames['$getterPrefix$accessorName']; - } - if (unmangledName == null) unmangledName = accessorName; - if (!hasSetter) { - // TODO(ahe): This is a hack to handle checked setters in checked mode. - var setterName = s('$unmangledName='); - for (JsMethodMirror method in owner._methods) { - if (method.simpleName == setterName) { - isFinal = false; - break; - } - } - } - int type = int.parse(fieldInformation[1]); - return new JsVariableMirror(s(unmangledName), - jsName, - type, - isFinal, - isStatic, - metadataFunction, - owner); - } - - String get _prettyName => 'VariableMirror'; - - TypeMirror get type { - return typeMirrorFromRuntimeTypeRepresentation(owner, getMetadata(_type)); - } - - DeclarationMirror get owner => _owner; - - List get metadata { - preserveMetadata(); - if (_metadata == null) { - _metadata = (_metadataFunction == null) - ? const [] : JS('', '#()', _metadataFunction); - } - return _metadata.map(reflect).toList(); - } - - static int fieldCode(int code) { - if (code >= 60 && code <= 64) return code - 59; - if (code >= 123 && code <= 126) return code - 117; - if (code >= 37 && code <= 43) return code - 27; - return 0; - } - - _getField(JsMirror receiver) => receiver._loadField(_jsName); - - void _setField(JsMirror receiver, Object arg) { - if (isFinal) { - // TODO(floitsch): when the field is non-static we don't want to have - // a mirror as receiver. - if (isStatic) { - throw new NoSuchStaticMethodError.method( - null, setterSymbol(simpleName), [arg], null); - } - throw new NoSuchMethodError(this, setterSymbol(simpleName), [arg], null); - } - receiver._storeField(_jsName, arg); - } - - // TODO(ahe): Implement this method. - bool get isConst => throw new UnimplementedError(); -} - -class JsClosureMirror extends JsInstanceMirror implements ClosureMirror { - JsClosureMirror(reflectee) - : super(reflectee); - - MethodMirror get function { - String cacheName = Primitives.mirrorFunctionCacheName; - JsMethodMirror cachedFunction; - // TODO(ahe): Restore caching. - //= JS('JsMethodMirror|Null', r'#.constructor[#]', reflectee, cacheName); - if (cachedFunction != null) return cachedFunction; - disableTreeShaking(); - // TODO(ahe): What about optional parameters (named or not). - String callPrefix = "${JS_GET_NAME("CALL_PREFIX")}\$"; - var extractCallName = JS('', r''' -function(reflectee) { - for (var property in reflectee) { - if (# == property.substring(0, #) && - property[#] >= '0' && - property[#] <= '9') return property; - } - return null; -} -''', callPrefix, callPrefix.length, callPrefix.length, callPrefix.length); - String callName = JS('String|Null', '#(#)', extractCallName, reflectee); - if (callName == null) { - throw new RuntimeError('Cannot find callName on "$reflectee"'); - } - // TODO(floitsch): What about optional parameters? - int parameterCount = int.parse(callName.split(r'$')[1]); - if (reflectee is BoundClosure) { - var target = BoundClosure.targetOf(reflectee); - var self = BoundClosure.selfOf(reflectee); - var name = mangledNames[BoundClosure.nameOf(reflectee)]; - if (name == null) { - throwInvalidReflectionError(name); - } - cachedFunction = new JsMethodMirror.fromUnmangledName( - name, target, false, false); - } else { - bool isStatic = true; // TODO(ahe): Compute isStatic correctly. - var jsFunction = JS('', '#[#]', reflectee, callName); - var dummyOptionalParameterCount = 0; - cachedFunction = new JsMethodMirror( - s(callName), jsFunction, parameterCount, dummyOptionalParameterCount, - false, false, isStatic, false, false); - } - JS('void', r'#.constructor[#] = #', reflectee, cacheName, cachedFunction); - return cachedFunction; - } - - InstanceMirror apply(List positionalArguments, - [Map namedArguments]) { - return reflect( - Function.apply(reflectee, positionalArguments, namedArguments)); - } - - String toString() => "ClosureMirror on '${Error.safeToString(reflectee)}'"; - - // TODO(ahe): Implement this method. - String get source => throw new UnimplementedError(); -} - -class JsMethodMirror extends JsDeclarationMirror implements MethodMirror { - final _jsFunction; - final int _requiredParameterCount; - final int _optionalParameterCount; - final bool isGetter; - final bool isSetter; - final bool isStatic; - final bool isConstructor; - final bool isOperator; - DeclarationMirror _owner; - List _metadata; - TypeMirror _returnType; - UnmodifiableListView _parameters; - - JsMethodMirror(Symbol simpleName, - this._jsFunction, - this._requiredParameterCount, - this._optionalParameterCount, - this.isGetter, - this.isSetter, - this.isStatic, - this.isConstructor, - this.isOperator) - : super(simpleName); - - factory JsMethodMirror.fromUnmangledName(String name, - jsFunction, - bool isStatic, - bool isConstructor) { - List info = name.split(':'); - name = info[0]; - bool isOperator = isOperatorName(name); - bool isSetter = !isOperator && name.endsWith('='); - int requiredParameterCount = 0; - int optionalParameterCount = 0; - bool isGetter = false; - if (info.length == 1) { - if (isSetter) { - requiredParameterCount = 1; - } else { - isGetter = true; - requiredParameterCount = 0; - } - } else { - requiredParameterCount = int.parse(info[1]); - optionalParameterCount = int.parse(info[2]); - } - return new JsMethodMirror( - s(name), jsFunction, requiredParameterCount, optionalParameterCount, - isGetter, isSetter, isStatic, isConstructor, isOperator); - } - - String get _prettyName => 'MethodMirror'; - - int get _parameterCount => _requiredParameterCount + _optionalParameterCount; - - List get parameters { - if (_parameters != null) return _parameters; - metadata; // Compute _parameters as a side-effect of extracting metadata. - return _parameters; - } - - bool canInvokeReflectively() { - return hasReflectableProperty(_jsFunction); - } - - DeclarationMirror get owner => _owner; - - TypeMirror get returnType { - metadata; // Compute _returnType as a side-effect of extracting metadata. - return _returnType; - } - - List get metadata { - if (_metadata == null) { - var raw = extractMetadata(_jsFunction); - var formals = new List(_parameterCount); - ReflectionInfo info = new ReflectionInfo(_jsFunction); - if (info != null) { - assert(_parameterCount - == info.requiredParameterCount + info.optionalParameterCount); - var functionType = info.functionType; - var type; - if (functionType is int) { - type = new JsFunctionTypeMirror(info.computeFunctionRti(null), this); - assert(_parameterCount == type.parameters.length); - } else if (isTopLevel) { - type = new JsFunctionTypeMirror(info.computeFunctionRti(null), owner); - } else { - TypeMirror ownerType = owner; - JsClassMirror ownerClass = ownerType.originalDeclaration; - type = new JsFunctionTypeMirror( - info.computeFunctionRti(ownerClass._jsConstructor), - owner); - } - // Constructors aren't reified with their return type. - if (isConstructor) { - _returnType = owner; - } else { - _returnType = type.returnType; - } - int i = 0; - bool isNamed = info.areOptionalParametersNamed; - for (JsParameterMirror parameter in type.parameters) { - var name = info.parameterName(i); - List annotations = info.parameterMetadataAnnotations(i); - var p; - if (i < info.requiredParameterCount) { - p = new JsParameterMirror(name, this, parameter._type, - metadataList: annotations); - } else { - var defaultValue = info.defaultValue(i); - p = new JsParameterMirror( - name, this, parameter._type, metadataList: annotations, - isOptional: true, isNamed: isNamed, defaultValue: defaultValue); - } - formals[i++] = p; - } - } - _parameters = new UnmodifiableListView(formals); - _metadata = new UnmodifiableListView(raw.map(reflect)); - } - return _metadata; - } - - Symbol get constructorName { - // TODO(ahe): I believe it is more appropriate to throw an exception or - // return null. - if (!isConstructor) return const Symbol(''); - String name = n(simpleName); - int index = name.indexOf('.'); - if (index == -1) return const Symbol(''); - return s(name.substring(index + 1)); - } - - _invoke(List positionalArguments, Map namedArguments) { - if (namedArguments != null && !namedArguments.isEmpty) { - throw new UnsupportedError('Named arguments are not implemented.'); - } - if (!isStatic && !isConstructor) { - throw new RuntimeError('Cannot invoke instance method without receiver.'); - } - int positionalLength = positionalArguments.length; - if (positionalLength < _requiredParameterCount || - positionalLength > _parameterCount || - _jsFunction == null) { - // TODO(ahe): What receiver to use? - throw new NoSuchMethodError( - owner, simpleName, positionalArguments, namedArguments); - } - if (positionalLength < _parameterCount) { - // Fill up with default values. - // Make a copy so we don't modify the input. - positionalArguments = positionalArguments.toList(); - for (int i = positionalLength; i < parameters.length; i++) { - JsParameterMirror parameter = parameters[i]; - positionalArguments.add(parameter.defaultValue.reflectee); - } - } - // Using JS_CURRENT_ISOLATE() ('$') here is actually correct, although - // _jsFunction may not be a property of '$', most static functions do not - // care who their receiver is. But to lazy getters, it is important that - // 'this' is '$'. - return JS('', r'#.apply(#, #)', _jsFunction, JS_CURRENT_ISOLATE(), - new List.from(positionalArguments)); - } - - _getField(JsMirror receiver) { - if (isGetter) { - return _invoke([], null); - } else { - // TODO(ahe): Closurize method. - throw new UnimplementedError('getField on $receiver'); - } - } - - _setField(JsMirror receiver, Object arg) { - if (isSetter) { - return _invoke([arg], null); - } else { - throw new NoSuchMethodError(this, setterSymbol(simpleName), [], null); - } - } - - // Abstract methods are tree-shaken away. - bool get isAbstract => false; - - // TODO(ahe, 14633): This might not be true for all cases. - bool get isSynthetic => false; - - // TODO(ahe): Test this. - bool get isRegularMethod => !isGetter && !isSetter && !isConstructor; - - // TODO(ahe): Implement this method. - bool get isConstConstructor => throw new UnimplementedError(); - - // TODO(ahe): Implement this method. - bool get isGenerativeConstructor => throw new UnimplementedError(); - - // TODO(ahe): Implement this method. - bool get isRedirectingConstructor => throw new UnimplementedError(); - - // TODO(ahe): Implement this method. - bool get isFactoryConstructor => throw new UnimplementedError(); - - // TODO(ahe): Implement this method. - String get source => throw new UnimplementedError(); -} - -class JsParameterMirror extends JsDeclarationMirror implements ParameterMirror { - final DeclarationMirror owner; - // A JS object representing the type. - final _type; - - final bool isOptional; - - final bool isNamed; - - final int _defaultValue; - - final List metadataList; - - JsParameterMirror(String unmangledName, - this.owner, - this._type, - {this.metadataList: const [], - this.isOptional: false, - this.isNamed: false, - defaultValue}) - : _defaultValue = defaultValue, - super(s(unmangledName)); - - String get _prettyName => 'ParameterMirror'; - - TypeMirror get type { - return typeMirrorFromRuntimeTypeRepresentation(owner, _type); - } - - // Only true for static fields, never for a parameter. - bool get isStatic => false; - - // TODO(ahe): Implement this. - bool get isFinal => false; - - // TODO(ahe): Implement this. - bool get isConst => false; - - bool get hasDefaultValue => _defaultValue != null; - - get defaultValue { - return hasDefaultValue ? reflect(getMetadata(_defaultValue)) : null; - } - - List get metadata { - preserveMetadata(); - return metadataList.map((int i) => reflect(getMetadata(i))).toList(); - } -} - -class JsTypedefMirror extends JsDeclarationMirror implements TypedefMirror { - final String _mangledName; - JsFunctionTypeMirror referent; - - JsTypedefMirror(Symbol simpleName, this._mangledName, _typeData) - : super(simpleName) { - referent = new JsFunctionTypeMirror(_typeData, this); - } - - JsFunctionTypeMirror get value => referent; - - String get _prettyName => 'TypedefMirror'; - - bool get hasReflectedType => throw new UnimplementedError(); - - Type get reflectedType => createRuntimeType(_mangledName); - - // TODO(floitsch): Implement this method. - List get typeVariables => throw new UnimplementedError(); - - // TODO(floitsch): Implement this method. - List get typeArguments => throw new UnimplementedError(); - - bool get isOriginalDeclaration => true; - - TypeMirror get originalDeclaration => this; - - // TODO(floitsch): Implement this method. - DeclarationMirror get owner => throw new UnimplementedError(); - - // TODO(ahe): Implement this method. - List get metadata => throw new UnimplementedError(); - - bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError(); - bool isAssignableTo(TypeMirror other) => throw new UnimplementedError(); -} - -// TODO(ahe): Remove this class when API is updated. -class BrokenClassMirror { - bool get hasReflectedType => throw new UnimplementedError(); - Type get reflectedType => throw new UnimplementedError(); - ClassMirror get superclass => throw new UnimplementedError(); - List get superinterfaces => throw new UnimplementedError(); - Map get declarations - => throw new UnimplementedError(); - Map get instanceMembers - => throw new UnimplementedError(); - Map get staticMembers => throw new UnimplementedError(); - ClassMirror get mixin => throw new UnimplementedError(); - InstanceMirror newInstance( - Symbol constructorName, - List positionalArguments, - [Map namedArguments]) => throw new UnimplementedError(); - InstanceMirror invoke(Symbol memberName, - List positionalArguments, - [Map namedArguments]) - => throw new UnimplementedError(); - InstanceMirror getField(Symbol fieldName) => throw new UnimplementedError(); - InstanceMirror setField(Symbol fieldName, Object value) - => throw new UnimplementedError(); - List get typeVariables => throw new UnimplementedError(); - List get typeArguments => throw new UnimplementedError(); - TypeMirror get originalDeclaration => throw new UnimplementedError(); - Symbol get simpleName => throw new UnimplementedError(); - Symbol get qualifiedName => throw new UnimplementedError(); - bool get isPrivate => throw new UnimplementedError(); - bool get isTopLevel => throw new UnimplementedError(); - SourceLocation get location => throw new UnimplementedError(); - List get metadata => throw new UnimplementedError(); -} - -class JsFunctionTypeMirror extends BrokenClassMirror - implements FunctionTypeMirror { - final _typeData; - String _cachedToString; - TypeMirror _cachedReturnType; - UnmodifiableListView _cachedParameters; - DeclarationMirror owner; - - JsFunctionTypeMirror(this._typeData, this.owner); - - bool get _hasReturnType { - return JS('bool', '# in #', JS_FUNCTION_TYPE_RETURN_TYPE_TAG(), _typeData); - } - get _returnType { - return JS('', '#[#]', _typeData, JS_FUNCTION_TYPE_RETURN_TYPE_TAG()); - } - - bool get _isVoid { - return JS('bool', '!!#[#]', _typeData, JS_FUNCTION_TYPE_VOID_RETURN_TAG()); - } - - bool get _hasArguments { - return JS('bool', '# in #', - JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG(), _typeData); - } - List get _arguments { - return JS('JSExtendableArray', '#[#]', - _typeData, JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG()); - } - - bool get _hasOptionalArguments { - return JS('bool', '# in #', - JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG(), _typeData); - } - List get _optionalArguments { - return JS('JSExtendableArray', '#[#]', - _typeData, JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG()); - } - - bool get _hasNamedArguments { - return JS('bool', '# in #', - JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG(), _typeData); - } - get _namedArguments { - return JS('=Object', '#[#]', - _typeData, JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG()); - } - - bool get isOriginalDeclaration => true; - - bool get isAbstract => false; - - TypeMirror get returnType { - if (_cachedReturnType != null) return _cachedReturnType; - if (_isVoid) return _cachedReturnType = JsMirrorSystem._voidType; - if (!_hasReturnType) return _cachedReturnType = JsMirrorSystem._dynamicType; - return _cachedReturnType = - typeMirrorFromRuntimeTypeRepresentation(owner, _returnType); - } - - List get parameters { - if (_cachedParameters != null) return _cachedParameters; - List result = []; - int parameterCount = 0; - if (_hasArguments) { - for (var type in _arguments) { - result.add( - new JsParameterMirror('argument${parameterCount++}', this, type)); - } - } - if (_hasOptionalArguments) { - for (var type in _optionalArguments) { - result.add( - new JsParameterMirror('argument${parameterCount++}', this, type)); - } - } - if (_hasNamedArguments) { - for (var name in extractKeys(_namedArguments)) { - var type = JS('', '#[#]', _namedArguments, name); - result.add(new JsParameterMirror(name, this, type)); - } - } - return _cachedParameters = new UnmodifiableListView( - result); - } - - String _unmangleIfPreserved(String mangled) { - String result = unmangleGlobalNameIfPreservedAnyways(mangled); - if (result != null) return result; - return mangled; - } - - String toString() { - if (_cachedToString != null) return _cachedToString; - var s = "FunctionTypeMirror on '("; - var sep = ''; - if (_hasArguments) { - for (var argument in _arguments) { - s += sep; - s += _unmangleIfPreserved(runtimeTypeToString(argument)); - sep = ', '; - } - } - if (_hasOptionalArguments) { - s += '$sep['; - sep = ''; - for (var argument in _optionalArguments) { - s += sep; - s += _unmangleIfPreserved(runtimeTypeToString(argument)); - sep = ', '; - } - s += ']'; - } - if (_hasNamedArguments) { - s += '$sep{'; - sep = ''; - for (var name in extractKeys(_namedArguments)) { - s += sep; - s += '$name: '; - s += _unmangleIfPreserved( - runtimeTypeToString(JS('', '#[#]', _namedArguments, name))); - sep = ', '; - } - s += '}'; - } - s += ') -> '; - if (_isVoid) { - s += 'void'; - } else if (_hasReturnType) { - s += _unmangleIfPreserved(runtimeTypeToString(_returnType)); - } else { - s += 'dynamic'; - } - return _cachedToString = "$s'"; - } - - bool isSubclassOf(ClassMirror other) => false; - - bool isSubtypeOf(TypeMirror other) => throw new UnimplementedError(); - - bool isAssignableTo(TypeMirror other) => throw new UnimplementedError(); - - // TODO(ahe): Implement this method. - MethodMirror get callMethod => throw new UnimplementedError(); -} - -int findTypeVariableIndex(List typeVariables, String name) { - for (int i = 0; i < typeVariables.length; i++) { - if (typeVariables[i].simpleName == s(name)) { - return i; - } - } - throw new ArgumentError('Type variable not present in list.'); -} - -TypeMirror typeMirrorFromRuntimeTypeRepresentation( - DeclarationMirror owner, - var /*int|List|JsFunction|TypeImpl*/ type) { - // TODO(ahe): This method might benefit from using convertRtiToRuntimeType - // instead of working on strings. - ClassMirror ownerClass; - DeclarationMirror context = owner; - while (context != null) { - if (context is ClassMirror) { - ownerClass = context; - break; - } - // TODO(ahe): Get type parameters and arguments from typedefs. - if (context is TypedefMirror) break; - context = context.owner; - } - - String representation; - if (type == null) { - return JsMirrorSystem._dynamicType; - } else if (type is TypeImpl) { - return reflectType(type); - } else if (ownerClass == null) { - representation = runtimeTypeToString(type); - } else if (ownerClass.isOriginalDeclaration) { - if (type is num) { - // [type] represents a type variable so in the context of an original - // declaration the corresponding type variable should be returned. - TypeVariable typeVariable = getMetadata(type); - List typeVariables = ownerClass.typeVariables; - int index = findTypeVariableIndex(typeVariables, typeVariable.name); - return typeVariables[index]; - } else { - // Nested type variables will be retrieved lazily (the integer - // representation is kept in the string) so they are not processed here. - representation = runtimeTypeToString(type); - } - } else { - TypeMirror getTypeArgument(int index) { - TypeVariable typeVariable = getMetadata(index); - int variableIndex = - findTypeVariableIndex(ownerClass.typeVariables, typeVariable.name); - return ownerClass.typeArguments[variableIndex]; - } - - if (type is num) { - // [type] represents a type variable used as type argument for example - // the type argument of Bar: class Foo extends Bar {} - TypeMirror typeArgument = getTypeArgument(type); - if (typeArgument is JsTypeVariableMirror) - return typeArgument; - } - String substituteTypeVariable(int index) { - var typeArgument = getTypeArgument(index); - if (typeArgument is JsTypeVariableMirror) { - return '${typeArgument._metadataIndex}'; - } - if (typeArgument is! JsClassMirror && - typeArgument is! JsTypeBoundClassMirror) { - if (typeArgument == JsMirrorSystem._dynamicType) { - return 'dynamic'; - } else if (typeArgument == JsMirrorSystem._voidType) { - return 'void'; - } else { - // TODO(ahe): This case shouldn't happen. - return 'dynamic'; - } - } - return typeArgument._mangledName; - } - representation = - runtimeTypeToString(type, onTypeVariable: substituteTypeVariable); - } - if (representation != null) { - return reflectClassByMangledName( - getMangledTypeName(createRuntimeType(representation))); - } - String typedefPropertyName = JS_TYPEDEF_TAG(); - String functionTagPropertyName = JS_FUNCTION_TYPE_TAG(); - if (type != null && JS('', '#[#]', type, typedefPropertyName) != null) { - return typeMirrorFromRuntimeTypeRepresentation( - owner, JS('', '#[#]', type, typedefPropertyName)); - } else if (type != null && - JS('', '#[#]', type, functionTagPropertyName) != null) { - return new JsFunctionTypeMirror(type, owner); - } - return reflectClass(Function); -} - -Symbol computeQualifiedName(DeclarationMirror owner, Symbol simpleName) { - if (owner == null) return simpleName; - String ownerName = n(owner.qualifiedName); - return s('$ownerName.${n(simpleName)}'); -} - -List extractMetadata(victim) { - preserveMetadata(); - var metadataFunction; - if (JS('bool', 'Object.prototype.hasOwnProperty.call(#, "@")', victim)) { - metadataFunction = JS('', '#["@"]', victim); - } - if (metadataFunction != null) return JS('', '#()', metadataFunction); - if (JS('bool', 'typeof # != "function"', victim)) return const []; - if (JS('bool', '# in #', r'$metadataIndex', victim)) { - return JSArray.markFixedList( - JS('JSExtendableArray', - r'#.$reflectionInfo.splice(#.$metadataIndex)', victim, victim)) - .map((int i) => getMetadata(i)).toList(); - } - return const []; -} - -void parseCompactFieldSpecification( - JsDeclarationMirror owner, - fieldSpecification, - bool isStatic, - List result) { - List fieldsMetadata = null; - List fields; - if (fieldSpecification is List) { - fields = splitFields(fieldSpecification[0], ','); - fieldsMetadata = fieldSpecification.sublist(1); - } else if (fieldSpecification is String) { - fields = splitFields(fieldSpecification, ','); - } else { - fields = []; - } - int fieldNumber = 0; - for (String field in fields) { - var metadata; - if (fieldsMetadata != null) { - metadata = fieldsMetadata[fieldNumber++]; - } - var mirror = new JsVariableMirror.from(field, metadata, owner, isStatic); - if (mirror != null) { - result.add(mirror); - } - } -} - -/// Similar to [String.split], but returns an empty list if [string] is empty. -List splitFields(String string, Pattern pattern) { - if (string.isEmpty) return []; - return string.split(pattern); -} - -bool isOperatorName(String name) { - switch (name) { - case '==': - case '[]': - case '*': - case '/': - case '%': - case '~/': - case '+': - case '<<': - case '>>': - case '>=': - case '>': - case '<=': - case '<': - case '&': - case '^': - case '|': - case '-': - case 'unary-': - case '[]=': - case '~': - return true; - default: - return false; - } -} - -/// Returns true if the key represent ancillary reflection data, that is, not a -/// method. -bool isReflectiveDataInPrototype(String key) { - if (key == JS_GET_NAME('CLASS_DESCRIPTOR_PROPERTY') || - key == METHODS_WITH_OPTIONAL_ARGUMENTS) { - return true; - } - String firstChar = key[0]; - return firstChar == '*' || firstChar == '+'; -} - -bool isNoSuchMethodStub(var jsFunction) { - return JS('bool', r'#.$reflectable == 2', jsFunction); -} - -/// Returns true if [key] is only an aliased entry for [function] in the -/// prototype. -bool isAliasedSuperMethod(var jsFunction, String key) { - var stubName = JS('String|Null', r'#.$stubName', jsFunction); - return stubName != null && key != stubName; -} - -class NoSuchStaticMethodError extends Error implements NoSuchMethodError { - static const int MISSING_CONSTRUCTOR = 0; - static const int MISSING_METHOD = 1; - final ClassMirror _cls; - final Symbol _name; - final List _positionalArguments; - final Map _namedArguments; - final int _kind; - - NoSuchStaticMethodError.missingConstructor( - this._cls, - this._name, - this._positionalArguments, - this._namedArguments) - : _kind = MISSING_CONSTRUCTOR; - - /// If the given class is `null` the static method/getter/setter is top-level. - NoSuchStaticMethodError.method( - this._cls, - this._name, - this._positionalArguments, - this._namedArguments) - : _kind = MISSING_METHOD; - - String toString() { - // TODO(floitsch): show arguments. - switch(_kind) { - case MISSING_CONSTRUCTOR: - return - "NoSuchMethodError: No constructor named '${n(_name)}' in class" - " '${n(_cls.qualifiedName)}'."; - case MISSING_METHOD: - if (_cls == null) { - return "NoSuchMethodError: No top-level method named '${n(_name)}'."; - } - return "NoSuchMethodError: No static method named '${n(_name)}' in" - " class '${n(_cls.qualifiedName)}'"; - default: - return 'NoSuchMethodError'; - } - } -} - -Symbol getSymbol(String name, LibraryMirror library) { - if (_isPublicSymbol(name)) { - return new _symbol_dev.Symbol.validated(name); - } - if (library == null) { - throw new ArgumentError( - "Library required for private symbol name: $name"); - } - if (!_symbol_dev.Symbol.isValidSymbol(name)) { - throw new ArgumentError("Not a valid symbol name: $name"); - } - throw new UnimplementedError( - "MirrorSystem.getSymbol not implemented for private names"); -} - -bool _isPublicSymbol(String name) { - // A symbol is public if it doesn't start with '_' and it doesn't - // have a part (following a '.') that starts with '_'. - const int UNDERSCORE = 0x5f; - if (name.isEmpty) return true; - int index = -1; - do { - if (name.codeUnitAt(index + 1) == UNDERSCORE) return false; - index = name.indexOf('.', index + 1); - } while (index >= 0 && index + 1 < name.length); - return true; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_names.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_names.dart deleted file mode 100644 index 3933e787245a..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_names.dart +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -library dart._js_names; - -import 'dart:_js_embedded_names' show - MANGLED_GLOBAL_NAMES, - MANGLED_NAMES; - -import 'dart:_foreign_helper' show - JS, - JS_EMBEDDED_GLOBAL, - JS_GET_NAME; - -import 'dart:_js_helper' show - JsCache, - NoInline; - -import 'dart:_interceptors' show JSArray; - -/// No-op method that is called to inform the compiler that unmangled named -/// must be preserved. -preserveNames() {} - -/// A map from mangled names to "reflective" names, that is, unmangled names -/// with some additional information, such as, number of required arguments. -/// This map is for mangled names used as instance members. -final Map mangledNames = - computeMangledNames( - JS_EMBEDDED_GLOBAL('=Object', MANGLED_NAMES), - false); - -/// A map from "reflective" names to mangled names (the reverse of -/// [mangledNames]). -final Map reflectiveNames = - computeReflectiveNames(mangledNames); - -/// A map from mangled names to "reflective" names (see [mangledNames]). This -/// map is for globals, that is, static and top-level members. -final Map mangledGlobalNames = computeMangledNames( - JS_EMBEDDED_GLOBAL('=Object', MANGLED_GLOBAL_NAMES), - true); - -/// A map from "reflective" names to mangled names (the reverse of -/// [mangledGlobalNames]). -final Map reflectiveGlobalNames = - computeReflectiveNames(mangledGlobalNames); - -/// [jsMangledNames] is a JavaScript object literal. The keys are the mangled -/// names, and the values are the "reflective" names. -Map computeMangledNames(jsMangledNames, bool isGlobal) { - preserveNames(); - var keys = extractKeys(jsMangledNames); - var result = {}; - String getterPrefix = JS_GET_NAME('GETTER_PREFIX'); - int getterPrefixLength = getterPrefix.length; - String setterPrefix = JS_GET_NAME('SETTER_PREFIX'); - for (String key in keys) { - String value = JS('String', '#[#]', jsMangledNames, key); - result[key] = value; - if (!isGlobal) { - if (key.startsWith(getterPrefix)) { - result['$setterPrefix${key.substring(getterPrefixLength)}'] = '$value='; - } - } - } - return result; -} - -Map computeReflectiveNames(Map map) { - preserveNames(); - var result = {}; - map.forEach((String mangledName, String reflectiveName) { - result[reflectiveName] = mangledName; - }); - return result; -} - -@NoInline() -List extractKeys(victim) { - var result = JS('', ''' -(function(victim, hasOwnProperty) { - var result = []; - for (var key in victim) { - if (hasOwnProperty.call(victim, key)) result.push(key); - } - return result; -})(#, Object.prototype.hasOwnProperty)''', victim); - return new JSArray.markFixed(result); -} - -/** - * Returns the (global) unmangled version of [name]. - * - * Normally, you should use [mangledGlobalNames] directly, but this method - * doesn't tell the compiler to preserve names. So this method only returns a - * non-null value if some other component has made the compiler preserve names. - * - * This is used, for example, to return unmangled names from TypeImpl.toString - * *if* names are being preserved for other reasons (use of dart:mirrors, for - * example). - */ -String unmangleGlobalNameIfPreservedAnyways(String name) { - var names = JS_EMBEDDED_GLOBAL('=Object', MANGLED_GLOBAL_NAMES); - return JsCache.fetch(names, name); -} - -String unmangleAllIdentifiersIfPreservedAnyways(String str) { - return JS("String", - r"(#).replace(/[^<,> ]+/g," - r"function(m) { return #[m] || m; })", - str, - JS_EMBEDDED_GLOBAL('', MANGLED_GLOBAL_NAMES)); -} \ No newline at end of file diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_number.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_number.dart deleted file mode 100644 index 6bc999a4239d..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_number.dart +++ /dev/null @@ -1,422 +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. - -part of _interceptors; - -/** - * The super interceptor class for [JSInt] and [JSDouble]. The compiler - * recognizes this class as an interceptor, and changes references to - * [:this:] to actually use the receiver of the method, which is - * generated as an extra argument added to each member. - * - * Note that none of the methods here delegate to a method defined on JSInt or - * JSDouble. This is exploited in [tryComputeConstantInterceptor]. - */ -class JSNumber extends Interceptor implements num { - const JSNumber(); - - int compareTo(num b) { - if (b is! num) throw new ArgumentError(b); - if (this < b) { - return -1; - } else if (this > b) { - return 1; - } else if (this == b) { - if (this == 0) { - bool bIsNegative = b.isNegative; - if (isNegative == bIsNegative) return 0; - if (isNegative) return -1; - return 1; - } - return 0; - } else if (isNaN) { - if (b.isNaN) { - return 0; - } - return 1; - } else { - return -1; - } - } - - bool get isNegative => (this == 0) ? (1 / this) < 0 : this < 0; - - bool get isNaN => JS('bool', r'isNaN(#)', this); - - bool get isInfinite { - return JS('bool', r'# == Infinity', this) - || JS('bool', r'# == -Infinity', this); - } - - bool get isFinite => JS('bool', r'isFinite(#)', this); - - num remainder(num b) { - checkNull(b); // TODO(ngeoffray): This is not specified but co19 tests it. - if (b is! num) throw new ArgumentError(b); - return JS('num', r'# % #', this, b); - } - - num abs() => JS('num', r'Math.abs(#)', this); - - num get sign => this > 0 ? 1 : this < 0 ? -1 : this; - - static const int _MIN_INT32 = -0x80000000; - static const int _MAX_INT32 = 0x7FFFFFFF; - - int toInt() { - if (this >= _MIN_INT32 && this <= _MAX_INT32) { - return JS('int', '# | 0', this); - } - if (JS('bool', r'isFinite(#)', this)) { - return JS('int', r'# + 0', truncateToDouble()); // Converts -0.0 to +0.0. - } - // This is either NaN, Infinity or -Infinity. - throw new UnsupportedError(JS("String", "''+#", this)); - } - - int truncate() => toInt(); - int ceil() => ceilToDouble().toInt(); - int floor() => floorToDouble().toInt(); - int round() => roundToDouble().toInt(); - - double ceilToDouble() => JS('num', r'Math.ceil(#)', this); - - double floorToDouble() => JS('num', r'Math.floor(#)', this); - - double roundToDouble() { - if (this < 0) { - return JS('num', r'-Math.round(-#)', this); - } else { - return JS('num', r'Math.round(#)', this); - } - } - - double truncateToDouble() => this < 0 ? ceilToDouble() : floorToDouble(); - - num clamp(num lowerLimit, num upperLimit) { - if (lowerLimit is! num) throw new ArgumentError(lowerLimit); - if (upperLimit is! num) throw new ArgumentError(upperLimit); - if (lowerLimit.compareTo(upperLimit) > 0) { - throw new ArgumentError(lowerLimit); - } - if (this.compareTo(lowerLimit) < 0) return lowerLimit; - if (this.compareTo(upperLimit) > 0) return upperLimit; - return this; - } - - // The return type is intentionally omitted to avoid type checker warnings - // from assigning JSNumber to double. - toDouble() => this; - - String toStringAsFixed(int fractionDigits) { - checkInt(fractionDigits); - if (fractionDigits < 0 || fractionDigits > 20) { - throw new RangeError(fractionDigits); - } - String result = JS('String', r'#.toFixed(#)', this, fractionDigits); - if (this == 0 && isNegative) return "-$result"; - return result; - } - - String toStringAsExponential([int fractionDigits]) { - String result; - if (fractionDigits != null) { - checkInt(fractionDigits); - if (fractionDigits < 0 || fractionDigits > 20) { - throw new RangeError(fractionDigits); - } - result = JS('String', r'#.toExponential(#)', this, fractionDigits); - } else { - result = JS('String', r'#.toExponential()', this); - } - if (this == 0 && isNegative) return "-$result"; - return result; - } - - String toStringAsPrecision(int precision) { - checkInt(precision); - if (precision < 1 || precision > 21) { - throw new RangeError(precision); - } - String result = JS('String', r'#.toPrecision(#)', - this, precision); - if (this == 0 && isNegative) return "-$result"; - return result; - } - - String toRadixString(int radix) { - checkInt(radix); - if (radix < 2 || radix > 36) throw new RangeError(radix); - String result = JS('String', r'#.toString(#)', this, radix); - const int rightParenCode = 0x29; - if (result.codeUnitAt(result.length - 1) != rightParenCode) { - return result; - } - return _handleIEtoString(result); - } - - static String _handleIEtoString(String result) { - // Result is probably IE's untraditional format for large numbers, - // e.g., "8.0000000000008(e+15)" for 0x8000000000000800.toString(16). - var match = JS('List|Null', - r'/^([\da-z]+)(?:\.([\da-z]+))?\(e\+(\d+)\)$/.exec(#)', - result); - if (match == null) { - // Then we don't know how to handle it at all. - throw new UnsupportedError("Unexpected toString result: $result"); - } - result = JS('String', '#', match[1]); - int exponent = JS("int", "+#", match[3]); - if (match[2] != null) { - result = JS('String', '# + #', result, match[2]); - exponent -= JS('int', '#.length', match[2]); - } - return result + "0" * exponent; - } - - // Note: if you change this, also change the function [S]. - String toString() { - if (this == 0 && JS('bool', '(1 / #) < 0', this)) { - return '-0.0'; - } else { - return JS('String', r'"" + (#)', this); - } - } - - int get hashCode => JS('int', '# & 0x1FFFFFFF', this); - - num operator -() => JS('num', r'-#', this); - - num operator +(num other) { - if (other is !num) throw new ArgumentError(other); - return JS('num', '# + #', this, other); - } - - num operator -(num other) { - if (other is !num) throw new ArgumentError(other); - return JS('num', '# - #', this, other); - } - - double operator /(num other) { - if (other is !num) throw new ArgumentError(other); - return JS('double', '# / #', this, other); - } - - num operator *(num other) { - if (other is !num) throw new ArgumentError(other); - return JS('num', '# * #', this, other); - } - - num operator %(num other) { - if (other is !num) throw new ArgumentError(other); - // Euclidean Modulo. - num result = JS('num', r'# % #', this, other); - if (result == 0) return 0; // Make sure we don't return -0.0. - if (result > 0) return result; - if (JS('num', '#', other) < 0) { - return result - JS('num', '#', other); - } else { - return result + JS('num', '#', other); - } - } - - bool _isInt32(value) => JS('bool', '(# | 0) === #', value, value); - - int operator ~/(num other) { - if (false) _tdivFast(other); // Ensure resolution. - if (_isInt32(this) && _isInt32(other) && 0 != other && -1 != other) { - return JS('int', r'(# / #) | 0', this, other); - } else { - return _tdivSlow(other); - } - } - - int _tdivFast(num other) { - return _isInt32(this) - ? JS('int', r'(# / #) | 0', this, other) - : (JS('num', r'# / #', this, other)).toInt(); - } - - int _tdivSlow(num other) { - if (other is !num) throw new ArgumentError(other); - return (JS('num', r'# / #', this, other)).toInt(); - } - - // TODO(ngeoffray): Move the bit operations below to [JSInt] and - // make them take an int. Because this will make operations slower, - // we define these methods on number for now but we need to decide - // the grain at which we do the type checks. - - num operator <<(num other) { - if (other is !num) throw new ArgumentError(other); - if (JS('num', '#', other) < 0) throw new ArgumentError(other); - return _shlPositive(other); - } - - num _shlPositive(num other) { - // JavaScript only looks at the last 5 bits of the shift-amount. Shifting - // by 33 is hence equivalent to a shift by 1. - return JS('bool', r'# > 31', other) - ? 0 - : JS('JSUInt32', r'(# << #) >>> 0', this, other); - } - - num operator >>(num other) { - if (false) _shrReceiverPositive(other); - if (other is !num) throw new ArgumentError(other); - if (JS('num', '#', other) < 0) throw new ArgumentError(other); - return _shrOtherPositive(other); - } - - num _shrOtherPositive(num other) { - return JS('num', '#', this) > 0 - ? _shrBothPositive(other) - // For negative numbers we just clamp the shift-by amount. - // `this` 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. - : JS('JSUInt32', r'(# >> #) >>> 0', this, other > 31 ? 31 : other); - } - - num _shrReceiverPositive(num other) { - if (JS('num', '#', other) < 0) throw new ArgumentError(other); - return _shrBothPositive(other); - } - - num _shrBothPositive(num other) { - return JS('bool', r'# > 31', other) - // JavaScript only looks at the last 5 bits of the shift-amount. In JS - // shifting by 33 is hence equivalent to a shift by 1. Shortcut the - // computation when that happens. - ? 0 - // Given that `this` is positive we must not use '>>'. Otherwise a - // number that has the 31st bit set would be treated as negative and - // shift in ones. - : JS('JSUInt32', r'# >>> #', this, other); - } - - num operator &(num other) { - if (other is !num) throw new ArgumentError(other); - return JS('JSUInt32', r'(# & #) >>> 0', this, other); - } - - num operator |(num other) { - if (other is !num) throw new ArgumentError(other); - return JS('JSUInt32', r'(# | #) >>> 0', this, other); - } - - num operator ^(num other) { - if (other is !num) throw new ArgumentError(other); - return JS('JSUInt32', r'(# ^ #) >>> 0', this, other); - } - - bool operator <(num other) { - if (other is !num) throw new ArgumentError(other); - return JS('bool', '# < #', this, other); - } - - bool operator >(num other) { - if (other is !num) throw new ArgumentError(other); - return JS('bool', '# > #', this, other); - } - - bool operator <=(num other) { - if (other is !num) throw new ArgumentError(other); - return JS('bool', '# <= #', this, other); - } - - bool operator >=(num other) { - if (other is !num) throw new ArgumentError(other); - return JS('bool', '# >= #', this, other); - } - - Type get runtimeType => num; -} - -/** - * The interceptor class for [int]s. - * - * This class implements double since in JavaScript all numbers are doubles, so - * while we want to treat `2.0` as an integer for some operations, its - * interceptor should answer `true` to `is double`. - */ -class JSInt extends JSNumber implements int, double { - const JSInt(); - - bool get isEven => (this & 1) == 0; - - bool get isOdd => (this & 1) == 1; - - int toUnsigned(int width) { - return this & ((1 << width) - 1); - } - - int toSigned(int width) { - int signMask = 1 << (width - 1); - return (this & (signMask - 1)) - (this & signMask); - } - - int get bitLength { - int nonneg = this < 0 ? -this - 1 : this; - if (nonneg >= 0x100000000) { - nonneg = nonneg ~/ 0x100000000; - return _bitCount(_spread(nonneg)) + 32; - } - return _bitCount(_spread(nonneg)); - } - - // Assumes i is <= 32-bit and unsigned. - static int _bitCount(int i) { - // See "Hacker's Delight", section 5-1, "Counting 1-Bits". - - // The basic strategy is to use "divide and conquer" to - // add pairs (then quads, etc.) of bits together to obtain - // sub-counts. - // - // A straightforward approach would look like: - // - // i = (i & 0x55555555) + ((i >> 1) & 0x55555555); - // i = (i & 0x33333333) + ((i >> 2) & 0x33333333); - // i = (i & 0x0F0F0F0F) + ((i >> 4) & 0x0F0F0F0F); - // i = (i & 0x00FF00FF) + ((i >> 8) & 0x00FF00FF); - // i = (i & 0x0000FFFF) + ((i >> 16) & 0x0000FFFF); - // - // The code below removes unnecessary &'s and uses a - // trick to remove one instruction in the first line. - - i = _shru(i, 0) - (_shru(i, 1) & 0x55555555); - i = (i & 0x33333333) + (_shru(i, 2) & 0x33333333); - i = 0x0F0F0F0F & (i + _shru(i, 4)); - i += _shru(i, 8); - i += _shru(i, 16); - return (i & 0x0000003F); - } - - static int _shru(int value, int shift) => JS('int', '# >>> #', value, shift); - static int _shrs(int value, int shift) => JS('int', '# >> #', value, shift); - static int _ors(int a, int b) => JS('int', '# | #', a, b); - - // Assumes i is <= 32-bit - static int _spread(int i) { - i = _ors(i, _shrs(i, 1)); - i = _ors(i, _shrs(i, 2)); - i = _ors(i, _shrs(i, 4)); - i = _ors(i, _shrs(i, 8)); - i = _shru(_ors(i, _shrs(i, 16)), 0); - return i; - } - - Type get runtimeType => int; - - 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/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_primitives.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_primitives.dart deleted file mode 100644 index 389471dc3ec0..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_primitives.dart +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// dart2js "primitives", that is, features that cannot be implemented without -/// access to JavaScript features. -library dart2js._js_primitives; - -import 'dart:_foreign_helper' show - JS; - -/** - * This is the low-level method that is used to implement [print]. It is - * possible to override this function from JavaScript by defining a function in - * JavaScript called "dartPrint". - * - * Notice that it is also possible to intercept calls to [print] from within a - * Dart program using zones. This means that there is no guarantee that a call - * to print ends in this method. - */ -void printString(String string) { - if (JS('bool', r'typeof dartPrint == "function"')) { - // Support overriding print from JavaScript. - JS('void', r'dartPrint(#)', string); - return; - } - - // Inside browser or nodejs. - if (JS('bool', r'typeof console == "object"') && - JS('bool', r'typeof console.log != "undefined"')) { - JS('void', r'console.log(#)', string); - return; - } - - // Don't throw inside IE, the console is only defined if dev tools is open. - if (JS('bool', r'typeof window == "object"')) { - return; - } - - // Running in d8, the V8 developer shell, or in Firefox' js-shell. - if (JS('bool', r'typeof print == "function"')) { - JS('void', r'print(#)', string); - return; - } - - // This is somewhat nasty, but we don't want to drag in a bunch of - // dependencies to handle a situation that cannot happen. So we - // avoid using Dart [:throw:] and Dart [toString]. - JS('void', 'throw "Unable to print message: " + String(#)', string); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_rti.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_rti.dart deleted file mode 100644 index 08c52dd960e7..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_rti.dart +++ /dev/null @@ -1,688 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/** - * This part contains helpers for supporting runtime type information. - * - * The helper use a mixture of Dart and JavaScript objects. To indicate which is - * used where we adopt the scheme of using explicit type annotation for Dart - * objects and 'var' or omitted return type for JavaScript objects. - * - * Since bool, int, and String values are represented by the same JavaScript - * primitives, type annotations are used for these types in all cases. - * - * Several methods use a common JavaScript encoding of runtime type information. - * This encoding is referred to as the type representation which is one of - * these: - * 1) a JavaScript constructor for a class C: the represented type is the raw - * type C. - * 2) a Dart object: this is the interceptor instance for a native type. - * 3) a JavaScript object: this represents a class for which there is no - * JavaScript constructor, because it is only used in type arguments or it - * is native. The represented type is the raw type of this class. - * 4) a JavaScript array: the first entry is of type 1, 2 or 3 and contains the - * subtyping flags and the substitution of the type and the rest of the - * array are the type arguments. - * 5) `null`: the dynamic type. - * - * - * To check subtype relations between generic classes we use a JavaScript - * expression that describes the necessary substitution for type arguments. - * Such a substitution expresssion can be: - * 1) `null`, if no substituted check is necessary, because the - * type variables are the same or there are no type variables in the class - * that is checked for. - * 2) A list expression describing the type arguments to be used in the - * subtype check, if the type arguments to be used in the check do not - * depend on the type arguments of the object. - * 3) A function mapping the type variables of the object to be checked to - * a list expression. - */ - -part of _js_helper; - -Type createRuntimeType(String name) => new TypeImpl(name); - -class TypeImpl implements Type { - final String _typeName; - String _unmangledName; - - TypeImpl(this._typeName); - - String toString() { - if (_unmangledName != null) return _unmangledName; - String unmangledName = unmangleAllIdentifiersIfPreservedAnyways(_typeName); - return _unmangledName = unmangledName; - } - - // TODO(ahe): This is a poor hashCode as it collides with its name. - int get hashCode => _typeName.hashCode; - - bool operator ==(other) { - return (other is TypeImpl) && _typeName == other._typeName; - } -} - -/** - * Represents a type variable. - * - * This class holds the information needed when reflecting on generic classes - * and their members. - */ -class TypeVariable { - final Type owner; - final String name; - final int bound; - - const TypeVariable(this.owner, this.name, this.bound); -} - -getMangledTypeName(TypeImpl type) => type._typeName; - -/** - * Sets the runtime type information on [target]. [typeInfo] is a type - * representation of type 4 or 5, that is, either a JavaScript array or - * `null`. - */ -Object setRuntimeTypeInfo(Object target, var typeInfo) { - assert(typeInfo == null || isJsArray(typeInfo)); - // We have to check for null because factories may return null. - if (target != null) JS('var', r'#.$builtinTypeInfo = #', target, typeInfo); - return target; -} - -/** - * Returns the runtime type information of [target]. The returned value is a - * list of type representations for the type arguments. - */ -getRuntimeTypeInfo(Object target) { - if (target == null) return null; - return JS('var', r'#.$builtinTypeInfo', target); -} - -/** - * Returns the type arguments of [target] as an instance of [substitutionName]. - */ -getRuntimeTypeArguments(target, substitutionName) { - var substitution = - getField(target, '${JS_OPERATOR_AS_PREFIX()}$substitutionName'); - return substitute(substitution, getRuntimeTypeInfo(target)); -} - -/** - * Returns the [index]th type argument of [target] as an instance of - * [substitutionName]. - */ -@NoThrows() @NoSideEffects() @NoInline() -getRuntimeTypeArgument(Object target, String substitutionName, int index) { - var arguments = getRuntimeTypeArguments(target, substitutionName); - return arguments == null ? null : getIndex(arguments, index); -} - -@NoThrows() @NoSideEffects() @NoInline() -getTypeArgumentByIndex(Object target, int index) { - var rti = getRuntimeTypeInfo(target); - return rti == null ? null : getIndex(rti, index); -} - -void copyTypeArguments(Object source, Object target) { - JS('var', r'#.$builtinTypeInfo = #.$builtinTypeInfo', target, source); -} - -/** - * Retrieves the class name from type information stored on the constructor - * of [object]. - */ -String getClassName(var object) { - return JS('String', r'#.constructor.builtin$cls', getInterceptor(object)); -} - -/** - * Creates the string representation for the type representation [runtimeType] - * of type 4, the JavaScript array, where the first element represents the class - * and the remaining elements represent the type arguments. - */ -String getRuntimeTypeAsString(var runtimeType, {String onTypeVariable(int i)}) { - assert(isJsArray(runtimeType)); - String className = getConstructorName(getIndex(runtimeType, 0)); - return '$className' - '${joinArguments(runtimeType, 1, onTypeVariable: onTypeVariable)}'; -} - -/** - * Retrieves the class name from type information stored on the constructor - * [type]. - */ -String getConstructorName(var type) => JS('String', r'#.builtin$cls', type); - -/** - * Returns a human-readable representation of the type representation [type]. - */ -String runtimeTypeToString(var type, {String onTypeVariable(int i)}) { - if (type == null) { - return 'dynamic'; - } else if (isJsArray(type)) { - // A list representing a type with arguments. - return getRuntimeTypeAsString(type, onTypeVariable: onTypeVariable); - } else if (isJsFunction(type)) { - // A reference to the constructor. - return getConstructorName(type); - } else if (type is int) { - if (onTypeVariable == null) { - return type.toString(); - } else { - return onTypeVariable(type); - } - } else { - // TODO(ahe): Handle function types, and be sure to always return a string. - return null; - } -} - -/** - * Creates a comma-separated string of human-readable representations of the - * type representations in the JavaScript array [types] starting at index - * [startIndex]. - */ -String joinArguments(var types, int startIndex, - {String onTypeVariable(int i)}) { - if (types == null) return ''; - assert(isJsArray(types)); - bool firstArgument = true; - bool allDynamic = true; - StringBuffer buffer = new StringBuffer(); - for (int index = startIndex; index < getLength(types); index++) { - if (firstArgument) { - firstArgument = false; - } else { - buffer.write(', '); - } - var argument = getIndex(types, index); - if (argument != null) { - allDynamic = false; - } - buffer.write(runtimeTypeToString(argument, onTypeVariable: onTypeVariable)); - } - return allDynamic ? '' : '<$buffer>'; -} - -/** - * Returns a human-readable representation of the type of [object]. - * - * In minified mode does *not* use unminified identifiers (even when present). - */ -String getRuntimeTypeString(var object) { - String className = getClassName(object); - if (object == null) return className; - var typeInfo = JS('var', r'#.$builtinTypeInfo', object); - return "$className${joinArguments(typeInfo, 0)}"; -} - -Type getRuntimeType(var object) { - String type = getRuntimeTypeString(object); - return new TypeImpl(type); -} - -/** - * Applies the [substitution] on the [arguments]. - * - * See the comment in the beginning of this file for a description of the - * possible values for [substitution]. - */ -substitute(var substitution, var arguments) { - assert(substitution == null || - isJsFunction(substitution)); - assert(arguments == null || isJsArray(arguments)); - if (isJsFunction(substitution)) { - substitution = invoke(substitution, arguments); - if (isJsArray(substitution)) { - arguments = substitution; - } else if (isJsFunction(substitution)) { - // TODO(johnniwinther): Check if this is still needed. - arguments = invoke(substitution, arguments); - } - } - return arguments; -} - -/** - * Perform a type check with arguments on the Dart object [object]. - * - * Parameters: - * - [isField]: the name of the flag/function to check if the object - * is of the correct class. - * - [checks]: the (JavaScript) list of type representations for the - * arguments to check against. - * - [asField]: the name of the function that transforms the type - * arguments of [objects] to an instance of the class that we check - * against. - */ -bool checkSubtype(Object object, String isField, List checks, String asField) { - if (object == null) return false; - var arguments = getRuntimeTypeInfo(object); - // Interceptor is needed for JSArray and native classes. - // TODO(sra): It could be a more specialized interceptor since [object] is not - // `null` or a primitive. - // TODO(9586): Move type info for static functions onto an interceptor. - var interceptor = getInterceptor(object); - var isSubclass = getField(interceptor, isField); - // When we read the field and it is not there, [isSubclass] will be `null`. - if (isSubclass == null) return false; - // Should the asField function be passed the receiver? - var substitution = getField(interceptor, asField); - return checkArguments(substitution, arguments, checks); -} - -/// Returns the field's type name. -/// -/// In minified mode, uses the unminified names if available. -String computeTypeName(String isField, List arguments) { - // Shorten the field name to the class name and append the textual - // representation of the type arguments. - int prefixLength = JS_OPERATOR_IS_PREFIX().length; - return Primitives.formatType(isField.substring(prefixLength, isField.length), - arguments); -} - -Object subtypeCast(Object object, String isField, List checks, String asField) { - if (object != null && !checkSubtype(object, isField, checks, asField)) { - String actualType = Primitives.objectTypeName(object); - String typeName = computeTypeName(isField, checks); - // TODO(johnniwinther): Move type lookup to [CastErrorImplementation] to - // align with [TypeErrorImplementation]. - throw new CastErrorImplementation(actualType, typeName); - } - return object; -} - -Object assertSubtype(Object object, String isField, List checks, - String asField) { - if (object != null && !checkSubtype(object, isField, checks, asField)) { - String typeName = computeTypeName(isField, checks); - throw new TypeErrorImplementation(object, typeName); - } - return object; -} - -/// Checks that the type represented by [subtype] is a subtype of [supertype]. -/// If not a type error with [message] is thrown. -assertIsSubtype(var subtype, var supertype, String message) { - if (!isSubtype(subtype, supertype)) { - throwTypeError(message); - } -} - -throwTypeError(message) { - throw new TypeErrorImplementation.fromMessage(message); -} - -/** - * Check that the types in the list [arguments] are subtypes of the types in - * list [checks] (at the respective positions), possibly applying [substitution] - * to the arguments before the check. - * - * See the comment in the beginning of this file for a description of the - * possible values for [substitution]. - */ -bool checkArguments(var substitution, var arguments, var checks) { - return areSubtypes(substitute(substitution, arguments), checks); -} - -/** - * Checks whether the types of [s] are all subtypes of the types of [t]. - * - * [s] and [t] are either `null` or JavaScript arrays of type representations, - * A `null` argument is interpreted as the arguments of a raw type, that is a - * list of `dynamic`. If [s] and [t] are JavaScript arrays they must be of the - * same length. - * - * See the comment in the beginning of this file for a description of type - * representations. - */ -bool areSubtypes(var s, var t) { - // `null` means a raw type. - if (s == null || t == null) return true; - - assert(isJsArray(s)); - assert(isJsArray(t)); - assert(getLength(s) == getLength(t)); - - int len = getLength(s); - for (int i = 0; i < len; i++) { - if (!isSubtype(getIndex(s, i), getIndex(t, i))) { - return false; - } - } - return true; -} - -/** - * Computes the signature by applying the type arguments of [context] as an - * instance of [contextName] to the signature function [signature]. - */ -computeSignature(var signature, var context, var contextName) { - var typeArguments = getRuntimeTypeArguments(context, contextName); - return invokeOn(signature, context, typeArguments); -} - -/** - * Returns `true` if the runtime type representation [type] is a supertype of - * [Null]. - */ -bool isSupertypeOfNull(var type) { - // `null` means `dynamic`. - return type == null || getConstructorName(type) == JS_OBJECT_CLASS_NAME() - || getConstructorName(type) == JS_NULL_CLASS_NAME(); -} - -/** - * Tests whether the Dart object [o] is a subtype of the runtime type - * representation [t]. - * - * See the comment in the beginning of this file for a description of type - * representations. - */ -bool checkSubtypeOfRuntimeType(o, t) { - if (o == null) return isSupertypeOfNull(t); - if (t == null) return true; - // Get the runtime type information from the object here, because we may - // overwrite o with the interceptor below. - var rti = getRuntimeTypeInfo(o); - o = getInterceptor(o); - var type = JS('', '#.constructor', o); - if (rti != null) { - // If the type has type variables (that is, `rti != null`), make a copy of - // the type arguments and insert [o] in the first position to create a - // compound type representation. - rti = JS('JSExtendableArray', '#.slice()', rti); // Make a copy. - JS('', '#.splice(0, 0, #)', rti, type); // Insert type at position 0. - type = rti; - } else if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) { - // Functions are treated specially and have their type information stored - // directly in the instance. - var signatureName = - '${JS_OPERATOR_IS_PREFIX()}_${getField(t, JS_FUNCTION_TYPE_TAG())}'; - if (hasField(o, signatureName)) return true; - var targetSignatureFunction = getField(o, '${JS_SIGNATURE_NAME()}'); - if (targetSignatureFunction == null) return false; - type = invokeOn(targetSignatureFunction, o, null); - return isFunctionSubtype(type, t); - } - return isSubtype(type, t); -} - -Object subtypeOfRuntimeTypeCast(Object object, var type) { - if (object != null && !checkSubtypeOfRuntimeType(object, type)) { - String actualType = Primitives.objectTypeName(object); - throw new CastErrorImplementation(actualType, runtimeTypeToString(type)); - } - return object; -} - -Object assertSubtypeOfRuntimeType(Object object, var type) { - if (object != null && !checkSubtypeOfRuntimeType(object, type)) { - throw new TypeErrorImplementation(object, runtimeTypeToString(type)); - } - return object; -} - -/** - * Extracts the type arguments from a type representation. The result is a - * JavaScript array or `null`. - */ -getArguments(var type) { - return isJsArray(type) ? JS('var', r'#.slice(1)', type) : null; -} - -/** - * Checks whether the type represented by the type representation [s] is a - * subtype of the type represented by the type representation [t]. - * - * See the comment in the beginning of this file for a description of type - * representations. - * - * The arguments [s] and [t] must be types, usually represented by the - * constructor of the class, or an array (for generic types). - */ -bool isSubtype(var s, var t) { - // Subtyping is reflexive. - if (isIdentical(s, t)) return true; - // If either type is dynamic, [s] is a subtype of [t]. - if (s == null || t == null) return true; - if (hasField(t, '${JS_FUNCTION_TYPE_TAG()}')) { - return isFunctionSubtype(s, t); - } - // Check function types against the Function class. - if (hasField(s, '${JS_FUNCTION_TYPE_TAG()}')) { - return getConstructorName(t) == JS_FUNCTION_CLASS_NAME(); - } - - // Get the object describing the class and check for the subtyping flag - // constructed from the type of [t]. - var typeOfS = isJsArray(s) ? getIndex(s, 0) : s; - var typeOfT = isJsArray(t) ? getIndex(t, 0) : t; - // Check for a subtyping flag. - var name = runtimeTypeToString(typeOfT); - // Get the necessary substitution of the type arguments, if there is one. - var substitution; - if (isNotIdentical(typeOfT, typeOfS)) { - var test = '${JS_OPERATOR_IS_PREFIX()}${name}'; - var typeOfSPrototype = JS('', '#.prototype', typeOfS); - if (hasNoField(typeOfSPrototype, test)) return false; - var field = '${JS_OPERATOR_AS_PREFIX()}${runtimeTypeToString(typeOfT)}'; - substitution = getField(typeOfSPrototype, field); - } - // The class of [s] is a subclass of the class of [t]. If [s] has no type - // arguments and no substitution, it is used as raw type. If [t] has no - // type arguments, it used as a raw type. In both cases, [s] is a subtype - // of [t]. - if ((!isJsArray(s) && substitution == null) || !isJsArray(t)) { - return true; - } - // Recursively check the type arguments. - return checkArguments(substitution, getArguments(s), getArguments(t)); -} - -bool isAssignable(var s, var t) { - return isSubtype(s, t) || isSubtype(t, s); -} - -/** - * If [allowShorter] is `true`, [t] is allowed to be shorter than [s]. - */ -bool areAssignable(List s, List t, bool allowShorter) { - // Both lists are empty and thus equal. - if (t ==null && s == null) return true; - // [t] is empty (and [s] is not) => only OK if [allowShorter]. - if (t == null) return allowShorter; - // [s] is empty (and [t] is not) => [s] is not longer or equal to [t]. - if (s == null) return false; - - assert(isJsArray(s)); - assert(isJsArray(t)); - - int sLength = getLength(s); - int tLength = getLength(t); - if (allowShorter) { - if (sLength < tLength) return false; - } else { - if (sLength != tLength) return false; - } - - for (int i = 0; i < tLength; i++) { - if (!isAssignable(getIndex(s, i), getIndex(t, i))) { - return false; - } - } - return true; -} - -bool areAssignableMaps(var s, var t) { - if (t == null) return true; - if (s == null) return false; - - assert(isJsObject(s)); - assert(isJsObject(t)); - - List names = - JSArray.markFixedList(JS('', 'Object.getOwnPropertyNames(#)', t)); - for (int i = 0; i < names.length; i++) { - var name = names[i]; - if (JS('bool', '!Object.hasOwnProperty.call(#, #)', s, name)) { - return false; - } - var tType = JS('', '#[#]', t, name); - var sType = JS('', '#[#]', s, name); - if (!isAssignable(tType, sType)) return false; - } - return true; -} - -bool isFunctionSubtype(var s, var t) { - assert(hasField(t, '${JS_FUNCTION_TYPE_TAG()}')); - if (hasNoField(s, '${JS_FUNCTION_TYPE_TAG()}')) return false; - if (hasField(s, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}')) { - if (hasNoField(t, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}') && - hasField(t, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}')) { - return false; - } - } else if (hasNoField(t, '${JS_FUNCTION_TYPE_VOID_RETURN_TAG()}')) { - var sReturnType = getField(s, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}'); - var tReturnType = getField(t, '${JS_FUNCTION_TYPE_RETURN_TYPE_TAG()}'); - if (!isAssignable(sReturnType, tReturnType)) return false; - } - var sParameterTypes = - getField(s, '${JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG()}'); - var tParameterTypes = - getField(t, '${JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG()}'); - - var sOptionalParameterTypes = - getField(s, '${JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG()}'); - var tOptionalParameterTypes = - getField(t, '${JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG()}'); - - int sParametersLen = sParameterTypes != null ? getLength(sParameterTypes) : 0; - int tParametersLen = tParameterTypes != null ? getLength(tParameterTypes) : 0; - - int sOptionalParametersLen = - sOptionalParameterTypes != null ? getLength(sOptionalParameterTypes) : 0; - int tOptionalParametersLen = - tOptionalParameterTypes != null ? getLength(tOptionalParameterTypes) : 0; - - if (sParametersLen > tParametersLen) { - // Too many required parameters in [s]. - return false; - } - if (sParametersLen + sOptionalParametersLen < - tParametersLen + tOptionalParametersLen) { - // Too few required and optional parameters in [s]. - return false; - } - if (sParametersLen == tParametersLen) { - // Simple case: Same number of required parameters. - if (!areAssignable(sParameterTypes, tParameterTypes, false)) return false; - if (!areAssignable(sOptionalParameterTypes, - tOptionalParameterTypes, true)) { - return false; - } - } else { - // Complex case: Optional parameters of [s] for required parameters of [t]. - int pos = 0; - // Check all required parameters of [s]. - for (; pos < sParametersLen; pos++) { - if (!isAssignable(getIndex(sParameterTypes, pos), - getIndex(tParameterTypes, pos))) { - return false; - } - } - int sPos = 0; - int tPos = pos; - // Check the remaining parameters of [t] with the first optional parameters - // of [s]. - for (; tPos < tParametersLen ; sPos++, tPos++) { - if (!isAssignable(getIndex(sOptionalParameterTypes, sPos), - getIndex(tParameterTypes, tPos))) { - return false; - } - } - tPos = 0; - // Check the optional parameters of [t] with the remaining optional - // parameters of [s]: - for (; tPos < tOptionalParametersLen ; sPos++, tPos++) { - if (!isAssignable(getIndex(sOptionalParameterTypes, sPos), - getIndex(tOptionalParameterTypes, tPos))) { - return false; - } - } - } - - var sNamedParameters = - getField(s, '${JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG()}'); - var tNamedParameters = - getField(t, '${JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG()}'); - return areAssignableMaps(sNamedParameters, tNamedParameters); -} - -/** - * Calls the JavaScript [function] with the [arguments] with the global scope - * as the `this` context. - */ -invoke(var function, var arguments) => invokeOn(function, null, arguments); - -/** - * Calls the JavaScript [function] with the [arguments] with [receiver] as the - * `this` context. - */ -Object invokeOn(function, receiver, arguments) { - assert(isJsFunction(function)); - assert(arguments == null || isJsArray(arguments)); - return JS('var', r'#.apply(#, #)', function, receiver, arguments); -} - -/// Calls the property [name] on the JavaScript [object]. -call(var object, String name) => JS('var', r'#[#]()', object, name); - -/// Returns the property [name] of the JavaScript object [object]. -getField(var object, String name) => JS('var', r'#[#]', object, name); - -/// Returns the property [index] of the JavaScript array [array]. -getIndex(var array, int index) { - assert(isJsArray(array)); - return JS('var', r'#[#]', array, index); -} - -/// Returns the length of the JavaScript array [array]. -int getLength(var array) { - assert(isJsArray(array)); - return JS('int', r'#.length', array); -} - -/// Returns whether [value] is a JavaScript array. -bool isJsArray(var value) { - return value is JSArray; -} - -hasField(var object, var name) => JS('bool', r'# in #', name, object); - -hasNoField(var object, var name) => !hasField(object, name); - -/// Returns `true` if [o] is a JavaScript function. -bool isJsFunction(var o) => JS('bool', r'typeof # == "function"', o); - -/// Returns `true` if [o] is a JavaScript object. -bool isJsObject(var o) => JS('bool', r"typeof # == 'object'", o); - -/** - * Returns `true` if the JavaScript values [s] and [t] are identical. We use - * this helper instead of [identical] because `identical` needs to merge - * `null` and `undefined` (which we can avoid). - */ -bool isIdentical(var s, var t) => JS('bool', '# === #', s, t); - -/** - * Returns `true` if the JavaScript values [s] and [t] are not identical. We use - * this helper instead of [identical] because `identical` needs to merge - * `null` and `undefined` (which we can avoid). - */ -bool isNotIdentical(var s, var t) => JS('bool', '# !== #', s, t); diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_string.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_string.dart deleted file mode 100644 index c7fd9aba51aa..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/js_string.dart +++ /dev/null @@ -1,471 +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. - -part of _interceptors; - -/** - * The interceptor class for [String]. The compiler recognizes this - * class as an interceptor, and changes references to [:this:] to - * actually use the receiver of the method, which is generated as an extra - * argument added to each member. - */ -class JSString extends Interceptor implements String, JSIndexable { - const JSString(); - - int codeUnitAt(int index) { - if (index is !int) throw new ArgumentError(index); - if (index < 0) throw new RangeError.value(index); - if (index >= length) throw new RangeError.value(index); - return JS('JSUInt31', r'#.charCodeAt(#)', this, index); - } - - Iterable allMatches(String string, [int start = 0]) { - checkString(string); - checkInt(start); - if (0 > start || start > string.length) { - throw new RangeError.range(start, 0, string.length); - } - return allMatchesInStringUnchecked(this, string, start); - } - - Match matchAsPrefix(String string, [int start = 0]) { - if (start < 0 || start > string.length) { - throw new RangeError.range(start, 0, string.length); - } - if (start + this.length > string.length) return null; - // TODO(lrn): See if this can be optimized. - for (int i = 0; i < this.length; i++) { - if (string.codeUnitAt(start + i) != this.codeUnitAt(i)) { - return null; - } - } - return new StringMatch(start, string, this); - } - - String operator +(String other) { - if (other is !String) throw new ArgumentError(other); - return JS('String', r'# + #', this, other); - } - - bool endsWith(String other) { - checkString(other); - int otherLength = other.length; - if (otherLength > length) return false; - return other == substring(length - otherLength); - } - - String replaceAll(Pattern from, String to) { - checkString(to); - return stringReplaceAllUnchecked(this, from, to); - } - - String replaceAllMapped(Pattern from, String convert(Match match)) { - return this.splitMapJoin(from, onMatch: convert); - } - - String splitMapJoin(Pattern from, - {String onMatch(Match match), - String onNonMatch(String nonMatch)}) { - return stringReplaceAllFuncUnchecked(this, from, onMatch, onNonMatch); - } - - String replaceFirst(Pattern from, String to, [int startIndex = 0]) { - checkString(to); - checkInt(startIndex); - if (startIndex < 0 || startIndex > this.length) { - throw new RangeError.range(startIndex, 0, this.length); - } - return stringReplaceFirstUnchecked(this, from, to, startIndex); - } - - List split(Pattern pattern) { - checkNull(pattern); - if (pattern is String) { - return JS('JSExtendableArray', r'#.split(#)', this, pattern); - } else if (pattern is JSSyntaxRegExp && regExpCaptureCount(pattern) == 0) { - var re = regExpGetNative(pattern); - return JS('JSExtendableArray', r'#.split(#)', this, re); - } else { - return _defaultSplit(pattern); - } - } - - List _defaultSplit(Pattern pattern) { - List result = []; - // End of most recent match. That is, start of next part to add to result. - int start = 0; - // Length of most recent match. - // Set >0, so no match on the empty string causes the result to be [""]. - int length = 1; - for (var match in pattern.allMatches(this)) { - int matchStart = match.start; - int matchEnd = match.end; - length = matchEnd - matchStart; - if (length == 0 && start == matchStart) { - // An empty match right after another match is ignored. - // This includes an empty match at the start of the string. - continue; - } - int end = matchStart; - result.add(this.substring(start, end)); - start = matchEnd; - } - if (start < this.length || length > 0) { - // An empty match at the end of the string does not cause a "" at the end. - // A non-empty match ending at the end of the string does add a "". - result.add(this.substring(start)); - } - return result; - } - - bool startsWith(Pattern pattern, [int index = 0]) { - checkInt(index); - if (index < 0 || index > this.length) { - throw new RangeError.range(index, 0, this.length); - } - if (pattern is String) { - String other = pattern; - int otherLength = other.length; - int endIndex = index + otherLength; - if (endIndex > length) return false; - return other == JS('String', r'#.substring(#, #)', this, index, endIndex); - } - return pattern.matchAsPrefix(this, index) != null; - } - - String substring(int startIndex, [int endIndex]) { - checkInt(startIndex); - if (endIndex == null) endIndex = length; - checkInt(endIndex); - if (startIndex < 0 ) throw new RangeError.value(startIndex); - if (startIndex > endIndex) throw new RangeError.value(startIndex); - if (endIndex > length) throw new RangeError.value(endIndex); - return JS('String', r'#.substring(#, #)', this, startIndex, endIndex); - } - - String toLowerCase() { - return JS('String', r'#.toLowerCase()', this); - } - - String toUpperCase() { - return JS('String', r'#.toUpperCase()', this); - } - - // Characters with Whitespace property (Unicode 6.2). - // 0009..000D ; White_Space # Cc .. - // 0020 ; White_Space # Zs SPACE - // 0085 ; White_Space # Cc - // 00A0 ; White_Space # Zs NO-BREAK SPACE - // 1680 ; White_Space # Zs OGHAM SPACE MARK - // 180E ; White_Space # Zs MONGOLIAN VOWEL SEPARATOR - // 2000..200A ; White_Space # Zs EN QUAD..HAIR SPACE - // 2028 ; White_Space # Zl LINE SEPARATOR - // 2029 ; White_Space # Zp PARAGRAPH SEPARATOR - // 202F ; White_Space # Zs NARROW NO-BREAK SPACE - // 205F ; White_Space # Zs MEDIUM MATHEMATICAL SPACE - // 3000 ; White_Space # Zs IDEOGRAPHIC SPACE - // - // BOM: 0xFEFF - static bool _isWhitespace(int codeUnit) { - // Most codeUnits should be less than 256. Special case with a smaller - // switch. - if (codeUnit < 256) { - switch (codeUnit) { - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x20: - case 0x85: - case 0xA0: - return true; - default: - return false; - } - } - switch (codeUnit) { - case 0x1680: - case 0x180E: - case 0x2000: - case 0x2001: - case 0x2002: - case 0x2003: - case 0x2004: - case 0x2005: - case 0x2006: - case 0x2007: - case 0x2008: - case 0x2009: - case 0x200A: - case 0x2028: - case 0x2029: - case 0x202F: - case 0x205F: - case 0x3000: - case 0xFEFF: - return true; - default: - return false; - } - } - - /// Finds the index of the first non-whitespace character, or the - /// end of the string. Start looking at position [index]. - static int _skipLeadingWhitespace(String string, int index) { - const int SPACE = 0x20; - const int CARRIAGE_RETURN = 0x0D; - while (index < string.length) { - int codeUnit = string.codeUnitAt(index); - if (codeUnit != SPACE && - codeUnit != CARRIAGE_RETURN && - !_isWhitespace(codeUnit)) { - break; - } - index++; - } - return index; - } - - /// Finds the index after the the last non-whitespace character, or 0. - /// Start looking at position [index - 1]. - static int _skipTrailingWhitespace(String string, int index) { - const int SPACE = 0x20; - const int CARRIAGE_RETURN = 0x0D; - while (index > 0) { - int codeUnit = string.codeUnitAt(index - 1); - if (codeUnit != SPACE && - codeUnit != CARRIAGE_RETURN && - !_isWhitespace(codeUnit)) { - break; - } - index--; - } - return index; - } - - // Dart2js can't use JavaScript trim directly, - // because JavaScript does not trim - // the NEXT LINE (NEL) character (0x85). - String trim() { - const int NEL = 0x85; - - // Start by doing JS trim. Then check if it leaves a NEL at - // either end of the string. - String result = JS('String', '#.trim()', this); - if (result.length == 0) return result; - int firstCode = result.codeUnitAt(0); - int startIndex = 0; - if (firstCode == NEL) { - startIndex = _skipLeadingWhitespace(result, 1); - if (startIndex == result.length) return ""; - } - - int endIndex = result.length; - // We know that there is at least one character that is non-whitespace. - // Therefore we don't need to verify that endIndex > startIndex. - int lastCode = result.codeUnitAt(endIndex - 1); - if (lastCode == NEL) { - endIndex = _skipTrailingWhitespace(result, endIndex - 1); - } - if (startIndex == 0 && endIndex == result.length) return result; - return JS('String', r'#.substring(#, #)', result, startIndex, endIndex); - } - - // Dart2js can't use JavaScript trimLeft directly, - // because it is not in ES5, so not every browser implements it, - // and because those that do will not trim the NEXT LINE character (0x85). - String trimLeft() { - const int NEL = 0x85; - - // Start by doing JS trim. Then check if it leaves a NEL at - // the beginning of the string. - String result; - int startIndex = 0; - if (JS('bool', 'typeof #.trimLeft != "undefined"', this)) { - result = JS('String', '#.trimLeft()', this); - if (result.length == 0) return result; - int firstCode = result.codeUnitAt(0); - if (firstCode == NEL) { - startIndex = _skipLeadingWhitespace(result, 1); - } - } else { - result = this; - startIndex = _skipLeadingWhitespace(this, 0); - } - if (startIndex == 0) return result; - if (startIndex == result.length) return ""; - return JS('String', r'#.substring(#)', result, startIndex); - } - - // Dart2js can't use JavaScript trimRight directly, - // because it is not in ES5 and because JavaScript does not trim - // the NEXT LINE character (0x85). - String trimRight() { - const int NEL = 0x85; - - // Start by doing JS trim. Then check if it leaves a NEL or BOM at - // the end of the string. - String result; - int endIndex; - // trimRight is implemented by Firefox and Chrome/Blink, - // so use it if it is there. - if (JS('bool', 'typeof #.trimRight != "undefined"', this)) { - result = JS('String', '#.trimRight()', this); - endIndex = result.length; - if (endIndex == 0) return result; - int lastCode = result.codeUnitAt(endIndex - 1); - if (lastCode == NEL) { - endIndex = _skipTrailingWhitespace(result, endIndex - 1); - } - } else { - result = this; - endIndex = _skipTrailingWhitespace(this, this.length); - } - - if (endIndex == result.length) return result; - if (endIndex == 0) return ""; - return JS('String', r'#.substring(#, #)', result, 0, endIndex); - } - - String operator*(int times) { - if (0 >= times) return ''; // Unnecessary but hoists argument type check. - if (times == 1 || this.length == 0) return this; - if (times != JS('JSUInt32', '# >>> 0', times)) { - // times >= 2^32. We can't create a string that big. - throw const OutOfMemoryError(); - } - var result = ''; - var s = this; - while (true) { - if (times & 1 == 1) result = s + result; - times = JS('JSUInt31', '# >>> 1', times); - if (times == 0) break; - s += s; - } - return result; - } - - String padLeft(int width, [String padding = ' ']) { - int delta = width - this.length; - if (delta <= 0) return this; - return padding * delta + this; - } - - String padRight(int width, [String padding = ' ']) { - int delta = width - this.length; - if (delta <= 0) return this; - return this + padding * delta; - } - - List get codeUnits => new _CodeUnits(this); - - Runes get runes => new Runes(this); - - int indexOf(Pattern pattern, [int start = 0]) { - checkNull(pattern); - if (start is! int) throw new ArgumentError(start); - if (start < 0 || start > this.length) { - throw new RangeError.range(start, 0, this.length); - } - if (pattern is String) { - return JS('int', r'#.indexOf(#, #)', this, pattern, start); - } - if (pattern is JSSyntaxRegExp) { - JSSyntaxRegExp re = pattern; - Match match = firstMatchAfter(re, this, start); - return (match == null) ? -1 : match.start; - } - for (int i = start; i <= this.length; i++) { - if (pattern.matchAsPrefix(this, i) != null) return i; - } - return -1; - } - - int lastIndexOf(Pattern pattern, [int start]) { - checkNull(pattern); - if (start == null) { - start = length; - } else if (start is! int) { - throw new ArgumentError(start); - } else if (start < 0 || start > this.length) { - throw new RangeError.range(start, 0, this.length); - } - if (pattern is String) { - String other = pattern; - if (start + other.length > this.length) { - start = this.length - other.length; - } - return stringLastIndexOfUnchecked(this, other, start); - } - for (int i = start; i >= 0; i--) { - if (pattern.matchAsPrefix(this, i) != null) return i; - } - return -1; - } - - bool contains(Pattern other, [int startIndex = 0]) { - checkNull(other); - if (startIndex < 0 || startIndex > this.length) { - throw new RangeError.range(startIndex, 0, this.length); - } - return stringContainsUnchecked(this, other, startIndex); - } - - bool get isEmpty => length == 0; - - bool get isNotEmpty => !isEmpty; - - int compareTo(String other) { - if (other is !String) throw new ArgumentError(other); - return this == other ? 0 - : JS('bool', r'# < #', this, other) ? -1 : 1; - } - - // Note: if you change this, also change the function [S]. - String toString() => this; - - /** - * This is the [Jenkins hash function][1] but using masking to keep - * values in SMI range. - * - * [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function - */ - int get hashCode { - // TODO(ahe): This method shouldn't have to use JS. Update when our - // optimizations are smarter. - int hash = 0; - for (int i = 0; i < length; i++) { - hash = 0x1fffffff & (hash + JS('int', r'#.charCodeAt(#)', this, i)); - hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); - hash = JS('int', '# ^ (# >> 6)', hash, hash); - } - hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); - hash = JS('int', '# ^ (# >> 11)', hash, hash); - return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); - } - - Type get runtimeType => String; - - int get length => JS('int', r'#.length', this); - - String operator [](int index) { - if (index is !int) throw new ArgumentError(index); - if (index >= length || index < 0) throw new RangeError.value(index); - return JS('String', '#[#]', this, index); - } -} - -/** - * An [Iterable] of the UTF-16 code units of a [String] in index order. - */ -class _CodeUnits extends UnmodifiableListBase { - /** The string that this is the code units of. */ - String _string; - - _CodeUnits(this._string); - - int get length => _string.length; - int operator[](int i) => _string.codeUnitAt(i); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/mirror_helper.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/mirror_helper.dart deleted file mode 100644 index 9c3024fa6068..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/mirror_helper.dart +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. -/** - * Helps dealing with reflection in the case that the source code has been - * changed as a result of compiling with dart2dart. - */ -library _mirror_helper; - -import 'dart:mirrors'; - -/// The compiler will replace this variable with a map containing all the -/// renames made in dart2dart. -const Map _SYMBOLS = null; - -/// This method is a wrapper for MirrorSystem.getName() and will be inlined and -/// called in the generated output Dart code. -String helperGetName(Symbol sym) { - var name = MirrorSystem.getName(sym); - if (_SYMBOLS.containsKey(name)) { - return _SYMBOLS[name]; - } else { - return name; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/native_helper.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/native_helper.dart deleted file mode 100644 index bec5bbae9b95..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/native_helper.dart +++ /dev/null @@ -1,652 +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. - -part of _js_helper; - - -// TODO(ngeoffray): stop using this method once our optimizers can -// change str1.contains(str2) into str1.indexOf(str2) != -1. -bool contains(String userAgent, String name) { - return JS('int', '#.indexOf(#)', userAgent, name) != -1; -} - -int arrayLength(List array) { - return JS('int', '#.length', array); -} - -arrayGet(List array, int index) { - return JS('var', '#[#]', array, index); -} - -void arraySet(List array, int index, var value) { - JS('var', '#[#] = #', array, index, value); -} - -propertyGet(var object, String property) { - return JS('var', '#[#]', object, property); -} - -bool callHasOwnProperty(var function, var object, String property) { - return JS('bool', '#.call(#, #)', function, object, property); -} - -void propertySet(var object, String property, var value) { - JS('var', '#[#] = #', object, property, value); -} - -getPropertyFromPrototype(var object, String name) { - return JS('var', 'Object.getPrototypeOf(#)[#]', object, name); -} - -/** - * Returns a String tag identifying the type of the native object, or `null`. - * The tag is not the name of the type, but usually the name of the JavaScript - * constructor function. Initialized by [initHooks]. - */ -Function getTagFunction; - -/** - * If a lookup via [getTagFunction] on an object [object] that has [tag] fails, - * this function is called to provide an alternate tag. This allows us to fail - * gracefully if we can make a good guess, for example, when browsers add novel - * kinds of HTMLElement that we have never heard of. Initialized by - * [initHooks]. - */ -Function alternateTagFunction; - -/** - * Returns the prototype for the JavaScript constructor named by an input tag. - * Returns `null` if there is no such constructor, or if pre-patching of the - * constructor is to be avoided. Initialized by [initHooks]. - */ -Function prototypeForTagFunction; - - -String toStringForNativeObject(var obj) { - // TODO(sra): Is this code dead? - // [getTagFunction] might be uninitialized, but in usual usage, toString has - // been called via an interceptor and initialized it. - String name = getTagFunction == null - ? '' - : JS('String', '#', getTagFunction(obj)); - return 'Instance of $name'; -} - -int hashCodeForNativeObject(object) => Primitives.objectHashCode(object); - -/** - * Sets a JavaScript property on an object. - */ -void defineProperty(var obj, String property, var value) { - JS('void', - 'Object.defineProperty(#, #, ' - '{value: #, enumerable: false, writable: true, configurable: true})', - obj, - property, - value); -} - - -// Is [obj] an instance of a Dart-defined class? -bool isDartObject(obj) { - // Some of the extra parens here are necessary. - return JS('bool', '((#) instanceof (#))', obj, JS_DART_OBJECT_CONSTRUCTOR()); -} - -/** - * A JavaScript object mapping tags to the constructors of interceptors. - * This is a JavaScript object with no prototype. - * - * Example: 'HTMLImageElement' maps to the ImageElement class constructor. - */ -get interceptorsByTag => JS_EMBEDDED_GLOBAL('=Object', INTERCEPTORS_BY_TAG); - -/** - * A JavaScript object mapping tags to `true` or `false`. - * - * Example: 'HTMLImageElement' maps to `true` since, as there are no subclasses - * of ImageElement, it is a leaf class in the native class hierarchy. - */ -get leafTags => JS_EMBEDDED_GLOBAL('=Object', LEAF_TAGS); - -String findDispatchTagForInterceptorClass(interceptorClassConstructor) { - return JS('', r'#.#', - interceptorClassConstructor, NATIVE_SUPERCLASS_TAG_NAME); -} - -/** - * Cache of dispatch records for instances. This is a JavaScript object used as - * a map. Keys are instance tags, e.g. "!SomeThing". The cache permits the - * sharing of one dispatch record between multiple instances. - */ -var dispatchRecordsForInstanceTags; - -/** - * Cache of interceptors indexed by uncacheable tags, e.g. "~SomeThing". - * This is a JavaScript object used as a map. - */ -var interceptorsForUncacheableTags; - - -lookupInterceptor(String tag) { - return propertyGet(interceptorsByTag, tag); -} - - -// Dispatch tag marks are optional prefixes for a dispatch tag that direct how -// the interceptor for the tag may be cached. - -/// No caching permitted. -const UNCACHED_MARK = '~'; - -/// Dispatch record must be cached per instance -const INSTANCE_CACHED_MARK = '!'; - -/// Dispatch record is cached on immediate prototype. -const LEAF_MARK = '-'; - -/// Dispatch record is cached on immediate prototype with a prototype -/// verification to prevent the interceptor being associated with a subclass -/// before a dispatch record is cached on the subclass. -const INTERIOR_MARK = '+'; - -/// A 'discriminator' function is to be used. TBD. -const DISCRIMINATED_MARK = '*'; - - -/** - * Returns the interceptor for a native object, or returns `null` if not found. - * - * A dispatch record is cached according to the specification of the dispatch - * tag for [obj]. - */ -lookupAndCacheInterceptor(obj) { - assert(!isDartObject(obj)); - String tag = getTagFunction(obj); - - // Fast path for instance (and uncached) tags because the lookup is repeated - // for each instance (or getInterceptor call). - var record = propertyGet(dispatchRecordsForInstanceTags, tag); - if (record != null) return patchInstance(obj, record); - var interceptor = propertyGet(interceptorsForUncacheableTags, tag); - if (interceptor != null) return interceptor; - - // This lookup works for derived dispatch tags because we add them all in - // [initNativeDispatch]. - var interceptorClass = lookupInterceptor(tag); - if (interceptorClass == null) { - tag = alternateTagFunction(obj, tag); - if (tag != null) { - // Fast path for instance and uncached tags again. - record = propertyGet(dispatchRecordsForInstanceTags, tag); - if (record != null) return patchInstance(obj, record); - interceptor = propertyGet(interceptorsForUncacheableTags, tag); - if (interceptor != null) return interceptor; - - interceptorClass = lookupInterceptor(tag); - } - } - - if (interceptorClass == null) { - // This object is not known to Dart. There could be several reasons for - // that, including (but not limited to): - // - // * A bug in native code (hopefully this is caught during development). - // * An unknown DOM object encountered. - // * JavaScript code running in an unexpected context. For example, on - // node.js. - return null; - } - - interceptor = JS('', '#.prototype', interceptorClass); - - var mark = JS('String|Null', '#[0]', tag); - - if (mark == INSTANCE_CACHED_MARK) { - record = makeLeafDispatchRecord(interceptor); - propertySet(dispatchRecordsForInstanceTags, tag, record); - return patchInstance(obj, record); - } - - if (mark == UNCACHED_MARK) { - propertySet(interceptorsForUncacheableTags, tag, interceptor); - return interceptor; - } - - if (mark == LEAF_MARK) { - return patchProto(obj, makeLeafDispatchRecord(interceptor)); - } - - if (mark == INTERIOR_MARK) { - return patchInteriorProto(obj, interceptor); - } - - if (mark == DISCRIMINATED_MARK) { - // TODO(sra): Use discriminator of tag. - throw new UnimplementedError(tag); - } - - // [tag] was not explicitly an interior or leaf tag, so - var isLeaf = JS('bool', '(#[#]) === true', leafTags, tag); - if (isLeaf) { - return patchProto(obj, makeLeafDispatchRecord(interceptor)); - } else { - return patchInteriorProto(obj, interceptor); - } -} - -patchInstance(obj, record) { - setDispatchProperty(obj, record); - return dispatchRecordInterceptor(record); -} - -patchProto(obj, record) { - setDispatchProperty(JS('', 'Object.getPrototypeOf(#)', obj), record); - return dispatchRecordInterceptor(record); -} - -patchInteriorProto(obj, interceptor) { - var proto = JS('', 'Object.getPrototypeOf(#)', obj); - var record = makeDispatchRecord(interceptor, proto, null, null); - setDispatchProperty(proto, record); - return interceptor; -} - - -makeLeafDispatchRecord(interceptor) { - var fieldName = JS_IS_INDEXABLE_FIELD_NAME(); - bool indexability = JS('bool', r'!!#[#]', interceptor, fieldName); - return makeDispatchRecord(interceptor, false, null, indexability); -} - -makeDefaultDispatchRecord(tag, interceptorClass, proto) { - var interceptor = JS('', '#.prototype', interceptorClass); - var isLeaf = JS('bool', '(#[#]) === true', leafTags, tag); - if (isLeaf) { - return makeLeafDispatchRecord(interceptor); - } else { - return makeDispatchRecord(interceptor, proto, null, null); - } -} - -/** - * [proto] should have no shadowing prototypes that are not also assigned a - * dispatch rescord. - */ -setNativeSubclassDispatchRecord(proto, interceptor) { - setDispatchProperty(proto, makeLeafDispatchRecord(interceptor)); -} - -String constructorNameFallback(object) { - return JS('String', '#(#)', _constructorNameFallback, object); -} - - -var initNativeDispatchFlag; // null or true - -void initNativeDispatch() { - if (true == initNativeDispatchFlag) return; - initNativeDispatchFlag = true; - initNativeDispatchContinue(); -} - -void initNativeDispatchContinue() { - - dispatchRecordsForInstanceTags = JS('', 'Object.create(null)'); - interceptorsForUncacheableTags = JS('', 'Object.create(null)'); - - initHooks(); - - // Try to pro-actively patch prototypes of DOM objects. For each of our known - // tags `TAG`, if `window.TAG` is a (constructor) function, set the dispatch - // property if the function's prototype to a dispatch record. - var map = interceptorsByTag; - var tags = JS('JSMutableArray', 'Object.getOwnPropertyNames(#)', map); - - if (JS('bool', 'typeof window != "undefined"')) { - var context = JS('=Object', 'window'); - var fun = JS('=Object', 'function () {}'); - for (int i = 0; i < tags.length; i++) { - var tag = tags[i]; - var proto = prototypeForTagFunction(tag); - if (proto != null) { - var interceptorClass = JS('', '#[#]', map, tag); - var record = makeDefaultDispatchRecord(tag, interceptorClass, proto); - if (record != null) { - setDispatchProperty(proto, record); - // Ensure the modified prototype is still fast by assigning it to - // the prototype property of a function object. - JS('', '#.prototype = #', fun, proto); - } - } - } - } - - // [interceptorsByTag] maps 'plain' dispatch tags. Add all the derived - // dispatch tags to simplify lookup of derived tags. - for (int i = 0; i < tags.length; i++) { - var tag = JS('String', '#[#]', tags, i); - if (JS('bool', '/^[A-Za-z_]/.test(#)', tag)) { - var interceptorClass = propertyGet(map, tag); - propertySet(map, INSTANCE_CACHED_MARK + tag, interceptorClass); - propertySet(map, UNCACHED_MARK + tag, interceptorClass); - propertySet(map, LEAF_MARK + tag, interceptorClass); - propertySet(map, INTERIOR_MARK + tag, interceptorClass); - propertySet(map, DISCRIMINATED_MARK + tag, interceptorClass); - } - } -} - - -/** - * Initializes [getTagFunction] and [alternateTagFunction]. - * - * These functions are 'hook functions', collectively 'hooks'. They initialized - * by applying a series of hooks transformers. Built-in hooks transformers deal - * with various known browser behaviours. - * - * Each hook tranformer takes a 'hooks' input which is a JavaScript object - * containing the hook functions, and returns the same or a new object with - * replacements. The replacements can wrap the originals to provide alternate - * or modified behaviour. - * - * { getTag: function(obj) {...}, - * getUnknownTag: function(obj, tag) {...}, - * prototypeForTag: function(tag) {...}, - * discriminator: function(tag) {...}, - * } - * - * * getTag(obj) returns the dispatch tag, or `null`. - * * getUnknownTag(obj, tag) returns a tag when [getTag] fails. - * * prototypeForTag(tag) returns the prototype of the constructor for tag, - * or `null` if not available or prepatching is undesirable. - * * discriminator(tag) returns a function TBD. - * - * The web site can adapt a dart2js application by loading code ahead of the - * dart2js application that defines hook transformers to be after the built in - * ones. Code defining a transformer HT should use the following pattern to - * ensure multiple transformers can be composed: - * - * (dartNativeDispatchHooksTransformer = - * window.dartNativeDispatchHooksTransformer || []).push(HT); - * - * - * TODO: Implement and describe dispatch tags and their caching methods. - */ -void initHooks() { - // The initial simple hooks: - var hooks = JS('', '#()', _baseHooks); - - // Customize for browsers where `object.constructor.name` fails: - var _fallbackConstructorHooksTransformer = - JS('', '#(#)', _fallbackConstructorHooksTransformerGenerator, - _constructorNameFallback); - hooks = applyHooksTransformer(_fallbackConstructorHooksTransformer, hooks); - - // Customize for browsers: - hooks = applyHooksTransformer(_firefoxHooksTransformer, hooks); - hooks = applyHooksTransformer(_ieHooksTransformer, hooks); - 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, - hooks); - - // Apply global hooks. - // - // If defined, dartNativeDispatchHookdTransformer should be a single function - // of a JavaScript Array of functions. - - if (JS('bool', 'typeof dartNativeDispatchHooksTransformer != "undefined"')) { - var transformers = JS('', 'dartNativeDispatchHooksTransformer'); - if (JS('bool', 'typeof # == "function"', transformers)) { - transformers = [transformers]; - } - if (JS('bool', '#.constructor == Array', transformers)) { - for (int i = 0; i < JS('int', '#.length', transformers); i++) { - var transformer = JS('', '#[#]', transformers, i); - if (JS('bool', 'typeof # == "function"', transformer)) { - hooks = applyHooksTransformer(transformer, hooks); - } - } - } - } - - var getTag = JS('', '#.getTag', hooks); - var getUnknownTag = JS('', '#.getUnknownTag', hooks); - var prototypeForTag = JS('', '#.prototypeForTag', hooks); - - getTagFunction = (o) => JS('String|Null', '#(#)', getTag, o); - alternateTagFunction = - (o, String tag) => JS('String|Null', '#(#, #)', getUnknownTag, o, tag); - prototypeForTagFunction = - (String tag) => JS('', '#(#)', prototypeForTag, tag); -} - -applyHooksTransformer(transformer, hooks) { - var newHooks = JS('=Object|Null', '#(#)', transformer, hooks); - return JS('', '# || #', newHooks, hooks); -} - -// JavaScript code fragments. -// -// This is a temporary place for the JavaScript code. -// -// TODO(sra): These code fragments are not minified. They could be generated by -// the code emitter, or JS_CONST could be improved to parse entire functions and -// take care of the minification. - -const _baseHooks = const JS_CONST(r''' -function() { - function typeNameInChrome(o) { - var constructor = o.constructor; - if (constructor) { - var name = constructor.name; - if (name) return name; - } - var s = Object.prototype.toString.call(o); - return s.substring(8, s.length - 1); - } - function getUnknownTag(object, tag) { - // This code really belongs in [getUnknownTagGenericBrowser] but having it - // here allows [getUnknownTag] to be tested on d8. - if (/^HTML[A-Z].*Element$/.test(tag)) { - // Check that it is not a simple JavaScript object. - var name = Object.prototype.toString.call(object); - if (name == "[object Object]") return null; - return "HTMLElement"; - } - } - function getUnknownTagGenericBrowser(object, tag) { - if (self.HTMLElement && object instanceof HTMLElement) return "HTMLElement"; - return getUnknownTag(object, tag); - } - function prototypeForTag(tag) { - if (typeof window == "undefined") return null; - if (typeof window[tag] == "undefined") return null; - var constructor = window[tag]; - if (typeof constructor != "function") return null; - return constructor.prototype; - } - function discriminator(tag) { return null; } - - var isBrowser = typeof navigator == "object"; - - return { - getTag: typeNameInChrome, - getUnknownTag: isBrowser ? getUnknownTagGenericBrowser : getUnknownTag, - prototypeForTag: prototypeForTag, - discriminator: discriminator }; -}'''); - - -/** - * Returns the name of the constructor function for browsers where - * `object.constructor.name` is not reliable. - * - * This function is split out of [_fallbackConstructorHooksTransformerGenerator] - * as it is called from both the dispatch hooks and via - * [constructorNameFallback] from objectToString. - */ -const _constructorNameFallback = const JS_CONST(r''' -function getTagFallback(o) { - var constructor = o.constructor; - if (typeof constructor == "function") { - var name = constructor.name; - // If the name is a non-empty string, we use that as the type name of this - // object. There are various cases where that does not work, so we have to - // detect them and fall through to the toString() based implementation. - - if (typeof name == "string" && - - // Sometimes the string is empty. This test also catches minified - // shadow dom polyfil wrapper for Window on Firefox where the faked - // constructor name does not 'stick'. The shortest real DOM object - // names have three characters (e.g. URL, CSS). - name.length > 2 && - - // On Firefox we often get "Object" as the constructor name, even for - // more specialized DOM objects. - name !== "Object" && - - // This can happen in Opera. - name !== "Function.prototype") { - return name; - } - } - var s = Object.prototype.toString.call(o); - return s.substring(8, s.length - 1); -}'''); - - -const _fallbackConstructorHooksTransformerGenerator = const JS_CONST(r''' -function(getTagFallback) { - return function(hooks) { - // If we are not in a browser, assume we are in d8. - // TODO(sra): Recognize jsshell. - if (typeof navigator != "object") return hooks; - - var ua = navigator.userAgent; - // TODO(antonm): remove a reference to DumpRenderTree. - 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; - }; -}'''); - - -const _ieHooksTransformer = const JS_CONST(r''' -function(hooks) { - var userAgent = typeof navigator == "object" ? navigator.userAgent : ""; - if (userAgent.indexOf("Trident/") == -1) return hooks; - - var getTag = hooks.getTag; - - var quickMap = { - "BeforeUnloadEvent": "Event", - "DataTransfer": "Clipboard", - "HTMLDDElement": "HTMLElement", - "HTMLDTElement": "HTMLElement", - "HTMLPhraseElement": "HTMLElement", - "Position": "Geoposition" - }; - - function getTagIE(o) { - var tag = getTag(o); - var newTag = quickMap[tag]; - if (newTag) return newTag; - // Patches for types which report themselves as Objects. - if (tag == "Object") { - if (window.DataView && (o instanceof window.DataView)) return "DataView"; - } - return tag; - } - - function prototypeForTagIE(tag) { - var constructor = window[tag]; - if (constructor == null) return null; - return constructor.prototype; - } - - hooks.getTag = getTagIE; - 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) { - var userAgent = typeof navigator == "object" ? navigator.userAgent : ""; - if (userAgent.indexOf("Firefox") == -1) return hooks; - - var getTag = hooks.getTag; - - var quickMap = { - "BeforeUnloadEvent": "Event", - "DataTransfer": "Clipboard", - "GeoGeolocation": "Geolocation", - "Location": "!Location", // Fixes issue 18151 - "WorkerMessageEvent": "MessageEvent", - "XMLDocument": "!Document"}; - - function getTagFirefox(o) { - var tag = getTag(o); - return quickMap[tag] || tag; - } - - hooks.getTag = getTagFirefox; -}'''); - - -const _operaHooksTransformer = const JS_CONST(r''' -function(hooks) { return hooks; } -'''); - - -const _safariHooksTransformer = const JS_CONST(r''' -function(hooks) { return hooks; } -'''); - - -const _dartExperimentalFixupGetTagHooksTransformer = const JS_CONST(r''' -function(hooks) { - if (typeof dartExperimentalFixupGetTag != "function") return hooks; - hooks.getTag = dartExperimentalFixupGetTag(hooks.getTag); -}'''); diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/native_typed_data.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/native_typed_data.dart deleted file mode 100644 index 4f159126f512..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/native_typed_data.dart +++ /dev/null @@ -1,2013 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/** - * Specialized integers and floating point numbers, - * with SIMD support and efficient lists. - */ -library dart.typed_data.implementation; - -import 'dart:collection'; -import 'dart:_internal'; -import 'dart:_interceptors' show JSIndexable, JSUInt32, JSUInt31; -import 'dart:_js_helper' -show Creates, JavaScriptIndexingBehavior, JSName, Native, Null, Returns; -import 'dart:_foreign_helper' show JS; -import 'dart:math' as Math; - -import 'dart:typed_data'; - -@Native("ArrayBuffer") -class NativeByteBuffer implements ByteBuffer { - @JSName('byteLength') - final int lengthInBytes; - - Type get runtimeType => ByteBuffer; - - Uint8List asUint8List([int offsetInBytes = 0, int length]) { - return new NativeUint8List.view(this, offsetInBytes, length); - } - - Int8List asInt8List([int offsetInBytes = 0, int length]) { - return new NativeInt8List.view(this, offsetInBytes, length); - } - - Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]) { - return new NativeUint8ClampedList.view(this, offsetInBytes, length); - } - - Uint16List asUint16List([int offsetInBytes = 0, int length]) { - return new NativeUint16List.view(this, offsetInBytes, length); - } - Int16List asInt16List([int offsetInBytes = 0, int length]) { - return new NativeInt16List.view(this, offsetInBytes, length); - } - - Uint32List asUint32List([int offsetInBytes = 0, int length]) { - return new NativeUint32List.view(this, offsetInBytes, length); - } - - Int32List asInt32List([int offsetInBytes = 0, int length]) { - return new NativeInt32List.view(this, offsetInBytes, length); - } - - Uint64List asUint64List([int offsetInBytes = 0, int length]) { - throw new UnsupportedError("Uint64List not supported by dart2js."); - } - - Int64List asInt64List([int offsetInBytes = 0, int length]) { - throw new UnsupportedError("Int64List not supported by dart2js."); - } - - Int32x4List asInt32x4List([int offsetInBytes = 0, int length]) { - NativeInt32List storage = - this.asInt32List(offsetInBytes, length != null ? length * 4 : null); - return new NativeInt32x4List._externalStorage(storage); - } - - Float32List asFloat32List([int offsetInBytes = 0, int length]) { - return new NativeFloat32List.view(this, offsetInBytes, length); - } - - Float64List asFloat64List([int offsetInBytes = 0, int length]) { - return new NativeFloat64List.view(this, offsetInBytes, length); - } - - Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]) { - NativeFloat32List storage = - this.asFloat32List(offsetInBytes, length != null ? length * 4 : null); - return new NativeFloat32x4List._externalStorage(storage); - } - - Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]) { - NativeFloat64List storage = - this.asFloat64List(offsetInBytes, length != null ? length * 2 : null); - return new NativeFloat64x2List._externalStorage(storage); - } - - ByteData asByteData([int offsetInBytes = 0, int length]) { - return new NativeByteData.view(this, offsetInBytes, length); - } -} - - - -/** - * A fixed-length list of Float32x4 numbers that is viewable as a - * [TypedData]. For long lists, this implementation will be considerably more - * space- and time-efficient than the default [List] implementation. - */ -class NativeFloat32x4List - extends Object with ListMixin, FixedLengthListMixin - implements Float32x4List { - - final NativeFloat32List _storage; - - /** - * Creates a [Float32x4List] of the specified length (in elements), - * all of whose elements are initially zero. - */ - NativeFloat32x4List(int length) - : _storage = new NativeFloat32List(length * 4); - - NativeFloat32x4List._externalStorage(this._storage); - - NativeFloat32x4List._slowFromList(List list) - : _storage = new NativeFloat32List(list.length * 4) { - for (int i = 0; i < list.length; i++) { - var e = list[i]; - _storage[(i * 4) + 0] = e.x; - _storage[(i * 4) + 1] = e.y; - _storage[(i * 4) + 2] = e.z; - _storage[(i * 4) + 3] = e.w; - } - } - - Type get runtimeType => Float32x4List; - - /** - * Creates a [Float32x4List] with the same size as the [elements] list - * and copies over the elements. - */ - factory NativeFloat32x4List.fromList(List list) { - if (list is NativeFloat32x4List) { - return new NativeFloat32x4List._externalStorage( - new NativeFloat32List.fromList(list._storage)); - } else { - return new NativeFloat32x4List._slowFromList(list); - } - } - - ByteBuffer get buffer => _storage.buffer; - - int get lengthInBytes => _storage.lengthInBytes; - - int get offsetInBytes => _storage.offsetInBytes; - - int get elementSizeInBytes => Float32x4List.BYTES_PER_ELEMENT; - - void _invalidIndex(int index, int length) { - if (index < 0 || index >= length) { - if (length == this.length) { - throw new RangeError.index(index, this); - } - throw new RangeError.range(index, 0, length - 1); - } else { - throw new ArgumentError('Invalid list index $index'); - } - } - - void _checkIndex(int index, int length) { - if (JS('bool', '(# >>> 0 != #)', index, index) || index >= length) { - _invalidIndex(index, length); - } - } - - int _checkSublistArguments(int start, int end, int length) { - // For `sublist` the [start] and [end] indices are allowed to be equal to - // [length]. However, [_checkIndex] only allows indices in the range - // 0 .. length - 1. We therefore increment the [length] argument by one - // for the [_checkIndex] checks. - _checkIndex(start, length + 1); - if (end == null) return length; - _checkIndex(end, length + 1); - if (start > end) throw new RangeError.range(start, 0, end); - return end; - } - - int get length => _storage.length ~/ 4; - - Float32x4 operator[](int index) { - _checkIndex(index, length); - double _x = _storage[(index * 4) + 0]; - double _y = _storage[(index * 4) + 1]; - double _z = _storage[(index * 4) + 2]; - double _w = _storage[(index * 4) + 3]; - return new NativeFloat32x4._truncated(_x, _y, _z, _w); - } - - void operator[]=(int index, Float32x4 value) { - _checkIndex(index, length); - _storage[(index * 4) + 0] = value.x; - _storage[(index * 4) + 1] = value.y; - _storage[(index * 4) + 2] = value.z; - _storage[(index * 4) + 3] = value.w; - } - - List sublist(int start, [int end]) { - end = _checkSublistArguments(start, end, length); - return new NativeFloat32x4List._externalStorage( - _storage.sublist(start * 4, end * 4)); - } -} - - -/** - * A fixed-length list of Int32x4 numbers that is viewable as a - * [TypedData]. For long lists, this implementation will be considerably more - * space- and time-efficient than the default [List] implementation. - */ -class NativeInt32x4List - extends Object with ListMixin, FixedLengthListMixin - implements Int32x4List { - - final Int32List _storage; - - /** - * Creates a [Int32x4List] of the specified length (in elements), - * all of whose elements are initially zero. - */ - NativeInt32x4List(int length) : _storage = new NativeInt32List(length * 4); - - NativeInt32x4List._externalStorage(Int32List storage) : _storage = storage; - - NativeInt32x4List._slowFromList(List list) - : _storage = new NativeInt32List(list.length * 4) { - for (int i = 0; i < list.length; i++) { - var e = list[i]; - _storage[(i * 4) + 0] = e.x; - _storage[(i * 4) + 1] = e.y; - _storage[(i * 4) + 2] = e.z; - _storage[(i * 4) + 3] = e.w; - } - } - - Type get runtimeType => Int32x4List; - - /** - * Creates a [Int32x4List] with the same size as the [elements] list - * and copies over the elements. - */ - factory NativeInt32x4List.fromList(List list) { - if (list is NativeInt32x4List) { - return new NativeInt32x4List._externalStorage( - new NativeInt32List.fromList(list._storage)); - } else { - return new NativeInt32x4List._slowFromList(list); - } - } - - ByteBuffer get buffer => _storage.buffer; - - int get lengthInBytes => _storage.lengthInBytes; - - int get offsetInBytes => _storage.offsetInBytes; - - int get elementSizeInBytes => Int32x4List.BYTES_PER_ELEMENT; - - void _invalidIndex(int index, int length) { - if (index < 0 || index >= length) { - if (length == this.length) { - throw new RangeError.index(index, this); - } - throw new RangeError.range(index, 0, length - 1); - } else { - throw new ArgumentError('Invalid list index $index'); - } - } - - void _checkIndex(int index, int length) { - if (JS('bool', '(# >>> 0 != #)', index, index) - || JS('bool', '# >= #', index, length)) { - _invalidIndex(index, length); - } - } - - int _checkSublistArguments(int start, int end, int length) { - // For `sublist` the [start] and [end] indices are allowed to be equal to - // [length]. However, [_checkIndex] only allows indices in the range - // 0 .. length - 1. We therefore increment the [length] argument by one - // for the [_checkIndex] checks. - _checkIndex(start, length + 1); - if (end == null) return length; - _checkIndex(end, length + 1); - if (start > end) throw new RangeError.range(start, 0, end); - return end; - } - - int get length => _storage.length ~/ 4; - - Int32x4 operator[](int index) { - _checkIndex(index, length); - int _x = _storage[(index * 4) + 0]; - int _y = _storage[(index * 4) + 1]; - int _z = _storage[(index * 4) + 2]; - int _w = _storage[(index * 4) + 3]; - return new NativeInt32x4._truncated(_x, _y, _z, _w); - } - - void operator[]=(int index, Int32x4 value) { - _checkIndex(index, length); - _storage[(index * 4) + 0] = value.x; - _storage[(index * 4) + 1] = value.y; - _storage[(index * 4) + 2] = value.z; - _storage[(index * 4) + 3] = value.w; - } - - List sublist(int start, [int end]) { - end = _checkSublistArguments(start, end, length); - return new NativeInt32x4List._externalStorage( - _storage.sublist(start * 4, end * 4)); - } -} - - -/** - * A fixed-length list of Float64x2 numbers that is viewable as a - * [TypedData]. For long lists, this implementation will be considerably more - * space- and time-efficient than the default [List] implementation. - */ -class NativeFloat64x2List - extends Object with ListMixin, FixedLengthListMixin - implements Float64x2List { - - final NativeFloat64List _storage; - - /** - * Creates a [Float64x2List] of the specified length (in elements), - * all of whose elements are initially zero. - */ - NativeFloat64x2List(int length) - : _storage = new NativeFloat64List(length * 2); - - NativeFloat64x2List._externalStorage(this._storage); - - NativeFloat64x2List._slowFromList(List list) - : _storage = new NativeFloat64List(list.length * 2) { - for (int i = 0; i < list.length; i++) { - var e = list[i]; - _storage[(i * 2) + 0] = e.x; - _storage[(i * 2) + 1] = e.y; - } - } - - /** - * Creates a [Float64x2List] with the same size as the [elements] list - * and copies over the elements. - */ - factory NativeFloat64x2List.fromList(List list) { - if (list is NativeFloat64x2List) { - return new NativeFloat64x2List._externalStorage( - new NativeFloat64List.fromList(list._storage)); - } else { - return new NativeFloat64x2List._slowFromList(list); - } - } - - Type get runtimeType => Float64x2List; - - ByteBuffer get buffer => _storage.buffer; - - int get lengthInBytes => _storage.lengthInBytes; - - int get offsetInBytes => _storage.offsetInBytes; - - int get elementSizeInBytes => Float64x2List.BYTES_PER_ELEMENT; - - void _invalidIndex(int index, int length) { - if (index < 0 || index >= length) { - if (length == this.length) { - throw new RangeError.index(index, this); - } - throw new RangeError.range(index, 0, length - 1); - } else { - throw new ArgumentError('Invalid list index $index'); - } - } - - void _checkIndex(int index, int length) { - if (JS('bool', '(# >>> 0 != #)', index, index) || index >= length) { - _invalidIndex(index, length); - } - } - - int _checkSublistArguments(int start, int end, int length) { - // For `sublist` the [start] and [end] indices are allowed to be equal to - // [length]. However, [_checkIndex] only allows indices in the range - // 0 .. length - 1. We therefore increment the [length] argument by one - // for the [_checkIndex] checks. - _checkIndex(start, length + 1); - if (end == null) return length; - _checkIndex(end, length + 1); - if (start > end) throw new RangeError.range(start, 0, end); - return end; - } - - int get length => _storage.length ~/ 2; - - Float64x2 operator[](int index) { - _checkIndex(index, length); - double _x = _storage[(index * 2) + 0]; - double _y = _storage[(index * 2) + 1]; - return new Float64x2(_x, _y); - } - - void operator[]=(int index, Float64x2 value) { - _checkIndex(index, length); - _storage[(index * 2) + 0] = value.x; - _storage[(index * 2) + 1] = value.y; - } - - List sublist(int start, [int end]) { - end = _checkSublistArguments(start, end, length); - return new NativeFloat64x2List._externalStorage( - _storage.sublist(start * 2, end * 2)); - } -} - -@Native("ArrayBufferView") -class NativeTypedData implements TypedData { - /** - * Returns the byte buffer associated with this object. - */ - @Creates('NativeByteBuffer') - // May be Null for IE's CanvasPixelArray. - @Returns('NativeByteBuffer|Null') - final ByteBuffer buffer; - - /** - * Returns the length of this view, in bytes. - */ - @JSName('byteLength') - final int lengthInBytes; - - /** - * Returns the offset in bytes into the underlying byte buffer of this view. - */ - @JSName('byteOffset') - final int offsetInBytes; - - /** - * Returns the number of bytes in the representation of each element in this - * list. - */ - @JSName('BYTES_PER_ELEMENT') - final int elementSizeInBytes; - - void _invalidIndex(int index, int length) { - if (index < 0 || index >= length) { - if (this is List) { - var list = this; // Typed as dynamic to avoid warning. - if (length == list.length) { - throw new RangeError.index(index, this); - } - } - throw new RangeError.range(index, 0, length - 1); - } else { - throw new ArgumentError('Invalid list index $index'); - } - } - - void _checkIndex(int index, int length) { - if (JS('bool', '(# >>> 0) !== #', index, index) || - JS('int', '#', index) >= length) { // 'int' guaranteed by above test. - _invalidIndex(index, length); - } - } - - int _checkSublistArguments(int start, int end, int length) { - // For `sublist` the [start] and [end] indices are allowed to be equal to - // [length]. However, [_checkIndex] only allows indices in the range - // 0 .. length - 1. We therefore increment the [length] argument by one - // for the [_checkIndex] checks. - _checkIndex(start, length + 1); - if (end == null) return length; - _checkIndex(end, length + 1); - if (start > end) throw new RangeError.range(start, 0, end); - return end; - } -} - - -// Validates the unnamed constructor length argument. Checking is necessary -// because passing unvalidated values to the native constructors can cause -// conversions or create views. -int _checkLength(length) { - if (length is! int) throw new ArgumentError('Invalid length $length'); - return length; -} - -// Validates `.view` constructor arguments. Checking is necessary because -// passing unvalidated values to the native constructors can cause conversions -// (e.g. String arguments) or create typed data objects that are not actually -// views of the input. -void _checkViewArguments(buffer, offsetInBytes, length) { - if (buffer is! NativeByteBuffer) { - throw new ArgumentError('Invalid view buffer'); - } - if (offsetInBytes is! int) { - throw new ArgumentError('Invalid view offsetInBytes $offsetInBytes'); - } - if (length != null && length is! int) { - throw new ArgumentError('Invalid view length $length'); - } -} - -// Ensures that [list] is a JavaScript Array or a typed array. If necessary, -// returns a copy of the list. -List _ensureNativeList(List list) { - if (list is JSIndexable) return list; - List result = new List(list.length); - for (int i = 0; i < list.length; i++) { - result[i] = list[i]; - } - return result; -} - - -@Native("DataView") -class NativeByteData extends NativeTypedData implements ByteData { - /** - * Creates a [ByteData] of the specified length (in elements), all of - * whose elements are initially zero. - */ - factory NativeByteData(int length) => _create1(_checkLength(length)); - - /** - * Creates an [ByteData] _view_ of the specified region in the specified - * byte buffer. Changes in the [ByteData] will be visible in the byte - * buffer and vice versa. If the [offsetInBytes] index of the region is not - * specified, it defaults to zero (the first byte in the byte buffer). - * If the length is not specified, it defaults to null, which indicates - * that the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - */ - factory NativeByteData.view(ByteBuffer buffer, - int offsetInBytes, int length) { - _checkViewArguments(buffer, offsetInBytes, length); - return length == null - ? _create2(buffer, offsetInBytes) - : _create3(buffer, offsetInBytes, length); - } - - Type get runtimeType => ByteData; - - int get elementSizeInBytes => 1; - - /** - * Returns the floating point number represented by the four bytes at - * the specified [byteOffset] in this object, in IEEE 754 - * single-precision binary floating-point format (binary32). - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 4` is greater than the length of this object. - */ - double getFloat32(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) => - _getFloat32(byteOffset, Endianness.LITTLE_ENDIAN == endian); - - @JSName('getFloat32') - @Returns('double') - double _getFloat32(int byteOffset, [bool littleEndian]) native; - - /** - * Returns the floating point number represented by the eight bytes at - * the specified [byteOffset] in this object, in IEEE 754 - * double-precision binary floating-point format (binary64). - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 8` is greater than the length of this object. - */ - double getFloat64(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) => - _getFloat64(byteOffset, Endianness.LITTLE_ENDIAN == endian); - - @JSName('getFloat64') - @Returns('double') - double _getFloat64(int byteOffset, [bool littleEndian]) native; - - /** - * Returns the (possibly negative) integer represented by the two bytes at - * the specified [byteOffset] in this object, in two's complement binary - * form. - * The return value will be between 215 and 215 - 1, - * inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 2` is greater than the length of this object. - */ - int getInt16(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) => - _getInt16(byteOffset, Endianness.LITTLE_ENDIAN == endian); - - @JSName('getInt16') - @Returns('int') - int _getInt16(int byteOffset, [bool littleEndian]) native; - - /** - * Returns the (possibly negative) integer represented by the four bytes at - * the specified [byteOffset] in this object, in two's complement binary - * form. - * The return value will be between 231 and 231 - 1, - * inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 4` is greater than the length of this object. - */ - int getInt32(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) => - _getInt32(byteOffset, Endianness.LITTLE_ENDIAN == endian); - - @JSName('getInt32') - @Returns('int') - int _getInt32(int byteOffset, [bool littleEndian]) native; - - /** - * Returns the (possibly negative) integer represented by the eight bytes at - * the specified [byteOffset] in this object, in two's complement binary - * form. - * The return value will be between 263 and 263 - 1, - * inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 8` is greater than the length of this object. - */ - int getInt64(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) { - throw new UnsupportedError('Int64 accessor not supported by dart2js.'); - } - - /** - * Returns the (possibly negative) integer represented by the byte at the - * specified [byteOffset] in this object, in two's complement binary - * representation. The return value will be between -128 and 127, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * greater than or equal to the length of this object. - */ - int getInt8(int byteOffset) native; - - /** - * Returns the positive integer represented by the two bytes starting - * at the specified [byteOffset] in this object, in unsigned binary - * form. - * The return value will be between 0 and 216 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 2` is greater than the length of this object. - */ - int getUint16(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) => - _getUint16(byteOffset, Endianness.LITTLE_ENDIAN == endian); - - @JSName('getUint16') - @Returns('JSUInt31') - int _getUint16(int byteOffset, [bool littleEndian]) native; - - /** - * Returns the positive integer represented by the four bytes starting - * at the specified [byteOffset] in this object, in unsigned binary - * form. - * The return value will be between 0 and 232 - 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, Endianness.LITTLE_ENDIAN == endian); - - @JSName('getUint32') - @Returns('JSUInt32') - int _getUint32(int byteOffset, [bool littleEndian]) native; - - /** - * Returns the positive integer represented by the eight bytes starting - * at the specified [byteOffset] in this object, in unsigned binary - * form. - * The return value will be between 0 and 264 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 8` is greater than the length of this object. - */ - int getUint64(int byteOffset, [Endianness endian=Endianness.BIG_ENDIAN]) { - throw new UnsupportedError('Uint64 accessor not supported by dart2js.'); - } - - /** - * Returns the positive integer represented by the byte at the specified - * [byteOffset] in this object, in unsigned binary form. The - * return value will be between 0 and 255, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * greater than or equal to the length of this object. - */ - int getUint8(int byteOffset) native; - - /** - * Sets the four bytes starting at the specified [byteOffset] in this - * object to the IEEE 754 single-precision binary floating-point - * (binary32) representation of the specified [value]. - * - * **Note that this method can lose precision.** The input [value] is - * a 64-bit floating point value, which will be converted to 32-bit - * floating point value by IEEE 754 rounding rules before it is stored. - * If [value] cannot be represented exactly as a binary32, it will be - * converted to the nearest binary32 value. If two binary32 values are - * equally close, the one whose least significant bit is zero will be used. - * Note that finite (but large) values can be converted to infinity, and - * small non-zero values can be converted to zero. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 4` is greater than the length of this object. - */ - void setFloat32(int byteOffset, num value, - [Endianness endian=Endianness.BIG_ENDIAN]) => - _setFloat32(byteOffset, value, Endianness.LITTLE_ENDIAN == endian); - - @JSName('setFloat32') - void _setFloat32(int byteOffset, num value, [bool littleEndian]) native; - - /** - * Sets the eight bytes starting at the specified [byteOffset] in this - * object to the IEEE 754 double-precision binary floating-point - * (binary64) representation of the specified [value]. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 8` is greater than the length of this object. - */ - void setFloat64(int byteOffset, num value, - [Endianness endian=Endianness.BIG_ENDIAN]) => - _setFloat64(byteOffset, value, Endianness.LITTLE_ENDIAN == endian); - - @JSName('setFloat64') - void _setFloat64(int byteOffset, num value, [bool littleEndian]) native; - - /** - * Sets the two bytes starting at the specified [byteOffset] in this - * object to the two's complement binary representation of the specified - * [value], which must fit in two bytes. In other words, [value] must lie - * between 215 and 215 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 2` is greater than the length of this object. - */ - void setInt16(int byteOffset, int value, - [Endianness endian=Endianness.BIG_ENDIAN]) => - _setInt16(byteOffset, value, Endianness.LITTLE_ENDIAN == endian); - - @JSName('setInt16') - void _setInt16(int byteOffset, int value, [bool littleEndian]) native; - - /** - * Sets the four bytes starting at the specified [byteOffset] in this - * object to the two's complement binary representation of the specified - * [value], which must fit in four bytes. In other words, [value] must lie - * between 231 and 231 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 4` is greater than the length of this object. - */ - void setInt32(int byteOffset, int value, - [Endianness endian=Endianness.BIG_ENDIAN]) => - _setInt32(byteOffset, value, Endianness.LITTLE_ENDIAN == endian); - - @JSName('setInt32') - void _setInt32(int byteOffset, int value, [bool littleEndian]) native; - - /** - * Sets the eight bytes starting at the specified [byteOffset] in this - * object to the two's complement binary representation of the specified - * [value], which must fit in eight bytes. In other words, [value] must lie - * between 263 and 263 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 8` is greater than the length of this object. - */ - void setInt64(int byteOffset, int value, - [Endianness endian=Endianness.BIG_ENDIAN]) { - throw new UnsupportedError('Int64 accessor not supported by dart2js.'); - } - - /** - * Sets the byte at the specified [byteOffset] in this object to the - * two's complement binary representation of the specified [value], which - * must fit in a single byte. In other words, [value] must be between - * -128 and 127, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * greater than or equal to the length of this object. - */ - void setInt8(int byteOffset, int value) native; - - /** - * Sets the two bytes starting at the specified [byteOffset] in this object - * to the unsigned binary representation of the specified [value], - * which must fit in two bytes. in other words, [value] must be between - * 0 and 216 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 2` is greater than the length of this object. - */ - void setUint16(int byteOffset, int value, - [Endianness endian=Endianness.BIG_ENDIAN]) => - _setUint16(byteOffset, value, Endianness.LITTLE_ENDIAN == endian); - - @JSName('setUint16') - void _setUint16(int byteOffset, int value, [bool littleEndian]) native; - - /** - * Sets the four bytes starting at the specified [byteOffset] in this object - * to the unsigned binary representation of the specified [value], - * which must fit in four bytes. in other words, [value] must be between - * 0 and 232 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 4` is greater than the length of this object. - */ - void setUint32(int byteOffset, int value, - [Endianness endian=Endianness.BIG_ENDIAN]) => - _setUint32(byteOffset, value, Endianness.LITTLE_ENDIAN == endian); - - @JSName('setUint32') - void _setUint32(int byteOffset, int value, [bool littleEndian]) native; - - /** - * Sets the eight bytes starting at the specified [byteOffset] in this object - * to the unsigned binary representation of the specified [value], - * which must fit in eight bytes. in other words, [value] must be between - * 0 and 264 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 8` is greater than the length of this object. - */ - void setUint64(int byteOffset, int value, - [Endianness endian=Endianness.BIG_ENDIAN]) { - throw new UnsupportedError('Uint64 accessor not supported by dart2js.'); - } - - /** - * Sets the byte at the specified [byteOffset] in this object to the - * unsigned binary representation of the specified [value], which must fit - * in a single byte. in other words, [value] must be between 0 and 255, - * inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, - * or greater than or equal to the length of this object. - */ - void setUint8(int byteOffset, int value) native; - - static NativeByteData _create1(arg) => - JS('NativeByteData', 'new DataView(new ArrayBuffer(#))', arg); - - static NativeByteData _create2(arg1, arg2) => - JS('NativeByteData', 'new DataView(#, #)', arg1, arg2); - - static NativeByteData _create3(arg1, arg2, arg3) => - JS('NativeByteData', 'new DataView(#, #, #)', arg1, arg2, arg3); -} - - -abstract class NativeTypedArray extends NativeTypedData - implements JavaScriptIndexingBehavior { - // TODO(jmesserly): moved `length` to subclass to (somewhat) mitigate - // - - void _setRangeFast(int start, int end, - NativeTypedArray source, int skipCount) { - int targetLength = this.length; - _checkIndex(start, targetLength + 1); - _checkIndex(end, targetLength + 1); - if (start > end) throw new RangeError.range(start, 0, end); - int count = end - start; - - if (skipCount < 0) throw new ArgumentError(skipCount); - - int sourceLength = source.length; - if (sourceLength - skipCount < count) { - throw new StateError('Not enough elements'); - } - - if (skipCount != 0 || sourceLength != count) { - // Create a view of the exact subrange that is copied from the source. - source = JS('', '#.subarray(#, #)', - source, skipCount, skipCount + count); - } - JS('void', '#.set(#, #)', this, source, start); - } -} - -abstract class NativeTypedArrayOfDouble - extends NativeTypedArray - with ListMixin, FixedLengthListMixin { - - int get length => JS('JSUInt32', '#.length', this); - - double operator[](int index) { - _checkIndex(index, length); - return JS('double', '#[#]', this, index); - } - - void operator[]=(int index, num value) { - _checkIndex(index, length); - JS('void', '#[#] = #', this, index, value); - } - - void setRange(int start, int end, Iterable iterable, - [int skipCount = 0]) { - if (iterable is NativeTypedArrayOfDouble) { - _setRangeFast(start, end, iterable, skipCount); - return; - } - super.setRange(start, end, iterable, skipCount); - } -} - -abstract class NativeTypedArrayOfInt - extends NativeTypedArray - with ListMixin, FixedLengthListMixin - implements List { - - int get length => JS('JSUInt32', '#.length', this); - - // operator[]() is not here since different versions have different return - // types - - void operator[]=(int index, int value) { - _checkIndex(index, length); - JS('void', '#[#] = #', this, index, value); - } - - void setRange(int start, int end, Iterable iterable, - [int skipCount = 0]) { - if (iterable is NativeTypedArrayOfInt) { - _setRangeFast(start, end, iterable, skipCount); - return; - } - super.setRange(start, end, iterable, skipCount); - } -} - - -@Native("Float32Array") -class NativeFloat32List - extends NativeTypedArrayOfDouble - implements Float32List { - - factory NativeFloat32List(int length) => _create1(_checkLength(length)); - - factory NativeFloat32List.fromList(List elements) => - _create1(_ensureNativeList(elements)); - - factory NativeFloat32List.view(ByteBuffer buffer, - int offsetInBytes, int length) { - _checkViewArguments(buffer, offsetInBytes, length); - return length == null - ? _create2(buffer, offsetInBytes) - : _create3(buffer, offsetInBytes, length); - } - - Type get runtimeType => Float32List; - - List sublist(int start, [int end]) { - end = _checkSublistArguments(start, end, length); - var source = JS('NativeFloat32List', '#.subarray(#, #)', this, start, end); - return _create1(source); - } - - static NativeFloat32List _create1(arg) => - JS('NativeFloat32List', 'new Float32Array(#)', arg); - - static NativeFloat32List _create2(arg1, arg2) => - JS('NativeFloat32List', 'new Float32Array(#, #)', arg1, arg2); - - static NativeFloat32List _create3(arg1, arg2, arg3) => - JS('NativeFloat32List', 'new Float32Array(#, #, #)', arg1, arg2, arg3); -} - - -@Native("Float64Array") -class NativeFloat64List - extends NativeTypedArrayOfDouble - implements Float64List { - - factory NativeFloat64List(int length) => _create1(_checkLength(length)); - - factory NativeFloat64List.fromList(List elements) => - _create1(_ensureNativeList(elements)); - - factory NativeFloat64List.view(ByteBuffer buffer, - int offsetInBytes, int length) { - _checkViewArguments(buffer, offsetInBytes, length); - return length == null - ? _create2(buffer, offsetInBytes) - : _create3(buffer, offsetInBytes, length); - } - - Type get runtimeType => Float64List; - - List sublist(int start, [int end]) { - end = _checkSublistArguments(start, end, length); - var source = JS('NativeFloat64List', '#.subarray(#, #)', this, start, end); - return _create1(source); - } - - static NativeFloat64List _create1(arg) => - JS('NativeFloat64List', 'new Float64Array(#)', arg); - - static NativeFloat64List _create2(arg1, arg2) => - JS('NativeFloat64List', 'new Float64Array(#, #)', arg1, arg2); - - static NativeFloat64List _create3(arg1, arg2, arg3) => - JS('NativeFloat64List', 'new Float64Array(#, #, #)', arg1, arg2, arg3); -} - - -@Native("Int16Array") -class NativeInt16List - extends NativeTypedArrayOfInt - implements Int16List { - - factory NativeInt16List(int length) => _create1(_checkLength(length)); - - factory NativeInt16List.fromList(List elements) => - _create1(_ensureNativeList(elements)); - - factory NativeInt16List.view(NativeByteBuffer buffer, - int offsetInBytes, int length) { - _checkViewArguments(buffer, offsetInBytes, length); - return length == null - ? _create2(buffer, offsetInBytes) - : _create3(buffer, offsetInBytes, length); - } - - Type get runtimeType => Int16List; - - int operator[](int index) { - _checkIndex(index, length); - return JS('int', '#[#]', this, index); - } - - List sublist(int start, [int end]) { - end = _checkSublistArguments(start, end, length); - var source = JS('NativeInt16List', '#.subarray(#, #)', this, start, end); - return _create1(source); - } - - static NativeInt16List _create1(arg) => - JS('NativeInt16List', 'new Int16Array(#)', arg); - - static NativeInt16List _create2(arg1, arg2) => - JS('NativeInt16List', 'new Int16Array(#, #)', arg1, arg2); - - static NativeInt16List _create3(arg1, arg2, arg3) => - JS('NativeInt16List', 'new Int16Array(#, #, #)', arg1, arg2, arg3); -} - - -@Native("Int32Array") -class NativeInt32List extends NativeTypedArrayOfInt implements Int32List { - - factory NativeInt32List(int length) => _create1(_checkLength(length)); - - factory NativeInt32List.fromList(List elements) => - _create1(_ensureNativeList(elements)); - - factory NativeInt32List.view(ByteBuffer buffer, - int offsetInBytes, int length) { - _checkViewArguments(buffer, offsetInBytes, length); - return length == null - ? _create2(buffer, offsetInBytes) - : _create3(buffer, offsetInBytes, length); - } - - Type get runtimeType => Int32List; - - int operator[](int index) { - _checkIndex(index, length); - return JS('int', '#[#]', this, index); - } - - List sublist(int start, [int end]) { - end = _checkSublistArguments(start, end, length); - var source = JS('NativeInt32List', '#.subarray(#, #)', this, start, end); - return _create1(source); - } - - static NativeInt32List _create1(arg) => - JS('NativeInt32List', 'new Int32Array(#)', arg); - - static NativeInt32List _create2(arg1, arg2) => - JS('NativeInt32List', 'new Int32Array(#, #)', arg1, arg2); - - static NativeInt32List _create3(arg1, arg2, arg3) => - JS('NativeInt32List', 'new Int32Array(#, #, #)', arg1, arg2, arg3); -} - - -@Native("Int8Array") -class NativeInt8List extends NativeTypedArrayOfInt implements Int8List { - - factory NativeInt8List(int length) => _create1(_checkLength(length)); - - factory NativeInt8List.fromList(List elements) => - _create1(_ensureNativeList(elements)); - - factory NativeInt8List.view(ByteBuffer buffer, - int offsetInBytes, int length) { - _checkViewArguments(buffer, offsetInBytes, length); - return length == null - ? _create2(buffer, offsetInBytes) - : _create3(buffer, offsetInBytes, length); - } - - Type get runtimeType => Int8List; - - int operator[](int index) { - _checkIndex(index, length); - return JS('int', '#[#]', this, index); - } - - List sublist(int start, [int end]) { - end = _checkSublistArguments(start, end, length); - var source = JS('NativeInt8List', '#.subarray(#, #)', this, start, end); - return _create1(source); - } - - static NativeInt8List _create1(arg) => - JS('NativeInt8List', 'new Int8Array(#)', arg); - - static NativeInt8List _create2(arg1, arg2) => - JS('NativeInt8List', 'new Int8Array(#, #)', arg1, arg2); - - static Int8List _create3(arg1, arg2, arg3) => - JS('NativeInt8List', 'new Int8Array(#, #, #)', arg1, arg2, arg3); -} - - -@Native("Uint16Array") -class NativeUint16List extends NativeTypedArrayOfInt implements Uint16List { - - factory NativeUint16List(int length) => _create1(_checkLength(length)); - - factory NativeUint16List.fromList(List list) => - _create1(_ensureNativeList(list)); - - factory NativeUint16List.view(ByteBuffer buffer, - int offsetInBytes, int length) { - _checkViewArguments(buffer, offsetInBytes, length); - return length == null - ? _create2(buffer, offsetInBytes) - : _create3(buffer, offsetInBytes, length); - } - - Type get runtimeType => Uint16List; - - int operator[](int index) { - _checkIndex(index, length); - return JS('JSUInt31', '#[#]', this, index); - } - - List sublist(int start, [int end]) { - end = _checkSublistArguments(start, end, length); - var source = JS('NativeUint16List', '#.subarray(#, #)', this, start, end); - return _create1(source); - } - - static NativeUint16List _create1(arg) => - JS('NativeUint16List', 'new Uint16Array(#)', arg); - - static NativeUint16List _create2(arg1, arg2) => - JS('NativeUint16List', 'new Uint16Array(#, #)', arg1, arg2); - - static NativeUint16List _create3(arg1, arg2, arg3) => - JS('NativeUint16List', 'new Uint16Array(#, #, #)', arg1, arg2, arg3); -} - - -@Native("Uint32Array") -class NativeUint32List extends NativeTypedArrayOfInt implements Uint32List { - - factory NativeUint32List(int length) => _create1(_checkLength(length)); - - factory NativeUint32List.fromList(List elements) => - _create1(_ensureNativeList(elements)); - - factory NativeUint32List.view(ByteBuffer buffer, - int offsetInBytes, int length) { - _checkViewArguments(buffer, offsetInBytes, length); - return length == null - ? _create2(buffer, offsetInBytes) - : _create3(buffer, offsetInBytes, length); - } - - Type get runtimeType => Uint32List; - - int operator[](int index) { - _checkIndex(index, length); - return JS('JSUInt32', '#[#]', this, index); - } - - List sublist(int start, [int end]) { - end = _checkSublistArguments(start, end, length); - var source = JS('NativeUint32List', '#.subarray(#, #)', this, start, end); - return _create1(source); - } - - static NativeUint32List _create1(arg) => - JS('NativeUint32List', 'new Uint32Array(#)', arg); - - static NativeUint32List _create2(arg1, arg2) => - JS('NativeUint32List', 'new Uint32Array(#, #)', arg1, arg2); - - static NativeUint32List _create3(arg1, arg2, arg3) => - JS('NativeUint32List', 'new Uint32Array(#, #, #)', arg1, arg2, arg3); -} - - -@Native("Uint8ClampedArray,CanvasPixelArray") -class NativeUint8ClampedList - extends NativeTypedArrayOfInt - implements Uint8ClampedList { - - factory NativeUint8ClampedList(int length) => _create1(_checkLength(length)); - - factory NativeUint8ClampedList.fromList(List elements) => - _create1(_ensureNativeList(elements)); - - factory NativeUint8ClampedList.view(ByteBuffer buffer, - int offsetInBytes, int length) { - _checkViewArguments(buffer, offsetInBytes, length); - return length == null - ? _create2(buffer, offsetInBytes) - : _create3(buffer, offsetInBytes, length); - } - - Type get runtimeType => Uint8ClampedList; - - int get length => JS('JSUInt32', '#.length', this); - - int operator[](int index) { - _checkIndex(index, length); - return JS('JSUInt31', '#[#]', this, index); - } - - List sublist(int start, [int end]) { - end = _checkSublistArguments(start, end, length); - var source = JS('NativeUint8ClampedList', '#.subarray(#, #)', - this, start, end); - return _create1(source); - } - - static NativeUint8ClampedList _create1(arg) => - JS('NativeUint8ClampedList', 'new Uint8ClampedArray(#)', arg); - - static NativeUint8ClampedList _create2(arg1, arg2) => - JS('NativeUint8ClampedList', 'new Uint8ClampedArray(#, #)', arg1, arg2); - - static NativeUint8ClampedList _create3(arg1, arg2, arg3) => - JS('NativeUint8ClampedList', 'new Uint8ClampedArray(#, #, #)', - arg1, arg2, arg3); -} - - -// On some browsers Uint8ClampedArray is a subtype of Uint8Array. Marking -// Uint8List as !nonleaf ensures that the native dispatch correctly handles -// the potential for Uint8ClampedArray to 'accidentally' pick up the -// dispatch record for Uint8List. -@Native("Uint8Array,!nonleaf") -class NativeUint8List extends NativeTypedArrayOfInt implements Uint8List { - - factory NativeUint8List(int length) => _create1(_checkLength(length)); - - factory NativeUint8List.fromList(List elements) => - _create1(_ensureNativeList(elements)); - - factory NativeUint8List.view(ByteBuffer buffer, - int offsetInBytes, int length) { - _checkViewArguments(buffer, offsetInBytes, length); - return length == null - ? _create2(buffer, offsetInBytes) - : _create3(buffer, offsetInBytes, length); - } - - Type get runtimeType => Uint8List; - - int get length => JS('JSUInt32', '#.length', this); - - int operator[](int index) { - _checkIndex(index, length); - return JS('JSUInt31', '#[#]', this, index); - } - - List sublist(int start, [int end]) { - end = _checkSublistArguments(start, end, length); - var source = JS('NativeUint8List', '#.subarray(#, #)', this, start, end); - return _create1(source); - } - - static NativeUint8List _create1(arg) => - JS('NativeUint8List', 'new Uint8Array(#)', arg); - - static NativeUint8List _create2(arg1, arg2) => - JS('NativeUint8List', 'new Uint8Array(#, #)', arg1, arg2); - - static NativeUint8List _create3(arg1, arg2, arg3) => - JS('NativeUint8List', 'new Uint8Array(#, #, #)', arg1, arg2, arg3); -} - - -/** - * Implementation of Dart Float32x4 immutable value type and operations. - * Float32x4 stores 4 32-bit floating point values in "lanes". - * The lanes are "x", "y", "z", and "w" respectively. - */ -class NativeFloat32x4 implements Float32x4 { - final double x; - final double y; - final double z; - final double w; - - static final NativeFloat32List _list = new NativeFloat32List(4); - static final Uint32List _uint32view = _list.buffer.asUint32List(); - - static _truncate(x) { - _list[0] = x; - return _list[0]; - } - - NativeFloat32x4(double x, double y, double z, double w) - : this.x = _truncate(x), - this.y = _truncate(y), - this.z = _truncate(z), - this.w = _truncate(w) { - // We would prefer to check for `double` but in dart2js we can't see the - // difference anyway. - if (x is! num) throw new ArgumentError(x); - if (y is! num) throw new ArgumentError(y); - if (z is! num) throw new ArgumentError(z); - if (w is! num) throw new ArgumentError(w); - } - - NativeFloat32x4.splat(double v) : this(v, v, v, v); - NativeFloat32x4.zero() : this._truncated(0.0, 0.0, 0.0, 0.0); - - /// Returns a bit-wise copy of [i] as a Float32x4. - factory NativeFloat32x4.fromInt32x4Bits(Int32x4 i) { - _uint32view[0] = i.x; - _uint32view[1] = i.y; - _uint32view[2] = i.z; - _uint32view[3] = i.w; - return new NativeFloat32x4._truncated(_list[0], _list[1], _list[2], _list[3]); - } - - NativeFloat32x4.fromFloat64x2(Float64x2 v) - : this._truncated(_truncate(v.x), _truncate(v.y), 0.0, 0.0); - - /// Creates a new NativeFloat32x4. - /// - /// Does not verify if the given arguments are non-null. - NativeFloat32x4._doubles(double x, double y, double z, double w) - : this.x = _truncate(x), - this.y = _truncate(y), - this.z = _truncate(z), - this.w = _truncate(w); - - /// Creates a new NativeFloat32x4. - /// - /// The constructor does not truncate the arguments. They must already be in - /// the correct range. It does not verify the type of the given arguments, - /// either. - NativeFloat32x4._truncated(this.x, this.y, this.z, this.w); - - String toString() { - return '[$x, $y, $z, $w]'; - } - - /// Addition operator. - Float32x4 operator+(Float32x4 other) { - double _x = x + other.x; - double _y = y + other.y; - double _z = z + other.z; - double _w = w + other.w; - return new NativeFloat32x4._doubles(_x, _y, _z, _w); - } - - /// Negate operator. - Float32x4 operator-() { - return new NativeFloat32x4._truncated(-x, -y, -z, -w); - } - - /// Subtraction operator. - Float32x4 operator-(Float32x4 other) { - double _x = x - other.x; - double _y = y - other.y; - double _z = z - other.z; - double _w = w - other.w; - return new NativeFloat32x4._doubles(_x, _y, _z, _w); - } - - /// Multiplication operator. - Float32x4 operator*(Float32x4 other) { - double _x = x * other.x; - double _y = y * other.y; - double _z = z * other.z; - double _w = w * other.w; - return new NativeFloat32x4._doubles(_x, _y, _z, _w); - } - - /// Division operator. - Float32x4 operator/(Float32x4 other) { - double _x = x / other.x; - double _y = y / other.y; - double _z = z / other.z; - double _w = w / other.w; - return new NativeFloat32x4._doubles(_x, _y, _z, _w); - } - - /// Relational less than. - Int32x4 lessThan(Float32x4 other) { - bool _cx = x < other.x; - bool _cy = y < other.y; - bool _cz = z < other.z; - bool _cw = w < other.w; - return new NativeInt32x4._truncated(_cx ? -1 : 0, - _cy ? -1 : 0, - _cz ? -1 : 0, - _cw ? -1 : 0); - } - - /// Relational less than or equal. - Int32x4 lessThanOrEqual(Float32x4 other) { - bool _cx = x <= other.x; - bool _cy = y <= other.y; - bool _cz = z <= other.z; - bool _cw = w <= other.w; - return new NativeInt32x4._truncated(_cx ? -1 : 0, - _cy ? -1 : 0, - _cz ? -1 : 0, - _cw ? -1 : 0); - } - - /// Relational greater than. - Int32x4 greaterThan(Float32x4 other) { - bool _cx = x > other.x; - bool _cy = y > other.y; - bool _cz = z > other.z; - bool _cw = w > other.w; - return new NativeInt32x4._truncated(_cx ? -1 : 0, - _cy ? -1 : 0, - _cz ? -1 : 0, - _cw ? -1 : 0); - } - - /// Relational greater than or equal. - Int32x4 greaterThanOrEqual(Float32x4 other) { - bool _cx = x >= other.x; - bool _cy = y >= other.y; - bool _cz = z >= other.z; - bool _cw = w >= other.w; - return new NativeInt32x4._truncated(_cx ? -1 : 0, - _cy ? -1 : 0, - _cz ? -1 : 0, - _cw ? -1 : 0); - } - - /// Relational equal. - Int32x4 equal(Float32x4 other) { - bool _cx = x == other.x; - bool _cy = y == other.y; - bool _cz = z == other.z; - bool _cw = w == other.w; - return new NativeInt32x4._truncated(_cx ? -1 : 0, - _cy ? -1 : 0, - _cz ? -1 : 0, - _cw ? -1 : 0); - } - - /// Relational not-equal. - Int32x4 notEqual(Float32x4 other) { - bool _cx = x != other.x; - bool _cy = y != other.y; - bool _cz = z != other.z; - bool _cw = w != other.w; - return new NativeInt32x4._truncated(_cx ? -1 : 0, - _cy ? -1 : 0, - _cz ? -1 : 0, - _cw ? -1 : 0); - } - - /// Returns a copy of [this] each lane being scaled by [s]. - Float32x4 scale(double s) { - double _x = s * x; - double _y = s * y; - double _z = s * z; - double _w = s * w; - return new NativeFloat32x4._doubles(_x, _y, _z, _w); - } - - /// Returns the absolute value of this [Float32x4]. - Float32x4 abs() { - double _x = x.abs(); - double _y = y.abs(); - double _z = z.abs(); - double _w = w.abs(); - return new NativeFloat32x4._truncated(_x, _y, _z, _w); - } - - /// Clamps [this] to be in the range [lowerLimit]-[upperLimit]. - Float32x4 clamp(Float32x4 lowerLimit, Float32x4 upperLimit) { - double _lx = lowerLimit.x; - double _ly = lowerLimit.y; - double _lz = lowerLimit.z; - double _lw = lowerLimit.w; - double _ux = upperLimit.x; - double _uy = upperLimit.y; - double _uz = upperLimit.z; - double _uw = upperLimit.w; - double _x = x; - double _y = y; - double _z = z; - double _w = w; - // MAX(MIN(self, upper), lower). - _x = _x > _ux ? _ux : _x; - _y = _y > _uy ? _uy : _y; - _z = _z > _uz ? _uz : _z; - _w = _w > _uw ? _uw : _w; - _x = _x < _lx ? _lx : _x; - _y = _y < _ly ? _ly : _y; - _z = _z < _lz ? _lz : _z; - _w = _w < _lw ? _lw : _w; - return new NativeFloat32x4._truncated(_x, _y, _z, _w); - } - - /// Extract the sign bit from each lane return them in the first 4 bits. - int get signMask { - var view = _uint32view; - var mx, my, mz, mw; - _list[0] = x; - _list[1] = y; - _list[2] = z; - _list[3] = w; - // This is correct because dart2js uses the unsigned right shift. - mx = (view[0] & 0x80000000) >> 31; - my = (view[1] & 0x80000000) >> 30; - mz = (view[2] & 0x80000000) >> 29; - mw = (view[3] & 0x80000000) >> 28; - return mx | my | mz | mw; - } - - /// Shuffle the lane values. [mask] must be one of the 256 shuffle constants. - Float32x4 shuffle(int m) { - if ((m < 0) || (m > 255)) { - throw new RangeError('mask $m must be in the range [0..256)'); - } - _list[0] = x; - _list[1] = y; - _list[2] = z; - _list[3] = w; - - double _x = _list[m & 0x3]; - double _y = _list[(m >> 2) & 0x3]; - double _z = _list[(m >> 4) & 0x3]; - double _w = _list[(m >> 6) & 0x3]; - return new NativeFloat32x4._truncated(_x, _y, _z, _w); - } - - /// Shuffle the lane values in [this] and [other]. The returned - /// Float32x4 will have XY lanes from [this] and ZW lanes from [other]. - /// Uses the same [mask] as [shuffle]. - Float32x4 shuffleMix(Float32x4 other, int m) { - if ((m < 0) || (m > 255)) { - throw new RangeError('mask $m must be in the range [0..256)'); - } - _list[0] = x; - _list[1] = y; - _list[2] = z; - _list[3] = w; - double _x = _list[m & 0x3]; - double _y = _list[(m >> 2) & 0x3]; - - _list[0] = other.x; - _list[1] = other.y; - _list[2] = other.z; - _list[3] = other.w; - double _z = _list[(m >> 4) & 0x3]; - double _w = _list[(m >> 6) & 0x3]; - return new NativeFloat32x4._truncated(_x, _y, _z, _w); - } - - /// Copy [this] and replace the [x] lane. - Float32x4 withX(double newX) { - return new NativeFloat32x4._truncated(_truncate(newX), y, z, w); - } - - /// Copy [this] and replace the [y] lane. - Float32x4 withY(double newY) { - return new NativeFloat32x4._truncated(x, _truncate(newY), z, w); - } - - /// Copy [this] and replace the [z] lane. - Float32x4 withZ(double newZ) { - return new NativeFloat32x4._truncated(x, y, _truncate(newZ), w); - } - - /// Copy [this] and replace the [w] lane. - Float32x4 withW(double newW) { - return new NativeFloat32x4._truncated(x, y, z, _truncate(newW)); - } - - /// Returns the lane-wise minimum value in [this] or [other]. - Float32x4 min(Float32x4 other) { - double _x = x < other.x ? x : other.x; - double _y = y < other.y ? y : other.y; - double _z = z < other.z ? z : other.z; - double _w = w < other.w ? w : other.w; - return new NativeFloat32x4._truncated(_x, _y, _z, _w); - } - - /// Returns the lane-wise maximum value in [this] or [other]. - Float32x4 max(Float32x4 other) { - double _x = x > other.x ? x : other.x; - double _y = y > other.y ? y : other.y; - double _z = z > other.z ? z : other.z; - double _w = w > other.w ? w : other.w; - return new NativeFloat32x4._truncated(_x, _y, _z, _w); - } - - /// Returns the square root of [this]. - Float32x4 sqrt() { - double _x = Math.sqrt(x); - double _y = Math.sqrt(y); - double _z = Math.sqrt(z); - double _w = Math.sqrt(w); - return new NativeFloat32x4._doubles(_x, _y, _z, _w); - } - - /// Returns the reciprocal of [this]. - Float32x4 reciprocal() { - double _x = 1.0 / x; - double _y = 1.0 / y; - double _z = 1.0 / z; - double _w = 1.0 / w; - return new NativeFloat32x4._doubles(_x, _y, _z, _w); - } - - /// Returns the square root of the reciprocal of [this]. - Float32x4 reciprocalSqrt() { - double _x = Math.sqrt(1.0 / x); - double _y = Math.sqrt(1.0 / y); - double _z = Math.sqrt(1.0 / z); - double _w = Math.sqrt(1.0 / w); - return new NativeFloat32x4._doubles(_x, _y, _z, _w); - } -} - - -/** - * Interface of Dart Int32x4 and operations. - * Int32x4 stores 4 32-bit bit-masks in "lanes". - * The lanes are "x", "y", "z", and "w" respectively. - */ -class NativeInt32x4 implements Int32x4 { - final int x; - final int y; - final int z; - final int w; - - static final _list = new NativeInt32List(4); - - static _truncate(x) { - _list[0] = x; - return _list[0]; - } - - NativeInt32x4(int x, int y, int z, int w) - : this.x = _truncate(x), - this.y = _truncate(y), - this.z = _truncate(z), - this.w = _truncate(w) { - if (x != this.x && x is! int) throw new ArgumentError(x); - if (y != this.y && y is! int) throw new ArgumentError(y); - if (z != this.z && z is! int) throw new ArgumentError(z); - if (w != this.w && w is! int) throw new ArgumentError(w); - } - - NativeInt32x4.bool(bool x, bool y, bool z, bool w) - : this.x = x ? -1 : 0, - this.y = y ? -1 : 0, - this.z = z ? -1 : 0, - this.w = w ? -1 : 0; - - /// Returns a bit-wise copy of [f] as a Int32x4. - factory NativeInt32x4.fromFloat32x4Bits(Float32x4 f) { - NativeFloat32List floatList = NativeFloat32x4._list; - floatList[0] = f.x; - floatList[1] = f.y; - floatList[2] = f.z; - floatList[3] = f.w; - NativeInt32List view = floatList.buffer.asInt32List(); - return new NativeInt32x4._truncated(view[0], view[1], view[2], view[3]); - } - - NativeInt32x4._truncated(this.x, this.y, this.z, this.w); - - String toString() => '[$x, $y, $z, $w]'; - - - /// The bit-wise or operator. - Int32x4 operator|(Int32x4 other) { - // Dart2js uses unsigned results for bit-operations. - // We use "JS" to fall back to the signed versions. - return new NativeInt32x4._truncated(JS("int", "# | #", x, other.x), - JS("int", "# | #", y, other.y), - JS("int", "# | #", z, other.z), - JS("int", "# | #", w, other.w)); - } - - /// The bit-wise and operator. - Int32x4 operator&(Int32x4 other) { - // Dart2js uses unsigned results for bit-operations. - // We use "JS" to fall back to the signed versions. - return new NativeInt32x4._truncated(JS("int", "# & #", x, other.x), - JS("int", "# & #", y, other.y), - JS("int", "# & #", z, other.z), - JS("int", "# & #", w, other.w)); - } - - /// The bit-wise xor operator. - Int32x4 operator^(Int32x4 other) { - // Dart2js uses unsigned results for bit-operations. - // We use "JS" to fall back to the signed versions. - return new NativeInt32x4._truncated(JS("int", "# ^ #", x, other.x), - JS("int", "# ^ #", y, other.y), - JS("int", "# ^ #", z, other.z), - JS("int", "# ^ #", w, other.w)); - } - - Int32x4 operator+(Int32x4 other) { - // Avoid going through the typed array by "| 0" the result. - return new NativeInt32x4._truncated(JS("int", "(# + #) | 0", x, other.x), - JS("int", "(# + #) | 0", y, other.y), - JS("int", "(# + #) | 0", z, other.z), - JS("int", "(# + #) | 0", w, other.w)); - } - - Int32x4 operator-(Int32x4 other) { - // Avoid going through the typed array by "| 0" the result. - return new NativeInt32x4._truncated(JS("int", "(# - #) | 0", x, other.x), - JS("int", "(# - #) | 0", y, other.y), - JS("int", "(# - #) | 0", z, other.z), - JS("int", "(# - #) | 0", w, other.w)); - } - - Int32x4 operator-() { - // Avoid going through the typed array by "| 0" the result. - return new NativeInt32x4._truncated(JS("int", "(-#) | 0", x), - JS("int", "(-#) | 0", y), - JS("int", "(-#) | 0", z), - JS("int", "(-#) | 0", w)); - } - - /// Extract the top bit from each lane return them in the first 4 bits. - int get signMask { - int mx = (x & 0x80000000) >> 31; - int my = (y & 0x80000000) >> 31; - int mz = (z & 0x80000000) >> 31; - int mw = (w & 0x80000000) >> 31; - return mx | my << 1 | mz << 2 | mw << 3; - } - - /// Shuffle the lane values. [mask] must be one of the 256 shuffle constants. - Int32x4 shuffle(int mask) { - if ((mask < 0) || (mask > 255)) { - throw new RangeError('mask $mask must be in the range [0..256)'); - } - _list[0] = x; - _list[1] = y; - _list[2] = z; - _list[3] = w; - int _x = _list[mask & 0x3]; - int _y = _list[(mask >> 2) & 0x3]; - int _z = _list[(mask >> 4) & 0x3]; - int _w = _list[(mask >> 6) & 0x3]; - return new NativeInt32x4._truncated(_x, _y, _z, _w); - } - - /// Shuffle the lane values in [this] and [other]. The returned - /// Int32x4 will have XY lanes from [this] and ZW lanes from [other]. - /// Uses the same [mask] as [shuffle]. - Int32x4 shuffleMix(Int32x4 other, int mask) { - if ((mask < 0) || (mask > 255)) { - throw new RangeError('mask $mask must be in the range [0..256)'); - } - _list[0] = x; - _list[1] = y; - _list[2] = z; - _list[3] = w; - int _x = _list[mask & 0x3]; - int _y = _list[(mask >> 2) & 0x3]; - - _list[0] = other.x; - _list[1] = other.y; - _list[2] = other.z; - _list[3] = other.w; - int _z = _list[(mask >> 4) & 0x3]; - int _w = _list[(mask >> 6) & 0x3]; - return new NativeInt32x4._truncated(_x, _y, _z, _w); - } - - /// Returns a new [Int32x4] copied from [this] with a new x value. - Int32x4 withX(int x) { - int _x = _truncate(x); - return new NativeInt32x4._truncated(_x, y, z, w); - } - - /// Returns a new [Int32x4] copied from [this] with a new y value. - Int32x4 withY(int y) { - int _y = _truncate(y); - return new NativeInt32x4._truncated(x, _y, z, w); - } - - /// Returns a new [Int32x4] copied from [this] with a new z value. - Int32x4 withZ(int z) { - int _z = _truncate(z); - return new NativeInt32x4._truncated(x, y, _z, w); - } - - /// Returns a new [Int32x4] copied from [this] with a new w value. - Int32x4 withW(int w) { - int _w = _truncate(w); - return new NativeInt32x4._truncated(x, y, z, _w); - } - - /// Extracted x value. Returns `false` for 0, `true` for any other value. - bool get flagX => x != 0; - /// Extracted y value. Returns `false` for 0, `true` for any other value. - bool get flagY => y != 0; - /// Extracted z value. Returns `false` for 0, `true` for any other value. - bool get flagZ => z != 0; - /// Extracted w value. Returns `false` for 0, `true` for any other value. - bool get flagW => w != 0; - - /// Returns a new [Int32x4] copied from [this] with a new x value. - Int32x4 withFlagX(bool flagX) { - int _x = flagX ? -1 : 0; - return new NativeInt32x4._truncated(_x, y, z, w); - } - - /// Returns a new [Int32x4] copied from [this] with a new y value. - Int32x4 withFlagY(bool flagY) { - int _y = flagY ? -1 : 0; - return new NativeInt32x4._truncated(x, _y, z, w); - } - - /// Returns a new [Int32x4] copied from [this] with a new z value. - Int32x4 withFlagZ(bool flagZ) { - int _z = flagZ ? -1 : 0; - return new NativeInt32x4._truncated(x, y, _z, w); - } - - /// Returns a new [Int32x4] copied from [this] with a new w value. - Int32x4 withFlagW(bool flagW) { - int _w = flagW ? -1 : 0; - return new NativeInt32x4._truncated(x, y, z, _w); - } - - /// Merge [trueValue] and [falseValue] based on [this]' bit mask: - /// Select bit from [trueValue] when bit in [this] is on. - /// Select bit from [falseValue] when bit in [this] is off. - Float32x4 select(Float32x4 trueValue, Float32x4 falseValue) { - var floatList = NativeFloat32x4._list; - var intView = NativeFloat32x4._uint32view; - - floatList[0] = trueValue.x; - floatList[1] = trueValue.y; - floatList[2] = trueValue.z; - floatList[3] = trueValue.w; - int stx = intView[0]; - int sty = intView[1]; - int stz = intView[2]; - int stw = intView[3]; - - floatList[0] = falseValue.x; - floatList[1] = falseValue.y; - floatList[2] = falseValue.z; - floatList[3] = falseValue.w; - int sfx = intView[0]; - int sfy = intView[1]; - int sfz = intView[2]; - int sfw = intView[3]; - int _x = (x & stx) | (~x & sfx); - int _y = (y & sty) | (~y & sfy); - int _z = (z & stz) | (~z & sfz); - int _w = (w & stw) | (~w & sfw); - intView[0] = _x; - intView[1] = _y; - intView[2] = _z; - intView[3] = _w; - return new NativeFloat32x4._truncated( - floatList[0], floatList[1], floatList[2], floatList[3]); - } -} - -class NativeFloat64x2 implements Float64x2 { - final double x; - final double y; - - static NativeFloat64List _list = new NativeFloat64List(2); - static NativeUint32List _uint32View = _list.buffer.asUint32List(); - - NativeFloat64x2(this.x, this.y) { - if (x is! num) throw new ArgumentError(x); - if (y is! num) throw new ArgumentError(y); - } - - NativeFloat64x2.splat(double v) : this(v, v); - - NativeFloat64x2.zero() : this.splat(0.0); - - NativeFloat64x2.fromFloat32x4(Float32x4 v) : this(v.x, v.y); - - /// Arguments [x] and [y] must be doubles. - NativeFloat64x2._doubles(this.x, this.y); - - String toString() => '[$x, $y]'; - - /// Addition operator. - Float64x2 operator+(Float64x2 other) { - return new NativeFloat64x2._doubles(x + other.x, y + other.y); - } - - /// Negate operator. - Float64x2 operator-() { - return new NativeFloat64x2._doubles(-x, -y); - } - - /// Subtraction operator. - Float64x2 operator-(Float64x2 other) { - return new NativeFloat64x2._doubles(x - other.x, y - other.y); - } - /// Multiplication operator. - Float64x2 operator*(Float64x2 other) { - return new NativeFloat64x2._doubles(x * other.x, y * other.y); - } - /// Division operator. - Float64x2 operator/(Float64x2 other) { - return new NativeFloat64x2._doubles(x / other.x, y / other.y); - } - - /// Returns a copy of [this] each lane being scaled by [s]. - Float64x2 scale(double s) { - return new NativeFloat64x2._doubles(x * s, y * s); - } - - /// Returns the absolute value of this [Float64x2]. - Float64x2 abs() { - return new NativeFloat64x2._doubles(x.abs(), y.abs()); - } - - /// Clamps [this] to be in the range [lowerLimit]-[upperLimit]. - Float64x2 clamp(Float64x2 lowerLimit, - Float64x2 upperLimit) { - double _lx = lowerLimit.x; - double _ly = lowerLimit.y; - double _ux = upperLimit.x; - double _uy = upperLimit.y; - double _x = x; - double _y = y; - // MAX(MIN(self, upper), lower). - _x = _x > _ux ? _ux : _x; - _y = _y > _uy ? _uy : _y; - _x = _x < _lx ? _lx : _x; - _y = _y < _ly ? _ly : _y; - return new NativeFloat64x2._doubles(_x, _y); - } - - /// Extract the sign bits from each lane return them in the first 2 bits. - int get signMask { - var view = _uint32View; - _list[0] = x; - _list[1] = y; - var mx = (view[1] & 0x80000000) >> 31; - var my = (view[3] & 0x80000000) >> 31; - return mx | my << 1; - } - - /// Returns a new [Float64x2] copied from [this] with a new x value. - Float64x2 withX(double x) { - if (x is! num) throw new ArgumentError(x); - return new NativeFloat64x2._doubles(x, y); - } - - /// Returns a new [Float64x2] copied from [this] with a new y value. - Float64x2 withY(double y) { - if (y is! num) throw new ArgumentError(y); - return new NativeFloat64x2._doubles(x, y); - } - - /// Returns the lane-wise minimum value in [this] or [other]. - Float64x2 min(Float64x2 other) { - return new NativeFloat64x2._doubles(x < other.x ? x : other.x, - y < other.y ? y : other.y); - - } - - /// Returns the lane-wise maximum value in [this] or [other]. - Float64x2 max(Float64x2 other) { - return new NativeFloat64x2._doubles(x > other.x ? x : other.x, - y > other.y ? y : other.y); - } - - /// Returns the lane-wise square root of [this]. - Float64x2 sqrt() { - return new NativeFloat64x2._doubles(Math.sqrt(x), Math.sqrt(y)); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/regexp_helper.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/regexp_helper.dart deleted file mode 100644 index 4bdf754f718b..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/regexp_helper.dart +++ /dev/null @@ -1,237 +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. - -part of _js_helper; - -// Helper method used by internal libraries. -regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp; - -/** - * Returns a native version of the RegExp with the global flag set. - * - * The RegExp's `lastIndex` property is zero when it is returned. - * - * The returned regexp is shared, and its `lastIndex` property may be - * modified by other uses, so the returned regexp must be used immediately - * when it's returned, with no user-provided code run in between. - */ -regExpGetGlobalNative(JSSyntaxRegExp regexp) { - var nativeRegexp = regexp._nativeGlobalVersion; - JS("void", "#.lastIndex = 0", nativeRegexp); - return nativeRegexp; -} - -/** - * Computes the number of captures in a regexp. - * - * This currently involves creating a new RegExp object with a different - * source and running it against the empty string (the last part is usually - * fast). - * - * The JSSyntaxRegExp could cache the result, and set the cache any time - * it finds a match. - */ -int regExpCaptureCount(JSSyntaxRegExp regexp) { - var nativeAnchoredRegExp = regexp._nativeAnchoredVersion; - var match = JS('JSExtendableArray', "#.exec('')", nativeAnchoredRegExp); - // The native-anchored regexp always have one capture more than the original, - // and always matches the empty string. - return match.length - 2; -} - -class JSSyntaxRegExp implements RegExp { - final String pattern; - final _nativeRegExp; - var _nativeGlobalRegExp; - var _nativeAnchoredRegExp; - - String toString() => "RegExp/$pattern/"; - - JSSyntaxRegExp(String source, - { bool multiLine: false, - bool caseSensitive: true }) - : this.pattern = source, - this._nativeRegExp = - makeNative(source, multiLine, caseSensitive, false); - - get _nativeGlobalVersion { - if (_nativeGlobalRegExp != null) return _nativeGlobalRegExp; - return _nativeGlobalRegExp = makeNative(pattern, - _isMultiLine, - _isCaseSensitive, - true); - } - - get _nativeAnchoredVersion { - if (_nativeAnchoredRegExp != null) return _nativeAnchoredRegExp; - // An "anchored version" of a regexp is created by adding "|()" to the - // source. This means that the regexp always matches at the first position - // that it tries, and you can see if the original regexp matched, or it - // was the added zero-width match that matched, by looking at the last - // capture. If it is a String, the match participated, otherwise it didn't. - return _nativeAnchoredRegExp = makeNative("$pattern|()", - _isMultiLine, - _isCaseSensitive, - true); - } - - bool get _isMultiLine => JS("bool", "#.multiline", _nativeRegExp); - bool get _isCaseSensitive => JS("bool", "!#.ignoreCase", _nativeRegExp); - - static makeNative( - String source, bool multiLine, bool caseSensitive, bool global) { - checkString(source); - String m = multiLine ? 'm' : ''; - String i = caseSensitive ? '' : 'i'; - String g = global ? 'g' : ''; - // We're using the JavaScript's try catch instead of the Dart one - // to avoid dragging in Dart runtime support just because of using - // RegExp. - var regexp = JS('', - '(function() {' - 'try {' - 'return new RegExp(#, # + # + #);' - '} catch (e) {' - 'return e;' - '}' - '})()', source, m, i, g); - if (JS('bool', '# instanceof RegExp', regexp)) return regexp; - // The returned value is the JavaScript exception. Turn it into a - // Dart exception. - String errorMessage = JS('String', r'String(#)', regexp); - throw new FormatException( - "Illegal RegExp pattern: $source, $errorMessage"); - } - - Match firstMatch(String string) { - List m = JS('JSExtendableArray|Null', - r'#.exec(#)', - _nativeRegExp, - checkString(string)); - if (m == null) return null; - return new _MatchImplementation(this, m); - } - - bool hasMatch(String string) { - return JS('bool', r'#.test(#)', _nativeRegExp, checkString(string)); - } - - String stringMatch(String string) { - var match = firstMatch(string); - if (match != null) return match.group(0); - return null; - } - - Iterable allMatches(String string, [int start = 0]) { - checkString(string); - checkInt(start); - if (start < 0 || start > string.length) { - throw new RangeError.range(start, 0, string.length); - } - return new _AllMatchesIterable(this, string, start); - } - - Match _execGlobal(String string, int start) { - Object regexp = _nativeGlobalVersion; - JS("void", "#.lastIndex = #", regexp, start); - List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string); - if (match == null) return null; - return new _MatchImplementation(this, match); - } - - Match _execAnchored(String string, int start) { - Object regexp = _nativeAnchoredVersion; - JS("void", "#.lastIndex = #", regexp, start); - List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string); - if (match == null) return null; - // If the last capture group participated, the original regexp did not - // match at the start position. - if (match[match.length - 1] != null) return null; - match.length -= 1; - return new _MatchImplementation(this, match); - } - - Match matchAsPrefix(String string, [int start = 0]) { - if (start < 0 || start > string.length) { - throw new RangeError.range(start, 0, string.length); - } - return _execAnchored(string, start); - } - - bool get isMultiLine => _isMultiLine; - bool get isCaseSensitive => _isCaseSensitive; -} - -class _MatchImplementation implements Match { - final Pattern pattern; - // Contains a JS RegExp match object. - // It is an Array of String values with extra "index" and "input" properties. - final List _match; - - _MatchImplementation(this.pattern, this._match) { - assert(JS("var", "#.input", _match) is String); - assert(JS("var", "#.index", _match) is int); - } - - String get input => JS("String", "#.input", _match); - int get start => JS("int", "#.index", _match); - int get end => start + _match[0].length; - - String group(int index) => _match[index]; - String operator [](int index) => group(index); - int get groupCount => _match.length - 1; - - List groups(List groups) { - List out = []; - for (int i in groups) { - out.add(group(i)); - } - return out; - } -} - -class _AllMatchesIterable extends IterableBase { - final JSSyntaxRegExp _re; - final String _string; - final int _start; - - _AllMatchesIterable(this._re, this._string, this._start); - - Iterator get iterator => new _AllMatchesIterator(_re, _string, _start); -} - -class _AllMatchesIterator implements Iterator { - final JSSyntaxRegExp _regExp; - String _string; - int _nextIndex; - Match _current; - - _AllMatchesIterator(this._regExp, this._string, this._nextIndex); - - Match get current => _current; - - bool moveNext() { - if (_string == null) return false; - if (_nextIndex <= _string.length) { - var match = _regExp._execGlobal(_string, _nextIndex); - if (match != null) { - _current = match; - int nextIndex = match.end; - if (match.start == nextIndex) { - nextIndex++; - } - _nextIndex = nextIndex; - return true; - } - } - _current = null; - _string = null; // Marks iteration as ended. - return false; - } -} - -/** Find the first match of [regExp] in [string] at or after [start]. */ -Match firstMatchAfter(JSSyntaxRegExp regExp, String string, int start) { - return regExp._execGlobal(string, start); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart deleted file mode 100644 index bd72f0927eed..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/// Contains the names of globals that are embedded into the output by the -/// compiler. -/// -/// Variables embedded this way should be access with `JS_EMBEDDED_GLOBAL` from -/// the `_foreign_helper` library. -/// -/// This library is shared between the compiler and the runtime system. -library dart2js._embedded_names; - -const DISPATCH_PROPERTY_NAME = "dispatchPropertyName"; -const TYPE_INFORMATION = 'typeInformation'; -const GLOBAL_FUNCTIONS = 'globalFunctions'; -const STATICS = 'statics'; - -/** - * If [JSInvocationMirror._invokeOn] is being used, this embedded global - * contains a JavaScript map with the names of methods that are - * intercepted. - */ -const INTERCEPTED_NAMES = 'interceptedNames'; - -const MANGLED_GLOBAL_NAMES = 'mangledGlobalNames'; -const MANGLED_NAMES = 'mangledNames'; -const LIBRARIES = 'libraries'; -const FINISHED_CLASSES = 'finishedClasses'; -const ALL_CLASSES = 'allClasses'; -const METADATA = 'metadata'; -const INTERCEPTORS_BY_TAG = 'interceptorsByTag'; -const LEAF_TAGS = 'leafTags'; -const LAZIES = 'lazies'; -const GET_ISOLATE_TAG = 'getIsolateTag'; -const ISOLATE_TAG = 'isolateTag'; -const CURRENT_SCRIPT = 'currentScript'; -const DEFERRED_LIBRARY_URIS = 'deferredLibraryUris'; -const DEFERRED_LIBRARY_HASHES = 'deferredLibraryHashes'; -const INITIALIZE_LOADED_HUNK = 'initializeLoadedHunk'; -const IS_HUNK_LOADED = 'isHunkLoaded'; -const IS_HUNK_INITIALIZED = 'isHunkInitialized'; -const DEFERRED_INITIALIZED = 'deferredInitialized'; -const CLASS_ID_EXTRACTOR = 'classIdExtractor'; -const CLASS_FIELDS_EXTRACTOR = 'classFieldsExtractor'; -const INSTANCE_FROM_CLASS_ID = "instanceFromClassId"; -const INITIALIZE_EMPTY_INSTANCE = "initializeEmptyInstance"; -const TYPEDEF_TYPE_PROPERTY_NAME = r"$typedefType"; -const TYPEDEF_PREDICATE_PROPERTY_NAME = r"$$isTypedef"; -const NATIVE_SUPERCLASS_TAG_NAME = r"$nativeSuperclassTag"; - -const MAP_TYPE_TO_INTERCEPTOR = "mapTypeToInterceptor"; diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/string_helper.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/string_helper.dart deleted file mode 100644 index ff2505729a1b..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/compiler/js_lib/string_helper.dart +++ /dev/null @@ -1,215 +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. - -part of _js_helper; - -class StringMatch implements Match { - const StringMatch(int this.start, - String this.input, - String this.pattern); - - int get end => start + pattern.length; - String operator[](int g) => group(g); - int get groupCount => 0; - - String group(int group_) { - if (group_ != 0) { - throw new RangeError.value(group_); - } - return pattern; - } - - List groups(List groups_) { - List result = new List(); - for (int g in groups_) { - result.add(group(g)); - } - return result; - } - - final int start; - final String input; - final String pattern; -} - -List allMatchesInStringUnchecked(String needle, String haystack, - int startIndex) { - // Copied from StringBase.allMatches in - // /runtime/lib/string_base.dart - List result = new List(); - int length = haystack.length; - int patternLength = needle.length; - while (true) { - int position = haystack.indexOf(needle, startIndex); - if (position == -1) { - break; - } - result.add(new StringMatch(position, haystack, needle)); - int endIndex = position + patternLength; - if (endIndex == length) { - break; - } else if (position == endIndex) { - ++startIndex; // empty match, advance and restart - } else { - startIndex = endIndex; - } - } - return result; -} - -stringContainsUnchecked(receiver, other, startIndex) { - if (other is String) { - return receiver.indexOf(other, startIndex) != -1; - } else if (other is JSSyntaxRegExp) { - return other.hasMatch(receiver.substring(startIndex)); - } else { - var substr = receiver.substring(startIndex); - return other.allMatches(substr).isNotEmpty; - } -} - -stringReplaceJS(receiver, replacer, to) { - // The JavaScript String.replace method recognizes replacement - // patterns in the replacement string. Dart does not have that - // behavior. - to = JS('String', r'#.replace(/\$/g, "$$$$")', to); - return JS('String', r'#.replace(#, #)', receiver, replacer, to); -} - -stringReplaceFirstRE(receiver, regexp, to, startIndex) { - var match = regexp._execGlobal(receiver, startIndex); - if (match == null) return receiver; - var start = match.start; - var end = match.end; - return "${receiver.substring(0,start)}$to${receiver.substring(end)}"; -} - -const String ESCAPE_REGEXP = r'[[\]{}()*+?.\\^$|]'; - -stringReplaceAllUnchecked(receiver, from, to) { - checkString(to); - if (from is String) { - if (from == "") { - if (receiver == "") { - return to; - } else { - StringBuffer result = new StringBuffer(); - int length = receiver.length; - result.write(to); - for (int i = 0; i < length; i++) { - result.write(receiver[i]); - result.write(to); - } - return result.toString(); - } - } else { - var quoter = JS('', "new RegExp(#, 'g')", ESCAPE_REGEXP); - var quoted = JS('String', r'#.replace(#, "\\$&")', from, quoter); - var replacer = JS('', "new RegExp(#, 'g')", quoted); - return stringReplaceJS(receiver, replacer, to); - } - } else if (from is JSSyntaxRegExp) { - var re = regExpGetGlobalNative(from); - return stringReplaceJS(receiver, re, to); - } else { - checkNull(from); - // TODO(floitsch): implement generic String.replace (with patterns). - throw "String.replaceAll(Pattern) UNIMPLEMENTED"; - } -} - -String _matchString(Match match) => match[0]; -String _stringIdentity(String string) => string; - -stringReplaceAllFuncUnchecked(receiver, pattern, onMatch, onNonMatch) { - if (pattern is! Pattern) { - throw new ArgumentError("${pattern} is not a Pattern"); - } - if (onMatch == null) onMatch = _matchString; - if (onNonMatch == null) onNonMatch = _stringIdentity; - if (pattern is String) { - return stringReplaceAllStringFuncUnchecked(receiver, pattern, - onMatch, onNonMatch); - } - StringBuffer buffer = new StringBuffer(); - int startIndex = 0; - for (Match match in pattern.allMatches(receiver)) { - buffer.write(onNonMatch(receiver.substring(startIndex, match.start))); - buffer.write(onMatch(match)); - startIndex = match.end; - } - buffer.write(onNonMatch(receiver.substring(startIndex))); - return buffer.toString(); -} - -stringReplaceAllEmptyFuncUnchecked(receiver, onMatch, onNonMatch) { - // Pattern is the empty string. - StringBuffer buffer = new StringBuffer(); - int length = receiver.length; - int i = 0; - buffer.write(onNonMatch("")); - while (i < length) { - buffer.write(onMatch(new StringMatch(i, receiver, ""))); - // Special case to avoid splitting a surrogate pair. - int code = receiver.codeUnitAt(i); - if ((code & ~0x3FF) == 0xD800 && length > i + 1) { - // Leading surrogate; - code = receiver.codeUnitAt(i + 1); - if ((code & ~0x3FF) == 0xDC00) { - // Matching trailing surrogate. - buffer.write(onNonMatch(receiver.substring(i, i + 2))); - i += 2; - continue; - } - } - buffer.write(onNonMatch(receiver[i])); - i++; - } - buffer.write(onMatch(new StringMatch(i, receiver, ""))); - buffer.write(onNonMatch("")); - return buffer.toString(); -} - -stringReplaceAllStringFuncUnchecked(receiver, pattern, onMatch, onNonMatch) { - int patternLength = pattern.length; - if (patternLength == 0) { - return stringReplaceAllEmptyFuncUnchecked(receiver, onMatch, onNonMatch); - } - int length = receiver.length; - StringBuffer buffer = new StringBuffer(); - int startIndex = 0; - while (startIndex < length) { - int position = receiver.indexOf(pattern, startIndex); - if (position == -1) { - break; - } - buffer.write(onNonMatch(receiver.substring(startIndex, position))); - buffer.write(onMatch(new StringMatch(position, receiver, pattern))); - startIndex = position + patternLength; - } - buffer.write(onNonMatch(receiver.substring(startIndex))); - return buffer.toString(); -} - - -stringReplaceFirstUnchecked(receiver, from, to, [int startIndex = 0]) { - if (from is String) { - var index = receiver.indexOf(from, startIndex); - if (index < 0) return receiver; - return '${receiver.substring(0, index)}$to' - '${receiver.substring(index + from.length)}'; - } else if (from is JSSyntaxRegExp) { - return startIndex == 0 ? - stringReplaceJS(receiver, regExpGetNative(from), to) : - stringReplaceFirstRE(receiver, from, to, startIndex); - } else { - checkNull(from); - // TODO(floitsch): implement generic String.replace (with patterns). - throw "String.replace(Pattern) UNIMPLEMENTED"; - } -} - -stringJoinUnchecked(array, separator) { - return JS('String', r'#.join(#)', array, separator); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/_internal/libraries.dart b/pkg/dev_compiler/test/generated_sdk/lib/_internal/libraries.dart deleted file mode 100644 index 7594c938f9ef..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/_internal/libraries.dart +++ /dev/null @@ -1,329 +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. - -library libraries; - -/** - * A bit flag used by [LibraryInfo] indicating that a library is used by dart2js - */ -const int DART2JS_PLATFORM = 1; - -/** - * A bit flag used by [LibraryInfo] indicating that a library is used by the VM - */ -const int VM_PLATFORM = 2; - -/** - * Mapping of "dart:" library name (e.g. "core") to information about that library. - * This information is structured such that Dart Editor can parse this file - * and extract the necessary information without executing it - * while other tools can access via execution. - */ -const Map LIBRARIES = const { - - "async": const LibraryInfo( - "async/async.dart", - maturity: Maturity.STABLE, - dart2jsPatchPath: "_internal/compiler/js_lib/async_patch.dart"), - - "_blink": const LibraryInfo( - "_blink/dartium/_blink_dartium.dart", - category: "Client", - implementation: true, - documented: false, - platforms: VM_PLATFORM), - - "_chrome": const LibraryInfo( - "_chrome/dart2js/chrome_dart2js.dart", - documented: false, - category: "Client"), - - "collection": const LibraryInfo( - "collection/collection.dart", - maturity: Maturity.STABLE, - dart2jsPatchPath: "_internal/compiler/js_lib/collection_patch.dart"), - - "convert": const LibraryInfo( - "convert/convert.dart", - maturity: Maturity.STABLE, - dart2jsPatchPath: "_internal/compiler/js_lib/convert_patch.dart"), - - "core": const LibraryInfo( - "core/core.dart", - maturity: Maturity.STABLE, - dart2jsPatchPath: "_internal/compiler/js_lib/core_patch.dart"), - - "html": const LibraryInfo( - "html/dartium/html_dartium.dart", - category: "Client", - maturity: Maturity.WEB_STABLE, - dart2jsPath: "html/dart2js/html_dart2js.dart"), - - "html_common": const LibraryInfo( - "html/html_common/html_common.dart", - category: "Client", - maturity: Maturity.WEB_STABLE, - dart2jsPath: "html/html_common/html_common_dart2js.dart", - documented: false, - implementation: true), - - "indexed_db": const LibraryInfo( - "indexed_db/dartium/indexed_db_dartium.dart", - category: "Client", - maturity: Maturity.WEB_STABLE, - dart2jsPath: "indexed_db/dart2js/indexed_db_dart2js.dart"), - - "io": const LibraryInfo( - "io/io.dart", - category: "Server", - maturity: Maturity.STABLE, - dart2jsPatchPath: "_internal/compiler/js_lib/io_patch.dart"), - - "isolate": const LibraryInfo( - "isolate/isolate.dart", - maturity: Maturity.STABLE, - dart2jsPatchPath: "_internal/compiler/js_lib/isolate_patch.dart"), - - "js": const LibraryInfo( - "js/dartium/js_dartium.dart", - category: "Client", - maturity: Maturity.STABLE, - dart2jsPath: "js/dart2js/js_dart2js.dart"), - - "math": const LibraryInfo( - "math/math.dart", - maturity: Maturity.STABLE, - dart2jsPatchPath: "_internal/compiler/js_lib/math_patch.dart"), - - "mirrors": const LibraryInfo( - "mirrors/mirrors.dart", - maturity: Maturity.UNSTABLE, - dart2jsPatchPath: "_internal/compiler/js_lib/mirrors_patch.dart"), - - "profiler": const LibraryInfo( - "profiler/profiler.dart", - maturity: Maturity.UNSTABLE), - - "nativewrappers": const LibraryInfo( - "html/dartium/nativewrappers.dart", - category: "Client", - implementation: true, - documented: false, - platforms: VM_PLATFORM), - - "typed_data": const LibraryInfo( - "typed_data/typed_data.dart", - maturity: Maturity.STABLE, - dart2jsPatchPath: "_internal/compiler/js_lib/typed_data_patch.dart"), - - "_native_typed_data": const LibraryInfo( - "_internal/compiler/js_lib/native_typed_data.dart", - category: "Internal", - implementation: true, - documented: false, - platforms: DART2JS_PLATFORM), - - "svg": const LibraryInfo( - "svg/dartium/svg_dartium.dart", - category: "Client", - maturity: Maturity.WEB_STABLE, - dart2jsPath: "svg/dart2js/svg_dart2js.dart"), - - "web_audio": const LibraryInfo( - "web_audio/dartium/web_audio_dartium.dart", - category: "Client", - maturity: Maturity.WEB_STABLE, - dart2jsPath: "web_audio/dart2js/web_audio_dart2js.dart"), - - "web_gl": const LibraryInfo( - "web_gl/dartium/web_gl_dartium.dart", - category: "Client", - maturity: Maturity.WEB_STABLE, - dart2jsPath: "web_gl/dart2js/web_gl_dart2js.dart"), - - "web_sql": const LibraryInfo( - "web_sql/dartium/web_sql_dartium.dart", - category: "Client", - maturity: Maturity.WEB_STABLE, - dart2jsPath: "web_sql/dart2js/web_sql_dart2js.dart"), - - "_internal": const LibraryInfo( - "internal/internal.dart", - category: "Internal", - documented: false, - dart2jsPatchPath: - "_internal/compiler/js_lib/internal_patch.dart"), - - "_js_helper": const LibraryInfo( - "_internal/compiler/js_lib/js_helper.dart", - category: "Internal", - documented: false, - platforms: DART2JS_PLATFORM), - - "_interceptors": const LibraryInfo( - "_internal/compiler/js_lib/interceptors.dart", - category: "Internal", - documented: false, - platforms: DART2JS_PLATFORM), - - "_foreign_helper": const LibraryInfo( - "_internal/compiler/js_lib/foreign_helper.dart", - category: "Internal", - documented: false, - platforms: DART2JS_PLATFORM), - - "_isolate_helper": const LibraryInfo( - "_internal/compiler/js_lib/isolate_helper.dart", - category: "Internal", - documented: false, - platforms: DART2JS_PLATFORM), - - "_js_mirrors": const LibraryInfo( - "_internal/compiler/js_lib/js_mirrors.dart", - category: "Internal", - documented: false, - platforms: DART2JS_PLATFORM), - - "_js_names": const LibraryInfo( - "_internal/compiler/js_lib/js_names.dart", - category: "Internal", - documented: false, - platforms: DART2JS_PLATFORM), - - "_js_primitives": const LibraryInfo( - "_internal/compiler/js_lib/js_primitives.dart", - category: "Internal", - documented: false, - platforms: DART2JS_PLATFORM), - - // TODO(ahe): This library is only for dart2dart, perhaps it should use a - // different platform. - "_mirror_helper": const LibraryInfo( - "_internal/compiler/js_lib/mirror_helper.dart", - category: "Internal", - documented: false, - platforms: DART2JS_PLATFORM), - - "_js_embedded_names": const LibraryInfo( - "_internal/compiler/js_lib/shared/embedded_names.dart", - category: "Internal", - documented: false, - platforms: DART2JS_PLATFORM), - - "_metadata": const LibraryInfo( - "html/html_common/metadata.dart", - category: "Internal", - documented: false, - platforms: DART2JS_PLATFORM), -}; - -/** - * Information about a "dart:" library. - */ -class LibraryInfo { - - /** - * Path to the library's *.dart file relative to this file. - */ - final String path; - - /** - * The category in which the library should appear in the editor - * (e.g. "Shared", "Client", "Server", ...). - * If a category is not specified it defaults to "Shared". - */ - final String category; - - /** - * Path to the dart2js library's *.dart file relative to this file - * or null if dart2js uses the common library path defined above. - * Access using the [#getDart2JsPath()] method. - */ - final String dart2jsPath; - - /** - * Path to the dart2js library's patch file relative to this file - * or null if no dart2js patch file associated with this library. - * Access using the [#getDart2JsPatchPath()] method. - */ - final String dart2jsPatchPath; - - /** - * True if this library is documented and should be shown to the user. - */ - final bool documented; - - /** - * Bit flags indicating which platforms consume this library. - * See [DART2JS_LIBRARY] and [VM_LIBRARY]. - */ - final int platforms; - - /** - * True if the library contains implementation details for another library. - * The implication is that these libraries are less commonly used - * and that tools like Dart Editor should not show these libraries - * in a list of all libraries unless the user specifically asks the tool to - * do so. - */ - final bool implementation; - - /** - * States the current maturity of this library. - */ - final Maturity maturity; - - const LibraryInfo(this.path, { - this.category: "Shared", - this.dart2jsPath, - this.dart2jsPatchPath, - this.implementation: false, - this.documented: true, - this.maturity: Maturity.UNSPECIFIED, - this.platforms: DART2JS_PLATFORM | VM_PLATFORM}); - - bool get isDart2jsLibrary => (platforms & DART2JS_PLATFORM) != 0; - bool get isVmLibrary => (platforms & VM_PLATFORM) != 0; -} - - - -/** - * Abstraction to capture the maturity of a library. - */ -class Maturity { - final int level; - final String name; - final String description; - - const Maturity(this.level, this.name, this.description); - - String toString() => "$name: $level\n$description\n"; - - static const Maturity DEPRECATED = const Maturity(0, "Deprecated", - "This library will be remove before next major release."); - - static const Maturity EXPERIMENTAL = const Maturity(1, "Experimental", - "This library is experimental and will likely change or be removed\n" - "in future versions."); - - static const Maturity UNSTABLE = const Maturity(2, "Unstable", - "This library is in still changing and have not yet endured\n" - "sufficient real-world testing.\n" - "Backwards-compatibility is NOT guaranteed."); - - static const Maturity WEB_STABLE = const Maturity(3, "Web Stable", - "This library is tracking the DOM evolution as defined by WC3.\n" - "Backwards-compatibility is NOT guaranteed."); - - static const Maturity STABLE = const Maturity(4, "Stable", - "The library is stable. API backwards-compatibility is guaranteed.\n" - "However implementation details might change."); - - static const Maturity LOCKED = const Maturity(5, "Locked", - "This library will not change except when serious bugs are encountered."); - - static const Maturity UNSPECIFIED = const Maturity(-1, "Unspecified", - "The maturity for this library has not been specified."); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/async.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/async.dart deleted file mode 100644 index 05bee577b51f..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/async.dart +++ /dev/null @@ -1,123 +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. - -/** - * Support for asynchronous programming, - * with classes such as Future and Stream. - * - * Understanding [Future]s and [Stream]s is a prerequisite for - * writing just about any Dart program. - * - * To use this library in your code: - * - * import 'dart:async'; - * - * ## Future - * - * A Future object represents a computation whose return value - * might not yet be available. - * The Future returns the value of the computation - * when it completes at some time in the future. - * Futures are often used for potentially lengthy computations - * such as I/O and interaction with users. - * - * Many methods in the Dart libraries return Futures when - * performing tasks. For example, when binding an HttpServer - * to a host and port, the `bind()` method returns a Future. - * - * HttpServer.bind('127.0.0.1', 4444) - * .then((server) => print('${server.isBroadcast}')) - * .catchError(print); - * - * [Future.then] registers a callback function that runs - * when the Future's operation, in this case the `bind()` method, - * completes successfully. - * The value returned by the operation - * is passed into the callback function. - * In this example, the `bind()` method returns the HttpServer - * object. The callback function prints one of its properties. - * [Future.catchError] registers a callback function that - * runs if an error occurs within the Future. - * - * ## Stream - * - * A Stream provides an asynchronous sequence of data. - * Examples of data sequences include individual events, like mouse clicks, - * or sequential chunks of larger data, like multiple byte lists with the - * contents of a file - * such as mouse clicks, and a stream of byte lists read from a file. - * The following example opens a file for reading. - * [Stream.listen] registers a callback function that runs - * each time more data is available. - * - * Stream> stream = new File('quotes.txt').openRead(); - * stream.transform(UTF8.decoder).listen(print); - * - * The stream emits a sequence of a list of bytes. - * The program must interpret the bytes or handle the raw byte data. - * Here, the code uses a UTF8 decoder (provided in the `dart:convert` library) - * to convert the sequence of bytes into a sequence - * of Dart strings. - * - * Another common use of streams is for user-generated events - * in a web app: The following code listens for mouse clicks on a button. - * - * querySelector('#myButton').onClick.listen((_) => print('Click.')); - * - * ## Other resources - * - * * The [dart:async section of the library tour] - * (https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html#ch03-asynchronous-programming): - * A brief overview of asynchronous programming. - * - * * [Use Future-Based APIs] - * (https://www.dartlang.org/docs/tutorials/futures/): A closer look at - * Futures and how to use them to write asynchronous Dart code. - * - * * [Futures and Error Handling] - * (https://www.dartlang.org/articles/futures-and-error-handling/): Everything - * you wanted to know about handling errors and exceptions when working with - * Futures (but were afraid to ask). - * - * * [The Event Loop and Dart](https://www.dartlang.org/articles/event-loop/): - * Learn how Dart handles the event queue and microtask queue, so you can write - * better asynchronous code with fewer surprises. - * - * * [Asynchronous Unit Testing with Dart] - * (https://www.dartlang.org/articles/dart-unit-tests/#asynchronous-tests): How - * to test asynchronous code. - */ -library dart.async; - -import "dart:collection"; -import "dart:_internal" show deprecated, printToZone, printToConsole, - IterableElementError; -import 'dart:_js_helper' show - patch, - Primitives, - convertDartClosureToJS, - requiresPreamble; -import 'dart:_isolate_helper' show - IsolateNatives, - TimerImpl, - leaveJsAsync, - enterJsAsync, - isWorker; -import 'dart:_foreign_helper' show JS; - -part 'async_error.dart'; -part 'broadcast_stream_controller.dart'; -part 'deferred_load.dart'; -part 'future.dart'; -part 'future_impl.dart'; -part 'schedule_microtask.dart'; -part 'stream.dart'; -part 'stream_controller.dart'; -part 'stream_impl.dart'; -part 'stream_pipe.dart'; -part 'stream_transformers.dart'; -part 'timer.dart'; -part 'zone.dart'; - -bool get _hasDocument => JS('String', 'typeof document') == 'object'; \ No newline at end of file diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/async_error.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/async_error.dart deleted file mode 100644 index 9a640859b124..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/async_error.dart +++ /dev/null @@ -1,44 +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. - -part of dart.async; - -_invokeErrorHandler(Function errorHandler, - Object error, StackTrace stackTrace) { - if (errorHandler is ZoneBinaryCallback) { - return errorHandler(error, stackTrace); - } else { - return errorHandler(error); - } -} - -Function _registerErrorHandler(Function errorHandler, Zone zone) { - if (errorHandler is ZoneBinaryCallback) { - return zone.registerBinaryCallback(errorHandler); - } else { - return zone.registerUnaryCallback(errorHandler); - } -} - -class _UncaughtAsyncError extends AsyncError { - _UncaughtAsyncError(error, StackTrace stackTrace) - : super(error, _getBestStackTrace(error, stackTrace)); - - static StackTrace _getBestStackTrace(error, StackTrace stackTrace) { - if (stackTrace != null) return stackTrace; - if (error is Error) { - return error.stackTrace; - } - return null; - } - - String toString() { - String result = "Uncaught Error: ${error}"; - - if (stackTrace != null) { - result += "\nStack Trace:\n$stackTrace"; - } - return result; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/broadcast_stream_controller.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/broadcast_stream_controller.dart deleted file mode 100644 index e71d3a3deeac..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/broadcast_stream_controller.dart +++ /dev/null @@ -1,512 +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. - -part of dart.async; - -class _BroadcastStream extends _ControllerStream { - _BroadcastStream(_StreamControllerLifecycle controller) : super(controller); - - bool get isBroadcast => true; -} - -abstract class _BroadcastSubscriptionLink { - _BroadcastSubscriptionLink _next; - _BroadcastSubscriptionLink _previous; -} - -class _BroadcastSubscription extends _ControllerSubscription - implements _BroadcastSubscriptionLink { - static const int _STATE_EVENT_ID = 1; - static const int _STATE_FIRING = 2; - static const int _STATE_REMOVE_AFTER_FIRING = 4; - // TODO(lrn): Use the _state field on _ControllerSubscription to - // also store this state. Requires that the subscription implementation - // does not assume that it's use of the state integer is the only use. - int _eventState; - - _BroadcastSubscriptionLink _next; - _BroadcastSubscriptionLink _previous; - - _BroadcastSubscription(_StreamControllerLifecycle controller, - void onData(T data), - Function onError, - void onDone(), - bool cancelOnError) - : super(controller, onData, onError, onDone, cancelOnError) { - _next = _previous = this; - } - - _BroadcastStreamController get _controller => super._controller; - - bool _expectsEvent(int eventId) => - (_eventState & _STATE_EVENT_ID) == eventId; - - void _toggleEventId() { - _eventState ^= _STATE_EVENT_ID; - } - - bool get _isFiring => (_eventState & _STATE_FIRING) != 0; - - void _setRemoveAfterFiring() { - assert(_isFiring); - _eventState |= _STATE_REMOVE_AFTER_FIRING; - } - - bool get _removeAfterFiring => - (_eventState & _STATE_REMOVE_AFTER_FIRING) != 0; - - // The controller._recordPause doesn't do anything for a broadcast controller, - // so we don't bother calling it. - void _onPause() { } - - // The controller._recordResume doesn't do anything for a broadcast - // controller, so we don't bother calling it. - void _onResume() { } - - // _onCancel is inherited. -} - - -abstract class _BroadcastStreamController - implements StreamController, - _StreamControllerLifecycle, - _BroadcastSubscriptionLink, - _EventSink, - _EventDispatch { - static const int _STATE_INITIAL = 0; - static const int _STATE_EVENT_ID = 1; - static const int _STATE_FIRING = 2; - static const int _STATE_CLOSED = 4; - static const int _STATE_ADDSTREAM = 8; - - final _NotificationHandler _onListen; - final _NotificationHandler _onCancel; - - // State of the controller. - int _state; - - // Double-linked list of active listeners. - _BroadcastSubscriptionLink _next; - _BroadcastSubscriptionLink _previous; - - // Extra state used during an [addStream] call. - _AddStreamState _addStreamState; - - /** - * Future returned by [close] and [done]. - * - * The future is completed whenever the done event has been sent to all - * relevant listeners. - * The relevant listeners are the ones that were listening when [close] was - * called. When all of these have been canceled (sending the done event makes - * them cancel, but they can also be canceled before sending the event), - * this future completes. - * - * Any attempt to listen after calling [close] will throw, so there won't - * be any further listeners. - */ - _Future _doneFuture; - - _BroadcastStreamController(this._onListen, this._onCancel) - : _state = _STATE_INITIAL { - _next = _previous = this; - } - - // StreamController interface. - - Stream get stream => new _BroadcastStream(this); - - StreamSink get sink => new _StreamSinkWrapper(this); - - bool get isClosed => (_state & _STATE_CLOSED) != 0; - - /** - * A broadcast controller is never paused. - * - * Each receiving stream may be paused individually, and they handle their - * own buffering. - */ - bool get isPaused => false; - - /** Whether there are currently one or more subscribers. */ - bool get hasListener => !_isEmpty; - - /** - * Test whether the stream has exactly one listener. - * - * Assumes that the stream has a listener (not [_isEmpty]). - */ - bool get _hasOneListener { - assert(!_isEmpty); - return identical(_next._next, this); - } - - /** Whether an event is being fired (sent to some, but not all, listeners). */ - bool get _isFiring => (_state & _STATE_FIRING) != 0; - - bool get _isAddingStream => (_state & _STATE_ADDSTREAM) != 0; - - bool get _mayAddEvent => (_state < _STATE_CLOSED); - - _Future _ensureDoneFuture() { - if (_doneFuture != null) return _doneFuture; - return _doneFuture = new _Future(); - } - - // Linked list helpers - - bool get _isEmpty => identical(_next, this); - - /** Adds subscription to linked list of active listeners. */ - void _addListener(_BroadcastSubscription subscription) { - assert(identical(subscription._next, subscription)); - // Insert in linked list just before `this`. - subscription._previous = _previous; - subscription._next = this; - this._previous._next = subscription; - this._previous = subscription; - subscription._eventState = (_state & _STATE_EVENT_ID); - } - - void _removeListener(_BroadcastSubscription subscription) { - assert(identical(subscription._controller, this)); - assert(!identical(subscription._next, subscription)); - _BroadcastSubscriptionLink previous = subscription._previous; - _BroadcastSubscriptionLink next = subscription._next; - previous._next = next; - next._previous = previous; - subscription._next = subscription._previous = subscription; - } - - // _StreamControllerLifecycle interface. - - StreamSubscription _subscribe( - void onData(T data), - Function onError, - void onDone(), - bool cancelOnError) { - if (isClosed) { - if (onDone == null) onDone = _nullDoneHandler; - return new _DoneStreamSubscription(onDone); - } - StreamSubscription subscription = - new _BroadcastSubscription(this, onData, onError, onDone, - cancelOnError); - _addListener(subscription); - if (identical(_next, _previous)) { - // Only one listener, so it must be the first listener. - _runGuarded(_onListen); - } - return subscription; - } - - Future _recordCancel(StreamSubscription subscription) { - // If already removed by the stream, don't remove it again. - if (identical(subscription._next, subscription)) return null; - assert(!identical(subscription._next, subscription)); - if (subscription._isFiring) { - subscription._setRemoveAfterFiring(); - } else { - assert(!identical(subscription._next, subscription)); - _removeListener(subscription); - // If we are currently firing an event, the empty-check is performed at - // the end of the listener loop instead of here. - if (!_isFiring && _isEmpty) { - _callOnCancel(); - } - } - return null; - } - - void _recordPause(StreamSubscription subscription) {} - void _recordResume(StreamSubscription subscription) {} - - // EventSink interface. - - Error _addEventError() { - if (isClosed) { - return new StateError("Cannot add new events after calling close"); - } - assert(_isAddingStream); - return new StateError("Cannot add new events while doing an addStream"); - } - - void add(T data) { - if (!_mayAddEvent) throw _addEventError(); - _sendData(data); - } - - void addError(Object error, [StackTrace stackTrace]) { - error = _nonNullError(error); - if (!_mayAddEvent) throw _addEventError(); - AsyncError replacement = Zone.current.errorCallback(error, stackTrace); - if (replacement != null) { - error = _nonNullError(replacement.error); - stackTrace = replacement.stackTrace; - } - _sendError(error, stackTrace); - } - - Future close() { - if (isClosed) { - assert(_doneFuture != null); - return _doneFuture; - } - if (!_mayAddEvent) throw _addEventError(); - _state |= _STATE_CLOSED; - Future doneFuture = _ensureDoneFuture(); - _sendDone(); - return doneFuture; - } - - Future get done => _ensureDoneFuture(); - - Future addStream(Stream stream, {bool cancelOnError: true}) { - if (!_mayAddEvent) throw _addEventError(); - _state |= _STATE_ADDSTREAM; - _addStreamState = new _AddStreamState(this, stream, cancelOnError); - return _addStreamState.addStreamFuture; - } - - // _EventSink interface, called from AddStreamState. - void _add(T data) { - _sendData(data); - } - - void _addError(Object error, StackTrace stackTrace) { - _sendError(error, stackTrace); - } - - void _close() { - assert(_isAddingStream); - _AddStreamState addState = _addStreamState; - _addStreamState = null; - _state &= ~_STATE_ADDSTREAM; - addState.complete(); - } - - // Event handling. - void _forEachListener( - void action(_BufferingStreamSubscription subscription)) { - if (_isFiring) { - throw new StateError( - "Cannot fire new event. Controller is already firing an event"); - } - if (_isEmpty) return; - - // Get event id of this event. - int id = (_state & _STATE_EVENT_ID); - // Start firing (set the _STATE_FIRING bit). We don't do [_onCancel] - // callbacks while firing, and we prevent reentrancy of this function. - // - // Set [_state]'s event id to the next event's id. - // Any listeners added while firing this event will expect the next event, - // not this one, and won't get notified. - _state ^= _STATE_EVENT_ID | _STATE_FIRING; - _BroadcastSubscriptionLink link = _next; - while (!identical(link, this)) { - _BroadcastSubscription subscription = link; - if (subscription._expectsEvent(id)) { - subscription._eventState |= _BroadcastSubscription._STATE_FIRING; - action(subscription); - subscription._toggleEventId(); - link = subscription._next; - if (subscription._removeAfterFiring) { - _removeListener(subscription); - } - subscription._eventState &= ~_BroadcastSubscription._STATE_FIRING; - } else { - link = subscription._next; - } - } - _state &= ~_STATE_FIRING; - - if (_isEmpty) { - _callOnCancel(); - } - } - - void _callOnCancel() { - assert(_isEmpty); - if (isClosed && _doneFuture._mayComplete) { - // When closed, _doneFuture is not null. - _doneFuture._asyncComplete(null); - } - _runGuarded(_onCancel); - } -} - -class _SyncBroadcastStreamController extends _BroadcastStreamController { - _SyncBroadcastStreamController(void onListen(), void onCancel()) - : super(onListen, onCancel); - - // EventDispatch interface. - - void _sendData(T data) { - if (_isEmpty) return; - if (_hasOneListener) { - _state |= _BroadcastStreamController._STATE_FIRING; - _BroadcastSubscription subscription = _next; - subscription._add(data); - _state &= ~_BroadcastStreamController._STATE_FIRING; - if (_isEmpty) { - _callOnCancel(); - } - return; - } - _forEachListener((_BufferingStreamSubscription subscription) { - subscription._add(data); - }); - } - - void _sendError(Object error, StackTrace stackTrace) { - if (_isEmpty) return; - _forEachListener((_BufferingStreamSubscription subscription) { - subscription._addError(error, stackTrace); - }); - } - - void _sendDone() { - if (!_isEmpty) { - _forEachListener((_BroadcastSubscription subscription) { - subscription._close(); - }); - } else { - assert(_doneFuture != null); - assert(_doneFuture._mayComplete); - _doneFuture._asyncComplete(null); - } - } -} - -class _AsyncBroadcastStreamController extends _BroadcastStreamController { - _AsyncBroadcastStreamController(void onListen(), void onCancel()) - : super(onListen, onCancel); - - // EventDispatch interface. - - void _sendData(T data) { - for (_BroadcastSubscriptionLink link = _next; - !identical(link, this); - link = link._next) { - _BroadcastSubscription subscription = link; - subscription._addPending(new _DelayedData(data)); - } - } - - void _sendError(Object error, StackTrace stackTrace) { - for (_BroadcastSubscriptionLink link = _next; - !identical(link, this); - link = link._next) { - _BroadcastSubscription subscription = link; - subscription._addPending(new _DelayedError(error, stackTrace)); - } - } - - void _sendDone() { - if (!_isEmpty) { - for (_BroadcastSubscriptionLink link = _next; - !identical(link, this); - link = link._next) { - _BroadcastSubscription subscription = link; - subscription._addPending(const _DelayedDone()); - } - } else { - assert(_doneFuture != null); - assert(_doneFuture._mayComplete); - _doneFuture._asyncComplete(null); - } - } -} - -/** - * Stream controller that is used by [Stream.asBroadcastStream]. - * - * This stream controller allows incoming events while it is firing - * other events. This is handled by delaying the events until the - * current event is done firing, and then fire the pending events. - * - * This class extends [_SyncBroadcastStreamController]. Events of - * an "asBroadcastStream" stream are always initiated by events - * on another stream, and it is fine to forward them synchronously. - */ -class _AsBroadcastStreamController - extends _SyncBroadcastStreamController - implements _EventDispatch { - _StreamImplEvents _pending; - - _AsBroadcastStreamController(void onListen(), void onCancel()) - : super(onListen, onCancel); - - bool get _hasPending => _pending != null && ! _pending.isEmpty; - - void _addPendingEvent(_DelayedEvent event) { - if (_pending == null) { - _pending = new _StreamImplEvents(); - } - _pending.add(event); - } - - void add(T data) { - if (!isClosed && _isFiring) { - _addPendingEvent(new _DelayedData(data)); - return; - } - super.add(data); - while (_hasPending) { - _pending.handleNext(this); - } - } - - void addError(Object error, [StackTrace stackTrace]) { - if (!isClosed && _isFiring) { - _addPendingEvent(new _DelayedError(error, stackTrace)); - return; - } - if (!_mayAddEvent) throw _addEventError(); - _sendError(error, stackTrace); - while (_hasPending) { - _pending.handleNext(this); - } - } - - Future close() { - if (!isClosed && _isFiring) { - _addPendingEvent(const _DelayedDone()); - _state |= _BroadcastStreamController._STATE_CLOSED; - return super.done; - } - Future result = super.close(); - assert(!_hasPending); - return result; - } - - void _callOnCancel() { - if (_hasPending) { - _pending.clear(); - _pending = null; - } - super._callOnCancel(); - } -} - -// A subscription that never receives any events. -// It can simulate pauses, but otherwise does nothing. -class _DoneSubscription implements StreamSubscription { - int _pauseCount = 0; - void onData(void handleData(T data)) {} - void onError(Function handleError) {} - void onDone(void handleDone()) {} - void pause([Future resumeSignal]) { - if (resumeSignal != null) resumeSignal.then(_resume); - _pauseCount++; - } - void resume() { _resume(null); } - void _resume(_) { - if (_pauseCount > 0) _pauseCount--; - } - Future cancel() { return new _Future.immediate(null); } - bool get isPaused => _pauseCount > 0; - Future asFuture([Object value]) => new _Future(); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/deferred_load.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/deferred_load.dart deleted file mode 100644 index 01b2c16e161e..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/deferred_load.dart +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.async; - -/** - * Indicates that loading of [libraryName] is deferred. - * - * This class is obsolete. Instead use the syntax: - * import "library.dart" deferred as prefix; - */ -@Deprecated("Dart sdk v. 1.8") -class DeferredLibrary { - final String libraryName; - final String uri; - - const DeferredLibrary(this.libraryName, {this.uri}); - - /** - * Ensure that [libraryName] has been loaded. - * - * If the library fails to load, the Future will complete with a - * DeferredLoadException. - */ - Future load() { - throw 'DeferredLibrary not supported. ' - 'please use the `import "lib.dart" deferred as lib` syntax.'; - } -} - -/** - * Thrown when a deferred library fails to load. - */ -class DeferredLoadException implements Exception { - DeferredLoadException(String this._s); - String toString() => "DeferredLoadException: '$_s'"; - final String _s; -} \ No newline at end of file diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/future.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/future.dart deleted file mode 100644 index 78ba2b88e658..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/future.dart +++ /dev/null @@ -1,729 +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. - -part of dart.async; - -/** - * An object representing a delayed computation. - * - * A [Future] is used to represent a potential value, or error, - * that will be available at some time in the future. - * Receivers of a [Future] can register callbacks - * that handle the value or error once it is available. - * For example: - * - * Future future = getFuture(); - * future.then((value) => handleValue(value)) - * .catchError((error) => handleError(error)); - * - * A [Future] can complete in two ways: - * with a value ("the future succeeds") - * or with an error ("the future fails"). - * Users can install callbacks for each case. - * The result of registering a pair of callbacks is a new Future (the - * "successor") which in turn is completed with the result of invoking the - * corresponding callback. - * The successor is completed with an error if the invoked callback throws. - * For example: - * - * Future successor = future.then((int value) { - * // Invoked when the future is completed with a value. - * return 42; // The successor is completed with the value 42. - * }, - * onError: (e) { - * // Invoked when the future is completed with an error. - * if (canHandle(e)) { - * return 499; // The successor is completed with the value 499. - * } else { - * throw e; // The successor is completed with the error e. - * } - * }); - * - * If a future does not have a successor when it completes with an error, - * it forwards the error message to the global error-handler. - * This behavior makes sure that no error is silently dropped. - * However, it also means that error handlers should be installed early, - * so that they are present as soon as a future is completed with an error. - * The following example demonstrates this potential bug: - * - * var future = getFuture(); - * new Timer(new Duration(milliseconds: 5), () { - * // The error-handler is not attached until 5 ms after the future has - * // been received. If the future fails before that, the error is - * // forwarded to the global error-handler, even though there is code - * // (just below) to eventually handle the error. - * future.then((value) { useValue(value); }, - * onError: (e) { handleError(e); }); - * }); - * - * When registering callbacks, it's often more readable to register the two - * callbacks separately, by first using [then] with one argument - * (the value handler) and using a second [catchError] for handling errors. - * Each of these will forward the result that they don't handle - * to their successors, and together they handle both value and error result. - * It also has the additional benefit of the [catchError] handling errors in the - * [then] value callback too. - * Using sequential handlers instead of parallel ones often leads to code that - * is easier to reason about. - * It also makes asynchronous code very similar to synchronous code: - * - * // Synchronous code. - * try { - * int value = foo(); - * return bar(value); - * } catch (e) { - * return 499; - * } - * - * Equivalent asynchronous code, based on futures: - * - * Future future = new Future(foo); // Result of foo() as a future. - * future.then((int value) => bar(value)) - * .catchError((e) => 499); - * - * Similar to the synchronous code, the error handler (registered with - * [catchError]) is handling any errors thrown by either `foo` or `bar`. - * If the error-handler had been registered as the `onError` parameter of - * the `then` call, it would not catch errors from the `bar` call. - * - * Futures can have more than one callback-pair registered. Each successor is - * treated independently and is handled as if it was the only successor. - * - * A future may also fail to ever complete. In that case, no callbacks are - * called. - */ -abstract class Future { - // The `_nullFuture` is a completed Future with the value `null`. - static final _Future _nullFuture = new _Future.immediate(null); - - /** - * Creates a future containing the result of calling [computation] - * asynchronously with [Timer.run]. - * - * If the result of executing [computation] throws, the returned future is - * completed with the error. - * - * If the returned value is itself a [Future], completion of - * the created future will wait until the returned future completes, - * and will then complete with the same result. - * - * If a non-future value is returned, the returned future is completed - * with that value. - */ - factory Future(computation()) { - _Future result = new _Future(); - Timer.run(() { - try { - result._complete(computation()); - } catch (e, s) { - _completeWithErrorCallback(result, e, s); - } - }); - return result; - } - - /** - * Creates a future containing the result of calling [computation] - * asynchronously with [scheduleMicrotask]. - * - * If executing [computation] throws, - * the returned future is completed with the thrown error. - * - * If calling [computation] returns a [Future], completion of - * the created future will wait until the returned future completes, - * and will then complete with the same result. - * - * If calling [computation] returns a non-future value, - * the returned future is completed with that value. - */ - factory Future.microtask(computation()) { - _Future result = new _Future(); - scheduleMicrotask(() { - try { - result._complete(computation()); - } catch (e, s) { - _completeWithErrorCallback(result, e, s); - } - }); - return result; - } - - /** - * Creates a future containing the result of immediately calling - * [computation]. - * - * If calling [computation] throws, the returned future is completed with the - * error. - * - * If calling [computation] returns a [Future], completion of - * the created future will wait until the returned future completes, - * and will then complete with the same result. - * - * If calling [computation] returns a non-future value, - * the returned future is completed with that value. - */ - factory Future.sync(computation()) { - try { - var result = computation(); - return new Future.value(result); - } catch (error, stackTrace) { - return new Future.error(error, stackTrace); - } - } - - /** - * A future whose value is available in the next event-loop iteration. - * - * If [value] is not a [Future], using this constructor is equivalent - * to [:new Future.sync(() => value):]. - * - * Use [Completer] to create a Future and complete it later. - */ - factory Future.value([value]) { - return new _Future.immediate(value); - } - - /** - * A future that completes with an error in the next event-loop iteration. - * - * If [error] is `null`, it is replaced by a [NullThrownError]. - * - * Use [Completer] to create a future and complete it later. - */ - factory Future.error(Object error, [StackTrace stackTrace]) { - error = _nonNullError(error); - if (!identical(Zone.current, _ROOT_ZONE)) { - AsyncError replacement = Zone.current.errorCallback(error, stackTrace); - if (replacement != null) { - error = _nonNullError(replacement.error); - stackTrace = replacement.stackTrace; - } - } - return new _Future.immediateError(error, stackTrace); - } - - /** - * Creates a future that runs its computation after a delay. - * - * The [computation] will be executed after the given [duration] has passed, - * and the future is completed with the result. - * If the duration is 0 or less, - * it completes no sooner than in the next event-loop iteration. - * - * If [computation] is omitted, - * it will be treated as if [computation] was set to `() => null`, - * and the future will eventually complete with the `null` value. - * - * If calling [computation] throws, the created future will complete with the - * error. - * - * See also [Completer] for a way to create and complete a future at a - * later time that isn't necessarily after a known fixed duration. - */ - factory Future.delayed(Duration duration, [T computation()]) { - _Future result = new _Future(); - new Timer(duration, () { - try { - result._complete(computation == null ? null : computation()); - } catch (e, s) { - _completeWithErrorCallback(result, e, s); - } - }); - return result; - } - - /** - * Wait for all the given futures to complete and collect their values. - * - * Returns a future which will complete once all the futures in a list are - * complete. If any of the futures in the list completes with an error, - * the resulting future also completes with an error. Otherwise the value - * of the returned future will be a list of all the values that were - * produced. - * - * If `eagerError` is true, the future completes with an error immediately on - * the first error from one of the futures. Otherwise all futures must - * complete before the returned future is completed (still with the first - * error to occur, the remaining errors are silently dropped). - * - * If [cleanUp] is provided, in the case of an error, any non-null result of - * a successful future is passed to `cleanUp`, which can then release any - * resources that the successful operation allocated. - * - * The call to `cleanUp` should not throw. If it does, the error will be an - * uncaught asynchronous error. - */ - static Future wait(Iterable futures, - {bool eagerError: false, - void cleanUp(successValue)}) { - final _Future result = new _Future(); - List values; // Collects the values. Set to null on error. - int remaining = 0; // How many futures are we waiting for. - var error; // The first error from a future. - StackTrace stackTrace; // The stackTrace that came with the error. - - // Handle an error from any of the futures. - void handleError(theError, theStackTrace) { - remaining--; - if (values != null) { - if (cleanUp != null) { - for (var value in values) { - if (value != null) { - // Ensure errors from cleanUp are uncaught. - new Future.sync(() { cleanUp(value); }); - } - } - } - values = null; - if (remaining == 0 || eagerError) { - result._completeError(theError, theStackTrace); - } else { - error = theError; - stackTrace = theStackTrace; - } - } else if (remaining == 0 && !eagerError) { - result._completeError(error, stackTrace); - } - } - - // As each future completes, put its value into the corresponding - // position in the list of values. - for (Future future in futures) { - int pos = remaining++; - future.then((Object value) { - remaining--; - if (values != null) { - values[pos] = value; - if (remaining == 0) { - result._completeWithValue(values); - } - } else { - if (cleanUp != null && value != null) { - // Ensure errors from cleanUp are uncaught. - new Future.sync(() { cleanUp(value); }); - } - if (remaining == 0 && !eagerError) { - result._completeError(error, stackTrace); - } - } - }, onError: handleError); - } - if (remaining == 0) { - return new Future.value(const []); - } - values = new List(remaining); - return result; - } - - /** - * Perform an async operation for each element of the iterable, in turn. - * - * Runs [f] for each element in [input] in order, moving to the next element - * only when the [Future] returned by [f] completes. Returns a [Future] that - * completes when all elements have been processed. - * - * The return values of all [Future]s are discarded. Any errors will cause the - * iteration to stop and will be piped through the returned [Future]. - * - * If [f] returns a non-[Future], iteration continues immediately. Otherwise - * it waits for the returned [Future] to complete. - */ - static Future forEach(Iterable input, f(element)) { - Iterator iterator = input.iterator; - return doWhile(() { - if (!iterator.moveNext()) return false; - return new Future.sync(() => f(iterator.current)).then((_) => true); - }); - } - - /** - * Perform an async operation repeatedly until it returns `false`. - * - * Runs [f] repeatedly, starting the next iteration only when the [Future] - * returned by [f] completes to `true`. Returns a [Future] that completes once - * [f] returns `false`. - * - * The return values of all [Future]s are discarded. Any errors will cause the - * iteration to stop and will be piped through the returned [Future]. - * - * The function [f] may return either a [bool] or a [Future] that completes to - * a [bool]. If it returns a non-[Future], iteration continues immediately. - * Otherwise it waits for the returned [Future] to complete. - */ - static Future doWhile(f()) { - _Future doneSignal = new _Future(); - var nextIteration; - // Bind this callback explicitly so that each iteration isn't bound in the - // context of all the previous iterations' callbacks. - nextIteration = Zone.current.bindUnaryCallback((bool keepGoing) { - if (keepGoing) { - new Future.sync(f).then(nextIteration, - onError: doneSignal._completeError); - } else { - doneSignal._complete(null); - } - }, runGuarded: true); - nextIteration(true); - return doneSignal; - } - - /** - * Register callbacks to be called when this future completes. - * - * When this future completes with a value, - * the [onValue] callback will be called with that value. - * If this future is already completed, the callback will not be called - * immediately, but will be scheduled in a later microtask. - * - * If [onError] is provided, and this future completes with an error, - * the `onError` callback is called with that error and its stack trace. - * The `onError` callback must accept either one argument or two arguments. - * If `onError` accepts two arguments, - * it is called with both the error and the stack trace, - * otherwise it is called with just the error object. - * - * Returns a new [Future] - * which is completed with the result of the call to `onValue` - * (if this future completes with a value) - * or to `onError` (if this future completes with an error). - * - * If the invoked callback throws, - * the returned future is completed with the thrown error - * and a stack trace for the error. - * In the case of `onError`, - * if the exception thrown is `identical` to the error argument to `onError`, - * the throw is considered a rethrow, - * and the original stack trace is used instead. - * - * If the callback returns a [Future], - * the future returned by `then` will be completed with - * the same result as the future returned by the callback. - * - * If [onError] is not given, and this future completes with an error, - * the error is forwarded directly to the returned future. - * - * In most cases, it is more readable to use [catchError] separately, possibly - * with a `test` parameter, instead of handling both value and error in a - * single [then] call. - */ - Future then(onValue(T value), { Function onError }); - - /** - * Handles errors emitted by this [Future]. - * - * This is the asynchronous equivalent of a "catch" block. - * - * Returns a new [Future] that will be completed with either the result of - * this future or the result of calling the `onError` callback. - * - * If this future completes with a value, - * the returned future completes with the same value. - * - * If this future completes with an error, - * then [test] is first called with the error value. - * - * If `test` returns false, the exception is not handled by this `catchError`, - * and the returned future completes with the same error and stack trace - * as this future. - * - * If `test` returns `true`, - * [onError] is called with the error and possibly stack trace, - * and the returned future is completed with the result of this call - * in exactly the same way as for [then]'s `onError`. - * - * If `test` is omitted, it defaults to a function that always returns true. - * The `test` function should not throw, but if it does, it is handled as - * if the the `onError` function had thrown. - * - * Example: - * - * foo - * .catchError(..., test: (e) => e is ArgumentError) - * .catchError(..., test: (e) => e is NoSuchMethodError) - * .then((v) { ... }); - * - * This method is equivalent to: - * - * Future catchError(onError(error), - * {bool test(error)}) { - * this.then((v) => v, // Forward the value. - * // But handle errors, if the [test] succeeds. - * onError: (e, stackTrace) { - * if (test == null || test(e)) { - * if (onError is ZoneBinaryCallback) { - * return onError(e, stackTrace); - * } - * return onError(e); - * } - * throw e; - * }); - * } - * - */ - Future catchError(Function onError, - {bool test(Object error)}); - - /** - * Register a function to be called when this future completes. - * - * The [action] function is called when this future completes, whether it - * does so with a value or with an error. - * - * This is the asynchronous equivalent of a "finally" block. - * - * The future returned by this call, `f`, will complete the same way - * as this future unless an error occurs in the [action] call, or in - * a [Future] returned by the [action] call. If the call to [action] - * does not return a future, its return value is ignored. - * - * If the call to [action] throws, then `f` is completed with the - * thrown error. - * - * If the call to [action] returns a [Future], `f2`, then completion of - * `f` is delayed until `f2` completes. If `f2` completes with - * an error, that will be the result of `f` too. The value of `f2` is always - * ignored. - * - * This method is equivalent to: - * - * Future whenComplete(action()) { - * return this.then((v) { - * var f2 = action(); - * if (f2 is Future) return f2.then((_) => v); - * return v - * }, onError: (e) { - * var f2 = action(); - * if (f2 is Future) return f2.then((_) { throw e; }); - * throw e; - * }); - * } - */ - Future whenComplete(action()); - - /** - * Creates a [Stream] containing the result of this future. - * - * The stream will produce single data or error event containing the - * completion result of this future, and then it will close with a - * done event. - * - * If the future never completes, the stream will not produce any events. - */ - Stream 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, {onTimeout()}); -} - -/** - * Thrown when a scheduled timeout happens while waiting for an async result. - */ -class TimeoutException implements Exception { - /** Description of the cause of the timeout. */ - final String message; - /** The duration that was exceeded. */ - final Duration duration; - - TimeoutException(this.message, [this.duration]); - - String toString() { - String result = "TimeoutException"; - if (duration != null) result = "TimeoutException after $duration"; - if (message != null) result = "$result: $message"; - return result; - } -} - -/** - * A way to produce Future objects and to complete them later - * with a value or error. - * - * Most of the time, the simplest way to create a future is to just use - * one of the [Future] constructors to capture the result of a single - * asynchronous computation: - * - * new Future(() { doSomething(); return result; }); - * - * or, if the future represents the result of a sequence of asynchronous - * computations, they can be chained using [Future.then] or similar functions - * on [Future]: - * - * Future doStuff(){ - * return someAsyncOperation().then((result) { - * return someOtherAsyncOperation(result); - * }); - * } - * - * If you do need to create a Future from scratch — for example, - * when you're converting a callback-based API into a Future-based - * one — you can use a Completer as follows: - * - * class AsyncOperation { - * Completer _completer = new Completer(); - * - * Future doOperation() { - * _startOperation(); - * return _completer.future; // Send future object back to client. - * } - * - * // Something calls this when the value is ready. - * void _finishOperation(T result) { - * _completer.complete(result); - * } - * - * // If something goes wrong, call this. - * void _errorHappened(error) { - * _completer.completeError(error); - * } - * } - */ -abstract class Completer { - - /** - * Creates a new completer. - * - * The general workflow for creating a new future is to 1) create a - * new completer, 2) hand out its future, and, at a later point, 3) invoke - * either [complete] or [completeError]. - * - * The completer completes the future asynchronously. That means that - * callbacks registered on the future, are not called immediately when - * [complete] or [completeError] is called. Instead the callbacks are - * delayed until a later microtask. - * - * Example: - * - * var completer = new Completer(); - * handOut(completer.future); - * later: { - * completer.complete('completion value'); - * } - */ - factory Completer() => new _AsyncCompleter(); - - /** - * Completes the future synchronously. - * - * This constructor should be avoided unless the completion of the future is - * known to be the final result of another asynchronous operation. If in doubt - * use the default [Completer] constructor. - * - * Using an normal, asynchronous, completer will never give the wrong - * behavior, but using a synchronous completer incorrectly can cause - * otherwise correct programs to break. - * - * An asynchronous completer is only intended for optimizing event - * propagation when one asynchronous event immediately triggers another. - * It should not be used unless the calls to [complete] and [completeError] - * are guaranteed to occur in places where it won't break `Future` invariants. - * - * Completing synchronously means that the completer's future will be - * completed immediately when calling the [complete] or [completeError] - * method on a synchronous completer, which also calls any callbacks - * registered on that future. - * - * Completing synchronously must not break the rule that when you add a - * callback on a future, that callback must not be called until the code - * that added the callback has completed. - * For that reason, a synchronous completion must only occur at the very end - * (in "tail position") of another synchronous event, - * because at that point, completing the future immediately is be equivalent - * to returning to the event loop and completing the future in the next - * microtask. - * - * Example: - * - * var completer = new Completer.sync(); - * // The completion is the result of the asynchronous onDone event. - * // No other operation is performed after the completion. It is safe - * // to use the Completer.sync constructor. - * stream.listen(print, onDone: () { completer.complete("done"); }); - * - * Bad example. Do not use this code. Only for illustrative purposes: - * - * var completer = new Completer.sync(); - * completer.future.then((_) { bar(); }); - * // The completion is the result of the asynchronous onDone event. - * // However, there is still code executed after the completion. This - * // operation is *not* safe. - * stream.listen(print, onDone: () { - * completer.complete("done"); - * foo(); // In this case, foo() runs after bar(). - * }); - */ - factory Completer.sync() => new _SyncCompleter(); - - /** The future that will contain the result provided to this completer. */ - Future get future; - - /** - * Completes [future] with the supplied values. - * - * The value must be either a value of type [T] - * or a future of type `Future`. - * - * If the value is itself a future, the completer will wait for that future - * to complete, and complete with the same result, whether it is a success - * or an error. - * - * Calling `complete` or [completeError] must not be done more than once. - * - * All listeners on the future are informed about the value. - */ - void complete([value]); - - /** - * Complete [future] with an error. - * - * Calling [complete] or `completeError` must not be done more than once. - * - * Completing a future with an error indicates that an exception was thrown - * while trying to produce a value. - * - * If [error] is `null`, it is replaced by a [NullThrownError]. - * - * If `error` is a `Future`, the future itself is used as the error value. - * If you want to complete with the result of the future, you can use: - * - * thisCompleter.complete(theFuture) - * - * or if you only want to handle an error from the future: - * - * theFuture.catchError(thisCompleter.completeError); - * - */ - void completeError(Object error, [StackTrace stackTrace]); - - /** - * Whether the future has been completed. - */ - bool get isCompleted; -} - -// Helper function completing a _Future with error, but checking the zone -// for error replacement first. -void _completeWithErrorCallback(_Future result, error, stackTrace) { - AsyncError replacement = Zone.current.errorCallback(error, stackTrace); - if (replacement != null) { - error = _nonNullError(replacement.error); - stackTrace = replacement.stackTrace; - } - result._completeError(error, stackTrace); -} - -/** Helper function that converts `null` to a [NullThrownError]. */ -Object _nonNullError(Object error) => - (error != null) ? error : new NullThrownError(); diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/future_impl.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/future_impl.dart deleted file mode 100644 index a0cfeb16efe9..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/future_impl.dart +++ /dev/null @@ -1,651 +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. - -part of dart.async; - -/** The onValue and onError handlers return either a value or a future */ -typedef dynamic _FutureOnValue(T value); -/** Test used by [Future.catchError] to handle skip some errors. */ -typedef bool _FutureErrorTest(var error); -/** Used by [WhenFuture]. */ -typedef _FutureAction(); - -abstract class _Completer implements Completer { - final _Future future = new _Future(); - - void complete([value]); - - void completeError(Object error, [StackTrace stackTrace]) { - error = _nonNullError(error); - if (!future._mayComplete) throw new StateError("Future already completed"); - AsyncError replacement = Zone.current.errorCallback(error, stackTrace); - if (replacement != null) { - error = _nonNullError(replacement.error); - stackTrace = replacement.stackTrace; - } - _completeError(error, stackTrace); - } - - void _completeError(Object error, StackTrace stackTrace); - - // The future's _isComplete doesn't take into account pending completions. - // We therefore use _mayComplete. - bool get isCompleted => !future._mayComplete; -} - -class _AsyncCompleter extends _Completer { - - void complete([value]) { - if (!future._mayComplete) throw new StateError("Future already completed"); - future._asyncComplete(value); - } - - void _completeError(Object error, StackTrace stackTrace) { - future._asyncCompleteError(error, stackTrace); - } -} - -class _SyncCompleter extends _Completer { - void complete([value]) { - if (!future._mayComplete) throw new StateError("Future already completed"); - future._complete(value); - } - - void _completeError(Object error, StackTrace stackTrace) { - future._completeError(error, stackTrace); - } -} - -class _FutureListener { - static const int MASK_VALUE = 1; - static const int MASK_ERROR = 2; - static const int MASK_TEST_ERROR = 4; - static const int MASK_WHENCOMPLETE = 8; - static const int STATE_CHAIN = 0; - static const int STATE_THEN = MASK_VALUE; - static const int STATE_THEN_ONERROR = MASK_VALUE | MASK_ERROR; - static const int STATE_CATCHERROR = MASK_ERROR; - static const int STATE_CATCHERROR_TEST = MASK_ERROR | MASK_TEST_ERROR; - static const int STATE_WHENCOMPLETE = MASK_WHENCOMPLETE; - // Listeners on the same future are linked through this link. - _FutureListener _nextListener = null; - // The future to complete when this listener is activated. - final _Future result; - // Which fields means what. - final int state; - // Used for then/whenDone callback and error test - final Function callback; - // Used for error callbacks. - final Function errorCallback; - - _FutureListener.then(this.result, - _FutureOnValue onValue, Function errorCallback) - : callback = onValue, - errorCallback = errorCallback, - state = (errorCallback == null) ? STATE_THEN : STATE_THEN_ONERROR; - - _FutureListener.catchError(this.result, - this.errorCallback, _FutureErrorTest test) - : callback = test, - state = (test == null) ? STATE_CATCHERROR : STATE_CATCHERROR_TEST; - - _FutureListener.whenComplete(this.result, _FutureAction onComplete) - : callback = onComplete, - errorCallback = null, - state = STATE_WHENCOMPLETE; - - _FutureListener.chain(this.result) - : callback = null, - errorCallback = null, - state = STATE_CHAIN; - - Zone get _zone => result._zone; - - bool get handlesValue => (state & MASK_VALUE != 0); - bool get handlesError => (state & MASK_ERROR != 0); - bool get hasErrorTest => (state == STATE_CATCHERROR_TEST); - bool get handlesComplete => (state == STATE_WHENCOMPLETE); - - _FutureOnValue get _onValue { - assert(handlesValue); - return callback; - } - Function get _onError => errorCallback; - _FutureErrorTest get _errorTest { - assert(hasErrorTest); - return callback; - } - _FutureAction get _whenCompleteAction { - assert(handlesComplete); - return callback; - } -} - -class _Future implements Future { - /// Initial state, waiting for a result. In this state, the - /// [resultOrListeners] field holds a single-linked list of - /// [_FutureListener] listeners. - static const int _INCOMPLETE = 0; - /// Pending completion. Set when completed using [_asyncComplete] or - /// [_asyncCompleteError]. It is an error to try to complete it again. - /// [resultOrListeners] holds listeners. - static const int _PENDING_COMPLETE = 1; - /// The future has been chained to another future. The result of that - /// other future becomes the result of this future as well. - // TODO(floitsch): we don't really need a special "_CHAINED" state. We could - // just use the PENDING_COMPLETE state instead. - static const int _CHAINED = 2; - /// The future has been completed with a value result. - static const int _VALUE = 4; - /// The future has been completed with an error result. - static const int _ERROR = 8; - - /** Whether the future is complete, and as what. */ - int _state = _INCOMPLETE; - - /** - * Zone that the future was completed from. - * This is the zone that an error result belongs to. - * - * Until the future is completed, the field may hold the zone that - * listener callbacks used to create this future should be run in. - */ - final Zone _zone = Zone.current; - - /** - * Either the result, a list of listeners or another future. - * - * The result of the future is either a value or an error. - * A result is only stored when the future has completed. - * - * The listeners is an internally linked list of [_FutureListener]s. - * Listeners are only remembered while the future is not yet complete, - * and it is not chained to another future. - * - * The future is another future that his future is chained to. This future - * is waiting for the other future to complete, and when it does, this future - * will complete with the same result. - * All listeners are forwarded to the other future. - * - * The cases are disjoint - incomplete and unchained ([_INCOMPLETE]), - * incomplete and chained ([_CHAINED]), or completed with value or error - * ([_VALUE] or [_ERROR]) - so the field only needs to hold - * one value at a time. - */ - var _resultOrListeners; - - _Future(); - - /// Valid types for value: `T` or `Future`. - _Future.immediate(value) { - _asyncComplete(value); - } - - _Future.immediateError(var error, [StackTrace stackTrace]) { - _asyncCompleteError(error, stackTrace); - } - - bool get _mayComplete => _state == _INCOMPLETE; - bool get _isChained => _state == _CHAINED; - bool get _isComplete => _state >= _VALUE; - bool get _hasValue => _state == _VALUE; - bool get _hasError => _state == _ERROR; - - set _isChained(bool value) { - if (value) { - assert(!_isComplete); - _state = _CHAINED; - } else { - assert(_isChained); - _state = _INCOMPLETE; - } - } - - Future then(f(T value), { Function onError }) { - _Future result = new _Future(); - if (!identical(result._zone, _ROOT_ZONE)) { - f = result._zone.registerUnaryCallback(f); - if (onError != null) { - onError = _registerErrorHandler(onError, result._zone); - } - } - _addListener(new _FutureListener.then(result, f, onError)); - return result; - } - - Future catchError(Function onError, { bool test(error) }) { - _Future result = new _Future(); - if (!identical(result._zone, _ROOT_ZONE)) { - onError = _registerErrorHandler(onError, result._zone); - if (test != null) test = result._zone.registerUnaryCallback(test); - } - _addListener(new _FutureListener.catchError(result, onError, test)); - return result; - } - - Future whenComplete(action()) { - _Future result = new _Future(); - if (!identical(result._zone, _ROOT_ZONE)) { - action = result._zone.registerCallback(action); - } - _addListener(new _FutureListener.whenComplete(result, action)); - return result; - } - - Stream asStream() => new Stream.fromFuture(this); - - void _markPendingCompletion() { - if (!_mayComplete) throw new StateError("Future already completed"); - _state = _PENDING_COMPLETE; - } - - T get _value { - assert(_isComplete && _hasValue); - return _resultOrListeners; - } - - AsyncError get _error { - assert(_isComplete && _hasError); - return _resultOrListeners; - } - - void _setValue(T value) { - assert(!_isComplete); // But may have a completion pending. - _state = _VALUE; - _resultOrListeners = value; - } - - void _setErrorObject(AsyncError error) { - assert(!_isComplete); // But may have a completion pending. - _state = _ERROR; - _resultOrListeners = error; - } - - void _setError(Object error, StackTrace stackTrace) { - _setErrorObject(new AsyncError(error, stackTrace)); - } - - void _addListener(_FutureListener listener) { - assert(listener._nextListener == null); - if (_isComplete) { - // Handle late listeners asynchronously. - _zone.scheduleMicrotask(() { - _propagateToListeners(this, listener); - }); - } else { - listener._nextListener = _resultOrListeners; - _resultOrListeners = listener; - } - } - - _FutureListener _removeListeners() { - // Reverse listeners before returning them, so the resulting list is in - // subscription order. - assert(!_isComplete); - _FutureListener current = _resultOrListeners; - _resultOrListeners = null; - _FutureListener prev = null; - while (current != null) { - _FutureListener next = current._nextListener; - current._nextListener = prev; - prev = current; - current = next; - } - return prev; - } - - // Take the value (when completed) of source and complete target with that - // value (or error). This function can chain all Futures, but is slower - // for _Future than _chainCoreFuture - Use _chainCoreFuture in that case. - static void _chainForeignFuture(Future source, _Future target) { - assert(!target._isComplete); - assert(source is! _Future); - - // Mark the target as chained (and as such half-completed). - target._isChained = true; - source.then((value) { - assert(target._isChained); - target._completeWithValue(value); - }, - // TODO(floitsch): eventually we would like to make this non-optional - // and dependent on the listeners of the target future. If none of - // the target future's listeners want to have the stack trace we don't - // need a trace. - onError: (error, [stackTrace]) { - assert(target._isChained); - target._completeError(error, stackTrace); - }); - } - - // Take the value (when completed) of source and complete target with that - // value (or error). This function expects that source is a _Future. - static void _chainCoreFuture(_Future source, _Future target) { - assert(!target._isComplete); - assert(source is _Future); - - // Mark the target as chained (and as such half-completed). - target._isChained = true; - _FutureListener listener = new _FutureListener.chain(target); - if (source._isComplete) { - _propagateToListeners(source, listener); - } else { - source._addListener(listener); - } - } - - void _complete(value) { - assert(!_isComplete); - if (value is Future) { - if (value is _Future) { - _chainCoreFuture(value, this); - } else { - _chainForeignFuture(value, this); - } - } else { - _FutureListener listeners = _removeListeners(); - _setValue(value); - _propagateToListeners(this, listeners); - } - } - - void _completeWithValue(value) { - assert(!_isComplete); - assert(value is! Future); - - _FutureListener listeners = _removeListeners(); - _setValue(value); - _propagateToListeners(this, listeners); - } - - void _completeError(error, [StackTrace stackTrace]) { - assert(!_isComplete); - - _FutureListener listeners = _removeListeners(); - _setError(error, stackTrace); - _propagateToListeners(this, listeners); - } - - void _asyncComplete(value) { - assert(!_isComplete); - // Two corner cases if the value is a future: - // 1. the future is already completed and an error. - // 2. the future is not yet completed but might become an error. - // The first case means that we must not immediately complete the Future, - // as our code would immediately start propagating the error without - // giving the time to install error-handlers. - // However the second case requires us to deal with the value immediately. - // Otherwise the value could complete with an error and report an - // unhandled error, even though we know we are already going to listen to - // it. - - if (value == null) { - // No checks for `null`. - } else if (value is Future) { - // Assign to typed variables so we get earlier checks in checked mode. - Future typedFuture = value; - if (typedFuture is _Future) { - _Future coreFuture = typedFuture; - if (coreFuture._isComplete && coreFuture._hasError) { - // Case 1 from above. Delay completion to enable the user to register - // callbacks. - _markPendingCompletion(); - _zone.scheduleMicrotask(() { - _chainCoreFuture(coreFuture, this); - }); - } else { - _chainCoreFuture(coreFuture, this); - } - } else { - // Case 2 from above. Chain the future immidiately. - // Note that we are still completing asynchronously (through - // _chainForeignFuture).. - _chainForeignFuture(typedFuture, this); - } - return; - } else { - T typedValue = value; - } - - _markPendingCompletion(); - _zone.scheduleMicrotask(() { - _completeWithValue(value); - }); - } - - void _asyncCompleteError(error, StackTrace stackTrace) { - assert(!_isComplete); - - _markPendingCompletion(); - _zone.scheduleMicrotask(() { - _completeError(error, stackTrace); - }); - } - - /** - * Propagates the value/error of [source] to its [listeners], executing the - * listeners' callbacks. - */ - static void _propagateToListeners(_Future source, _FutureListener listeners) { - while (true) { - assert(source._isComplete); - bool hasError = source._hasError; - if (listeners == null) { - if (hasError) { - AsyncError asyncError = source._error; - source._zone.handleUncaughtError( - asyncError.error, asyncError.stackTrace); - } - return; - } - // Usually futures only have one listener. If they have several, we - // call handle them separately in recursive calls, continuing - // here only when there is only one listener left. - while (listeners._nextListener != null) { - _FutureListener listener = listeners; - listeners = listener._nextListener; - listener._nextListener = null; - _propagateToListeners(source, listener); - } - _FutureListener listener = listeners; - // Do the actual propagation. - // Set initial state of listenerHasValue and listenerValueOrError. These - // variables are updated, with the outcome of potential callbacks. - bool listenerHasValue = true; - final sourceValue = hasError ? null : source._value; - var listenerValueOrError = sourceValue; - // Set to true if a whenComplete needs to wait for a future. - // The whenComplete action will resume the propagation by itself. - bool isPropagationAborted = false; - // TODO(floitsch): mark the listener as pending completion. Currently - // we can't do this, since the markPendingCompletion verifies that - // the future is not already marked (or chained). - // Only if we either have an error or callbacks, go into this, somewhat - // expensive, branch. Here we'll enter/leave the zone. Many futures - // doesn't have callbacks, so this is a significant optimization. - if (hasError || (listener.handlesValue || listener.handlesComplete)) { - Zone zone = listener._zone; - if (hasError && !source._zone.inSameErrorZone(zone)) { - // Don't cross zone boundaries with errors. - AsyncError asyncError = source._error; - source._zone.handleUncaughtError( - asyncError.error, asyncError.stackTrace); - return; - } - - Zone oldZone; - if (!identical(Zone.current, zone)) { - // Change zone if it's not current. - oldZone = Zone._enter(zone); - } - - bool handleValueCallback() { - try { - listenerValueOrError = zone.runUnary(listener._onValue, - sourceValue); - return true; - } catch (e, s) { - listenerValueOrError = new AsyncError(e, s); - return false; - } - } - - void handleError() { - AsyncError asyncError = source._error; - bool matchesTest = true; - if (listener.hasErrorTest) { - _FutureErrorTest test = listener._errorTest; - try { - matchesTest = zone.runUnary(test, asyncError.error); - } catch (e, s) { - listenerValueOrError = identical(asyncError.error, e) ? - asyncError : new AsyncError(e, s); - listenerHasValue = false; - return; - } - } - Function errorCallback = listener._onError; - if (matchesTest && errorCallback != null) { - try { - if (errorCallback is ZoneBinaryCallback) { - listenerValueOrError = zone.runBinary(errorCallback, - asyncError.error, - asyncError.stackTrace); - } else { - listenerValueOrError = zone.runUnary(errorCallback, - asyncError.error); - } - } catch (e, s) { - listenerValueOrError = identical(asyncError.error, e) ? - asyncError : new AsyncError(e, s); - listenerHasValue = false; - return; - } - listenerHasValue = true; - } else { - // Copy over the error from the source. - listenerValueOrError = asyncError; - listenerHasValue = false; - } - } - - void handleWhenCompleteCallback() { - var completeResult; - try { - completeResult = zone.run(listener._whenCompleteAction); - } catch (e, s) { - if (hasError && identical(source._error.error, e)) { - listenerValueOrError = source._error; - } else { - listenerValueOrError = new AsyncError(e, s); - } - listenerHasValue = false; - return; - } - if (completeResult is Future) { - _Future result = listener.result; - result._isChained = true; - isPropagationAborted = true; - completeResult.then((ignored) { - _propagateToListeners(source, new _FutureListener.chain(result)); - }, onError: (error, [stackTrace]) { - // When there is an error, we have to make the error the new - // result of the current listener. - if (completeResult is! _Future) { - // This should be a rare case. - completeResult = new _Future(); - completeResult._setError(error, stackTrace); - } - _propagateToListeners(completeResult, - new _FutureListener.chain(result)); - }); - } - } - - if (!hasError) { - if (listener.handlesValue) { - listenerHasValue = handleValueCallback(); - } - } else { - handleError(); - } - if (listener.handlesComplete) { - handleWhenCompleteCallback(); - } - // If we changed zone, oldZone will not be null. - if (oldZone != null) Zone._leave(oldZone); - - if (isPropagationAborted) return; - // If the listener's value is a future we need to chain it. Note that - // this can only happen if there is a callback. Since 'is' checks - // can be expensive, we're trying to avoid it. - if (listenerHasValue && - !identical(sourceValue, listenerValueOrError) && - listenerValueOrError is Future) { - Future chainSource = listenerValueOrError; - // Shortcut if the chain-source is already completed. Just continue - // the loop. - _Future result = listener.result; - if (chainSource is _Future) { - if (chainSource._isComplete) { - // propagate the value (simulating a tail call). - result._isChained = true; - source = chainSource; - listeners = new _FutureListener.chain(result); - continue; - } else { - _chainCoreFuture(chainSource, result); - } - } else { - _chainForeignFuture(chainSource, result); - } - return; - } - } - _Future result = listener.result; - listeners = result._removeListeners(); - if (listenerHasValue) { - result._setValue(listenerValueOrError); - } else { - AsyncError asyncError = listenerValueOrError; - result._setErrorObject(asyncError); - } - // Prepare for next round. - source = result; - } - } - - Future timeout(Duration timeLimit, {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("Future not completed", - 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._completeWithValue(v); - } - }, onError: (e, s) { - if (timer.isActive) { - timer.cancel(); - result._completeError(e, s); - } - }); - return result; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/schedule_microtask.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/schedule_microtask.dart deleted file mode 100644 index 361831be7969..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/schedule_microtask.dart +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.async; - -typedef void _AsyncCallback(); - -class _AsyncCallbackEntry { - final _AsyncCallback callback; - _AsyncCallbackEntry next; - _AsyncCallbackEntry(this.callback); -} - -/** Head of single linked list of pending callbacks. */ -_AsyncCallbackEntry _nextCallback; -/** Tail of single linked list of pending callbacks. */ -_AsyncCallbackEntry _lastCallback; -/** - * Tail of priority callbacks added by the currently executing callback. - * - * Priority callbacks are put at the beginning of the - * callback queue, so that if one callback schedules more than one - * priority callback, they are still enqueued in scheduling order. - */ -_AsyncCallbackEntry _lastPriorityCallback; -/** - * Whether we are currently inside the callback loop. - * - * If we are inside the loop, we never need to schedule the loop, - * even if adding a first element. - */ -bool _isInCallbackLoop = false; - -void _asyncRunCallbackLoop() { - while (_nextCallback != null) { - _lastPriorityCallback = null; - _AsyncCallbackEntry entry = _nextCallback; - _nextCallback = entry.next; - if (_nextCallback == null) _lastCallback = null; - entry.callback(); - } -} - -void _asyncRunCallback() { - _isInCallbackLoop = true; - try { - _asyncRunCallbackLoop(); - } finally { - _lastPriorityCallback = null; - _isInCallbackLoop = false; - if (_nextCallback != null) _AsyncRun._scheduleImmediate(_asyncRunCallback); - } -} - -/** - * Schedules a callback to be called as a microtask. - * - * The microtask is called after all other currently scheduled - * microtasks, but as part of the current system event. - */ -void _scheduleAsyncCallback(callback) { - // Optimizing a group of Timer.run callbacks to be executed in the - // same Timer callback. - if (_nextCallback == null) { - _nextCallback = _lastCallback = new _AsyncCallbackEntry(callback); - if (!_isInCallbackLoop) { - _AsyncRun._scheduleImmediate(_asyncRunCallback); - } - } else { - _AsyncCallbackEntry newEntry = new _AsyncCallbackEntry(callback); - _lastCallback.next = newEntry; - _lastCallback = newEntry; - } -} - -/** - * Schedules a callback to be called before all other currently scheduled ones. - * - * This callback takes priority over existing scheduled callbacks. - * It is only used internally to give higher priority to error reporting. - */ -void _schedulePriorityAsyncCallback(callback) { - _AsyncCallbackEntry entry = new _AsyncCallbackEntry(callback); - if (_nextCallback == null) { - _scheduleAsyncCallback(callback); - _lastPriorityCallback = _lastCallback; - } else if (_lastPriorityCallback == null) { - entry.next = _nextCallback; - _nextCallback = _lastPriorityCallback = entry; - } else { - entry.next = _lastPriorityCallback.next; - _lastPriorityCallback.next = entry; - _lastPriorityCallback = entry; - if (entry.next == null) { - _lastCallback = entry; - } - } -} - -/** - * Runs a function asynchronously. - * - * Callbacks registered through this function are always executed in order and - * are guaranteed to run before other asynchronous events (like [Timer] events, - * or DOM events). - * - * **Warning:** it is possible to starve the DOM by registering asynchronous - * callbacks through this method. For example the following program runs - * the callbacks without ever giving the Timer callback a chance to execute: - * - * main() { - * Timer.run(() { print("executed"); }); // Will never be executed. - * foo() { - * scheduleMicrotask(foo); // Schedules [foo] in front of other events. - * } - * foo(); - * } - * - * ## Other resources - * - * * [The Event Loop and Dart](https://www.dartlang.org/articles/event-loop/): - * Learn how Dart handles the event queue and microtask queue, so you can write - * better asynchronous code with fewer surprises. - */ -void scheduleMicrotask(void callback()) { - if (identical(_ROOT_ZONE, Zone.current)) { - // No need to bind the callback. We know that the root's scheduleMicrotask - // will be invoked in the root zone. - _rootScheduleMicrotask(null, null, _ROOT_ZONE, callback); - return; - } - Zone.current.scheduleMicrotask( - Zone.current.bindCallback(callback, runGuarded: true)); -} - -class _AsyncRun { - /** Schedule the given callback before any other event in the event-loop. */ - static void _scheduleImmediate(void callback()) { - scheduleImmediateClosure(callback); - } - - static final Function scheduleImmediateClosure = - _initializeScheduleImmediate(); - - static Function _initializeScheduleImmediate() { - requiresPreamble(); - if (JS('', 'self.scheduleImmediate') != null) { - return _scheduleImmediateJsOverride; - } - if (JS('', 'self.MutationObserver') != null && - JS('', 'self.document') != null) { - // Use mutationObservers. - var div = JS('', 'self.document.createElement("div")'); - var span = JS('', 'self.document.createElement("span")'); - var storedCallback; - - internalCallback(_) { - leaveJsAsync(); - var f = storedCallback; - storedCallback = null; - f(); - }; - - var observer = JS('', 'new self.MutationObserver(#)', - convertDartClosureToJS(internalCallback, 1)); - JS('', '#.observe(#, { childList: true })', - observer, div); - - return (void callback()) { - assert(storedCallback == null); - enterJsAsync(); - storedCallback = callback; - // Because of a broken shadow-dom polyfill we have to change the - // children instead a cheap property. - // See https://github.com/Polymer/ShadowDOM/issues/468 - JS('', '#.firstChild ? #.removeChild(#): #.appendChild(#)', - div, div, span, div, span); - }; - } else if (JS('', 'self.setImmediate') != null) { - return _scheduleImmediateWithSetImmediate; - } - // TODO(20055): We should use DOM promises when available. - return _scheduleImmediateWithTimer; - } - - static void _scheduleImmediateJsOverride(void callback()) { - internalCallback() { - leaveJsAsync(); - callback(); - }; - enterJsAsync(); - JS('void', 'self.scheduleImmediate(#)', - convertDartClosureToJS(internalCallback, 0)); - } - - static void _scheduleImmediateWithSetImmediate(void callback()) { - internalCallback() { - leaveJsAsync(); - callback(); - }; - enterJsAsync(); - JS('void', 'self.setImmediate(#)', - convertDartClosureToJS(internalCallback, 0)); - } - - static void _scheduleImmediateWithTimer(void callback()) { - Timer._createTimer(Duration.ZERO, callback); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/stream.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/stream.dart deleted file mode 100644 index 6d1fc63b37c4..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/stream.dart +++ /dev/null @@ -1,1669 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.async; - -// ------------------------------------------------------------------- -// Core Stream types -// ------------------------------------------------------------------- - -/** - * A source of asynchronous data events. - * - * A Stream provides a way to receive a sequence of events. - * Each event is either a data event or an error event, - * representing the result of a single computation. - * When the events provided by a Stream have all been sent, - * a single "done" event will mark the end. - * - * You can [listen] on a stream to make it start generating events, - * and to set up listeners that receive the events. - * When you listen, you receive a [StreamSubscription] object - * which is the active object providing the events, - * and which can be used to stop listening again, - * or to temporarily pause events from the subscription. - * - * There are two kinds of streams: "Single-subscription" streams and - * "broadcast" streams. - * - * *A single-subscription stream* allows only a single listener during the whole - * lifetime of the stream. - * It doesn't start generating events until it has a listener, - * and it stops sending events when the listener is unsubscribed, - * even if the source of events could still provide more. - * - * Listening twice on a single-subscription stream is not allowed, even after - * the first subscription has been canceled. - * - * Single-subscription streams are generally used for streaming chunks of - * larger contiguous data like file I/O. - * - * *A broadcast stream* allows any number of listeners, and it fires - * its events when they are ready, whether there are listeners or not. - * - * Broadcast streams are used for independent events/observers. - * - * If several listeners want to listen to a single subscription stream, - * use [asBroadcastStream] to create a broadcast stream on top of the - * non-broadcast stream. - * - * On either kind of stream, stream transformationss, such as [where] and - * [skip], return the same type of stream as the one the method was called on, - * unless otherwise noted. - * - * When an event is fired, the listener(s) at that time will receive the event. - * If a listener is added to a broadcast stream while an event is being fired, - * that listener will not receive the event currently being fired. - * If a listener is canceled, it immediately stops receiving events. - * - * When the "done" event is fired, subscribers are unsubscribed before - * receiving the event. After the event has been sent, the stream has no - * subscribers. Adding new subscribers to a broadcast stream after this point - * is allowed, but they will just receive a new "done" event as soon - * as possible. - * - * Stream subscriptions always respect "pause" requests. If necessary they need - * to buffer their input, but often, and preferably, they can simply request - * their input to pause too. - * - * The default implementation of [isBroadcast] returns false. - * A broadcast stream inheriting from [Stream] must override [isBroadcast] - * to return `true`. - */ -abstract class Stream { - Stream(); - - /** - * Creates a new single-subscription stream from the future. - * - * When the future completes, the stream will fire one event, either - * data or error, and then close with a done-event. - */ - factory Stream.fromFuture(Future future) { - // Use the controller's buffering to fill in the value even before - // the stream has a listener. For a single value, it's not worth it - // to wait for a listener before doing the `then` on the future. - _StreamController controller = - new StreamController(sync: true) as _StreamController; - future.then((value) { - controller._add(value); - controller._closeUnchecked(); - }, - onError: (error, stackTrace) { - controller._addError(error, stackTrace); - controller._closeUnchecked(); - }); - return controller.stream; - } - - /** - * Creates a single-subscription stream that gets its data from [data]. - * - * The iterable is iterated when the stream receives a listener, and stops - * iterating if the listener cancels the subscription. - * - * If iterating [data] throws an error, the stream ends immediately with - * that error. No done event will be sent (iteration is not complete), but no - * further data events will be generated either, since iteration cannot - * continue. - */ - factory Stream.fromIterable(Iterable data) { - return new _GeneratedStreamImpl( - () => new _IterablePendingEvents(data)); - } - - /** - * Creates a stream that repeatedly emits events at [period] intervals. - * - * The event values are computed by invoking [computation]. The argument to - * this callback is an integer that starts with 0 and is incremented for - * every event. - * - * If [computation] is omitted the event values will all be `null`. - */ - factory Stream.periodic(Duration period, - [T computation(int computationCount)]) { - if (computation == null) computation = ((i) => null); - - Timer timer; - int computationCount = 0; - StreamController controller; - // Counts the time that the Stream was running (and not paused). - Stopwatch watch = new Stopwatch(); - - void sendEvent() { - watch.reset(); - T data = computation(computationCount++); - controller.add(data); - } - - void startPeriodicTimer() { - assert(timer == null); - timer = new Timer.periodic(period, (Timer timer) { - sendEvent(); - }); - } - - controller = new StreamController(sync: true, - onListen: () { - watch.start(); - startPeriodicTimer(); - }, - onPause: () { - timer.cancel(); - timer = null; - watch.stop(); - }, - onResume: () { - assert(timer == null); - Duration elapsed = watch.elapsed; - watch.start(); - timer = new Timer(period - elapsed, () { - timer = null; - startPeriodicTimer(); - sendEvent(); - }); - }, - onCancel: () { - if (timer != null) timer.cancel(); - timer = null; - }); - return controller.stream; - } - - /** - * Creates a stream where all events of an existing stream are piped through - * a sink-transformation. - * - * The given [mapSink] closure is invoked when the returned stream is - * listened to. All events from the [source] are added into the event sink - * that is returned from the invocation. The transformation puts all - * transformed events into the sink the [mapSink] closure received during - * its invocation. Conceptually the [mapSink] creates a transformation pipe - * with the input sink being the returned [EventSink] and the output sink - * being the sink it received. - * - * This constructor is frequently used to build transformers. - * - * Example use for a duplicating transformer: - * - * class DuplicationSink implements EventSink { - * final EventSink _outputSink; - * DuplicationSink(this._outputSink); - * - * void add(String data) { - * _outputSink.add(data); - * _outputSink.add(data); - * } - * - * void addError(e, [st]) => _outputSink(e, st); - * void close() => _outputSink.close(); - * } - * - * class DuplicationTransformer implements StreamTransformer { - * // Some generic types ommitted for brevety. - * Stream bind(Stream stream) => new Stream.eventTransform( - * stream, - * (EventSink sink) => new DuplicationSink(sink)); - * } - * - * stringStream.transform(new DuplicationTransformer()); - * - * The resulting stream is a broadcast stream if [source] is. - */ - factory Stream.eventTransformed(Stream source, - EventSink mapSink(EventSink sink)) { - return new _BoundSinkStream(source, mapSink); - } - - /** - * Reports whether this stream is a broadcast stream. - */ - bool get isBroadcast => false; - - /** - * Returns a multi-subscription stream that produces the same events as this. - * - * The returned stream will subscribe to this stream when its first - * subscriber is added, and will stay subscribed until this stream ends, - * or a callback cancels the subscription. - * - * If [onListen] is provided, it is called with a subscription-like object - * that represents the underlying subscription to this stream. It is - * possible to pause, resume or cancel the subscription during the call - * to [onListen]. It is not possible to change the event handlers, including - * using [StreamSubscription.asFuture]. - * - * If [onCancel] is provided, it is called in a similar way to [onListen] - * when the returned stream stops having listener. If it later gets - * a new listener, the [onListen] function is called again. - * - * Use the callbacks, for example, for pausing the underlying subscription - * while having no subscribers to prevent losing events, or canceling the - * subscription when there are no listeners. - */ - Stream asBroadcastStream({ - void onListen(StreamSubscription subscription), - void onCancel(StreamSubscription subscription) }) { - return new _AsBroadcastStream(this, onListen, onCancel); - } - - /** - * Adds a subscription to this stream. - * - * On each data event from this stream, the subscriber's [onData] handler - * is called. If [onData] is null, nothing happens. - * - * On errors from this stream, the [onError] handler is given a - * object describing the error. - * - * The [onError] callback must be of type `void onError(error)` or - * `void onError(error, StackTrace stackTrace)`. If [onError] accepts - * two arguments it is called with the stack trace (which could be `null` if - * the stream itself received an error without stack trace). - * Otherwise it is called with just the error object. - * - * If this stream closes, the [onDone] handler is called. - * - * If [cancelOnError] is true, the subscription is ended when - * the first error is reported. The default is false. - */ - StreamSubscription listen(void onData(T event), - { Function onError, - void onDone(), - bool cancelOnError}); - - /** - * Creates a new stream from this stream that discards some data events. - * - * The new stream sends the same error and done events as this stream, - * but it only sends the data events that satisfy the [test]. - * - * The returned stream is a broadcast stream if this stream is. - * If a broadcast stream is listened to more than once, each subscription - * will individually perform the `test`. - */ - Stream where(bool test(T event)) { - return new _WhereStream(this, test); - } - - /** - * Creates a new stream that converts each element of this stream - * to a new value using the [convert] function. - * - * The returned stream is a broadcast stream if this stream is. - * If a broadcast stream is listened to more than once, each subscription - * will individually execute `map` for each event. - */ - Stream map(convert(T event)) { - return new _MapStream(this, convert); - } - - /** - * Creates a new stream with each data event of this stream asynchronously - * mapped to a new event. - * - * This acts like [map], except that [convert] may return a [Future], - * and in that case, the stream waits for that future to complete before - * continuing with its result. - * - * The returned stream is a broadcast stream if this stream is. - */ - Stream asyncMap(convert(T event)) { - StreamController controller; - StreamSubscription subscription; - void onListen () { - final add = controller.add; - assert(controller is _StreamController || - controller is _BroadcastStreamController); - final eventSink = controller; - final addError = eventSink._addError; - subscription = this.listen( - (T event) { - var newValue; - try { - newValue = convert(event); - } catch (e, s) { - controller.addError(e, s); - return; - } - if (newValue is Future) { - subscription.pause(); - newValue.then(add, onError: addError) - .whenComplete(subscription.resume); - } else { - controller.add(newValue); - } - }, - onError: addError, - onDone: controller.close - ); - } - if (this.isBroadcast) { - controller = new StreamController.broadcast( - onListen: onListen, - onCancel: () { subscription.cancel(); }, - sync: true - ); - } else { - controller = new StreamController( - onListen: onListen, - onPause: () { subscription.pause(); }, - onResume: () { subscription.resume(); }, - onCancel: () { subscription.cancel(); }, - sync: true - ); - } - return controller.stream; - } - - /** - * Creates a new stream with the events of a stream per original event. - * - * This acts like [expand], except that [convert] returns a [Stream] - * instead of an [Iterable]. - * The events of the returned stream becomes the events of the returned - * stream, in the order they are produced. - * - * If [convert] returns `null`, no value is put on the output stream, - * just as if it returned an empty stream. - * - * The returned stream is a broadcast stream if this stream is. - */ - Stream asyncExpand(Stream convert(T event)) { - StreamController controller; - StreamSubscription subscription; - void onListen() { - assert(controller is _StreamController || - controller is _BroadcastStreamController); - final eventSink = controller; - subscription = this.listen( - (T event) { - Stream newStream; - try { - newStream = convert(event); - } catch (e, s) { - controller.addError(e, s); - return; - } - if (newStream != null) { - subscription.pause(); - controller.addStream(newStream) - .whenComplete(subscription.resume); - } - }, - onError: eventSink._addError, // Avoid Zone error replacement. - onDone: controller.close - ); - } - if (this.isBroadcast) { - controller = new StreamController.broadcast( - onListen: onListen, - onCancel: () { subscription.cancel(); }, - sync: true - ); - } else { - controller = new StreamController( - onListen: onListen, - onPause: () { subscription.pause(); }, - onResume: () { subscription.resume(); }, - onCancel: () { subscription.cancel(); }, - sync: true - ); - } - return controller.stream; - } - - /** - * Creates a wrapper Stream that intercepts some errors from this stream. - * - * If this stream sends an error that matches [test], then it is intercepted - * by the [handle] function. - * - * The [onError] callback must be of type `void onError(error)` or - * `void onError(error, StackTrace stackTrace)`. Depending on the function - * type the the stream either invokes [onError] with or without a stack - * trace. The stack trace argument might be `null` if the stream itself - * received an error without stack trace. - * - * An asynchronous error [:e:] is matched by a test function if [:test(e):] - * returns true. If [test] is omitted, every error is considered matching. - * - * If the error is intercepted, the [handle] function can decide what to do - * with it. It can throw if it wants to raise a new (or the same) error, - * or simply return to make the stream forget the error. - * - * If you need to transform an error into a data event, use the more generic - * [Stream.transform] to handle the event by writing a data event to - * the output sink. - * - * The returned stream is a broadcast stream if this stream is. - * If a broadcast stream is listened to more than once, each subscription - * will individually perform the `test` and handle the error. - */ - Stream handleError(Function onError, { bool test(error) }) { - return new _HandleErrorStream(this, onError, test); - } - - /** - * Creates a new stream from this stream that converts each element - * into zero or more events. - * - * Each incoming event is converted to an [Iterable] of new events, - * and each of these new events are then sent by the returned stream - * in order. - * - * The returned stream is a broadcast stream if this stream is. - * If a broadcast stream is listened to more than once, each subscription - * will individually call `convert` and expand the events. - */ - Stream expand(Iterable convert(T value)) { - return new _ExpandStream(this, convert); - } - - /** - * Binds this stream as the input of the provided [StreamConsumer]. - * - * The `streamConsumer` is closed when the stream has been added to it. - * - * Returns a future which completes when the stream has been consumed - * and the consumer has been closed. - */ - Future pipe(StreamConsumer streamConsumer) { - return streamConsumer.addStream(this).then((_) => streamConsumer.close()); - } - - /** - * Chains this stream as the input of the provided [StreamTransformer]. - * - * Returns the result of [:streamTransformer.bind:] itself. - * - * The `streamTransformer` can decide whether it wants to return a - * broadcast stream or not. - */ - Stream transform(StreamTransformer streamTransformer) { - return streamTransformer.bind(this); - } - - /** - * Reduces a sequence of values by repeatedly applying [combine]. - */ - Future reduce(T combine(T previous, T element)) { - _Future result = new _Future(); - bool seenFirst = false; - T value; - StreamSubscription subscription; - subscription = this.listen( - (T element) { - if (seenFirst) { - _runUserCode(() => combine(value, element), - (T newValue) { value = newValue; }, - _cancelAndErrorClosure(subscription, result)); - } else { - value = element; - seenFirst = true; - } - }, - onError: result._completeError, - onDone: () { - if (!seenFirst) { - try { - throw IterableElementError.noElement(); - } catch (e, s) { - _completeWithErrorCallback(result, e, s); - } - } else { - result._complete(value); - } - }, - cancelOnError: true - ); - return result; - } - - /** Reduces a sequence of values by repeatedly applying [combine]. */ - Future fold(var initialValue, combine(var previous, T element)) { - _Future result = new _Future(); - var value = initialValue; - StreamSubscription subscription; - subscription = this.listen( - (T element) { - _runUserCode( - () => combine(value, element), - (newValue) { value = newValue; }, - _cancelAndErrorClosure(subscription, result) - ); - }, - onError: (e, st) { - result._completeError(e, st); - }, - onDone: () { - result._complete(value); - }, - cancelOnError: true); - return result; - } - - /** - * Collects string of data events' string representations. - * - * If [separator] is provided, it is inserted between any two - * elements. - * - * Any error in the stream causes the future to complete with that - * error. Otherwise it completes with the collected string when - * the "done" event arrives. - */ - Future join([String separator = ""]) { - _Future result = new _Future(); - StringBuffer buffer = new StringBuffer(); - StreamSubscription subscription; - bool first = true; - subscription = this.listen( - (T element) { - if (!first) { - buffer.write(separator); - } - first = false; - try { - buffer.write(element); - } catch (e, s) { - _cancelAndErrorWithReplacement(subscription, result, e, s); - } - }, - onError: (e) { - result._completeError(e); - }, - onDone: () { - result._complete(buffer.toString()); - }, - cancelOnError: true); - return result; - } - - /** - * Checks whether [needle] occurs in the elements provided by this stream. - * - * Completes the [Future] when the answer is known. - * If this stream reports an error, the [Future] will report that error. - */ - Future contains(Object needle) { - _Future future = new _Future(); - StreamSubscription subscription; - subscription = this.listen( - (T element) { - _runUserCode( - () => (element == needle), - (bool isMatch) { - if (isMatch) { - _cancelAndValue(subscription, future, true); - } - }, - _cancelAndErrorClosure(subscription, future) - ); - }, - onError: future._completeError, - onDone: () { - future._complete(false); - }, - cancelOnError: true); - return future; - } - - /** - * Executes [action] on each data event of the stream. - * - * Completes the returned [Future] when all events of the stream - * have been processed. Completes the future with an error if the - * stream has an error event, or if [action] throws. - */ - Future forEach(void action(T element)) { - _Future future = new _Future(); - StreamSubscription subscription; - subscription = this.listen( - (T element) { - _runUserCode( - () => action(element), - (_) {}, - _cancelAndErrorClosure(subscription, future) - ); - }, - onError: future._completeError, - onDone: () { - future._complete(null); - }, - cancelOnError: true); - return future; - } - - /** - * Checks whether [test] accepts all elements provided by this stream. - * - * Completes the [Future] when the answer is known. - * If this stream reports an error, the [Future] will report that error. - */ - Future every(bool test(T element)) { - _Future future = new _Future(); - StreamSubscription subscription; - subscription = this.listen( - (T element) { - _runUserCode( - () => test(element), - (bool isMatch) { - if (!isMatch) { - _cancelAndValue(subscription, future, false); - } - }, - _cancelAndErrorClosure(subscription, future) - ); - }, - onError: future._completeError, - onDone: () { - future._complete(true); - }, - cancelOnError: true); - return future; - } - - /** - * Checks whether [test] accepts any element provided by this stream. - * - * Completes the [Future] when the answer is known. - * - * If this stream reports an error, the [Future] reports that error. - * - * Stops listening to the stream after the first matching element has been - * found. - * - * Internally the method cancels its subscription after this element. This - * means that single-subscription (non-broadcast) streams are closed and - * cannot be reused after a call to this method. - */ - Future any(bool test(T element)) { - _Future future = new _Future(); - StreamSubscription subscription; - subscription = this.listen( - (T element) { - _runUserCode( - () => test(element), - (bool isMatch) { - if (isMatch) { - _cancelAndValue(subscription, future, true); - } - }, - _cancelAndErrorClosure(subscription, future) - ); - }, - onError: future._completeError, - onDone: () { - future._complete(false); - }, - cancelOnError: true); - return future; - } - - - /** Counts the elements in the stream. */ - Future get length { - _Future future = new _Future(); - int count = 0; - this.listen( - (_) { count++; }, - onError: future._completeError, - onDone: () { - future._complete(count); - }, - cancelOnError: true); - return future; - } - - /** - * Reports whether this stream contains any elements. - * - * Stops listening to the stream after the first element has been received. - * - * Internally the method cancels its subscription after the first element. - * This means that single-subscription (non-broadcast) streams are closed and - * cannot be reused after a call to this getter. - */ - Future get isEmpty { - _Future future = new _Future(); - StreamSubscription subscription; - subscription = this.listen( - (_) { - _cancelAndValue(subscription, future, false); - }, - onError: future._completeError, - onDone: () { - future._complete(true); - }, - cancelOnError: true); - return future; - } - - /** Collects the data of this stream in a [List]. */ - Future> toList() { - List result = []; - _Future> future = new _Future>(); - this.listen( - (T data) { - result.add(data); - }, - onError: future._completeError, - onDone: () { - future._complete(result); - }, - cancelOnError: true); - return future; - } - - /** - * Collects the data of this stream in a [Set]. - * - * The returned set is the same type as returned by `new Set()`. - * If another type of set is needed, either use [forEach] to add each - * element to the set, or use - * `toList().then((list) => new SomeOtherSet.from(list))` - * to create the set. - */ - Future> toSet() { - Set result = new Set(); - _Future> future = new _Future>(); - this.listen( - (T data) { - result.add(data); - }, - onError: future._completeError, - onDone: () { - future._complete(result); - }, - cancelOnError: true); - return future; - } - - /** - * Discards all data on the stream, but signals when it's done or an error - * occured. - * - * When subscribing using [drain], cancelOnError will be true. This means - * that the future will complete with the first error on the stream and then - * cancel the subscription. - * - * In case of a `done` event the future completes with the given - * [futureValue]. - */ - Future drain([var futureValue]) => listen(null, cancelOnError: true) - .asFuture(futureValue); - - /** - * Provides at most the first [n] values of this stream. - * - * Forwards the first [n] data events of this stream, and all error - * events, to the returned stream, and ends with a done event. - * - * If this stream produces fewer than [count] values before it's done, - * so will the returned stream. - * - * Stops listening to the stream after the first [n] elements have been - * received. - * - * Internally the method cancels its subscription after these elements. This - * means that single-subscription (non-broadcast) streams are closed and - * cannot be reused after a call to this method. - * - * The returned stream is a broadcast stream if this stream is. - * For a broadcast stream, the events are only counted from the time - * the returned stream is listened to. - */ - Stream take(int count) { - return new _TakeStream(this, count); - } - - /** - * Forwards data events while [test] is successful. - * - * The returned stream provides the same events as this stream as long - * as [test] returns [:true:] for the event data. The stream is done - * when either this stream is done, or when this stream first provides - * a value that [test] doesn't accept. - * - * Stops listening to the stream after the accepted elements. - * - * Internally the method cancels its subscription after these elements. This - * means that single-subscription (non-broadcast) streams are closed and - * cannot be reused after a call to this method. - * - * The returned stream is a broadcast stream if this stream is. - * For a broadcast stream, the events are only tested from the time - * the returned stream is listened to. - */ - Stream takeWhile(bool test(T element)) { - return new _TakeWhileStream(this, test); - } - - /** - * Skips the first [count] data events from this stream. - * - * The returned stream is a broadcast stream if this stream is. - * For a broadcast stream, the events are only counted from the time - * the returned stream is listened to. - */ - Stream skip(int count) { - return new _SkipStream(this, count); - } - - /** - * Skip data events from this stream while they are matched by [test]. - * - * Error and done events are provided by the returned stream unmodified. - * - * Starting with the first data event where [test] returns false for the - * event data, the returned stream will have the same events as this stream. - * - * The returned stream is a broadcast stream if this stream is. - * For a broadcast stream, the events are only tested from the time - * the returned stream is listened to. - */ - Stream skipWhile(bool test(T element)) { - return new _SkipWhileStream(this, test); - } - - /** - * Skips data events if they are equal to the previous data event. - * - * The returned stream provides the same events as this stream, except - * that it never provides two consequtive data events that are equal. - * - * Equality is determined by the provided [equals] method. If that is - * omitted, the '==' operator on the last provided data element is used. - * - * The returned stream is a broadcast stream if this stream is. - * If a broadcast stream is listened to more than once, each subscription - * will individually perform the `equals` test. - */ - Stream distinct([bool equals(T previous, T next)]) { - return new _DistinctStream(this, equals); - } - - /** - * Returns the first element of the stream. - * - * Stops listening to the stream after the first element has been received. - * - * Internally the method cancels its subscription after the first element. - * This means that single-subscription (non-broadcast) streams are closed - * and cannot be reused after a call to this getter. - * - * If an error event occurs before the first data event, the resulting future - * is completed with that error. - * - * If this stream is empty (a done event occurs before the first data event), - * the resulting future completes with a [StateError]. - * - * Except for the type of the error, this method is equivalent to - * [:this.elementAt(0):]. - */ - Future get first { - _Future future = new _Future(); - StreamSubscription subscription; - subscription = this.listen( - (T value) { - _cancelAndValue(subscription, future, value); - }, - onError: future._completeError, - onDone: () { - try { - throw IterableElementError.noElement(); - } catch (e, s) { - _completeWithErrorCallback(future, e, s); - } - }, - cancelOnError: true); - return future; - } - - /** - * Returns the last element of the stream. - * - * If an error event occurs before the first data event, the resulting future - * is completed with that error. - * - * If this stream is empty (a done event occurs before the first data event), - * the resulting future completes with a [StateError]. - */ - Future get last { - _Future future = new _Future(); - T result = null; - bool foundResult = false; - StreamSubscription subscription; - subscription = this.listen( - (T value) { - foundResult = true; - result = value; - }, - onError: future._completeError, - onDone: () { - if (foundResult) { - future._complete(result); - return; - } - try { - throw IterableElementError.noElement(); - } catch (e, s) { - _completeWithErrorCallback(future, e, s); - } - }, - cancelOnError: true); - return future; - } - - /** - * Returns the single element. - * - * If an error event occurs before or after the first data event, the - * resulting future is completed with that error. - * - * If [this] is empty or has more than one element throws a [StateError]. - */ - Future get single { - _Future future = new _Future(); - T result = null; - bool foundResult = false; - StreamSubscription subscription; - subscription = this.listen( - (T value) { - if (foundResult) { - // This is the second element we get. - try { - throw IterableElementError.tooMany(); - } catch (e, s) { - _cancelAndErrorWithReplacement(subscription, future, e, s); - } - return; - } - foundResult = true; - result = value; - }, - onError: future._completeError, - onDone: () { - if (foundResult) { - future._complete(result); - return; - } - try { - throw IterableElementError.noElement(); - } catch (e, s) { - _completeWithErrorCallback(future, e, s); - } - }, - cancelOnError: true); - return future; - } - - /** - * Finds the first element of this stream matching [test]. - * - * Returns a future that is filled with the first element of this stream - * that [test] returns true for. - * - * If no such element is found before this stream is done, and a - * [defaultValue] function is provided, the result of calling [defaultValue] - * becomes the value of the future. - * - * Stops listening to the stream after the first matching element has been - * received. - * - * Internally the method cancels its subscription after the first element that - * matches the predicate. This means that single-subscription (non-broadcast) - * streams are closed and cannot be reused after a call to this method. - * - * If an error occurs, or if this stream ends without finding a match and - * with no [defaultValue] function provided, the future will receive an - * error. - */ - Future firstWhere(bool test(T element), {Object defaultValue()}) { - _Future future = new _Future(); - StreamSubscription subscription; - subscription = this.listen( - (T value) { - _runUserCode( - () => test(value), - (bool isMatch) { - if (isMatch) { - _cancelAndValue(subscription, future, value); - } - }, - _cancelAndErrorClosure(subscription, future) - ); - }, - onError: future._completeError, - onDone: () { - if (defaultValue != null) { - _runUserCode(defaultValue, future._complete, future._completeError); - return; - } - try { - throw IterableElementError.noElement(); - } catch (e, s) { - _completeWithErrorCallback(future, e, s); - } - }, - cancelOnError: true); - return future; - } - - /** - * Finds the last element in this stream matching [test]. - * - * As [firstWhere], except that the last matching element is found. - * That means that the result cannot be provided before this stream - * is done. - */ - Future lastWhere(bool test(T element), {Object defaultValue()}) { - _Future future = new _Future(); - T result = null; - bool foundResult = false; - StreamSubscription subscription; - subscription = this.listen( - (T value) { - _runUserCode( - () => true == test(value), - (bool isMatch) { - if (isMatch) { - foundResult = true; - result = value; - } - }, - _cancelAndErrorClosure(subscription, future) - ); - }, - onError: future._completeError, - onDone: () { - if (foundResult) { - future._complete(result); - return; - } - if (defaultValue != null) { - _runUserCode(defaultValue, future._complete, future._completeError); - return; - } - try { - throw IterableElementError.noElement(); - } catch (e, s) { - _completeWithErrorCallback(future, e, s); - } - }, - cancelOnError: true); - return future; - } - - /** - * Finds the single element in this stream matching [test]. - * - * Like [lastMatch], except that it is an error if more than one - * matching element occurs in the stream. - */ - Future singleWhere(bool test(T element)) { - _Future future = new _Future(); - T result = null; - bool foundResult = false; - StreamSubscription subscription; - subscription = this.listen( - (T value) { - _runUserCode( - () => true == test(value), - (bool isMatch) { - if (isMatch) { - if (foundResult) { - try { - throw IterableElementError.tooMany(); - } catch (e, s) { - _cancelAndErrorWithReplacement(subscription, future, e, s); - } - return; - } - foundResult = true; - result = value; - } - }, - _cancelAndErrorClosure(subscription, future) - ); - }, - onError: future._completeError, - onDone: () { - if (foundResult) { - future._complete(result); - return; - } - try { - throw IterableElementError.noElement(); - } catch (e, s) { - _completeWithErrorCallback(future, e, s); - } - }, - cancelOnError: true); - return future; - } - - /** - * Returns the value of the [index]th data event of this stream. - * - * Stops listening to the stream after the [index]th data event has been - * received. - * - * Internally the method cancels its subscription after these elements. This - * means that single-subscription (non-broadcast) streams are closed and - * cannot be reused after a call to this method. - * - * If an error event occurs before the value is found, the future completes - * with this error. - * - * If a done event occurs before the value is found, the future completes - * with a [RangeError]. - */ - Future elementAt(int index) { - if (index is! int || index < 0) throw new ArgumentError(index); - _Future future = new _Future(); - StreamSubscription subscription; - int elementIndex = 0; - subscription = this.listen( - (T value) { - if (index == elementIndex) { - _cancelAndValue(subscription, future, value); - return; - } - elementIndex += 1; - }, - onError: future._completeError, - onDone: () { - future._completeError( - new RangeError.index(index, this, "index", null, elementIndex)); - }, - cancelOnError: true); - return future; - } - - /** - * Creates a new stream with the same events as this stream. - * - * Whenever more than [timeLimit] passes between two events from this stream, - * the [onTimeout] function is called. - * - * The countdown doesn't start until the returned stream is listened to. - * The countdown is reset every time an event is forwarded from this stream, - * or when the stream is paused and resumed. - * - * The [onTimeout] function is called with one argument: an - * [EventSink] that allows putting events into the returned stream. - * This `EventSink` is only valid during the call to `onTimeout`. - * - * If `onTimeout` is omitted, a timeout will just put a [TimeoutException] - * into the error channel of the returned stream. - * - * The returned stream is a broadcast stream if this stream is. - * If a broadcast stream is listened to more than once, each subscription - * will have its individually timer that starts counting on listen, - * and the subscriptions' timers can be paused individually. - */ - Stream timeout(Duration timeLimit, {void onTimeout(EventSink sink)}) { - StreamController controller; - // The following variables are set on listen. - StreamSubscription subscription; - Timer timer; - Zone zone; - Function timeout; - - void onData(T event) { - timer.cancel(); - controller.add(event); - timer = zone.createTimer(timeLimit, timeout); - } - void onError(error, StackTrace stackTrace) { - timer.cancel(); - assert(controller is _StreamController || - controller is _BroadcastStreamController); - var eventSink = controller; - eventSink._addError(error, stackTrace); // Avoid Zone error replacement. - timer = zone.createTimer(timeLimit, timeout); - } - void onDone() { - timer.cancel(); - controller.close(); - } - void onListen() { - // This is the onListen callback for of controller. - // It runs in the same zone that the subscription was created in. - // Use that zone for creating timers and running the onTimeout - // callback. - zone = Zone.current; - if (onTimeout == null) { - timeout = () { - controller.addError(new TimeoutException("No stream event", - timeLimit), null); - }; - } else { - onTimeout = zone.registerUnaryCallback(onTimeout); - _ControllerEventSinkWrapper wrapper = - new _ControllerEventSinkWrapper(null); - timeout = () { - wrapper._sink = controller; // Only valid during call. - zone.runUnaryGuarded(onTimeout, wrapper); - wrapper._sink = null; - }; - } - - subscription = this.listen(onData, onError: onError, onDone: onDone); - timer = zone.createTimer(timeLimit, timeout); - } - Future onCancel() { - timer.cancel(); - Future result = subscription.cancel(); - subscription = null; - return result; - } - controller = isBroadcast - ? new _SyncBroadcastStreamController(onListen, onCancel) - : new _SyncStreamController( - onListen, - () { - // Don't null the timer, onCancel may call cancel again. - timer.cancel(); - subscription.pause(); - }, - () { - subscription.resume(); - timer = zone.createTimer(timeLimit, timeout); - }, - onCancel); - return controller.stream; - } -} - -/** - * A subscritption on events from a [Stream]. - * - * When you listen on a [Stream] using [Stream.listen], - * a [StreamSubscription] object is returned. - * - * The subscription provides events to the listener, - * and holds the callbacks used to handle the events. - * The subscription can also be used to unsubscribe from the events, - * or to temporarily pause the events from the stream. - */ -abstract class StreamSubscription { - /** - * Cancels this subscription. It will no longer receive events. - * - * May return a future which completes when the stream is done cleaning up. - * This can be used if the stream needs to release some resources - * that are needed for a following operation, - * for example a file being read, that should be deleted afterwards. - * In that case, the file may not be able to be deleted successfully - * until the returned future has completed. - * - * The future will be completed with a `null` value. - * If the cleanup throws, which it really shouldn't, the returned future - * will be completed with that error. - * - * Returns `null` if there is no need to wait. - */ - Future cancel(); - - /** - * Set or override the data event handler of this subscription. - * - * This method overrides the handler that has been set at the invocation of - * [Stream.listen]. - */ - void onData(void handleData(T data)); - - /** - * Set or override the error event handler of this subscription. - * - * This method overrides the handler that has been set at the invocation of - * [Stream.listen] or by calling [asFuture]. - */ - void onError(Function handleError); - - /** - * Set or override the done event handler of this subscription. - * - * This method overrides the handler that has been set at the invocation of - * [Stream.listen] or by calling [asFuture]. - */ - void onDone(void handleDone()); - - /** - * Request that the stream pauses events until further notice. - * - * While paused, the subscription will not fire any events. - * If it receives events from its source, they will be buffered until - * the subscription is resumed. - * The underlying source is usually informed about the pause, - * so it can stop generating events until the subscription is resumed. - * - * To avoid buffering events on a broadcast stream, it is better to - * cancel this subscription, and start to listen again when events - * are needed. - * - * If [resumeSignal] is provided, the stream will undo the pause - * when the future completes. If the future completes with an error, - * the stream will resume, but the error will not be handled! - * - * A call to [resume] will also undo a pause. - * - * If the subscription is paused more than once, an equal number - * of resumes must be performed to resume the stream. - * - * Currently DOM streams silently drop events when the stream is paused. This - * is a bug and will be fixed. - */ - void pause([Future resumeSignal]); - - /** - * Resume after a pause. - */ - void resume(); - - /** - * Returns true if the [StreamSubscription] is paused. - */ - bool get isPaused; - - /** - * Returns a future that handles the [onDone] and [onError] callbacks. - * - * This method *overwrites* the existing [onDone] and [onError] callbacks - * with new ones that complete the returned future. - * - * In case of an error the subscription will automatically cancel (even - * when it was listening with `cancelOnError` set to `false`). - * - * In case of a `done` event the future completes with the given - * [futureValue]. - */ - Future asFuture([var futureValue]); -} - - -/** - * An interface that abstracts creation or handling of [Stream] events. - */ -abstract class EventSink implements Sink { - /** Send a data event to a stream. */ - void add(T event); - - /** Send an async error to a stream. */ - void addError(errorEvent, [StackTrace stackTrace]); - - /** Close the sink. No further events can be added after closing. */ - void close(); -} - - -/** [Stream] wrapper that only exposes the [Stream] interface. */ -class StreamView extends Stream { - Stream _stream; - - StreamView(this._stream); - - bool get isBroadcast => _stream.isBroadcast; - - Stream asBroadcastStream({void onListen(StreamSubscription subscription), - void onCancel(StreamSubscription subscription)}) - => _stream.asBroadcastStream(onListen: onListen, onCancel: onCancel); - - StreamSubscription listen(void onData(T value), - { Function onError, - void onDone(), - bool cancelOnError }) { - return _stream.listen(onData, onError: onError, onDone: onDone, - cancelOnError: cancelOnError); - } -} - - -/** - * The target of a [Stream.pipe] call. - * - * The [Stream.pipe] call will pass itself to this object, and then return - * the resulting [Future]. The pipe should complete the future when it's - * done. - */ -abstract class StreamConsumer { - /** - * Consumes the elements of [stream]. - * - * Listens on [stream] and does something for each event. - * - * The consumer may stop listening after an error, or it may consume - * all the errors and only stop at a done event. - */ - Future addStream(Stream stream); - - /** - * Tell the consumer that no futher streams will be added. - * - * Returns a future that is completed when the consumer is done handling - * events. - */ - Future close(); -} - - -/** - * A [StreamSink] unifies the asynchronous methods from [StreamConsumer] and - * the synchronous methods from [EventSink]. - * - * The [EventSink] methods can't be used while the [addStream] is called. - * As soon as the [addStream]'s [Future] completes with a value, the - * [EventSink] methods can be used again. - * - * If [addStream] is called after any of the [EventSink] methods, it'll - * be delayed until the underlying system has consumed the data added by the - * [EventSink] methods. - * - * When [EventSink] methods are used, the [done] [Future] can be used to - * catch any errors. - * - * When [close] is called, it will return the [done] [Future]. - */ -abstract class StreamSink implements StreamConsumer, EventSink { - /** - * As [EventSink.close], but returns a future. - * - * Returns the same future as [done]. - */ - Future close(); - - /** - * Return a future which is completed when the [StreamSink] is finished. - * - * If the `StreamSink` fails with an error, - * perhaps in response to adding events using [add], [addError] or [close], - * the [done] future will complete with that error. - * - * Otherwise, the returned future will complete when either: - * - * * all events have been processed and the sink has been closed, or - * * the sink has otherwise been stopped from handling more events - * (for example by cancelling a stream subscription). - */ - Future get done; -} - - -/** - * The target of a [Stream.transform] call. - * - * The [Stream.transform] call will pass itself to this object and then return - * the resulting stream. - * - * It is good practice to write transformers that can be used multiple times. - */ -abstract class StreamTransformer { - /** - * Creates a [StreamTransformer]. - * - * The returned instance takes responsibility of implementing ([bind]). - * When the user invokes `bind` it returns a new "bound" stream. Only when - * the user starts listening to the bound stream, the `listen` method - * invokes the given closure [transformer]. - * - * The [transformer] closure receives the stream, that was bound, as argument - * and returns a [StreamSubscription]. In almost all cases the closure - * listens itself to the stream that is given as argument. - * - * The result of invoking the [transformer] closure is a [StreamSubscription]. - * The bound stream-transformer (created by the `bind` method above) then sets - * the handlers it received as part of the `listen` call. - * - * Conceptually this can be summarized as follows: - * - * 1. `var transformer = new StreamTransformer(transformerClosure);` - * creates a `StreamTransformer` that supports the `bind` method. - * 2. `var boundStream = stream.transform(transformer);` binds the `stream` - * and returns a bound stream that has a pointer to `stream`. - * 3. `boundStream.listen(f1, onError: f2, onDone: f3, cancelOnError: b)` - * starts the listening and transformation. This is accomplished - * in 2 steps: first the `boundStream` invokes the `transformerClosure` with - * the `stream` it captured: `transformerClosure(stream, b)`. - * The result `subscription`, a [StreamSubscription], is then - * updated to receive its handlers: `subscription.onData(f1)`, - * `subscription.onError(f2)`, `subscription(f3)`. Finally the subscription - * is returned as result of the `listen` call. - * - * There are two common ways to create a StreamSubscription: - * - * 1. by creating a new class that implements [StreamSubscription]. - * Note that the subscription should run callbacks in the [Zone] the - * stream was listened to. - * 2. by allocating a [StreamController] and to return the result of - * listening to its stream. - * - * Example use of a duplicating transformer: - * - * stringStream.transform(new StreamTransformer( - * (Stream input, bool cancelOnError) { - * StreamController controller; - * StreamSubscription subscription; - * controller = new StreamController( - * onListen: () { - * subscription = input.listen((data) { - * // Duplicate the data. - * controller.add(data); - * controller.add(data); - * }, - * onError: controller.addError, - * onDone: controller.close, - * cancelOnError: cancelOnError); - * }, - * onPause: subscription.pause, - * onResume: subscription.resume, - * onCancel: subscription.cancel, - * sync: true); - * return controller.stream.listen(null); - * }); - */ - const factory StreamTransformer( - StreamSubscription transformer(Stream stream, bool cancelOnError)) - = _StreamSubscriptionTransformer; - - /** - * Creates a [StreamTransformer] that delegates events to the given functions. - * - * Example use of a duplicating transformer: - * - * stringStream.transform(new StreamTransformer.fromHandlers( - * handleData: (String value, EventSink sink) { - * sink.add(value); - * sink.add(value); // Duplicate the incoming events. - * })); - */ - factory StreamTransformer.fromHandlers({ - void handleData(S data, EventSink sink), - void handleError(Object error, StackTrace stackTrace, EventSink sink), - void handleDone(EventSink sink)}) - = _StreamHandlerTransformer; - - /** - * Transform the incoming [stream]'s events. - * - * Creates a new stream. - * When this stream is listened to, it will start listening on [stream], - * and generate events on the new stream based on the events from [stream]. - * - * Subscriptions on the returned stream should propagate pause state - * to the subscription on [stream]. - */ - Stream bind(Stream stream); -} - -/** - * An [Iterable] like interface for the values of a [Stream]. - * - * This wraps a [Stream] and a subscription on the stream. It listens - * on the stream, and completes the future returned by [moveNext] when the - * next value becomes available. - */ -abstract class StreamIterator { - - /** Create a [StreamIterator] on [stream]. */ - factory StreamIterator(Stream stream) - // TODO(lrn): use redirecting factory constructor when type - // arguments are supported. - => new _StreamIteratorImpl(stream); - - /** - * Wait for the next stream value to be available. - * - * It is not allowed to call this function again until the future has - * completed. If the returned future completes with anything except `true`, - * the iterator is done, and no new value will ever be available. - * - * The future may complete with an error, if the stream produces an error. - */ - Future moveNext(); - - /** - * The current value of the stream. - * - * Only valid when the future returned by [moveNext] completes with `true` - * as value, and only until the next call to [moveNext]. - */ - T get current; - - /** - * Cancels the stream iterator (and the underlying stream subscription) early. - * - * The stream iterator is automatically canceled if the [moveNext] future - * completes with either `false` or an error. - * - * If a [moveNext] call has been made, it will complete with `false` as value, - * as will all further calls to [moveNext]. - * - * If you need to stop listening for values before the stream iterator is - * automatically closed, you must call [cancel] to ensure that the stream - * is properly closed. - * - * Returns a future if the cancel-operation is not completed synchronously. - * Otherwise returns `null`. - */ - Future cancel(); -} - - -/** - * Wraps an [_EventSink] so it exposes only the [EventSink] interface. - */ -class _ControllerEventSinkWrapper implements EventSink { - EventSink _sink; - _ControllerEventSinkWrapper(this._sink); - - void add(T data) { _sink.add(data); } - void addError(error, [StackTrace stackTrace]) { - _sink.addError(error, stackTrace); - } - void close() { _sink.close(); } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/stream_controller.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/stream_controller.dart deleted file mode 100644 index aa45876e3286..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/stream_controller.dart +++ /dev/null @@ -1,803 +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. - -part of dart.async; - -// ------------------------------------------------------------------- -// Controller for creating and adding events to a stream. -// ------------------------------------------------------------------- - -/** - * A controller with the stream it controls. - * - * This controller allows sending data, error and done events on - * its [stream]. - * This class can be used to create a simple stream that others - * can listen on, and to push events to that stream. - * - * It's possible to check whether the stream is paused or not, and whether - * it has subscribers or not, as well as getting a callback when either of - * these change. - * - * If the stream starts or stops having listeners (first listener subscribing, - * last listener unsubscribing), the `onSubscriptionStateChange` callback - * is notified as soon as possible. If the subscription stat changes during - * an event firing or a callback being executed, the change will not be reported - * until the current event or callback has finished. - * If the pause state has also changed during an event or callback, only the - * subscription state callback is notified. - * - * If the subscriber state has not changed, but the pause state has, the - * `onPauseStateChange` callback is notified as soon as possible, after firing - * a current event or completing another callback. This happens if the stream - * is not paused, and a listener pauses it, or if the stream has been resumed - * from pause and has no pending events. If the listeners resume a paused stream - * while it still has queued events, the controller will still consider the - * stream paused until all queued events have been dispatched. - * - * Whether to invoke a callback depends only on the state before and after - * a stream action, for example firing an event. If the state changes multiple - * times during the action, and then ends up in the same state as before, no - * callback is performed. - * - * If listeners are added after the stream has completed (sent a "done" event), - * the listeners will be sent a "done" event eventually, but they won't affect - * the stream at all, and won't trigger callbacks. From the controller's point - * of view, the stream is completely inert when has completed. - */ -abstract class StreamController implements StreamSink { - /** The stream that this controller is controlling. */ - Stream get stream; - - /** - * A controller with a [stream] that supports only one single subscriber. - * - * If [sync] is true, events may be passed directly to the stream's listener - * during an [add], [addError] or [close] call. If [sync] is false, the event - * will be passed to the listener at a later time, after the code creating - * the event has returned. - * - * The controller will buffer all incoming events until the subscriber is - * registered. - * - * The [onPause] function is called when the stream becomes - * paused. [onResume] is called when the stream resumed. - * - * The [onListen] callback is called when the stream - * receives its listener and [onCancel] when the listener ends - * its subscription. If [onCancel] needs to perform an asynchronous operation, - * [onCancel] should return a future that completes when the cancel operation - * is done. - * - * If the stream is canceled before the controller needs new data the - * [onResume] call might not be executed. - */ - factory StreamController({void onListen(), - void onPause(), - void onResume(), - onCancel(), - bool sync: false}) { - if (onListen == null && onPause == null && - onResume == null && onCancel == null) { - return sync - ? new _NoCallbackSyncStreamController/**/() - : new _NoCallbackAsyncStreamController/**/(); - } - return sync - ? new _SyncStreamController(onListen, onPause, onResume, onCancel) - : new _AsyncStreamController(onListen, onPause, onResume, onCancel); - } - - /** - * A controller where [stream] can be listened to more than once. - * - * The [Stream] returned by [stream] is a broadcast stream. - * It can be listened to more than once. - * - * The controller distributes any events to all currently subscribed - * listeners at the time when [add], [addError] or [close] is called. - * It is not allowed to call `add`, `addError`, or `close` before a previous - * call has returned. The controller does not have any internal queue of - * events, and if there are no listeners at the time the event is added, - * it will just be dropped, or, if it is an error, be reported as uncaught. - * - * Each listener subscription is handled independently, - * and if one pauses, only the pausing listener is affected. - * A paused listener will buffer events internally until unpaused or canceled. - * - * If [sync] is true, events may be fired directly by the stream's - * subscriptions during an [add], [addError] or [close] call. - * If [sync] is false, the event will be fired at a later time, - * after the code adding the event has completed. - * - * When [sync] is false, no guarantees are given with regard to when - * multiple listeners get the events, except that each listener will get - * all events in the correct order. Each subscription handles the events - * individually. - * If two events are sent on an async controller with two listeners, - * one of the listeners may get both events - * before the other listener gets any. - * A listener must be subscribed both when the event is initiated - * (that is, when [add] is called) - * and when the event is later delivered, - * in order to receive the event. - * - * The [onListen] callback is called when the first listener is subscribed, - * and the [onCancel] is called when there are no longer any active listeners. - * If a listener is added again later, after the [onCancel] was called, - * the [onListen] will be called again. - */ - factory StreamController.broadcast({void onListen(), - void onCancel(), - bool sync: false}) { - return sync - ? new _SyncBroadcastStreamController(onListen, onCancel) - : new _AsyncBroadcastStreamController(onListen, onCancel); - } - - /** - * Returns a view of this object that only exposes the [StreamSink] interface. - */ - StreamSink get sink; - - /** - * Whether the stream is closed for adding more events. - * - * If true, the "done" event might not have fired yet, but it has been - * scheduled, and it is too late to add more events. - */ - bool get isClosed; - - /** - * Whether the subscription would need to buffer events. - * - * This is the case if the controller's stream has a listener and it is - * paused, or if it has not received a listener yet. In that case, the - * controller is considered paused as well. - * - * A broadcast stream controller is never considered paused. It always - * forwards its events to all uncanceled listeners, if any, and let them - * handle their own pausing. - */ - bool get isPaused; - - /** Whether there is a subscriber on the [Stream]. */ - bool get hasListener; - - /** - * Send or enqueue an error event. - * - * If [error] is `null`, it is replaced by a [NullThrownError]. - * - * Also allows an objection stack trace object, on top of what [EventSink] - * allows. - */ - void addError(Object error, [StackTrace stackTrace]); - - /** - * Receives events from [source] and puts them into this controller's stream. - * - * Returns a future which completes when the source stream is done. - * - * Events must not be added directly to this controller using [add], - * [addError], [close] or [addStream], until the returned future - * is complete. - * - * Data and error events are forwarded to this controller's stream. A done - * event on the source will end the `addStream` operation and complete the - * returned future. - * - * If [cancelOnError] is true, only the first error on [source] is - * forwarded to the controller's stream, and the `addStream` ends - * after this. If [cancelOnError] is false, all errors are forwarded - * and only a done event will end the `addStream`. - */ - Future addStream(Stream source, {bool cancelOnError: true}); -} - - -abstract class _StreamControllerLifecycle { - StreamSubscription _subscribe( - void onData(T data), - Function onError, - void onDone(), - bool cancelOnError); - void _recordPause(StreamSubscription subscription) {} - void _recordResume(StreamSubscription subscription) {} - Future _recordCancel(StreamSubscription subscription) => null; -} - -/** - * Default implementation of [StreamController]. - * - * Controls a stream that only supports a single controller. - */ -abstract class _StreamController implements StreamController, - _StreamControllerLifecycle, - _EventSink, - _EventDispatch { - // The states are bit-flags. More than one can be set at a time. - // - // The "subscription state" goes through the states: - // initial -> subscribed -> canceled. - // These are mutually exclusive. - // The "closed" state records whether the [close] method has been called - // on the controller. This can be done at any time. If done before - // subscription, the done event is queued. If done after cancel, the done - // event is ignored (just as any other event after a cancel). - - /** The controller is in its initial state with no subscription. */ - static const int _STATE_INITIAL = 0; - /** The controller has a subscription, but hasn't been closed or canceled. */ - static const int _STATE_SUBSCRIBED = 1; - /** The subscription is canceled. */ - static const int _STATE_CANCELED = 2; - /** Mask for the subscription state. */ - static const int _STATE_SUBSCRIPTION_MASK = 3; - - // The following state relate to the controller, not the subscription. - // If closed, adding more events is not allowed. - // If executing an [addStream], new events are not allowed either, but will - // be added by the stream. - - /** - * The controller is closed due to calling [close]. - * - * When the stream is closed, you can neither add new events nor add new - * listeners. - */ - static const int _STATE_CLOSED = 4; - /** - * The controller is in the middle of an [addStream] operation. - * - * While adding events from a stream, no new events can be added directly - * on the controller. - */ - static const int _STATE_ADDSTREAM = 8; - - /** - * Field containing different data depending on the current subscription - * state. - * - * If [_state] is [_STATE_INITIAL], the field may contain a [_PendingEvents] - * for events added to the controller before a subscription. - * - * While [_state] is [_STATE_SUBSCRIBED], the field contains the subscription. - * - * When [_state] is [_STATE_CANCELED] the field is currently not used. - */ - var _varData; - - /** Current state of the controller. */ - int _state = _STATE_INITIAL; - - /** - * Future completed when the stream sends its last event. - * - * This is also the future returned by [close]. - */ - // TODO(lrn): Could this be stored in the varData field too, if it's not - // accessed until the call to "close"? Then we need to special case if it's - // accessed earlier, or if close is called before subscribing. - _Future _doneFuture; - - _StreamController(); - - _NotificationHandler get _onListen; - _NotificationHandler get _onPause; - _NotificationHandler get _onResume; - _NotificationHandler get _onCancel; - - // Return a new stream every time. The streams are equal, but not identical. - Stream get stream => new _ControllerStream(this); - - /** - * Returns a view of this object that only exposes the [StreamSink] interface. - */ - StreamSink get sink => new _StreamSinkWrapper(this); - - /** - * Whether a listener has existed and been canceled. - * - * After this, adding more events will be ignored. - */ - bool get _isCanceled => (_state & _STATE_CANCELED) != 0; - - /** Whether there is an active listener. */ - bool get hasListener => (_state & _STATE_SUBSCRIBED) != 0; - - /** Whether there has not been a listener yet. */ - bool get _isInitialState => - (_state & _STATE_SUBSCRIPTION_MASK) == _STATE_INITIAL; - - bool get isClosed => (_state & _STATE_CLOSED) != 0; - - bool get isPaused => hasListener ? _subscription._isInputPaused - : !_isCanceled; - - bool get _isAddingStream => (_state & _STATE_ADDSTREAM) != 0; - - /** New events may not be added after close, or during addStream. */ - bool get _mayAddEvent => (_state < _STATE_CLOSED); - - // Returns the pending events. - // Pending events are events added before a subscription exists. - // They are added to the subscription when it is created. - // Pending events, if any, are kept in the _varData field until the - // stream is listened to. - // While adding a stream, pending events are moved into the - // state object to allow the state object to use the _varData field. - _PendingEvents get _pendingEvents { - assert(_isInitialState); - if (!_isAddingStream) { - return _varData; - } - _StreamControllerAddStreamState state = _varData; - return state.varData; - } - - // Returns the pending events, and creates the object if necessary. - _StreamImplEvents _ensurePendingEvents() { - assert(_isInitialState); - if (!_isAddingStream) { - if (_varData == null) _varData = new _StreamImplEvents(); - return _varData; - } - _StreamControllerAddStreamState state = _varData; - if (state.varData == null) state.varData = new _StreamImplEvents(); - return state.varData; - } - - // Get the current subscription. - // If we are adding a stream, the subscription is moved into the state - // object to allow the state object to use the _varData field. - _ControllerSubscription get _subscription { - assert(hasListener); - if (_isAddingStream) { - _StreamControllerAddStreamState addState = _varData; - return addState.varData; - } - return _varData; - } - - /** - * Creates an error describing why an event cannot be added. - * - * The reason, and therefore the error message, depends on the current state. - */ - Error _badEventState() { - if (isClosed) { - return new StateError("Cannot add event after closing"); - } - assert(_isAddingStream); - return new StateError("Cannot add event while adding a stream"); - } - - // StreamSink interface. - Future addStream(Stream source, {bool cancelOnError: true}) { - if (!_mayAddEvent) throw _badEventState(); - if (_isCanceled) return new _Future.immediate(null); - _StreamControllerAddStreamState addState = - new _StreamControllerAddStreamState(this, - _varData, - source, - cancelOnError); - _varData = addState; - _state |= _STATE_ADDSTREAM; - return addState.addStreamFuture; - } - - /** - * Returns a future that is completed when the stream is done - * processing events. - * - * This happens either when the done event has been sent, or if the - * subscriber of a single-subscription stream is cancelled. - */ - Future get done => _ensureDoneFuture(); - - Future _ensureDoneFuture() { - if (_doneFuture == null) { - _doneFuture = _isCanceled ? Future._nullFuture : new _Future(); - } - return _doneFuture; - } - - /** - * Send or enqueue a data event. - */ - void add(T value) { - if (!_mayAddEvent) throw _badEventState(); - _add(value); - } - - /** - * Send or enqueue an error event. - */ - void addError(Object error, [StackTrace stackTrace]) { - error = _nonNullError(error); - if (!_mayAddEvent) throw _badEventState(); - AsyncError replacement = Zone.current.errorCallback(error, stackTrace); - if (replacement != null) { - error = _nonNullError(replacement.error); - stackTrace = replacement.stackTrace; - } - _addError(error, stackTrace); - } - - /** - * Closes this controller and sends a done event on the stream. - * - * The first time a controller is closed, a "done" event is added to its - * stream. - * - * You are allowed to close the controller more than once, but only the first - * call has any effect. - * - * After closing, no further events may be added using [add] or [addError]. - * - * The returned future is completed when the done event has been delivered. - */ - Future close() { - if (isClosed) { - return _ensureDoneFuture(); - } - if (!_mayAddEvent) throw _badEventState(); - _closeUnchecked(); - return _ensureDoneFuture(); - } - - void _closeUnchecked() { - _state |= _STATE_CLOSED; - if (hasListener) { - _sendDone(); - } else if (_isInitialState) { - _ensurePendingEvents().add(const _DelayedDone()); - } - } - - // EventSink interface. Used by the [addStream] events. - - // Add data event, used both by the [addStream] events and by [add]. - void _add(T value) { - if (hasListener) { - _sendData(value); - } else if (_isInitialState) { - _ensurePendingEvents().add(new _DelayedData(value)); - } - } - - void _addError(Object error, StackTrace stackTrace) { - if (hasListener) { - _sendError(error, stackTrace); - } else if (_isInitialState) { - _ensurePendingEvents().add(new _DelayedError(error, stackTrace)); - } - } - - void _close() { - // End of addStream stream. - assert(_isAddingStream); - _StreamControllerAddStreamState addState = _varData; - _varData = addState.varData; - _state &= ~_STATE_ADDSTREAM; - addState.complete(); - } - - // _StreamControllerLifeCycle interface - - StreamSubscription _subscribe( - void onData(T data), - Function onError, - void onDone(), - bool cancelOnError) { - if (!_isInitialState) { - throw new StateError("Stream has already been listened to."); - } - _ControllerSubscription subscription = - new _ControllerSubscription(this, onData, onError, onDone, - cancelOnError); - - _PendingEvents pendingEvents = _pendingEvents; - _state |= _STATE_SUBSCRIBED; - if (_isAddingStream) { - _StreamControllerAddStreamState addState = _varData; - addState.varData = subscription; - addState.resume(); - } else { - _varData = subscription; - } - subscription._setPendingEvents(pendingEvents); - subscription._guardCallback(() { - _runGuarded(_onListen); - }); - - return subscription; - } - - Future _recordCancel(StreamSubscription subscription) { - // When we cancel, we first cancel any stream being added, - // Then we call _onCancel, and finally the _doneFuture is completed. - // If either of addStream's cancel or _onCancel returns a future, - // we wait for it before continuing. - // Any error during this process ends up in the returned future. - // If more errors happen, we act as if it happens inside nested try/finallys - // or whenComplete calls, and only the last error ends up in the - // returned future. - Future result; - if (_isAddingStream) { - _StreamControllerAddStreamState addState = _varData; - result = addState.cancel(); - } - _varData = null; - _state = - (_state & ~(_STATE_SUBSCRIBED | _STATE_ADDSTREAM)) | _STATE_CANCELED; - - if (_onCancel != null) { - if (result == null) { - // Only introduce a future if one is needed. - // If _onCancel returns null, no future is needed. - try { - result = _onCancel(); - } catch (e, s) { - // Return the error in the returned future. - // Complete it asynchronously, so there is time for a listener - // to handle the error. - result = new _Future().._asyncCompleteError(e, s); - } - } else { - // Simpler case when we already know that we will return a future. - result = result.whenComplete(_onCancel); - } - } - - void complete() { - if (_doneFuture != null && _doneFuture._mayComplete) { - _doneFuture._asyncComplete(null); - } - } - - if (result != null) { - result = result.whenComplete(complete); - } else { - complete(); - } - - return result; - } - - void _recordPause(StreamSubscription subscription) { - if (_isAddingStream) { - _StreamControllerAddStreamState addState = _varData; - addState.pause(); - } - _runGuarded(_onPause); - } - - void _recordResume(StreamSubscription subscription) { - if (_isAddingStream) { - _StreamControllerAddStreamState addState = _varData; - addState.resume(); - } - _runGuarded(_onResume); - } -} - -abstract class _SyncStreamControllerDispatch - implements _StreamController { - void _sendData(T data) { - _subscription._add(data); - } - - void _sendError(Object error, StackTrace stackTrace) { - _subscription._addError(error, stackTrace); - } - - void _sendDone() { - _subscription._close(); - } -} - -abstract class _AsyncStreamControllerDispatch - implements _StreamController { - void _sendData(T data) { - _subscription._addPending(new _DelayedData(data)); - } - - void _sendError(Object error, StackTrace stackTrace) { - _subscription._addPending(new _DelayedError(error, stackTrace)); - } - - void _sendDone() { - _subscription._addPending(const _DelayedDone()); - } -} - -// TODO(lrn): Use common superclass for callback-controllers when VM supports -// constructors in mixin superclasses. - -class _AsyncStreamController extends _StreamController - with _AsyncStreamControllerDispatch { - final _NotificationHandler _onListen; - final _NotificationHandler _onPause; - final _NotificationHandler _onResume; - final _NotificationHandler _onCancel; - - _AsyncStreamController(void this._onListen(), - void this._onPause(), - void this._onResume(), - this._onCancel()); -} - -class _SyncStreamController extends _StreamController - with _SyncStreamControllerDispatch { - final _NotificationHandler _onListen; - final _NotificationHandler _onPause; - final _NotificationHandler _onResume; - final _NotificationHandler _onCancel; - - _SyncStreamController(void this._onListen(), - void this._onPause(), - void this._onResume(), - this._onCancel()); -} - -abstract class _NoCallbacks { - _NotificationHandler get _onListen => null; - _NotificationHandler get _onPause => null; - _NotificationHandler get _onResume => null; - _NotificationHandler get _onCancel => null; -} - -class _NoCallbackAsyncStreamController/**/ = _StreamController/**/ - with _AsyncStreamControllerDispatch/**/, _NoCallbacks; - -class _NoCallbackSyncStreamController/**/ = _StreamController/**/ - with _SyncStreamControllerDispatch/**/, _NoCallbacks; - -typedef _NotificationHandler(); - -Future _runGuarded(_NotificationHandler notificationHandler) { - if (notificationHandler == null) return null; - try { - var result = notificationHandler(); - if (result is Future) return result; - return null; - } catch (e, s) { - Zone.current.handleUncaughtError(e, s); - } -} - -class _ControllerStream extends _StreamImpl { - _StreamControllerLifecycle _controller; - - _ControllerStream(this._controller); - - StreamSubscription _createSubscription( - void onData(T data), - Function onError, - void onDone(), - bool cancelOnError) => - _controller._subscribe(onData, onError, onDone, cancelOnError); - - // Override == and hashCode so that new streams returned by the same - // controller are considered equal. The controller returns a new stream - // each time it's queried, but doesn't have to cache the result. - - int get hashCode => _controller.hashCode ^ 0x35323532; - - bool operator==(Object other) { - if (identical(this, other)) return true; - if (other is! _ControllerStream) return false; - _ControllerStream otherStream = other; - return identical(otherStream._controller, this._controller); - } -} - -class _ControllerSubscription extends _BufferingStreamSubscription { - final _StreamControllerLifecycle _controller; - - _ControllerSubscription(this._controller, void onData(T data), - Function onError, void onDone(), bool cancelOnError) - : super(onData, onError, onDone, cancelOnError); - - Future _onCancel() { - return _controller._recordCancel(this); - } - - void _onPause() { - _controller._recordPause(this); - } - - void _onResume() { - _controller._recordResume(this); - } -} - - -/** A class that exposes only the [StreamSink] interface of an object. */ -class _StreamSinkWrapper implements StreamSink { - final StreamController _target; - _StreamSinkWrapper(this._target); - void add(T data) { _target.add(data); } - void addError(Object error, [StackTrace stackTrace]) { - _target.addError(error, stackTrace); - } - Future close() => _target.close(); - Future addStream(Stream source, {bool cancelOnError: true}) => - _target.addStream(source, cancelOnError: cancelOnError); - Future get done => _target.done; -} - -/** - * Object containing the state used to handle [StreamController.addStream]. - */ -class _AddStreamState { - // [_Future] returned by call to addStream. - final _Future addStreamFuture; - - // Subscription on stream argument to addStream. - final StreamSubscription addSubscription; - - _AddStreamState(_EventSink controller, Stream source, bool cancelOnError) - : addStreamFuture = new _Future(), - addSubscription = source.listen(controller._add, - onError: cancelOnError - ? makeErrorHandler(controller) - : controller._addError, - onDone: controller._close, - cancelOnError: cancelOnError); - - static makeErrorHandler(_EventSink controller) => - (e, StackTrace s) { - controller._addError(e, s); - controller._close(); - }; - - void pause() { - addSubscription.pause(); - } - - void resume() { - addSubscription.resume(); - } - - /** - * Stop adding the stream. - * - * Complete the future returned by `StreamController.addStream` when - * the cancel is complete. - * - * Return a future if the cancel takes time, otherwise return `null`. - */ - Future cancel() { - var cancel = addSubscription.cancel(); - if (cancel == null) { - addStreamFuture._asyncComplete(null); - return null; - } - return cancel.whenComplete(() { addStreamFuture._asyncComplete(null); }); - } - - void complete() { - addStreamFuture._asyncComplete(null); - } -} - -class _StreamControllerAddStreamState extends _AddStreamState { - // The subscription or pending data of a _StreamController. - // Stored here because we reuse the `_varData` field in the _StreamController - // to store this state object. - var varData; - - _StreamControllerAddStreamState(_StreamController controller, - this.varData, - Stream source, - bool cancelOnError) - : super(controller, source, cancelOnError) { - if (controller.isPaused) { - addSubscription.pause(); - } - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/stream_impl.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/stream_impl.dart deleted file mode 100644 index dbf3f1b6398a..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/stream_impl.dart +++ /dev/null @@ -1,1082 +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. - -part of dart.async; - -/** Abstract and private interface for a place to put events. */ -abstract class _EventSink { - void _add(T data); - void _addError(Object error, StackTrace stackTrace); - void _close(); -} - -/** - * Abstract and private interface for a place to send events. - * - * Used by event buffering to finally dispatch the pending event, where - * [_EventSink] is where the event first enters the stream subscription, - * and may yet be buffered. - */ -abstract class _EventDispatch { - void _sendData(T data); - void _sendError(Object error, StackTrace stackTrace); - void _sendDone(); -} - -/** - * Default implementation of stream subscription of buffering events. - * - * The only public methods are those of [StreamSubscription], so instances of - * [_BufferingStreamSubscription] can be returned directly as a - * [StreamSubscription] without exposing internal functionality. - * - * The [StreamController] is a public facing version of [Stream] and this class, - * with some methods made public. - * - * The user interface of [_BufferingStreamSubscription] are the following - * methods: - * - * * [_add]: Add a data event to the stream. - * * [_addError]: Add an error event to the stream. - * * [_close]: Request to close the stream. - * * [_onCancel]: Called when the subscription will provide no more events, - * either due to being actively canceled, or after sending a done event. - * * [_onPause]: Called when the subscription wants the event source to pause. - * * [_onResume]: Called when allowing new events after a pause. - * - * The user should not add new events when the subscription requests a paused, - * but if it happens anyway, the subscription will enqueue the events just as - * when new events arrive while still firing an old event. - */ -class _BufferingStreamSubscription implements StreamSubscription, - _EventSink, - _EventDispatch { - /** The `cancelOnError` flag from the `listen` call. */ - static const int _STATE_CANCEL_ON_ERROR = 1; - /** - * Whether the "done" event has been received. - * No further events are accepted after this. - */ - static const int _STATE_CLOSED = 2; - /** - * Set if the input has been asked not to send events. - * - * This is not the same as being paused, since the input will remain paused - * after a call to [resume] if there are pending events. - */ - static const int _STATE_INPUT_PAUSED = 4; - /** - * Whether the subscription has been canceled. - * - * Set by calling [cancel], or by handling a "done" event, or an "error" event - * when `cancelOnError` is true. - */ - static const int _STATE_CANCELED = 8; - /** - * Set when either: - * - * * an error is sent, and [cancelOnError] is true, or - * * a done event is sent. - * - * If the subscription is canceled while _STATE_WAIT_FOR_CANCEL is set, the - * state is unset, and no furher events must be delivered. - */ - static const int _STATE_WAIT_FOR_CANCEL = 16; - static const int _STATE_IN_CALLBACK = 32; - static const int _STATE_HAS_PENDING = 64; - static const int _STATE_PAUSE_COUNT = 128; - static const int _STATE_PAUSE_COUNT_SHIFT = 7; - - /* Event handlers provided in constructor. */ - _DataHandler _onData; - Function _onError; - _DoneHandler _onDone; - final Zone _zone = Zone.current; - - /** Bit vector based on state-constants above. */ - int _state; - - // TODO(floitsch): reuse another field - /** The future [_onCancel] may return. */ - Future _cancelFuture; - - /** - * Queue of pending events. - * - * Is created when necessary, or set in constructor for preconfigured events. - */ - _PendingEvents _pending; - - _BufferingStreamSubscription(void onData(T data), - Function onError, - void onDone(), - bool cancelOnError) - : _state = (cancelOnError ? _STATE_CANCEL_ON_ERROR : 0) { - this.onData(onData); - this.onError(onError); - this.onDone(onDone); - } - - /** - * Sets the subscription's pending events object. - * - * This can only be done once. The pending events object is used for the - * rest of the subscription's life cycle. - */ - void _setPendingEvents(_PendingEvents pendingEvents) { - assert(_pending == null); - if (pendingEvents == null) return; - _pending = pendingEvents; - if (!pendingEvents.isEmpty) { - _state |= _STATE_HAS_PENDING; - _pending.schedule(this); - } - } - - /** - * Extracts the pending events from a canceled stream. - * - * This can only be done during the [_onCancel] method call. After that, - * any remaining pending events will be cleared. - */ - _PendingEvents _extractPending() { - assert(_isCanceled); - _PendingEvents events = _pending; - _pending = null; - return events; - } - - // StreamSubscription interface. - - void onData(void handleData(T event)) { - if (handleData == null) handleData = _nullDataHandler; - _onData = _zone.registerUnaryCallback(handleData); - } - - void onError(Function handleError) { - if (handleError == null) handleError = _nullErrorHandler; - _onError = _registerErrorHandler(handleError, _zone); - } - - void onDone(void handleDone()) { - if (handleDone == null) handleDone = _nullDoneHandler; - _onDone = _zone.registerCallback(handleDone); - } - - void pause([Future resumeSignal]) { - if (_isCanceled) return; - bool wasPaused = _isPaused; - bool wasInputPaused = _isInputPaused; - // Increment pause count and mark input paused (if it isn't already). - _state = (_state + _STATE_PAUSE_COUNT) | _STATE_INPUT_PAUSED; - if (resumeSignal != null) resumeSignal.whenComplete(resume); - if (!wasPaused && _pending != null) _pending.cancelSchedule(); - if (!wasInputPaused && !_inCallback) _guardCallback(_onPause); - } - - void resume() { - if (_isCanceled) return; - if (_isPaused) { - _decrementPauseCount(); - if (!_isPaused) { - if (_hasPending && !_pending.isEmpty) { - // Input is still paused. - _pending.schedule(this); - } else { - assert(_mayResumeInput); - _state &= ~_STATE_INPUT_PAUSED; - if (!_inCallback) _guardCallback(_onResume); - } - } - } - } - - Future cancel() { - // The user doesn't want to receive any further events. If there is an - // error or done event pending (waiting for the cancel to be done) discard - // that event. - _state &= ~_STATE_WAIT_FOR_CANCEL; - if (_isCanceled) return _cancelFuture; - _cancel(); - return _cancelFuture; - } - - Future asFuture([var futureValue]) { - _Future result = new _Future(); - - // Overwrite the onDone and onError handlers. - _onDone = () { result._complete(futureValue); }; - _onError = (error, stackTrace) { - cancel(); - result._completeError(error, stackTrace); - }; - - return result; - } - - // State management. - - bool get _isInputPaused => (_state & _STATE_INPUT_PAUSED) != 0; - bool get _isClosed => (_state & _STATE_CLOSED) != 0; - bool get _isCanceled => (_state & _STATE_CANCELED) != 0; - bool get _waitsForCancel => (_state & _STATE_WAIT_FOR_CANCEL) != 0; - bool get _inCallback => (_state & _STATE_IN_CALLBACK) != 0; - bool get _hasPending => (_state & _STATE_HAS_PENDING) != 0; - bool get _isPaused => _state >= _STATE_PAUSE_COUNT; - bool get _canFire => _state < _STATE_IN_CALLBACK; - bool get _mayResumeInput => - !_isPaused && (_pending == null || _pending.isEmpty); - bool get _cancelOnError => (_state & _STATE_CANCEL_ON_ERROR) != 0; - - bool get isPaused => _isPaused; - - void _cancel() { - _state |= _STATE_CANCELED; - if (_hasPending) { - _pending.cancelSchedule(); - } - if (!_inCallback) _pending = null; - _cancelFuture = _onCancel(); - } - - /** - * Increment the pause count. - * - * Also marks input as paused. - */ - void _incrementPauseCount() { - _state = (_state + _STATE_PAUSE_COUNT) | _STATE_INPUT_PAUSED; - } - - /** - * Decrements the pause count. - * - * Does not automatically unpause the input (call [_onResume]) when - * the pause count reaches zero. This is handled elsewhere, and only - * if there are no pending events buffered. - */ - void _decrementPauseCount() { - assert(_isPaused); - _state -= _STATE_PAUSE_COUNT; - } - - // _EventSink interface. - - void _add(T data) { - assert(!_isClosed); - if (_isCanceled) return; - if (_canFire) { - _sendData(data); - } else { - _addPending(new _DelayedData(data)); - } - } - - void _addError(Object error, StackTrace stackTrace) { - if (_isCanceled) return; - if (_canFire) { - _sendError(error, stackTrace); // Reports cancel after sending. - } else { - _addPending(new _DelayedError(error, stackTrace)); - } - } - - void _close() { - assert(!_isClosed); - if (_isCanceled) return; - _state |= _STATE_CLOSED; - if (_canFire) { - _sendDone(); - } else { - _addPending(const _DelayedDone()); - } - } - - // Hooks called when the input is paused, unpaused or canceled. - // These must not throw. If overwritten to call user code, include suitable - // try/catch wrapping and send any errors to - // [_Zone.current.handleUncaughtError]. - void _onPause() { - assert(_isInputPaused); - } - - void _onResume() { - assert(!_isInputPaused); - } - - Future _onCancel() { - assert(_isCanceled); - return null; - } - - // Handle pending events. - - /** - * Add a pending event. - * - * If the subscription is not paused, this also schedules a firing - * of pending events later (if necessary). - */ - void _addPending(_DelayedEvent event) { - _StreamImplEvents pending = _pending; - if (_pending == null) pending = _pending = new _StreamImplEvents(); - pending.add(event); - if (!_hasPending) { - _state |= _STATE_HAS_PENDING; - if (!_isPaused) { - _pending.schedule(this); - } - } - } - - /* _EventDispatch interface. */ - - void _sendData(T data) { - assert(!_isCanceled); - assert(!_isPaused); - assert(!_inCallback); - bool wasInputPaused = _isInputPaused; - _state |= _STATE_IN_CALLBACK; - _zone.runUnaryGuarded(_onData, data); - _state &= ~_STATE_IN_CALLBACK; - _checkState(wasInputPaused); - } - - void _sendError(Object error, StackTrace stackTrace) { - assert(!_isCanceled); - assert(!_isPaused); - assert(!_inCallback); - bool wasInputPaused = _isInputPaused; - - void sendError() { - // If the subscription has been canceled while waiting for the cancel - // future to finish we must not report the error. - if (_isCanceled && !_waitsForCancel) return; - _state |= _STATE_IN_CALLBACK; - if (_onError is ZoneBinaryCallback) { - _zone.runBinaryGuarded(_onError, error, stackTrace); - } else { - _zone.runUnaryGuarded(_onError, error); - } - _state &= ~_STATE_IN_CALLBACK; - } - - if (_cancelOnError) { - _state |= _STATE_WAIT_FOR_CANCEL; - _cancel(); - if (_cancelFuture is Future) { - _cancelFuture.whenComplete(sendError); - } else { - sendError(); - } - } else { - sendError(); - // Only check state if not cancelOnError. - _checkState(wasInputPaused); - } - } - - void _sendDone() { - assert(!_isCanceled); - assert(!_isPaused); - assert(!_inCallback); - - void sendDone() { - // If the subscription has been canceled while waiting for the cancel - // future to finish we must not report the done event. - if (!_waitsForCancel) return; - _state |= (_STATE_CANCELED | _STATE_CLOSED | _STATE_IN_CALLBACK); - _zone.runGuarded(_onDone); - _state &= ~_STATE_IN_CALLBACK; - } - - _cancel(); - _state |= _STATE_WAIT_FOR_CANCEL; - if (_cancelFuture is Future) { - _cancelFuture.whenComplete(sendDone); - } else { - sendDone(); - } - } - - /** - * Call a hook function. - * - * The call is properly wrapped in code to avoid other callbacks - * during the call, and it checks for state changes after the call - * that should cause further callbacks. - */ - void _guardCallback(callback) { - assert(!_inCallback); - bool wasInputPaused = _isInputPaused; - _state |= _STATE_IN_CALLBACK; - callback(); - _state &= ~_STATE_IN_CALLBACK; - _checkState(wasInputPaused); - } - - /** - * Check if the input needs to be informed of state changes. - * - * State changes are pausing, resuming and canceling. - * - * After canceling, no further callbacks will happen. - * - * The cancel callback is called after a user cancel, or after - * the final done event is sent. - */ - void _checkState(bool wasInputPaused) { - assert(!_inCallback); - if (_hasPending && _pending.isEmpty) { - _state &= ~_STATE_HAS_PENDING; - if (_isInputPaused && _mayResumeInput) { - _state &= ~_STATE_INPUT_PAUSED; - } - } - // If the state changes during a callback, we immediately - // make a new state-change callback. Loop until the state didn't change. - while (true) { - if (_isCanceled) { - _pending = null; - return; - } - bool isInputPaused = _isInputPaused; - if (wasInputPaused == isInputPaused) break; - _state ^= _STATE_IN_CALLBACK; - if (isInputPaused) { - _onPause(); - } else { - _onResume(); - } - _state &= ~_STATE_IN_CALLBACK; - wasInputPaused = isInputPaused; - } - if (_hasPending && !_isPaused) { - _pending.schedule(this); - } - } -} - -// ------------------------------------------------------------------- -// Common base class for single and multi-subscription streams. -// ------------------------------------------------------------------- -abstract class _StreamImpl extends Stream { - // ------------------------------------------------------------------ - // Stream interface. - - StreamSubscription listen(void onData(T data), - { Function onError, - void onDone(), - bool cancelOnError }) { - cancelOnError = identical(true, cancelOnError); - StreamSubscription subscription = - _createSubscription(onData, onError, onDone, cancelOnError); - _onListen(subscription); - return subscription; - } - - // ------------------------------------------------------------------- - /** Create a subscription object. Called by [subcribe]. */ - StreamSubscription _createSubscription( - void onData(T data), - Function onError, - void onDone(), - bool cancelOnError) { - return new _BufferingStreamSubscription(onData, onError, onDone, - cancelOnError); - } - - /** Hook called when the subscription has been created. */ - void _onListen(StreamSubscription subscription) {} -} - -typedef _PendingEvents _EventGenerator(); - -/** Stream that generates its own events. */ -class _GeneratedStreamImpl extends _StreamImpl { - final _EventGenerator _pending; - bool _isUsed = false; - /** - * Initializes the stream to have only the events provided by a - * [_PendingEvents]. - * - * A new [_PendingEvents] must be generated for each listen. - */ - _GeneratedStreamImpl(this._pending); - - StreamSubscription _createSubscription( - void onData(T data), - Function onError, - void onDone(), - bool cancelOnError) { - if (_isUsed) throw new StateError("Stream has already been listened to."); - _isUsed = true; - return new _BufferingStreamSubscription( - onData, onError, onDone, cancelOnError).._setPendingEvents(_pending()); - } -} - - -/** Pending events object that gets its events from an [Iterable]. */ -class _IterablePendingEvents extends _PendingEvents { - // The iterator providing data for data events. - // Set to null when iteration has completed. - Iterator _iterator; - - _IterablePendingEvents(Iterable data) : _iterator = data.iterator; - - bool get isEmpty => _iterator == null; - - void handleNext(_EventDispatch dispatch) { - if (_iterator == null) { - throw new StateError("No events pending."); - } - // Send one event per call to moveNext. - // If moveNext returns true, send the current element as data. - // If moveNext returns false, send a done event and clear the _iterator. - // If moveNext throws an error, send an error and clear the _iterator. - // After an error, no further events will be sent. - bool isDone; - try { - isDone = !_iterator.moveNext(); - } catch (e, s) { - _iterator = null; - dispatch._sendError(e, s); - return; - } - if (!isDone) { - dispatch._sendData(_iterator.current); - } else { - _iterator = null; - dispatch._sendDone(); - } - } - - void clear() { - if (isScheduled) cancelSchedule(); - _iterator = null; - } -} - - -// Internal helpers. - -// Types of the different handlers on a stream. Types used to type fields. -typedef void _DataHandler(T value); -typedef void _DoneHandler(); - - -/** Default data handler, does nothing. */ -void _nullDataHandler(var value) {} - -/** Default error handler, reports the error to the current zone's handler. */ -void _nullErrorHandler(error, [StackTrace stackTrace]) { - Zone.current.handleUncaughtError(error, stackTrace); -} - -/** Default done handler, does nothing. */ -void _nullDoneHandler() {} - - -/** A delayed event on a buffering stream subscription. */ -abstract class _DelayedEvent { - /** Added as a linked list on the [StreamController]. */ - _DelayedEvent next; - /** Execute the delayed event on the [StreamController]. */ - void perform(_EventDispatch dispatch); -} - -/** A delayed data event. */ -class _DelayedData extends _DelayedEvent { - final T value; - _DelayedData(this.value); - void perform(_EventDispatch dispatch) { - dispatch._sendData(value); - } -} - -/** A delayed error event. */ -class _DelayedError extends _DelayedEvent { - final error; - final StackTrace stackTrace; - - _DelayedError(this.error, this.stackTrace); - void perform(_EventDispatch dispatch) { - dispatch._sendError(error, stackTrace); - } -} - -/** A delayed done event. */ -class _DelayedDone implements _DelayedEvent { - const _DelayedDone(); - void perform(_EventDispatch dispatch) { - dispatch._sendDone(); - } - - _DelayedEvent get next => null; - - void set next(_DelayedEvent _) { - throw new StateError("No events after a done."); - } -} - -/** Superclass for provider of pending events. */ -abstract class _PendingEvents { - // No async event has been scheduled. - static const int _STATE_UNSCHEDULED = 0; - // An async event has been scheduled to run a function. - static const int _STATE_SCHEDULED = 1; - // An async event has been scheduled, but it will do nothing when it runs. - // Async events can't be preempted. - static const int _STATE_CANCELED = 3; - - /** - * State of being scheduled. - * - * Set to [_STATE_SCHEDULED] when pending events are scheduled for - * async dispatch. Since we can't cancel a [scheduleMicrotask] call, if - * scheduling is "canceled", the _state is simply set to [_STATE_CANCELED] - * which will make the async code do nothing except resetting [_state]. - * - * If events are scheduled while the state is [_STATE_CANCELED], it is - * merely switched back to [_STATE_SCHEDULED], but no new call to - * [scheduleMicrotask] is performed. - */ - int _state = _STATE_UNSCHEDULED; - - bool get isEmpty; - - bool get isScheduled => _state == _STATE_SCHEDULED; - bool get _eventScheduled => _state >= _STATE_SCHEDULED; - - /** - * Schedule an event to run later. - * - * If called more than once, it should be called with the same dispatch as - * argument each time. It may reuse an earlier argument in some cases. - */ - void schedule(_EventDispatch dispatch) { - if (isScheduled) return; - assert(!isEmpty); - if (_eventScheduled) { - assert(_state == _STATE_CANCELED); - _state = _STATE_SCHEDULED; - return; - } - scheduleMicrotask(() { - int oldState = _state; - _state = _STATE_UNSCHEDULED; - if (oldState == _STATE_CANCELED) return; - handleNext(dispatch); - }); - _state = _STATE_SCHEDULED; - } - - void cancelSchedule() { - if (isScheduled) _state = _STATE_CANCELED; - } - - void handleNext(_EventDispatch dispatch); - - /** Throw away any pending events and cancel scheduled events. */ - void clear(); -} - - -/** Class holding pending events for a [_StreamImpl]. */ -class _StreamImplEvents extends _PendingEvents { - /// Single linked list of [_DelayedEvent] objects. - _DelayedEvent firstPendingEvent = null; - /// Last element in the list of pending events. New events are added after it. - _DelayedEvent lastPendingEvent = null; - - bool get isEmpty => lastPendingEvent == null; - - void add(_DelayedEvent event) { - if (lastPendingEvent == null) { - firstPendingEvent = lastPendingEvent = event; - } else { - lastPendingEvent = lastPendingEvent.next = event; - } - } - - void handleNext(_EventDispatch dispatch) { - assert(!isScheduled); - _DelayedEvent event = firstPendingEvent; - firstPendingEvent = event.next; - if (firstPendingEvent == null) { - lastPendingEvent = null; - } - event.perform(dispatch); - } - - void clear() { - if (isScheduled) cancelSchedule(); - firstPendingEvent = lastPendingEvent = null; - } -} - -class _BroadcastLinkedList { - _BroadcastLinkedList _next; - _BroadcastLinkedList _previous; - - void _unlink() { - _previous._next = _next; - _next._previous = _previous; - _next = _previous = this; - } - - void _insertBefore(_BroadcastLinkedList newNext) { - _BroadcastLinkedList newPrevious = newNext._previous; - newPrevious._next = this; - newNext._previous = _previous; - _previous._next = newNext; - _previous = newPrevious; - } -} - -typedef void _broadcastCallback(StreamSubscription subscription); - -/** - * Done subscription that will send one done event as soon as possible. - */ -class _DoneStreamSubscription implements StreamSubscription { - static const int _DONE_SENT = 1; - static const int _SCHEDULED = 2; - static const int _PAUSED = 4; - - final Zone _zone; - int _state = 0; - _DoneHandler _onDone; - - _DoneStreamSubscription(this._onDone) : _zone = Zone.current { - _schedule(); - } - - bool get _isSent => (_state & _DONE_SENT) != 0; - bool get _isScheduled => (_state & _SCHEDULED) != 0; - bool get isPaused => _state >= _PAUSED; - - void _schedule() { - if (_isScheduled) return; - _zone.scheduleMicrotask(_sendDone); - _state |= _SCHEDULED; - } - - void onData(void handleData(T data)) {} - void onError(Function handleError) {} - void onDone(void handleDone()) { _onDone = handleDone; } - - void pause([Future resumeSignal]) { - _state += _PAUSED; - if (resumeSignal != null) resumeSignal.whenComplete(resume); - } - - void resume() { - if (isPaused) { - _state -= _PAUSED; - if (!isPaused && !_isSent) { - _schedule(); - } - } - } - - Future cancel() => null; - - Future asFuture([futureValue]) { - _Future result = new _Future(); - _onDone = () { result._completeWithValue(null); }; - return result; - } - - void _sendDone() { - _state &= ~_SCHEDULED; - if (isPaused) return; - _state |= _DONE_SENT; - if (_onDone != null) _zone.runGuarded(_onDone); - } -} - -class _AsBroadcastStream extends Stream { - final Stream _source; - final _broadcastCallback _onListenHandler; - final _broadcastCallback _onCancelHandler; - final Zone _zone; - - _AsBroadcastStreamController _controller; - StreamSubscription _subscription; - - _AsBroadcastStream(this._source, - void onListenHandler(StreamSubscription subscription), - void onCancelHandler(StreamSubscription subscription)) - : _onListenHandler = Zone.current.registerUnaryCallback(onListenHandler), - _onCancelHandler = Zone.current.registerUnaryCallback(onCancelHandler), - _zone = Zone.current { - _controller = new _AsBroadcastStreamController(_onListen, _onCancel); - } - - bool get isBroadcast => true; - - StreamSubscription listen(void onData(T data), - { Function onError, - void onDone(), - bool cancelOnError}) { - if (_controller == null || _controller.isClosed) { - // Return a dummy subscription backed by nothing, since - // it will only ever send one done event. - return new _DoneStreamSubscription(onDone); - } - if (_subscription == null) { - _subscription = _source.listen(_controller.add, - onError: _controller.addError, - onDone: _controller.close); - } - cancelOnError = identical(true, cancelOnError); - return _controller._subscribe(onData, onError, onDone, cancelOnError); - } - - void _onCancel() { - bool shutdown = (_controller == null) || _controller.isClosed; - if (_onCancelHandler != null) { - _zone.runUnary(_onCancelHandler, new _BroadcastSubscriptionWrapper(this)); - } - if (shutdown) { - if (_subscription != null) { - _subscription.cancel(); - _subscription = null; - } - } - } - - void _onListen() { - if (_onListenHandler != null) { - _zone.runUnary(_onListenHandler, new _BroadcastSubscriptionWrapper(this)); - } - } - - // Methods called from _BroadcastSubscriptionWrapper. - void _cancelSubscription() { - if (_subscription == null) return; - // Called by [_controller] when it has no subscribers left. - StreamSubscription subscription = _subscription; - _subscription = null; - _controller = null; // Marks the stream as no longer listenable. - subscription.cancel(); - } - - void _pauseSubscription(Future resumeSignal) { - if (_subscription == null) return; - _subscription.pause(resumeSignal); - } - - void _resumeSubscription() { - if (_subscription == null) return; - _subscription.resume(); - } - - bool get _isSubscriptionPaused { - if (_subscription == null) return false; - return _subscription.isPaused; - } -} - -/** - * Wrapper for subscription that disallows changing handlers. - */ -class _BroadcastSubscriptionWrapper implements StreamSubscription { - final _AsBroadcastStream _stream; - - _BroadcastSubscriptionWrapper(this._stream); - - void onData(void handleData(T data)) { - throw new UnsupportedError( - "Cannot change handlers of asBroadcastStream source subscription."); - } - - void onError(Function handleError) { - throw new UnsupportedError( - "Cannot change handlers of asBroadcastStream source subscription."); - } - - void onDone(void handleDone()) { - throw new UnsupportedError( - "Cannot change handlers of asBroadcastStream source subscription."); - } - - void pause([Future resumeSignal]) { - _stream._pauseSubscription(resumeSignal); - } - - void resume() { - _stream._resumeSubscription(); - } - - Future cancel() { - _stream._cancelSubscription(); - return null; - } - - bool get isPaused { - return _stream._isSubscriptionPaused; - } - - Future asFuture([var futureValue]) { - throw new UnsupportedError( - "Cannot change handlers of asBroadcastStream source subscription."); - } -} - - -/** - * Simple implementation of [StreamIterator]. - */ -class _StreamIteratorImpl implements StreamIterator { - // Internal state of the stream iterator. - // At any time, it is in one of these states. - // The interpretation of the [_futureOrPrefecth] field depends on the state. - // In _STATE_MOVING, the _data field holds the most recently returned - // future. - // When in one of the _STATE_EXTRA_* states, the it may hold the - // next data/error object, and the subscription is paused. - - /// The simple state where [_data] holds the data to return, and [moveNext] - /// is allowed. The subscription is actively listening. - static const int _STATE_FOUND = 0; - /// State set after [moveNext] has returned false or an error, - /// or after calling [cancel]. The subscription is always canceled. - static const int _STATE_DONE = 1; - /// State set after calling [moveNext], but before its returned future has - /// completed. Calling [moveNext] again is not allowed in this state. - /// The subscription is actively listening. - static const int _STATE_MOVING = 2; - /// States set when another event occurs while in _STATE_FOUND. - /// This extra overflow event is cached until the next call to [moveNext], - /// which will complete as if it received the event normally. - /// The subscription is paused in these states, so we only ever get one - /// event too many. - static const int _STATE_EXTRA_DATA = 3; - static const int _STATE_EXTRA_ERROR = 4; - static const int _STATE_EXTRA_DONE = 5; - - /// Subscription being listened to. - StreamSubscription _subscription; - - /// The current element represented by the most recent call to moveNext. - /// - /// Is null between the time moveNext is called and its future completes. - T _current = null; - - /// The future returned by the most recent call to [moveNext]. - /// - /// Also used to store the next value/error in case the stream provides an - /// event before [moveNext] is called again. In that case, the stream will - /// be paused to prevent further events. - var _futureOrPrefetch = null; - - /// The current state. - int _state = _STATE_FOUND; - - _StreamIteratorImpl(final Stream stream) { - _subscription = stream.listen(_onData, - onError: _onError, - onDone: _onDone, - cancelOnError: true); - } - - T get current => _current; - - Future moveNext() { - if (_state == _STATE_DONE) { - return new _Future.immediate(false); - } - if (_state == _STATE_MOVING) { - throw new StateError("Already waiting for next."); - } - if (_state == _STATE_FOUND) { - _state = _STATE_MOVING; - _current = null; - _futureOrPrefetch = new _Future(); - return _futureOrPrefetch; - } else { - assert(_state >= _STATE_EXTRA_DATA); - switch (_state) { - case _STATE_EXTRA_DATA: - _state = _STATE_FOUND; - _current = _futureOrPrefetch; - _futureOrPrefetch = null; - _subscription.resume(); - return new _Future.immediate(true); - case _STATE_EXTRA_ERROR: - AsyncError prefetch = _futureOrPrefetch; - _clear(); - return new _Future.immediateError(prefetch.error, - prefetch.stackTrace); - case _STATE_EXTRA_DONE: - _clear(); - return new _Future.immediate(false); - } - } - } - - /** Clears up the internal state when the iterator ends. */ - void _clear() { - _subscription = null; - _futureOrPrefetch = null; - _current = null; - _state = _STATE_DONE; - } - - Future cancel() { - StreamSubscription subscription = _subscription; - if (_state == _STATE_MOVING) { - _Future hasNext = _futureOrPrefetch; - _clear(); - hasNext._complete(false); - } else { - _clear(); - } - return subscription.cancel(); - } - - void _onData(T data) { - if (_state == _STATE_MOVING) { - _current = data; - _Future hasNext = _futureOrPrefetch; - _futureOrPrefetch = null; - _state = _STATE_FOUND; - hasNext._complete(true); - return; - } - _subscription.pause(); - assert(_futureOrPrefetch == null); - _futureOrPrefetch = data; - _state = _STATE_EXTRA_DATA; - } - - void _onError(Object error, [StackTrace stackTrace]) { - if (_state == _STATE_MOVING) { - _Future hasNext = _futureOrPrefetch; - // We have cancelOnError: true, so the subscription is canceled. - _clear(); - hasNext._completeError(error, stackTrace); - return; - } - _subscription.pause(); - assert(_futureOrPrefetch == null); - _futureOrPrefetch = new AsyncError(error, stackTrace); - _state = _STATE_EXTRA_ERROR; - } - - void _onDone() { - if (_state == _STATE_MOVING) { - _Future hasNext = _futureOrPrefetch; - _clear(); - hasNext._complete(false); - return; - } - _subscription.pause(); - _futureOrPrefetch = null; - _state = _STATE_EXTRA_DONE; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/stream_pipe.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/stream_pipe.dart deleted file mode 100644 index 3683719062d3..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/stream_pipe.dart +++ /dev/null @@ -1,438 +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. - -part of dart.async; - -/** Runs user code and takes actions depending on success or failure. */ -_runUserCode(userCode(), - onSuccess(value), - onError(error, StackTrace stackTrace)) { - try { - onSuccess(userCode()); - } catch (e, s) { - AsyncError replacement = Zone.current.errorCallback(e, s); - if (replacement == null) { - onError(e, s); - } else { - var error = _nonNullError(replacement.error); - var stackTrace = replacement.stackTrace; - onError(error, stackTrace); - } - } -} - -/** Helper function to cancel a subscription and wait for the potential future, - before completing with an error. */ -void _cancelAndError(StreamSubscription subscription, - _Future future, - error, - StackTrace stackTrace) { - var cancelFuture = subscription.cancel(); - if (cancelFuture is Future) { - cancelFuture.whenComplete(() => future._completeError(error, stackTrace)); - } else { - future._completeError(error, stackTrace); - } -} - -void _cancelAndErrorWithReplacement(StreamSubscription subscription, - _Future future, - error, StackTrace stackTrace) { - AsyncError replacement = Zone.current.errorCallback(error, stackTrace); - if (replacement != null) { - error = _nonNullError(replacement.error); - stackTrace = replacement.stackTrace; - } - _cancelAndError(subscription, future, error, stackTrace); -} - -/** Helper function to make an onError argument to [_runUserCode]. */ -_cancelAndErrorClosure(StreamSubscription subscription, _Future future) => - ((error, StackTrace stackTrace) => _cancelAndError( - subscription, future, error, stackTrace)); - -/** Helper function to cancel a subscription and wait for the potential future, - before completing with a value. */ -void _cancelAndValue(StreamSubscription subscription, _Future future, value) { - var cancelFuture = subscription.cancel(); - if (cancelFuture is Future) { - cancelFuture.whenComplete(() => future._complete(value)); - } else { - future._complete(value); - } -} - - -/** - * A [Stream] that forwards subscriptions to another stream. - * - * This stream implements [Stream], but forwards all subscriptions - * to an underlying stream, and wraps the returned subscription to - * modify the events on the way. - * - * This class is intended for internal use only. - */ -abstract class _ForwardingStream extends Stream { - final Stream _source; - - _ForwardingStream(this._source); - - bool get isBroadcast => _source.isBroadcast; - - StreamSubscription listen(void onData(T value), - { Function onError, - void onDone(), - bool cancelOnError }) { - cancelOnError = identical(true, cancelOnError); - return _createSubscription(onData, onError, onDone, cancelOnError); - } - - StreamSubscription _createSubscription( - void onData(T data), - Function onError, - void onDone(), - bool cancelOnError) { - return new _ForwardingStreamSubscription( - this, onData, onError, onDone, cancelOnError); - } - - // Override the following methods in subclasses to change the behavior. - - void _handleData(S data, _EventSink sink) { - dynamic outputData = data; - sink._add(outputData); - } - - void _handleError(error, StackTrace stackTrace, _EventSink sink) { - sink._addError(error, stackTrace); - } - - void _handleDone(_EventSink sink) { - sink._close(); - } -} - -/** - * Abstract superclass for subscriptions that forward to other subscriptions. - */ -class _ForwardingStreamSubscription - extends _BufferingStreamSubscription { - final _ForwardingStream _stream; - - StreamSubscription _subscription; - - _ForwardingStreamSubscription(this._stream, void onData(T data), - Function onError, void onDone(), - bool cancelOnError) - : super(onData, onError, onDone, cancelOnError) { - _subscription = _stream._source.listen(_handleData, - onError: _handleError, - onDone: _handleDone); - } - - // _StreamSink interface. - // Transformers sending more than one event have no way to know if the stream - // is canceled or closed after the first, so we just ignore remaining events. - - void _add(T data) { - if (_isClosed) return; - super._add(data); - } - - void _addError(Object error, StackTrace stackTrace) { - if (_isClosed) return; - super._addError(error, stackTrace); - } - - // StreamSubscription callbacks. - - void _onPause() { - if (_subscription == null) return; - _subscription.pause(); - } - - void _onResume() { - if (_subscription == null) return; - _subscription.resume(); - } - - Future _onCancel() { - if (_subscription != null) { - StreamSubscription subscription = _subscription; - _subscription = null; - subscription.cancel(); - } - return null; - } - - // Methods used as listener on source subscription. - - void _handleData(S data) { - _stream._handleData(data, this); - } - - void _handleError(error, StackTrace stackTrace) { - _stream._handleError(error, stackTrace, this); - } - - void _handleDone() { - _stream._handleDone(this); - } -} - -// ------------------------------------------------------------------- -// Stream transformers used by the default Stream implementation. -// ------------------------------------------------------------------- - -typedef bool _Predicate(T value); - -void _addErrorWithReplacement(_EventSink sink, error, stackTrace) { - AsyncError replacement = Zone.current.errorCallback(error, stackTrace); - if (replacement != null) { - error = _nonNullError(replacement.error); - stackTrace = replacement.stackTrace; - } - sink._addError(error, stackTrace); -} - - -class _WhereStream extends _ForwardingStream { - final _Predicate _test; - - _WhereStream(Stream source, bool test(T value)) - : _test = test, super(source); - - void _handleData(T inputEvent, _EventSink sink) { - bool satisfies; - try { - satisfies = _test(inputEvent); - } catch (e, s) { - _addErrorWithReplacement(sink, e, s); - return; - } - if (satisfies) { - sink._add(inputEvent); - } - } -} - - -typedef T _Transformation(S value); - -/** - * A stream pipe that converts data events before passing them on. - */ -class _MapStream extends _ForwardingStream { - final _Transformation _transform; - - _MapStream(Stream source, T transform(S event)) - : this._transform = transform, super(source); - - void _handleData(S inputEvent, _EventSink sink) { - T outputEvent; - try { - outputEvent = _transform(inputEvent); - } catch (e, s) { - _addErrorWithReplacement(sink, e, s); - return; - } - sink._add(outputEvent); - } -} - -/** - * A stream pipe that converts data events before passing them on. - */ -class _ExpandStream extends _ForwardingStream { - final _Transformation> _expand; - - _ExpandStream(Stream source, Iterable expand(S event)) - : this._expand = expand, super(source); - - void _handleData(S inputEvent, _EventSink sink) { - try { - for (T value in _expand(inputEvent)) { - sink._add(value); - } - } catch (e, s) { - // If either _expand or iterating the generated iterator throws, - // we abort the iteration. - _addErrorWithReplacement(sink, e, s); - } - } -} - - -typedef bool _ErrorTest(error); - -/** - * A stream pipe that converts or disposes error events - * before passing them on. - */ -class _HandleErrorStream extends _ForwardingStream { - final Function _transform; - final _ErrorTest _test; - - _HandleErrorStream(Stream source, - Function onError, - bool test(error)) - : this._transform = onError, this._test = test, super(source); - - void _handleError(Object error, StackTrace stackTrace, _EventSink sink) { - bool matches = true; - if (_test != null) { - try { - matches = _test(error); - } catch (e, s) { - _addErrorWithReplacement(sink, e, s); - return; - } - } - if (matches) { - try { - _invokeErrorHandler(_transform, error, stackTrace); - } catch (e, s) { - if (identical(e, error)) { - sink._addError(error, stackTrace); - } else { - _addErrorWithReplacement(sink, e, s); - } - return; - } - } else { - sink._addError(error, stackTrace); - } - } -} - - -class _TakeStream extends _ForwardingStream { - int _remaining; - - _TakeStream(Stream source, int count) - : this._remaining = count, super(source) { - // This test is done early to avoid handling an async error - // in the _handleData method. - if (count is! int) throw new ArgumentError(count); - } - - void _handleData(T inputEvent, _EventSink sink) { - if (_remaining > 0) { - sink._add(inputEvent); - _remaining -= 1; - if (_remaining == 0) { - // Closing also unsubscribes all subscribers, which unsubscribes - // this from source. - sink._close(); - } - } - } -} - - -class _TakeWhileStream extends _ForwardingStream { - final _Predicate _test; - - _TakeWhileStream(Stream source, bool test(T value)) - : this._test = test, super(source); - - void _handleData(T inputEvent, _EventSink sink) { - bool satisfies; - try { - satisfies = _test(inputEvent); - } catch (e, s) { - _addErrorWithReplacement(sink, e, s); - // The test didn't say true. Didn't say false either, but we stop anyway. - sink._close(); - return; - } - if (satisfies) { - sink._add(inputEvent); - } else { - sink._close(); - } - } -} - -class _SkipStream extends _ForwardingStream { - int _remaining; - - _SkipStream(Stream source, int count) - : this._remaining = count, super(source) { - // This test is done early to avoid handling an async error - // in the _handleData method. - if (count is! int || count < 0) throw new ArgumentError(count); - } - - void _handleData(T inputEvent, _EventSink sink) { - if (_remaining > 0) { - _remaining--; - return; - } - sink._add(inputEvent); - } -} - -class _SkipWhileStream extends _ForwardingStream { - final _Predicate _test; - bool _hasFailed = false; - - _SkipWhileStream(Stream source, bool test(T value)) - : this._test = test, super(source); - - void _handleData(T inputEvent, _EventSink sink) { - if (_hasFailed) { - sink._add(inputEvent); - return; - } - bool satisfies; - try { - satisfies = _test(inputEvent); - } catch (e, s) { - _addErrorWithReplacement(sink, e, s); - // A failure to return a boolean is considered "not matching". - _hasFailed = true; - return; - } - if (!satisfies) { - _hasFailed = true; - sink._add(inputEvent); - } - } -} - -typedef bool _Equality(T a, T b); - -class _DistinctStream extends _ForwardingStream { - static var _SENTINEL = new Object(); - - _Equality _equals; - var _previous = _SENTINEL; - - _DistinctStream(Stream source, bool equals(T a, T b)) - : _equals = equals, super(source); - - void _handleData(T inputEvent, _EventSink sink) { - if (identical(_previous, _SENTINEL)) { - _previous = inputEvent; - return sink._add(inputEvent); - } else { - bool isEqual; - try { - if (_equals == null) { - isEqual = (_previous == inputEvent); - } else { - isEqual = _equals(_previous, inputEvent); - } - } catch (e, s) { - _addErrorWithReplacement(sink, e, s); - return null; - } - if (!isEqual) { - sink._add(inputEvent); - _previous = inputEvent; - } - } - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/stream_transformers.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/stream_transformers.dart deleted file mode 100644 index b18d226fbe7c..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/stream_transformers.dart +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.async; - -/** - * Wraps an [_EventSink] so it exposes only the [EventSink] interface. - */ -class _EventSinkWrapper implements EventSink { - _EventSink _sink; - _EventSinkWrapper(this._sink); - - void add(T data) { _sink._add(data); } - void addError(error, [StackTrace stackTrace]) { - _sink._addError(error, stackTrace); - } - void close() { _sink._close(); } -} - -/** - * A StreamSubscription that pipes data through a sink. - * - * The constructor of this class takes a [_SinkMapper] which maps from - * [EventSink] to [EventSink]. The input to the mapper is the output of - * the transformation. The returned sink is the transformation's input. - */ -class _SinkTransformerStreamSubscription - extends _BufferingStreamSubscription { - /// The transformer's input sink. - EventSink _transformerSink; - - /// The subscription to the input stream. - StreamSubscription _subscription; - - _SinkTransformerStreamSubscription(Stream source, - _SinkMapper mapper, - void onData(T data), - Function onError, - void onDone(), - bool cancelOnError) - // We set the adapter's target only when the user is allowed to send data. - : super(onData, onError, onDone, cancelOnError) { - _EventSinkWrapper eventSink = new _EventSinkWrapper(this); - _transformerSink = mapper(eventSink); - _subscription = source.listen(_handleData, - onError: _handleError, - onDone: _handleDone); - } - - /** Whether this subscription is still subscribed to its source. */ - bool get _isSubscribed => _subscription != null; - - // _EventSink interface. - - /** - * Adds an event to this subscriptions. - * - * Contrary to normal [_BufferingStreamSubscription]s we may receive - * events when the stream is already closed. Report them as state - * error. - */ - void _add(T data) { - if (_isClosed) { - throw new StateError("Stream is already closed"); - } - super._add(data); - } - - /** - * Adds an error event to this subscriptions. - * - * Contrary to normal [_BufferingStreamSubscription]s we may receive - * events when the stream is already closed. Report them as state - * error. - */ - void _addError(Object error, StackTrace stackTrace) { - if (_isClosed) { - throw new StateError("Stream is already closed"); - } - super._addError(error, stackTrace); - } - - /** - * Adds a close event to this subscriptions. - * - * Contrary to normal [_BufferingStreamSubscription]s we may receive - * events when the stream is already closed. Report them as state - * error. - */ - void _close() { - if (_isClosed) { - throw new StateError("Stream is already closed"); - } - super._close(); - } - - // _BufferingStreamSubscription hooks. - - void _onPause() { - if (_isSubscribed) _subscription.pause(); - } - - void _onResume() { - if (_isSubscribed) _subscription.resume(); - } - - Future _onCancel() { - if (_isSubscribed) { - StreamSubscription subscription = _subscription; - _subscription = null; - subscription.cancel(); - } - return null; - } - - void _handleData(S data) { - try { - _transformerSink.add(data); - } catch (e, s) { - _addError(e, s); - } - } - - void _handleError(error, [stackTrace]) { - try { - _transformerSink.addError(error, stackTrace); - } catch (e, s) { - if (identical(e, error)) { - _addError(error, stackTrace); - } else { - _addError(e, s); - } - } - } - - void _handleDone() { - try { - _subscription = null; - _transformerSink.close(); - } catch (e, s) { - _addError(e, s); - } - } -} - - -typedef EventSink _SinkMapper(EventSink output); - -/** - * A StreamTransformer for Sink-mappers. - * - * A Sink-mapper takes an [EventSink] (its output) and returns another - * EventSink (its input). - * - * Note that this class can be `const`. - */ -class _StreamSinkTransformer implements StreamTransformer { - final _SinkMapper _sinkMapper; - const _StreamSinkTransformer(this._sinkMapper); - - Stream bind(Stream stream) - => new _BoundSinkStream(stream, _sinkMapper); -} - -/** - * The result of binding a StreamTransformer for Sink-mappers. - * - * It contains the bound Stream and the sink-mapper. Only when the user starts - * listening to this stream is the sink-mapper invoked. The result is used - * to create a StreamSubscription that transforms events. - */ -class _BoundSinkStream extends Stream { - final _SinkMapper _sinkMapper; - final Stream _stream; - - bool get isBroadcast => _stream.isBroadcast; - - _BoundSinkStream(this._stream, this._sinkMapper); - - StreamSubscription listen(void onData(T event), - { Function onError, - void onDone(), - bool cancelOnError }) { - cancelOnError = identical(true, cancelOnError); - StreamSubscription subscription = new _SinkTransformerStreamSubscription( - _stream, _sinkMapper, onData, onError, onDone, cancelOnError); - return subscription; - } -} - -/// Data-handler coming from [StreamTransformer.fromHandlers]. -typedef void _TransformDataHandler(S data, EventSink sink); -/// Error-handler coming from [StreamTransformer.fromHandlers]. -typedef void _TransformErrorHandler( - Object error, StackTrace stackTrace, EventSink sink); -/// Done-handler coming from [StreamTransformer.fromHandlers]. -typedef void _TransformDoneHandler(EventSink sink); - -/** - * Wraps handlers (from [StreamTransformer.fromHandlers]) into an `EventSink`. - * - * This way we can reuse the code from [_StreamSinkTransformer]. - */ -class _HandlerEventSink implements EventSink { - final _TransformDataHandler _handleData; - final _TransformErrorHandler _handleError; - final _TransformDoneHandler _handleDone; - - /// The output sink where the handlers should send their data into. - final EventSink _sink; - - _HandlerEventSink(this._handleData, this._handleError, this._handleDone, - this._sink); - - void add(S data) => _handleData(data, _sink); - void addError(Object error, [StackTrace stackTrace]) - => _handleError(error, stackTrace, _sink); - void close() => _handleDone(_sink); -} - -/** - * A StreamTransformer that transformers events with the given handlers. - * - * Note that this transformer can only be used once. - */ -class _StreamHandlerTransformer extends _StreamSinkTransformer { - - _StreamHandlerTransformer({ - void handleData(S data, EventSink sink), - void handleError(Object error, StackTrace stackTrace, EventSink sink), - void handleDone(EventSink sink)}) - : super((EventSink outputSink) { - if (handleData == null) handleData = _defaultHandleData; - if (handleError == null) handleError = _defaultHandleError; - if (handleDone == null) handleDone = _defaultHandleDone; - return new _HandlerEventSink( - handleData, handleError, handleDone, outputSink); - }); - - Stream bind(Stream stream) { - return super.bind(stream); - } - - /** Default data handler forwards all data. */ - static void _defaultHandleData(var data, EventSink sink) { - sink.add(data); - } - - /** Default error handler forwards all errors. */ - static void _defaultHandleError(error, StackTrace stackTrace, - EventSink sink) { - sink.addError(error); - } - - /** Default done handler forwards done. */ - static void _defaultHandleDone(EventSink sink) { - sink.close(); - } -} - -/// A closure mapping a stream and cancelOnError to a StreamSubscription. -typedef StreamSubscription _SubscriptionTransformer( - Stream stream, bool cancelOnError); - -/** - * A [StreamTransformer] that minimizes the number of additional classes. - * - * Instead of implementing three classes: a [StreamTransformer], a [Stream] - * (as the result of a `bind` call) and a [StreamSubscription] (which does the - * actual work), this class only requires a fincution that is invoked when the - * last bit (the subscription) of the transformer-workflow is needed. - * - * The given transformer function maps from Stream and cancelOnError to a - * `StreamSubscription`. As such it can also act on `cancel` events, making it - * fully general. - */ -class _StreamSubscriptionTransformer implements StreamTransformer { - final _SubscriptionTransformer _transformer; - - const _StreamSubscriptionTransformer(this._transformer); - - Stream bind(Stream stream) => - new _BoundSubscriptionStream(stream, _transformer); -} - -/** - * A stream transformed by a [_StreamSubscriptionTransformer]. - * - * When this stream is listened to it invokes the [_transformer] function with - * the stored [_stream]. Usually the transformer starts listening at this - * moment. - */ -class _BoundSubscriptionStream extends Stream { - final _SubscriptionTransformer _transformer; - final Stream _stream; - - _BoundSubscriptionStream(this._stream, this._transformer); - - StreamSubscription listen(void onData(T event), - { Function onError, - void onDone(), - bool cancelOnError }) { - cancelOnError = identical(true, cancelOnError); - StreamSubscription result = _transformer(_stream, cancelOnError); - result.onData(onData); - result.onError(onError); - result.onDone(onDone); - return result; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/timer.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/timer.dart deleted file mode 100644 index 5389e5adc1d0..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/timer.dart +++ /dev/null @@ -1,119 +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. - -part of dart.async; - -/** - * A count-down timer that can be configured to fire once or repeatedly. - * - * The timer counts down from the specified duration to 0. - * When the timer reaches 0, the timer invokes the specified callback function. - * Use a periodic timer to repeatedly count down the same interval. - * - * A negative duration is treated the same as a duration of 0. - * If the duration is statically known to be 0, consider using [run]. - * - * Frequently the duration is either a constant or computed as in the - * following example (taking advantage of the multiplication operator of - * the [Duration] class): - * - * const TIMEOUT = const Duration(seconds: 3); - * const ms = const Duration(milliseconds: 1); - * - * startTimeout([int milliseconds]) { - * var duration = milliseconds == null ? TIMEOUT : ms * milliseconds; - * return new Timer(duration, handleTimeout); - * } - * ... - * void handleTimeout() { // callback function - * ... - * } - * - * Note: If Dart code using Timer is compiled to JavaScript, the finest - * granularity available in the browser is 4 milliseconds. - * - * See [Stopwatch] for measuring elapsed time. - */ -abstract class Timer { - - /** - * Creates a new timer. - * - * The [callback] function is invoked after the given [duration]. - * - */ - factory Timer(Duration duration, void callback()) { - 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. - return Zone.current.createTimer(duration, callback); - } - return Zone.current.createTimer( - duration, Zone.current.bindCallback(callback, runGuarded: true)); - } - - /** - * Creates a new repeating timer. - * - * The [callback] is invoked repeatedly with [duration] intervals until - * canceled with the [cancel] function. - * - * The exact timing depends on the underlying timer implementation. - * No more than `n` callbacks will be made in `duration * n` time, - * but the time between two consecutive callbacks - * can be shorter and longer than `duration`. - * - * In particular, an implementation may schedule the next callback, e.g., - * a `duration` after either when the previous callback ended, - * when the previous callback started, or when the previous callback was - * scheduled for - even if the actual callback was delayed. - */ - factory Timer.periodic(Duration duration, - 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. - return Zone.current.createPeriodicTimer(duration, callback); - } - return Zone.current.createPeriodicTimer( - duration, Zone.current.bindUnaryCallback(callback, runGuarded: true)); - } - - /** - * Runs the given [callback] asynchronously as soon as possible. - * - * This function is equivalent to `new Timer(Duration.ZERO, callback)`. - */ - static void run(void callback()) { - new Timer(Duration.ZERO, callback); - } - - /** - * Cancels the timer. - */ - void cancel(); - - /** - * Returns whether the timer is still active. - * - * A non-periodic timer is active if the callback has not been executed, - * and the timer has not been canceled. - * - * A periodic timer is active if it has not been canceled. - */ - bool get isActive; - - static Timer _createTimer(Duration duration, void callback()) { - int milliseconds = duration.inMilliseconds; - if (milliseconds < 0) milliseconds = 0; - return new TimerImpl(milliseconds, callback); - } - static Timer _createPeriodicTimer(Duration duration, - void callback(Timer timer)) { - int milliseconds = duration.inMilliseconds; - if (milliseconds < 0) milliseconds = 0; - return new TimerImpl.periodic(milliseconds, callback); - } -} - diff --git a/pkg/dev_compiler/test/generated_sdk/lib/async/zone.dart b/pkg/dev_compiler/test/generated_sdk/lib/async/zone.dart deleted file mode 100644 index 43132d5d36c6..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/async/zone.dart +++ /dev/null @@ -1,1253 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.async; - -typedef dynamic ZoneCallback(); -typedef dynamic ZoneUnaryCallback(arg); -typedef dynamic ZoneBinaryCallback(arg1, arg2); - -typedef dynamic HandleUncaughtErrorHandler( - Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace); -typedef dynamic RunHandler(Zone self, ZoneDelegate parent, Zone zone, f()); -typedef dynamic RunUnaryHandler( - Zone self, ZoneDelegate parent, Zone zone, f(arg), arg); -typedef dynamic RunBinaryHandler( - Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2), arg1, arg2); -typedef ZoneCallback RegisterCallbackHandler( - Zone self, ZoneDelegate parent, Zone zone, f()); -typedef ZoneUnaryCallback RegisterUnaryCallbackHandler( - Zone self, ZoneDelegate parent, Zone zone, f(arg)); -typedef ZoneBinaryCallback RegisterBinaryCallbackHandler( - Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2)); -typedef AsyncError ErrorCallbackHandler(Zone self, ZoneDelegate parent, - Zone zone, Object error, StackTrace stackTrace); -typedef void ScheduleMicrotaskHandler( - Zone self, ZoneDelegate parent, Zone zone, f()); -typedef Timer CreateTimerHandler( - Zone self, ZoneDelegate parent, Zone zone, Duration duration, void f()); -typedef Timer CreatePeriodicTimerHandler( - Zone self, ZoneDelegate parent, Zone zone, - Duration period, void f(Timer timer)); -typedef void PrintHandler( - Zone self, ZoneDelegate parent, Zone zone, String line); -typedef Zone ForkHandler(Zone self, ZoneDelegate parent, Zone zone, - ZoneSpecification specification, - Map zoneValues); - -/** Pair of error and stack trace. Returned by [Zone.errorCallback]. */ -class AsyncError implements Error { - final error; - final StackTrace stackTrace; - - AsyncError(this.error, this.stackTrace); - - String toString() => error.toString(); -} - - -class _ZoneFunction { - final _Zone zone; - final Function function; - const _ZoneFunction(this.zone, this.function); -} - -/** - * This class provides the specification for a forked zone. - * - * When forking a new zone (see [Zone.fork]) one can override the default - * behavior of the zone by providing callbacks. These callbacks must be - * given in an instance of this class. - * - * Handlers have the same signature as the same-named methods on [Zone] but - * receive three additional arguments: - * - * 1. the zone the handlers are attached to (the "self" zone). - * 2. a [ZoneDelegate] to the parent zone. - * 3. the zone that first received the request (before the request was - * bubbled up). - * - * Handlers can either stop propagation the request (by simply not calling the - * parent handler), or forward to the parent zone, potentially modifying the - * arguments on the way. - */ -abstract class ZoneSpecification { - /** - * Creates a specification with the provided handlers. - */ - const factory ZoneSpecification({ - dynamic handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone, - error, StackTrace stackTrace), - dynamic run(Zone self, ZoneDelegate parent, Zone zone, f()), - dynamic runUnary( - Zone self, ZoneDelegate parent, Zone zone, f(arg), arg), - dynamic runBinary(Zone self, ZoneDelegate parent, Zone zone, - f(arg1, arg2), arg1, arg2), - ZoneCallback registerCallback( - Zone self, ZoneDelegate parent, Zone zone, f()), - ZoneUnaryCallback registerUnaryCallback( - Zone self, ZoneDelegate parent, Zone zone, f(arg)), - ZoneBinaryCallback registerBinaryCallback( - Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2)), - AsyncError errorCallback(Zone self, ZoneDelegate parent, Zone zone, - Object error, StackTrace stackTrace), - void scheduleMicrotask( - Zone self, ZoneDelegate parent, Zone zone, f()), - Timer createTimer(Zone self, ZoneDelegate parent, Zone zone, - Duration duration, void f()), - Timer createPeriodicTimer(Zone self, ZoneDelegate parent, Zone zone, - Duration period, void f(Timer timer)), - void print(Zone self, ZoneDelegate parent, Zone zone, String line), - Zone fork(Zone self, ZoneDelegate parent, Zone zone, - ZoneSpecification specification, Map zoneValues) - }) = _ZoneSpecification; - - /** - * Creates a specification from [other] with the provided handlers overriding - * the ones in [other]. - */ - factory ZoneSpecification.from(ZoneSpecification other, { - dynamic handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone, - error, StackTrace stackTrace): null, - dynamic run(Zone self, ZoneDelegate parent, Zone zone, f()): null, - dynamic runUnary( - Zone self, ZoneDelegate parent, Zone zone, f(arg), arg): null, - dynamic runBinary(Zone self, ZoneDelegate parent, Zone zone, - f(arg1, arg2), arg1, arg2): null, - ZoneCallback registerCallback( - Zone self, ZoneDelegate parent, Zone zone, f()): null, - ZoneUnaryCallback registerUnaryCallback( - Zone self, ZoneDelegate parent, Zone zone, f(arg)): null, - ZoneBinaryCallback registerBinaryCallback( - Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2)): null, - AsyncError errorCallback(Zone self, ZoneDelegate parent, Zone zone, - Object error, StackTrace stackTrace), - void scheduleMicrotask( - Zone self, ZoneDelegate parent, Zone zone, f()): null, - Timer createTimer(Zone self, ZoneDelegate parent, Zone zone, - Duration duration, void f()): null, - Timer createPeriodicTimer(Zone self, ZoneDelegate parent, Zone zone, - Duration period, void f(Timer timer)): null, - void print(Zone self, ZoneDelegate parent, Zone zone, String line): null, - Zone fork(Zone self, ZoneDelegate parent, Zone zone, - ZoneSpecification specification, - Map zoneValues): null - }) { - return new ZoneSpecification( - handleUncaughtError: handleUncaughtError != null - ? handleUncaughtError - : other.handleUncaughtError, - run: run != null ? run : other.run, - runUnary: runUnary != null ? runUnary : other.runUnary, - runBinary: runBinary != null ? runBinary : other.runBinary, - registerCallback: registerCallback != null - ? registerCallback - : other.registerCallback, - registerUnaryCallback: registerUnaryCallback != null - ? registerUnaryCallback - : other.registerUnaryCallback, - registerBinaryCallback: registerBinaryCallback != null - ? registerBinaryCallback - : other.registerBinaryCallback, - errorCallback: errorCallback != null - ? errorCallback - : other.errorCallback, - scheduleMicrotask: scheduleMicrotask != null - ? scheduleMicrotask - : other.scheduleMicrotask, - createTimer : createTimer != null ? createTimer : other.createTimer, - createPeriodicTimer: createPeriodicTimer != null - ? createPeriodicTimer - : other.createPeriodicTimer, - print : print != null ? print : other.print, - fork: fork != null ? fork : other.fork); - } - - HandleUncaughtErrorHandler get handleUncaughtError; - RunHandler get run; - RunUnaryHandler get runUnary; - RunBinaryHandler get runBinary; - RegisterCallbackHandler get registerCallback; - RegisterUnaryCallbackHandler get registerUnaryCallback; - RegisterBinaryCallbackHandler get registerBinaryCallback; - ErrorCallbackHandler get errorCallback; - ScheduleMicrotaskHandler get scheduleMicrotask; - CreateTimerHandler get createTimer; - CreatePeriodicTimerHandler get createPeriodicTimer; - PrintHandler get print; - ForkHandler get fork; -} - -/** - * Internal [ZoneSpecification] class. - * - * The implementation wants to rely on the fact that the getters cannot change - * dynamically. We thus require users to go through the redirecting - * [ZoneSpecification] constructor which instantiates this class. - */ -class _ZoneSpecification implements ZoneSpecification { - const _ZoneSpecification({ - this.handleUncaughtError: null, - this.run: null, - this.runUnary: null, - this.runBinary: null, - this.registerCallback: null, - this.registerUnaryCallback: null, - this.registerBinaryCallback: null, - this.errorCallback: null, - this.scheduleMicrotask: null, - this.createTimer: null, - this.createPeriodicTimer: null, - this.print: null, - this.fork: null - }); - - // TODO(13406): Enable types when dart2js supports it. - final /*HandleUncaughtErrorHandler*/ handleUncaughtError; - final /*RunHandler*/ run; - final /*RunUnaryHandler*/ runUnary; - final /*RunBinaryHandler*/ runBinary; - final /*RegisterCallbackHandler*/ registerCallback; - final /*RegisterUnaryCallbackHandler*/ registerUnaryCallback; - final /*RegisterBinaryCallbackHandler*/ registerBinaryCallback; - final /*ErrorCallbackHandler*/ errorCallback; - final /*ScheduleMicrotaskHandler*/ scheduleMicrotask; - final /*CreateTimerHandler*/ createTimer; - final /*CreatePeriodicTimerHandler*/ createPeriodicTimer; - final /*PrintHandler*/ print; - final /*ForkHandler*/ fork; -} - -/** - * This class wraps zones for delegation. - * - * When forwarding to parent zones one can't just invoke the parent zone's - * exposed functions (like [Zone.run]), but one needs to provide more - * information (like the zone the `run` was initiated). Zone callbacks thus - * receive more information including this [ZoneDelegate] class. When delegating - * to the parent zone one should go through the given instance instead of - * directly invoking the parent zone. - */ -abstract class ZoneDelegate { - dynamic handleUncaughtError(Zone zone, error, StackTrace stackTrace); - dynamic run(Zone zone, f()); - dynamic runUnary(Zone zone, f(arg), arg); - dynamic runBinary(Zone zone, f(arg1, arg2), arg1, arg2); - ZoneCallback registerCallback(Zone zone, f()); - ZoneUnaryCallback registerUnaryCallback(Zone zone, f(arg)); - ZoneBinaryCallback registerBinaryCallback(Zone zone, f(arg1, arg2)); - AsyncError errorCallback(Zone zone, Object error, StackTrace stackTrace); - void scheduleMicrotask(Zone zone, f()); - Timer createTimer(Zone zone, Duration duration, void f()); - Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer)); - void print(Zone zone, String line); - Zone fork(Zone zone, ZoneSpecification specification, Map zoneValues); -} - -/** - * A Zone represents the asynchronous version of a dynamic extent. Asynchronous - * callbacks are executed in the zone they have been queued in. For example, - * the callback of a `future.then` is executed in the same zone as the one where - * the `then` was invoked. - */ -abstract class Zone { - // Private constructor so that it is not possible instantiate a Zone class. - Zone._(); - - /** The root zone that is implicitly created. */ - static const Zone ROOT = _ROOT_ZONE; - - /** The currently running zone. */ - static Zone _current = _ROOT_ZONE; - - static Zone get current => _current; - - dynamic handleUncaughtError(error, StackTrace stackTrace); - - /** - * Returns the parent zone. - * - * Returns `null` if `this` is the [ROOT] zone. - */ - Zone get parent; - - /** - * The error zone is the one that is responsible for dealing with uncaught - * errors. - * Errors are not allowed to cross between zones with different error-zones. - * - * This is the closest parent or ancestor zone of this zone that has a custom - * [handleUncaughtError] method. - */ - Zone get errorZone; - - /** - * Returns true if `this` and [otherZone] are in the same error zone. - * - * Two zones are in the same error zone if they inherit their - * [handleUncaughtError] callback from the same [errorZone]. - */ - bool inSameErrorZone(Zone otherZone); - - /** - * Creates a new zone as a child of `this`. - * - * The new zone will have behavior like the current zone, except where - * overridden by functions in [specification]. - * - * The new zone will have the same stored values (accessed through - * `operator []`) as this zone, but updated with the keys and values - * in [zoneValues]. If a key is in both this zone's values and in - * `zoneValues`, the new zone will use the value from `zoneValues``. - */ - Zone fork({ ZoneSpecification specification, - Map zoneValues }); - - /** - * Executes the given function [f] in this zone. - */ - dynamic run(f()); - - /** - * Executes the given callback [f] with argument [arg] in this zone. - */ - dynamic runUnary(f(arg), var arg); - - /** - * Executes the given callback [f] with argument [arg1] and [arg2] in this - * zone. - */ - dynamic runBinary(f(arg1, arg2), var arg1, var arg2); - - /** - * Executes the given function [f] in this zone. - * - * Same as [run] but catches uncaught errors and gives them to - * [handleUncaughtError]. - */ - dynamic runGuarded(f()); - - /** - * Executes the given callback [f] in this zone. - * - * Same as [runUnary] but catches uncaught errors and gives them to - * [handleUncaughtError]. - */ - dynamic runUnaryGuarded(f(arg), var arg); - - /** - * Executes the given callback [f] in this zone. - * - * Same as [runBinary] but catches uncaught errors and gives them to - * [handleUncaughtError]. - */ - dynamic runBinaryGuarded(f(arg1, arg2), var arg1, var arg2); - - /** - * Registers the given callback in this zone. - * - * It is good practice to register asynchronous or delayed callbacks before - * invoking [run]. This gives the zone a chance to wrap the callback and - * to store information with the callback. For example, a zone may decide - * to store the stack trace (at the time of the registration) with the - * callback. - * - * Returns a potentially new callback that should be used in place of the - * given [callback]. - */ - ZoneCallback registerCallback(callback()); - - /** - * Registers the given callback in this zone. - * - * Similar to [registerCallback] but with a unary callback. - */ - ZoneUnaryCallback registerUnaryCallback(callback(arg)); - - /** - * Registers the given callback in this zone. - * - * Similar to [registerCallback] but with a unary callback. - */ - ZoneBinaryCallback registerBinaryCallback(callback(arg1, arg2)); - - /** - * Equivalent to: - * - * ZoneCallback registered = registerCallback(f); - * if (runGuarded) return () => this.runGuarded(registered); - * return () => this.run(registered); - * - */ - ZoneCallback bindCallback(f(), { bool runGuarded: true }); - - /** - * Equivalent to: - * - * ZoneCallback registered = registerUnaryCallback(f); - * if (runGuarded) return (arg) => this.runUnaryGuarded(registered, arg); - * return (arg) => thin.runUnary(registered, arg); - */ - ZoneUnaryCallback bindUnaryCallback(f(arg), { bool runGuarded: true }); - - /** - * Equivalent to: - * - * ZoneCallback registered = registerBinaryCallback(f); - * if (runGuarded) { - * return (arg1, arg2) => this.runBinaryGuarded(registered, arg); - * } - * return (arg1, arg2) => thin.runBinary(registered, arg1, arg2); - */ - ZoneBinaryCallback bindBinaryCallback( - f(arg1, arg2), { bool runGuarded: true }); - - /** - * Intercepts errors when added programmtically to a `Future` or `Stream`. - * - * When caling [Completer.completeError], [Stream.addError], - * or [Future] constructors that take an error or a callback that may throw, - * the current zone is allowed to intercept and replace the error. - * - * When other libraries use intermediate controllers or completers, such - * calls may contain errors that have already been processed. - * - * Return `null` if no replacement is desired. - * The original error is used unchanged in that case. - * Otherwise return an instance of [AsyncError] holding - * the new pair of error and stack trace. - * If the [AsyncError.error] is `null`, it is replaced by a [NullThrownError]. - */ - AsyncError errorCallback(Object error, StackTrace stackTrace); - - /** - * Runs [f] asynchronously in this zone. - */ - void scheduleMicrotask(void f()); - - /** - * Creates a Timer where the callback is executed in this zone. - */ - Timer createTimer(Duration duration, void callback()); - - /** - * Creates a periodic Timer where the callback is executed in this zone. - */ - Timer createPeriodicTimer(Duration period, void callback(Timer timer)); - - /** - * Prints the given [line]. - */ - void print(String line); - - /** - * Call to enter the Zone. - * - * The previous current zone is returned. - */ - static Zone _enter(Zone zone) { - assert(zone != null); - assert(!identical(zone, _current)); - Zone previous = _current; - _current = zone; - return previous; - } - - /** - * Call to leave the Zone. - * - * The previous Zone must be provided as `previous`. - */ - static void _leave(Zone previous) { - assert(previous != null); - Zone._current = previous; - } - - /** - * Retrieves the zone-value associated with [key]. - * - * If this zone does not contain the value looks up the same key in the - * parent zone. If the [key] is not found returns `null`. - * - * Any object can be used as key, as long as it has compatible `operator ==` - * and `hashCode` implementations. - * By controlling access to the key, a zone can grant or deny access to the - * zone value. - */ - operator [](Object key); -} - -ZoneDelegate _parentDelegate(_Zone zone) { - if (zone.parent == null) return null; - return zone.parent._delegate; -} - -class _ZoneDelegate implements ZoneDelegate { - final _Zone _delegationTarget; - - _ZoneDelegate(this._delegationTarget); - - dynamic handleUncaughtError(Zone zone, error, StackTrace stackTrace) { - _ZoneFunction implementation = _delegationTarget._handleUncaughtError; - _Zone implZone = implementation.zone; - return (implementation.function)( - implZone, _parentDelegate(implZone), zone, error, stackTrace); - } - - dynamic run(Zone zone, f()) { - _ZoneFunction implementation = _delegationTarget._run; - _Zone implZone = implementation.zone; - return (implementation.function)( - implZone, _parentDelegate(implZone), zone, f); - } - - dynamic runUnary(Zone zone, f(arg), arg) { - _ZoneFunction implementation = _delegationTarget._runUnary; - _Zone implZone = implementation.zone; - return (implementation.function)( - implZone, _parentDelegate(implZone), zone, f, arg); - } - - dynamic runBinary(Zone zone, f(arg1, arg2), arg1, arg2) { - _ZoneFunction implementation = _delegationTarget._runBinary; - _Zone implZone = implementation.zone; - return (implementation.function)( - implZone, _parentDelegate(implZone), zone, f, arg1, arg2); - } - - ZoneCallback registerCallback(Zone zone, f()) { - _ZoneFunction implementation = _delegationTarget._registerCallback; - _Zone implZone = implementation.zone; - return (implementation.function)( - implZone, _parentDelegate(implZone), zone, f); - } - - ZoneUnaryCallback registerUnaryCallback(Zone zone, f(arg)) { - _ZoneFunction implementation = _delegationTarget._registerUnaryCallback; - _Zone implZone = implementation.zone; - return (implementation.function)( - implZone, _parentDelegate(implZone), zone, f); - } - - ZoneBinaryCallback registerBinaryCallback(Zone zone, f(arg1, arg2)) { - _ZoneFunction implementation = _delegationTarget._registerBinaryCallback; - _Zone implZone = implementation.zone; - return (implementation.function)( - implZone, _parentDelegate(implZone), zone, f); - } - - AsyncError errorCallback(Zone zone, Object error, StackTrace stackTrace) { - _ZoneFunction implementation = _delegationTarget._errorCallback; - _Zone implZone = implementation.zone; - if (identical(implZone, _ROOT_ZONE)) return null; - return (implementation.function)(implZone, _parentDelegate(implZone), zone, - error, stackTrace); - } - - void scheduleMicrotask(Zone zone, f()) { - _ZoneFunction implementation = _delegationTarget._scheduleMicrotask; - _Zone implZone = implementation.zone; - (implementation.function)( - implZone, _parentDelegate(implZone), zone, f); - } - - Timer createTimer(Zone zone, Duration duration, void f()) { - _ZoneFunction implementation = _delegationTarget._createTimer; - _Zone implZone = implementation.zone; - return (implementation.function)( - implZone, _parentDelegate(implZone), zone, duration, f); - } - - Timer createPeriodicTimer(Zone zone, Duration period, void f(Timer timer)) { - _ZoneFunction implementation = _delegationTarget._createPeriodicTimer; - _Zone implZone = implementation.zone; - return (implementation.function)( - implZone, _parentDelegate(implZone), zone, period, f); - } - - void print(Zone zone, String line) { - _ZoneFunction implementation = _delegationTarget._print; - _Zone implZone = implementation.zone; - (implementation.function)( - implZone, _parentDelegate(implZone), zone, line); - } - - Zone fork(Zone zone, ZoneSpecification specification, - Map zoneValues) { - _ZoneFunction implementation = _delegationTarget._fork; - _Zone implZone = implementation.zone; - return (implementation.function)( - implZone, _parentDelegate(implZone), zone, specification, zoneValues); - } -} - - -/** - * Base class for Zone implementations. - */ -abstract class _Zone implements Zone { - const _Zone(); - - _ZoneFunction get _runUnary; - _ZoneFunction get _run; - _ZoneFunction get _runBinary; - _ZoneFunction get _registerCallback; - _ZoneFunction get _registerUnaryCallback; - _ZoneFunction get _registerBinaryCallback; - _ZoneFunction get _errorCallback; - _ZoneFunction get _scheduleMicrotask; - _ZoneFunction get _createTimer; - _ZoneFunction get _createPeriodicTimer; - _ZoneFunction get _print; - _ZoneFunction get _fork; - _ZoneFunction get _handleUncaughtError; - _Zone get parent; - ZoneDelegate get _delegate; - Map get _map; - - bool inSameErrorZone(Zone otherZone) { - return identical(this, otherZone) || - identical(errorZone, otherZone.errorZone); - } -} - -class _CustomZone extends _Zone { - // The actual zone and implementation of each of these - // inheritable zone functions. - _ZoneFunction _runUnary; - _ZoneFunction _run; - _ZoneFunction _runBinary; - _ZoneFunction _registerCallback; - _ZoneFunction _registerUnaryCallback; - _ZoneFunction _registerBinaryCallback; - _ZoneFunction _errorCallback; - _ZoneFunction _scheduleMicrotask; - _ZoneFunction _createTimer; - _ZoneFunction _createPeriodicTimer; - _ZoneFunction _print; - _ZoneFunction _fork; - _ZoneFunction _handleUncaughtError; - - // A cached delegate to this zone. - ZoneDelegate _delegateCache; - - /// The parent zone. - final _Zone parent; - - /// The zone's scoped value declaration map. - /// - /// This is always a [HashMap]. - final Map _map; - - ZoneDelegate get _delegate { - if (_delegateCache != null) return _delegateCache; - _delegateCache = new _ZoneDelegate(this); - return _delegateCache; - } - - _CustomZone(this.parent, ZoneSpecification specification, this._map) { - // The root zone will have implementations of all parts of the - // specification, so it will never try to access the (null) parent. - // All other zones have a non-null parent. - _run = (specification.run != null) - ? new _ZoneFunction(this, specification.run) - : parent._run; - _runUnary = (specification.runUnary != null) - ? new _ZoneFunction(this, specification.runUnary) - : parent._runUnary; - _runBinary = (specification.runBinary != null) - ? new _ZoneFunction(this, specification.runBinary) - : parent._runBinary; - _registerCallback = (specification.registerCallback != null) - ? new _ZoneFunction(this, specification.registerCallback) - : parent._registerCallback; - _registerUnaryCallback = (specification.registerUnaryCallback != null) - ? new _ZoneFunction(this, specification.registerUnaryCallback) - : parent._registerUnaryCallback; - _registerBinaryCallback = (specification.registerBinaryCallback != null) - ? new _ZoneFunction(this, specification.registerBinaryCallback) - : parent._registerBinaryCallback; - _errorCallback = (specification.errorCallback != null) - ? new _ZoneFunction(this, specification.errorCallback) - : parent._errorCallback; - _scheduleMicrotask = (specification.scheduleMicrotask != null) - ? new _ZoneFunction(this, specification.scheduleMicrotask) - : parent._scheduleMicrotask; - _createTimer = (specification.createTimer != null) - ? new _ZoneFunction(this, specification.createTimer) - : parent._createTimer; - _createPeriodicTimer = (specification.createPeriodicTimer != null) - ? new _ZoneFunction(this, specification.createPeriodicTimer) - : parent._createPeriodicTimer; - _print = (specification.print != null) - ? new _ZoneFunction(this, specification.print) - : parent._print; - _fork = (specification.fork != null) - ? new _ZoneFunction(this, specification.fork) - : parent._fork; - _handleUncaughtError = (specification.handleUncaughtError != null) - ? new _ZoneFunction(this, specification.handleUncaughtError) - : parent._handleUncaughtError; - } - - /** - * The closest error-handling zone. - * - * Returns `this` if `this` has an error-handler. Otherwise returns the - * parent's error-zone. - */ - Zone get errorZone => _handleUncaughtError.zone; - - dynamic runGuarded(f()) { - try { - return run(f); - } catch (e, s) { - return handleUncaughtError(e, s); - } - } - - dynamic runUnaryGuarded(f(arg), arg) { - try { - return runUnary(f, arg); - } catch (e, s) { - return handleUncaughtError(e, s); - } - } - - dynamic runBinaryGuarded(f(arg1, arg2), arg1, arg2) { - try { - return runBinary(f, arg1, arg2); - } catch (e, s) { - return handleUncaughtError(e, s); - } - } - - ZoneCallback bindCallback(f(), { bool runGuarded: true }) { - ZoneCallback registered = registerCallback(f); - if (runGuarded) { - return () => this.runGuarded(registered); - } else { - return () => this.run(registered); - } - } - - ZoneUnaryCallback bindUnaryCallback(f(arg), { bool runGuarded: true }) { - ZoneUnaryCallback registered = registerUnaryCallback(f); - if (runGuarded) { - return (arg) => this.runUnaryGuarded(registered, arg); - } else { - return (arg) => this.runUnary(registered, arg); - } - } - - ZoneBinaryCallback bindBinaryCallback( - f(arg1, arg2), { bool runGuarded: true }) { - ZoneBinaryCallback registered = registerBinaryCallback(f); - if (runGuarded) { - return (arg1, arg2) => this.runBinaryGuarded(registered, arg1, arg2); - } else { - return (arg1, arg2) => this.runBinary(registered, arg1, arg2); - } - } - - operator [](Object key) { - var result = _map[key]; - if (result != null || _map.containsKey(key)) return result; - // If we are not the root zone, look up in the parent zone. - if (parent != null) { - // We do not optimize for repeatedly looking up a key which isn't - // there. That would require storing the key and keeping it alive. - // Copying the key/value from the parent does not keep any new values - // alive. - var value = parent[key]; - if (value != null) { - _map[key] = value; - } - return value; - } - assert(this == _ROOT_ZONE); - return null; - } - - // Methods that can be customized by the zone specification. - - dynamic handleUncaughtError(error, StackTrace stackTrace) { - _ZoneFunction implementation = this._handleUncaughtError; - assert(implementation != null); - ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); - return (implementation.function)( - implementation.zone, parentDelegate, this, error, stackTrace); - } - - Zone fork({ZoneSpecification specification, Map zoneValues}) { - _ZoneFunction implementation = this._fork; - assert(implementation != null); - ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); - return (implementation.function)( - implementation.zone, parentDelegate, this, - specification, zoneValues); - } - - dynamic run(f()) { - _ZoneFunction implementation = this._run; - assert(implementation != null); - ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); - return (implementation.function)( - implementation.zone, parentDelegate, this, f); - } - - dynamic runUnary(f(arg), arg) { - _ZoneFunction implementation = this._runUnary; - assert(implementation != null); - ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); - return (implementation.function)( - implementation.zone, parentDelegate, this, f, arg); - } - - dynamic runBinary(f(arg1, arg2), arg1, arg2) { - _ZoneFunction implementation = this._runBinary; - assert(implementation != null); - ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); - return (implementation.function)( - implementation.zone, parentDelegate, this, f, arg1, arg2); - } - - ZoneCallback registerCallback(f()) { - _ZoneFunction implementation = this._registerCallback; - assert(implementation != null); - ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); - return (implementation.function)( - implementation.zone, parentDelegate, this, f); - } - - ZoneUnaryCallback registerUnaryCallback(f(arg)) { - _ZoneFunction implementation = this._registerUnaryCallback; - assert(implementation != null); - ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); - return (implementation.function)( - implementation.zone, parentDelegate, this, f); - } - - ZoneBinaryCallback registerBinaryCallback(f(arg1, arg2)) { - _ZoneFunction implementation = this._registerBinaryCallback; - assert(implementation != null); - ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); - return (implementation.function)( - implementation.zone, parentDelegate, this, f); - } - - AsyncError errorCallback(Object error, StackTrace stackTrace) { - final _ZoneFunction implementation = this._errorCallback; - assert(implementation != null); - final Zone implementationZone = implementation.zone; - if (identical(implementationZone, _ROOT_ZONE)) return null; - final ZoneDelegate parentDelegate = _parentDelegate(implementationZone); - return (implementation.function)( - implementationZone, parentDelegate, this, error, stackTrace); - } - - void scheduleMicrotask(void f()) { - _ZoneFunction implementation = this._scheduleMicrotask; - assert(implementation != null); - ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); - return (implementation.function)( - implementation.zone, parentDelegate, this, f); - } - - Timer createTimer(Duration duration, void f()) { - _ZoneFunction implementation = this._createTimer; - assert(implementation != null); - ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); - return (implementation.function)( - implementation.zone, parentDelegate, this, duration, f); - } - - Timer createPeriodicTimer(Duration duration, void f(Timer timer)) { - _ZoneFunction implementation = this._createPeriodicTimer; - assert(implementation != null); - ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); - return (implementation.function)( - implementation.zone, parentDelegate, this, duration, f); - } - - void print(String line) { - _ZoneFunction implementation = this._print; - assert(implementation != null); - ZoneDelegate parentDelegate = _parentDelegate(implementation.zone); - return (implementation.function)( - implementation.zone, parentDelegate, this, line); - } -} - -void _rootHandleUncaughtError( - Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) { - _schedulePriorityAsyncCallback(() { - throw new _UncaughtAsyncError(error, stackTrace); - }); -} - -dynamic _rootRun(Zone self, ZoneDelegate parent, Zone zone, f()) { - if (Zone._current == zone) return f(); - - Zone old = Zone._enter(zone); - try { - return f(); - } finally { - Zone._leave(old); - } -} - -dynamic _rootRunUnary(Zone self, ZoneDelegate parent, Zone zone, f(arg), arg) { - if (Zone._current == zone) return f(arg); - - Zone old = Zone._enter(zone); - try { - return f(arg); - } finally { - Zone._leave(old); - } -} - -dynamic _rootRunBinary(Zone self, ZoneDelegate parent, Zone zone, - f(arg1, arg2), arg1, arg2) { - if (Zone._current == zone) return f(arg1, arg2); - - Zone old = Zone._enter(zone); - try { - return f(arg1, arg2); - } finally { - Zone._leave(old); - } -} - -ZoneCallback _rootRegisterCallback( - Zone self, ZoneDelegate parent, Zone zone, f()) { - return f; -} - -ZoneUnaryCallback _rootRegisterUnaryCallback( - Zone self, ZoneDelegate parent, Zone zone, f(arg)) { - return f; -} - -ZoneBinaryCallback _rootRegisterBinaryCallback( - Zone self, ZoneDelegate parent, Zone zone, f(arg1, arg2)) { - return f; -} - -AsyncError _rootErrorCallback(Zone self, ZoneDelegate parent, Zone zone, - Object error, StackTrace stackTrace) => null; - -void _rootScheduleMicrotask(Zone self, ZoneDelegate parent, Zone zone, f()) { - if (!identical(_ROOT_ZONE, zone)) { - bool hasErrorHandler = !_ROOT_ZONE.inSameErrorZone(zone); - f = zone.bindCallback(f, runGuarded: hasErrorHandler); - } - _scheduleAsyncCallback(f); -} - -Timer _rootCreateTimer(Zone self, ZoneDelegate parent, Zone zone, - Duration duration, void callback()) { - if (!identical(_ROOT_ZONE, zone)) { - callback = zone.bindCallback(callback); - } - return Timer._createTimer(duration, callback); -} - -Timer _rootCreatePeriodicTimer( - Zone self, ZoneDelegate parent, Zone zone, - Duration duration, void callback(Timer timer)) { - if (!identical(_ROOT_ZONE, zone)) { - callback = zone.bindUnaryCallback(callback); - } - return Timer._createPeriodicTimer(duration, callback); -} - -void _rootPrint(Zone self, ZoneDelegate parent, Zone zone, String line) { - printToConsole(line); -} - -void _printToZone(String line) { - Zone.current.print(line); -} - -Zone _rootFork(Zone self, ZoneDelegate parent, Zone zone, - ZoneSpecification specification, - Map zoneValues) { - // TODO(floitsch): it would be nice if we could get rid of this hack. - // Change the static zoneOrDirectPrint function to go through zones - // from now on. - printToZone = _printToZone; - - if (specification == null) { - specification = const ZoneSpecification(); - } else if (specification is! _ZoneSpecification) { - throw new ArgumentError("ZoneSpecifications must be instantiated" - " with the provided constructor."); - } - Map valueMap; - if (zoneValues == null) { - if (zone is _Zone) { - valueMap = zone._map; - } else { - valueMap = new HashMap(); - } - } else { - valueMap = new HashMap.from(zoneValues); - } - return new _CustomZone(zone, specification, valueMap); -} - -class _RootZoneSpecification implements ZoneSpecification { - HandleUncaughtErrorHandler get handleUncaughtError => - _rootHandleUncaughtError; - RunHandler get run => _rootRun; - RunUnaryHandler get runUnary => _rootRunUnary; - RunBinaryHandler get runBinary => _rootRunBinary; - RegisterCallbackHandler get registerCallback => _rootRegisterCallback; - RegisterUnaryCallbackHandler get registerUnaryCallback => - _rootRegisterUnaryCallback; - RegisterBinaryCallbackHandler get registerBinaryCallback => - _rootRegisterBinaryCallback; - ErrorCallbackHandler get errorCallback => _rootErrorCallback; - ScheduleMicrotaskHandler get scheduleMicrotask => _rootScheduleMicrotask; - CreateTimerHandler get createTimer => _rootCreateTimer; - CreatePeriodicTimerHandler get createPeriodicTimer => - _rootCreatePeriodicTimer; - PrintHandler get print => _rootPrint; - ForkHandler get fork => _rootFork; -} - -class _RootZone extends _Zone { - const _RootZone(); - - _ZoneFunction get _run => - const _ZoneFunction(_ROOT_ZONE, _rootRun); - _ZoneFunction get _runUnary => - const _ZoneFunction(_ROOT_ZONE, _rootRunUnary); - _ZoneFunction get _runBinary => - const _ZoneFunction(_ROOT_ZONE, _rootRunBinary); - _ZoneFunction get _registerCallback => - const _ZoneFunction(_ROOT_ZONE, _rootRegisterCallback); - _ZoneFunction get _registerUnaryCallback => - const _ZoneFunction(_ROOT_ZONE, _rootRegisterUnaryCallback); - _ZoneFunction get _registerBinaryCallback => - const _ZoneFunction(_ROOT_ZONE, _rootRegisterBinaryCallback); - _ZoneFunction get _errorCallback => - const _ZoneFunction(_ROOT_ZONE, _rootErrorCallback); - _ZoneFunction get _scheduleMicrotask => - const _ZoneFunction(_ROOT_ZONE, _rootScheduleMicrotask); - _ZoneFunction get _createTimer => - const _ZoneFunction(_ROOT_ZONE, _rootCreateTimer); - _ZoneFunction get _createPeriodicTimer => - const _ZoneFunction(_ROOT_ZONE, _rootCreatePeriodicTimer); - _ZoneFunction get _print => - const _ZoneFunction(_ROOT_ZONE, _rootPrint); - _ZoneFunction get _fork => - const _ZoneFunction(_ROOT_ZONE, _rootFork); - _ZoneFunction get _handleUncaughtError => - const _ZoneFunction(_ROOT_ZONE, _rootHandleUncaughtError); - - // The parent zone. - _Zone get parent => null; - - /// The zone's scoped value declaration map. - /// - /// This is always a [HashMap]. - Map get _map => _rootMap; - - static Map _rootMap = new HashMap(); - - static ZoneDelegate _rootDelegate; - - ZoneDelegate get _delegate { - if (_rootDelegate != null) return _rootDelegate; - return _rootDelegate = new _ZoneDelegate(this); - } - - /** - * The closest error-handling zone. - * - * Returns `this` if `this` has an error-handler. Otherwise returns the - * parent's error-zone. - */ - Zone get errorZone => this; - - // Zone interface. - - dynamic runGuarded(f()) { - try { - if (identical(_ROOT_ZONE, Zone._current)) { - return f(); - } - return _rootRun(null, null, this, f); - } catch (e, s) { - return handleUncaughtError(e, s); - } - } - - dynamic runUnaryGuarded(f(arg), arg) { - try { - if (identical(_ROOT_ZONE, Zone._current)) { - return f(arg); - } - return _rootRunUnary(null, null, this, f, arg); - } catch (e, s) { - return handleUncaughtError(e, s); - } - } - - dynamic runBinaryGuarded(f(arg1, arg2), arg1, arg2) { - try { - if (identical(_ROOT_ZONE, Zone._current)) { - return f(arg1, arg2); - } - return _rootRunBinary(null, null, this, f, arg1, arg2); - } catch (e, s) { - return handleUncaughtError(e, s); - } - } - - ZoneCallback bindCallback(f(), { bool runGuarded: true }) { - if (runGuarded) { - return () => this.runGuarded(f); - } else { - return () => this.run(f); - } - } - - ZoneUnaryCallback bindUnaryCallback(f(arg), { bool runGuarded: true }) { - if (runGuarded) { - return (arg) => this.runUnaryGuarded(f, arg); - } else { - return (arg) => this.runUnary(f, arg); - } - } - - ZoneBinaryCallback bindBinaryCallback( - f(arg1, arg2), { bool runGuarded: true }) { - if (runGuarded) { - return (arg1, arg2) => this.runBinaryGuarded(f, arg1, arg2); - } else { - return (arg1, arg2) => this.runBinary(f, arg1, arg2); - } - } - - operator [](Object key) => null; - - // Methods that can be customized by the zone specification. - - dynamic handleUncaughtError(error, StackTrace stackTrace) { - return _rootHandleUncaughtError(null, null, this, error, stackTrace); - } - - Zone fork({ZoneSpecification specification, Map zoneValues}) { - return _rootFork(null, null, this, specification, zoneValues); - } - - dynamic run(f()) { - if (identical(Zone._current, _ROOT_ZONE)) return f(); - return _rootRun(null, null, this, f); - } - - dynamic runUnary(f(arg), arg) { - if (identical(Zone._current, _ROOT_ZONE)) return f(arg); - return _rootRunUnary(null, null, this, f, arg); - } - - dynamic runBinary(f(arg1, arg2), arg1, arg2) { - if (identical(Zone._current, _ROOT_ZONE)) return f(arg1, arg2); - return _rootRunBinary(null, null, this, f, arg1, arg2); - } - - ZoneCallback registerCallback(f()) => f; - - ZoneUnaryCallback registerUnaryCallback(f(arg)) => f; - - ZoneBinaryCallback registerBinaryCallback(f(arg1, arg2)) => f; - - AsyncError errorCallback(Object error, StackTrace stackTrace) => null; - - void scheduleMicrotask(void f()) { - _rootScheduleMicrotask(null, null, this, f); - } - - Timer createTimer(Duration duration, void f()) { - return Timer._createTimer(duration, f); - } - - Timer createPeriodicTimer(Duration duration, void f(Timer timer)) { - return Timer._createPeriodicTimer(duration, f); - } - - void print(String line) { - printToConsole(line); - } -} - -const _ROOT_ZONE = const _RootZone(); - -/** - * Runs [body] in its own zone. - * - * If [onError] is non-null the zone is considered an error zone. All uncaught - * errors, synchronous or asynchronous, in the zone are caught and handled - * by the callback. - * - * Errors may never cross error-zone boundaries. This is intuitive for leaving - * a zone, but it also applies for errors that would enter an error-zone. - * Errors that try to cross error-zone boundaries are considered uncaught. - * - * var future = new Future.value(499); - * runZoned(() { - * future = future.then((_) { throw "error in first error-zone"; }); - * runZoned(() { - * future = future.catchError((e) { print("Never reached!"); }); - * }, onError: (e) { print("unused error handler"); }); - * }, onError: (e) { print("catches error of first error-zone."); }); - * - * Example: - * - * runZoned(() { - * new Future(() { throw "asynchronous error"; }); - * }, onError: print); // Will print "asynchronous error". - */ -dynamic runZoned(body(), - { Map zoneValues, - ZoneSpecification zoneSpecification, - Function onError }) { - HandleUncaughtErrorHandler errorHandler; - if (onError != null) { - errorHandler = (Zone self, ZoneDelegate parent, Zone zone, - error, StackTrace stackTrace) { - try { - if (onError is ZoneBinaryCallback) { - return self.parent.runBinary(onError, error, stackTrace); - } - return self.parent.runUnary(onError, error); - } catch(e, s) { - if (identical(e, error)) { - return parent.handleUncaughtError(zone, error, stackTrace); - } else { - return parent.handleUncaughtError(zone, e, s); - } - } - }; - } - if (zoneSpecification == null) { - zoneSpecification = - new ZoneSpecification(handleUncaughtError: errorHandler); - } else if (errorHandler != null) { - zoneSpecification = - new ZoneSpecification.from(zoneSpecification, - handleUncaughtError: errorHandler); - } - Zone zone = Zone.current.fork(specification: zoneSpecification, - zoneValues: zoneValues); - if (onError != null) { - return zone.runGuarded(body); - } else { - return zone.run(body); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/collection.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/collection.dart deleted file mode 100644 index 8eca257c4110..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/collection.dart +++ /dev/null @@ -1,1683 +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. - -/** - * Classes and utilities that supplement the collection support in dart:core. - */ -library dart.collection; - -import 'dart:_internal'; -import 'dart:math' show Random; -import 'dart:_foreign_helper' show JS; -import 'dart:_js_helper' show - fillLiteralMap, InternalMap, NoInline, NoThrows, patch; // Used by ListMixin.shuffle. - -part 'collections.dart'; -part 'hash_map.dart'; -part 'hash_set.dart'; -part 'iterable.dart'; -part 'iterator.dart'; -part 'linked_hash_map.dart'; -part 'linked_hash_set.dart'; -part 'linked_list.dart'; -part 'list.dart'; -part 'maps.dart'; -part 'queue.dart'; -part 'set.dart'; -part 'splay_tree.dart'; - -class _HashMap implements HashMap { - int _length = 0; - - // The hash map contents are divided into three parts: one part for - // string keys, one for numeric keys, and one for the rest. String - // and numeric keys map directly to their values, but the rest of - // the entries are stored in bucket lists of the form: - // - // [key-0, value-0, key-1, value-1, ...] - // - // where all keys in the same bucket share the same hash code. - var _strings; - var _nums; - var _rest; - - // When iterating over the hash map, it is very convenient to have a - // list of all the keys. We cache that on the instance and clear the - // the cache whenever the key set changes. This is also used to - // guard against concurrent modifications. - List _keys; - - _HashMap(); - - - int get length => _length; - bool get isEmpty => _length == 0; - bool get isNotEmpty => !isEmpty; - - Iterable get keys { - return new HashMapKeyIterable(this); - } - - Iterable get values { - return new MappedIterable(keys, (each) => this[each]); - } - - bool containsKey(Object key) { - if (_isStringKey(key)) { - var strings = _strings; - return (strings == null) ? false : _hasTableEntry(strings, key); - } else if (_isNumericKey(key)) { - var nums = _nums; - return (nums == null) ? false : _hasTableEntry(nums, key); - } else { - return _containsKey(key); - } - } - - bool _containsKey(Object key) { - var rest = _rest; - if (rest == null) return false; - var bucket = _getBucket(rest, key); - return _findBucketIndex(bucket, key) >= 0; - } - - bool containsValue(Object value) { - return _computeKeys().any((each) => this[each] == value); - } - - void addAll(Map other) { - other.forEach((K key, V value) { - this[key] = value; - }); - } - - V operator[](Object key) { - if (_isStringKey(key)) { - var strings = _strings; - return (strings == null) ? null : _getTableEntry(strings, key); - } else if (_isNumericKey(key)) { - var nums = _nums; - return (nums == null) ? null : _getTableEntry(nums, key); - } else { - return _get(key); - } - } - - V _get(Object key) { - var rest = _rest; - if (rest == null) return null; - var bucket = _getBucket(rest, key); - int index = _findBucketIndex(bucket, key); - return (index < 0) ? null : JS('var', '#[#]', bucket, index + 1); - } - - void operator[]=(K key, V value) { - if (_isStringKey(key)) { - var strings = _strings; - if (strings == null) _strings = strings = _newHashTable(); - _addHashTableEntry(strings, key, value); - } else if (_isNumericKey(key)) { - var nums = _nums; - if (nums == null) _nums = nums = _newHashTable(); - _addHashTableEntry(nums, key, value); - } else { - _set(key, value); - } - } - - void _set(K key, V value) { - var rest = _rest; - if (rest == null) _rest = rest = _newHashTable(); - var hash = _computeHashCode(key); - var bucket = JS('var', '#[#]', rest, hash); - if (bucket == null) { - _setTableEntry(rest, hash, JS('var', '[#, #]', key, value)); - _length++; - _keys = null; - } else { - int index = _findBucketIndex(bucket, key); - if (index >= 0) { - JS('void', '#[#] = #', bucket, index + 1, value); - } else { - JS('void', '#.push(#, #)', bucket, key, value); - _length++; - _keys = null; - } - } - } - - V putIfAbsent(K key, V ifAbsent()) { - if (containsKey(key)) return this[key]; - V value = ifAbsent(); - this[key] = value; - return value; - } - - V remove(Object key) { - if (_isStringKey(key)) { - return _removeHashTableEntry(_strings, key); - } else if (_isNumericKey(key)) { - return _removeHashTableEntry(_nums, key); - } else { - return _remove(key); - } - } - - V _remove(Object key) { - var rest = _rest; - if (rest == null) return null; - var bucket = _getBucket(rest, key); - int index = _findBucketIndex(bucket, key); - if (index < 0) return null; - // TODO(kasperl): Consider getting rid of the bucket list when - // the length reaches zero. - _length--; - _keys = null; - // Use splice to remove the two [key, value] elements at the - // index and return the value. - return JS('var', '#.splice(#, 2)[1]', bucket, index); - } - - void clear() { - if (_length > 0) { - _strings = _nums = _rest = _keys = null; - _length = 0; - } - } - - void forEach(void action(K key, V value)) { - List keys = _computeKeys(); - for (int i = 0, length = keys.length; i < length; i++) { - var key = JS('var', '#[#]', keys, i); - action(key, this[key]); - if (JS('bool', '# !== #', keys, _keys)) { - throw new ConcurrentModificationError(this); - } - } - } - - List _computeKeys() { - if (_keys != null) return _keys; - List result = new List(_length); - int index = 0; - - // Add all string keys to the list. - var strings = _strings; - if (strings != null) { - var names = JS('var', 'Object.getOwnPropertyNames(#)', strings); - int entries = JS('int', '#.length', names); - for (int i = 0; i < entries; i++) { - String key = JS('String', '#[#]', names, i); - JS('void', '#[#] = #', result, index, key); - index++; - } - } - - // Add all numeric keys to the list. - var nums = _nums; - if (nums != null) { - var names = JS('var', 'Object.getOwnPropertyNames(#)', nums); - int entries = JS('int', '#.length', names); - for (int i = 0; i < entries; i++) { - // Object.getOwnPropertyNames returns a list of strings, so we - // have to convert the keys back to numbers (+). - num key = JS('num', '+#[#]', names, i); - JS('void', '#[#] = #', result, index, key); - index++; - } - } - - // Add all the remaining keys to the list. - var rest = _rest; - if (rest != null) { - var names = JS('var', 'Object.getOwnPropertyNames(#)', rest); - int entries = JS('int', '#.length', names); - for (int i = 0; i < entries; i++) { - var key = JS('String', '#[#]', names, i); - var bucket = JS('var', '#[#]', rest, key); - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i += 2) { - var key = JS('var', '#[#]', bucket, i); - JS('void', '#[#] = #', result, index, key); - index++; - } - } - } - assert(index == _length); - return _keys = result; - } - - void _addHashTableEntry(var table, K key, V value) { - if (!_hasTableEntry(table, key)) { - _length++; - _keys = null; - } - _setTableEntry(table, key, value); - } - - V _removeHashTableEntry(var table, Object key) { - if (table != null && _hasTableEntry(table, key)) { - V value = _getTableEntry(table, key); - _deleteTableEntry(table, key); - _length--; - _keys = null; - return value; - } else { - return null; - } - } - - static bool _isStringKey(var key) { - return key is String && key != '__proto__'; - } - - static bool _isNumericKey(var key) { - // Only treat unsigned 30-bit integers as numeric keys. This way, - // we avoid converting them to strings when we use them as keys in - // the JavaScript hash table object. - return key is num && JS('bool', '(# & 0x3ffffff) === #', key, key); - } - - int _computeHashCode(var key) { - // We force the hash codes to be unsigned 30-bit integers to avoid - // issues with problematic keys like '__proto__'. Another option - // would be to throw an exception if the hash code isn't a number. - return JS('int', '# & 0x3ffffff', key.hashCode); - } - - static bool _hasTableEntry(var table, var key) { - var entry = JS('var', '#[#]', table, key); - // We take care to only store non-null entries in the table, so we - // can check if the table has an entry for the given key with a - // simple null check. - return entry != null; - } - - static _getTableEntry(var table, var key) { - var entry = JS('var', '#[#]', table, key); - // We store the table itself as the entry to signal that it really - // is a null value, so we have to map back to null here. - return JS('bool', '# === #', entry, table) ? null : entry; - } - - static void _setTableEntry(var table, var key, var value) { - // We only store non-null entries in the table, so we have to - // change null values to refer to the table itself. Such values - // will be recognized and mapped back to null on access. - if (value == null) { - // Do not update [value] with [table], otherwise our - // optimizations could be confused by this opaque object being - // now used for more things than storing and fetching from it. - JS('void', '#[#] = #', table, key, table); - } else { - JS('void', '#[#] = #', table, key, value); - } - } - - static void _deleteTableEntry(var table, var key) { - JS('void', 'delete #[#]', table, key); - } - - List _getBucket(var table, var key) { - var hash = _computeHashCode(key); - return JS('var', '#[#]', table, hash); - } - - int _findBucketIndex(var bucket, var key) { - if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i += 2) { - if (JS('var', '#[#]', bucket, i) == key) return i; - } - return -1; - } - - static _newHashTable() { - // Create a new JavaScript object to be used as a hash table. Use - // Object.create to avoid the properties on Object.prototype - // showing up as entries. - var table = JS('var', 'Object.create(null)'); - // Attempt to force the hash table into 'dictionary' mode by - // adding a property to it and deleting it again. - var temporaryKey = ''; - _setTableEntry(table, temporaryKey, table); - _deleteTableEntry(table, temporaryKey); - return table; - } -} -class _IdentityHashMap extends _HashMap { - int _computeHashCode(var key) { - // We force the hash codes to be unsigned 30-bit integers to avoid - // issues with problematic keys like '__proto__'. Another option - // would be to throw an exception if the hash code isn't a number. - return JS('int', '# & 0x3ffffff', identityHashCode(key)); - } - - int _findBucketIndex(var bucket, var key) { - if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i += 2) { - if (identical(JS('var', '#[#]', bucket, i), key)) return i; - } - return -1; - } -} -class _CustomHashMap extends _HashMap { - final _Equality _equals; - final _Hasher _hashCode; - final _Predicate _validKey; - _CustomHashMap(this._equals, this._hashCode, - bool validKey(Object potentialKey)) - : _validKey = (validKey != null) ? validKey : ((v) => v is K); - - V operator[](Object key) { - if (!_validKey(key)) return null; - return super._get(key); - } - - void operator[]=(K key, V value) { - super._set(key, value); - } - - bool containsKey(Object key) { - if (!_validKey(key)) return false; - return super._containsKey(key); - } - - V remove(Object key) { - if (!_validKey(key)) return null; - return super._remove(key); - } - - int _computeHashCode(var key) { - // We force the hash codes to be unsigned 30-bit integers to avoid - // issues with problematic keys like '__proto__'. Another option - // would be to throw an exception if the hash code isn't a number. - return JS('int', '# & 0x3ffffff', _hashCode(key)); - } - - int _findBucketIndex(var bucket, var key) { - if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i += 2) { - if (_equals(JS('var', '#[#]', bucket, i), key)) return i; - } - return -1; - } - - String toString() => Maps.mapToString(this); -} -class HashMapKeyIterable extends IterableBase - implements EfficientLength { - final _map; - HashMapKeyIterable(this._map); - - int get length => _map._length; - bool get isEmpty => _map._length == 0; - - Iterator get iterator { - return new HashMapKeyIterator(_map, _map._computeKeys()); - } - - bool contains(Object element) { - return _map.containsKey(element); - } - - void forEach(void f(E element)) { - List keys = _map._computeKeys(); - for (int i = 0, length = JS('int', '#.length', keys); i < length; i++) { - f(JS('var', '#[#]', keys, i)); - if (JS('bool', '# !== #', keys, _map._keys)) { - throw new ConcurrentModificationError(_map); - } - } - } -} -class HashMapKeyIterator implements Iterator { - final _map; - final List _keys; - int _offset = 0; - E _current; - - HashMapKeyIterator(this._map, this._keys); - - E get current => _current; - - bool moveNext() { - var keys = _keys; - int offset = _offset; - if (JS('bool', '# !== #', keys, _map._keys)) { - throw new ConcurrentModificationError(_map); - } else if (offset >= JS('int', '#.length', keys)) { - _current = null; - return false; - } else { - _current = JS('var', '#[#]', keys, offset); - // TODO(kasperl): For now, we have to tell the type inferrer to - // treat the result of doing offset + 1 as an int. Otherwise, we - // get unnecessary bailout code. - _offset = JS('int', '#', offset + 1); - return true; - } - } -} -class _LinkedHashMap implements LinkedHashMap, InternalMap { - int _length = 0; - - // The hash map contents are divided into three parts: one part for - // string keys, one for numeric keys, and one for the rest. String - // and numeric keys map directly to their linked cells, but the rest - // of the entries are stored in bucket lists of the form: - // - // [cell-0, cell-1, ...] - // - // where all keys in the same bucket share the same hash code. - var _strings; - var _nums; - var _rest; - - // The keys and values are stored in cells that are linked together - // to form a double linked list. - LinkedHashMapCell _first; - LinkedHashMapCell _last; - - // We track the number of modifications done to the key set of the - // hash map to be able to throw when the map is modified while being - // iterated over. - int _modifications = 0; - - _LinkedHashMap(); - - - int get length => _length; - bool get isEmpty => _length == 0; - bool get isNotEmpty => !isEmpty; - - Iterable get keys { - return new LinkedHashMapKeyIterable(this); - } - - Iterable get values { - return new MappedIterable(keys, (each) => this[each]); - } - - bool containsKey(Object key) { - if (_isStringKey(key)) { - var strings = _strings; - if (strings == null) return false; - LinkedHashMapCell cell = _getTableEntry(strings, key); - return cell != null; - } else if (_isNumericKey(key)) { - var nums = _nums; - if (nums == null) return false; - LinkedHashMapCell cell = _getTableEntry(nums, key); - return cell != null; - } else { - return _containsKey(key); - } - } - - bool _containsKey(Object key) { - var rest = _rest; - if (rest == null) return false; - var bucket = _getBucket(rest, key); - return _findBucketIndex(bucket, key) >= 0; - } - - bool containsValue(Object value) { - return keys.any((each) => this[each] == value); - } - - void addAll(Map other) { - other.forEach((K key, V value) { - this[key] = value; - }); - } - - V operator[](Object key) { - if (_isStringKey(key)) { - var strings = _strings; - if (strings == null) return null; - LinkedHashMapCell cell = _getTableEntry(strings, key); - return (cell == null) ? null : cell._value; - } else if (_isNumericKey(key)) { - var nums = _nums; - if (nums == null) return null; - LinkedHashMapCell cell = _getTableEntry(nums, key); - return (cell == null) ? null : cell._value; - } else { - return _get(key); - } - } - - V _get(Object key) { - var rest = _rest; - if (rest == null) return null; - var bucket = _getBucket(rest, key); - int index = _findBucketIndex(bucket, key); - if (index < 0) return null; - LinkedHashMapCell cell = JS('var', '#[#]', bucket, index); - return cell._value; - } - - void operator[]=(K key, V value) { - if (_isStringKey(key)) { - var strings = _strings; - if (strings == null) _strings = strings = _newHashTable(); - _addHashTableEntry(strings, key, value); - } else if (_isNumericKey(key)) { - var nums = _nums; - if (nums == null) _nums = nums = _newHashTable(); - _addHashTableEntry(nums, key, value); - } else { - _set(key, value); - } - } - - void _set(K key, V value) { - var rest = _rest; - if (rest == null) _rest = rest = _newHashTable(); - var hash = _computeHashCode(key); - var bucket = JS('var', '#[#]', rest, hash); - if (bucket == null) { - LinkedHashMapCell cell = _newLinkedCell(key, value); - _setTableEntry(rest, hash, JS('var', '[#]', cell)); - } else { - int index = _findBucketIndex(bucket, key); - if (index >= 0) { - LinkedHashMapCell cell = JS('var', '#[#]', bucket, index); - cell._value = value; - } else { - LinkedHashMapCell cell = _newLinkedCell(key, value); - JS('void', '#.push(#)', bucket, cell); - } - } - } - - V putIfAbsent(K key, V ifAbsent()) { - if (containsKey(key)) return this[key]; - V value = ifAbsent(); - this[key] = value; - return value; - } - - V remove(Object key) { - if (_isStringKey(key)) { - return _removeHashTableEntry(_strings, key); - } else if (_isNumericKey(key)) { - return _removeHashTableEntry(_nums, key); - } else { - return _remove(key); - } - } - - V _remove(Object key) { - var rest = _rest; - if (rest == null) return null; - var bucket = _getBucket(rest, key); - int index = _findBucketIndex(bucket, key); - if (index < 0) return null; - // Use splice to remove the [cell] element at the index and - // unlink the cell before returning its value. - LinkedHashMapCell cell = JS('var', '#.splice(#, 1)[0]', bucket, index); - _unlinkCell(cell); - // TODO(kasperl): Consider getting rid of the bucket list when - // the length reaches zero. - return cell._value; - } - - void clear() { - if (_length > 0) { - _strings = _nums = _rest = _first = _last = null; - _length = 0; - _modified(); - } - } - - void forEach(void action(K key, V value)) { - LinkedHashMapCell cell = _first; - int modifications = _modifications; - while (cell != null) { - action(cell._key, cell._value); - if (modifications != _modifications) { - throw new ConcurrentModificationError(this); - } - cell = cell._next; - } - } - - void _addHashTableEntry(var table, K key, V value) { - LinkedHashMapCell cell = _getTableEntry(table, key); - if (cell == null) { - _setTableEntry(table, key, _newLinkedCell(key, value)); - } else { - cell._value = value; - } - } - - V _removeHashTableEntry(var table, Object key) { - if (table == null) return null; - LinkedHashMapCell cell = _getTableEntry(table, key); - if (cell == null) return null; - _unlinkCell(cell); - _deleteTableEntry(table, key); - return cell._value; - } - - void _modified() { - // Value cycles after 2^30 modifications. If you keep hold of an - // iterator for that long, you might miss a modification - // detection, and iteration can go sour. Don't do that. - _modifications = (_modifications + 1) & 0x3ffffff; - } - - // Create a new cell and link it in as the last one in the list. - LinkedHashMapCell _newLinkedCell(K key, V value) { - LinkedHashMapCell cell = new LinkedHashMapCell(key, value); - if (_first == null) { - _first = _last = cell; - } else { - LinkedHashMapCell last = _last; - cell._previous = last; - _last = last._next = cell; - } - _length++; - _modified(); - return cell; - } - - // Unlink the given cell from the linked list of cells. - void _unlinkCell(LinkedHashMapCell cell) { - LinkedHashMapCell previous = cell._previous; - LinkedHashMapCell next = cell._next; - if (previous == null) { - assert(cell == _first); - _first = next; - } else { - previous._next = next; - } - if (next == null) { - assert(cell == _last); - _last = previous; - } else { - next._previous = previous; - } - _length--; - _modified(); - } - - static bool _isStringKey(var key) { - return key is String && key != '__proto__'; - } - - static bool _isNumericKey(var key) { - // Only treat unsigned 30-bit integers as numeric keys. This way, - // we avoid converting them to strings when we use them as keys in - // the JavaScript hash table object. - return key is num && JS('bool', '(# & 0x3ffffff) === #', key, key); - } - - int _computeHashCode(var key) { - // We force the hash codes to be unsigned 30-bit integers to avoid - // issues with problematic keys like '__proto__'. Another option - // would be to throw an exception if the hash code isn't a number. - return JS('int', '# & 0x3ffffff', key.hashCode); - } - - static _getTableEntry(var table, var key) { - return JS('var', '#[#]', table, key); - } - - static void _setTableEntry(var table, var key, var value) { - assert(value != null); - JS('void', '#[#] = #', table, key, value); - } - - static void _deleteTableEntry(var table, var key) { - JS('void', 'delete #[#]', table, key); - } - - List _getBucket(var table, var key) { - var hash = _computeHashCode(key); - return JS('var', '#[#]', table, hash); - } - - int _findBucketIndex(var bucket, var key) { - if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i++) { - LinkedHashMapCell cell = JS('var', '#[#]', bucket, i); - if (cell._key == key) return i; - } - return -1; - } - - static _newHashTable() { - // Create a new JavaScript object to be used as a hash table. Use - // Object.create to avoid the properties on Object.prototype - // showing up as entries. - var table = JS('var', 'Object.create(null)'); - // Attempt to force the hash table into 'dictionary' mode by - // adding a property to it and deleting it again. - var temporaryKey = ''; - _setTableEntry(table, temporaryKey, table); - _deleteTableEntry(table, temporaryKey); - return table; - } - - String toString() => Maps.mapToString(this); -} -class _LinkedIdentityHashMap extends _LinkedHashMap { - int _computeHashCode(var key) { - // We force the hash codes to be unsigned 30-bit integers to avoid - // issues with problematic keys like '__proto__'. Another option - // would be to throw an exception if the hash code isn't a number. - return JS('int', '# & 0x3ffffff', identityHashCode(key)); - } - - int _findBucketIndex(var bucket, var key) { - if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i++) { - LinkedHashMapCell cell = JS('var', '#[#]', bucket, i); - if (identical(cell._key, key)) return i; - } - return -1; - } -} -class _LinkedCustomHashMap extends _LinkedHashMap { - final _Equality _equals; - final _Hasher _hashCode; - final _Predicate _validKey; - _LinkedCustomHashMap(this._equals, this._hashCode, - bool validKey(Object potentialKey)) - : _validKey = (validKey != null) ? validKey : ((v) => v is K); - - V operator[](Object key) { - if (!_validKey(key)) return null; - return super._get(key); - } - - void operator[]=(K key, V value) { - super._set(key, value); - } - - bool containsKey(Object key) { - if (!_validKey(key)) return false; - return super._containsKey(key); - } - - V remove(Object key) { - if (!_validKey(key)) return null; - return super._remove(key); - } - - int _computeHashCode(var key) { - // We force the hash codes to be unsigned 30-bit integers to avoid - // issues with problematic keys like '__proto__'. Another option - // would be to throw an exception if the hash code isn't a number. - return JS('int', '# & 0x3ffffff', _hashCode(key)); - } - - int _findBucketIndex(var bucket, var key) { - if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i++) { - LinkedHashMapCell cell = JS('var', '#[#]', bucket, i); - if (_equals(cell._key, key)) return i; - } - return -1; - } -} -class LinkedHashMapCell { - final _key; - var _value; - - LinkedHashMapCell _next; - LinkedHashMapCell _previous; - - LinkedHashMapCell(this._key, this._value); -} -class LinkedHashMapKeyIterable extends IterableBase - implements EfficientLength { - final _map; - LinkedHashMapKeyIterable(this._map); - - int get length => _map._length; - bool get isEmpty => _map._length == 0; - - Iterator get iterator { - return new LinkedHashMapKeyIterator(_map, _map._modifications); - } - - bool contains(Object element) { - return _map.containsKey(element); - } - - void forEach(void f(E element)) { - LinkedHashMapCell cell = _map._first; - int modifications = _map._modifications; - while (cell != null) { - f(cell._key); - if (modifications != _map._modifications) { - throw new ConcurrentModificationError(_map); - } - cell = cell._next; - } - } -} -class LinkedHashMapKeyIterator implements Iterator { - final _map; - final int _modifications; - LinkedHashMapCell _cell; - E _current; - - LinkedHashMapKeyIterator(this._map, this._modifications) { - _cell = _map._first; - } - - E get current => _current; - - bool moveNext() { - if (_modifications != _map._modifications) { - throw new ConcurrentModificationError(_map); - } else if (_cell == null) { - _current = null; - return false; - } else { - _current = _cell._key; - _cell = _cell._next; - return true; - } - } -} -class _HashSet extends _HashSetBase implements HashSet { - int _length = 0; - - // The hash set contents are divided into three parts: one part for - // string elements, one for numeric elements, and one for the - // rest. String and numeric elements map directly to a sentinel - // value, but the rest of the entries are stored in bucket lists of - // the form: - // - // [element-0, element-1, element-2, ...] - // - // where all elements in the same bucket share the same hash code. - var _strings; - var _nums; - var _rest; - - // When iterating over the hash set, it is very convenient to have a - // list of all the elements. We cache that on the instance and clear - // the the cache whenever the set changes. This is also used to - // guard against concurrent modifications. - List _elements; - - _HashSet(); - - Set _newSet() => new _HashSet(); - - // Iterable. - Iterator get iterator { - return new HashSetIterator(this, _computeElements()); - } - - int get length => _length; - bool get isEmpty => _length == 0; - bool get isNotEmpty => !isEmpty; - - bool contains(Object object) { - if (_isStringElement(object)) { - var strings = _strings; - return (strings == null) ? false : _hasTableEntry(strings, object); - } else if (_isNumericElement(object)) { - var nums = _nums; - return (nums == null) ? false : _hasTableEntry(nums, object); - } else { - return _contains(object); - } - } - - bool _contains(Object object) { - var rest = _rest; - if (rest == null) return false; - var bucket = _getBucket(rest, object); - return _findBucketIndex(bucket, object) >= 0; - } - - E lookup(Object object) { - if (_isStringElement(object) || _isNumericElement(object)) { - return this.contains(object) ? object : null; - } - return _lookup(object); - } - - E _lookup(Object object) { - var rest = _rest; - if (rest == null) return null; - var bucket = _getBucket(rest, object); - var index = _findBucketIndex(bucket, object); - if (index < 0) return null; - return bucket[index]; - } - - // Collection. - bool add(E element) { - if (_isStringElement(element)) { - var strings = _strings; - if (strings == null) _strings = strings = _newHashTable(); - return _addHashTableEntry(strings, element); - } else if (_isNumericElement(element)) { - var nums = _nums; - if (nums == null) _nums = nums = _newHashTable(); - return _addHashTableEntry(nums, element); - } else { - return _add(element); - } - } - - bool _add(E element) { - var rest = _rest; - if (rest == null) _rest = rest = _newHashTable(); - var hash = _computeHashCode(element); - var bucket = JS('var', '#[#]', rest, hash); - if (bucket == null) { - _setTableEntry(rest, hash, JS('var', '[#]', element)); - } else { - int index = _findBucketIndex(bucket, element); - if (index >= 0) return false; - JS('void', '#.push(#)', bucket, element); - } - _length++; - _elements = null; - return true; - } - - void addAll(Iterable objects) { - for (E each in objects) { - add(each); - } - } - - bool remove(Object object) { - if (_isStringElement(object)) { - return _removeHashTableEntry(_strings, object); - } else if (_isNumericElement(object)) { - return _removeHashTableEntry(_nums, object); - } else { - return _remove(object); - } - } - - bool _remove(Object object) { - var rest = _rest; - if (rest == null) return false; - var bucket = _getBucket(rest, object); - int index = _findBucketIndex(bucket, object); - if (index < 0) return false; - // TODO(kasperl): Consider getting rid of the bucket list when - // the length reaches zero. - _length--; - _elements = null; - // TODO(kasperl): It would probably be faster to move the - // element to the end and reduce the length of the bucket list. - JS('void', '#.splice(#, 1)', bucket, index); - return true; - } - - void clear() { - if (_length > 0) { - _strings = _nums = _rest = _elements = null; - _length = 0; - } - } - - List _computeElements() { - if (_elements != null) return _elements; - List result = new List(_length); - int index = 0; - - // Add all string elements to the list. - var strings = _strings; - if (strings != null) { - var names = JS('var', 'Object.getOwnPropertyNames(#)', strings); - int entries = JS('int', '#.length', names); - for (int i = 0; i < entries; i++) { - String element = JS('String', '#[#]', names, i); - JS('void', '#[#] = #', result, index, element); - index++; - } - } - - // Add all numeric elements to the list. - var nums = _nums; - if (nums != null) { - var names = JS('var', 'Object.getOwnPropertyNames(#)', nums); - int entries = JS('int', '#.length', names); - for (int i = 0; i < entries; i++) { - // Object.getOwnPropertyNames returns a list of strings, so we - // have to convert the elements back to numbers (+). - num element = JS('num', '+#[#]', names, i); - JS('void', '#[#] = #', result, index, element); - index++; - } - } - - // Add all the remaining elements to the list. - var rest = _rest; - if (rest != null) { - var names = JS('var', 'Object.getOwnPropertyNames(#)', rest); - int entries = JS('int', '#.length', names); - for (int i = 0; i < entries; i++) { - var entry = JS('String', '#[#]', names, i); - var bucket = JS('var', '#[#]', rest, entry); - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i++) { - JS('void', '#[#] = #[#]', result, index, bucket, i); - index++; - } - } - } - assert(index == _length); - return _elements = result; - } - - bool _addHashTableEntry(var table, E element) { - if (_hasTableEntry(table, element)) return false; - _setTableEntry(table, element, 0); - _length++; - _elements = null; - return true; - } - - bool _removeHashTableEntry(var table, Object element) { - if (table != null && _hasTableEntry(table, element)) { - _deleteTableEntry(table, element); - _length--; - _elements = null; - return true; - } else { - return false; - } - } - - static bool _isStringElement(var element) { - return element is String && element != '__proto__'; - } - - static bool _isNumericElement(var element) { - // Only treat unsigned 30-bit integers as numeric elements. This - // way, we avoid converting them to strings when we use them as - // keys in the JavaScript hash table object. - return element is num && - JS('bool', '(# & 0x3ffffff) === #', element, element); - } - - int _computeHashCode(var element) { - // We force the hash codes to be unsigned 30-bit integers to avoid - // issues with problematic elements like '__proto__'. Another - // option would be to throw an exception if the hash code isn't a - // number. - return JS('int', '# & 0x3ffffff', element.hashCode); - } - - static bool _hasTableEntry(var table, var key) { - var entry = JS('var', '#[#]', table, key); - // We take care to only store non-null entries in the table, so we - // can check if the table has an entry for the given key with a - // simple null check. - return entry != null; - } - - static void _setTableEntry(var table, var key, var value) { - assert(value != null); - JS('void', '#[#] = #', table, key, value); - } - - static void _deleteTableEntry(var table, var key) { - JS('void', 'delete #[#]', table, key); - } - - List _getBucket(var table, var element) { - var hash = _computeHashCode(element); - return JS('var', '#[#]', table, hash); - } - - int _findBucketIndex(var bucket, var element) { - if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i++) { - if (JS('var', '#[#]', bucket, i) == element) return i; - } - return -1; - } - - static _newHashTable() { - // Create a new JavaScript object to be used as a hash table. Use - // Object.create to avoid the properties on Object.prototype - // showing up as entries. - var table = JS('var', 'Object.create(null)'); - // Attempt to force the hash table into 'dictionary' mode by - // adding a property to it and deleting it again. - var temporaryKey = ''; - _setTableEntry(table, temporaryKey, table); - _deleteTableEntry(table, temporaryKey); - return table; - } -} -class _IdentityHashSet extends _HashSet { - Set _newSet() => new _IdentityHashSet(); - - int _computeHashCode(var key) { - // We force the hash codes to be unsigned 30-bit integers to avoid - // issues with problematic keys like '__proto__'. Another option - // would be to throw an exception if the hash code isn't a number. - return JS('int', '# & 0x3ffffff', identityHashCode(key)); - } - - int _findBucketIndex(var bucket, var element) { - if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i++) { - if (identical(JS('var', '#[#]', bucket, i), element)) return i; - } - return -1; - } -} -class _CustomHashSet extends _HashSet { - _Equality _equality; - _Hasher _hasher; - _Predicate _validKey; - _CustomHashSet(this._equality, this._hasher, - bool validKey(Object potentialKey)) - : _validKey = (validKey != null) ? validKey : ((x) => x is E); - - Set _newSet() => new _CustomHashSet(_equality, _hasher, _validKey); - - int _findBucketIndex(var bucket, var element) { - if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i++) { - if (_equality(JS('var', '#[#]', bucket, i), element)) return i; - } - return -1; - } - - int _computeHashCode(var element) { - // We force the hash codes to be unsigned 30-bit integers to avoid - // issues with problematic elements like '__proto__'. Another - // option would be to throw an exception if the hash code isn't a - // number. - return JS('int', '# & 0x3ffffff', _hasher(element)); - } - - bool add(E object) => super._add(object); - - bool contains(Object object) { - if (!_validKey(object)) return false; - return super._contains(object); - } - - E lookup(Object object) { - if (!_validKey(object)) return null; - return super._lookup(object); - } - - bool remove(Object object) { - if (!_validKey(object)) return false; - return super._remove(object); - } -} -class HashSetIterator implements Iterator { - final _set; - final List _elements; - int _offset = 0; - E _current; - - HashSetIterator(this._set, this._elements); - - E get current => _current; - - bool moveNext() { - var elements = _elements; - int offset = _offset; - if (JS('bool', '# !== #', elements, _set._elements)) { - throw new ConcurrentModificationError(_set); - } else if (offset >= JS('int', '#.length', elements)) { - _current = null; - return false; - } else { - _current = JS('var', '#[#]', elements, offset); - // TODO(kasperl): For now, we have to tell the type inferrer to - // treat the result of doing offset + 1 as an int. Otherwise, we - // get unnecessary bailout code. - _offset = JS('int', '#', offset + 1); - return true; - } - } -} -class _LinkedHashSet extends _HashSetBase implements LinkedHashSet { - int _length = 0; - - // The hash set contents are divided into three parts: one part for - // string elements, one for numeric elements, and one for the - // rest. String and numeric elements map directly to their linked - // cells, but the rest of the entries are stored in bucket lists of - // the form: - // - // [cell-0, cell-1, ...] - // - // where all elements in the same bucket share the same hash code. - var _strings; - var _nums; - var _rest; - - // The elements are stored in cells that are linked together - // to form a double linked list. - LinkedHashSetCell _first; - LinkedHashSetCell _last; - - // We track the number of modifications done to the element set to - // be able to throw when the set is modified while being iterated - // over. - int _modifications = 0; - - _LinkedHashSet(); - - Set _newSet() => new _LinkedHashSet(); - - void _unsupported(String operation) { - throw 'LinkedHashSet: unsupported $operation'; - } - - // Iterable. - Iterator get iterator { - return new LinkedHashSetIterator(this, _modifications); - } - - int get length => _length; - bool get isEmpty => _length == 0; - bool get isNotEmpty => !isEmpty; - - bool contains(Object object) { - if (_isStringElement(object)) { - var strings = _strings; - if (strings == null) return false; - LinkedHashSetCell cell = _getTableEntry(strings, object); - return cell != null; - } else if (_isNumericElement(object)) { - var nums = _nums; - if (nums == null) return false; - LinkedHashSetCell cell = _getTableEntry(nums, object); - return cell != null; - } else { - return _contains(object); - } - } - - bool _contains(Object object) { - var rest = _rest; - if (rest == null) return false; - var bucket = _getBucket(rest, object); - return _findBucketIndex(bucket, object) >= 0; - } - - E lookup(Object object) { - if (_isStringElement(object) || _isNumericElement(object)) { - return this.contains(object) ? object : null; - } else { - return _lookup(object); - } - } - - E _lookup(Object object) { - var rest = _rest; - if (rest == null) return null; - var bucket = _getBucket(rest, object); - var index = _findBucketIndex(bucket, object); - if (index < 0) return null; - return bucket[index]._element; - } - - void forEach(void action(E element)) { - LinkedHashSetCell cell = _first; - int modifications = _modifications; - while (cell != null) { - action(cell._element); - if (modifications != _modifications) { - throw new ConcurrentModificationError(this); - } - cell = cell._next; - } - } - - E get first { - if (_first == null) throw new StateError("No elements"); - return _first._element; - } - - E get last { - if (_last == null) throw new StateError("No elements"); - return _last._element; - } - - // Collection. - bool add(E element) { - if (_isStringElement(element)) { - var strings = _strings; - if (strings == null) _strings = strings = _newHashTable(); - return _addHashTableEntry(strings, element); - } else if (_isNumericElement(element)) { - var nums = _nums; - if (nums == null) _nums = nums = _newHashTable(); - return _addHashTableEntry(nums, element); - } else { - return _add(element); - } - } - - bool _add(E element) { - var rest = _rest; - if (rest == null) _rest = rest = _newHashTable(); - var hash = _computeHashCode(element); - var bucket = JS('var', '#[#]', rest, hash); - if (bucket == null) { - LinkedHashSetCell cell = _newLinkedCell(element); - _setTableEntry(rest, hash, JS('var', '[#]', cell)); - } else { - int index = _findBucketIndex(bucket, element); - if (index >= 0) return false; - LinkedHashSetCell cell = _newLinkedCell(element); - JS('void', '#.push(#)', bucket, cell); - } - return true; - } - - bool remove(Object object) { - if (_isStringElement(object)) { - return _removeHashTableEntry(_strings, object); - } else if (_isNumericElement(object)) { - return _removeHashTableEntry(_nums, object); - } else { - return _remove(object); - } - } - - bool _remove(Object object) { - var rest = _rest; - if (rest == null) return false; - var bucket = _getBucket(rest, object); - int index = _findBucketIndex(bucket, object); - if (index < 0) return false; - // Use splice to remove the [cell] element at the index and - // unlink it. - LinkedHashSetCell cell = JS('var', '#.splice(#, 1)[0]', bucket, index); - _unlinkCell(cell); - return true; - } - - void removeWhere(bool test(E element)) { - _filterWhere(test, true); - } - - void retainWhere(bool test(E element)) { - _filterWhere(test, false); - } - - void _filterWhere(bool test(E element), bool removeMatching) { - LinkedHashSetCell cell = _first; - while (cell != null) { - E element = cell._element; - LinkedHashSetCell next = cell._next; - int modifications = _modifications; - bool shouldRemove = (removeMatching == test(element)); - if (modifications != _modifications) { - throw new ConcurrentModificationError(this); - } - if (shouldRemove) remove(element); - cell = next; - } - } - - void clear() { - if (_length > 0) { - _strings = _nums = _rest = _first = _last = null; - _length = 0; - _modified(); - } - } - - bool _addHashTableEntry(var table, E element) { - LinkedHashSetCell cell = _getTableEntry(table, element); - if (cell != null) return false; - _setTableEntry(table, element, _newLinkedCell(element)); - return true; - } - - bool _removeHashTableEntry(var table, Object element) { - if (table == null) return false; - LinkedHashSetCell cell = _getTableEntry(table, element); - if (cell == null) return false; - _unlinkCell(cell); - _deleteTableEntry(table, element); - return true; - } - - void _modified() { - // Value cycles after 2^30 modifications. If you keep hold of an - // iterator for that long, you might miss a modification - // detection, and iteration can go sour. Don't do that. - _modifications = (_modifications + 1) & 0x3ffffff; - } - - // Create a new cell and link it in as the last one in the list. - LinkedHashSetCell _newLinkedCell(E element) { - LinkedHashSetCell cell = new LinkedHashSetCell(element); - if (_first == null) { - _first = _last = cell; - } else { - LinkedHashSetCell last = _last; - cell._previous = last; - _last = last._next = cell; - } - _length++; - _modified(); - return cell; - } - - // Unlink the given cell from the linked list of cells. - void _unlinkCell(LinkedHashSetCell cell) { - LinkedHashSetCell previous = cell._previous; - LinkedHashSetCell next = cell._next; - if (previous == null) { - assert(cell == _first); - _first = next; - } else { - previous._next = next; - } - if (next == null) { - assert(cell == _last); - _last = previous; - } else { - next._previous = previous; - } - _length--; - _modified(); - } - - static bool _isStringElement(var element) { - return element is String && element != '__proto__'; - } - - static bool _isNumericElement(var element) { - // Only treat unsigned 30-bit integers as numeric elements. This - // way, we avoid converting them to strings when we use them as - // keys in the JavaScript hash table object. - return element is num && - JS('bool', '(# & 0x3ffffff) === #', element, element); - } - - int _computeHashCode(var element) { - // We force the hash codes to be unsigned 30-bit integers to avoid - // issues with problematic elements like '__proto__'. Another - // option would be to throw an exception if the hash code isn't a - // number. - return JS('int', '# & 0x3ffffff', element.hashCode); - } - - static _getTableEntry(var table, var key) { - return JS('var', '#[#]', table, key); - } - - static void _setTableEntry(var table, var key, var value) { - assert(value != null); - JS('void', '#[#] = #', table, key, value); - } - - static void _deleteTableEntry(var table, var key) { - JS('void', 'delete #[#]', table, key); - } - - List _getBucket(var table, var element) { - var hash = _computeHashCode(element); - return JS('var', '#[#]', table, hash); - } - - int _findBucketIndex(var bucket, var element) { - if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i++) { - LinkedHashSetCell cell = JS('var', '#[#]', bucket, i); - if (cell._element == element) return i; - } - return -1; - } - - static _newHashTable() { - // Create a new JavaScript object to be used as a hash table. Use - // Object.create to avoid the properties on Object.prototype - // showing up as entries. - var table = JS('var', 'Object.create(null)'); - // Attempt to force the hash table into 'dictionary' mode by - // adding a property to it and deleting it again. - var temporaryKey = ''; - _setTableEntry(table, temporaryKey, table); - _deleteTableEntry(table, temporaryKey); - return table; - } -} -class _LinkedIdentityHashSet extends _LinkedHashSet { - Set _newSet() => new _LinkedIdentityHashSet(); - - int _computeHashCode(var key) { - // We force the hash codes to be unsigned 30-bit integers to avoid - // issues with problematic keys like '__proto__'. Another option - // would be to throw an exception if the hash code isn't a number. - return JS('int', '# & 0x3ffffff', identityHashCode(key)); - } - - int _findBucketIndex(var bucket, var element) { - if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i++) { - LinkedHashSetCell cell = JS('var', '#[#]', bucket, i); - if (identical(cell._element, element)) return i; - } - return -1; - } -} -class _LinkedCustomHashSet extends _LinkedHashSet { - _Equality _equality; - _Hasher _hasher; - _Predicate _validKey; - _LinkedCustomHashSet(this._equality, this._hasher, - bool validKey(Object potentialKey)) - : _validKey = (validKey != null) ? validKey : ((x) => x is E); - - Set _newSet() => - new _LinkedCustomHashSet(_equality, _hasher, _validKey); - - int _findBucketIndex(var bucket, var element) { - if (bucket == null) return -1; - int length = JS('int', '#.length', bucket); - for (int i = 0; i < length; i++) { - LinkedHashSetCell cell = JS('var', '#[#]', bucket, i); - if (_equality(cell._element, element)) return i; - } - return -1; - } - - int _computeHashCode(var element) { - // We force the hash codes to be unsigned 30-bit integers to avoid - // issues with problematic elements like '__proto__'. Another - // option would be to throw an exception if the hash code isn't a - // number. - return JS('int', '# & 0x3ffffff', _hasher(element)); - } - - bool add(E element) => super._add(element); - - bool contains(Object object) { - if (!_validKey(object)) return false; - return super._contains(object); - } - - E lookup(Object object) { - if (!_validKey(object)) return null; - return super._lookup(object); - } - - bool remove(Object object) { - if (!_validKey(object)) return false; - return super._remove(object); - } - - bool containsAll(Iterable elements) { - for (Object element in elements) { - if (!_validKey(element) || !this.contains(element)) return false; - } - return true; - } - - void removeAll(Iterable elements) { - for (Object element in elements) { - if (_validKey(element)) { - super._remove(element); - } - } - } -} -class LinkedHashSetCell { - final _element; - - LinkedHashSetCell _next; - LinkedHashSetCell _previous; - - LinkedHashSetCell(this._element); -} -class LinkedHashSetIterator implements Iterator { - final _set; - final int _modifications; - LinkedHashSetCell _cell; - E _current; - - LinkedHashSetIterator(this._set, this._modifications) { - _cell = _set._first; - } - - E get current => _current; - - bool moveNext() { - if (_modifications != _set._modifications) { - throw new ConcurrentModificationError(_set); - } else if (_cell == null) { - _current = null; - return false; - } else { - _current = _cell._element; - _cell = _cell._next; - return true; - } - } -} \ No newline at end of file diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/collections.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/collections.dart deleted file mode 100644 index fb9a94b8832d..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/collections.dart +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.collection; - -/** - * An unmodifiable [List] view of another List. - * - * The source of the elements may be a [List] or any [Iterable] with - * efficient [Iterable.length] and [Iterable.elementAt]. - */ -class UnmodifiableListView extends UnmodifiableListBase { - final Iterable _source; - /** Create an unmodifiable list backed by [source]. */ - UnmodifiableListView(Iterable source) : _source = source; - int get length => _source.length; - E operator[](int index) => _source.elementAt(index); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/hash_map.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/hash_map.dart deleted file mode 100644 index 0f98975e17c9..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/hash_map.dart +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.collection; - -/** Default function for equality comparison in customized HashMaps */ -bool _defaultEquals(Object a, Object b) => a == b; -/** Default function for hash-code computation in customized HashMaps */ -int _defaultHashCode(Object a) => a.hashCode; - -/** Type of custom equality function */ -typedef bool _Equality(K a, K b); -/** Type of custom hash code function. */ -typedef int _Hasher(K object); - -/** - * A hash-table based implementation of [Map]. - * - * The keys of a `HashMap` must have consistent [Object.operator==] - * and [Object.hashCode] implementations. This means that the `==` operator - * must define a stable equivalence relation on the keys (reflexive, - * symmetric, transitive, and consistent over time), and that `hashCode` - * must be the same for objects that are considered equal by `==`. - * - * The map allows `null` as a key. - * - * Iterating the map's keys, values or entries (through [forEach]) - * may happen in any order. - * The itearation order only changes when the map is modified. - * Values are iterated in the same order as their associated keys, - * so iterating the [keys] and [values] in parallel - * will give matching key and value pairs. - */ -abstract class HashMap implements Map { - /** - * Creates an unordered hash-table based [Map]. - * - * The created map is not ordered in any way. When iterating the keys or - * values, the iteration order is unspecified except that it will stay the - * same as long as the map isn't changed. - * - * If [equals] is provided, it is used to compare the keys in the table with - * new keys. If [equals] is omitted, the key's own [Object.operator==] is used - * instead. - * - * Similar, if [hashCode] is provided, it is used to produce a hash value - * for keys in order to place them in the hash table. If it is omitted, the - * key's own [Object.hashCode] is used. - * - * If using methods like [operator[]], [remove] and [containsKey] together - * with a custom equality and hashcode, an extra `isValidKey` function - * can be supplied. This function is called before calling [equals] or - * [hashCode] with an argument that may not be a [K] instance, and if the - * call returns false, the key is assumed to not be in the set. - * The [isValidKey] function defaults to just testing if the object is a - * [K] instance. - * - * The used `equals` and `hashCode` method should always be consistent, - * so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash - * of an object, or what it compares equal to, should not change while the - * object is in the table. If it does change, the result is unpredictable. - * - * If you supply one of [equals] and [hashCode], - * you should generally also to supply the other. - * An example would be using [identical] and [identityHashCode], - * which is equivalent to using the shorthand [HashMap.identity]). - */ - factory HashMap({ bool equals(K key1, K key2), - int hashCode(K key), - bool isValidKey(Object potentialKey) }) { - if (isValidKey == null) { - if (hashCode == null) { - if (equals == null) { - return new _HashMap(); - } - hashCode = _defaultHashCode; - } else { - if (identical(identityHashCode, hashCode) && - identical(identical, equals)) { - return new _IdentityHashMap(); - } - if (equals == null) { - equals = _defaultEquals; - } - } - } else { - if (hashCode == null) { - hashCode = _defaultHashCode; - } - if (equals == null) { - equals = _defaultEquals; - } - } - return new _CustomHashMap(equals, hashCode, isValidKey); - } - - /** - * Creates an unordered identity-based map. - * - * Effectively a shorthand for: - * - * new HashMap(equals: identical, hashCode: identityHashCodeOf) - */ - factory HashMap.identity() = _IdentityHashMap; - - /** - * Creates a [HashMap] that contains all key/value pairs of [other]. - */ - factory HashMap.from(Map other) { - HashMap result = new HashMap(); - other.forEach((k, v) { result[k] = v; }); - return result; - } - - /** - * Creates a [HashMap] where the keys and values are computed from the - * [iterable]. - * - * For each element of the [iterable] this constructor computes a key/value - * pair, by applying [key] and [value] respectively. - * - * The keys of the key/value pairs do not need to be unique. The last - * occurrence of a key will simply overwrite any previous value. - * - * If no values are specified for [key] and [value] the default is the - * identity function. - */ - factory HashMap.fromIterable(Iterable iterable, - {K key(element), V value(element)}) { - HashMap map = new HashMap(); - Maps._fillMapWithMappedIterable(map, iterable, key, value); - return map; - } - - /** - * Creates a [HashMap] associating the given [keys] to [values]. - * - * This constructor iterates over [keys] and [values] and maps each element of - * [keys] to the corresponding element of [values]. - * - * If [keys] contains the same object multiple times, the last occurrence - * overwrites the previous value. - * - * It is an error if the two [Iterable]s don't have the same length. - */ - factory HashMap.fromIterables(Iterable keys, Iterable values) { - HashMap map = new HashMap(); - Maps._fillMapWithIterables(map, keys, values); - return map; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/hash_set.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/hash_set.dart deleted file mode 100644 index 641890f4159c..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/hash_set.dart +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.collection; - -/** Common parts of [HashSet] and [LinkedHashSet] implementations. */ -abstract class _HashSetBase extends SetBase { - - // The following two methods override the ones in SetBase. - // It's possible to be more efficient if we have a way to create an empty - // set of the correct type. - - Set difference(Set other) { - Set result = _newSet(); - for (var element in this) { - if (!other.contains(element)) result.add(element); - } - return result; - } - - Set intersection(Set other) { - Set result = _newSet(); - for (var element in this) { - if (other.contains(element)) result.add(element); - } - return result; - } - - Set _newSet(); - - // Subclasses can optimize this further. - Set toSet() => _newSet()..addAll(this); -} - -/** - * An unordered hash-table based [Set] implementation. - * - * The elements of a `HashSet` must have consistent equality - * and hashCode implementations. This means that the equals operation - * must define a stable equivalence relation on the elements (reflexive, - * symmetric, transitive, and consistent over time), and that the hashCode - * must consistent with equality, so that the same for objects that are - * considered equal. - * - * The set allows `null` as an element. - * - * Most simple operations on `HashSet` are done in (potentially amorteized) - * constant time: [add], [contains], [remove], and [length], provided the hash - * codes of objects are well distributed. - */ -abstract class HashSet implements Set { - /** - * Create a hash set using the provided [equals] as equality. - * - * The provided [equals] must define a stable equivalence relation, and - * [hashCode] must be consistent with [equals]. If the [equals] or [hashCode] - * methods won't work on all objects, but only to instances of E, the - * [isValidKey] predicate can be used to restrict the keys that they are - * applied to. Any key for which [isValidKey] returns false is automatically - * assumed to not be in the set. - * - * If [equals] or [hashCode] are omitted, the set uses - * the objects' intrinsic [Object.operator==] and [Object.hashCode]. - * - * If [isValidKey] is omitted, it defaults to testing if the object is an - * [E] instance. - * - * If you supply one of [equals] and [hashCode], - * you should generally also to supply the other. - * An example would be using [identical] and [identityHashCode], - * which is equivalent to using the shorthand [LinkedSet.identity]). - */ - factory HashSet({ bool equals(E e1, E e2), - int hashCode(E e), - bool isValidKey(Object potentialKey) }) { - if (isValidKey == null) { - if (hashCode == null) { - if (equals == null) { - return new _HashSet(); - } - hashCode = _defaultHashCode; - } else { - if (identical(identityHashCode, hashCode) && - identical(identical, equals)) { - return new _IdentityHashSet(); - } - if (equals == null) { - equals = _defaultEquals; - } - } - } else { - if (hashCode == null) { - hashCode = _defaultHashCode; - } - if (equals == null) { - equals = _defaultEquals; - } - } - return new _CustomHashSet(equals, hashCode, isValidKey); - } - - /** - * Creates an unordered identity-based set. - * - * Effectively a shorthand for: - * - * new HashSet(equals: identical, hashCode: identityHashCodeOf) - */ - factory HashSet.identity() = _IdentityHashSet; - - /** - * Create a hash set containing all [elements]. - * - * Creates a hash set as by `new HashSet()` and adds each element of - * `elements` to this set in the order they are iterated. - * - * All the [elements] should be assignable to [E]. - * The `elements` iterable itself may have any element type, so this - * constructor can be used to down-cast a `Set`, for example as: - * - * Set superSet = ...; - * Set subSet = - * new HashSet.from(superSet.where((e) => e is SubType)); - */ - factory HashSet.from(Iterable elements) { - HashSet result = new HashSet(); - for (E e in elements) result.add(e); - return result; - } - - /** - * Provides an iterator that iterates over the elements of this set. - * - * The order of iteration is unspecified, - * but consistent between changes to the set. - */ - Iterator get iterator; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/iterable.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/iterable.dart deleted file mode 100644 index 8020e7e68fa8..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/iterable.dart +++ /dev/null @@ -1,600 +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. - -part of dart.collection; - -/** - * This [Iterable] mixin implements all [Iterable] members except `iterator`. - * - * All other methods are implemented in terms of `iterator`. - */ -abstract class IterableMixin implements Iterable { - // This class has methods copied verbatim into: - // - IterableBase - // - SetMixin - // If changing a method here, also change the other copies. - - Iterable map(f(E element)) => new MappedIterable(this, f); - - Iterable where(bool f(E element)) => new WhereIterable(this, f); - - Iterable expand(Iterable f(E element)) => - new ExpandIterable(this, f); - - bool contains(Object element) { - for (E e in this) { - if (e == element) return true; - } - return false; - } - - void forEach(void f(E element)) { - for (E element in this) f(element); - } - - E reduce(E combine(E value, E element)) { - Iterator iterator = this.iterator; - if (!iterator.moveNext()) { - throw IterableElementError.noElement(); - } - E value = iterator.current; - while (iterator.moveNext()) { - value = combine(value, iterator.current); - } - return value; - } - - dynamic fold(var initialValue, - dynamic combine(var previousValue, E element)) { - var value = initialValue; - for (E element in this) value = combine(value, element); - return value; - } - - bool every(bool f(E element)) { - for (E element in this) { - if (!f(element)) return false; - } - return true; - } - - String join([String separator = ""]) { - Iterator iterator = this.iterator; - if (!iterator.moveNext()) return ""; - StringBuffer buffer = new StringBuffer(); - if (separator == null || separator == "") { - do { - buffer.write("${iterator.current}"); - } while (iterator.moveNext()); - } else { - buffer.write("${iterator.current}"); - while (iterator.moveNext()) { - buffer.write(separator); - buffer.write("${iterator.current}"); - } - } - return buffer.toString(); - } - - bool any(bool f(E element)) { - for (E element in this) { - if (f(element)) return true; - } - return false; - } - - List toList({ bool growable: true }) => - new List.from(this, growable: growable); - - Set toSet() => new Set.from(this); - - int get length { - assert(this is! EfficientLength); - int count = 0; - Iterator it = iterator; - while (it.moveNext()) { - count++; - } - return count; - } - - bool get isEmpty => !iterator.moveNext(); - - bool get isNotEmpty => !isEmpty; - - Iterable take(int n) { - return new TakeIterable(this, n); - } - - Iterable takeWhile(bool test(E value)) { - return new TakeWhileIterable(this, test); - } - - Iterable skip(int n) { - return new SkipIterable(this, n); - } - - Iterable skipWhile(bool test(E value)) { - return new SkipWhileIterable(this, test); - } - - E get first { - Iterator it = iterator; - if (!it.moveNext()) { - throw IterableElementError.noElement(); - } - return it.current; - } - - E get last { - Iterator it = iterator; - if (!it.moveNext()) { - throw IterableElementError.noElement(); - } - E result; - do { - result = it.current; - } while(it.moveNext()); - return result; - } - - E get single { - Iterator it = iterator; - if (!it.moveNext()) throw IterableElementError.noElement(); - E result = it.current; - if (it.moveNext()) throw IterableElementError.tooMany(); - return result; - } - - E firstWhere(bool test(E value), { E orElse() }) { - for (E element in this) { - if (test(element)) return element; - } - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - E lastWhere(bool test(E value), { E orElse() }) { - E result = null; - bool foundMatching = false; - for (E element in this) { - if (test(element)) { - result = element; - foundMatching = true; - } - } - if (foundMatching) return result; - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - E singleWhere(bool test(E value)) { - E result = null; - bool foundMatching = false; - for (E element in this) { - if (test(element)) { - if (foundMatching) { - throw IterableElementError.tooMany(); - } - result = element; - foundMatching = true; - } - } - if (foundMatching) return result; - throw IterableElementError.noElement(); - } - - E elementAt(int index) { - if (index is! int) throw new ArgumentError.notNull("index"); - RangeError.checkNotNegative(index, "index"); - int elementIndex = 0; - for (E element in this) { - if (index == elementIndex) return element; - elementIndex++; - } - throw new RangeError.index(index, this, "index", null, elementIndex); - } - - - String toString() => IterableBase.iterableToShortString(this, '(', ')'); -} - -/** - * Base class for implementing [Iterable]. - * - * This class implements all methods of [Iterable] except [Iterable.iterator] - * in terms of `iterator`. - */ -abstract class IterableBase implements Iterable { - // TODO(lrn): Base this on IterableMixin if there ever becomes a way - // to combine const constructors and mixins. - const IterableBase(); - - Iterable map(f(E element)) => new MappedIterable(this, f); - - Iterable where(bool f(E element)) => new WhereIterable(this, f); - - Iterable expand(Iterable f(E element)) => - new ExpandIterable(this, f); - - bool contains(Object element) { - for (E e in this) { - if (e == element) return true; - } - return false; - } - - void forEach(void f(E element)) { - for (E element in this) f(element); - } - - E reduce(E combine(E value, E element)) { - Iterator iterator = this.iterator; - if (!iterator.moveNext()) { - throw IterableElementError.noElement(); - } - E value = iterator.current; - while (iterator.moveNext()) { - value = combine(value, iterator.current); - } - return value; - } - - dynamic fold(var initialValue, - dynamic combine(var previousValue, E element)) { - var value = initialValue; - for (E element in this) value = combine(value, element); - return value; - } - - bool every(bool f(E element)) { - for (E element in this) { - if (!f(element)) return false; - } - return true; - } - - String join([String separator = ""]) { - Iterator iterator = this.iterator; - if (!iterator.moveNext()) return ""; - StringBuffer buffer = new StringBuffer(); - if (separator == null || separator == "") { - do { - buffer.write("${iterator.current}"); - } while (iterator.moveNext()); - } else { - buffer.write("${iterator.current}"); - while (iterator.moveNext()) { - buffer.write(separator); - buffer.write("${iterator.current}"); - } - } - return buffer.toString(); - } - - bool any(bool f(E element)) { - for (E element in this) { - if (f(element)) return true; - } - return false; - } - - List toList({ bool growable: true }) => - new List.from(this, growable: growable); - - Set toSet() => new Set.from(this); - - int get length { - assert(this is! EfficientLength); - int count = 0; - Iterator it = iterator; - while (it.moveNext()) { - count++; - } - return count; - } - - bool get isEmpty => !iterator.moveNext(); - - bool get isNotEmpty => !isEmpty; - - Iterable take(int n) { - return new TakeIterable(this, n); - } - - Iterable takeWhile(bool test(E value)) { - return new TakeWhileIterable(this, test); - } - - Iterable skip(int n) { - return new SkipIterable(this, n); - } - - Iterable skipWhile(bool test(E value)) { - return new SkipWhileIterable(this, test); - } - - E get first { - Iterator it = iterator; - if (!it.moveNext()) { - throw IterableElementError.noElement(); - } - return it.current; - } - - E get last { - Iterator it = iterator; - if (!it.moveNext()) { - throw IterableElementError.noElement(); - } - E result; - do { - result = it.current; - } while(it.moveNext()); - return result; - } - - E get single { - Iterator it = iterator; - if (!it.moveNext()) throw IterableElementError.noElement(); - E result = it.current; - if (it.moveNext()) throw IterableElementError.tooMany(); - return result; - } - - E firstWhere(bool test(E value), { E orElse() }) { - for (E element in this) { - if (test(element)) return element; - } - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - E lastWhere(bool test(E value), { E orElse() }) { - E result = null; - bool foundMatching = false; - for (E element in this) { - if (test(element)) { - result = element; - foundMatching = true; - } - } - if (foundMatching) return result; - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - E singleWhere(bool test(E value)) { - E result = null; - bool foundMatching = false; - for (E element in this) { - if (test(element)) { - if (foundMatching) { - throw IterableElementError.tooMany(); - } - result = element; - foundMatching = true; - } - } - if (foundMatching) return result; - throw IterableElementError.noElement(); - } - - E elementAt(int index) { - if (index is! int) throw new ArgumentError.notNull("index"); - RangeError.checkNotNegative(index, "index"); - int elementIndex = 0; - for (E element in this) { - if (index == elementIndex) return element; - elementIndex++; - } - throw new RangeError.index(index, this, "index", null, elementIndex); - } - - /** - * Returns a string representation of (some of) the elements of `this`. - * - * Elements are represented by their own `toString` results. - * - * The representation always contains the first three elements. - * If there are less than a hundred elements in the iterable, it also - * contains the last two elements. - * - * If the resulting string isn't above 80 characters, more elements are - * included from the start of the iterable. - * - * The conversion may omit calling `toString` on some elements if they - * are known to not occur in the output, and it may stop iterating after - * a hundred elements. - */ - String toString() => iterableToShortString(this, '(', ')'); - - /** - * Convert an `Iterable` to a string like [IterableBase.toString]. - * - * Allows using other delimiters than '(' and ')'. - * - * Handles circular references where converting one of the elements - * to a string ends up converting [iterable] to a string again. - */ - static String iterableToShortString(Iterable iterable, - [String leftDelimiter = '(', - String rightDelimiter = ')']) { - if (_isToStringVisiting(iterable)) { - if (leftDelimiter == "(" && rightDelimiter == ")") { - // Avoid creating a new string in the "common" case. - return "(...)"; - } - return "$leftDelimiter...$rightDelimiter"; - } - List parts = []; - _toStringVisiting.add(iterable); - try { - _iterablePartsToStrings(iterable, parts); - } finally { - assert(identical(_toStringVisiting.last, iterable)); - _toStringVisiting.removeLast(); - } - return (new StringBuffer(leftDelimiter) - ..writeAll(parts, ", ") - ..write(rightDelimiter)).toString(); - } - - /** - * Converts an `Iterable` to a string. - * - * Converts each elements to a string, and separates the results by ", ". - * Then wraps the result in [leftDelimiter] and [rightDelimiter]. - * - * Unlike [iterableToShortString], this conversion doesn't omit any - * elements or puts any limit on the size of the result. - * - * Handles circular references where converting one of the elements - * to a string ends up converting [iterable] to a string again. - */ - static String iterableToFullString(Iterable iterable, - [String leftDelimiter = '(', - String rightDelimiter = ')']) { - if (_isToStringVisiting(iterable)) { - return "$leftDelimiter...$rightDelimiter"; - } - StringBuffer buffer = new StringBuffer(leftDelimiter); - _toStringVisiting.add(iterable); - try { - buffer.writeAll(iterable, ", "); - } finally { - assert(identical(_toStringVisiting.last, iterable)); - _toStringVisiting.removeLast(); - } - buffer.write(rightDelimiter); - return buffer.toString(); - } - - /** A set used to identify cyclic lists during toString() calls. */ - static final List _toStringVisiting = []; - - /** Check if we are currently visiting `o` in a toString call. */ - static bool _isToStringVisiting(Object o) { - for (int i = 0; i < _toStringVisiting.length; i++) { - if (identical(o, _toStringVisiting[i])) return true; - } - return false; - } - - /** - * Convert elments of [iterable] to strings and store them in [parts]. - */ - static void _iterablePartsToStrings(Iterable iterable, List parts) { - /* - * This is the complicated part of [iterableToShortString]. - * It is extracted as a separate function to avoid having too much code - * inside the try/finally. - */ - /// Try to stay below this many characters. - const int LENGTH_LIMIT = 80; - /// Always at least this many elements at the start. - const int HEAD_COUNT = 3; - /// Always at least this many elements at the end. - const int TAIL_COUNT = 2; - /// Stop iterating after this many elements. Iterables can be infinite. - const int MAX_COUNT = 100; - // Per entry length overhead. It's for ", " for all after the first entry, - // and for "(" and ")" for the initial entry. By pure luck, that's the same - // number. - const int OVERHEAD = 2; - const int ELLIPSIS_SIZE = 3; // "...".length. - - int length = 0; - int count = 0; - Iterator it = iterable.iterator; - // Initial run of elements, at least HEAD_COUNT, and then continue until - // passing at most LENGTH_LIMIT characters. - while (length < LENGTH_LIMIT || count < HEAD_COUNT) { - if (!it.moveNext()) return; - String next = "${it.current}"; - parts.add(next); - length += next.length + OVERHEAD; - count++; - } - - String penultimateString; - String ultimateString; - - // Find last two elements. One or more of them may already be in the - // parts array. Include their length in `length`. - var penultimate = null; - var ultimate = null; - if (!it.moveNext()) { - if (count <= HEAD_COUNT + TAIL_COUNT) return; - ultimateString = parts.removeLast(); - penultimateString = parts.removeLast(); - } else { - penultimate = it.current; - count++; - if (!it.moveNext()) { - if (count <= HEAD_COUNT + 1) { - parts.add("$penultimate"); - return; - } - ultimateString = "$penultimate"; - penultimateString = parts.removeLast(); - length += ultimateString.length + OVERHEAD; - } else { - ultimate = it.current; - count++; - // Then keep looping, keeping the last two elements in variables. - assert(count < MAX_COUNT); - while (it.moveNext()) { - penultimate = ultimate; - ultimate = it.current; - count++; - if (count > MAX_COUNT) { - // If we haven't found the end before MAX_COUNT, give up. - // This cannot happen in the code above because each entry - // increases length by at least two, so there is no way to - // visit more than ~40 elements before this loop. - - // Remove any surplus elements until length, including ", ...)", - // is at most LENGTH_LIMIT. - while (length > LENGTH_LIMIT - ELLIPSIS_SIZE - OVERHEAD && - count > HEAD_COUNT) { - length -= parts.removeLast().length + OVERHEAD; - count--; - } - parts.add("..."); - return; - } - } - penultimateString = "$penultimate"; - ultimateString = "$ultimate"; - length += - ultimateString.length + penultimateString.length + 2 * OVERHEAD; - } - } - - // If there is a gap between the initial run and the last two, - // prepare to add an ellipsis. - String elision = null; - if (count > parts.length + TAIL_COUNT) { - elision = "..."; - length += ELLIPSIS_SIZE + OVERHEAD; - } - - // If the last two elements were very long, and we have more than - // HEAD_COUNT elements in the initial run, drop some to make room for - // the last two. - while (length > LENGTH_LIMIT && parts.length > HEAD_COUNT) { - length -= parts.removeLast().length + OVERHEAD; - if (elision == null) { - elision = "..."; - length += ELLIPSIS_SIZE + OVERHEAD; - } - } - if (elision != null) { - parts.add(elision); - } - parts.add(penultimateString); - parts.add(ultimateString); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/iterator.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/iterator.dart deleted file mode 100644 index 1fe49cd2dc4d..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/iterator.dart +++ /dev/null @@ -1,45 +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. - -part of dart.collection; - -/** - * The [HasNextIterator] class wraps an [Iterator] and provides methods to - * iterate over an object using `hasNext` and `next`. - * - * An [HasNextIterator] does not implement the [Iterator] interface. - */ -class HasNextIterator { - static const int _HAS_NEXT_AND_NEXT_IN_CURRENT = 0; - static const int _NO_NEXT = 1; - static const int _NOT_MOVED_YET = 2; - - Iterator _iterator; - int _state = _NOT_MOVED_YET; - - HasNextIterator(this._iterator); - - bool get hasNext { - if (_state == _NOT_MOVED_YET) _move(); - return _state == _HAS_NEXT_AND_NEXT_IN_CURRENT; - } - - E next() { - // Call to hasNext is necessary to make sure we are positioned at the first - // element when we start iterating. - if (!hasNext) throw new StateError("No more elements"); - assert(_state == _HAS_NEXT_AND_NEXT_IN_CURRENT); - E result = _iterator.current; - _move(); - return result; - } - - void _move() { - if (_iterator.moveNext()) { - _state = _HAS_NEXT_AND_NEXT_IN_CURRENT; - } else { - _state = _NO_NEXT; - } - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/linked_hash_map.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/linked_hash_map.dart deleted file mode 100644 index 098767eccf80..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/linked_hash_map.dart +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.collection; - -/** - * A hash-table based implementation of [Map]. - * - * The insertion order of keys is remembered, - * and keys are iterated in the order they were inserted into the map. - * Values are iterated in their corresponding key's order. - * Changing a key's value, when the key is already in the map, - * does not change the iteration order, - * but removing the key and adding it again - * will make it be last in the iteration order. - * - * The keys of a `LinkedHashMap` must have consistent [Object.operator==] - * and [Object.hashCode] implementations. This means that the `==` operator - * must define a stable equivalence relation on the keys (reflexive, - * symmetric, transitive, and consistent over time), and that `hashCode` - * must be the same for objects that are considered equal by `==`. - * - * The map allows `null` as a key. - */ -abstract class LinkedHashMap implements HashMap { - /** - * Creates an insertion-ordered hash-table based [Map]. - * - * If [equals] is provided, it is used to compare the keys in the table with - * new keys. If [equals] is omitted, the key's own [Object.operator==] is used - * instead. - * - * Similar, if [hashCode] is provided, it is used to produce a hash value - * for keys in order to place them in the hash table. If it is omitted, the - * key's own [Object.hashCode] is used. - * - * If using methods like [operator[]], [remove] and [containsKey] together - * with a custom equality and hashcode, an extra `isValidKey` function - * can be supplied. This function is called before calling [equals] or - * [hashCode] with an argument that may not be a [K] instance, and if the - * call returns false, the key is assumed to not be in the set. - * The [isValidKey] function defaults to just testing if the object is a - * [K] instance. - * - * The used `equals` and `hashCode` method should always be consistent, - * so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash - * of an object, or what it compares equal to, should not change while the - * object is in the table. If it does change, the result is unpredictable. - * - * If you supply one of [equals] and [hashCode], - * you should generally also to supply the other. - * An example would be using [identical] and [identityHashCode], - * which is equivalent to using the shorthand [LinkedHashMap.identity]). - */ - factory LinkedHashMap({ bool equals(K key1, K key2), - int hashCode(K key), - bool isValidKey(Object potentialKey) }) { - if (isValidKey == null) { - if (hashCode == null) { - if (equals == null) { - return new _LinkedHashMap(); - } - hashCode = _defaultHashCode; - } else { - if (identical(identityHashCode, hashCode) && - identical(identical, equals)) { - return new _LinkedIdentityHashMap(); - } - if (equals == null) { - equals = _defaultEquals; - } - } - } else { - if (hashCode == null) { - hashCode = _defaultHashCode; - } - if (equals == null) { - equals = _defaultEquals; - } - } - return new _LinkedCustomHashMap(equals, hashCode, isValidKey); - } - - /** - * Creates an insertion-ordered identity-based map. - * - * Effectively a shorthand for: - * - * new LinkedHashMap(equals: identical, hashCode: identityHashCodeOf) - */ - factory LinkedHashMap.identity() = _LinkedIdentityHashMap; - - /** - * Creates a [LinkedHashMap] that contains all key value pairs of [other]. - */ - factory LinkedHashMap.from(Map other) { - LinkedHashMap result = new LinkedHashMap(); - other.forEach((k, v) { result[k] = v; }); - return result; - } - - /** - * Creates a [LinkedHashMap] where the keys and values are computed from the - * [iterable]. - * - * For each element of the [iterable] this constructor computes a key/value - * pair, by applying [key] and [value] respectively. - * - * The keys of the key/value pairs do not need to be unique. The last - * occurrence of a key will simply overwrite any previous value. - * - * If no values are specified for [key] and [value] the default is the - * identity function. - */ - factory LinkedHashMap.fromIterable(Iterable iterable, - {K key(element), V value(element)}) { - LinkedHashMap map = new LinkedHashMap(); - Maps._fillMapWithMappedIterable(map, iterable, key, value); - return map; - } - - /** - * Creates a [LinkedHashMap] associating the given [keys] to [values]. - * - * This constructor iterates over [keys] and [values] and maps each element of - * [keys] to the corresponding element of [values]. - * - * If [keys] contains the same object multiple times, the last occurrence - * overwrites the previous value. - * - * It is an error if the two [Iterable]s don't have the same length. - */ - factory LinkedHashMap.fromIterables(Iterable keys, Iterable values) { - LinkedHashMap map = new LinkedHashMap(); - Maps._fillMapWithIterables(map, keys, values); - return map; - } - - @NoInline() - factory LinkedHashMap._literal(List keyValuePairs) { - return fillLiteralMap(keyValuePairs, new _LinkedHashMap()); - } - - @NoThrows() @NoInline() - factory LinkedHashMap._empty() { - return new _LinkedHashMap(); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/linked_hash_set.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/linked_hash_set.dart deleted file mode 100644 index 14ba17e6094e..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/linked_hash_set.dart +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.collection; - -/** - * A [LinkedHashSet] is a hash-table based [Set] implementation. - * - * The `LinkedHashSet` also keep track of the order that elements were inserted - * in, and iteration happens in first-to-last insertion order. - * - * The elements of a `LinkedHashSet` must have consistent [Object.operator==] - * and [Object.hashCode] implementations. This means that the `==` operator - * must define a stable equivalence relation on the elements (reflexive, - * symmetric, transitive, and consistent over time), and that `hashCode` - * must be the same for objects that are considered equal by `==`. - * - * The set allows `null` as an element. - * - * Iteration of elements is done in element insertion order. - * An element that was added after another will occur later in the iteration. - * Adding an element that is already in the set - * does not change its position in the iteration order, - * but removing an element and adding it again, - * will make it the last element of an iteration. - * - * Most simple operations on `HashSet` are done in (potentially amortized) - * constant time: [add], [contains], [remove], and [length], provided the hash - * codes of objects are well distributed.. - */ -abstract class LinkedHashSet implements HashSet { - /** - * Create an insertion-ordered hash set using the provided - * [equals] and [hashCode]. - * - * The provided [equals] must define a stable equivalence relation, and - * [hashCode] must be consistent with [equals]. If the [equals] or [hashCode] - * methods won't work on all objects, but only to instances of E, the - * [isValidKey] predicate can be used to restrict the keys that they are - * applied to. Any key for which [isValidKey] returns false is automatically - * assumed to not be in the set. - * - * If [equals] or [hashCode] are omitted, the set uses - * the objects' intrinsic [Object.operator==] and [Object.hashCode], - * - * If [isValidKey] is omitted, it defaults to testing if the object is an - * [E] instance. - * - * If you supply one of [equals] and [hashCode], - * you should generally also to supply the other. - * An example would be using [identical] and [identityHashCode], - * which is equivalent to using the shorthand [LinkedSet.identity]). - */ - factory LinkedHashSet({ bool equals(E e1, E e2), - int hashCode(E e), - bool isValidKey(Object potentialKey) }) { - if (isValidKey == null) { - if (hashCode == null) { - if (equals == null) { - return new _LinkedHashSet(); - } - hashCode = _defaultHashCode; - } else { - if (identical(identityHashCode, hashCode) && - identical(identical, equals)) { - return new _LinkedIdentityHashSet(); - } - if (equals == null) { - equals = _defaultEquals; - } - } - } else { - if (hashCode == null) { - hashCode = _defaultHashCode; - } - if (equals == null) { - equals = _defaultEquals; - } - } - return new _LinkedCustomHashSet(equals, hashCode, isValidKey); - } - - /** - * Creates an insertion-ordered identity-based set. - * - * Effectively a shorthand for: - * - * new LinkedHashSet(equals: identical, hashCode: identityHashCodeOf) - */ - factory LinkedHashSet.identity() = _LinkedIdentityHashSet; - - /** - * Create a linked hash set containing all [elements]. - * - * Creates a linked hash set as by `new LinkedHashSet()` and adds each - * element of`elements` to this set in the order they are iterated. - * - * All the [elements] should be assignable to [E]. - * The `elements` iterable itself may have any element type, - * so this constructor can be used to down-cast a `Set`, for example as: - * - * Set superSet = ...; - * Iterable tmp = superSet.where((e) => e is SubType); - * Set subSet = new LinkedHashSet.from(tmp); - */ - factory LinkedHashSet.from(Iterable elements) { - LinkedHashSet result = new LinkedHashSet(); - for (final E element in elements) { - result.add(element); - } - return result; - } - - /** - * Executes a function on each element of the set. - * - * The elements are iterated in insertion order. - */ - void forEach(void action(E element)); - - /** - * Provides an iterator that iterates over the elements in insertion order. - */ - Iterator get iterator; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/linked_list.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/linked_list.dart deleted file mode 100644 index 5bff429b98b8..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/linked_list.dart +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.collection; - - -/** - * A specialized double-linked list of elements that extends [LinkedListEntry]. - * - * This is not a generic data structure. It only accepts elements that extend - * the [LinkedListEntry] class. See the [Queue] implementations for - * generic collections that allow constant time adding and removing at the ends. - * - * This is not a [List] implementation. Despite its name, this class does not - * implement the [List] interface. It does not allow constant time lookup by - * index. - * - * Because the elements themselves contain the links of this linked list, - * each element can be in only one list at a time. To add an element to another - * list, it must first be removed from its current list (if any). - * - * In return, each element knows its own place in the linked list, as well as - * which list it is in. This allows constant time [LinkedListEntry.addAfter], - * [LinkedListEntry.addBefore] and [LinkedListEntry.unlink] operations - * when all you have is the element. - * - * A `LinkedList` also allows constant time adding and removing at either end, - * and a constant time length getter. - */ -class LinkedList> - extends IterableBase - implements _LinkedListLink { - - int _modificationCount = 0; - int _length = 0; - _LinkedListLink _next; - _LinkedListLink _previous; - - /** - * Construct a new empty linked list. - */ - LinkedList() { - _next = _previous = this; - } - - /** - * Add [entry] to the beginning of the linked list. - */ - void addFirst(E entry) { - _insertAfter(this, entry); - } - - /** - * Add [entry] to the end of the linked list. - */ - void add(E entry) { - _insertAfter(_previous, entry); - } - - /** - * Add [entries] to the end of the linked list. - */ - void addAll(Iterable entries) { - entries.forEach((entry) => _insertAfter(_previous, entry)); - } - - /** - * Remove [entry] from the linked list. - * - * Returns false and does nothing if [entry] is not in this linked list. - * - * This is equivalent to calling `entry.unlink()` if the entry is in this - * list. - */ - bool remove(E entry) { - if (entry._list != this) return false; - _unlink(entry); // Unlink will decrement length. - return true; - } - - Iterator get iterator => new _LinkedListIterator(this); - - int get length => _length; - - /** - * Remove all elements from this linked list. - */ - void clear() { - _modificationCount++; - _LinkedListLink next = _next; - while (!identical(next, this)) { - E entry = next; - next = entry._next; - entry._next = entry._previous = entry._list = null; - } - _next = _previous = this; - _length = 0; - } - - E get first { - if (identical(_next, this)) { - throw new StateError('No such element'); - } - return _next; - } - - E get last { - if (identical(_previous, this)) { - throw new StateError('No such element'); - } - return _previous; - } - - E get single { - if (identical(_previous, this)) { - throw new StateError('No such element'); - } - if (!identical(_previous, _next)) { - throw new StateError('Too many elements'); - } - return _next; - } - - /** - * Call [action] with each entry in this linked list. - * - * It's an error if [action] modify the linked list. - */ - void forEach(void action(E entry)) { - int modificationCount = _modificationCount; - _LinkedListLink current = _next; - while (!identical(current, this)) { - action(current); - if (modificationCount != _modificationCount) { - throw new ConcurrentModificationError(this); - } - current = current._next; - } - } - - bool get isEmpty => _length == 0; - - void _insertAfter(_LinkedListLink entry, E newEntry) { - if (newEntry.list != null) { - throw new StateError( - 'LinkedListEntry is already in a LinkedList'); - } - _modificationCount++; - newEntry._list = this; - var predecessor = entry; - var successor = entry._next; - successor._previous = newEntry; - newEntry._previous = predecessor; - newEntry._next = successor; - predecessor._next = newEntry; - _length++; - } - - void _unlink(LinkedListEntry entry) { - _modificationCount++; - entry._next._previous = entry._previous; - entry._previous._next = entry._next; - _length--; - entry._list = entry._next = entry._previous = null; - } -} - - -class _LinkedListIterator> - implements Iterator { - final LinkedList _list; - final int _modificationCount; - E _current; - _LinkedListLink _next; - - _LinkedListIterator(LinkedList list) - : _list = list, - _modificationCount = list._modificationCount, - _next = list._next; - - E get current => _current; - - bool moveNext() { - if (identical(_next, _list)) { - _current = null; - return false; - } - if (_modificationCount != _list._modificationCount) { - throw new ConcurrentModificationError(this); - } - _current = _next; - _next = _next._next; - return true; - } -} - - -class _LinkedListLink { - _LinkedListLink _next; - _LinkedListLink _previous; -} - - -/** - * An object that can be an element in a [LinkedList]. - * - * All elements of a `LinkedList` must extend this class. - * The class provides the internal links that link elements together - * in the `LinkedList`, and a reference to the linked list itself - * that an element is currently part of. - * - * An entry can be in at most one linked list at a time. - * While an entry is in a linked list, the [list] property points to that - * linked list, and otherwise the `list` property is `null`. - * - * When created, an entry is not in any linked list. - */ -abstract class LinkedListEntry> - implements _LinkedListLink { - LinkedList _list; - _LinkedListLink _next; - _LinkedListLink _previous; - - /** - * Get the linked list containing this element. - * - * Returns `null` if this entry is not currently in any list. - */ - LinkedList get list => _list; - - /** - * Unlink the element from its linked list. - * - * The entry must currently be in a linked list when this method is called. - */ - void unlink() { - _list._unlink(this); - } - - /** - * Return the succeessor of this element in its linked list. - * - * Returns `null` if there is no successor in the linked list, or if this - * entry is not currently in any list. - */ - E get next { - if (identical(_next, _list)) return null; - E result = _next; - return result; - } - - /** - * Return the predecessor of this element in its linked list. - * - * Returns `null` if there is no predecessor in the linked list, or if this - * entry is not currently in any list. - */ - E get previous { - if (identical(_previous, _list)) return null; - return _previous as E; - } - - /** - * Insert an element after this element in this element's linked list. - * - * This entry must be in a linked list when this method is called. - * The [entry] must not be in a linked list. - */ - void insertAfter(E entry) { - _list._insertAfter(this, entry); - } - - /** - * Insert an element before this element in this element's linked list. - * - * This entry must be in a linked list when this method is called. - * The [entry] must not be in a linked list. - */ - void insertBefore(E entry) { - _list._insertAfter(_previous, entry); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/list.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/list.dart deleted file mode 100644 index dd0c14a43042..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/list.dart +++ /dev/null @@ -1,500 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.collection; - -/** - * Abstract implementation of a list. - * - * `ListBase` can be used as a base class for implementing the `List` interface. - * - * 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/wrappers.dart" instead. - */ -abstract class ListBase extends Object with ListMixin { - /** - * Convert a `List` to a string as `[each, element, as, string]`. - * - * Handles circular references where converting one of the elements - * to a string ends up converting [list] to a string again. - */ - static String listToString(List list) => - IterableBase.iterableToFullString(list, '[', ']'); -} - -/** - * Base implementation of a [List] class. - * - * `ListMixin` can be used as a mixin to make a class implement - * the `List` interface. - * - * 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/wrappers.dart" instead. - */ -abstract class ListMixin implements List { - // Iterable interface. - Iterator get iterator => new ListIterator(this); - - E elementAt(int index) => this[index]; - - void forEach(void action(E element)) { - int length = this.length; - for (int i = 0; i < length; i++) { - action(this[i]); - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - } - - bool get isEmpty => length == 0; - - bool get isNotEmpty => !isEmpty; - - E get first { - if (length == 0) throw IterableElementError.noElement(); - return this[0]; - } - - E get last { - if (length == 0) throw IterableElementError.noElement(); - return this[length - 1]; - } - - E get single { - if (length == 0) throw IterableElementError.noElement(); - if (length > 1) throw IterableElementError.tooMany(); - return this[0]; - } - - bool contains(Object element) { - int length = this.length; - for (int i = 0; i < this.length; i++) { - if (this[i] == element) return true; - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - return false; - } - - bool every(bool test(E element)) { - int length = this.length; - for (int i = 0; i < length; i++) { - if (!test(this[i])) return false; - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - return true; - } - - bool any(bool test(E element)) { - int length = this.length; - for (int i = 0; i < length; i++) { - if (test(this[i])) return true; - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - return false; - } - - E firstWhere(bool test(E element), { E orElse() }) { - int length = this.length; - for (int i = 0; i < length; i++) { - E element = this[i]; - if (test(element)) return element; - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - E lastWhere(bool test(E element), { E orElse() }) { - int length = this.length; - for (int i = length - 1; i >= 0; i--) { - E element = this[i]; - if (test(element)) return element; - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - E singleWhere(bool test(E element)) { - int length = this.length; - E match = null; - bool matchFound = false; - for (int i = 0; i < length; i++) { - E element = this[i]; - if (test(element)) { - if (matchFound) { - throw IterableElementError.tooMany(); - } - matchFound = true; - match = element; - } - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - if (matchFound) return match; - throw IterableElementError.noElement(); - } - - String join([String separator = ""]) { - if (length == 0) return ""; - StringBuffer buffer = new StringBuffer()..writeAll(this, separator); - return buffer.toString(); - } - - Iterable where(bool test(E element)) => new WhereIterable(this, test); - - Iterable map(f(E element)) => new MappedListIterable(this, f); - - Iterable expand(Iterable f(E element)) => - new ExpandIterable(this, f); - - E reduce(E combine(E previousValue, E element)) { - int length = this.length; - if (length == 0) throw IterableElementError.noElement(); - E value = this[0]; - for (int i = 1; i < length; i++) { - value = combine(value, this[i]); - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - return value; - } - - fold(var initialValue, combine(var previousValue, E element)) { - var value = initialValue; - int length = this.length; - for (int i = 0; i < length; i++) { - value = combine(value, this[i]); - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - return value; - } - - Iterable skip(int count) => new SubListIterable(this, count, null); - - Iterable skipWhile(bool test(E element)) { - return new SkipWhileIterable(this, test); - } - - Iterable take(int count) => new SubListIterable(this, 0, count); - - Iterable takeWhile(bool test(E element)) { - return new TakeWhileIterable(this, test); - } - - List toList({ bool growable: true }) { - List result; - if (growable) { - result = new List()..length = length; - } else { - result = new List(length); - } - for (int i = 0; i < length; i++) { - result[i] = this[i]; - } - return result; - } - - Set toSet() { - Set result = new Set(); - for (int i = 0; i < length; i++) { - result.add(this[i]); - } - return result; - } - - // Collection interface. - void add(E element) { - this[this.length++] = element; - } - - void addAll(Iterable iterable) { - for (E element in iterable) { - this[this.length++] = element; - } - } - - bool remove(Object element) { - for (int i = 0; i < this.length; i++) { - if (this[i] == element) { - this.setRange(i, this.length - 1, this, i + 1); - this.length -= 1; - return true; - } - } - return false; - } - - void removeWhere(bool test(E element)) { - _filter(this, test, false); - } - - void retainWhere(bool test(E element)) { - _filter(this, test, true); - } - - static void _filter(List source, - bool test(var element), - bool retainMatching) { - List retained = []; - int length = source.length; - for (int i = 0; i < length; i++) { - var element = source[i]; - if (test(element) == retainMatching) { - retained.add(element); - } - if (length != source.length) { - throw new ConcurrentModificationError(source); - } - } - if (retained.length != source.length) { - source.setRange(0, retained.length, retained); - source.length = retained.length; - } - } - - void clear() { this.length = 0; } - - // List interface. - - E removeLast() { - if (length == 0) { - throw IterableElementError.noElement(); - } - E result = this[length - 1]; - length--; - return result; - } - - void sort([int compare(E a, E b)]) { - Sort.sort(this, compare == null ? Comparable.compare : compare); - } - - void shuffle([Random random]) { - if (random == null) random = new Random(); - int length = this.length; - while (length > 1) { - int pos = random.nextInt(length); - length -= 1; - var tmp = this[length]; - this[length] = this[pos]; - this[pos] = tmp; - } - } - - Map asMap() { - return new ListMapView(this); - } - - List sublist(int start, [int end]) { - int listLength = this.length; - if (end == null) end = listLength; - RangeError.checkValidRange(start, end, listLength); - int length = end - start; - List result = new List()..length = length; - for (int i = 0; i < length; i++) { - result[i] = this[start + i]; - } - return result; - } - - Iterable getRange(int start, int end) { - RangeError.checkValidRange(start, end, this.length); - return new SubListIterable(this, start, end); - } - - void removeRange(int start, int end) { - RangeError.checkValidRange(start, end, this.length); - int length = end - start; - setRange(start, this.length - length, this, end); - this.length -= length; - } - - void fillRange(int start, int end, [E fill]) { - RangeError.checkValidRange(start, end, this.length); - for (int i = start; i < end; i++) { - this[i] = fill; - } - } - - void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { - RangeError.checkValidRange(start, end, this.length); - int length = end - start; - if (length == 0) return; - RangeError.checkNotNegative(skipCount, "skipCount"); - - List otherList; - int otherStart; - // TODO(floitsch): Make this accept more. - if (iterable is List) { - otherList = iterable; - otherStart = skipCount; - } else { - otherList = iterable.skip(skipCount).toList(growable: false); - otherStart = 0; - } - if (otherStart + length > otherList.length) { - throw IterableElementError.tooFew(); - } - if (otherStart < start) { - // Copy backwards to ensure correct copy if [from] is this. - for (int i = length - 1; i >= 0; i--) { - this[start + i] = otherList[otherStart + i]; - } - } else { - for (int i = 0; i < length; i++) { - this[start + i] = otherList[otherStart + i]; - } - } - } - - void replaceRange(int start, int end, Iterable newContents) { - RangeError.checkValidRange(start, end, this.length); - if (newContents is! EfficientLength) { - newContents = newContents.toList(); - } - int removeLength = end - start; - int insertLength = newContents.length; - if (removeLength >= insertLength) { - int delta = removeLength - insertLength; - int insertEnd = start + insertLength; - int newLength = this.length - delta; - this.setRange(start, insertEnd, newContents); - if (delta != 0) { - this.setRange(insertEnd, newLength, this, end); - this.length = newLength; - } - } else { - int delta = insertLength - removeLength; - int newLength = this.length + delta; - int insertEnd = start + insertLength; // aka. end + delta. - this.length = newLength; - this.setRange(insertEnd, newLength, this, end); - this.setRange(start, insertEnd, newContents); - } - } - - int indexOf(Object element, [int startIndex = 0]) { - if (startIndex >= this.length) { - return -1; - } - if (startIndex < 0) { - startIndex = 0; - } - for (int i = startIndex; i < this.length; i++) { - if (this[i] == element) { - return i; - } - } - return -1; - } - - /** - * Returns the last index in the list [a] of the given [element], starting - * the search at index [startIndex] to 0. - * Returns -1 if [element] is not found. - */ - int lastIndexOf(Object element, [int startIndex]) { - if (startIndex == null) { - startIndex = this.length - 1; - } else { - if (startIndex < 0) { - return -1; - } - if (startIndex >= this.length) { - startIndex = this.length - 1; - } - } - for (int i = startIndex; i >= 0; i--) { - if (this[i] == element) { - return i; - } - } - return -1; - } - - void insert(int index, E element) { - RangeError.checkValueInInterval(index, 0, length, "index"); - if (index == this.length) { - add(element); - return; - } - // We are modifying the length just below the is-check. Without the check - // Array.copy could throw an exception, leaving the list in a bad state - // (with a length that has been increased, but without a new element). - if (index is! int) throw new ArgumentError(index); - this.length++; - setRange(index + 1, this.length, this, index); - this[index] = element; - } - - E removeAt(int index) { - E result = this[index]; - setRange(index, this.length - 1, this, index + 1); - length--; - return result; - } - - void insertAll(int index, Iterable iterable) { - RangeError.checkValueInInterval(index, 0, length, "index"); - if (iterable is EfficientLength) { - iterable = iterable.toList(); - } - int insertionLength = iterable.length; - // There might be errors after the length change, in which case the list - // will end up being modified but the operation not complete. Unless we - // always go through a "toList" we can't really avoid that. - this.length += insertionLength; - setRange(index + insertionLength, this.length, this, index); - setAll(index, iterable); - } - - void setAll(int index, Iterable iterable) { - if (iterable is List) { - setRange(index, index + iterable.length, iterable); - } else { - for (E element in iterable) { - this[index++] = element; - } - } - } - - Iterable get reversed => new ReversedListIterable(this); - - String toString() => IterableBase.iterableToFullString(this, '[', ']'); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/maps.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/maps.dart deleted file mode 100644 index 5da1e8225e44..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/maps.dart +++ /dev/null @@ -1,353 +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. - -part of dart.collection; - -/** - * Base class for implementing a [Map]. - * - * This class has a basic implementation of all but five of the members of - * [Map]. - * A basic `Map` class can be implemented by extending this class and - * implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`. - * The remaining operations are implemented in terms of these five. - * - * The `keys` iterable should have efficient [length] and [contains] - * operations, and it should catch concurrent modifications of the keys - * while iterating. - * - * A more efficient implementation is usually possible by overriding - * some of the other members as well. - */ -abstract class MapBase = Object with MapMixin; - - -/** - * Mixin implementing a [Map]. - * - * This mixin has a basic implementation of all but five of the members of - * [Map]. - * A basic `Map` class can be implemented by mixin in this class and - * implementing `keys`, `operator[]`, `operator[]=`, `remove` and `clear`. - * The remaining operations are implemented in terms of these five. - * - * The `keys` iterable should have efficient [length] and [contains] - * operations, and it should catch concurrent modifications of the keys - * while iterating. - * - * A more efficient implementation is usually possible by overriding - * some of the other members as well. - */ -abstract class MapMixin implements Map { - Iterable get keys; - V operator[](Object key); - operator []=(K key, V value); - V remove(Object key); - // The `clear` operation should not be based on `remove`. - // It should clear the map even if some keys are not equal to themselves. - void clear(); - - void forEach(void action(K key, V value)) { - for (K key in keys) { - action(key, this[key]); - } - } - - void addAll(Map other) { - for (K key in other.keys) { - this[key] = other[key]; - } - } - - bool containsValue(Object value) { - for (K key in keys) { - if (this[key] == value) return true; - } - return false; - } - - V putIfAbsent(K key, V ifAbsent()) { - if (keys.contains(key)) { - return this[key]; - } - return this[key] = ifAbsent(); - } - - bool containsKey(Object key) => keys.contains(key); - int get length => keys.length; - bool get isEmpty => keys.isEmpty; - bool get isNotEmpty => keys.isNotEmpty; - Iterable get values => new _MapBaseValueIterable(this); - String toString() => Maps.mapToString(this); -} - -/** - * Basic implementation of an unmodifiable [Map]. - * - * This class has a basic implementation of all but two of the members of - * an umodifiable [Map]. - * A simple unmodifiable `Map` class can be implemented by extending this - * class and implementing `keys` and `operator[]`. - * - * Modifying operations throw when used. - * The remaining non-modifying operations are implemented in terms of `keys` - * and `operator[]`. - * - * The `keys` iterable should have efficient [length] and [contains] - * operations, and it should catch concurrent modifications of the keys - * while iterating. - * - * A more efficient implementation is usually possible by overriding - * some of the other members as well. - */ -abstract class UnmodifiableMapBase = - MapBase with _UnmodifiableMapMixin; - -/** - * Implementation of [Map.values] based on the map and its [Map.keys] iterable. - * - * Iterable that iterates over the values of a `Map`. - * It accesses the values by iterating over the keys of the map, and using the - * map's `operator[]` to lookup the keys. - */ -class _MapBaseValueIterable extends IterableBase - implements EfficientLength { - final Map _map; - _MapBaseValueIterable(this._map); - - int get length => _map.length; - bool get isEmpty => _map.isEmpty; - bool get isNotEmpty => _map.isNotEmpty; - V get first => _map[_map.keys.first]; - V get single => _map[_map.keys.single]; - V get last => _map[_map.keys.last]; - - Iterator get iterator => new _MapBaseValueIterator(_map); -} - -/** - * Iterator created by [_MapBaseValueIterable]. - * - * Iterates over the values of a map by iterating its keys and lookup up the - * values. - */ -class _MapBaseValueIterator implements Iterator { - final Iterator _keys; - final Map _map; - V _current = null; - - _MapBaseValueIterator(Map map) : _map = map, _keys = map.keys.iterator; - - bool moveNext() { - if (_keys.moveNext()) { - _current = _map[_keys.current]; - return true; - } - _current = null; - return false; - } - - V get current => _current; -} - -/** - * Mixin that overrides mutating map operations with implementations that throw. - */ -abstract class _UnmodifiableMapMixin implements Map { - void operator[]=(K key, V value) { - throw new UnsupportedError("Cannot modify unmodifiable map"); - } - void addAll(Map other) { - throw new UnsupportedError("Cannot modify unmodifiable map"); - } - void clear() { - throw new UnsupportedError("Cannot modify unmodifiable map"); - } - V remove(Object key) { - throw new UnsupportedError("Cannot modify unmodifiable map"); - } - V putIfAbsent(K key, V ifAbsent()) { - throw new UnsupportedError("Cannot modify unmodifiable map"); - } -} - -/** - * Wrapper around a class that implements [Map] that only exposes `Map` members. - * - * A simple wrapper that delegates all `Map` members to the map provided in the - * constructor. - * - * Base for delegating map implementations like [UnmodifiableMapView]. - */ -class MapView implements Map { - final Map _map; - const MapView(Map map) : _map = map; - - V operator[](Object key) => _map[key]; - void operator[]=(K key, V value) { _map[key] = value; } - void addAll(Map other) { _map.addAll(other); } - void clear() { _map.clear(); } - V putIfAbsent(K key, V ifAbsent()) => _map.putIfAbsent(key, ifAbsent); - bool containsKey(Object key) => _map.containsKey(key); - bool containsValue(Object value) => _map.containsValue(value); - void forEach(void action(K key, V value)) { _map.forEach(action); } - bool get isEmpty => _map.isEmpty; - bool get isNotEmpty => _map.isNotEmpty; - int get length => _map.length; - Iterable get keys => _map.keys; - V remove(Object key) => _map.remove(key); - String toString() => _map.toString(); - Iterable get values => _map.values; -} - -/** - * View of a [Map] that disallow modifying the map. - * - * A wrapper around a `Map` that forwards all members to the map provided in - * the constructor, except for operations that modify the map. - * Modifying operations throw instead. - */ -class UnmodifiableMapView = - MapView with _UnmodifiableMapMixin; - -/** - * Helper class which implements complex [Map] operations - * in term of basic ones ([Map.keys], [Map.operator []], - * [Map.operator []=] and [Map.remove].) Not all methods are - * necessary to implement each particular operation. - */ -class Maps { - static bool containsValue(Map map, value) { - for (final v in map.values) { - if (value == v) { - return true; - } - } - return false; - } - - static bool containsKey(Map map, key) { - for (final k in map.keys) { - if (key == k) { - return true; - } - } - return false; - } - - static putIfAbsent(Map map, key, ifAbsent()) { - if (map.containsKey(key)) { - return map[key]; - } - final v = ifAbsent(); - map[key] = v; - return v; - } - - static clear(Map map) { - for (final k in map.keys.toList()) { - map.remove(k); - } - } - - static forEach(Map map, void f(key, value)) { - for (final k in map.keys) { - f(k, map[k]); - } - } - - static Iterable getValues(Map map) { - return map.keys.map((key) => map[key]); - } - - static int length(Map map) => map.keys.length; - - static bool isEmpty(Map map) => map.keys.isEmpty; - - static bool isNotEmpty(Map map) => map.keys.isNotEmpty; - - /** - * Returns a string representing the specified map. The returned string - * looks like this: [:'{key0: value0, key1: value1, ... keyN: valueN}':]. - * The value returned by its [toString] method is used to represent each - * key or value. - * - * If the map collection contains a reference to itself, either - * directly as a key or value, or indirectly through other collections - * or maps, the contained reference is rendered as [:'{...}':]. This - * prevents the infinite regress that would otherwise occur. So, for example, - * calling this method on a map whose sole entry maps the string key 'me' - * to a reference to the map would return [:'{me: {...}}':]. - * - * A typical implementation of a map's [toString] method will - * simply return the results of this method applied to the collection. - */ - static String mapToString(Map m) { - // Reuse the list in IterableBase for detecting toString cycles. - if (IterableBase._isToStringVisiting(m)) { return '{...}'; } - - var result = new StringBuffer(); - try { - IterableBase._toStringVisiting.add(m); - result.write('{'); - bool first = true; - m.forEach((k, v) { - if(!first) { - result.write(', '); - } - first = false; - result.write(k); - result.write(': '); - result.write(v); - }); - result.write('}'); - } finally { - assert(identical(IterableBase._toStringVisiting.last, m)); - IterableBase._toStringVisiting.removeLast(); - } - - return result.toString(); - } - - static _id(x) => x; - - /** - * Fills a map with key/value pairs computed from [iterable]. - * - * This method is used by Map classes in the named constructor fromIterable. - */ - static void _fillMapWithMappedIterable(Map map, Iterable iterable, - key(element), value(element)) { - if (key == null) key = _id; - if (value == null) value = _id; - - for (var element in iterable) { - map[key(element)] = value(element); - } - } - - /** - * Fills a map by associating the [keys] to [values]. - * - * This method is used by Map classes in the named constructor fromIterables. - */ - static void _fillMapWithIterables(Map map, Iterable keys, - Iterable values) { - Iterator keyIterator = keys.iterator; - Iterator valueIterator = values.iterator; - - bool hasNextKey = keyIterator.moveNext(); - bool hasNextValue = valueIterator.moveNext(); - - while (hasNextKey && hasNextValue) { - map[keyIterator.current] = valueIterator.current; - hasNextKey = keyIterator.moveNext(); - hasNextValue = valueIterator.moveNext(); - } - - if (hasNextKey || hasNextValue) { - throw new ArgumentError("Iterables do not have same length."); - } - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/queue.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/queue.dart deleted file mode 100644 index f515392bf8cb..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/queue.dart +++ /dev/null @@ -1,742 +0,0 @@ -// 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. - -part of dart.collection; - -/** - * A [Queue] is a collection that can be manipulated at both ends. One - * can iterate over the elements of a queue through [forEach] or with - * an [Iterator]. - * - * It is generally not allowed to modify the queue (add or remove entries) while - * an operation on the queue is being performed, for example during a call to - * [forEach]. - * Modifying the queue while it is being iterated will most likely break the - * iteration. - * This goes both for using the [iterator] directly, or for iterating an - * `Iterable` returned by a method like [map] or [where]. - */ -abstract class Queue implements Iterable, EfficientLength { - - /** - * Creates a queue. - */ - factory Queue() = ListQueue; - - /** - * Creates a queue containing all [elements]. - * - * The element order in the queue is as if the elements were added using - * [addLast] in the order provided by [elements.iterator]. - */ - factory Queue.from(Iterable elements) = ListQueue.from; - - /** - * Removes and returns the first element of this queue. - * - * The queue must not be empty when this method is called. - */ - E removeFirst(); - - /** - * Removes and returns the last element of the queue. - * - * The queue must not be empty when this method is called. - */ - E removeLast(); - - /** - * Adds [value] at the beginning of the queue. - */ - void addFirst(E value); - - /** - * Adds [value] at the end of the queue. - */ - void addLast(E value); - - /** - * Adds [value] at the end of the queue. - */ - void add(E value); - - /** - * Remove a single instance of [value] from the queue. - * - * Returns `true` if a value was removed, or `false` if the queue - * contained no element equal to [value]. - */ - bool remove(Object object); - - /** - * Adds all elements of [iterable] at the end of the queue. The - * length of the queue is extended by the length of [iterable]. - */ - void addAll(Iterable iterable); - - /** - * Removes all elements matched by [test] from the queue. - * - * The `test` function must not throw or modify the queue. - */ - void removeWhere(bool test(E element)); - - /** - * Removes all elements not matched by [test] from the queue. - * - * The `test` function must not throw or modify the queue. - */ - void retainWhere(bool test(E element)); - - /** - * Removes all elements in the queue. The size of the queue becomes zero. - */ - void clear(); -} - - -/** - * An entry in a doubly linked list. It contains a pointer to the next - * entry, the previous entry, and the boxed element. - */ -class DoubleLinkedQueueEntry { - DoubleLinkedQueueEntry _previous; - DoubleLinkedQueueEntry _next; - E _element; - - DoubleLinkedQueueEntry(E e) : _element = e; - - void _link(DoubleLinkedQueueEntry previous, - DoubleLinkedQueueEntry next) { - _next = next; - _previous = previous; - previous._next = this; - next._previous = this; - } - - void append(E e) { - new DoubleLinkedQueueEntry(e)._link(this, _next); - } - - void prepend(E e) { - new DoubleLinkedQueueEntry(e)._link(_previous, this); - } - - E remove() { - _previous._next = _next; - _next._previous = _previous; - _next = null; - _previous = null; - return _element; - } - - DoubleLinkedQueueEntry _asNonSentinelEntry() { - return this; - } - - DoubleLinkedQueueEntry previousEntry() { - return _previous._asNonSentinelEntry(); - } - - DoubleLinkedQueueEntry nextEntry() { - return _next._asNonSentinelEntry(); - } - - E get element { - return _element; - } - - void set element(E e) { - _element = e; - } -} - -/** - * A sentinel in a double linked list is used to manipulate the list - * at both ends. - * A double linked list has exactly one sentinel, - * which is the only entry when the list is constructed. - * Initially, a sentinel has its next and previous entry point to itself. - * A sentinel does not box any user element. - */ -class _DoubleLinkedQueueEntrySentinel extends DoubleLinkedQueueEntry { - _DoubleLinkedQueueEntrySentinel() : super(null) { - _link(this, this); - } - - E remove() { - throw IterableElementError.noElement(); - } - - DoubleLinkedQueueEntry _asNonSentinelEntry() { - return null; - } - - void set element(E e) { - // This setter is unreachable. - // TODO(lrn): Don't inherit the field if we don't use it. - assert(false); - } - - E get element { - throw IterableElementError.noElement(); - } -} - -/** - * A [Queue] implementation based on a double-linked list. - * - * Allows constant time add, remove-at-ends and peek operations. - */ -class DoubleLinkedQueue extends IterableBase implements Queue { - _DoubleLinkedQueueEntrySentinel _sentinel; - int _elementCount = 0; - - DoubleLinkedQueue() { - _sentinel = new _DoubleLinkedQueueEntrySentinel(); - } - - /** - * Creates a double-linked queue containing all [elements]. - * - * The element order in the queue is as if the elements were added using - * [addLast] in the order provided by [elements.iterator]. - */ - factory DoubleLinkedQueue.from(Iterable elements) { - Queue list = new DoubleLinkedQueue(); - for (final E e in elements) { - list.addLast(e); - } - return list; - } - - int get length => _elementCount; - - void addLast(E value) { - _sentinel.prepend(value); - _elementCount++; - } - - void addFirst(E value) { - _sentinel.append(value); - _elementCount++; - } - - void add(E value) { - _sentinel.prepend(value); - _elementCount++; - } - - void addAll(Iterable iterable) { - for (final E value in iterable) { - _sentinel.prepend(value); - _elementCount++; - } - } - - E removeLast() { - E result = _sentinel._previous.remove(); - _elementCount--; - return result; - } - - E removeFirst() { - E result = _sentinel._next.remove(); - _elementCount--; - return result; - } - - bool remove(Object o) { - DoubleLinkedQueueEntry entry = _sentinel._next; - while (!identical(entry, _sentinel)) { - if (entry.element == o) { - entry.remove(); - _elementCount--; - return true; - } - entry = entry._next; - } - return false; - } - - void _filter(bool test(E element), bool removeMatching) { - DoubleLinkedQueueEntry entry = _sentinel._next; - while (!identical(entry, _sentinel)) { - DoubleLinkedQueueEntry next = entry._next; - if (identical(removeMatching, test(entry.element))) { - entry.remove(); - _elementCount--; - } - entry = next; - } - } - - void removeWhere(bool test(E element)) { - _filter(test, true); - } - - void retainWhere(bool test(E element)) { - _filter(test, false); - } - - E get first { - return _sentinel._next.element; - } - - E get last { - return _sentinel._previous.element; - } - - E get single { - // Note that this throws correctly if the queue is empty. - if (identical(_sentinel._next, _sentinel._previous)) { - return _sentinel._next.element; - } - throw IterableElementError.tooMany(); - } - - DoubleLinkedQueueEntry lastEntry() { - return _sentinel.previousEntry(); - } - - DoubleLinkedQueueEntry firstEntry() { - return _sentinel.nextEntry(); - } - - bool get isEmpty { - return (identical(_sentinel._next, _sentinel)); - } - - void clear() { - _sentinel._next = _sentinel; - _sentinel._previous = _sentinel; - _elementCount = 0; - } - - void forEachEntry(void f(DoubleLinkedQueueEntry element)) { - DoubleLinkedQueueEntry entry = _sentinel._next; - while (!identical(entry, _sentinel)) { - DoubleLinkedQueueEntry nextEntry = entry._next; - f(entry); - entry = nextEntry; - } - } - - _DoubleLinkedQueueIterator get iterator { - return new _DoubleLinkedQueueIterator(_sentinel); - } - - String toString() => IterableBase.iterableToFullString(this, '{', '}'); -} - -class _DoubleLinkedQueueIterator implements Iterator { - _DoubleLinkedQueueEntrySentinel _sentinel; - DoubleLinkedQueueEntry _nextEntry = null; - E _current; - - _DoubleLinkedQueueIterator(_DoubleLinkedQueueEntrySentinel sentinel) - : _sentinel = sentinel, _nextEntry = sentinel._next; - - bool moveNext() { - // When [_currentEntry] it is set to [:null:] then it is at the end. - if (!identical(_nextEntry, _sentinel)) { - _current = _nextEntry._element; - _nextEntry = _nextEntry._next; - return true; - } - _current = null; - _nextEntry = _sentinel = null; // Still identical. - return false; - } - - E get current => _current; -} - -/** - * List based [Queue]. - * - * Keeps a cyclic buffer of elements, and grows to a larger buffer when - * it fills up. This guarantees constant time peek and remove operations, and - * amortized constant time add operations. - * - * The structure is efficient for any queue or stack usage. - */ -class ListQueue extends IterableBase implements Queue { - static const int _INITIAL_CAPACITY = 8; - List _table; - int _head; - int _tail; - int _modificationCount = 0; - - /** - * Create an empty queue. - * - * If [initialCapacity] is given, prepare the queue for at least that many - * elements. - */ - ListQueue([int initialCapacity]) : _head = 0, _tail = 0 { - if (initialCapacity == null || initialCapacity < _INITIAL_CAPACITY) { - initialCapacity = _INITIAL_CAPACITY; - } else if (!_isPowerOf2(initialCapacity)) { - initialCapacity = _nextPowerOf2(initialCapacity); - } - assert(_isPowerOf2(initialCapacity)); - _table = new List(initialCapacity); - } - - /** - * Create a `ListQueue` containing all [elements]. - * - * The elements are added to the queue, as by [addLast], in the order given by - * `elements.iterator`. - * - * All `elements` should be assignable to [E]. - */ - factory ListQueue.from(Iterable elements) { - if (elements is List) { - int length = elements.length; - ListQueue queue = new ListQueue(length + 1); - assert(queue._table.length > length); - List sourceList = elements; - queue._table.setRange(0, length, sourceList, 0); - queue._tail = length; - return queue; - } else { - int capacity = _INITIAL_CAPACITY; - if (elements is EfficientLength) { - capacity = elements.length; - } - ListQueue result = new ListQueue(capacity); - for (final E element in elements) { - result.addLast(element); - } - return result; - } - } - - // Iterable interface. - - Iterator get iterator => new _ListQueueIterator(this); - - void forEach(void action (E element)) { - int modificationCount = _modificationCount; - for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) { - action(_table[i]); - _checkModification(modificationCount); - } - } - - bool get isEmpty => _head == _tail; - - int get length => (_tail - _head) & (_table.length - 1); - - E get first { - if (_head == _tail) throw IterableElementError.noElement(); - return _table[_head]; - } - - E get last { - if (_head == _tail) throw IterableElementError.noElement(); - return _table[(_tail - 1) & (_table.length - 1)]; - } - - E get single { - if (_head == _tail) throw IterableElementError.noElement(); - if (length > 1) throw IterableElementError.tooMany(); - return _table[_head]; - } - - E elementAt(int index) { - RangeError.checkValidIndex(index, this); - return _table[(_head + index) & (_table.length - 1)]; - } - - List toList({ bool growable: true }) { - List list; - if (growable) { - list = new List()..length = length; - } else { - list = new List(length); - } - _writeToList(list); - return list; - } - - // Collection interface. - - void add(E element) { - _add(element); - } - - void addAll(Iterable elements) { - if (elements is List) { - List list = elements; - int addCount = list.length; - int length = this.length; - if (length + addCount >= _table.length) { - _preGrow(length + addCount); - // After preGrow, all elements are at the start of the list. - _table.setRange(length, length + addCount, list, 0); - _tail += addCount; - } else { - // Adding addCount elements won't reach _head. - int endSpace = _table.length - _tail; - if (addCount < endSpace) { - _table.setRange(_tail, _tail + addCount, list, 0); - _tail += addCount; - } else { - int preSpace = addCount - endSpace; - _table.setRange(_tail, _tail + endSpace, list, 0); - _table.setRange(0, preSpace, list, endSpace); - _tail = preSpace; - } - } - _modificationCount++; - } else { - for (E element in elements) _add(element); - } - } - - bool remove(Object object) { - for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) { - E element = _table[i]; - if (element == object) { - _remove(i); - _modificationCount++; - return true; - } - } - return false; - } - - void _filterWhere(bool test(E element), bool removeMatching) { - int index = _head; - int modificationCount = _modificationCount; - int i = _head; - while (i != _tail) { - E element = _table[i]; - bool remove = identical(removeMatching, test(element)); - _checkModification(modificationCount); - if (remove) { - i = _remove(i); - modificationCount = ++_modificationCount; - } else { - i = (i + 1) & (_table.length - 1); - } - } - } - - /** - * Remove all elements matched by [test]. - * - * This method is inefficient since it works by repeatedly removing single - * elements, each of which can take linear time. - */ - void removeWhere(bool test(E element)) { - _filterWhere(test, true); - } - - /** - * Remove all elements not matched by [test]. - * - * This method is inefficient since it works by repeatedly removing single - * elements, each of which can take linear time. - */ - void retainWhere(bool test(E element)) { - _filterWhere(test, false); - } - - void clear() { - if (_head != _tail) { - for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) { - _table[i] = null; - } - _head = _tail = 0; - _modificationCount++; - } - } - - String toString() => IterableBase.iterableToFullString(this, "{", "}"); - - // Queue interface. - - void addLast(E element) { _add(element); } - - void addFirst(E element) { - _head = (_head - 1) & (_table.length - 1); - _table[_head] = element; - if (_head == _tail) _grow(); - _modificationCount++; - } - - E removeFirst() { - if (_head == _tail) throw IterableElementError.noElement(); - _modificationCount++; - E result = _table[_head]; - _table[_head] = null; - _head = (_head + 1) & (_table.length - 1); - return result; - } - - E removeLast() { - if (_head == _tail) throw IterableElementError.noElement(); - _modificationCount++; - _tail = (_tail - 1) & (_table.length - 1); - E result = _table[_tail]; - _table[_tail] = null; - return result; - } - - // Internal helper functions. - - /** - * Whether [number] is a power of two. - * - * Only works for positive numbers. - */ - static bool _isPowerOf2(int number) => (number & (number - 1)) == 0; - - /** - * Rounds [number] up to the nearest power of 2. - * - * If [number] is a power of 2 already, it is returned. - * - * Only works for positive numbers. - */ - static int _nextPowerOf2(int number) { - assert(number > 0); - number = (number << 1) - 1; - for(;;) { - int nextNumber = number & (number - 1); - if (nextNumber == 0) return number; - number = nextNumber; - } - } - - /** Check if the queue has been modified during iteration. */ - void _checkModification(int expectedModificationCount) { - if (expectedModificationCount != _modificationCount) { - throw new ConcurrentModificationError(this); - } - } - - /** Adds element at end of queue. Used by both [add] and [addAll]. */ - void _add(E element) { - _table[_tail] = element; - _tail = (_tail + 1) & (_table.length - 1); - if (_head == _tail) _grow(); - _modificationCount++; - } - - /** - * Removes the element at [offset] into [_table]. - * - * Removal is performed by linerarly moving elements either before or after - * [offset] by one position. - * - * Returns the new offset of the following element. This may be the same - * offset or the following offset depending on how elements are moved - * to fill the hole. - */ - int _remove(int offset) { - int mask = _table.length - 1; - int startDistance = (offset - _head) & mask; - int endDistance = (_tail - offset) & mask; - if (startDistance < endDistance) { - // Closest to start. - int i = offset; - while (i != _head) { - int prevOffset = (i - 1) & mask; - _table[i] = _table[prevOffset]; - i = prevOffset; - } - _table[_head] = null; - _head = (_head + 1) & mask; - return (offset + 1) & mask; - } else { - _tail = (_tail - 1) & mask; - int i = offset; - while (i != _tail) { - int nextOffset = (i + 1) & mask; - _table[i] = _table[nextOffset]; - i = nextOffset; - } - _table[_tail] = null; - return offset; - } - } - - /** - * Grow the table when full. - */ - void _grow() { - List newTable = new List(_table.length * 2); - int split = _table.length - _head; - newTable.setRange(0, split, _table, _head); - newTable.setRange(split, split + _head, _table, 0); - _head = 0; - _tail = _table.length; - _table = newTable; - } - - int _writeToList(List target) { - assert(target.length >= length); - if (_head <= _tail) { - int length = _tail - _head; - target.setRange(0, length, _table, _head); - return length; - } else { - int firstPartSize = _table.length - _head; - target.setRange(0, firstPartSize, _table, _head); - target.setRange(firstPartSize, firstPartSize + _tail, _table, 0); - return _tail + firstPartSize; - } - } - - /** Grows the table even if it is not full. */ - void _preGrow(int newElementCount) { - assert(newElementCount >= length); - - // Add some extra room to ensure that there's room for more elements after - // expansion. - newElementCount += newElementCount >> 1; - int newCapacity = _nextPowerOf2(newElementCount); - List newTable = new List(newCapacity); - _tail = _writeToList(newTable); - _table = newTable; - _head = 0; - } -} - -/** - * Iterator for a [ListQueue]. - * - * Considers any add or remove operation a concurrent modification. - */ -class _ListQueueIterator implements Iterator { - final ListQueue _queue; - final int _end; - final int _modificationCount; - int _position; - E _current; - - _ListQueueIterator(ListQueue queue) - : _queue = queue, - _end = queue._tail, - _modificationCount = queue._modificationCount, - _position = queue._head; - - E get current => _current; - - bool moveNext() { - _queue._checkModification(_modificationCount); - if (_position == _end) { - _current = null; - return false; - } - _current = _queue._table[_position]; - _position = (_position + 1) & (_queue._table.length - 1); - return true; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/set.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/set.dart deleted file mode 100644 index 717089e0b9e7..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/set.dart +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/** - * Base implementations of [Set]. - */ -part of dart.collection; - -/** - * Mixin implementation of [Set]. - * - * This class provides a base implementation of a `Set` that depends only - * on the abstract members: [add], [contains], [lookup], [remove], - * [iterator], [length] and [toSet]. - * - * Some of the methods assume that `toSet` creates a modifiable set. - * If using this mixin for an unmodifiable set, - * where `toSet` should return an unmodifiable set, - * it's necessary to reimplement - * [retainAll], [union], [intersection] and [difference]. - * - * Implementations of `Set` using this mixin should consider also implementing - * `clear` in constant time. The default implementation works by removing every - * element. - */ -abstract class SetMixin implements Set { - // This class reimplements all of [IterableMixin]. - // If/when Dart mixins get more powerful, we should just create a single - // Mixin class from IterableMixin and the new methods of thisclass. - - bool add(E element); - - bool contains(Object element); - - E lookup(Object element); - - bool remove(Object element); - - Iterator get iterator; - - Set toSet(); - - int get length; - - bool get isEmpty => length == 0; - - bool get isNotEmpty => length != 0; - - void clear() { - removeAll(toList()); - } - - void addAll(Iterable elements) { - for (E element in elements) add(element); - } - - void removeAll(Iterable elements) { - for (Object element in elements) remove(element); - } - - void retainAll(Iterable elements) { - // Create a copy of the set, remove all of elements from the copy, - // then remove all remaining elements in copy from this. - Set toRemove = toSet(); - for (Object o in elements) { - toRemove.remove(o); - } - removeAll(toRemove); - } - - void removeWhere(bool test(E element)) { - List toRemove = []; - for (E element in this) { - if (test(element)) toRemove.add(element); - } - removeAll(toRemove); - } - - void retainWhere(bool test(E element)) { - List toRemove = []; - for (E element in this) { - if (!test(element)) toRemove.add(element); - } - removeAll(toRemove); - } - - bool containsAll(Iterable other) { - for (Object o in other) { - if (!contains(o)) return false; - } - return true; - } - - Set union(Set other) { - return toSet()..addAll(other); - } - - Set intersection(Set other) { - Set result = toSet(); - for (E element in this) { - if (!other.contains(element)) result.remove(element); - } - return result; - } - - Set difference(Set other) { - Set result = toSet(); - for (E element in this) { - if (other.contains(element)) result.remove(element); - } - return result; - } - - List toList({bool growable: true}) { - List result = growable ? (new List()..length = length) - : new List(length); - int i = 0; - for (E element in this) result[i++] = element; - return result; - } - - Iterable map(f(E element)) => - new EfficientLengthMappedIterable(this, f); - - E get single { - if (length > 1) throw IterableElementError.tooMany(); - Iterator it = iterator; - if (!it.moveNext()) throw IterableElementError.noElement(); - E result = it.current; - return result; - } - - String toString() => IterableBase.iterableToFullString(this, '{', '}'); - - // Copied from IterableMixin. - // Should be inherited if we had multi-level mixins. - - Iterable where(bool f(E element)) => new WhereIterable(this, f); - - Iterable expand(Iterable f(E element)) => - new ExpandIterable(this, f); - - void forEach(void f(E element)) { - for (E element in this) f(element); - } - - E reduce(E combine(E value, E element)) { - Iterator iterator = this.iterator; - if (!iterator.moveNext()) { - throw IterableElementError.noElement(); - } - E value = iterator.current; - while (iterator.moveNext()) { - value = combine(value, iterator.current); - } - return value; - } - - dynamic fold(var initialValue, - dynamic combine(var previousValue, E element)) { - var value = initialValue; - for (E element in this) value = combine(value, element); - return value; - } - - bool every(bool f(E element)) { - for (E element in this) { - if (!f(element)) return false; - } - return true; - } - - String join([String separator = ""]) { - Iterator iterator = this.iterator; - if (!iterator.moveNext()) return ""; - StringBuffer buffer = new StringBuffer(); - if (separator == null || separator == "") { - do { - buffer.write("${iterator.current}"); - } while (iterator.moveNext()); - } else { - buffer.write("${iterator.current}"); - while (iterator.moveNext()) { - buffer.write(separator); - buffer.write("${iterator.current}"); - } - } - return buffer.toString(); - } - - bool any(bool test(E element)) { - for (E element in this) { - if (test(element)) return true; - } - return false; - } - - Iterable take(int n) { - return new TakeIterable(this, n); - } - - Iterable takeWhile(bool test(E value)) { - return new TakeWhileIterable(this, test); - } - - Iterable skip(int n) { - return new SkipIterable(this, n); - } - - Iterable skipWhile(bool test(E value)) { - return new SkipWhileIterable(this, test); - } - - E get first { - Iterator it = iterator; - if (!it.moveNext()) { - throw IterableElementError.noElement(); - } - return it.current; - } - - E get last { - Iterator it = iterator; - if (!it.moveNext()) { - throw IterableElementError.noElement(); - } - E result; - do { - result = it.current; - } while(it.moveNext()); - return result; - } - - E firstWhere(bool test(E value), { E orElse() }) { - for (E element in this) { - if (test(element)) return element; - } - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - E lastWhere(bool test(E value), { E orElse() }) { - E result = null; - bool foundMatching = false; - for (E element in this) { - if (test(element)) { - result = element; - foundMatching = true; - } - } - if (foundMatching) return result; - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - E singleWhere(bool test(E value)) { - E result = null; - bool foundMatching = false; - for (E element in this) { - if (test(element)) { - if (foundMatching) { - throw IterableElementError.tooMany(); - } - result = element; - foundMatching = true; - } - } - if (foundMatching) return result; - throw IterableElementError.noElement(); - } - - E elementAt(int index) { - if (index is! int) throw new ArgumentError.notNull("index"); - RangeError.checkNotNegative(index, "index"); - int elementIndex = 0; - for (E element in this) { - if (index == elementIndex) return element; - elementIndex++; - } - throw new RangeError.index(index, this, "index", null, elementIndex); - } -} - -/** - * Base implementation of [Set]. - * - * This class provides a base implementation of a `Set` that depends only - * on the abstract members: [add], [contains], [lookup], [remove], - * [iterator], [length] and [toSet]. - * - * Some of the methods assume that `toSet` creates a modifiable set. - * If using this base class for an unmodifiable set, - * where `toSet` should return an unmodifiable set, - * it's necessary to reimplement - * [retainAll], [union], [intersection] and [difference]. - * - * Implementations of `Set` using this base should consider also implementing - * `clear` in constant time. The default implementation works by removing every - * element. - */ -abstract class SetBase extends SetMixin { - /** - * Convert a `Set` to a string as `{each, element, as, string}`. - * - * Handles circular references where converting one of the elements - * to a string ends up converting [set] to a string again. - */ - static String setToString(Set set) => - IterableBase.iterableToFullString(set, '{', '}'); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/collection/splay_tree.dart b/pkg/dev_compiler/test/generated_sdk/lib/collection/splay_tree.dart deleted file mode 100644 index 112698b98b7e..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/collection/splay_tree.dart +++ /dev/null @@ -1,836 +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. - -part of dart.collection; - -typedef bool _Predicate(T value); - -/** - * A node in a splay tree. It holds the sorting key and the left - * and right children in the tree. - */ -class _SplayTreeNode { - final K key; - _SplayTreeNode left; - _SplayTreeNode right; - - _SplayTreeNode(K this.key); -} - -/** - * A node in a splay tree based map. - * - * A [_SplayTreeNode] that also contains a value - */ -class _SplayTreeMapNode extends _SplayTreeNode { - V value; - _SplayTreeMapNode(K key, V this.value) : super(key); -} - -/** - * A splay tree is a self-balancing binary search tree. - * - * It has the additional property that recently accessed elements - * are quick to access again. - * It performs basic operations such as insertion, look-up and - * removal, in O(log(n)) amortized time. - */ -abstract class _SplayTree { - // The root node of the splay tree. It will contain either the last - // element inserted or the last element looked up. - _SplayTreeNode _root; - - // The dummy node used when performing a splay on the tree. Reusing it - // avoids allocating a node each time a splay is performed. - _SplayTreeNode _dummy = new _SplayTreeNode(null); - - // Number of elements in the splay tree. - int _count = 0; - - /** - * Counter incremented whenever the keys in the map changes. - * - * Used to detect concurrent modifications. - */ - int _modificationCount = 0; - - /** - * Counter incremented whenever the tree structure changes. - * - * Used to detect that an in-place traversal cannot use - * cached information that relies on the tree structure. - */ - int _splayCount = 0; - - /** Comparison used to compare keys. */ - int _compare(K key1, K key2); - - /** - * Perform the splay operation for the given key. Moves the node with - * the given key to the top of the tree. If no node has the given - * key, the last node on the search path is moved to the top of the - * tree. This is the simplified top-down splaying algorithm from: - * "Self-adjusting Binary Search Trees" by Sleator and Tarjan. - * - * Returns the result of comparing the new root of the tree to [key]. - * Returns -1 if the table is empty. - */ - int _splay(K key) { - if (_root == null) return -1; - - // The right child of the dummy node will hold - // the L tree of the algorithm. The left child of the dummy node - // will hold the R tree of the algorithm. Using a dummy node, left - // and right will always be nodes and we avoid special cases. - _SplayTreeNode left = _dummy; - _SplayTreeNode right = _dummy; - _SplayTreeNode current = _root; - int comp; - while (true) { - comp = _compare(current.key, key); - if (comp > 0) { - if (current.left == null) break; - comp = _compare(current.left.key, key); - if (comp > 0) { - // Rotate right. - _SplayTreeNode tmp = current.left; - current.left = tmp.right; - tmp.right = current; - current = tmp; - if (current.left == null) break; - } - // Link right. - right.left = current; - right = current; - current = current.left; - } else if (comp < 0) { - if (current.right == null) break; - comp = _compare(current.right.key, key); - if (comp < 0) { - // Rotate left. - _SplayTreeNode tmp = current.right; - current.right = tmp.left; - tmp.left = current; - current = tmp; - if (current.right == null) break; - } - // Link left. - left.right = current; - left = current; - current = current.right; - } else { - break; - } - } - // Assemble. - left.right = current.left; - right.left = current.right; - current.left = _dummy.right; - current.right = _dummy.left; - _root = current; - - _dummy.right = null; - _dummy.left = null; - _splayCount++; - return comp; - } - - // Emulates splaying with a key that is smaller than any in the subtree - // anchored at [node]. - // and that node is returned. It should replace the reference to [node] - // in any parent tree or root pointer. - _SplayTreeNode _splayMin(_SplayTreeNode node) { - _SplayTreeNode current = node; - while (current.left != null) { - _SplayTreeNode left = current.left; - current.left = left.right; - left.right = current; - current = left; - } - return current; - } - - // Emulates splaying with a key that is greater than any in the subtree - // anchored at [node]. - // After this, the largest element in the tree is the root of the subtree, - // and that node is returned. It should replace the reference to [node] - // in any parent tree or root pointer. - _SplayTreeNode _splayMax(_SplayTreeNode node) { - _SplayTreeNode current = node; - while (current.right != null) { - _SplayTreeNode right = current.right; - current.right = right.left; - right.left = current; - current = right; - } - return current; - } - - _SplayTreeNode _remove(K key) { - if (_root == null) return null; - int comp = _splay(key); - if (comp != 0) return null; - _SplayTreeNode result = _root; - _count--; - // assert(_count >= 0); - if (_root.left == null) { - _root = _root.right; - } else { - _SplayTreeNode right = _root.right; - // Splay to make sure that the new root has an empty right child. - _root = _splayMax(_root.left); - // Insert the original right child as the right child of the new - // root. - _root.right = right; - } - _modificationCount++; - return result; - } - - /** - * Adds a new root node with the given [key] or [value]. - * - * The [comp] value is the result of comparing the existing root's key - * with key. - */ - void _addNewRoot(_SplayTreeNode node, int comp) { - _count++; - _modificationCount++; - if (_root == null) { - _root = node; - return; - } - // assert(_count >= 0); - if (comp < 0) { - node.left = _root; - node.right = _root.right; - _root.right = null; - } else { - node.right = _root; - node.left = _root.left; - _root.left = null; - } - _root = node; - } - - _SplayTreeNode get _first { - if (_root == null) return null; - _root = _splayMin(_root); - return _root; - } - - _SplayTreeNode get _last { - if (_root == null) return null; - _root = _splayMax(_root); - return _root; - } - - void _clear() { - _root = null; - _count = 0; - _modificationCount++; - } -} - -/** - * A [Map] of objects that can be ordered relative to each other. - * - * The map is based on a self-balancing binary tree. It allows most operations - * in amortized logarithmic time. - * - * Keys of the map are compared using the `compare` function passed in - * the constructor, both for ordering and for equality. - * If the map contains only the key `a`, then `map.containsKey(b)` - * will return `true` if and only if `compare(a, b) == 0`, - * and the value of `a == b` is not even checked. - * If the compare function is omitted, the objects are assumed to be - * [Comparable], and are compared using their [Comparable.compareTo] method. - * Non-comparable objects (including `null`) will not work as keys - * in that case. - * - * To allow calling [operator[]], [remove] or [containsKey] with objects - * that are not supported by the `compare` function, an extra `isValidKey` - * predicate function can be supplied. This function is tested before - * using the `compare` function on an argument value that may not be a [K] - * value. If omitted, the `isValidKey` function defaults to testing if the - * value is a [K]. - */ -class SplayTreeMap extends _SplayTree implements Map { - Comparator _comparator; - _Predicate _validKey; - - SplayTreeMap([int compare(K key1, K key2), - bool isValidKey(Object potentialKey)]) - : _comparator = (compare == null) ? Comparable.compare : compare, - _validKey = (isValidKey != null) ? isValidKey : ((v) => v is K); - - /** - * Creates a [SplayTreeMap] that contains all key/value pairs of [other]. - */ - factory SplayTreeMap.from(Map other, - [int compare(K key1, K key2), - bool isValidKey(Object potentialKey)]) { - SplayTreeMap result = new SplayTreeMap(); - other.forEach((k, v) { result[k] = v; }); - return result; - } - - /** - * Creates a [SplayTreeMap] where the keys and values are computed from the - * [iterable]. - * - * For each element of the [iterable] this constructor computes a key/value - * pair, by applying [key] and [value] respectively. - * - * The keys of the key/value pairs do not need to be unique. The last - * occurrence of a key will simply overwrite any previous value. - * - * If no functions are specified for [key] and [value] the default is to - * use the iterable value itself. - */ - factory SplayTreeMap.fromIterable(Iterable iterable, - {K key(element), - V value(element), - int compare(K key1, K key2), - bool isValidKey(Object potentialKey) }) { - SplayTreeMap map = new SplayTreeMap(compare, isValidKey); - Maps._fillMapWithMappedIterable(map, iterable, key, value); - return map; - } - - /** - * Creates a [SplayTreeMap] associating the given [keys] to [values]. - * - * This constructor iterates over [keys] and [values] and maps each element of - * [keys] to the corresponding element of [values]. - * - * If [keys] contains the same object multiple times, the last occurrence - * overwrites the previous value. - * - * It is an error if the two [Iterable]s don't have the same length. - */ - factory SplayTreeMap.fromIterables(Iterable keys, Iterable values, - [int compare(K key1, K key2), bool isValidKey(Object potentialKey)]) { - SplayTreeMap map = new SplayTreeMap(compare, isValidKey); - Maps._fillMapWithIterables(map, keys, values); - return map; - } - - int _compare(K key1, K key2) => _comparator(key1, key2); - - SplayTreeMap._internal(); - - V operator [](Object key) { - if (key == null) throw new ArgumentError(key); - if (!_validKey(key)) return null; - if (_root != null) { - int comp = _splay(key); - if (comp == 0) { - _SplayTreeMapNode mapRoot = _root; - return mapRoot.value; - } - } - return null; - } - - V remove(Object key) { - if (!_validKey(key)) return null; - _SplayTreeMapNode mapRoot = _remove(key); - if (mapRoot != null) return mapRoot.value; - return null; - } - - void operator []=(K key, V value) { - if (key == null) throw new ArgumentError(key); - // Splay on the key to move the last node on the search path for - // the key to the root of the tree. - int comp = _splay(key); - if (comp == 0) { - _SplayTreeMapNode mapRoot = _root; - mapRoot.value = value; - return; - } - _addNewRoot(new _SplayTreeMapNode(key, value), comp); - } - - - V putIfAbsent(K key, V ifAbsent()) { - if (key == null) throw new ArgumentError(key); - int comp = _splay(key); - if (comp == 0) { - _SplayTreeMapNode mapRoot = _root; - return mapRoot.value; - } - int modificationCount = _modificationCount; - int splayCount = _splayCount; - V value = ifAbsent(); - if (modificationCount != _modificationCount) { - throw new ConcurrentModificationError(this); - } - if (splayCount != _splayCount) { - comp = _splay(key); - // Key is still not there, otherwise _modificationCount would be changed. - assert(comp != 0); - } - _addNewRoot(new _SplayTreeMapNode(key, value), comp); - return value; - } - - void addAll(Map other) { - other.forEach((K key, V value) { this[key] = value; }); - } - - bool get isEmpty { - return (_root == null); - } - - bool get isNotEmpty => !isEmpty; - - void forEach(void f(K key, V value)) { - Iterator<_SplayTreeNode> nodes = - new _SplayTreeNodeIterator(this); - while (nodes.moveNext()) { - _SplayTreeMapNode node = nodes.current; - f(node.key, node.value); - } - } - - int get length { - return _count; - } - - void clear() { - _clear(); - } - - bool containsKey(Object key) { - return _validKey(key) && _splay(key) == 0; - } - - bool containsValue(Object value) { - bool found = false; - int initialSplayCount = _splayCount; - bool visit(_SplayTreeMapNode node) { - while (node != null) { - if (node.value == value) return true; - if (initialSplayCount != _splayCount) { - throw new ConcurrentModificationError(this); - } - if (node.right != null && visit(node.right)) return true; - node = node.left; - } - return false; - } - return visit(_root); - } - - Iterable get keys => new _SplayTreeKeyIterable(this); - - Iterable get values => new _SplayTreeValueIterable(this); - - String toString() { - return Maps.mapToString(this); - } - - /** - * Get the first key in the map. Returns [:null:] if the map is empty. - */ - K firstKey() { - if (_root == null) return null; - return _first.key; - } - - /** - * Get the last key in the map. Returns [:null:] if the map is empty. - */ - K lastKey() { - if (_root == null) return null; - return _last.key; - } - - /** - * Get the last key in the map that is strictly smaller than [key]. Returns - * [:null:] if no key was not found. - */ - K lastKeyBefore(K key) { - if (key == null) throw new ArgumentError(key); - if (_root == null) return null; - int comp = _splay(key); - if (comp < 0) return _root.key; - _SplayTreeNode node = _root.left; - if (node == null) return null; - while (node.right != null) { - node = node.right; - } - return node.key; - } - - /** - * Get the first key in the map that is strictly larger than [key]. Returns - * [:null:] if no key was not found. - */ - K firstKeyAfter(K key) { - if (key == null) throw new ArgumentError(key); - if (_root == null) return null; - int comp = _splay(key); - if (comp > 0) return _root.key; - _SplayTreeNode node = _root.right; - if (node == null) return null; - while (node.left != null) { - node = node.left; - } - return node.key; - } -} - -abstract class _SplayTreeIterator implements Iterator { - final _SplayTree _tree; - /** - * Worklist of nodes to visit. - * - * These nodes have been passed over on the way down in a - * depth-first left-to-right traversal. Visiting each node, - * and their right subtrees will visit the remainder of - * the nodes of a full traversal. - * - * Only valid as long as the original tree isn't reordered. - */ - final List<_SplayTreeNode> _workList = <_SplayTreeNode>[]; - - /** - * Original modification counter of [_tree]. - * - * Incremented on [_tree] when a key is added or removed. - * If it changes, iteration is aborted. - * - * Not final because some iterators may modify the tree knowingly, - * and they update the modification count in that case. - */ - int _modificationCount; - - /** - * Count of splay operations on [_tree] when [_workList] was built. - * - * If the splay count on [_tree] increases, [_workList] becomes invalid. - */ - int _splayCount; - - /** Current node. */ - _SplayTreeNode _currentNode; - - _SplayTreeIterator(_SplayTree tree) - : _tree = tree, - _modificationCount = tree._modificationCount, - _splayCount = tree._splayCount { - _findLeftMostDescendent(tree._root); - } - - _SplayTreeIterator.startAt(_SplayTree tree, var startKey) - : _tree = tree, - _modificationCount = tree._modificationCount { - if (tree._root == null) return; - int compare = tree._splay(startKey); - _splayCount = tree._splayCount; - if (compare < 0) { - // Don't include the root, start at the next element after the root. - _findLeftMostDescendent(tree._root.right); - } else { - _workList.add(tree._root); - } - } - - T get current { - if (_currentNode == null) return null; - return _getValue(_currentNode); - } - - void _findLeftMostDescendent(_SplayTreeNode node) { - while (node != null) { - _workList.add(node); - node = node.left; - } - } - - /** - * Called when the tree structure of the tree has changed. - * - * This can be caused by a splay operation. - * If the key-set changes, iteration is aborted before getting - * here, so we know that the keys are the same as before, it's - * only the tree that has been reordered. - */ - void _rebuildWorkList(_SplayTreeNode currentNode) { - assert(!_workList.isEmpty); - _workList.clear(); - if (currentNode == null) { - _findLeftMostDescendent(_tree._root); - } else { - _tree._splay(currentNode.key); - _findLeftMostDescendent(_tree._root.right); - assert(!_workList.isEmpty); - } - } - - bool moveNext() { - if (_modificationCount != _tree._modificationCount) { - throw new ConcurrentModificationError(_tree); - } - // Picks the next element in the worklist as current. - // Updates the worklist with the left-most path of the current node's - // right-hand child. - // If the worklist is no longer valid (after a splay), it is rebuild - // from scratch. - if (_workList.isEmpty) { - _currentNode = null; - return false; - } - if (_tree._splayCount != _splayCount && _currentNode != null) { - _rebuildWorkList(_currentNode); - } - _currentNode = _workList.removeLast(); - _findLeftMostDescendent(_currentNode.right); - return true; - } - - T _getValue(_SplayTreeMapNode node); -} - -class _SplayTreeKeyIterable extends IterableBase - implements EfficientLength { - _SplayTree _tree; - _SplayTreeKeyIterable(this._tree); - int get length => _tree._count; - bool get isEmpty => _tree._count == 0; - Iterator get iterator => new _SplayTreeKeyIterator(_tree); - - Set toSet() { - var setOrMap = _tree; // Both have _comparator and _validKey. - SplayTreeSet set = - new SplayTreeSet(setOrMap._comparator, setOrMap._validKey); - set._count = _tree._count; - set._root = set._copyNode(_tree._root); - return set; - } -} - -class _SplayTreeValueIterable extends IterableBase - implements EfficientLength { - SplayTreeMap _map; - _SplayTreeValueIterable(this._map); - int get length => _map._count; - bool get isEmpty => _map._count == 0; - Iterator get iterator => new _SplayTreeValueIterator(_map); -} - -class _SplayTreeKeyIterator extends _SplayTreeIterator { - _SplayTreeKeyIterator(_SplayTree map): super(map); - K _getValue(_SplayTreeNode node) => node.key; -} - -class _SplayTreeValueIterator extends _SplayTreeIterator { - _SplayTreeValueIterator(SplayTreeMap map): super(map); - V _getValue(_SplayTreeMapNode node) => node.value; -} - -class _SplayTreeNodeIterator - extends _SplayTreeIterator<_SplayTreeNode> { - _SplayTreeNodeIterator(_SplayTree tree): super(tree); - _SplayTreeNodeIterator.startAt(_SplayTree tree, var startKey) - : super.startAt(tree, startKey); - _SplayTreeNode _getValue(_SplayTreeNode node) => node; -} - - -/** - * A [Set] of objects that can be ordered relative to each other. - * - * The set is based on a self-balancing binary tree. It allows most operations - * in amortized logarithmic time. - * - * Elements of the set are compared using the `compare` function passed in - * the constructor, both for ordering and for equality. - * If the set contains only an object `a`, then `set.contains(b)` - * will return `true` if and only if `compare(a, b) == 0`, - * and the value of `a == b` is not even checked. - * If the compare function is omitted, the objects are assumed to be - * [Comparable], and are compared using their [Comparable.compareTo] method. - * Non-comparable objects (including `null`) will not work as an element - * in that case. - */ -class SplayTreeSet extends _SplayTree with IterableMixin, SetMixin { - Comparator _comparator; - _Predicate _validKey; - - /** - * Create a new [SplayTreeSet] with the given compare function. - * - * If the [compare] function is omitted, it defaults to [Comparable.compare], - * and the elements must be comparable. - * - * A provided `compare` function may not work on all objects. It may not even - * work on all `E` instances. - * - * For operations that add elements to the set, the user is supposed to not - * pass in objects that doesn't work with the compare function. - * - * The methods [contains], [remove], [lookup], [removeAll] or [retainAll] - * are typed to accept any object(s), and the [isValidKey] test can used to - * filter those objects before handing them to the `compare` function. - * - * If [isValidKey] is provided, only values satisfying `isValidKey(other)` - * are compared using the `compare` method in the methods mentioned above. - * If the `isValidKey` function returns false for an object, it is assumed to - * not be in the set. - * - * If omitted, the `isValidKey` function defaults to checking against the - * type parameter: `other is E`. - */ - SplayTreeSet([int compare(E key1, E key2), - bool isValidKey(Object potentialKey)]) - : _comparator = (compare == null) ? Comparable.compare : compare, - _validKey = (isValidKey != null) ? isValidKey : ((v) => v is E); - - /** - * Creates a [SplayTreeSet] that contains all [elements]. - * - * The set works as if created by `new SplayTreeSet(compare, isValidKey)`. - * - * All the [elements] should be valid as arguments to the [compare] function. - */ - factory SplayTreeSet.from(Iterable elements, - [int compare(E key1, E key2), - bool isValidKey(Object potentialKey)]) { - SplayTreeSet result = new SplayTreeSet(compare, isValidKey); - for (final E element in elements) { - result.add(element); - } - return result; - } - - int _compare(E e1, E e2) => _comparator(e1, e2); - - // From Iterable. - - Iterator get iterator => new _SplayTreeKeyIterator(this); - - int get length => _count; - bool get isEmpty => _root == null; - bool get isNotEmpty => _root != null; - - E get first { - if (_count == 0) throw IterableElementError.noElement(); - return _first.key; - } - - E get last { - if (_count == 0) throw IterableElementError.noElement(); - return _last.key; - } - - E get single { - if (_count == 0) throw IterableElementError.noElement(); - if (_count > 1) throw IterableElementError.tooMany(); - return _root.key; - } - - // From Set. - bool contains(Object object) { - return _validKey(object) && _splay(object) == 0; - } - - bool add(E element) { - int compare = _splay(element); - if (compare == 0) return false; - _addNewRoot(new _SplayTreeNode(element), compare); - return true; - } - - bool remove(Object object) { - if (!_validKey(object)) return false; - return _remove(object) != null; - } - - void addAll(Iterable elements) { - for (E element in elements) { - int compare = _splay(element); - if (compare != 0) { - _addNewRoot(new _SplayTreeNode(element), compare); - } - } - } - - void removeAll(Iterable elements) { - for (Object element in elements) { - if (_validKey(element)) _remove(element); - } - } - - void retainAll(Iterable elements) { - // Build a set with the same sense of equality as this set. - SplayTreeSet retainSet = new SplayTreeSet(_comparator, _validKey); - int modificationCount = _modificationCount; - for (Object object in elements) { - if (modificationCount != _modificationCount) { - // The iterator should not have side effects. - throw new ConcurrentModificationError(this); - } - // Equivalent to this.contains(object). - if (_validKey(object) && _splay(object) == 0) retainSet.add(_root.key); - } - // Take over the elements from the retained set, if it differs. - if (retainSet._count != _count) { - _root = retainSet._root; - _count = retainSet._count; - _modificationCount++; - } - } - - E lookup(Object object) { - if (!_validKey(object)) return null; - int comp = _splay(object); - if (comp != 0) return null; - return _root.key; - } - - Set intersection(Set other) { - Set result = new SplayTreeSet(_comparator, _validKey); - for (E element in this) { - if (other.contains(element)) result.add(element); - } - return result; - } - - Set difference(Set other) { - Set result = new SplayTreeSet(_comparator, _validKey); - for (E element in this) { - if (!other.contains(element)) result.add(element); - } - return result; - } - - Set union(Set other) { - return _clone()..addAll(other); - } - - SplayTreeSet _clone() { - var set = new SplayTreeSet(_comparator, _validKey); - set._count = _count; - set._root = _copyNode(_root); - return set; - } - - // Copies the structure of a SplayTree into a new similar structure. - // Works on _SplayTreeMapNode as well, but only copies the keys, - _SplayTreeNode _copyNode(_SplayTreeNode node) { - if (node == null) return null; - return new _SplayTreeNode(node.key)..left = _copyNode(node.left) - ..right = _copyNode(node.right); - } - - void clear() { _clear(); } - - Set toSet() => _clone(); - - String toString() => IterableBase.iterableToFullString(this, '{', '}'); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/convert/ascii.dart b/pkg/dev_compiler/test/generated_sdk/lib/convert/ascii.dart deleted file mode 100644 index 1caffe05afb8..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/convert/ascii.dart +++ /dev/null @@ -1,311 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.convert; - -/** - * An instance of the default implementation of the [AsciiCodec]. - * - * This instance provides a convenient access to the most common ASCII - * use cases. - * - * Examples: - * - * var encoded = ASCII.encode("This is ASCII!"); - * var decoded = ASCII.decode([0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, - * 0x20, 0x41, 0x53, 0x43, 0x49, 0x49, 0x21]); - */ -const AsciiCodec ASCII = const AsciiCodec(); - -const int _ASCII_MASK = 0x7F; - -/** - * An [AsciiCodec] allows encoding strings as ASCII bytes - * and decoding ASCII bytes to strings. - */ -class AsciiCodec extends Encoding { - final bool _allowInvalid; - /** - * Instantiates a new [AsciiCodec]. - * - * If [allowInvalid] is true, the [decode] method and the converter - * returned by [decoder] will default to allowing invalid values. - * If allowing invalid values, the values will be decoded into the Unicode - * Replacement character (U+FFFD). If not, an exception will be thrown. - * Calls to the [decode] method can choose to override this default. - * - * Encoders will not accept invalid (non Latin-1) characters. - */ - const AsciiCodec({bool allowInvalid: false}) : _allowInvalid = allowInvalid; - - String get name => "us-ascii"; - - /** - * Decodes the ASCII [bytes] (a list of unsigned 7-bit integers) to the - * corresponding string. - * - * If [bytes] contains values that are not in the range 0 .. 127, the decoder - * will eventually throw a [FormatException]. - * - * If [allowInvalid] is not provided, it defaults to the value used to create - * this [AsciiCodec]. - */ - String decode(List bytes, { bool allowInvalid }) { - if (allowInvalid == null) allowInvalid = _allowInvalid; - if (allowInvalid) { - return const AsciiDecoder(allowInvalid: true).convert(bytes); - } else { - return const AsciiDecoder(allowInvalid: false).convert(bytes); - } - } - - AsciiEncoder get encoder => const AsciiEncoder(); - - AsciiDecoder get decoder => - _allowInvalid ? const AsciiDecoder(allowInvalid: true) - : const AsciiDecoder(allowInvalid: false); -} - -// Superclass for [AsciiEncoder] and [Latin1Encoder]. -// Generalizes common operations that only differ by a mask; -class _UnicodeSubsetEncoder extends Converter> { - final int _subsetMask; - - const _UnicodeSubsetEncoder(this._subsetMask); - - /** - * Converts the [String] into a list of its code units. - * - * If [start] and [end] are provided, only the substring - * `string.substring(start, end)` is used as input to the conversion. - */ - List convert(String string, [int start = 0, int end]) { - int stringLength = string.length; - RangeError.checkValidRange(start, end, stringLength); - if (end == null) end = stringLength; - int length = end - start; - List result = new Uint8List(length); - for (int i = 0; i < length; i++) { - var codeUnit = string.codeUnitAt(start + i); - if ((codeUnit & ~_subsetMask) != 0) { - throw new ArgumentError("String contains invalid characters."); - } - result[i] = codeUnit; - } - return result; - } - - /** - * Starts a chunked conversion. - * - * The converter works more efficiently if the given [sink] is a - * [ByteConversionSink]. - */ - StringConversionSink startChunkedConversion(Sink> sink) { - if (sink is! ByteConversionSink) { - sink = new ByteConversionSink.from(sink); - } - return new _UnicodeSubsetEncoderSink(_subsetMask, sink); - } - - // Override the base-class' bind, to provide a better type. - Stream> bind(Stream stream) => super.bind(stream); -} - -/** - * This class converts strings of only ASCII characters to bytes. - */ -class AsciiEncoder extends _UnicodeSubsetEncoder { - const AsciiEncoder() : super(_ASCII_MASK); -} - -/** - * This class encodes chunked strings to bytes (unsigned 8-bit - * integers). - */ -class _UnicodeSubsetEncoderSink extends StringConversionSinkBase { - final ByteConversionSink _sink; - final int _subsetMask; - - _UnicodeSubsetEncoderSink(this._subsetMask, this._sink); - - void close() { - _sink.close(); - } - - void addSlice(String source, int start, int end, bool isLast) { - RangeError.checkValidRange(start, end, source.length); - for (int i = start; i < end; i++) { - int codeUnit = source.codeUnitAt(i); - if ((codeUnit & ~_subsetMask) != 0) { - throw new ArgumentError( - "Source contains invalid character with code point: $codeUnit."); - } - } - _sink.add(source.codeUnits.sublist(start, end)); - if (isLast) { - close(); - } - } -} - -/** - * This class converts Latin-1 bytes (lists of unsigned 8-bit integers) - * to a string. - */ -abstract class _UnicodeSubsetDecoder extends Converter, String> { - final bool _allowInvalid; - final int _subsetMask; - - /** - * Instantiates a new decoder. - * - * The [_allowInvalid] argument defines how [convert] deals - * with invalid bytes. - * - * The [_subsetMask] argument is a bit mask used to define the subset - * of Unicode being decoded. Use [_LATIN1_MASK] for Latin-1 (8-bit) or - * [_ASCII_MASK] for ASCII (7-bit). - * - * If [_allowInvalid] is `true`, [convert] replaces invalid bytes with the - * Unicode Replacement character `U+FFFD` (�). - * Otherwise it throws a [FormatException]. - */ - const _UnicodeSubsetDecoder(this._allowInvalid, this._subsetMask); - - /** - * Converts the [bytes] (a list of unsigned 7- or 8-bit integers) to the - * corresponding string. - * - * If [start] and [end] are provided, only the sub-list of bytes from - * `start` to `end` (`end` not inclusive) is used as input to the conversion. - */ - String convert(List bytes, [int start = 0, int end]) { - int byteCount = bytes.length; - RangeError.checkValidRange(start, end, byteCount); - if (end == null) end = byteCount; - int length = end - start; - - for (int i = start; i < end; i++) { - int byte = bytes[i]; - if ((byte & ~_subsetMask) != 0) { - if (!_allowInvalid) { - throw new FormatException("Invalid value in input: $byte"); - } - return _convertInvalid(bytes, start, end); - } - } - return new String.fromCharCodes(bytes, start, end); - } - - String _convertInvalid(List bytes, int start, int end) { - StringBuffer buffer = new StringBuffer(); - for (int i = start; i < end; i++) { - int value = bytes[i]; - if ((value & ~_subsetMask) != 0) value = 0xFFFD; - buffer.writeCharCode(value); - } - return buffer.toString(); - } - - /** - * Starts a chunked conversion. - * - * The converter works more efficiently if the given [sink] is a - * [StringConversionSink]. - */ - ByteConversionSink startChunkedConversion(Sink sink); - - // Override the base-class's bind, to provide a better type. - Stream bind(Stream> stream) => super.bind(stream); -} - -class AsciiDecoder extends _UnicodeSubsetDecoder { - const AsciiDecoder({bool allowInvalid: false}) - : super(allowInvalid, _ASCII_MASK); - - /** - * Starts a chunked conversion. - * - * The converter works more efficiently if the given [sink] is a - * [StringConversionSink]. - */ - ByteConversionSink startChunkedConversion(Sink sink) { - StringConversionSink stringSink; - if (sink is StringConversionSink) { - stringSink = sink; - } else { - stringSink = new StringConversionSink.from(sink); - } - // TODO(lrn): Use asUtf16Sink when it becomes available. It - // works just as well, is likely to have less decoding overhead, - // and make adding U+FFFD easier. - // At that time, merge this with _Latin1DecoderSink; - if (_allowInvalid) { - return new _ErrorHandlingAsciiDecoderSink(stringSink.asUtf8Sink(false)); - } else { - return new _SimpleAsciiDecoderSink(stringSink); - } - } -} - -class _ErrorHandlingAsciiDecoderSink extends ByteConversionSinkBase { - ByteConversionSink _utf8Sink; - _ErrorHandlingAsciiDecoderSink(this._utf8Sink); - - void close() { - _utf8Sink.close(); - } - - void add(List source) { - addSlice(source, 0, source.length, false); - } - - void addSlice(List source, int start, int end, bool isLast) { - RangeError.checkValidRange(start, end, source.length); - for (int i = start; i < end; i++) { - if ((source[i] & ~_ASCII_MASK) != 0) { - if (i > start) _utf8Sink.addSlice(source, start, i, false); - // Add UTF-8 encoding of U+FFFD. - _utf8Sink.add(const[0xEF, 0xBF, 0xBD]); - start = i + 1; - } - } - if (start < end) { - _utf8Sink.addSlice(source, start, end, isLast); - } else if (isLast) { - close(); - } - } -} - -class _SimpleAsciiDecoderSink extends ByteConversionSinkBase { - Sink _sink; - _SimpleAsciiDecoderSink(this._sink); - - void close() { - _sink.close(); - } - - void add(List source) { - for (int i = 0; i < source.length; i++) { - if ((source[i] & ~_ASCII_MASK) != 0) { - throw new FormatException("Source contains non-ASCII bytes."); - } - } - _sink.add(new String.fromCharCodes(source)); - } - - void addSlice(List source, int start, int end, bool isLast) { - final int length = source.length; - RangeError.checkValidRange(start, end, length); - if (start < end) { - if (start != 0 || end != length) { - source = source.sublist(start, end); - } - add(source); - } - if (isLast) close(); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/convert/byte_conversion.dart b/pkg/dev_compiler/test/generated_sdk/lib/convert/byte_conversion.dart deleted file mode 100644 index d27b40fcf89b..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/convert/byte_conversion.dart +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.convert; - -/** - * The [ByteConversionSink] provides an interface for converters to - * efficiently transmit byte data. - * - * Instead of limiting the interface to one non-chunked list of bytes it - * accepts its input in chunks (themselves being lists of bytes). - * - * This abstract class will likely get more methods over time. Implementers are - * urged to extend or mix in [ByteConversionSinkBase] to ensure that their - * class covers the newly added methods. - */ -abstract class ByteConversionSink extends ChunkedConversionSink> { - ByteConversionSink(); - factory ByteConversionSink.withCallback(void callback(List accumulated)) - = _ByteCallbackSink; - factory ByteConversionSink.from(Sink> sink) - = _ByteAdapterSink; - - /** - * Adds the next [chunk] to `this`. - * - * Adds the bytes defined by [start] and [end]-exclusive to `this`. - * - * If [isLast] is `true` closes `this`. - * - * Contrary to `add` the given [chunk] must not be held onto. Once the method - * returns, it is safe to overwrite the data in it. - */ - void addSlice(List chunk, int start, int end, bool isLast); - - // TODO(floitsch): add more methods: - // - iterateBytes. -} - -/** - * This class provides a base-class for converters that need to accept byte - * inputs. - */ -abstract class ByteConversionSinkBase extends ByteConversionSink { - - void add(List chunk); - void close(); - - void addSlice(List chunk, int start, int end, bool isLast) { - add(chunk.sublist(start, end)); - if (isLast) close(); - } -} - -/** - * This class adapts a simple [Sink] to a [ByteConversionSink]. - * - * All additional methods of the [ByteConversionSink] (compared to the - * ChunkedConversionSink) are redirected to the `add` method. - */ -class _ByteAdapterSink extends ByteConversionSinkBase { - final Sink> _sink; - - _ByteAdapterSink(this._sink); - - void add(List chunk) => _sink.add(chunk); - void close() => _sink.close(); -} - -/** - * This class accumulates all chunks into one list of bytes - * and invokes a callback when the sink is closed. - * - * This class can be used to terminate a chunked conversion. - */ -class _ByteCallbackSink extends ByteConversionSinkBase { - static const _INITIAL_BUFFER_SIZE = 1024; - - final _ChunkedConversionCallback> _callback; - List _buffer = new Uint8List(_INITIAL_BUFFER_SIZE); - int _bufferIndex = 0; - - _ByteCallbackSink(void callback(List accumulated)) - : this._callback = callback; - - void add(Iterable chunk) { - int freeCount = _buffer.length - _bufferIndex; - if (chunk.length > freeCount) { - // Grow the buffer. - int oldLength = _buffer.length; - int newLength = _roundToPowerOf2(chunk.length + oldLength) * 2; - List grown = new Uint8List(newLength); - grown.setRange(0, _buffer.length, _buffer); - _buffer = grown; - } - _buffer.setRange(_bufferIndex, _bufferIndex + chunk.length, chunk); - _bufferIndex += chunk.length; - } - - static int _roundToPowerOf2(int v) { - assert(v > 0); - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - return v; - } - - void close() { - _callback(_buffer.sublist(0, _bufferIndex)); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/convert/chunked_conversion.dart b/pkg/dev_compiler/test/generated_sdk/lib/convert/chunked_conversion.dart deleted file mode 100644 index c9a874c56905..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/convert/chunked_conversion.dart +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.convert; - -typedef void _ChunkedConversionCallback(T accumulated); - -/** - * A [ChunkedConversionSink] is used to transmit data more efficiently between - * two converters during chunked conversions. - * - * The basic `ChunkedConversionSink` is just a [Sink], and converters should - * work with a plain `Sink`, but may work more efficiently with certain - * specialized types of `ChunkedConversionSink`. - * - * It is recommended that implementations of `ChunkedConversionSink` extends - * this class, to inherit any further methods that may be added to the class. - */ -abstract class ChunkedConversionSink implements Sink { - ChunkedConversionSink(); - factory ChunkedConversionSink.withCallback( - void callback(List accumulated)) = _SimpleCallbackSink; - - /** - * Adds chunked data to this sink. - * - * This method is also used when converters are used as [StreamTransformer]s. - */ - void add(T chunk); - - /** - * Closes the sink. - * - * This signals the end of the chunked conversion. This method is called - * when converters are used as [StreamTransformer]'s. - */ - void close(); -} - -/** - * This class accumulates all chunks and invokes a callback with a list of - * the chunks when the sink is closed. - * - * This class can be used to terminate a chunked conversion. - */ -class _SimpleCallbackSink extends ChunkedConversionSink { - final _ChunkedConversionCallback> _callback; - final List _accumulated = []; - - _SimpleCallbackSink(this._callback); - - void add(T chunk) { _accumulated.add(chunk); } - void close() { _callback(_accumulated); } -} - -class _EventSinkAdapter implements ChunkedConversionSink { - final EventSink _sink; - - _EventSinkAdapter(this._sink); - - void add(T data) => _sink.add(data); - void close() => _sink.close(); -} - -/** - * This class converts implements the logic for a chunked conversion as a - * stream transformer. - * - * It is used as strategy in the [EventTransformStream]. - * - * It also implements the [ChunkedConversionSink] interface so that it - * can be used as output sink in a chunked conversion. - */ -class _ConverterStreamEventSink implements EventSink { - /** The output sink for the converter. */ - final EventSink _eventSink; - - /** - * The input sink for new data. All data that is received with - * [handleData] is added into this sink. - */ - ChunkedConversionSink _chunkedSink; - - _ConverterStreamEventSink(Converter converter, EventSink sink) - : this._eventSink = sink, - _chunkedSink = converter.startChunkedConversion(sink); - - void add(S o) => _chunkedSink.add(o); - void addError(Object error, [StackTrace stackTrace]) { - _eventSink.addError(error, stackTrace); - } - void close() => _chunkedSink.close(); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/convert/codec.dart b/pkg/dev_compiler/test/generated_sdk/lib/convert/codec.dart deleted file mode 100644 index 1afe63a7105c..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/convert/codec.dart +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.convert; - -/** - * A [Codec] encodes and (if supported) decodes data. - * - * Codecs can be fused. For example fusing [JSON] and [UTF8] produces - * an encoder that can convert Json objects directly to bytes, or can decode - * bytes directly to json objects. - * - * Fused codecs generally attempt to optimize the operations and can be faster - * than executing each step of an encoding separately. - * - * *Codecs are still experimental and are subject to change without notice.* - */ -abstract class Codec { - const Codec(); - - T encode(S input) => encoder.convert(input); - S decode(T encoded) => decoder.convert(encoded); - - /** - * Returns the encoder from [S] to [T]. - * - * It may be stateful and should not be reused. - */ - Converter get encoder; - /** - * Returns the decoder of `this`, converting from [T] to [S]. - * - * It may be stateful an should not be reused. - */ - Converter get decoder; - - /** - * Fuses `this` with `other`. - * - * When encoding, the resulting codec encodes with `this` before - * encoding with [other]. - * - * When decoding, the resulting codec decodes with [other] before decoding - * with `this`. - * - * In some cases one needs to use the [inverted] codecs to be able to fuse - * them correctly. That is, the output type of `this` ([T]) must match the - * input type of the second codec [other]. - * - * Examples: - * - * final JSON_TO_BYTES = JSON.fuse(UTF8); - * List bytes = JSON_TO_BYTES.encode(["json-object"]); - * var decoded = JSON_TO_BYTES.decode(bytes); - * assert(decoded is List && decoded[0] == "json-object"); - * - * var inverted = JSON.inverted; - * var jsonIdentity = JSON.fuse(inverted); - * var jsonObject = jsonIdentity.encode(["1", 2]); - * assert(jsonObject is List && jsonObject[0] == "1" && jsonObject[1] == 2); - */ - // TODO(floitsch): use better example with line-splitter once that one is - // in this library. - Codec fuse(Codec other) { - return new _FusedCodec(this, other); - } - - /** - * Inverts `this`. - * - * The [encoder] and [decoder] of the resulting codec are swapped. - */ - Codec get inverted => new _InvertedCodec(this); -} - -/** - * Fuses the given codecs. - * - * In the non-chunked conversion simply invokes the non-chunked conversions in - * sequence. - */ -class _FusedCodec extends Codec { - final Codec _first; - final Codec _second; - - Converter get encoder => _first.encoder.fuse(_second.encoder); - Converter get decoder => _second.decoder.fuse(_first.decoder); - - _FusedCodec(this._first, this._second); -} - -class _InvertedCodec extends Codec { - final Codec _codec; - - _InvertedCodec(Codec codec) : _codec = codec; - - Converter get encoder => _codec.decoder; - Converter get decoder => _codec.encoder; - - Codec get inverted => _codec; -} \ No newline at end of file diff --git a/pkg/dev_compiler/test/generated_sdk/lib/convert/convert.dart b/pkg/dev_compiler/test/generated_sdk/lib/convert/convert.dart deleted file mode 100644 index fbb7683bbea7..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/convert/convert.dart +++ /dev/null @@ -1,414 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -/** - * - * Encoders and decoders for converting between different data representations, - * including JSON and UTF-8. - * - * In addition to converters for common data representations, this library - * provides support for implementing converters in a way which makes them easy to - * chain and to use with streams. - * - * The `dart:convert` library works in both web apps and command-line apps. - * To use it: - * - * import 'dart:convert'; - * - * Two commonly used converters are the top-level instances of - * [JsonCodec] and [Utf8Codec], named JSON and UTF8, respectively. - * - * JSON is a simple text format for representing - * structured objects and collections. - * The JSON encoder/decoder transforms between strings and - * object structures, such as lists and maps, using the JSON format. - * - * UTF-8 is a common variable-width encoding that can represent - * every character in the Unicode character set. - * The UTF-8 encoder/decoder transforms between Strings and bytes. - * - * Converters are often used with streams - * to transform the data that comes through the stream - * as it becomes available. - * The following code uses two converters. - * The first is a UTF-8 decoder, which converts the data from bytes to UTF-8 - * as it's read from a file, - * The second is an instance of [LineSplitter], - * which splits the data on newline boundaries. - * - * int lineNumber = 1; - * Stream> stream = new File('quotes.txt').openRead(); - * - * stream.transform(UTF8.decoder) - * .transform(const LineSplitter()) - * .listen((line) { - * if (showLineNumbers) { - * stdout.write('${lineNumber++} '); - * } - * stdout.writeln(line); - * }); - * - * See the documentation for the [Codec] and [Converter] classes - * for information about creating your own converters. - */ -library dart.convert; - -import 'dart:async'; -import 'dart:typed_data'; -import 'dart:_js_helper' show patch; -import 'dart:_foreign_helper' show JS; -import 'dart:_interceptors' show JSExtendableArray; -import 'dart:_internal' show MappedIterable, ListIterable; -import 'dart:collection' show Maps, LinkedHashMap; - -part 'ascii.dart'; -part 'byte_conversion.dart'; -part 'chunked_conversion.dart'; -part 'codec.dart'; -part 'converter.dart'; -part 'encoding.dart'; -part 'html_escape.dart'; -part 'json.dart'; -part 'latin1.dart'; -part 'line_splitter.dart'; -part 'string_conversion.dart'; -part 'utf.dart'; - -/** - * Walks the raw JavaScript value [json], replacing JavaScript Objects with - * Maps. [json] is expected to be freshly allocated so elements can be replaced - * in-place. - */ -_convertJsonToDart(json, reviver(key, value)) { - assert(reviver != null); - walk(e) { - // JavaScript null, string, number, bool are in the correct representation. - if (JS('bool', '# == null', e) || JS('bool', 'typeof # != "object"', e)) { - return e; - } - - // This test is needed to avoid identifing '{"__proto__":[]}' as an Array. - // TODO(sra): Replace this test with cheaper '#.constructor === Array' when - // bug 621 below is fixed. - if (JS('bool', 'Object.getPrototypeOf(#) === Array.prototype', e)) { - // In-place update of the elements since JS Array is a Dart List. - for (int i = 0; i < JS('int', '#.length', e); i++) { - // Use JS indexing to avoid range checks. We know this is the only - // reference to the list, but the compiler will likely never be able to - // tell that this instance of the list cannot have its length changed by - // the reviver even though it later will be passed to the reviver at the - // outer level. - var item = JS('', '#[#]', e, i); - JS('', '#[#]=#', e, i, reviver(i, walk(item))); - } - return e; - } - - // Otherwise it is a plain object, so copy to a JSON map, so we process - // and revive all entries recursively. - _JsonMap map = new _JsonMap(e); - var processed = map._processed; - List keys = map._computeKeys(); - for (int i = 0; i < keys.length; i++) { - String key = keys[i]; - var revived = reviver(key, walk(JS('', '#[#]', e, key))); - JS('', '#[#]=#', processed, key, revived); - } - - // Update the JSON map structure so future access is cheaper. - map._original = processed; // Don't keep two objects around. - return map; - } - - return reviver(null, walk(json)); -} -_convertJsonToDartLazy(object) { - // JavaScript null and undefined are represented as null. - if (object == null) return null; - - // JavaScript string, number, bool already has the correct representation. - if (JS('bool', 'typeof # != "object"', object)) { - return object; - } - - // This test is needed to avoid identifing '{"__proto__":[]}' as an array. - // TODO(sra): Replace this test with cheaper '#.constructor === Array' when - // bug https://code.google.com/p/v8/issues/detail?id=621 is fixed. - if (JS('bool', 'Object.getPrototypeOf(#) !== Array.prototype', object)) { - return new _JsonMap(object); - } - - // Update the elements in place since JS arrays are Dart lists. - for (int i = 0; i < JS('int', '#.length', object); i++) { - // Use JS indexing to avoid range checks. We know this is the only - // reference to the list, but the compiler will likely never be able to - // tell that this instance of the list cannot have its length changed by - // the reviver even though it later will be passed to the reviver at the - // outer level. - var item = JS('', '#[#]', object, i); - JS('', '#[#]=#', object, i, _convertJsonToDartLazy(item)); - } - return object; -} -class _JsonMap implements LinkedHashMap { - // The original JavaScript object remains unchanged until - // the map is eventually upgraded, in which case we null it - // out to reclaim the memory used by it. - var _original; - - // We keep track of the map entries that we have already - // processed by adding them to a separate JavaScript object. - var _processed = _newJavaScriptObject(); - - // If the data slot isn't null, it represents either the list - // of keys (for non-upgraded JSON maps) or the upgraded map. - var _data = null; - - _JsonMap(this._original); - - operator[](Object key) { - if (_isUpgraded) { - return _upgradedMap[key]; - } else if (key is !String) { - return null; - } else { - var result = _getProperty(_processed, key); - if (_isUnprocessed(result)) result = _process(key); - return result; - } - } - - int get length => _isUpgraded - ? _upgradedMap.length - : _computeKeys().length; - - bool get isEmpty => length == 0; - bool get isNotEmpty => length > 0; - - Iterable get keys { - if (_isUpgraded) return _upgradedMap.keys; - return new _JsonMapKeyIterable(this); - } - - Iterable get values { - if (_isUpgraded) return _upgradedMap.values; - return new MappedIterable(_computeKeys(), (each) => this[each]); - } - - operator[]=(key, value) { - if (_isUpgraded) { - _upgradedMap[key] = value; - } else if (containsKey(key)) { - var processed = _processed; - _setProperty(processed, key, value); - var original = _original; - if (!identical(original, processed)) { - _setProperty(original, key, null); // Reclaim memory. - } - } else { - _upgrade()[key] = value; - } - } - - void addAll(Map other) { - other.forEach((key, value) { - this[key] = value; - }); - } - - bool containsValue(Object value) { - if (_isUpgraded) return _upgradedMap.containsValue(value); - List keys = _computeKeys(); - for (int i = 0; i < keys.length; i++) { - String key = keys[i]; - if (this[key] == value) return true; - } - return false; - } - - bool containsKey(Object key) { - if (_isUpgraded) return _upgradedMap.containsKey(key); - if (key is !String) return false; - return _hasProperty(_original, key); - } - - putIfAbsent(key, ifAbsent()) { - if (containsKey(key)) return this[key]; - var value = ifAbsent(); - this[key] = value; - return value; - } - - remove(Object key) { - if (!_isUpgraded && !containsKey(key)) return null; - return _upgrade().remove(key); - } - - void clear() { - if (_isUpgraded) { - _upgradedMap.clear(); - } else { - if (_data != null) { - // Clear the list of keys to make sure we force - // a concurrent modification error if anyone is - // currently iterating over it. - _data.clear(); - } - _original = _processed = null; - _data = {}; - } - } - - void forEach(void f(key, value)) { - if (_isUpgraded) return _upgradedMap.forEach(f); - List keys = _computeKeys(); - for (int i = 0; i < keys.length; i++) { - String key = keys[i]; - - // Compute the value under the assumption that the property - // is present but potentially not processed. - var value = _getProperty(_processed, key); - if (_isUnprocessed(value)) { - value = _convertJsonToDartLazy(_getProperty(_original, key)); - _setProperty(_processed, key, value); - } - - // Do the callback. - f(key, value); - - // Check if invoking the callback function changed - // the key set. If so, throw an exception. - if (!identical(keys, _data)) { - throw new ConcurrentModificationError(this); - } - } - } - - String toString() => Maps.mapToString(this); - - - // ------------------------------------------ - // Private helper methods. - // ------------------------------------------ - - bool get _isUpgraded => _processed == null; - - Map get _upgradedMap { - assert(_isUpgraded); - // 'cast' the union type to LinkedHashMap. It would be even better if we - // could 'cast' to the implementation type, since LinkedHashMap includes - // _JsonMap. - return JS('LinkedHashMap', '#', _data); - } - - List _computeKeys() { - assert(!_isUpgraded); - List keys = _data; - if (keys == null) { - keys = _data = _getPropertyNames(_original); - } - return JS('JSExtendableArray', '#', keys); - } - - Map _upgrade() { - if (_isUpgraded) return _upgradedMap; - - // Copy all the (key, value) pairs to a freshly allocated - // linked hash map thus preserving the ordering. - Map result = {}; - List keys = _computeKeys(); - for (int i = 0; i < keys.length; i++) { - String key = keys[i]; - result[key] = this[key]; - } - - // We only upgrade when we need to extend the map, so we can - // safely force a concurrent modification error in case - // someone is iterating over the map here. - if (keys.isEmpty) { - keys.add(null); - } else { - keys.clear(); - } - - // Clear out the associated JavaScript objects and mark the - // map as having been upgraded. - _original = _processed = null; - _data = result; - assert(_isUpgraded); - return result; - } - - _process(String key) { - if (!_hasProperty(_original, key)) return null; - var result = _convertJsonToDartLazy(_getProperty(_original, key)); - return _setProperty(_processed, key, result); - } - - - // ------------------------------------------ - // Private JavaScript helper methods. - // ------------------------------------------ - - static bool _hasProperty(object, String key) - => JS('bool', 'Object.prototype.hasOwnProperty.call(#,#)', object, key); - static _getProperty(object, String key) - => JS('', '#[#]', object, key); - static _setProperty(object, String key, value) - => JS('', '#[#]=#', object, key, value); - static List _getPropertyNames(object) - => JS('JSExtendableArray', 'Object.keys(#)', object); - static bool _isUnprocessed(object) - => JS('bool', 'typeof(#)=="undefined"', object); - static _newJavaScriptObject() - => JS('=Object', 'Object.create(null)'); -} -class _JsonMapKeyIterable extends ListIterable { - final _JsonMap _parent; - - _JsonMapKeyIterable(this._parent); - - int get length => _parent.length; - - String elementAt(int index) { - return _parent._isUpgraded ? _parent.keys.elementAt(index) - : _parent._computeKeys()[index]; - } - - /// Although [ListIterable] defines its own iterator, we return the iterator - /// of the underlying list [_keys] in order to propagate - /// [ConcurrentModificationError]s. - Iterator get iterator { - return _parent._isUpgraded ? _parent.keys.iterator - : _parent._computeKeys().iterator; - } - - /// Delegate to [parent.containsKey] to ensure the performance expected - /// from [Map.keys.containsKey]. - bool contains(Object key) => _parent.containsKey(key); -} -/** - * Implements the chunked conversion from a JSON string to its corresponding - * object. - * - * The sink only creates one object, but its input can be chunked. - */ -// TODO(floitsch): don't accumulate everything before starting to decode. -class _JsonDecoderSink extends _StringSinkConversionSink { - final _Reviver _reviver; - final Sink _sink; - - _JsonDecoderSink(this._reviver, this._sink) - : super(new StringBuffer()); - - void close() { - super.close(); - StringBuffer buffer = _stringSink; - String accumulated = buffer.toString(); - buffer.clear(); - Object decoded = _parseJson(accumulated, _reviver); - _sink.add(decoded); - _sink.close(); - } -} \ No newline at end of file diff --git a/pkg/dev_compiler/test/generated_sdk/lib/convert/converter.dart b/pkg/dev_compiler/test/generated_sdk/lib/convert/converter.dart deleted file mode 100644 index bce2aab472e4..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/convert/converter.dart +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.convert; - -/** - * A [Converter] converts data from one representation into another. - * - * It is recommended that implementations of `Converter` extend this class, - * to inherit any further methods that may be added to the class. - */ -abstract class Converter implements StreamTransformer { - const Converter(); - - /** - * Converts [input] and returns the result of the conversion. - */ - T convert(S input); - - /** - * Fuses `this` with [other]. - * - * Encoding with the resulting converter is equivalent to converting with - * `this` before converting with `other`. - */ - Converter fuse(Converter other) { - return new _FusedConverter(this, other); - } - - /** - * Starts a chunked conversion. - */ - ChunkedConversionSink startChunkedConversion(Sink sink) { - throw new UnsupportedError( - "This converter does not support chunked conversions: $this"); - } - - // Subclasses are encouraged to provide better types. - Stream bind(Stream source) { - return new Stream.eventTransformed( - source, - (EventSink sink) => new _ConverterStreamEventSink(this, sink)); - } -} - -/** - * Fuses two converters. - * - * For a non-chunked conversion converts the input in sequence. - */ -class _FusedConverter extends Converter { - final Converter _first; - final Converter _second; - - _FusedConverter(this._first, this._second); - - T convert(S input) => _second.convert(_first.convert(input)); - - ChunkedConversionSink startChunkedConversion(Sink sink) { - return _first.startChunkedConversion(_second.startChunkedConversion(sink)); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/convert/encoding.dart b/pkg/dev_compiler/test/generated_sdk/lib/convert/encoding.dart deleted file mode 100644 index cc67f6f176c5..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/convert/encoding.dart +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.convert; - -/** - * Open-ended Encoding enum. - */ -abstract class Encoding extends Codec> { - const Encoding(); - - Future decodeStream(Stream> byteStream) { - return byteStream - .transform(decoder) - .fold(new StringBuffer(), (buffer, string) => buffer..write(string)) - .then((buffer) => buffer.toString()); - } - - /** - * Name of the encoding. - * - * If the encoding is standardized, this is the lower-case version of one of - * the IANA official names for the character set (see - * http://www.iana.org/assignments/character-sets/character-sets.xml) - */ - String get name; - - // All aliases (in lowercase) of supported encoding from - // http://www.iana.org/assignments/character-sets/character-sets.xml. - static Map _nameToEncoding = { - // ISO_8859-1:1987. - "iso_8859-1:1987": LATIN1, - "iso-ir-100": LATIN1, - "iso_8859-1": LATIN1, - "iso-8859-1": LATIN1, - "latin1": LATIN1, - "l1": LATIN1, - "ibm819": LATIN1, - "cp819": LATIN1, - "csisolatin1": LATIN1, - - // US-ASCII. - "iso-ir-6": ASCII, - "ansi_x3.4-1968": ASCII, - "ansi_x3.4-1986": ASCII, - "iso_646.irv:1991": ASCII, - "iso646-us": ASCII, - "us-ascii": ASCII, - "us": ASCII, - "ibm367": ASCII, - "cp367": ASCII, - "csascii": ASCII, - "ascii": ASCII, // This is not in the IANA official names. - - // UTF-8. - "csutf8": UTF8, - "utf-8": UTF8 - }; - - /** - * Gets an [Encoding] object from the name of the character set - * name. The names used are the IANA official names for the - * character set (see - * http://www.iana.org/assignments/character-sets/character-sets.xml). - * - * The [name] passed is case insensitive. - * - * If character set is not supported [:null:] is returned. - */ - static Encoding getByName(String name) { - if (name == null) return null; - name = name.toLowerCase(); - return _nameToEncoding[name]; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/convert/html_escape.dart b/pkg/dev_compiler/test/generated_sdk/lib/convert/html_escape.dart deleted file mode 100644 index 512d9c31f2bf..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/convert/html_escape.dart +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.convert; - -// TODO(floitsch) - Document - Issue 13097 -const HtmlEscape HTML_ESCAPE = const HtmlEscape(); - -class HtmlEscapeMode { - final String _name; - final bool escapeLtGt; - final bool escapeQuot; - final bool escapeApos; - final bool escapeSlash; - - // TODO(floitsch) - Document - Issue 13097 - static const HtmlEscapeMode UNKNOWN = - const HtmlEscapeMode._('unknown', true, true, true, true); - - // TODO(floitsch) - Document - Issue 13097 - static const HtmlEscapeMode ATTRIBUTE = - const HtmlEscapeMode._('attribute', false, true, false, false); - - // TODO(floitsch) - Document - Issue 13097 - static const HtmlEscapeMode ELEMENT = - const HtmlEscapeMode._('element', true, false, false, true); - - // TODO(floitsch) - Document - Issue 13097 - const HtmlEscapeMode._(this._name, this.escapeLtGt, this.escapeQuot, - this.escapeApos, this.escapeSlash); - - String toString() => _name; -} - - // TODO(floitsch) - Document - Issue 13097 -class HtmlEscape extends Converter { - - // TODO(floitsch) - Document - Issue 13097 - final HtmlEscapeMode mode; - - // TODO(floitsch) - Document - Issue 13097 - const HtmlEscape([this.mode = HtmlEscapeMode.UNKNOWN]); - - String convert(String text) { - var val = _convert(text, 0, text.length); - return val == null ? text : val; - } - - String _convert(String text, int start, int end) { - StringBuffer result = null; - for (int i = start; i < end; i++) { - var ch = text[i]; - String replace = null; - switch (ch) { - case '&': replace = '&'; break; - case '\u00A0'/*NO-BREAK SPACE*/: replace = ' '; break; - case '"': if (mode.escapeQuot) replace = '"'; break; - case "'": if (mode.escapeApos) replace = '''; break; - case '<': if (mode.escapeLtGt) replace = '<'; break; - case '>': if (mode.escapeLtGt) replace = '>'; break; - case '/': if (mode.escapeSlash) replace = '/'; break; - } - if (replace != null) { - if (result == null) result = new StringBuffer(text.substring(start, i)); - result.write(replace); - } else if (result != null) { - result.write(ch); - } - } - - return result != null ? result.toString() : null; - } - - StringConversionSink startChunkedConversion(Sink sink) { - if (sink is! StringConversionSink) { - sink = new StringConversionSink.from(sink); - } - return new _HtmlEscapeSink(this, sink); - } -} - -class _HtmlEscapeSink extends StringConversionSinkBase { - final HtmlEscape _escape; - final StringConversionSink _sink; - - _HtmlEscapeSink(this._escape, this._sink); - - void addSlice(String chunk, int start, int end, bool isLast) { - var val = _escape._convert(chunk, start, end); - if(val == null) { - _sink.addSlice(chunk, start, end, isLast); - } else { - _sink.add(val); - if (isLast) _sink.close(); - } - } - - void close() => _sink.close(); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/convert/json.dart b/pkg/dev_compiler/test/generated_sdk/lib/convert/json.dart deleted file mode 100644 index e0e24214ddce..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/convert/json.dart +++ /dev/null @@ -1,1058 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.convert; - -/** - * Error thrown by JSON serialization if an object cannot be serialized. - * - * The [unsupportedObject] field holds that object that failed to be serialized. - * - * If an object isn't directly serializable, the serializer calls the 'toJson' - * method on the object. If that call fails, the error will be stored in the - * [cause] field. If the call returns an object that isn't directly - * serializable, the [cause] is be null. - */ -class JsonUnsupportedObjectError extends Error { - /** The object that could not be serialized. */ - final unsupportedObject; - /** The exception thrown when trying to convert the object. */ - final cause; - - JsonUnsupportedObjectError(this.unsupportedObject, { this.cause }); - - String toString() { - if (cause != null) { - return "Converting object to an encodable object failed."; - } else { - return "Converting object did not return an encodable object."; - } - } -} - - -/** - * Reports that an object could not be stringified due to cyclic references. - * - * An object that references itself cannot be serialized by [stringify]. - * When the cycle is detected, a [JsonCyclicError] is thrown. - */ -class JsonCyclicError extends JsonUnsupportedObjectError { - /** The first object that was detected as part of a cycle. */ - JsonCyclicError(Object object): super(object); - String toString() => "Cyclic error in JSON stringify"; -} - - -/** - * An instance of the default implementation of the [JsonCodec]. - * - * This instance provides a convenient access to the most common JSON - * use cases. - * - * Examples: - * - * var encoded = JSON.encode([1, 2, { "a": null }]); - * var decoded = JSON.decode('["foo", { "bar": 499 }]'); - */ -const JsonCodec JSON = const JsonCodec(); - -typedef _Reviver(var key, var value); -typedef _ToEncodable(var o); - - -/** - * A [JsonCodec] encodes JSON objects to strings and decodes strings to - * JSON objects. - */ -class JsonCodec extends Codec { - final _Reviver _reviver; - final _ToEncodable _toEncodable; - - /** - * Creates a `JsonCodec` with the given reviver and encoding function. - * - * The [reviver] function is called during decoding. It is invoked - * once for each object or list property that has been parsed. - * The `key` argument is either the - * integer list index for a list property, the string map key for object - * properties, or `null` for the final result. - * - * If [reviver] is omitted, it defaults to returning the value argument. - * - * The [toEncodable] function is used during encoding. It is invoked for - * values that are not directly encodable to a JSON1toE - * string (a value that is not a number, boolean, string, null, list or a map - * with string keys). The function must return an object that is directly - * encodable. The elements of a returned list and values of a returned map - * do not need be directly encodable, and if they aren't, `toEncodable` will - * be used on them as well. - * Please notice that it is possible to cause an infinite recursive - * regress in this way, by effectively creating an infinite data structure - * through repeated call to `toEncodable`. - * - * If [toEncodable] is omitted, it defaults to a function that returns the - * result of calling `.toJson()` on the unencodable object. - */ - const JsonCodec({reviver(var key, var value), toEncodable(var object)}) - : _reviver = reviver, - _toEncodable = toEncodable; - - /** - * Creates a `JsonCodec` with the given reviver. - * - * The [reviver] function is called once for each object or list property - * that has been parsed during decoding. The `key` argument is either the - * integer list index for a list property, the string map key for object - * properties, or `null` for the final result. - */ - JsonCodec.withReviver(reviver(var key, var value)) : this(reviver: reviver); - - /** - * Parses the string and returns the resulting Json object. - * - * The optional [reviver] function is called once for each object or list - * property that has been parsed during decoding. The `key` argument is either - * the integer list index for a list property, the string map key for object - * properties, or `null` for the final result. - * - * The default [reviver] (when not provided) is the identity function. - */ - dynamic decode(String source, {reviver(var key, var value)}) { - if (reviver == null) reviver = _reviver; - if (reviver == null) return decoder.convert(source); - return new JsonDecoder(reviver).convert(source); - } - - /** - * Converts [value] to a JSON string. - * - * If value contains objects that are not directly encodable to a JSON - * string (a value that is not a number, boolean, string, null, list or a map - * with string keys), the [toEncodable] function is used to convert it to an - * object that must be directly encodable. - * - * If [toEncodable] is omitted, it defaults to a function that returns the - * result of calling `.toJson()` on the unencodable object. - */ - String encode(Object value, {toEncodable(var object)}) { - if (toEncodable == null) toEncodable = _toEncodable; - if (toEncodable == null) return encoder.convert(value); - return new JsonEncoder(toEncodable).convert(value); - } - - JsonEncoder get encoder { - if (_toEncodable == null) return const JsonEncoder(); - return new JsonEncoder(_toEncodable); - } - - JsonDecoder get decoder { - if (_reviver == null) return const JsonDecoder(); - return new JsonDecoder(_reviver); - } -} - -/** - * This class converts JSON objects to strings. - */ -class JsonEncoder extends Converter { - /** - * The string used for indention. - * - * When generating multi-line output, this string is inserted once at the - * beginning of each indented line for each level of indentation. - * - * If `null`, the output is encoded as a single line. - */ - final String indent; - - /** - * Function called on non-encodable objects to return a replacement - * encodable object that will be encoded in the orignal's place. - */ - final Function _toEncodable; - - /** - * Creates a JSON encoder. - * - * The JSON encoder handles numbers, strings, booleans, null, lists and - * maps directly. - * - * Any other object is attempted converted by [toEncodable] to an - * object that is of one of the convertible types. - * - * If [toEncodable] is omitted, it defaults to calling `.toJson()` on - * the object. - */ - const JsonEncoder([Object toEncodable(Object nonSerializable)]) - : this.indent = null, - this._toEncodable = toEncodable; - - /** - * Creates a JSON encoder that creates multi-line JSON. - * - * The encoding of elements of lists and maps are indented and put on separate - * lines. The [indent] string is prepended to these elements, once for each - * level of indentation. - * - * If [indent] is `null`, the output is encoded as a single line. - * - * The JSON encoder handles numbers, strings, booleans, null, lists and - * maps directly. - * - * Any other object is attempted converted by [toEncodable] to an - * object that is of one of the convertible types. - * - * If [toEncodable] is omitted, it defaults to calling `.toJson()` on - * the object. - */ - const JsonEncoder.withIndent(this.indent, - [Object toEncodable(Object nonSerializable)]) - : this._toEncodable = toEncodable; - - /** - * Converts [object] to a JSON [String]. - * - * Directly serializable values are [num], [String], [bool], and [Null], as - * well as some [List] and [Map] values. - * For [List], the elements must all be serializable. - * For [Map], the keys must be [String] and the values must be serializable. - * - * If a value is any other type is attempted serialized, the conversion - * function provided in the constructor is invoked with the object as argument - * and the result, which must be a directly serializable value, - * is serialized instead of the original value. - * - * If the conversion throws, or returns a value that is not directly - * serializable, a [JsonUnsupportedObjectError] exception is thrown. - * If the call throws, the error is caught and stored in the - * [JsonUnsupportedObjectError]'s [:cause:] field. - * - * If a [List] or [Map] contains a reference to itself, directly or through - * other lists or maps, it cannot be serialized and a [JsonCyclicError] is - * thrown. - * - * [object] should not change during serialization. - * - * If an object is serialized more than once, [convert] may cache the text - * for it. In other words, if the content of an object changes after it is - * first serialized, the new values may not be reflected in the result. - */ - String convert(Object object) => - _JsonStringStringifier.stringify(object, _toEncodable, indent); - - /** - * Starts a chunked conversion. - * - * The converter works more efficiently if the given [sink] is a - * [StringConversionSink]. - * - * Returns a chunked-conversion sink that accepts at most one object. It is - * an error to invoke `add` more than once on the returned sink. - */ - ChunkedConversionSink startChunkedConversion(Sink sink) { - if (sink is! StringConversionSink) { - sink = new StringConversionSink.from(sink); - } else if (sink is _Utf8EncoderSink) { - return new _JsonUtf8EncoderSink(sink._sink, _toEncodable, - JsonUtf8Encoder._utf8Encode(indent), - JsonUtf8Encoder.DEFAULT_BUFFER_SIZE); - } - return new _JsonEncoderSink(sink, _toEncodable, indent); - } - - // Override the base-classes bind, to provide a better type. - Stream bind(Stream stream) => super.bind(stream); - - Converter fuse(Converter other) { - if (other is Utf8Encoder) { - return new JsonUtf8Encoder(indent, _toEncodable); - } - return super.fuse(other); - } -} - -/** - * Encoder that encodes a single object as a UTF-8 encoded JSON string. - * - * This encoder works equivalently to first converting the object to - * a JSON string, and then UTF-8 encoding the string, but without - * creating an intermediate string. - */ -class JsonUtf8Encoder extends Converter> { - /** Default buffer size used by the JSON-to-UTF-8 encoder. */ - static const int DEFAULT_BUFFER_SIZE = 256; - /** Indentation used in pretty-print mode, `null` if not pretty. */ - final List _indent; - /** Function called with each un-encodable object encountered. */ - final Function _toEncodable; - /** UTF-8 buffer size. */ - final int _bufferSize; - - /** - * Create converter. - * - * If [indent] is non-`null`, the converter attempts to "pretty-print" the - * JSON, and uses `indent` as the indentation. Otherwise the result has no - * whitespace outside of string literals. - * If `indent` contains characters that are not valid JSON whitespace - * characters, the result will not be valid JSON. JSON whitespace characters - * are space (U+0020), tab (U+0009), line feed (U+000a) and carriage return - * (U+000d) (ECMA 404). - * - * The [bufferSize] is the size of the internal buffers used to collect - * UTF-8 code units. - * If using [startChunkedConversion], it will be the size of the chunks. - * - * The JSON encoder handles numbers, strings, booleans, null, lists and - * maps directly. - * - * Any other object is attempted converted by [toEncodable] to an - * object that is of one of the convertible types. - * - * If [toEncodable] is omitted, it defaults to calling `.toJson()` on - * the object. - */ - JsonUtf8Encoder([String indent, - toEncodable(Object object), - int bufferSize = DEFAULT_BUFFER_SIZE]) - : _indent = _utf8Encode(indent), - _toEncodable = toEncodable, - _bufferSize = bufferSize; - - static List _utf8Encode(String string) { - if (string == null) return null; - if (string.isEmpty) return new Uint8List(0); - checkAscii: { - for (int i = 0; i < string.length; i++) { - if (string.codeUnitAt(i) >= 0x80) break checkAscii; - } - return string.codeUnits; - } - return UTF8.encode(string); - } - - /** Convert [object] into UTF-8 encoded JSON. */ - List convert(Object object) { - List> bytes = []; - // The `stringify` function always converts into chunks. - // Collect the chunks into the `bytes` list, then combine them afterwards. - void addChunk(Uint8List chunk, int start, int end) { - if (start > 0 || end < chunk.length) { - int length = end - start; - chunk = new Uint8List.view(chunk.buffer, - chunk.offsetInBytes + start, - length); - } - bytes.add(chunk); - } - _JsonUtf8Stringifier.stringify(object, - _indent, - _toEncodable, - _bufferSize, - addChunk); - if (bytes.length == 1) return bytes[0]; - int length = 0; - for (int i = 0; i < bytes.length; i++) { - length += bytes[i].length; - } - Uint8List result = new Uint8List(length); - for (int i = 0, offset = 0; i < bytes.length; i++) { - var byteList = bytes[i]; - int end = offset + byteList.length; - result.setRange(offset, end, byteList); - offset = end; - } - return result; - } - - /** - * Start a chunked conversion. - * - * Only one object can be passed into the returned sink. - * - * The argument [sink] will receive byte lists in sizes depending on the - * `bufferSize` passed to the constructor when creating this encoder. - */ - ChunkedConversionSink startChunkedConversion(Sink> sink) { - ByteConversionSink byteSink; - if (sink is ByteConversionSink) { - byteSink = sink; - } else { - byteSink = new ByteConversionSink.from(sink); - } - return new _JsonUtf8EncoderSink(byteSink, _toEncodable, - _indent, _bufferSize); - } - - // Override the base-classes bind, to provide a better type. - Stream> bind(Stream stream) { - return super.bind(stream); - } - - Converter fuse(Converter, dynamic> other) { - return super.fuse(other); - } -} - -/** - * Implements the chunked conversion from object to its JSON representation. - * - * The sink only accepts one value, but will produce output in a chunked way. - */ -class _JsonEncoderSink extends ChunkedConversionSink { - final String _indent; - final Function _toEncodable; - final StringConversionSink _sink; - bool _isDone = false; - - _JsonEncoderSink(this._sink, this._toEncodable, this._indent); - - /** - * Encodes the given object [o]. - * - * It is an error to invoke this method more than once on any instance. While - * this makes the input effectly non-chunked the output will be generated in - * a chunked way. - */ - void add(Object o) { - if (_isDone) { - throw new StateError("Only one call to add allowed"); - } - _isDone = true; - ClosableStringSink stringSink = _sink.asStringSink(); - _JsonStringStringifier.printOn(o, stringSink, _toEncodable, _indent); - stringSink.close(); - } - - void close() { /* do nothing */ } -} - -/** - * Sink returned when starting a chunked conversion from object to bytes. - */ -class _JsonUtf8EncoderSink extends ChunkedConversionSink { - /** The byte sink receiveing the encoded chunks. */ - final ByteConversionSink _sink; - final List _indent; - final Function _toEncodable; - final int _bufferSize; - bool _isDone = false; - _JsonUtf8EncoderSink(this._sink, this._toEncodable, this._indent, - this._bufferSize); - - /** Callback called for each slice of result bytes. */ - void _addChunk(Uint8List chunk, int start, int end) { - _sink.addSlice(chunk, start, end, false); - } - - void add(Object object) { - if (_isDone) { - throw new StateError("Only one call to add allowed"); - } - _isDone = true; - _JsonUtf8Stringifier.stringify(object, _indent, _toEncodable, - _bufferSize, - _addChunk); - _sink.close(); - } - - void close() { - if (!_isDone) { - _isDone = true; - _sink.close(); - } - } -} - -/** - * This class parses JSON strings and builds the corresponding objects. - */ -class JsonDecoder extends Converter { - final _Reviver _reviver; - /** - * Constructs a new JsonDecoder. - * - * The [reviver] may be `null`. - */ - const JsonDecoder([reviver(var key, var value)]) : this._reviver = reviver; - - /** - * Converts the given JSON-string [input] to its corresponding object. - * - * Parsed JSON values are of the types [num], [String], [bool], [Null], - * [List]s of parsed JSON values or [Map]s from [String] to parsed - * JSON values. - * - * If `this` was initialized with a reviver, then the parsing operation - * invokes the reviver on every object or list property that has been parsed. - * The arguments are the property name ([String]) or list index ([int]), and - * the value is the parsed value. The return value of the reviver is used as - * the value of that property instead the parsed value. - * - * Throws [FormatException] if the input is not valid JSON text. - */ - dynamic convert(String input) => _parseJson(input, _reviver); - - /** - * Starts a conversion from a chunked JSON string to its corresponding - * object. - * - * The output [sink] receives exactly one decoded element through `add`. - */ - StringConversionSink startChunkedConversion(Sink sink) { - return new _JsonDecoderSink(_reviver, sink); - } - - // Override the base-classes bind, to provide a better type. - Stream bind(Stream stream) => super.bind(stream); -} - -// Internal optimized JSON parsing implementation. -_parseJson(String source, reviver(key, value)) { - if (source is! String) throw new ArgumentError(source); - - var parsed; - try { - parsed = JS('=Object|JSExtendableArray|Null|bool|num|String', - 'JSON.parse(#)', - source); - } catch (e) { - throw new FormatException(JS('String', 'String(#)', e)); - } - - if (reviver == null) { - return _convertJsonToDartLazy(parsed); - } else { - return _convertJsonToDart(parsed, reviver); - } -} - - -// Implementation of encoder/stringifier. - -Object _defaultToEncodable(object) => object.toJson(); - -/** - * JSON encoder that traverses an object structure and writes JSON source. - * - * This is an abstract implementation that doesn't decide on the output - * format, but writes the JSON through abstract methods like [writeString]. - */ -abstract class _JsonStringifier { - // Character code constants. - static const int BACKSPACE = 0x08; - static const int TAB = 0x09; - static const int NEWLINE = 0x0a; - static const int CARRIAGE_RETURN = 0x0d; - static const int FORM_FEED = 0x0c; - static const int QUOTE = 0x22; - static const int CHAR_0 = 0x30; - static const int BACKSLASH = 0x5c; - static const int CHAR_b = 0x62; - static const int CHAR_f = 0x66; - static const int CHAR_n = 0x6e; - static const int CHAR_r = 0x72; - static const int CHAR_t = 0x74; - static const int CHAR_u = 0x75; - - /** List of objects currently being traversed. Used to detect cycles. */ - final List _seen = new List(); - /** Function called for each un-encodable object encountered. */ - final Function _toEncodable; - - _JsonStringifier(Object _toEncodable(Object o)) - : _toEncodable = (_toEncodable != null) ? _toEncodable - : _defaultToEncodable; - - /** Append a string to the JSON output. */ - void writeString(String characters); - /** Append part of a string to the JSON output. */ - void writeStringSlice(String characters, int start, int end); - /** Append a single character, given by its code point, to the JSON output. */ - void writeCharCode(int charCode); - /** Write a number to the JSON output. */ - void writeNumber(num number); - - // ('0' + x) or ('a' + x - 10) - static int hexDigit(int x) => x < 10 ? 48 + x : 87 + x; - - /** - * Write, and suitably escape, a string's content as a JSON string literal. - */ - void writeStringContent(String s) { - int offset = 0; - final int length = s.length; - for (int i = 0; i < length; i++) { - int charCode = s.codeUnitAt(i); - if (charCode > BACKSLASH) continue; - if (charCode < 32) { - if (i > offset) writeStringSlice(s, offset, i); - offset = i + 1; - writeCharCode(BACKSLASH); - switch (charCode) { - case BACKSPACE: - writeCharCode(CHAR_b); - break; - case TAB: - writeCharCode(CHAR_t); - break; - case NEWLINE: - writeCharCode(CHAR_n); - break; - case FORM_FEED: - writeCharCode(CHAR_f); - break; - case CARRIAGE_RETURN: - writeCharCode(CHAR_r); - break; - default: - writeCharCode(CHAR_u); - writeCharCode(CHAR_0); - writeCharCode(CHAR_0); - writeCharCode(hexDigit((charCode >> 4) & 0xf)); - writeCharCode(hexDigit(charCode & 0xf)); - break; - } - } else if (charCode == QUOTE || charCode == BACKSLASH) { - if (i > offset) writeStringSlice(s, offset, i); - offset = i + 1; - writeCharCode(BACKSLASH); - writeCharCode(charCode); - } - } - if (offset == 0) { - writeString(s); - } else if (offset < length) { - writeStringSlice(s, offset, length); - } - } - - /** - * Check if an encountered object is already being traversed. - * - * Records the object if it isn't already seen. - * Should have a matching call to [_removeSeen] when the object - * is no longer being traversed. - */ - void _checkCycle(object) { - for (int i = 0; i < _seen.length; i++) { - if (identical(object, _seen[i])) { - throw new JsonCyclicError(object); - } - } - _seen.add(object); - } - - /** - * Removes object from the list of currently traversed objects. - * - * Should be called in the opposite order of the matching [_checkCycle] - * calls. - */ - void _removeSeen(object) { - assert(!_seen.isEmpty); - assert(identical(_seen.last, object)); - _seen.removeLast(); - } - - /** - * Writes an object. - * - * If the object isn't directly encodable, the [_toEncodable] function - * gets one chance to return a replacement which is encodable. - */ - void writeObject(object) { - // Tries stringifying object directly. If it's not a simple value, List or - // Map, call toJson() to get a custom representation and try serializing - // that. - if (writeJsonValue(object)) return; - _checkCycle(object); - try { - var customJson = _toEncodable(object); - if (!writeJsonValue(customJson)) { - throw new JsonUnsupportedObjectError(object); - } - _removeSeen(object); - } catch (e) { - throw new JsonUnsupportedObjectError(object, cause: e); - } - } - - /** - * Serializes a [num], [String], [bool], [Null], [List] or [Map] value. - * - * Returns true if the value is one of these types, and false if not. - * If a value is both a [List] and a [Map], it's serialized as a [List]. - */ - bool writeJsonValue(object) { - if (object is num) { - if (!object.isFinite) return false; - writeNumber(object); - return true; - } else if (identical(object, true)) { - writeString('true'); - return true; - } else if (identical(object, false)) { - writeString('false'); - return true; - } else if (object == null) { - writeString('null'); - return true; - } else if (object is String) { - writeString('"'); - writeStringContent(object); - writeString('"'); - return true; - } else if (object is List) { - _checkCycle(object); - writeList(object); - _removeSeen(object); - return true; - } else if (object is Map) { - _checkCycle(object); - writeMap(object); - _removeSeen(object); - return true; - } else { - return false; - } - } - - /** Serializes a [List]. */ - void writeList(List list) { - writeString('['); - if (list.length > 0) { - writeObject(list[0]); - for (int i = 1; i < list.length; i++) { - writeString(','); - writeObject(list[i]); - } - } - writeString(']'); - } - - /** Serializes a [Map]. */ - void writeMap(Map map) { - writeString('{'); - String separator = '"'; - map.forEach((String key, value) { - writeString(separator); - separator = ',"'; - writeStringContent(key); - writeString('":'); - writeObject(value); - }); - writeString('}'); - } -} - -/** - * A modification of [_JsonStringifier] which indents the contents of [List] and - * [Map] objects using the specified indent value. - * - * Subclasses should implement [writeIndentation]. - */ -abstract class _JsonPrettyPrintMixin implements _JsonStringifier { - int _indentLevel = 0; - - /** - * Add [indentLevel] indentations to the JSON output. - */ - void writeIndentation(indentLevel); - - void writeList(List list) { - if (list.isEmpty) { - writeString('[]'); - } else { - writeString('[\n'); - _indentLevel++; - writeIndentation(_indentLevel); - writeObject(list[0]); - for (int i = 1; i < list.length; i++) { - writeString(',\n'); - writeIndentation(_indentLevel); - writeObject(list[i]); - } - writeString('\n'); - _indentLevel--; - writeIndentation(_indentLevel); - writeString(']'); - } - } - - void writeMap(Map map) { - if (map.isEmpty) { - writeString('{}'); - } else { - writeString('{\n'); - _indentLevel++; - bool first = true; - map.forEach((String key, Object value) { - if (!first) { - writeString(",\n"); - } - writeIndentation(_indentLevel); - writeString('"'); - writeStringContent(key); - writeString('": '); - writeObject(value); - first = false; - }); - writeString('\n'); - _indentLevel--; - writeIndentation(_indentLevel); - writeString('}'); - } - } -} - -/** - * A specialziation of [_JsonStringifier] that writes its JSON to a string. - */ -class _JsonStringStringifier extends _JsonStringifier { - final StringSink _sink; - - _JsonStringStringifier(this._sink, _toEncodable) : super(_toEncodable); - - /** - * Convert object to a string. - * - * The [toEncodable] function is used to convert non-encodable objects - * to encodable ones. - * - * If [indent] is not `null`, the resulting JSON will be "pretty-printed" - * with newlines and indentation. The `indent` string is added as indentation - * for each indentation level. It should only contain valid JSON whitespace - * characters (space, tab, carriage return or line feed). - */ - static String stringify(object, toEncodable(object), String indent) { - StringBuffer output = new StringBuffer(); - printOn(object, output, toEncodable, indent); - return output.toString(); - } - - /** - * Convert object to a string, and write the result to the [output] sink. - * - * The result is written piecemally to the sink. - */ - static void printOn(object, StringSink output, toEncodable(object), - String indent) { - var stringifier; - if (indent == null) { - stringifier = new _JsonStringStringifier(output, toEncodable); - } else { - stringifier = - new _JsonStringStringifierPretty(output, toEncodable, indent); - } - stringifier.writeObject(object); - } - - void writeNumber(num number) { - _sink.write(number.toString()); - } - void writeString(String string) { - _sink.write(string); - } - void writeStringSlice(String string, int start, int end) { - _sink.write(string.substring(start, end)); - } - void writeCharCode(int charCode) { - _sink.writeCharCode(charCode); - } -} - -class _JsonStringStringifierPretty extends _JsonStringStringifier - with _JsonPrettyPrintMixin { - final String _indent; - - _JsonStringStringifierPretty(StringSink sink, Function toEncodable, - this._indent) - : super(sink, toEncodable); - - void writeIndentation(int count) { - for (int i = 0; i < count; i++) writeString(_indent); - } -} - -/** - * Specialization of [_JsonStringifier] that writes the JSON as UTF-8. - * - * The JSON text is UTF-8 encoded and written to [Uint8List] buffers. - * The buffers are then passed back to a user provided callback method. - */ -class _JsonUtf8Stringifier extends _JsonStringifier { - final int bufferSize; - final Function addChunk; - Uint8List buffer; - int index = 0; - - _JsonUtf8Stringifier(toEncodable, int bufferSize, this.addChunk) - : this.bufferSize = bufferSize, - buffer = new Uint8List(bufferSize), - super(toEncodable) - ; - - /** - * Convert [object] to UTF-8 encoded JSON. - * - * Calls [addChunk] with slices of UTF-8 code units. - * These will typically have size [bufferSize], but may be shorter. - * The buffers are not reused, so the [addChunk] call may keep and reuse - * the chunks. - * - * If [indent] is non-`null`, the result will be "pretty-printed" with - * extra newlines and indentation, using [indent] as the indentation. - */ - static void stringify(Object object, - List indent, - toEncodableFunction(Object o), - int bufferSize, - void addChunk(Uint8List chunk, int start, int end)) { - _JsonUtf8Stringifier stringifier; - if (indent != null) { - stringifier = new _JsonUtf8StringifierPretty(toEncodableFunction, indent, - bufferSize, addChunk); - } else { - stringifier = new _JsonUtf8Stringifier(toEncodableFunction, - bufferSize, addChunk); - } - stringifier.writeObject(object); - stringifier.flush(); - } - - /** - * Must be called at the end to push the last chunk to the [addChunk] - * callback. - */ - void flush() { - if (index > 0) { - addChunk(buffer, 0, index); - } - buffer = null; - index = 0; - } - - void writeNumber(num number) { - writeAsciiString(number.toString()); - } - - /** Write a string that is known to not have non-ASCII characters. */ - void writeAsciiString(String string) { - // TODO(lrn): Optimize by copying directly into buffer instead of going - // through writeCharCode; - for (int i = 0; i < string.length; i++) { - int char = string.codeUnitAt(i); - assert(char <= 0x7f); - writeByte(char); - } - } - - void writeString(String string) { - writeStringSlice(string, 0, string.length); - } - - void writeStringSlice(String string, int start, int end) { - // TODO(lrn): Optimize by copying directly into buffer instead of going - // through writeCharCode/writeByte. Assumption is the most characters - // in starings are plain ASCII. - for (int i = start; i < end; i++) { - int char = string.codeUnitAt(i); - if (char <= 0x7f) { - writeByte(char); - } else { - if ((char & 0xFC00) == 0xD800 && i + 1 < end) { - // Lead surrogate. - int nextChar = string.codeUnitAt(i + 1); - if ((nextChar & 0xFC00) == 0xDC00) { - // Tail surrogate. - char = 0x10000 + ((char & 0x3ff) << 10) + (nextChar & 0x3ff); - writeFourByteCharCode(char); - i++; - continue; - } - } - writeMultiByteCharCode(char); - } - } - } - - void writeCharCode(int charCode) { - if (charCode <= 0x7f) { - writeByte(charCode); - return; - } - writeMultiByteCharCode(charCode); - } - - void writeMultiByteCharCode(int charCode) { - if (charCode <= 0x7ff) { - writeByte(0xC0 | (charCode >> 6)); - writeByte(0x80 | (charCode & 0x3f)); - return; - } - if (charCode <= 0xffff) { - writeByte(0xE0 | (charCode >> 12)); - writeByte(0x80 | ((charCode >> 6) & 0x3f)); - writeByte(0x80 | (charCode & 0x3f)); - return; - } - writeFourByteCharCode(charCode); - } - - void writeFourByteCharCode(int charCode) { - assert(charCode <= 0x10ffff); - writeByte(0xF0 | (charCode >> 18)); - writeByte(0x80 | ((charCode >> 12) & 0x3f)); - writeByte(0x80 | ((charCode >> 6) & 0x3f)); - writeByte(0x80 | (charCode & 0x3f)); - } - - void writeByte(int byte) { - assert(byte <= 0xff); - if (index == buffer.length) { - addChunk(buffer, 0, index); - buffer = new Uint8List(bufferSize); - index = 0; - } - buffer[index++] = byte; - } -} - -/** - * Pretty-printing version of [_JsonUtf8Stringifier]. - */ -class _JsonUtf8StringifierPretty extends _JsonUtf8Stringifier - with _JsonPrettyPrintMixin { - final List indent; - _JsonUtf8StringifierPretty(toEncodableFunction, this.indent, - bufferSize, addChunk) - : super(toEncodableFunction, bufferSize, addChunk); - - void writeIndentation(int count) { - List indent = this.indent; - int indentLength = indent.length; - if (indentLength == 1) { - int char = indent[0]; - while (count > 0) { - writeByte(char); - count -= 1; - } - return; - } - while (count > 0) { - count--; - int end = index + indentLength; - if (end <= buffer.length) { - buffer.setRange(index, end, indent); - index = end; - } else { - for (int i = 0; i < indentLength; i++) { - writeByte(indent[i]); - } - } - } - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/convert/latin1.dart b/pkg/dev_compiler/test/generated_sdk/lib/convert/latin1.dart deleted file mode 100644 index 7f7fef883ca1..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/convert/latin1.dart +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.convert; - -/** - * An instance of the default implementation of the [Latin1Codec]. - * - * This instance provides a convenient access to the most common ISO Latin 1 - * use cases. - * - * Examples: - * - * var encoded = LATIN1.encode("blåbærgrød"); - * var decoded = LATIN1.decode([0x62, 0x6c, 0xe5, 0x62, 0xe6, - * 0x72, 0x67, 0x72, 0xf8, 0x64]); - */ -const Latin1Codec LATIN1 = const Latin1Codec(); - -const int _LATIN1_MASK = 0xFF; - -/** - * A [LatinCodec] encodes strings to ISO Latin-1 (aka ISO-8859-1) bytes - * and decodes Latin-1 bytes to strings. - */ -class Latin1Codec extends Encoding { - final bool _allowInvalid; - /** - * Instantiates a new [Latin1Codec]. - * - * If [allowInvalid] is true, the [decode] method and the converter - * returned by [decoder] will default to allowing invalid values. Invalid - * values are decoded into the Unicode Replacement character (U+FFFD). - * Calls to the [decode] method can override this default. - * - * Encoders will not accept invalid (non Latin-1) characters. - */ - const Latin1Codec({bool allowInvalid: false}) : _allowInvalid = allowInvalid; - - String get name => "iso-8859-1"; - - /** - * Decodes the Latin-1 [bytes] (a list of unsigned 8-bit integers) to the - * corresponding string. - * - * If [bytes] contains values that are not in the range 0 .. 255, the decoder - * will eventually throw a [FormatException]. - * - * If [allowInvalid] is not provided, it defaults to the value used to create - * this [Latin1Codec]. - */ - String decode(List bytes, { bool allowInvalid }) { - if (allowInvalid == null) allowInvalid = _allowInvalid; - if (allowInvalid) { - return const Latin1Decoder(allowInvalid: true).convert(bytes); - } else { - return const Latin1Decoder(allowInvalid: false).convert(bytes); - } - } - - Converter> get encoder => const Latin1Encoder(); - - Converter, String> get decoder => - _allowInvalid ? const Latin1Decoder(allowInvalid: true) - : const Latin1Decoder(allowInvalid: false); -} - -/** - * This class converts strings of only ISO Latin-1 characters to bytes. - */ -class Latin1Encoder extends _UnicodeSubsetEncoder { - const Latin1Encoder() : super(_LATIN1_MASK); -} - -/** - * This class converts Latin-1 bytes (lists of unsigned 8-bit integers) - * to a string. - */ -class Latin1Decoder extends _UnicodeSubsetDecoder { - /** - * Instantiates a new [Latin1Decoder]. - * - * The optional [allowInvalid] argument defines how [convert] deals - * with invalid bytes. - * - * If it is `true`, [convert] replaces invalid bytes with the Unicode - * Replacement character `U+FFFD` (�). - * Otherwise it throws a [FormatException]. - */ - const Latin1Decoder({ bool allowInvalid: false }) - : super(allowInvalid, _LATIN1_MASK); - - /** - * Starts a chunked conversion. - * - * The converter works more efficiently if the given [sink] is a - * [StringConversionSink]. - */ - ByteConversionSink startChunkedConversion(Sink sink) { - StringConversionSink stringSink; - if (sink is StringConversionSink) { - stringSink = sink; - } else { - stringSink = new StringConversionSink.from(sink); - } - // TODO(lrn): Use stringSink.asUtf16Sink() if it becomes available. - if (!_allowInvalid) return new _Latin1DecoderSink(stringSink); - return new _Latin1AllowInvalidDecoderSink(stringSink); - } -} - -class _Latin1DecoderSink extends ByteConversionSinkBase { - StringConversionSink _sink; - _Latin1DecoderSink(this._sink); - - void close() { - _sink.close(); - } - - void add(List source) { - addSlice(source, 0, source.length, false); - } - - void _addSliceToSink(List source, int start, int end, bool isLast) { - // If _sink was a UTF-16 conversion sink, just add the slice directly with - // _sink.addSlice(source, start, end, isLast). - // The code below is an moderately stupid workaround until a real - // solution can be made. - _sink.add(new String.fromCharCodes(source, start, end)); - if (isLast) close(); - } - - void addSlice(List source, int start, int end, bool isLast) { - RangeError.checkValidRange(start, end, source.length); - for (int i = start; i < end; i++) { - int char = source[i]; - if (char > _LATIN1_MASK || char < 0) { - throw new FormatException("Source contains non-Latin-1 characters."); - } - } - if (start < end) { - _addSliceToSink(source, start, end, isLast); - } - if (isLast) { - close(); - } - } -} - -class _Latin1AllowInvalidDecoderSink extends _Latin1DecoderSink { - _Latin1AllowInvalidDecoderSink(StringConversionSink sink): super(sink); - - void addSlice(List source, int start, int end, bool isLast) { - RangeError.checkValidRange(start, end, source.length); - for (int i = start; i < end; i++) { - int char = source[i]; - if (char > _LATIN1_MASK || char < 0) { - if (i > start) _addSliceToSink(source, start, i, false); - // Add UTF-8 encoding of U+FFFD. - _addSliceToSink(const[0xFFFD], 0, 1, false); - start = i + 1; - } - } - if (start < end) { - _addSliceToSink(source, start, end, isLast); - } - if (isLast) { - close(); - } - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/convert/line_splitter.dart b/pkg/dev_compiler/test/generated_sdk/lib/convert/line_splitter.dart deleted file mode 100644 index 53337f00fffc..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/convert/line_splitter.dart +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.convert; - -/** - * This class splits [String] values into individual lines. - */ -class LineSplitter extends Converter> { - - const LineSplitter(); - - List convert(String data) { - var lines = new List(); - - _LineSplitterSink._addSlice(data, 0, data.length, true, lines.add); - - return lines; - } - - StringConversionSink startChunkedConversion(Sink sink) { - if (sink is! StringConversionSink) { - sink = new StringConversionSink.from(sink); - } - return new _LineSplitterSink(sink); - } -} - -// TODO(floitsch): deal with utf8. -class _LineSplitterSink extends StringConversionSinkBase { - static const int _LF = 10; - static const int _CR = 13; - - final StringConversionSink _sink; - - String _carry; - - _LineSplitterSink(this._sink); - - void addSlice(String chunk, int start, int end, bool isLast) { - if (_carry != null) { - chunk = _carry + chunk.substring(start, end); - start = 0; - end = chunk.length; - _carry = null; - } - _carry = _addSlice(chunk, start, end, isLast, _sink.add); - if (isLast) _sink.close(); - } - - void close() { - addSlice('', 0, 0, true); - } - - static String _addSlice(String chunk, int start, int end, bool isLast, - void adder(String val)) { - - int pos = start; - while (pos < end) { - int skip = 0; - int char = chunk.codeUnitAt(pos); - if (char == _LF) { - skip = 1; - } else if (char == _CR) { - skip = 1; - if (pos + 1 < end) { - if (chunk.codeUnitAt(pos + 1) == _LF) { - skip = 2; - } - } else if (!isLast) { - return chunk.substring(start, end); - } - } - if (skip > 0) { - adder(chunk.substring(start, pos)); - start = pos = pos + skip; - } else { - pos++; - } - } - if (pos != start) { - var carry = chunk.substring(start, pos); - if (isLast) { - // Add remaining - adder(carry); - } else { - return carry; - } - } - return null; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/convert/string_conversion.dart b/pkg/dev_compiler/test/generated_sdk/lib/convert/string_conversion.dart deleted file mode 100644 index 47329923f405..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/convert/string_conversion.dart +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.convert; - -/** - * This class provides an interface for converters to - * efficiently transmit String data. - * - * Instead of limiting the interface to one non-chunked String it accepts - * partial strings or can be transformed into a byte sink that - * accepts UTF-8 code units. - * - * This abstract class will likely get more methods over time. Implementers are - * urged to extend [StringConversionSinkBase] or to mix in - * [StringConversionSinkMixin], to ensure that their class covers the newly - * added methods. - */ -abstract class StringConversionSink - extends ChunkedConversionSink { - StringConversionSink(); - factory StringConversionSink.withCallback(void callback(String accumulated)) - = _StringCallbackSink; - factory StringConversionSink.from(Sink sink) - = _StringAdapterSink; - - /** - * Creates a new instance wrapping the given [sink]. - * - * Every string that is added to the returned instance is forwarded to - * the [sink]. The instance is allowed to buffer and is not required to - * forward immediately. - */ - factory StringConversionSink.fromStringSink(StringSink sink) = - _StringSinkConversionSink; - - /** - * Adds the next [chunk] to `this`. - * - * Adds the substring defined by [start] and [end]-exclusive to `this`. - * - * If [isLast] is `true` closes `this`. - */ - void addSlice(String chunk, int start, int end, bool isLast); - - /** - * Returns `this` as a sink that accepts UTF-8 input. - * - * If used, this method must be the first and only call to `this`. It - * invalidates `this`. All further operations must be performed on the result. - */ - ByteConversionSink asUtf8Sink(bool allowMalformed); - // - asRuneSink - // - asCodeUnitsSink - - /** - * Returns `this` as a [ClosableStringSink]. - * - * If used, this method must be the first and only call to `this`. It - * invalidates `this`. All further operations must be performed on the result. - */ - ClosableStringSink asStringSink(); -} - -/** - * A [ClosableStringSink] extends the [StringSink] interface by adding a - * `close` method. - */ -abstract class ClosableStringSink extends StringSink { - /** - * Creates a new instance combining a [StringSink] [sink] and a callback - * [onClose] which is invoked when the returned instance is closed. - */ - factory ClosableStringSink.fromStringSink(StringSink sink, void onClose()) - = _ClosableStringSink; - - /** - * Closes `this` and flushes any outstanding data. - */ - void close(); -} - -typedef void _StringSinkCloseCallback(); - -/** - * This class wraps an existing [StringSink] and invokes a - * closure when [close] is invoked. - */ -class _ClosableStringSink implements ClosableStringSink { - final _StringSinkCloseCallback _callback; - final StringSink _sink; - - _ClosableStringSink(this._sink, this._callback); - - void close() => _callback(); - - void writeCharCode(int charCode) => _sink.writeCharCode(charCode); - void write(Object o) => _sink.write(o); - void writeln([Object o = ""]) => _sink.writeln(o); - void writeAll(Iterable objects, [String separator = ""]) - => _sink.writeAll(objects, separator); -} - -/** - * This class wraps an existing [StringConversionSink] and exposes a - * [ClosableStringSink] interface. The wrapped sink only needs to implement - * `add` and `close`. - */ -// TODO(floitsch): make this class public? -class _StringConversionSinkAsStringSinkAdapter implements ClosableStringSink { - static const _MIN_STRING_SIZE = 16; - - StringBuffer _buffer; - StringConversionSink _chunkedSink; - - _StringConversionSinkAsStringSinkAdapter(this._chunkedSink) - : _buffer = new StringBuffer(); - - void close() { - if (_buffer.isNotEmpty) _flush(); - _chunkedSink.close(); - } - - void writeCharCode(int charCode) { - _buffer.writeCharCode(charCode); - if (_buffer.length > _MIN_STRING_SIZE) _flush(); - } - - void write(Object o) { - if (_buffer.isNotEmpty) _flush(); - String str = o.toString(); - _chunkedSink.add(o.toString()); - } - - void writeln([Object o = ""]) { - _buffer.writeln(o); - if (_buffer.length > _MIN_STRING_SIZE) _flush(); - } - - void writeAll(Iterable objects, [String separator = ""]) { - if (_buffer.isNotEmpty) _flush(); - Iterator iterator = objects.iterator; - if (!iterator.moveNext()) return; - if (separator.isEmpty) { - do { - _chunkedSink.add(iterator.current.toString()); - } while (iterator.moveNext()); - } else { - _chunkedSink.add(iterator.current.toString()); - while (iterator.moveNext()) { - write(separator); - _chunkedSink.add(iterator.current.toString()); - } - } - } - - void _flush() { - String accumulated = _buffer.toString(); - _buffer.clear(); - _chunkedSink.add(accumulated); - } -} - -/** - * This class provides a base-class for converters that need to accept String - * inputs. - */ -abstract class StringConversionSinkBase extends StringConversionSinkMixin { -} - -/** - * This class provides a mixin for converters that need to accept String - * inputs. - */ -abstract class StringConversionSinkMixin implements StringConversionSink { - - void addSlice(String str, int start, int end, bool isLast); - void close(); - - void add(String str) => addSlice(str, 0, str.length, false); - - ByteConversionSink asUtf8Sink(bool allowMalformed) { - return new _Utf8ConversionSink(this, allowMalformed); - } - - ClosableStringSink asStringSink() { - return new _StringConversionSinkAsStringSinkAdapter(this); - } -} - -/** - * This class is a [StringConversionSink] that wraps a [StringSink]. - */ -class _StringSinkConversionSink extends StringConversionSinkBase { - StringSink _stringSink; - _StringSinkConversionSink(StringSink this._stringSink); - - void close() {} - void addSlice(String str, int start, int end, bool isLast) { - if (start != 0 || end != str.length) { - for (int i = start; i < end; i++) { - _stringSink.writeCharCode(str.codeUnitAt(i)); - } - } else { - _stringSink.write(str); - } - if (isLast) close(); - } - - void add(String str) => _stringSink.write(str); - - ByteConversionSink asUtf8Sink(bool allowMalformed) { - return new _Utf8StringSinkAdapter(this, _stringSink, allowMalformed); - } - - ClosableStringSink asStringSink() { - return new ClosableStringSink.fromStringSink(_stringSink, this.close); - } -} - -/** - * This class accumulates all chunks into one string - * and invokes a callback when the sink is closed. - * - * This class can be used to terminate a chunked conversion. - */ -class _StringCallbackSink extends _StringSinkConversionSink { - final _ChunkedConversionCallback _callback; - _StringCallbackSink(this._callback) : super(new StringBuffer()); - - void close() { - StringBuffer buffer = _stringSink; - String accumulated = buffer.toString(); - buffer.clear(); - _callback(accumulated); - } - - ByteConversionSink asUtf8Sink(bool allowMalformed) { - return new _Utf8StringSinkAdapter( - this, _stringSink, allowMalformed); - } -} - -/** - * This class adapts a simple [ChunkedConversionSink] to a - * [StringConversionSink]. - * - * All additional methods of the [StringConversionSink] (compared to the - * ChunkedConversionSink) are redirected to the `add` method. - */ -class _StringAdapterSink extends StringConversionSinkBase { - final Sink _sink; - - _StringAdapterSink(this._sink); - - void add(String str) => _sink.add(str); - - void addSlice(String str, int start, int end, bool isLast) { - if (start == 0 && end == str.length) { - add(str); - } else { - add(str.substring(start, end)); - } - if (isLast) close(); - } - - void close() => _sink.close(); -} - - -/** - * Decodes UTF-8 code units and stores them in a [StringSink]. - */ -class _Utf8StringSinkAdapter extends ByteConversionSink { - final _Utf8Decoder _decoder; - final Sink _sink; - - _Utf8StringSinkAdapter(this._sink, - StringSink stringSink, bool allowMalformed) - : _decoder = new _Utf8Decoder(stringSink, allowMalformed); - - void close() { - _decoder.close(); - if(_sink != null) _sink.close(); - } - - void add(List chunk) { - addSlice(chunk, 0, chunk.length, false); - } - - void addSlice(List codeUnits, int startIndex, int endIndex, - bool isLast) { - _decoder.convert(codeUnits, startIndex, endIndex); - if (isLast) close(); - } -} - -/** - * Decodes UTF-8 code units. - * - * Forwards the decoded strings to the given [StringConversionSink]. - */ -// TODO(floitsch): make this class public? -class _Utf8ConversionSink extends ByteConversionSink { - - final _Utf8Decoder _decoder; - final StringConversionSink _chunkedSink; - final StringBuffer _buffer; - _Utf8ConversionSink(StringConversionSink sink, bool allowMalformed) - : this._(sink, new StringBuffer(), allowMalformed); - - _Utf8ConversionSink._(this._chunkedSink, StringBuffer stringBuffer, - bool allowMalformed) - : _decoder = new _Utf8Decoder(stringBuffer, allowMalformed), - _buffer = stringBuffer; - - void close() { - _decoder.close(); - if (_buffer.isNotEmpty) { - String accumulated = _buffer.toString(); - _buffer.clear(); - _chunkedSink.addSlice(accumulated, 0, accumulated.length, true); - } else { - _chunkedSink.close(); - } - } - - void add(List chunk) { - addSlice(chunk, 0, chunk.length, false); - } - - void addSlice(List chunk, int startIndex, int endIndex, bool isLast) { - _decoder.convert(chunk, startIndex, endIndex); - if (_buffer.isNotEmpty) { - String accumulated = _buffer.toString(); - _chunkedSink.addSlice(accumulated, 0, accumulated.length, isLast); - _buffer.clear(); - return; - } - if (isLast) close(); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/convert/utf.dart b/pkg/dev_compiler/test/generated_sdk/lib/convert/utf.dart deleted file mode 100644 index eaf01fc61a3f..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/convert/utf.dart +++ /dev/null @@ -1,566 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.convert; - -/** The Unicode Replacement character `U+FFFD` (�). */ -const int UNICODE_REPLACEMENT_CHARACTER_RUNE = 0xFFFD; - -/** The Unicode Byte Order Marker (BOM) character `U+FEFF`. */ -const int UNICODE_BOM_CHARACTER_RUNE = 0xFEFF; - -/** - * An instance of the default implementation of the [Utf8Codec]. - * - * This instance provides a convenient access to the most common UTF-8 - * use cases. - * - * Examples: - * - * var encoded = UTF8.encode("Îñţérñåţîöñåļîžåţîờñ"); - * var decoded = UTF8.decode([0x62, 0x6c, 0xc3, 0xa5, 0x62, 0xc3, 0xa6, - * 0x72, 0x67, 0x72, 0xc3, 0xb8, 0x64]); - */ -const Utf8Codec UTF8 = const Utf8Codec(); - -/** - * A [Utf8Codec] encodes strings to utf-8 code units (bytes) and decodes - * UTF-8 code units to strings. - */ -class Utf8Codec extends Encoding { - final bool _allowMalformed; - - /** - * Instantiates a new [Utf8Codec]. - * - * The optional [allowMalformed] argument defines how [decoder] (and [decode]) - * deal with invalid or unterminated character sequences. - * - * If it is `true` (and not overriden at the method invocation) [decode] and - * the [decoder] replace invalid (or unterminated) octet - * sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise - * they throw a [FormatException]. - */ - const Utf8Codec({ bool allowMalformed: false }) - : _allowMalformed = allowMalformed; - - String get name => "utf-8"; - - /** - * Decodes the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the - * corresponding string. - * - * If the [codeUnits] start with a leading [UNICODE_BOM_CHARACTER_RUNE] this - * character is discarded. - * - * If [allowMalformed] is `true` the decoder replaces invalid (or - * unterminated) character sequences with the Unicode Replacement character - * `U+FFFD` (�). Otherwise it throws a [FormatException]. - * - * If [allowMalformed] is not given, it defaults to the `allowMalformed` that - * was used to instantiate `this`. - */ - String decode(List codeUnits, { bool allowMalformed }) { - if (allowMalformed == null) allowMalformed = _allowMalformed; - return new Utf8Decoder(allowMalformed: allowMalformed).convert(codeUnits); - } - - Utf8Encoder get encoder => new Utf8Encoder(); - Utf8Decoder get decoder { - return new Utf8Decoder(allowMalformed: _allowMalformed); - } -} - -/** - * This class converts strings to their UTF-8 code units (a list of - * unsigned 8-bit integers). - */ -class Utf8Encoder extends Converter> { - - const Utf8Encoder(); - - /** - * Converts [string] to its UTF-8 code units (a list of - * unsigned 8-bit integers). - * - * If [start] and [end] are provided, only the substring - * `string.substring(start, end)` is converted. - */ - List convert(String string, [int start = 0, int end]) { - int stringLength = string.length; - RangeError.checkValidRange(start, end, stringLength); - if (end == null) end = stringLength; - int length = end - start; - if (length == 0) return new Uint8List(0); - // Create a new encoder with a length that is guaranteed to be big enough. - // A single code unit uses at most 3 bytes, a surrogate pair at most 4. - _Utf8Encoder encoder = new _Utf8Encoder.withBufferSize(length * 3); - int endPosition = encoder._fillBuffer(string, start, end); - assert(endPosition >= end - 1); - if (endPosition != end) { - // Encoding skipped the last code unit. - // That can only happen if the last code unit is a leadsurrogate. - // Force encoding of the lead surrogate by itself. - int lastCodeUnit = string.codeUnitAt(end - 1); - assert(_isLeadSurrogate(lastCodeUnit)); - // We use a non-surrogate as `nextUnit` so that _writeSurrogate just - // writes the lead-surrogate. - bool wasCombined = encoder._writeSurrogate(lastCodeUnit, 0); - assert(!wasCombined); - } - return encoder._buffer.sublist(0, encoder._bufferIndex); - } - - /** - * Starts a chunked conversion. - * - * The converter works more efficiently if the given [sink] is a - * [ByteConversionSink]. - */ - StringConversionSink startChunkedConversion(Sink> sink) { - if (sink is! ByteConversionSink) { - sink = new ByteConversionSink.from(sink); - } - return new _Utf8EncoderSink(sink); - } - - // Override the base-classes bind, to provide a better type. - Stream> bind(Stream stream) => super.bind(stream); -} - -/** - * This class encodes Strings to UTF-8 code units (unsigned 8 bit integers). - */ -// TODO(floitsch): make this class public. -class _Utf8Encoder { - int _carry = 0; - int _bufferIndex = 0; - final List _buffer; - - static const _DEFAULT_BYTE_BUFFER_SIZE = 1024; - - _Utf8Encoder() : this.withBufferSize(_DEFAULT_BYTE_BUFFER_SIZE); - - _Utf8Encoder.withBufferSize(int bufferSize) - : _buffer = _createBuffer(bufferSize); - - /** - * Allow an implementation to pick the most efficient way of storing bytes. - */ - static List _createBuffer(int size) => new Uint8List(size); - - /** - * Tries to combine the given [leadingSurrogate] with the [nextCodeUnit] and - * writes it to [_buffer]. - * - * Returns true if the [nextCodeUnit] was combined with the - * [leadingSurrogate]. If it wasn't then nextCodeUnit was not a trailing - * surrogate and has not been written yet. - * - * It is safe to pass 0 for [nextCodeUnit] in which case only the leading - * surrogate is written. - */ - bool _writeSurrogate(int leadingSurrogate, int nextCodeUnit) { - if (_isTailSurrogate(nextCodeUnit)) { - int rune = _combineSurrogatePair(leadingSurrogate, nextCodeUnit); - // If the rune is encoded with 2 code-units then it must be encoded - // with 4 bytes in UTF-8. - assert(rune > _THREE_BYTE_LIMIT); - assert(rune <= _FOUR_BYTE_LIMIT); - _buffer[_bufferIndex++] = 0xF0 | (rune >> 18); - _buffer[_bufferIndex++] = 0x80 | ((rune >> 12) & 0x3f); - _buffer[_bufferIndex++] = 0x80 | ((rune >> 6) & 0x3f); - _buffer[_bufferIndex++] = 0x80 | (rune & 0x3f); - return true; - } else { - // TODO(floitsch): allow to throw on malformed strings. - // Encode the half-surrogate directly into UTF-8. This yields - // invalid UTF-8, but we started out with invalid UTF-16. - - // Surrogates are always encoded in 3 bytes in UTF-8. - _buffer[_bufferIndex++] = 0xE0 | (leadingSurrogate >> 12); - _buffer[_bufferIndex++] = 0x80 | ((leadingSurrogate >> 6) & 0x3f); - _buffer[_bufferIndex++] = 0x80 | (leadingSurrogate & 0x3f); - return false; - } - } - - /** - * Fills the [_buffer] with as many characters as possible. - * - * Does not encode any trailing lead-surrogate. This must be done by the - * caller. - * - * Returns the position in the string. The returned index points to the - * first code unit that hasn't been encoded. - */ - int _fillBuffer(String str, int start, int end) { - if (start != end && _isLeadSurrogate(str.codeUnitAt(end - 1))) { - // Don't handle a trailing lead-surrogate in this loop. The caller has - // to deal with those. - end--; - } - int stringIndex; - for (stringIndex = start; stringIndex < end; stringIndex++) { - int codeUnit = str.codeUnitAt(stringIndex); - // ASCII has the same representation in UTF-8 and UTF-16. - if (codeUnit <= _ONE_BYTE_LIMIT) { - if (_bufferIndex >= _buffer.length) break; - _buffer[_bufferIndex++] = codeUnit; - } else if (_isLeadSurrogate(codeUnit)) { - if (_bufferIndex + 3 >= _buffer.length) break; - // Note that it is safe to read the next code unit. We decremented - // [end] above when the last valid code unit was a leading surrogate. - int nextCodeUnit = str.codeUnitAt(stringIndex + 1); - bool wasCombined = _writeSurrogate(codeUnit, nextCodeUnit); - if (wasCombined) stringIndex++; - } else { - int rune = codeUnit; - if (rune <= _TWO_BYTE_LIMIT) { - if (_bufferIndex + 1 >= _buffer.length) break; - _buffer[_bufferIndex++] = 0xC0 | (rune >> 6); - _buffer[_bufferIndex++] = 0x80 | (rune & 0x3f); - } else { - assert(rune <= _THREE_BYTE_LIMIT); - if (_bufferIndex + 2 >= _buffer.length) break; - _buffer[_bufferIndex++] = 0xE0 | (rune >> 12); - _buffer[_bufferIndex++] = 0x80 | ((rune >> 6) & 0x3f); - _buffer[_bufferIndex++] = 0x80 | (rune & 0x3f); - } - } - } - return stringIndex; - } -} - -/** - * This class encodes chunked strings to UTF-8 code units (unsigned 8-bit - * integers). - */ -class _Utf8EncoderSink extends _Utf8Encoder with StringConversionSinkMixin { - - final ByteConversionSink _sink; - - _Utf8EncoderSink(this._sink); - - void close() { - if (_carry != 0) { - // addSlice will call close again, but then the carry must be equal to 0. - addSlice("", 0, 0, true); - return; - } - _sink.close(); - } - - void addSlice(String str, int start, int end, bool isLast) { - _bufferIndex = 0; - - if (start == end && !isLast) { - return; - } - - if (_carry != 0) { - int nextCodeUnit = 0; - if (start != end) { - nextCodeUnit = str.codeUnitAt(start); - } else { - assert(isLast); - } - bool wasCombined = _writeSurrogate(_carry, nextCodeUnit); - // Either we got a non-empty string, or we must not have been combined. - assert(!wasCombined || start != end ); - if (wasCombined) start++; - _carry = 0; - } - do { - start = _fillBuffer(str, start, end); - bool isLastSlice = isLast && (start == end); - if (start == end - 1 && _isLeadSurrogate(str.codeUnitAt(start))) { - if (isLast && _bufferIndex < _buffer.length - 3) { - // There is still space for the last incomplete surrogate. - // We use a non-surrogate as second argument. This way the - // function will just add the surrogate-half to the buffer. - bool hasBeenCombined = _writeSurrogate(str.codeUnitAt(start), 0); - assert(!hasBeenCombined); - } else { - // Otherwise store it in the carry. If isLast is true, then - // close will flush the last carry. - _carry = str.codeUnitAt(start); - } - start++; - } - _sink.addSlice(_buffer, 0, _bufferIndex, isLastSlice); - _bufferIndex = 0; - } while (start < end); - if (isLast) close(); - } - - // TODO(floitsch): implement asUtf8Sink. Sligthly complicated because it - // needs to deal with malformed input. -} - -/** - * This class converts UTF-8 code units (lists of unsigned 8-bit integers) - * to a string. - */ -class Utf8Decoder extends Converter, String> { - final bool _allowMalformed; - - /** - * Instantiates a new [Utf8Decoder]. - * - * The optional [allowMalformed] argument defines how [convert] deals - * with invalid or unterminated character sequences. - * - * If it is `true` [convert] replaces invalid (or unterminated) character - * sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise - * it throws a [FormatException]. - */ - const Utf8Decoder({ bool allowMalformed: false }) - : this._allowMalformed = allowMalformed; - - /** - * Converts the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the - * corresponding string. - * - * Uses the code units from [start] to, but no including, [end]. - * If [end] is omitted, it defaults to `codeUnits.length`. - * - * If the [codeUnits] start with a leading [UNICODE_BOM_CHARACTER_RUNE] this - * character is discarded. - */ - String convert(List codeUnits, [int start = 0, int end]) { - int length = codeUnits.length; - RangeError.checkValidRange(start, end, length); - if (end == null) end = length; - StringBuffer buffer = new StringBuffer(); - _Utf8Decoder decoder = new _Utf8Decoder(buffer, _allowMalformed); - decoder.convert(codeUnits, start, end); - decoder.close(); - return buffer.toString(); - } - - /** - * Starts a chunked conversion. - * - * The converter works more efficiently if the given [sink] is a - * [StringConversionSink]. - */ - ByteConversionSink startChunkedConversion(Sink sink) { - StringConversionSink stringSink; - if (sink is StringConversionSink) { - stringSink = sink; - } else { - stringSink = new StringConversionSink.from(sink); - } - return stringSink.asUtf8Sink(_allowMalformed); - } - - // Override the base-classes bind, to provide a better type. - Stream bind(Stream> stream) => super.bind(stream); - - Converter,dynamic> fuse(Converter next) { - return super.fuse(next); - } -} - -// UTF-8 constants. -const int _ONE_BYTE_LIMIT = 0x7f; // 7 bits -const int _TWO_BYTE_LIMIT = 0x7ff; // 11 bits -const int _THREE_BYTE_LIMIT = 0xffff; // 16 bits -const int _FOUR_BYTE_LIMIT = 0x10ffff; // 21 bits, truncated to Unicode max. - -// UTF-16 constants. -const int _SURROGATE_MASK = 0xF800; -const int _SURROGATE_TAG_MASK = 0xFC00; -const int _SURROGATE_VALUE_MASK = 0x3FF; -const int _LEAD_SURROGATE_MIN = 0xD800; -const int _TAIL_SURROGATE_MIN = 0xDC00; - -bool _isSurrogate(int codeUnit) => - (codeUnit & _SURROGATE_MASK) == _LEAD_SURROGATE_MIN; -bool _isLeadSurrogate(int codeUnit) => - (codeUnit & _SURROGATE_TAG_MASK) == _LEAD_SURROGATE_MIN; -bool _isTailSurrogate(int codeUnit) => - (codeUnit & _SURROGATE_TAG_MASK) == _TAIL_SURROGATE_MIN; -int _combineSurrogatePair(int lead, int tail) => - 0x10000 + ((lead & _SURROGATE_VALUE_MASK) << 10) - | (tail & _SURROGATE_VALUE_MASK); - - -/** - * Decodes UTF-8. - * - * The decoder handles chunked input. - */ -// TODO(floitsch): make this class public. -class _Utf8Decoder { - final bool _allowMalformed; - final StringSink _stringSink; - bool _isFirstCharacter = true; - int _value = 0; - int _expectedUnits = 0; - int _extraUnits = 0; - - _Utf8Decoder(this._stringSink, this._allowMalformed); - - bool get hasPartialInput => _expectedUnits > 0; - - // Limits of one through four byte encodings. - static const List _LIMITS = const [ - _ONE_BYTE_LIMIT, - _TWO_BYTE_LIMIT, - _THREE_BYTE_LIMIT, - _FOUR_BYTE_LIMIT ]; - - void close() { - flush(); - } - - /** - * Flushes this decoder as if closed. - * - * This method throws if the input was partial and the decoder was - * constructed with `allowMalformed` set to `false`. - */ - void flush() { - if (hasPartialInput) { - if (!_allowMalformed) { - throw new FormatException("Unfinished UTF-8 octet sequence"); - } - _stringSink.writeCharCode(UNICODE_REPLACEMENT_CHARACTER_RUNE); - _value = 0; - _expectedUnits = 0; - _extraUnits = 0; - } - } - - void convert(List codeUnits, int startIndex, int endIndex) { - int value = _value; - int expectedUnits = _expectedUnits; - int extraUnits = _extraUnits; - _value = 0; - _expectedUnits = 0; - _extraUnits = 0; - - int scanOneByteCharacters(units, int from) { - final to = endIndex; - final mask = _ONE_BYTE_LIMIT; - for (var i = from; i < to; i++) { - final unit = units[i]; - if ((unit & mask) != unit) return i - from; - } - return to - from; - } - - void addSingleBytes(int from, int to) { - assert(from >= startIndex && from <= endIndex); - assert(to >= startIndex && to <= endIndex); - _stringSink.write(new String.fromCharCodes(codeUnits, from, to)); - } - - int i = startIndex; - loop: while (true) { - multibyte: if (expectedUnits > 0) { - do { - if (i == endIndex) { - break loop; - } - int unit = codeUnits[i]; - if ((unit & 0xC0) != 0x80) { - expectedUnits = 0; - if (!_allowMalformed) { - throw new FormatException( - "Bad UTF-8 encoding 0x${unit.toRadixString(16)}"); - } - _isFirstCharacter = false; - _stringSink.writeCharCode(UNICODE_REPLACEMENT_CHARACTER_RUNE); - break multibyte; - } else { - value = (value << 6) | (unit & 0x3f); - expectedUnits--; - i++; - } - } while (expectedUnits > 0); - if (value <= _LIMITS[extraUnits - 1]) { - // Overly long encoding. The value could be encoded with a shorter - // encoding. - if (!_allowMalformed) { - throw new FormatException( - "Overlong encoding of 0x${value.toRadixString(16)}"); - } - expectedUnits = extraUnits = 0; - value = UNICODE_REPLACEMENT_CHARACTER_RUNE; - } - if (value > _FOUR_BYTE_LIMIT) { - if (!_allowMalformed) { - throw new FormatException("Character outside valid Unicode range: " - "0x${value.toRadixString(16)}"); - } - value = UNICODE_REPLACEMENT_CHARACTER_RUNE; - } - if (!_isFirstCharacter || value != UNICODE_BOM_CHARACTER_RUNE) { - _stringSink.writeCharCode(value); - } - _isFirstCharacter = false; - } - - while (i < endIndex) { - int oneBytes = scanOneByteCharacters(codeUnits, i); - if (oneBytes > 0) { - _isFirstCharacter = false; - addSingleBytes(i, i + oneBytes); - i += oneBytes; - if (i == endIndex) break; - } - int unit = codeUnits[i++]; - // TODO(floitsch): the way we test we could potentially allow - // units that are too large, if they happen to have the - // right bit-pattern. (Same is true for the multibyte loop above). - // TODO(floitsch): optimize this loop. See: - // https://codereview.chromium.org/22929022/diff/1/sdk/lib/convert/utf.dart?column_width=80 - if (unit < 0) { - // TODO(floitsch): should this be unit <= 0 ? - if (!_allowMalformed) { - throw new FormatException( - "Negative UTF-8 code unit: -0x${(-unit).toRadixString(16)}"); - } - _stringSink.writeCharCode(UNICODE_REPLACEMENT_CHARACTER_RUNE); - } else { - assert(unit > _ONE_BYTE_LIMIT); - if ((unit & 0xE0) == 0xC0) { - value = unit & 0x1F; - expectedUnits = extraUnits = 1; - continue loop; - } - if ((unit & 0xF0) == 0xE0) { - value = unit & 0x0F; - expectedUnits = extraUnits = 2; - continue loop; - } - // 0xF5, 0xF6 ... 0xFF never appear in valid UTF-8 sequences. - if ((unit & 0xF8) == 0xF0 && unit < 0xF5) { - value = unit & 0x07; - expectedUnits = extraUnits = 3; - continue loop; - } - if (!_allowMalformed) { - throw new FormatException( - "Bad UTF-8 encoding 0x${unit.toRadixString(16)}"); - } - value = UNICODE_REPLACEMENT_CHARACTER_RUNE; - expectedUnits = extraUnits = 0; - _isFirstCharacter = false; - _stringSink.writeCharCode(value); - } - } - break loop; - } - if (expectedUnits > 0) { - _value = value; - _expectedUnits = expectedUnits; - _extraUnits = extraUnits; - } - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/annotations.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/annotations.dart deleted file mode 100644 index 536eddff94fa..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/annotations.dart +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.core; - -// TODO(jacobr): move these annotations to a different package. E.g. dart:js - -class JsName { - /// The JavaScript name. - /// Used for classes and libraries. - /// Note that this could be an expression, e.g. `lib.TypeName` in JS, but it - /// should be kept simple, as it will be generated directly into the code. - final String name; - const JsName({this.name}); -} - -class JsPeerInterface { - /// The JavaScript type that we should match the API of. - /// Used for classes where Dart subclasses should be callable from JavaScript - /// matching the JavaScript calling conventions. - final String name; - const JsPeerInterface({this.name}); -} - -/// A Dart interface may only be implemented by a native JavaScript object -/// if it is marked with this annotation. -class SupportJsExtensionMethod { - const SupportJsExtensionMethod(); -} - -/** - * The annotation `@Deprecated('expires when')` marks a feature as deprecated. - * - * The annotation `@deprecated` is a shorthand for deprecating until - * an unspecified "next release". - * - * The intent of the `@Deprecated` annotation is to inform users of a feature - * that they should change their code, even if it is currently still working - * correctly. - * - * A deprecated feature is scheduled to be removed at a later time, possibly - * specified as the "expires" field of the annotation. - * This means that a deprecated feature should not be used, or code using it - * will break at some point in the future. If there is code using the feature, - * that code should be rewritten to not use the deprecated feature. - * - * A deprecated feature should document how the same effect can be achieved, - * so the programmer knows how to rewrite the code. - * - * The `@Deprecated` annotation applies to libraries, top-level declarations - * (variables, getters, setters, functions, classes and typedefs), - * class-level declarations (variables, getters, setters, methods, operators or - * constructors, whether static or not), named optional arguments and - * trailing optional positional parameters. - * - * Deprecation is transitive: - * - * - If a library is deprecated, so is every member of it. - * - If a class is deprecated, so is every member of it. - * - If a variable is deprecated, so are its implicit getter and setter. - * - * - * A tool that processes Dart source code may report when: - * - * - the code imports a deprecated library. - * - the code exports a deprecated library, or any deprecated member of - *  a non-deprecated library. - * - the code refers statically to a deprecated declaration. - * - the code dynamically uses a member of an object with a statically known - * type, where the member is deprecated on the static type of the object. - * - the code dynamically calls a method with an argument where the - * corresponding optional parameter is deprecated on the object's static type. - * - * - * If the deprecated use is inside a library, class or method which is itself - * deprecated, the tool should not bother the user about it. - * A deprecated feature is expected to use other deprecated features. - */ -class Deprecated { - /** - * A description of when the deprecated feature is expected to be retired. - */ - final String expires; - - /** - * Create a deprecation annotation which specifies the expiration of the - * annotated feature. - * - * The [expires] argument should be readable by programmers, and should state - * when an annotated feature is expected to be removed. - * This can be specified, for example, as a date, as a release number, or - * as relative to some other change (like "when bug 4418 is fixed"). - */ - const Deprecated(String expires) : this.expires = expires; - - String toString() => "Deprecated feature. Will be removed $expires"; -} - -class _Override { - const _Override(); -} - -/** - * Marks a feature as [Deprecated] until the next release. - */ -const Deprecated deprecated = const Deprecated("next release"); - -/** - * The annotation `@override` marks an instance member as overriding a - * superclass member with the same name. - * - * The annotation applies to instance methods, getters and setters, and to - * instance fields, where it means that the implicit getter and setter of the - * field is marked as overriding, but the field itself is not. - * - * The intent of the `@override` notation is to catch situations where a - * superclass renames a member, and an independent subclass which used to - * override the member, could silently continue working using the - * superclass implementation. - * - * The editor, or a similar tool aimed at the programmer, may report if no - * declaration of an annotated member is inherited by the class from either a - * superclass or an interface. - * - * Use the `@override` annotation judiciously and only for methods where - * the superclass is not under the programmer's control, the superclass is in a - * different library or package, and it is not considered stable. - * In any case, the use of `@override` is optional. - * - * For example, the annotation is intentionally not used in the Dart platform - * libraries, since they only depend on themselves. - */ -const Object override = const _Override(); - -class _Proxy { - const _Proxy(); -} - -/** - * The annotation `@proxy` marks a class as implementing interfaces and members - * dynamically through `noSuchMethod`. - * - * The annotation applies to any class. It is inherited by subclasses from both - * superclass and interfaces. - * - * If a class is annotated with `@proxy`, or it implements any class that is - * annotated, then the class is considered to implement any interface and - * any member with regard to static type analysis. As such, it is not a static - * type warning to assign the object to a variable of any type, and it is not - * a static type warning to access any member of the object. - * - * This only applies to static type warnings. The runtime type of the object - * is unaffected. It is not considered to implement any special interfaces at - * runtime, so assigning it to a typed variable may fail in checked mode, and - * testing it with the `is` operator will not work for any type except the - * ones it actually implements. - * - * Tools that understand `@proxy` should tell the user if a class using `@proxy` - * does not override the `noSuchMethod` declared on [Object]. - * - * The intent of the `@proxy` notation is to create objects that implement a - * type (or multiple types) that are not known at compile time. If the types - * are known at compile time, a class can be written that implements these - * types. - */ -const Object proxy = const _Proxy(); diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/bool.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/bool.dart deleted file mode 100644 index 14bc53587543..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/bool.dart +++ /dev/null @@ -1,45 +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. - -part of dart.core; - -/** - * The reserved words [:true:] and [:false:] denote objects that are the only - * instances of this class. - * - * It is a compile-time error for a class to attempt to extend or implement - * bool. - */ -class bool { - /** - * Returns the boolean value of the environment declaration [name]. - * - * The boolean value of the declaration is `true` if the declared value is - * the string `"true"`, and `false` if the value is `"false"`. - * - * In all other cases, including when there is no declaration for `name`, - * the result is the [defaultValue]. - * - * Example: - * - * const loggingFlag = const bool.fromEnvironment("logging"); - * - * If you want to use a different truth-string, you can use the - * [String.fromEnvironment] constructor directly: - * - * const isLoggingOn = (const String.fromEnvironment("logging") == "on"); - */ - factory bool.fromEnvironment(String name, {bool defaultValue: false}) { - throw new UnsupportedError( - 'bool.fromEnvironment can only be used as a const constructor'); - } - - /** - * Returns [:"true":] if the receiver is [:true:], or [:"false":] if the - * receiver is [:false:]. - */ - String toString() { - return this ? "true" : "false"; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/comparable.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/comparable.dart deleted file mode 100644 index 7a22948a080f..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/comparable.dart +++ /dev/null @@ -1,94 +0,0 @@ -// 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. - -part of dart.core; - -/** - * The signature of a generic comparison function. - * - * A comparison function represents an ordering on a type of objects. - * A total ordering on a type means that for two values, either they - * are equal or one is greater than the other (and the latter must then be - * smaller than the former). - * - * A [Comparator] function represents such a total ordering by returning - * - * * a negative integer if [a] is smaller than [b], - * * zero if [a] is equal to [b], and - * * a positive integer if [a] is greater than [b]. - */ -typedef int Comparator(T a, T b); - -/** - * Interface used by types that have an intrinsic ordering. - * - * The [compareTo] operation defines a total ordering of objects, - * which can be used for ordering and sorting. - * - * The [Comparable] interface should be used for the natural ordering of a type. - * If a type can be ordered in more than one way, - * and none of them is the obvious natural ordering, - * then it might be better not to use the [Comparable] interface, - * and to provide separate [Comparator]s instead. - * - * It is recommended that the order of a [Comparable] agrees - * with its operator [==] equality (`a.compareTo(b) == 0` iff `a == b`), - * but this is not a requirement. - * For example, [double] and [DateTime] have `compareTo` methods - * that do not agree with operator [==]. - * For doubles the [compareTo] method is more precise than the equality, - * and for [DateTime] it is less precise. - * - * Examples: - * - * (0.0).compareTo(-0.0); // => 1 - * 0.0 == -0.0; // => true - * var dt = new DateTime.now(); - * var dt2 = dt.toUtc(); - * dt == dt2; // => false - * dt.compareTo(dt2); // => 0 - * - * The [Comparable] interface does not imply the existence - * of the comparison operators `<`, `<=`, `>` and `>=`. - * These should only be defined - * if the ordering is a less-than/greater-than ordering, - * that is, an ordering where you would naturally - * use the words "less than" about the order of two elements. - * - * If the equality operator and [compareTo] disagree, - * the comparison operators should follow the equality operator, - * and will likely also disagree with [compareTo]. - * Otherwise they should match the [compareTo] method, - * so that `a < b` iff `a.compareTo(b) < 0`. - * - * The [double] class defines comparison operators - * that are compatible with equality. - * The operators differ from `double.compareTo` on -0.0 and NaN. - * - * The [DateTime] class has no comparison operators, instead it has the more - * precisely named [DateTime.isBefore] and [DateTime.isAfter]. - */ -abstract class Comparable { - /** - * Compares this object to another [Comparable] - * - * Returns a value like a [Comparator] when comparing `this` to [other]. - * That is, it returns a negative integer if `this` is ordered before [other], - * a positive integer if `this` is ordered after [other], - * and zero if `this` and [other] are ordered together. - * - * The [other] argument must be a value that is comparable to this object. - */ - int compareTo(T other); - - /** - * A [Comparator] that compares one comparable to another. - * - * It returns the result of `a.compareTo(b)`. - * - * This utility function is used as the default comparator - * for ordering collections, for example in the [List] sort function. - */ - static int compare(Comparable a, Comparable b) => a.compareTo(b); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/core.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/core.dart deleted file mode 100644 index 71d53fc3d238..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/core.dart +++ /dev/null @@ -1,220 +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. - -/** - * - * Built-in types, collections, - * and other core functionality for every Dart program. - * - * This library is automatically imported. - * - * Some classes in this library, - * such as [String] and [num], - * support Dart's built-in data types. - * Other classes, such as [List] and [Map], provide data structures - * for managing collections of objects. - * And still other classes represent commonly used types of data - * such as URIs, dates and times, and errors. - * - * ## Numbers and booleans - * - * [int] and [double] provide support for Dart's built-in numerical data types: - * integers and double-precision floating point numbers, respectively. - * An object of type [bool] is either true or false. - * Variables of these types can be constructed from literals: - * - * int meaningOfLife = 42; - * double valueOfPi = 3.141592; - * bool visible = true; - * - * ## Strings and regular expressions - * - * A [String] is immutable and represents a sequence of characters. - * - * String shakespeareQuote = "All the world's a stage, ..."; - * - * [StringBuffer] provides a way to construct strings efficiently. - * - * StringBuffer moreShakespeare = new StringBuffer(); - * moreShakespeare.write('And all the men and women '); - * moreShakespeare.write('merely players; ...'); - * - * The String and StringBuffer classes implement string concatenation, - * interpolation, and other string manipulation features. - * - * String philosophy = 'Live on '; - * String get palindrome => philosophy + philosophy.split('').reversed.join(); - * - * [RegExp] implements Dart regular expressions, - * which provide a grammar for matching patterns within text. - * For example, here's a regular expression that matches - * a string of one or more digits: - * - * var numbers = new RegExp(r'\d+'); - * - * Dart regular expressions have the same syntax and semantics as - * JavaScript regular expressions. See - * - * for the specification of JavaScript regular expressions. - * - * ## Collections - * - * The dart:core library provides basic collections, - * such as [List], [Map], and [Set]. - * - * A List is an ordered collection of objects, with a length. - * Lists are sometimes called arrays. - * Use a List when you need to access objects by index. - * - * List superheroes = [ 'Batman', 'Superman', 'Harry Potter' ]; - * - * A Set is an unordered collection of unique objects. - * You cannot get an item by index (position). - * Adding a duplicate item has no effect. - * - * Set villains = new Set(); - * villains.add('Joker'); - * villains.addAll( ['Lex Luther', 'Voldemort'] ); - * - * A Map is an unordered collection of key-value pairs. - * Maps are sometimes called associative arrays because - * maps associate a key to some value for easy retrieval. - * Keys are unique. - * Use a Map when you need to access objects - * by a unique identifier. - * - * Map sidekicks = { 'Batman': 'Robin', - * 'Superman': 'Lois Lane', - * 'Harry Potter': 'Ron and Hermione' }; - * - * In addition to these classes, - * dart:core contains [Iterable], - * an interface that defines functionality - * common in collections of objects. - * Examples include the ability - * to run a function on each element in the collection, - * to apply a test to each element, - * to retrieve an object, and to determine length. - * - * Iterable is implemented by List and Set, - * and used by Map for its keys and values. - * - * For other kinds of collections, check out the - * [dart:collection](#dart-collection) library. - * - * ## Date and time - * - * Use [DateTime] to represent a point in time - * and [Duration] to represent a span of time. - * - * You can create DateTime objects with constructors - * or by parsing a correctly formatted string. - * - * DateTime now = new DateTime.now(); - * DateTime berlinWallFell = new DateTime(1989, 11, 9); - * DateTime moonLanding = DateTime.parse("1969-07-20"); - * - * Create a Duration object specifying the individual time units. - * - * Duration timeRemaining = new Duration(hours:56, minutes:14); - * - * In addition to DateTime and Duration, - * dart:core contains the [Stopwatch] class for measuring elapsed time. - * - * ## Uri - * - * A [Uri] object represents a uniform resource identifier, - * which identifies a resource on the web. - * - * Uri dartlang = Uri.parse('http://dartlang.org/'); - * - * ## Errors - * - * The [Error] class represents the occurrence of an error - * during runtime. - * Subclasses of this class represent specific kinds of errors. - * - * ## Other documentation - * - * For more information about how to use the built-in types, refer to - * [Built-in Types](http://www.dartlang.org/docs/dart-up-and-running/contents/ch02.html#built-in-types) - * in Chapter 2 of - * [Dart: Up and Running](http://www.dartlang.org/docs/dart-up-and-running/). - * - * Also, see - * [dart:core - Numbers, Collections, Strings, and More](http://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html#ch03-dartcore---strings-collections-and-more) - * for more coverage of classes in this package. - * - * The - * [Dart Language Specification](http://www.dartlang.org/docs/spec/) - * provides technical details. - */ -library dart.core; - -import "dart:collection"; -import "dart:_internal" hide Symbol; -import "dart:_internal" as internal show Symbol; -import "dart:convert" show UTF8, LATIN1, Encoding; -import "dart:math" show Random; -import "dart:_internal" as _symbol_dev; -import 'dart:_interceptors'; -import 'dart:_js_helper' show patch, - checkInt, - getRuntimeType, - jsonEncodeNative, - JSSyntaxRegExp, - Primitives, - stringJoinUnchecked, - objectHashCode; -import 'dart:_foreign_helper' show JS; // Used by List.shuffle. - -part "annotations.dart"; -part "bool.dart"; -part "comparable.dart"; -part "date_time.dart"; -part "double.dart"; -part "duration.dart"; -part "errors.dart"; -part "exceptions.dart"; -part "expando.dart"; -part "function.dart"; -part "identical.dart"; -part "int.dart"; -part "invocation.dart"; -part "iterable.dart"; -part "iterator.dart"; -part "list.dart"; -part "map.dart"; -part "null.dart"; -part "num.dart"; -part "object.dart"; -part "pattern.dart"; -part "print.dart"; -part "regexp.dart"; -part "set.dart"; -part "sink.dart"; -part "stacktrace.dart"; -part "stopwatch.dart"; -part "string.dart"; -part "string_buffer.dart"; -part "string_sink.dart"; -part "symbol.dart"; -part "type.dart"; -part "uri.dart"; - -String _symbolToString(Symbol symbol) => _symbol_dev.Symbol.getName(symbol); -_symbolMapToStringMap(Map map) { - if (map == null) return null; - var result = new Map(); - map.forEach((Symbol key, value) { - result[_symbolToString(key)] = value; - }); - return result; -} -class SupportJsExtensionMethods { - const SupportJsExtensionMethods(); -} -class _ListConstructorSentinel { - const _ListConstructorSentinel(); -} \ No newline at end of file diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/date_time.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/date_time.dart deleted file mode 100644 index 30805ea38e33..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/date_time.dart +++ /dev/null @@ -1,696 +0,0 @@ -// 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. - -part of dart.core; - -/** - * An instant in time, such as July 20, 1969, 8:18pm GMT. - * - * Create a DateTime object by using one of the constructors - * or by parsing a correctly formatted string, - * which complies with a subset of ISO 8601. - * Note that hours are specified between 0 and 23, - * as in a 24-hour clock. - * For example: - * - * DateTime now = new DateTime.now(); - * DateTime berlinWallFell = new DateTime(1989, 11, 9); - * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); // 8:18pm - * - * A DateTime object is anchored either in the UTC time zone - * or in the local time zone of the current computer - * when the object is created. - * - * Once created, neither the value nor the time zone - * of a DateTime object may be changed. - * - * You can use properties to get - * the individual units of a DateTime object. - * - * assert(berlinWallFell.month == 11); - * assert(moonLanding.hour == 20); - * - * For convenience and readability, - * the DateTime class provides a constant for each day and month - * name—for example, [AUGUST] and [FRIDAY]. - * You can use these constants to improve code readibility: - * - * DateTime berlinWallFell = new DateTime(1989, DateTime.NOVEMBER, 9); - * assert(berlinWallFell.weekday == DateTime.THURSDAY); - * - * Day and month values begin at 1, and the week starts on Monday. - * That is, the constants [JANUARY] and [MONDAY] are both 1. - * - * ## Working with UTC and local time - * - * A DateTime object is in the local time zone - * unless explicitly created in the UTC time zone. - * - * DateTime dDay = new DateTime.utc(1944, 6, 6); - * - * Use [isUtc] to determine whether a DateTime object is based in UTC. - * Use the methods [toLocal] and [toUtc] - * to get the equivalent date/time value specified in the other time zone. - * Use [timeZoneName] to get an abbreviated name of the time zone - * for the DateTime object. - * To find the difference - * between UTC and the time zone of a DateTime object - * call [timeZoneOffset]. - * - * ## Comparing DateTime objects - * - * The DateTime class contains several handy methods, - * such as [isAfter], [isBefore], and [isAtSameMomentAs], - * for comparing DateTime objects. - * - * assert(berlinWallFell.isAfter(moonLanding) == true); - * assert(berlinWallFell.isBefore(moonLanding) == false); - * - * ## Using DateTime with Duration - * - * Use the [add] and [subtract] methods with a [Duration] object - * to create a new DateTime object based on another. - * For example, to find the date that is sixty days after today, write: - * - * DateTime today = new DateTime.now(); - * DateTime sixtyDaysFromNow = today.add(new Duration(days: 60)); - * - * To find out how much time is between two DateTime objects use - * [difference], which returns a [Duration] object: - * - * Duration difference = berlinWallFell.difference(moonLanding) - * assert(difference.inDays == 7416); - * - * The difference between two dates in different time zones - * is just the number of nanoseconds between the two points in time. - * It doesn't take calendar days into account. - * That means that the difference between two midnights in local time may be - * less than 24 hours times the number of days between them, - * if there is a daylight saving change in between. - * If the difference above is calculated using Australian local time, the - * difference is 7415 days and 23 hours, which is only 7415 whole days as - * reported by `inDays`. - * - * ## Other resources - * - * See [Duration] to represent a span of time. - * See [Stopwatch] to measure timespans. - * - * The DateTime class does not provide internationalization. - * To internationalize your code, use - * the [intl](http://pub.dartlang.org/packages/intl) package. - * - */ -class DateTime implements Comparable { - // Weekday constants that are returned by [weekday] method: - static const int MONDAY = 1; - static const int TUESDAY = 2; - static const int WEDNESDAY = 3; - static const int THURSDAY = 4; - static const int FRIDAY = 5; - static const int SATURDAY = 6; - static const int SUNDAY = 7; - static const int DAYS_PER_WEEK = 7; - - // Month constants that are returned by the [month] getter. - static const int JANUARY = 1; - static const int FEBRUARY = 2; - static const int MARCH = 3; - static const int APRIL = 4; - static const int MAY = 5; - static const int JUNE = 6; - static const int JULY = 7; - static const int AUGUST = 8; - static const int SEPTEMBER = 9; - static const int OCTOBER = 10; - static const int NOVEMBER = 11; - static const int DECEMBER = 12; - static const int MONTHS_PER_YEAR = 12; - - /** - * The number of milliseconds since - * the "Unix epoch" 1970-01-01T00:00:00Z (UTC). - * - * This value is independent of the time zone. - * - * This value is at most - * 8,640,000,000,000,000ms (100,000,000 days) from the Unix epoch. - * In other words: [:millisecondsSinceEpoch.abs() <= 8640000000000000:]. - * - */ - final int millisecondsSinceEpoch; - - /** - * True if this [DateTime] is set to UTC time. - * - * DateTime dDay = new DateTime.utc(1944, 6, 6); - * assert(dDay.isUtc); - * - */ - final bool isUtc; - - /** - * Constructs a [DateTime] instance specified in the local time zone. - * - * For example, - * to create a new DateTime object representing April 29, 2014, 6:04am: - * - * DateTime annularEclipse = new DateTime(2014, DateTime.APRIL, 29, 6, 4); - */ - DateTime(int year, - [int month = 1, - int day = 1, - int hour = 0, - int minute = 0, - int second = 0, - int millisecond = 0]) - : this._internal( - year, month, day, hour, minute, second, millisecond, false); - - /** - * Constructs a [DateTime] instance specified in the UTC time zone. - * - * DateTime dDay = new DateTime.utc(1944, DateTime.JUNE, 6); - */ - DateTime.utc(int year, - [int month = 1, - int day = 1, - int hour = 0, - int minute = 0, - int second = 0, - int millisecond = 0]) - : this._internal( - year, month, day, hour, minute, second, millisecond, true); - - /** - * Constructs a [DateTime] instance with current date and time in the - * local time zone. - * - * DateTime thisInstant = new DateTime.now(); - * - */ - DateTime.now() : this._now(); - - /** - * Constructs a new [DateTime] instance based on [formattedString]. - * - * Throws a [FormatException] if the input cannot be parsed. - * - * The function parses a subset of ISO 8601 - * which includes the subset accepted by RFC 3339. - * - * The accepted inputs are currently: - * - * * A date: A signed four-to-six digit year, two digit month and - * two digit day, optionally separated by `-` characters. - * Examples: "19700101", "-0004-12-24", "81030-04-01". - * * An optional time part, separated from the date by either `T` or a space. - * The time part is a two digit hour, - * then optionally a two digit minutes value, - * then optionally a two digit seconds value, and - * then optionally a '.' followed by a one-to-six digit second fraction. - * The minuts and seconds may be separated from the previous parts by a ':'. - * Examples: "12", "12:30:24.124", "123010.50". - * * An optional time-zone offset part, - * possibly separated from the previous by a space. - * The time zone is either 'z' or 'Z', or it is a signed two digit hour - * part and an optional two digit minute part. - * The minutes may be separted from the hours by a ':'. - * Examples: "Z", "-10", "01:30", "1130". - * - * This includes the output of both [toString] and [toIso8601String], which - * will be parsed back into a `DateTime` object with the same time as the - * original. - * - * The result is always in either local time or UTC. - * If a time zone offset other than UTC is specified, - * the time is converted to the equivalent UTC time. - * - * Examples of accepted strings: - * - * * `"2012-02-27 13:27:00"` - * * `"2012-02-27 13:27:00.123456z"` - * * `"20120227 13:27:00"` - * * `"20120227T132700"` - * * `"20120227"` - * * `"+20120227"` - * * `"2012-02-27T14Z"` - * * `"2012-02-27T14+00:00"` - * * `"-123450101 00:00:00 Z"`: in the year -12345. - * * `"2002-02-27T14:00:00-0500"`: Same as `"2002-02-27T19:00:00Z"` - */ - // TODO(lrn): restrict incorrect values like 2003-02-29T50:70:80. - // Or not, that may be a breaking change. - static DateTime parse(String formattedString) { - /* - * date ::= yeardate time_opt timezone_opt - * yeardate ::= year colon_opt month colon_opt day - * year ::= sign_opt digit{4,6} - * colon_opt :: | ':' - * sign ::= '+' | '-' - * sign_opt ::= | sign - * month ::= digit{2} - * day ::= digit{2} - * time_opt ::= | (' ' | 'T') hour minutes_opt - * minutes_opt ::= | colon_opt digit{2} seconds_opt - * seconds_opt ::= | colon_opt digit{2} millis_opt - * millis_opt ::= | '.' digit{1,6} - * timezone_opt ::= | space_opt timezone - * space_opt :: ' ' | - * timezone ::= 'z' | 'Z' | sign digit{2} timezonemins_opt - * timezonemins_opt ::= | colon_opt digit{2} - */ - final RegExp re = new RegExp( - r'^([+-]?\d{4,6})-?(\d\d)-?(\d\d)' // The day part. - r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(.\d{1,6})?)?)?' // The time part - r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // The timezone part - - Match match = re.firstMatch(formattedString); - if (match != null) { - int parseIntOrZero(String matched) { - if (matched == null) return 0; - return int.parse(matched); - } - - double parseDoubleOrZero(String matched) { - if (matched == null) return 0.0; - return double.parse(matched); - } - - int years = int.parse(match[1]); - int month = int.parse(match[2]); - int day = int.parse(match[3]); - int hour = parseIntOrZero(match[4]); - int minute = parseIntOrZero(match[5]); - int second = parseIntOrZero(match[6]); - bool addOneMillisecond = false; - int millisecond = (parseDoubleOrZero(match[7]) * 1000).round(); - if (millisecond == 1000) { - addOneMillisecond = true; - millisecond = 999; - } - bool isUtc = false; - if (match[8] != null) { // timezone part - isUtc = true; - if (match[9] != null) { - // timezone other than 'Z' and 'z'. - int sign = (match[9] == '-') ? -1 : 1; - int hourDifference = int.parse(match[10]); - int minuteDifference = parseIntOrZero(match[11]); - minuteDifference += 60 * hourDifference; - minute -= sign * minuteDifference; - } - } - int millisecondsSinceEpoch = _brokenDownDateToMillisecondsSinceEpoch( - years, month, day, hour, minute, second, millisecond, isUtc); - if (millisecondsSinceEpoch == null) { - throw new FormatException("Time out of range", formattedString); - } - if (addOneMillisecond) millisecondsSinceEpoch++; - return new DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch, - isUtc: isUtc); - } else { - throw new FormatException("Invalid date format", formattedString); - } - } - - static const int _MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000; - - /** - * Constructs a new [DateTime] instance - * with the given [millisecondsSinceEpoch]. - * - * If [isUtc] is false then the date is in the local time zone. - * - * The constructed [DateTime] represents - * 1970-01-01T00:00:00Z + [millisecondsSinceEpoch] ms in the given - * time zone (local or UTC). - */ - DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch, - {bool isUtc: false}) - : this.millisecondsSinceEpoch = millisecondsSinceEpoch, - this.isUtc = isUtc { - if (millisecondsSinceEpoch.abs() > _MAX_MILLISECONDS_SINCE_EPOCH) { - throw new ArgumentError(millisecondsSinceEpoch); - } - if (isUtc == null) throw new ArgumentError(isUtc); - } - - /** - * Returns true if [other] is a [DateTime] at the same moment and in the - * same time zone (UTC or local). - * - * DateTime dDayUtc = new DateTime.utc(1944, DateTime.JUNE, 6); - * DateTime dDayLocal = new DateTime(1944, DateTime.JUNE, 6); - * - * assert(dDayUtc.isAtSameMomentAs(dDayLocal) == false); - * - * See [isAtSameMomentAs] for a comparison that adjusts for time zone. - */ - bool operator ==(other) { - if (!(other is DateTime)) return false; - return (millisecondsSinceEpoch == other.millisecondsSinceEpoch && - isUtc == other.isUtc); - } - - /** - * Returns true if [this] occurs before [other]. - * - * The comparison is independent - * of whether the time is in UTC or in the local time zone. - * - * DateTime berlinWallFell = new DateTime(1989, 11, 9); - * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); - * - * assert(berlinWallFell.isBefore(moonLanding) == false); - * - */ - bool isBefore(DateTime other) { - return millisecondsSinceEpoch < other.millisecondsSinceEpoch; - } - - /** - * Returns true if [this] occurs after [other]. - * - * The comparison is independent - * of whether the time is in UTC or in the local time zone. - * - * DateTime berlinWallFell = new DateTime(1989, 11, 9); - * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); - * - * assert(berlinWallFell.isAfter(moonLanding) == true); - * - */ - bool isAfter(DateTime other) { - return millisecondsSinceEpoch > other.millisecondsSinceEpoch; - } - - /** - * Returns true if [this] occurs at the same moment as [other]. - * - * The comparison is independent of whether the time is in UTC or in the local - * time zone. - * - * DateTime berlinWallFell = new DateTime(1989, 11, 9); - * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); - * - * assert(berlinWallFell.isAtSameMomentAs(moonLanding) == false); - */ - bool isAtSameMomentAs(DateTime other) { - return millisecondsSinceEpoch == other.millisecondsSinceEpoch; - } - - /** - * Compares this DateTime object to [other], - * returning zero if the values are equal. - * - * This function returns a negative integer - * if this DateTime is smaller (earlier) than [other], - * or a positive integer if it is greater (later). - */ - int compareTo(DateTime other) - => millisecondsSinceEpoch.compareTo(other.millisecondsSinceEpoch); - - int get hashCode => millisecondsSinceEpoch; - - /** - * Returns this DateTime value in the local time zone. - * - * Returns [this] if it is already in the local time zone. - * Otherwise this method is equivalent to: - * - * new DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch, - * isUtc: false) - */ - DateTime toLocal() { - if (isUtc) { - return new DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch, - isUtc: false); - } - return this; - } - - /** - * Returns this DateTime value in the UTC time zone. - * - * Returns [this] if it is already in UTC. - * Otherwise this method is equivalent to: - * - * new DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch, - * isUtc: true) - */ - DateTime toUtc() { - if (isUtc) return this; - return new DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch, - isUtc: true); - } - - static String _fourDigits(int n) { - int absN = n.abs(); - String sign = n < 0 ? "-" : ""; - if (absN >= 1000) return "$n"; - if (absN >= 100) return "${sign}0$absN"; - if (absN >= 10) return "${sign}00$absN"; - return "${sign}000$absN"; - } - - static String _sixDigits(int n) { - assert(n < -9999 || n > 9999); - int absN = n.abs(); - String sign = n < 0 ? "-" : "+"; - if (absN >= 100000) return "$sign$absN"; - return "${sign}0$absN"; - } - - static String _threeDigits(int n) { - if (n >= 100) return "${n}"; - if (n >= 10) return "0${n}"; - return "00${n}"; - } - - static String _twoDigits(int n) { - if (n >= 10) return "${n}"; - return "0${n}"; - } - - /** - * Returns a human-readable string for this instance. - * - * The returned string is constructed for the time zone of this instance. - * The `toString()` method provides a simply formatted string. - * It does not support internationalized strings. - * Use the [intl](http://pub.dartlang.org/packages/intl) package - * at the pub shared packages repo. - * - * The resulting string can be parsed back using [parse]. - */ - String toString() { - String y = _fourDigits(year); - String m = _twoDigits(month); - String d = _twoDigits(day); - String h = _twoDigits(hour); - String min = _twoDigits(minute); - String sec = _twoDigits(second); - String ms = _threeDigits(millisecond); - if (isUtc) { - return "$y-$m-$d $h:$min:$sec.${ms}Z"; - } else { - return "$y-$m-$d $h:$min:$sec.$ms"; - } - } - - /** - * Returns an ISO-8601 full-precision extended format representation. - * - * The format is `yyyy-MM-ddTHH:mm:ss.sssZ` for UTC time, and - * `yyyy-MM-ddTHH:mm:ss.sss` (no trailing "Z") for local/non-UTC time, - * where: - * - * * `yyyy` is a, possibly negative, four digit representation of the year, - * if the year is in the range -9999 to 9999, - * otherwise it is a signed six digit representation of the year. - * * `MM` is the month in the range 01 to 12, - * * `dd` is the day of the month in the range 01 to 31, - * * `HH` are hours in the range 00 to 23, - * * `mm` are minutes in the range 00 to 59, - * * `ss` are seconds in the range 00 to 59 (no leap seconds), and - * * `sss` are milliseconds in the range 000 to 999. - * - * The resulting string can be parsed back using [parse]. - */ - String toIso8601String() { - String y = (year >= -9999 && year <= 9999) ? _fourDigits(year) - : _sixDigits(year); - String m = _twoDigits(month); - String d = _twoDigits(day); - String h = _twoDigits(hour); - String min = _twoDigits(minute); - String sec = _twoDigits(second); - String ms = _threeDigits(millisecond); - if (isUtc) { - return "$y-$m-${d}T$h:$min:$sec.${ms}Z"; - } else { - return "$y-$m-${d}T$h:$min:$sec.$ms"; - } - } - - /** - * Returns a new [DateTime] instance with [duration] added to [this]. - * - * DateTime today = new DateTime.now(); - * DateTime sixtyDaysFromNow = today.add(new Duration(days: 60)); - */ - DateTime add(Duration duration) { - int ms = millisecondsSinceEpoch; - return new DateTime.fromMillisecondsSinceEpoch( - ms + duration.inMilliseconds, isUtc: isUtc); - } - - /** - * Returns a new [DateTime] instance with [duration] subtracted from [this]. - * - * DateTime today = new DateTime.now(); - * DateTime sixtyDaysAgo = today.subtract(new Duration(days: 60)); - */ - DateTime subtract(Duration duration) { - int ms = millisecondsSinceEpoch; - return new DateTime.fromMillisecondsSinceEpoch( - ms - duration.inMilliseconds, isUtc: isUtc); - } - - /** - * Returns a [Duration] with the difference between [this] and [other]. - * - * DateTime berlinWallFell = new DateTime(1989, DateTime.NOVEMBER, 9); - * DateTime dDay = new DateTime(1944, DateTime.JUNE, 6); - * - * Duration difference = berlinWallFell.difference(dDay); - * assert(difference.inDays == 16592); - */ - - Duration difference(DateTime other) { - int ms = millisecondsSinceEpoch; - int otherMs = other.millisecondsSinceEpoch; - return new Duration(milliseconds: ms - otherMs); - } - - DateTime._internal(int year, - int month, - int day, - int hour, - int minute, - int second, - int millisecond, - bool isUtc) - // checkBool is manually inlined here because dart2js doesn't inline it - // and [isUtc] is usually a constant. - : this.isUtc = isUtc is bool ? isUtc : throw new ArgumentError(isUtc), - millisecondsSinceEpoch = checkInt(Primitives.valueFromDecomposedDate( - year, month, day, hour, minute, second, millisecond, isUtc)); - DateTime._now() - : isUtc = false, - millisecondsSinceEpoch = Primitives.dateNow(); - /// Returns the time as milliseconds since epoch, or null if the - /// values are out of range. - static int _brokenDownDateToMillisecondsSinceEpoch( - int year, int month, int day, int hour, int minute, int second, - int millisecond, bool isUtc) { - return Primitives.valueFromDecomposedDate( - year, month, day, hour, minute, second, millisecond, isUtc); - } - - /** - * The abbreviated time zone name—for example, - * [:"CET":] or [:"CEST":]. - */ - String get timeZoneName { - if (isUtc) return "UTC"; - return Primitives.getTimeZoneName(this); - } - - /** - * The time zone offset, which - * is the difference between local time and UTC. - * - * The offset is positive for time zones east of UTC. - * - * Note, that JavaScript, Python and C return the difference between UTC and - * local time. Java, C# and Ruby return the difference between local time and - * UTC. - */ - Duration get timeZoneOffset { - if (isUtc) return new Duration(); - return new Duration(minutes: Primitives.getTimeZoneOffsetInMinutes(this)); - } - - /** - * The year. - * - * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); - * assert(moonLanding.year == 1969); - */ - int get year => Primitives.getYear(this); - - /** - * The month [1..12]. - * - * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); - * assert(moonLanding.month == 7); - * assert(moonLanding.month == DateTime.JULY); - */ - int get month => Primitives.getMonth(this); - - /** - * The day of the month [1..31]. - * - * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); - * assert(moonLanding.day == 20); - */ - int get day => Primitives.getDay(this); - - /** - * The hour of the day, expressed as in a 24-hour clock [0..23]. - * - * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); - * assert(moonLanding.hour == 20); - */ - int get hour => Primitives.getHours(this); - - /** - * The minute [0...59]. - * - * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); - * assert(moonLanding.minute == 18); - */ - int get minute => Primitives.getMinutes(this); - - /** - * The second [0...59]. - * - * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); - * assert(moonLanding.second == 0); - */ - int get second => Primitives.getSeconds(this); - - /** - * The millisecond [0...999]. - * - * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); - * assert(moonLanding.millisecond == 0); - */ - int get millisecond => Primitives.getMilliseconds(this); - - /** - * The day of the week [MONDAY]..[SUNDAY]. - * - * In accordance with ISO 8601 - * a week starts with Monday, which has the value 1. - * - * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); - * assert(moonLanding.weekday == 7); - * assert(moonLanding.weekday == DateTime.SUNDAY); - * - */ - int get weekday => Primitives.getWeekday(this); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/double.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/double.dart deleted file mode 100644 index 90bd0e4f92b4..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/double.dart +++ /dev/null @@ -1,208 +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. - -part of dart.core; - -// TODO: Convert this abstract class into a concrete class double -// that uses the patch class functionality to account for the -// different platform implementations. - -/** - * A double-precision floating point number. - * - * Representation of Dart doubles containing double specific constants - * and operations and specializations of operations inherited from - * [num]. Dart doubles are 64-bit floating-point numbers as specified in the - * IEEE 754 standard. - * - * The [double] type is contagious. Operations on [double]s return - * [double] results. - * - * It is a compile-time error for a class to attempt to extend or implement - * double. - */ -abstract class double extends num { - static const double NAN = 0.0 / 0.0; - static const double INFINITY = 1.0 / 0.0; - static const double NEGATIVE_INFINITY = -INFINITY; - static const double MIN_POSITIVE = 5e-324; - static const double MAX_FINITE = 1.7976931348623157e+308; - - double remainder(num other); - - /** Addition operator. */ - double operator +(num other); - - /** Subtraction operator. */ - double operator -(num other); - - /** Multiplication operator. */ - double operator *(num other); - - double operator %(num other); - - /** Division operator. */ - double operator /(num other); - - /** - * Truncating division operator. - * - * The result of the truncating division `a ~/ b` is equivalent to - * `(a / b).truncate()`. - */ - int operator ~/(num other); - - /** Negate operator. */ - double operator -(); - - /** Returns the absolute value of this [double]. */ - double abs(); - - /** - * Returns the sign of the double's numerical value. - * - * Returns -1.0 if the value is less than zero, - * +1.0 if the value is greater than zero, - * and the value itself if it is -0.0, 0.0 or NaN. - */ - double get sign; - - /** - * Returns the integer closest to `this`. - * - * Rounds away from zero when there is no closest integer: - * `(3.5).round() == 4` and `(-3.5).round() == -4`. - * - * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError]. - */ - int round(); - - /** - * Returns the greatest integer no greater than `this`. - * - * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError]. - */ - int floor(); - - /** - * Returns the least integer no smaller than `this`. - * - * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError]. - */ - int ceil(); - - /** - * Returns the integer obtained by discarding any fractional - * digits from `this`. - * - * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError]. - */ - int truncate(); - - /** - * Returns the integer double value closest to `this`. - * - * Rounds away from zero when there is no closest integer: - * `(3.5).roundToDouble() == 4` and `(-3.5).roundToDouble() == -4`. - * - * If this is already an integer valued double, including `-0.0`, or it is not - * a finite value, the value is returned unmodified. - * - * For the purpose of rounding, `-0.0` is considered to be below `0.0`, - * and `-0.0` is therefore considered closer to negative numbers than `0.0`. - * This means that for a value, `d` in the range `-0.5 < d < 0.0`, - * the result is `-0.0`. - */ - double roundToDouble(); - - /** - * Returns the greatest integer double value no greater than `this`. - * - * If this is already an integer valued double, including `-0.0`, or it is not - * a finite value, the value is returned unmodified. - * - * For the purpose of rounding, `-0.0` is considered to be below `0.0`. - * A number `d` in the range `0.0 < d < 1.0` will return `0.0`. - */ - double floorToDouble(); - - /** - * Returns the least integer double value no smaller than `this`. - * - * If this is already an integer valued double, including `-0.0`, or it is not - * a finite value, the value is returned unmodified. - * - * For the purpose of rounding, `-0.0` is considered to be below `0.0`. - * A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`. - */ - double ceilToDouble(); - - /** - * Returns the integer double value obtained by discarding any fractional - * digits from `this`. - * - * If this is already an integer valued double, including `-0.0`, or it is not - * a finite value, the value is returned unmodified. - * - * For the purpose of rounding, `-0.0` is considered to be below `0.0`. - * A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`, and - * in the range `0.0 < d < 1.0` it will return 0.0. - */ - double truncateToDouble(); - - /** - * Provide a representation of this [double] value. - * - * The representation is a number literal such that the closest double value - * to the representation's mathematical value is this [double]. - * - * Returns "NaN" for the Not-a-Number value. - * Returns "Infinity" and "-Infinity" for positive and negative Infinity. - * Returns "-0.0" for negative zero. - * - * For all doubles, `d`, converting to a string and parsing the string back - * gives the same value again: `d == double.parse(d.toString())` (except when - * `d` is NaN). - */ - String toString(); - - /** - * Parse [source] as an double literal and return its value. - * - * Accepts an optional sign (`+` or `-`) followed by either the characters - * "Infinity", the characters "NaN" or a floating-point representation. - * A floating-point representation is composed of a mantissa and an optional - * exponent part. The mantissa is either a decimal point (`.`) followed by a - * sequence of (decimal) digits, or a sequence of digits - * optionally followed by a decimal point and optionally more digits. The - * (optional) exponent part consists of the character "e" or "E", an optional - * sign, and one or more digits. - * - * Leading and trailing whitespace is ignored. - * - * If the [source] is not a valid double literal, the [onError] - * is called with the [source] as argument, and its return value is - * used instead. If no `onError` is provided, a [FormatException] - * is thrown instead. - * - * The [onError] function is only invoked if [source] is a [String] with an - * invalid format. It is not invoked if the [source] is invalid for some - * other reason, for example by being `null`. - * - * Examples of accepted strings: - * - * "3.14" - * " 3.14 \xA0" - * "0." - * ".0" - * "-1.e3" - * "1234E+7" - * "+.12e-9" - * "-NaN" - */ - static double parse(String source, - [double onError(String source)]) { - return Primitives.parseDouble(source, onError); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/duration.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/duration.dart deleted file mode 100644 index 402d289e12d0..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/duration.dart +++ /dev/null @@ -1,289 +0,0 @@ -// 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. - -part of dart.core; - -/** - * A span of time, such as 27 days, 4 hours, 12 minutes, and 3 seconds. - * - * A `Duration` represents a difference from one point in time to another. The - * duration may be "negative" if the difference is from a later time to an - * earlier. - * - * To create a new Duration object, use this class's single constructor - * giving the appropriate arguments: - * - * Duration fastestMarathon = new Duration(hours:2, minutes:3, seconds:2); - * - * The Duration is the sum of all individual parts. - * This means that individual parts can be larger than the next-bigger unit. - * For example, [minutes] can be greater than 59. - * - * assert(fastestMarathon.inMinutes == 123); - * - * All individual parts are allowed to be negative. - * - * Use one of the properties, such as [inDays], - * to retrieve the integer value of the Duration in the specified time unit. - * Note that the returned value is rounded down. - * For example, - * - * Duration aLongWeekend = new Duration(hours:88); - * assert(aLongWeekend.inDays == 3); - * - * This class provides a collection of arithmetic - * and comparison operators, - * plus a set of constants useful for converting time units. - * - * See [DateTime] to represent a point in time. - * See [Stopwatch] to measure time-spans. - * - */ -class Duration implements Comparable { - static const int MICROSECONDS_PER_MILLISECOND = 1000; - static const int MILLISECONDS_PER_SECOND = 1000; - static const int SECONDS_PER_MINUTE = 60; - static const int MINUTES_PER_HOUR = 60; - static const int HOURS_PER_DAY = 24; - - static const int MICROSECONDS_PER_SECOND = - MICROSECONDS_PER_MILLISECOND * MILLISECONDS_PER_SECOND; - static const int MICROSECONDS_PER_MINUTE = - MICROSECONDS_PER_SECOND * SECONDS_PER_MINUTE; - static const int MICROSECONDS_PER_HOUR = - MICROSECONDS_PER_MINUTE * MINUTES_PER_HOUR; - static const int MICROSECONDS_PER_DAY = - MICROSECONDS_PER_HOUR * HOURS_PER_DAY; - - - static const int MILLISECONDS_PER_MINUTE = - MILLISECONDS_PER_SECOND * SECONDS_PER_MINUTE; - static const int MILLISECONDS_PER_HOUR = - MILLISECONDS_PER_MINUTE * MINUTES_PER_HOUR; - static const int MILLISECONDS_PER_DAY = - MILLISECONDS_PER_HOUR * HOURS_PER_DAY; - - static const int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR; - static const int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY; - - static const int MINUTES_PER_DAY = MINUTES_PER_HOUR * HOURS_PER_DAY; - - static const Duration ZERO = const Duration(seconds: 0); - - /* - * The value of this Duration object in microseconds. - */ - final int _duration; - - /** - * Creates a new Duration object whose value - * is the sum of all individual parts. - * - * Individual parts can be larger than the next-bigger unit. - * For example, [hours] can be greater than 23. - * - * All individual parts are allowed to be negative. - * All arguments are 0 by default. - */ - const Duration({int days: 0, - int hours: 0, - int minutes: 0, - int seconds: 0, - int milliseconds: 0, - int microseconds: 0}) - : this._microseconds( - days * MICROSECONDS_PER_DAY + - hours * MICROSECONDS_PER_HOUR + - minutes * MICROSECONDS_PER_MINUTE + - seconds * MICROSECONDS_PER_SECOND + - milliseconds * MICROSECONDS_PER_MILLISECOND + - microseconds); - - // Fast path internal direct constructor to avoids the optional arguments and - // [_microseconds] recomputation. - const Duration._microseconds(this._duration); - - /** - * Adds this Duration and [other] and - * returns the sum as a new Duration object. - */ - Duration operator +(Duration other) { - return new Duration._microseconds(_duration + other._duration); - } - - /** - * Subtracts [other] from this Duration and - * returns the difference as a new Duration object. - */ - Duration operator -(Duration other) { - return new Duration._microseconds(_duration - other._duration); - } - - /** - * Multiplies this Duration by the given [factor] and returns the result - * as a new Duration object. - * - * Note that when [factor] is a double, and the duration is greater than - * 53 bits, precision is lost because of double-precision arithmetic. - */ - Duration operator *(num factor) { - return new Duration._microseconds((_duration * factor).round()); - } - - /** - * Divides this Duration by the given [quotient] and returns the truncated - * result as a new Duration object. - * - * Throws an [IntegerDivisionByZeroException] if [quotient] is `0`. - */ - Duration operator ~/(int quotient) { - // By doing the check here instead of relying on "~/" below we get the - // exception even with dart2js. - if (quotient == 0) throw new IntegerDivisionByZeroException(); - return new Duration._microseconds(_duration ~/ quotient); - } - - /** - * Returns `true` if the value of this Duration - * is less than the value of [other]. - */ - bool operator <(Duration other) => this._duration < other._duration; - - /** - * Returns `true` if the value of this Duration - * is greater than the value of [other]. - */ - bool operator >(Duration other) => this._duration > other._duration; - - /** - * Returns `true` if the value of this Duration - * is less than or equal to the value of [other]. - */ - bool operator <=(Duration other) => this._duration <= other._duration; - - /** - * Returns `true` if the value of this Duration - * is greater than or equal to the value of [other]. - */ - bool operator >=(Duration other) => this._duration >= other._duration; - - /** - * Returns the number of whole days spanned by this Duration. - */ - int get inDays => _duration ~/ Duration.MICROSECONDS_PER_DAY; - - /** - * Returns the number of whole hours spanned by this Duration. - * - * The returned value can be greater than 23. - */ - int get inHours => _duration ~/ Duration.MICROSECONDS_PER_HOUR; - - /** - * Returns the number of whole minutes spanned by this Duration. - * - * The returned value can be greater than 59. - */ - int get inMinutes => _duration ~/ Duration.MICROSECONDS_PER_MINUTE; - - /** - * Returns the number of whole seconds spanned by this Duration. - * - * The returned value can be greater than 59. - */ - int get inSeconds => _duration ~/ Duration.MICROSECONDS_PER_SECOND; - - /** - * Returns number of whole milliseconds spanned by this Duration. - * - * The returned value can be greater than 999. - */ - int get inMilliseconds => _duration ~/ Duration.MICROSECONDS_PER_MILLISECOND; - - /** - * Returns number of whole microseconds spanned by this Duration. - */ - int get inMicroseconds => _duration; - - /** - * Returns `true` if this Duration is the same object as [other]. - */ - bool operator ==(other) { - if (other is !Duration) return false; - return _duration == other._duration; - } - - int get hashCode => _duration.hashCode; - - /** - * Compares this Duration to [other], returning zero if the values are equal. - * - * Returns a negative integer if this `Duration` is shorter than - * [other], or a positive integer if it is longer. - * - * A negative `Duration` is always considered shorter than a positive one. - * - * It is always the case that `duration1.compareTo(duration2) < 0` iff - * `(someDate + duration1).compareTo(someDate + duration2) < 0`. - */ - int compareTo(Duration other) => _duration.compareTo(other._duration); - - /** - * Returns a string representation of this `Duration`. - * - * Returns a string with hours, minutes, seconds, and microseconds, in the - * following format: `HH:MM:SS.mmmmmm`. For example, - * - * var d = new Duration(days:1, hours:1, minutes:33, microseconds: 500); - * d.toString(); // "25:33:00.000500" - */ - String toString() { - String sixDigits(int n) { - if (n >= 100000) return "$n"; - if (n >= 10000) return "0$n"; - if (n >= 1000) return "00$n"; - if (n >= 100) return "000$n"; - if (n >= 10) return "0000$n"; - return "00000$n"; - } - String twoDigits(int n) { - if (n >= 10) return "$n"; - return "0$n"; - } - - if (inMicroseconds < 0) { - return "-${-this}"; - } - String twoDigitMinutes = twoDigits(inMinutes.remainder(MINUTES_PER_HOUR)); - String twoDigitSeconds = twoDigits(inSeconds.remainder(SECONDS_PER_MINUTE)); - String sixDigitUs = - sixDigits(inMicroseconds.remainder(MICROSECONDS_PER_SECOND)); - return "$inHours:$twoDigitMinutes:$twoDigitSeconds.$sixDigitUs"; - } - - /** - * Returns whether this `Duration` is negative. - * - * A negative `Duration` represents the difference from a later time to an - * earlier time. - */ - bool get isNegative => _duration < 0; - - /** - * Returns a new `Duration` representing the absolute value of this - * `Duration`. - * - * The returned `Duration` has the same length as this one, but is always - * positive. - */ - Duration abs() => new Duration._microseconds(_duration.abs()); - - /** - * Returns a new `Duration` representing this `Duration` negated. - * - * The returned `Duration` has the same length as this one, but will have the - * opposite sign of this one. - */ - Duration operator -() => new Duration._microseconds(-_duration); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/errors.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/errors.dart deleted file mode 100644 index d1cba8cbf39c..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/errors.dart +++ /dev/null @@ -1,603 +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. - -part of dart.core; - -/** - * Error objects thrown in the case of a program failure. - * - * An `Error` object represents a program failure that the programmer - * should have avoided. - * - * Examples include calling a function with invalid arguments, - * or even with the wrong number of arguments, - * or calling it at a time when it is not allowed. - * - * These are not errors that a caller should expect or catch - - * if they occur, the program is erroneous, - * and terminating the program may be the safest response. - * - * When deciding that a function throws an error, - * the conditions where it happens should be clearly described, - * and they should be detectable and predictable, - * so the programmer using the function can avoid triggering the error. - * - * Such descriptions often uses words like - * "must" or "must not" to describe the condition, - * and if you see words like that in a function's documentation, - * then not satisfying the requirement - * is very likely to cause an error to be thrown. - * - * Example (from [String.contains]): - * - * `startIndex` must not be negative or greater than `length`. - * - * In this case, an error will be thrown if `startIndex` is negative - * or too large. - * - * If the conditions are not detectable before calling a function, - * the called function should not throw an `Error`. - * It may still throw a value, - * but the caller will have to catch the thrown value, - * effectively making it an alternative result rather than an error. - * The thrown object can choose to implement [Exception] - * to document that it represents an exceptional, but not erroneous, occurrence, - * but it has no other effect than documentation. - * - * All non-`null` values can be thrown in Dart. - * Objects extending `Error` are handled specially: - * The first time they are thrown, - * the stack trace at the throw point is recorded - * and stored in the error object. - * It can be retrieved using the [stackTrace] getter. - * An error object that merely implements `Error`, and doesn't extend it, - * will not store the stack trace automatically. - * - * Error objects are also used for system wide failures - * like stack overflow or an out-of-memory situation. - * - * Since errors are not created to be caught, - * there is no need for subclasses to distinguish the errors. - * Instead subclasses have been created in order to make groups - * of related errors easy to create with consistent error messages. - * For example, the [String.contains] method will use a [RangeError] - * if its `startIndex` isn't in the range `0..length`, - * which is easily created by `new RangeError.range(startIndex, 0, length)`. - */ -class Error { - Error(); // Prevent use as mixin. - - /** - * Safely convert a value to a [String] description. - * - * The conversion is guaranteed to not throw, so it won't use the object's - * toString method. - */ - static String safeToString(Object object) { - if (object is num || object is bool || null == object) { - return object.toString(); - } - if (object is String) { - return _stringToSafeString(object); - } - return _objectToString(object); - } - - /** Convert string to a valid string literal with no control characters. */ - static String _stringToSafeString(String string) { - return jsonEncodeNative(string); - } - - static String _objectToString(Object object) { - return Primitives.objectToString(object); - } - - StackTrace get stackTrace => Primitives.extractStackTrace(this); -} - -/** - * Error thrown by the runtime system when an assert statement fails. - */ -class AssertionError extends Error { -} - -/** - * Error thrown by the runtime system when a type assertion fails. - */ -class TypeError extends AssertionError { -} - -/** - * Error thrown by the runtime system when a cast operation fails. - */ -class CastError extends Error { -} - -/** - * Error thrown when attempting to throw [:null:]. - */ -class NullThrownError extends Error { - String toString() => "Throw of null."; -} - -/** - * Error thrown when a function is passed an unacceptable argument. - */ -class ArgumentError extends Error { - /** Whether value was provided. */ - final bool _hasValue; - /** The invalid value. */ - final invalidValue; - /** Name of the invalid argument, if available. */ - final String name; - /** Message describing the problem. */ - final message; - - /** - * The [message] describes the erroneous argument. - * - * Existing code may be using `message` to hold the invalid value. - * If the `message` is not a [String], it is assumed to be a value instead - * of a message. - */ - ArgumentError([this.message]) - : invalidValue = null, - _hasValue = false, - name = null; - - /** - * Creates error containing the invalid [value]. - * - * A message is built by suffixing the [message] argument with - * the [name] argument (if provided) and the value. Example - * - * "Invalid argument (foo): null" - * - * The `name` should match the argument name of the function, but if - * the function is a method implementing an interface, and its argument - * names differ from the interface, it might be more useful to use the - * interface method's argument name (or just rename arguments to match). - */ - ArgumentError.value(value, - [String this.name, - String this.message = "Invalid argument"]) - : invalidValue = value, - _hasValue = true; - - /** - * Create an argument error for a `null` argument that must not be `null`. - * - * Shorthand for calling [ArgumentError.value] with a `null` value and a - * message of `"Must not be null"`. - */ - ArgumentError.notNull([String name]) - : this.value(null, name, "Must not be null"); - - String toString() { - if (!_hasValue) { - var result = "Invalid arguments(s)"; - if (message != null) { - result = "$result: $message"; - } - return result; - } - String nameString = ""; - if (name != null) { - nameString = " ($name)"; - } - return "$message$nameString: ${Error.safeToString(invalidValue)}"; - } -} - -/** - * Error thrown due to an index being outside a valid range. - */ -class RangeError extends ArgumentError { - /** The minimum value that [value] is allowed to assume. */ - final num start; - /** The maximum value that [value] is allowed to assume. */ - final num end; - - // TODO(lrn): This constructor should be called only with string values. - // It currently isn't in all cases. - /** - * Create a new [RangeError] with the given [message]. - */ - RangeError(var message) - : start = null, end = null, super(message); - - /** - * Create a new [RangeError] with a message for the given [value]. - * - * An optional [name] can specify the argument name that has the - * invalid value, and the [message] can override the default error - * description. - */ - RangeError.value(num value, [String name, String message]) - : start = null, end = null, - super.value(value, name, - (message != null) ? message : "Value not in range"); - - /** - * Create a new [RangeError] with for an invalid value being outside a range. - * - * The allowed range is from [minValue] to [maxValue], inclusive. - * If `minValue` or `maxValue` are `null`, the range is infinite in - * that direction. - * - * For a range from 0 to the length of something, end exclusive, use - * [RangeError.index]. - * - * An optional [name] can specify the argument name that has the - * invalid value, and the [message] can override the default error - * description. - */ - RangeError.range(num invalidValue, int minValue, int maxValue, - [String name, String message]) - : start = minValue, - end = maxValue, - super.value(invalidValue, name, - (message != null) ? message : "Invalid value"); - - /** - * Creates a new [RangeError] stating that [index] is not a valid index - * into [indexable]. - * - * An optional [name] can specify the argument name that has the - * invalid value, and the [message] can override the default error - * description. - * - * The [length] is the length of [indexable] at the time of the error. - * If `length` is omitted, it defaults to `indexable.length`. - */ - factory RangeError.index(int index, indexable, - [String name, - String message, - int length]) = IndexError; - - /** - * Check that a [value] lies in a specific interval. - * - * Throws if [value] is not in the interval. - * The interval is from [minValue] to [maxValue], both inclusive. - */ - static void checkValueInInterval(int value, int minValue, int maxValue, - [String name, String message]) { - if (value < minValue || value > maxValue) { - throw new RangeError.range(value, minValue, maxValue, name, message); - } - } - - /** - * Check that a value is a valid index into an indexable object. - * - * Throws if [index] is not a valid index into [indexable]. - * - * An indexable object is one that has a `length` and a and index-operator - * `[]` that accepts an index if `0 <= index < length`. - * - * If [length] is provided, it is used as the length of the indexable object, - * otherwise the length is found as `idexable.length`. - */ - static void checkValidIndex(int index, var indexable, - [String name, int length, String message]) { - if (length == null) length = indexable.length; - if (index < 0 || index >= length) { - if (name == null) name = "index"; - throw new RangeError.index(index, indexable, name, message, length); - } - } - - /** - * Check that a range represents a slice of an indexable object. - * - * Throws if the range is not valid for an indexable object with - * the given [length]. - * A range is valid for an indexable object with a given [length] - * - * if `0 <= [start] <= [end] <= [length]`. - * An `end` of `null` is considered equivalent to `length`. - * - * The [startName] and [endName] defaults to `"start"` and `"end"`, - * respectively. - */ - static void checkValidRange(int start, int end, int length, - [String startName, String endName, - String message]) { - if (start < 0 || start > length) { - if (startName == null) startName = "start"; - throw new RangeError.range(start, 0, length, startName, message); - } - if (end != null && (end < start || end > length)) { - if (endName == null) endName = "end"; - throw new RangeError.range(end, start, length, endName, message); - } - } - - /** - * Check that an integer value isn't negative. - * - * Throws if the value is negative. - */ - static void checkNotNegative(int value, [String name, String message]) { - if (value < 0) throw new RangeError.range(value, 0, null, name, message); - } - - String toString() { - if (!_hasValue) return "RangeError: $message"; - String value = Error.safeToString(invalidValue); - String explanation = ""; - if (start == null) { - if (end != null) { - explanation = ": Not less than or equal to $end"; - } - // If both are null, we don't add a description of the limits. - } else if (end == null) { - explanation = ": Not greater than or equal to $start"; - } else if (end > start) { - explanation = ": Not in range $start..$end, inclusive."; - } else if (end < start) { - explanation = ": Valid value range is empty"; - } else { - // end == start. - explanation = ": Only valid value is $start"; - } - return "RangeError: $message ($value)$explanation"; - } -} - -/** - * A specialized [RangeError] used when an index is not in the range - * `0..indexable.length-1`. - * - * Also contains the indexable object, its length at the time of the error, - * and the invalid index itself. - */ -class IndexError extends ArgumentError implements RangeError { - /** The indexable object that [index] was not a valid index into. */ - final indexable; - /** The length of [indexable] at the time of the error. */ - final int length; - - /** - * Creates a new [IndexError] stating that [invalidValue] is not a valid index - * into [indexable]. - * - * The [length] is the length of [indexable] at the time of the error. - * If `length` is omitted, it defaults to `indexable.length`. - * - * The message is used as part of the string representation of the error. - */ - IndexError(int invalidValue, indexable, - [String name, String message, int length]) - : this.indexable = indexable, - this.length = (length != null) ? length : indexable.length, - super.value(invalidValue, name, - (message != null) ? message : "Index out of range"); - - // Getters inherited from RangeError. - int get start => 0; - int get end => length - 1; - - String toString() { - assert(_hasValue); - String target = Error.safeToString(indexable); - var explanation = "index should be less than $length"; - if (invalidValue < 0) { - explanation = "index must not be negative"; - } - return "RangeError: $message ($target[$invalidValue]): $explanation"; - } -} - - -/** - * Error thrown when control reaches the end of a switch case. - * - * The Dart specification requires this error to be thrown when - * control reaches the end of a switch case (except the last case - * of a switch) without meeting a break or similar end of the control - * flow. - */ -class FallThroughError extends Error { - FallThroughError(); -} - -/** - * Error thrown when trying to instantiate an abstract class. - */ -class AbstractClassInstantiationError extends Error { - final String _className; - AbstractClassInstantiationError(String this._className); - String toString() => "Cannot instantiate abstract class: '$_className'"; -} - - -/** - * Error thrown by the default implementation of [:noSuchMethod:] on [Object]. - */ -class NoSuchMethodError extends Error { - final Object _receiver; - final Symbol _memberName; - final List _arguments; - final Map _namedArguments; - final List _existingArgumentNames; - - /** - * Create a [NoSuchMethodError] corresponding to a failed method call. - * - * The [receiver] is the receiver of the method call. - * That is, the object on which the method was attempted called. - * If the receiver is `null`, it is interpreted as a call to a top-level - * function of a library. - * - * The [memberName] is a [Symbol] representing the name of the called method - * or accessor. It should not be `null`. - * - * The [positionalArguments] is a list of the positional arguments that the - * method was called with. If `null`, it is considered equivalent to the - * empty list. - * - * The [namedArguments] is a map from [Symbol]s to the values of named - * arguments that the method was called with. - * - * The optional [exisitingArgumentNames] is the expected parameters of a - * method with the same name on the receiver, if available. This is - * the signature of the method that would have been called if the parameters - * had matched. - */ - NoSuchMethodError(Object receiver, - Symbol memberName, - List positionalArguments, - Map namedArguments, - [List existingArgumentNames = null]) - : _receiver = receiver, - _memberName = memberName, - _arguments = positionalArguments, - _namedArguments = namedArguments, - _existingArgumentNames = existingArgumentNames; - - String toString() { - StringBuffer sb = new StringBuffer(); - int i = 0; - if (_arguments != null) { - for (; i < _arguments.length; i++) { - if (i > 0) { - sb.write(", "); - } - sb.write(Error.safeToString(_arguments[i])); - } - } - if (_namedArguments != null) { - _namedArguments.forEach((Symbol key, var value) { - if (i > 0) { - sb.write(", "); - } - sb.write(_symbolToString(key)); - sb.write(": "); - sb.write(Error.safeToString(value)); - i++; - }); - } - if (_existingArgumentNames == null) { - return "NoSuchMethodError : method not found: '$_memberName'\n" - "Receiver: ${Error.safeToString(_receiver)}\n" - "Arguments: [$sb]"; - } else { - String actualParameters = sb.toString(); - sb = new StringBuffer(); - for (int i = 0; i < _existingArgumentNames.length; i++) { - if (i > 0) { - sb.write(", "); - } - sb.write(_existingArgumentNames[i]); - } - String formalParameters = sb.toString(); - return "NoSuchMethodError: incorrect number of arguments passed to " - "method named '$_memberName'\n" - "Receiver: ${Error.safeToString(_receiver)}\n" - "Tried calling: $_memberName($actualParameters)\n" - "Found: $_memberName($formalParameters)"; - } - } -} - - -/** - * The operation was not allowed by the object. - * - * This [Error] is thrown when an instance cannot implement one of the methods - * in its signature. - */ -class UnsupportedError extends Error { - final String message; - UnsupportedError(this.message); - String toString() => "Unsupported operation: $message"; -} - - -/** - * Thrown by operations that have not been implemented yet. - * - * This [Error] is thrown by unfinished code that hasn't yet implemented - * all the features it needs. - * - * If a class is not intending to implement the feature, it should throw - * an [UnsupportedError] instead. This error is only intended for - * use during development. - */ -class UnimplementedError extends Error implements UnsupportedError { - final String message; - UnimplementedError([String this.message]); - String toString() => (this.message != null - ? "UnimplementedError: $message" - : "UnimplementedError"); -} - - -/** - * The operation was not allowed by the current state of the object. - * - * This is a generic error used for a variety of different erroneous - * actions. The message should be descriptive. - */ -class StateError extends Error { - final String message; - StateError(this.message); - String toString() => "Bad state: $message"; -} - - -/** - * Error occurring when a collection is modified during iteration. - * - * Some modifications may be allowed for some collections, so each collection - * ([Iterable] or similar collection of values) should declare which operations - * are allowed during an iteration. - */ -class ConcurrentModificationError extends Error { - /** The object that was modified in an incompatible way. */ - final Object modifiedObject; - - ConcurrentModificationError([this.modifiedObject]); - - String toString() { - if (modifiedObject == null) { - return "Concurrent modification during iteration."; - } - return "Concurrent modification during iteration: " - "${Error.safeToString(modifiedObject)}."; - } -} - - -class OutOfMemoryError implements Error { - const OutOfMemoryError(); - String toString() => "Out of Memory"; - - StackTrace get stackTrace => null; -} - - -class StackOverflowError implements Error { - const StackOverflowError(); - String toString() => "Stack Overflow"; - - StackTrace get stackTrace => null; -} - -/** - * Error thrown when a lazily initialized variable cannot be initialized. - * - * A static/library variable with an initializer expression is initialized - * the first time it is read. If evaluating the initializer expression causes - * another read of the variable, this error is thrown. - */ -class CyclicInitializationError extends Error { - final String variableName; - CyclicInitializationError([this.variableName]); - String toString() => variableName == null - ? "Reading static variable during its initialization" - : "Reading static variable '$variableName' during its initialization"; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/exceptions.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/exceptions.dart deleted file mode 100644 index 6191e27c05ae..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/exceptions.dart +++ /dev/null @@ -1,180 +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. - -part of dart.core; - -// Exceptions are thrown either by the VM or from Dart code. - -/** - * A marker interface implemented by all core library exceptions. - * - * An [Exception] is intended to convey information to the user about a failure, - * so that the error can be addressed programmatically. It is intended to be - * caught, and it should contain useful data fields. - * - * Creating instances of [Exception] directly with [:new Exception("message"):] - * is discouraged, and only included as a temporary measure during development, - * until the actual exceptions used by a library are done. - */ -abstract class Exception { - factory Exception([var message]) => new _ExceptionImplementation(message); -} - - -/** Default implementation of [Exception] which carries a message. */ -class _ExceptionImplementation implements Exception { - final message; - - _ExceptionImplementation([this.message]); - - String toString() { - if (message == null) return "Exception"; - return "Exception: $message"; - } -} - - -/** - * Exception thrown when a string or some other data does not have an expected - * format and cannot be parsed or processed. - */ -class FormatException implements Exception { - /** - * A message describing the format error. - */ - final String message; - - /** - * The actual source input that caused the error. - * - * This is usually a [String], but can be other types too. - * If it is a string, parts of it may be included in the [toString] message. - * - * The source is `null` if omitted or unknown. - */ - final source; - - /** - * The offset in [source] where the error was detected. - * - * A zero-based offset into the source that marks the format error causing - * this exception to be created. If `source` is a string, this should be a - * string index in the range `0 <= offset <= source.length`. - * - * If input is a string, the [toString] method may represent this offset as - * a line and character position. The offset should be inside the string, - * or at the end of the string. - * - * May be omitted. If present, [source] should also be present if possible. - */ - final int offset; - - /** - * Creates a new FormatException with an optional error [message]. - * - * Optionally also supply the actual [source] that had the incorrect format, - * and an [offset] in the format where a problem was detected. - */ - const FormatException([this.message = "", this.source, this.offset = -1]); - - /** - * Returns a description of the format exception. - * - * The description always contains the [message]. - * - * If [source] is present and is a string, the description will contain - * (at least a part of) the source. - * If [offset] is also provided, the part of the source included will - * contain that offset, and the offset will be marked. - * - * If the source is a string and it contains a line break before offset, - * only the line containing offset will be included, and its line number - * will also be part of the description. Line and character offsets are - * 1-based. - */ - String toString() { - String report = "FormatException"; - if (message != null && "" != message) { - report = "$report: $message"; - } - int offset = this.offset; - if (source is! String) { - if (offset != -1) { - report += " (at offset $offset)"; - } - return report; - } - if (offset != -1 && (offset < 0 || offset > source.length)) { - offset = -1; - } - // Source is string and offset is null or valid. - if (offset == -1) { - String source = this.source; - if (source.length > 78) { - source = source.substring(0, 75) + "..."; - } - return "$report\n$source"; - } - int lineNum = 1; - int lineStart = 0; - bool lastWasCR; - for (int i = 0; i < offset; i++) { - int char = source.codeUnitAt(i); - if (char == 0x0a) { - if (lineStart != i || !lastWasCR) { - lineNum++; - } - lineStart = i + 1; - lastWasCR = false; - } else if (char == 0x0d) { - lineNum++; - lineStart = i + 1; - lastWasCR = true; - } - } - if (lineNum > 1) { - report += " (at line $lineNum, character ${offset - lineStart + 1})\n"; - } else { - report += " (at character ${offset + 1})\n"; - } - int lineEnd = source.length; - for (int i = offset; i < source.length; i++) { - int char = source.codeUnitAt(i); - if (char == 0x0a || char == 0x0d) { - lineEnd = i; - break; - } - } - int length = lineEnd - lineStart; - int start = lineStart; - int end = lineEnd; - String prefix = ""; - String postfix = ""; - if (length > 78) { - // Can't show entire line. Try to anchor at the nearest end, if - // one is within reach. - int index = offset - lineStart; - if (index < 75) { - end = start + 75; - postfix = "..."; - } else if (end - offset < 75) { - start = end - 75; - prefix = "..."; - } else { - // Neither end is near, just pick an area around the offset. - start = offset - 36; - end = offset + 36; - prefix = postfix = "..."; - } - } - String slice = source.substring(start, end); - int markOffset = offset - start + prefix.length; - return "$report$prefix$slice$postfix\n${" " * markOffset}^\n"; - } -} - -class IntegerDivisionByZeroException implements Exception { - const IntegerDivisionByZeroException(); - String toString() => "IntegerDivisionByZeroException"; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/expando.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/expando.dart deleted file mode 100644 index 26577ad274bf..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/expando.dart +++ /dev/null @@ -1,89 +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. - -part of dart.core; - -/** - * An [Expando] allows adding new properties to objects. - * - * Does not work on numbers, strings, booleans or null. - * - * An `Expando` does not hold on to the added property value after an object - * becomes inacessible. - * - * Since you can always create a new number that is identical to an existing - * number, it means that an expando property on a number could never be - * released. To avoid this, expando properties cannot be added to numbers. - * The same argument applies to strings, booleans and null, which also have - * literals that evaluate to identical values when they occur more than once. - * - * There is no restriction on other classes, even for compile time constant - * objects. Be careful if adding expando properties to compile time constants, - * since they will stay alive forever. - */ -class Expando { - - /** - * The name of the this [Expando] as passed to the constructor. If - * no name was passed to the constructor, the name is [:null:]. - */ - final String name; - - /** - * Creates a new [Expando]. The optional name is only used for - * debugging purposes and creating two different [Expando]s with the - * same name yields two [Expando]s that work on different properties - * of the objects they are used on. - */ - Expando([String name]) : this.name = name; - - /** - * Expando toString method override. - */ - String toString() => "Expando:$name"; - - /** - * Gets the value of this [Expando]'s property on the given - * object. If the object hasn't been expanded, the method returns - * [:null:]. - * - * The object must not be a number, a string, a boolean or null. - */ - T operator[](Object object) { - var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME); - return (values == null) ? null : Primitives.getProperty(values, _getKey()); - } - - /** - * Sets the value of this [Expando]'s property on the given - * object. Properties can effectively be removed again by setting - * their value to null. - * - * The object must not be a number, a string, a boolean or null. - */ - void operator[]=(Object object, T value) { - var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME); - if (values == null) { - values = new Object(); - Primitives.setProperty(object, _EXPANDO_PROPERTY_NAME, values); - } - Primitives.setProperty(values, _getKey(), value); - } - - String _getKey() { - String key = Primitives.getProperty(this, _KEY_PROPERTY_NAME); - if (key == null) { - key = "expando\$key\$${_keyCount++}"; - Primitives.setProperty(this, _KEY_PROPERTY_NAME, key); - } - return key; - } - - static const String _KEY_PROPERTY_NAME = 'expando\$key'; - - static const String _EXPANDO_PROPERTY_NAME = 'expando\$values'; - - static int _keyCount = 0; - -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/function.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/function.dart deleted file mode 100644 index cdd298791c52..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/function.dart +++ /dev/null @@ -1,80 +0,0 @@ -// 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. - -part of dart.core; - -/** - * The base class for all function types. - * - * A function value, or an instance of a class with a "call" method, is a - * subtype of a function type, and as such, a subtype of [Function]. - */ -abstract class Function { - /** - * Dynamically call [function] with the specified arguments. - * - * Acts the same as calling function with positional arguments - * corresponding to the elements of [positionalArguments] and - * named arguments corresponding to the elements of [namedArguments]. - * - * This includes giving the same errors if [function] isn't callable or - * if it expects different parameters. - * - * Example: - * Map namedArguments = new Map(); - * namedArguments[const Symbol("f")] = 4; - * namedArguments[const Symbol("g")] = 5; - * Function.apply(foo, [1,2,3], namedArguments); - * - * gives exactly the same result as - * foo(1, 2, 3, f: 4, g: 5). - * - * If [positionalArguments] is null, it's considered an empty list. - * If [namedArguments] is omitted or null, it is considered an empty map. - */ - static apply(Function f, - List positionalArguments, - [Map namedArguments]) { - // TODO(vsm): Handle named args. - // See: https://github.com/dart-lang/dev_compiler/issues/176 - return JS('', 'dart.dcall.apply(null, [#].concat(#))', f, positionalArguments); - } - - /** - * Returns a hash code value that is compatible with `operator==`. - */ - int get hashCode; - - /** - * Test whether another object is equal to this function. - * - * System-created function objects are only equal to other functions. - * - * Two function objects are known to represent the same function if - * - * - It is the same object. Static and top-level functions are compile time - * constants when used as values, so referring to the same function twice - * always give the same object, - * - or if they refer to the same member method extracted from the same object. - * Extracting a member method as a function value twice gives equal, but - * not necessarily identical, function values. - * - * Function expressions never give rise to equal function objects. Each time - * a function expression is evaluated, it creates a new closure value that - * is not known to be equal to other closures created by the same expression. - * - * Classes implementing `Function` by having a `call` method should have their - * own `operator==` and `hashCode` depending on the object. - */ - bool operator==(Object other); - - static Map _toMangledNames( - Map namedArguments) { - Map result = {}; - namedArguments.forEach((symbol, value) { - result[_symbolToString(symbol)] = value; - }); - return result; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/identical.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/identical.dart deleted file mode 100644 index 58543749bd7a..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/identical.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. - -part of dart.core; - -/** - * Check whether two references are to the same object. - */ -bool identical(Object a, Object b) { - return Primitives.identicalImplementation(a, b); -} - -/** - * Returns the identity hash code of `object`. - * - * Returns the same value as `object.hashCode` if [object] has not overridden - * [Object.hashCode]. Returns the value that [Object.hashCode] would return - * on this object, even if `hashCode` has been overridden. - * - * This hash code is compatible with [identical]. - */ -int identityHashCode(Object object) => objectHashCode(object); diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/int.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/int.dart deleted file mode 100644 index ca21390fbd17..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/int.dart +++ /dev/null @@ -1,283 +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. - -part of dart.core; - -/** - * An arbitrarily large integer. - * - * **Note:** When compiling to JavaScript, integers are - * implemented as JavaScript numbers. When compiling to JavaScript, - * integers are therefore restricted to 53 significant bits because - * all JavaScript numbers are double-precision floating point - * values. The behavior of the operators and methods in the [int] - * class therefore sometimes differs between the Dart VM and Dart code - * compiled to JavaScript. - * - * It is a compile-time error for a class to attempt to extend or implement int. - */ -abstract class int extends num { - /** - * Returns the integer value of the given environment declaration [name]. - * - * The result is the same as would be returned by: - * - * int.parse(const String.fromEnvironment(name, defaultValue: ""), - * (_) => defaultValue) - * - * Example: - * - * const int.fromEnvironment("defaultPort", defaultValue: 80) - */ - factory int.fromEnvironment(String name, {int defaultValue}) { - throw new UnsupportedError( - 'int.fromEnvironment can only be used as a const constructor'); - } - - /** - * Bit-wise and operator. - * - * Treating both `this` and [other] as sufficiently large two's component - * integers, the result is a number with only the bits set that are set in - * both `this` and [other] - * - * Of both operands are negative, the result is negative, otherwise - * the result is non-negative. - */ - int operator &(int other); - - /** - * Bit-wise or operator. - * - * Treating both `this` and [other] as sufficiently large two's component - * integers, the result is a number with the bits set that are set in either - * of `this` and [other] - * - * If both operands are non-negative, the result is non-negative, - * otherwise the result us negative. - */ - int operator |(int other); - - /** - * Bit-wise exclusive-or operator. - * - * Treating both `this` and [other] as sufficiently large two's component - * integers, the result is a number with the bits set that are set in one, - * but not both, of `this` and [other] - * - * If the operands have the same sign, the result is non-negative, - * otherwise the result is negative. - */ - int operator ^(int other); - - /** - * The bit-wise negate operator. - * - * Treating `this` as a sufficiently large two's component integer, - * the result is a number with the opposite bits set. - * - * This maps any integer `x` to `-x - 1`. - */ - int operator ~(); - - /** - * Shift the bits of this integer to the left by [shiftAmount]. - * - * Shifting to the left makes the number larger, effectively multiplying - * the number by `pow(2, shiftIndex)`. - * - * There is no limit on the size of the result. It may be relevant to - * limit intermediate values by using the "and" operator with a suitable - * mask. - * - * It is an error of [shiftAmount] is negative. - */ - int operator <<(int shiftAmount); - - /** - * Shift the bits of this integer to the right by [shiftAmount]. - * - * Shifting to the right makes the number smaller and drops the least - * significant bits, effectively doing an integer division by - *`pow(2, shiftIndex)`. - * - * It is an error of [shiftAmount] is negative. - */ - int operator >>(int shiftAmount); - - /** Returns true if and only if this integer is even. */ - bool get isEven; - - /** Returns true if and only if this integer is odd. */ - bool get isOdd; - - /** - * Returns the minimum number of bits required to store this integer. - * - * The number of bits excludes the sign bit, which gives the natural length - * for non-negative (unsigned) values. Negative values are complemented to - * return the bit position of the first bit that differs from the sign bit. - * - * To find the the number of bits needed to store the value as a signed value, - * add one, i.e. use `x.bitLength + 1`. - * - * x.bitLength == (-x-1).bitLength - * - * 3.bitLength == 2; // 00000011 - * 2.bitLength == 2; // 00000010 - * 1.bitLength == 1; // 00000001 - * 0.bitLength == 0; // 00000000 - * (-1).bitLength == 0; // 11111111 - * (-2).bitLength == 1; // 11111110 - * (-3).bitLength == 2; // 11111101 - * (-4).bitLength == 2; // 11111100 - */ - int get bitLength; - - /** - * Returns the least significant [width] bits of this integer as a - * non-negative number (i.e. unsigned representation). The returned value has - * zeros in all bit positions higher than [width]. - * - * (-1).toUnsigned(5) == 32 // 11111111 -> 00011111 - * - * This operation can be used to simulate arithmetic from low level languages. - * For example, to increment an 8 bit quantity: - * - * q = (q + 1).toUnsigned(8); - * - * `q` will count from `0` up to `255` and then wrap around to `0`. - * - * If the input fits in [width] bits without truncation, the result is the - * same as the input. The minimum width needed to avoid truncation of `x` is - * given by `x.bitLength`, i.e. - * - * x == x.toUnsigned(x.bitLength); - */ - int toUnsigned(int width); - - /** - * Returns the least significant [width] bits of this integer, extending the - * highest retained bit to the sign. This is the same as truncating the value - * to fit in [width] bits using an signed 2-s complement representation. The - * returned value has the same bit value in all positions higher than [width]. - * - * V--sign bit-V - * 16.toSigned(5) == -16 // 00010000 -> 11110000 - * 239.toSigned(5) == 15 // 11101111 -> 00001111 - * ^ ^ - * - * This operation can be used to simulate arithmetic from low level languages. - * For example, to increment an 8 bit signed quantity: - * - * q = (q + 1).toSigned(8); - * - * `q` will count from `0` up to `127`, wrap to `-128` and count back up to - * `127`. - * - * If the input value fits in [width] bits without truncation, the result is - * the same as the input. The minimum width needed to avoid truncation of `x` - * is `x.bitLength + 1`, i.e. - * - * x == x.toSigned(x.bitLength + 1); - */ - int toSigned(int width); - - /** - * Return the negative value of this integer. - * - * The result of negating an integer always has the opposite sign, except - * for zero, which is its own negation. - */ - int operator -(); - - /** - * Returns the absolute value of this integer. - * - * For any integer `x`, the result is the same as `x < 0 ? -x : x`. - */ - int abs(); - - /** - * Returns the sign of this integer. - * - * Returns 0 for zero, -1 for values less than zero and - * +1 for values greater than zero. - */ - int get sign; - - /** Returns `this`. */ - int round(); - - /** Returns `this`. */ - int floor(); - - /** Returns `this`. */ - int ceil(); - - /** Returns `this`. */ - int truncate(); - - /** Returns `this.toDouble()`. */ - double roundToDouble(); - - /** Returns `this.toDouble()`. */ - double floorToDouble(); - - /** Returns `this.toDouble()`. */ - double ceilToDouble(); - - /** Returns `this.toDouble()`. */ - double truncateToDouble(); - - /** - * Returns a String-representation of this integer. - * - * The returned string is parsable by [parse]. - * For any `int` [:i:], it is guaranteed that - * [:i == int.parse(i.toString()):]. - */ - String toString(); - - /** - * Converts [this] to a string representation in the given [radix]. - * - * In the string representation, lower-case letters are used for digits above - * '9'. - * - * The [radix] argument must be an integer in the range 2 to 36. - */ - String toRadixString(int radix); - - /** - * Parse [source] as an integer literal and return its value. - * - * The [radix] must be in the range 2..36. The digits used are - * 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 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 '+'). - * - * It must always be the case for an int [:n:] and radix [:r:] that - * [:n == int.parse(n.toRadixString(r), radix: r):]. - * - * If the [source] is not a valid integer literal, optionally prefixed by a - * sign, the [onError] is called with the [source] as argument, and its return - * value is used instead. If no [onError] is provided, a [FormatException] - * is thrown. - * - * The [onError] function is only invoked if [source] is a [String]. It is - * not invoked if the [source] is, for example, `null`. - */ - static int parse(String source, - { int radix, - int onError(String source) }) { - return Primitives.parseInt(source, radix, onError); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/invocation.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/invocation.dart deleted file mode 100644 index 7deaeecda002..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/invocation.dart +++ /dev/null @@ -1,52 +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. - -part of dart.core; - -/** - * Representation of the invocation of a member on an object. - * - * This is the type of objects passed to [Object.noSuchMethod] when - * an object doesn't support the member invocation that was attempted - * on it. - */ -abstract class Invocation { - /** The name of the invoked member. */ - Symbol get memberName; - - /** - * An unmodifiable view of the positional arguments of the call. - * - * If the member is a getter, the positional arguments is empty. - */ - List get positionalArguments; - - /** - * An unmodifiable view of the named arguments of the call. - * - * If the member is a getter, setter or operator, the named arguments - * is empty. - */ - Map get namedArguments; - - /** Whether the invocation was a method call. */ - bool get isMethod; - - /** - * Whether the invocation was a getter call. - * If so, both types of arguments is empty. - */ - bool get isGetter; - - /** - * Whether the invocation was a setter call. - * - * If so, [arguments] has exactly one positonal argument, - * and [namedArguments] is empty. - */ - bool get isSetter; - - /** Whether the invocation was a getter or a setter call. */ - bool get isAccessor => isGetter || isSetter; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/iterable.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/iterable.dart deleted file mode 100644 index 0a2df71f9de6..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/iterable.dart +++ /dev/null @@ -1,380 +0,0 @@ -// 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. - -part of dart.core; - -/** - * An object that uses an [Iterator] to serve objects one at a time. - * - * You can iterate over all objects served by an Iterable object - * using the for-in loop construct. - * For example, you can iterate over all of the keys in a [Map], - * because Map keys are iterable. - * - * Map kidsBooks = {'Matilda': 'Roald Dahl', - * 'Green Eggs and Ham': 'Dr Seuss', - * 'Where the Wild Things Are': 'Maurice Sendak'}; - * for (var book in kidsBooks.keys) { - * print('$book was written by ${kidsBooks[book]}'); - * } - * - * The [List] class and the [Set] class implement this interface, - * as do classes in the [dart:collection](#dart-collection) library. - * - * You can implement Iterable in your own class. - * If you do, then an instance of your Iterable class - * can be the right-hand side of a for-in construct. - * - * Some subclasss of [Iterable] can be modified. It is generally not allowed - * to modify such collections while they are being iterated. Doing so will break - * the iteration, which is typically signalled by throwing a - * [ConcurrentModificationError] when it is detected. - */ -@SupportJsExtensionMethods() -abstract class Iterable { - const Iterable(); - - /** - * Creates an Iterable that generates its elements dynamically. - * - * The Iterators created by the Iterable count from - * zero to [:count - 1:] while iterating, and call [generator] - * with that index to create the next value. - * - * If [generator] is omitted, it defaults to an identity function - * on integers `(int x) => x`, so it should only be omitted if the type - * parameter allows integer values. - * - * As an Iterable, [:new Iterable.generate(n, generator)):] is equivalent to - * [:const [0, ..., n - 1].map(generator):] - */ - factory Iterable.generate(int count, [E generator(int index)]) { - if (count <= 0) return new EmptyIterable(); - return new _GeneratorIterable(count, generator); - } - - /** - * Returns a new `Iterator` that allows iterating the elements of this - * `Iterable`. - * - * Modifying the underlying data after creating the new iterator - * may cause an error the next time [Iterator.moveNext] is called. - */ - Iterator get iterator; - - /** - * Returns a new lazy [Iterable] with elements that are created by - * calling `f` on the elements of this `Iterable`. - * - * This method returns a view of the mapped elements. As long as the - * returned [Iterable] is not iterated over, the supplied function [f] will - * not be invoked. The transformed elements will not be cached. Iterating - * multiple times over the the returned [Iterable] will invoke the supplied - * function [f] multiple times on the same element. - */ - Iterable map(f(E element)); - - /** - * Returns a new lazy [Iterable] with all elements that satisfy the - * predicate [test]. - * - * This method returns a view of the mapped elements. As long as the - * returned [Iterable] is not iterated over, the supplied function [test] will - * not be invoked. Iterating will not cache results, and thus iterating - * multiple times over the returned [Iterable] will invoke the supplied - * function [test] multiple times on the same element. - */ - Iterable where(bool test(E element)); - - /** - * Expands each element of this [Iterable] into zero or more elements. - * - * The resulting Iterable runs through the elements returned - * by [f] for each element of this, in order. - * - * The returned [Iterable] is lazy, and calls [f] for each element - * of this every time it's iterated. - */ - Iterable expand(Iterable f(E element)); - - /** - * Returns true if the collection contains an element equal to [element]. - * - * The equality used to determine whether [element] is equal to an element of - * the iterable, depends on the type of iterable. - * For example, a [Set] may have a custom equality - * (see, e.g., [Set.identical]) that its `contains` uses. - * Likewise the `Iterable` returned by a [Map.keys] call - * will likely use the same equality that the `Map` uses for keys. - */ - bool contains(Object element); - - /** - * Applies the function [f] to each element of this collection. - */ - void forEach(void f(E element)); - - /** - * Reduces a collection to a single value by iteratively combining elements - * of the collection using the provided function. - * - * Example of calculating the sum of an iterable: - * - * iterable.reduce((value, element) => value + element); - * - */ - E reduce(E combine(E value, E element)); - - /** - * Reduces a collection to a single value by iteratively combining each - * element of the collection with an existing value using the provided - * function. - * - * Use [initialValue] as the initial value, and the function [combine] to - * create a new value from the previous one and an element. - * - * Example of calculating the sum of an iterable: - * - * iterable.fold(0, (prev, element) => prev + element); - * - */ - dynamic fold(var initialValue, - dynamic combine(var previousValue, E element)); - - /** - * Returns true if every elements of this collection satisify the - * predicate [test]. Returns `false` otherwise. - */ - bool every(bool test(E element)); - - /** - * Converts each element to a [String] and concatenates the strings. - * - * Converts each element to a [String] by calling [Object.toString] on it. - * Then concatenates the strings, optionally separated by the [separator] - * string. - */ - String join([String separator = ""]) { - StringBuffer buffer = new StringBuffer(); - buffer.writeAll(this, separator); - return buffer.toString(); - } - - /** - * Returns true if one element of this collection satisfies the - * predicate [test]. Returns false otherwise. - */ - bool any(bool test(E element)); - - /** - * Creates a [List] containing the elements of this [Iterable]. - * - * The elements are in iteration order. The list is fixed-length - * if [growable] is false. - */ - List toList({ bool growable: true }); - - /** - * Creates a [Set] containing the same elements as this iterable. - * - * The set may contain fewer elements than the iterable, - * if the iterable contains the an element more than once, - * or it contains one or more elements that are equal. - * The order of the elements in the set is not guaranteed to be the same - * as for the iterable. - */ - Set toSet(); - - /** - * Returns the number of elements in [this]. - * - * Counting all elements may be involve running through all elements and can - * therefore be slow. - */ - int get length; - - /** - * Returns true if there is no element in this collection. - */ - bool get isEmpty; - - /** - * Returns true if there is at least one element in this collection. - */ - bool get isNotEmpty; - - /** - * Returns an [Iterable] with at most [count] elements. - * - * The returned `Iterable` may contain fewer than `count` elements, if `this` - * contains fewer than `count` elements. - * - * It is an error if `count` is negative. - */ - Iterable take(int count); - - /** - * Returns an Iterable that stops once [test] is not satisfied anymore. - * - * The filtering happens lazily. Every new Iterator of the returned - * Iterable starts iterating over the elements of `this`. - * - * When the iterator encounters an element `e` that does not satisfy [test], - * it discards `e` and moves into the finished state. That is, it does not - * get or provide any more elements. - */ - Iterable takeWhile(bool test(E value)); - - /** - * Returns an Iterable that skips the first [count] elements. - * - * If `this` has fewer than `count` elements, then the resulting Iterable is - * empty. - * - * It is an error if `count` is negative. - */ - Iterable skip(int count); - - /** - * Returns an Iterable that skips elements while [test] is satisfied. - * - * The filtering happens lazily. Every new Iterator of the returned - * Iterable iterates over all elements of `this`. - * - * As long as the iterator's elements satisfy [test] they are - * discarded. Once an element does not satisfy the [test] the iterator stops - * testing and uses every later element unconditionally. That is, the elements - * of the returned Iterable are the elements of `this` starting from the - * first element that does not satisfy [test]. - */ - Iterable skipWhile(bool test(E value)); - - /** - * Returns the first element. - * - * If `this` is empty throws a [StateError]. Otherwise this method is - * equivalent to [:this.elementAt(0):] - */ - E get first; - - /** - * Returns the last element. - * - * If `this` is empty throws a [StateError]. - */ - E get last; - - /** - * Returns the single element in `this`. - * - * If `this` is empty or has more than one element throws a [StateError]. - */ - E get single; - - /** - * Returns the first element that satisfies the given predicate [test]. - * - * If none matches, the result of invoking the [orElse] function is - * returned. By default, when [orElse] is `null`, a [StateError] is - * thrown. - */ - E firstWhere(bool test(E element), { E orElse() }); - - /** - * Returns the last element that satisfies the given predicate [test]. - * - * If none matches, the result of invoking the [orElse] function is - * returned. By default, when [orElse] is `null`, a [StateError] is - * thrown. - */ - E lastWhere(bool test(E element), {E orElse()}); - - /** - * Returns the single element that satisfies [test]. If no or more than one - * element match then a [StateError] is thrown. - */ - E singleWhere(bool test(E element)); - - /** - * Returns the [index]th element. - * - * The [index] must be non-negative and less than [length]. - * - * Note: if `this` does not have a deterministic iteration order then the - * function may simply return any element without any iteration if there are - * at least [index] elements in `this`. - */ - E elementAt(int index); -} - -typedef E _Generator(int index); - -class _GeneratorIterable extends IterableBase - implements EfficientLength { - final int _start; - final int _end; - final _Generator _generator; - _GeneratorIterable(this._end, E generator(int n)) - : _start = 0, - _generator = (generator != null) ? generator : _id; - - _GeneratorIterable.slice(this._start, this._end, this._generator); - - Iterator get iterator => - new _GeneratorIterator(_start, _end, _generator); - int get length => _end - _start; - - Iterable skip(int count) { - RangeError.checkNotNegative(count, "count"); - if (count == 0) return this; - int newStart = _start + count; - if (newStart >= _end) return new EmptyIterable(); - return new _GeneratorIterable.slice(newStart, _end, _generator); - } - - Iterable take(int count) { - RangeError.checkNotNegative(count, "count"); - if (count == 0) return new EmptyIterable(); - int newEnd = _start + count; - if (newEnd >= _end) return this; - return new _GeneratorIterable.slice(_start, newEnd, _generator); - } - - static int _id(int n) => n; -} - -class _GeneratorIterator implements Iterator { - final int _end; - final _Generator _generator; - int _index; - E _current; - - _GeneratorIterator(this._index, this._end, this._generator); - - bool moveNext() { - if (_index < _end) { - _current = _generator(_index); - _index++; - return true; - } else { - _current = null; - return false; - } - } - - E get current => _current; -} - -/** - * An Iterator that allows moving backwards as well as forwards. - */ -abstract class BidirectionalIterator implements Iterator { - /** - * Move back to the previous element. - * - * Returns true and updates [current] if successful. Returns false - * and sets [current] to null if there is no previous element. - */ - bool movePrevious(); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/iterator.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/iterator.dart deleted file mode 100644 index ed7aca9b67a1..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/iterator.dart +++ /dev/null @@ -1,51 +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. - -part of dart.core; - -/** - * An interface for getting items, one at a time, from an object. - * - * The for-in construct transparently uses Iterator to test for the end - * of the iteration, and to get each item (or _element_). - * - * If the object iterated over is changed during the iteration, the - * behavior is unspecified. - * - * The Iterator is initially positioned before the first element. Before - * accessing the first element the iterator must thus be advanced ([moveNext]) - * to point to the first element. If no element is left, then [moveNext] - * returns false. - * - * A typical usage of an Iterator looks as follows: - * - * var it = obj.iterator; - * while (it.moveNext()) { - * use(it.current); - * } - * - * **See also:** [Iteration] - * (http://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html#ch03-iteration) - * in the [library tour] - * (http://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html) - */ -abstract class Iterator { - /** - * Moves to the next element. Returns true if [current] contains the next - * element. Returns false, if no element was left. - * - * It is safe to invoke [moveNext] even when the iterator is already - * positioned after the last element. In this case [moveNext] has no effect. - */ - bool moveNext(); - - /** - * Returns the current element. - * - * Return [:null:] if the iterator has not yet been moved to the first - * element, or if the iterator has been moved after the last element of the - * [Iterable]. - */ - E get current; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/list.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/list.dart deleted file mode 100644 index c693ba1f05b9..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/list.dart +++ /dev/null @@ -1,748 +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. - -part of dart.core; - -/** - * An indexable collection of objects with a length. - * - * Subclasses of this class implement different kinds of lists. - * The most common kinds of lists are: - * - * * Fixed-length list. - * An error occurs when attempting to use operations - * that can change the length of the list. - * - * * Growable list. Full implementation of the API defined in this class. - * - * The default growable list, as returned by `new List()` or `[]`, keeps - * an internal buffer, and grows that buffer when necessary. This guarantees - * that a sequence of [add] operations will each execute in amortized constant - * time. Setting the length directly may take time proportional to the new - * length, and may change the internal capacity so that a following add - * operation will need to immediately increase the buffer capacity. - * Other list implementations may have different performance behavior. - * - * The following code illustrates that some List implementations support - * only a subset of the API. - * - * List fixedLengthList = new List(5); - * fixedLengthList.length = 0; // Error - * fixedLengthList.add(499); // Error - * fixedLengthList[0] = 87; - * List growableList = [1, 2]; - * growableList.length = 0; - * growableList.add(499); - * growableList[0] = 87; - * - * Lists are [Iterable]. Iteration occurs over values in index order. Changing - * the values does not affect iteration, but changing the valid - * indices—that is, changing the list's length—between iteration - * steps causes a [ConcurrentModificationError]. This means that only growable - * lists can throw ConcurrentModificationError. If the length changes - * temporarily and is restored before continuing the iteration, the iterator - * does not detect it. - * - * It is generally not allowed to modify the list's length (adding or removing - * elements) while an operation on the list is being performed, - * for example during a call to [forEach] or [sort]. - * Changing the list's length while it is being iterated, either by iterating it - * directly or through iterating an [Iterable] that is backed by the list, will - * break the iteration. - */ -@SupportJsExtensionMethod() -@JsPeerInterface(name: 'Array') -abstract class List implements Iterable, EfficientLength { - /** - * Creates a list of the given length. - * - * The created list is fixed-length if [length] is provided. - * - * List fixedLengthList = new List(3); - * fixedLengthList.length; // 3 - * fixedLengthList.length = 1; // Error - * - * The list has length 0 and is growable if [length] is omitted. - * - * List growableList = new List(); - * growableList.length; // 0; - * growableList.length = 3; - * - * To create a growable list with a given length, just assign the length - * right after creation: - * - * List growableList = new List()..length = 500; - * - * The [length] must not be negative or null, if it is provided. - */ - factory List([int length]) { - dynamic list; - if (length == null) { - list = JS('', '[]'); - } else { - // Explicit type test is necessary to guard against JavaScript conversions - // in unchecked mode. - if ((length is !int) || (length < 0)) { - throw new ArgumentError("Length must be a non-negative integer: $length"); - } - list = JS('', 'new Array(#)', length); - // TODO(jmesserly): consider a fixed array subclass instead. - JS('void', r'#.fixed$length = Array', list); - } - // TODO(jmesserly): skip this when E is dynamic and Object. - JS('void', 'dart.setType(#, List\$(#))', list, E); - // TODO(jmesserly): compiler creates a bogus type check here. - return list; - } - - /** - * Creates a fixed-length list of the given length, and initializes the - * value at each position with [fill]: - * - * new List.filled(3, 0); // [0, 0, 0] - * - * The [length] must not be negative or null. - */ - factory List.filled(int length, E fill) { - List result = new List(length); - if (length != 0 && fill != null) { - for (int i = 0; i < result.length; i++) { - result[i] = fill; - } - } - return result; - } - - /** - * Creates a list containing all [elements]. - * - * The [Iterator] of [elements] provides the order of the elements. - * - * This constructor returns a growable list when [growable] is true; - * otherwise, it returns a fixed-length list. - */ - factory List.from(Iterable elements, { bool growable: true }) { - List list = new List(); - for (var e in elements) { - list.add(e); - } - if (growable) return list; - return makeListFixedLength(list); - } - - /** - * Generates a list of values. - * - * Creates a list with [length] positions and fills it with values created by - * calling [generator] for each index in the range `0` .. `length - 1` - * in increasing order. - * - * new List.generate(3, (int index) => index * index); // [0, 1, 4] - * - * The created list is fixed-length unless [growable] is true. - */ - factory List.generate(int length, E generator(int index), - { bool growable: true }) { - List result; - if (growable) { - result = []..length = length; - } else { - result = new List(length); - } - for (int i = 0; i < length; i++) { - result[i] = generator(i); - } - return result; - } - - checkMutable(reason) { - /* TODO(jacobr): implement. - if (this is !JSMutableArray) { - throw new UnsupportedError(reason); - } - * */ - } - - checkGrowable(reason) { - /* TODO(jacobr): implement - if (this is !JSExtendableArray) { - throw new UnsupportedError(reason); - } - * */ - } - - Iterable where(bool f(E element)) { - return new IterableMixinWorkaround().where(this, f); - } - - Iterable expand(Iterable f(E element)) { - return IterableMixinWorkaround.expand(this, f); - } - - void forEach(void f(E element)) { - int length = this.length; - for (int i = 0; i < length; i++) { - f(JS('', '#[#]', this, i)); - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - } - - Iterable map(f(E element)) { - return IterableMixinWorkaround.mapList(this, f); - } - - String join([String separator = ""]) { - var list = new List(this.length); - for (int i = 0; i < this.length; i++) { - list[i] = "${this[i]}"; - } - return JS('String', "#.join(#)", list, separator); - } - - Iterable take(int n) { - return new IterableMixinWorkaround().takeList(this, n); - } - - Iterable takeWhile(bool test(E value)) { - return new IterableMixinWorkaround().takeWhile(this, test); - } - - Iterable skip(int n) { - return new IterableMixinWorkaround().skipList(this, n); - } - - Iterable skipWhile(bool test(E value)) { - return new IterableMixinWorkaround().skipWhile(this, test); - } - - E reduce(E combine(E value, E element)) { - return IterableMixinWorkaround.reduce(this, combine); - } - - fold(initialValue, combine(previousValue, E element)) { - return IterableMixinWorkaround.fold(this, initialValue, combine); - } - - E firstWhere(bool test(E value), {E orElse()}) { - return IterableMixinWorkaround.firstWhere(this, test, orElse); - } - - E lastWhere(bool test(E value), {E orElse()}) { - return IterableMixinWorkaround.lastWhereList(this, test, orElse); - } - - E singleWhere(bool test(E value)) { - return IterableMixinWorkaround.singleWhere(this, test); - } - - E elementAt(int index) { - return this[index]; - } - - E get first { - if (length > 0) return this[0]; - throw new StateError("No elements"); - } - - E get last { - if (length > 0) return this[length - 1]; - throw new StateError("No elements"); - } - - E get single { - if (length == 1) return this[0]; - if (length == 0) throw new StateError("No elements"); - throw new StateError("More than one element"); - } - - bool any(bool f(E element)) => IterableMixinWorkaround.any(this, f); - - bool every(bool f(E element)) => IterableMixinWorkaround.every(this, f); - - bool contains(Object other) { - for (int i = 0; i < length; i++) { - if (this[i] == other) return true; - } - return false; - } - - bool get isEmpty => length == 0; - - bool get isNotEmpty => !isEmpty; - - String toString() => ListBase.listToString(this); - - List toList({ bool growable: true }) { - // TODO(vsm): Enforce growable / non-growable. - // See: https://github.com/dart-lang/dev_compiler/issues/175 - return JS('', 'dart.setType(#.slice(), core.List\$(#))', this, E); - } - - Set toSet() => new Set.from(this); - - Iterator get iterator => new ListIterator(this); - - int get hashCode => Primitives.objectHashCode(this); - - // BORDER XXXX - - /** - * Returns the object at the given [index] in the list - * or throws a [RangeError] if [index] is out of bounds. - */ - E operator [](int index) { - if (index is !int) throw new ArgumentError(index); - if (index >= length || index < 0) throw new RangeError.value(index); - return JS('var', '#[#]', this, index); - } - - /** - * Sets the value at the given [index] in the list to [value] - * or throws a [RangeError] if [index] is out of bounds. - */ - void operator []=(int index, E value) { - checkMutable('indexed set'); - if (index is !int) throw new ArgumentError(index); - if (index >= length || index < 0) throw new RangeError.value(index); - JS('void', r'#[#] = #', this, index, value); - } - - /** - * Returns the number of objects in this list. - * - * The valid indices for a list are `0` through `length - 1`. - */ - int get length => JS('JSUInt32', r'#.length', this); - - /** - * Changes the length of this list. - * - * If [newLength] is greater than - * the current length, entries are initialized to [:null:]. - * - * Throws an [UnsupportedError] if the list is fixed-length. - */ - void set length(int newLength) { - if (newLength is !int) throw new ArgumentError(newLength); - if (newLength < 0) throw new RangeError.value(newLength); - checkGrowable('set length'); - JS('void', r'#.length = #', this, newLength); - } - - /** - * Adds [value] to the end of this list, - * extending the length by one. - * - * Throws an [UnsupportedError] if the list is fixed-length. - */ - void add(E value) { - checkGrowable('add'); - JS('void', r'#.push(#)', this, value); - } - - /** - * Appends all objects of [iterable] to the end of this list. - * - * Extends the length of the list by the number of objects in [iterable]. - * Throws an [UnsupportedError] if this list is fixed-length. - */ - void addAll(Iterable iterable) { - for (E e in iterable) { - this.add(e); - } - } - - /** - * Returns an [Iterable] of the objects in this list in reverse order. - */ - Iterable get reversed => - new IterableMixinWorkaround().reversedList(this); - - /** - * Sorts this list according to the order specified by the [compare] function. - * - * The [compare] function must act as a [Comparator]. - - * List numbers = ['one', 'two', 'three', 'four']; - * // Sort from shortest to longest. - * numbers.sort((x, y) => x.length.compareTo(y.length)); - * numbers.join(', '); // 'one, two, four, three' - * - * The default List implementations use [Comparable.compare] if - * [compare] is omitted. - * - * List nums = [13, 2, -11]; - * nums.sort(); - nums.join(', '); // '-11, 2, 13' - */ - void sort([int compare(E a, E b)]) { - checkMutable('sort'); - IterableMixinWorkaround.sortList(this, compare); - } - - /** - * Shuffles the elements of this list randomly. - */ - void shuffle([Random random]) { - IterableMixinWorkaround.shuffleList(this, random); - } - - /** - * Returns the first index of [element] in this list. - * - * Searches the list from index [start] to the end of the list. - * The first time an object [:o:] is encountered so that [:o == element:], - * the index of [:o:] is returned. - * - * List notes = ['do', 're', 'mi', 're']; - * notes.indexOf('re'); // 1 - * notes.indexOf('re', 2); // 3 - * - * Returns -1 if [element] is not found. - * - * notes.indexOf('fa'); // -1 - */ - int indexOf(E element, [int start = 0]) { - return IterableMixinWorkaround.indexOfList(this, element, start); - } - - /** - * Returns the last index of [element] in this list. - * - * Searches the list backwards from index [start] to 0. - * - * The first time an object [:o:] is encountered so that [:o == element:], - * the index of [:o:] is returned. - * - * List notes = ['do', 're', 'mi', 're']; - * notes.lastIndexOf('re', 2); // 1 - * - * If [start] is not provided, this method searches from the end of the - * list./Returns - * - * notes.lastIndexOf('re'); // 3 - * - * Returns -1 if [element] is not found. - * - * notes.lastIndexOf('fa'); // -1 - */ - int lastIndexOf(E element, [int start]) { - return IterableMixinWorkaround.lastIndexOfList(this, element, start); - } - - /** - * Removes all objects from this list; - * the length of the list becomes zero. - * - * Throws an [UnsupportedError], and retains all objects, if this - * is a fixed-length list. - */ - void clear() { - length = 0; - } - - /** - * Inserts the object at position [index] in this list. - * - * This increases the length of the list by one and shifts all objects - * at or after the index towards the end of the list. - * - * An error occurs if the [index] is less than 0 or greater than length. - * An [UnsupportedError] occurs if the list is fixed-length. - */ - void insert(int index, E element) { - if (index is !int) throw new ArgumentError(index); - if (index < 0 || index > length) { - throw new RangeError.value(index); - } - checkGrowable('insert'); - JS('void', r'#.splice(#, 0, #)', this, index, element); - } - - - /** - * Inserts all objects of [iterable] at position [index] in this list. - * - * This increases the length of the list by the length of [iterable] and - * shifts all later objects towards the end of the list. - * - * An error occurs if the [index] is less than 0 or greater than length. - * An [UnsupportedError] occurs if the list is fixed-length. - */ - void insertAll(int index, Iterable iterable) { - checkGrowable('insertAll'); - IterableMixinWorkaround.insertAllList(this, index, iterable); - } - - /** - * Overwrites objects of `this` with the objects of [iterable], starting - * at position [index] in this list. - * - * List list = ['a', 'b', 'c']; - * list.setAll(1, ['bee', 'sea']); - * list.join(', '); // 'a, bee, sea' - * - * This operation does not increase the length of `this`. - * - * The [index] must be non-negative and no greater than [length]. - * - * The [iterable] must not have more elements than what can fit from [index] - * to [length]. - * - * If `iterable` is based on this list, its values may change /during/ the - * `setAll` operation. - */ - void setAll(int index, Iterable iterable) { - checkMutable('setAll'); - IterableMixinWorkaround.setAllList(this, index, iterable); - } - - /** - * Removes the first occurence of [value] from this list. - * - * Returns true if [value] was in the list, false otherwise. - * - * List parts = ['head', 'shoulders', 'knees', 'toes']; - * parts.remove('head'); // true - * parts.join(', '); // 'shoulders, knees, toes' - * - * The method has no effect if [value] was not in the list. - * - * // Note: 'head' has already been removed. - * parts.remove('head'); // false - * parts.join(', '); // 'shoulders, knees, toes' - * - * An [UnsupportedError] occurs if the list is fixed-length. - */ - bool remove(Object element) { - checkGrowable('remove'); - for (int i = 0; i < this.length; i++) { - if (this[i] == value) { - JS('var', r'#.splice(#, 1)', this, i); - return true; - } - } - return false; - } - - /** - * Removes the object at position [index] from this list. - * - * This method reduces the length of `this` by one and moves all later objects - * down by one position. - * - * Returns the removed object. - * - * The [index] must be in the range `0 ≤ index < length`. - * - * Throws an [UnsupportedError] if this is a fixed-length list. In that case - * the list is not modified. - */ - E removeAt(int index) { - if (index is !int) throw new ArgumentError(index); - if (index < 0 || index >= length) { - throw new RangeError.value(index); - } - checkGrowable('removeAt'); - return JS('var', r'#.splice(#, 1)[0]', this, index); - } - - /** - * Pops and returns the last object in this list. - * - * Throws an [UnsupportedError] if this is a fixed-length list. - */ - E removeLast() { - checkGrowable('removeLast'); - if (length == 0) throw new RangeError.value(-1); - return JS('var', r'#.pop()', this); - } - - /** - * Removes all objects from this list that satisfy [test]. - * - * An object [:o:] satisfies [test] if [:test(o):] is true. - * - * List numbers = ['one', 'two', 'three', 'four']; - * numbers.removeWhere((item) => item.length == 3); - * numbers.join(', '); // 'three, four' - * - * Throws an [UnsupportedError] if this is a fixed-length list. - */ - void removeWhere(bool test(E element)) { - // This could, and should, be optimized. - IterableMixinWorkaround.removeWhereList(this, test); - } - - - /** - * Removes all objects from this list that fail to satisfy [test]. - * - * An object [:o:] satisfies [test] if [:test(o):] is true. - * - * List numbers = ['one', 'two', 'three', 'four']; - * numbers.retainWhere((item) => item.length == 3); - * numbers.join(', '); // 'one, two' - * - * Throws an [UnsupportedError] if this is a fixed-length list. - */ - void retainWhere(bool test(E element)) { - IterableMixinWorkaround.removeWhereList(this, - (E element) => !test(element)); - } - - /** - * Returns a new list containing the objects from [start] inclusive to [end] - * exclusive. - * - * List colors = ['red', 'green', 'blue', 'orange', 'pink']; - * colors.sublist(1, 3); // ['green', 'blue'] - * - * If [end] is omitted, the [length] of `this` is used. - * - * colors.sublist(1); // ['green', 'blue', 'orange', 'pink'] - * - * An error occurs if [start] is outside the range `0` .. `length` or if - * [end] is outside the range `start` .. `length`. - */ - List sublist(int start, [int end]) { - checkNull(start); // TODO(ahe): This is not specified but co19 tests it. - if (start is !int) throw new ArgumentError(start); - if (start < 0 || start > length) { - throw new RangeError.range(start, 0, length); - } - if (end == null) { - end = length; - } else { - if (end is !int) throw new ArgumentError(end); - if (end < start || end > length) { - throw new RangeError.range(end, start, length); - } - } - if (start == end) return []; - return new JSArray.markGrowable( - JS('', r'#.slice(#, #)', this, start, end)); - } - - /** - * Returns an [Iterable] that iterates over the objects in the range - * [start] inclusive to [end] exclusive. - * - * An error occurs if [end] is before [start]. - * - * An error occurs if the [start] and [end] are not valid ranges at the time - * of the call to this method. The returned [Iterable] behaves like - * `skip(start).take(end - start)`. That is, it does not throw exceptions - * if `this` changes size. - * - * List colors = ['red', 'green', 'blue', 'orange', 'pink']; - * Iterable range = colors.getRange(1, 4); - * range.join(', '); // 'green, blue, orange' - * colors.length = 3; - * range.join(', '); // 'green, blue' - */ - Iterable getRange(int start, int end) { - return new IterableMixinWorkaround().getRangeList(this, start, end); - } - - - /** - * Copies the objects of [iterable], skipping [skipCount] objects first, - * into the range [start], inclusive, to [end], exclusive, of the list. - * - * List list1 = [1, 2, 3, 4]; - * List list2 = [5, 6, 7, 8, 9]; - * // Copies the 4th and 5th items in list2 as the 2nd and 3rd items - * // of list1. - * list1.setRange(1, 3, list2, 3); - * list1.join(', '); // '1, 8, 9, 4' - * - * The [start] and [end] indices must satisfy `0 ≤ start ≤ end ≤ length`. - * If [start] equals [end], this method has no effect. - * - * The [iterable] must have enough objects to fill the range from `start` - * to `end` after skipping [skipCount] objects. - * - * If `iterable` is this list, the operation will copy the elements originally - * in the range from `skipCount` to `skipCount + (end - start)` to the - * range `start` to `end`, even if the two ranges overlap. - * - * If `iterable` depends on this list in some other way, no guarantees are - * made. - */ - void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { - checkMutable('set range'); - IterableMixinWorkaround.setRangeList(this, start, end, iterable, skipCount); - } - - /** - * Removes the objects in the range [start] inclusive to [end] exclusive. - * - * The [start] and [end] indices must be in the range - * `0 ≤ index ≤ length`, and `start ≤ end`. - * - * Throws an [UnsupportedError] if this is a fixed-length list. In that case - * the list is not modified. - */ - void removeRange(int start, int end) { - checkGrowable('removeRange'); - int receiverLength = this.length; - if (start < 0 || start > receiverLength) { - throw new RangeError.range(start, 0, receiverLength); - } - if (end < start || end > receiverLength) { - throw new RangeError.range(end, start, receiverLength); - } - Lists.copy(this, - end, - this, - start, - receiverLength - end); - this.length = receiverLength - (end - start); - } - - /** - * Sets the objects in the range [start] inclusive to [end] exclusive - * to the given [fillValue]. - * - * An error occurs if [start]..[end] is not a valid range for `this`. - */ - void fillRange(int start, int end, [E fillValue]) { - checkMutable('fill range'); - IterableMixinWorkaround.fillRangeList(this, start, end, fillValue); - } - - /** - * Removes the objects in the range [start] inclusive to [end] exclusive - * and inserts the contents of [replacement] in its place. - * - * List list = [1, 2, 3, 4, 5]; - * list.replaceRange(1, 4, [6, 7]); - * list.join(', '); // '1, 6, 7, 5' - * - * An error occurs if [start]..[end] is not a valid range for `this`. - */ - void replaceRange(int start, int end, Iterable replacement) { - checkGrowable('removeRange'); - IterableMixinWorkaround.replaceRangeList(this, start, end, replacement); - } - - /** - * Returns an unmodifiable [Map] view of `this`. - * - * The map uses the indices of this list as keys and the corresponding objects - * as values. The `Map.keys` [Iterable] iterates the indices of this list - * in numerical order. - * - * List words = ['fee', 'fi', 'fo', 'fum']; - * Map map = words.asMap(); - * map[0] + map[1]; // 'feefi'; - * map.keys.toList(); // [0, 1, 2, 3] - */ - Map asMap() { - return new IterableMixinWorkaround().asMapList(this); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/map.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/map.dart deleted file mode 100644 index c011a2044a5a..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/map.dart +++ /dev/null @@ -1,254 +0,0 @@ -// 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. - -part of dart.core; - -/** - * An collection of key-value pairs, from which you retrieve a value - * using its associated key. - * - * There is a finite number of keys in the map, - * and each key has exactly one value associated with it. - * - * Maps, and their keys and values, can be iterated. - * The order of iteration is defined by the individual type of map. - * Examples: - * - * * The plain [HashMap] is unordered (no order is guaranteed), - * * the [LinkedHashMap] iterates in key insertion order, - * * and a sorted map like [SplayTreeMap] iterates the keys in sorted order. - * - * It is generally not allowed to modify the map (add or remove keys) while - * an operation is being performed on the map, for example in functions called - * during a [forEach] or [putIfAbsent] call. - * Modifying the map while iterating the keys or values - * may also break the iteration. - */ -abstract class Map { - /** - * Creates a Map instance with the default implementation, [LinkedHashMap]. - * - * This constructor is equivalent to the non-const map literal `{}`. - * - * A `LinkedHashMap` requires the keys to implement compatible - * `operator==` and `hashCode`, and it allows null as a key. - * It iterates in key insertion order. - */ - factory Map() = LinkedHashMap; - - /** - * Creates a [LinkedHashMap] instance that contains all key-value pairs of - * [other]. - * - * The keys must all be assignable to [K] and the values to [V]. - * The [other] map itself can have any type. - * - * A `LinkedHashMap` requires the keys to implement compatible - * `operator==` and `hashCode`, and it allows null as a key. - * It iterates in key insertion order. - */ - factory Map.from(Map other) = LinkedHashMap.from; - - /** - * Creates an identity map with the default implementation, [LinkedHashMap]. - * - * The returned map allows `null` as a key. - * It iterates in key insertion order. - */ - factory Map.identity() = LinkedHashMap.identity; - - /** - * Creates a Map instance in which the keys and values are computed from the - * [iterable]. - * - * The created map is a [LinkedHashMap]. - * A `LinkedHashMap` requires the keys to implement compatible - * `operator==` and `hashCode`, and it allows null as a key. - * It iterates in key insertion order. - * - * For each element of the [iterable] this constructor computes a key-value - * pair, by applying [key] and [value] respectively. - * - * The example below creates a new Map from a List. The keys of `map` are - * `list` values converted to strings, and the values of the `map` are the - * squares of the `list` values: - * - * List list = [1, 2, 3]; - * Map map = new Map.fromIterable(list, - * key: (item) => item.toString(), - * value: (item) => item * item)); - * - * map['1'] + map['2']; // 1 + 4 - * map['3'] - map['2']; // 9 - 4 - * - * If no values are specified for [key] and [value] the default is the - * identity function. - * - * In the following example, the keys and corresponding values of `map` - * are `list` values: - * - * map = new Map.fromIterable(list); - * map[1] + map[2]; // 1 + 2 - * map[3] - map[2]; // 3 - 2 - * - * The keys computed by the source [iterable] do not need to be unique. The - * last occurrence of a key will simply overwrite any previous value. - */ - factory Map.fromIterable(Iterable iterable, - {K key(element), V value(element)}) = LinkedHashMap.fromIterable; - - /** - * Creates a Map instance associating the given [keys] to [values]. - * - * The created map is a [LinkedHashMap]. - * A `LinkedHashMap` requires the keys to implement compatible - * `operator==` and `hashCode`, and it allows null as a key. - * It iterates in key insertion order. - * - * This constructor iterates over [keys] and [values] and maps each element of - * [keys] to the corresponding element of [values]. - * - * List letters = ['b', 'c']; - * List words = ['bad', 'cat']; - * Map map = new Map.fromIterables(letters, words); - * map['b'] + map['c']; // badcat - * - * If [keys] contains the same object multiple times, the last occurrence - * overwrites the previous value. - * - * The two [Iterable]s must have the same length. - */ - factory Map.fromIterables(Iterable keys, Iterable values) - = LinkedHashMap.fromIterables; - - /** - * Returns true if this map contains the given [value]. - * - * Returns true if any of the values in the map are equal to `value` - * according to the `==` operator. - */ - bool containsValue(Object value); - - /** - * Returns true if this map contains the given [key]. - * - * Returns true if any of the keys in the map ar equal to `key` - * according to the equality used by the map. - */ - bool containsKey(Object key); - - /** - * Returns the value for the given [key] or null if [key] is not in the map. - * - * Some maps allows keys to have `null` as a value, - * For those maps, a lookup using this operator does cannot be used to - * distinguish between a key not being in the map, and the key having a null - * value. - * Methods like [containsKey] or [putIfAbsent] can be use if the distinction - * is important. - */ - V operator [](Object key); - - /** - * Associates the [key] with the given [value]. - * - * If the key was already in the map, its associated value is changed. - * Otherwise the key-value pair is added to the map. - */ - void operator []=(K key, V value); - - /** - * Look up the value of [key], or add a new value if it isn't there. - * - * Returns the value associated to [key], if there is one. - * Otherwise calls [ifAbsent] to get a new value, associates [key] to - * that value, and then returns the new value. - * - * Map scores = {'Bob': 36}; - * for (var key in ['Bob', 'Rohan', 'Sophena']) { - * scores.putIfAbsent(key, () => key.length); - * } - * scores['Bob']; // 36 - * scores['Rohan']; // 5 - * scores['Sophena']; // 7 - * - * Calling [ifAbsent] must not add or remove keys from the map. - */ - V putIfAbsent(K key, V ifAbsent()); - - /** - * Adds all key-value pairs of [other] to this map. - * - * If a key of [other] is already in this map, its value is overwritten. - * - * The operation is equivalent to doing `this[key] = value` for each key - * and associated value in other. It iterates over [other], which must - * therefore not change during the iteration. - */ - void addAll(Map other); - - /** - * Removes [key] and its associated value, if present, from the map. - * - * Returns the value associated with `key` before it was removed. - * Returns `null` if `key` was not in the map. - * - * Note that values can be `null` and a returned `null` value doesn't - * always mean that the key was absent. - */ - V remove(Object key); - - /** - * Removes all pairs from the map. - * - * After this, the map is empty. - */ - void clear(); - - /** - * Applies [f] to each key-value pair of the map. - * - * Calling `f` must not add or remove keys from the map. - */ - void forEach(void f(K key, V value)); - - /** - * The keys of [this]. - * - * The returned iterable has efficient `length` and `contains` operations, - * based on [length] and [containsKey] of the map. - * - * The order of iteration is defined by the individual `Map` implementation, - * but must be consistent between changes to the map. - */ - Iterable get keys; - - /** - * The values of [this]. - * - * The values are iterated in the order of their corresponding keys. - * This means that iterating [keys] and [values] in parrallel will - * provided matching pairs of keys and values. - * - * The returned iterable has an efficient `length` method based on the - * [length] of the map. Its [Iterable.contains] method is based on - * `==` comparison. - */ - Iterable get values; - - /** - * The number of key-value pairs in the map. - */ - int get length; - - /** - * Returns true if there is no key-value pair in the map. - */ - bool get isEmpty; - - /** - * Returns true if there is at least one key-value pair in the map. - */ - bool get isNotEmpty; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/null.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/null.dart deleted file mode 100644 index dd914a3be90a..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/null.dart +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.core; - -/** - * The reserved word [:null:] denotes an object that is the sole instance of - * this class. - * - * It is a compile-time error for a class to attempt to extend or implement - * Null. - */ -class Null { - factory Null._uninstantiable() { - throw new UnsupportedError('class Null cannot be instantiated'); - } - - /** Returns the string `"null"`. */ - String toString() => "null"; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/num.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/num.dart deleted file mode 100644 index 2fc4234b60f8..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/num.dart +++ /dev/null @@ -1,462 +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. - -part of dart.core; - -/** - * An integer or floating-point number. - * - * It is a compile-time error for any type other than [int] or [double] - * to attempt to extend or implement num. - */ -abstract class num implements Comparable { - /** - * Test whether this value is numerically equal to `other`. - * - * If both operands are doubles, they are equal if they have the same - * representation, except that: - * - * * zero and minus zero (0.0 and -0.0) are considered equal. They - * both have the numerical value zero. - * * NaN is not equal to anything, including NaN. If either operand is - * NaN, the result is always false. - * - * If one operand is a double and the other is an int, they are equal if - * the double has an integer value (finite with no fractional part) and - * `identical(doubleValue.toInt(), intValue)` is true. - * - * If both operands are integers, they are equal if they have the same value. - * - * Returns false if `other` is not a [num]. - * - * Notice that the behavior for NaN is non-reflexive. This means that - * equality of double values is not a proper equality relation, as is - * otherwise required of `operator==`. Using NaN in, e.g., a [HashSet] - * will fail to work. The behavior is the standard IEEE-754 equality of - * doubles. - * - * If you can avoid NaN values, the remaining doubles do have a proper eqality - * relation, and can be used safely. - * - * Use [compareTo] for a comparison that distinguishes zero and minus zero, - * and that considers NaN values as equal. - */ - bool operator==(Object other); - - /** - * Returns a hash code for a numerical value. - * - * The hash code is compatible with equality. It returns the same value - * for an [int] and a [double] with the same numerical value, and therefore - * the same value for the doubles zero and minus zero. - * - * No guarantees are made about the hash code of NaN. - */ - int get hashCode; - - /** - * Compares this to `other`. - * - * Returns a negative number if `this` is less than `other`, zero if they are - * equal, and a positive number if `this` is greater than `other`. - * - * The orderding represented by this method is a total ordering of [num] - * values. All distinct doubles are non-equal, as are all distinct integers, - * but integers are equal to doubles if they have the same numerical - * value. - * - * For ordering, the double NaN value is considered equal to itself, and - * greater than any numeric value (unlike its behavior in `operator==`). - * - * The double value -0.0 is considered less than 0.0 (and the integer 0), but - * greater than any non-zero negative value. - * - * Positive infinity is greater than any finite value (any value apart from - * itself and NaN), and negative infinity is less than any other value. - * - * All other values are compared using their numeric value. - */ - int compareTo(num other); - - /** Addition operator. */ - num operator +(num other); - - /** Subtraction operator. */ - num operator -(num other); - - /** Multiplication operator. */ - num operator *(num other); - - /** - * Euclidean modulo operator. - * - * Returns the remainder of the euclidean division. The euclidean division of - * two integers `a` and `b` yields two integers `q` and `r` such that - * `a == b * q + r` and `0 <= r < b.abs()`. - * - * The euclidean division is only defined for integers, but can be easily - * extended to work with doubles. In that case `r` may have a non-integer - * value, but it still verifies `0 <= r < |b|`. - * - * The sign of the returned value `r` is always positive. - * - * See [remainder] for the remainder of the truncating division. - */ - num operator %(num other); - - /** Division operator. */ - double operator /(num other); - - /** - * Truncating division operator. - * - * If either operand is a [double] then the result of the truncating division - * `a ~/ b` is equivalent to `(a / b).truncate().toInt()`. - * - * If both operands are [int]s then `a ~/ b` performs the truncating - * integer division. - */ - int operator ~/(num other); - - /** Negate operator. */ - num operator -(); - - /** - * Returns the remainder of the truncating division of `this` by [other]. - * - * The result `r` of this operation satisfies: - * `this == (this ~/ other) * other + r`. - * As a consequence the remainder `r` has the same sign as the divider `this`. - */ - num remainder(num other); - - /** Relational less than operator. */ - bool operator <(num other); - - /** Relational less than or equal operator. */ - bool operator <=(num other); - - /** Relational greater than operator. */ - bool operator >(num other); - - /** Relational greater than or equal operator. */ - bool operator >=(num other); - - /** True if the number is the double Not-a-Number value; otherwise, false. */ - bool get isNaN; - - /** - * True if the number is negative; otherwise, false. - * - * Negative numbers are those less than zero, and the double `-0.0`. - */ - bool get isNegative; - - /** - * True if the number is positive infinity or negative infinity; otherwise, - * false. - */ - bool get isInfinite; - - /** - * True if the number is finite; otherwise, false. - * - * The only non-finite numbers are NaN, positive infinitity and - * negative infinity. - */ - bool get isFinite; - - /** Returns the absolute value of this [num]. */ - num abs(); - - /** - * Returns minus one, zero or plus one depending on the sign and - * numerical value of the number. - * - * Returns minus one if the number is less than zero, - * plus one if the number is greater than zero, - * and zero if the number is equal to zero. - * - * Returns NaN if the number is the double NaN value. - * - * Returns a number of the same type as this number. - * For doubles, `-0.0.sign == -0.0`. - - * The result satisfies: - * - * n == n.sign * n.abs() - * - * for all numbers `n` (except NaN, because NaN isn't `==` to itself). - */ - num get sign; - - /** - * Returns the integer closest to `this`. - * - * Rounds away from zero when there is no closest integer: - * `(3.5).round() == 4` and `(-3.5).round() == -4`. - * - * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError]. - */ - int round(); - - /** - * Returns the greatest integer no greater than `this`. - * - * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError]. - */ - int floor(); - - /** - * Returns the least integer no smaller than `this`. - * - * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError]. - */ - int ceil(); - - /** - * Returns the integer obtained by discarding any fractional - * digits from `this`. - * - * If `this` is not finite (`NaN` or infinity), throws an [UnsupportedError]. - */ - int truncate(); - - /** - * Returns the double integer value closest to `this`. - * - * Rounds away from zero when there is no closest integer: - * `(3.5).roundToDouble() == 4` and `(-3.5).roundToDouble() == -4`. - * - * If this is already an integer valued double, including `-0.0`, or it is a - * non-finite double value, the value is returned unmodified. - * - * For the purpose of rounding, `-0.0` is considered to be below `0.0`, - * and `-0.0` is therefore considered closer to negative numbers than `0.0`. - * This means that for a value, `d` in the range `-0.5 < d < 0.0`, - * the result is `-0.0`. - * - * The result is always a double. - * If this is a numerically large integer, the result may be an infinite - * double. - */ - double roundToDouble(); - - /** - * Returns the greatest double integer value no greater than `this`. - * - * If this is already an integer valued double, including `-0.0`, or it is a - * non-finite double value, the value is returned unmodified. - * - * For the purpose of rounding, `-0.0` is considered to be below `0.0`. - * A number `d` in the range `0.0 < d < 1.0` will return `0.0`. - * - * The result is always a double. - * If this is a numerically large integer, the result may be an infinite - * double. - */ - double floorToDouble(); - - /** - * Returns the least double integer value no smaller than `this`. - * - * If this is already an integer valued double, including `-0.0`, or it is a - * non-finite double value, the value is returned unmodified. - * - * For the purpose of rounding, `-0.0` is considered to be below `0.0`. - * A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`. - * - * The result is always a double. - * If this is a numerically large integer, the result may be an infinite - * double. - */ - double ceilToDouble(); - - /** - * Returns the double integer value obtained by discarding any fractional - * digits from the double value of `this`. - * - * If this is already an integer valued double, including `-0.0`, or it is a - * non-finite double value, the value is returned unmodified. - * - * For the purpose of rounding, `-0.0` is considered to be below `0.0`. - * A number `d` in the range `-1.0 < d < 0.0` will return `-0.0`, and - * in the range `0.0 < d < 1.0` it will return 0.0. - * - * The result is always a double. - * If this is a numerically large integer, the result may be an infinite - * double. - */ - double truncateToDouble(); - - /** - * Returns this [num] clamped to be in the range [lowerLimit]-[upperLimit]. - * - * The comparison is done using [compareTo] and therefore takes `-0.0` into - * account. This also implies that [double.NAN] is treated as the maximal - * double value. - */ - num clamp(num lowerLimit, num upperLimit); - - /** Truncates this [num] to an integer and returns the result as an [int]. */ - int toInt(); - - /** - * Return this [num] as a [double]. - * - * If the number is not representable as a [double], an - * approximation is returned. For numerically large integers, the - * approximation may be infinite. - */ - double toDouble(); - - /** - * Returns a decimal-point string-representation of `this`. - * - * Converts `this` to a [double] before computing the string representation. - * - * If the absolute value of `this` is greater or equal to `10^21` then this - * methods returns an exponential representation computed by - * `this.toStringAsExponential()`. Otherwise the result - * is the closest string representation with exactly [fractionDigits] digits - * after the decimal point. If [fractionDigits] equals 0 then the decimal - * point is omitted. - * - * The parameter [fractionDigits] must be an integer satisfying: - * `0 <= fractionDigits <= 20`. - * - * Examples: - * - * 1.toStringAsFixed(3); // 1.000 - * (4321.12345678).toStringAsFixed(3); // 4321.123 - * (4321.12345678).toStringAsFixed(5); // 4321.12346 - * 123456789012345678901.toStringAsFixed(3); // 123456789012345683968.000 - * 1000000000000000000000.toStringAsFixed(3); // 1e+21 - * 5.25.toStringAsFixed(0); // 5 - */ - String toStringAsFixed(int fractionDigits); - - /** - * Returns an exponential string-representation of `this`. - * - * Converts `this` to a [double] before computing the string representation. - * - * If [fractionDigits] is given then it must be an integer satisfying: - * `0 <= fractionDigits <= 20`. In this case the string contains exactly - * [fractionDigits] after the decimal point. Otherwise, without the parameter, - * the returned string uses the shortest number of digits that accurately - * represent [this]. - * - * If [fractionDigits] equals 0 then the decimal point is omitted. - * Examples: - * - * 1.toStringAsExponential(); // 1e+0 - * 1.toStringAsExponential(3); // 1.000e+0 - * 123456.toStringAsExponential(); // 1.23456e+5 - * 123456.toStringAsExponential(3); // 1.235e+5 - * 123.toStringAsExponential(0); // 1e+2 - */ - String toStringAsExponential([int fractionDigits]); - - /** - * Converts `this` to a double and returns a string representation with - * exactly [precision] significant digits. - * - * The parameter [precision] must be an integer satisfying: - * `1 <= precision <= 21`. - * - * Examples: - * - * 1.toStringAsPrecision(2); // 1.0 - * 1e15.toStringAsPrecision(3); // 1.00+15 - * 1234567.toStringAsPrecision(3); // 1.23e+6 - * 1234567.toStringAsPrecision(9); // 1234567.00 - * 12345678901234567890.toStringAsPrecision(20); // 12345678901234567168 - * 12345678901234567890.toStringAsPrecision(14); // 1.2345678901235e+19 - * 0.00000012345.toPrecision(15); // 1.23450000000000e-7 - * 0.0000012345.toPrecision(15); // 0.00000123450000000000 - */ - String toStringAsPrecision(int precision); - - /** - * Returns the shortest string that correctly represent the input number. - * - * All [double]s in the range `10^-6` (inclusive) to `10^21` (exclusive) - * are converted to their decimal representation with at least one digit - * after the decimal point. For all other doubles, - * except for special values like `NaN` or `Infinity`, this method returns an - * exponential representation (see [toStringAsExponential]). - * - * Returns `"NaN"` for [double.NAN], `"Infinity"` for [double.INFINITY], and - * `"-Infinity"` for [double.MINUS_INFINITY]. - * - * An [int] is converted to a decimal representation with no decimal point. - * - * Examples: - * - * (0.000001).toString(); // "0.000001" - * (0.0000001).toString(); // "1e-7" - * (111111111111111111111.0).toString(); // "111111111111111110000.0" - * (100000000000000000000.0).toString(); // "100000000000000000000.0" - * (1000000000000000000000.0).toString(); // "1e+21" - * (1111111111111111111111.0).toString(); // "1.1111111111111111e+21" - * 1.toString(); // "1" - * 111111111111111111111.toString(); // "111111111111111110000" - * 100000000000000000000.toString(); // "100000000000000000000" - * 1000000000000000000000.toString(); // "1000000000000000000000" - * 1111111111111111111111.toString(); // "1111111111111111111111" - * 1.234e5.toString(); // 123400 - * 1234.5e6.toString(); // 1234500000 - * 12.345e67.toString(); // 1.2345e+68 - * - * Note: the conversion may round the output if the returned string - * is accurate enough to uniquely identify the input-number. - * For example the most precise representation of the [double] `9e59` equals - * `"899999999999999918767229449717619953810131273674690656206848"`, but - * this method returns the shorter (but still uniquely identifying) `"9e59"`. - * - */ - 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], and the result - * of that invocation becomes the result of calling `parse`. - * - * 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()))` (except when `n` is a NaN `double` - * with a payload). - */ - 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. - _parseError = false; - num result = int.parse(source, onError: _onParseErrorInt); - if (!_parseError) return result; - _parseError = false; - result = double.parse(source, _onParseErrorDouble); - if (!_parseError) return result; - if (onError == null) throw new FormatException(input); - return onError(input); - } - - /** Helper functions for [parse]. */ - static bool _parseError = false; - static int _onParseErrorInt(String _) { - _parseError = true; - return 0; - } - static double _onParseErrorDouble(String _) { - _parseError = true; - return 0.0; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/object.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/object.dart deleted file mode 100644 index 35967d4fd03a..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/object.dart +++ /dev/null @@ -1,102 +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. - -part of dart.core; - -/** - * The base class for all Dart objects. - * - * Because Object is the root of the Dart class hierarchy, - * every other Dart class is a subclass of Object. - * - * When you define a class, you should override [toString] - * to return a string describing an instance of that class. - * You might also need to define [hashCode] and [==], as described in the - * [Implementing map keys] - * (http://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html#ch03-implementing-map-keys) - * section of the [library tour] - * (http://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html). - */ -class Object { - /** - * Creates a new [Object] instance. - * - * [Object] instances have no meaningful state, and are only useful - * through their identity. An [Object] instance is equal to itself - * only. - */ - const Object(); - - /** - * The equality operator. - * - * The default behavior for all [Object]s is to return true if and - * only if [:this:] and [other] are the same object. - * - * Override this method to specify a different equality relation on - * a class. The overriding method must still be an equivalence relation. - * That is, it must be: - * - * * Total: It must return a boolean for all arguments. It should never throw - * or return `null`. - * - * * Reflexive: For all objects `o`, `o == o` must be true. - * - * * Symmetric: For all objects `o1` and `o2`, `o1 == o2` and `o2 == o1` must - * either both be true, or both be false. - * - * * Transitive: For all objects `o1`, `o2`, and `o3`, if `o1 == o2` and - * `o2 == o3` are true, then `o1 == o3` must be true. - * - * The method should also be consistent over time, so equality of two objects - * should not change over time, or at least only change if one of the objects - * was modified. - * - * If a subclass overrides the equality operator it should override - * the [hashCode] method as well to maintain consistency. - */ - bool operator ==(other) => identical(this, other); - - /** - * Get a hash code for this object. - * - * All objects have hash codes. Hash codes are guaranteed to be the - * same for objects that are equal when compared using the equality - * operator [:==:]. Other than that there are no guarantees about - * the hash codes. They will not be consistent between runs and - * there are no distribution guarantees. - * - * If a subclass overrides [hashCode] it should override the - * equality operator as well to maintain consistency. - */ - int get hashCode => Primitives.objectHashCode(this); - - /** - * Returns a string representation of this object. - */ - String toString() => Primitives.objectToString(this); - - /** - * [noSuchMethod] is invoked when users invoke a non-existent method - * on an object. The name of the method and the arguments of the - * invocation are passed to [noSuchMethod] in an [Invocation]. - * If [noSuchMethod] returns a value, that value becomes the result of - * the original invocation. - * - * The default behavior of [noSuchMethod] is to throw a - * [NoSuchMethodError]. - */ - dynamic noSuchMethod(Invocation invocation) { - throw new NoSuchMethodError( - this, - invocation.memberName, - invocation.positionalArguments, - invocation.namedArguments); - } - - /** - * A representation of the runtime type of the object. - */ - Type get runtimeType => JS('Type', 'dart.realRuntimeType(#)', this); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/pattern.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/pattern.dart deleted file mode 100644 index cf898afff379..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/pattern.dart +++ /dev/null @@ -1,42 +0,0 @@ -// 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. - -part of dart.core; - -/** - * An interface for basic searches within strings. - */ -abstract class Pattern { - // NOTE: When using "start" index from the language library, call - // without an argument if start is zero. This allows backwards compatiblity - // with implementations of the older interface that didn't have the start - // index argument. - /** - * Match this pattern against the string repeatedly. - * - * If [start] is provided, matching will start at that index. - * - * The iterable will contain all the non-overlapping matches of the - * pattern on the string, ordered by start index. - * - * The matches are found by repeatedly finding the first match - * of the pattern on the string, starting from the end of the previous - * match, and initially starting from index zero. - * - * If the pattern matches the empty string at some point, the next - * match is found by starting at the previous match's end plus one. - */ - Iterable allMatches(String string, [int start = 0]); - - /** - * Match this pattern against the start of `string`. - * - * If [start] is provided, it must be an integer in the range `0` .. - * `string.length`. In that case, this patten is tested against the - * string at the [start] position. That is, a [Match] is returned if the - * pattern can match a part of the string starting from position [start]. - * Returns `null` if the pattern doesn't match. - */ - Match matchAsPrefix(String string, [int start = 0]); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/print.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/print.dart deleted file mode 100644 index 42c7d1ca4aa4..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/print.dart +++ /dev/null @@ -1,15 +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. - -part of dart.core; - -/// Prints a string representation of the object to the console. -void print(Object object) { - String line = "$object"; - if (printToZone == null) { - printToConsole(line); - } else { - printToZone(line); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/regexp.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/regexp.dart deleted file mode 100644 index d5ef3db7f6d0..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/regexp.dart +++ /dev/null @@ -1,179 +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. - -part of dart.core; - -/** - * A result from searching within a string. - * - * A Match or an [Iterable] of Match objects is returned from [Pattern] - * matching methods. - * - * The following example finds all matches of a [RegExp] in a [String] - * and iterates through the returned iterable of Match objects. - * - * RegExp exp = new RegExp(r"(\w+)"); - * String str = "Parse my string"; - * Iterable matches = exp.allMatches(str); - * for (Match m in matches) { - * String match = m.group(0); - * print(match); - * } - * - * The output of the example is: - * - * Parse - * my - * string - * - * Some patterns, regular expressions in particular, may record subtrings - * that were part of the matching. These are called _groups_ in the Match - * object. Some patterns may never have any groups, and their matches always - * have zero [groupCount]. - */ -abstract class Match { - /** - * Returns the index in the string where the match starts. - */ - int get start; - - /** - * Returns the index in the string after the last character of the - * match. - */ - int get end; - - /** - * Returns the string matched by the given [group]. - * - * If [group] is 0, returns the match of the pattern. - * - * The result may be `null` if the pattern didn't assign a value to it - * as part of this match. - */ - String group(int group); - - /** - * Returns the string matched by the given [group]. - * - * If [group] is 0, returns the match of the pattern. - * - * Short alias for [Match.group]. - */ - String operator [](int group); - - /** - * Returns a list of the groups with the given indices. - * - * The list contains the strings returned by [group] for each index in - * [groupIndices]. - */ - List groups(List groupIndices); - - /** - * Returns the number of captured groups in the match. - * - * Some patterns may capture parts of the input that was used to - * compute the full match. This is the number of captured groups, - * which is also the maximal allowed argument to the [group] method. - */ - int get groupCount; - - /** - * The string on which this match was computed. - */ - String get input; - - /** - * The pattern used to search in [input]. - */ - Pattern get pattern; -} - - -/** - * A regular expression pattern. - * - * Regular expressions are [Pattern]s, and can as such be used to match strings - * or parts of strings. - * - * Dart regular expressions have the same syntax and semantics as - * JavaScript regular expressions. See - * - * for the specification of JavaScript regular expressions. - * - * [firstMatch] is the main implementation method that applies a regular - * expression to a string and returns the first [Match]. All - * other methods in [RegExp] can build on it. - * - * Use [allMatches] to look for all matches of a regular expression in - * a string. - * - * The following example finds all matches of a regular expression in - * a string. - * - * RegExp exp = new RegExp(r"(\w+)"); - * String str = "Parse my string"; - * Iterable matches = exp.allMatches(str); - */ -abstract class RegExp implements Pattern { - /** - * Constructs a regular expression. - * - * Throws a [FormatException] if [source] is not valid regular - * expression syntax. - */ - factory RegExp(String source, - {bool multiLine: false, - bool caseSensitive: true}) - => new JSSyntaxRegExp(source, - multiLine: multiLine, - caseSensitive: caseSensitive); - - /** - * Searches for the first match of the regular expression - * in the string [input]. Returns `null` if there is no match. - */ - Match firstMatch(String input); - - /** - * Returns an iterable of the matches of the regular expression on [input]. - * - * If [start] is provided, only start looking for matches at `start`. - */ - Iterable allMatches(String input, [int start = 0]); - - /** - * Returns whether the regular expression has a match in the string [input]. - */ - bool hasMatch(String input); - - /** - * Returns the first substring match of this regular expression in [input]. - */ - String stringMatch(String input); - - /** - * The source regular expression string used to create this `RegExp`. - */ - String get pattern; - - /** - * Whether this regular expression matches multiple lines. - * - * If the regexp does match multiple lines, the "^" and "$" characters - * match the beginning and end of lines. If not, the character match the - * beginning and end of the input. - */ - bool get isMultiLine; - - /** - * Whether this regular expression is case sensitive. - * - * If the regular expression is not case sensitive, it will match an input - * letter with a pattern letter even if the two letters are different case - * versions of the same letter. - */ - bool get isCaseSensitive; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/set.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/set.dart deleted file mode 100644 index 6c3ec0081301..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/set.dart +++ /dev/null @@ -1,188 +0,0 @@ -// 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. - -part of dart.core; - -/** - * A collection of objects in which each object can occur only once. - * - * That is, for each object of the element type, the object is either considered - * to be in the set, or to _not_ be in the set. - * - * Set implementations may consider some elements indistinguishable. These - * elements are treated as being the same for any operation on the set. - * - * The default [Set] implementation, [LinkedHashSet], considers objects - * indistinguishable if they are equal with regard to - * operator [Object.==]. - * - * Iterating over elements of a set may be either unordered - * or ordered in some way. Examples: - * - * * A [HashSet] is unordered, which means that its iteration order is - * uspecified, - * * [LinkedHashSet] iterates in the insertion order of its elements, and - * * a sorted set like [SplayTreeSet] iterates the elements in sorted order. - * - * It is generally not allowed to modify the set (add or remove elements) while - * an operation on the set is being performed, for example during a call to - * [forEach] or [containsAll]. Nor is it allowed to modify the set while - * iterating either the set itself or any [Iterable] that is backed by the set, - * such as the ones returned by methods like [where] and [map]. - */ -abstract class Set extends IterableBase implements EfficientLength { - /** - * Creates an empty [Set]. - * - * The created [Set] is a plain [LinkedHashSet]. - * As such, it considers elements that are equal (using [==]) to be - * indistinguishable, and requires them to have a compatible - * [Object.hashCode] implementation. - * - * The set is equivalent to one created by `new LinkedHashSet()`. - */ - factory Set() = LinkedHashSet; - - /** - * Creates an empty identity [Set]. - * - * The created [Set] is a [LinkedHashSet] that uses identity as equality - * relation. - * - * The set is equivalent to one created by `new LinkedHashSet.identity()`. - */ - factory Set.identity() = LinkedHashSet.identity; - - /** - * Creates a [Set] that contains all [elements]. - * - * All the [elements] should be assignable to [E]. - * The `elements` iterable itself can have any type, - * so this constructor can be used to down-cast a `Set`, for example as: - * - * Set superSet = ...; - * Set subSet = - * new Set.from(superSet.where((e) => e is SubType)); - * - * The created [Set] is a [LinkedHashSet]. As such, it considers elements that - * are equal (using [==]) to be indistinguishable, and requires them to - * have a compatible [Object.hashCode] implementation. - * - * The set is equivalent to one created by - * `new LinkedHashSet.from(elements)`. - */ - factory Set.from(Iterable elements) = LinkedHashSet.from; - - /** - * Provides an iterator that iterates over the elements of this set. - * - * The order of iteration is defined by the individual `Set` implementation, - * but must be consistent between changes to the set. - */ - Iterator get iterator; - - /** - * Returns true if [value] is in the set. - */ - bool contains(Object value); - - /** - * Adds [value] into the set. Returns `true` if [value] was added to the set. - * - * If [value] already exists, the set is not changed and `false` is returned. - */ - bool add(E value); - - /** - * Adds all [elements] to this Set. - * - * Equivalent to adding each element in [elements] using [add], - * but some collections may be able to optimize it. - */ - void addAll(Iterable elements); - - /** - * Removes [value] from the set. Returns true if [value] was - * in the set. Returns false otherwise. The method has no effect - * if [value] value was not in the set. - */ - bool remove(Object value); - - /** - * If an object equal to [object] is in the set, return it. - * - * Checks if there is an object in the set that is equal to [object]. - * If so, that object is returned, otherwise returns null. - */ - E lookup(Object object); - - /** - * Removes each element of [elements] from this set. - */ - void removeAll(Iterable elements); - - /** - * Removes all elements of this set that are not elements in [elements]. - * - * Checks for each element of [elements] whether there is an element in this - * set that is equal to it (according to `this.contains`), and if so, the - * equal element in this set is retained, and elements that are not equal - * to any element in `elements` are removed. - */ - void retainAll(Iterable elements); - - /** - * Removes all elements of this set that satisfy [test]. - */ - void removeWhere(bool test(E element)); - - /** - * Removes all elements of this set that fail to satisfy [test]. - */ - void retainWhere(bool test(E element)); - - /** - * Returns whether this Set contains all the elements of [other]. - */ - bool containsAll(Iterable other); - - /** - * Returns a new set which is the intersection between this set and [other]. - * - * That is, the returned set contains all the elements of this [Set] that - * are also elements of [other] according to `other.contains`. - */ - Set intersection(Set other); - - /** - * Returns a new set which contains all the elements of this set and [other]. - * - * That is, the returned set contains all the elements of this [Set] and - * all the elements of [other]. - */ - Set union(Set other); - - /** - * Returns a new set with the the elements of this that are not in [other]. - * - * That is, the returned set contains all the elements of this [Set] that - * are not elements of [other] according to `other.contains`. - */ - Set difference(Set other); - - /** - * Removes all elements in the set. - */ - void clear(); - - /* Creates a [Set] with the same elements and behavior as this `Set`. - * - * The returned set behaves the same as this set - * with regard to adding and removing elements. - * It initially contains the same elements. - * If this set specifies an ordering of the elements, - * the returned set will have the same order. - */ - Set toSet(); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/sink.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/sink.dart deleted file mode 100644 index 0d8f2eff254a..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/sink.dart +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.core; - -/** - * A generic destination for data. - * - * Multiple data values can be put into a sink, and when no more data is - * available, the sink should be closed. - * - * This is a generic interface that other data receivers can implement. - */ -abstract class Sink { - /** - * Put the data into the sink. - * - * Must not be called after a call to [close]. - */ - void add(T data); - - /** - * Tell the sink that no further data will be added. - * - * Calling this method more than once is allowed, but does nothing. - * - * The [add] method must not be called after this method. - */ - void close(); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/stacktrace.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/stacktrace.dart deleted file mode 100644 index ef8cc4dbb4ad..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/stacktrace.dart +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.core; - -/** - * An interface implemented by all stack trace objects. - * - * A [StackTrace] is intended to convey information to the user about the call - * sequence that triggered an exception. - * - * These objects are created by the runtime, it is not possible to create - * them programmatically. - */ -abstract class StackTrace { - /** - * Returns a [String] representation of the stack trace. - * - * The string represents the full stack trace starting from - * the point where a throw ocurred to the top of the current call sequence. - * - * The exact format of the string representation is not final. - */ - String toString(); -} - diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/stopwatch.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/stopwatch.dart deleted file mode 100644 index 1307eb1118fc..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/stopwatch.dart +++ /dev/null @@ -1,146 +0,0 @@ -// 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. - -part of dart.core; - -/** - * A simple stopwatch interface to measure elapsed time. - */ -class Stopwatch { - /** - * Frequency of the elapsed counter in Hz. - */ - int get frequency => _frequency; - - // The _start and _stop fields capture the time when [start] and [stop] - // are called respectively. - // If _start is null, then the [Stopwatch] has not been started yet. - // If _stop is null, then the [Stopwatch] has not been stopped yet, - // or is running. - num _start; - num _stop; - - /** - * Creates a [Stopwatch] in stopped state with a zero elapsed count. - * - * The following example shows how to start a [Stopwatch] - * immediately after allocation. - * - * Stopwatch stopwatch = new Stopwatch()..start(); - */ - Stopwatch() { - _initTicker(); - } - - /** - * Starts the [Stopwatch]. - * - * The [elapsed] count is increasing monotonically. If the [Stopwatch] has - * been stopped, then calling start again restarts it without resetting the - * [elapsed] count. - * - * If the [Stopwatch] is currently running, then calling start does nothing. - */ - void start() { - if (isRunning) return; - if (_start == null) { - // This stopwatch has never been started. - _start = _now(); - } else { - // Restart this stopwatch. Prepend the elapsed time to the current - // start time. - _start = _now() - (_stop - _start); - _stop = null; - } - } - - /** - * Stops the [Stopwatch]. - * - * The [elapsedTicks] count stops increasing after this call. If the - * [Stopwatch] is currently not running, then calling this method has no - * effect. - */ - void stop() { - if (!isRunning) return; - _stop = _now(); - } - - /** - * Resets the [elapsed] count to zero. - * - * This method does not stop or start the [Stopwatch]. - */ - void reset() { - if (_start == null) return; - // If [_start] is not null, then the stopwatch had already been started. It - // may running right now. - _start = _now(); - if (_stop != null) { - // The watch is not running. So simply set the [_stop] to [_start] thus - // having an elapsed time of 0. - _stop = _start; - } - } - - /** - * Returns the elapsed number of clock ticks since calling [start] while the - * [Stopwatch] is running. - * - * Returns the elapsed number of clock ticks between calling [start] and - * calling [stop]. - * - * Returns 0 if the [Stopwatch] has never been started. - * - * The elapsed number of clock ticks increases by [frequency] every second. - */ - int get elapsedTicks { - if (_start == null) { - return 0; - } - return (_stop == null) ? (_now() - _start) : (_stop - _start); - } - - /** - * Returns the [elapsedTicks] counter converted to a [Duration]. - */ - Duration get elapsed { - return new Duration(microseconds: elapsedMicroseconds); - } - - /** - * Returns the [elapsedTicks] counter converted to microseconds. - */ - int get elapsedMicroseconds { - return (elapsedTicks * 1000000) ~/ frequency; - } - - /** - * Returns the [elapsedTicks] counter converted to milliseconds. - */ - int get elapsedMilliseconds { - return (elapsedTicks * 1000) ~/ frequency; - } - - - /** - * Returns wether the [StopWatch] is currently running. - */ - bool get isRunning => _start != null && _stop == null; - - /** - * Cached frequency of the system. Must be initialized in [_initTicker]; - */ - static int _frequency; - - /** - * Initializes the time-measuring system. *Must* initialize the [_frequency] - * variable. - */ - static void _initTicker() { - Primitives.initTicker(); - _frequency = Primitives.timerFrequency; - } - static int _now() => Primitives.timerTicks(); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/string.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/string.dart deleted file mode 100644 index 1b00277ecae8..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/string.dart +++ /dev/null @@ -1,817 +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. - -part of dart.core; - -/** - * A sequence of characters. - * - * A string can be either single or multiline. Single line strings are - * written using matching single or double quotes, and multiline strings are - * written using triple quotes. The following are all valid Dart strings: - * - * 'Single quotes'; - * "Double quotes"; - * 'Double quotes in "single" quotes'; - * "Single quotes in 'double' quotes"; - * - * '''A - * multiline - * string'''; - * - * """ - * Another - * multiline - * string"""; - * - * Strings are immutable. Although you cannot change a string, you can perform - * an operation on a string and assign the result to a new string: - * - * var string = 'Dart is fun'; - * var newString = string.substring(0, 5); - * - * You can use the plus (`+`) operator to concatenate strings: - * - * 'Dart ' + 'is ' + 'fun!'; // 'Dart is fun!' - * - * You can also use adjacent string literals for concatenation: - * - * 'Dart ' 'is ' 'fun!'; // 'Dart is fun!' - * - * You can use `${}` to interpolate the value of Dart expressions - * within strings. The curly braces can be omitted when evaluating identifiers: - * - * string = 'dartlang'; - * '$string has ${string.length} letters'; // 'dartlang has 8 letters' - * - * A string is represented by a sequence of Unicode UTF-16 code units - * accessible through the [codeUnitAt] or the [codeUnits] members: - * - * string = 'Dart'; - * string.codeUnitAt(0); // 68 - * string.codeUnits; // [68, 97, 114, 116] - * - * The string representation of code units is accessible through the index - * operator: - * - * string[0]; // 'D' - * - * The characters of a string are encoded in UTF-16. Decoding UTF-16, which - * combines surrogate pairs, yields Unicode code points. Following a similar - * terminology to Go, we use the name 'rune' for an integer representing a - * Unicode code point. Use the [runes] property to get the runes of a string: - * - * string.runes.toList(); // [68, 97, 114, 116] - * - * For a character outside the Basic Multilingual Plane (plane 0) that is - * composed of a surrogate pair, [runes] combines the pair and returns a - * single integer. For example, the Unicode character for a - * musical G-clef ('𝄞') with rune value 0x1D11E consists of a UTF-16 surrogate - * pair: `0xD834` and `0xDD1E`. Using [codeUnits] returns the surrogate pair, - * and using `runes` returns their combined value: - * - * var clef = '\u{1D11E}'; - * clef.codeUnits; // [0xD834, 0xDD1E] - * clef.runes.toList(); // [0x1D11E] - * - * The String class can not be extended or implemented. Attempting to do so - * yields a compile-time error. - * - * ## Other resources - * - * See [StringBuffer] to efficiently build a string incrementally. See - * [RegExp] to work with regular expressions. - * - * Also see: - - * * [Dart Cookbook](https://www.dartlang.org/docs/cookbook/#strings) - * for String examples and recipes. - * * [Dart Up and Running] - * (https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html#ch03-strings-and-regular-expressions) - */ -abstract class String implements Comparable, Pattern { - /** - * Allocates a new String for the specified [charCodes]. - * - * The [charCodes] can be UTF-16 code units or runes. If a char-code value is - * 16-bit, it is copied verbatim: - * - * new String.fromCharCodes([68]); // 'D' - * - * If a char-code value is greater than 16-bits, it is decomposed into a - * surrogate pair: - * - * var clef = new String.fromCharCodes([0x1D11E]); - * clef.codeUnitAt(0); // 0xD834 - * clef.codeUnitAt(1); // 0xDD1E - * - * If [start] and [end] is provided, only the values of [charCodes] - * at positions from `start` to, but not including, `end`, are used. - * The `start` and `end` values must satisfy - * `0 <= start <= end <= charCodes.length`. - */ - factory String.fromCharCodes(Iterable charCodes, - [int start = 0, int end]) { - // If possible, recognize typed lists too. - if (charCodes is! JSArray) { - return _stringFromIterable(charCodes, start, end); - } - - List list = charCodes; - int len = list.length; - if (start < 0 || start > len) { - throw new RangeError.range(start, 0, len); - } - if (end == null) { - end = len; - } else if (end < start || end > len) { - throw new RangeError.range(end, start, len); - } - - if (start > 0 || end < len) { - list = list.sublist(start, end); - } - return Primitives.stringFromCharCodes(list); - } - - /** - * Allocates a new String for the specified [charCode]. - * - * If the [charCode] can be represented by a single UTF-16 code unit, the new - * string contains a single code unit. Otherwise, the [length] is 2 and - * the code units form a surrogate pair. See documentation for - * [fromCharCodes]. - * - * Creating a String with half of a surrogate pair is allowed. - */ - factory String.fromCharCode(int charCode) { - return Primitives.stringFromCharCode(charCode); - } - - /** - * Returns the string value of the environment declaration [name]. - * - * Environment declarations are provided by the surrounding system compiling - * or running the Dart program. Declarations map a string key to a string - * value. - * - * If [name] is not declared in the environment, the result is instead - * [defaultValue]. - * - * Example of getting a value: - * - * const String.fromEnvironment("defaultFloo", defaultValue: "no floo") - * - * Example of checking whether a declaration is there at all: - * - * var isDeclared = const String.fromEnvironment("maybeDeclared") != null; - */ - factory String.fromEnvironment(String name, {String defaultValue}) { - throw new UnsupportedError( - 'String.fromEnvironment can only be used as a const constructor'); - } - - /** - * Gets the character (as a single-code-unit [String]) at the given [index]. - * - * The returned string represents exactly one UTF-16 code unit, which may be - * half of a surrogate pair. A single member of a surrogate pair is an - * invalid UTF-16 string: - * - * var clef = '\u{1D11E}'; - * // These represent invalid UTF-16 strings. - * clef[0].codeUnits; // [0xD834] - * clef[1].codeUnits; // [0xDD1E] - * - * This method is equivalent to - * `new String.fromCharCode(this.codeUnitAt(index))`. - */ - String operator [](int index); - - /** - * Returns the 16-bit UTF-16 code unit at the given [index]. - */ - int codeUnitAt(int index); - - /** - * The length of the string. - * - * Returns the number of UTF-16 code units in this string. The number - * of [runes] might be fewer, if the string contains characters outside - * the Basic Multilingual Plane (plane 0): - * - * 'Dart'.length; // 4 - * 'Dart'.runes.length; // 4 - * - * var clef = '\u{1D11E}'; - * clef.length; // 2 - * clef.runes.length; // 1 - */ - int get length; - - /** - * Returns a hash code derived from the code units of the string. - * - * This is compatible with [operator==]. Strings with the same sequence - * of code units have the same hash code. - */ - int get hashCode; - - /** - * Returns true if other is a `String` with the same sequence of code units. - * - * This method compares each individual code unit of the strings. - * It does not check for Unicode equivalence. - * For example, both the following strings represent the string 'Amélie', - * but due to their different encoding, are not equal: - * - * 'Am\xe9lie' == 'Ame\u{301}lie'; // false - * - * The first string encodes 'é' as a single unicode code unit (also - * a single rune), whereas the second string encodes it as 'e' with the - * combining accent character '◌́'. - */ - bool operator ==(Object other); - - /** - * Returns true if this string ends with [other]. For example: - * - * 'Dart'.endsWith('t'); // true - */ - bool endsWith(String other); - - /** - * Returns true if this string starts with a match of [pattern]. - * - * var string = 'Dart'; - * string.startsWith('D'); // true - * string.startsWith(new RegExp(r'[A-Z][a-z]')); // true - * - * If [index] is provided, this method checks if the substring starting - * at that index starts with a match of [pattern]: - * - * string.startsWith('art', 1); // true - * string.startsWith(new RegExp(r'\w{3}')); // true - * - * [index] must not be negative or greater than [length]. - * - * A [RegExp] containing '^' does not match if the [index] is greater than - * zero. The pattern works on the string as a whole, and does not extract - * a substring starting at [index] first: - * - * string.startsWith(new RegExp(r'^art'), 1); // false - * string.startsWith(new RegExp(r'art'), 1); // true - */ - bool startsWith(Pattern pattern, [int index = 0]); - - /** - * Returns the position of the first match of [pattern] in this string, - * starting at [start], inclusive: - * - * var string = 'Dartisans'; - * string.indexOf('art'); // 1 - * string.indexOf(new RegExp(r'[A-Z][a-z]')); // 0 - * - * Returns -1 if no match is found: - * - * string.indexOf(new RegExp(r'dart')); // -1 - * - * [start] must not be negative or greater than [length]. - */ - int indexOf(Pattern pattern, [int start]); - - /** - * Returns the position of the last match [pattern] in this string, searching - * backward starting at [start], inclusive: - * - * var string = 'Dartisans'; - * string.lastIndexOf('a'); // 6 - * string.lastIndexOf(new RegExp(r'a(r|n)')); // 6 - * - * Returns -1 if [other] could not be found. - * - * string.lastIndexOf(new RegExp(r'DART')); // -1 - * - * [start] must not be negative or greater than [length]. - */ - int lastIndexOf(Pattern pattern, [int start]); - - /** - * Returns true if this string is empty. - */ - bool get isEmpty; - - /** - * Returns true if this string is not empty. - */ - bool get isNotEmpty; - - /** - * Creates a new string by concatenating this string with [other]. - * - * 'dart' + 'lang'; // 'dartlang' - */ - String operator +(String other); - - /** - * Returns the substring of this string that extends from [startIndex], - * inclusive, to [endIndex], exclusive. - * - * var string = 'dartlang'; - * string.substring(1); // 'artlang' - * string.substring(1, 4); // 'art' - */ - String substring(int startIndex, [int endIndex]); - - /** - * Returns the string without any leading and trailing whitespace. - * - * If the string contains leading or trailing whitespace, a new string with no - * leading and no trailing whitespace is returned: - * - * '\tDart is fun\n'.trim(); // 'Dart is fun' - * - * Otherwise, the original string itself is returned: - * - * var str1 = 'Dart'; - * var str2 = str1.trim(); - * identical(str1, str2); // true - * - * Whitespace is defined by the Unicode White_Space property (as defined in - * version 6.2 or later) and the BOM character, 0xFEFF. - * - * Here is the list of trimmed characters (following version 6.2): - * - * 0009..000D ; White_Space # Cc .. - * 0020 ; White_Space # Zs SPACE - * 0085 ; White_Space # Cc - * 00A0 ; White_Space # Zs NO-BREAK SPACE - * 1680 ; White_Space # Zs OGHAM SPACE MARK - * 180E ; White_Space # Zs MONGOLIAN VOWEL SEPARATOR - * 2000..200A ; White_Space # Zs EN QUAD..HAIR SPACE - * 2028 ; White_Space # Zl LINE SEPARATOR - * 2029 ; White_Space # Zp PARAGRAPH SEPARATOR - * 202F ; White_Space # Zs NARROW NO-BREAK SPACE - * 205F ; White_Space # Zs MEDIUM MATHEMATICAL SPACE - * 3000 ; White_Space # Zs IDEOGRAPHIC SPACE - * - * FEFF ; BOM ZERO WIDTH NO_BREAK SPACE - */ - String trim(); - - /** - * Returns the string without any leading whitespace. - * - * As [trim], but only removes leading whitespace. - */ - String trimLeft(); - - /** - * Returns the string without any trailing whitespace. - * - * As [trim], but only removes trailing whitespace. - */ - String trimRight(); - - /** - * Creates a new string by concatenating this string with itself a number - * of times. - * - * The result of `str * n` is equivalent to - * `str + str + ...`(n times)`... + str`. - * - * Returns an empty string if [times] is zero or negative. - */ - String operator *(int times); - - /** - * Pads this string on the left if it is shorther than [width]. - * - * Return a new string that prepends [padding] onto this string - * one time for each position the length is less than [width]. - * - * If [width] is already smaller than or equal to `this.length`, - * no padding is added. A negative `width` is treated as zero. - * - * If [padding] has length different from 1, the result will not - * have length `width`. This may be useful for cases where the - * padding is a longer string representing a single character, like - * `" "` or `"\u{10002}`". - * In that case, the user should make sure that `this.length` is - * the correct measure of the strings length. - */ - String padLeft(int width, [String padding = ' ']); - - /** - * Pads this string on the right if it is shorther than [width]. - * - * Return a new string that appends [padding] after this string - * one time for each position the length is less than [width]. - * - * If [width] is already smaller than or equal to `this.length`, - * no padding is added. A negative `width` is treated as zero. - * - * If [padding] has length different from 1, the result will not - * have length `width`. This may be useful for cases where the - * padding is a longer string representing a single character, like - * `" "` or `"\u{10002}`". - * In that case, the user should make sure that `this.length` is - * the correct measure of the strings length. - */ - String padRight(int width, [String padding = ' ']); - - /** - * Returns true if this string contains a match of [other]: - * - * var string = 'Dart strings'; - * string.contains('D'); // true - * string.contains(new RegExp(r'[A-Z]')); // true - * - * If [startIndex] is provided, this method matches only at or after that - * index: - * - * string.contains('X', 1); // false - * string.contains(new RegExp(r'[A-Z]'), 1); // false - * - * [startIndex] must not be negative or greater than [length]. - */ - bool contains(Pattern other, [int startIndex = 0]); - - /** - * Returns a new string in which the first occurence of [from] in this string - * is replaced with [to], starting from [startIndex]: - * - * '0.0001'.replaceFirst(new RegExp(r'0'), ''); // '.0001' - * '0.0001'.replaceFirst(new RegExp(r'0'), '7', 1); // '0.7001' - */ - String replaceFirst(Pattern from, String to, [int startIndex = 0]); - - /** - * Replaces all substrings that match [from] with [replace]. - * - * Returns a new string in which the non-overlapping substrings matching - * [from] (the ones iterated by `from.allMatches(thisString)`) are replaced - * by the literal string [replace]. - * - * 'resume'.replaceAll(new RegExp(r'e'), 'é'); // 'résumé' - * - * Notice that the [replace] string is not interpreted. If the replacement - * depends on the match (for example on a [RegExp]'s capture groups), use - * the [replaceAllMapped] method instead. - */ - String replaceAll(Pattern from, String replace); - - /** - * Replace all substrings that match [from] by a string computed from the - * match. - * - * Returns a new string in which the non-overlapping substrings that match - * [from] (the ones iterated by `from.allMatches(thisString)`) are replaced - * by the result of calling [replace] on the corresponding [Match] object. - * - * This can be used to replace matches with new content that depends on the - * match, unlike [replaceAll] where the replacement string is always the same. - * - * The [replace] function is called with the [Match] generated - * by the pattern, and its result is used as replacement. - * - * The function defined below converts each word in a string to simplified - * 'pig latin' using [replaceAllMapped]: - * - * pigLatin(String words) => words.replaceAllMapped( - * new RegExp(r'\b(\w*?)([aeiou]\w*)', caseSensitive: false), - * (Match m) => "${m[2]}${m[1]}${m[1].isEmpty ? 'way' : 'ay'}"); - * - * pigLatin('I have a secret now!'); // 'Iway avehay away ecretsay ownay!' - */ - String replaceAllMapped(Pattern from, String replace(Match match)); - - /** - * Splits the string at matches of [pattern] and returns a list of substrings. - * - * Finds all the matches of `pattern` in this string, - * and returns the list of the substrings between the matches. - * - * var string = "Hello world!"; - * string.split(" "); // ['Hello', 'world!']; - * - * Empty matches at the beginning and end of the strings are ignored, - * and so are empty matches right after another match. - * - * var string = "abba"; - * string.split(new RegExp(r"b*")); // ['a', 'a'] - * // not ['', 'a', 'a', ''] - * - * If this string is empty, the result is an empty list if `pattern` matches - * the empty string, and it is `[""]` if the pattern doesn't match. - * - * var string = ''; - * string.split(''); // [] - * string.split("a"); // [''] - * - * Splitting with an empty pattern splits the string into single-code unit - * strings. - * - * var string = 'Pub'; - * string.split(''); // ['P', 'u', 'b'] - * - * string.codeUnits.map((unit) { - * return new String.fromCharCode(unit); - * }).toList(); // ['P', 'u', 'b'] - * - * Splitting happens at UTF-16 code unit boundaries, - * and not at rune boundaries: - * - * // String made up of two code units, but one rune. - * string = '\u{1D11E}'; - * string.split('').length; // 2 surrogate values - * - * To get a list of strings containing the individual runes of a string, - * you should not use split. You can instead map each rune to a string - * as follows: - * - * string.runes.map((rune) => new String.fromCharCode(rune)).toList(); - */ - List split(Pattern pattern); - - /** - * Splits the string, converts its parts, and combines them into a new - * string. - * - * [pattern] is used to split the string into parts and separating matches. - * - * Each match is converted to a string by calling [onMatch]. If [onMatch] - * is omitted, the matched string is used. - * - * Each non-matched part is converted by a call to [onNonMatch]. If - * [onNonMatch] is omitted, the non-matching part is used. - * - * Then all the converted parts are combined into the resulting string. - * - * 'Eats shoots leaves'.splitMapJoin((new RegExp(r'shoots')), - * onMatch: (m) => '${m.group(0)}', - * onNonMatch: (n) => '*'); // *shoots* - */ - String splitMapJoin(Pattern pattern, - {String onMatch(Match match), - String onNonMatch(String nonMatch)}); - - /** - * Returns an unmodifiable list of the UTF-16 code units of this string. - */ - List get codeUnits; - - /** - * Returns an [Iterable] of Unicode code-points of this string. - * - * If the string contains surrogate pairs, they are combined and returned - * as one integer by this iterator. Unmatched surrogate halves are treated - * like valid 16-bit code-units. - */ - Runes get runes; - - /** - * Converts all characters in this string to lower case. - * If the string is already in all lower case, this method returns [:this:]. - * - * 'ALPHABET'.toLowerCase(); // 'alphabet' - * 'abc'.toLowerCase(); // 'abc' - * - * This function uses the language independent Unicode mapping and thus only - * works in some languages. - */ - // TODO(floitsch): document better. (See EcmaScript for description). - String toLowerCase(); - - /** - * Converts all characters in this string to upper case. - * If the string is already in all upper case, this method returns [:this:]. - * - * 'alphabet'.toUpperCase(); // 'ALPHABET' - * 'ABC'.toUpperCase(); // 'ABC' - * - * This function uses the language independent Unicode mapping and thus only - * works in some languages. - */ - // TODO(floitsch): document better. (See EcmaScript for description). - String toUpperCase(); - - static String _stringFromIterable(Iterable charCodes, - int start, int end) { - if (start < 0) throw new RangeError.range(start, 0, charCodes.length); - if (end != null && end < start) { - throw new RangeError.range(end, start, charCodes.length); - } - var it = charCodes.iterator; - for (int i = 0; i < start; i++) { - if (!it.moveNext()) { - throw new RangeError.range(start, 0, i); - } - } - var list = []; - if (end == null) { - while (it.moveNext()) list.add(it.current); - } else { - for (int i = start; i < end; i++) { - if (!it.moveNext()) { - throw new RangeError.range(end, start, i); - } - list.add(it.current); - } - } - return Primitives.stringFromCharCodes(list); - } -} - -/** - * The runes (integer Unicode code points) of a [String]. - */ -class Runes extends IterableBase { - final String string; - Runes(this.string); - - RuneIterator get iterator => new RuneIterator(string); - - int get last { - if (string.length == 0) { - throw new StateError('No elements.'); - } - int length = string.length; - int code = string.codeUnitAt(length - 1); - if (_isTrailSurrogate(code) && string.length > 1) { - int previousCode = string.codeUnitAt(length - 2); - if (_isLeadSurrogate(previousCode)) { - return _combineSurrogatePair(previousCode, code); - } - } - return code; - } - -} - -// Is then code (a 16-bit unsigned integer) a UTF-16 lead surrogate. -bool _isLeadSurrogate(int code) => (code & 0xFC00) == 0xD800; - -// Is then code (a 16-bit unsigned integer) a UTF-16 trail surrogate. -bool _isTrailSurrogate(int code) => (code & 0xFC00) == 0xDC00; - -// Combine a lead and a trail surrogate value into a single code point. -int _combineSurrogatePair(int start, int end) { - return 0x10000 + ((start & 0x3FF) << 10) + (end & 0x3FF); -} - -/** [Iterator] for reading runes (integer Unicode code points) out of a Dart - * string. - */ -class RuneIterator implements BidirectionalIterator { - /** String being iterated. */ - final String string; - /** Position before the current code point. */ - int _position; - /** Position after the current code point. */ - int _nextPosition; - /** - * Current code point. - * - * If the iterator has hit either end, the [_currentCodePoint] is null - * and [: _position == _nextPosition :]. - */ - num _currentCodePoint; - - /** Create an iterator positioned at the beginning of the string. */ - RuneIterator(String string) - : this.string = string, _position = 0, _nextPosition = 0; - - /** - * Create an iterator positioned before the [index]th code unit of the string. - * - * When created, there is no [current] value. - * A [moveNext] will use the rune starting at [index] the current value, - * and a [movePrevious] will use the rune ending just before [index] as the - * the current value. - * - * The [index] position must not be in the middle of a surrogate pair. - */ - RuneIterator.at(String string, int index) - : string = string, _position = index, _nextPosition = index { - RangeError.checkValueInInterval(index, 0, string.length); - _checkSplitSurrogate(index); - } - - /** Throw an error if the index is in the middle of a surrogate pair. */ - void _checkSplitSurrogate(int index) { - if (index > 0 && index < string.length && - _isLeadSurrogate(string.codeUnitAt(index - 1)) && - _isTrailSurrogate(string.codeUnitAt(index))) { - throw new ArgumentError('Index inside surrogate pair: $index'); - } - } - - /** - * Returns the starting position of the current rune in the string. - * - * Returns null if the [current] rune is null. - */ - int get rawIndex => (_position != _nextPosition) ? _position : null; - - /** - * Resets the iterator to the rune at the specified index of the string. - * - * Setting a negative [rawIndex], or one greater than or equal to - * [:string.length:], - * is an error. So is setting it in the middle of a surrogate pair. - * - * Setting the position to the end of then string will set [current] to null. - */ - void set rawIndex(int rawIndex) { - RangeError.checkValidIndex(rawIndex, string, "rawIndex"); - reset(rawIndex); - moveNext(); - } - - /** - * Resets the iterator to the given index into the string. - * - * After this the [current] value is unset. - * You must call [moveNext] make the rune at the position current, - * or [movePrevious] for the last rune before the position. - * - * Setting a negative [rawIndex], or one greater than [:string.length:], - * is an error. So is setting it in the middle of a surrogate pair. - */ - void reset([int rawIndex = 0]) { - RangeError.checkValueInInterval(rawIndex, 0, string.length, "rawIndex"); - _checkSplitSurrogate(rawIndex); - _position = _nextPosition = rawIndex; - _currentCodePoint = null; - } - - /** The rune (integer Unicode code point) starting at the current position in - * the string. - */ - int get current => _currentCodePoint; - - /** - * The number of code units comprising the current rune. - * - * Returns zero if there is no current rune ([current] is null). - */ - int get currentSize => _nextPosition - _position; - - /** - * A string containing the current rune. - * - * For runes outside the basic multilingual plane, this will be - * a String of length 2, containing two code units. - * - * Returns null if [current] is null. - */ - String get currentAsString { - if (_position == _nextPosition) return null; - if (_position + 1 == _nextPosition) return string[_position]; - return string.substring(_position, _nextPosition); - } - - bool moveNext() { - _position = _nextPosition; - if (_position == string.length) { - _currentCodePoint = null; - return false; - } - int codeUnit = string.codeUnitAt(_position); - int nextPosition = _position + 1; - if (_isLeadSurrogate(codeUnit) && nextPosition < string.length) { - int nextCodeUnit = string.codeUnitAt(nextPosition); - if (_isTrailSurrogate(nextCodeUnit)) { - _nextPosition = nextPosition + 1; - _currentCodePoint = _combineSurrogatePair(codeUnit, nextCodeUnit); - return true; - } - } - _nextPosition = nextPosition; - _currentCodePoint = codeUnit; - return true; - } - - bool movePrevious() { - _nextPosition = _position; - if (_position == 0) { - _currentCodePoint = null; - return false; - } - int position = _position - 1; - int codeUnit = string.codeUnitAt(position); - if (_isTrailSurrogate(codeUnit) && position > 0) { - int prevCodeUnit = string.codeUnitAt(position - 1); - if (_isLeadSurrogate(prevCodeUnit)) { - _position = position - 1; - _currentCodePoint = _combineSurrogatePair(prevCodeUnit, codeUnit); - return true; - } - } - _position = position; - _currentCodePoint = codeUnit; - return true; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/string_buffer.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/string_buffer.dart deleted file mode 100644 index c48adf1805ab..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/string_buffer.dart +++ /dev/null @@ -1,80 +0,0 @@ -// 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. - -part of dart.core; - -/** - * A class for concatenating strings efficiently. - * - * Allows for the incremental building of a string using write*() methods. - * The strings are concatenated to a single string only when [toString] is - * called. - */ -class StringBuffer implements StringSink { - - /** Creates the string buffer with an initial content. */ - StringBuffer([Object content = ""]) : _contents = '$content'; - - /** - * Returns the length of the content that has been accumulated so far. - * This is a constant-time operation. - */ - int get length => _contents.length; - - /** Returns whether the buffer is empty. This is a constant-time operation. */ - bool get isEmpty => length == 0; - - /** - * Returns whether the buffer is not empty. This is a constant-time - * operation. - */ - bool get isNotEmpty => !isEmpty; - - /// Adds the contents of [obj], converted to a string, to the buffer. - void write(Object obj) { - _writeString('$obj'); - } - - /// Adds the string representation of [charCode] to the buffer. - void writeCharCode(int charCode) { - _writeString(new String.fromCharCode(charCode)); - } - - void writeAll(Iterable objects, [String separator = ""]) { - Iterator iterator = objects.iterator; - if (!iterator.moveNext()) return; - if (separator.isEmpty) { - do { - write(iterator.current); - } while (iterator.moveNext()); - } else { - write(iterator.current); - while (iterator.moveNext()) { - write(separator); - write(iterator.current); - } - } - } - - void writeln([Object obj = ""]) { - write(obj); - write("\n"); - } - - /** - * Clears the string buffer. - */ - void clear() { - _contents = ""; - } - - /// Returns the contents of buffer as a concatenated string. - String toString() => Primitives.flattenString(_contents); - - String _contents; - - void _writeString(str) { - _contents = Primitives.stringConcatUnchecked(_contents, str); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/string_sink.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/string_sink.dart deleted file mode 100644 index 5fdd0f25a35e..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/string_sink.dart +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.core; - -abstract class StringSink { - - /** - * Converts [obj] to a String by invoking [Object.toString] and - * adds the result to `this`. - */ - void write(Object obj); - - /** - * Iterates over the given [objects] and [write]s them in sequence. - */ - void writeAll(Iterable objects, [String separator = ""]); - - /** - * Converts [obj] to a String by invoking [Object.toString] and - * adds the result to `this`, followed by a newline. - */ - void writeln([Object obj = ""]); - - /** - * Writes the [charCode] to `this`. - * - * This method is equivalent to `write(new String.fromCharCode(charCode))`. - */ - void writeCharCode(int charCode); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/symbol.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/symbol.dart deleted file mode 100644 index f60cdd145e9d..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/symbol.dart +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.core; - -/// Opaque name used by mirrors, invocations and [Function.apply]. -abstract class Symbol { - /** - * Constructs a new Symbol. - * - * The name must be a valid public Dart member name, - * public constructor name, or library name, optionally qualified. - * - * A qualified name is a valid name preceded by a public identifier name - * and a '`.`', e.g., `foo.bar.baz=` is a qualified version of `baz=`. - * That means that the content of the [name] String must be either - * - * * a valid public Dart identifier - * (that is, an identifier not starting with "`_`"), - * * such an identifier followed by "=" (a setter name), - * * the name of a declarable operator - * (one of "`+`", "`-`", "`*`", "`/`", "`%`", "`~/`", "`&`", "`|`", - * "`^`", "`~`", "`<<`", "`>>`", "`<`", "`<=`", "`>`", "`>=`", "`==`", - * "`[]`", "`[]=`", or "`unary-`"), - * * any of the above preceeded by any number of qualifiers, - * where a qualifier is a non-private identifier followed by '`.`', - * * or the empty string (the default name of a library with no library - * name declaration). - * - * The following text is non-normative: - * - * Creating non-const Symbol instances may result in larger output. If - * possible, use [MirrorsUsed] in "dart:mirrors" to specify which names might - * be passed to this constructor. - */ - const factory Symbol(String name) = internal.Symbol; - - /** - * Returns a hash code compatible with [operator==]. - * - * Equal symbols have the same hash code. - */ - int get hashCode; - - /** - * Symbols are equal to other symbols that correspond to the same member name. - * - * Qualified member names, like `#foo.bar` are equal only if they have the - * same identifiers before the same final member name. - */ - bool operator ==(Object other); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/type.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/type.dart deleted file mode 100644 index d2e107b6b183..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/type.dart +++ /dev/null @@ -1,10 +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. - -part of dart.core; - -/** - * Runtime representation of a type. - */ -abstract class Type {} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/core/uri.dart b/pkg/dev_compiler/test/generated_sdk/lib/core/uri.dart deleted file mode 100644 index c407bab7efa9..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/core/uri.dart +++ /dev/null @@ -1,2412 +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. - -part of dart.core; - -/** - * A parsed URI, such as a URL. - * - * **See also:** - * - * * [URIs][uris] in the [library tour][libtour] - * * [RFC-3986](http://tools.ietf.org/html/rfc3986) - * - * [uris]: http://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html#ch03-uri - * [libtour]: http://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html - */ -class Uri { - // The host name of the URI. - // Set to `null` if there is no authority in a URI. - final String _host; - // The port. Set to null if there is no port. Normalized to null if - // the port is the default port for the scheme. - // Set to the value of the default port if an empty port was supplied. - num _port; - // The path. Always non-null. - String _path; - - /** - * Returns the scheme component. - * - * Returns the empty string if there is no scheme component. - */ - // We represent the missing scheme as an empty string. - // A valid scheme cannot be empty. - final String scheme; - - /** - * Returns the authority component. - * - * The authority is formatted from the [userInfo], [host] and [port] - * parts. - * - * Returns the empty string if there is no authority component. - */ - String get authority { - if (!hasAuthority) return ""; - var sb = new StringBuffer(); - _writeAuthority(sb); - return sb.toString(); - } - - /** - * The user-info part of the authority. - * - * Does not distinguish between an empty user-info and an absent one. - * The value is always non-null. - */ - final String _userInfo; - - /** - * Returns the user info part of the authority component. - * - * Returns the empty string if there is no user info in the - * authority component. - */ - String get userInfo => _userInfo; - - /** - * Returns the host part of the authority component. - * - * Returns the empty string if there is no authority component and - * hence no host. - * - * If the host is an IP version 6 address, the surrounding `[` and `]` is - * removed. - */ - String get host { - if (_host == null) return ""; - if (_host.startsWith('[')) { - return _host.substring(1, _host.length - 1); - } - return _host; - } - - /** - * Returns the port part of the authority component. - * - * Returns the defualt port if there is no port number in the authority - * component. That's 80 for http, 443 for https, and 0 for everything else. - */ - int get port { - if (_port == null) return _defaultPort(scheme); - return _port; - } - - // The default port for the scheme of this Uri.. - static int _defaultPort(String scheme) { - if (scheme == "http") return 80; - if (scheme == "https") return 443; - return 0; - } - - /** - * Returns the path component. - * - * The returned path is encoded. To get direct access to the decoded - * path use [pathSegments]. - * - * Returns the empty string if there is no path component. - */ - String get path => _path; - - // The query content, or null if there is no query. - final String _query; - - /** - * Returns the query component. The returned query is encoded. To get - * direct access to the decoded query use [queryParameters]. - * - * Returns the empty string if there is no query component. - */ - String get query => (_query == null) ? "" : _query; - - // The fragment content, or null if there is no fragment. - final String _fragment; - - /** - * Returns the fragment identifier component. - * - * Returns the empty string if there is no fragment identifier - * component. - */ - String get fragment => (_fragment == null) ? "" : _fragment; - - /** - * Cache the computed return value of [pathSegements]. - */ - List _pathSegments; - - /** - * Cache the computed return value of [queryParameters]. - */ - Map _queryParameters; - - /** - * Creates a new `Uri` object by parsing a URI string. - * - * If the string is not valid as a URI or URI reference, - * invalid characters will be percent escaped where possible. - * The resulting `Uri` will represent a valid URI or URI reference. - */ - static Uri parse(String uri) { - // This parsing will not validate percent-encoding, IPv6, etc. When done - // it will call `new Uri(...)` which will perform these validations. - // This is purely splitting up the URI string into components. - // - // Important parts of the RFC 3986 used here: - // URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] - // - // hier-part = "//" authority path-abempty - // / path-absolute - // / path-rootless - // / path-empty - // - // URI-reference = URI / relative-ref - // - // absolute-URI = scheme ":" hier-part [ "?" query ] - // - // relative-ref = relative-part [ "?" query ] [ "#" fragment ] - // - // relative-part = "//" authority path-abempty - // / path-absolute - // / path-noscheme - // / path-empty - // - // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - // - // authority = [ userinfo "@" ] host [ ":" port ] - // userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) - // host = IP-literal / IPv4address / reg-name - // port = *DIGIT - // reg-name = *( unreserved / pct-encoded / sub-delims ) - // - // path = path-abempty ; begins with "/" or is empty - // / path-absolute ; begins with "/" but not "//" - // / path-noscheme ; begins with a non-colon segment - // / path-rootless ; begins with a segment - // / path-empty ; zero characters - // - // path-abempty = *( "/" segment ) - // path-absolute = "/" [ segment-nz *( "/" segment ) ] - // path-noscheme = segment-nz-nc *( "/" segment ) - // path-rootless = segment-nz *( "/" segment ) - // path-empty = 0 - // - // segment = *pchar - // segment-nz = 1*pchar - // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) - // ; non-zero-length segment without any colon ":" - // - // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - // - // query = *( pchar / "/" / "?" ) - // - // fragment = *( pchar / "/" / "?" ) - bool isRegName(int ch) { - return ch < 128 && ((_regNameTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); - } - const int EOI = -1; - - String scheme = ""; - String userinfo = ""; - String host = null; - num port = null; - String path = null; - String query = null; - String fragment = null; - - int index = 0; - int pathStart = 0; - // End of input-marker. - int char = EOI; - - void parseAuth() { - if (index == uri.length) { - char = EOI; - return; - } - int authStart = index; - int lastColon = -1; - int lastAt = -1; - char = uri.codeUnitAt(index); - while (index < uri.length) { - char = uri.codeUnitAt(index); - if (char == _SLASH || char == _QUESTION || char == _NUMBER_SIGN) { - break; - } - if (char == _AT_SIGN) { - lastAt = index; - lastColon = -1; - } else if (char == _COLON) { - lastColon = index; - } else if (char == _LEFT_BRACKET) { - lastColon = -1; - int endBracket = uri.indexOf(']', index + 1); - if (endBracket == -1) { - index = uri.length; - char = EOI; - break; - } else { - index = endBracket; - } - } - index++; - char = EOI; - } - int hostStart = authStart; - int hostEnd = index; - if (lastAt >= 0) { - userinfo = _makeUserInfo(uri, authStart, lastAt); - hostStart = lastAt + 1; - } - if (lastColon >= 0) { - int portNumber; - if (lastColon + 1 < index) { - portNumber = 0; - for (int i = lastColon + 1; i < index; i++) { - int digit = uri.codeUnitAt(i); - if (_ZERO > digit || _NINE < digit) { - _fail(uri, i, "Invalid port number"); - } - portNumber = portNumber * 10 + (digit - _ZERO); - } - } - port = _makePort(portNumber, scheme); - hostEnd = lastColon; - } - host = _makeHost(uri, hostStart, hostEnd, true); - if (index < uri.length) { - char = uri.codeUnitAt(index); - } - } - - // When reaching path parsing, the current character is known to not - // be part of the path. - const int NOT_IN_PATH = 0; - // When reaching path parsing, the current character is part - // of the a non-empty path. - const int IN_PATH = 1; - // When reaching authority parsing, authority is possible. - // This is only true at start or right after scheme. - const int ALLOW_AUTH = 2; - - // Current state. - // Initialized to the default value that is used when exiting the - // scheme loop by reaching the end of input. - // All other breaks set their own state. - int state = NOT_IN_PATH; - int i = index; // Temporary alias for index to avoid bug 19550 in dart2js. - while (i < uri.length) { - char = uri.codeUnitAt(i); - if (char == _QUESTION || char == _NUMBER_SIGN) { - state = NOT_IN_PATH; - break; - } - if (char == _SLASH) { - state = (i == 0) ? ALLOW_AUTH : IN_PATH; - break; - } - if (char == _COLON) { - if (i == 0) _fail(uri, 0, "Invalid empty scheme"); - scheme = _makeScheme(uri, i); - i++; - pathStart = i; - if (i == uri.length) { - char = EOI; - state = NOT_IN_PATH; - } else { - char = uri.codeUnitAt(i); - if (char == _QUESTION || char == _NUMBER_SIGN) { - state = NOT_IN_PATH; - } else if (char == _SLASH) { - state = ALLOW_AUTH; - } else { - state = IN_PATH; - } - } - break; - } - i++; - char = EOI; - } - index = i; // Remove alias when bug is fixed. - - if (state == ALLOW_AUTH) { - assert(char == _SLASH); - // Have seen one slash either at start or right after scheme. - // If two slashes, it's an authority, otherwise it's just the path. - index++; - if (index == uri.length) { - char = EOI; - state = NOT_IN_PATH; - } else { - char = uri.codeUnitAt(index); - if (char == _SLASH) { - index++; - parseAuth(); - pathStart = index; - } - if (char == _QUESTION || char == _NUMBER_SIGN || char == EOI) { - state = NOT_IN_PATH; - } else { - state = IN_PATH; - } - } - } - - assert(state == IN_PATH || state == NOT_IN_PATH); - if (state == IN_PATH) { - // Characters from pathStart to index (inclusive) are known - // to be part of the path. - while (++index < uri.length) { - char = uri.codeUnitAt(index); - if (char == _QUESTION || char == _NUMBER_SIGN) { - break; - } - char = EOI; - } - state = NOT_IN_PATH; - } - - assert(state == NOT_IN_PATH); - bool isFile = (scheme == "file"); - bool ensureLeadingSlash = host != null; - path = _makePath(uri, pathStart, index, null, ensureLeadingSlash, isFile); - - if (char == _QUESTION) { - int numberSignIndex = uri.indexOf('#', index + 1); - if (numberSignIndex < 0) { - query = _makeQuery(uri, index + 1, uri.length, null); - } else { - query = _makeQuery(uri, index + 1, numberSignIndex, null); - fragment = _makeFragment(uri, numberSignIndex + 1, uri.length); - } - } else if (char == _NUMBER_SIGN) { - fragment = _makeFragment(uri, index + 1, uri.length); - } - return new Uri._internal(scheme, - userinfo, - host, - port, - path, - query, - fragment); - } - - // Report a parse failure. - static void _fail(String uri, int index, String message) { - throw new FormatException(message, uri, index); - } - - /// Internal non-verifying constructor. Only call with validated arguments. - Uri._internal(this.scheme, - this._userInfo, - this._host, - this._port, - this._path, - this._query, - this._fragment); - - /** - * Creates a new URI from its components. - * - * Each component is set through a named argument. Any number of - * components can be provided. The [path] and [query] components can be set - * using either of two different named arguments. - * - * The scheme component is set through [scheme]. The scheme is - * normalized to all lowercase letters. If the scheme is omitted or empty, - * the URI will not have a scheme part. - * - * The user info part of the authority component is set through - * [userInfo]. It defaults to the empty string, which will be omitted - * from the string representation of the URI. - * - * The host part of the authority component is set through - * [host]. The host can either be a hostname, an IPv4 address or an - * IPv6 address, contained in '[' and ']'. If the host contains a - * ':' character, the '[' and ']' are added if not already provided. - * The host is normalized to all lowercase letters. - * - * The port part of the authority component is set through - * [port]. - * If [port] is omitted or `null`, it implies the default port for - * the URI's scheme, and is equivalent to passing that port explicitly. - * The recognized schemes, and their default ports, are "http" (80) and - * "https" (443). All other schemes are considered as having zero as the - * default port. - * - * If any of `userInfo`, `host` or `port` are provided, - * the URI will have an autority according to [hasAuthority]. - * - * The path component is set through either [path] or - * [pathSegments]. When [path] is used, it should be a valid URI path, - * but invalid characters, except the general delimiters ':/@[]?#', - * will be escaped if necessary. - * When [pathSegments] is used, each of the provided segments - * is first percent-encoded and then joined using the forward slash - * separator. The percent-encoding of the path segments encodes all - * characters except for the unreserved characters and the following - * list of characters: `!$&'()*+,;=:@`. If the other components - * calls for an absolute path a leading slash `/` is prepended if - * not already there. - * - * The query component is set through either [query] or - * [queryParameters]. When [query] is used the provided string should - * be a valid URI query, but invalid characters other than general delimiters, - * will be escaped if necessary. - * When [queryParameters] is used the query is built from the - * provided map. Each key and value in the map is percent-encoded - * and joined using equal and ampersand characters. The - * percent-encoding of the keys and values encodes all characters - * except for the unreserved characters. - * If `query` is the empty string, it is equivalent to omitting it. - * To have an actual empty query part, - * use an empty list for `queryParameters`. - * If both `query` and `queryParameters` are omitted or `null`, the - * URI will have no query part. - * - * The fragment component is set through [fragment]. - * It should be a valid URI fragment, but invalid characters other than - * general delimiters, will be escaped if necessary. - * If `fragment` is omitted or `null`, the URI will have no fragment part. - */ - factory Uri({String scheme : "", - String userInfo : "", - String host, - int port, - String path, - Iterable pathSegments, - String query, - Map queryParameters, - String fragment}) { - scheme = _makeScheme(scheme, _stringOrNullLength(scheme)); - userInfo = _makeUserInfo(userInfo, 0, _stringOrNullLength(userInfo)); - host = _makeHost(host, 0, _stringOrNullLength(host), false); - // Special case this constructor for backwards compatibility. - if (query == "") query = null; - query = _makeQuery(query, 0, _stringOrNullLength(query), queryParameters); - fragment = _makeFragment(fragment, 0, _stringOrNullLength(fragment)); - port = _makePort(port, scheme); - bool isFile = (scheme == "file"); - if (host == null && - (userInfo.isNotEmpty || port != null || isFile)) { - host = ""; - } - bool ensureLeadingSlash = host != null; - path = _makePath(path, 0, _stringOrNullLength(path), pathSegments, - ensureLeadingSlash, isFile); - return new Uri._internal(scheme, userInfo, host, port, - path, query, fragment); - } - - /** - * Creates a new `http` URI from authority, path and query. - * - * Examples: - * - * ``` - * // http://example.org/path?q=dart. - * new Uri.http("google.com", "/search", { "q" : "dart" }); - * - * // http://user:pass@localhost:8080 - * new Uri.http("user:pass@localhost:8080", ""); - * - * // http://example.org/a%20b - * new Uri.http("example.org", "a b"); - * - * // http://example.org/a%252F - * new Uri.http("example.org", "/a%2F"); - * ``` - * - * The `scheme` is always set to `http`. - * - * The `userInfo`, `host` and `port` components are set from the - * [authority] argument. If `authority` is `null` or empty, - * the created `Uri` will have no authority, and will not be directly usable - * as an HTTP URL, which must have a non-empty host. - * - * The `path` component is set from the [unencodedPath] - * argument. The path passed must not be encoded as this constructor - * encodes the path. - * - * The `query` component is set from the optional [queryParameters] - * argument. - */ - factory Uri.http(String authority, - String unencodedPath, - [Map queryParameters]) { - return _makeHttpUri("http", authority, unencodedPath, queryParameters); - } - - /** - * Creates a new `https` URI from authority, path and query. - * - * This constructor is the same as [Uri.http] except for the scheme - * which is set to `https`. - */ - factory Uri.https(String authority, - String unencodedPath, - [Map queryParameters]) { - return _makeHttpUri("https", authority, unencodedPath, queryParameters); - } - - static Uri _makeHttpUri(String scheme, - String authority, - String unencodedPath, - Map queryParameters) { - var userInfo = ""; - var host = null; - var port = null; - - if (authority != null && authority.isNotEmpty) { - var hostStart = 0; - // Split off the user info. - bool hasUserInfo = false; - for (int i = 0; i < authority.length; i++) { - if (authority.codeUnitAt(i) == _AT_SIGN) { - hasUserInfo = true; - userInfo = authority.substring(0, i); - hostStart = i + 1; - break; - } - } - var hostEnd = hostStart; - if (hostStart < authority.length && - authority.codeUnitAt(hostStart) == _LEFT_BRACKET) { - // IPv6 host. - for (; hostEnd < authority.length; hostEnd++) { - if (authority.codeUnitAt(hostEnd) == _RIGHT_BRACKET) break; - } - if (hostEnd == authority.length) { - throw new FormatException("Invalid IPv6 host entry.", - authority, hostStart); - } - parseIPv6Address(authority, hostStart + 1, hostEnd); - hostEnd++; // Skip the closing bracket. - if (hostEnd != authority.length && - authority.codeUnitAt(hostEnd) != _COLON) { - throw new FormatException("Invalid end of authority", - authority, hostEnd); - } - } - // Split host and port. - bool hasPort = false; - for (; hostEnd < authority.length; hostEnd++) { - if (authority.codeUnitAt(hostEnd) == _COLON) { - var portString = authority.substring(hostEnd + 1); - // We allow the empty port - falling back to initial value. - if (portString.isNotEmpty) port = int.parse(portString); - break; - } - } - host = authority.substring(hostStart, hostEnd); - } - return new Uri(scheme: scheme, - userInfo: userInfo, - host: host, - port: port, - pathSegments: unencodedPath.split("/"), - queryParameters: queryParameters); - } - - /** - * Creates a new file URI from an absolute or relative file path. - * - * The file path is passed in [path]. - * - * This path is interpreted using either Windows or non-Windows - * semantics. - * - * With non-Windows semantics the slash ("/") is used to separate - * path segments. - * - * With Windows semantics, backslash ("\") and forward-slash ("/") - * are used to separate path segments, except if the path starts - * with "\\?\" in which case, only backslash ("\") separates path - * segments. - * - * If the path starts with a path separator an absolute URI is - * created. Otherwise a relative URI is created. One exception from - * this rule is that when Windows semantics is used and the path - * starts with a drive letter followed by a colon (":") and a - * path separator then an absolute URI is created. - * - * The default for whether to use Windows or non-Windows semantics - * determined from the platform Dart is running on. When running in - * the standalone VM this is detected by the VM based on the - * operating system. When running in a browser non-Windows semantics - * is always used. - * - * To override the automatic detection of which semantics to use pass - * a value for [windows]. Passing `true` will use Windows - * semantics and passing `false` will use non-Windows semantics. - * - * Examples using non-Windows semantics: - * - * ``` - * // xxx/yyy - * new Uri.file("xxx/yyy", windows: false); - * - * // xxx/yyy/ - * new Uri.file("xxx/yyy/", windows: false); - * - * // file:///xxx/yyy - * new Uri.file("/xxx/yyy", windows: false); - * - * // file:///xxx/yyy/ - * new Uri.file("/xxx/yyy/", windows: false); - * - * // C: - * new Uri.file("C:", windows: false); - * ``` - * - * Examples using Windows semantics: - * - * ``` - * // xxx/yyy - * new Uri.file(r"xxx\yyy", windows: true); - * - * // xxx/yyy/ - * new Uri.file(r"xxx\yyy\", windows: true); - * - * file:///xxx/yyy - * new Uri.file(r"\xxx\yyy", windows: true); - * - * file:///xxx/yyy/ - * new Uri.file(r"\xxx\yyy/", windows: true); - * - * // file:///C:/xxx/yyy - * new Uri.file(r"C:\xxx\yyy", windows: true); - * - * // This throws an error. A path with a drive letter is not absolute. - * new Uri.file(r"C:", windows: true); - * - * // This throws an error. A path with a drive letter is not absolute. - * new Uri.file(r"C:xxx\yyy", windows: true); - * - * // file://server/share/file - * new Uri.file(r"\\server\share\file", windows: true); - * ``` - * - * If the path passed is not a legal file path [ArgumentError] is thrown. - */ - factory Uri.file(String path, {bool windows}) { - windows = windows == null ? Uri._isWindows : windows; - return windows ? _makeWindowsFileUrl(path) : _makeFileUri(path); - } - - /** - * Returns the natural base URI for the current platform. - * - * When running in a browser this is the current URL (from - * `window.location.href`). - * - * When not running in a browser this is the file URI referencing - * the current working directory. - */ - static Uri get base { - String uri = Primitives.currentUri(); - if (uri != null) return Uri.parse(uri); - throw new UnsupportedError("'Uri.base' is not supported"); - } - - static bool get _isWindows => false; - - static _checkNonWindowsPathReservedCharacters(List segments, - bool argumentError) { - segments.forEach((segment) { - if (segment.contains("/")) { - if (argumentError) { - throw new ArgumentError("Illegal path character $segment"); - } else { - throw new UnsupportedError("Illegal path character $segment"); - } - } - }); - } - - static _checkWindowsPathReservedCharacters(List segments, - bool argumentError, - [int firstSegment = 0]) { - segments.skip(firstSegment).forEach((segment) { - if (segment.contains(new RegExp(r'["*/:<>?\\|]'))) { - if (argumentError) { - throw new ArgumentError("Illegal character in path"); - } else { - throw new UnsupportedError("Illegal character in path"); - } - } - }); - } - - static _checkWindowsDriveLetter(int charCode, bool argumentError) { - if ((_UPPER_CASE_A <= charCode && charCode <= _UPPER_CASE_Z) || - (_LOWER_CASE_A <= charCode && charCode <= _LOWER_CASE_Z)) { - return; - } - if (argumentError) { - throw new ArgumentError("Illegal drive letter " + - new String.fromCharCode(charCode)); - } else { - throw new UnsupportedError("Illegal drive letter " + - new String.fromCharCode(charCode)); - } - } - - static _makeFileUri(String path) { - String sep = "/"; - if (path.startsWith(sep)) { - // Absolute file:// URI. - return new Uri(scheme: "file", pathSegments: path.split(sep)); - } else { - // Relative URI. - return new Uri(pathSegments: path.split(sep)); - } - } - - static _makeWindowsFileUrl(String path) { - if (path.startsWith("\\\\?\\")) { - if (path.startsWith("\\\\?\\UNC\\")) { - path = "\\${path.substring(7)}"; - } else { - path = path.substring(4); - if (path.length < 3 || - path.codeUnitAt(1) != _COLON || - path.codeUnitAt(2) != _BACKSLASH) { - throw new ArgumentError( - "Windows paths with \\\\?\\ prefix must be absolute"); - } - } - } else { - path = path.replaceAll("/", "\\"); - } - String sep = "\\"; - if (path.length > 1 && path[1] == ":") { - _checkWindowsDriveLetter(path.codeUnitAt(0), true); - if (path.length == 2 || path.codeUnitAt(2) != _BACKSLASH) { - throw new ArgumentError( - "Windows paths with drive letter must be absolute"); - } - // Absolute file://C:/ URI. - var pathSegments = path.split(sep); - _checkWindowsPathReservedCharacters(pathSegments, true, 1); - return new Uri(scheme: "file", pathSegments: pathSegments); - } - - if (path.length > 0 && path[0] == sep) { - if (path.length > 1 && path[1] == sep) { - // Absolute file:// URI with host. - int pathStart = path.indexOf("\\", 2); - String hostPart = - pathStart == -1 ? path.substring(2) : path.substring(2, pathStart); - String pathPart = - pathStart == -1 ? "" : path.substring(pathStart + 1); - var pathSegments = pathPart.split(sep); - _checkWindowsPathReservedCharacters(pathSegments, true); - return new Uri( - scheme: "file", host: hostPart, pathSegments: pathSegments); - } else { - // Absolute file:// URI. - var pathSegments = path.split(sep); - _checkWindowsPathReservedCharacters(pathSegments, true); - return new Uri(scheme: "file", pathSegments: pathSegments); - } - } else { - // Relative URI. - var pathSegments = path.split(sep); - _checkWindowsPathReservedCharacters(pathSegments, true); - return new Uri(pathSegments: pathSegments); - } - } - - /** - * Returns a new `Uri` based on this one, but with some parts replaced. - * - * This method takes the same parameters as the [new Uri] constructor, - * and they have the same meaning. - * - * At most one of [path] and [pathSegments] must be provided. - * Likewise, at most one of [query] and [queryParameters] must be provided. - * - * Each part that is not provided will default to the corresponding - * value from this `Uri` instead. - * - * This method is different from [Uri.resolve] which overrides in a - * hierarchial manner, - * and can instead replace each part of a `Uri` individually. - * - * Example: - * - * Uri uri1 = Uri.parse("a://b@c:4/d/e?f#g"); - * Uri uri2 = uri1.replace(scheme: "A", path: "D/E/E", fragment: "G"); - * print(uri2); // prints "A://b@c:4/D/E/E/?f#G" - * - * This method acts similarly to using the `new Uri` constructor with - * some of the arguments taken from this `Uri` . Example: - * - * Uri uri3 = new Uri( - * scheme: "A", - * userInfo: uri1.userInfo, - * host: uri1.host, - * port: uri1.port, - * path: "D/E/E", - * query: uri1.query, - * fragment: "G"); - * print(uri3); // prints "A://b@c:4/D/E/E/?f#G" - * print(uri2 == uri3); // prints true. - * - * Using this method can be seen as a shorthand for the `Uri` constructor - * call above, but may also be slightly faster because the parts taken - * from this `Uri` need not be checked for validity again. - */ - Uri replace({String scheme, - String userInfo, - String host, - int port, - String path, - Iterable pathSegments, - String query, - Map queryParameters, - String fragment}) { - // Set to true if the scheme has (potentially) changed. - // In that case, the default port may also have changed and we need - // to check even the existing port. - bool schemeChanged = false; - if (scheme != null) { - scheme = _makeScheme(scheme, scheme.length); - schemeChanged = true; - } else { - scheme = this.scheme; - } - bool isFile = (scheme == "file"); - if (userInfo != null) { - userInfo = _makeUserInfo(userInfo, 0, userInfo.length); - } else { - userInfo = this.userInfo; - } - if (port != null) { - port = _makePort(port, scheme); - } else { - port = this._port; - if (schemeChanged) { - // The default port might have changed. - port = _makePort(port, scheme); - } - } - if (host != null) { - host = _makeHost(host, 0, host.length, false); - } else if (this.hasAuthority) { - host = this.host; - } else if (userInfo.isNotEmpty || port != null || isFile) { - host = ""; - } - - bool ensureLeadingSlash = (host != null); - if (path != null || pathSegments != null) { - path = _makePath(path, 0, _stringOrNullLength(path), pathSegments, - ensureLeadingSlash, isFile); - } else { - path = this.path; - if ((isFile || (ensureLeadingSlash && !path.isEmpty)) && - !path.startsWith('/')) { - path = "/$path"; - } - } - - if (query != null || queryParameters != null) { - query = _makeQuery(query, 0, _stringOrNullLength(query), queryParameters); - } else if (this.hasQuery) { - query = this.query; - } - - if (fragment != null) { - fragment = _makeFragment(fragment, 0, fragment.length); - } else if (this.hasFragment) { - fragment = this.fragment; - } - - return new Uri._internal( - scheme, userInfo, host, port, path, query, fragment); - } - - /** - * Returns the URI path split into its segments. Each of the - * segments in the returned list have been decoded. If the path is - * empty the empty list will be returned. A leading slash `/` does - * not affect the segments returned. - * - * The returned list is unmodifiable and will throw [UnsupportedError] on any - * calls that would mutate it. - */ - List get pathSegments { - if (_pathSegments == null) { - var pathToSplit = !path.isEmpty && path.codeUnitAt(0) == _SLASH - ? path.substring(1) - : path; - _pathSegments = new UnmodifiableListView( - pathToSplit == "" ? const[] - : new List.from( - pathToSplit.split("/") - .map(Uri.decodeComponent), - growable: false)); - } - return _pathSegments; - } - - /** - * Returns the URI query split into a map according to the rules - * specified for FORM post in the [HTML 4.01 specification section 17.13.4] - * (http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4 - * "HTML 4.01 section 17.13.4"). Each key and value in the returned map - * has been decoded. If there is no query the empty map is returned. - * - * Keys in the query string that have no value are mapped to the - * empty string. - * - * The returned map is unmodifiable and will throw [UnsupportedError] on any - * calls that would mutate it. - */ - Map get queryParameters { - if (_queryParameters == null) { - _queryParameters = new UnmodifiableMapView(splitQueryString(query)); - } - return _queryParameters; - } - - static int _makePort(int port, String scheme) { - // Perform scheme specific normalization. - if (port != null && port == _defaultPort(scheme)) return null; - return port; - } - - /** - * Check and normalize a most name. - * - * If the host name starts and ends with '[' and ']', it is considered an - * IPv6 address. If [strictIPv6] is false, the address is also considered - * an IPv6 address if it contains any ':' character. - * - * If it is not an IPv6 address, it is case- and escape-normalized. - * This escapes all characters not valid in a reg-name, - * and converts all non-escape upper-case letters to lower-case. - */ - static String _makeHost(String host, int start, int end, bool strictIPv6) { - // TODO(lrn): Should we normalize IPv6 addresses according to RFC 5952? - if (host == null) return null; - if (start == end) return ""; - // Host is an IPv6 address if it starts with '[' or contains a colon. - if (host.codeUnitAt(start) == _LEFT_BRACKET) { - if (host.codeUnitAt(end - 1) != _RIGHT_BRACKET) { - _fail(host, start, 'Missing end `]` to match `[` in host'); - } - parseIPv6Address(host, start + 1, end - 1); - // RFC 5952 requires hex digits to be lower case. - return host.substring(start, end).toLowerCase(); - } - if (!strictIPv6) { - // TODO(lrn): skip if too short to be a valid IPv6 address? - for (int i = start; i < end; i++) { - if (host.codeUnitAt(i) == _COLON) { - parseIPv6Address(host, start, end); - return '[$host]'; - } - } - } - return _normalizeRegName(host, start, end); - } - - static bool _isRegNameChar(int char) { - return char < 127 && (_regNameTable[char >> 4] & (1 << (char & 0xf))) != 0; - } - - /** - * Validates and does case- and percent-encoding normalization. - * - * The [host] must be an RFC3986 "reg-name". It is converted - * to lower case, and percent escapes are converted to either - * lower case unreserved characters or upper case escapes. - */ - static String _normalizeRegName(String host, int start, int end) { - StringBuffer buffer; - int sectionStart = start; - int index = start; - // Whether all characters between sectionStart and index are normalized, - bool isNormalized = true; - - while (index < end) { - int char = host.codeUnitAt(index); - if (char == _PERCENT) { - // The _regNameTable contains "%", so we check that first. - String replacement = _normalizeEscape(host, index, true); - if (replacement == null && isNormalized) { - index += 3; - continue; - } - if (buffer == null) buffer = new StringBuffer(); - String slice = host.substring(sectionStart, index); - if (!isNormalized) slice = slice.toLowerCase(); - buffer.write(slice); - int sourceLength = 3; - if (replacement == null) { - replacement = host.substring(index, index + 3); - } else if (replacement == "%") { - replacement = "%25"; - sourceLength = 1; - } - buffer.write(replacement); - index += sourceLength; - sectionStart = index; - isNormalized = true; - } else if (_isRegNameChar(char)) { - if (isNormalized && _UPPER_CASE_A <= char && _UPPER_CASE_Z >= char) { - // Put initial slice in buffer and continue in non-normalized mode - if (buffer == null) buffer = new StringBuffer(); - if (sectionStart < index) { - buffer.write(host.substring(sectionStart, index)); - sectionStart = index; - } - isNormalized = false; - } - index++; - } else if (_isGeneralDelimiter(char)) { - _fail(host, index, "Invalid character"); - } else { - int sourceLength = 1; - if ((char & 0xFC00) == 0xD800 && (index + 1) < end) { - int tail = host.codeUnitAt(index + 1); - if ((tail & 0xFC00) == 0xDC00) { - char = 0x10000 | ((char & 0x3ff) << 10) | (tail & 0x3ff); - sourceLength = 2; - } - } - if (buffer == null) buffer = new StringBuffer(); - String slice = host.substring(sectionStart, index); - if (!isNormalized) slice = slice.toLowerCase(); - buffer.write(slice); - buffer.write(_escapeChar(char)); - index += sourceLength; - sectionStart = index; - } - } - if (buffer == null) return host.substring(start, end); - if (sectionStart < end) { - String slice = host.substring(sectionStart, end); - if (!isNormalized) slice = slice.toLowerCase(); - buffer.write(slice); - } - return buffer.toString(); - } - - /** - * Validates scheme characters and does case-normalization. - * - * Schemes are converted to lower case. They cannot contain escapes. - */ - static String _makeScheme(String scheme, int end) { - if (end == 0) return ""; - final int firstCodeUnit = scheme.codeUnitAt(0); - if (!_isAlphabeticCharacter(firstCodeUnit)) { - _fail(scheme, 0, "Scheme not starting with alphabetic character"); - } - bool allLowercase = firstCodeUnit >= _LOWER_CASE_A; - for (int i = 0; i < end; i++) { - final int codeUnit = scheme.codeUnitAt(i); - if (!_isSchemeCharacter(codeUnit)) { - _fail(scheme, i, "Illegal scheme character"); - } - if (codeUnit < _LOWER_CASE_A || codeUnit > _LOWER_CASE_Z) { - allLowercase = false; - } - } - scheme = scheme.substring(0, end); - if (!allLowercase) scheme = scheme.toLowerCase(); - return scheme; - } - - static String _makeUserInfo(String userInfo, int start, int end) { - if (userInfo == null) return ""; - return _normalize(userInfo, start, end, _userinfoTable); - } - - static String _makePath(String path, int start, int end, - Iterable pathSegments, - bool ensureLeadingSlash, - bool isFile) { - if (path == null && pathSegments == null) return isFile ? "/" : ""; - if (path != null && pathSegments != null) { - throw new ArgumentError('Both path and pathSegments specified'); - } - var result; - if (path != null) { - result = _normalize(path, start, end, _pathCharOrSlashTable); - } else { - result = pathSegments.map((s) => _uriEncode(_pathCharTable, s)).join("/"); - } - if (result.isEmpty) { - if (isFile) return "/"; - } else if ((isFile || ensureLeadingSlash) && - result.codeUnitAt(0) != _SLASH) { - return "/$result"; - } - return result; - } - - static String _makeQuery(String query, int start, int end, - Map queryParameters) { - if (query == null && queryParameters == null) return null; - if (query != null && queryParameters != null) { - throw new ArgumentError('Both query and queryParameters specified'); - } - if (query != null) return _normalize(query, start, end, _queryCharTable); - - var result = new StringBuffer(); - var first = true; - queryParameters.forEach((key, value) { - if (!first) { - result.write("&"); - } - first = false; - result.write(Uri.encodeQueryComponent(key)); - if (value != null && !value.isEmpty) { - result.write("="); - result.write(Uri.encodeQueryComponent(value)); - } - }); - return result.toString(); - } - - static String _makeFragment(String fragment, int start, int end) { - if (fragment == null) return null; - return _normalize(fragment, start, end, _queryCharTable); - } - - static int _stringOrNullLength(String s) => (s == null) ? 0 : s.length; - - static bool _isHexDigit(int char) { - if (_NINE >= char) return _ZERO <= char; - char |= 0x20; - return _LOWER_CASE_A <= char && _LOWER_CASE_F >= char; - } - - static int _hexValue(int char) { - assert(_isHexDigit(char)); - if (_NINE >= char) return char - _ZERO; - char |= 0x20; - return char - (_LOWER_CASE_A - 10); - } - - /** - * Performs RFC 3986 Percent-Encoding Normalization. - * - * Returns a replacement string that should be replace the original escape. - * Returns null if no replacement is necessary because the escape is - * not for an unreserved character and is already non-lower-case. - * - * Returns "%" if the escape is invalid (not two valid hex digits following - * the percent sign). The calling code should replace the percent - * sign with "%25", but leave the following two characters unmodified. - * - * If [lowerCase] is true, a single character returned is always lower case, - */ - static String _normalizeEscape(String source, int index, bool lowerCase) { - assert(source.codeUnitAt(index) == _PERCENT); - if (index + 2 >= source.length) { - return "%"; // Marks the escape as invalid. - } - int firstDigit = source.codeUnitAt(index + 1); - int secondDigit = source.codeUnitAt(index + 2); - if (!_isHexDigit(firstDigit) || !_isHexDigit(secondDigit)) { - return "%"; // Marks the escape as invalid. - } - int value = _hexValue(firstDigit) * 16 + _hexValue(secondDigit); - if (_isUnreservedChar(value)) { - if (lowerCase && _UPPER_CASE_A <= value && _UPPER_CASE_Z >= value) { - value |= 0x20; - } - return new String.fromCharCode(value); - } - if (firstDigit >= _LOWER_CASE_A || secondDigit >= _LOWER_CASE_A) { - // Either digit is lower case. - return source.substring(index, index + 3).toUpperCase(); - } - // Escape is retained, and is already non-lower case, so return null to - // represent "no replacement necessary". - return null; - } - - static bool _isUnreservedChar(int ch) { - return ch < 127 && - ((_unreservedTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); - } - - static String _escapeChar(char) { - assert(char <= 0x10ffff); // It's a valid unicode code point. - const hexDigits = "0123456789ABCDEF"; - List codeUnits; - if (char < 0x80) { - // ASCII, a single percent encoded sequence. - codeUnits = new List(3); - codeUnits[0] = _PERCENT; - codeUnits[1] = hexDigits.codeUnitAt(char >> 4); - codeUnits[2] = hexDigits.codeUnitAt(char & 0xf); - } else { - // Do UTF-8 encoding of character, then percent encode bytes. - int flag = 0xc0; // The high-bit markers on the first byte of UTF-8. - int encodedBytes = 2; - if (char > 0x7ff) { - flag = 0xe0; - encodedBytes = 3; - if (char > 0xffff) { - encodedBytes = 4; - flag = 0xf0; - } - } - codeUnits = new List(3 * encodedBytes); - int index = 0; - while (--encodedBytes >= 0) { - int byte = ((char >> (6 * encodedBytes)) & 0x3f) | flag; - codeUnits[index] = _PERCENT; - codeUnits[index + 1] = hexDigits.codeUnitAt(byte >> 4); - codeUnits[index + 2] = hexDigits.codeUnitAt(byte & 0xf); - index += 3; - flag = 0x80; // Following bytes have only high bit set. - } - } - return new String.fromCharCodes(codeUnits); - } - - /** - * Runs through component checking that each character is valid and - * normalize percent escapes. - * - * Uses [charTable] to check if a non-`%` character is allowed. - * Each `%` character must be followed by two hex digits. - * If the hex-digits are lower case letters, they are converted to - * upper case. - */ - static String _normalize(String component, int start, int end, - List charTable) { - StringBuffer buffer; - int sectionStart = start; - int index = start; - // Loop while characters are valid and escapes correct and upper-case. - while (index < end) { - int char = component.codeUnitAt(index); - if (char < 127 && (charTable[char >> 4] & (1 << (char & 0x0f))) != 0) { - index++; - } else { - String replacement; - int sourceLength; - if (char == _PERCENT) { - replacement = _normalizeEscape(component, index, false); - // Returns null if we should keep the existing escape. - if (replacement == null) { - index += 3; - continue; - } - // Returns "%" if we should escape the existing percent. - if ("%" == replacement) { - replacement = "%25"; - sourceLength = 1; - } else { - sourceLength = 3; - } - } else if (_isGeneralDelimiter(char)) { - _fail(component, index, "Invalid character"); - } else { - sourceLength = 1; - if ((char & 0xFC00) == 0xD800) { - // Possible lead surrogate. - if (index + 1 < end) { - int tail = component.codeUnitAt(index + 1); - if ((tail & 0xFC00) == 0xDC00) { - // Tail surrogat. - sourceLength = 2; - char = 0x10000 | ((char & 0x3ff) << 10) | (tail & 0x3ff); - } - } - } - replacement = _escapeChar(char); - } - if (buffer == null) buffer = new StringBuffer(); - buffer.write(component.substring(sectionStart, index)); - buffer.write(replacement); - index += sourceLength; - sectionStart = index; - } - } - if (buffer == null) { - // Makes no copy if start == 0 and end == component.length. - return component.substring(start, end); - } - if (sectionStart < end) { - buffer.write(component.substring(sectionStart, end)); - } - return buffer.toString(); - } - - static bool _isSchemeCharacter(int ch) { - return ch < 128 && ((_schemeTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); - } - - static bool _isGeneralDelimiter(int ch) { - return ch <= _RIGHT_BRACKET && - ((_genDelimitersTable[ch >> 4] & (1 << (ch & 0x0f))) != 0); - } - - /** - * Returns whether the URI is absolute. - */ - bool get isAbsolute => scheme != "" && fragment == ""; - - String _merge(String base, String reference) { - if (base.isEmpty) return "/$reference"; - // Optimize for the case: absolute base, reference beginning with "../". - int backCount = 0; - int refStart = 0; - // Count number of "../" at beginning of reference. - while (reference.startsWith("../", refStart)) { - refStart += 3; - backCount++; - } - - // Drop last segment - everything after last '/' of base. - int baseEnd = base.lastIndexOf('/'); - // Drop extra segments for each leading "../" of reference. - while (baseEnd > 0 && backCount > 0) { - int newEnd = base.lastIndexOf('/', baseEnd - 1); - if (newEnd < 0) { - break; - } - int delta = baseEnd - newEnd; - // If we see a "." or ".." segment in base, stop here and let - // _removeDotSegments handle it. - if ((delta == 2 || delta == 3) && - base.codeUnitAt(newEnd + 1) == _DOT && - (delta == 2 || base.codeUnitAt(newEnd + 2) == _DOT)) { - break; - } - baseEnd = newEnd; - backCount--; - } - return base.substring(0, baseEnd + 1) + - reference.substring(refStart - 3 * backCount); - } - - bool _hasDotSegments(String path) { - if (path.length > 0 && path.codeUnitAt(0) == _DOT) return true; - int index = path.indexOf("/."); - return index != -1; - } - - String _removeDotSegments(String path) { - if (!_hasDotSegments(path)) return path; - List output = []; - bool appendSlash = false; - for (String segment in path.split("/")) { - appendSlash = false; - if (segment == "..") { - if (!output.isEmpty && - ((output.length != 1) || (output[0] != ""))) output.removeLast(); - appendSlash = true; - } else if ("." == segment) { - appendSlash = true; - } else { - output.add(segment); - } - } - if (appendSlash) output.add(""); - return output.join("/"); - } - - /** - * Resolve [reference] as an URI relative to `this`. - * - * First turn [reference] into a URI using [Uri.parse]. Then resolve the - * resulting URI relative to `this`. - * - * Returns the resolved URI. - * - * See [resolveUri] for details. - */ - Uri resolve(String reference) { - return resolveUri(Uri.parse(reference)); - } - - /** - * Resolve [reference] as an URI relative to `this`. - * - * Returns the resolved URI. - * - * The algorithm for resolving a reference is described in - * [RFC-3986 Section 5] - * (http://tools.ietf.org/html/rfc3986#section-5 "RFC-1123"). - */ - Uri resolveUri(Uri reference) { - // From RFC 3986. - String targetScheme; - String targetUserInfo = ""; - String targetHost; - int targetPort; - String targetPath; - String targetQuery; - if (reference.scheme.isNotEmpty) { - targetScheme = reference.scheme; - if (reference.hasAuthority) { - targetUserInfo = reference.userInfo; - targetHost = reference.host; - targetPort = reference.hasPort ? reference.port : null; - } - targetPath = _removeDotSegments(reference.path); - if (reference.hasQuery) { - targetQuery = reference.query; - } - } else { - targetScheme = this.scheme; - if (reference.hasAuthority) { - targetUserInfo = reference.userInfo; - targetHost = reference.host; - targetPort = _makePort(reference.hasPort ? reference.port : null, - targetScheme); - targetPath = _removeDotSegments(reference.path); - if (reference.hasQuery) targetQuery = reference.query; - } else { - if (reference.path == "") { - targetPath = this._path; - if (reference.hasQuery) { - targetQuery = reference.query; - } else { - targetQuery = this._query; - } - } else { - if (reference.path.startsWith("/")) { - targetPath = _removeDotSegments(reference.path); - } else { - targetPath = _removeDotSegments(_merge(this._path, reference.path)); - } - if (reference.hasQuery) targetQuery = reference.query; - } - targetUserInfo = this._userInfo; - targetHost = this._host; - targetPort = this._port; - } - } - String fragment = reference.hasFragment ? reference.fragment : null; - return new Uri._internal(targetScheme, - targetUserInfo, - targetHost, - targetPort, - targetPath, - targetQuery, - fragment); - } - - /** - * Returns whether the URI has an [authority] component. - */ - bool get hasAuthority => _host != null; - - /** - * Returns whether the URI has an explicit port. - * - * If the port number is the default port number - * (zero for unrecognized schemes, with http (80) and https (443) being - * recognized), - * then the port is made implicit and omitted from the URI. - */ - bool get hasPort => _port != null; - - /** - * Returns whether the URI has a query part. - */ - bool get hasQuery => _query != null; - - /** - * Returns whether the URI has a fragment part. - */ - bool get hasFragment => _fragment != null; - - /** - * Returns the origin of the URI in the form scheme://host:port for the - * schemes http and https. - * - * It is an error if the scheme is not "http" or "https". - * - * See: http://www.w3.org/TR/2011/WD-html5-20110405/origin-0.html#origin - */ - String get origin { - if (scheme == "" || _host == null || _host == "") { - throw new StateError("Cannot use origin without a scheme: $this"); - } - if (scheme != "http" && scheme != "https") { - throw new StateError( - "Origin is only applicable schemes http and https: $this"); - } - if (_port == null) return "$scheme://$_host"; - return "$scheme://$_host:$_port"; - } - - /** - * Returns the file path from a file URI. - * - * The returned path has either Windows or non-Windows - * semantics. - * - * For non-Windows semantics the slash ("/") is used to separate - * path segments. - * - * For Windows semantics the backslash ("\") separator is used to - * separate path segments. - * - * If the URI is absolute the path starts with a path separator - * unless Windows semantics is used and the first path segment is a - * drive letter. When Windows semantics is used a host component in - * the uri in interpreted as a file server and a UNC path is - * returned. - * - * The default for whether to use Windows or non-Windows semantics - * determined from the platform Dart is running on. When running in - * the standalone VM this is detected by the VM based on the - * operating system. When running in a browser non-Windows semantics - * is always used. - * - * To override the automatic detection of which semantics to use pass - * a value for [windows]. Passing `true` will use Windows - * semantics and passing `false` will use non-Windows semantics. - * - * If the URI ends with a slash (i.e. the last path component is - * empty) the returned file path will also end with a slash. - * - * With Windows semantics URIs starting with a drive letter cannot - * be relative to the current drive on the designated drive. That is - * for the URI `file:///c:abc` calling `toFilePath` will throw as a - * path segment cannot contain colon on Windows. - * - * Examples using non-Windows semantics (resulting of calling - * toFilePath in comment): - * - * Uri.parse("xxx/yyy"); // xxx/yyy - * Uri.parse("xxx/yyy/"); // xxx/yyy/ - * Uri.parse("file:///xxx/yyy"); // /xxx/yyy - * Uri.parse("file:///xxx/yyy/"); // /xxx/yyy/ - * Uri.parse("file:///C:"); // /C: - * Uri.parse("file:///C:a"); // /C:a - * - * Examples using Windows semantics (resulting URI in comment): - * - * Uri.parse("xxx/yyy"); // xxx\yyy - * Uri.parse("xxx/yyy/"); // xxx\yyy\ - * Uri.parse("file:///xxx/yyy"); // \xxx\yyy - * Uri.parse("file:///xxx/yyy/"); // \xxx\yyy/ - * Uri.parse("file:///C:/xxx/yyy"); // C:\xxx\yyy - * Uri.parse("file:C:xxx/yyy"); // Throws as a path segment - * // cannot contain colon on Windows. - * Uri.parse("file://server/share/file"); // \\server\share\file - * - * If the URI is not a file URI calling this throws - * [UnsupportedError]. - * - * If the URI cannot be converted to a file path calling this throws - * [UnsupportedError]. - */ - String toFilePath({bool windows}) { - if (scheme != "" && scheme != "file") { - throw new UnsupportedError( - "Cannot extract a file path from a $scheme URI"); - } - if (query != "") { - throw new UnsupportedError( - "Cannot extract a file path from a URI with a query component"); - } - if (fragment != "") { - throw new UnsupportedError( - "Cannot extract a file path from a URI with a fragment component"); - } - if (windows == null) windows = _isWindows; - return windows ? _toWindowsFilePath() : _toFilePath(); - } - - String _toFilePath() { - if (host != "") { - throw new UnsupportedError( - "Cannot extract a non-Windows file path from a file URI " - "with an authority"); - } - _checkNonWindowsPathReservedCharacters(pathSegments, false); - var result = new StringBuffer(); - if (_isPathAbsolute) result.write("/"); - result.writeAll(pathSegments, "/"); - return result.toString(); - } - - String _toWindowsFilePath() { - bool hasDriveLetter = false; - var segments = pathSegments; - if (segments.length > 0 && - segments[0].length == 2 && - segments[0].codeUnitAt(1) == _COLON) { - _checkWindowsDriveLetter(segments[0].codeUnitAt(0), false); - _checkWindowsPathReservedCharacters(segments, false, 1); - hasDriveLetter = true; - } else { - _checkWindowsPathReservedCharacters(segments, false); - } - var result = new StringBuffer(); - if (_isPathAbsolute && !hasDriveLetter) result.write("\\"); - if (host != "") { - result.write("\\"); - result.write(host); - result.write("\\"); - } - result.writeAll(segments, "\\"); - if (hasDriveLetter && segments.length == 1) result.write("\\"); - return result.toString(); - } - - bool get _isPathAbsolute { - if (path == null || path.isEmpty) return false; - return path.startsWith('/'); - } - - void _writeAuthority(StringSink ss) { - if (_userInfo.isNotEmpty) { - ss.write(_userInfo); - ss.write("@"); - } - if (_host != null) ss.write(_host); - if (_port != null) { - ss.write(":"); - ss.write(_port); - } - } - - String toString() { - StringBuffer sb = new StringBuffer(); - _addIfNonEmpty(sb, scheme, scheme, ':'); - if (hasAuthority || path.startsWith("//") || (scheme == "file")) { - // File URIS always have the authority, even if it is empty. - // The empty URI means "localhost". - sb.write("//"); - _writeAuthority(sb); - } - sb.write(path); - if (_query != null) { sb..write("?")..write(_query); } - if (_fragment != null) { sb..write("#")..write(_fragment); } - return sb.toString(); - } - - bool operator==(other) { - if (other is! Uri) return false; - Uri uri = other; - return scheme == uri.scheme && - hasAuthority == uri.hasAuthority && - userInfo == uri.userInfo && - host == uri.host && - port == uri.port && - path == uri.path && - hasQuery == uri.hasQuery && - query == uri.query && - hasFragment == uri.hasFragment && - fragment == uri.fragment; - } - - int get hashCode { - int combine(part, current) { - // The sum is truncated to 30 bits to make sure it fits into a Smi. - return (current * 31 + part.hashCode) & 0x3FFFFFFF; - } - return combine(scheme, combine(userInfo, combine(host, combine(port, - combine(path, combine(query, combine(fragment, 1))))))); - } - - static void _addIfNonEmpty(StringBuffer sb, String test, - String first, String second) { - if ("" != test) { - sb.write(first); - sb.write(second); - } - } - - /** - * Encode the string [component] using percent-encoding to make it - * safe for literal use as a URI component. - * - * All characters except uppercase and lowercase letters, digits and - * the characters `-_.!~*'()` are percent-encoded. This is the - * set of characters specified in RFC 2396 and the which is - * specified for the encodeUriComponent in ECMA-262 version 5.1. - * - * When manually encoding path segments or query components remember - * to encode each part separately before building the path or query - * string. - * - * For encoding the query part consider using - * [encodeQueryComponent]. - * - * To avoid the need for explicitly encoding use the [pathSegments] - * and [queryParameters] optional named arguments when constructing - * a [Uri]. - */ - static String encodeComponent(String component) { - return _uriEncode(_unreserved2396Table, component); - } - - /** - * Encode the string [component] according to the HTML 4.01 rules - * for encoding the posting of a HTML form as a query string - * component. - * - * Encode the string [component] according to the HTML 4.01 rules - * for encoding the posting of a HTML form as a query string - * component. - - * The component is first encoded to bytes using [encoding]. - * The default is to use [UTF8] encoding, which preserves all - * the characters that don't need encoding. - - * Then the resulting bytes are "percent-encoded". This transforms - * spaces (U+0020) to a plus sign ('+') and all bytes that are not - * the ASCII decimal digits, letters or one of '-._~' are written as - * a percent sign '%' followed by the two-digit hexadecimal - * representation of the byte. - - * Note that the set of characters which are percent-encoded is a - * superset of what HTML 4.01 requires, since it refers to RFC 1738 - * for reserved characters. - * - * When manually encoding query components remember to encode each - * part separately before building the query string. - * - * To avoid the need for explicitly encoding the query use the - * [queryParameters] optional named arguments when constructing a - * [Uri]. - * - * See http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 for more - * details. - */ - static String encodeQueryComponent(String component, - {Encoding encoding: UTF8}) { - return _uriEncode( - _unreservedTable, component, encoding: encoding, spaceToPlus: true); - } - - /** - * Decodes the percent-encoding in [encodedComponent]. - * - * Note that decoding a URI component might change its meaning as - * some of the decoded characters could be characters with are - * delimiters for a given URI componene type. Always split a URI - * component using the delimiters for the component before decoding - * the individual parts. - * - * For handling the [path] and [query] components consider using - * [pathSegments] and [queryParameters] to get the separated and - * decoded component. - */ - static String decodeComponent(String encodedComponent) { - return _uriDecode(encodedComponent); - } - - /** - * Decodes the percent-encoding in [encodedComponent], converting - * pluses to spaces. - * - * It will create a byte-list of the decoded characters, and then use - * [encoding] to decode the byte-list to a String. The default encoding is - * UTF-8. - */ - static String decodeQueryComponent( - String encodedComponent, - {Encoding encoding: UTF8}) { - return _uriDecode(encodedComponent, plusToSpace: true, encoding: encoding); - } - - /** - * Encode the string [uri] using percent-encoding to make it - * safe for literal use as a full URI. - * - * All characters except uppercase and lowercase letters, digits and - * the characters `!#$&'()*+,-./:;=?@_~` are percent-encoded. This - * is the set of characters specified in in ECMA-262 version 5.1 for - * the encodeURI function . - */ - static String encodeFull(String uri) { - return _uriEncode(_encodeFullTable, uri); - } - - /** - * Decodes the percent-encoding in [uri]. - * - * Note that decoding a full URI might change its meaning as some of - * the decoded characters could be reserved characters. In most - * cases an encoded URI should be parsed into components using - * [Uri.parse] before decoding the separate components. - */ - static String decodeFull(String uri) { - return _uriDecode(uri); - } - - /** - * Returns the [query] split into a map according to the rules - * specified for FORM post in the - * [HTML 4.01 specification section 17.13.4] - * (http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4 - * "HTML 4.01 section 17.13.4"). Each key and value in the returned - * map has been decoded. If the [query] - * is the empty string an empty map is returned. - * - * Keys in the query string that have no value are mapped to the - * empty string. - * - * Each query component will be decoded using [encoding]. The default encoding - * is UTF-8. - */ - static Map splitQueryString(String query, - {Encoding encoding: UTF8}) { - return query.split("&").fold({}, (map, element) { - int index = element.indexOf("="); - if (index == -1) { - if (element != "") { - map[decodeQueryComponent(element, encoding: encoding)] = ""; - } - } else if (index != 0) { - var key = element.substring(0, index); - var value = element.substring(index + 1); - map[Uri.decodeQueryComponent(key, encoding: encoding)] = - decodeQueryComponent(value, encoding: encoding); - } - return map; - }); - } - - /** - * Parse the [host] as an IP version 4 (IPv4) address, returning the address - * as a list of 4 bytes in network byte order (big endian). - * - * Throws a [FormatException] if [host] is not a valid IPv4 address - * representation. - */ - static List parseIPv4Address(String host) { - void error(String msg) { - throw new FormatException('Illegal IPv4 address, $msg'); - } - var bytes = host.split('.'); - if (bytes.length != 4) { - error('IPv4 address should contain exactly 4 parts'); - } - // TODO(ajohnsen): Consider using Uint8List. - return bytes - .map((byteString) { - int byte = int.parse(byteString); - if (byte < 0 || byte > 255) { - error('each part must be in the range of `0..255`'); - } - return byte; - }) - .toList(); - } - - /** - * Parse the [host] as an IP version 6 (IPv6) address, returning the address - * as a list of 16 bytes in network byte order (big endian). - * - * Throws a [FormatException] if [host] is not a valid IPv6 address - * representation. - * - * Acts on the substring from [start] to [end]. If [end] is omitted, it - * defaults ot the end of the string. - * - * Some examples of IPv6 addresses: - * * ::1 - * * FEDC:BA98:7654:3210:FEDC:BA98:7654:3210 - * * 3ffe:2a00:100:7031::1 - * * ::FFFF:129.144.52.38 - * * 2010:836B:4179::836B:4179 - */ - static List parseIPv6Address(String host, [int start = 0, int end]) { - if (end == null) end = host.length; - // An IPv6 address consists of exactly 8 parts of 1-4 hex digits, seperated - // by `:`'s, with the following exceptions: - // - // - One (and only one) wildcard (`::`) may be present, representing a fill - // of 0's. The IPv6 `::` is thus 16 bytes of `0`. - // - The last two parts may be replaced by an IPv4 address. - void error(String msg, [position]) { - throw new FormatException('Illegal IPv6 address, $msg', host, position); - } - int parseHex(int start, int end) { - if (end - start > 4) { - error('an IPv6 part can only contain a maximum of 4 hex digits', start); - } - int value = int.parse(host.substring(start, end), radix: 16); - if (value < 0 || value > (1 << 16) - 1) { - error('each part must be in the range of `0x0..0xFFFF`', start); - } - return value; - } - if (host.length < 2) error('address is too short'); - List parts = []; - bool wildcardSeen = false; - int partStart = start; - // Parse all parts, except a potential last one. - for (int i = start; i < end; i++) { - if (host.codeUnitAt(i) == _COLON) { - if (i == start) { - // If we see a `:` in the beginning, expect wildcard. - i++; - if (host.codeUnitAt(i) != _COLON) { - error('invalid start colon.', i); - } - partStart = i; - } - if (i == partStart) { - // Wildcard. We only allow one. - if (wildcardSeen) { - error('only one wildcard `::` is allowed', i); - } - wildcardSeen = true; - parts.add(-1); - } else { - // Found a single colon. Parse [partStart..i] as a hex entry. - parts.add(parseHex(partStart, i)); - } - partStart = i + 1; - } - } - if (parts.length == 0) error('too few parts'); - bool atEnd = (partStart == end); - bool isLastWildcard = (parts.last == -1); - if (atEnd && !isLastWildcard) { - error('expected a part after last `:`', end); - } - if (!atEnd) { - try { - parts.add(parseHex(partStart, end)); - } catch (e) { - // Failed to parse the last chunk as hex. Try IPv4. - try { - List last = parseIPv4Address(host.substring(partStart, end)); - parts.add(last[0] << 8 | last[1]); - parts.add(last[2] << 8 | last[3]); - } catch (e) { - error('invalid end of IPv6 address.', partStart); - } - } - } - if (wildcardSeen) { - if (parts.length > 7) { - error('an address with a wildcard must have less than 7 parts'); - } - } else if (parts.length != 8) { - error('an address without a wildcard must contain exactly 8 parts'); - } - // TODO(ajohnsen): Consider using Uint8List. - List bytes = new List(16); - for (int i = 0, index = 0; i < parts.length; i++) { - int value = parts[i]; - if (value == -1) { - int wildCardLength = 9 - parts.length; - for (int j = 0; j < wildCardLength; j++) { - bytes[index] = 0; - bytes[index + 1] = 0; - index += 2; - } - } else { - bytes[index] = value >> 8; - bytes[index + 1] = value & 0xff; - index += 2; - } - } - return bytes; - } - - // Frequently used character codes. - static const int _SPACE = 0x20; - static const int _DOUBLE_QUOTE = 0x22; - static const int _NUMBER_SIGN = 0x23; - static const int _PERCENT = 0x25; - static const int _ASTERISK = 0x2A; - static const int _PLUS = 0x2B; - static const int _DOT = 0x2E; - static const int _SLASH = 0x2F; - static const int _ZERO = 0x30; - static const int _NINE = 0x39; - static const int _COLON = 0x3A; - static const int _LESS = 0x3C; - static const int _GREATER = 0x3E; - static const int _QUESTION = 0x3F; - static const int _AT_SIGN = 0x40; - static const int _UPPER_CASE_A = 0x41; - static const int _UPPER_CASE_F = 0x46; - static const int _UPPER_CASE_Z = 0x5A; - static const int _LEFT_BRACKET = 0x5B; - static const int _BACKSLASH = 0x5C; - static const int _RIGHT_BRACKET = 0x5D; - static const int _LOWER_CASE_A = 0x61; - static const int _LOWER_CASE_F = 0x66; - static const int _LOWER_CASE_Z = 0x7A; - static const int _BAR = 0x7C; - - /** - * This is the internal implementation of JavaScript's encodeURI function. - * It encodes all characters in the string [text] except for those - * that appear in [canonicalTable], and returns the escaped string. - */ - static String _uriEncode(List canonicalTable, - String text, - {Encoding encoding: UTF8, - bool spaceToPlus: false}) { - byteToHex(byte, buffer) { - const String hex = '0123456789ABCDEF'; - buffer.writeCharCode(hex.codeUnitAt(byte >> 4)); - buffer.writeCharCode(hex.codeUnitAt(byte & 0x0f)); - } - - // Encode the string into bytes then generate an ASCII only string - // by percent encoding selected bytes. - StringBuffer result = new StringBuffer(); - var bytes = encoding.encode(text); - for (int i = 0; i < bytes.length; i++) { - int byte = bytes[i]; - if (byte < 128 && - ((canonicalTable[byte >> 4] & (1 << (byte & 0x0f))) != 0)) { - result.writeCharCode(byte); - } else if (spaceToPlus && byte == _SPACE) { - result.writeCharCode(_PLUS); - } else { - result.writeCharCode(_PERCENT); - byteToHex(byte, result); - } - } - return result.toString(); - } - - /** - * Convert a byte (2 character hex sequence) in string [s] starting - * at position [pos] to its ordinal value - */ - static int _hexCharPairToByte(String s, int pos) { - int byte = 0; - for (int i = 0; i < 2; i++) { - var charCode = s.codeUnitAt(pos + i); - if (0x30 <= charCode && charCode <= 0x39) { - byte = byte * 16 + charCode - 0x30; - } else { - // Check ranges A-F (0x41-0x46) and a-f (0x61-0x66). - charCode |= 0x20; - if (0x61 <= charCode && charCode <= 0x66) { - byte = byte * 16 + charCode - 0x57; - } else { - throw new ArgumentError("Invalid URL encoding"); - } - } - } - return byte; - } - - /** - * Uri-decode a percent-encoded string. - * - * It unescapes the string [text] and returns the unescaped string. - * - * This function is similar to the JavaScript-function `decodeURI`. - * - * If [plusToSpace] is `true`, plus characters will be converted to spaces. - * - * The decoder will create a byte-list of the percent-encoded parts, and then - * decode the byte-list using [encoding]. The default encodingis UTF-8. - */ - static String _uriDecode(String text, - {bool plusToSpace: false, - Encoding encoding: UTF8}) { - // First check whether there is any characters which need special handling. - bool simple = true; - for (int i = 0; i < text.length && simple; i++) { - var codeUnit = text.codeUnitAt(i); - simple = codeUnit != _PERCENT && codeUnit != _PLUS; - } - List bytes; - if (simple) { - if (encoding == UTF8 || encoding == LATIN1) { - return text; - } else { - bytes = text.codeUnits; - } - } else { - bytes = new List(); - for (int i = 0; i < text.length; i++) { - var codeUnit = text.codeUnitAt(i); - if (codeUnit > 127) { - throw new ArgumentError("Illegal percent encoding in URI"); - } - if (codeUnit == _PERCENT) { - if (i + 3 > text.length) { - throw new ArgumentError('Truncated URI'); - } - bytes.add(_hexCharPairToByte(text, i + 1)); - i += 2; - } else if (plusToSpace && codeUnit == _PLUS) { - bytes.add(_SPACE); - } else { - bytes.add(codeUnit); - } - } - } - return encoding.decode(bytes); - } - - static bool _isAlphabeticCharacter(int codeUnit) - => (codeUnit >= _LOWER_CASE_A && codeUnit <= _LOWER_CASE_Z) || - (codeUnit >= _UPPER_CASE_A && codeUnit <= _UPPER_CASE_Z); - - // Tables of char-codes organized as a bit vector of 128 bits where - // each bit indicate whether a character code on the 0-127 needs to - // be escaped or not. - - // The unreserved characters of RFC 3986. - static const _unreservedTable = const [ - // LSB MSB - // | | - 0x0000, // 0x00 - 0x0f 0000000000000000 - 0x0000, // 0x10 - 0x1f 0000000000000000 - // -. - 0x6000, // 0x20 - 0x2f 0000000000000110 - // 0123456789 - 0x03ff, // 0x30 - 0x3f 1111111111000000 - // ABCDEFGHIJKLMNO - 0xfffe, // 0x40 - 0x4f 0111111111111111 - // PQRSTUVWXYZ _ - 0x87ff, // 0x50 - 0x5f 1111111111100001 - // abcdefghijklmno - 0xfffe, // 0x60 - 0x6f 0111111111111111 - // pqrstuvwxyz ~ - 0x47ff]; // 0x70 - 0x7f 1111111111100010 - - // The unreserved characters of RFC 2396. - static const _unreserved2396Table = const [ - // LSB MSB - // | | - 0x0000, // 0x00 - 0x0f 0000000000000000 - 0x0000, // 0x10 - 0x1f 0000000000000000 - // ! '()* -. - 0x6782, // 0x20 - 0x2f 0100000111100110 - // 0123456789 - 0x03ff, // 0x30 - 0x3f 1111111111000000 - // ABCDEFGHIJKLMNO - 0xfffe, // 0x40 - 0x4f 0111111111111111 - // PQRSTUVWXYZ _ - 0x87ff, // 0x50 - 0x5f 1111111111100001 - // abcdefghijklmno - 0xfffe, // 0x60 - 0x6f 0111111111111111 - // pqrstuvwxyz ~ - 0x47ff]; // 0x70 - 0x7f 1111111111100010 - - // Table of reserved characters specified by ECMAScript 5. - static const _encodeFullTable = const [ - // LSB MSB - // | | - 0x0000, // 0x00 - 0x0f 0000000000000000 - 0x0000, // 0x10 - 0x1f 0000000000000000 - // ! #$ &'()*+,-./ - 0xffda, // 0x20 - 0x2f 0101101111111111 - // 0123456789:; = ? - 0xafff, // 0x30 - 0x3f 1111111111110101 - // @ABCDEFGHIJKLMNO - 0xffff, // 0x40 - 0x4f 1111111111111111 - // PQRSTUVWXYZ _ - 0x87ff, // 0x50 - 0x5f 1111111111100001 - // abcdefghijklmno - 0xfffe, // 0x60 - 0x6f 0111111111111111 - // pqrstuvwxyz ~ - 0x47ff]; // 0x70 - 0x7f 1111111111100010 - - // Characters allowed in the scheme. - static const _schemeTable = const [ - // LSB MSB - // | | - 0x0000, // 0x00 - 0x0f 0000000000000000 - 0x0000, // 0x10 - 0x1f 0000000000000000 - // + -. - 0x6800, // 0x20 - 0x2f 0000000000010110 - // 0123456789 - 0x03ff, // 0x30 - 0x3f 1111111111000000 - // ABCDEFGHIJKLMNO - 0xfffe, // 0x40 - 0x4f 0111111111111111 - // PQRSTUVWXYZ - 0x07ff, // 0x50 - 0x5f 1111111111100001 - // abcdefghijklmno - 0xfffe, // 0x60 - 0x6f 0111111111111111 - // pqrstuvwxyz - 0x07ff]; // 0x70 - 0x7f 1111111111100010 - - // Characters allowed in scheme except for upper case letters. - static const _schemeLowerTable = const [ - // LSB MSB - // | | - 0x0000, // 0x00 - 0x0f 0000000000000000 - 0x0000, // 0x10 - 0x1f 0000000000000000 - // + -. - 0x6800, // 0x20 - 0x2f 0000000000010110 - // 0123456789 - 0x03ff, // 0x30 - 0x3f 1111111111000000 - // - 0x0000, // 0x40 - 0x4f 0111111111111111 - // - 0x0000, // 0x50 - 0x5f 1111111111100001 - // abcdefghijklmno - 0xfffe, // 0x60 - 0x6f 0111111111111111 - // pqrstuvwxyz - 0x07ff]; // 0x70 - 0x7f 1111111111100010 - - // Sub delimiter characters combined with unreserved as of 3986. - // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - // / "*" / "+" / "," / ";" / "=" - // RFC 3986 section 2.3. - // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - static const _subDelimitersTable = const [ - // LSB MSB - // | | - 0x0000, // 0x00 - 0x0f 0000000000000000 - 0x0000, // 0x10 - 0x1f 0000000000000000 - // ! $ &'()*+,-. - 0x7fd2, // 0x20 - 0x2f 0100101111111110 - // 0123456789 ; = - 0x2bff, // 0x30 - 0x3f 1111111111010100 - // ABCDEFGHIJKLMNO - 0xfffe, // 0x40 - 0x4f 0111111111111111 - // PQRSTUVWXYZ _ - 0x87ff, // 0x50 - 0x5f 1111111111100001 - // abcdefghijklmno - 0xfffe, // 0x60 - 0x6f 0111111111111111 - // pqrstuvwxyz ~ - 0x47ff]; // 0x70 - 0x7f 1111111111100010 - - // General delimiter characters, RFC 3986 section 2.2. - // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" - // - static const _genDelimitersTable = const [ - // LSB MSB - // | | - 0x0000, // 0x00 - 0x0f 0000000000000000 - 0x0000, // 0x10 - 0x1f 0000000000000000 - // # / - 0x8008, // 0x20 - 0x2f 0001000000000001 - // : ? - 0x8400, // 0x30 - 0x3f 0000000000100001 - // @ - 0x0001, // 0x40 - 0x4f 1000000000000000 - // [ ] - 0x2800, // 0x50 - 0x5f 0000000000010100 - // - 0x0000, // 0x60 - 0x6f 0000000000000000 - // - 0x0000]; // 0x70 - 0x7f 0000000000000000 - - // Characters allowed in the userinfo as of RFC 3986. - // RFC 3986 Apendix A - // userinfo = *( unreserved / pct-encoded / sub-delims / ':') - static const _userinfoTable = const [ - // LSB MSB - // | | - 0x0000, // 0x00 - 0x0f 0000000000000000 - 0x0000, // 0x10 - 0x1f 0000000000000000 - // ! $ &'()*+,-. - 0x7fd2, // 0x20 - 0x2f 0100101111111110 - // 0123456789:; = - 0x2fff, // 0x30 - 0x3f 1111111111110100 - // ABCDEFGHIJKLMNO - 0xfffe, // 0x40 - 0x4f 0111111111111111 - // PQRSTUVWXYZ _ - 0x87ff, // 0x50 - 0x5f 1111111111100001 - // abcdefghijklmno - 0xfffe, // 0x60 - 0x6f 0111111111111111 - // pqrstuvwxyz ~ - 0x47ff]; // 0x70 - 0x7f 1111111111100010 - - // Characters allowed in the reg-name as of RFC 3986. - // RFC 3986 Apendix A - // reg-name = *( unreserved / pct-encoded / sub-delims ) - static const _regNameTable = const [ - // LSB MSB - // | | - 0x0000, // 0x00 - 0x0f 0000000000000000 - 0x0000, // 0x10 - 0x1f 0000000000000000 - // ! $%&'()*+,-. - 0x7ff2, // 0x20 - 0x2f 0100111111111110 - // 0123456789 ; = - 0x2bff, // 0x30 - 0x3f 1111111111010100 - // ABCDEFGHIJKLMNO - 0xfffe, // 0x40 - 0x4f 0111111111111111 - // PQRSTUVWXYZ _ - 0x87ff, // 0x50 - 0x5f 1111111111100001 - // abcdefghijklmno - 0xfffe, // 0x60 - 0x6f 0111111111111111 - // pqrstuvwxyz ~ - 0x47ff]; // 0x70 - 0x7f 1111111111100010 - - // Characters allowed in the path as of RFC 3986. - // RFC 3986 section 3.3. - // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - static const _pathCharTable = const [ - // LSB MSB - // | | - 0x0000, // 0x00 - 0x0f 0000000000000000 - 0x0000, // 0x10 - 0x1f 0000000000000000 - // ! $ &'()*+,-. - 0x7fd2, // 0x20 - 0x2f 0100101111111110 - // 0123456789:; = - 0x2fff, // 0x30 - 0x3f 1111111111110100 - // @ABCDEFGHIJKLMNO - 0xffff, // 0x40 - 0x4f 1111111111111111 - // PQRSTUVWXYZ _ - 0x87ff, // 0x50 - 0x5f 1111111111100001 - // abcdefghijklmno - 0xfffe, // 0x60 - 0x6f 0111111111111111 - // pqrstuvwxyz ~ - 0x47ff]; // 0x70 - 0x7f 1111111111100010 - - // Characters allowed in the path as of RFC 3986. - // RFC 3986 section 3.3 *and* slash. - static const _pathCharOrSlashTable = const [ - // LSB MSB - // | | - 0x0000, // 0x00 - 0x0f 0000000000000000 - 0x0000, // 0x10 - 0x1f 0000000000000000 - // ! $ &'()*+,-./ - 0xffd2, // 0x20 - 0x2f 0100101111111111 - // 0123456789:; = - 0x2fff, // 0x30 - 0x3f 1111111111110100 - // @ABCDEFGHIJKLMNO - 0xffff, // 0x40 - 0x4f 1111111111111111 - - // PQRSTUVWXYZ _ - 0x87ff, // 0x50 - 0x5f 1111111111100001 - // abcdefghijklmno - 0xfffe, // 0x60 - 0x6f 0111111111111111 - // pqrstuvwxyz ~ - 0x47ff]; // 0x70 - 0x7f 1111111111100010 - - // Characters allowed in the query as of RFC 3986. - // RFC 3986 section 3.4. - // query = *( pchar / "/" / "?" ) - static const _queryCharTable = const [ - // LSB MSB - // | | - 0x0000, // 0x00 - 0x0f 0000000000000000 - 0x0000, // 0x10 - 0x1f 0000000000000000 - // ! $ &'()*+,-./ - 0xffd2, // 0x20 - 0x2f 0100101111111111 - // 0123456789:; = ? - 0xafff, // 0x30 - 0x3f 1111111111110101 - // @ABCDEFGHIJKLMNO - 0xffff, // 0x40 - 0x4f 1111111111111111 - // PQRSTUVWXYZ _ - 0x87ff, // 0x50 - 0x5f 1111111111100001 - // abcdefghijklmno - 0xfffe, // 0x60 - 0x6f 0111111111111111 - // pqrstuvwxyz ~ - 0x47ff]; // 0x70 - 0x7f 1111111111100010 -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/internal/internal.dart b/pkg/dev_compiler/test/generated_sdk/lib/internal/internal.dart deleted file mode 100644 index a3f6e63676a3..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/internal/internal.dart +++ /dev/null @@ -1,50 +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. - -library dart._internal; - -import 'dart:collection'; - -import 'dart:core' hide Symbol; -import 'dart:core' as core; -import 'dart:math' show Random; -import 'dart:_js_primitives' show printString; -import 'dart:_js_helper' show JS, patch; -import 'dart:_interceptors' show JSArray; - -part 'iterable.dart'; -part 'list.dart'; -part 'lists.dart'; -part 'print.dart'; -part 'sort.dart'; -part 'symbol.dart'; - -// Powers of 10 up to 10^22 are representable as doubles. -// Powers of 10 above that are only approximate due to lack of precission. -// Used by double-parsing. -const POWERS_OF_TEN = const [ - 1.0, /* 0 */ - 10.0, - 100.0, - 1000.0, - 10000.0, - 100000.0, /* 5 */ - 1000000.0, - 10000000.0, - 100000000.0, - 1000000000.0, - 10000000000.0, /* 10 */ - 100000000000.0, - 1000000000000.0, - 10000000000000.0, - 100000000000000.0, - 1000000000000000.0, /* 15 */ - 10000000000000000.0, - 100000000000000000.0, - 1000000000000000000.0, - 10000000000000000000.0, - 100000000000000000000.0, /* 20 */ - 1000000000000000000000.0, - 10000000000000000000000.0, -]; diff --git a/pkg/dev_compiler/test/generated_sdk/lib/internal/iterable.dart b/pkg/dev_compiler/test/generated_sdk/lib/internal/iterable.dart deleted file mode 100644 index 0262927a1924..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/internal/iterable.dart +++ /dev/null @@ -1,1169 +0,0 @@ -// 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. - -part of dart._internal; - -/** - * Marker interface for [Iterable] subclasses that have an efficient - * [length] implementation. - */ -abstract class EfficientLength { - /** - * Returns the number of elements in the iterable. - * - * This is an efficient operation that doesn't require iterating through - * the elements. - */ - int get length; -} - -/** - * An [Iterable] for classes that have efficient [length] and [elementAt]. - * - * All other methods are implemented in terms of [length] and [elementAt], - * including [iterator]. - */ -abstract class ListIterable extends IterableBase - implements EfficientLength { - int get length; - E elementAt(int i); - - const ListIterable(); - - Iterator get iterator => new ListIterator(this); - - void forEach(void action(E element)) { - int length = this.length; - for (int i = 0; i < length; i++) { - action(elementAt(i)); - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - } - - bool get isEmpty => length == 0; - - E get first { - if (length == 0) throw IterableElementError.noElement(); - return elementAt(0); - } - - E get last { - if (length == 0) throw IterableElementError.noElement(); - return elementAt(length - 1); - } - - E get single { - if (length == 0) throw IterableElementError.noElement(); - if (length > 1) throw IterableElementError.tooMany(); - return elementAt(0); - } - - bool contains(Object element) { - int length = this.length; - for (int i = 0; i < length; i++) { - if (elementAt(i) == element) return true; - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - return false; - } - - bool every(bool test(E element)) { - int length = this.length; - for (int i = 0; i < length; i++) { - if (!test(elementAt(i))) return false; - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - return true; - } - - bool any(bool test(E element)) { - int length = this.length; - for (int i = 0; i < length; i++) { - if (test(elementAt(i))) return true; - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - return false; - } - - E firstWhere(bool test(E element), { E orElse() }) { - int length = this.length; - for (int i = 0; i < length; i++) { - E element = elementAt(i); - if (test(element)) return element; - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - E lastWhere(bool test(E element), { E orElse() }) { - int length = this.length; - for (int i = length - 1; i >= 0; i--) { - E element = elementAt(i); - if (test(element)) return element; - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - E singleWhere(bool test(E element)) { - int length = this.length; - E match = null; - bool matchFound = false; - for (int i = 0; i < length; i++) { - E element = elementAt(i); - if (test(element)) { - if (matchFound) { - throw IterableElementError.tooMany(); - } - matchFound = true; - match = element; - } - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - if (matchFound) return match; - throw IterableElementError.noElement(); - } - - String join([String separator = ""]) { - int length = this.length; - if (!separator.isEmpty) { - if (length == 0) return ""; - String first = "${elementAt(0)}"; - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - StringBuffer buffer = new StringBuffer(first); - for (int i = 1; i < length; i++) { - buffer.write(separator); - buffer.write(elementAt(i)); - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - return buffer.toString(); - } else { - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < length; i++) { - buffer.write(elementAt(i)); - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - return buffer.toString(); - } - } - - Iterable where(bool test(E element)) => super.where(test); - - Iterable map(f(E element)) => new MappedListIterable(this, f); - - E reduce(E combine(var value, E element)) { - int length = this.length; - if (length == 0) throw IterableElementError.noElement(); - E value = elementAt(0); - for (int i = 1; i < length; i++) { - value = combine(value, elementAt(i)); - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - - } - return value; - } - - fold(var initialValue, combine(var previousValue, E element)) { - var value = initialValue; - int length = this.length; - for (int i = 0; i < length; i++) { - value = combine(value, elementAt(i)); - if (length != this.length) { - throw new ConcurrentModificationError(this); - } - } - return value; - } - - Iterable skip(int count) => new SubListIterable(this, count, null); - - Iterable skipWhile(bool test(E element)) => super.skipWhile(test); - - Iterable take(int count) => new SubListIterable(this, 0, count); - - Iterable takeWhile(bool test(E element)) => super.takeWhile(test); - - List toList({ bool growable: true }) { - List result; - if (growable) { - result = new List()..length = length; - } else { - result = new List(length); - } - for (int i = 0; i < length; i++) { - result[i] = elementAt(i); - } - return result; - } - - Set toSet() { - Set result = new Set(); - for (int i = 0; i < length; i++) { - result.add(elementAt(i)); - } - return result; - } -} - -class SubListIterable extends ListIterable { - final Iterable _iterable; // Has efficient length and elementAt. - final int _start; - /** If null, represents the length of the iterable. */ - final int _endOrLength; - - SubListIterable(this._iterable, this._start, this._endOrLength) { - RangeError.checkNotNegative(_start, "start"); - if (_endOrLength != null) { - RangeError.checkNotNegative(_endOrLength, "end"); - if (_start > _endOrLength) { - throw new RangeError.range(_start, 0, _endOrLength, "start"); - } - } - } - - int get _endIndex { - int length = _iterable.length; - if (_endOrLength == null || _endOrLength > length) return length; - return _endOrLength; - } - - int get _startIndex { - int length = _iterable.length; - if (_start > length) return length; - return _start; - } - - int get length { - int length = _iterable.length; - if (_start >= length) return 0; - if (_endOrLength == null || _endOrLength >= length) { - return length - _start; - } - return _endOrLength - _start; - } - - E elementAt(int index) { - int realIndex = _startIndex + index; - if (index < 0 || realIndex >= _endIndex) { - throw new RangeError.index(index, this, "index"); - } - return _iterable.elementAt(realIndex); - } - - Iterable skip(int count) { - RangeError.checkNotNegative(count, "count"); - int newStart = _start + count; - if (_endOrLength != null && newStart >= _endOrLength) { - return new EmptyIterable(); - } - return new SubListIterable(_iterable, newStart, _endOrLength); - } - - Iterable take(int count) { - RangeError.checkNotNegative(count, "count"); - if (_endOrLength == null) { - return new SubListIterable(_iterable, _start, _start + count); - } else { - int newEnd = _start + count; - if (_endOrLength < newEnd) return this; - return new SubListIterable(_iterable, _start, newEnd); - } - } - - List toList({bool growable: true}) { - int start = _start; - int end = _iterable.length; - if (_endOrLength != null && _endOrLength < end) end = _endOrLength; - int length = end - start; - if (length < 0) length = 0; - List result = growable ? (new List()..length = length) - : new List(length); - for (int i = 0; i < length; i++) { - result[i] = _iterable.elementAt(start + i); - if (_iterable.length < end) throw new ConcurrentModificationError(this); - } - return result; - } -} - -/** - * An [Iterator] that iterates a list-like [Iterable]. - * - * All iterations is done in terms of [Iterable.length] and - * [Iterable.elementAt]. These operations are fast for list-like - * iterables. - */ -class ListIterator implements Iterator { - final Iterable _iterable; - final int _length; - int _index; - E _current; - - ListIterator(Iterable iterable) - : _iterable = iterable, _length = iterable.length, _index = 0; - - E get current => _current; - - bool moveNext() { - int length = _iterable.length; - if (_length != length) { - throw new ConcurrentModificationError(_iterable); - } - if (_index >= length) { - _current = null; - return false; - } - _current = _iterable.elementAt(_index); - _index++; - return true; - } -} - -typedef T _Transformation(S value); - -class MappedIterable extends IterableBase { - final Iterable _iterable; - final _Transformation _f; - - factory MappedIterable(Iterable iterable, T function(S value)) { - if (iterable is EfficientLength) { - return new EfficientLengthMappedIterable(iterable, function); - } - return new MappedIterable._(iterable, function); - } - - MappedIterable._(this._iterable, T this._f(S element)); - - Iterator get iterator => new MappedIterator(_iterable.iterator, _f); - - // Length related functions are independent of the mapping. - int get length => _iterable.length; - bool get isEmpty => _iterable.isEmpty; - - // Index based lookup can be done before transforming. - T get first => _f(_iterable.first); - T get last => _f(_iterable.last); - T get single => _f(_iterable.single); - T elementAt(int index) => _f(_iterable.elementAt(index)); -} - -class EfficientLengthMappedIterable extends MappedIterable - implements EfficientLength { - EfficientLengthMappedIterable(Iterable iterable, T function(S value)) - : super._(iterable, function); -} - -class MappedIterator extends Iterator { - T _current; - final Iterator _iterator; - final _Transformation _f; - - MappedIterator(this._iterator, T this._f(S element)); - - bool moveNext() { - if (_iterator.moveNext()) { - _current = _f(_iterator.current); - return true; - } - _current = null; - return false; - } - - T get current => _current; -} - -/** - * Specialized alternative to [MappedIterable] for mapped [List]s. - * - * Expects efficient `length` and `elementAt` on the source iterable. - */ -class MappedListIterable extends ListIterable - implements EfficientLength { - final Iterable _source; - final _Transformation _f; - - MappedListIterable(this._source, T this._f(S value)); - - int get length => _source.length; - T elementAt(int index) => _f(_source.elementAt(index)); -} - - -typedef bool _ElementPredicate(E element); - -class WhereIterable extends IterableBase { - final Iterable _iterable; - final _ElementPredicate _f; - - WhereIterable(this._iterable, bool this._f(E element)); - - Iterator get iterator => new WhereIterator(_iterable.iterator, _f); -} - -class WhereIterator extends Iterator { - final Iterator _iterator; - final _ElementPredicate _f; - - WhereIterator(this._iterator, bool this._f(E element)); - - bool moveNext() { - while (_iterator.moveNext()) { - if (_f(_iterator.current)) { - return true; - } - } - return false; - } - - E get current => _iterator.current; -} - -typedef Iterable _ExpandFunction(S sourceElement); - -class ExpandIterable extends IterableBase { - final Iterable _iterable; - final _ExpandFunction _f; - - ExpandIterable(this._iterable, Iterable this._f(S element)); - - Iterator get iterator => new ExpandIterator(_iterable.iterator, _f); -} - -class ExpandIterator implements Iterator { - final Iterator _iterator; - final _ExpandFunction _f; - // Initialize _currentExpansion to an empty iterable. A null value - // marks the end of iteration, and we don't want to call _f before - // the first moveNext call. - Iterator _currentExpansion = const EmptyIterator(); - T _current; - - ExpandIterator(this._iterator, Iterable this._f(S element)); - - void _nextExpansion() { - } - - T get current => _current; - - bool moveNext() { - if (_currentExpansion == null) return false; - while (!_currentExpansion.moveNext()) { - _current = null; - if (_iterator.moveNext()) { - // If _f throws, this ends iteration. Otherwise _currentExpansion and - // _current will be set again below. - _currentExpansion = null; - _currentExpansion = _f(_iterator.current).iterator; - } else { - return false; - } - } - _current = _currentExpansion.current; - return true; - } -} - -class TakeIterable extends IterableBase { - final Iterable _iterable; - final int _takeCount; - - factory TakeIterable(Iterable iterable, int takeCount) { - if (takeCount is! int || takeCount < 0) { - throw new ArgumentError(takeCount); - } - if (iterable is EfficientLength) { - return new EfficientLengthTakeIterable(iterable, takeCount); - } - return new TakeIterable._(iterable, takeCount); - } - - TakeIterable._(this._iterable, this._takeCount); - - Iterator get iterator { - return new TakeIterator(_iterable.iterator, _takeCount); - } -} - -class EfficientLengthTakeIterable extends TakeIterable - implements EfficientLength { - EfficientLengthTakeIterable(Iterable iterable, int takeCount) - : super._(iterable, takeCount); - - int get length { - int iterableLength = _iterable.length; - if (iterableLength > _takeCount) return _takeCount; - return iterableLength; - } -} - - -class TakeIterator extends Iterator { - final Iterator _iterator; - int _remaining; - - TakeIterator(this._iterator, this._remaining) { - assert(_remaining is int && _remaining >= 0); - } - - bool moveNext() { - _remaining--; - if (_remaining >= 0) { - return _iterator.moveNext(); - } - _remaining = -1; - return false; - } - - E get current { - if (_remaining < 0) return null; - return _iterator.current; - } -} - -class TakeWhileIterable extends IterableBase { - final Iterable _iterable; - final _ElementPredicate _f; - - TakeWhileIterable(this._iterable, bool this._f(E element)); - - Iterator get iterator { - return new TakeWhileIterator(_iterable.iterator, _f); - } -} - -class TakeWhileIterator extends Iterator { - final Iterator _iterator; - final _ElementPredicate _f; - bool _isFinished = false; - - TakeWhileIterator(this._iterator, bool this._f(E element)); - - bool moveNext() { - if (_isFinished) return false; - if (!_iterator.moveNext() || !_f(_iterator.current)) { - _isFinished = true; - return false; - } - return true; - } - - E get current { - if (_isFinished) return null; - return _iterator.current; - } -} - -class SkipIterable extends IterableBase { - final Iterable _iterable; - final int _skipCount; - - factory SkipIterable(Iterable iterable, int count) { - if (iterable is EfficientLength) { - return new EfficientLengthSkipIterable(iterable, count); - } - return new SkipIterable._(iterable, count); - } - - SkipIterable._(this._iterable, this._skipCount) { - if (_skipCount is! int) { - throw new ArgumentError.value(_skipCount, "count is not an integer"); - } - RangeError.checkNotNegative(_skipCount, "count"); - } - - Iterable skip(int count) { - if (_skipCount is! int) { - throw new ArgumentError.value(_skipCount, "count is not an integer"); - } - RangeError.checkNotNegative(_skipCount, "count"); - return new SkipIterable._(_iterable, _skipCount + count); - } - - Iterator get iterator { - return new SkipIterator(_iterable.iterator, _skipCount); - } -} - -class EfficientLengthSkipIterable extends SkipIterable - implements EfficientLength { - EfficientLengthSkipIterable(Iterable iterable, int skipCount) - : super._(iterable, skipCount); - - int get length { - int length = _iterable.length - _skipCount; - if (length >= 0) return length; - return 0; - } -} - -class SkipIterator extends Iterator { - final Iterator _iterator; - int _skipCount; - - SkipIterator(this._iterator, this._skipCount) { - assert(_skipCount is int && _skipCount >= 0); - } - - bool moveNext() { - for (int i = 0; i < _skipCount; i++) _iterator.moveNext(); - _skipCount = 0; - return _iterator.moveNext(); - } - - E get current => _iterator.current; -} - -class SkipWhileIterable extends IterableBase { - final Iterable _iterable; - final _ElementPredicate _f; - - SkipWhileIterable(this._iterable, bool this._f(E element)); - - Iterator get iterator { - return new SkipWhileIterator(_iterable.iterator, _f); - } -} - -class SkipWhileIterator extends Iterator { - final Iterator _iterator; - final _ElementPredicate _f; - bool _hasSkipped = false; - - SkipWhileIterator(this._iterator, bool this._f(E element)); - - bool moveNext() { - if (!_hasSkipped) { - _hasSkipped = true; - while (_iterator.moveNext()) { - if (!_f(_iterator.current)) return true; - } - } - return _iterator.moveNext(); - } - - E get current => _iterator.current; -} - -/** - * The always empty [Iterable]. - */ -class EmptyIterable extends IterableBase implements EfficientLength { - const EmptyIterable(); - - Iterator get iterator => const EmptyIterator(); - - void forEach(void action(E element)) {} - - bool get isEmpty => true; - - int get length => 0; - - E get first { throw IterableElementError.noElement(); } - - E get last { throw IterableElementError.noElement(); } - - E get single { throw IterableElementError.noElement(); } - - E elementAt(int index) { throw new RangeError.range(index, 0, 0, "index"); } - - bool contains(Object element) => false; - - bool every(bool test(E element)) => true; - - bool any(bool test(E element)) => false; - - E firstWhere(bool test(E element), { E orElse() }) { - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - E lastWhere(bool test(E element), { E orElse() }) { - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - E singleWhere(bool test(E element), { E orElse() }) { - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - String join([String separator = ""]) => ""; - - Iterable where(bool test(E element)) => this; - - Iterable map(f(E element)) => const EmptyIterable(); - - E reduce(E combine(E value, E element)) { - throw IterableElementError.noElement(); - } - - fold(var initialValue, combine(var previousValue, E element)) { - return initialValue; - } - - Iterable skip(int count) { - RangeError.checkNotNegative(count, "count"); - return this; - } - - Iterable skipWhile(bool test(E element)) => this; - - Iterable take(int count) { - RangeError.checkNotNegative(count, "count"); - return this; - } - - Iterable takeWhile(bool test(E element)) => this; - - List toList({ bool growable: true }) => growable ? [] : new List(0); - - Set toSet() => new Set(); -} - -/** The always empty iterator. */ -class EmptyIterator implements Iterator { - const EmptyIterator(); - bool moveNext() => false; - E get current => null; -} - -/** An [Iterator] that can move in both directions. */ -abstract class BidirectionalIterator implements Iterator { - bool movePrevious(); -} - -/** - * This class provides default implementations for Iterables (including Lists). - * - * The uses of this class will be replaced by mixins. - */ -class IterableMixinWorkaround { - static bool contains(Iterable iterable, var element) { - for (final e in iterable) { - if (e == element) return true; - } - return false; - } - - static void forEach(Iterable iterable, void f(o)) { - for (final e in iterable) { - f(e); - } - } - - static bool any(Iterable iterable, bool f(o)) { - for (final e in iterable) { - if (f(e)) return true; - } - return false; - } - - static bool every(Iterable iterable, bool f(o)) { - for (final e in iterable) { - if (!f(e)) return false; - } - return true; - } - - static dynamic reduce(Iterable iterable, - dynamic combine(previousValue, element)) { - Iterator iterator = iterable.iterator; - if (!iterator.moveNext()) throw IterableElementError.noElement(); - var value = iterator.current; - while (iterator.moveNext()) { - value = combine(value, iterator.current); - } - return value; - } - - static dynamic fold(Iterable iterable, - dynamic initialValue, - dynamic combine(dynamic previousValue, element)) { - for (final element in iterable) { - initialValue = combine(initialValue, element); - } - return initialValue; - } - - /** - * Removes elements matching [test] from [list]. - * - * This is performed in two steps, to avoid exposing an inconsistent state - * to the [test] function. First the elements to retain are found, and then - * the original list is updated to contain those elements. - */ - static void removeWhereList(List list, bool test(var element)) { - List retained = []; - int length = list.length; - for (int i = 0; i < length; i++) { - var element = list[i]; - if (!test(element)) { - retained.add(element); - } - if (length != list.length) { - throw new ConcurrentModificationError(list); - } - } - if (retained.length == length) return; - list.length = retained.length; - for (int i = 0; i < retained.length; i++) { - list[i] = retained[i]; - } - } - - static bool isEmpty(Iterable iterable) { - return !iterable.iterator.moveNext(); - } - - static dynamic first(Iterable iterable) { - Iterator it = iterable.iterator; - if (!it.moveNext()) { - throw IterableElementError.noElement(); - } - return it.current; - } - - static dynamic last(Iterable iterable) { - Iterator it = iterable.iterator; - if (!it.moveNext()) { - throw IterableElementError.noElement(); - } - dynamic result; - do { - result = it.current; - } while(it.moveNext()); - return result; - } - - static dynamic single(Iterable iterable) { - Iterator it = iterable.iterator; - if (!it.moveNext()) throw IterableElementError.noElement(); - dynamic result = it.current; - if (it.moveNext()) throw IterableElementError.tooMany(); - return result; - } - - static dynamic firstWhere(Iterable iterable, - bool test(dynamic value), - dynamic orElse()) { - for (dynamic element in iterable) { - if (test(element)) return element; - } - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - static dynamic lastWhere(Iterable iterable, - bool test(dynamic value), - dynamic orElse()) { - dynamic result = null; - bool foundMatching = false; - for (dynamic element in iterable) { - if (test(element)) { - result = element; - foundMatching = true; - } - } - if (foundMatching) return result; - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - static dynamic lastWhereList(List list, - bool test(dynamic value), - dynamic orElse()) { - // TODO(floitsch): check that arguments are of correct type? - for (int i = list.length - 1; i >= 0; i--) { - dynamic element = list[i]; - if (test(element)) return element; - } - if (orElse != null) return orElse(); - throw IterableElementError.noElement(); - } - - static dynamic singleWhere(Iterable iterable, bool test(dynamic value)) { - dynamic result = null; - bool foundMatching = false; - for (dynamic element in iterable) { - if (test(element)) { - if (foundMatching) { - throw IterableElementError.tooMany(); - } - result = element; - foundMatching = true; - } - } - if (foundMatching) return result; - throw IterableElementError.noElement(); - } - - static elementAt(Iterable iterable, int index) { - if (index is! int) throw new ArgumentError.notNull("index"); - RangeError.checkNotNegative(index, "index"); - int elementIndex = 0; - for (var element in iterable) { - if (index == elementIndex) return element; - elementIndex++; - } - throw new RangeError.index(index, iterable, "index", null, elementIndex); - } - - static String join(Iterable iterable, [String separator]) { - StringBuffer buffer = new StringBuffer(); - buffer.writeAll(iterable, separator); - return buffer.toString(); - } - - static String joinList(List list, [String separator]) { - if (list.isEmpty) return ""; - if (list.length == 1) return "${list[0]}"; - StringBuffer buffer = new StringBuffer(); - if (separator.isEmpty) { - for (int i = 0; i < list.length; i++) { - buffer.write(list[i]); - } - } else { - buffer.write(list[0]); - for (int i = 1; i < list.length; i++) { - buffer.write(separator); - buffer.write(list[i]); - } - } - return buffer.toString(); - } - - Iterable where(Iterable iterable, bool f(var element)) { - return new WhereIterable(iterable, f); - } - - static Iterable map(Iterable iterable, f(var element)) { - return new MappedIterable(iterable, f); - } - - static Iterable mapList(List list, f(var element)) { - return new MappedListIterable(list, f); - } - - static Iterable expand(Iterable iterable, Iterable f(var element)) { - return new ExpandIterable(iterable, f); - } - - Iterable takeList(List list, int n) { - // The generic type is currently lost. It will be fixed with mixins. - return new SubListIterable(list, 0, n); - } - - Iterable takeWhile(Iterable iterable, bool test(var value)) { - // The generic type is currently lost. It will be fixed with mixins. - return new TakeWhileIterable(iterable, test); - } - - Iterable skipList(List list, int n) { - // The generic type is currently lost. It will be fixed with mixins. - return new SubListIterable(list, n, null); - } - - Iterable skipWhile(Iterable iterable, bool test(var value)) { - // The generic type is currently lost. It will be fixed with mixins. - return new SkipWhileIterable(iterable, test); - } - - Iterable reversedList(List list) { - return new ReversedListIterable(list); - } - - static void sortList(List list, int compare(a, b)) { - if (compare == null) compare = Comparable.compare; - Sort.sort(list, compare); - } - - static void shuffleList(List list, Random random) { - if (random == null) random = new Random(); - int length = list.length; - while (length > 1) { - int pos = random.nextInt(length); - length -= 1; - var tmp = list[length]; - list[length] = list[pos]; - list[pos] = tmp; - } - } - - static int indexOfList(List list, var element, int start) { - return Lists.indexOf(list, element, start, list.length); - } - - static int lastIndexOfList(List list, var element, int start) { - if (start == null) start = list.length - 1; - return Lists.lastIndexOf(list, element, start); - } - - static void _rangeCheck(List list, int start, int end) { - RangeError.checkValidRange(start, end, list.length); - } - - Iterable getRangeList(List list, int start, int end) { - _rangeCheck(list, start, end); - // The generic type is currently lost. It will be fixed with mixins. - return new SubListIterable(list, start, end); - } - - static void setRangeList(List list, int start, int end, - Iterable from, int skipCount) { - _rangeCheck(list, start, end); - int length = end - start; - if (length == 0) return; - - if (skipCount < 0) throw new ArgumentError(skipCount); - - // TODO(floitsch): Make this accept more. - List otherList; - int otherStart; - if (from is List) { - otherList = from; - otherStart = skipCount; - } else { - otherList = from.skip(skipCount).toList(growable: false); - otherStart = 0; - } - if (otherStart + length > otherList.length) { - throw IterableElementError.tooFew(); - } - Lists.copy(otherList, otherStart, list, start, length); - } - - static void replaceRangeList(List list, int start, int end, - Iterable iterable) { - _rangeCheck(list, start, end); - if (iterable is! EfficientLength) { - iterable = iterable.toList(); - } - int removeLength = end - start; - int insertLength = iterable.length; - if (removeLength >= insertLength) { - int delta = removeLength - insertLength; - int insertEnd = start + insertLength; - int newEnd = list.length - delta; - list.setRange(start, insertEnd, iterable); - if (delta != 0) { - list.setRange(insertEnd, newEnd, list, end); - list.length = newEnd; - } - } else { - int delta = insertLength - removeLength; - int newLength = list.length + delta; - int insertEnd = start + insertLength; // aka. end + delta. - list.length = newLength; - list.setRange(insertEnd, newLength, list, end); - list.setRange(start, insertEnd, iterable); - } - } - - static void fillRangeList(List list, int start, int end, fillValue) { - _rangeCheck(list, start, end); - for (int i = start; i < end; i++) { - list[i] = fillValue; - } - } - - static void insertAllList(List list, int index, Iterable iterable) { - RangeError.checkValueInInterval(index, 0, list.length, "index"); - if (iterable is! EfficientLength) { - iterable = iterable.toList(growable: false); - } - int insertionLength = iterable.length; - list.length += insertionLength; - list.setRange(index + insertionLength, list.length, list, index); - for (var element in iterable) { - list[index++] = element; - } - } - - static void setAllList(List list, int index, Iterable iterable) { - RangeError.checkValueInInterval(index, 0, list.length, "index"); - for (var element in iterable) { - list[index++] = element; - } - } - - Map asMapList(List l) { - return new ListMapView(l); - } - - static bool setContainsAll(Set set, Iterable other) { - for (var element in other) { - if (!set.contains(element)) return false; - } - return true; - } - - static Set setIntersection(Set set, Set other, Set result) { - Set smaller; - Set larger; - if (set.length < other.length) { - smaller = set; - larger = other; - } else { - smaller = other; - larger = set; - } - for (var element in smaller) { - if (larger.contains(element)) { - result.add(element); - } - } - return result; - } - - static Set setUnion(Set set, Set other, Set result) { - result.addAll(set); - result.addAll(other); - return result; - } - - static Set setDifference(Set set, Set other, Set result) { - for (var element in set) { - if (!other.contains(element)) { - result.add(element); - } - } - return result; - } -} - -/** - * Creates errors throw by [Iterable] when the element count is wrong. - */ -abstract class IterableElementError { - /** Error thrown thrown by, e.g., [Iterable.first] when there is no result. */ - static StateError noElement() => new StateError("No element"); - /** Error thrown by, e.g., [Iterable.single] if there are too many results. */ - static StateError tooMany() => new StateError("Too many elements"); - /** Error thrown by, e.g., [List.setRange] if there are too few elements. */ - static StateError tooFew() => new StateError("Too few elements"); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/internal/list.dart b/pkg/dev_compiler/test/generated_sdk/lib/internal/list.dart deleted file mode 100644 index a3e22f0d46ce..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/internal/list.dart +++ /dev/null @@ -1,379 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart._internal; - -/** - * Mixin that throws on the length changing operations of [List]. - * - * Intended to mix-in on top of [ListMixin] for fixed-length lists. - */ -abstract class FixedLengthListMixin { - /** This operation is not supported by a fixed length list. */ - void set length(int newLength) { - throw new UnsupportedError( - "Cannot change the length of a fixed-length list"); - } - - /** This operation is not supported by a fixed length list. */ - void add(E value) { - throw new UnsupportedError( - "Cannot add to a fixed-length list"); - } - - /** This operation is not supported by a fixed length list. */ - void insert(int index, E value) { - throw new UnsupportedError( - "Cannot add to a fixed-length list"); - } - - /** This operation is not supported by a fixed length list. */ - void insertAll(int at, Iterable iterable) { - throw new UnsupportedError( - "Cannot add to a fixed-length list"); - } - - /** This operation is not supported by a fixed length list. */ - void addAll(Iterable iterable) { - throw new UnsupportedError( - "Cannot add to a fixed-length list"); - } - - /** This operation is not supported by a fixed length list. */ - bool remove(Object element) { - throw new UnsupportedError( - "Cannot remove from a fixed-length list"); - } - - /** This operation is not supported by a fixed length list. */ - void removeWhere(bool test(E element)) { - throw new UnsupportedError( - "Cannot remove from a fixed-length list"); - } - - /** This operation is not supported by a fixed length list. */ - void retainWhere(bool test(E element)) { - throw new UnsupportedError( - "Cannot remove from a fixed-length list"); - } - - /** This operation is not supported by a fixed length list. */ - void clear() { - throw new UnsupportedError( - "Cannot clear a fixed-length list"); - } - - /** This operation is not supported by a fixed length list. */ - E removeAt(int index) { - throw new UnsupportedError( - "Cannot remove from a fixed-length list"); - } - - /** This operation is not supported by a fixed length list. */ - E removeLast() { - throw new UnsupportedError( - "Cannot remove from a fixed-length list"); - } - - /** This operation is not supported by a fixed length list. */ - void removeRange(int start, int end) { - throw new UnsupportedError( - "Cannot remove from a fixed-length list"); - } - - /** This operation is not supported by a fixed length list. */ - void replaceRange(int start, int end, Iterable iterable) { - throw new UnsupportedError( - "Cannot remove from a fixed-length list"); - } -} - -/** - * Mixin for an unmodifiable [List] class. - * - * This overrides all mutating methods with methods that throw. - * This mixin is intended to be mixed in on top of [ListMixin] on - * unmodifiable lists. - */ -abstract class UnmodifiableListMixin implements List { - - /** This operation is not supported by an unmodifiable list. */ - void operator []=(int index, E value) { - throw new UnsupportedError( - "Cannot modify an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void set length(int newLength) { - throw new UnsupportedError( - "Cannot change the length of an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void setAll(int at, Iterable iterable) { - throw new UnsupportedError( - "Cannot modify an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void add(E value) { - throw new UnsupportedError( - "Cannot add to an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - E insert(int index, E value) { - throw new UnsupportedError( - "Cannot add to an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void insertAll(int at, Iterable iterable) { - throw new UnsupportedError( - "Cannot add to an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void addAll(Iterable iterable) { - throw new UnsupportedError( - "Cannot add to an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - bool remove(Object element) { - throw new UnsupportedError( - "Cannot remove from an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void removeWhere(bool test(E element)) { - throw new UnsupportedError( - "Cannot remove from an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void retainWhere(bool test(E element)) { - throw new UnsupportedError( - "Cannot remove from an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void sort([Comparator compare]) { - throw new UnsupportedError( - "Cannot modify an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void shuffle([Random random]) { - throw new UnsupportedError( - "Cannot modify an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void clear() { - throw new UnsupportedError( - "Cannot clear an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - E removeAt(int index) { - throw new UnsupportedError( - "Cannot remove from an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - E removeLast() { - throw new UnsupportedError( - "Cannot remove from an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { - throw new UnsupportedError( - "Cannot modify an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void removeRange(int start, int end) { - throw new UnsupportedError( - "Cannot remove from an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void replaceRange(int start, int end, Iterable iterable) { - throw new UnsupportedError( - "Cannot remove from an unmodifiable list"); - } - - /** This operation is not supported by an unmodifiable list. */ - void fillRange(int start, int end, [E fillValue]) { - throw new UnsupportedError( - "Cannot modify an unmodifiable list"); - } -} - -/** - * Abstract implementation of a fixed-length list. - * - * All operations are defined in terms of `length`, `operator[]` and - * `operator[]=`, which need to be implemented. - */ -abstract class FixedLengthListBase = - ListBase with FixedLengthListMixin; - -/** - * Abstract implementation of an unmodifiable list. - * - * All operations are defined in terms of `length` and `operator[]`, - * which need to be implemented. - */ -abstract class UnmodifiableListBase = - ListBase with UnmodifiableListMixin; - -class _ListIndicesIterable extends ListIterable { - List _backedList; - - _ListIndicesIterable(this._backedList); - - int get length => _backedList.length; - int elementAt(int index) { - RangeError.checkValidIndex(index, this); - return index; - } -} - -class ListMapView implements Map { - List _values; - - ListMapView(this._values); - - E operator[] (Object key) => containsKey(key) ? _values[key] : null; - int get length => _values.length; - - Iterable get values => new SubListIterable(_values, 0, null); - Iterable get keys => new _ListIndicesIterable(_values); - - bool get isEmpty => _values.isEmpty; - bool get isNotEmpty => _values.isNotEmpty; - bool containsValue(Object value) => _values.contains(value); - bool containsKey(Object key) => key is int && key >= 0 && key < length; - - void forEach(void f(int key, E value)) { - int length = _values.length; - for (int i = 0; i < length; i++) { - f(i, _values[i]); - if (length != _values.length) { - throw new ConcurrentModificationError(_values); - } - } - } - - /** This operation is not supported by an unmodifiable map. */ - void operator[]= (int key, E value) { - throw new UnsupportedError("Cannot modify an unmodifiable map"); - } - - /** This operation is not supported by an unmodifiable map. */ - E putIfAbsent(int key, E ifAbsent()) { - throw new UnsupportedError("Cannot modify an unmodifiable map"); - } - - /** This operation is not supported by an unmodifiable map. */ - E remove(Object key) { - throw new UnsupportedError("Cannot modify an unmodifiable map"); - } - - /** This operation is not supported by an unmodifiable map. */ - void clear() { - throw new UnsupportedError("Cannot modify an unmodifiable map"); - } - - /** This operation is not supported by an unmodifiable map. */ - void addAll(Map other) { - throw new UnsupportedError("Cannot modify an unmodifiable map"); - } - - String toString() => Maps.mapToString(this); -} - -class ReversedListIterable extends ListIterable { - Iterable _source; - ReversedListIterable(this._source); - - int get length => _source.length; - - E elementAt(int index) => _source.elementAt(_source.length - 1 - index); -} - -/** - * Creates errors thrown by unmodifiable lists when they are attempted modified. - * - * This class creates [UnsupportedError]s with specialized messages. - */ -abstract class UnmodifiableListError { - /** Error thrown when trying to add elements to an unmodifiable list. */ - static UnsupportedError add() - => new UnsupportedError("Cannot add to unmodifiable List"); - - /** Error thrown when trying to add elements to an unmodifiable list. */ - static UnsupportedError change() - => new UnsupportedError( - "Cannot change the content of an unmodifiable List"); - - /** Error thrown when trying to change the length of an unmodifiable list. */ - static UnsupportedError length() - => new UnsupportedError("Cannot change length of unmodifiable List"); - - /** Error thrown when trying to remove elements from an unmodifiable list. */ - static UnsupportedError remove() - => new UnsupportedError("Cannot remove from unmodifiable List"); -} - -/** - * Creates errors thrown by non-growable lists when they are attempted modified. - * - * This class creates [UnsupportedError]s with specialized messages. - */ -abstract class NonGrowableListError { - /** Error thrown when trying to add elements to an non-growable list. */ - static UnsupportedError add() - => new UnsupportedError("Cannot add to non-growable List"); - - /** Error thrown when trying to change the length of an non-growable list. */ - static UnsupportedError length() - => new UnsupportedError("Cannot change length of non-growable List"); - - /** Error thrown when trying to remove elements from an non-growable list. */ - static UnsupportedError remove() - => new UnsupportedError("Cannot remove from non-growable List"); -} - -/** - * Converts a growable list to a fixed length list with the same elements. - * - * For internal use only. - * Only works on growable lists as created by `[]` or `new List()`. - * May throw on any other list. - * - * The operation is efficient. It doesn't copy the elements, but converts - * the existing list directly to a fixed length list. - * That means that it is a destructive conversion. - * The original list should not be used afterwards. - * - * The returned list may be the same list as the orginal, - * or it may be a different list (according to [identical]). - * The original list may have changed type to be a fixed list, - * or become empty or been otherwise modified. - * It will still be a valid object, so references to it will not, e.g., crash - * the runtime if accessed, but no promises are made wrt. its contents. - * - * This unspecified behavior is the reason the function is not exposed to - * users. We allow the underlying implementation to make the most efficient - * conversion, at the cost of leaving the original list in an unspecified - * state. - */ -List makeListFixedLength(List growableList) { - JSArray.markFixedList(growableList); - return growableList; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/internal/lists.dart b/pkg/dev_compiler/test/generated_sdk/lib/internal/lists.dart deleted file mode 100644 index 0f5d8e745233..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/internal/lists.dart +++ /dev/null @@ -1,90 +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. - -part of dart._internal; - -class Lists { - static void copy(List src, int srcStart, - List dst, int dstStart, int count) { - if (srcStart < dstStart) { - for (int i = srcStart + count - 1, j = dstStart + count - 1; - i >= srcStart; i--, j--) { - dst[j] = src[i]; - } - } else { - for (int i = srcStart, j = dstStart; i < srcStart + count; i++, j++) { - dst[j] = src[i]; - } - } - } - - static bool areEqual(List a, var b) { - if (identical(a, b)) return true; - if (!(b is List)) return false; - int length = a.length; - if (length != b.length) return false; - - for (int i = 0; i < length; i++) { - if (!identical(a[i], b[i])) return false; - } - return true; - } - - /** - * Returns the index in the list [a] of the given [element], starting - * the search at index [startIndex] to [endIndex] (exclusive). - * Returns -1 if [element] is not found. - */ - static int indexOf(List a, - Object element, - int startIndex, - int endIndex) { - if (startIndex >= a.length) { - return -1; - } - if (startIndex < 0) { - startIndex = 0; - } - for (int i = startIndex; i < endIndex; i++) { - if (a[i] == element) { - return i; - } - } - return -1; - } - - /** - * Returns the last index in the list [a] of the given [element], starting - * the search at index [startIndex] to 0. - * Returns -1 if [element] is not found. - */ - static int lastIndexOf(List a, Object element, int startIndex) { - if (startIndex < 0) { - return -1; - } - if (startIndex >= a.length) { - startIndex = a.length - 1; - } - for (int i = startIndex; i >= 0; i--) { - if (a[i] == element) { - return i; - } - } - return -1; - } - - static void indicesCheck(List a, int start, int end) { - RangeError.checkValidRange(start, end, a.length); - } - - static void rangeCheck(List a, int start, int length) { - RangeError.checkNotNegative(length); - RangeError.checkNotNegative(start); - if (start + length > a.length) { - String message = "$start + $length must be in the range [0..${a.length}]"; - throw new RangeError.range(length, 0, a.length - start, - "length", message); - } - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/internal/print.dart b/pkg/dev_compiler/test/generated_sdk/lib/internal/print.dart deleted file mode 100644 index 17890c097f32..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/internal/print.dart +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart._internal; - -/** - * This function is set by the first allocation of a Zone. - * - * Once the function is set the core `print` function calls this closure instead - * of [printToConsole]. - * - * This decouples the core library from the async library. - */ -Function printToZone = null; - -void printToConsole(String line) { - printString('$line'); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/internal/sort.dart b/pkg/dev_compiler/test/generated_sdk/lib/internal/sort.dart deleted file mode 100644 index 562d8b834bd0..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/internal/sort.dart +++ /dev/null @@ -1,344 +0,0 @@ -// 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. - -part of dart._internal; - -/** - * Dual-Pivot Quicksort algorithm. - * - * This class implements the dual-pivot quicksort algorithm as presented in - * Vladimir Yaroslavskiy's paper. - * - * Some improvements have been copied from Android's implementation. - */ -class Sort { - // When a list has less then [:_INSERTION_SORT_THRESHOLD:] elements it will - // be sorted by an insertion sort. - static const int _INSERTION_SORT_THRESHOLD = 32; - - /** - * Sorts all elements of the given list [:a:] according to the given - * [:compare:] function. - * - * The [:compare:] function takes two arguments [:x:] and [:y:] and returns - * -1 if [:x < y:], - * 0 if [:x == y:], and - * 1 if [:x > y:]. - * - * The function's behavior must be consistent. It must not return different - * results for the same values. - */ - static void sort(List a, int compare(a, b)) { - _doSort(a, 0, a.length - 1, compare); - } - - /** - * Sorts all elements in the range [:from:] (inclusive) to [:to:] (exclusive) - * of the given list [:a:]. - * - * If the given range is invalid an "OutOfRange" error is raised. - * TODO(floitsch): do we want an error? - * - * See [:sort:] for requirements of the [:compare:] function. - */ - static void sortRange(List a, int from, int to, int compare(a, b)) { - if ((from < 0) || (to > a.length) || (to < from)) { - throw "OutOfRange"; - } - _doSort(a, from, to - 1, compare); - } - - /** - * Sorts the list in the interval [:left:] to [:right:] (both inclusive). - */ - static void _doSort(List a, int left, int right, int compare(a, b)) { - if ((right - left) <= _INSERTION_SORT_THRESHOLD) { - _insertionSort(a, left, right, compare); - } else { - _dualPivotQuicksort(a, left, right, compare); - } - } - - static void _insertionSort(List a, int left, int right, int compare(a, b)) { - for (int i = left + 1; i <= right; i++) { - var el = a[i]; - int j = i; - while ((j > left) && (compare(a[j - 1], el) > 0)) { - a[j] = a[j - 1]; - j--; - } - a[j] = el; - } - } - - static void _dualPivotQuicksort(List a, - int left, int right, - int compare(a, b)) { - assert(right - left > _INSERTION_SORT_THRESHOLD); - - // Compute the two pivots by looking at 5 elements. - int sixth = (right - left + 1) ~/ 6; - int index1 = left + sixth; - int index5 = right - sixth; - int index3 = (left + right) ~/ 2; // The midpoint. - int index2 = index3 - sixth; - int index4 = index3 + sixth; - - var el1 = a[index1]; - var el2 = a[index2]; - var el3 = a[index3]; - var el4 = a[index4]; - var el5 = a[index5]; - - // Sort the selected 5 elements using a sorting network. - if (compare(el1, el2) > 0) { var t = el1; el1 = el2; el2 = t; } - if (compare(el4, el5) > 0) { var t = el4; el4 = el5; el5 = t; } - if (compare(el1, el3) > 0) { var t = el1; el1 = el3; el3 = t; } - if (compare(el2, el3) > 0) { var t = el2; el2 = el3; el3 = t; } - if (compare(el1, el4) > 0) { var t = el1; el1 = el4; el4 = t; } - if (compare(el3, el4) > 0) { var t = el3; el3 = el4; el4 = t; } - if (compare(el2, el5) > 0) { var t = el2; el2 = el5; el5 = t; } - if (compare(el2, el3) > 0) { var t = el2; el2 = el3; el3 = t; } - if (compare(el4, el5) > 0) { var t = el4; el4 = el5; el5 = t; } - - var pivot1 = el2; - var pivot2 = el4; - - // el2 and el4 have been saved in the pivot variables. They will be written - // back, once the partioning is finished. - a[index1] = el1; - a[index3] = el3; - a[index5] = el5; - - a[index2] = a[left]; - a[index4] = a[right]; - - int less = left + 1; // First element in the middle partition. - int great = right - 1; // Last element in the middle partition. - - bool pivots_are_equal = (compare(pivot1, pivot2) == 0); - if (pivots_are_equal) { - var pivot = pivot1; - // Degenerated case where the partioning becomes a dutch national flag - // problem. - // - // [ | < pivot | == pivot | unpartitioned | > pivot | ] - // ^ ^ ^ ^ ^ - // left less k great right - // - // a[left] and a[right] are undefined and are filled after the - // partitioning. - // - // Invariants: - // 1) for x in ]left, less[ : x < pivot. - // 2) for x in [less, k[ : x == pivot. - // 3) for x in ]great, right[ : x > pivot. - for (int k = less; k <= great; k++) { - var ak = a[k]; - int comp = compare(ak, pivot); - if (comp == 0) continue; - if (comp < 0) { - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } - less++; - } else { - // comp > 0. - // - // Find the first element <= pivot in the range [k - 1, great] and - // put [:ak:] there. We know that such an element must exist: - // When k == less, then el3 (which is equal to pivot) lies in the - // interval. Otherwise a[k - 1] == pivot and the search stops at k-1. - // Note that in the latter case invariant 2 will be violated for a - // short amount of time. The invariant will be restored when the - // pivots are put into their final positions. - while (true) { - comp = compare(a[great], pivot); - if (comp > 0) { - great--; - // This is the only location in the while-loop where a new - // iteration is started. - continue; - } else if (comp < 0) { - // Triple exchange. - a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; - break; - } else { - // comp == 0; - a[k] = a[great]; - a[great--] = ak; - // Note: if great < k then we will exit the outer loop and fix - // invariant 2 (which we just violated). - break; - } - } - } - } - } else { - // We partition the list into three parts: - // 1. < pivot1 - // 2. >= pivot1 && <= pivot2 - // 3. > pivot2 - // - // During the loop we have: - // [ | < pivot1 | >= pivot1 && <= pivot2 | unpartitioned | > pivot2 | ] - // ^ ^ ^ ^ ^ - // left less k great right - // - // a[left] and a[right] are undefined and are filled after the - // partitioning. - // - // Invariants: - // 1. for x in ]left, less[ : x < pivot1 - // 2. for x in [less, k[ : pivot1 <= x && x <= pivot2 - // 3. for x in ]great, right[ : x > pivot2 - for (int k = less; k <= great; k++) { - var ak = a[k]; - int comp_pivot1 = compare(ak, pivot1); - if (comp_pivot1 < 0) { - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } - less++; - } else { - int comp_pivot2 = compare(ak, pivot2); - if (comp_pivot2 > 0) { - while (true) { - int comp = compare(a[great], pivot2); - if (comp > 0) { - great--; - if (great < k) break; - // This is the only location inside the loop where a new - // iteration is started. - continue; - } else { - // a[great] <= pivot2. - comp = compare(a[great], pivot1); - if (comp < 0) { - // Triple exchange. - a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; - } else { - // a[great] >= pivot1. - a[k] = a[great]; - a[great--] = ak; - } - break; - } - } - } - } - } - } - - // Move pivots into their final positions. - // We shrunk the list from both sides (a[left] and a[right] have - // meaningless values in them) and now we move elements from the first - // and third partition into these locations so that we can store the - // pivots. - a[left] = a[less - 1]; - a[less - 1] = pivot1; - a[right] = a[great + 1]; - a[great + 1] = pivot2; - - // The list is now partitioned into three partitions: - // [ < pivot1 | >= pivot1 && <= pivot2 | > pivot2 ] - // ^ ^ ^ ^ - // left less great right - - // Recursive descent. (Don't include the pivot values.) - _doSort(a, left, less - 2, compare); - _doSort(a, great + 2, right, compare); - - if (pivots_are_equal) { - // All elements in the second partition are equal to the pivot. No - // need to sort them. - return; - } - - // In theory it should be enough to call _doSort recursively on the second - // partition. - // The Android source however removes the pivot elements from the recursive - // call if the second partition is too large (more than 2/3 of the list). - if (less < index1 && great > index5) { - while (compare(a[less], pivot1) == 0) { less++; } - while (compare(a[great], pivot2) == 0) { great--; } - - // Copy paste of the previous 3-way partitioning with adaptions. - // - // We partition the list into three parts: - // 1. == pivot1 - // 2. > pivot1 && < pivot2 - // 3. == pivot2 - // - // During the loop we have: - // [ == pivot1 | > pivot1 && < pivot2 | unpartitioned | == pivot2 ] - // ^ ^ ^ - // less k great - // - // Invariants: - // 1. for x in [ *, less[ : x == pivot1 - // 2. for x in [less, k[ : pivot1 < x && x < pivot2 - // 3. for x in ]great, * ] : x == pivot2 - for (int k = less; k <= great; k++) { - var ak = a[k]; - int comp_pivot1 = compare(ak, pivot1); - if (comp_pivot1 == 0) { - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } - less++; - } else { - int comp_pivot2 = compare(ak, pivot2); - if (comp_pivot2 == 0) { - while (true) { - int comp = compare(a[great], pivot2); - if (comp == 0) { - great--; - if (great < k) break; - // This is the only location inside the loop where a new - // iteration is started. - continue; - } else { - // a[great] < pivot2. - comp = compare(a[great], pivot1); - if (comp < 0) { - // Triple exchange. - a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; - } else { - // a[great] == pivot1. - a[k] = a[great]; - a[great--] = ak; - } - break; - } - } - } - } - } - // The second partition has now been cleared of pivot elements and looks - // as follows: - // [ * | > pivot1 && < pivot2 | * ] - // ^ ^ - // less great - // Sort the second partition using recursive descent. - _doSort(a, less, great, compare); - } else { - // The second partition looks as follows: - // [ * | >= pivot1 && <= pivot2 | * ] - // ^ ^ - // less great - // Simply sort it by recursive descent. - _doSort(a, less, great, compare); - } - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/internal/symbol.dart b/pkg/dev_compiler/test/generated_sdk/lib/internal/symbol.dart deleted file mode 100644 index 34088280c18a..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/internal/symbol.dart +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart._internal; - -/** - * Implementation of [core.Symbol]. This class uses the same name as - * a core class so a user can't tell the difference. - * - * The purpose of this class is to hide [_name] from user code, but - * make it accessible to Dart platform code via the static method - * [getName]. - */ -class Symbol implements core.Symbol { - final String _name; - - /** - * Source of RegExp matching Dart reserved words. - * - * Reserved words are not allowed as identifiers. - */ - static const String reservedWordRE = - r'(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|d(?:efault|o)|' - r'e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?:ew|ull)|' - r'ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|r(?:ue|y))|' - r'v(?:ar|oid)|w(?:hile|ith))'; - /** - * Source of RegExp matching any public identifier. - * - * A public identifier is a valid identifier (not a reserved word) - * that doesn't start with '_'. - */ - static const String publicIdentifierRE = - r'(?!' '$reservedWordRE' r'\b(?!\$))[a-zA-Z$][\w$]*'; - /** - * Source of RegExp matching any identifier. - * - * It matches identifiers but not reserved words. The identifiers - * may start with '_'. - */ - static const String identifierRE = - r'(?!' '$reservedWordRE' r'\b(?!\$))[a-zA-Z$_][\w$]*'; - /** - * Source of RegExp matching a declarable operator names. - * - * The operators that can be declared using `operator` declarations are - * also the only ones allowed as symbols. The name of the oeprators is - * the same as the operator itself except for unary minus, where the name - * is "unary-". - */ - static const String operatorRE = - r'(?:[\-+*/%&|^]|\[\]=?|==|~/?|<[<=]?|>[>=]?|unary-)'; - - // Grammar if symbols: - // symbol ::= qualifiedName | - // qualifiedName ::= publicIdentifier '.' qualifiedName | name - // name ::= publicIdentifier - // | publicIdentifier '=' - // | operator - // where publicIdentifier is any valid identifier (not a reserved word) - // that isn't private (doesn't start with '_'). - // - // Railroad diagram of the accepted grammar: - // - // /----------------\ - // | | - // | /-[.]-/ /-[=]-\ - // \ / / \ - // -------[id]-------------------------> - // \ / - // \------[operator]---/ - // \ / - // \------------/ - // - - /** - * RegExp that validates a non-empty non-private symbol. - * - * The empty symbol is handled before this regexp is used, and is not - * accepted. - */ - static final RegExp publicSymbolPattern = new RegExp( - '^(?:$operatorRE\$|$publicIdentifierRE(?:=?\$|[.](?!\$)))+?\$'); - - // The grammar of symbols that may be private is the same as for public - // symbols, except that "publicIdentifier" is replaced by "identifier", - // which matches any identifier. - - /** - * RegExp that validates a non-empty symbol. - * - * Private symbols are accepted. - * - * The empty symbol is handled before this regexp is used, and is not - * accepted. - */ - static final RegExp symbolPattern = new RegExp( - '^(?:$operatorRE\$|$identifierRE(?:=?\$|[.](?!\$)))+?\$'); - - const Symbol(String name) - : this._name = name; - - /** - * Platform-private method used by the mirror system to create - * otherwise invalid names. - */ - const Symbol.unvalidated(this._name); - - // This is called by dart2js. - Symbol.validated(String name) - : this._name = validatePublicSymbol(name); - - bool operator ==(Object other) => other is Symbol && _name == other._name; - - int get hashCode { - const arbitraryPrime = 664597; - return 0x1fffffff & (arbitraryPrime * _name.hashCode); - } - - toString() => 'Symbol("$_name")'; - - /// Platform-private accessor which cannot be called from user libraries. - static String getName(Symbol symbol) => symbol._name; - - static String validatePublicSymbol(String name) { - if (name.isEmpty || publicSymbolPattern.hasMatch(name)) return name; - if (name.startsWith('_')) { - // There may be other private parts in a qualified name than the first - // one, but this is a common case that deserves a specific error - // message. - throw new ArgumentError('"$name" is a private identifier'); - } - throw new ArgumentError( - '"$name" is not a valid (qualified) symbol name'); - } - - /** - * Checks whether name is a valid symbol name. - * - * This test allows both private and non-private symbols. - */ - static bool isValidSymbol(String name) { - return (name.isEmpty || symbolPattern.hasMatch(name)); - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/isolate/capability.dart b/pkg/dev_compiler/test/generated_sdk/lib/isolate/capability.dart deleted file mode 100644 index 87aa19c5600b..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/isolate/capability.dart +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of dart.isolate; - -/** - * An unforgeable object that comes back as equal when passed through other - * isolates. - * - * Sending a capability object to another isolate, and getting it back, - * will produce an object that is equal to the original. - * There is no other way to create objects equal to a capability object. - * - * Capabilities can be used as access guards: A remote isolate can send - * a request for an operation, but it is only allowed if the request contains - * the correct capability object. - * - * This allows exposing the same interface to multiple clients, - * but restricting some operations to only those clients - * that have also been given the corresponding capability. - * - * Capabilities can be used inside a single isolate, - * but they have no advantage over - * just using `new Object` to create a unique object, - * and it offers no real security against other code - * running in the same isolate. - */ -class Capability { - /** - * Create a new unforgeable capability object. - */ - factory Capability() = CapabilityImpl; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/isolate/isolate.dart b/pkg/dev_compiler/test/generated_sdk/lib/isolate/isolate.dart deleted file mode 100644 index 12fd02be47ea..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/isolate/isolate.dart +++ /dev/null @@ -1,703 +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. - -/** - * Concurrent programming using _isolates_: - * independent workers that are similar to threads - * but don't share memory, - * communicating only via messages. - */ -library dart.isolate; - -import "dart:async"; -import 'dart:_js_helper' show patch; -import 'dart:_isolate_helper' show CapabilityImpl, - CloseToken, - IsolateNatives, - JsIsolateSink, - ReceivePortImpl, - RawReceivePortImpl; - -part "capability.dart"; - -/** - * Thrown when an isolate cannot be created. - */ -class IsolateSpawnException implements Exception { - /** Error message reported by the spawn operation. */ - final String message; - IsolateSpawnException(this.message); - String toString() => "IsolateSpawnException: $message"; -} - -/** - * An isolated Dart execution context. - * - * All Dart code runs in an isolate, and code can access classes and values - * only from the same isolate. Different isolates can communicate by sending - * values through ports (see [ReceivePort], [SendPort]). - * - * An `Isolate` object is a reference to an isolate, usually different from - * the current isolate. - * It represents, and can be used control, the other isolate. - * - * When spawning a new isolate, the spawning isolate receives an `Isolate` - * object representing the new isolate when the spawn operation succeeds. - * - * Isolates run code in its own event loop, and each event may run smaller tasks - * in a nested microtask queue. - * - * An `Isolate` object allows other isolates to control the event loop - * of the isolate that it represents, and to inspect the isolate, - * for example by pausing the isolate or by getting events when the isolate - * has an uncaught error. - * - * The [controlPort] gives access to controlling the isolate, and the - * [pauseCapability] and [terminateCapability] guard access to some control - * operations. - * The `Isolate` object provided by a spawn operation will have the - * control port and capabilities needed to control the isolate. - * New isolates objects can be created without some of these capabilities - * if necessary. - * - * An `Isolate` object cannot be sent over a `SendPort`, but the control port - * and capabilities can be sent, and can be used to create a new functioning - * `Isolate` object in the receiving port's isolate. - */ -class Isolate { - /** Argument to `ping` and `kill`: Ask for immediate action. */ - static const int IMMEDIATE = 0; - /** Argument to `ping` and `kill`: Ask for action before the next event. */ - static const int BEFORE_NEXT_EVENT = 1; - /** Argument to `ping` and `kill`: Ask for action after normal events. */ - static const int AS_EVENT = 2; - - /** - * Control port used to send control messages to the isolate. - * - * This class provides helper functions that sends control messages - * to the control port. - * - * The control port identifies the isolate. - */ - final SendPort controlPort; - - /** - * Capability granting the ability to pause the isolate. - * - * This capability is used by [pause]. - * If the capability is not the correct pause capability of the isolate, - * including if the capability is `null`, then calls to `pause` will have no - * effect. - * - * If the isolate is started in a paused state, use this capability as - * argument to [resume] to resume the isolate. - */ - final Capability pauseCapability; - - /** - * Capability granting the ability to terminate the isolate. - * - * This capability is used by [kill] and [setErrorsFatal]. - * If the capability is not the correct termination capability of the isolate, - * including if the capability is `null`, then calls to those methods will - * have no effect. - */ - final Capability terminateCapability; - - /** - * Create a new [Isolate] object with a restricted set of capabilities. - * - * The port should be a control port for an isolate, as taken from - * another `Isolate` object. - * - * The capabilities should be the subset of the capabilities that are - * available to the original isolate. - * Capabilities of an isolate are locked to that isolate, and have no effect - * anywhere else, so the capabilities should come from the same isolate as - * the control port. - * - * If all the available capabilities are included, - * there is no reason to create a new object, - * since the behavior is defined entirely - * by the control port and capabilities. - */ - Isolate(this.controlPort, {this.pauseCapability, - this.terminateCapability}); - - /** - * Return the current [Isolate]. - * - * The isolate gives access to the capabilities needed to inspect, - * pause or kill the isolate, and allows granting these capabilities - * to others. - */ - static Isolate get current => _currentIsolateCache; - - /** - * Creates and spawns an isolate that shares the same code as the current - * isolate. - * - * The argument [entryPoint] specifies the entry point of the spawned - * isolate. It must be a top-level function or a static method that - * takes one argument - that is, one-parameter functions that can be - * compile-time constant function values. - * It is not allowed to pass the value of function expressions or an instance - * method extracted from an object. - * - * The entry-point function is invoked with the initial [message]. - * Usually the initial [message] contains a [SendPort] so - * that the spawner and spawnee can communicate with each other. - * - * If the [paused] parameter is set to `true`, - * the isolate will start up in a paused state, - * as if by an initial call of `isolate.pause(isolate.pauseCapability)`. - * This allows setting up error or exit listeners on the isolate - * before it starts running. - * To resume the isolate, call `isolate.resume(isolate.pauseCapability)`. - * - * WARNING: The `pause` parameter is not implemented on all platforms yet. - * - * Returns a future that will complete with an [Isolate] instance if the - * spawning succeeded. It will complete with an error otherwise. - */ - static Future spawn(void entryPoint(message), var message, - { bool paused: false }) { - try { - return IsolateNatives.spawnFunction(entryPoint, message, paused) - .then((msg) => new Isolate(msg[1], - pauseCapability: msg[2], - terminateCapability: msg[3])); - } catch (e, st) { - return new Future.error(e, st); - } - } - - /** - * Creates and spawns an isolate that runs the code from the library with - * the specified URI. - * - * The isolate starts executing the top-level `main` function of the library - * with the given URI. - * - * The target `main` must be a subtype of one of these three signatures: - * - * * `main()` - * * `main(args)` - * * `main(args, message)` - * - * When present, the parameter `args` is set to the provided [args] list. - * When present, the parameter `message` is set to the initial [message]. - * - * If the [packageRoot] parameter is provided, it is used to find the location - * of packages imports in the spawned isolate. - * The `packageRoot` URI must be a "file" or "http"/"https" URI that specifies - * a directory. If it doesn't end in a slash, one will be added before - * using the URI, and any query or fragment parts are ignored. - * Package imports (like "package:foo/bar.dart") in the new isolate are - * resolved against this location, as by - * `packageRoot.resolve("foo/bar.dart")`. - * This includes the main entry [uri] if it happens to be a package-URL. - * If [packageRoot] is omitted, it defaults to the same URI that - * the current isolate is using. - * - * WARNING: The [packageRoot] parameter is not implemented on all - * platforms yet. - * - * If the [paused] parameter is set to `true`, - * the isolate will start up in a paused state, - * as if by an initial call of `isolate.pause(isolate.pauseCapability)`. - * This allows setting up error or exit listeners on the isolate - * before it starts running. - * To resume the isolate, call `isolate.resume(isolate.pauseCapability)`. - * - * WARNING: The `pause` parameter is not implemented on all platforms yet. - * - * Returns a future that will complete with an [Isolate] instance if the - * spawning succeeded. It will complete with an error otherwise. - */ - static Future spawnUri( - Uri uri, List args, var message, { bool paused: false, - Uri packageRoot }) { - if (packageRoot != null) throw new UnimplementedError("packageRoot"); - try { - if (args is List) { - for (int i = 0; i < args.length; i++) { - if (args[i] is! String) { - throw new ArgumentError("Args must be a list of Strings $args"); - } - } - } else if (args != null) { - throw new ArgumentError("Args must be a list of Strings $args"); - } - return IsolateNatives.spawnUri(uri, args, message, paused) - .then((msg) => new Isolate(msg[1], - pauseCapability: msg[2], - terminateCapability: msg[3])); - } catch (e, st) { - return new Future.error(e, st); - } - } - - /** - * Requests the isolate to pause. - * - * WARNING: This method is experimental and not handled on every platform yet. - * - * The isolate should stop handling events by pausing its event queue. - * The request will eventually make the isolate stop doing anything. - * It will be handled before any other messages that are later sent to the - * isolate from the current isolate, but no other guarantees are provided. - * - * The event loop may be paused before previously sent, but not yet exeuted, - * messages have been reached. - * - * If [resumeCapability] is provided, it is used to identity the pause, - * and must be used again to end the pause using [resume]. - * Otherwise a new resume capability is created and returned. - * - * If an isolate is paused more than once using the same capability, - * only one resume with that capability is needed to end the pause. - * - * If an isolate is paused using more than one capability, - * they must all be individully ended before the isolate resumes. - * - * Returns the capability that must be used to resume end the pause. - */ - Capability pause([Capability resumeCapability]) { - if (resumeCapability == null) resumeCapability = new Capability(); - _pause(resumeCapability); - return resumeCapability; - } - - /** Internal implementation of [pause]. */ - void _pause(Capability resumeCapability) { - var message = new List(3) - ..[0] = "pause" - ..[1] = pauseCapability - ..[2] = resumeCapability; - controlPort.send(message); - } - - /** - * Resumes a paused isolate. - * - * WARNING: This method is experimental and not handled on every platform yet. - * - * Sends a message to an isolate requesting that it ends a pause - * that was requested using the [resumeCapability]. - * - * When all active pause requests have been cancelled, the isolate - * will continue handling normal messages. - * - * The capability must be one returned by a call to [pause] on this - * isolate, otherwise the resume call does nothing. - */ - void resume(Capability resumeCapability) { - var message = new List(2) - ..[0] = "resume" - ..[1] = resumeCapability; - controlPort.send(message); - } - - /** - * Asks the isolate to send a message on [responsePort] when it terminates. - * - * WARNING: This method is experimental and not handled on every platform yet. - * - * The isolate will send a `null` message on [responsePort] as the last - * thing before it terminates. It will run no further code after the message - * has been sent. - * - * If the isolate is already dead, no message will be sent. - */ - /* TODO(lrn): Can we do better? Can the system recognize this message and - * send a reply if the receiving isolate is dead? - */ - void addOnExitListener(SendPort responsePort) { - // TODO(lrn): Can we have an internal method that checks if the receiving - // isolate of a SendPort is still alive? - var message = new List(2) - ..[0] = "add-ondone" - ..[1] = responsePort; - controlPort.send(message); - } - - /** - * Stop listening on exit messages from the isolate. - * - * WARNING: This method is experimental and not handled on every platform yet. - * - * If a call has previously been made to [addOnExitListener] with the same - * send-port, this will unregister the port, and it will no longer receive - * a message when the isolate terminates. - * A response may still be sent until this operation is fully processed by - * the isolate. - */ - void removeOnExitListener(SendPort responsePort) { - var message = new List(2) - ..[0] = "remove-ondone" - ..[1] = responsePort; - controlPort.send(message); - } - - /** - * Set whether uncaught errors will terminate the isolate. - * - * WARNING: This method is experimental and not handled on every platform yet. - * - * If errors are fatal, any uncaught error will terminate the isolate - * event loop and shut down the isolate. - * - * This call requires the [terminateCapability] for the isolate. - * If the capability is not correct, no change is made. - */ - void setErrorsFatal(bool errorsAreFatal) { - var message = new List(3) - ..[0] = "set-errors-fatal" - ..[1] = terminateCapability - ..[2] = errorsAreFatal; - controlPort.send(message); - } - - /** - * Requests the isolate to shut down. - * - * WARNING: This method is experimental and not handled on every platform yet. - * - * The isolate is requested to terminate itself. - * The [priority] argument specifies when this must happen. - * - * The [priority] must be one of [IMMEDIATE], [BEFORE_NEXT_EVENT] or - * [AS_EVENT]. - * The shutdown is performed at different times depending on the priority: - * - * * `IMMEDIATE`: The the isolate shuts down as soon as possible. - * Control messages are handled in order, so all previously sent control - * events from this isolate will all have been processed. - * The shutdown should happen no later than if sent with - * `BEFORE_NEXT_EVENT`. - * It may happen earlier if the system has a way to shut down cleanly - * at an earlier time, even during the execution of another event. - * * `BEFORE_NEXT_EVENT`: The shutdown is scheduled for the next time - * control returns to the event loop of the receiving isolate, - * after the current event, and any already scheduled control events, - * are completed. - * * `AS_EVENT`: The shutdown does not happen until all prevously sent - * non-control messages from the current isolate to the receiving isolate - * have been processed. - * The kill operation effectively puts the shutdown into the normal event - * queue after previously sent messages, and it is affected by any control - * messages that affect normal events, including `pause`. - * This can be used to wait for a another event to be processed. - */ - void kill([int priority = BEFORE_NEXT_EVENT]) { - controlPort.send(["kill", terminateCapability, priority]); - } - - /** - * Request that the isolate send a response on the [responsePort]. - * - * WARNING: This method is experimental and not handled on every platform yet. - * - * If the isolate is alive, it will eventually send a `null` response on - * the response port. - * - * The [pingType] must be one of [IMMEDIATE], [BEFORE_NEXT_EVENT] or - * [AS_EVENT]. - * The response is sent at different times depending on the ping type: - * - * * `IMMEDIATE`: The the isolate responds as soon as it receives the - * control message. This is after any previous control message - * from the same isolate has been received. - * * `BEFORE_NEXT_EVENT`: The response is scheduled for the next time - * control returns to the event loop of the receiving isolate, - * after the current event, and any already scheduled control events, - * are completed. - * * `AS_EVENT`: The response is not sent until all prevously sent - * non-control messages from the current isolate to the receiving isolate - * have been processed. - * The ping effectively puts the response into the normal event queue - * after previously sent messages, and it is affected by any control - * messages that affect normal events, including `pause`. - * This can be used to wait for a another event to be processed. - */ - void ping(SendPort responsePort, [int pingType = IMMEDIATE]) { - var message = new List(3) - ..[0] = "ping" - ..[1] = responsePort - ..[2] = pingType; - controlPort.send(message); - } - - /** - * Requests that uncaught errors of the isolate are sent back to [port]. - * - * WARNING: This method is experimental and not handled on every platform yet. - * - * The errors are sent back as two elements lists. - * The first element is a `String` representation of the error, usually - * created by calling `toString` on the error. - * The second element is a `String` representation of an accompanying - * stack trace, or `null` if no stack trace was provided. - * - * Listening using the same port more than once does nothing. It will only - * get each error once. - */ - void addErrorListener(SendPort port) { - var message = new List(2) - ..[0] = "getErrors" - ..[1] = port; - controlPort.send(message); - } - - /** - * Stop listening for uncaught errors through [port]. - * - * WARNING: This method is experimental and not handled on every platform yet. - * - * The `port` should be a port that is listening for errors through - * [addErrorListener]. This call requests that the isolate stops sending - * errors on the port. - * - * If the same port has been passed via `addErrorListener` more than once, - * only one call to `removeErrorListener` is needed to stop it from receiving - * errors. - * - * Closing the receive port at the end of the send port will not stop the - * isolate from sending errors, they are just going to be lost. - */ - void removeErrorListener(SendPort port) { - var message = new List(2) - ..[0] = "stopErrors" - ..[1] = port; - controlPort.send(message); - } - - /** - * Returns a broadcast stream of uncaught errors from the isolate. - * - * Each error is provided as an error event on the stream. - * - * The actual error object and stackTraces will not necessarily - * be the same object types as in the actual isolate, but they will - * always have the same [Object.toString] result. - * - * This stream is based on [addErrorListener] and [removeErrorListener]. - */ - Stream get errors { - StreamController controller; - RawReceivePort port; - void handleError(message) { - String errorDescription = message[0]; - String stackDescription = message[1]; - var error = new RemoteError(errorDescription, stackDescription); - controller.addError(error, error.stackTrace); - } - controller = new StreamController.broadcast( - sync: true, - onListen: () { - port = new RawReceivePort(handleError); - this.addErrorListener(port.sendPort); - }, - onCancel: () { - this.removeErrorListener(port.sendPort); - port.close(); - port = null; - }); - return controller.stream; - } - - static final _currentIsolateCache = IsolateNatives.currentIsolate; -} - -/** - * Sends messages to its [ReceivePort]s. - * - * [SendPort]s are created from [ReceivePort]s. Any message sent through - * a [SendPort] is delivered to its corresponding [ReceivePort]. There might be - * many [SendPort]s for the same [ReceivePort]. - * - * [SendPort]s can be transmitted to other isolates, and they preserve equality - * when sent. - */ -abstract class SendPort implements Capability { - - /** - * Sends an asynchronous [message] through this send port, to its - * corresponding `ReceivePort`. - * - * The content of [message] can be: primitive values (null, num, bool, double, - * String), instances of [SendPort], and lists and maps whose elements are any - * of these. List and maps are also allowed to be cyclic. - * - * In the special circumstances when two isolates share the same code and are - * running in the same process (e.g. isolates created via [Isolate.spawn]), it - * is also possible to send object instances (which would be copied in the - * process). This is currently only supported by the dartvm. For now, the - * dart2js compiler only supports the restricted messages described above. - */ - void send(var message); - - /** - * Tests whether [other] is a [SendPort] pointing to the same - * [ReceivePort] as this one. - */ - bool operator==(var other); - - /** - * Returns an immutable hash code for this send port that is - * consistent with the == operator. - */ - int get hashCode; -} - -/** - * Together with [SendPort], the only means of communication between isolates. - * - * [ReceivePort]s have a `sendPort` getter which returns a [SendPort]. - * Any message that is sent through this [SendPort] - * is delivered to the [ReceivePort] it has been created from. There, the - * message is dispatched to the `ReceivePort`'s listener. - * - * A [ReceivePort] is a non-broadcast stream. This means that it buffers - * incoming messages until a listener is registered. Only one listener can - * receive messages. See [Stream.asBroadcastStream] for transforming the port - * to a broadcast stream. - * - * A [ReceivePort] may have many [SendPort]s. - */ -abstract class ReceivePort implements Stream { - - /** - * Opens a long-lived port for receiving messages. - * - * A [ReceivePort] is a non-broadcast stream. This means that it buffers - * incoming messages until a listener is registered. Only one listener can - * receive messages. See [Stream.asBroadcastStream] for transforming the port - * to a broadcast stream. - * - * A receive port is closed by canceling its subscription. - */ - factory ReceivePort() = ReceivePortImpl; - - /** - * Creates a [ReceivePort] from a [RawReceivePort]. - * - * The handler of the given [rawPort] is overwritten during the construction - * of the result. - */ - factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) { - return new ReceivePortImpl.fromRawReceivePort(rawPort); - } - - /** - * Inherited from [Stream]. - * - * Note that [onError] and [cancelOnError] are ignored since a ReceivePort - * will never receive an error. - * - * The [onDone] handler will be called when the stream closes. - * The stream closes when [close] is called. - */ - StreamSubscription listen(void onData(var message), - { Function onError, - void onDone(), - bool cancelOnError }); - - /** - * Closes `this`. - * - * If the stream has not been canceled yet, adds a close-event to the event - * queue and discards any further incoming messages. - * - * If the stream has already been canceled this method has no effect. - */ - void close(); - - /** - * Returns a [SendPort] that sends to this receive port. - */ - SendPort get sendPort; -} - -abstract class RawReceivePort { - /** - * Opens a long-lived port for receiving messages. - * - * A [RawReceivePort] is low level and does not work with [Zone]s. It - * can not be paused. The data-handler must be set before the first - * event is received. - */ - factory RawReceivePort([void handler(event)]) { - return new RawReceivePortImpl(handler); - } - - /** - * Sets the handler that is invoked for every incoming message. - * - * The handler is invoked in the root-zone ([Zone.ROOT]). - */ - void set handler(Function newHandler); - - /** - * Closes the port. - * - * After a call to this method any incoming message is silently dropped. - */ - void close(); - - /** - * Returns a [SendPort] that sends to this raw receive port. - */ - SendPort get sendPort; -} - -/** - * Wraps unhandled exceptions thrown during isolate execution. It is - * used to show both the error message and the stack trace for unhandled - * exceptions. - */ -// TODO(floitsch): probably going to remove and replace with something else. -class _IsolateUnhandledException implements Exception { - /** Message being handled when exception occurred. */ - final message; - - /** Wrapped exception. */ - final source; - - /** Trace for the wrapped exception. */ - final StackTrace stackTrace; - - const _IsolateUnhandledException(this.message, this.source, this.stackTrace); - - String toString() { - return 'IsolateUnhandledException: exception while handling message: ' - '${message} \n ' - '${source.toString().replaceAll("\n", "\n ")}\n' - 'original stack trace:\n ' - '${stackTrace.toString().replaceAll("\n","\n ")}'; - } -} - -/** - * Description of an error from another isolate. - * - * This error has the same `toString()` and `stackTrace.toString()` behavior - * as the original error, but has no other features of the original error. - */ -class RemoteError implements Error { - final String _description; - final StackTrace stackTrace; - RemoteError(String description, String stackDescription) - : _description = description, - stackTrace = new _RemoteStackTrace(stackDescription); - String toString() => _description; -} - -class _RemoteStackTrace implements StackTrace { - String _trace; - _RemoteStackTrace(this._trace); - String toString() => _trace; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/math/jenkins_smi_hash.dart b/pkg/dev_compiler/test/generated_sdk/lib/math/jenkins_smi_hash.dart deleted file mode 100644 index 8a0056eac9fa..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/math/jenkins_smi_hash.dart +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. -part of dart.math; - -/** - * This is the [Jenkins hash function][1] but using masking to keep - * values in SMI range. - * - * [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function - * - * Use: - * Hash each value with the hash of the previous value, then get the final - * hash by calling finish. - * - * var hash = 0; - * for (var value in values) { - * hash = JenkinsSmiHash.combine(hash, value.hashCode); - * } - * hash = JenkinsSmiHash.finish(hash); - */ -class _JenkinsSmiHash { - // TODO(11617): This class should be optimized and standardized elsewhere. - - static int combine(int hash, int value) { - hash = 0x1fffffff & (hash + value); - hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); - return hash ^ (hash >> 6); - } - - static int finish(int hash) { - hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); - hash = hash ^ (hash >> 11); - return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); - } - - static int hash2(a, b) => finish(combine(combine(0, a), b)); - - static int hash4(a, b, c, d) => - finish(combine(combine(combine(combine(0, a), b), c), d)); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/math/math.dart b/pkg/dev_compiler/test/generated_sdk/lib/math/math.dart deleted file mode 100644 index 8ea0713a10f7..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/math/math.dart +++ /dev/null @@ -1,443 +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. - -/** - * Mathematical constants and functions, plus a random number generator. - */ -library dart.math; -import 'dart:_foreign_helper' show JS; -import 'dart:_js_helper' show patch, checkNum; - -part "jenkins_smi_hash.dart"; -part "point.dart"; -part "random.dart"; -part "rectangle.dart"; - -/** - * Base of the natural logarithms. - * - * Typically written as "e". - */ -const double E = 2.718281828459045; - -/** - * Natural logarithm of 10. - */ -const double LN10 = 2.302585092994046; - -/** - * Natural logarithm of 2. - */ -const double LN2 = 0.6931471805599453; - -/** - * Base-2 logarithm of [E]. - */ -const double LOG2E = 1.4426950408889634; - -/** - * Base-10 logarithm of [E]. - */ -const double LOG10E = 0.4342944819032518; - -/** - * The PI constant. - */ -const double PI = 3.1415926535897932; - -/** - * Square root of 1/2. - */ -const double SQRT1_2 = 0.7071067811865476; - -/** - * Square root of 2. - */ -const double SQRT2 = 1.4142135623730951; - -/** - * Returns the lesser of two numbers. - * - * Returns NaN if either argument is NaN. - * The lesser of [:-0.0:] and [:0.0:] is [:-0.0:]. - * If the arguments are otherwise equal (including int and doubles with the - * same mathematical value) then it is unspecified which of the two arguments - * is returned. - */ -num min(num a, num b) { - // These partially redundant type checks improve code quality for dart2js. - // Most of the improvement is at call sites from the inferred non-null num - // return type. - if (a is! num) throw new ArgumentError(a); - if (b is! num) throw new ArgumentError(b); - - if (a > b) return b; - if (a < b) return a; - if (b is double) { - // Special case for NaN and -0.0. If one argument is NaN return NaN. - // [min] must also distinguish between -0.0 and 0.0. - if (a is double) { - if (a == 0.0) { - // a is either 0.0 or -0.0. b is either 0.0, -0.0 or NaN. - // The following returns -0.0 if either a or b is -0.0, and it - // returns NaN if b is NaN. - return (a + b) * a * b; - } - } - // Check for NaN and b == -0.0. - if (a == 0 && b.isNegative || b.isNaN) return b; - return a; - } - return a; -} - -/** - * Returns the larger of two numbers. - * - * Returns NaN if either argument is NaN. - * The larger of [:-0.0:] and [:0.0:] is [:0.0:]. If the arguments are - * otherwise equal (including int and doubles with the same mathematical value) - * then it is unspecified which of the two arguments is returned. - */ -num max(num a, num b) { - // These partially redundant type checks improve code quality for dart2js. - // Most of the improvement is at call sites from the inferred non-null num - // return type. - if (a is! num) throw new ArgumentError(a); - if (b is! num) throw new ArgumentError(b); - - if (a > b) return a; - if (a < b) return b; - if (b is double) { - // Special case for NaN and -0.0. If one argument is NaN return NaN. - // [max] must also distinguish between -0.0 and 0.0. - if (a is double) { - if (a == 0.0) { - // a is either 0.0 or -0.0. b is either 0.0, -0.0, or NaN. - // The following returns 0.0 if either a or b is 0.0, and it - // returns NaN if b is NaN. - return a + b; - } - } - // Check for NaN. - if (b.isNaN) return b; - return a; - } - // max(-0.0, 0) must return 0. - if (b == 0 && a.isNegative) return b; - return a; -} - -/** - * A variant of [atan]. - * - * Converts both arguments to doubles. - * - * Returns the angle between the positive x-axis and the vector ([b],[a]). - * The result, in radians, is in the range -PI..PI. - * - * If [b] is positive, this is the same as [:atan(b/a):]. - * - * The result is negative when [a] is negative (including when [a] is the - * double -0.0). - * - * If [a] is equal to zero, the vector ([b],[a]) is considered parallel to - * the x-axis, even if [b] is also equal to zero. The sign of [b] determines - * the direction of the vector along the x-axis. - * - * Returns NaN if either argument is NaN. - */ -double atan2(num a, num b) - => JS('double', r'Math.atan2(#, #)', checkNum(a), checkNum(b)); - -/** - * Returns [x] to the power of [exponent]. - * - * If [x] is an [int] and [exponent] is a non-negative [int], the result is - * an [int], otherwise both arguments are converted to doubles first, and the - * result is a [double]. - * - * For integers, the power is always equal to the mathematical result of `x` to - * the power `exponent`, only limited by the available memory. - * - * For doubles, `pow(x, y)` handles edge cases as follows: - * - * - if `y` is zero (0.0 or -0.0), the result is always 1.0. - * - if `x` is 1.0, the result is always 1.0. - * - otherwise, if either `x` or `y` is NaN then the result is NaN. - * - if `x` is negative (but not -0.0) and `y` is a finite non-integer, the - * result is NaN. - * - if `x` is Infinity and `y` is negative, the result is 0.0. - * - if `x` is Infinity and `y` is positive, the result is Infinity. - * - if `x` is 0.0 and `y` is negative, the result is Infinity. - * - if `x` is 0.0 and `y` is positive, the result is 0.0. - * - if `x` is -Infinity or -0.0 and `y` is an odd integer, then the result is - * `-pow(-x ,y)`. - * - if `x` is -Infinity or -0.0 and `y` is not an odd integer, then the result - * is the same as `pow(-x , y)`. - * - if `y` is Infinity and the absolute value of `x` is less than 1, the - * result is 0.0. - * - if `y` is Infinity and `x` is -1, the result is 1.0. - * - if `y` is Infinity and the absolute value of `x` is greater than 1, - * the result is Infinity. - * - if `y` is -Infinity, the result is `1/pow(x, Infinity)`. - * - * This corresponds to the `pow` function defined in the IEEE Standard 754-2008. - * - * Notice that an [int] result cannot overflow, but a [double] result might - * be [double.INFINITY]. - */ -num pow(num x, num exponent) { - checkNum(x); - checkNum(exponent); - return JS('num', r'Math.pow(#, #)', x, exponent); -} - -/** - * Converts [x] to a double and returns the sine of the value. - * - * If [x] is not a finite number, the result is NaN. - */ -double sin(num x) - => JS('double', r'Math.sin(#)', checkNum(x)); - -/** - * Converts [x] to a double and returns the cosine of the value. - * - * If [x] is not a finite number, the result is NaN. - */ -double cos(num x) - => JS('double', r'Math.cos(#)', checkNum(x)); - -/** - * Converts [x] to a double and returns the tangent of the value. - * - * The tangent function is equivalent to [:sin(x)/cos(x):] and may be - * infinite (positive or negative) when [:cos(x):] is equal to zero. - * If [x] is not a finite number, the result is NaN. - */ -double tan(num x) - => JS('double', r'Math.tan(#)', checkNum(x)); - -/** - * Converts [x] to a double and returns the arc cosine of the value. - * - * Returns a value in the range -PI..PI, or NaN if [x] is outside - * the range -1..1. - */ -double acos(num x) - => JS('double', r'Math.acos(#)', checkNum(x)); - -/** - * Converts [x] to a double and returns the arc sine of the value. - * Returns a value in the range -PI..PI, or NaN if [x] is outside - * the range -1..1. - */ -double asin(num x) - => JS('double', r'Math.asin(#)', checkNum(x)); - -/** - * Converts [x] to a dobule and returns the arc tangent of the vlaue. - * Returns a value in the range -PI/2..PI/2, or NaN if [x] is NaN. - */ -double atan(num x) - => JS('double', r'Math.atan(#)', checkNum(x)); - -/** - * Converts [x] to a double and returns the positive square root of the value. - * - * Returns -0.0 if [x] is -0.0, and NaN if [x] is otherwise negative or NaN. - */ -double sqrt(num x) - => JS('double', r'Math.sqrt(#)', checkNum(x)); - -/** - * Converts [x] to a double and returns the natural exponent, [E], - * to the power [x]. - * Returns NaN if [x] is NaN. - */ -double exp(num x) - => JS('double', r'Math.exp(#)', checkNum(x)); - -/** - * Converts [x] to a double and returns the natural logarithm of the value. - * Returns negative infinity if [x] is equal to zero. - * Returns NaN if [x] is NaN or less than zero. - */ -double log(num x) - => JS('double', r'Math.log(#)', checkNum(x)); - -const int _POW2_32 = 0x100000000; -class _JSRandom implements Random { - // The Dart2JS implementation of Random doesn't use a seed. - const _JSRandom(); - - int nextInt(int max) { - if (max <= 0 || max > _POW2_32) { - throw new RangeError("max must be in range 0 < max ≤ 2^32, was $max"); - } - return JS("int", "(Math.random() * #) >>> 0", max); - } - - /** - * Generates a positive random floating point value uniformly distributed on - * the range from 0.0, inclusive, to 1.0, exclusive. - */ - double nextDouble() => JS("double", "Math.random()"); - - /** - * Generates a random boolean value. - */ - bool nextBool() => JS("bool", "Math.random() < 0.5"); -} -class _Random implements Random { - // Constants used by the algorithm or masking. - static const double _POW2_53_D = 1.0 * (0x20000000000000); - static const double _POW2_27_D = 1.0 * (1 << 27); - static const int _MASK32 = 0xFFFFFFFF; - - // State comprised of two unsigned 32 bit integers. - int _lo = 0; - int _hi = 0; - - // Implements: - // uint64_t hash = 0; - // do { - // hash = hash * 1037 ^ mix64((uint64_t)seed); - // seed >>= 64; - // } while (seed != 0 && seed != -1); // Limits for pos/neg seed. - // if (hash == 0) { - // hash = 0x5A17; - // } - // _lo = hash & _MASK_32; - // _hi = hash >> 32; - // and then does four _nextState calls to shuffle bits around. - _Random(int seed) { - int empty_seed = 0; - if (seed < 0) { - empty_seed = -1; - } - do { - int low = seed & _MASK32; - seed = (seed - low) ~/ _POW2_32; - int high = seed & _MASK32; - seed = (seed - high) ~/ _POW2_32; - - // Thomas Wang's 64-bit mix function. - // http://www.concentric.net/~Ttwang/tech/inthash.htm - // via. http://web.archive.org/web/20071223173210/http://www.concentric.net/~Ttwang/tech/inthash.htm - - // key = ~key + (key << 21); - int tmplow = low << 21; - int tmphigh = (high << 21) | (low >> 11); - tmplow = (~low & _MASK32) + tmplow; - low = tmplow & _MASK32; - high = (~high + tmphigh + ((tmplow - low) ~/ 0x100000000)) & _MASK32; - // key = key ^ (key >> 24). - tmphigh = high >> 24; - tmplow = (low >> 24) | (high << 8); - low ^= tmplow; - high ^= tmphigh; - // key = key * 265 - tmplow = low * 265; - low = tmplow & _MASK32; - high = (high * 265 + (tmplow - low) ~/ 0x100000000) & _MASK32; - // key = key ^ (key >> 14); - tmphigh = high >> 14; - tmplow = (low >> 14) | (high << 18); - low ^= tmplow; - high ^= tmphigh; - // key = key * 21 - tmplow = low * 21; - low = tmplow & _MASK32; - high = (high * 21 + (tmplow - low) ~/ 0x100000000) & _MASK32; - // key = key ^ (key >> 28). - tmphigh = high >> 28; - tmplow = (low >> 28) | (high << 4); - low ^= tmplow; - high ^= tmphigh; - // key = key + (key << 31); - tmplow = low << 31; - tmphigh = (high << 31) | (low >> 1); - tmplow += low; - low = tmplow & _MASK32; - high = (high + tmphigh + (tmplow - low) ~/ 0x100000000) & _MASK32; - // Mix end. - - // seed = seed * 1037 ^ key; - tmplow = _lo * 1037; - _lo = tmplow & _MASK32; - _hi = (_hi * 1037 + (tmplow - _lo) ~/ 0x100000000) & _MASK32; - _lo ^= low; - _hi ^= high; - } while (seed != empty_seed); - - if (_hi == 0 && _lo == 0) { - _lo = 0x5A17; - } - _nextState(); - _nextState(); - _nextState(); - _nextState(); - } - - // The algorithm used here is Multiply with Carry (MWC) with a Base b = 2^32. - // http://en.wikipedia.org/wiki/Multiply-with-carry - // The constant A (0xFFFFDA61) is selected from "Numerical Recipes 3rd - // Edition" p.348 B1. - - // Implements: - // var state = (A * _lo + _hi) & _MASK_64; - // _lo = state & _MASK_32; - // _hi = state >> 32; - void _nextState() { - // Simulate (0xFFFFDA61 * lo + hi) without overflowing 53 bits. - int tmpHi = 0xFFFF0000 * _lo; // At most 48 bits of significant result. - int tmpHiLo = tmpHi & _MASK32; // Get the lower 32 bits. - int tmpHiHi = tmpHi - tmpHiLo; // And just the upper 32 bits. - int tmpLo = 0xDA61 * _lo; - int tmpLoLo = tmpLo & _MASK32; - int tmpLoHi = tmpLo - tmpLoLo; - - int newLo = tmpLoLo + tmpHiLo + _hi; - _lo = newLo & _MASK32; - int newLoHi = newLo - _lo; - _hi = ((tmpLoHi + tmpHiHi + newLoHi) ~/ _POW2_32) & _MASK32; - assert(_lo < _POW2_32); - assert(_hi < _POW2_32); - } - - int nextInt(int max) { - if (max <= 0 || max > _POW2_32) { - throw new RangeError("max must be in range 0 < max ≤ 2^32, was $max"); - } - if ((max & (max - 1)) == 0) { - // Fast case for powers of two. - _nextState(); - return _lo & (max - 1); - } - - int rnd32; - int result; - do { - _nextState(); - rnd32 = _lo; - result = rnd32.remainder(max); // % max; - } while ((rnd32 - result + max) >= _POW2_32); - return result; - } - - double nextDouble() { - _nextState(); - int bits26 = _lo & ((1 << 26) - 1); - _nextState(); - int bits27 = _lo & ((1 << 27) - 1); - return (bits26 * _POW2_27_D + bits27) / _POW2_53_D; - } - - bool nextBool() { - _nextState(); - return (_lo & 1) == 0; - } -} \ No newline at end of file diff --git a/pkg/dev_compiler/test/generated_sdk/lib/math/point.dart b/pkg/dev_compiler/test/generated_sdk/lib/math/point.dart deleted file mode 100644 index 42fcc469eb11..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/math/point.dart +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. -part of dart.math; - -/** - * A utility class for representing two-dimensional positions. - */ -class Point { - final T x; - final T y; - - const Point(T x, T y): this.x = x, this.y = y; - - String toString() => 'Point($x, $y)'; - - /** - * A `Point` is only equal to another `Point` with the same coordinates. - * - * This point is equal to `other` if, and only if, - * `other` is a `Point` with - * [x] equal to `other.x` and [y] equal to `other.y`. - */ - bool operator ==(other) { - if (other is !Point) return false; - return x == other.x && y == other.y; - } - - int get hashCode => _JenkinsSmiHash.hash2(x.hashCode, y.hashCode); - - /** - * Add [other] to `this`, as if both points were vectors. - * - * Returns the resulting "vector" as a Point. - */ - Point operator +(Point other) { - return new Point(x + other.x, y + other.y); - } - - /** - * Subtract [other] from `this`, as if both points were vectors. - * - * Returns the resulting "vector" as a Point. - */ - Point operator -(Point other) { - return new Point(x - other.x, y - other.y); - } - - /** - * Scale this point by [factor] as if it were a vector. - * - * *Important* *Note*: This function accepts a `num` as its argument only so - * that you can scale Point objects by an `int` factor. Because the - * star operator always returns the same type of Point that originally called - * it, passing in a double [factor] on a `Point` _causes_ _a_ - * _runtime_ _error_ in checked mode. - */ - Point operator *(num factor) { - return new Point(x * factor, y * factor); - } - - /** - * Get the straight line (Euclidean) distance between the origin (0, 0) and - * this point. - */ - double get magnitude => sqrt(x * x + y * y); - - /** - * Returns the distance between `this` and [other]. - */ - double distanceTo(Point other) { - var dx = x - other.x; - var dy = y - other.y; - return sqrt(dx * dx + dy * dy); - } - - /** - * Returns the squared distance between `this` and [other]. - * - * Squared distances can be used for comparisons when the actual value is not - * required. - */ - T squaredDistanceTo(Point other) { - var dx = x - other.x; - var dy = y - other.y; - return dx * dx + dy * dy; - } -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/math/random.dart b/pkg/dev_compiler/test/generated_sdk/lib/math/random.dart deleted file mode 100644 index 13654cdcfe49..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/math/random.dart +++ /dev/null @@ -1,41 +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. - -part of dart.math; - -/** - * A generator of random bool, int, or double values. - * - * The default implementation supplies a stream of - * pseudo-random bits that are not suitable for cryptographic purposes. - */ -abstract class Random { - /** - * Creates a random-number generator. The optional parameter [seed] is used - * to initialize the internal state of the generator. The implementation of - * the random stream can change between releases of the library. - */ - factory Random([int seed]) => - (seed == null) ? const _JSRandom() : new _Random(seed); - - /** - * Generates a positive random integer uniformly distributed on the range - * from 0, inclusive, to [max], exclusive. - * - * Implementation note: The default implementation supports [max] values - * between 1 and ((1<<32) - 1) inclusive. - */ - int nextInt(int max); - - /** - * Generates a positive random floating point value uniformly distributed on - * the range from 0.0, inclusive, to 1.0, exclusive. - */ - double nextDouble(); - - /** - * Generates a random boolean value. - */ - bool nextBool(); -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/math/rectangle.dart b/pkg/dev_compiler/test/generated_sdk/lib/math/rectangle.dart deleted file mode 100644 index 1ab292a29afc..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/math/rectangle.dart +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. -part of dart.math; - -/** - * A base class for representing two-dimensional axis-aligned rectangles. - * - * This rectangle uses a left-handed Cartesian coordinate system, with x - * directed to the right and y directed down, as per the convention in 2D - * computer graphics. - * - * See also: - * [W3C Coordinate Systems Specification](http://www.w3.org/TR/SVG/coords.html#InitialCoordinateSystem). - * - * The rectangle is the set of points with representable coordinates greater - * than or equal to left/top, and with distance to left/top no greater than - * width/height (to the limit of the precission of the coordinates). - */ -abstract class _RectangleBase { - const _RectangleBase(); - - /** The x-coordinate of the left edge. */ - T get left; - /** The y-coordinate of the top edge. */ - T get top; - /** The width of the rectangle. */ - T get width; - /** The height of the rectangle. */ - T get height; - - /** The x-coordinate of the right edge. */ - T get right => left + width; - /** The y-coordinate of the bottom edge. */ - T get bottom => top + height; - - String toString() { - return 'Rectangle ($left, $top) $width x $height'; - } - - bool operator ==(other) { - if (other is !Rectangle) return false; - return left == other.left && top == other.top && right == other.right && - bottom == other.bottom; - } - - int get hashCode => _JenkinsSmiHash.hash4(left.hashCode, top.hashCode, - right.hashCode, bottom.hashCode); - - /** - * Computes the intersection of `this` and [other]. - * - * The intersection of two axis-aligned rectangles, if any, is always another - * axis-aligned rectangle. - * - * Returns the intersection of this and `other`, or `null` if they don't - * intersect. - */ - Rectangle intersection(Rectangle other) { - var x0 = max(left, other.left); - var x1 = min(left + width, other.left + other.width); - - if (x0 <= x1) { - var y0 = max(top, other.top); - var y1 = min(top + height, other.top + other.height); - - if (y0 <= y1) { - return new Rectangle(x0, y0, x1 - x0, y1 - y0); - } - } - return null; - } - - - /** - * Returns true if `this` intersects [other]. - */ - bool intersects(Rectangle other) { - return (left <= other.left + other.width && - other.left <= left + width && - top <= other.top + other.height && - other.top <= top + height); - } - - /** - * Returns a new rectangle which completely contains `this` and [other]. - */ - Rectangle boundingBox(Rectangle other) { - var right = max(this.left + this.width, other.left + other.width); - var bottom = max(this.top + this.height, other.top + other.height); - - var left = min(this.left, other.left); - var top = min(this.top, other.top); - - return new Rectangle(left, top, right - left, bottom - top); - } - - /** - * Tests whether `this` entirely contains [another]. - */ - bool containsRectangle(Rectangle another) { - return left <= another.left && - left + width >= another.left + another.width && - top <= another.top && - top + height >= another.top + another.height; - } - - /** - * Tests whether [another] is inside or along the edges of `this`. - */ - bool containsPoint(Point another) { - return another.x >= left && - another.x <= left + width && - another.y >= top && - another.y <= top + height; - } - - Point get topLeft => new Point(this.left, this.top); - Point get topRight => new Point(this.left + this.width, this.top); - Point get bottomRight => new Point(this.left + this.width, - this.top + this.height); - Point get bottomLeft => new Point(this.left, - this.top + this.height); -} - - -/** - * A class for representing two-dimensional rectangles whose properties are - * immutable. - */ -class Rectangle extends _RectangleBase { - final T left; - final T top; - final T width; - final T height; - - /** - * Create a rectangle spanned by `(left, top)` and `(left+width, top+height)`. - * - * The rectangle contains the points - * with x-coordinate between `left` and `left + width`, and - * with y-coordinate between `top` and `top + height`, both inclusive. - * - * The `width` and `height` should be non-negative. - * If `width` or `height` are negative, they are clamped to zero. - * - * If `width` and `height` are zero, the "rectangle" comprises only the single - * point `(left, top)`. - */ - const Rectangle(this.left, this.top, T width, T height) - : this.width = (width < 0) ? -width * 0 : width, // Inline _clampToZero. - this.height = (height < 0) ? -height * 0 : height; - - /** - * Create a rectangle spanned by the points [a] and [b]; - * - * The rectangle contains the points - * with x-coordinate between `a.x` and `b.x`, and - * with y-coordinate between `a.y` and `b.y`, both inclusive. - * - * If the distance between `a.x` and `b.x` is not representable - * (which can happen if one or both is a double), - * the actual right edge might be slightly off from `max(a.x, b.x)`. - * Similar for the y-coordinates and the bottom edge. - */ - factory Rectangle.fromPoints(Point a, Point b) { - T left = min(a.x, b.x); - T width = max(a.x, b.x) - left; - T top = min(a.y, b.y); - T height = max(a.y, b.y) - top; - return new Rectangle(left, top, width, height); - } -} - -/** - * A class for representing two-dimensional axis-aligned rectangles with mutable - * properties. - */ -class MutableRectangle extends _RectangleBase - implements Rectangle { - - /** - * The x-coordinate of the left edge. - * - * Setting the value will move the rectangle without changing its width. - */ - T left; - /** - * The y-coordinate of the left edge. - * - * Setting the value will move the rectangle without changing its height. - */ - T top; - T _width; - T _height; - - /** - * Create a mutable rectangle spanned by `(left, top)` and - * `(left+width, top+height)`. - * - * The rectangle contains the points - * with x-coordinate between `left` and `left + width`, and - * with y-coordinate between `top` and `top + height`, both inclusive. - * - * The `width` and `height` should be non-negative. - * If `width` or `height` are negative, they are clamped to zero. - * - * If `width` and `height` are zero, the "rectangle" comprises only the single - * point `(left, top)`. - */ - MutableRectangle(this.left, this.top, T width, T height) - : this._width = (width < 0) ? _clampToZero(width) : width, - this._height = (height < 0) ? _clampToZero(height) : height; - - /** - * Create a mutable rectangle spanned by the points [a] and [b]; - * - * The rectangle contains the points - * with x-coordinate between `a.x` and `b.x`, and - * with y-coordinate between `a.y` and `b.y`, both inclusive. - * - * If the distance between `a.x` and `b.x` is not representable - * (which can happen if one or both is a double), - * the actual right edge might be slightly off from `max(a.x, b.x)`. - * Similar for the y-coordinates and the bottom edge. - */ - factory MutableRectangle.fromPoints(Point a, Point b) { - T left = min(a.x, b.x); - T width = max(a.x, b.x) - left; - T top = min(a.y, b.y); - T height = max(a.y, b.y) - top; - return new MutableRectangle(left, top, width, height); - } - - T get width => _width; - - /** - * Sets the width of the rectangle. - * - * The width must be non-negative. - * If a negative width is supplied, it is clamped to zero. - * - * Setting the value will change the right edge of the rectangle, - * but will not change [left]. - */ - void set width(T width) { - if (width < 0) width = _clampToZero(width); - _width = width; - } - - T get height => _height; - - /** - * Sets the height of the rectangle. - * - * The height must be non-negative. - * If a negative height is supplied, it is clamped to zero. - * - * Setting the value will change the bottom edge of the rectangle, - * but will not change [top]. - */ - void set height(T height) { - if (height < 0) height = _clampToZero(height); - _height = height; - } -} - -/** - * Converts a negative [int] or [double] to a zero-value of the same type. - * - * Returns `0` if value is int, `0.0` if value is double. - */ -num _clampToZero(num value) { - assert(value < 0); - return -value * 0; -} diff --git a/pkg/dev_compiler/test/generated_sdk/lib/typed_data/typed_data.dart b/pkg/dev_compiler/test/generated_sdk/lib/typed_data/typed_data.dart deleted file mode 100644 index e51eb3971d51..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/lib/typed_data/typed_data.dart +++ /dev/null @@ -1,1779 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -library dart.typed_data; - -import 'dart:collection'; -import 'dart:_internal' show FixedLengthListMixin; -import 'dart:_native_typed_data'; -import 'dart:_js_helper' - show Creates, JavaScriptIndexingBehavior, JSName, Null, Returns, patch; -import 'dart:_interceptors' show JSIndexable, JSUInt32, JSUInt31; -import 'dart:_internal'; -import 'dart:math' as Math; -import 'dart:_foreign_helper' show JS; - -/** - * A sequence of bytes underlying a typed data object. - * Used to process large quantities of binary or numerical data - * more efficiently using a typed view. - */ -abstract class ByteBuffer { - /** - * Returns the length of this byte buffer, in bytes. - */ - int get lengthInBytes; - - /** - * Creates a new [Uint8List] view of this buffer. - */ - Uint8List asUint8List([int offsetInBytes = 0, int length]); - /** - * Creates a new [Int8List] view of this buffer. - */ - Int8List asInt8List([int offsetInBytes = 0, int length]); - /** - * Creates a new [Uint8Clamped] view of this buffer. - */ - Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]); - /** - * Creates a new [Uint16List] view of this buffer. - */ - Uint16List asUint16List([int offsetInBytes = 0, int length]); - /** - * Creates a new [Int16List] view of this buffer. - */ - Int16List asInt16List([int offsetInBytes = 0, int length]); - /** - * Creates a new [Uint32List] view of this buffer. - */ - Uint32List asUint32List([int offsetInBytes = 0, int length]); - /** - * Creates a new [Int32List] view of this buffer. - */ - Int32List asInt32List([int offsetInBytes = 0, int length]); - /** - * Creates a new [Uint64List] view of this buffer. - */ - Uint64List asUint64List([int offsetInBytes = 0, int length]); - /** - * Creates a new [Int64List] view of this buffer. - */ - Int64List asInt64List([int offsetInBytes = 0, int length]); - /** - * Creates a new [Int32x4List] view of this buffer. - */ - Int32x4List asInt32x4List([int offsetInBytes = 0, int length]); - /** - * Creates a new [Float32List] view of this buffer. - */ - Float32List asFloat32List([int offsetInBytes = 0, int length]); - /** - * Creates a new [Float64List] view of this buffer. - */ - Float64List asFloat64List([int offsetInBytes = 0, int length]); - /** - * Creates a new [Float32x4List] view of this buffer. - */ - Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]); - /** - * Creates a new [Float64x2List] view of this buffer. - */ - Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]); - /** - * Creates a new [ByteData] view of this buffer. - */ - ByteData asByteData([int offsetInBytes = 0, int length]); -} - - -/** - * A typed view of a sequence of bytes. - */ -abstract class TypedData { - /** - * Returns the number of bytes in the representation of each element in this - * list. - */ - int get elementSizeInBytes; - - /** - * Returns the offset in bytes into the underlying byte buffer of this view. - */ - int get offsetInBytes; - - /** - * Returns the length of this view, in bytes. - */ - int get lengthInBytes; - - /** - * Returns the byte buffer associated with this object. - */ - ByteBuffer get buffer; -} - - -/** - * Describes endianness to be used when accessing or updating a - * sequence of bytes. - */ -class Endianness { - const Endianness._(this._littleEndian); - - static const Endianness BIG_ENDIAN = const Endianness._(false); - static const Endianness LITTLE_ENDIAN = const Endianness._(true); - static final Endianness HOST_ENDIAN = - (new ByteData.view(new Uint16List.fromList([1]).buffer)).getInt8(0) == 1 ? - LITTLE_ENDIAN : BIG_ENDIAN; - - final bool _littleEndian; -} - - -/** - * A fixed-length, random-access sequence of bytes that also provides random - * and unaligned access to the fixed-width integers and floating point - * numbers represented by those bytes. - * ByteData may be used to pack and unpack data from external sources - * (such as networks or files systems), and to process large quantities - * of numerical data more efficiently than would be possible - * with ordinary [List] implementations. ByteData can save space, by - * eliminating the need for object headers, and time, by eliminating the - * need for data copies. Finally, ByteData may be used to intentionally - * reinterpret the bytes representing one arithmetic type as another. - * For example this code fragment determine what 32-bit signed integer - * is represented by the bytes of a 32-bit floating point number: - * - * var buffer = new Uint8List(8).buffer; - * var bdata = new ByteData.view(buffer); - * bdata.setFloat32(0, 3.04); - * int huh = bdata.getInt32(0); - */ -abstract class ByteData implements TypedData { - /** - * Creates a [ByteData] of the specified length (in elements), all of - * whose elements are initially zero. - */ - factory ByteData(int length) = NativeByteData; - - /** - * Creates an [ByteData] _view_ of the specified region in the specified - * byte buffer. Changes in the [ByteData] will be visible in the byte - * buffer and vice versa. If the [offsetInBytes] index of the region is not - * specified, it defaults to zero (the first byte in the byte buffer). - * If the length is not specified, it defaults to null, which indicates - * that the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - */ - factory ByteData.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asByteData(offsetInBytes, length); - } - - /** - * Returns the (possibly negative) integer represented by the byte at the - * specified [byteOffset] in this object, in two's complement binary - * representation. The return value will be between -128 and 127, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * greater than or equal to the length of this object. - */ - int getInt8(int byteOffset); - - /** - * Sets the byte at the specified [byteOffset] in this object to the - * two's complement binary representation of the specified [value], which - * must fit in a single byte. In other words, [value] must be between - * -128 and 127, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * greater than or equal to the length of this object. - */ - void setInt8(int byteOffset, int value); - - /** - * Returns the positive integer represented by the byte at the specified - * [byteOffset] in this object, in unsigned binary form. The - * return value will be between 0 and 255, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * greater than or equal to the length of this object. - */ - int getUint8(int byteOffset); - - /** - * Sets the byte at the specified [byteOffset] in this object to the - * unsigned binary representation of the specified [value], which must fit - * in a single byte. in other words, [value] must be between 0 and 255, - * inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, - * or greater than or equal to the length of this object. - */ - void setUint8(int byteOffset, int value); - - /** - * Returns the (possibly negative) integer represented by the two bytes at - * the specified [byteOffset] in this object, in two's complement binary - * form. - * The return value will be between 215 and 215 - 1, - * inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 2` is greater than the length of this object. - */ - int getInt16(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Sets the two bytes starting at the specified [byteOffset] in this - * object to the two's complement binary representation of the specified - * [value], which must fit in two bytes. In other words, [value] must lie - * between 215 and 215 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 2` is greater than the length of this object. - */ - void setInt16(int byteOffset, - int value, - [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Returns the positive integer represented by the two bytes starting - * at the specified [byteOffset] in this object, in unsigned binary - * form. - * The return value will be between 0 and 216 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 2` is greater than the length of this object. - */ - int getUint16(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Sets the two bytes starting at the specified [byteOffset] in this object - * to the unsigned binary representation of the specified [value], - * which must fit in two bytes. in other words, [value] must be between - * 0 and 216 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 2` is greater than the length of this object. - */ - void setUint16(int byteOffset, - int value, - [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Returns the (possibly negative) integer represented by the four bytes at - * the specified [byteOffset] in this object, in two's complement binary - * form. - * The return value will be between 231 and 231 - 1, - * inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 4` is greater than the length of this object. - */ - int getInt32(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Sets the four bytes starting at the specified [byteOffset] in this - * object to the two's complement binary representation of the specified - * [value], which must fit in four bytes. In other words, [value] must lie - * between 231 and 231 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 4` is greater than the length of this object. - */ - void setInt32(int byteOffset, - int value, - [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Returns the positive integer represented by the four bytes starting - * at the specified [byteOffset] in this object, in unsigned binary - * form. - * The return value will be between 0 and 232 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 4` is greater than the length of this object. - */ - int getUint32(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Sets the four bytes starting at the specified [byteOffset] in this object - * to the unsigned binary representation of the specified [value], - * which must fit in four bytes. in other words, [value] must be between - * 0 and 232 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 4` is greater than the length of this object. - */ - void setUint32(int byteOffset, - int value, - [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Returns the (possibly negative) integer represented by the eight bytes at - * the specified [byteOffset] in this object, in two's complement binary - * form. - * The return value will be between 263 and 263 - 1, - * inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 8` is greater than the length of this object. - */ - int getInt64(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Sets the eight bytes starting at the specified [byteOffset] in this - * object to the two's complement binary representation of the specified - * [value], which must fit in eight bytes. In other words, [value] must lie - * between 263 and 263 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 8` is greater than the length of this object. - */ - void setInt64(int byteOffset, - int value, - [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Returns the positive integer represented by the eight bytes starting - * at the specified [byteOffset] in this object, in unsigned binary - * form. - * The return value will be between 0 and 264 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 8` is greater than the length of this object. - */ - int getUint64(int byteOffset, [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Sets the eight bytes starting at the specified [byteOffset] in this object - * to the unsigned binary representation of the specified [value], - * which must fit in eight bytes. in other words, [value] must be between - * 0 and 264 - 1, inclusive. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 8` is greater than the length of this object. - */ - void setUint64(int byteOffset, - int value, - [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Returns the floating point number represented by the four bytes at - * the specified [byteOffset] in this object, in IEEE 754 - * single-precision binary floating-point format (binary32). - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 4` is greater than the length of this object. - */ - double getFloat32(int byteOffset, - [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Sets the four bytes starting at the specified [byteOffset] in this - * object to the IEEE 754 single-precision binary floating-point - * (binary32) representation of the specified [value]. - * - * **Note that this method can lose precision.** The input [value] is - * a 64-bit floating point value, which will be converted to 32-bit - * floating point value by IEEE 754 rounding rules before it is stored. - * If [value] cannot be represented exactly as a binary32, it will be - * converted to the nearest binary32 value. If two binary32 values are - * equally close, the one whose least significant bit is zero will be used. - * Note that finite (but large) values can be converted to infinity, and - * small non-zero values can be converted to zero. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 4` is greater than the length of this object. - */ - void setFloat32(int byteOffset, - double value, - [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Returns the floating point number represented by the eight bytes at - * the specified [byteOffset] in this object, in IEEE 754 - * double-precision binary floating-point format (binary64). - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 8` is greater than the length of this object. - */ - double getFloat64(int byteOffset, - [Endianness endian = Endianness.BIG_ENDIAN]); - - /** - * Sets the eight bytes starting at the specified [byteOffset] in this - * object to the IEEE 754 double-precision binary floating-point - * (binary64) representation of the specified [value]. - * - * Throws [RangeError] if [byteOffset] is negative, or - * `byteOffset + 8` is greater than the length of this object. - */ - void setFloat64(int byteOffset, - double value, - [Endianness endian = Endianness.BIG_ENDIAN]); -} - - -/** - * A fixed-length list of 8-bit signed integers. - * For long lists, this implementation can be considerably - * more space- and time-efficient than the default [List] implementation. - */ -abstract class Int8List implements List, TypedData { - /** - * Creates an [Int8List] of the specified length (in elements), all of - * whose elements are initially zero. - */ - factory Int8List(int length) = NativeInt8List; - - /** - * Creates a [Int8List] with the same length as the [elements] list - * and copies over the elements. - */ - factory Int8List.fromList(List elements) = - NativeInt8List.fromList; - - /** - * Creates an [Int8List] _view_ of the specified region in the specified - * byte buffer. Changes in the [Int8List] will be visible in the byte - * buffer and vice versa. If the [offsetInBytes] index of the region is not - * specified, it defaults to zero (the first byte in the byte buffer). - * If the length is not specified, it defaults to null, which indicates - * that the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - */ - factory Int8List.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asInt8List(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 1; -} - - -/** - * A fixed-length list of 8-bit unsigned integers. - * For long lists, this implementation can be considerably - * more space- and time-efficient than the default [List] implementation. - */ -abstract class Uint8List implements List, TypedData { - /** - * Creates a [Uint8List] of the specified length (in elements), all of - * whose elements are initially zero. - */ - factory Uint8List(int length) = NativeUint8List; - - /** - * Creates a [Uint8List] with the same length as the [elements] list - * and copies over the elements. - */ - factory Uint8List.fromList(List elements) = - NativeUint8List.fromList; - - /** - * Creates a [Uint8List] _view_ of the specified region in the specified - * byte buffer. Changes in the [Uint8List] will be visible in the byte - * buffer and vice versa. If the [offsetInBytes] index of the region is not - * specified, it defaults to zero (the first byte in the byte buffer). - * If the length is not specified, it defaults to null, which indicates - * that the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - */ - factory Uint8List.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asUint8List(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 1; -} - - -/** - * A fixed-length list of 8-bit unsigned integers. - * For long lists, this implementation can be considerably - * more space- and time-efficient than the default [List] implementation. - * Indexed store clamps the value to range 0..0xFF. - */ -abstract class Uint8ClampedList implements List, TypedData { - /** - * Creates a [Uint8ClampedList] of the specified length (in elements), all of - * whose elements are initially zero. - */ - factory Uint8ClampedList(int length) = NativeUint8ClampedList; - - /** - * Creates a [Uint8ClampedList] of the same size as the [elements] - * list and copies over the values clamping when needed. - */ - factory Uint8ClampedList.fromList(List elements) = - NativeUint8ClampedList.fromList; - - /** - * Creates a [Uint8ClampedList] _view_ of the specified region in the - * specified byte [buffer]. Changes in the [Uint8List] will be visible in the - * byte buffer and vice versa. If the [offsetInBytes] index of the region is - * not specified, it defaults to zero (the first byte in the byte buffer). - * If the length is not specified, it defaults to null, which indicates that - * the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - */ - factory Uint8ClampedList.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asUint8ClampedList(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 1; -} - - -/** - * A fixed-length list of 16-bit signed integers that is viewable as a - * [TypedData]. For long lists, this implementation can be considerably - * more space- and time-efficient than the default [List] implementation. - */ -abstract class Int16List implements List, TypedData { - /** - * Creates an [Int16List] of the specified length (in elements), all of - * whose elements are initially zero. - */ - factory Int16List(int length) = NativeInt16List; - - /** - * Creates a [Int16List] with the same length as the [elements] list - * and copies over the elements. - */ - factory Int16List.fromList(List elements) = - NativeInt16List.fromList; - - /** - * Creates an [Int16List] _view_ of the specified region in the specified - * byte buffer. Changes in the [Int16List] will be visible in the byte - * buffer and vice versa. If the [offsetInBytes] index of the region is not - * specified, it defaults to zero (the first byte in the byte buffer). - * If the length is not specified, it defaults to null, which indicates - * that the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - * - * Throws [ArgumentError] if [offsetInBytes] is not a multiple of - * [BYTES_PER_ELEMENT]. - */ - factory Int16List.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asInt16List(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 2; -} - - -/** - * A fixed-length list of 16-bit unsigned integers that is viewable as a - * [TypedData]. For long lists, this implementation can be considerably - * more space- and time-efficient than the default [List] implementation. - */ -abstract class Uint16List implements List, TypedData { - /** - * Creates a [Uint16List] of the specified length (in elements), all - * of whose elements are initially zero. - */ - factory Uint16List(int length) = NativeUint16List; - - /** - * Creates a [Uint16List] with the same length as the [elements] list - * and copies over the elements. - */ - factory Uint16List.fromList(List elements) = - NativeUint16List.fromList; - - /** - * Creates a [Uint16List] _view_ of the specified region in - * the specified byte buffer. Changes in the [Uint16List] will be - * visible in the byte buffer and vice versa. If the [offsetInBytes] index - * of the region is not specified, it defaults to zero (the first byte in - * the byte buffer). If the length is not specified, it defaults to null, - * which indicates that the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - * - * Throws [ArgumentError] if [offsetInBytes] is not a multiple of - * [BYTES_PER_ELEMENT]. - */ - factory Uint16List.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asUint16List(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 2; -} - - -/** - * A fixed-length list of 32-bit signed integers that is viewable as a - * [TypedData]. For long lists, this implementation can be considerably - * more space- and time-efficient than the default [List] implementation. - */ -abstract class Int32List implements List, TypedData { - /** - * Creates an [Int32List] of the specified length (in elements), all of - * whose elements are initially zero. - */ - factory Int32List(int length) = NativeInt32List; - - /** - * Creates a [Int32List] with the same length as the [elements] list - * and copies over the elements. - */ - factory Int32List.fromList(List elements) = - NativeInt32List.fromList; - - /** - * Creates an [Int32List] _view_ of the specified region in the specified - * byte buffer. Changes in the [Int32List] will be visible in the byte - * buffer and vice versa. If the [offsetInBytes] index of the region is not - * specified, it defaults to zero (the first byte in the byte buffer). - * If the length is not specified, it defaults to null, which indicates - * that the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - * - * Throws [ArgumentError] if [offsetInBytes] is not a multiple of - * [BYTES_PER_ELEMENT]. - */ - factory Int32List.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asInt32List(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 4; -} - - -/** - * A fixed-length list of 32-bit unsigned integers that is viewable as a - * [TypedData]. For long lists, this implementation can be considerably - * more space- and time-efficient than the default [List] implementation. - */ -abstract class Uint32List implements List, TypedData { - /** - * Creates a [Uint32List] of the specified length (in elements), all - * of whose elements are initially zero. - */ - factory Uint32List(int length) = NativeUint32List; - - /** - * Creates a [Uint32List] with the same length as the [elements] list - * and copies over the elements. - */ - factory Uint32List.fromList(List elements) = - NativeUint32List.fromList; - - /** - * Creates a [Uint32List] _view_ of the specified region in - * the specified byte buffer. Changes in the [Uint32] will be - * visible in the byte buffer and vice versa. If the [offsetInBytes] index - * of the region is not specified, it defaults to zero (the first byte in - * the byte buffer). If the length is not specified, it defaults to null, - * which indicates that the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - * - * Throws [ArgumentError] if [offsetInBytes] is not a multiple of - * [BYTES_PER_ELEMENT]. - */ - factory Uint32List.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asUint32List(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 4; -} - - -/** - * A fixed-length list of 64-bit signed integers that is viewable as a - * [TypedData]. For long lists, this implementation can be considerably - * more space- and time-efficient than the default [List] implementation. - */ -abstract class Int64List implements List, TypedData { - /** - * Creates an [Int64List] of the specified length (in elements), all of - * whose elements are initially zero. - */ - factory Int64List(int length) { - throw new UnsupportedError("Int64List not supported by dart2js."); - } - - /** - * Creates a [Int64List] with the same length as the [elements] list - * and copies over the elements. - */ - factory Int64List.fromList(List elements) { - throw new UnsupportedError("Int64List not supported by dart2js."); - } - - /** - * Creates an [Int64List] _view_ of the specified region in the specified - * byte buffer. Changes in the [Int64List] will be visible in the byte buffer - * and vice versa. If the [offsetInBytes] index of the region is not - * specified, it defaults to zero (the first byte in the byte buffer). - * If the length is not specified, it defaults to null, which indicates that - * the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - * - * Throws [ArgumentError] if [offsetInBytes] is not a multiple of - * [BYTES_PER_ELEMENT]. - */ - factory Int64List.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asInt64List(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 8; -} - - -/** - * A fixed-length list of 64-bit unsigned integers that is viewable as a - * [TypedData]. For long lists, this implementation can be considerably - * more space- and time-efficient than the default [List] implementation. - */ -abstract class Uint64List implements List, TypedData { - /** - * Creates a [Uint64List] of the specified length (in elements), all - * of whose elements are initially zero. - */ - factory Uint64List(int length) { - throw new UnsupportedError("Uint64List not supported by dart2js."); - } - - /** - * Creates a [Uint64List] with the same length as the [elements] list - * and copies over the elements. - */ - factory Uint64List.fromList(List elements) { - throw new UnsupportedError("Uint64List not supported by dart2js."); - } - - /** - * Creates an [Uint64List] _view_ of the specified region in - * the specified byte buffer. Changes in the [Uint64List] will be - * visible in the byte buffer and vice versa. If the [offsetInBytes] - * index of the region is not specified, it defaults to zero (the first - * byte in the byte buffer). If the length is not specified, it defaults - * to null, which indicates that the view extends to the end of the byte - * buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - * - * Throws [ArgumentError] if [offsetInBytes] is not a multiple of - * [BYTES_PER_ELEMENT]. - */ - factory Uint64List.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asUint64List(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 8; -} - - -/** - * A fixed-length list of IEEE 754 single-precision binary floating-point - * numbers that is viewable as a [TypedData]. For long lists, this - * implementation can be considerably more space- and time-efficient than - * the default [List] implementation. - */ -abstract class Float32List implements List, TypedData { - /** - * Creates a [Float32List] of the specified length (in elements), all of - * whose elements are initially zero. - */ - factory Float32List(int length) = NativeFloat32List; - - /** - * Creates a [Float32List] with the same length as the [elements] list - * and copies over the elements. - */ - factory Float32List.fromList(List elements) = - NativeFloat32List.fromList; - - /** - * Creates a [Float32List] _view_ of the specified region in the specified - * byte buffer. Changes in the [Float32List] will be visible in the byte - * buffer and vice versa. If the [offsetInBytes] index of the region is not - * specified, it defaults to zero (the first byte in the byte buffer). - * If the length is not specified, it defaults to null, which indicates - * that the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - * - * Throws [ArgumentError] if [offsetInBytes] is not a multiple of - * [BYTES_PER_ELEMENT]. - */ - factory Float32List.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asFloat32List(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 4; -} - - -/** - * A fixed-length list of IEEE 754 double-precision binary floating-point - * numbers that is viewable as a [TypedData]. For long lists, this - * implementation can be considerably more space- and time-efficient than - * the default [List] implementation. - */ -abstract class Float64List implements List, TypedData { - /** - * Creates a [Float64List] of the specified length (in elements), all of - * whose elements are initially zero. - */ - factory Float64List(int length) = NativeFloat64List; - - /** - * Creates a [Float64List] with the same length as the [elements] list - * and copies over the elements. - */ - factory Float64List.fromList(List elements) = - NativeFloat64List.fromList; - - /** - * Creates a [Float64List] _view_ of the specified region in the specified - * byte buffer. Changes in the [Float64List] will be visible in the byte - * buffer and vice versa. If the [offsetInBytes] index of the region is not - * specified, it defaults to zero (the first byte in the byte buffer). - * If the length is not specified, it defaults to null, which indicates - * that the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - * - * Throws [ArgumentError] if [offsetInBytes] is not a multiple of - * [BYTES_PER_ELEMENT]. - */ - factory Float64List.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asFloat64List(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 8; -} - - -/** - * A fixed-length list of Float32x4 numbers that is viewable as a - * [TypedData]. For long lists, this implementation will be considerably more - * space- and time-efficient than the default [List] implementation. - */ -abstract class Float32x4List implements List, TypedData { - /** - * Creates a [Float32x4List] of the specified length (in elements), - * all of whose elements are initially zero. - */ - factory Float32x4List(int length) = NativeFloat32x4List; - - /** - * Creates a [Float32x4List] with the same length as the [elements] list - * and copies over the elements. - */ - factory Float32x4List.fromList(List elements) = - NativeFloat32x4List.fromList; - - /** - * Creates a [Float32x4List] _view_ of the specified region in the specified - * byte buffer. Changes in the [Float32x4List] will be visible in the byte - * buffer and vice versa. If the [offsetInBytes] index of the region is not - * specified, it defaults to zero (the first byte in the byte buffer). - * If the length is not specified, it defaults to null, which indicates - * that the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - * - * Throws [ArgumentError] if [offsetInBytes] is not a multiple of - * [BYTES_PER_ELEMENT]. - */ - factory Float32x4List.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asFloat32x4List(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 16; -} - - -/** - * A fixed-length list of Int32x4 numbers that is viewable as a - * [TypedData]. For long lists, this implementation will be considerably more - * space- and time-efficient than the default [List] implementation. - */ -abstract class Int32x4List implements List, TypedData { - /** - * Creates a [Int32x4List] of the specified length (in elements), - * all of whose elements are initially zero. - */ - factory Int32x4List(int length) = NativeInt32x4List; - - /** - * Creates a [Int32x4List] with the same length as the [elements] list - * and copies over the elements. - */ - factory Int32x4List.fromList(List elements) = - NativeInt32x4List.fromList; - - /** - * Creates a [Int32x4List] _view_ of the specified region in the specified - * byte buffer. Changes in the [Int32x4List] will be visible in the byte - * buffer and vice versa. If the [offsetInBytes] index of the region is not - * specified, it defaults to zero (the first byte in the byte buffer). - * If the length is not specified, it defaults to null, which indicates - * that the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - * - * Throws [ArgumentError] if [offsetInBytes] is not a multiple of - * [BYTES_PER_ELEMENT]. - */ - factory Int32x4List.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asInt32x4List(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 16; -} - - -/** - * A fixed-length list of Float64x2 numbers that is viewable as a - * [TypedData]. For long lists, this implementation will be considerably more - * space- and time-efficient than the default [List] implementation. - */ -abstract class Float64x2List implements List, TypedData { - /** - * Creates a [Float64x2List] of the specified length (in elements), - * all of whose elements have all lanes set to zero. - */ - factory Float64x2List(int length) = NativeFloat64x2List; - - /** - * Creates a [Float64x2List] with the same length as the [elements] list - * and copies over the elements. - */ - factory Float64x2List.fromList(List elements) = - NativeFloat64x2List.fromList; - - /** - * Creates a [Float64x2List] _view_ of the specified region in the specified - * byte buffer. Changes in the [Float64x2List] will be visible in the byte - * buffer and vice versa. If the [offsetInBytes] index of the region is not - * specified, it defaults to zero (the first byte in the byte buffer). - * If the length is not specified, it defaults to null, which indicates - * that the view extends to the end of the byte buffer. - * - * Throws [RangeError] if [offsetInBytes] or [length] are negative, or - * if [offsetInBytes] + ([length] * elementSizeInBytes) is greater than - * the length of [buffer]. - * - * Throws [ArgumentError] if [offsetInBytes] is not a multiple of - * [BYTES_PER_ELEMENT]. - */ - factory Float64x2List.view(ByteBuffer buffer, - [int offsetInBytes = 0, int length]) { - return buffer.asFloat64x2List(offsetInBytes, length); - } - - static const int BYTES_PER_ELEMENT = 16; -} - - -/** - * Float32x4 immutable value type and operations. - * Float32x4 stores 4 32-bit floating point values in "lanes". - * The lanes are "x", "y", "z", and "w" respectively. - */ -abstract class Float32x4 { - factory Float32x4(double x, double y, double z, double w) = - NativeFloat32x4; - factory Float32x4.splat(double v) = NativeFloat32x4.splat; - factory Float32x4.zero() = NativeFloat32x4.zero; - factory Float32x4.fromInt32x4Bits(Int32x4 x) = - NativeFloat32x4.fromInt32x4Bits; - /// Sets the x and y lanes to their respective values in [v] and sets the z - /// and w lanes to 0.0. - factory Float32x4.fromFloat64x2(Float64x2 v) = - NativeFloat32x4.fromFloat64x2; - - /// Addition operator. - Float32x4 operator+(Float32x4 other); - /// Negate operator. - Float32x4 operator-(); - /// Subtraction operator. - Float32x4 operator-(Float32x4 other); - /// Multiplication operator. - Float32x4 operator*(Float32x4 other); - /// Division operator. - Float32x4 operator/(Float32x4 other); - - /// Relational less than. - Int32x4 lessThan(Float32x4 other); - /// Relational less than or equal. - Int32x4 lessThanOrEqual(Float32x4 other); - /// Relational greater than. - Int32x4 greaterThan(Float32x4 other); - /// Relational greater than or equal. - Int32x4 greaterThanOrEqual(Float32x4 other); - /// Relational equal. - Int32x4 equal(Float32x4 other); - /// Relational not-equal. - Int32x4 notEqual(Float32x4 other); - - /// Returns a copy of [this] each lane being scaled by [s]. - /// Equivalent to this * new Float32x4.splat(s) - Float32x4 scale(double s); - /// Returns the lane-wise absolute value of this [Float32x4]. - Float32x4 abs(); - /// Lane-wise clamp [this] to be in the range [lowerLimit]-[upperLimit]. - Float32x4 clamp(Float32x4 lowerLimit, Float32x4 upperLimit); - - /// Extracted x value. - double get x; - /// Extracted y value. - double get y; - /// Extracted z value. - double get z; - /// Extracted w value. - double get w; - - /// Extract the sign bits from each lane return them in the first 4 bits. - /// "x" lane is bit 0. - /// "y" lane is bit 1. - /// "z" lane is bit 2. - /// "w" lane is bit 3. - int get signMask; - - /// Mask passed to [shuffle] or [shuffleMix]. - static const int XXXX = 0x0; - static const int XXXY = 0x40; - static const int XXXZ = 0x80; - static const int XXXW = 0xC0; - static const int XXYX = 0x10; - static const int XXYY = 0x50; - static const int XXYZ = 0x90; - static const int XXYW = 0xD0; - static const int XXZX = 0x20; - static const int XXZY = 0x60; - static const int XXZZ = 0xA0; - static const int XXZW = 0xE0; - static const int XXWX = 0x30; - static const int XXWY = 0x70; - static const int XXWZ = 0xB0; - static const int XXWW = 0xF0; - static const int XYXX = 0x4; - static const int XYXY = 0x44; - static const int XYXZ = 0x84; - static const int XYXW = 0xC4; - static const int XYYX = 0x14; - static const int XYYY = 0x54; - static const int XYYZ = 0x94; - static const int XYYW = 0xD4; - static const int XYZX = 0x24; - static const int XYZY = 0x64; - static const int XYZZ = 0xA4; - static const int XYZW = 0xE4; - static const int XYWX = 0x34; - static const int XYWY = 0x74; - static const int XYWZ = 0xB4; - static const int XYWW = 0xF4; - static const int XZXX = 0x8; - static const int XZXY = 0x48; - static const int XZXZ = 0x88; - static const int XZXW = 0xC8; - static const int XZYX = 0x18; - static const int XZYY = 0x58; - static const int XZYZ = 0x98; - static const int XZYW = 0xD8; - static const int XZZX = 0x28; - static const int XZZY = 0x68; - static const int XZZZ = 0xA8; - static const int XZZW = 0xE8; - static const int XZWX = 0x38; - static const int XZWY = 0x78; - static const int XZWZ = 0xB8; - static const int XZWW = 0xF8; - static const int XWXX = 0xC; - static const int XWXY = 0x4C; - static const int XWXZ = 0x8C; - static const int XWXW = 0xCC; - static const int XWYX = 0x1C; - static const int XWYY = 0x5C; - static const int XWYZ = 0x9C; - static const int XWYW = 0xDC; - static const int XWZX = 0x2C; - static const int XWZY = 0x6C; - static const int XWZZ = 0xAC; - static const int XWZW = 0xEC; - static const int XWWX = 0x3C; - static const int XWWY = 0x7C; - static const int XWWZ = 0xBC; - static const int XWWW = 0xFC; - static const int YXXX = 0x1; - static const int YXXY = 0x41; - static const int YXXZ = 0x81; - static const int YXXW = 0xC1; - static const int YXYX = 0x11; - static const int YXYY = 0x51; - static const int YXYZ = 0x91; - static const int YXYW = 0xD1; - static const int YXZX = 0x21; - static const int YXZY = 0x61; - static const int YXZZ = 0xA1; - static const int YXZW = 0xE1; - static const int YXWX = 0x31; - static const int YXWY = 0x71; - static const int YXWZ = 0xB1; - static const int YXWW = 0xF1; - static const int YYXX = 0x5; - static const int YYXY = 0x45; - static const int YYXZ = 0x85; - static const int YYXW = 0xC5; - static const int YYYX = 0x15; - static const int YYYY = 0x55; - static const int YYYZ = 0x95; - static const int YYYW = 0xD5; - static const int YYZX = 0x25; - static const int YYZY = 0x65; - static const int YYZZ = 0xA5; - static const int YYZW = 0xE5; - static const int YYWX = 0x35; - static const int YYWY = 0x75; - static const int YYWZ = 0xB5; - static const int YYWW = 0xF5; - static const int YZXX = 0x9; - static const int YZXY = 0x49; - static const int YZXZ = 0x89; - static const int YZXW = 0xC9; - static const int YZYX = 0x19; - static const int YZYY = 0x59; - static const int YZYZ = 0x99; - static const int YZYW = 0xD9; - static const int YZZX = 0x29; - static const int YZZY = 0x69; - static const int YZZZ = 0xA9; - static const int YZZW = 0xE9; - static const int YZWX = 0x39; - static const int YZWY = 0x79; - static const int YZWZ = 0xB9; - static const int YZWW = 0xF9; - static const int YWXX = 0xD; - static const int YWXY = 0x4D; - static const int YWXZ = 0x8D; - static const int YWXW = 0xCD; - static const int YWYX = 0x1D; - static const int YWYY = 0x5D; - static const int YWYZ = 0x9D; - static const int YWYW = 0xDD; - static const int YWZX = 0x2D; - static const int YWZY = 0x6D; - static const int YWZZ = 0xAD; - static const int YWZW = 0xED; - static const int YWWX = 0x3D; - static const int YWWY = 0x7D; - static const int YWWZ = 0xBD; - static const int YWWW = 0xFD; - static const int ZXXX = 0x2; - static const int ZXXY = 0x42; - static const int ZXXZ = 0x82; - static const int ZXXW = 0xC2; - static const int ZXYX = 0x12; - static const int ZXYY = 0x52; - static const int ZXYZ = 0x92; - static const int ZXYW = 0xD2; - static const int ZXZX = 0x22; - static const int ZXZY = 0x62; - static const int ZXZZ = 0xA2; - static const int ZXZW = 0xE2; - static const int ZXWX = 0x32; - static const int ZXWY = 0x72; - static const int ZXWZ = 0xB2; - static const int ZXWW = 0xF2; - static const int ZYXX = 0x6; - static const int ZYXY = 0x46; - static const int ZYXZ = 0x86; - static const int ZYXW = 0xC6; - static const int ZYYX = 0x16; - static const int ZYYY = 0x56; - static const int ZYYZ = 0x96; - static const int ZYYW = 0xD6; - static const int ZYZX = 0x26; - static const int ZYZY = 0x66; - static const int ZYZZ = 0xA6; - static const int ZYZW = 0xE6; - static const int ZYWX = 0x36; - static const int ZYWY = 0x76; - static const int ZYWZ = 0xB6; - static const int ZYWW = 0xF6; - static const int ZZXX = 0xA; - static const int ZZXY = 0x4A; - static const int ZZXZ = 0x8A; - static const int ZZXW = 0xCA; - static const int ZZYX = 0x1A; - static const int ZZYY = 0x5A; - static const int ZZYZ = 0x9A; - static const int ZZYW = 0xDA; - static const int ZZZX = 0x2A; - static const int ZZZY = 0x6A; - static const int ZZZZ = 0xAA; - static const int ZZZW = 0xEA; - static const int ZZWX = 0x3A; - static const int ZZWY = 0x7A; - static const int ZZWZ = 0xBA; - static const int ZZWW = 0xFA; - static const int ZWXX = 0xE; - static const int ZWXY = 0x4E; - static const int ZWXZ = 0x8E; - static const int ZWXW = 0xCE; - static const int ZWYX = 0x1E; - static const int ZWYY = 0x5E; - static const int ZWYZ = 0x9E; - static const int ZWYW = 0xDE; - static const int ZWZX = 0x2E; - static const int ZWZY = 0x6E; - static const int ZWZZ = 0xAE; - static const int ZWZW = 0xEE; - static const int ZWWX = 0x3E; - static const int ZWWY = 0x7E; - static const int ZWWZ = 0xBE; - static const int ZWWW = 0xFE; - static const int WXXX = 0x3; - static const int WXXY = 0x43; - static const int WXXZ = 0x83; - static const int WXXW = 0xC3; - static const int WXYX = 0x13; - static const int WXYY = 0x53; - static const int WXYZ = 0x93; - static const int WXYW = 0xD3; - static const int WXZX = 0x23; - static const int WXZY = 0x63; - static const int WXZZ = 0xA3; - static const int WXZW = 0xE3; - static const int WXWX = 0x33; - static const int WXWY = 0x73; - static const int WXWZ = 0xB3; - static const int WXWW = 0xF3; - static const int WYXX = 0x7; - static const int WYXY = 0x47; - static const int WYXZ = 0x87; - static const int WYXW = 0xC7; - static const int WYYX = 0x17; - static const int WYYY = 0x57; - static const int WYYZ = 0x97; - static const int WYYW = 0xD7; - static const int WYZX = 0x27; - static const int WYZY = 0x67; - static const int WYZZ = 0xA7; - static const int WYZW = 0xE7; - static const int WYWX = 0x37; - static const int WYWY = 0x77; - static const int WYWZ = 0xB7; - static const int WYWW = 0xF7; - static const int WZXX = 0xB; - static const int WZXY = 0x4B; - static const int WZXZ = 0x8B; - static const int WZXW = 0xCB; - static const int WZYX = 0x1B; - static const int WZYY = 0x5B; - static const int WZYZ = 0x9B; - static const int WZYW = 0xDB; - static const int WZZX = 0x2B; - static const int WZZY = 0x6B; - static const int WZZZ = 0xAB; - static const int WZZW = 0xEB; - static const int WZWX = 0x3B; - static const int WZWY = 0x7B; - static const int WZWZ = 0xBB; - static const int WZWW = 0xFB; - static const int WWXX = 0xF; - static const int WWXY = 0x4F; - static const int WWXZ = 0x8F; - static const int WWXW = 0xCF; - static const int WWYX = 0x1F; - static const int WWYY = 0x5F; - static const int WWYZ = 0x9F; - static const int WWYW = 0xDF; - static const int WWZX = 0x2F; - static const int WWZY = 0x6F; - static const int WWZZ = 0xAF; - static const int WWZW = 0xEF; - static const int WWWX = 0x3F; - static const int WWWY = 0x7F; - static const int WWWZ = 0xBF; - static const int WWWW = 0xFF; - - /// Shuffle the lane values. [mask] must be one of the 256 shuffle constants. - Float32x4 shuffle(int mask); - - /// Shuffle the lane values in [this] and [other]. The returned - /// Float32x4 will have XY lanes from [this] and ZW lanes from [other]. - /// Uses the same [mask] as [shuffle]. - Float32x4 shuffleMix(Float32x4 other, int mask); - - /// Returns a new [Float32x4] copied from [this] with a new x value. - Float32x4 withX(double x); - /// Returns a new [Float32x4] copied from [this] with a new y value. - Float32x4 withY(double y); - /// Returns a new [Float32x4] copied from [this] with a new z value. - Float32x4 withZ(double z); - /// Returns a new [Float32x4] copied from [this] with a new w value. - Float32x4 withW(double w); - - /// Returns the lane-wise minimum value in [this] or [other]. - Float32x4 min(Float32x4 other); - - /// Returns the lane-wise maximum value in [this] or [other]. - Float32x4 max(Float32x4 other); - - /// Returns the square root of [this]. - Float32x4 sqrt(); - - /// Returns the reciprocal of [this]. - Float32x4 reciprocal(); - - /// Returns the square root of the reciprocal of [this]. - Float32x4 reciprocalSqrt(); -} - - -/** - * Int32x4 and operations. - * Int32x4 stores 4 32-bit bit-masks in "lanes". - * The lanes are "x", "y", "z", and "w" respectively. - */ -abstract class Int32x4 { - factory Int32x4(int x, int y, int z, int w) = NativeInt32x4; - factory Int32x4.bool(bool x, bool y, bool z, bool w) = - NativeInt32x4.bool; - factory Int32x4.fromFloat32x4Bits(Float32x4 x) = - NativeInt32x4.fromFloat32x4Bits; - - /// The bit-wise or operator. - Int32x4 operator|(Int32x4 other); - /// The bit-wise and operator. - Int32x4 operator&(Int32x4 other); - /// The bit-wise xor operator. - Int32x4 operator^(Int32x4 other); - /// Addition operator. - Int32x4 operator+(Int32x4 other); - /// Subtraction operator. - Int32x4 operator-(Int32x4 other); - - /// Extract 32-bit mask from x lane. - int get x; - /// Extract 32-bit mask from y lane. - int get y; - /// Extract 32-bit mask from z lane. - int get z; - /// Extract 32-bit mask from w lane. - int get w; - - /// Extract the top bit from each lane return them in the first 4 bits. - /// "x" lane is bit 0. - /// "y" lane is bit 1. - /// "z" lane is bit 2. - /// "w" lane is bit 3. - int get signMask; - - /// Mask passed to [shuffle] or [shuffleMix]. - static const int XXXX = 0x0; - static const int XXXY = 0x40; - static const int XXXZ = 0x80; - static const int XXXW = 0xC0; - static const int XXYX = 0x10; - static const int XXYY = 0x50; - static const int XXYZ = 0x90; - static const int XXYW = 0xD0; - static const int XXZX = 0x20; - static const int XXZY = 0x60; - static const int XXZZ = 0xA0; - static const int XXZW = 0xE0; - static const int XXWX = 0x30; - static const int XXWY = 0x70; - static const int XXWZ = 0xB0; - static const int XXWW = 0xF0; - static const int XYXX = 0x4; - static const int XYXY = 0x44; - static const int XYXZ = 0x84; - static const int XYXW = 0xC4; - static const int XYYX = 0x14; - static const int XYYY = 0x54; - static const int XYYZ = 0x94; - static const int XYYW = 0xD4; - static const int XYZX = 0x24; - static const int XYZY = 0x64; - static const int XYZZ = 0xA4; - static const int XYZW = 0xE4; - static const int XYWX = 0x34; - static const int XYWY = 0x74; - static const int XYWZ = 0xB4; - static const int XYWW = 0xF4; - static const int XZXX = 0x8; - static const int XZXY = 0x48; - static const int XZXZ = 0x88; - static const int XZXW = 0xC8; - static const int XZYX = 0x18; - static const int XZYY = 0x58; - static const int XZYZ = 0x98; - static const int XZYW = 0xD8; - static const int XZZX = 0x28; - static const int XZZY = 0x68; - static const int XZZZ = 0xA8; - static const int XZZW = 0xE8; - static const int XZWX = 0x38; - static const int XZWY = 0x78; - static const int XZWZ = 0xB8; - static const int XZWW = 0xF8; - static const int XWXX = 0xC; - static const int XWXY = 0x4C; - static const int XWXZ = 0x8C; - static const int XWXW = 0xCC; - static const int XWYX = 0x1C; - static const int XWYY = 0x5C; - static const int XWYZ = 0x9C; - static const int XWYW = 0xDC; - static const int XWZX = 0x2C; - static const int XWZY = 0x6C; - static const int XWZZ = 0xAC; - static const int XWZW = 0xEC; - static const int XWWX = 0x3C; - static const int XWWY = 0x7C; - static const int XWWZ = 0xBC; - static const int XWWW = 0xFC; - static const int YXXX = 0x1; - static const int YXXY = 0x41; - static const int YXXZ = 0x81; - static const int YXXW = 0xC1; - static const int YXYX = 0x11; - static const int YXYY = 0x51; - static const int YXYZ = 0x91; - static const int YXYW = 0xD1; - static const int YXZX = 0x21; - static const int YXZY = 0x61; - static const int YXZZ = 0xA1; - static const int YXZW = 0xE1; - static const int YXWX = 0x31; - static const int YXWY = 0x71; - static const int YXWZ = 0xB1; - static const int YXWW = 0xF1; - static const int YYXX = 0x5; - static const int YYXY = 0x45; - static const int YYXZ = 0x85; - static const int YYXW = 0xC5; - static const int YYYX = 0x15; - static const int YYYY = 0x55; - static const int YYYZ = 0x95; - static const int YYYW = 0xD5; - static const int YYZX = 0x25; - static const int YYZY = 0x65; - static const int YYZZ = 0xA5; - static const int YYZW = 0xE5; - static const int YYWX = 0x35; - static const int YYWY = 0x75; - static const int YYWZ = 0xB5; - static const int YYWW = 0xF5; - static const int YZXX = 0x9; - static const int YZXY = 0x49; - static const int YZXZ = 0x89; - static const int YZXW = 0xC9; - static const int YZYX = 0x19; - static const int YZYY = 0x59; - static const int YZYZ = 0x99; - static const int YZYW = 0xD9; - static const int YZZX = 0x29; - static const int YZZY = 0x69; - static const int YZZZ = 0xA9; - static const int YZZW = 0xE9; - static const int YZWX = 0x39; - static const int YZWY = 0x79; - static const int YZWZ = 0xB9; - static const int YZWW = 0xF9; - static const int YWXX = 0xD; - static const int YWXY = 0x4D; - static const int YWXZ = 0x8D; - static const int YWXW = 0xCD; - static const int YWYX = 0x1D; - static const int YWYY = 0x5D; - static const int YWYZ = 0x9D; - static const int YWYW = 0xDD; - static const int YWZX = 0x2D; - static const int YWZY = 0x6D; - static const int YWZZ = 0xAD; - static const int YWZW = 0xED; - static const int YWWX = 0x3D; - static const int YWWY = 0x7D; - static const int YWWZ = 0xBD; - static const int YWWW = 0xFD; - static const int ZXXX = 0x2; - static const int ZXXY = 0x42; - static const int ZXXZ = 0x82; - static const int ZXXW = 0xC2; - static const int ZXYX = 0x12; - static const int ZXYY = 0x52; - static const int ZXYZ = 0x92; - static const int ZXYW = 0xD2; - static const int ZXZX = 0x22; - static const int ZXZY = 0x62; - static const int ZXZZ = 0xA2; - static const int ZXZW = 0xE2; - static const int ZXWX = 0x32; - static const int ZXWY = 0x72; - static const int ZXWZ = 0xB2; - static const int ZXWW = 0xF2; - static const int ZYXX = 0x6; - static const int ZYXY = 0x46; - static const int ZYXZ = 0x86; - static const int ZYXW = 0xC6; - static const int ZYYX = 0x16; - static const int ZYYY = 0x56; - static const int ZYYZ = 0x96; - static const int ZYYW = 0xD6; - static const int ZYZX = 0x26; - static const int ZYZY = 0x66; - static const int ZYZZ = 0xA6; - static const int ZYZW = 0xE6; - static const int ZYWX = 0x36; - static const int ZYWY = 0x76; - static const int ZYWZ = 0xB6; - static const int ZYWW = 0xF6; - static const int ZZXX = 0xA; - static const int ZZXY = 0x4A; - static const int ZZXZ = 0x8A; - static const int ZZXW = 0xCA; - static const int ZZYX = 0x1A; - static const int ZZYY = 0x5A; - static const int ZZYZ = 0x9A; - static const int ZZYW = 0xDA; - static const int ZZZX = 0x2A; - static const int ZZZY = 0x6A; - static const int ZZZZ = 0xAA; - static const int ZZZW = 0xEA; - static const int ZZWX = 0x3A; - static const int ZZWY = 0x7A; - static const int ZZWZ = 0xBA; - static const int ZZWW = 0xFA; - static const int ZWXX = 0xE; - static const int ZWXY = 0x4E; - static const int ZWXZ = 0x8E; - static const int ZWXW = 0xCE; - static const int ZWYX = 0x1E; - static const int ZWYY = 0x5E; - static const int ZWYZ = 0x9E; - static const int ZWYW = 0xDE; - static const int ZWZX = 0x2E; - static const int ZWZY = 0x6E; - static const int ZWZZ = 0xAE; - static const int ZWZW = 0xEE; - static const int ZWWX = 0x3E; - static const int ZWWY = 0x7E; - static const int ZWWZ = 0xBE; - static const int ZWWW = 0xFE; - static const int WXXX = 0x3; - static const int WXXY = 0x43; - static const int WXXZ = 0x83; - static const int WXXW = 0xC3; - static const int WXYX = 0x13; - static const int WXYY = 0x53; - static const int WXYZ = 0x93; - static const int WXYW = 0xD3; - static const int WXZX = 0x23; - static const int WXZY = 0x63; - static const int WXZZ = 0xA3; - static const int WXZW = 0xE3; - static const int WXWX = 0x33; - static const int WXWY = 0x73; - static const int WXWZ = 0xB3; - static const int WXWW = 0xF3; - static const int WYXX = 0x7; - static const int WYXY = 0x47; - static const int WYXZ = 0x87; - static const int WYXW = 0xC7; - static const int WYYX = 0x17; - static const int WYYY = 0x57; - static const int WYYZ = 0x97; - static const int WYYW = 0xD7; - static const int WYZX = 0x27; - static const int WYZY = 0x67; - static const int WYZZ = 0xA7; - static const int WYZW = 0xE7; - static const int WYWX = 0x37; - static const int WYWY = 0x77; - static const int WYWZ = 0xB7; - static const int WYWW = 0xF7; - static const int WZXX = 0xB; - static const int WZXY = 0x4B; - static const int WZXZ = 0x8B; - static const int WZXW = 0xCB; - static const int WZYX = 0x1B; - static const int WZYY = 0x5B; - static const int WZYZ = 0x9B; - static const int WZYW = 0xDB; - static const int WZZX = 0x2B; - static const int WZZY = 0x6B; - static const int WZZZ = 0xAB; - static const int WZZW = 0xEB; - static const int WZWX = 0x3B; - static const int WZWY = 0x7B; - static const int WZWZ = 0xBB; - static const int WZWW = 0xFB; - static const int WWXX = 0xF; - static const int WWXY = 0x4F; - static const int WWXZ = 0x8F; - static const int WWXW = 0xCF; - static const int WWYX = 0x1F; - static const int WWYY = 0x5F; - static const int WWYZ = 0x9F; - static const int WWYW = 0xDF; - static const int WWZX = 0x2F; - static const int WWZY = 0x6F; - static const int WWZZ = 0xAF; - static const int WWZW = 0xEF; - static const int WWWX = 0x3F; - static const int WWWY = 0x7F; - static const int WWWZ = 0xBF; - static const int WWWW = 0xFF; - - /// Shuffle the lane values. [mask] must be one of the 256 shuffle constants. - Int32x4 shuffle(int mask); - - /// Shuffle the lane values in [this] and [other]. The returned - /// Int32x4 will have XY lanes from [this] and ZW lanes from [other]. - /// Uses the same [mask] as [shuffle]. - Int32x4 shuffleMix(Int32x4 other, int mask); - - /// Returns a new [Int32x4] copied from [this] with a new x value. - Int32x4 withX(int x); - /// Returns a new [Int32x4] copied from [this] with a new y value. - Int32x4 withY(int y); - /// Returns a new [Int32x4] copied from [this] with a new z value. - Int32x4 withZ(int z); - /// Returns a new [Int32x4] copied from [this] with a new w value. - Int32x4 withW(int w); - - /// Extracted x value. Returns false for 0, true for any other value. - bool get flagX; - /// Extracted y value. Returns false for 0, true for any other value. - bool get flagY; - /// Extracted z value. Returns false for 0, true for any other value. - bool get flagZ; - /// Extracted w value. Returns false for 0, true for any other value. - bool get flagW; - - /// Returns a new [Int32x4] copied from [this] with a new x value. - Int32x4 withFlagX(bool x); - /// Returns a new [Int32x4] copied from [this] with a new y value. - Int32x4 withFlagY(bool y); - /// Returns a new [Int32x4] copied from [this] with a new z value. - Int32x4 withFlagZ(bool z); - /// Returns a new [Int32x4] copied from [this] with a new w value. - Int32x4 withFlagW(bool w); - - /// Merge [trueValue] and [falseValue] based on [this]' bit mask: - /// Select bit from [trueValue] when bit in [this] is on. - /// Select bit from [falseValue] when bit in [this] is off. - Float32x4 select(Float32x4 trueValue, Float32x4 falseValue); -} - -/** - * Float64x2 immutable value type and operations. - * Float64x2 stores 2 64-bit floating point values in "lanes". - * The lanes are "x" and "y" respectively. - */ -abstract class Float64x2 { - factory Float64x2(double x, double y) = NativeFloat64x2; - factory Float64x2.splat(double v) = NativeFloat64x2.splat; - factory Float64x2.zero() = NativeFloat64x2.zero; - /// Uses the "x" and "y" lanes from [v]. - factory Float64x2.fromFloat32x4(Float32x4 v) = - NativeFloat64x2.fromFloat32x4; - - /// Addition operator. - Float64x2 operator+(Float64x2 other); - /// Negate operator. - Float64x2 operator-(); - /// Subtraction operator. - Float64x2 operator-(Float64x2 other); - /// Multiplication operator. - Float64x2 operator*(Float64x2 other); - /// Division operator. - Float64x2 operator/(Float64x2 other); - - /// Returns a copy of [this] each lane being scaled by [s]. - /// Equivalent to this * new Float64x2.splat(s) - Float64x2 scale(double s); - /// Returns the lane-wise absolute value of this [Float64x2]. - Float64x2 abs(); - - /// Lane-wise clamp [this] to be in the range [lowerLimit]-[upperLimit]. - Float64x2 clamp(Float64x2 lowerLimit, - Float64x2 upperLimit); - - /// Extracted x value. - double get x; - /// Extracted y value. - double get y; - - /// Extract the sign bits from each lane return them in the first 2 bits. - /// "x" lane is bit 0. - /// "y" lane is bit 1. - int get signMask; - - /// Returns a new [Float64x2] copied from [this] with a new x value. - Float64x2 withX(double x); - /// Returns a new [Float64x2] copied from [this] with a new y value. - Float64x2 withY(double y); - - /// Returns the lane-wise minimum value in [this] or [other]. - Float64x2 min(Float64x2 other); - - /// Returns the lane-wise maximum value in [this] or [other]. - Float64x2 max(Float64x2 other); - - /// Returns the lane-wise square root of [this]. - Float64x2 sqrt(); -} diff --git a/pkg/dev_compiler/test/generated_sdk/version b/pkg/dev_compiler/test/generated_sdk/version deleted file mode 100644 index c8f7f49e1eec..000000000000 --- a/pkg/dev_compiler/test/generated_sdk/version +++ /dev/null @@ -1 +0,0 @@ -1.9.0-dev.4.0 diff --git a/pkg/dev_compiler/tool/README.md b/pkg/dev_compiler/tool/README.md index 613bcdeb6f46..d0d4c2d091d7 100644 --- a/pkg/dev_compiler/tool/README.md +++ b/pkg/dev_compiler/tool/README.md @@ -4,19 +4,20 @@ This script combines: - tool/input_sdk_src/... - tool/input_sdk_patch/... + tool/input_sdk/lib/... + tool/input_sdk/patch/... + tool/input_sdk/private/... and produces the merged SDK sources in: - test/generated_sdk/... + tool/generated_sdk/... The result has all "external" keywords replaced with the @patch implementations. -Generally local edits should be to `input_sdk_patch`, as it is specific to DDC. -`input_sdk_src` should represent unmodified SDK sources to the maximum extent -possible. Currently there are slight edits to the type annotations in some -cases. +Generally local edits should be to `input_sdk/patch` and `input_sdk/private`, +as those two directories are specific to DDC. `input_sdk/lib` should represent +unmodified SDK sources to the maximum extent possible. Currently there are +slight edits to the type annotations in some cases. See patch_sdk.dart for more information. diff --git a/pkg/dev_compiler/tool/build_sdk.sh b/pkg/dev_compiler/tool/build_sdk.sh index 80d387acd202..9d5078ee981c 100755 --- a/pkg/dev_compiler/tool/build_sdk.sh +++ b/pkg/dev_compiler/tool/build_sdk.sh @@ -4,8 +4,8 @@ set -e cd $( dirname "${BASH_SOURCE[0]}" )/.. echo "*** Patching SDK" -rm -r test/generated_sdk || true -dart -c tool/patch_sdk.dart tool/input_sdk test/generated_sdk +rm -r tool/generated_sdk || true +dart -c tool/patch_sdk.dart tool/input_sdk tool/generated_sdk echo "*** Compiling SDK to JavaScript" if [[ -d lib/runtime/dart ]] ; then @@ -14,8 +14,8 @@ fi # TODO(jmesserly): for now we're suppressing errors in SDK compilation dart -c bin/devc.dart --no-source-maps --sdk-check --force-compile -l warning \ - --dart-sdk test/generated_sdk -o lib/runtime/ dart:core \ - > test/generated_sdk/sdk_errors.txt || true + --dart-sdk tool/generated_sdk -o lib/runtime/ dart:core \ + > tool/generated_sdk/sdk_errors.txt || true if [[ ! -f lib/runtime/dart/core.js ]] ; then echo 'core.js not found, assuming build failed.' @@ -23,7 +23,7 @@ if [[ ! -f lib/runtime/dart/core.js ]] ; then exit 1 fi -DIFF_ARGS="-u tool/sdk_expected_errors.txt test/generated_sdk/sdk_errors.txt" +DIFF_ARGS="-u tool/sdk_expected_errors.txt tool/generated_sdk/sdk_errors.txt" if ! (diff $DIFF_ARGS > /dev/null) ; then diff $DIFF_ARGS |\ @@ -31,6 +31,6 @@ if ! (diff $DIFF_ARGS > /dev/null) ; then sed -e "s/^\(-.*\)/\1/" echo echo 'SDK errors have changed. To update expectations, run:' - echo '$ cp test/generated_sdk/sdk_errors.txt tool/sdk_expected_errors.txt' + echo '$ cp tool/generated_sdk/sdk_errors.txt tool/sdk_expected_errors.txt' exit 1 fi